theme.js 991 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264226522662267226822692270227122722273227422752276227722782279228022812282228322842285228622872288228922902291229222932294229522962297229822992300230123022303230423052306230723082309231023112312231323142315231623172318231923202321232223232324232523262327232823292330233123322333233423352336233723382339234023412342234323442345234623472348234923502351235223532354235523562357235823592360236123622363236423652366236723682369237023712372237323742375237623772378237923802381238223832384238523862387238823892390239123922393239423952396239723982399240024012402240324042405240624072408240924102411241224132414241524162417241824192420242124222423242424252426242724282429243024312432243324342435243624372438243924402441244224432444244524462447244824492450245124522453245424552456245724582459246024612462246324642465246624672468246924702471247224732474247524762477247824792480248124822483248424852486248724882489249024912492249324942495249624972498249925002501250225032504250525062507250825092510251125122513251425152516251725182519252025212522252325242525252625272528252925302531253225332534253525362537253825392540254125422543254425452546254725482549255025512552255325542555255625572558255925602561256225632564256525662567256825692570257125722573257425752576257725782579258025812582258325842585258625872588258925902591259225932594259525962597259825992600260126022603260426052606260726082609261026112612261326142615261626172618261926202621262226232624262526262627262826292630263126322633263426352636263726382639264026412642264326442645264626472648264926502651265226532654265526562657265826592660266126622663266426652666266726682669267026712672267326742675267626772678267926802681268226832684268526862687268826892690269126922693269426952696269726982699270027012702270327042705270627072708270927102711271227132714271527162717271827192720272127222723272427252726272727282729273027312732273327342735273627372738273927402741274227432744274527462747274827492750275127522753275427552756275727582759276027612762276327642765276627672768276927702771277227732774277527762777277827792780278127822783278427852786278727882789279027912792279327942795279627972798279928002801280228032804280528062807280828092810281128122813281428152816281728182819282028212822282328242825282628272828282928302831283228332834283528362837283828392840284128422843284428452846284728482849285028512852285328542855285628572858285928602861286228632864286528662867286828692870287128722873287428752876287728782879288028812882288328842885288628872888288928902891289228932894289528962897289828992900290129022903290429052906290729082909291029112912291329142915291629172918291929202921292229232924292529262927292829292930293129322933293429352936293729382939294029412942294329442945294629472948294929502951295229532954295529562957295829592960296129622963296429652966296729682969297029712972297329742975297629772978297929802981298229832984298529862987298829892990299129922993299429952996299729982999300030013002300330043005300630073008300930103011301230133014301530163017301830193020302130223023302430253026302730283029303030313032303330343035303630373038303930403041304230433044304530463047304830493050305130523053305430553056305730583059306030613062306330643065306630673068306930703071307230733074307530763077307830793080308130823083308430853086308730883089309030913092309330943095309630973098309931003101310231033104310531063107310831093110311131123113311431153116311731183119312031213122312331243125312631273128312931303131313231333134313531363137313831393140314131423143314431453146314731483149315031513152315331543155315631573158315931603161316231633164316531663167316831693170317131723173317431753176317731783179318031813182318331843185318631873188318931903191319231933194319531963197319831993200320132023203320432053206320732083209321032113212321332143215321632173218321932203221322232233224322532263227322832293230323132323233323432353236323732383239324032413242324332443245324632473248324932503251325232533254325532563257325832593260326132623263326432653266326732683269327032713272327332743275327632773278327932803281328232833284328532863287328832893290329132923293329432953296329732983299330033013302330333043305330633073308330933103311331233133314331533163317331833193320332133223323332433253326332733283329333033313332333333343335333633373338333933403341334233433344334533463347334833493350335133523353335433553356335733583359336033613362336333643365336633673368336933703371337233733374337533763377337833793380338133823383338433853386338733883389339033913392339333943395339633973398339934003401340234033404340534063407340834093410341134123413341434153416341734183419342034213422342334243425342634273428342934303431343234333434343534363437343834393440344134423443344434453446344734483449345034513452345334543455345634573458345934603461346234633464346534663467346834693470347134723473347434753476347734783479348034813482348334843485348634873488348934903491349234933494349534963497349834993500350135023503350435053506350735083509351035113512351335143515351635173518351935203521352235233524352535263527352835293530353135323533353435353536353735383539354035413542354335443545354635473548354935503551355235533554355535563557355835593560356135623563356435653566356735683569357035713572357335743575357635773578357935803581358235833584358535863587358835893590359135923593359435953596359735983599360036013602360336043605360636073608360936103611361236133614361536163617361836193620362136223623362436253626362736283629363036313632363336343635363636373638363936403641364236433644364536463647364836493650365136523653365436553656365736583659366036613662366336643665366636673668366936703671367236733674367536763677367836793680368136823683368436853686368736883689369036913692369336943695369636973698369937003701370237033704370537063707370837093710371137123713371437153716371737183719372037213722372337243725372637273728372937303731373237333734373537363737373837393740374137423743374437453746374737483749375037513752375337543755375637573758375937603761376237633764376537663767376837693770377137723773377437753776377737783779378037813782378337843785378637873788378937903791379237933794379537963797379837993800380138023803380438053806380738083809381038113812381338143815381638173818381938203821382238233824382538263827382838293830383138323833383438353836383738383839384038413842384338443845384638473848384938503851385238533854385538563857385838593860386138623863386438653866386738683869387038713872387338743875387638773878387938803881388238833884388538863887388838893890389138923893389438953896389738983899390039013902390339043905390639073908390939103911391239133914391539163917391839193920392139223923392439253926392739283929393039313932393339343935393639373938393939403941394239433944394539463947394839493950395139523953395439553956395739583959396039613962396339643965396639673968396939703971397239733974397539763977397839793980398139823983398439853986398739883989399039913992399339943995399639973998399940004001400240034004400540064007400840094010401140124013401440154016401740184019402040214022402340244025402640274028402940304031403240334034403540364037403840394040404140424043404440454046404740484049405040514052405340544055405640574058405940604061406240634064406540664067406840694070407140724073407440754076407740784079408040814082408340844085408640874088408940904091409240934094409540964097409840994100410141024103410441054106410741084109411041114112411341144115411641174118411941204121412241234124412541264127412841294130413141324133413441354136413741384139414041414142414341444145414641474148414941504151415241534154415541564157415841594160416141624163416441654166416741684169417041714172417341744175417641774178417941804181418241834184418541864187418841894190419141924193419441954196419741984199420042014202420342044205420642074208420942104211421242134214421542164217421842194220422142224223422442254226422742284229423042314232423342344235423642374238423942404241424242434244424542464247424842494250425142524253425442554256425742584259426042614262426342644265426642674268426942704271427242734274427542764277427842794280428142824283428442854286428742884289429042914292429342944295429642974298429943004301430243034304430543064307430843094310431143124313431443154316431743184319432043214322432343244325432643274328432943304331433243334334433543364337433843394340434143424343434443454346434743484349435043514352435343544355435643574358435943604361436243634364436543664367436843694370437143724373437443754376437743784379438043814382438343844385438643874388438943904391439243934394439543964397439843994400440144024403440444054406440744084409441044114412441344144415441644174418441944204421442244234424442544264427442844294430443144324433443444354436443744384439444044414442444344444445444644474448444944504451445244534454445544564457445844594460446144624463446444654466446744684469447044714472447344744475447644774478447944804481448244834484448544864487448844894490449144924493449444954496449744984499450045014502450345044505450645074508450945104511451245134514451545164517451845194520452145224523452445254526452745284529453045314532453345344535453645374538453945404541454245434544454545464547454845494550455145524553455445554556455745584559456045614562456345644565456645674568456945704571457245734574457545764577457845794580458145824583458445854586458745884589459045914592459345944595459645974598459946004601460246034604460546064607460846094610461146124613461446154616461746184619462046214622462346244625462646274628462946304631463246334634463546364637463846394640464146424643464446454646464746484649465046514652465346544655465646574658465946604661466246634664466546664667466846694670467146724673467446754676467746784679468046814682468346844685468646874688468946904691469246934694469546964697469846994700470147024703470447054706470747084709471047114712471347144715471647174718471947204721472247234724472547264727472847294730473147324733473447354736473747384739474047414742474347444745474647474748474947504751475247534754475547564757475847594760476147624763476447654766476747684769477047714772477347744775477647774778477947804781478247834784478547864787478847894790479147924793479447954796479747984799480048014802480348044805480648074808480948104811481248134814481548164817481848194820482148224823482448254826482748284829483048314832483348344835483648374838483948404841484248434844484548464847484848494850485148524853485448554856485748584859486048614862486348644865486648674868486948704871487248734874487548764877487848794880488148824883488448854886488748884889489048914892489348944895489648974898489949004901490249034904490549064907490849094910491149124913491449154916491749184919492049214922492349244925492649274928492949304931493249334934493549364937493849394940494149424943494449454946494749484949495049514952495349544955495649574958495949604961496249634964496549664967496849694970497149724973497449754976497749784979498049814982498349844985498649874988498949904991499249934994499549964997499849995000500150025003500450055006500750085009501050115012501350145015501650175018501950205021502250235024502550265027502850295030503150325033503450355036503750385039504050415042504350445045504650475048504950505051505250535054505550565057505850595060506150625063506450655066506750685069507050715072507350745075507650775078507950805081508250835084508550865087508850895090509150925093509450955096509750985099510051015102510351045105510651075108510951105111511251135114511551165117511851195120512151225123512451255126512751285129513051315132513351345135513651375138513951405141514251435144514551465147514851495150515151525153515451555156515751585159516051615162516351645165516651675168516951705171517251735174517551765177517851795180518151825183518451855186518751885189519051915192519351945195519651975198519952005201520252035204520552065207520852095210521152125213521452155216521752185219522052215222522352245225522652275228522952305231523252335234523552365237523852395240524152425243524452455246524752485249525052515252525352545255525652575258525952605261526252635264526552665267526852695270527152725273527452755276527752785279528052815282528352845285528652875288528952905291529252935294529552965297529852995300530153025303530453055306530753085309531053115312531353145315531653175318531953205321532253235324532553265327532853295330533153325333533453355336533753385339534053415342534353445345534653475348534953505351535253535354535553565357535853595360536153625363536453655366536753685369537053715372537353745375537653775378537953805381538253835384538553865387538853895390539153925393539453955396539753985399540054015402540354045405540654075408540954105411541254135414541554165417541854195420542154225423542454255426542754285429543054315432543354345435543654375438543954405441544254435444544554465447544854495450545154525453545454555456545754585459546054615462546354645465546654675468546954705471547254735474547554765477547854795480548154825483548454855486548754885489549054915492549354945495549654975498549955005501550255035504550555065507550855095510551155125513551455155516551755185519552055215522552355245525552655275528552955305531553255335534553555365537553855395540554155425543554455455546554755485549555055515552555355545555555655575558555955605561556255635564556555665567556855695570557155725573557455755576557755785579558055815582558355845585558655875588558955905591559255935594559555965597559855995600560156025603560456055606560756085609561056115612561356145615561656175618561956205621562256235624562556265627562856295630563156325633563456355636563756385639564056415642564356445645564656475648564956505651565256535654565556565657565856595660566156625663566456655666566756685669567056715672567356745675567656775678567956805681568256835684568556865687568856895690569156925693569456955696569756985699570057015702570357045705570657075708570957105711571257135714571557165717571857195720572157225723572457255726572757285729573057315732573357345735573657375738573957405741574257435744574557465747574857495750575157525753575457555756575757585759576057615762576357645765576657675768576957705771577257735774577557765777577857795780578157825783578457855786578757885789579057915792579357945795579657975798579958005801580258035804580558065807580858095810581158125813581458155816581758185819582058215822582358245825582658275828582958305831583258335834583558365837583858395840584158425843584458455846584758485849585058515852585358545855585658575858585958605861586258635864586558665867586858695870587158725873587458755876587758785879588058815882588358845885588658875888588958905891589258935894589558965897589858995900590159025903590459055906590759085909591059115912591359145915591659175918591959205921592259235924592559265927592859295930593159325933593459355936593759385939594059415942594359445945594659475948594959505951595259535954595559565957595859595960596159625963596459655966596759685969597059715972597359745975597659775978597959805981598259835984598559865987598859895990599159925993599459955996599759985999600060016002600360046005600660076008600960106011601260136014601560166017601860196020602160226023602460256026602760286029603060316032603360346035603660376038603960406041604260436044604560466047604860496050605160526053605460556056605760586059606060616062606360646065606660676068606960706071607260736074607560766077607860796080608160826083608460856086608760886089609060916092609360946095609660976098609961006101610261036104610561066107610861096110611161126113611461156116611761186119612061216122612361246125612661276128612961306131613261336134613561366137613861396140614161426143614461456146614761486149615061516152615361546155615661576158615961606161616261636164616561666167616861696170617161726173617461756176617761786179618061816182618361846185618661876188618961906191619261936194619561966197619861996200620162026203620462056206620762086209621062116212621362146215621662176218621962206221622262236224622562266227622862296230623162326233623462356236623762386239624062416242624362446245624662476248624962506251625262536254625562566257625862596260626162626263626462656266626762686269627062716272627362746275627662776278627962806281628262836284628562866287628862896290629162926293629462956296629762986299630063016302630363046305630663076308630963106311631263136314631563166317631863196320632163226323632463256326632763286329633063316332633363346335633663376338633963406341634263436344634563466347634863496350635163526353635463556356635763586359636063616362636363646365636663676368636963706371637263736374637563766377637863796380638163826383638463856386638763886389639063916392639363946395639663976398639964006401640264036404640564066407640864096410641164126413641464156416641764186419642064216422642364246425642664276428642964306431643264336434643564366437643864396440644164426443644464456446644764486449645064516452645364546455645664576458645964606461646264636464646564666467646864696470647164726473647464756476647764786479648064816482648364846485648664876488648964906491649264936494649564966497649864996500650165026503650465056506650765086509651065116512651365146515651665176518651965206521652265236524652565266527652865296530653165326533653465356536653765386539654065416542654365446545654665476548654965506551655265536554655565566557655865596560656165626563656465656566656765686569657065716572657365746575657665776578657965806581658265836584658565866587658865896590659165926593659465956596659765986599660066016602660366046605660666076608660966106611661266136614661566166617661866196620662166226623662466256626662766286629663066316632663366346635663666376638663966406641664266436644664566466647664866496650665166526653665466556656665766586659666066616662666366646665666666676668666966706671667266736674667566766677667866796680668166826683668466856686668766886689669066916692669366946695669666976698669967006701670267036704670567066707670867096710671167126713671467156716671767186719672067216722672367246725672667276728672967306731673267336734673567366737673867396740674167426743674467456746674767486749675067516752675367546755675667576758675967606761676267636764676567666767676867696770677167726773677467756776677767786779678067816782678367846785678667876788678967906791679267936794679567966797679867996800680168026803680468056806680768086809681068116812681368146815681668176818681968206821682268236824682568266827682868296830683168326833683468356836683768386839684068416842684368446845684668476848684968506851685268536854685568566857685868596860686168626863686468656866686768686869687068716872687368746875687668776878687968806881688268836884688568866887688868896890689168926893689468956896689768986899690069016902690369046905690669076908690969106911691269136914691569166917691869196920692169226923692469256926692769286929693069316932693369346935693669376938693969406941694269436944694569466947694869496950695169526953695469556956695769586959696069616962696369646965696669676968696969706971697269736974697569766977697869796980698169826983698469856986698769886989699069916992699369946995699669976998699970007001700270037004700570067007700870097010701170127013701470157016701770187019702070217022702370247025702670277028702970307031703270337034703570367037703870397040704170427043704470457046704770487049705070517052705370547055705670577058705970607061706270637064706570667067706870697070707170727073707470757076707770787079708070817082708370847085708670877088708970907091709270937094709570967097709870997100710171027103710471057106710771087109711071117112711371147115711671177118711971207121712271237124712571267127712871297130713171327133713471357136713771387139714071417142714371447145714671477148714971507151715271537154715571567157715871597160716171627163716471657166716771687169717071717172717371747175717671777178717971807181718271837184718571867187718871897190719171927193719471957196719771987199720072017202720372047205720672077208720972107211721272137214721572167217721872197220722172227223722472257226722772287229723072317232723372347235723672377238723972407241724272437244724572467247724872497250725172527253725472557256725772587259726072617262726372647265726672677268726972707271727272737274727572767277727872797280728172827283728472857286728772887289729072917292729372947295729672977298729973007301730273037304730573067307730873097310731173127313731473157316731773187319732073217322732373247325732673277328732973307331733273337334733573367337733873397340734173427343734473457346734773487349735073517352735373547355735673577358735973607361736273637364736573667367736873697370737173727373737473757376737773787379738073817382738373847385738673877388738973907391739273937394739573967397739873997400740174027403740474057406740774087409741074117412741374147415741674177418741974207421742274237424742574267427742874297430743174327433743474357436743774387439744074417442744374447445744674477448744974507451745274537454745574567457745874597460746174627463746474657466746774687469747074717472747374747475747674777478747974807481748274837484748574867487748874897490749174927493749474957496749774987499750075017502750375047505750675077508750975107511751275137514751575167517751875197520752175227523752475257526752775287529753075317532753375347535753675377538753975407541754275437544754575467547754875497550755175527553755475557556755775587559756075617562756375647565756675677568756975707571757275737574757575767577757875797580758175827583758475857586758775887589759075917592759375947595759675977598759976007601760276037604760576067607760876097610761176127613761476157616761776187619762076217622762376247625762676277628762976307631763276337634763576367637763876397640764176427643764476457646764776487649765076517652765376547655765676577658765976607661766276637664766576667667766876697670767176727673767476757676767776787679768076817682768376847685768676877688768976907691769276937694769576967697769876997700770177027703770477057706770777087709771077117712771377147715771677177718771977207721772277237724772577267727772877297730773177327733773477357736773777387739774077417742774377447745774677477748774977507751775277537754775577567757775877597760776177627763776477657766776777687769777077717772777377747775777677777778777977807781778277837784778577867787778877897790779177927793779477957796779777987799780078017802780378047805780678077808780978107811781278137814781578167817781878197820782178227823782478257826782778287829783078317832783378347835783678377838783978407841784278437844784578467847784878497850785178527853785478557856785778587859786078617862786378647865786678677868786978707871787278737874787578767877787878797880788178827883788478857886788778887889789078917892789378947895789678977898789979007901790279037904790579067907790879097910791179127913791479157916791779187919792079217922792379247925792679277928792979307931793279337934793579367937793879397940794179427943794479457946794779487949795079517952795379547955795679577958795979607961796279637964796579667967796879697970797179727973797479757976797779787979798079817982798379847985798679877988798979907991799279937994799579967997799879998000800180028003800480058006800780088009801080118012801380148015801680178018801980208021802280238024802580268027802880298030803180328033803480358036803780388039804080418042804380448045804680478048804980508051805280538054805580568057805880598060806180628063806480658066806780688069807080718072807380748075807680778078807980808081808280838084808580868087808880898090809180928093809480958096809780988099810081018102810381048105810681078108810981108111811281138114811581168117811881198120812181228123812481258126812781288129813081318132813381348135813681378138813981408141814281438144814581468147814881498150815181528153815481558156815781588159816081618162816381648165816681678168816981708171817281738174817581768177817881798180818181828183818481858186818781888189819081918192819381948195819681978198819982008201820282038204820582068207820882098210821182128213821482158216821782188219822082218222822382248225822682278228822982308231823282338234823582368237823882398240824182428243824482458246824782488249825082518252825382548255825682578258825982608261826282638264826582668267826882698270827182728273827482758276827782788279828082818282828382848285828682878288828982908291829282938294829582968297829882998300830183028303830483058306830783088309831083118312831383148315831683178318831983208321832283238324832583268327832883298330833183328333833483358336833783388339834083418342834383448345834683478348834983508351835283538354835583568357835883598360836183628363836483658366836783688369837083718372837383748375837683778378837983808381838283838384838583868387838883898390839183928393839483958396839783988399840084018402840384048405840684078408840984108411841284138414841584168417841884198420842184228423842484258426842784288429843084318432843384348435843684378438843984408441844284438444844584468447844884498450845184528453845484558456845784588459846084618462846384648465846684678468846984708471847284738474847584768477847884798480848184828483848484858486848784888489849084918492849384948495849684978498849985008501850285038504850585068507850885098510851185128513851485158516851785188519852085218522852385248525852685278528852985308531853285338534853585368537853885398540854185428543854485458546854785488549855085518552855385548555855685578558855985608561856285638564856585668567856885698570857185728573857485758576857785788579858085818582858385848585858685878588858985908591859285938594859585968597859885998600860186028603860486058606860786088609861086118612861386148615861686178618861986208621862286238624862586268627862886298630863186328633863486358636863786388639864086418642864386448645864686478648864986508651865286538654865586568657865886598660866186628663866486658666866786688669867086718672867386748675867686778678867986808681868286838684868586868687868886898690869186928693869486958696869786988699870087018702870387048705870687078708870987108711871287138714871587168717871887198720872187228723872487258726872787288729873087318732873387348735873687378738873987408741874287438744874587468747874887498750875187528753875487558756875787588759876087618762876387648765876687678768876987708771877287738774877587768777877887798780878187828783878487858786878787888789879087918792879387948795879687978798879988008801880288038804880588068807880888098810881188128813881488158816881788188819882088218822882388248825882688278828882988308831883288338834883588368837883888398840884188428843884488458846884788488849885088518852885388548855885688578858885988608861886288638864886588668867886888698870887188728873887488758876887788788879888088818882888388848885888688878888888988908891889288938894889588968897889888998900890189028903890489058906890789088909891089118912891389148915891689178918891989208921892289238924892589268927892889298930893189328933893489358936893789388939894089418942894389448945894689478948894989508951895289538954895589568957895889598960896189628963896489658966896789688969897089718972897389748975897689778978897989808981898289838984898589868987898889898990899189928993899489958996899789988999900090019002900390049005900690079008900990109011901290139014901590169017901890199020902190229023902490259026902790289029903090319032903390349035903690379038903990409041904290439044904590469047904890499050905190529053905490559056905790589059906090619062906390649065906690679068906990709071907290739074907590769077907890799080908190829083908490859086908790889089909090919092909390949095909690979098909991009101910291039104910591069107910891099110911191129113911491159116911791189119912091219122912391249125912691279128912991309131913291339134913591369137913891399140914191429143914491459146914791489149915091519152915391549155915691579158915991609161916291639164916591669167916891699170917191729173917491759176917791789179918091819182918391849185918691879188918991909191919291939194919591969197919891999200920192029203920492059206920792089209921092119212921392149215921692179218921992209221922292239224922592269227922892299230923192329233923492359236923792389239924092419242924392449245924692479248924992509251925292539254925592569257925892599260926192629263926492659266926792689269927092719272927392749275927692779278927992809281928292839284928592869287928892899290929192929293929492959296929792989299930093019302930393049305930693079308930993109311931293139314931593169317931893199320932193229323932493259326932793289329933093319332933393349335933693379338933993409341934293439344934593469347934893499350935193529353935493559356935793589359936093619362936393649365936693679368936993709371937293739374937593769377937893799380938193829383938493859386938793889389939093919392939393949395939693979398939994009401940294039404940594069407940894099410941194129413941494159416941794189419942094219422942394249425942694279428942994309431943294339434943594369437943894399440944194429443944494459446944794489449945094519452945394549455945694579458945994609461946294639464946594669467946894699470947194729473947494759476947794789479948094819482948394849485948694879488948994909491949294939494949594969497949894999500950195029503950495059506950795089509951095119512951395149515951695179518951995209521952295239524952595269527952895299530953195329533953495359536953795389539954095419542954395449545954695479548954995509551955295539554955595569557955895599560956195629563956495659566956795689569957095719572957395749575957695779578957995809581958295839584958595869587958895899590959195929593959495959596959795989599960096019602960396049605960696079608960996109611961296139614961596169617961896199620962196229623962496259626962796289629963096319632963396349635963696379638963996409641964296439644964596469647964896499650965196529653965496559656965796589659966096619662966396649665966696679668966996709671967296739674967596769677967896799680968196829683968496859686968796889689969096919692969396949695969696979698969997009701970297039704970597069707970897099710971197129713971497159716971797189719972097219722972397249725972697279728972997309731973297339734973597369737973897399740974197429743974497459746974797489749975097519752975397549755975697579758975997609761976297639764976597669767976897699770977197729773977497759776977797789779978097819782978397849785978697879788978997909791979297939794979597969797979897999800980198029803980498059806980798089809981098119812981398149815981698179818981998209821982298239824982598269827982898299830983198329833983498359836983798389839984098419842984398449845984698479848984998509851985298539854985598569857985898599860986198629863986498659866986798689869987098719872987398749875987698779878987998809881988298839884988598869887988898899890989198929893989498959896989798989899990099019902990399049905990699079908990999109911991299139914991599169917991899199920992199229923992499259926992799289929993099319932993399349935993699379938993999409941994299439944994599469947994899499950995199529953995499559956995799589959996099619962996399649965996699679968996999709971997299739974997599769977997899799980998199829983998499859986998799889989999099919992999399949995999699979998999910000100011000210003100041000510006100071000810009100101001110012100131001410015100161001710018100191002010021100221002310024100251002610027100281002910030100311003210033100341003510036100371003810039100401004110042100431004410045100461004710048100491005010051100521005310054100551005610057100581005910060100611006210063100641006510066100671006810069100701007110072100731007410075100761007710078100791008010081100821008310084100851008610087100881008910090100911009210093100941009510096100971009810099101001010110102101031010410105101061010710108101091011010111101121011310114101151011610117101181011910120101211012210123101241012510126101271012810129101301013110132101331013410135101361013710138101391014010141101421014310144101451014610147101481014910150101511015210153101541015510156101571015810159101601016110162101631016410165101661016710168101691017010171101721017310174101751017610177101781017910180101811018210183101841018510186101871018810189101901019110192101931019410195101961019710198101991020010201102021020310204102051020610207102081020910210102111021210213102141021510216102171021810219102201022110222102231022410225102261022710228102291023010231102321023310234102351023610237102381023910240102411024210243102441024510246102471024810249102501025110252102531025410255102561025710258102591026010261102621026310264102651026610267102681026910270102711027210273102741027510276102771027810279102801028110282102831028410285102861028710288102891029010291102921029310294102951029610297102981029910300103011030210303103041030510306103071030810309103101031110312103131031410315103161031710318103191032010321103221032310324103251032610327103281032910330103311033210333103341033510336103371033810339103401034110342103431034410345103461034710348103491035010351103521035310354103551035610357103581035910360103611036210363103641036510366103671036810369103701037110372103731037410375103761037710378103791038010381103821038310384103851038610387103881038910390103911039210393103941039510396103971039810399104001040110402104031040410405104061040710408104091041010411104121041310414104151041610417104181041910420104211042210423104241042510426104271042810429104301043110432104331043410435104361043710438104391044010441104421044310444104451044610447104481044910450104511045210453104541045510456104571045810459104601046110462104631046410465104661046710468104691047010471104721047310474104751047610477104781047910480104811048210483104841048510486104871048810489104901049110492104931049410495104961049710498104991050010501105021050310504105051050610507105081050910510105111051210513105141051510516105171051810519105201052110522105231052410525105261052710528105291053010531105321053310534105351053610537105381053910540105411054210543105441054510546105471054810549105501055110552105531055410555105561055710558105591056010561105621056310564105651056610567105681056910570105711057210573105741057510576105771057810579105801058110582105831058410585105861058710588105891059010591105921059310594105951059610597105981059910600106011060210603106041060510606106071060810609106101061110612106131061410615106161061710618106191062010621106221062310624106251062610627106281062910630106311063210633106341063510636106371063810639106401064110642106431064410645106461064710648106491065010651106521065310654106551065610657106581065910660106611066210663106641066510666106671066810669106701067110672106731067410675106761067710678106791068010681106821068310684106851068610687106881068910690106911069210693106941069510696106971069810699107001070110702107031070410705107061070710708107091071010711107121071310714107151071610717107181071910720107211072210723107241072510726107271072810729107301073110732107331073410735107361073710738107391074010741107421074310744107451074610747107481074910750107511075210753107541075510756107571075810759107601076110762107631076410765107661076710768107691077010771107721077310774107751077610777107781077910780107811078210783107841078510786107871078810789107901079110792107931079410795107961079710798107991080010801108021080310804108051080610807108081080910810108111081210813108141081510816108171081810819108201082110822108231082410825108261082710828108291083010831108321083310834108351083610837108381083910840108411084210843108441084510846108471084810849108501085110852108531085410855108561085710858108591086010861108621086310864108651086610867108681086910870108711087210873108741087510876108771087810879108801088110882108831088410885108861088710888108891089010891108921089310894108951089610897108981089910900109011090210903109041090510906109071090810909109101091110912109131091410915109161091710918109191092010921109221092310924109251092610927109281092910930109311093210933109341093510936109371093810939109401094110942109431094410945109461094710948109491095010951109521095310954109551095610957109581095910960109611096210963109641096510966109671096810969109701097110972109731097410975109761097710978109791098010981109821098310984109851098610987109881098910990109911099210993109941099510996109971099810999110001100111002110031100411005110061100711008110091101011011110121101311014110151101611017110181101911020110211102211023110241102511026110271102811029110301103111032110331103411035110361103711038110391104011041110421104311044110451104611047110481104911050110511105211053110541105511056110571105811059110601106111062110631106411065110661106711068110691107011071110721107311074110751107611077110781107911080110811108211083110841108511086110871108811089110901109111092110931109411095110961109711098110991110011101111021110311104111051110611107111081110911110111111111211113111141111511116111171111811119111201112111122111231112411125111261112711128111291113011131111321113311134111351113611137111381113911140111411114211143111441114511146111471114811149111501115111152111531115411155111561115711158111591116011161111621116311164111651116611167111681116911170111711117211173111741117511176111771117811179111801118111182111831118411185111861118711188111891119011191111921119311194111951119611197111981119911200112011120211203112041120511206112071120811209112101121111212112131121411215112161121711218112191122011221112221122311224112251122611227112281122911230112311123211233112341123511236112371123811239112401124111242112431124411245112461124711248112491125011251112521125311254112551125611257112581125911260112611126211263112641126511266112671126811269112701127111272112731127411275112761127711278112791128011281112821128311284112851128611287112881128911290112911129211293112941129511296112971129811299113001130111302113031130411305113061130711308113091131011311113121131311314113151131611317113181131911320113211132211323113241132511326113271132811329113301133111332113331133411335113361133711338113391134011341113421134311344113451134611347113481134911350113511135211353113541135511356113571135811359113601136111362113631136411365113661136711368113691137011371113721137311374113751137611377113781137911380113811138211383113841138511386113871138811389113901139111392113931139411395113961139711398113991140011401114021140311404114051140611407114081140911410114111141211413114141141511416114171141811419114201142111422114231142411425114261142711428114291143011431114321143311434114351143611437114381143911440114411144211443114441144511446114471144811449114501145111452114531145411455114561145711458114591146011461114621146311464114651146611467114681146911470114711147211473114741147511476114771147811479114801148111482114831148411485114861148711488114891149011491114921149311494114951149611497114981149911500115011150211503115041150511506115071150811509115101151111512115131151411515115161151711518115191152011521115221152311524115251152611527115281152911530115311153211533115341153511536115371153811539115401154111542115431154411545115461154711548115491155011551115521155311554115551155611557115581155911560115611156211563115641156511566115671156811569115701157111572115731157411575115761157711578115791158011581115821158311584115851158611587115881158911590115911159211593115941159511596115971159811599116001160111602116031160411605116061160711608116091161011611116121161311614116151161611617116181161911620116211162211623116241162511626116271162811629116301163111632116331163411635116361163711638116391164011641116421164311644116451164611647116481164911650116511165211653116541165511656116571165811659116601166111662116631166411665116661166711668116691167011671116721167311674116751167611677116781167911680116811168211683116841168511686116871168811689116901169111692116931169411695116961169711698116991170011701117021170311704117051170611707117081170911710117111171211713117141171511716117171171811719117201172111722117231172411725117261172711728117291173011731117321173311734117351173611737117381173911740117411174211743117441174511746117471174811749117501175111752117531175411755117561175711758117591176011761117621176311764117651176611767117681176911770117711177211773117741177511776117771177811779117801178111782117831178411785117861178711788117891179011791117921179311794117951179611797117981179911800118011180211803118041180511806118071180811809118101181111812118131181411815118161181711818118191182011821118221182311824118251182611827118281182911830118311183211833118341183511836118371183811839118401184111842118431184411845118461184711848118491185011851118521185311854118551185611857118581185911860118611186211863118641186511866118671186811869118701187111872118731187411875118761187711878118791188011881118821188311884118851188611887118881188911890118911189211893118941189511896118971189811899119001190111902119031190411905119061190711908119091191011911119121191311914119151191611917119181191911920119211192211923119241192511926119271192811929119301193111932119331193411935119361193711938119391194011941119421194311944119451194611947119481194911950119511195211953119541195511956119571195811959119601196111962119631196411965119661196711968119691197011971119721197311974119751197611977119781197911980119811198211983119841198511986119871198811989119901199111992119931199411995119961199711998119991200012001120021200312004120051200612007120081200912010120111201212013120141201512016120171201812019120201202112022120231202412025120261202712028120291203012031120321203312034120351203612037120381203912040120411204212043120441204512046120471204812049120501205112052120531205412055120561205712058120591206012061120621206312064120651206612067120681206912070120711207212073120741207512076120771207812079120801208112082120831208412085120861208712088120891209012091120921209312094120951209612097120981209912100121011210212103121041210512106121071210812109121101211112112121131211412115121161211712118121191212012121121221212312124121251212612127121281212912130121311213212133121341213512136121371213812139121401214112142121431214412145121461214712148121491215012151121521215312154121551215612157121581215912160121611216212163121641216512166121671216812169121701217112172121731217412175121761217712178121791218012181121821218312184121851218612187121881218912190121911219212193121941219512196121971219812199122001220112202122031220412205122061220712208122091221012211122121221312214122151221612217122181221912220122211222212223122241222512226122271222812229122301223112232122331223412235122361223712238122391224012241122421224312244122451224612247122481224912250122511225212253122541225512256122571225812259122601226112262122631226412265122661226712268122691227012271122721227312274122751227612277122781227912280122811228212283122841228512286122871228812289122901229112292122931229412295122961229712298122991230012301123021230312304123051230612307123081230912310123111231212313123141231512316123171231812319123201232112322123231232412325123261232712328123291233012331123321233312334123351233612337123381233912340123411234212343123441234512346123471234812349123501235112352123531235412355123561235712358123591236012361123621236312364123651236612367123681236912370123711237212373123741237512376123771237812379123801238112382123831238412385123861238712388123891239012391123921239312394123951239612397123981239912400124011240212403124041240512406124071240812409124101241112412124131241412415124161241712418124191242012421124221242312424124251242612427124281242912430124311243212433124341243512436124371243812439124401244112442124431244412445124461244712448124491245012451124521245312454124551245612457124581245912460124611246212463124641246512466124671246812469124701247112472124731247412475124761247712478124791248012481124821248312484124851248612487124881248912490124911249212493124941249512496124971249812499125001250112502125031250412505125061250712508125091251012511125121251312514125151251612517125181251912520125211252212523125241252512526125271252812529125301253112532125331253412535125361253712538125391254012541125421254312544125451254612547125481254912550125511255212553125541255512556125571255812559125601256112562125631256412565125661256712568125691257012571125721257312574125751257612577125781257912580125811258212583125841258512586125871258812589125901259112592125931259412595125961259712598125991260012601126021260312604126051260612607126081260912610126111261212613126141261512616126171261812619126201262112622126231262412625126261262712628126291263012631126321263312634126351263612637126381263912640126411264212643126441264512646126471264812649126501265112652126531265412655126561265712658126591266012661126621266312664126651266612667126681266912670126711267212673126741267512676126771267812679126801268112682126831268412685126861268712688126891269012691126921269312694126951269612697126981269912700127011270212703127041270512706127071270812709127101271112712127131271412715127161271712718127191272012721127221272312724127251272612727127281272912730127311273212733127341273512736127371273812739127401274112742127431274412745127461274712748127491275012751127521275312754127551275612757127581275912760127611276212763127641276512766127671276812769127701277112772127731277412775127761277712778127791278012781127821278312784127851278612787127881278912790127911279212793127941279512796127971279812799128001280112802128031280412805128061280712808128091281012811128121281312814128151281612817128181281912820128211282212823128241282512826128271282812829128301283112832128331283412835128361283712838128391284012841128421284312844128451284612847128481284912850128511285212853128541285512856128571285812859128601286112862128631286412865128661286712868128691287012871128721287312874128751287612877128781287912880128811288212883128841288512886128871288812889128901289112892128931289412895128961289712898128991290012901129021290312904129051290612907129081290912910129111291212913129141291512916129171291812919129201292112922129231292412925129261292712928129291293012931129321293312934129351293612937129381293912940129411294212943129441294512946129471294812949129501295112952129531295412955129561295712958129591296012961129621296312964129651296612967129681296912970129711297212973129741297512976129771297812979129801298112982129831298412985129861298712988129891299012991129921299312994129951299612997129981299913000130011300213003130041300513006130071300813009130101301113012130131301413015130161301713018130191302013021130221302313024130251302613027130281302913030130311303213033130341303513036130371303813039130401304113042130431304413045130461304713048130491305013051130521305313054130551305613057130581305913060130611306213063130641306513066130671306813069130701307113072130731307413075130761307713078130791308013081130821308313084130851308613087130881308913090130911309213093130941309513096130971309813099131001310113102131031310413105131061310713108131091311013111131121311313114131151311613117131181311913120131211312213123131241312513126131271312813129131301313113132131331313413135131361313713138131391314013141131421314313144131451314613147131481314913150131511315213153131541315513156131571315813159131601316113162131631316413165131661316713168131691317013171131721317313174131751317613177131781317913180131811318213183131841318513186131871318813189131901319113192131931319413195131961319713198131991320013201132021320313204132051320613207132081320913210132111321213213132141321513216132171321813219132201322113222132231322413225132261322713228132291323013231132321323313234132351323613237132381323913240132411324213243132441324513246132471324813249132501325113252132531325413255132561325713258132591326013261132621326313264132651326613267132681326913270132711327213273132741327513276132771327813279132801328113282132831328413285132861328713288132891329013291132921329313294132951329613297132981329913300133011330213303133041330513306133071330813309133101331113312133131331413315133161331713318133191332013321133221332313324133251332613327133281332913330133311333213333133341333513336133371333813339133401334113342133431334413345133461334713348133491335013351133521335313354133551335613357133581335913360133611336213363133641336513366133671336813369133701337113372133731337413375133761337713378133791338013381133821338313384133851338613387133881338913390133911339213393133941339513396133971339813399134001340113402134031340413405134061340713408134091341013411134121341313414134151341613417134181341913420134211342213423134241342513426134271342813429134301343113432134331343413435134361343713438134391344013441134421344313444134451344613447134481344913450134511345213453134541345513456134571345813459134601346113462134631346413465134661346713468134691347013471134721347313474134751347613477134781347913480134811348213483134841348513486134871348813489134901349113492134931349413495134961349713498134991350013501135021350313504135051350613507135081350913510135111351213513135141351513516135171351813519135201352113522135231352413525135261352713528135291353013531135321353313534135351353613537135381353913540135411354213543135441354513546135471354813549135501355113552135531355413555135561355713558135591356013561135621356313564135651356613567135681356913570135711357213573135741357513576135771357813579135801358113582135831358413585135861358713588135891359013591135921359313594135951359613597135981359913600136011360213603136041360513606136071360813609136101361113612136131361413615136161361713618136191362013621136221362313624136251362613627136281362913630136311363213633136341363513636136371363813639136401364113642136431364413645136461364713648136491365013651136521365313654136551365613657136581365913660136611366213663136641366513666136671366813669136701367113672136731367413675136761367713678136791368013681136821368313684136851368613687136881368913690136911369213693136941369513696136971369813699137001370113702137031370413705137061370713708137091371013711137121371313714137151371613717137181371913720137211372213723137241372513726137271372813729137301373113732137331373413735137361373713738137391374013741137421374313744137451374613747137481374913750137511375213753137541375513756137571375813759137601376113762137631376413765137661376713768137691377013771137721377313774137751377613777137781377913780137811378213783137841378513786137871378813789137901379113792137931379413795137961379713798137991380013801138021380313804138051380613807138081380913810138111381213813138141381513816138171381813819138201382113822138231382413825138261382713828138291383013831138321383313834138351383613837138381383913840138411384213843138441384513846138471384813849138501385113852138531385413855138561385713858138591386013861138621386313864138651386613867138681386913870138711387213873138741387513876138771387813879138801388113882138831388413885138861388713888138891389013891138921389313894138951389613897138981389913900139011390213903139041390513906139071390813909139101391113912139131391413915139161391713918139191392013921139221392313924139251392613927139281392913930139311393213933139341393513936139371393813939139401394113942139431394413945139461394713948139491395013951139521395313954139551395613957139581395913960139611396213963139641396513966139671396813969139701397113972139731397413975139761397713978139791398013981139821398313984139851398613987139881398913990139911399213993139941399513996139971399813999140001400114002140031400414005140061400714008140091401014011140121401314014140151401614017140181401914020140211402214023140241402514026140271402814029140301403114032140331403414035140361403714038140391404014041140421404314044140451404614047140481404914050140511405214053140541405514056140571405814059140601406114062140631406414065140661406714068140691407014071140721407314074140751407614077140781407914080140811408214083140841408514086140871408814089140901409114092140931409414095140961409714098140991410014101141021410314104141051410614107141081410914110141111411214113141141411514116141171411814119141201412114122141231412414125141261412714128141291413014131141321413314134141351413614137141381413914140141411414214143141441414514146141471414814149141501415114152141531415414155141561415714158141591416014161141621416314164141651416614167141681416914170141711417214173141741417514176141771417814179141801418114182141831418414185141861418714188141891419014191141921419314194141951419614197141981419914200142011420214203142041420514206142071420814209142101421114212142131421414215142161421714218142191422014221142221422314224142251422614227142281422914230142311423214233142341423514236142371423814239142401424114242142431424414245142461424714248142491425014251142521425314254142551425614257142581425914260142611426214263142641426514266142671426814269142701427114272142731427414275142761427714278142791428014281142821428314284142851428614287142881428914290142911429214293142941429514296142971429814299143001430114302143031430414305143061430714308143091431014311143121431314314143151431614317143181431914320143211432214323143241432514326143271432814329143301433114332143331433414335143361433714338143391434014341143421434314344143451434614347143481434914350143511435214353143541435514356143571435814359143601436114362143631436414365143661436714368143691437014371143721437314374143751437614377143781437914380143811438214383143841438514386143871438814389143901439114392143931439414395143961439714398143991440014401144021440314404144051440614407144081440914410144111441214413144141441514416144171441814419144201442114422144231442414425144261442714428144291443014431144321443314434144351443614437144381443914440144411444214443144441444514446144471444814449144501445114452144531445414455144561445714458144591446014461144621446314464144651446614467144681446914470144711447214473144741447514476144771447814479144801448114482144831448414485144861448714488144891449014491144921449314494144951449614497144981449914500145011450214503145041450514506145071450814509145101451114512145131451414515145161451714518145191452014521145221452314524145251452614527145281452914530145311453214533145341453514536145371453814539145401454114542145431454414545145461454714548145491455014551145521455314554145551455614557145581455914560145611456214563145641456514566145671456814569145701457114572145731457414575145761457714578145791458014581145821458314584145851458614587145881458914590145911459214593145941459514596145971459814599146001460114602146031460414605146061460714608146091461014611146121461314614146151461614617146181461914620146211462214623146241462514626146271462814629146301463114632146331463414635146361463714638146391464014641146421464314644146451464614647146481464914650146511465214653146541465514656146571465814659146601466114662146631466414665146661466714668146691467014671146721467314674146751467614677146781467914680146811468214683146841468514686146871468814689146901469114692146931469414695146961469714698146991470014701147021470314704147051470614707147081470914710147111471214713147141471514716147171471814719147201472114722147231472414725147261472714728147291473014731147321473314734147351473614737147381473914740147411474214743147441474514746147471474814749147501475114752147531475414755147561475714758147591476014761147621476314764147651476614767147681476914770147711477214773147741477514776147771477814779147801478114782147831478414785147861478714788147891479014791147921479314794147951479614797147981479914800148011480214803148041480514806148071480814809148101481114812148131481414815148161481714818148191482014821148221482314824148251482614827148281482914830148311483214833148341483514836148371483814839148401484114842148431484414845148461484714848148491485014851148521485314854148551485614857148581485914860148611486214863148641486514866148671486814869148701487114872148731487414875148761487714878148791488014881148821488314884148851488614887148881488914890148911489214893148941489514896148971489814899149001490114902149031490414905149061490714908149091491014911149121491314914149151491614917149181491914920149211492214923149241492514926149271492814929149301493114932149331493414935149361493714938149391494014941149421494314944149451494614947149481494914950149511495214953149541495514956149571495814959149601496114962149631496414965149661496714968149691497014971149721497314974149751497614977149781497914980149811498214983149841498514986149871498814989149901499114992149931499414995149961499714998149991500015001150021500315004150051500615007150081500915010150111501215013150141501515016150171501815019150201502115022150231502415025150261502715028150291503015031150321503315034150351503615037150381503915040150411504215043150441504515046150471504815049150501505115052150531505415055150561505715058150591506015061150621506315064150651506615067150681506915070150711507215073150741507515076150771507815079150801508115082150831508415085150861508715088150891509015091150921509315094150951509615097150981509915100151011510215103151041510515106151071510815109151101511115112151131511415115151161511715118151191512015121151221512315124151251512615127151281512915130151311513215133151341513515136151371513815139151401514115142151431514415145151461514715148151491515015151151521515315154151551515615157151581515915160151611516215163151641516515166151671516815169151701517115172151731517415175151761517715178151791518015181151821518315184151851518615187151881518915190151911519215193151941519515196151971519815199152001520115202152031520415205152061520715208152091521015211152121521315214152151521615217152181521915220152211522215223152241522515226152271522815229152301523115232152331523415235152361523715238152391524015241152421524315244152451524615247152481524915250152511525215253152541525515256152571525815259152601526115262152631526415265152661526715268152691527015271152721527315274152751527615277152781527915280152811528215283152841528515286152871528815289152901529115292152931529415295152961529715298152991530015301153021530315304153051530615307153081530915310153111531215313153141531515316153171531815319153201532115322153231532415325153261532715328153291533015331153321533315334153351533615337153381533915340153411534215343153441534515346153471534815349153501535115352153531535415355153561535715358153591536015361153621536315364153651536615367153681536915370153711537215373153741537515376153771537815379153801538115382153831538415385153861538715388153891539015391153921539315394153951539615397153981539915400154011540215403154041540515406154071540815409154101541115412154131541415415154161541715418154191542015421154221542315424154251542615427154281542915430154311543215433154341543515436154371543815439154401544115442154431544415445154461544715448154491545015451154521545315454154551545615457154581545915460154611546215463154641546515466154671546815469154701547115472154731547415475154761547715478154791548015481154821548315484154851548615487154881548915490154911549215493154941549515496154971549815499155001550115502155031550415505155061550715508155091551015511155121551315514155151551615517155181551915520155211552215523155241552515526155271552815529155301553115532155331553415535155361553715538155391554015541155421554315544155451554615547155481554915550155511555215553155541555515556155571555815559155601556115562155631556415565155661556715568155691557015571155721557315574155751557615577155781557915580155811558215583155841558515586155871558815589155901559115592155931559415595155961559715598155991560015601156021560315604156051560615607156081560915610156111561215613156141561515616156171561815619156201562115622156231562415625156261562715628156291563015631156321563315634156351563615637156381563915640156411564215643156441564515646156471564815649156501565115652156531565415655156561565715658156591566015661156621566315664156651566615667156681566915670156711567215673156741567515676156771567815679156801568115682156831568415685156861568715688156891569015691156921569315694156951569615697156981569915700157011570215703157041570515706157071570815709157101571115712157131571415715157161571715718157191572015721157221572315724157251572615727157281572915730157311573215733157341573515736157371573815739157401574115742157431574415745157461574715748157491575015751157521575315754157551575615757157581575915760157611576215763157641576515766157671576815769157701577115772157731577415775157761577715778157791578015781157821578315784157851578615787157881578915790157911579215793157941579515796157971579815799158001580115802158031580415805158061580715808158091581015811158121581315814158151581615817158181581915820158211582215823158241582515826158271582815829158301583115832158331583415835158361583715838158391584015841158421584315844158451584615847158481584915850158511585215853158541585515856158571585815859158601586115862158631586415865158661586715868158691587015871158721587315874158751587615877158781587915880158811588215883158841588515886158871588815889158901589115892158931589415895158961589715898158991590015901159021590315904159051590615907159081590915910159111591215913159141591515916159171591815919159201592115922159231592415925159261592715928159291593015931159321593315934159351593615937159381593915940159411594215943159441594515946159471594815949159501595115952159531595415955159561595715958159591596015961159621596315964159651596615967159681596915970159711597215973159741597515976159771597815979159801598115982159831598415985159861598715988159891599015991159921599315994159951599615997159981599916000160011600216003160041600516006160071600816009160101601116012160131601416015160161601716018160191602016021160221602316024160251602616027160281602916030160311603216033160341603516036160371603816039160401604116042160431604416045160461604716048160491605016051160521605316054160551605616057160581605916060160611606216063160641606516066160671606816069160701607116072160731607416075160761607716078160791608016081160821608316084160851608616087160881608916090160911609216093160941609516096160971609816099161001610116102161031610416105161061610716108161091611016111161121611316114161151611616117161181611916120161211612216123161241612516126161271612816129161301613116132161331613416135161361613716138161391614016141161421614316144161451614616147161481614916150161511615216153161541615516156161571615816159161601616116162161631616416165161661616716168161691617016171161721617316174161751617616177161781617916180161811618216183161841618516186161871618816189161901619116192161931619416195161961619716198161991620016201162021620316204162051620616207162081620916210162111621216213162141621516216162171621816219162201622116222162231622416225162261622716228162291623016231162321623316234162351623616237162381623916240162411624216243162441624516246162471624816249162501625116252162531625416255162561625716258162591626016261162621626316264162651626616267162681626916270162711627216273162741627516276162771627816279162801628116282162831628416285162861628716288162891629016291162921629316294162951629616297162981629916300163011630216303163041630516306163071630816309163101631116312163131631416315163161631716318163191632016321163221632316324163251632616327163281632916330163311633216333163341633516336163371633816339163401634116342163431634416345163461634716348163491635016351163521635316354163551635616357163581635916360163611636216363163641636516366163671636816369163701637116372163731637416375163761637716378163791638016381163821638316384163851638616387163881638916390163911639216393163941639516396163971639816399164001640116402164031640416405164061640716408164091641016411164121641316414164151641616417164181641916420164211642216423164241642516426164271642816429164301643116432164331643416435164361643716438164391644016441164421644316444164451644616447164481644916450164511645216453164541645516456164571645816459164601646116462164631646416465164661646716468164691647016471164721647316474164751647616477164781647916480164811648216483164841648516486164871648816489164901649116492164931649416495164961649716498164991650016501165021650316504165051650616507165081650916510165111651216513165141651516516165171651816519165201652116522165231652416525165261652716528165291653016531165321653316534165351653616537165381653916540165411654216543165441654516546165471654816549165501655116552165531655416555165561655716558165591656016561165621656316564165651656616567165681656916570165711657216573165741657516576165771657816579165801658116582165831658416585165861658716588165891659016591165921659316594165951659616597165981659916600166011660216603166041660516606166071660816609166101661116612166131661416615166161661716618166191662016621166221662316624166251662616627166281662916630166311663216633166341663516636166371663816639166401664116642166431664416645166461664716648166491665016651166521665316654166551665616657166581665916660166611666216663166641666516666166671666816669166701667116672166731667416675166761667716678166791668016681166821668316684166851668616687166881668916690166911669216693166941669516696166971669816699167001670116702167031670416705167061670716708167091671016711167121671316714167151671616717167181671916720167211672216723167241672516726167271672816729167301673116732167331673416735167361673716738167391674016741167421674316744167451674616747167481674916750167511675216753167541675516756167571675816759167601676116762167631676416765167661676716768167691677016771167721677316774167751677616777167781677916780167811678216783167841678516786167871678816789167901679116792167931679416795167961679716798167991680016801168021680316804168051680616807168081680916810168111681216813168141681516816168171681816819168201682116822168231682416825168261682716828168291683016831168321683316834168351683616837168381683916840168411684216843168441684516846168471684816849168501685116852168531685416855168561685716858168591686016861168621686316864168651686616867168681686916870168711687216873168741687516876168771687816879168801688116882168831688416885168861688716888168891689016891168921689316894168951689616897168981689916900169011690216903169041690516906169071690816909169101691116912169131691416915169161691716918169191692016921169221692316924169251692616927169281692916930169311693216933169341693516936169371693816939169401694116942169431694416945169461694716948169491695016951169521695316954169551695616957169581695916960169611696216963169641696516966169671696816969169701697116972169731697416975169761697716978169791698016981169821698316984169851698616987169881698916990169911699216993169941699516996169971699816999170001700117002170031700417005170061700717008170091701017011170121701317014170151701617017170181701917020170211702217023170241702517026170271702817029170301703117032170331703417035170361703717038170391704017041170421704317044170451704617047170481704917050170511705217053170541705517056170571705817059170601706117062170631706417065170661706717068170691707017071170721707317074170751707617077170781707917080170811708217083170841708517086170871708817089170901709117092170931709417095170961709717098170991710017101171021710317104171051710617107171081710917110171111711217113171141711517116171171711817119171201712117122171231712417125171261712717128171291713017131171321713317134171351713617137171381713917140171411714217143171441714517146171471714817149171501715117152171531715417155171561715717158171591716017161171621716317164171651716617167171681716917170171711717217173171741717517176171771717817179171801718117182171831718417185171861718717188171891719017191171921719317194171951719617197171981719917200172011720217203172041720517206172071720817209172101721117212172131721417215172161721717218172191722017221172221722317224172251722617227172281722917230172311723217233172341723517236172371723817239172401724117242172431724417245172461724717248172491725017251172521725317254172551725617257172581725917260172611726217263172641726517266172671726817269172701727117272172731727417275172761727717278172791728017281172821728317284172851728617287172881728917290172911729217293172941729517296172971729817299173001730117302173031730417305173061730717308173091731017311173121731317314173151731617317173181731917320173211732217323173241732517326173271732817329173301733117332173331733417335173361733717338173391734017341173421734317344173451734617347173481734917350173511735217353173541735517356173571735817359173601736117362173631736417365173661736717368173691737017371173721737317374173751737617377173781737917380173811738217383173841738517386173871738817389173901739117392173931739417395173961739717398173991740017401174021740317404174051740617407174081740917410174111741217413174141741517416174171741817419174201742117422174231742417425174261742717428174291743017431174321743317434174351743617437174381743917440174411744217443174441744517446174471744817449174501745117452174531745417455174561745717458174591746017461174621746317464174651746617467174681746917470174711747217473174741747517476174771747817479174801748117482174831748417485174861748717488174891749017491174921749317494174951749617497174981749917500175011750217503175041750517506175071750817509175101751117512175131751417515175161751717518175191752017521175221752317524175251752617527175281752917530175311753217533175341753517536175371753817539175401754117542175431754417545175461754717548175491755017551175521755317554175551755617557175581755917560175611756217563175641756517566175671756817569175701757117572175731757417575175761757717578175791758017581175821758317584175851758617587175881758917590175911759217593175941759517596175971759817599176001760117602176031760417605176061760717608176091761017611176121761317614176151761617617176181761917620176211762217623176241762517626176271762817629176301763117632176331763417635176361763717638176391764017641176421764317644176451764617647176481764917650176511765217653176541765517656176571765817659176601766117662176631766417665176661766717668176691767017671176721767317674176751767617677176781767917680176811768217683176841768517686176871768817689176901769117692176931769417695176961769717698176991770017701177021770317704177051770617707177081770917710177111771217713177141771517716177171771817719177201772117722177231772417725177261772717728177291773017731177321773317734177351773617737177381773917740177411774217743177441774517746177471774817749177501775117752177531775417755177561775717758177591776017761177621776317764177651776617767177681776917770177711777217773177741777517776177771777817779177801778117782177831778417785177861778717788177891779017791177921779317794177951779617797177981779917800178011780217803178041780517806178071780817809178101781117812178131781417815178161781717818178191782017821178221782317824178251782617827178281782917830178311783217833178341783517836178371783817839178401784117842178431784417845178461784717848178491785017851178521785317854178551785617857178581785917860178611786217863178641786517866178671786817869178701787117872178731787417875178761787717878178791788017881178821788317884178851788617887178881788917890178911789217893178941789517896178971789817899179001790117902179031790417905179061790717908179091791017911179121791317914179151791617917179181791917920179211792217923179241792517926179271792817929179301793117932179331793417935179361793717938179391794017941179421794317944179451794617947179481794917950179511795217953179541795517956179571795817959179601796117962179631796417965179661796717968179691797017971179721797317974179751797617977179781797917980179811798217983179841798517986179871798817989179901799117992179931799417995179961799717998179991800018001180021800318004180051800618007180081800918010180111801218013180141801518016180171801818019180201802118022180231802418025180261802718028180291803018031180321803318034180351803618037180381803918040180411804218043180441804518046180471804818049180501805118052180531805418055180561805718058180591806018061180621806318064180651806618067180681806918070180711807218073180741807518076180771807818079180801808118082180831808418085180861808718088180891809018091180921809318094180951809618097180981809918100181011810218103181041810518106181071810818109181101811118112181131811418115181161811718118181191812018121181221812318124181251812618127181281812918130181311813218133181341813518136181371813818139181401814118142181431814418145181461814718148181491815018151181521815318154181551815618157181581815918160181611816218163181641816518166181671816818169181701817118172181731817418175181761817718178181791818018181181821818318184181851818618187181881818918190181911819218193181941819518196181971819818199182001820118202182031820418205182061820718208182091821018211182121821318214182151821618217182181821918220182211822218223182241822518226182271822818229182301823118232182331823418235182361823718238182391824018241182421824318244182451824618247182481824918250182511825218253182541825518256182571825818259182601826118262182631826418265182661826718268182691827018271182721827318274182751827618277182781827918280182811828218283182841828518286182871828818289182901829118292182931829418295182961829718298182991830018301183021830318304183051830618307183081830918310183111831218313183141831518316183171831818319183201832118322183231832418325183261832718328183291833018331183321833318334183351833618337183381833918340183411834218343183441834518346183471834818349183501835118352183531835418355183561835718358183591836018361183621836318364183651836618367183681836918370183711837218373183741837518376183771837818379183801838118382183831838418385183861838718388183891839018391183921839318394183951839618397183981839918400184011840218403184041840518406184071840818409184101841118412184131841418415184161841718418184191842018421184221842318424184251842618427184281842918430184311843218433184341843518436184371843818439184401844118442184431844418445184461844718448184491845018451184521845318454184551845618457184581845918460184611846218463184641846518466184671846818469184701847118472184731847418475184761847718478184791848018481184821848318484184851848618487184881848918490184911849218493184941849518496184971849818499185001850118502185031850418505185061850718508185091851018511185121851318514185151851618517185181851918520185211852218523185241852518526185271852818529185301853118532185331853418535185361853718538185391854018541185421854318544185451854618547185481854918550185511855218553185541855518556185571855818559185601856118562185631856418565185661856718568185691857018571185721857318574185751857618577185781857918580185811858218583185841858518586185871858818589185901859118592185931859418595185961859718598185991860018601186021860318604186051860618607186081860918610186111861218613186141861518616186171861818619186201862118622186231862418625186261862718628186291863018631186321863318634186351863618637186381863918640186411864218643186441864518646186471864818649186501865118652186531865418655186561865718658186591866018661186621866318664186651866618667186681866918670186711867218673186741867518676186771867818679186801868118682186831868418685186861868718688186891869018691186921869318694186951869618697186981869918700187011870218703187041870518706187071870818709187101871118712187131871418715187161871718718187191872018721187221872318724187251872618727187281872918730187311873218733187341873518736187371873818739187401874118742187431874418745187461874718748187491875018751187521875318754187551875618757187581875918760187611876218763187641876518766187671876818769187701877118772187731877418775187761877718778187791878018781187821878318784187851878618787187881878918790187911879218793187941879518796187971879818799188001880118802188031880418805188061880718808188091881018811188121881318814188151881618817188181881918820188211882218823188241882518826188271882818829188301883118832188331883418835188361883718838188391884018841188421884318844188451884618847188481884918850188511885218853188541885518856188571885818859188601886118862188631886418865188661886718868188691887018871188721887318874188751887618877188781887918880188811888218883188841888518886188871888818889188901889118892188931889418895188961889718898188991890018901189021890318904189051890618907189081890918910189111891218913189141891518916189171891818919189201892118922189231892418925189261892718928189291893018931189321893318934189351893618937189381893918940189411894218943189441894518946189471894818949189501895118952189531895418955189561895718958189591896018961189621896318964189651896618967189681896918970189711897218973189741897518976189771897818979189801898118982189831898418985189861898718988189891899018991189921899318994189951899618997189981899919000190011900219003190041900519006190071900819009190101901119012190131901419015190161901719018190191902019021190221902319024190251902619027190281902919030190311903219033190341903519036190371903819039190401904119042190431904419045190461904719048190491905019051190521905319054190551905619057190581905919060190611906219063190641906519066190671906819069190701907119072190731907419075190761907719078190791908019081190821908319084190851908619087190881908919090190911909219093190941909519096190971909819099191001910119102191031910419105191061910719108191091911019111191121911319114191151911619117191181911919120191211912219123191241912519126191271912819129191301913119132191331913419135191361913719138191391914019141191421914319144191451914619147191481914919150191511915219153191541915519156191571915819159191601916119162191631916419165191661916719168191691917019171191721917319174191751917619177191781917919180191811918219183191841918519186191871918819189191901919119192191931919419195191961919719198191991920019201192021920319204192051920619207192081920919210192111921219213192141921519216192171921819219192201922119222192231922419225192261922719228192291923019231192321923319234192351923619237192381923919240192411924219243192441924519246192471924819249192501925119252192531925419255192561925719258192591926019261192621926319264192651926619267192681926919270192711927219273192741927519276192771927819279192801928119282192831928419285192861928719288192891929019291192921929319294192951929619297192981929919300193011930219303193041930519306193071930819309193101931119312193131931419315193161931719318193191932019321193221932319324193251932619327193281932919330193311933219333193341933519336193371933819339193401934119342193431934419345193461934719348193491935019351193521935319354193551935619357193581935919360193611936219363193641936519366193671936819369193701937119372193731937419375193761937719378193791938019381193821938319384193851938619387193881938919390193911939219393193941939519396193971939819399194001940119402194031940419405194061940719408194091941019411194121941319414194151941619417194181941919420194211942219423194241942519426194271942819429194301943119432194331943419435194361943719438194391944019441194421944319444194451944619447194481944919450194511945219453194541945519456194571945819459194601946119462194631946419465194661946719468194691947019471194721947319474194751947619477194781947919480194811948219483194841948519486194871948819489194901949119492194931949419495194961949719498194991950019501195021950319504195051950619507195081950919510195111951219513195141951519516195171951819519195201952119522195231952419525195261952719528195291953019531195321953319534195351953619537195381953919540195411954219543195441954519546195471954819549195501955119552195531955419555195561955719558195591956019561195621956319564195651956619567195681956919570195711957219573195741957519576195771957819579195801958119582195831958419585195861958719588195891959019591195921959319594195951959619597195981959919600196011960219603196041960519606196071960819609196101961119612196131961419615196161961719618196191962019621196221962319624196251962619627196281962919630196311963219633196341963519636196371963819639196401964119642196431964419645196461964719648196491965019651196521965319654196551965619657196581965919660196611966219663196641966519666196671966819669196701967119672196731967419675196761967719678196791968019681196821968319684196851968619687196881968919690196911969219693196941969519696196971969819699197001970119702197031970419705197061970719708197091971019711197121971319714197151971619717197181971919720197211972219723197241972519726197271972819729197301973119732197331973419735197361973719738197391974019741197421974319744197451974619747197481974919750197511975219753197541975519756197571975819759197601976119762197631976419765197661976719768197691977019771197721977319774197751977619777197781977919780197811978219783197841978519786197871978819789197901979119792197931979419795197961979719798197991980019801198021980319804198051980619807198081980919810198111981219813198141981519816198171981819819198201982119822198231982419825198261982719828198291983019831198321983319834198351983619837198381983919840198411984219843198441984519846198471984819849198501985119852198531985419855198561985719858198591986019861198621986319864198651986619867198681986919870198711987219873198741987519876198771987819879198801988119882198831988419885198861988719888198891989019891198921989319894198951989619897198981989919900199011990219903199041990519906199071990819909199101991119912199131991419915199161991719918199191992019921199221992319924199251992619927199281992919930199311993219933199341993519936199371993819939199401994119942199431994419945199461994719948199491995019951199521995319954199551995619957199581995919960199611996219963199641996519966199671996819969199701997119972199731997419975199761997719978199791998019981199821998319984199851998619987199881998919990199911999219993199941999519996199971999819999200002000120002200032000420005200062000720008200092001020011200122001320014200152001620017200182001920020200212002220023200242002520026200272002820029200302003120032200332003420035200362003720038200392004020041200422004320044200452004620047200482004920050200512005220053200542005520056200572005820059200602006120062200632006420065200662006720068200692007020071200722007320074200752007620077200782007920080200812008220083200842008520086200872008820089200902009120092200932009420095200962009720098200992010020101201022010320104201052010620107201082010920110201112011220113201142011520116201172011820119201202012120122201232012420125201262012720128201292013020131201322013320134201352013620137201382013920140201412014220143201442014520146201472014820149201502015120152201532015420155201562015720158201592016020161201622016320164201652016620167201682016920170201712017220173201742017520176201772017820179201802018120182201832018420185201862018720188201892019020191201922019320194201952019620197201982019920200202012020220203202042020520206202072020820209202102021120212202132021420215202162021720218202192022020221202222022320224202252022620227202282022920230202312023220233202342023520236202372023820239202402024120242202432024420245202462024720248202492025020251202522025320254202552025620257202582025920260202612026220263202642026520266202672026820269202702027120272202732027420275202762027720278202792028020281202822028320284202852028620287202882028920290202912029220293202942029520296202972029820299203002030120302203032030420305203062030720308203092031020311203122031320314203152031620317203182031920320203212032220323203242032520326203272032820329203302033120332203332033420335203362033720338203392034020341203422034320344203452034620347203482034920350203512035220353203542035520356203572035820359203602036120362203632036420365203662036720368203692037020371203722037320374203752037620377203782037920380203812038220383203842038520386203872038820389203902039120392203932039420395203962039720398203992040020401204022040320404204052040620407204082040920410204112041220413204142041520416204172041820419204202042120422204232042420425204262042720428204292043020431204322043320434204352043620437204382043920440204412044220443204442044520446204472044820449204502045120452204532045420455204562045720458204592046020461204622046320464204652046620467204682046920470204712047220473204742047520476204772047820479204802048120482204832048420485204862048720488204892049020491204922049320494204952049620497204982049920500205012050220503205042050520506205072050820509205102051120512205132051420515205162051720518205192052020521205222052320524205252052620527205282052920530205312053220533205342053520536205372053820539205402054120542205432054420545205462054720548205492055020551205522055320554205552055620557205582055920560205612056220563205642056520566205672056820569205702057120572205732057420575205762057720578205792058020581205822058320584205852058620587205882058920590205912059220593205942059520596205972059820599206002060120602206032060420605206062060720608206092061020611206122061320614206152061620617206182061920620206212062220623206242062520626206272062820629206302063120632206332063420635206362063720638206392064020641206422064320644206452064620647206482064920650206512065220653206542065520656206572065820659206602066120662206632066420665206662066720668206692067020671206722067320674206752067620677206782067920680206812068220683206842068520686206872068820689206902069120692206932069420695206962069720698206992070020701207022070320704207052070620707207082070920710207112071220713207142071520716207172071820719207202072120722207232072420725207262072720728207292073020731207322073320734207352073620737207382073920740207412074220743207442074520746207472074820749207502075120752207532075420755207562075720758207592076020761207622076320764207652076620767207682076920770207712077220773207742077520776207772077820779207802078120782207832078420785207862078720788207892079020791207922079320794207952079620797207982079920800208012080220803208042080520806208072080820809208102081120812208132081420815208162081720818208192082020821208222082320824208252082620827208282082920830208312083220833208342083520836208372083820839208402084120842208432084420845208462084720848208492085020851208522085320854208552085620857208582085920860208612086220863208642086520866208672086820869208702087120872208732087420875208762087720878208792088020881208822088320884208852088620887208882088920890208912089220893208942089520896208972089820899209002090120902209032090420905209062090720908209092091020911209122091320914209152091620917209182091920920209212092220923209242092520926209272092820929209302093120932209332093420935209362093720938209392094020941209422094320944209452094620947209482094920950209512095220953209542095520956209572095820959209602096120962209632096420965209662096720968209692097020971209722097320974209752097620977209782097920980209812098220983209842098520986209872098820989209902099120992209932099420995209962099720998209992100021001210022100321004210052100621007210082100921010210112101221013210142101521016210172101821019210202102121022210232102421025210262102721028210292103021031210322103321034210352103621037210382103921040210412104221043210442104521046210472104821049210502105121052210532105421055210562105721058210592106021061210622106321064210652106621067210682106921070210712107221073210742107521076210772107821079210802108121082210832108421085210862108721088210892109021091210922109321094210952109621097210982109921100211012110221103211042110521106211072110821109211102111121112211132111421115211162111721118211192112021121211222112321124211252112621127211282112921130211312113221133211342113521136211372113821139211402114121142211432114421145211462114721148211492115021151211522115321154211552115621157211582115921160211612116221163211642116521166211672116821169211702117121172211732117421175211762117721178211792118021181211822118321184211852118621187211882118921190211912119221193211942119521196211972119821199212002120121202212032120421205212062120721208212092121021211212122121321214212152121621217212182121921220212212122221223212242122521226212272122821229212302123121232212332123421235212362123721238212392124021241212422124321244212452124621247212482124921250212512125221253212542125521256212572125821259212602126121262212632126421265212662126721268212692127021271212722127321274212752127621277212782127921280212812128221283212842128521286212872128821289212902129121292212932129421295212962129721298212992130021301213022130321304213052130621307213082130921310213112131221313213142131521316213172131821319213202132121322213232132421325213262132721328213292133021331213322133321334213352133621337213382133921340213412134221343213442134521346213472134821349213502135121352213532135421355213562135721358213592136021361213622136321364213652136621367213682136921370213712137221373213742137521376213772137821379213802138121382213832138421385213862138721388213892139021391213922139321394213952139621397213982139921400214012140221403214042140521406214072140821409214102141121412214132141421415214162141721418214192142021421214222142321424214252142621427214282142921430214312143221433214342143521436214372143821439214402144121442214432144421445214462144721448214492145021451214522145321454214552145621457214582145921460214612146221463214642146521466214672146821469214702147121472214732147421475214762147721478214792148021481214822148321484214852148621487214882148921490214912149221493214942149521496214972149821499215002150121502215032150421505215062150721508215092151021511215122151321514215152151621517215182151921520215212152221523215242152521526215272152821529215302153121532215332153421535215362153721538215392154021541215422154321544215452154621547215482154921550215512155221553215542155521556215572155821559215602156121562215632156421565215662156721568215692157021571215722157321574215752157621577215782157921580215812158221583215842158521586215872158821589215902159121592215932159421595215962159721598215992160021601216022160321604216052160621607216082160921610216112161221613216142161521616216172161821619216202162121622216232162421625216262162721628216292163021631216322163321634216352163621637216382163921640216412164221643216442164521646216472164821649216502165121652216532165421655216562165721658216592166021661216622166321664216652166621667216682166921670216712167221673216742167521676216772167821679216802168121682216832168421685216862168721688216892169021691216922169321694216952169621697216982169921700217012170221703217042170521706217072170821709217102171121712217132171421715217162171721718217192172021721217222172321724217252172621727217282172921730217312173221733217342173521736217372173821739217402174121742217432174421745217462174721748217492175021751217522175321754217552175621757217582175921760217612176221763217642176521766217672176821769217702177121772217732177421775217762177721778217792178021781217822178321784217852178621787217882178921790217912179221793217942179521796217972179821799218002180121802218032180421805218062180721808218092181021811218122181321814218152181621817218182181921820218212182221823218242182521826218272182821829218302183121832218332183421835218362183721838218392184021841218422184321844218452184621847218482184921850218512185221853218542185521856218572185821859218602186121862218632186421865218662186721868218692187021871218722187321874218752187621877218782187921880218812188221883218842188521886218872188821889218902189121892218932189421895218962189721898218992190021901219022190321904219052190621907219082190921910219112191221913219142191521916219172191821919219202192121922219232192421925219262192721928219292193021931219322193321934219352193621937219382193921940219412194221943219442194521946219472194821949219502195121952219532195421955219562195721958219592196021961219622196321964219652196621967219682196921970219712197221973219742197521976219772197821979219802198121982219832198421985219862198721988219892199021991219922199321994219952199621997219982199922000220012200222003220042200522006220072200822009220102201122012220132201422015220162201722018220192202022021220222202322024220252202622027220282202922030220312203222033220342203522036220372203822039220402204122042220432204422045220462204722048220492205022051220522205322054220552205622057220582205922060220612206222063220642206522066220672206822069220702207122072220732207422075220762207722078220792208022081220822208322084220852208622087220882208922090220912209222093220942209522096220972209822099221002210122102221032210422105221062210722108221092211022111221122211322114221152211622117221182211922120221212212222123221242212522126221272212822129221302213122132221332213422135221362213722138221392214022141221422214322144221452214622147221482214922150221512215222153221542215522156221572215822159221602216122162221632216422165221662216722168221692217022171221722217322174221752217622177221782217922180221812218222183221842218522186221872218822189221902219122192221932219422195221962219722198221992220022201222022220322204222052220622207222082220922210222112221222213222142221522216222172221822219222202222122222222232222422225222262222722228222292223022231222322223322234222352223622237222382223922240222412224222243222442224522246222472224822249222502225122252222532225422255222562225722258222592226022261222622226322264222652226622267222682226922270222712227222273222742227522276222772227822279222802228122282222832228422285222862228722288222892229022291222922229322294222952229622297222982229922300223012230222303223042230522306223072230822309223102231122312223132231422315223162231722318223192232022321223222232322324223252232622327223282232922330223312233222333223342233522336223372233822339223402234122342223432234422345223462234722348223492235022351223522235322354223552235622357223582235922360223612236222363223642236522366223672236822369223702237122372223732237422375223762237722378223792238022381223822238322384223852238622387223882238922390223912239222393223942239522396223972239822399224002240122402224032240422405224062240722408224092241022411224122241322414224152241622417224182241922420224212242222423224242242522426224272242822429224302243122432224332243422435224362243722438224392244022441224422244322444224452244622447224482244922450224512245222453224542245522456224572245822459224602246122462224632246422465224662246722468224692247022471224722247322474224752247622477224782247922480224812248222483224842248522486224872248822489224902249122492224932249422495224962249722498224992250022501225022250322504225052250622507225082250922510225112251222513225142251522516225172251822519225202252122522225232252422525225262252722528225292253022531225322253322534225352253622537225382253922540225412254222543225442254522546225472254822549225502255122552225532255422555225562255722558225592256022561225622256322564225652256622567225682256922570225712257222573225742257522576225772257822579225802258122582225832258422585225862258722588225892259022591225922259322594225952259622597225982259922600226012260222603226042260522606226072260822609226102261122612226132261422615226162261722618226192262022621226222262322624226252262622627226282262922630226312263222633226342263522636226372263822639226402264122642226432264422645226462264722648226492265022651226522265322654226552265622657226582265922660226612266222663226642266522666226672266822669226702267122672226732267422675226762267722678226792268022681226822268322684226852268622687226882268922690226912269222693226942269522696226972269822699227002270122702227032270422705227062270722708227092271022711227122271322714227152271622717227182271922720227212272222723227242272522726227272272822729227302273122732227332273422735227362273722738227392274022741227422274322744227452274622747227482274922750227512275222753227542275522756227572275822759227602276122762227632276422765227662276722768227692277022771227722277322774227752277622777227782277922780227812278222783227842278522786227872278822789227902279122792227932279422795227962279722798227992280022801228022280322804228052280622807228082280922810228112281222813228142281522816228172281822819228202282122822228232282422825228262282722828228292283022831228322283322834228352283622837228382283922840228412284222843228442284522846228472284822849228502285122852228532285422855228562285722858228592286022861228622286322864228652286622867228682286922870228712287222873228742287522876228772287822879228802288122882228832288422885228862288722888228892289022891228922289322894228952289622897228982289922900229012290222903229042290522906229072290822909229102291122912229132291422915229162291722918229192292022921229222292322924229252292622927229282292922930229312293222933229342293522936229372293822939229402294122942229432294422945229462294722948229492295022951229522295322954229552295622957229582295922960229612296222963229642296522966229672296822969229702297122972229732297422975229762297722978229792298022981229822298322984229852298622987229882298922990229912299222993229942299522996229972299822999230002300123002230032300423005230062300723008230092301023011230122301323014230152301623017230182301923020230212302223023230242302523026230272302823029230302303123032230332303423035230362303723038230392304023041230422304323044230452304623047230482304923050230512305223053230542305523056230572305823059230602306123062230632306423065230662306723068230692307023071230722307323074230752307623077230782307923080230812308223083230842308523086230872308823089230902309123092230932309423095230962309723098230992310023101231022310323104231052310623107231082310923110231112311223113231142311523116231172311823119231202312123122231232312423125231262312723128231292313023131231322313323134231352313623137231382313923140231412314223143231442314523146231472314823149231502315123152231532315423155231562315723158231592316023161231622316323164231652316623167231682316923170231712317223173231742317523176231772317823179231802318123182231832318423185231862318723188231892319023191231922319323194231952319623197231982319923200232012320223203232042320523206232072320823209232102321123212232132321423215232162321723218232192322023221232222322323224232252322623227232282322923230232312323223233232342323523236232372323823239232402324123242232432324423245232462324723248232492325023251232522325323254232552325623257232582325923260232612326223263232642326523266232672326823269232702327123272232732327423275232762327723278232792328023281232822328323284232852328623287232882328923290232912329223293232942329523296232972329823299233002330123302233032330423305233062330723308233092331023311233122331323314233152331623317233182331923320233212332223323233242332523326233272332823329233302333123332233332333423335233362333723338233392334023341233422334323344233452334623347233482334923350233512335223353233542335523356233572335823359233602336123362233632336423365233662336723368233692337023371233722337323374233752337623377233782337923380233812338223383233842338523386233872338823389233902339123392233932339423395233962339723398233992340023401234022340323404234052340623407234082340923410234112341223413234142341523416234172341823419234202342123422234232342423425234262342723428234292343023431234322343323434234352343623437234382343923440234412344223443234442344523446234472344823449234502345123452234532345423455234562345723458234592346023461234622346323464234652346623467234682346923470234712347223473234742347523476234772347823479234802348123482234832348423485234862348723488234892349023491234922349323494234952349623497234982349923500235012350223503235042350523506235072350823509235102351123512235132351423515235162351723518235192352023521235222352323524235252352623527235282352923530235312353223533235342353523536235372353823539235402354123542235432354423545235462354723548235492355023551235522355323554235552355623557235582355923560235612356223563235642356523566235672356823569235702357123572235732357423575235762357723578235792358023581235822358323584235852358623587235882358923590235912359223593235942359523596235972359823599236002360123602236032360423605236062360723608236092361023611236122361323614236152361623617236182361923620236212362223623236242362523626236272362823629236302363123632236332363423635236362363723638236392364023641236422364323644236452364623647236482364923650236512365223653236542365523656236572365823659236602366123662236632366423665236662366723668236692367023671236722367323674236752367623677236782367923680236812368223683236842368523686236872368823689236902369123692236932369423695236962369723698236992370023701237022370323704237052370623707237082370923710237112371223713237142371523716237172371823719237202372123722237232372423725237262372723728237292373023731237322373323734237352373623737237382373923740237412374223743237442374523746237472374823749237502375123752237532375423755237562375723758237592376023761237622376323764237652376623767237682376923770237712377223773237742377523776237772377823779237802378123782237832378423785237862378723788237892379023791237922379323794237952379623797237982379923800238012380223803238042380523806238072380823809238102381123812238132381423815238162381723818238192382023821238222382323824238252382623827238282382923830238312383223833238342383523836238372383823839238402384123842238432384423845238462384723848238492385023851238522385323854238552385623857238582385923860238612386223863238642386523866238672386823869238702387123872238732387423875238762387723878238792388023881238822388323884238852388623887238882388923890238912389223893238942389523896238972389823899239002390123902239032390423905239062390723908239092391023911239122391323914239152391623917239182391923920239212392223923239242392523926239272392823929239302393123932239332393423935239362393723938239392394023941239422394323944239452394623947239482394923950239512395223953239542395523956239572395823959239602396123962239632396423965239662396723968239692397023971239722397323974239752397623977239782397923980239812398223983239842398523986239872398823989239902399123992239932399423995239962399723998239992400024001240022400324004240052400624007240082400924010240112401224013240142401524016240172401824019240202402124022240232402424025240262402724028240292403024031240322403324034240352403624037240382403924040240412404224043240442404524046240472404824049240502405124052240532405424055240562405724058240592406024061240622406324064240652406624067240682406924070240712407224073240742407524076240772407824079240802408124082240832408424085240862408724088240892409024091240922409324094240952409624097240982409924100241012410224103241042410524106241072410824109241102411124112241132411424115241162411724118241192412024121241222412324124241252412624127241282412924130241312413224133241342413524136241372413824139241402414124142241432414424145241462414724148241492415024151241522415324154241552415624157241582415924160241612416224163241642416524166241672416824169241702417124172241732417424175241762417724178241792418024181241822418324184241852418624187241882418924190241912419224193241942419524196241972419824199242002420124202242032420424205242062420724208242092421024211242122421324214242152421624217242182421924220242212422224223242242422524226242272422824229242302423124232242332423424235242362423724238242392424024241242422424324244242452424624247242482424924250242512425224253242542425524256242572425824259242602426124262242632426424265242662426724268242692427024271242722427324274242752427624277242782427924280242812428224283242842428524286242872428824289242902429124292242932429424295242962429724298242992430024301243022430324304243052430624307243082430924310243112431224313243142431524316243172431824319243202432124322243232432424325243262432724328243292433024331243322433324334243352433624337243382433924340243412434224343243442434524346243472434824349243502435124352243532435424355243562435724358243592436024361243622436324364243652436624367243682436924370243712437224373243742437524376243772437824379243802438124382243832438424385243862438724388243892439024391243922439324394243952439624397243982439924400244012440224403244042440524406244072440824409244102441124412244132441424415244162441724418244192442024421244222442324424244252442624427244282442924430244312443224433244342443524436244372443824439244402444124442244432444424445244462444724448244492445024451244522445324454244552445624457244582445924460244612446224463244642446524466244672446824469244702447124472244732447424475244762447724478244792448024481244822448324484244852448624487244882448924490244912449224493244942449524496244972449824499245002450124502245032450424505245062450724508245092451024511245122451324514245152451624517245182451924520245212452224523245242452524526245272452824529245302453124532245332453424535245362453724538245392454024541245422454324544245452454624547245482454924550245512455224553245542455524556245572455824559245602456124562245632456424565245662456724568245692457024571245722457324574245752457624577245782457924580245812458224583245842458524586245872458824589245902459124592245932459424595245962459724598245992460024601246022460324604246052460624607246082460924610246112461224613246142461524616246172461824619246202462124622246232462424625246262462724628246292463024631246322463324634246352463624637246382463924640246412464224643246442464524646246472464824649246502465124652246532465424655246562465724658246592466024661246622466324664246652466624667246682466924670246712467224673246742467524676246772467824679246802468124682246832468424685246862468724688246892469024691246922469324694246952469624697246982469924700247012470224703247042470524706247072470824709247102471124712247132471424715247162471724718247192472024721247222472324724247252472624727247282472924730247312473224733247342473524736247372473824739247402474124742247432474424745247462474724748247492475024751247522475324754247552475624757247582475924760247612476224763247642476524766247672476824769247702477124772247732477424775247762477724778247792478024781247822478324784247852478624787247882478924790247912479224793247942479524796247972479824799248002480124802248032480424805248062480724808248092481024811248122481324814248152481624817248182481924820248212482224823248242482524826248272482824829248302483124832248332483424835248362483724838248392484024841248422484324844248452484624847248482484924850248512485224853248542485524856248572485824859248602486124862248632486424865248662486724868248692487024871248722487324874248752487624877248782487924880248812488224883248842488524886248872488824889248902489124892248932489424895248962489724898248992490024901249022490324904249052490624907249082490924910249112491224913249142491524916249172491824919249202492124922249232492424925249262492724928249292493024931249322493324934249352493624937249382493924940249412494224943249442494524946249472494824949249502495124952249532495424955249562495724958249592496024961249622496324964249652496624967249682496924970249712497224973249742497524976249772497824979249802498124982249832498424985249862498724988249892499024991249922499324994249952499624997249982499925000250012500225003250042500525006250072500825009250102501125012250132501425015250162501725018250192502025021250222502325024250252502625027250282502925030250312503225033250342503525036250372503825039250402504125042250432504425045250462504725048250492505025051250522505325054250552505625057250582505925060250612506225063250642506525066250672506825069250702507125072250732507425075250762507725078250792508025081250822508325084250852508625087250882508925090250912509225093250942509525096250972509825099251002510125102251032510425105251062510725108251092511025111251122511325114251152511625117251182511925120251212512225123251242512525126251272512825129251302513125132251332513425135251362513725138251392514025141251422514325144251452514625147251482514925150251512515225153251542515525156251572515825159251602516125162251632516425165251662516725168251692517025171251722517325174251752517625177251782517925180251812518225183251842518525186251872518825189251902519125192251932519425195251962519725198251992520025201252022520325204252052520625207252082520925210252112521225213252142521525216252172521825219252202522125222252232522425225252262522725228252292523025231252322523325234252352523625237252382523925240252412524225243252442524525246252472524825249252502525125252252532525425255252562525725258252592526025261252622526325264252652526625267252682526925270252712527225273252742527525276252772527825279252802528125282252832528425285252862528725288252892529025291252922529325294252952529625297252982529925300253012530225303253042530525306253072530825309253102531125312253132531425315253162531725318253192532025321253222532325324253252532625327253282532925330253312533225333253342533525336253372533825339253402534125342253432534425345253462534725348253492535025351253522535325354253552535625357253582535925360253612536225363253642536525366253672536825369253702537125372253732537425375253762537725378253792538025381253822538325384253852538625387253882538925390253912539225393253942539525396253972539825399254002540125402254032540425405254062540725408254092541025411254122541325414254152541625417254182541925420254212542225423254242542525426254272542825429254302543125432254332543425435254362543725438254392544025441254422544325444254452544625447254482544925450254512545225453254542545525456254572545825459254602546125462254632546425465254662546725468254692547025471254722547325474254752547625477254782547925480254812548225483254842548525486254872548825489254902549125492254932549425495254962549725498254992550025501255022550325504255052550625507255082550925510255112551225513255142551525516255172551825519255202552125522255232552425525255262552725528255292553025531255322553325534255352553625537255382553925540255412554225543255442554525546255472554825549255502555125552255532555425555255562555725558255592556025561255622556325564255652556625567255682556925570255712557225573255742557525576255772557825579255802558125582255832558425585255862558725588255892559025591255922559325594255952559625597255982559925600256012560225603256042560525606256072560825609256102561125612256132561425615256162561725618256192562025621256222562325624256252562625627256282562925630256312563225633256342563525636256372563825639256402564125642256432564425645256462564725648256492565025651256522565325654256552565625657256582565925660256612566225663256642566525666256672566825669256702567125672256732567425675256762567725678256792568025681256822568325684256852568625687256882568925690256912569225693256942569525696256972569825699257002570125702257032570425705257062570725708257092571025711257122571325714257152571625717257182571925720257212572225723257242572525726257272572825729257302573125732257332573425735257362573725738257392574025741257422574325744257452574625747257482574925750257512575225753257542575525756257572575825759257602576125762257632576425765257662576725768257692577025771257722577325774257752577625777257782577925780257812578225783257842578525786257872578825789257902579125792257932579425795257962579725798257992580025801258022580325804258052580625807258082580925810258112581225813258142581525816258172581825819258202582125822258232582425825258262582725828258292583025831258322583325834258352583625837258382583925840258412584225843258442584525846258472584825849258502585125852258532585425855258562585725858258592586025861258622586325864258652586625867258682586925870258712587225873258742587525876258772587825879258802588125882258832588425885258862588725888258892589025891258922589325894258952589625897258982589925900259012590225903259042590525906259072590825909259102591125912259132591425915259162591725918259192592025921259222592325924259252592625927259282592925930259312593225933259342593525936259372593825939259402594125942259432594425945259462594725948259492595025951259522595325954259552595625957259582595925960259612596225963259642596525966259672596825969259702597125972259732597425975259762597725978259792598025981259822598325984259852598625987259882598925990259912599225993259942599525996259972599825999260002600126002260032600426005260062600726008260092601026011260122601326014260152601626017260182601926020260212602226023260242602526026260272602826029260302603126032260332603426035260362603726038260392604026041260422604326044260452604626047260482604926050260512605226053260542605526056260572605826059260602606126062260632606426065260662606726068260692607026071260722607326074260752607626077260782607926080260812608226083260842608526086260872608826089260902609126092260932609426095260962609726098260992610026101261022610326104261052610626107261082610926110261112611226113261142611526116261172611826119261202612126122261232612426125261262612726128261292613026131261322613326134261352613626137261382613926140261412614226143261442614526146261472614826149261502615126152261532615426155261562615726158261592616026161261622616326164261652616626167261682616926170261712617226173261742617526176261772617826179261802618126182261832618426185261862618726188261892619026191261922619326194261952619626197261982619926200262012620226203262042620526206262072620826209262102621126212262132621426215262162621726218262192622026221262222622326224262252622626227262282622926230262312623226233262342623526236262372623826239262402624126242262432624426245262462624726248262492625026251262522625326254262552625626257262582625926260262612626226263262642626526266262672626826269262702627126272262732627426275262762627726278262792628026281262822628326284262852628626287262882628926290262912629226293262942629526296262972629826299263002630126302263032630426305263062630726308263092631026311263122631326314263152631626317263182631926320263212632226323263242632526326263272632826329263302633126332263332633426335263362633726338263392634026341263422634326344263452634626347263482634926350263512635226353263542635526356263572635826359263602636126362263632636426365263662636726368263692637026371263722637326374263752637626377263782637926380263812638226383263842638526386263872638826389263902639126392263932639426395263962639726398263992640026401264022640326404264052640626407264082640926410264112641226413264142641526416264172641826419264202642126422264232642426425264262642726428264292643026431264322643326434264352643626437264382643926440264412644226443264442644526446264472644826449264502645126452264532645426455264562645726458264592646026461264622646326464264652646626467264682646926470264712647226473264742647526476264772647826479264802648126482264832648426485264862648726488264892649026491264922649326494264952649626497264982649926500265012650226503265042650526506265072650826509265102651126512265132651426515265162651726518265192652026521265222652326524265252652626527265282652926530265312653226533265342653526536265372653826539265402654126542265432654426545265462654726548265492655026551265522655326554265552655626557265582655926560265612656226563265642656526566265672656826569265702657126572265732657426575265762657726578265792658026581265822658326584265852658626587265882658926590265912659226593265942659526596265972659826599266002660126602266032660426605266062660726608266092661026611266122661326614266152661626617266182661926620266212662226623266242662526626266272662826629266302663126632266332663426635266362663726638266392664026641266422664326644266452664626647266482664926650266512665226653266542665526656266572665826659266602666126662266632666426665266662666726668266692667026671266722667326674266752667626677266782667926680266812668226683266842668526686266872668826689266902669126692266932669426695266962669726698266992670026701267022670326704267052670626707267082670926710267112671226713267142671526716267172671826719267202672126722267232672426725267262672726728267292673026731267322673326734267352673626737267382673926740267412674226743267442674526746267472674826749267502675126752267532675426755267562675726758267592676026761267622676326764267652676626767267682676926770267712677226773267742677526776267772677826779267802678126782267832678426785267862678726788267892679026791267922679326794267952679626797267982679926800268012680226803268042680526806268072680826809268102681126812268132681426815268162681726818268192682026821268222682326824268252682626827268282682926830268312683226833268342683526836268372683826839268402684126842268432684426845268462684726848268492685026851268522685326854268552685626857268582685926860268612686226863268642686526866268672686826869268702687126872268732687426875268762687726878268792688026881268822688326884268852688626887268882688926890268912689226893268942689526896268972689826899269002690126902269032690426905269062690726908269092691026911269122691326914269152691626917269182691926920269212692226923269242692526926269272692826929269302693126932269332693426935269362693726938269392694026941269422694326944269452694626947269482694926950269512695226953269542695526956269572695826959269602696126962269632696426965269662696726968269692697026971269722697326974269752697626977269782697926980269812698226983269842698526986269872698826989269902699126992269932699426995269962699726998269992700027001270022700327004270052700627007270082700927010270112701227013270142701527016270172701827019270202702127022270232702427025270262702727028270292703027031270322703327034270352703627037270382703927040270412704227043270442704527046270472704827049270502705127052270532705427055270562705727058270592706027061270622706327064270652706627067270682706927070270712707227073270742707527076270772707827079270802708127082270832708427085270862708727088270892709027091270922709327094270952709627097270982709927100271012710227103271042710527106271072710827109271102711127112271132711427115271162711727118271192712027121271222712327124271252712627127271282712927130271312713227133271342713527136271372713827139271402714127142271432714427145271462714727148271492715027151271522715327154271552715627157271582715927160271612716227163271642716527166271672716827169271702717127172271732717427175271762717727178271792718027181271822718327184271852718627187271882718927190271912719227193271942719527196271972719827199272002720127202272032720427205272062720727208272092721027211272122721327214272152721627217272182721927220272212722227223272242722527226272272722827229272302723127232272332723427235272362723727238272392724027241272422724327244272452724627247272482724927250272512725227253272542725527256272572725827259272602726127262272632726427265272662726727268272692727027271272722727327274272752727627277272782727927280272812728227283272842728527286272872728827289272902729127292272932729427295272962729727298272992730027301273022730327304273052730627307273082730927310273112731227313273142731527316273172731827319273202732127322273232732427325273262732727328273292733027331273322733327334273352733627337273382733927340273412734227343273442734527346273472734827349273502735127352273532735427355273562735727358273592736027361273622736327364273652736627367273682736927370273712737227373273742737527376273772737827379273802738127382273832738427385273862738727388273892739027391273922739327394273952739627397273982739927400274012740227403274042740527406274072740827409274102741127412274132741427415274162741727418274192742027421274222742327424274252742627427274282742927430274312743227433274342743527436274372743827439274402744127442274432744427445274462744727448274492745027451274522745327454274552745627457274582745927460274612746227463274642746527466274672746827469274702747127472274732747427475274762747727478274792748027481274822748327484274852748627487274882748927490274912749227493274942749527496274972749827499275002750127502275032750427505275062750727508275092751027511275122751327514275152751627517275182751927520275212752227523275242752527526275272752827529275302753127532275332753427535275362753727538275392754027541275422754327544275452754627547275482754927550275512755227553275542755527556275572755827559275602756127562275632756427565275662756727568275692757027571275722757327574275752757627577275782757927580275812758227583275842758527586275872758827589275902759127592275932759427595275962759727598275992760027601276022760327604276052760627607276082760927610276112761227613276142761527616276172761827619276202762127622276232762427625276262762727628276292763027631276322763327634276352763627637276382763927640276412764227643276442764527646276472764827649276502765127652276532765427655276562765727658276592766027661276622766327664276652766627667276682766927670276712767227673276742767527676276772767827679276802768127682276832768427685276862768727688276892769027691276922769327694276952769627697276982769927700277012770227703277042770527706277072770827709277102771127712277132771427715277162771727718277192772027721277222772327724277252772627727277282772927730277312773227733277342773527736277372773827739277402774127742277432774427745277462774727748277492775027751277522775327754277552775627757277582775927760277612776227763277642776527766277672776827769277702777127772277732777427775277762777727778277792778027781277822778327784277852778627787277882778927790277912779227793277942779527796277972779827799278002780127802278032780427805278062780727808278092781027811278122781327814278152781627817278182781927820278212782227823278242782527826278272782827829278302783127832278332783427835278362783727838278392784027841278422784327844278452784627847278482784927850278512785227853278542785527856278572785827859278602786127862278632786427865278662786727868278692787027871278722787327874278752787627877278782787927880278812788227883278842788527886278872788827889278902789127892278932789427895278962789727898278992790027901279022790327904279052790627907279082790927910279112791227913279142791527916279172791827919279202792127922279232792427925279262792727928279292793027931279322793327934279352793627937279382793927940279412794227943279442794527946279472794827949279502795127952279532795427955279562795727958279592796027961279622796327964279652796627967279682796927970279712797227973279742797527976279772797827979279802798127982279832798427985279862798727988279892799027991279922799327994279952799627997279982799928000280012800228003280042800528006280072800828009280102801128012280132801428015280162801728018280192802028021280222802328024280252802628027280282802928030280312803228033280342803528036280372803828039280402804128042280432804428045280462804728048280492805028051280522805328054280552805628057280582805928060280612806228063280642806528066280672806828069280702807128072280732807428075280762807728078280792808028081280822808328084280852808628087280882808928090280912809228093280942809528096280972809828099281002810128102281032810428105281062810728108281092811028111281122811328114281152811628117281182811928120281212812228123281242812528126281272812828129281302813128132281332813428135281362813728138281392814028141281422814328144281452814628147281482814928150281512815228153281542815528156281572815828159281602816128162281632816428165281662816728168281692817028171281722817328174281752817628177281782817928180281812818228183281842818528186281872818828189281902819128192281932819428195281962819728198281992820028201282022820328204282052820628207282082820928210282112821228213282142821528216282172821828219282202822128222282232822428225282262822728228282292823028231282322823328234282352823628237282382823928240282412824228243282442824528246282472824828249282502825128252282532825428255282562825728258282592826028261282622826328264282652826628267282682826928270282712827228273282742827528276282772827828279282802828128282282832828428285282862828728288282892829028291282922829328294282952829628297282982829928300283012830228303283042830528306283072830828309283102831128312283132831428315283162831728318283192832028321283222832328324283252832628327283282832928330283312833228333283342833528336283372833828339283402834128342283432834428345283462834728348283492835028351283522835328354283552835628357283582835928360283612836228363283642836528366283672836828369283702837128372283732837428375283762837728378283792838028381283822838328384283852838628387283882838928390283912839228393283942839528396283972839828399284002840128402284032840428405284062840728408284092841028411284122841328414284152841628417284182841928420284212842228423284242842528426284272842828429284302843128432284332843428435284362843728438284392844028441284422844328444284452844628447284482844928450284512845228453284542845528456284572845828459284602846128462284632846428465284662846728468284692847028471284722847328474284752847628477284782847928480284812848228483284842848528486284872848828489284902849128492284932849428495284962849728498284992850028501285022850328504285052850628507285082850928510285112851228513285142851528516285172851828519285202852128522285232852428525285262852728528285292853028531285322853328534285352853628537285382853928540285412854228543285442854528546285472854828549285502855128552285532855428555285562855728558285592856028561285622856328564285652856628567285682856928570285712857228573285742857528576285772857828579285802858128582285832858428585285862858728588285892859028591285922859328594285952859628597285982859928600286012860228603286042860528606286072860828609286102861128612286132861428615286162861728618286192862028621286222862328624286252862628627286282862928630286312863228633286342863528636286372863828639286402864128642286432864428645286462864728648286492865028651286522865328654286552865628657286582865928660286612866228663286642866528666286672866828669286702867128672286732867428675286762867728678286792868028681286822868328684286852868628687286882868928690286912869228693286942869528696
  1. /**
  2. * TinyMCE version 6.3.1 (2022-12-06)
  3. */
  4. (function () {
  5. 'use strict';
  6. const getPrototypeOf$2 = Object.getPrototypeOf;
  7. const hasProto = (v, constructor, predicate) => {
  8. var _a;
  9. if (predicate(v, constructor.prototype)) {
  10. return true;
  11. } else {
  12. return ((_a = v.constructor) === null || _a === void 0 ? void 0 : _a.name) === constructor.name;
  13. }
  14. };
  15. const typeOf = x => {
  16. const t = typeof x;
  17. if (x === null) {
  18. return 'null';
  19. } else if (t === 'object' && Array.isArray(x)) {
  20. return 'array';
  21. } else if (t === 'object' && hasProto(x, String, (o, proto) => proto.isPrototypeOf(o))) {
  22. return 'string';
  23. } else {
  24. return t;
  25. }
  26. };
  27. const isType$1 = type => value => typeOf(value) === type;
  28. const isSimpleType = type => value => typeof value === type;
  29. const eq$1 = t => a => t === a;
  30. const is$2 = (value, constructor) => isObject(value) && hasProto(value, constructor, (o, proto) => getPrototypeOf$2(o) === proto);
  31. const isString = isType$1('string');
  32. const isObject = isType$1('object');
  33. const isPlainObject = value => is$2(value, Object);
  34. const isArray = isType$1('array');
  35. const isNull = eq$1(null);
  36. const isBoolean = isSimpleType('boolean');
  37. const isUndefined = eq$1(undefined);
  38. const isNullable = a => a === null || a === undefined;
  39. const isNonNullable = a => !isNullable(a);
  40. const isFunction = isSimpleType('function');
  41. const isNumber = isSimpleType('number');
  42. const isArrayOf = (value, pred) => {
  43. if (isArray(value)) {
  44. for (let i = 0, len = value.length; i < len; ++i) {
  45. if (!pred(value[i])) {
  46. return false;
  47. }
  48. }
  49. return true;
  50. }
  51. return false;
  52. };
  53. const noop = () => {
  54. };
  55. const noarg = f => () => f();
  56. const compose = (fa, fb) => {
  57. return (...args) => {
  58. return fa(fb.apply(null, args));
  59. };
  60. };
  61. const compose1 = (fbc, fab) => a => fbc(fab(a));
  62. const constant$1 = value => {
  63. return () => {
  64. return value;
  65. };
  66. };
  67. const identity = x => {
  68. return x;
  69. };
  70. const tripleEquals = (a, b) => {
  71. return a === b;
  72. };
  73. function curry(fn, ...initialArgs) {
  74. return (...restArgs) => {
  75. const all = initialArgs.concat(restArgs);
  76. return fn.apply(null, all);
  77. };
  78. }
  79. const not = f => t => !f(t);
  80. const die = msg => {
  81. return () => {
  82. throw new Error(msg);
  83. };
  84. };
  85. const apply$1 = f => {
  86. return f();
  87. };
  88. const never = constant$1(false);
  89. const always = constant$1(true);
  90. var global$a = tinymce.util.Tools.resolve('tinymce.ThemeManager');
  91. class Optional {
  92. constructor(tag, value) {
  93. this.tag = tag;
  94. this.value = value;
  95. }
  96. static some(value) {
  97. return new Optional(true, value);
  98. }
  99. static none() {
  100. return Optional.singletonNone;
  101. }
  102. fold(onNone, onSome) {
  103. if (this.tag) {
  104. return onSome(this.value);
  105. } else {
  106. return onNone();
  107. }
  108. }
  109. isSome() {
  110. return this.tag;
  111. }
  112. isNone() {
  113. return !this.tag;
  114. }
  115. map(mapper) {
  116. if (this.tag) {
  117. return Optional.some(mapper(this.value));
  118. } else {
  119. return Optional.none();
  120. }
  121. }
  122. bind(binder) {
  123. if (this.tag) {
  124. return binder(this.value);
  125. } else {
  126. return Optional.none();
  127. }
  128. }
  129. exists(predicate) {
  130. return this.tag && predicate(this.value);
  131. }
  132. forall(predicate) {
  133. return !this.tag || predicate(this.value);
  134. }
  135. filter(predicate) {
  136. if (!this.tag || predicate(this.value)) {
  137. return this;
  138. } else {
  139. return Optional.none();
  140. }
  141. }
  142. getOr(replacement) {
  143. return this.tag ? this.value : replacement;
  144. }
  145. or(replacement) {
  146. return this.tag ? this : replacement;
  147. }
  148. getOrThunk(thunk) {
  149. return this.tag ? this.value : thunk();
  150. }
  151. orThunk(thunk) {
  152. return this.tag ? this : thunk();
  153. }
  154. getOrDie(message) {
  155. if (!this.tag) {
  156. throw new Error(message !== null && message !== void 0 ? message : 'Called getOrDie on None');
  157. } else {
  158. return this.value;
  159. }
  160. }
  161. static from(value) {
  162. return isNonNullable(value) ? Optional.some(value) : Optional.none();
  163. }
  164. getOrNull() {
  165. return this.tag ? this.value : null;
  166. }
  167. getOrUndefined() {
  168. return this.value;
  169. }
  170. each(worker) {
  171. if (this.tag) {
  172. worker(this.value);
  173. }
  174. }
  175. toArray() {
  176. return this.tag ? [this.value] : [];
  177. }
  178. toString() {
  179. return this.tag ? `some(${ this.value })` : 'none()';
  180. }
  181. }
  182. Optional.singletonNone = new Optional(false);
  183. const nativeSlice = Array.prototype.slice;
  184. const nativeIndexOf = Array.prototype.indexOf;
  185. const nativePush = Array.prototype.push;
  186. const rawIndexOf = (ts, t) => nativeIndexOf.call(ts, t);
  187. const indexOf = (xs, x) => {
  188. const r = rawIndexOf(xs, x);
  189. return r === -1 ? Optional.none() : Optional.some(r);
  190. };
  191. const contains$2 = (xs, x) => rawIndexOf(xs, x) > -1;
  192. const exists = (xs, pred) => {
  193. for (let i = 0, len = xs.length; i < len; i++) {
  194. const x = xs[i];
  195. if (pred(x, i)) {
  196. return true;
  197. }
  198. }
  199. return false;
  200. };
  201. const range$2 = (num, f) => {
  202. const r = [];
  203. for (let i = 0; i < num; i++) {
  204. r.push(f(i));
  205. }
  206. return r;
  207. };
  208. const chunk$1 = (array, size) => {
  209. const r = [];
  210. for (let i = 0; i < array.length; i += size) {
  211. const s = nativeSlice.call(array, i, i + size);
  212. r.push(s);
  213. }
  214. return r;
  215. };
  216. const map$2 = (xs, f) => {
  217. const len = xs.length;
  218. const r = new Array(len);
  219. for (let i = 0; i < len; i++) {
  220. const x = xs[i];
  221. r[i] = f(x, i);
  222. }
  223. return r;
  224. };
  225. const each$1 = (xs, f) => {
  226. for (let i = 0, len = xs.length; i < len; i++) {
  227. const x = xs[i];
  228. f(x, i);
  229. }
  230. };
  231. const eachr = (xs, f) => {
  232. for (let i = xs.length - 1; i >= 0; i--) {
  233. const x = xs[i];
  234. f(x, i);
  235. }
  236. };
  237. const partition$3 = (xs, pred) => {
  238. const pass = [];
  239. const fail = [];
  240. for (let i = 0, len = xs.length; i < len; i++) {
  241. const x = xs[i];
  242. const arr = pred(x, i) ? pass : fail;
  243. arr.push(x);
  244. }
  245. return {
  246. pass,
  247. fail
  248. };
  249. };
  250. const filter$2 = (xs, pred) => {
  251. const r = [];
  252. for (let i = 0, len = xs.length; i < len; i++) {
  253. const x = xs[i];
  254. if (pred(x, i)) {
  255. r.push(x);
  256. }
  257. }
  258. return r;
  259. };
  260. const foldr = (xs, f, acc) => {
  261. eachr(xs, (x, i) => {
  262. acc = f(acc, x, i);
  263. });
  264. return acc;
  265. };
  266. const foldl = (xs, f, acc) => {
  267. each$1(xs, (x, i) => {
  268. acc = f(acc, x, i);
  269. });
  270. return acc;
  271. };
  272. const findUntil = (xs, pred, until) => {
  273. for (let i = 0, len = xs.length; i < len; i++) {
  274. const x = xs[i];
  275. if (pred(x, i)) {
  276. return Optional.some(x);
  277. } else if (until(x, i)) {
  278. break;
  279. }
  280. }
  281. return Optional.none();
  282. };
  283. const find$5 = (xs, pred) => {
  284. return findUntil(xs, pred, never);
  285. };
  286. const findIndex$1 = (xs, pred) => {
  287. for (let i = 0, len = xs.length; i < len; i++) {
  288. const x = xs[i];
  289. if (pred(x, i)) {
  290. return Optional.some(i);
  291. }
  292. }
  293. return Optional.none();
  294. };
  295. const flatten = xs => {
  296. const r = [];
  297. for (let i = 0, len = xs.length; i < len; ++i) {
  298. if (!isArray(xs[i])) {
  299. throw new Error('Arr.flatten item ' + i + ' was not an array, input: ' + xs);
  300. }
  301. nativePush.apply(r, xs[i]);
  302. }
  303. return r;
  304. };
  305. const bind$3 = (xs, f) => flatten(map$2(xs, f));
  306. const forall = (xs, pred) => {
  307. for (let i = 0, len = xs.length; i < len; ++i) {
  308. const x = xs[i];
  309. if (pred(x, i) !== true) {
  310. return false;
  311. }
  312. }
  313. return true;
  314. };
  315. const reverse = xs => {
  316. const r = nativeSlice.call(xs, 0);
  317. r.reverse();
  318. return r;
  319. };
  320. const difference = (a1, a2) => filter$2(a1, x => !contains$2(a2, x));
  321. const mapToObject = (xs, f) => {
  322. const r = {};
  323. for (let i = 0, len = xs.length; i < len; i++) {
  324. const x = xs[i];
  325. r[String(x)] = f(x, i);
  326. }
  327. return r;
  328. };
  329. const pure$2 = x => [x];
  330. const sort = (xs, comparator) => {
  331. const copy = nativeSlice.call(xs, 0);
  332. copy.sort(comparator);
  333. return copy;
  334. };
  335. const get$h = (xs, i) => i >= 0 && i < xs.length ? Optional.some(xs[i]) : Optional.none();
  336. const head = xs => get$h(xs, 0);
  337. const last$1 = xs => get$h(xs, xs.length - 1);
  338. const from = isFunction(Array.from) ? Array.from : x => nativeSlice.call(x);
  339. const findMap = (arr, f) => {
  340. for (let i = 0; i < arr.length; i++) {
  341. const r = f(arr[i], i);
  342. if (r.isSome()) {
  343. return r;
  344. }
  345. }
  346. return Optional.none();
  347. };
  348. const keys = Object.keys;
  349. const hasOwnProperty$1 = Object.hasOwnProperty;
  350. const each = (obj, f) => {
  351. const props = keys(obj);
  352. for (let k = 0, len = props.length; k < len; k++) {
  353. const i = props[k];
  354. const x = obj[i];
  355. f(x, i);
  356. }
  357. };
  358. const map$1 = (obj, f) => {
  359. return tupleMap(obj, (x, i) => ({
  360. k: i,
  361. v: f(x, i)
  362. }));
  363. };
  364. const tupleMap = (obj, f) => {
  365. const r = {};
  366. each(obj, (x, i) => {
  367. const tuple = f(x, i);
  368. r[tuple.k] = tuple.v;
  369. });
  370. return r;
  371. };
  372. const objAcc = r => (x, i) => {
  373. r[i] = x;
  374. };
  375. const internalFilter = (obj, pred, onTrue, onFalse) => {
  376. each(obj, (x, i) => {
  377. (pred(x, i) ? onTrue : onFalse)(x, i);
  378. });
  379. };
  380. const bifilter = (obj, pred) => {
  381. const t = {};
  382. const f = {};
  383. internalFilter(obj, pred, objAcc(t), objAcc(f));
  384. return {
  385. t,
  386. f
  387. };
  388. };
  389. const filter$1 = (obj, pred) => {
  390. const t = {};
  391. internalFilter(obj, pred, objAcc(t), noop);
  392. return t;
  393. };
  394. const mapToArray = (obj, f) => {
  395. const r = [];
  396. each(obj, (value, name) => {
  397. r.push(f(value, name));
  398. });
  399. return r;
  400. };
  401. const find$4 = (obj, pred) => {
  402. const props = keys(obj);
  403. for (let k = 0, len = props.length; k < len; k++) {
  404. const i = props[k];
  405. const x = obj[i];
  406. if (pred(x, i, obj)) {
  407. return Optional.some(x);
  408. }
  409. }
  410. return Optional.none();
  411. };
  412. const values = obj => {
  413. return mapToArray(obj, identity);
  414. };
  415. const get$g = (obj, key) => {
  416. return has$2(obj, key) ? Optional.from(obj[key]) : Optional.none();
  417. };
  418. const has$2 = (obj, key) => hasOwnProperty$1.call(obj, key);
  419. const hasNonNullableKey = (obj, key) => has$2(obj, key) && obj[key] !== undefined && obj[key] !== null;
  420. const is$1 = (lhs, rhs, comparator = tripleEquals) => lhs.exists(left => comparator(left, rhs));
  421. const equals = (lhs, rhs, comparator = tripleEquals) => lift2(lhs, rhs, comparator).getOr(lhs.isNone() && rhs.isNone());
  422. const cat = arr => {
  423. const r = [];
  424. const push = x => {
  425. r.push(x);
  426. };
  427. for (let i = 0; i < arr.length; i++) {
  428. arr[i].each(push);
  429. }
  430. return r;
  431. };
  432. const sequence = arr => {
  433. const r = [];
  434. for (let i = 0; i < arr.length; i++) {
  435. const x = arr[i];
  436. if (x.isSome()) {
  437. r.push(x.getOrDie());
  438. } else {
  439. return Optional.none();
  440. }
  441. }
  442. return Optional.some(r);
  443. };
  444. const lift2 = (oa, ob, f) => oa.isSome() && ob.isSome() ? Optional.some(f(oa.getOrDie(), ob.getOrDie())) : Optional.none();
  445. const lift3 = (oa, ob, oc, f) => oa.isSome() && ob.isSome() && oc.isSome() ? Optional.some(f(oa.getOrDie(), ob.getOrDie(), oc.getOrDie())) : Optional.none();
  446. const mapFrom = (a, f) => a !== undefined && a !== null ? Optional.some(f(a)) : Optional.none();
  447. const someIf = (b, a) => b ? Optional.some(a) : Optional.none();
  448. const addToEnd = (str, suffix) => {
  449. return str + suffix;
  450. };
  451. const removeFromStart = (str, numChars) => {
  452. return str.substring(numChars);
  453. };
  454. const checkRange = (str, substr, start) => substr === '' || str.length >= substr.length && str.substr(start, start + substr.length) === substr;
  455. const removeLeading = (str, prefix) => {
  456. return startsWith(str, prefix) ? removeFromStart(str, prefix.length) : str;
  457. };
  458. const ensureTrailing = (str, suffix) => {
  459. return endsWith(str, suffix) ? str : addToEnd(str, suffix);
  460. };
  461. const contains$1 = (str, substr, start = 0, end) => {
  462. const idx = str.indexOf(substr, start);
  463. if (idx !== -1) {
  464. return isUndefined(end) ? true : idx + substr.length <= end;
  465. } else {
  466. return false;
  467. }
  468. };
  469. const startsWith = (str, prefix) => {
  470. return checkRange(str, prefix, 0);
  471. };
  472. const endsWith = (str, suffix) => {
  473. return checkRange(str, suffix, str.length - suffix.length);
  474. };
  475. const blank = r => s => s.replace(r, '');
  476. const trim$1 = blank(/^\s+|\s+$/g);
  477. const isNotEmpty = s => s.length > 0;
  478. const isEmpty = s => !isNotEmpty(s);
  479. const isSupported$1 = dom => dom.style !== undefined && isFunction(dom.style.getPropertyValue);
  480. const fromHtml$2 = (html, scope) => {
  481. const doc = scope || document;
  482. const div = doc.createElement('div');
  483. div.innerHTML = html;
  484. if (!div.hasChildNodes() || div.childNodes.length > 1) {
  485. const message = 'HTML does not have a single root node';
  486. console.error(message, html);
  487. throw new Error(message);
  488. }
  489. return fromDom(div.childNodes[0]);
  490. };
  491. const fromTag = (tag, scope) => {
  492. const doc = scope || document;
  493. const node = doc.createElement(tag);
  494. return fromDom(node);
  495. };
  496. const fromText = (text, scope) => {
  497. const doc = scope || document;
  498. const node = doc.createTextNode(text);
  499. return fromDom(node);
  500. };
  501. const fromDom = node => {
  502. if (node === null || node === undefined) {
  503. throw new Error('Node cannot be null or undefined');
  504. }
  505. return { dom: node };
  506. };
  507. const fromPoint = (docElm, x, y) => Optional.from(docElm.dom.elementFromPoint(x, y)).map(fromDom);
  508. const SugarElement = {
  509. fromHtml: fromHtml$2,
  510. fromTag,
  511. fromText,
  512. fromDom,
  513. fromPoint
  514. };
  515. const Global = typeof window !== 'undefined' ? window : Function('return this;')();
  516. const path$1 = (parts, scope) => {
  517. let o = scope !== undefined && scope !== null ? scope : Global;
  518. for (let i = 0; i < parts.length && o !== undefined && o !== null; ++i) {
  519. o = o[parts[i]];
  520. }
  521. return o;
  522. };
  523. const resolve = (p, scope) => {
  524. const parts = p.split('.');
  525. return path$1(parts, scope);
  526. };
  527. const unsafe = (name, scope) => {
  528. return resolve(name, scope);
  529. };
  530. const getOrDie$1 = (name, scope) => {
  531. const actual = unsafe(name, scope);
  532. if (actual === undefined || actual === null) {
  533. throw new Error(name + ' not available on this browser');
  534. }
  535. return actual;
  536. };
  537. const getPrototypeOf$1 = Object.getPrototypeOf;
  538. const sandHTMLElement = scope => {
  539. return getOrDie$1('HTMLElement', scope);
  540. };
  541. const isPrototypeOf = x => {
  542. const scope = resolve('ownerDocument.defaultView', x);
  543. return isObject(x) && (sandHTMLElement(scope).prototype.isPrototypeOf(x) || /^HTML\w*Element$/.test(getPrototypeOf$1(x).constructor.name));
  544. };
  545. const DOCUMENT = 9;
  546. const DOCUMENT_FRAGMENT = 11;
  547. const ELEMENT = 1;
  548. const TEXT = 3;
  549. const name$3 = element => {
  550. const r = element.dom.nodeName;
  551. return r.toLowerCase();
  552. };
  553. const type$1 = element => element.dom.nodeType;
  554. const isType = t => element => type$1(element) === t;
  555. const isHTMLElement = element => isElement$1(element) && isPrototypeOf(element.dom);
  556. const isElement$1 = isType(ELEMENT);
  557. const isText = isType(TEXT);
  558. const isDocument = isType(DOCUMENT);
  559. const isDocumentFragment = isType(DOCUMENT_FRAGMENT);
  560. const isTag = tag => e => isElement$1(e) && name$3(e) === tag;
  561. const is = (element, selector) => {
  562. const dom = element.dom;
  563. if (dom.nodeType !== ELEMENT) {
  564. return false;
  565. } else {
  566. const elem = dom;
  567. if (elem.matches !== undefined) {
  568. return elem.matches(selector);
  569. } else if (elem.msMatchesSelector !== undefined) {
  570. return elem.msMatchesSelector(selector);
  571. } else if (elem.webkitMatchesSelector !== undefined) {
  572. return elem.webkitMatchesSelector(selector);
  573. } else if (elem.mozMatchesSelector !== undefined) {
  574. return elem.mozMatchesSelector(selector);
  575. } else {
  576. throw new Error('Browser lacks native selectors');
  577. }
  578. }
  579. };
  580. const bypassSelector = dom => dom.nodeType !== ELEMENT && dom.nodeType !== DOCUMENT && dom.nodeType !== DOCUMENT_FRAGMENT || dom.childElementCount === 0;
  581. const all$3 = (selector, scope) => {
  582. const base = scope === undefined ? document : scope.dom;
  583. return bypassSelector(base) ? [] : map$2(base.querySelectorAll(selector), SugarElement.fromDom);
  584. };
  585. const one = (selector, scope) => {
  586. const base = scope === undefined ? document : scope.dom;
  587. return bypassSelector(base) ? Optional.none() : Optional.from(base.querySelector(selector)).map(SugarElement.fromDom);
  588. };
  589. const eq = (e1, e2) => e1.dom === e2.dom;
  590. const contains = (e1, e2) => {
  591. const d1 = e1.dom;
  592. const d2 = e2.dom;
  593. return d1 === d2 ? false : d1.contains(d2);
  594. };
  595. const owner$4 = element => SugarElement.fromDom(element.dom.ownerDocument);
  596. const documentOrOwner = dos => isDocument(dos) ? dos : owner$4(dos);
  597. const documentElement = element => SugarElement.fromDom(documentOrOwner(element).dom.documentElement);
  598. const defaultView = element => SugarElement.fromDom(documentOrOwner(element).dom.defaultView);
  599. const parent = element => Optional.from(element.dom.parentNode).map(SugarElement.fromDom);
  600. const parentElement = element => Optional.from(element.dom.parentElement).map(SugarElement.fromDom);
  601. const offsetParent = element => Optional.from(element.dom.offsetParent).map(SugarElement.fromDom);
  602. const nextSibling = element => Optional.from(element.dom.nextSibling).map(SugarElement.fromDom);
  603. const children = element => map$2(element.dom.childNodes, SugarElement.fromDom);
  604. const child$2 = (element, index) => {
  605. const cs = element.dom.childNodes;
  606. return Optional.from(cs[index]).map(SugarElement.fromDom);
  607. };
  608. const firstChild = element => child$2(element, 0);
  609. const spot = (element, offset) => ({
  610. element,
  611. offset
  612. });
  613. const leaf = (element, offset) => {
  614. const cs = children(element);
  615. return cs.length > 0 && offset < cs.length ? spot(cs[offset], 0) : spot(element, offset);
  616. };
  617. const isShadowRoot = dos => isDocumentFragment(dos) && isNonNullable(dos.dom.host);
  618. const supported = isFunction(Element.prototype.attachShadow) && isFunction(Node.prototype.getRootNode);
  619. const isSupported = constant$1(supported);
  620. const getRootNode = supported ? e => SugarElement.fromDom(e.dom.getRootNode()) : documentOrOwner;
  621. const getContentContainer = dos => isShadowRoot(dos) ? dos : SugarElement.fromDom(documentOrOwner(dos).dom.body);
  622. const isInShadowRoot = e => getShadowRoot(e).isSome();
  623. const getShadowRoot = e => {
  624. const r = getRootNode(e);
  625. return isShadowRoot(r) ? Optional.some(r) : Optional.none();
  626. };
  627. const getShadowHost = e => SugarElement.fromDom(e.dom.host);
  628. const getOriginalEventTarget = event => {
  629. if (isSupported() && isNonNullable(event.target)) {
  630. const el = SugarElement.fromDom(event.target);
  631. if (isElement$1(el) && isOpenShadowHost(el)) {
  632. if (event.composed && event.composedPath) {
  633. const composedPath = event.composedPath();
  634. if (composedPath) {
  635. return head(composedPath);
  636. }
  637. }
  638. }
  639. }
  640. return Optional.from(event.target);
  641. };
  642. const isOpenShadowHost = element => isNonNullable(element.dom.shadowRoot);
  643. const inBody = element => {
  644. const dom = isText(element) ? element.dom.parentNode : element.dom;
  645. if (dom === undefined || dom === null || dom.ownerDocument === null) {
  646. return false;
  647. }
  648. const doc = dom.ownerDocument;
  649. return getShadowRoot(SugarElement.fromDom(dom)).fold(() => doc.body.contains(dom), compose1(inBody, getShadowHost));
  650. };
  651. const body = () => getBody(SugarElement.fromDom(document));
  652. const getBody = doc => {
  653. const b = doc.dom.body;
  654. if (b === null || b === undefined) {
  655. throw new Error('Body is not available yet');
  656. }
  657. return SugarElement.fromDom(b);
  658. };
  659. const rawSet = (dom, key, value) => {
  660. if (isString(value) || isBoolean(value) || isNumber(value)) {
  661. dom.setAttribute(key, value + '');
  662. } else {
  663. console.error('Invalid call to Attribute.set. Key ', key, ':: Value ', value, ':: Element ', dom);
  664. throw new Error('Attribute value was not simple');
  665. }
  666. };
  667. const set$9 = (element, key, value) => {
  668. rawSet(element.dom, key, value);
  669. };
  670. const setAll$1 = (element, attrs) => {
  671. const dom = element.dom;
  672. each(attrs, (v, k) => {
  673. rawSet(dom, k, v);
  674. });
  675. };
  676. const get$f = (element, key) => {
  677. const v = element.dom.getAttribute(key);
  678. return v === null ? undefined : v;
  679. };
  680. const getOpt = (element, key) => Optional.from(get$f(element, key));
  681. const has$1 = (element, key) => {
  682. const dom = element.dom;
  683. return dom && dom.hasAttribute ? dom.hasAttribute(key) : false;
  684. };
  685. const remove$7 = (element, key) => {
  686. element.dom.removeAttribute(key);
  687. };
  688. const clone$2 = element => foldl(element.dom.attributes, (acc, attr) => {
  689. acc[attr.name] = attr.value;
  690. return acc;
  691. }, {});
  692. const internalSet = (dom, property, value) => {
  693. if (!isString(value)) {
  694. console.error('Invalid call to CSS.set. Property ', property, ':: Value ', value, ':: Element ', dom);
  695. throw new Error('CSS value must be a string: ' + value);
  696. }
  697. if (isSupported$1(dom)) {
  698. dom.style.setProperty(property, value);
  699. }
  700. };
  701. const internalRemove = (dom, property) => {
  702. if (isSupported$1(dom)) {
  703. dom.style.removeProperty(property);
  704. }
  705. };
  706. const set$8 = (element, property, value) => {
  707. const dom = element.dom;
  708. internalSet(dom, property, value);
  709. };
  710. const setAll = (element, css) => {
  711. const dom = element.dom;
  712. each(css, (v, k) => {
  713. internalSet(dom, k, v);
  714. });
  715. };
  716. const setOptions = (element, css) => {
  717. const dom = element.dom;
  718. each(css, (v, k) => {
  719. v.fold(() => {
  720. internalRemove(dom, k);
  721. }, value => {
  722. internalSet(dom, k, value);
  723. });
  724. });
  725. };
  726. const get$e = (element, property) => {
  727. const dom = element.dom;
  728. const styles = window.getComputedStyle(dom);
  729. const r = styles.getPropertyValue(property);
  730. return r === '' && !inBody(element) ? getUnsafeProperty(dom, property) : r;
  731. };
  732. const getUnsafeProperty = (dom, property) => isSupported$1(dom) ? dom.style.getPropertyValue(property) : '';
  733. const getRaw = (element, property) => {
  734. const dom = element.dom;
  735. const raw = getUnsafeProperty(dom, property);
  736. return Optional.from(raw).filter(r => r.length > 0);
  737. };
  738. const getAllRaw = element => {
  739. const css = {};
  740. const dom = element.dom;
  741. if (isSupported$1(dom)) {
  742. for (let i = 0; i < dom.style.length; i++) {
  743. const ruleName = dom.style.item(i);
  744. css[ruleName] = dom.style[ruleName];
  745. }
  746. }
  747. return css;
  748. };
  749. const isValidValue = (tag, property, value) => {
  750. const element = SugarElement.fromTag(tag);
  751. set$8(element, property, value);
  752. const style = getRaw(element, property);
  753. return style.isSome();
  754. };
  755. const remove$6 = (element, property) => {
  756. const dom = element.dom;
  757. internalRemove(dom, property);
  758. if (is$1(getOpt(element, 'style').map(trim$1), '')) {
  759. remove$7(element, 'style');
  760. }
  761. };
  762. const reflow = e => e.dom.offsetWidth;
  763. const Dimension = (name, getOffset) => {
  764. const set = (element, h) => {
  765. if (!isNumber(h) && !h.match(/^[0-9]+$/)) {
  766. throw new Error(name + '.set accepts only positive integer values. Value was ' + h);
  767. }
  768. const dom = element.dom;
  769. if (isSupported$1(dom)) {
  770. dom.style[name] = h + 'px';
  771. }
  772. };
  773. const get = element => {
  774. const r = getOffset(element);
  775. if (r <= 0 || r === null) {
  776. const css = get$e(element, name);
  777. return parseFloat(css) || 0;
  778. }
  779. return r;
  780. };
  781. const getOuter = get;
  782. const aggregate = (element, properties) => foldl(properties, (acc, property) => {
  783. const val = get$e(element, property);
  784. const value = val === undefined ? 0 : parseInt(val, 10);
  785. return isNaN(value) ? acc : acc + value;
  786. }, 0);
  787. const max = (element, value, properties) => {
  788. const cumulativeInclusions = aggregate(element, properties);
  789. const absoluteMax = value > cumulativeInclusions ? value - cumulativeInclusions : 0;
  790. return absoluteMax;
  791. };
  792. return {
  793. set,
  794. get,
  795. getOuter,
  796. aggregate,
  797. max
  798. };
  799. };
  800. const api$2 = Dimension('height', element => {
  801. const dom = element.dom;
  802. return inBody(element) ? dom.getBoundingClientRect().height : dom.offsetHeight;
  803. });
  804. const get$d = element => api$2.get(element);
  805. const getOuter$2 = element => api$2.getOuter(element);
  806. const setMax$1 = (element, value) => {
  807. const inclusions = [
  808. 'margin-top',
  809. 'border-top-width',
  810. 'padding-top',
  811. 'padding-bottom',
  812. 'border-bottom-width',
  813. 'margin-bottom'
  814. ];
  815. const absMax = api$2.max(element, value, inclusions);
  816. set$8(element, 'max-height', absMax + 'px');
  817. };
  818. const r$1 = (left, top) => {
  819. const translate = (x, y) => r$1(left + x, top + y);
  820. return {
  821. left,
  822. top,
  823. translate
  824. };
  825. };
  826. const SugarPosition = r$1;
  827. const boxPosition = dom => {
  828. const box = dom.getBoundingClientRect();
  829. return SugarPosition(box.left, box.top);
  830. };
  831. const firstDefinedOrZero = (a, b) => {
  832. if (a !== undefined) {
  833. return a;
  834. } else {
  835. return b !== undefined ? b : 0;
  836. }
  837. };
  838. const absolute$3 = element => {
  839. const doc = element.dom.ownerDocument;
  840. const body = doc.body;
  841. const win = doc.defaultView;
  842. const html = doc.documentElement;
  843. if (body === element.dom) {
  844. return SugarPosition(body.offsetLeft, body.offsetTop);
  845. }
  846. const scrollTop = firstDefinedOrZero(win === null || win === void 0 ? void 0 : win.pageYOffset, html.scrollTop);
  847. const scrollLeft = firstDefinedOrZero(win === null || win === void 0 ? void 0 : win.pageXOffset, html.scrollLeft);
  848. const clientTop = firstDefinedOrZero(html.clientTop, body.clientTop);
  849. const clientLeft = firstDefinedOrZero(html.clientLeft, body.clientLeft);
  850. return viewport$1(element).translate(scrollLeft - clientLeft, scrollTop - clientTop);
  851. };
  852. const viewport$1 = element => {
  853. const dom = element.dom;
  854. const doc = dom.ownerDocument;
  855. const body = doc.body;
  856. if (body === dom) {
  857. return SugarPosition(body.offsetLeft, body.offsetTop);
  858. }
  859. if (!inBody(element)) {
  860. return SugarPosition(0, 0);
  861. }
  862. return boxPosition(dom);
  863. };
  864. const api$1 = Dimension('width', element => element.dom.offsetWidth);
  865. const set$7 = (element, h) => api$1.set(element, h);
  866. const get$c = element => api$1.get(element);
  867. const getOuter$1 = element => api$1.getOuter(element);
  868. const setMax = (element, value) => {
  869. const inclusions = [
  870. 'margin-left',
  871. 'border-left-width',
  872. 'padding-left',
  873. 'padding-right',
  874. 'border-right-width',
  875. 'margin-right'
  876. ];
  877. const absMax = api$1.max(element, value, inclusions);
  878. set$8(element, 'max-width', absMax + 'px');
  879. };
  880. const cached = f => {
  881. let called = false;
  882. let r;
  883. return (...args) => {
  884. if (!called) {
  885. called = true;
  886. r = f.apply(null, args);
  887. }
  888. return r;
  889. };
  890. };
  891. const DeviceType = (os, browser, userAgent, mediaMatch) => {
  892. const isiPad = os.isiOS() && /ipad/i.test(userAgent) === true;
  893. const isiPhone = os.isiOS() && !isiPad;
  894. const isMobile = os.isiOS() || os.isAndroid();
  895. const isTouch = isMobile || mediaMatch('(pointer:coarse)');
  896. const isTablet = isiPad || !isiPhone && isMobile && mediaMatch('(min-device-width:768px)');
  897. const isPhone = isiPhone || isMobile && !isTablet;
  898. const iOSwebview = browser.isSafari() && os.isiOS() && /safari/i.test(userAgent) === false;
  899. const isDesktop = !isPhone && !isTablet && !iOSwebview;
  900. return {
  901. isiPad: constant$1(isiPad),
  902. isiPhone: constant$1(isiPhone),
  903. isTablet: constant$1(isTablet),
  904. isPhone: constant$1(isPhone),
  905. isTouch: constant$1(isTouch),
  906. isAndroid: os.isAndroid,
  907. isiOS: os.isiOS,
  908. isWebView: constant$1(iOSwebview),
  909. isDesktop: constant$1(isDesktop)
  910. };
  911. };
  912. const firstMatch = (regexes, s) => {
  913. for (let i = 0; i < regexes.length; i++) {
  914. const x = regexes[i];
  915. if (x.test(s)) {
  916. return x;
  917. }
  918. }
  919. return undefined;
  920. };
  921. const find$3 = (regexes, agent) => {
  922. const r = firstMatch(regexes, agent);
  923. if (!r) {
  924. return {
  925. major: 0,
  926. minor: 0
  927. };
  928. }
  929. const group = i => {
  930. return Number(agent.replace(r, '$' + i));
  931. };
  932. return nu$d(group(1), group(2));
  933. };
  934. const detect$4 = (versionRegexes, agent) => {
  935. const cleanedAgent = String(agent).toLowerCase();
  936. if (versionRegexes.length === 0) {
  937. return unknown$3();
  938. }
  939. return find$3(versionRegexes, cleanedAgent);
  940. };
  941. const unknown$3 = () => {
  942. return nu$d(0, 0);
  943. };
  944. const nu$d = (major, minor) => {
  945. return {
  946. major,
  947. minor
  948. };
  949. };
  950. const Version = {
  951. nu: nu$d,
  952. detect: detect$4,
  953. unknown: unknown$3
  954. };
  955. const detectBrowser$1 = (browsers, userAgentData) => {
  956. return findMap(userAgentData.brands, uaBrand => {
  957. const lcBrand = uaBrand.brand.toLowerCase();
  958. return find$5(browsers, browser => {
  959. var _a;
  960. return lcBrand === ((_a = browser.brand) === null || _a === void 0 ? void 0 : _a.toLowerCase());
  961. }).map(info => ({
  962. current: info.name,
  963. version: Version.nu(parseInt(uaBrand.version, 10), 0)
  964. }));
  965. });
  966. };
  967. const detect$3 = (candidates, userAgent) => {
  968. const agent = String(userAgent).toLowerCase();
  969. return find$5(candidates, candidate => {
  970. return candidate.search(agent);
  971. });
  972. };
  973. const detectBrowser = (browsers, userAgent) => {
  974. return detect$3(browsers, userAgent).map(browser => {
  975. const version = Version.detect(browser.versionRegexes, userAgent);
  976. return {
  977. current: browser.name,
  978. version
  979. };
  980. });
  981. };
  982. const detectOs = (oses, userAgent) => {
  983. return detect$3(oses, userAgent).map(os => {
  984. const version = Version.detect(os.versionRegexes, userAgent);
  985. return {
  986. current: os.name,
  987. version
  988. };
  989. });
  990. };
  991. const normalVersionRegex = /.*?version\/\ ?([0-9]+)\.([0-9]+).*/;
  992. const checkContains = target => {
  993. return uastring => {
  994. return contains$1(uastring, target);
  995. };
  996. };
  997. const browsers = [
  998. {
  999. name: 'Edge',
  1000. versionRegexes: [/.*?edge\/ ?([0-9]+)\.([0-9]+)$/],
  1001. search: uastring => {
  1002. return contains$1(uastring, 'edge/') && contains$1(uastring, 'chrome') && contains$1(uastring, 'safari') && contains$1(uastring, 'applewebkit');
  1003. }
  1004. },
  1005. {
  1006. name: 'Chromium',
  1007. brand: 'Chromium',
  1008. versionRegexes: [
  1009. /.*?chrome\/([0-9]+)\.([0-9]+).*/,
  1010. normalVersionRegex
  1011. ],
  1012. search: uastring => {
  1013. return contains$1(uastring, 'chrome') && !contains$1(uastring, 'chromeframe');
  1014. }
  1015. },
  1016. {
  1017. name: 'IE',
  1018. versionRegexes: [
  1019. /.*?msie\ ?([0-9]+)\.([0-9]+).*/,
  1020. /.*?rv:([0-9]+)\.([0-9]+).*/
  1021. ],
  1022. search: uastring => {
  1023. return contains$1(uastring, 'msie') || contains$1(uastring, 'trident');
  1024. }
  1025. },
  1026. {
  1027. name: 'Opera',
  1028. versionRegexes: [
  1029. normalVersionRegex,
  1030. /.*?opera\/([0-9]+)\.([0-9]+).*/
  1031. ],
  1032. search: checkContains('opera')
  1033. },
  1034. {
  1035. name: 'Firefox',
  1036. versionRegexes: [/.*?firefox\/\ ?([0-9]+)\.([0-9]+).*/],
  1037. search: checkContains('firefox')
  1038. },
  1039. {
  1040. name: 'Safari',
  1041. versionRegexes: [
  1042. normalVersionRegex,
  1043. /.*?cpu os ([0-9]+)_([0-9]+).*/
  1044. ],
  1045. search: uastring => {
  1046. return (contains$1(uastring, 'safari') || contains$1(uastring, 'mobile/')) && contains$1(uastring, 'applewebkit');
  1047. }
  1048. }
  1049. ];
  1050. const oses = [
  1051. {
  1052. name: 'Windows',
  1053. search: checkContains('win'),
  1054. versionRegexes: [/.*?windows\ nt\ ?([0-9]+)\.([0-9]+).*/]
  1055. },
  1056. {
  1057. name: 'iOS',
  1058. search: uastring => {
  1059. return contains$1(uastring, 'iphone') || contains$1(uastring, 'ipad');
  1060. },
  1061. versionRegexes: [
  1062. /.*?version\/\ ?([0-9]+)\.([0-9]+).*/,
  1063. /.*cpu os ([0-9]+)_([0-9]+).*/,
  1064. /.*cpu iphone os ([0-9]+)_([0-9]+).*/
  1065. ]
  1066. },
  1067. {
  1068. name: 'Android',
  1069. search: checkContains('android'),
  1070. versionRegexes: [/.*?android\ ?([0-9]+)\.([0-9]+).*/]
  1071. },
  1072. {
  1073. name: 'macOS',
  1074. search: checkContains('mac os x'),
  1075. versionRegexes: [/.*?mac\ os\ x\ ?([0-9]+)_([0-9]+).*/]
  1076. },
  1077. {
  1078. name: 'Linux',
  1079. search: checkContains('linux'),
  1080. versionRegexes: []
  1081. },
  1082. {
  1083. name: 'Solaris',
  1084. search: checkContains('sunos'),
  1085. versionRegexes: []
  1086. },
  1087. {
  1088. name: 'FreeBSD',
  1089. search: checkContains('freebsd'),
  1090. versionRegexes: []
  1091. },
  1092. {
  1093. name: 'ChromeOS',
  1094. search: checkContains('cros'),
  1095. versionRegexes: [/.*?chrome\/([0-9]+)\.([0-9]+).*/]
  1096. }
  1097. ];
  1098. const PlatformInfo = {
  1099. browsers: constant$1(browsers),
  1100. oses: constant$1(oses)
  1101. };
  1102. const edge = 'Edge';
  1103. const chromium = 'Chromium';
  1104. const ie = 'IE';
  1105. const opera = 'Opera';
  1106. const firefox = 'Firefox';
  1107. const safari = 'Safari';
  1108. const unknown$2 = () => {
  1109. return nu$c({
  1110. current: undefined,
  1111. version: Version.unknown()
  1112. });
  1113. };
  1114. const nu$c = info => {
  1115. const current = info.current;
  1116. const version = info.version;
  1117. const isBrowser = name => () => current === name;
  1118. return {
  1119. current,
  1120. version,
  1121. isEdge: isBrowser(edge),
  1122. isChromium: isBrowser(chromium),
  1123. isIE: isBrowser(ie),
  1124. isOpera: isBrowser(opera),
  1125. isFirefox: isBrowser(firefox),
  1126. isSafari: isBrowser(safari)
  1127. };
  1128. };
  1129. const Browser = {
  1130. unknown: unknown$2,
  1131. nu: nu$c,
  1132. edge: constant$1(edge),
  1133. chromium: constant$1(chromium),
  1134. ie: constant$1(ie),
  1135. opera: constant$1(opera),
  1136. firefox: constant$1(firefox),
  1137. safari: constant$1(safari)
  1138. };
  1139. const windows = 'Windows';
  1140. const ios = 'iOS';
  1141. const android = 'Android';
  1142. const linux = 'Linux';
  1143. const macos = 'macOS';
  1144. const solaris = 'Solaris';
  1145. const freebsd = 'FreeBSD';
  1146. const chromeos = 'ChromeOS';
  1147. const unknown$1 = () => {
  1148. return nu$b({
  1149. current: undefined,
  1150. version: Version.unknown()
  1151. });
  1152. };
  1153. const nu$b = info => {
  1154. const current = info.current;
  1155. const version = info.version;
  1156. const isOS = name => () => current === name;
  1157. return {
  1158. current,
  1159. version,
  1160. isWindows: isOS(windows),
  1161. isiOS: isOS(ios),
  1162. isAndroid: isOS(android),
  1163. isMacOS: isOS(macos),
  1164. isLinux: isOS(linux),
  1165. isSolaris: isOS(solaris),
  1166. isFreeBSD: isOS(freebsd),
  1167. isChromeOS: isOS(chromeos)
  1168. };
  1169. };
  1170. const OperatingSystem = {
  1171. unknown: unknown$1,
  1172. nu: nu$b,
  1173. windows: constant$1(windows),
  1174. ios: constant$1(ios),
  1175. android: constant$1(android),
  1176. linux: constant$1(linux),
  1177. macos: constant$1(macos),
  1178. solaris: constant$1(solaris),
  1179. freebsd: constant$1(freebsd),
  1180. chromeos: constant$1(chromeos)
  1181. };
  1182. const detect$2 = (userAgent, userAgentDataOpt, mediaMatch) => {
  1183. const browsers = PlatformInfo.browsers();
  1184. const oses = PlatformInfo.oses();
  1185. const browser = userAgentDataOpt.bind(userAgentData => detectBrowser$1(browsers, userAgentData)).orThunk(() => detectBrowser(browsers, userAgent)).fold(Browser.unknown, Browser.nu);
  1186. const os = detectOs(oses, userAgent).fold(OperatingSystem.unknown, OperatingSystem.nu);
  1187. const deviceType = DeviceType(os, browser, userAgent, mediaMatch);
  1188. return {
  1189. browser,
  1190. os,
  1191. deviceType
  1192. };
  1193. };
  1194. const PlatformDetection = { detect: detect$2 };
  1195. const mediaMatch = query => window.matchMedia(query).matches;
  1196. let platform = cached(() => PlatformDetection.detect(navigator.userAgent, Optional.from(navigator.userAgentData), mediaMatch));
  1197. const detect$1 = () => platform();
  1198. const mkEvent = (target, x, y, stop, prevent, kill, raw) => ({
  1199. target,
  1200. x,
  1201. y,
  1202. stop,
  1203. prevent,
  1204. kill,
  1205. raw
  1206. });
  1207. const fromRawEvent$1 = rawEvent => {
  1208. const target = SugarElement.fromDom(getOriginalEventTarget(rawEvent).getOr(rawEvent.target));
  1209. const stop = () => rawEvent.stopPropagation();
  1210. const prevent = () => rawEvent.preventDefault();
  1211. const kill = compose(prevent, stop);
  1212. return mkEvent(target, rawEvent.clientX, rawEvent.clientY, stop, prevent, kill, rawEvent);
  1213. };
  1214. const handle = (filter, handler) => rawEvent => {
  1215. if (filter(rawEvent)) {
  1216. handler(fromRawEvent$1(rawEvent));
  1217. }
  1218. };
  1219. const binder = (element, event, filter, handler, useCapture) => {
  1220. const wrapped = handle(filter, handler);
  1221. element.dom.addEventListener(event, wrapped, useCapture);
  1222. return { unbind: curry(unbind, element, event, wrapped, useCapture) };
  1223. };
  1224. const bind$2 = (element, event, filter, handler) => binder(element, event, filter, handler, false);
  1225. const capture$1 = (element, event, filter, handler) => binder(element, event, filter, handler, true);
  1226. const unbind = (element, event, handler, useCapture) => {
  1227. element.dom.removeEventListener(event, handler, useCapture);
  1228. };
  1229. const before$1 = (marker, element) => {
  1230. const parent$1 = parent(marker);
  1231. parent$1.each(v => {
  1232. v.dom.insertBefore(element.dom, marker.dom);
  1233. });
  1234. };
  1235. const after$2 = (marker, element) => {
  1236. const sibling = nextSibling(marker);
  1237. sibling.fold(() => {
  1238. const parent$1 = parent(marker);
  1239. parent$1.each(v => {
  1240. append$2(v, element);
  1241. });
  1242. }, v => {
  1243. before$1(v, element);
  1244. });
  1245. };
  1246. const prepend$1 = (parent, element) => {
  1247. const firstChild$1 = firstChild(parent);
  1248. firstChild$1.fold(() => {
  1249. append$2(parent, element);
  1250. }, v => {
  1251. parent.dom.insertBefore(element.dom, v.dom);
  1252. });
  1253. };
  1254. const append$2 = (parent, element) => {
  1255. parent.dom.appendChild(element.dom);
  1256. };
  1257. const appendAt = (parent, element, index) => {
  1258. child$2(parent, index).fold(() => {
  1259. append$2(parent, element);
  1260. }, v => {
  1261. before$1(v, element);
  1262. });
  1263. };
  1264. const append$1 = (parent, elements) => {
  1265. each$1(elements, x => {
  1266. append$2(parent, x);
  1267. });
  1268. };
  1269. const empty = element => {
  1270. element.dom.textContent = '';
  1271. each$1(children(element), rogue => {
  1272. remove$5(rogue);
  1273. });
  1274. };
  1275. const remove$5 = element => {
  1276. const dom = element.dom;
  1277. if (dom.parentNode !== null) {
  1278. dom.parentNode.removeChild(dom);
  1279. }
  1280. };
  1281. const get$b = _DOC => {
  1282. const doc = _DOC !== undefined ? _DOC.dom : document;
  1283. const x = doc.body.scrollLeft || doc.documentElement.scrollLeft;
  1284. const y = doc.body.scrollTop || doc.documentElement.scrollTop;
  1285. return SugarPosition(x, y);
  1286. };
  1287. const to = (x, y, _DOC) => {
  1288. const doc = _DOC !== undefined ? _DOC.dom : document;
  1289. const win = doc.defaultView;
  1290. if (win) {
  1291. win.scrollTo(x, y);
  1292. }
  1293. };
  1294. const get$a = _win => {
  1295. const win = _win === undefined ? window : _win;
  1296. if (detect$1().browser.isFirefox()) {
  1297. return Optional.none();
  1298. } else {
  1299. return Optional.from(win.visualViewport);
  1300. }
  1301. };
  1302. const bounds$1 = (x, y, width, height) => ({
  1303. x,
  1304. y,
  1305. width,
  1306. height,
  1307. right: x + width,
  1308. bottom: y + height
  1309. });
  1310. const getBounds$3 = _win => {
  1311. const win = _win === undefined ? window : _win;
  1312. const doc = win.document;
  1313. const scroll = get$b(SugarElement.fromDom(doc));
  1314. return get$a(win).fold(() => {
  1315. const html = win.document.documentElement;
  1316. const width = html.clientWidth;
  1317. const height = html.clientHeight;
  1318. return bounds$1(scroll.left, scroll.top, width, height);
  1319. }, visualViewport => bounds$1(Math.max(visualViewport.pageLeft, scroll.left), Math.max(visualViewport.pageTop, scroll.top), visualViewport.width, visualViewport.height));
  1320. };
  1321. const getDocument = () => SugarElement.fromDom(document);
  1322. const walkUp = (navigation, doc) => {
  1323. const frame = navigation.view(doc);
  1324. return frame.fold(constant$1([]), f => {
  1325. const parent = navigation.owner(f);
  1326. const rest = walkUp(navigation, parent);
  1327. return [f].concat(rest);
  1328. });
  1329. };
  1330. const pathTo = (element, navigation) => {
  1331. const d = navigation.owner(element);
  1332. const paths = walkUp(navigation, d);
  1333. return Optional.some(paths);
  1334. };
  1335. const view = doc => {
  1336. var _a;
  1337. const element = doc.dom === document ? Optional.none() : Optional.from((_a = doc.dom.defaultView) === null || _a === void 0 ? void 0 : _a.frameElement);
  1338. return element.map(SugarElement.fromDom);
  1339. };
  1340. const owner$3 = element => owner$4(element);
  1341. var Navigation = /*#__PURE__*/Object.freeze({
  1342. __proto__: null,
  1343. view: view,
  1344. owner: owner$3
  1345. });
  1346. const find$2 = element => {
  1347. const doc = getDocument();
  1348. const scroll = get$b(doc);
  1349. const path = pathTo(element, Navigation);
  1350. return path.fold(curry(absolute$3, element), frames => {
  1351. const offset = viewport$1(element);
  1352. const r = foldr(frames, (b, a) => {
  1353. const loc = viewport$1(a);
  1354. return {
  1355. left: b.left + loc.left,
  1356. top: b.top + loc.top
  1357. };
  1358. }, {
  1359. left: 0,
  1360. top: 0
  1361. });
  1362. return SugarPosition(r.left + offset.left + scroll.left, r.top + offset.top + scroll.top);
  1363. });
  1364. };
  1365. const pointed = (point, width, height) => ({
  1366. point,
  1367. width,
  1368. height
  1369. });
  1370. const rect = (x, y, width, height) => ({
  1371. x,
  1372. y,
  1373. width,
  1374. height
  1375. });
  1376. const bounds = (x, y, width, height) => ({
  1377. x,
  1378. y,
  1379. width,
  1380. height,
  1381. right: x + width,
  1382. bottom: y + height
  1383. });
  1384. const box$1 = element => {
  1385. const xy = absolute$3(element);
  1386. const w = getOuter$1(element);
  1387. const h = getOuter$2(element);
  1388. return bounds(xy.left, xy.top, w, h);
  1389. };
  1390. const absolute$2 = element => {
  1391. const position = find$2(element);
  1392. const width = getOuter$1(element);
  1393. const height = getOuter$2(element);
  1394. return bounds(position.left, position.top, width, height);
  1395. };
  1396. const win = () => getBounds$3(window);
  1397. const value$4 = value => {
  1398. const applyHelper = fn => fn(value);
  1399. const constHelper = constant$1(value);
  1400. const outputHelper = () => output;
  1401. const output = {
  1402. tag: true,
  1403. inner: value,
  1404. fold: (_onError, onValue) => onValue(value),
  1405. isValue: always,
  1406. isError: never,
  1407. map: mapper => Result.value(mapper(value)),
  1408. mapError: outputHelper,
  1409. bind: applyHelper,
  1410. exists: applyHelper,
  1411. forall: applyHelper,
  1412. getOr: constHelper,
  1413. or: outputHelper,
  1414. getOrThunk: constHelper,
  1415. orThunk: outputHelper,
  1416. getOrDie: constHelper,
  1417. each: fn => {
  1418. fn(value);
  1419. },
  1420. toOptional: () => Optional.some(value)
  1421. };
  1422. return output;
  1423. };
  1424. const error$1 = error => {
  1425. const outputHelper = () => output;
  1426. const output = {
  1427. tag: false,
  1428. inner: error,
  1429. fold: (onError, _onValue) => onError(error),
  1430. isValue: never,
  1431. isError: always,
  1432. map: outputHelper,
  1433. mapError: mapper => Result.error(mapper(error)),
  1434. bind: outputHelper,
  1435. exists: never,
  1436. forall: always,
  1437. getOr: identity,
  1438. or: identity,
  1439. getOrThunk: apply$1,
  1440. orThunk: apply$1,
  1441. getOrDie: die(String(error)),
  1442. each: noop,
  1443. toOptional: Optional.none
  1444. };
  1445. return output;
  1446. };
  1447. const fromOption = (optional, err) => optional.fold(() => error$1(err), value$4);
  1448. const Result = {
  1449. value: value$4,
  1450. error: error$1,
  1451. fromOption
  1452. };
  1453. var SimpleResultType;
  1454. (function (SimpleResultType) {
  1455. SimpleResultType[SimpleResultType['Error'] = 0] = 'Error';
  1456. SimpleResultType[SimpleResultType['Value'] = 1] = 'Value';
  1457. }(SimpleResultType || (SimpleResultType = {})));
  1458. const fold$1 = (res, onError, onValue) => res.stype === SimpleResultType.Error ? onError(res.serror) : onValue(res.svalue);
  1459. const partition$2 = results => {
  1460. const values = [];
  1461. const errors = [];
  1462. each$1(results, obj => {
  1463. fold$1(obj, err => errors.push(err), val => values.push(val));
  1464. });
  1465. return {
  1466. values,
  1467. errors
  1468. };
  1469. };
  1470. const mapError = (res, f) => {
  1471. if (res.stype === SimpleResultType.Error) {
  1472. return {
  1473. stype: SimpleResultType.Error,
  1474. serror: f(res.serror)
  1475. };
  1476. } else {
  1477. return res;
  1478. }
  1479. };
  1480. const map = (res, f) => {
  1481. if (res.stype === SimpleResultType.Value) {
  1482. return {
  1483. stype: SimpleResultType.Value,
  1484. svalue: f(res.svalue)
  1485. };
  1486. } else {
  1487. return res;
  1488. }
  1489. };
  1490. const bind$1 = (res, f) => {
  1491. if (res.stype === SimpleResultType.Value) {
  1492. return f(res.svalue);
  1493. } else {
  1494. return res;
  1495. }
  1496. };
  1497. const bindError = (res, f) => {
  1498. if (res.stype === SimpleResultType.Error) {
  1499. return f(res.serror);
  1500. } else {
  1501. return res;
  1502. }
  1503. };
  1504. const svalue = v => ({
  1505. stype: SimpleResultType.Value,
  1506. svalue: v
  1507. });
  1508. const serror = e => ({
  1509. stype: SimpleResultType.Error,
  1510. serror: e
  1511. });
  1512. const toResult$1 = res => fold$1(res, Result.error, Result.value);
  1513. const fromResult$1 = res => res.fold(serror, svalue);
  1514. const SimpleResult = {
  1515. fromResult: fromResult$1,
  1516. toResult: toResult$1,
  1517. svalue,
  1518. partition: partition$2,
  1519. serror,
  1520. bind: bind$1,
  1521. bindError,
  1522. map,
  1523. mapError,
  1524. fold: fold$1
  1525. };
  1526. const field$2 = (key, newKey, presence, prop) => ({
  1527. tag: 'field',
  1528. key,
  1529. newKey,
  1530. presence,
  1531. prop
  1532. });
  1533. const customField$1 = (newKey, instantiator) => ({
  1534. tag: 'custom',
  1535. newKey,
  1536. instantiator
  1537. });
  1538. const fold = (value, ifField, ifCustom) => {
  1539. switch (value.tag) {
  1540. case 'field':
  1541. return ifField(value.key, value.newKey, value.presence, value.prop);
  1542. case 'custom':
  1543. return ifCustom(value.newKey, value.instantiator);
  1544. }
  1545. };
  1546. const shallow$1 = (old, nu) => {
  1547. return nu;
  1548. };
  1549. const deep = (old, nu) => {
  1550. const bothObjects = isPlainObject(old) && isPlainObject(nu);
  1551. return bothObjects ? deepMerge(old, nu) : nu;
  1552. };
  1553. const baseMerge = merger => {
  1554. return (...objects) => {
  1555. if (objects.length === 0) {
  1556. throw new Error(`Can't merge zero objects`);
  1557. }
  1558. const ret = {};
  1559. for (let j = 0; j < objects.length; j++) {
  1560. const curObject = objects[j];
  1561. for (const key in curObject) {
  1562. if (has$2(curObject, key)) {
  1563. ret[key] = merger(ret[key], curObject[key]);
  1564. }
  1565. }
  1566. }
  1567. return ret;
  1568. };
  1569. };
  1570. const deepMerge = baseMerge(deep);
  1571. const merge$1 = baseMerge(shallow$1);
  1572. const required$2 = () => ({
  1573. tag: 'required',
  1574. process: {}
  1575. });
  1576. const defaultedThunk = fallbackThunk => ({
  1577. tag: 'defaultedThunk',
  1578. process: fallbackThunk
  1579. });
  1580. const defaulted$1 = fallback => defaultedThunk(constant$1(fallback));
  1581. const asOption = () => ({
  1582. tag: 'option',
  1583. process: {}
  1584. });
  1585. const mergeWithThunk = baseThunk => ({
  1586. tag: 'mergeWithThunk',
  1587. process: baseThunk
  1588. });
  1589. const mergeWith = base => mergeWithThunk(constant$1(base));
  1590. const mergeValues$1 = (values, base) => values.length > 0 ? SimpleResult.svalue(deepMerge(base, merge$1.apply(undefined, values))) : SimpleResult.svalue(base);
  1591. const mergeErrors$1 = errors => compose(SimpleResult.serror, flatten)(errors);
  1592. const consolidateObj = (objects, base) => {
  1593. const partition = SimpleResult.partition(objects);
  1594. return partition.errors.length > 0 ? mergeErrors$1(partition.errors) : mergeValues$1(partition.values, base);
  1595. };
  1596. const consolidateArr = objects => {
  1597. const partitions = SimpleResult.partition(objects);
  1598. return partitions.errors.length > 0 ? mergeErrors$1(partitions.errors) : SimpleResult.svalue(partitions.values);
  1599. };
  1600. const ResultCombine = {
  1601. consolidateObj,
  1602. consolidateArr
  1603. };
  1604. const formatObj = input => {
  1605. return isObject(input) && keys(input).length > 100 ? ' removed due to size' : JSON.stringify(input, null, 2);
  1606. };
  1607. const formatErrors = errors => {
  1608. const es = errors.length > 10 ? errors.slice(0, 10).concat([{
  1609. path: [],
  1610. getErrorInfo: constant$1('... (only showing first ten failures)')
  1611. }]) : errors;
  1612. return map$2(es, e => {
  1613. return 'Failed path: (' + e.path.join(' > ') + ')\n' + e.getErrorInfo();
  1614. });
  1615. };
  1616. const nu$a = (path, getErrorInfo) => {
  1617. return SimpleResult.serror([{
  1618. path,
  1619. getErrorInfo
  1620. }]);
  1621. };
  1622. const missingRequired = (path, key, obj) => nu$a(path, () => 'Could not find valid *required* value for "' + key + '" in ' + formatObj(obj));
  1623. const missingKey = (path, key) => nu$a(path, () => 'Choice schema did not contain choice key: "' + key + '"');
  1624. const missingBranch = (path, branches, branch) => nu$a(path, () => 'The chosen schema: "' + branch + '" did not exist in branches: ' + formatObj(branches));
  1625. const unsupportedFields = (path, unsupported) => nu$a(path, () => 'There are unsupported fields: [' + unsupported.join(', ') + '] specified');
  1626. const custom = (path, err) => nu$a(path, constant$1(err));
  1627. const value$3 = validator => {
  1628. const extract = (path, val) => {
  1629. return SimpleResult.bindError(validator(val), err => custom(path, err));
  1630. };
  1631. const toString = constant$1('val');
  1632. return {
  1633. extract,
  1634. toString
  1635. };
  1636. };
  1637. const anyValue$1 = value$3(SimpleResult.svalue);
  1638. const requiredAccess = (path, obj, key, bundle) => get$g(obj, key).fold(() => missingRequired(path, key, obj), bundle);
  1639. const fallbackAccess = (obj, key, fallback, bundle) => {
  1640. const v = get$g(obj, key).getOrThunk(() => fallback(obj));
  1641. return bundle(v);
  1642. };
  1643. const optionAccess = (obj, key, bundle) => bundle(get$g(obj, key));
  1644. const optionDefaultedAccess = (obj, key, fallback, bundle) => {
  1645. const opt = get$g(obj, key).map(val => val === true ? fallback(obj) : val);
  1646. return bundle(opt);
  1647. };
  1648. const extractField = (field, path, obj, key, prop) => {
  1649. const bundle = av => prop.extract(path.concat([key]), av);
  1650. const bundleAsOption = optValue => optValue.fold(() => SimpleResult.svalue(Optional.none()), ov => {
  1651. const result = prop.extract(path.concat([key]), ov);
  1652. return SimpleResult.map(result, Optional.some);
  1653. });
  1654. switch (field.tag) {
  1655. case 'required':
  1656. return requiredAccess(path, obj, key, bundle);
  1657. case 'defaultedThunk':
  1658. return fallbackAccess(obj, key, field.process, bundle);
  1659. case 'option':
  1660. return optionAccess(obj, key, bundleAsOption);
  1661. case 'defaultedOptionThunk':
  1662. return optionDefaultedAccess(obj, key, field.process, bundleAsOption);
  1663. case 'mergeWithThunk': {
  1664. return fallbackAccess(obj, key, constant$1({}), v => {
  1665. const result = deepMerge(field.process(obj), v);
  1666. return bundle(result);
  1667. });
  1668. }
  1669. }
  1670. };
  1671. const extractFields = (path, obj, fields) => {
  1672. const success = {};
  1673. const errors = [];
  1674. for (const field of fields) {
  1675. fold(field, (key, newKey, presence, prop) => {
  1676. const result = extractField(presence, path, obj, key, prop);
  1677. SimpleResult.fold(result, err => {
  1678. errors.push(...err);
  1679. }, res => {
  1680. success[newKey] = res;
  1681. });
  1682. }, (newKey, instantiator) => {
  1683. success[newKey] = instantiator(obj);
  1684. });
  1685. }
  1686. return errors.length > 0 ? SimpleResult.serror(errors) : SimpleResult.svalue(success);
  1687. };
  1688. const valueThunk = getDelegate => {
  1689. const extract = (path, val) => getDelegate().extract(path, val);
  1690. const toString = () => getDelegate().toString();
  1691. return {
  1692. extract,
  1693. toString
  1694. };
  1695. };
  1696. const getSetKeys = obj => keys(filter$1(obj, isNonNullable));
  1697. const objOfOnly = fields => {
  1698. const delegate = objOf(fields);
  1699. const fieldNames = foldr(fields, (acc, value) => {
  1700. return fold(value, key => deepMerge(acc, { [key]: true }), constant$1(acc));
  1701. }, {});
  1702. const extract = (path, o) => {
  1703. const keys = isBoolean(o) ? [] : getSetKeys(o);
  1704. const extra = filter$2(keys, k => !hasNonNullableKey(fieldNames, k));
  1705. return extra.length === 0 ? delegate.extract(path, o) : unsupportedFields(path, extra);
  1706. };
  1707. return {
  1708. extract,
  1709. toString: delegate.toString
  1710. };
  1711. };
  1712. const objOf = values => {
  1713. const extract = (path, o) => extractFields(path, o, values);
  1714. const toString = () => {
  1715. const fieldStrings = map$2(values, value => fold(value, (key, _okey, _presence, prop) => key + ' -> ' + prop.toString(), (newKey, _instantiator) => 'state(' + newKey + ')'));
  1716. return 'obj{\n' + fieldStrings.join('\n') + '}';
  1717. };
  1718. return {
  1719. extract,
  1720. toString
  1721. };
  1722. };
  1723. const arrOf = prop => {
  1724. const extract = (path, array) => {
  1725. const results = map$2(array, (a, i) => prop.extract(path.concat(['[' + i + ']']), a));
  1726. return ResultCombine.consolidateArr(results);
  1727. };
  1728. const toString = () => 'array(' + prop.toString() + ')';
  1729. return {
  1730. extract,
  1731. toString
  1732. };
  1733. };
  1734. const oneOf = (props, rawF) => {
  1735. const f = rawF !== undefined ? rawF : identity;
  1736. const extract = (path, val) => {
  1737. const errors = [];
  1738. for (const prop of props) {
  1739. const res = prop.extract(path, val);
  1740. if (res.stype === SimpleResultType.Value) {
  1741. return {
  1742. stype: SimpleResultType.Value,
  1743. svalue: f(res.svalue)
  1744. };
  1745. }
  1746. errors.push(res);
  1747. }
  1748. return ResultCombine.consolidateArr(errors);
  1749. };
  1750. const toString = () => 'oneOf(' + map$2(props, prop => prop.toString()).join(', ') + ')';
  1751. return {
  1752. extract,
  1753. toString
  1754. };
  1755. };
  1756. const setOf$1 = (validator, prop) => {
  1757. const validateKeys = (path, keys) => arrOf(value$3(validator)).extract(path, keys);
  1758. const extract = (path, o) => {
  1759. const keys$1 = keys(o);
  1760. const validatedKeys = validateKeys(path, keys$1);
  1761. return SimpleResult.bind(validatedKeys, validKeys => {
  1762. const schema = map$2(validKeys, vk => {
  1763. return field$2(vk, vk, required$2(), prop);
  1764. });
  1765. return objOf(schema).extract(path, o);
  1766. });
  1767. };
  1768. const toString = () => 'setOf(' + prop.toString() + ')';
  1769. return {
  1770. extract,
  1771. toString
  1772. };
  1773. };
  1774. const thunk = (_desc, processor) => {
  1775. const getP = cached(processor);
  1776. const extract = (path, val) => getP().extract(path, val);
  1777. const toString = () => getP().toString();
  1778. return {
  1779. extract,
  1780. toString
  1781. };
  1782. };
  1783. const arrOfObj = compose(arrOf, objOf);
  1784. const anyValue = constant$1(anyValue$1);
  1785. const typedValue = (validator, expectedType) => value$3(a => {
  1786. const actualType = typeof a;
  1787. return validator(a) ? SimpleResult.svalue(a) : SimpleResult.serror(`Expected type: ${ expectedType } but got: ${ actualType }`);
  1788. });
  1789. const number = typedValue(isNumber, 'number');
  1790. const string = typedValue(isString, 'string');
  1791. const boolean = typedValue(isBoolean, 'boolean');
  1792. const functionProcessor = typedValue(isFunction, 'function');
  1793. const isPostMessageable = val => {
  1794. if (Object(val) !== val) {
  1795. return true;
  1796. }
  1797. switch ({}.toString.call(val).slice(8, -1)) {
  1798. case 'Boolean':
  1799. case 'Number':
  1800. case 'String':
  1801. case 'Date':
  1802. case 'RegExp':
  1803. case 'Blob':
  1804. case 'FileList':
  1805. case 'ImageData':
  1806. case 'ImageBitmap':
  1807. case 'ArrayBuffer':
  1808. return true;
  1809. case 'Array':
  1810. case 'Object':
  1811. return Object.keys(val).every(prop => isPostMessageable(val[prop]));
  1812. default:
  1813. return false;
  1814. }
  1815. };
  1816. const postMessageable = value$3(a => {
  1817. if (isPostMessageable(a)) {
  1818. return SimpleResult.svalue(a);
  1819. } else {
  1820. return SimpleResult.serror('Expected value to be acceptable for sending via postMessage');
  1821. }
  1822. });
  1823. const chooseFrom = (path, input, branches, ch) => {
  1824. const fields = get$g(branches, ch);
  1825. return fields.fold(() => missingBranch(path, branches, ch), vp => vp.extract(path.concat(['branch: ' + ch]), input));
  1826. };
  1827. const choose$2 = (key, branches) => {
  1828. const extract = (path, input) => {
  1829. const choice = get$g(input, key);
  1830. return choice.fold(() => missingKey(path, key), chosen => chooseFrom(path, input, branches, chosen));
  1831. };
  1832. const toString = () => 'chooseOn(' + key + '). Possible values: ' + keys(branches);
  1833. return {
  1834. extract,
  1835. toString
  1836. };
  1837. };
  1838. const arrOfVal = () => arrOf(anyValue$1);
  1839. const valueOf = validator => value$3(v => validator(v).fold(SimpleResult.serror, SimpleResult.svalue));
  1840. const setOf = (validator, prop) => setOf$1(v => SimpleResult.fromResult(validator(v)), prop);
  1841. const extractValue = (label, prop, obj) => {
  1842. const res = prop.extract([label], obj);
  1843. return SimpleResult.mapError(res, errs => ({
  1844. input: obj,
  1845. errors: errs
  1846. }));
  1847. };
  1848. const asRaw = (label, prop, obj) => SimpleResult.toResult(extractValue(label, prop, obj));
  1849. const getOrDie = extraction => {
  1850. return extraction.fold(errInfo => {
  1851. throw new Error(formatError(errInfo));
  1852. }, identity);
  1853. };
  1854. const asRawOrDie$1 = (label, prop, obj) => getOrDie(asRaw(label, prop, obj));
  1855. const formatError = errInfo => {
  1856. return 'Errors: \n' + formatErrors(errInfo.errors).join('\n') + '\n\nInput object: ' + formatObj(errInfo.input);
  1857. };
  1858. const choose$1 = (key, branches) => choose$2(key, map$1(branches, objOf));
  1859. const thunkOf = (desc, schema) => thunk(desc, schema);
  1860. const field$1 = field$2;
  1861. const customField = customField$1;
  1862. const validateEnum = values => valueOf(value => contains$2(values, value) ? Result.value(value) : Result.error(`Unsupported value: "${ value }", choose one of "${ values.join(', ') }".`));
  1863. const required$1 = key => field$1(key, key, required$2(), anyValue());
  1864. const requiredOf = (key, schema) => field$1(key, key, required$2(), schema);
  1865. const requiredNumber = key => requiredOf(key, number);
  1866. const requiredString = key => requiredOf(key, string);
  1867. const requiredStringEnum = (key, values) => field$1(key, key, required$2(), validateEnum(values));
  1868. const requiredBoolean = key => requiredOf(key, boolean);
  1869. const requiredFunction = key => requiredOf(key, functionProcessor);
  1870. const forbid = (key, message) => field$1(key, key, asOption(), value$3(_v => SimpleResult.serror('The field: ' + key + ' is forbidden. ' + message)));
  1871. const requiredObjOf = (key, objSchema) => field$1(key, key, required$2(), objOf(objSchema));
  1872. const requiredArrayOfObj = (key, objFields) => field$1(key, key, required$2(), arrOfObj(objFields));
  1873. const requiredArrayOf = (key, schema) => field$1(key, key, required$2(), arrOf(schema));
  1874. const option$3 = key => field$1(key, key, asOption(), anyValue());
  1875. const optionOf = (key, schema) => field$1(key, key, asOption(), schema);
  1876. const optionNumber = key => optionOf(key, number);
  1877. const optionString = key => optionOf(key, string);
  1878. const optionStringEnum = (key, values) => optionOf(key, validateEnum(values));
  1879. const optionFunction = key => optionOf(key, functionProcessor);
  1880. const optionArrayOf = (key, schema) => optionOf(key, arrOf(schema));
  1881. const optionObjOf = (key, objSchema) => optionOf(key, objOf(objSchema));
  1882. const optionObjOfOnly = (key, objSchema) => optionOf(key, objOfOnly(objSchema));
  1883. const defaulted = (key, fallback) => field$1(key, key, defaulted$1(fallback), anyValue());
  1884. const defaultedOf = (key, fallback, schema) => field$1(key, key, defaulted$1(fallback), schema);
  1885. const defaultedNumber = (key, fallback) => defaultedOf(key, fallback, number);
  1886. const defaultedString = (key, fallback) => defaultedOf(key, fallback, string);
  1887. const defaultedStringEnum = (key, fallback, values) => defaultedOf(key, fallback, validateEnum(values));
  1888. const defaultedBoolean = (key, fallback) => defaultedOf(key, fallback, boolean);
  1889. const defaultedFunction = (key, fallback) => defaultedOf(key, fallback, functionProcessor);
  1890. const defaultedPostMsg = (key, fallback) => defaultedOf(key, fallback, postMessageable);
  1891. const defaultedArrayOf = (key, fallback, schema) => defaultedOf(key, fallback, arrOf(schema));
  1892. const defaultedObjOf = (key, fallback, objSchema) => defaultedOf(key, fallback, objOf(objSchema));
  1893. const Cell = initial => {
  1894. let value = initial;
  1895. const get = () => {
  1896. return value;
  1897. };
  1898. const set = v => {
  1899. value = v;
  1900. };
  1901. return {
  1902. get,
  1903. set
  1904. };
  1905. };
  1906. const generate$7 = cases => {
  1907. if (!isArray(cases)) {
  1908. throw new Error('cases must be an array');
  1909. }
  1910. if (cases.length === 0) {
  1911. throw new Error('there must be at least one case');
  1912. }
  1913. const constructors = [];
  1914. const adt = {};
  1915. each$1(cases, (acase, count) => {
  1916. const keys$1 = keys(acase);
  1917. if (keys$1.length !== 1) {
  1918. throw new Error('one and only one name per case');
  1919. }
  1920. const key = keys$1[0];
  1921. const value = acase[key];
  1922. if (adt[key] !== undefined) {
  1923. throw new Error('duplicate key detected:' + key);
  1924. } else if (key === 'cata') {
  1925. throw new Error('cannot have a case named cata (sorry)');
  1926. } else if (!isArray(value)) {
  1927. throw new Error('case arguments must be an array');
  1928. }
  1929. constructors.push(key);
  1930. adt[key] = (...args) => {
  1931. const argLength = args.length;
  1932. if (argLength !== value.length) {
  1933. throw new Error('Wrong number of arguments to case ' + key + '. Expected ' + value.length + ' (' + value + '), got ' + argLength);
  1934. }
  1935. const match = branches => {
  1936. const branchKeys = keys(branches);
  1937. if (constructors.length !== branchKeys.length) {
  1938. throw new Error('Wrong number of arguments to match. Expected: ' + constructors.join(',') + '\nActual: ' + branchKeys.join(','));
  1939. }
  1940. const allReqd = forall(constructors, reqKey => {
  1941. return contains$2(branchKeys, reqKey);
  1942. });
  1943. if (!allReqd) {
  1944. throw new Error('Not all branches were specified when using match. Specified: ' + branchKeys.join(', ') + '\nRequired: ' + constructors.join(', '));
  1945. }
  1946. return branches[key].apply(null, args);
  1947. };
  1948. return {
  1949. fold: (...foldArgs) => {
  1950. if (foldArgs.length !== cases.length) {
  1951. throw new Error('Wrong number of arguments to fold. Expected ' + cases.length + ', got ' + foldArgs.length);
  1952. }
  1953. const target = foldArgs[count];
  1954. return target.apply(null, args);
  1955. },
  1956. match,
  1957. log: label => {
  1958. console.log(label, {
  1959. constructors,
  1960. constructor: key,
  1961. params: args
  1962. });
  1963. }
  1964. };
  1965. };
  1966. });
  1967. return adt;
  1968. };
  1969. const Adt = { generate: generate$7 };
  1970. Adt.generate([
  1971. {
  1972. bothErrors: [
  1973. 'error1',
  1974. 'error2'
  1975. ]
  1976. },
  1977. {
  1978. firstError: [
  1979. 'error1',
  1980. 'value2'
  1981. ]
  1982. },
  1983. {
  1984. secondError: [
  1985. 'value1',
  1986. 'error2'
  1987. ]
  1988. },
  1989. {
  1990. bothValues: [
  1991. 'value1',
  1992. 'value2'
  1993. ]
  1994. }
  1995. ]);
  1996. const partition$1 = results => {
  1997. const errors = [];
  1998. const values = [];
  1999. each$1(results, result => {
  2000. result.fold(err => {
  2001. errors.push(err);
  2002. }, value => {
  2003. values.push(value);
  2004. });
  2005. });
  2006. return {
  2007. errors,
  2008. values
  2009. };
  2010. };
  2011. const exclude$1 = (obj, fields) => {
  2012. const r = {};
  2013. each(obj, (v, k) => {
  2014. if (!contains$2(fields, k)) {
  2015. r[k] = v;
  2016. }
  2017. });
  2018. return r;
  2019. };
  2020. const wrap$2 = (key, value) => ({ [key]: value });
  2021. const wrapAll$1 = keyvalues => {
  2022. const r = {};
  2023. each$1(keyvalues, kv => {
  2024. r[kv.key] = kv.value;
  2025. });
  2026. return r;
  2027. };
  2028. const exclude = (obj, fields) => exclude$1(obj, fields);
  2029. const wrap$1 = (key, value) => wrap$2(key, value);
  2030. const wrapAll = keyvalues => wrapAll$1(keyvalues);
  2031. const mergeValues = (values, base) => {
  2032. return values.length === 0 ? Result.value(base) : Result.value(deepMerge(base, merge$1.apply(undefined, values)));
  2033. };
  2034. const mergeErrors = errors => Result.error(flatten(errors));
  2035. const consolidate = (objs, base) => {
  2036. const partitions = partition$1(objs);
  2037. return partitions.errors.length > 0 ? mergeErrors(partitions.errors) : mergeValues(partitions.values, base);
  2038. };
  2039. const ensureIsRoot = isRoot => isFunction(isRoot) ? isRoot : never;
  2040. const ancestor$2 = (scope, transform, isRoot) => {
  2041. let element = scope.dom;
  2042. const stop = ensureIsRoot(isRoot);
  2043. while (element.parentNode) {
  2044. element = element.parentNode;
  2045. const el = SugarElement.fromDom(element);
  2046. const transformed = transform(el);
  2047. if (transformed.isSome()) {
  2048. return transformed;
  2049. } else if (stop(el)) {
  2050. break;
  2051. }
  2052. }
  2053. return Optional.none();
  2054. };
  2055. const closest$4 = (scope, transform, isRoot) => {
  2056. const current = transform(scope);
  2057. const stop = ensureIsRoot(isRoot);
  2058. return current.orThunk(() => stop(scope) ? Optional.none() : ancestor$2(scope, transform, stop));
  2059. };
  2060. const isSource = (component, simulatedEvent) => eq(component.element, simulatedEvent.event.target);
  2061. const defaultEventHandler = {
  2062. can: always,
  2063. abort: never,
  2064. run: noop
  2065. };
  2066. const nu$9 = parts => {
  2067. if (!hasNonNullableKey(parts, 'can') && !hasNonNullableKey(parts, 'abort') && !hasNonNullableKey(parts, 'run')) {
  2068. throw new Error('EventHandler defined by: ' + JSON.stringify(parts, null, 2) + ' does not have can, abort, or run!');
  2069. }
  2070. return {
  2071. ...defaultEventHandler,
  2072. ...parts
  2073. };
  2074. };
  2075. const all$2 = (handlers, f) => (...args) => foldl(handlers, (acc, handler) => acc && f(handler).apply(undefined, args), true);
  2076. const any = (handlers, f) => (...args) => foldl(handlers, (acc, handler) => acc || f(handler).apply(undefined, args), false);
  2077. const read$2 = handler => isFunction(handler) ? {
  2078. can: always,
  2079. abort: never,
  2080. run: handler
  2081. } : handler;
  2082. const fuse$1 = handlers => {
  2083. const can = all$2(handlers, handler => handler.can);
  2084. const abort = any(handlers, handler => handler.abort);
  2085. const run = (...args) => {
  2086. each$1(handlers, handler => {
  2087. handler.run.apply(undefined, args);
  2088. });
  2089. };
  2090. return {
  2091. can,
  2092. abort,
  2093. run
  2094. };
  2095. };
  2096. const constant = constant$1;
  2097. const touchstart = constant('touchstart');
  2098. const touchmove = constant('touchmove');
  2099. const touchend = constant('touchend');
  2100. const touchcancel = constant('touchcancel');
  2101. const mousedown = constant('mousedown');
  2102. const mousemove = constant('mousemove');
  2103. const mouseout = constant('mouseout');
  2104. const mouseup = constant('mouseup');
  2105. const mouseover = constant('mouseover');
  2106. const focusin = constant('focusin');
  2107. const focusout = constant('focusout');
  2108. const keydown = constant('keydown');
  2109. const keyup = constant('keyup');
  2110. const input = constant('input');
  2111. const change = constant('change');
  2112. const click = constant('click');
  2113. const transitioncancel = constant('transitioncancel');
  2114. const transitionend = constant('transitionend');
  2115. const transitionstart = constant('transitionstart');
  2116. const selectstart = constant('selectstart');
  2117. const prefixName = name => constant$1('alloy.' + name);
  2118. const alloy = { tap: prefixName('tap') };
  2119. const focus$4 = prefixName('focus');
  2120. const postBlur = prefixName('blur.post');
  2121. const postPaste = prefixName('paste.post');
  2122. const receive = prefixName('receive');
  2123. const execute$5 = prefixName('execute');
  2124. const focusItem = prefixName('focus.item');
  2125. const tap = alloy.tap;
  2126. const longpress = prefixName('longpress');
  2127. const sandboxClose = prefixName('sandbox.close');
  2128. const typeaheadCancel = prefixName('typeahead.cancel');
  2129. const systemInit = prefixName('system.init');
  2130. const documentTouchmove = prefixName('system.touchmove');
  2131. const documentTouchend = prefixName('system.touchend');
  2132. const windowScroll = prefixName('system.scroll');
  2133. const windowResize = prefixName('system.resize');
  2134. const attachedToDom = prefixName('system.attached');
  2135. const detachedFromDom = prefixName('system.detached');
  2136. const dismissRequested = prefixName('system.dismissRequested');
  2137. const repositionRequested = prefixName('system.repositionRequested');
  2138. const focusShifted = prefixName('focusmanager.shifted');
  2139. const slotVisibility = prefixName('slotcontainer.visibility');
  2140. const changeTab = prefixName('change.tab');
  2141. const dismissTab = prefixName('dismiss.tab');
  2142. const highlight$1 = prefixName('highlight');
  2143. const dehighlight$1 = prefixName('dehighlight');
  2144. const emit = (component, event) => {
  2145. dispatchWith(component, component.element, event, {});
  2146. };
  2147. const emitWith = (component, event, properties) => {
  2148. dispatchWith(component, component.element, event, properties);
  2149. };
  2150. const emitExecute = component => {
  2151. emit(component, execute$5());
  2152. };
  2153. const dispatch = (component, target, event) => {
  2154. dispatchWith(component, target, event, {});
  2155. };
  2156. const dispatchWith = (component, target, event, properties) => {
  2157. const data = {
  2158. target,
  2159. ...properties
  2160. };
  2161. component.getSystem().triggerEvent(event, target, data);
  2162. };
  2163. const retargetAndDispatchWith = (component, target, eventName, properties) => {
  2164. const data = {
  2165. ...properties,
  2166. target
  2167. };
  2168. component.getSystem().triggerEvent(eventName, target, data);
  2169. };
  2170. const dispatchEvent = (component, target, event, simulatedEvent) => {
  2171. component.getSystem().triggerEvent(event, target, simulatedEvent.event);
  2172. };
  2173. const derive$2 = configs => wrapAll(configs);
  2174. const abort = (name, predicate) => {
  2175. return {
  2176. key: name,
  2177. value: nu$9({ abort: predicate })
  2178. };
  2179. };
  2180. const can = (name, predicate) => {
  2181. return {
  2182. key: name,
  2183. value: nu$9({ can: predicate })
  2184. };
  2185. };
  2186. const preventDefault = name => {
  2187. return {
  2188. key: name,
  2189. value: nu$9({
  2190. run: (component, simulatedEvent) => {
  2191. simulatedEvent.event.prevent();
  2192. }
  2193. })
  2194. };
  2195. };
  2196. const run$1 = (name, handler) => {
  2197. return {
  2198. key: name,
  2199. value: nu$9({ run: handler })
  2200. };
  2201. };
  2202. const runActionExtra = (name, action, extra) => {
  2203. return {
  2204. key: name,
  2205. value: nu$9({
  2206. run: (component, simulatedEvent) => {
  2207. action.apply(undefined, [
  2208. component,
  2209. simulatedEvent
  2210. ].concat(extra));
  2211. }
  2212. })
  2213. };
  2214. };
  2215. const runOnName = name => {
  2216. return handler => run$1(name, handler);
  2217. };
  2218. const runOnSourceName = name => {
  2219. return handler => ({
  2220. key: name,
  2221. value: nu$9({
  2222. run: (component, simulatedEvent) => {
  2223. if (isSource(component, simulatedEvent)) {
  2224. handler(component, simulatedEvent);
  2225. }
  2226. }
  2227. })
  2228. });
  2229. };
  2230. const redirectToUid = (name, uid) => {
  2231. return run$1(name, (component, simulatedEvent) => {
  2232. component.getSystem().getByUid(uid).each(redirectee => {
  2233. dispatchEvent(redirectee, redirectee.element, name, simulatedEvent);
  2234. });
  2235. });
  2236. };
  2237. const redirectToPart = (name, detail, partName) => {
  2238. const uid = detail.partUids[partName];
  2239. return redirectToUid(name, uid);
  2240. };
  2241. const runWithTarget = (name, f) => {
  2242. return run$1(name, (component, simulatedEvent) => {
  2243. const ev = simulatedEvent.event;
  2244. const target = component.getSystem().getByDom(ev.target).getOrThunk(() => {
  2245. const closest = closest$4(ev.target, el => component.getSystem().getByDom(el).toOptional(), never);
  2246. return closest.getOr(component);
  2247. });
  2248. f(component, target, simulatedEvent);
  2249. });
  2250. };
  2251. const cutter = name => {
  2252. return run$1(name, (component, simulatedEvent) => {
  2253. simulatedEvent.cut();
  2254. });
  2255. };
  2256. const stopper = name => {
  2257. return run$1(name, (component, simulatedEvent) => {
  2258. simulatedEvent.stop();
  2259. });
  2260. };
  2261. const runOnSource = (name, f) => {
  2262. return runOnSourceName(name)(f);
  2263. };
  2264. const runOnAttached = runOnSourceName(attachedToDom());
  2265. const runOnDetached = runOnSourceName(detachedFromDom());
  2266. const runOnInit = runOnSourceName(systemInit());
  2267. const runOnExecute$1 = runOnName(execute$5());
  2268. const fromHtml$1 = (html, scope) => {
  2269. const doc = scope || document;
  2270. const div = doc.createElement('div');
  2271. div.innerHTML = html;
  2272. return children(SugarElement.fromDom(div));
  2273. };
  2274. const get$9 = element => element.dom.innerHTML;
  2275. const set$6 = (element, content) => {
  2276. const owner = owner$4(element);
  2277. const docDom = owner.dom;
  2278. const fragment = SugarElement.fromDom(docDom.createDocumentFragment());
  2279. const contentElements = fromHtml$1(content, docDom);
  2280. append$1(fragment, contentElements);
  2281. empty(element);
  2282. append$2(element, fragment);
  2283. };
  2284. const getOuter = element => {
  2285. const container = SugarElement.fromTag('div');
  2286. const clone = SugarElement.fromDom(element.dom.cloneNode(true));
  2287. append$2(container, clone);
  2288. return get$9(container);
  2289. };
  2290. const clone$1 = (original, isDeep) => SugarElement.fromDom(original.dom.cloneNode(isDeep));
  2291. const shallow = original => clone$1(original, false);
  2292. const getHtml = element => {
  2293. if (isShadowRoot(element)) {
  2294. return '#shadow-root';
  2295. } else {
  2296. const clone = shallow(element);
  2297. return getOuter(clone);
  2298. }
  2299. };
  2300. const element = elem => getHtml(elem);
  2301. const isRecursive = (component, originator, target) => eq(originator, component.element) && !eq(originator, target);
  2302. const events$i = derive$2([can(focus$4(), (component, simulatedEvent) => {
  2303. const event = simulatedEvent.event;
  2304. const originator = event.originator;
  2305. const target = event.target;
  2306. if (isRecursive(component, originator, target)) {
  2307. console.warn(focus$4() + ' did not get interpreted by the desired target. ' + '\nOriginator: ' + element(originator) + '\nTarget: ' + element(target) + '\nCheck the ' + focus$4() + ' event handlers');
  2308. return false;
  2309. } else {
  2310. return true;
  2311. }
  2312. })]);
  2313. var DefaultEvents = /*#__PURE__*/Object.freeze({
  2314. __proto__: null,
  2315. events: events$i
  2316. });
  2317. let unique = 0;
  2318. const generate$6 = prefix => {
  2319. const date = new Date();
  2320. const time = date.getTime();
  2321. const random = Math.floor(Math.random() * 1000000000);
  2322. unique++;
  2323. return prefix + '_' + random + unique + String(time);
  2324. };
  2325. const prefix$1 = constant$1('alloy-id-');
  2326. const idAttr$1 = constant$1('data-alloy-id');
  2327. const prefix = prefix$1();
  2328. const idAttr = idAttr$1();
  2329. const write = (label, elem) => {
  2330. const id = generate$6(prefix + label);
  2331. writeOnly(elem, id);
  2332. return id;
  2333. };
  2334. const writeOnly = (elem, uid) => {
  2335. Object.defineProperty(elem.dom, idAttr, {
  2336. value: uid,
  2337. writable: true
  2338. });
  2339. };
  2340. const read$1 = elem => {
  2341. const id = isElement$1(elem) ? elem.dom[idAttr] : null;
  2342. return Optional.from(id);
  2343. };
  2344. const generate$5 = prefix => generate$6(prefix);
  2345. const make$8 = identity;
  2346. const NoContextApi = getComp => {
  2347. const getMessage = event => `The component must be in a context to execute: ${ event }` + (getComp ? '\n' + element(getComp().element) + ' is not in context.' : '');
  2348. const fail = event => () => {
  2349. throw new Error(getMessage(event));
  2350. };
  2351. const warn = event => () => {
  2352. console.warn(getMessage(event));
  2353. };
  2354. return {
  2355. debugInfo: constant$1('fake'),
  2356. triggerEvent: warn('triggerEvent'),
  2357. triggerFocus: warn('triggerFocus'),
  2358. triggerEscape: warn('triggerEscape'),
  2359. broadcast: warn('broadcast'),
  2360. broadcastOn: warn('broadcastOn'),
  2361. broadcastEvent: warn('broadcastEvent'),
  2362. build: fail('build'),
  2363. buildOrPatch: fail('buildOrPatch'),
  2364. addToWorld: fail('addToWorld'),
  2365. removeFromWorld: fail('removeFromWorld'),
  2366. addToGui: fail('addToGui'),
  2367. removeFromGui: fail('removeFromGui'),
  2368. getByUid: fail('getByUid'),
  2369. getByDom: fail('getByDom'),
  2370. isConnected: never
  2371. };
  2372. };
  2373. const singleton$1 = NoContextApi();
  2374. const markAsBehaviourApi = (f, apiName, apiFunction) => {
  2375. const delegate = apiFunction.toString();
  2376. const endIndex = delegate.indexOf(')') + 1;
  2377. const openBracketIndex = delegate.indexOf('(');
  2378. const parameters = delegate.substring(openBracketIndex + 1, endIndex - 1).split(/,\s*/);
  2379. f.toFunctionAnnotation = () => ({
  2380. name: apiName,
  2381. parameters: cleanParameters(parameters.slice(0, 1).concat(parameters.slice(3)))
  2382. });
  2383. return f;
  2384. };
  2385. const cleanParameters = parameters => map$2(parameters, p => endsWith(p, '/*') ? p.substring(0, p.length - '/*'.length) : p);
  2386. const markAsExtraApi = (f, extraName) => {
  2387. const delegate = f.toString();
  2388. const endIndex = delegate.indexOf(')') + 1;
  2389. const openBracketIndex = delegate.indexOf('(');
  2390. const parameters = delegate.substring(openBracketIndex + 1, endIndex - 1).split(/,\s*/);
  2391. f.toFunctionAnnotation = () => ({
  2392. name: extraName,
  2393. parameters: cleanParameters(parameters)
  2394. });
  2395. return f;
  2396. };
  2397. const markAsSketchApi = (f, apiFunction) => {
  2398. const delegate = apiFunction.toString();
  2399. const endIndex = delegate.indexOf(')') + 1;
  2400. const openBracketIndex = delegate.indexOf('(');
  2401. const parameters = delegate.substring(openBracketIndex + 1, endIndex - 1).split(/,\s*/);
  2402. f.toFunctionAnnotation = () => ({
  2403. name: 'OVERRIDE',
  2404. parameters: cleanParameters(parameters.slice(1))
  2405. });
  2406. return f;
  2407. };
  2408. const premadeTag = generate$6('alloy-premade');
  2409. const premade$1 = comp => {
  2410. Object.defineProperty(comp.element.dom, premadeTag, {
  2411. value: comp.uid,
  2412. writable: true
  2413. });
  2414. return wrap$1(premadeTag, comp);
  2415. };
  2416. const isPremade = element => has$2(element.dom, premadeTag);
  2417. const getPremade = spec => get$g(spec, premadeTag);
  2418. const makeApi = f => markAsSketchApi((component, ...rest) => f(component.getApis(), component, ...rest), f);
  2419. const NoState = { init: () => nu$8({ readState: constant$1('No State required') }) };
  2420. const nu$8 = spec => spec;
  2421. const generateFrom$1 = (spec, all) => {
  2422. const schema = map$2(all, a => optionObjOf(a.name(), [
  2423. required$1('config'),
  2424. defaulted('state', NoState)
  2425. ]));
  2426. const validated = asRaw('component.behaviours', objOf(schema), spec.behaviours).fold(errInfo => {
  2427. throw new Error(formatError(errInfo) + '\nComplete spec:\n' + JSON.stringify(spec, null, 2));
  2428. }, identity);
  2429. return {
  2430. list: all,
  2431. data: map$1(validated, optBlobThunk => {
  2432. const output = optBlobThunk.map(blob => ({
  2433. config: blob.config,
  2434. state: blob.state.init(blob.config)
  2435. }));
  2436. return constant$1(output);
  2437. })
  2438. };
  2439. };
  2440. const getBehaviours$3 = bData => bData.list;
  2441. const getData$2 = bData => bData.data;
  2442. const byInnerKey = (data, tuple) => {
  2443. const r = {};
  2444. each(data, (detail, key) => {
  2445. each(detail, (value, indexKey) => {
  2446. const chain = get$g(r, indexKey).getOr([]);
  2447. r[indexKey] = chain.concat([tuple(key, value)]);
  2448. });
  2449. });
  2450. return r;
  2451. };
  2452. const nu$7 = s => ({
  2453. classes: isUndefined(s.classes) ? [] : s.classes,
  2454. attributes: isUndefined(s.attributes) ? {} : s.attributes,
  2455. styles: isUndefined(s.styles) ? {} : s.styles
  2456. });
  2457. const merge = (defnA, mod) => ({
  2458. ...defnA,
  2459. attributes: {
  2460. ...defnA.attributes,
  2461. ...mod.attributes
  2462. },
  2463. styles: {
  2464. ...defnA.styles,
  2465. ...mod.styles
  2466. },
  2467. classes: defnA.classes.concat(mod.classes)
  2468. });
  2469. const combine$2 = (info, baseMod, behaviours, base) => {
  2470. const modsByBehaviour = { ...baseMod };
  2471. each$1(behaviours, behaviour => {
  2472. modsByBehaviour[behaviour.name()] = behaviour.exhibit(info, base);
  2473. });
  2474. const byAspect = byInnerKey(modsByBehaviour, (name, modification) => ({
  2475. name,
  2476. modification
  2477. }));
  2478. const combineObjects = objects => foldr(objects, (b, a) => ({
  2479. ...a.modification,
  2480. ...b
  2481. }), {});
  2482. const combinedClasses = foldr(byAspect.classes, (b, a) => a.modification.concat(b), []);
  2483. const combinedAttributes = combineObjects(byAspect.attributes);
  2484. const combinedStyles = combineObjects(byAspect.styles);
  2485. return nu$7({
  2486. classes: combinedClasses,
  2487. attributes: combinedAttributes,
  2488. styles: combinedStyles
  2489. });
  2490. };
  2491. const sortKeys = (label, keyName, array, order) => {
  2492. try {
  2493. const sorted = sort(array, (a, b) => {
  2494. const aKey = a[keyName];
  2495. const bKey = b[keyName];
  2496. const aIndex = order.indexOf(aKey);
  2497. const bIndex = order.indexOf(bKey);
  2498. if (aIndex === -1) {
  2499. throw new Error('The ordering for ' + label + ' does not have an entry for ' + aKey + '.\nOrder specified: ' + JSON.stringify(order, null, 2));
  2500. }
  2501. if (bIndex === -1) {
  2502. throw new Error('The ordering for ' + label + ' does not have an entry for ' + bKey + '.\nOrder specified: ' + JSON.stringify(order, null, 2));
  2503. }
  2504. if (aIndex < bIndex) {
  2505. return -1;
  2506. } else if (bIndex < aIndex) {
  2507. return 1;
  2508. } else {
  2509. return 0;
  2510. }
  2511. });
  2512. return Result.value(sorted);
  2513. } catch (err) {
  2514. return Result.error([err]);
  2515. }
  2516. };
  2517. const uncurried = (handler, purpose) => ({
  2518. handler,
  2519. purpose
  2520. });
  2521. const curried = (handler, purpose) => ({
  2522. cHandler: handler,
  2523. purpose
  2524. });
  2525. const curryArgs = (descHandler, extraArgs) => curried(curry.apply(undefined, [descHandler.handler].concat(extraArgs)), descHandler.purpose);
  2526. const getCurried = descHandler => descHandler.cHandler;
  2527. const behaviourTuple = (name, handler) => ({
  2528. name,
  2529. handler
  2530. });
  2531. const nameToHandlers = (behaviours, info) => {
  2532. const r = {};
  2533. each$1(behaviours, behaviour => {
  2534. r[behaviour.name()] = behaviour.handlers(info);
  2535. });
  2536. return r;
  2537. };
  2538. const groupByEvents = (info, behaviours, base) => {
  2539. const behaviourEvents = {
  2540. ...base,
  2541. ...nameToHandlers(behaviours, info)
  2542. };
  2543. return byInnerKey(behaviourEvents, behaviourTuple);
  2544. };
  2545. const combine$1 = (info, eventOrder, behaviours, base) => {
  2546. const byEventName = groupByEvents(info, behaviours, base);
  2547. return combineGroups(byEventName, eventOrder);
  2548. };
  2549. const assemble = rawHandler => {
  2550. const handler = read$2(rawHandler);
  2551. return (component, simulatedEvent, ...rest) => {
  2552. const args = [
  2553. component,
  2554. simulatedEvent
  2555. ].concat(rest);
  2556. if (handler.abort.apply(undefined, args)) {
  2557. simulatedEvent.stop();
  2558. } else if (handler.can.apply(undefined, args)) {
  2559. handler.run.apply(undefined, args);
  2560. }
  2561. };
  2562. };
  2563. const missingOrderError = (eventName, tuples) => Result.error(['The event (' + eventName + ') has more than one behaviour that listens to it.\nWhen this occurs, you must ' + 'specify an event ordering for the behaviours in your spec (e.g. [ "listing", "toggling" ]).\nThe behaviours that ' + 'can trigger it are: ' + JSON.stringify(map$2(tuples, c => c.name), null, 2)]);
  2564. const fuse = (tuples, eventOrder, eventName) => {
  2565. const order = eventOrder[eventName];
  2566. if (!order) {
  2567. return missingOrderError(eventName, tuples);
  2568. } else {
  2569. return sortKeys('Event: ' + eventName, 'name', tuples, order).map(sortedTuples => {
  2570. const handlers = map$2(sortedTuples, tuple => tuple.handler);
  2571. return fuse$1(handlers);
  2572. });
  2573. }
  2574. };
  2575. const combineGroups = (byEventName, eventOrder) => {
  2576. const r = mapToArray(byEventName, (tuples, eventName) => {
  2577. const combined = tuples.length === 1 ? Result.value(tuples[0].handler) : fuse(tuples, eventOrder, eventName);
  2578. return combined.map(handler => {
  2579. const assembled = assemble(handler);
  2580. const purpose = tuples.length > 1 ? filter$2(eventOrder[eventName], o => exists(tuples, t => t.name === o)).join(' > ') : tuples[0].name;
  2581. return wrap$1(eventName, uncurried(assembled, purpose));
  2582. });
  2583. });
  2584. return consolidate(r, {});
  2585. };
  2586. const baseBehaviour = 'alloy.base.behaviour';
  2587. const schema$z = objOf([
  2588. field$1('dom', 'dom', required$2(), objOf([
  2589. required$1('tag'),
  2590. defaulted('styles', {}),
  2591. defaulted('classes', []),
  2592. defaulted('attributes', {}),
  2593. option$3('value'),
  2594. option$3('innerHtml')
  2595. ])),
  2596. required$1('components'),
  2597. required$1('uid'),
  2598. defaulted('events', {}),
  2599. defaulted('apis', {}),
  2600. field$1('eventOrder', 'eventOrder', mergeWith({
  2601. [execute$5()]: [
  2602. 'disabling',
  2603. baseBehaviour,
  2604. 'toggling',
  2605. 'typeaheadevents'
  2606. ],
  2607. [focus$4()]: [
  2608. baseBehaviour,
  2609. 'focusing',
  2610. 'keying'
  2611. ],
  2612. [systemInit()]: [
  2613. baseBehaviour,
  2614. 'disabling',
  2615. 'toggling',
  2616. 'representing'
  2617. ],
  2618. [input()]: [
  2619. baseBehaviour,
  2620. 'representing',
  2621. 'streaming',
  2622. 'invalidating'
  2623. ],
  2624. [detachedFromDom()]: [
  2625. baseBehaviour,
  2626. 'representing',
  2627. 'item-events',
  2628. 'tooltipping'
  2629. ],
  2630. [mousedown()]: [
  2631. 'focusing',
  2632. baseBehaviour,
  2633. 'item-type-events'
  2634. ],
  2635. [touchstart()]: [
  2636. 'focusing',
  2637. baseBehaviour,
  2638. 'item-type-events'
  2639. ],
  2640. [mouseover()]: [
  2641. 'item-type-events',
  2642. 'tooltipping'
  2643. ],
  2644. [receive()]: [
  2645. 'receiving',
  2646. 'reflecting',
  2647. 'tooltipping'
  2648. ]
  2649. }), anyValue()),
  2650. option$3('domModification')
  2651. ]);
  2652. const toInfo = spec => asRaw('custom.definition', schema$z, spec);
  2653. const toDefinition = detail => ({
  2654. ...detail.dom,
  2655. uid: detail.uid,
  2656. domChildren: map$2(detail.components, comp => comp.element)
  2657. });
  2658. const toModification = detail => detail.domModification.fold(() => nu$7({}), nu$7);
  2659. const toEvents = info => info.events;
  2660. const read = (element, attr) => {
  2661. const value = get$f(element, attr);
  2662. return value === undefined || value === '' ? [] : value.split(' ');
  2663. };
  2664. const add$4 = (element, attr, id) => {
  2665. const old = read(element, attr);
  2666. const nu = old.concat([id]);
  2667. set$9(element, attr, nu.join(' '));
  2668. return true;
  2669. };
  2670. const remove$4 = (element, attr, id) => {
  2671. const nu = filter$2(read(element, attr), v => v !== id);
  2672. if (nu.length > 0) {
  2673. set$9(element, attr, nu.join(' '));
  2674. } else {
  2675. remove$7(element, attr);
  2676. }
  2677. return false;
  2678. };
  2679. const supports = element => element.dom.classList !== undefined;
  2680. const get$8 = element => read(element, 'class');
  2681. const add$3 = (element, clazz) => add$4(element, 'class', clazz);
  2682. const remove$3 = (element, clazz) => remove$4(element, 'class', clazz);
  2683. const add$2 = (element, clazz) => {
  2684. if (supports(element)) {
  2685. element.dom.classList.add(clazz);
  2686. } else {
  2687. add$3(element, clazz);
  2688. }
  2689. };
  2690. const cleanClass = element => {
  2691. const classList = supports(element) ? element.dom.classList : get$8(element);
  2692. if (classList.length === 0) {
  2693. remove$7(element, 'class');
  2694. }
  2695. };
  2696. const remove$2 = (element, clazz) => {
  2697. if (supports(element)) {
  2698. const classList = element.dom.classList;
  2699. classList.remove(clazz);
  2700. } else {
  2701. remove$3(element, clazz);
  2702. }
  2703. cleanClass(element);
  2704. };
  2705. const has = (element, clazz) => supports(element) && element.dom.classList.contains(clazz);
  2706. const add$1 = (element, classes) => {
  2707. each$1(classes, x => {
  2708. add$2(element, x);
  2709. });
  2710. };
  2711. const remove$1 = (element, classes) => {
  2712. each$1(classes, x => {
  2713. remove$2(element, x);
  2714. });
  2715. };
  2716. const hasAll = (element, classes) => forall(classes, clazz => has(element, clazz));
  2717. const getNative = element => {
  2718. const classList = element.dom.classList;
  2719. const r = new Array(classList.length);
  2720. for (let i = 0; i < classList.length; i++) {
  2721. const item = classList.item(i);
  2722. if (item !== null) {
  2723. r[i] = item;
  2724. }
  2725. }
  2726. return r;
  2727. };
  2728. const get$7 = element => supports(element) ? getNative(element) : get$8(element);
  2729. const get$6 = element => element.dom.value;
  2730. const set$5 = (element, value) => {
  2731. if (value === undefined) {
  2732. throw new Error('Value.set was undefined');
  2733. }
  2734. element.dom.value = value;
  2735. };
  2736. const determineObsoleted = (parent, index, oldObsoleted) => {
  2737. const newObsoleted = child$2(parent, index);
  2738. return newObsoleted.map(newObs => {
  2739. const elemChanged = oldObsoleted.exists(o => !eq(o, newObs));
  2740. if (elemChanged) {
  2741. const oldTag = oldObsoleted.map(name$3).getOr('span');
  2742. const marker = SugarElement.fromTag(oldTag);
  2743. before$1(newObs, marker);
  2744. return marker;
  2745. } else {
  2746. return newObs;
  2747. }
  2748. });
  2749. };
  2750. const ensureInDom = (parent, child, obsoleted) => {
  2751. obsoleted.fold(() => append$2(parent, child), obs => {
  2752. if (!eq(obs, child)) {
  2753. before$1(obs, child);
  2754. remove$5(obs);
  2755. }
  2756. });
  2757. };
  2758. const patchChildrenWith = (parent, nu, f) => {
  2759. const builtChildren = map$2(nu, f);
  2760. const currentChildren = children(parent);
  2761. each$1(currentChildren.slice(builtChildren.length), remove$5);
  2762. return builtChildren;
  2763. };
  2764. const patchSpecChild = (parent, index, spec, build) => {
  2765. const oldObsoleted = child$2(parent, index);
  2766. const childComp = build(spec, oldObsoleted);
  2767. const obsoleted = determineObsoleted(parent, index, oldObsoleted);
  2768. ensureInDom(parent, childComp.element, obsoleted);
  2769. return childComp;
  2770. };
  2771. const patchSpecChildren = (parent, specs, build) => patchChildrenWith(parent, specs, (spec, index) => patchSpecChild(parent, index, spec, build));
  2772. const patchDomChildren = (parent, nodes) => patchChildrenWith(parent, nodes, (node, index) => {
  2773. const optObsoleted = child$2(parent, index);
  2774. ensureInDom(parent, node, optObsoleted);
  2775. return node;
  2776. });
  2777. const diffKeyValueSet = (newObj, oldObj) => {
  2778. const newKeys = keys(newObj);
  2779. const oldKeys = keys(oldObj);
  2780. const toRemove = difference(oldKeys, newKeys);
  2781. const toSet = bifilter(newObj, (v, k) => {
  2782. return !has$2(oldObj, k) || v !== oldObj[k];
  2783. }).t;
  2784. return {
  2785. toRemove,
  2786. toSet
  2787. };
  2788. };
  2789. const reconcileToDom = (definition, obsoleted) => {
  2790. const {
  2791. class: clazz,
  2792. style,
  2793. ...existingAttributes
  2794. } = clone$2(obsoleted);
  2795. const {
  2796. toSet: attrsToSet,
  2797. toRemove: attrsToRemove
  2798. } = diffKeyValueSet(definition.attributes, existingAttributes);
  2799. const updateAttrs = () => {
  2800. each$1(attrsToRemove, a => remove$7(obsoleted, a));
  2801. setAll$1(obsoleted, attrsToSet);
  2802. };
  2803. const existingStyles = getAllRaw(obsoleted);
  2804. const {
  2805. toSet: stylesToSet,
  2806. toRemove: stylesToRemove
  2807. } = diffKeyValueSet(definition.styles, existingStyles);
  2808. const updateStyles = () => {
  2809. each$1(stylesToRemove, s => remove$6(obsoleted, s));
  2810. setAll(obsoleted, stylesToSet);
  2811. };
  2812. const existingClasses = get$7(obsoleted);
  2813. const classesToRemove = difference(existingClasses, definition.classes);
  2814. const classesToAdd = difference(definition.classes, existingClasses);
  2815. const updateClasses = () => {
  2816. add$1(obsoleted, classesToAdd);
  2817. remove$1(obsoleted, classesToRemove);
  2818. };
  2819. const updateHtml = html => {
  2820. set$6(obsoleted, html);
  2821. };
  2822. const updateChildren = () => {
  2823. const children = definition.domChildren;
  2824. patchDomChildren(obsoleted, children);
  2825. };
  2826. const updateValue = () => {
  2827. const valueElement = obsoleted;
  2828. const value = definition.value.getOrUndefined();
  2829. if (value !== get$6(valueElement)) {
  2830. set$5(valueElement, value !== null && value !== void 0 ? value : '');
  2831. }
  2832. };
  2833. updateAttrs();
  2834. updateClasses();
  2835. updateStyles();
  2836. definition.innerHtml.fold(updateChildren, updateHtml);
  2837. updateValue();
  2838. return obsoleted;
  2839. };
  2840. const introduceToDom = definition => {
  2841. const subject = SugarElement.fromTag(definition.tag);
  2842. setAll$1(subject, definition.attributes);
  2843. add$1(subject, definition.classes);
  2844. setAll(subject, definition.styles);
  2845. definition.innerHtml.each(html => set$6(subject, html));
  2846. const children = definition.domChildren;
  2847. append$1(subject, children);
  2848. definition.value.each(value => {
  2849. set$5(subject, value);
  2850. });
  2851. return subject;
  2852. };
  2853. const attemptPatch = (definition, obsoleted) => {
  2854. try {
  2855. const e = reconcileToDom(definition, obsoleted);
  2856. return Optional.some(e);
  2857. } catch (err) {
  2858. return Optional.none();
  2859. }
  2860. };
  2861. const hasMixedChildren = definition => definition.innerHtml.isSome() && definition.domChildren.length > 0;
  2862. const renderToDom = (definition, optObsoleted) => {
  2863. const canBePatched = candidate => name$3(candidate) === definition.tag && !hasMixedChildren(definition) && !isPremade(candidate);
  2864. const elem = optObsoleted.filter(canBePatched).bind(obsoleted => attemptPatch(definition, obsoleted)).getOrThunk(() => introduceToDom(definition));
  2865. writeOnly(elem, definition.uid);
  2866. return elem;
  2867. };
  2868. const getBehaviours$2 = spec => {
  2869. const behaviours = get$g(spec, 'behaviours').getOr({});
  2870. return bind$3(keys(behaviours), name => {
  2871. const behaviour = behaviours[name];
  2872. return isNonNullable(behaviour) ? [behaviour.me] : [];
  2873. });
  2874. };
  2875. const generateFrom = (spec, all) => generateFrom$1(spec, all);
  2876. const generate$4 = spec => {
  2877. const all = getBehaviours$2(spec);
  2878. return generateFrom(spec, all);
  2879. };
  2880. const getDomDefinition = (info, bList, bData) => {
  2881. const definition = toDefinition(info);
  2882. const infoModification = toModification(info);
  2883. const baseModification = { 'alloy.base.modification': infoModification };
  2884. const modification = bList.length > 0 ? combine$2(bData, baseModification, bList, definition) : infoModification;
  2885. return merge(definition, modification);
  2886. };
  2887. const getEvents = (info, bList, bData) => {
  2888. const baseEvents = { 'alloy.base.behaviour': toEvents(info) };
  2889. return combine$1(bData, info.eventOrder, bList, baseEvents).getOrDie();
  2890. };
  2891. const build$2 = (spec, obsoleted) => {
  2892. const getMe = () => me;
  2893. const systemApi = Cell(singleton$1);
  2894. const info = getOrDie(toInfo(spec));
  2895. const bBlob = generate$4(spec);
  2896. const bList = getBehaviours$3(bBlob);
  2897. const bData = getData$2(bBlob);
  2898. const modDefinition = getDomDefinition(info, bList, bData);
  2899. const item = renderToDom(modDefinition, obsoleted);
  2900. const events = getEvents(info, bList, bData);
  2901. const subcomponents = Cell(info.components);
  2902. const connect = newApi => {
  2903. systemApi.set(newApi);
  2904. };
  2905. const disconnect = () => {
  2906. systemApi.set(NoContextApi(getMe));
  2907. };
  2908. const syncComponents = () => {
  2909. const children$1 = children(item);
  2910. const subs = bind$3(children$1, child => systemApi.get().getByDom(child).fold(() => [], pure$2));
  2911. subcomponents.set(subs);
  2912. };
  2913. const config = behaviour => {
  2914. const b = bData;
  2915. const f = isFunction(b[behaviour.name()]) ? b[behaviour.name()] : () => {
  2916. throw new Error('Could not find ' + behaviour.name() + ' in ' + JSON.stringify(spec, null, 2));
  2917. };
  2918. return f();
  2919. };
  2920. const hasConfigured = behaviour => isFunction(bData[behaviour.name()]);
  2921. const getApis = () => info.apis;
  2922. const readState = behaviourName => bData[behaviourName]().map(b => b.state.readState()).getOr('not enabled');
  2923. const me = {
  2924. uid: spec.uid,
  2925. getSystem: systemApi.get,
  2926. config,
  2927. hasConfigured,
  2928. spec,
  2929. readState,
  2930. getApis,
  2931. connect,
  2932. disconnect,
  2933. element: item,
  2934. syncComponents,
  2935. components: subcomponents.get,
  2936. events
  2937. };
  2938. return me;
  2939. };
  2940. const buildSubcomponents = (spec, obsoleted) => {
  2941. const components = get$g(spec, 'components').getOr([]);
  2942. return obsoleted.fold(() => map$2(components, build$1), obs => map$2(components, (c, i) => {
  2943. return buildOrPatch(c, child$2(obs, i));
  2944. }));
  2945. };
  2946. const buildFromSpec = (userSpec, obsoleted) => {
  2947. const {
  2948. events: specEvents,
  2949. ...spec
  2950. } = make$8(userSpec);
  2951. const components = buildSubcomponents(spec, obsoleted);
  2952. const completeSpec = {
  2953. ...spec,
  2954. events: {
  2955. ...DefaultEvents,
  2956. ...specEvents
  2957. },
  2958. components
  2959. };
  2960. return Result.value(build$2(completeSpec, obsoleted));
  2961. };
  2962. const text$2 = textContent => {
  2963. const element = SugarElement.fromText(textContent);
  2964. return external$1({ element });
  2965. };
  2966. const external$1 = spec => {
  2967. const extSpec = asRawOrDie$1('external.component', objOfOnly([
  2968. required$1('element'),
  2969. option$3('uid')
  2970. ]), spec);
  2971. const systemApi = Cell(NoContextApi());
  2972. const connect = newApi => {
  2973. systemApi.set(newApi);
  2974. };
  2975. const disconnect = () => {
  2976. systemApi.set(NoContextApi(() => me));
  2977. };
  2978. const uid = extSpec.uid.getOrThunk(() => generate$5('external'));
  2979. writeOnly(extSpec.element, uid);
  2980. const me = {
  2981. uid,
  2982. getSystem: systemApi.get,
  2983. config: Optional.none,
  2984. hasConfigured: never,
  2985. connect,
  2986. disconnect,
  2987. getApis: () => ({}),
  2988. element: extSpec.element,
  2989. spec,
  2990. readState: constant$1('No state'),
  2991. syncComponents: noop,
  2992. components: constant$1([]),
  2993. events: {}
  2994. };
  2995. return premade$1(me);
  2996. };
  2997. const uids = generate$5;
  2998. const isSketchSpec$1 = spec => has$2(spec, 'uid');
  2999. const buildOrPatch = (spec, obsoleted) => getPremade(spec).getOrThunk(() => {
  3000. const userSpecWithUid = isSketchSpec$1(spec) ? spec : {
  3001. uid: uids(''),
  3002. ...spec
  3003. };
  3004. return buildFromSpec(userSpecWithUid, obsoleted).getOrDie();
  3005. });
  3006. const build$1 = spec => buildOrPatch(spec, Optional.none());
  3007. const premade = premade$1;
  3008. var ClosestOrAncestor = (is, ancestor, scope, a, isRoot) => {
  3009. if (is(scope, a)) {
  3010. return Optional.some(scope);
  3011. } else if (isFunction(isRoot) && isRoot(scope)) {
  3012. return Optional.none();
  3013. } else {
  3014. return ancestor(scope, a, isRoot);
  3015. }
  3016. };
  3017. const ancestor$1 = (scope, predicate, isRoot) => {
  3018. let element = scope.dom;
  3019. const stop = isFunction(isRoot) ? isRoot : never;
  3020. while (element.parentNode) {
  3021. element = element.parentNode;
  3022. const el = SugarElement.fromDom(element);
  3023. if (predicate(el)) {
  3024. return Optional.some(el);
  3025. } else if (stop(el)) {
  3026. break;
  3027. }
  3028. }
  3029. return Optional.none();
  3030. };
  3031. const closest$3 = (scope, predicate, isRoot) => {
  3032. const is = (s, test) => test(s);
  3033. return ClosestOrAncestor(is, ancestor$1, scope, predicate, isRoot);
  3034. };
  3035. const child$1 = (scope, predicate) => {
  3036. const pred = node => predicate(SugarElement.fromDom(node));
  3037. const result = find$5(scope.dom.childNodes, pred);
  3038. return result.map(SugarElement.fromDom);
  3039. };
  3040. const descendant$1 = (scope, predicate) => {
  3041. const descend = node => {
  3042. for (let i = 0; i < node.childNodes.length; i++) {
  3043. const child = SugarElement.fromDom(node.childNodes[i]);
  3044. if (predicate(child)) {
  3045. return Optional.some(child);
  3046. }
  3047. const res = descend(node.childNodes[i]);
  3048. if (res.isSome()) {
  3049. return res;
  3050. }
  3051. }
  3052. return Optional.none();
  3053. };
  3054. return descend(scope.dom);
  3055. };
  3056. const closest$2 = (scope, predicate, isRoot) => closest$3(scope, predicate, isRoot).isSome();
  3057. const ancestor = (scope, selector, isRoot) => ancestor$1(scope, e => is(e, selector), isRoot);
  3058. const child = (scope, selector) => child$1(scope, e => is(e, selector));
  3059. const descendant = (scope, selector) => one(selector, scope);
  3060. const closest$1 = (scope, selector, isRoot) => {
  3061. const is$1 = (element, selector) => is(element, selector);
  3062. return ClosestOrAncestor(is$1, ancestor, scope, selector, isRoot);
  3063. };
  3064. const attribute = 'aria-controls';
  3065. const find$1 = queryElem => {
  3066. const dependent = closest$3(queryElem, elem => {
  3067. if (!isElement$1(elem)) {
  3068. return false;
  3069. }
  3070. const id = get$f(elem, 'id');
  3071. return id !== undefined && id.indexOf(attribute) > -1;
  3072. });
  3073. return dependent.bind(dep => {
  3074. const id = get$f(dep, 'id');
  3075. const dos = getRootNode(dep);
  3076. return descendant(dos, `[${ attribute }="${ id }"]`);
  3077. });
  3078. };
  3079. const manager = () => {
  3080. const ariaId = generate$6(attribute);
  3081. const link = elem => {
  3082. set$9(elem, attribute, ariaId);
  3083. };
  3084. const unlink = elem => {
  3085. remove$7(elem, attribute);
  3086. };
  3087. return {
  3088. id: ariaId,
  3089. link,
  3090. unlink
  3091. };
  3092. };
  3093. const isAriaPartOf = (component, queryElem) => find$1(queryElem).exists(owner => isPartOf$1(component, owner));
  3094. const isPartOf$1 = (component, queryElem) => closest$2(queryElem, el => eq(el, component.element), never) || isAriaPartOf(component, queryElem);
  3095. const unknown = 'unknown';
  3096. var EventConfiguration;
  3097. (function (EventConfiguration) {
  3098. EventConfiguration[EventConfiguration['STOP'] = 0] = 'STOP';
  3099. EventConfiguration[EventConfiguration['NORMAL'] = 1] = 'NORMAL';
  3100. EventConfiguration[EventConfiguration['LOGGING'] = 2] = 'LOGGING';
  3101. }(EventConfiguration || (EventConfiguration = {})));
  3102. const eventConfig = Cell({});
  3103. const makeEventLogger = (eventName, initialTarget) => {
  3104. const sequence = [];
  3105. const startTime = new Date().getTime();
  3106. return {
  3107. logEventCut: (_name, target, purpose) => {
  3108. sequence.push({
  3109. outcome: 'cut',
  3110. target,
  3111. purpose
  3112. });
  3113. },
  3114. logEventStopped: (_name, target, purpose) => {
  3115. sequence.push({
  3116. outcome: 'stopped',
  3117. target,
  3118. purpose
  3119. });
  3120. },
  3121. logNoParent: (_name, target, purpose) => {
  3122. sequence.push({
  3123. outcome: 'no-parent',
  3124. target,
  3125. purpose
  3126. });
  3127. },
  3128. logEventNoHandlers: (_name, target) => {
  3129. sequence.push({
  3130. outcome: 'no-handlers-left',
  3131. target
  3132. });
  3133. },
  3134. logEventResponse: (_name, target, purpose) => {
  3135. sequence.push({
  3136. outcome: 'response',
  3137. purpose,
  3138. target
  3139. });
  3140. },
  3141. write: () => {
  3142. const finishTime = new Date().getTime();
  3143. if (contains$2([
  3144. 'mousemove',
  3145. 'mouseover',
  3146. 'mouseout',
  3147. systemInit()
  3148. ], eventName)) {
  3149. return;
  3150. }
  3151. console.log(eventName, {
  3152. event: eventName,
  3153. time: finishTime - startTime,
  3154. target: initialTarget.dom,
  3155. sequence: map$2(sequence, s => {
  3156. if (!contains$2([
  3157. 'cut',
  3158. 'stopped',
  3159. 'response'
  3160. ], s.outcome)) {
  3161. return s.outcome;
  3162. } else {
  3163. return '{' + s.purpose + '} ' + s.outcome + ' at (' + element(s.target) + ')';
  3164. }
  3165. })
  3166. });
  3167. }
  3168. };
  3169. };
  3170. const processEvent = (eventName, initialTarget, f) => {
  3171. const status = get$g(eventConfig.get(), eventName).orThunk(() => {
  3172. const patterns = keys(eventConfig.get());
  3173. return findMap(patterns, p => eventName.indexOf(p) > -1 ? Optional.some(eventConfig.get()[p]) : Optional.none());
  3174. }).getOr(EventConfiguration.NORMAL);
  3175. switch (status) {
  3176. case EventConfiguration.NORMAL:
  3177. return f(noLogger());
  3178. case EventConfiguration.LOGGING: {
  3179. const logger = makeEventLogger(eventName, initialTarget);
  3180. const output = f(logger);
  3181. logger.write();
  3182. return output;
  3183. }
  3184. case EventConfiguration.STOP:
  3185. return true;
  3186. }
  3187. };
  3188. const path = [
  3189. 'alloy/data/Fields',
  3190. 'alloy/debugging/Debugging'
  3191. ];
  3192. const getTrace = () => {
  3193. const err = new Error();
  3194. if (err.stack !== undefined) {
  3195. const lines = err.stack.split('\n');
  3196. return find$5(lines, line => line.indexOf('alloy') > 0 && !exists(path, p => line.indexOf(p) > -1)).getOr(unknown);
  3197. } else {
  3198. return unknown;
  3199. }
  3200. };
  3201. const ignoreEvent = {
  3202. logEventCut: noop,
  3203. logEventStopped: noop,
  3204. logNoParent: noop,
  3205. logEventNoHandlers: noop,
  3206. logEventResponse: noop,
  3207. write: noop
  3208. };
  3209. const monitorEvent = (eventName, initialTarget, f) => processEvent(eventName, initialTarget, f);
  3210. const noLogger = constant$1(ignoreEvent);
  3211. const menuFields = constant$1([
  3212. required$1('menu'),
  3213. required$1('selectedMenu')
  3214. ]);
  3215. const itemFields = constant$1([
  3216. required$1('item'),
  3217. required$1('selectedItem')
  3218. ]);
  3219. constant$1(objOf(itemFields().concat(menuFields())));
  3220. const itemSchema$3 = constant$1(objOf(itemFields()));
  3221. const _initSize = requiredObjOf('initSize', [
  3222. required$1('numColumns'),
  3223. required$1('numRows')
  3224. ]);
  3225. const itemMarkers = () => requiredOf('markers', itemSchema$3());
  3226. const tieredMenuMarkers = () => requiredObjOf('markers', [required$1('backgroundMenu')].concat(menuFields()).concat(itemFields()));
  3227. const markers$1 = required => requiredObjOf('markers', map$2(required, required$1));
  3228. const onPresenceHandler = (label, fieldName, presence) => {
  3229. getTrace();
  3230. return field$1(fieldName, fieldName, presence, valueOf(f => Result.value((...args) => {
  3231. return f.apply(undefined, args);
  3232. })));
  3233. };
  3234. const onHandler = fieldName => onPresenceHandler('onHandler', fieldName, defaulted$1(noop));
  3235. const onKeyboardHandler = fieldName => onPresenceHandler('onKeyboardHandler', fieldName, defaulted$1(Optional.none));
  3236. const onStrictHandler = fieldName => onPresenceHandler('onHandler', fieldName, required$2());
  3237. const onStrictKeyboardHandler = fieldName => onPresenceHandler('onKeyboardHandler', fieldName, required$2());
  3238. const output$1 = (name, value) => customField(name, constant$1(value));
  3239. const snapshot = name => customField(name, identity);
  3240. const initSize = constant$1(_initSize);
  3241. const nu$6 = (x, y, bubble, direction, placement, boundsRestriction, labelPrefix, alwaysFit = false) => ({
  3242. x,
  3243. y,
  3244. bubble,
  3245. direction,
  3246. placement,
  3247. restriction: boundsRestriction,
  3248. label: `${ labelPrefix }-${ placement }`,
  3249. alwaysFit
  3250. });
  3251. const adt$a = Adt.generate([
  3252. { southeast: [] },
  3253. { southwest: [] },
  3254. { northeast: [] },
  3255. { northwest: [] },
  3256. { south: [] },
  3257. { north: [] },
  3258. { east: [] },
  3259. { west: [] }
  3260. ]);
  3261. const cata$2 = (subject, southeast, southwest, northeast, northwest, south, north, east, west) => subject.fold(southeast, southwest, northeast, northwest, south, north, east, west);
  3262. const cataVertical = (subject, south, middle, north) => subject.fold(south, south, north, north, south, north, middle, middle);
  3263. const cataHorizontal = (subject, east, middle, west) => subject.fold(east, west, east, west, middle, middle, east, west);
  3264. const southeast$3 = adt$a.southeast;
  3265. const southwest$3 = adt$a.southwest;
  3266. const northeast$3 = adt$a.northeast;
  3267. const northwest$3 = adt$a.northwest;
  3268. const south$3 = adt$a.south;
  3269. const north$3 = adt$a.north;
  3270. const east$3 = adt$a.east;
  3271. const west$3 = adt$a.west;
  3272. const cycleBy = (value, delta, min, max) => {
  3273. const r = value + delta;
  3274. if (r > max) {
  3275. return min;
  3276. } else if (r < min) {
  3277. return max;
  3278. } else {
  3279. return r;
  3280. }
  3281. };
  3282. const clamp = (value, min, max) => Math.min(Math.max(value, min), max);
  3283. const getRestriction = (anchor, restriction) => {
  3284. switch (restriction) {
  3285. case 1:
  3286. return anchor.x;
  3287. case 0:
  3288. return anchor.x + anchor.width;
  3289. case 2:
  3290. return anchor.y;
  3291. case 3:
  3292. return anchor.y + anchor.height;
  3293. }
  3294. };
  3295. const boundsRestriction = (anchor, restrictions) => mapToObject([
  3296. 'left',
  3297. 'right',
  3298. 'top',
  3299. 'bottom'
  3300. ], dir => get$g(restrictions, dir).map(restriction => getRestriction(anchor, restriction)));
  3301. const adjustBounds = (bounds$1, restriction, bubbleOffset) => {
  3302. const applyRestriction = (dir, current) => restriction[dir].map(pos => {
  3303. const isVerticalAxis = dir === 'top' || dir === 'bottom';
  3304. const offset = isVerticalAxis ? bubbleOffset.top : bubbleOffset.left;
  3305. const comparator = dir === 'left' || dir === 'top' ? Math.max : Math.min;
  3306. const newPos = comparator(pos, current) + offset;
  3307. return isVerticalAxis ? clamp(newPos, bounds$1.y, bounds$1.bottom) : clamp(newPos, bounds$1.x, bounds$1.right);
  3308. }).getOr(current);
  3309. const adjustedLeft = applyRestriction('left', bounds$1.x);
  3310. const adjustedTop = applyRestriction('top', bounds$1.y);
  3311. const adjustedRight = applyRestriction('right', bounds$1.right);
  3312. const adjustedBottom = applyRestriction('bottom', bounds$1.bottom);
  3313. return bounds(adjustedLeft, adjustedTop, adjustedRight - adjustedLeft, adjustedBottom - adjustedTop);
  3314. };
  3315. const labelPrefix$2 = 'layout';
  3316. const eastX$1 = anchor => anchor.x;
  3317. const middleX$1 = (anchor, element) => anchor.x + anchor.width / 2 - element.width / 2;
  3318. const westX$1 = (anchor, element) => anchor.x + anchor.width - element.width;
  3319. const northY$2 = (anchor, element) => anchor.y - element.height;
  3320. const southY$2 = anchor => anchor.y + anchor.height;
  3321. const centreY$1 = (anchor, element) => anchor.y + anchor.height / 2 - element.height / 2;
  3322. const eastEdgeX$1 = anchor => anchor.x + anchor.width;
  3323. const westEdgeX$1 = (anchor, element) => anchor.x - element.width;
  3324. const southeast$2 = (anchor, element, bubbles) => nu$6(eastX$1(anchor), southY$2(anchor), bubbles.southeast(), southeast$3(), 'southeast', boundsRestriction(anchor, {
  3325. left: 1,
  3326. top: 3
  3327. }), labelPrefix$2);
  3328. const southwest$2 = (anchor, element, bubbles) => nu$6(westX$1(anchor, element), southY$2(anchor), bubbles.southwest(), southwest$3(), 'southwest', boundsRestriction(anchor, {
  3329. right: 0,
  3330. top: 3
  3331. }), labelPrefix$2);
  3332. const northeast$2 = (anchor, element, bubbles) => nu$6(eastX$1(anchor), northY$2(anchor, element), bubbles.northeast(), northeast$3(), 'northeast', boundsRestriction(anchor, {
  3333. left: 1,
  3334. bottom: 2
  3335. }), labelPrefix$2);
  3336. const northwest$2 = (anchor, element, bubbles) => nu$6(westX$1(anchor, element), northY$2(anchor, element), bubbles.northwest(), northwest$3(), 'northwest', boundsRestriction(anchor, {
  3337. right: 0,
  3338. bottom: 2
  3339. }), labelPrefix$2);
  3340. const north$2 = (anchor, element, bubbles) => nu$6(middleX$1(anchor, element), northY$2(anchor, element), bubbles.north(), north$3(), 'north', boundsRestriction(anchor, { bottom: 2 }), labelPrefix$2);
  3341. const south$2 = (anchor, element, bubbles) => nu$6(middleX$1(anchor, element), southY$2(anchor), bubbles.south(), south$3(), 'south', boundsRestriction(anchor, { top: 3 }), labelPrefix$2);
  3342. const east$2 = (anchor, element, bubbles) => nu$6(eastEdgeX$1(anchor), centreY$1(anchor, element), bubbles.east(), east$3(), 'east', boundsRestriction(anchor, { left: 0 }), labelPrefix$2);
  3343. const west$2 = (anchor, element, bubbles) => nu$6(westEdgeX$1(anchor, element), centreY$1(anchor, element), bubbles.west(), west$3(), 'west', boundsRestriction(anchor, { right: 1 }), labelPrefix$2);
  3344. const all$1 = () => [
  3345. southeast$2,
  3346. southwest$2,
  3347. northeast$2,
  3348. northwest$2,
  3349. south$2,
  3350. north$2,
  3351. east$2,
  3352. west$2
  3353. ];
  3354. const allRtl$1 = () => [
  3355. southwest$2,
  3356. southeast$2,
  3357. northwest$2,
  3358. northeast$2,
  3359. south$2,
  3360. north$2,
  3361. east$2,
  3362. west$2
  3363. ];
  3364. const aboveOrBelow = () => [
  3365. northeast$2,
  3366. northwest$2,
  3367. southeast$2,
  3368. southwest$2,
  3369. north$2,
  3370. south$2
  3371. ];
  3372. const aboveOrBelowRtl = () => [
  3373. northwest$2,
  3374. northeast$2,
  3375. southwest$2,
  3376. southeast$2,
  3377. north$2,
  3378. south$2
  3379. ];
  3380. const belowOrAbove = () => [
  3381. southeast$2,
  3382. southwest$2,
  3383. northeast$2,
  3384. northwest$2,
  3385. south$2,
  3386. north$2
  3387. ];
  3388. const belowOrAboveRtl = () => [
  3389. southwest$2,
  3390. southeast$2,
  3391. northwest$2,
  3392. northeast$2,
  3393. south$2,
  3394. north$2
  3395. ];
  3396. const chooseChannels = (channels, message) => message.universal ? channels : filter$2(channels, ch => contains$2(message.channels, ch));
  3397. const events$h = receiveConfig => derive$2([run$1(receive(), (component, message) => {
  3398. const channelMap = receiveConfig.channels;
  3399. const channels = keys(channelMap);
  3400. const receivingData = message;
  3401. const targetChannels = chooseChannels(channels, receivingData);
  3402. each$1(targetChannels, ch => {
  3403. const channelInfo = channelMap[ch];
  3404. const channelSchema = channelInfo.schema;
  3405. const data = asRawOrDie$1('channel[' + ch + '] data\nReceiver: ' + element(component.element), channelSchema, receivingData.data);
  3406. channelInfo.onReceive(component, data);
  3407. });
  3408. })]);
  3409. var ActiveReceiving = /*#__PURE__*/Object.freeze({
  3410. __proto__: null,
  3411. events: events$h
  3412. });
  3413. var ReceivingSchema = [requiredOf('channels', setOf(Result.value, objOfOnly([
  3414. onStrictHandler('onReceive'),
  3415. defaulted('schema', anyValue())
  3416. ])))];
  3417. const executeEvent = (bConfig, bState, executor) => runOnExecute$1(component => {
  3418. executor(component, bConfig, bState);
  3419. });
  3420. const loadEvent = (bConfig, bState, f) => runOnInit((component, _simulatedEvent) => {
  3421. f(component, bConfig, bState);
  3422. });
  3423. const create$5 = (schema, name, active, apis, extra, state) => {
  3424. const configSchema = objOfOnly(schema);
  3425. const schemaSchema = optionObjOf(name, [optionObjOfOnly('config', schema)]);
  3426. return doCreate(configSchema, schemaSchema, name, active, apis, extra, state);
  3427. };
  3428. const createModes$1 = (modes, name, active, apis, extra, state) => {
  3429. const configSchema = modes;
  3430. const schemaSchema = optionObjOf(name, [optionOf('config', modes)]);
  3431. return doCreate(configSchema, schemaSchema, name, active, apis, extra, state);
  3432. };
  3433. const wrapApi = (bName, apiFunction, apiName) => {
  3434. const f = (component, ...rest) => {
  3435. const args = [component].concat(rest);
  3436. return component.config({ name: constant$1(bName) }).fold(() => {
  3437. throw new Error('We could not find any behaviour configuration for: ' + bName + '. Using API: ' + apiName);
  3438. }, info => {
  3439. const rest = Array.prototype.slice.call(args, 1);
  3440. return apiFunction.apply(undefined, [
  3441. component,
  3442. info.config,
  3443. info.state
  3444. ].concat(rest));
  3445. });
  3446. };
  3447. return markAsBehaviourApi(f, apiName, apiFunction);
  3448. };
  3449. const revokeBehaviour = name => ({
  3450. key: name,
  3451. value: undefined
  3452. });
  3453. const doCreate = (configSchema, schemaSchema, name, active, apis, extra, state) => {
  3454. const getConfig = info => hasNonNullableKey(info, name) ? info[name]() : Optional.none();
  3455. const wrappedApis = map$1(apis, (apiF, apiName) => wrapApi(name, apiF, apiName));
  3456. const wrappedExtra = map$1(extra, (extraF, extraName) => markAsExtraApi(extraF, extraName));
  3457. const me = {
  3458. ...wrappedExtra,
  3459. ...wrappedApis,
  3460. revoke: curry(revokeBehaviour, name),
  3461. config: spec => {
  3462. const prepared = asRawOrDie$1(name + '-config', configSchema, spec);
  3463. return {
  3464. key: name,
  3465. value: {
  3466. config: prepared,
  3467. me,
  3468. configAsRaw: cached(() => asRawOrDie$1(name + '-config', configSchema, spec)),
  3469. initialConfig: spec,
  3470. state
  3471. }
  3472. };
  3473. },
  3474. schema: constant$1(schemaSchema),
  3475. exhibit: (info, base) => {
  3476. return lift2(getConfig(info), get$g(active, 'exhibit'), (behaviourInfo, exhibitor) => {
  3477. return exhibitor(base, behaviourInfo.config, behaviourInfo.state);
  3478. }).getOrThunk(() => nu$7({}));
  3479. },
  3480. name: constant$1(name),
  3481. handlers: info => {
  3482. return getConfig(info).map(behaviourInfo => {
  3483. const getEvents = get$g(active, 'events').getOr(() => ({}));
  3484. return getEvents(behaviourInfo.config, behaviourInfo.state);
  3485. }).getOr({});
  3486. }
  3487. };
  3488. return me;
  3489. };
  3490. const derive$1 = capabilities => wrapAll(capabilities);
  3491. const simpleSchema = objOfOnly([
  3492. required$1('fields'),
  3493. required$1('name'),
  3494. defaulted('active', {}),
  3495. defaulted('apis', {}),
  3496. defaulted('state', NoState),
  3497. defaulted('extra', {})
  3498. ]);
  3499. const create$4 = data => {
  3500. const value = asRawOrDie$1('Creating behaviour: ' + data.name, simpleSchema, data);
  3501. return create$5(value.fields, value.name, value.active, value.apis, value.extra, value.state);
  3502. };
  3503. const modeSchema = objOfOnly([
  3504. required$1('branchKey'),
  3505. required$1('branches'),
  3506. required$1('name'),
  3507. defaulted('active', {}),
  3508. defaulted('apis', {}),
  3509. defaulted('state', NoState),
  3510. defaulted('extra', {})
  3511. ]);
  3512. const createModes = data => {
  3513. const value = asRawOrDie$1('Creating behaviour: ' + data.name, modeSchema, data);
  3514. return createModes$1(choose$1(value.branchKey, value.branches), value.name, value.active, value.apis, value.extra, value.state);
  3515. };
  3516. const revoke = constant$1(undefined);
  3517. const Receiving = create$4({
  3518. fields: ReceivingSchema,
  3519. name: 'receiving',
  3520. active: ActiveReceiving
  3521. });
  3522. const exhibit$6 = (base, posConfig) => nu$7({
  3523. classes: [],
  3524. styles: posConfig.useFixed() ? {} : { position: 'relative' }
  3525. });
  3526. var ActivePosition = /*#__PURE__*/Object.freeze({
  3527. __proto__: null,
  3528. exhibit: exhibit$6
  3529. });
  3530. const focus$3 = element => element.dom.focus();
  3531. const blur$1 = element => element.dom.blur();
  3532. const hasFocus = element => {
  3533. const root = getRootNode(element).dom;
  3534. return element.dom === root.activeElement;
  3535. };
  3536. const active$1 = (root = getDocument()) => Optional.from(root.dom.activeElement).map(SugarElement.fromDom);
  3537. const search = element => active$1(getRootNode(element)).filter(e => element.dom.contains(e.dom));
  3538. const preserve$1 = (f, container) => {
  3539. const dos = getRootNode(container);
  3540. const refocus = active$1(dos).bind(focused => {
  3541. const hasFocus = elem => eq(focused, elem);
  3542. return hasFocus(container) ? Optional.some(container) : descendant$1(container, hasFocus);
  3543. });
  3544. const result = f(container);
  3545. refocus.each(oldFocus => {
  3546. active$1(dos).filter(newFocus => eq(newFocus, oldFocus)).fold(() => {
  3547. focus$3(oldFocus);
  3548. }, noop);
  3549. });
  3550. return result;
  3551. };
  3552. const NuPositionCss = (position, left, top, right, bottom) => {
  3553. const toPx = num => num + 'px';
  3554. return {
  3555. position,
  3556. left: left.map(toPx),
  3557. top: top.map(toPx),
  3558. right: right.map(toPx),
  3559. bottom: bottom.map(toPx)
  3560. };
  3561. };
  3562. const toOptions = position => ({
  3563. ...position,
  3564. position: Optional.some(position.position)
  3565. });
  3566. const applyPositionCss = (element, position) => {
  3567. setOptions(element, toOptions(position));
  3568. };
  3569. const adt$9 = Adt.generate([
  3570. { none: [] },
  3571. {
  3572. relative: [
  3573. 'x',
  3574. 'y',
  3575. 'width',
  3576. 'height'
  3577. ]
  3578. },
  3579. {
  3580. fixed: [
  3581. 'x',
  3582. 'y',
  3583. 'width',
  3584. 'height'
  3585. ]
  3586. }
  3587. ]);
  3588. const positionWithDirection = (posName, decision, x, y, width, height) => {
  3589. const decisionRect = decision.rect;
  3590. const decisionX = decisionRect.x - x;
  3591. const decisionY = decisionRect.y - y;
  3592. const decisionWidth = decisionRect.width;
  3593. const decisionHeight = decisionRect.height;
  3594. const decisionRight = width - (decisionX + decisionWidth);
  3595. const decisionBottom = height - (decisionY + decisionHeight);
  3596. const left = Optional.some(decisionX);
  3597. const top = Optional.some(decisionY);
  3598. const right = Optional.some(decisionRight);
  3599. const bottom = Optional.some(decisionBottom);
  3600. const none = Optional.none();
  3601. return cata$2(decision.direction, () => NuPositionCss(posName, left, top, none, none), () => NuPositionCss(posName, none, top, right, none), () => NuPositionCss(posName, left, none, none, bottom), () => NuPositionCss(posName, none, none, right, bottom), () => NuPositionCss(posName, left, top, none, none), () => NuPositionCss(posName, left, none, none, bottom), () => NuPositionCss(posName, left, top, none, none), () => NuPositionCss(posName, none, top, right, none));
  3602. };
  3603. const reposition = (origin, decision) => origin.fold(() => {
  3604. const decisionRect = decision.rect;
  3605. return NuPositionCss('absolute', Optional.some(decisionRect.x), Optional.some(decisionRect.y), Optional.none(), Optional.none());
  3606. }, (x, y, width, height) => {
  3607. return positionWithDirection('absolute', decision, x, y, width, height);
  3608. }, (x, y, width, height) => {
  3609. return positionWithDirection('fixed', decision, x, y, width, height);
  3610. });
  3611. const toBox = (origin, element) => {
  3612. const rel = curry(find$2, element);
  3613. const position = origin.fold(rel, rel, () => {
  3614. const scroll = get$b();
  3615. return find$2(element).translate(-scroll.left, -scroll.top);
  3616. });
  3617. const width = getOuter$1(element);
  3618. const height = getOuter$2(element);
  3619. return bounds(position.left, position.top, width, height);
  3620. };
  3621. const viewport = (origin, getBounds) => getBounds.fold(() => origin.fold(win, win, bounds), b => origin.fold(b, b, () => {
  3622. const bounds$1 = b();
  3623. const pos = translate$2(origin, bounds$1.x, bounds$1.y);
  3624. return bounds(pos.left, pos.top, bounds$1.width, bounds$1.height);
  3625. }));
  3626. const translate$2 = (origin, x, y) => {
  3627. const pos = SugarPosition(x, y);
  3628. const removeScroll = () => {
  3629. const outerScroll = get$b();
  3630. return pos.translate(-outerScroll.left, -outerScroll.top);
  3631. };
  3632. return origin.fold(constant$1(pos), constant$1(pos), removeScroll);
  3633. };
  3634. const cata$1 = (subject, onNone, onRelative, onFixed) => subject.fold(onNone, onRelative, onFixed);
  3635. adt$9.none;
  3636. const relative$1 = adt$9.relative;
  3637. const fixed$1 = adt$9.fixed;
  3638. const anchor = (anchorBox, origin) => ({
  3639. anchorBox,
  3640. origin
  3641. });
  3642. const box = (anchorBox, origin) => anchor(anchorBox, origin);
  3643. const placementAttribute = 'data-alloy-placement';
  3644. const setPlacement$1 = (element, placement) => {
  3645. set$9(element, placementAttribute, placement);
  3646. };
  3647. const getPlacement = element => getOpt(element, placementAttribute);
  3648. const reset$2 = element => remove$7(element, placementAttribute);
  3649. const adt$8 = Adt.generate([
  3650. { fit: ['reposition'] },
  3651. {
  3652. nofit: [
  3653. 'reposition',
  3654. 'visibleW',
  3655. 'visibleH',
  3656. 'isVisible'
  3657. ]
  3658. }
  3659. ]);
  3660. const determinePosition = (box, bounds) => {
  3661. const {
  3662. x: boundsX,
  3663. y: boundsY,
  3664. right: boundsRight,
  3665. bottom: boundsBottom
  3666. } = bounds;
  3667. const {x, y, right, bottom, width, height} = box;
  3668. const xInBounds = x >= boundsX && x <= boundsRight;
  3669. const yInBounds = y >= boundsY && y <= boundsBottom;
  3670. const originInBounds = xInBounds && yInBounds;
  3671. const rightInBounds = right <= boundsRight && right >= boundsX;
  3672. const bottomInBounds = bottom <= boundsBottom && bottom >= boundsY;
  3673. const sizeInBounds = rightInBounds && bottomInBounds;
  3674. const visibleW = Math.min(width, x >= boundsX ? boundsRight - x : right - boundsX);
  3675. const visibleH = Math.min(height, y >= boundsY ? boundsBottom - y : bottom - boundsY);
  3676. return {
  3677. originInBounds,
  3678. sizeInBounds,
  3679. visibleW,
  3680. visibleH
  3681. };
  3682. };
  3683. const calcReposition = (box, bounds$1) => {
  3684. const {
  3685. x: boundsX,
  3686. y: boundsY,
  3687. right: boundsRight,
  3688. bottom: boundsBottom
  3689. } = bounds$1;
  3690. const {x, y, width, height} = box;
  3691. const maxX = Math.max(boundsX, boundsRight - width);
  3692. const maxY = Math.max(boundsY, boundsBottom - height);
  3693. const restrictedX = clamp(x, boundsX, maxX);
  3694. const restrictedY = clamp(y, boundsY, maxY);
  3695. const restrictedWidth = Math.min(restrictedX + width, boundsRight) - restrictedX;
  3696. const restrictedHeight = Math.min(restrictedY + height, boundsBottom) - restrictedY;
  3697. return bounds(restrictedX, restrictedY, restrictedWidth, restrictedHeight);
  3698. };
  3699. const calcMaxSizes = (direction, box, bounds) => {
  3700. const upAvailable = constant$1(box.bottom - bounds.y);
  3701. const downAvailable = constant$1(bounds.bottom - box.y);
  3702. const maxHeight = cataVertical(direction, downAvailable, downAvailable, upAvailable);
  3703. const westAvailable = constant$1(box.right - bounds.x);
  3704. const eastAvailable = constant$1(bounds.right - box.x);
  3705. const maxWidth = cataHorizontal(direction, eastAvailable, eastAvailable, westAvailable);
  3706. return {
  3707. maxWidth,
  3708. maxHeight
  3709. };
  3710. };
  3711. const attempt = (candidate, width, height, bounds$1) => {
  3712. const bubble = candidate.bubble;
  3713. const bubbleOffset = bubble.offset;
  3714. const adjustedBounds = adjustBounds(bounds$1, candidate.restriction, bubbleOffset);
  3715. const newX = candidate.x + bubbleOffset.left;
  3716. const newY = candidate.y + bubbleOffset.top;
  3717. const box = bounds(newX, newY, width, height);
  3718. const {originInBounds, sizeInBounds, visibleW, visibleH} = determinePosition(box, adjustedBounds);
  3719. const fits = originInBounds && sizeInBounds;
  3720. const fittedBox = fits ? box : calcReposition(box, adjustedBounds);
  3721. const isPartlyVisible = fittedBox.width > 0 && fittedBox.height > 0;
  3722. const {maxWidth, maxHeight} = calcMaxSizes(candidate.direction, fittedBox, bounds$1);
  3723. const reposition = {
  3724. rect: fittedBox,
  3725. maxHeight,
  3726. maxWidth,
  3727. direction: candidate.direction,
  3728. placement: candidate.placement,
  3729. classes: {
  3730. on: bubble.classesOn,
  3731. off: bubble.classesOff
  3732. },
  3733. layout: candidate.label,
  3734. testY: newY
  3735. };
  3736. return fits || candidate.alwaysFit ? adt$8.fit(reposition) : adt$8.nofit(reposition, visibleW, visibleH, isPartlyVisible);
  3737. };
  3738. const attempts = (element, candidates, anchorBox, elementBox, bubbles, bounds) => {
  3739. const panelWidth = elementBox.width;
  3740. const panelHeight = elementBox.height;
  3741. const attemptBestFit = (layout, reposition, visibleW, visibleH, isVisible) => {
  3742. const next = layout(anchorBox, elementBox, bubbles, element, bounds);
  3743. const attemptLayout = attempt(next, panelWidth, panelHeight, bounds);
  3744. return attemptLayout.fold(constant$1(attemptLayout), (newReposition, newVisibleW, newVisibleH, newIsVisible) => {
  3745. const improved = isVisible === newIsVisible ? newVisibleH > visibleH || newVisibleW > visibleW : !isVisible && newIsVisible;
  3746. return improved ? attemptLayout : adt$8.nofit(reposition, visibleW, visibleH, isVisible);
  3747. });
  3748. };
  3749. const abc = foldl(candidates, (b, a) => {
  3750. const bestNext = curry(attemptBestFit, a);
  3751. return b.fold(constant$1(b), bestNext);
  3752. }, adt$8.nofit({
  3753. rect: anchorBox,
  3754. maxHeight: elementBox.height,
  3755. maxWidth: elementBox.width,
  3756. direction: southeast$3(),
  3757. placement: 'southeast',
  3758. classes: {
  3759. on: [],
  3760. off: []
  3761. },
  3762. layout: 'none',
  3763. testY: anchorBox.y
  3764. }, -1, -1, false));
  3765. return abc.fold(identity, identity);
  3766. };
  3767. const singleton = doRevoke => {
  3768. const subject = Cell(Optional.none());
  3769. const revoke = () => subject.get().each(doRevoke);
  3770. const clear = () => {
  3771. revoke();
  3772. subject.set(Optional.none());
  3773. };
  3774. const isSet = () => subject.get().isSome();
  3775. const get = () => subject.get();
  3776. const set = s => {
  3777. revoke();
  3778. subject.set(Optional.some(s));
  3779. };
  3780. return {
  3781. clear,
  3782. isSet,
  3783. get,
  3784. set
  3785. };
  3786. };
  3787. const destroyable = () => singleton(s => s.destroy());
  3788. const unbindable = () => singleton(s => s.unbind());
  3789. const value$2 = () => {
  3790. const subject = singleton(noop);
  3791. const on = f => subject.get().each(f);
  3792. return {
  3793. ...subject,
  3794. on
  3795. };
  3796. };
  3797. const filter = always;
  3798. const bind = (element, event, handler) => bind$2(element, event, filter, handler);
  3799. const capture = (element, event, handler) => capture$1(element, event, filter, handler);
  3800. const fromRawEvent = fromRawEvent$1;
  3801. const properties = [
  3802. 'top',
  3803. 'bottom',
  3804. 'right',
  3805. 'left'
  3806. ];
  3807. const timerAttr = 'data-alloy-transition-timer';
  3808. const isTransitioning$1 = (element, transition) => hasAll(element, transition.classes);
  3809. const shouldApplyTransitionCss = (transition, decision, lastPlacement) => {
  3810. return lastPlacement.exists(placer => {
  3811. const mode = transition.mode;
  3812. return mode === 'all' ? true : placer[mode] !== decision[mode];
  3813. });
  3814. };
  3815. const hasChanges = (position, intermediate) => {
  3816. const round = value => parseFloat(value).toFixed(3);
  3817. return find$4(intermediate, (value, key) => {
  3818. const newValue = position[key].map(round);
  3819. const val = value.map(round);
  3820. return !equals(newValue, val);
  3821. }).isSome();
  3822. };
  3823. const getTransitionDuration = element => {
  3824. const get = name => {
  3825. const style = get$e(element, name);
  3826. const times = style.split(/\s*,\s*/);
  3827. return filter$2(times, isNotEmpty);
  3828. };
  3829. const parse = value => {
  3830. if (isString(value) && /^[\d.]+/.test(value)) {
  3831. const num = parseFloat(value);
  3832. return endsWith(value, 'ms') ? num : num * 1000;
  3833. } else {
  3834. return 0;
  3835. }
  3836. };
  3837. const delay = get('transition-delay');
  3838. const duration = get('transition-duration');
  3839. return foldl(duration, (acc, dur, i) => {
  3840. const time = parse(delay[i]) + parse(dur);
  3841. return Math.max(acc, time);
  3842. }, 0);
  3843. };
  3844. const setupTransitionListeners = (element, transition) => {
  3845. const transitionEnd = unbindable();
  3846. const transitionCancel = unbindable();
  3847. let timer;
  3848. const isSourceTransition = e => {
  3849. var _a;
  3850. const pseudoElement = (_a = e.raw.pseudoElement) !== null && _a !== void 0 ? _a : '';
  3851. return eq(e.target, element) && isEmpty(pseudoElement) && contains$2(properties, e.raw.propertyName);
  3852. };
  3853. const transitionDone = e => {
  3854. if (isNullable(e) || isSourceTransition(e)) {
  3855. transitionEnd.clear();
  3856. transitionCancel.clear();
  3857. const type = e === null || e === void 0 ? void 0 : e.raw.type;
  3858. if (isNullable(type) || type === transitionend()) {
  3859. clearTimeout(timer);
  3860. remove$7(element, timerAttr);
  3861. remove$1(element, transition.classes);
  3862. }
  3863. }
  3864. };
  3865. const transitionStart = bind(element, transitionstart(), e => {
  3866. if (isSourceTransition(e)) {
  3867. transitionStart.unbind();
  3868. transitionEnd.set(bind(element, transitionend(), transitionDone));
  3869. transitionCancel.set(bind(element, transitioncancel(), transitionDone));
  3870. }
  3871. });
  3872. const duration = getTransitionDuration(element);
  3873. requestAnimationFrame(() => {
  3874. timer = setTimeout(transitionDone, duration + 17);
  3875. set$9(element, timerAttr, timer);
  3876. });
  3877. };
  3878. const startTransitioning = (element, transition) => {
  3879. add$1(element, transition.classes);
  3880. getOpt(element, timerAttr).each(timerId => {
  3881. clearTimeout(parseInt(timerId, 10));
  3882. remove$7(element, timerAttr);
  3883. });
  3884. setupTransitionListeners(element, transition);
  3885. };
  3886. const applyTransitionCss = (element, origin, position, transition, decision, lastPlacement) => {
  3887. const shouldTransition = shouldApplyTransitionCss(transition, decision, lastPlacement);
  3888. if (shouldTransition || isTransitioning$1(element, transition)) {
  3889. set$8(element, 'position', position.position);
  3890. const rect = toBox(origin, element);
  3891. const intermediatePosition = reposition(origin, {
  3892. ...decision,
  3893. rect
  3894. });
  3895. const intermediateCssOptions = mapToObject(properties, prop => intermediatePosition[prop]);
  3896. if (hasChanges(position, intermediateCssOptions)) {
  3897. setOptions(element, intermediateCssOptions);
  3898. if (shouldTransition) {
  3899. startTransitioning(element, transition);
  3900. }
  3901. reflow(element);
  3902. }
  3903. } else {
  3904. remove$1(element, transition.classes);
  3905. }
  3906. };
  3907. const elementSize = p => ({
  3908. width: getOuter$1(p),
  3909. height: getOuter$2(p)
  3910. });
  3911. const layout = (anchorBox, element, bubbles, options) => {
  3912. remove$6(element, 'max-height');
  3913. remove$6(element, 'max-width');
  3914. const elementBox = elementSize(element);
  3915. return attempts(element, options.preference, anchorBox, elementBox, bubbles, options.bounds);
  3916. };
  3917. const setClasses = (element, decision) => {
  3918. const classInfo = decision.classes;
  3919. remove$1(element, classInfo.off);
  3920. add$1(element, classInfo.on);
  3921. };
  3922. const setHeight = (element, decision, options) => {
  3923. const maxHeightFunction = options.maxHeightFunction;
  3924. maxHeightFunction(element, decision.maxHeight);
  3925. };
  3926. const setWidth = (element, decision, options) => {
  3927. const maxWidthFunction = options.maxWidthFunction;
  3928. maxWidthFunction(element, decision.maxWidth);
  3929. };
  3930. const position$2 = (element, decision, options) => {
  3931. const positionCss = reposition(options.origin, decision);
  3932. options.transition.each(transition => {
  3933. applyTransitionCss(element, options.origin, positionCss, transition, decision, options.lastPlacement);
  3934. });
  3935. applyPositionCss(element, positionCss);
  3936. };
  3937. const setPlacement = (element, decision) => {
  3938. setPlacement$1(element, decision.placement);
  3939. };
  3940. const setMaxHeight = (element, maxHeight) => {
  3941. setMax$1(element, Math.floor(maxHeight));
  3942. };
  3943. const anchored = constant$1((element, available) => {
  3944. setMaxHeight(element, available);
  3945. setAll(element, {
  3946. 'overflow-x': 'hidden',
  3947. 'overflow-y': 'auto'
  3948. });
  3949. });
  3950. const expandable$1 = constant$1((element, available) => {
  3951. setMaxHeight(element, available);
  3952. });
  3953. const defaultOr = (options, key, dephault) => options[key] === undefined ? dephault : options[key];
  3954. const simple = (anchor, element, bubble, layouts, lastPlacement, getBounds, overrideOptions, transition) => {
  3955. const maxHeightFunction = defaultOr(overrideOptions, 'maxHeightFunction', anchored());
  3956. const maxWidthFunction = defaultOr(overrideOptions, 'maxWidthFunction', noop);
  3957. const anchorBox = anchor.anchorBox;
  3958. const origin = anchor.origin;
  3959. const options = {
  3960. bounds: viewport(origin, getBounds),
  3961. origin,
  3962. preference: layouts,
  3963. maxHeightFunction,
  3964. maxWidthFunction,
  3965. lastPlacement,
  3966. transition
  3967. };
  3968. return go(anchorBox, element, bubble, options);
  3969. };
  3970. const go = (anchorBox, element, bubble, options) => {
  3971. const decision = layout(anchorBox, element, bubble, options);
  3972. position$2(element, decision, options);
  3973. setPlacement(element, decision);
  3974. setClasses(element, decision);
  3975. setHeight(element, decision, options);
  3976. setWidth(element, decision, options);
  3977. return {
  3978. layout: decision.layout,
  3979. placement: decision.placement
  3980. };
  3981. };
  3982. const allAlignments = [
  3983. 'valignCentre',
  3984. 'alignLeft',
  3985. 'alignRight',
  3986. 'alignCentre',
  3987. 'top',
  3988. 'bottom',
  3989. 'left',
  3990. 'right',
  3991. 'inset'
  3992. ];
  3993. const nu$5 = (xOffset, yOffset, classes, insetModifier = 1) => {
  3994. const insetXOffset = xOffset * insetModifier;
  3995. const insetYOffset = yOffset * insetModifier;
  3996. const getClasses = prop => get$g(classes, prop).getOr([]);
  3997. const make = (xDelta, yDelta, alignmentsOn) => {
  3998. const alignmentsOff = difference(allAlignments, alignmentsOn);
  3999. return {
  4000. offset: SugarPosition(xDelta, yDelta),
  4001. classesOn: bind$3(alignmentsOn, getClasses),
  4002. classesOff: bind$3(alignmentsOff, getClasses)
  4003. };
  4004. };
  4005. return {
  4006. southeast: () => make(-xOffset, yOffset, [
  4007. 'top',
  4008. 'alignLeft'
  4009. ]),
  4010. southwest: () => make(xOffset, yOffset, [
  4011. 'top',
  4012. 'alignRight'
  4013. ]),
  4014. south: () => make(-xOffset / 2, yOffset, [
  4015. 'top',
  4016. 'alignCentre'
  4017. ]),
  4018. northeast: () => make(-xOffset, -yOffset, [
  4019. 'bottom',
  4020. 'alignLeft'
  4021. ]),
  4022. northwest: () => make(xOffset, -yOffset, [
  4023. 'bottom',
  4024. 'alignRight'
  4025. ]),
  4026. north: () => make(-xOffset / 2, -yOffset, [
  4027. 'bottom',
  4028. 'alignCentre'
  4029. ]),
  4030. east: () => make(xOffset, -yOffset / 2, [
  4031. 'valignCentre',
  4032. 'left'
  4033. ]),
  4034. west: () => make(-xOffset, -yOffset / 2, [
  4035. 'valignCentre',
  4036. 'right'
  4037. ]),
  4038. insetNortheast: () => make(insetXOffset, insetYOffset, [
  4039. 'top',
  4040. 'alignLeft',
  4041. 'inset'
  4042. ]),
  4043. insetNorthwest: () => make(-insetXOffset, insetYOffset, [
  4044. 'top',
  4045. 'alignRight',
  4046. 'inset'
  4047. ]),
  4048. insetNorth: () => make(-insetXOffset / 2, insetYOffset, [
  4049. 'top',
  4050. 'alignCentre',
  4051. 'inset'
  4052. ]),
  4053. insetSoutheast: () => make(insetXOffset, -insetYOffset, [
  4054. 'bottom',
  4055. 'alignLeft',
  4056. 'inset'
  4057. ]),
  4058. insetSouthwest: () => make(-insetXOffset, -insetYOffset, [
  4059. 'bottom',
  4060. 'alignRight',
  4061. 'inset'
  4062. ]),
  4063. insetSouth: () => make(-insetXOffset / 2, -insetYOffset, [
  4064. 'bottom',
  4065. 'alignCentre',
  4066. 'inset'
  4067. ]),
  4068. insetEast: () => make(-insetXOffset, -insetYOffset / 2, [
  4069. 'valignCentre',
  4070. 'right',
  4071. 'inset'
  4072. ]),
  4073. insetWest: () => make(insetXOffset, -insetYOffset / 2, [
  4074. 'valignCentre',
  4075. 'left',
  4076. 'inset'
  4077. ])
  4078. };
  4079. };
  4080. const fallback = () => nu$5(0, 0, {});
  4081. const nu$4 = identity;
  4082. const onDirection = (isLtr, isRtl) => element => getDirection(element) === 'rtl' ? isRtl : isLtr;
  4083. const getDirection = element => get$e(element, 'direction') === 'rtl' ? 'rtl' : 'ltr';
  4084. var AttributeValue;
  4085. (function (AttributeValue) {
  4086. AttributeValue['TopToBottom'] = 'toptobottom';
  4087. AttributeValue['BottomToTop'] = 'bottomtotop';
  4088. }(AttributeValue || (AttributeValue = {})));
  4089. const Attribute = 'data-alloy-vertical-dir';
  4090. const isBottomToTopDir = el => closest$2(el, current => isElement$1(current) && get$f(current, 'data-alloy-vertical-dir') === AttributeValue.BottomToTop);
  4091. const schema$y = () => optionObjOf('layouts', [
  4092. required$1('onLtr'),
  4093. required$1('onRtl'),
  4094. option$3('onBottomLtr'),
  4095. option$3('onBottomRtl')
  4096. ]);
  4097. const get$5 = (elem, info, defaultLtr, defaultRtl, defaultBottomLtr, defaultBottomRtl, dirElement) => {
  4098. const isBottomToTop = dirElement.map(isBottomToTopDir).getOr(false);
  4099. const customLtr = info.layouts.map(ls => ls.onLtr(elem));
  4100. const customRtl = info.layouts.map(ls => ls.onRtl(elem));
  4101. const ltr = isBottomToTop ? info.layouts.bind(ls => ls.onBottomLtr.map(f => f(elem))).or(customLtr).getOr(defaultBottomLtr) : customLtr.getOr(defaultLtr);
  4102. const rtl = isBottomToTop ? info.layouts.bind(ls => ls.onBottomRtl.map(f => f(elem))).or(customRtl).getOr(defaultBottomRtl) : customRtl.getOr(defaultRtl);
  4103. const f = onDirection(ltr, rtl);
  4104. return f(elem);
  4105. };
  4106. const placement$4 = (component, anchorInfo, origin) => {
  4107. const hotspot = anchorInfo.hotspot;
  4108. const anchorBox = toBox(origin, hotspot.element);
  4109. const layouts = get$5(component.element, anchorInfo, belowOrAbove(), belowOrAboveRtl(), aboveOrBelow(), aboveOrBelowRtl(), Optional.some(anchorInfo.hotspot.element));
  4110. return Optional.some(nu$4({
  4111. anchorBox,
  4112. bubble: anchorInfo.bubble.getOr(fallback()),
  4113. overrides: anchorInfo.overrides,
  4114. layouts,
  4115. placer: Optional.none()
  4116. }));
  4117. };
  4118. var HotspotAnchor = [
  4119. required$1('hotspot'),
  4120. option$3('bubble'),
  4121. defaulted('overrides', {}),
  4122. schema$y(),
  4123. output$1('placement', placement$4)
  4124. ];
  4125. const placement$3 = (component, anchorInfo, origin) => {
  4126. const pos = translate$2(origin, anchorInfo.x, anchorInfo.y);
  4127. const anchorBox = bounds(pos.left, pos.top, anchorInfo.width, anchorInfo.height);
  4128. const layouts = get$5(component.element, anchorInfo, all$1(), allRtl$1(), all$1(), allRtl$1(), Optional.none());
  4129. return Optional.some(nu$4({
  4130. anchorBox,
  4131. bubble: anchorInfo.bubble,
  4132. overrides: anchorInfo.overrides,
  4133. layouts,
  4134. placer: Optional.none()
  4135. }));
  4136. };
  4137. var MakeshiftAnchor = [
  4138. required$1('x'),
  4139. required$1('y'),
  4140. defaulted('height', 0),
  4141. defaulted('width', 0),
  4142. defaulted('bubble', fallback()),
  4143. defaulted('overrides', {}),
  4144. schema$y(),
  4145. output$1('placement', placement$3)
  4146. ];
  4147. const adt$7 = Adt.generate([
  4148. { screen: ['point'] },
  4149. {
  4150. absolute: [
  4151. 'point',
  4152. 'scrollLeft',
  4153. 'scrollTop'
  4154. ]
  4155. }
  4156. ]);
  4157. const toFixed = pos => pos.fold(identity, (point, scrollLeft, scrollTop) => point.translate(-scrollLeft, -scrollTop));
  4158. const toAbsolute = pos => pos.fold(identity, identity);
  4159. const sum = points => foldl(points, (b, a) => b.translate(a.left, a.top), SugarPosition(0, 0));
  4160. const sumAsFixed = positions => {
  4161. const points = map$2(positions, toFixed);
  4162. return sum(points);
  4163. };
  4164. const sumAsAbsolute = positions => {
  4165. const points = map$2(positions, toAbsolute);
  4166. return sum(points);
  4167. };
  4168. const screen = adt$7.screen;
  4169. const absolute$1 = adt$7.absolute;
  4170. const getOffset = (component, origin, anchorInfo) => {
  4171. const win = defaultView(anchorInfo.root).dom;
  4172. const hasSameOwner = frame => {
  4173. const frameOwner = owner$4(frame);
  4174. const compOwner = owner$4(component.element);
  4175. return eq(frameOwner, compOwner);
  4176. };
  4177. return Optional.from(win.frameElement).map(SugarElement.fromDom).filter(hasSameOwner).map(absolute$3);
  4178. };
  4179. const getRootPoint = (component, origin, anchorInfo) => {
  4180. const doc = owner$4(component.element);
  4181. const outerScroll = get$b(doc);
  4182. const offset = getOffset(component, origin, anchorInfo).getOr(outerScroll);
  4183. return absolute$1(offset, outerScroll.left, outerScroll.top);
  4184. };
  4185. const getBox = (left, top, width, height) => {
  4186. const point = screen(SugarPosition(left, top));
  4187. return Optional.some(pointed(point, width, height));
  4188. };
  4189. const calcNewAnchor = (optBox, rootPoint, anchorInfo, origin, elem) => optBox.map(box => {
  4190. const points = [
  4191. rootPoint,
  4192. box.point
  4193. ];
  4194. const topLeft = cata$1(origin, () => sumAsAbsolute(points), () => sumAsAbsolute(points), () => sumAsFixed(points));
  4195. const anchorBox = rect(topLeft.left, topLeft.top, box.width, box.height);
  4196. const layoutsLtr = anchorInfo.showAbove ? aboveOrBelow() : belowOrAbove();
  4197. const layoutsRtl = anchorInfo.showAbove ? aboveOrBelowRtl() : belowOrAboveRtl();
  4198. const layouts = get$5(elem, anchorInfo, layoutsLtr, layoutsRtl, layoutsLtr, layoutsRtl, Optional.none());
  4199. return nu$4({
  4200. anchorBox,
  4201. bubble: anchorInfo.bubble.getOr(fallback()),
  4202. overrides: anchorInfo.overrides,
  4203. layouts,
  4204. placer: Optional.none()
  4205. });
  4206. });
  4207. const placement$2 = (component, anchorInfo, origin) => {
  4208. const rootPoint = getRootPoint(component, origin, anchorInfo);
  4209. return anchorInfo.node.filter(inBody).bind(target => {
  4210. const rect = target.dom.getBoundingClientRect();
  4211. const nodeBox = getBox(rect.left, rect.top, rect.width, rect.height);
  4212. const elem = anchorInfo.node.getOr(component.element);
  4213. return calcNewAnchor(nodeBox, rootPoint, anchorInfo, origin, elem);
  4214. });
  4215. };
  4216. var NodeAnchor = [
  4217. required$1('node'),
  4218. required$1('root'),
  4219. option$3('bubble'),
  4220. schema$y(),
  4221. defaulted('overrides', {}),
  4222. defaulted('showAbove', false),
  4223. output$1('placement', placement$2)
  4224. ];
  4225. const zeroWidth = '\uFEFF';
  4226. const nbsp = '\xA0';
  4227. const create$3 = (start, soffset, finish, foffset) => ({
  4228. start,
  4229. soffset,
  4230. finish,
  4231. foffset
  4232. });
  4233. const SimRange = { create: create$3 };
  4234. const adt$6 = Adt.generate([
  4235. { before: ['element'] },
  4236. {
  4237. on: [
  4238. 'element',
  4239. 'offset'
  4240. ]
  4241. },
  4242. { after: ['element'] }
  4243. ]);
  4244. const cata = (subject, onBefore, onOn, onAfter) => subject.fold(onBefore, onOn, onAfter);
  4245. const getStart$1 = situ => situ.fold(identity, identity, identity);
  4246. const before = adt$6.before;
  4247. const on$1 = adt$6.on;
  4248. const after$1 = adt$6.after;
  4249. const Situ = {
  4250. before,
  4251. on: on$1,
  4252. after: after$1,
  4253. cata,
  4254. getStart: getStart$1
  4255. };
  4256. const adt$5 = Adt.generate([
  4257. { domRange: ['rng'] },
  4258. {
  4259. relative: [
  4260. 'startSitu',
  4261. 'finishSitu'
  4262. ]
  4263. },
  4264. {
  4265. exact: [
  4266. 'start',
  4267. 'soffset',
  4268. 'finish',
  4269. 'foffset'
  4270. ]
  4271. }
  4272. ]);
  4273. const exactFromRange = simRange => adt$5.exact(simRange.start, simRange.soffset, simRange.finish, simRange.foffset);
  4274. const getStart = selection => selection.match({
  4275. domRange: rng => SugarElement.fromDom(rng.startContainer),
  4276. relative: (startSitu, _finishSitu) => Situ.getStart(startSitu),
  4277. exact: (start, _soffset, _finish, _foffset) => start
  4278. });
  4279. const domRange = adt$5.domRange;
  4280. const relative = adt$5.relative;
  4281. const exact = adt$5.exact;
  4282. const getWin = selection => {
  4283. const start = getStart(selection);
  4284. return defaultView(start);
  4285. };
  4286. const range$1 = SimRange.create;
  4287. const SimSelection = {
  4288. domRange,
  4289. relative,
  4290. exact,
  4291. exactFromRange,
  4292. getWin,
  4293. range: range$1
  4294. };
  4295. const setStart = (rng, situ) => {
  4296. situ.fold(e => {
  4297. rng.setStartBefore(e.dom);
  4298. }, (e, o) => {
  4299. rng.setStart(e.dom, o);
  4300. }, e => {
  4301. rng.setStartAfter(e.dom);
  4302. });
  4303. };
  4304. const setFinish = (rng, situ) => {
  4305. situ.fold(e => {
  4306. rng.setEndBefore(e.dom);
  4307. }, (e, o) => {
  4308. rng.setEnd(e.dom, o);
  4309. }, e => {
  4310. rng.setEndAfter(e.dom);
  4311. });
  4312. };
  4313. const relativeToNative = (win, startSitu, finishSitu) => {
  4314. const range = win.document.createRange();
  4315. setStart(range, startSitu);
  4316. setFinish(range, finishSitu);
  4317. return range;
  4318. };
  4319. const exactToNative = (win, start, soffset, finish, foffset) => {
  4320. const rng = win.document.createRange();
  4321. rng.setStart(start.dom, soffset);
  4322. rng.setEnd(finish.dom, foffset);
  4323. return rng;
  4324. };
  4325. const toRect = rect => ({
  4326. left: rect.left,
  4327. top: rect.top,
  4328. right: rect.right,
  4329. bottom: rect.bottom,
  4330. width: rect.width,
  4331. height: rect.height
  4332. });
  4333. const getFirstRect$1 = rng => {
  4334. const rects = rng.getClientRects();
  4335. const rect = rects.length > 0 ? rects[0] : rng.getBoundingClientRect();
  4336. return rect.width > 0 || rect.height > 0 ? Optional.some(rect).map(toRect) : Optional.none();
  4337. };
  4338. const getBounds$2 = rng => {
  4339. const rect = rng.getBoundingClientRect();
  4340. return rect.width > 0 || rect.height > 0 ? Optional.some(rect).map(toRect) : Optional.none();
  4341. };
  4342. const adt$4 = Adt.generate([
  4343. {
  4344. ltr: [
  4345. 'start',
  4346. 'soffset',
  4347. 'finish',
  4348. 'foffset'
  4349. ]
  4350. },
  4351. {
  4352. rtl: [
  4353. 'start',
  4354. 'soffset',
  4355. 'finish',
  4356. 'foffset'
  4357. ]
  4358. }
  4359. ]);
  4360. const fromRange = (win, type, range) => type(SugarElement.fromDom(range.startContainer), range.startOffset, SugarElement.fromDom(range.endContainer), range.endOffset);
  4361. const getRanges = (win, selection) => selection.match({
  4362. domRange: rng => {
  4363. return {
  4364. ltr: constant$1(rng),
  4365. rtl: Optional.none
  4366. };
  4367. },
  4368. relative: (startSitu, finishSitu) => {
  4369. return {
  4370. ltr: cached(() => relativeToNative(win, startSitu, finishSitu)),
  4371. rtl: cached(() => Optional.some(relativeToNative(win, finishSitu, startSitu)))
  4372. };
  4373. },
  4374. exact: (start, soffset, finish, foffset) => {
  4375. return {
  4376. ltr: cached(() => exactToNative(win, start, soffset, finish, foffset)),
  4377. rtl: cached(() => Optional.some(exactToNative(win, finish, foffset, start, soffset)))
  4378. };
  4379. }
  4380. });
  4381. const doDiagnose = (win, ranges) => {
  4382. const rng = ranges.ltr();
  4383. if (rng.collapsed) {
  4384. const reversed = ranges.rtl().filter(rev => rev.collapsed === false);
  4385. return reversed.map(rev => adt$4.rtl(SugarElement.fromDom(rev.endContainer), rev.endOffset, SugarElement.fromDom(rev.startContainer), rev.startOffset)).getOrThunk(() => fromRange(win, adt$4.ltr, rng));
  4386. } else {
  4387. return fromRange(win, adt$4.ltr, rng);
  4388. }
  4389. };
  4390. const diagnose = (win, selection) => {
  4391. const ranges = getRanges(win, selection);
  4392. return doDiagnose(win, ranges);
  4393. };
  4394. const asLtrRange = (win, selection) => {
  4395. const diagnosis = diagnose(win, selection);
  4396. return diagnosis.match({
  4397. ltr: (start, soffset, finish, foffset) => {
  4398. const rng = win.document.createRange();
  4399. rng.setStart(start.dom, soffset);
  4400. rng.setEnd(finish.dom, foffset);
  4401. return rng;
  4402. },
  4403. rtl: (start, soffset, finish, foffset) => {
  4404. const rng = win.document.createRange();
  4405. rng.setStart(finish.dom, foffset);
  4406. rng.setEnd(start.dom, soffset);
  4407. return rng;
  4408. }
  4409. });
  4410. };
  4411. adt$4.ltr;
  4412. adt$4.rtl;
  4413. const descendants = (scope, selector) => all$3(selector, scope);
  4414. const makeRange = (start, soffset, finish, foffset) => {
  4415. const doc = owner$4(start);
  4416. const rng = doc.dom.createRange();
  4417. rng.setStart(start.dom, soffset);
  4418. rng.setEnd(finish.dom, foffset);
  4419. return rng;
  4420. };
  4421. const after = (start, soffset, finish, foffset) => {
  4422. const r = makeRange(start, soffset, finish, foffset);
  4423. const same = eq(start, finish) && soffset === foffset;
  4424. return r.collapsed && !same;
  4425. };
  4426. const getNativeSelection = win => Optional.from(win.getSelection());
  4427. const readRange = selection => {
  4428. if (selection.rangeCount > 0) {
  4429. const firstRng = selection.getRangeAt(0);
  4430. const lastRng = selection.getRangeAt(selection.rangeCount - 1);
  4431. return Optional.some(SimRange.create(SugarElement.fromDom(firstRng.startContainer), firstRng.startOffset, SugarElement.fromDom(lastRng.endContainer), lastRng.endOffset));
  4432. } else {
  4433. return Optional.none();
  4434. }
  4435. };
  4436. const doGetExact = selection => {
  4437. if (selection.anchorNode === null || selection.focusNode === null) {
  4438. return readRange(selection);
  4439. } else {
  4440. const anchor = SugarElement.fromDom(selection.anchorNode);
  4441. const focus = SugarElement.fromDom(selection.focusNode);
  4442. return after(anchor, selection.anchorOffset, focus, selection.focusOffset) ? Optional.some(SimRange.create(anchor, selection.anchorOffset, focus, selection.focusOffset)) : readRange(selection);
  4443. }
  4444. };
  4445. const getExact = win => getNativeSelection(win).filter(sel => sel.rangeCount > 0).bind(doGetExact);
  4446. const getFirstRect = (win, selection) => {
  4447. const rng = asLtrRange(win, selection);
  4448. return getFirstRect$1(rng);
  4449. };
  4450. const getBounds$1 = (win, selection) => {
  4451. const rng = asLtrRange(win, selection);
  4452. return getBounds$2(rng);
  4453. };
  4454. const NodeValue = (is, name) => {
  4455. const get = element => {
  4456. if (!is(element)) {
  4457. throw new Error('Can only get ' + name + ' value of a ' + name + ' node');
  4458. }
  4459. return getOption(element).getOr('');
  4460. };
  4461. const getOption = element => is(element) ? Optional.from(element.dom.nodeValue) : Optional.none();
  4462. const set = (element, value) => {
  4463. if (!is(element)) {
  4464. throw new Error('Can only set raw ' + name + ' value of a ' + name + ' node');
  4465. }
  4466. element.dom.nodeValue = value;
  4467. };
  4468. return {
  4469. get,
  4470. getOption,
  4471. set
  4472. };
  4473. };
  4474. const api = NodeValue(isText, 'text');
  4475. const get$4 = element => api.get(element);
  4476. const point = (element, offset) => ({
  4477. element,
  4478. offset
  4479. });
  4480. const descendOnce$1 = (element, offset) => {
  4481. const children$1 = children(element);
  4482. if (children$1.length === 0) {
  4483. return point(element, offset);
  4484. } else if (offset < children$1.length) {
  4485. return point(children$1[offset], 0);
  4486. } else {
  4487. const last = children$1[children$1.length - 1];
  4488. const len = isText(last) ? get$4(last).length : children(last).length;
  4489. return point(last, len);
  4490. }
  4491. };
  4492. const descendOnce = (element, offset) => isText(element) ? point(element, offset) : descendOnce$1(element, offset);
  4493. const getAnchorSelection = (win, anchorInfo) => {
  4494. const getSelection = anchorInfo.getSelection.getOrThunk(() => () => getExact(win));
  4495. return getSelection().map(sel => {
  4496. const modStart = descendOnce(sel.start, sel.soffset);
  4497. const modFinish = descendOnce(sel.finish, sel.foffset);
  4498. return SimSelection.range(modStart.element, modStart.offset, modFinish.element, modFinish.offset);
  4499. });
  4500. };
  4501. const placement$1 = (component, anchorInfo, origin) => {
  4502. const win = defaultView(anchorInfo.root).dom;
  4503. const rootPoint = getRootPoint(component, origin, anchorInfo);
  4504. const selectionBox = getAnchorSelection(win, anchorInfo).bind(sel => {
  4505. const optRect = getBounds$1(win, SimSelection.exactFromRange(sel)).orThunk(() => {
  4506. const x = SugarElement.fromText(zeroWidth);
  4507. before$1(sel.start, x);
  4508. const rect = getFirstRect(win, SimSelection.exact(x, 0, x, 1));
  4509. remove$5(x);
  4510. return rect;
  4511. });
  4512. return optRect.bind(rawRect => getBox(rawRect.left, rawRect.top, rawRect.width, rawRect.height));
  4513. });
  4514. const targetElement = getAnchorSelection(win, anchorInfo).bind(sel => isElement$1(sel.start) ? Optional.some(sel.start) : parentElement(sel.start));
  4515. const elem = targetElement.getOr(component.element);
  4516. return calcNewAnchor(selectionBox, rootPoint, anchorInfo, origin, elem);
  4517. };
  4518. var SelectionAnchor = [
  4519. option$3('getSelection'),
  4520. required$1('root'),
  4521. option$3('bubble'),
  4522. schema$y(),
  4523. defaulted('overrides', {}),
  4524. defaulted('showAbove', false),
  4525. output$1('placement', placement$1)
  4526. ];
  4527. const labelPrefix$1 = 'link-layout';
  4528. const eastX = anchor => anchor.x + anchor.width;
  4529. const westX = (anchor, element) => anchor.x - element.width;
  4530. const northY$1 = (anchor, element) => anchor.y - element.height + anchor.height;
  4531. const southY$1 = anchor => anchor.y;
  4532. const southeast$1 = (anchor, element, bubbles) => nu$6(eastX(anchor), southY$1(anchor), bubbles.southeast(), southeast$3(), 'southeast', boundsRestriction(anchor, {
  4533. left: 0,
  4534. top: 2
  4535. }), labelPrefix$1);
  4536. const southwest$1 = (anchor, element, bubbles) => nu$6(westX(anchor, element), southY$1(anchor), bubbles.southwest(), southwest$3(), 'southwest', boundsRestriction(anchor, {
  4537. right: 1,
  4538. top: 2
  4539. }), labelPrefix$1);
  4540. const northeast$1 = (anchor, element, bubbles) => nu$6(eastX(anchor), northY$1(anchor, element), bubbles.northeast(), northeast$3(), 'northeast', boundsRestriction(anchor, {
  4541. left: 0,
  4542. bottom: 3
  4543. }), labelPrefix$1);
  4544. const northwest$1 = (anchor, element, bubbles) => nu$6(westX(anchor, element), northY$1(anchor, element), bubbles.northwest(), northwest$3(), 'northwest', boundsRestriction(anchor, {
  4545. right: 1,
  4546. bottom: 3
  4547. }), labelPrefix$1);
  4548. const all = () => [
  4549. southeast$1,
  4550. southwest$1,
  4551. northeast$1,
  4552. northwest$1
  4553. ];
  4554. const allRtl = () => [
  4555. southwest$1,
  4556. southeast$1,
  4557. northwest$1,
  4558. northeast$1
  4559. ];
  4560. const placement = (component, submenuInfo, origin) => {
  4561. const anchorBox = toBox(origin, submenuInfo.item.element);
  4562. const layouts = get$5(component.element, submenuInfo, all(), allRtl(), all(), allRtl(), Optional.none());
  4563. return Optional.some(nu$4({
  4564. anchorBox,
  4565. bubble: fallback(),
  4566. overrides: submenuInfo.overrides,
  4567. layouts,
  4568. placer: Optional.none()
  4569. }));
  4570. };
  4571. var SubmenuAnchor = [
  4572. required$1('item'),
  4573. schema$y(),
  4574. defaulted('overrides', {}),
  4575. output$1('placement', placement)
  4576. ];
  4577. var AnchorSchema = choose$1('type', {
  4578. selection: SelectionAnchor,
  4579. node: NodeAnchor,
  4580. hotspot: HotspotAnchor,
  4581. submenu: SubmenuAnchor,
  4582. makeshift: MakeshiftAnchor
  4583. });
  4584. const TransitionSchema = [
  4585. requiredArrayOf('classes', string),
  4586. defaultedStringEnum('mode', 'all', [
  4587. 'all',
  4588. 'layout',
  4589. 'placement'
  4590. ])
  4591. ];
  4592. const PositionSchema = [
  4593. defaulted('useFixed', never),
  4594. option$3('getBounds')
  4595. ];
  4596. const PlacementSchema = [
  4597. requiredOf('anchor', AnchorSchema),
  4598. optionObjOf('transition', TransitionSchema)
  4599. ];
  4600. const getFixedOrigin = () => {
  4601. const html = document.documentElement;
  4602. return fixed$1(0, 0, html.clientWidth, html.clientHeight);
  4603. };
  4604. const getRelativeOrigin = component => {
  4605. const position = absolute$3(component.element);
  4606. const bounds = component.element.dom.getBoundingClientRect();
  4607. return relative$1(position.left, position.top, bounds.width, bounds.height);
  4608. };
  4609. const place = (component, origin, anchoring, getBounds, placee, lastPlace, transition) => {
  4610. const anchor = box(anchoring.anchorBox, origin);
  4611. return simple(anchor, placee.element, anchoring.bubble, anchoring.layouts, lastPlace, getBounds, anchoring.overrides, transition);
  4612. };
  4613. const position$1 = (component, posConfig, posState, placee, placementSpec) => {
  4614. positionWithin(component, posConfig, posState, placee, placementSpec, Optional.none());
  4615. };
  4616. const positionWithin = (component, posConfig, posState, placee, placementSpec, boxElement) => {
  4617. const boundsBox = boxElement.map(box$1);
  4618. return positionWithinBounds(component, posConfig, posState, placee, placementSpec, boundsBox);
  4619. };
  4620. const positionWithinBounds = (component, posConfig, posState, placee, placementSpec, bounds) => {
  4621. const placeeDetail = asRawOrDie$1('placement.info', objOf(PlacementSchema), placementSpec);
  4622. const anchorage = placeeDetail.anchor;
  4623. const element = placee.element;
  4624. const placeeState = posState.get(placee.uid);
  4625. preserve$1(() => {
  4626. set$8(element, 'position', 'fixed');
  4627. const oldVisibility = getRaw(element, 'visibility');
  4628. set$8(element, 'visibility', 'hidden');
  4629. const origin = posConfig.useFixed() ? getFixedOrigin() : getRelativeOrigin(component);
  4630. const placer = anchorage.placement;
  4631. const getBounds = bounds.map(constant$1).or(posConfig.getBounds);
  4632. placer(component, anchorage, origin).each(anchoring => {
  4633. const doPlace = anchoring.placer.getOr(place);
  4634. const newState = doPlace(component, origin, anchoring, getBounds, placee, placeeState, placeeDetail.transition);
  4635. posState.set(placee.uid, newState);
  4636. });
  4637. oldVisibility.fold(() => {
  4638. remove$6(element, 'visibility');
  4639. }, vis => {
  4640. set$8(element, 'visibility', vis);
  4641. });
  4642. if (getRaw(element, 'left').isNone() && getRaw(element, 'top').isNone() && getRaw(element, 'right').isNone() && getRaw(element, 'bottom').isNone() && is$1(getRaw(element, 'position'), 'fixed')) {
  4643. remove$6(element, 'position');
  4644. }
  4645. }, element);
  4646. };
  4647. const getMode = (component, pConfig, _pState) => pConfig.useFixed() ? 'fixed' : 'absolute';
  4648. const reset$1 = (component, pConfig, posState, placee) => {
  4649. const element = placee.element;
  4650. each$1([
  4651. 'position',
  4652. 'left',
  4653. 'right',
  4654. 'top',
  4655. 'bottom'
  4656. ], prop => remove$6(element, prop));
  4657. reset$2(element);
  4658. posState.clear(placee.uid);
  4659. };
  4660. var PositionApis = /*#__PURE__*/Object.freeze({
  4661. __proto__: null,
  4662. position: position$1,
  4663. positionWithin: positionWithin,
  4664. positionWithinBounds: positionWithinBounds,
  4665. getMode: getMode,
  4666. reset: reset$1
  4667. });
  4668. const init$g = () => {
  4669. let state = {};
  4670. const set = (id, data) => {
  4671. state[id] = data;
  4672. };
  4673. const get = id => get$g(state, id);
  4674. const clear = id => {
  4675. if (isNonNullable(id)) {
  4676. delete state[id];
  4677. } else {
  4678. state = {};
  4679. }
  4680. };
  4681. return nu$8({
  4682. readState: () => state,
  4683. clear,
  4684. set,
  4685. get
  4686. });
  4687. };
  4688. var PositioningState = /*#__PURE__*/Object.freeze({
  4689. __proto__: null,
  4690. init: init$g
  4691. });
  4692. const Positioning = create$4({
  4693. fields: PositionSchema,
  4694. name: 'positioning',
  4695. active: ActivePosition,
  4696. apis: PositionApis,
  4697. state: PositioningState
  4698. });
  4699. const isConnected = comp => comp.getSystem().isConnected();
  4700. const fireDetaching = component => {
  4701. emit(component, detachedFromDom());
  4702. const children = component.components();
  4703. each$1(children, fireDetaching);
  4704. };
  4705. const fireAttaching = component => {
  4706. const children = component.components();
  4707. each$1(children, fireAttaching);
  4708. emit(component, attachedToDom());
  4709. };
  4710. const virtualAttach = (parent, child) => {
  4711. parent.getSystem().addToWorld(child);
  4712. if (inBody(parent.element)) {
  4713. fireAttaching(child);
  4714. }
  4715. };
  4716. const virtualDetach = comp => {
  4717. fireDetaching(comp);
  4718. comp.getSystem().removeFromWorld(comp);
  4719. };
  4720. const attach$1 = (parent, child) => {
  4721. append$2(parent.element, child.element);
  4722. };
  4723. const detachChildren$1 = component => {
  4724. each$1(component.components(), childComp => remove$5(childComp.element));
  4725. empty(component.element);
  4726. component.syncComponents();
  4727. };
  4728. const replaceChildren = (component, newSpecs, buildNewChildren) => {
  4729. const subs = component.components();
  4730. detachChildren$1(component);
  4731. const newChildren = buildNewChildren(newSpecs);
  4732. const deleted = difference(subs, newChildren);
  4733. each$1(deleted, comp => {
  4734. fireDetaching(comp);
  4735. component.getSystem().removeFromWorld(comp);
  4736. });
  4737. each$1(newChildren, childComp => {
  4738. if (!isConnected(childComp)) {
  4739. component.getSystem().addToWorld(childComp);
  4740. attach$1(component, childComp);
  4741. if (inBody(component.element)) {
  4742. fireAttaching(childComp);
  4743. }
  4744. } else {
  4745. attach$1(component, childComp);
  4746. }
  4747. });
  4748. component.syncComponents();
  4749. };
  4750. const virtualReplaceChildren = (component, newSpecs, buildNewChildren) => {
  4751. const subs = component.components();
  4752. const existingComps = bind$3(newSpecs, spec => getPremade(spec).toArray());
  4753. each$1(subs, childComp => {
  4754. if (!contains$2(existingComps, childComp)) {
  4755. virtualDetach(childComp);
  4756. }
  4757. });
  4758. const newChildren = buildNewChildren(newSpecs);
  4759. const deleted = difference(subs, newChildren);
  4760. each$1(deleted, deletedComp => {
  4761. if (isConnected(deletedComp)) {
  4762. virtualDetach(deletedComp);
  4763. }
  4764. });
  4765. each$1(newChildren, childComp => {
  4766. if (!isConnected(childComp)) {
  4767. virtualAttach(component, childComp);
  4768. }
  4769. });
  4770. component.syncComponents();
  4771. };
  4772. const attach = (parent, child) => {
  4773. attachWith(parent, child, append$2);
  4774. };
  4775. const attachWith = (parent, child, insertion) => {
  4776. parent.getSystem().addToWorld(child);
  4777. insertion(parent.element, child.element);
  4778. if (inBody(parent.element)) {
  4779. fireAttaching(child);
  4780. }
  4781. parent.syncComponents();
  4782. };
  4783. const doDetach = component => {
  4784. fireDetaching(component);
  4785. remove$5(component.element);
  4786. component.getSystem().removeFromWorld(component);
  4787. };
  4788. const detach = component => {
  4789. const parent$1 = parent(component.element).bind(p => component.getSystem().getByDom(p).toOptional());
  4790. doDetach(component);
  4791. parent$1.each(p => {
  4792. p.syncComponents();
  4793. });
  4794. };
  4795. const detachChildren = component => {
  4796. const subs = component.components();
  4797. each$1(subs, doDetach);
  4798. empty(component.element);
  4799. component.syncComponents();
  4800. };
  4801. const attachSystem = (element, guiSystem) => {
  4802. attachSystemWith(element, guiSystem, append$2);
  4803. };
  4804. const attachSystemAfter = (element, guiSystem) => {
  4805. attachSystemWith(element, guiSystem, after$2);
  4806. };
  4807. const attachSystemWith = (element, guiSystem, inserter) => {
  4808. inserter(element, guiSystem.element);
  4809. const children$1 = children(guiSystem.element);
  4810. each$1(children$1, child => {
  4811. guiSystem.getByDom(child).each(fireAttaching);
  4812. });
  4813. };
  4814. const detachSystem = guiSystem => {
  4815. const children$1 = children(guiSystem.element);
  4816. each$1(children$1, child => {
  4817. guiSystem.getByDom(child).each(fireDetaching);
  4818. });
  4819. remove$5(guiSystem.element);
  4820. };
  4821. const rebuild = (sandbox, sConfig, sState, data) => {
  4822. sState.get().each(_data => {
  4823. detachChildren(sandbox);
  4824. });
  4825. const point = sConfig.getAttachPoint(sandbox);
  4826. attach(point, sandbox);
  4827. const built = sandbox.getSystem().build(data);
  4828. attach(sandbox, built);
  4829. sState.set(built);
  4830. return built;
  4831. };
  4832. const open$1 = (sandbox, sConfig, sState, data) => {
  4833. const newState = rebuild(sandbox, sConfig, sState, data);
  4834. sConfig.onOpen(sandbox, newState);
  4835. return newState;
  4836. };
  4837. const setContent = (sandbox, sConfig, sState, data) => sState.get().map(() => rebuild(sandbox, sConfig, sState, data));
  4838. const openWhileCloaked = (sandbox, sConfig, sState, data, transaction) => {
  4839. cloak(sandbox, sConfig);
  4840. open$1(sandbox, sConfig, sState, data);
  4841. transaction();
  4842. decloak(sandbox, sConfig);
  4843. };
  4844. const close$1 = (sandbox, sConfig, sState) => {
  4845. sState.get().each(data => {
  4846. detachChildren(sandbox);
  4847. detach(sandbox);
  4848. sConfig.onClose(sandbox, data);
  4849. sState.clear();
  4850. });
  4851. };
  4852. const isOpen$1 = (_sandbox, _sConfig, sState) => sState.isOpen();
  4853. const isPartOf = (sandbox, sConfig, sState, queryElem) => isOpen$1(sandbox, sConfig, sState) && sState.get().exists(data => sConfig.isPartOf(sandbox, data, queryElem));
  4854. const getState$2 = (_sandbox, _sConfig, sState) => sState.get();
  4855. const store = (sandbox, cssKey, attr, newValue) => {
  4856. getRaw(sandbox.element, cssKey).fold(() => {
  4857. remove$7(sandbox.element, attr);
  4858. }, v => {
  4859. set$9(sandbox.element, attr, v);
  4860. });
  4861. set$8(sandbox.element, cssKey, newValue);
  4862. };
  4863. const restore = (sandbox, cssKey, attr) => {
  4864. getOpt(sandbox.element, attr).fold(() => remove$6(sandbox.element, cssKey), oldValue => set$8(sandbox.element, cssKey, oldValue));
  4865. };
  4866. const cloak = (sandbox, sConfig, _sState) => {
  4867. const sink = sConfig.getAttachPoint(sandbox);
  4868. set$8(sandbox.element, 'position', Positioning.getMode(sink));
  4869. store(sandbox, 'visibility', sConfig.cloakVisibilityAttr, 'hidden');
  4870. };
  4871. const hasPosition = element => exists([
  4872. 'top',
  4873. 'left',
  4874. 'right',
  4875. 'bottom'
  4876. ], pos => getRaw(element, pos).isSome());
  4877. const decloak = (sandbox, sConfig, _sState) => {
  4878. if (!hasPosition(sandbox.element)) {
  4879. remove$6(sandbox.element, 'position');
  4880. }
  4881. restore(sandbox, 'visibility', sConfig.cloakVisibilityAttr);
  4882. };
  4883. var SandboxApis = /*#__PURE__*/Object.freeze({
  4884. __proto__: null,
  4885. cloak: cloak,
  4886. decloak: decloak,
  4887. open: open$1,
  4888. openWhileCloaked: openWhileCloaked,
  4889. close: close$1,
  4890. isOpen: isOpen$1,
  4891. isPartOf: isPartOf,
  4892. getState: getState$2,
  4893. setContent: setContent
  4894. });
  4895. const events$g = (sandboxConfig, sandboxState) => derive$2([run$1(sandboxClose(), (sandbox, _simulatedEvent) => {
  4896. close$1(sandbox, sandboxConfig, sandboxState);
  4897. })]);
  4898. var ActiveSandbox = /*#__PURE__*/Object.freeze({
  4899. __proto__: null,
  4900. events: events$g
  4901. });
  4902. var SandboxSchema = [
  4903. onHandler('onOpen'),
  4904. onHandler('onClose'),
  4905. required$1('isPartOf'),
  4906. required$1('getAttachPoint'),
  4907. defaulted('cloakVisibilityAttr', 'data-precloak-visibility')
  4908. ];
  4909. const init$f = () => {
  4910. const contents = value$2();
  4911. const readState = constant$1('not-implemented');
  4912. return nu$8({
  4913. readState,
  4914. isOpen: contents.isSet,
  4915. clear: contents.clear,
  4916. set: contents.set,
  4917. get: contents.get
  4918. });
  4919. };
  4920. var SandboxState = /*#__PURE__*/Object.freeze({
  4921. __proto__: null,
  4922. init: init$f
  4923. });
  4924. const Sandboxing = create$4({
  4925. fields: SandboxSchema,
  4926. name: 'sandboxing',
  4927. active: ActiveSandbox,
  4928. apis: SandboxApis,
  4929. state: SandboxState
  4930. });
  4931. const dismissPopups = constant$1('dismiss.popups');
  4932. const repositionPopups = constant$1('reposition.popups');
  4933. const mouseReleased = constant$1('mouse.released');
  4934. const schema$x = objOfOnly([
  4935. defaulted('isExtraPart', never),
  4936. optionObjOf('fireEventInstead', [defaulted('event', dismissRequested())])
  4937. ]);
  4938. const receivingChannel$1 = rawSpec => {
  4939. const detail = asRawOrDie$1('Dismissal', schema$x, rawSpec);
  4940. return {
  4941. [dismissPopups()]: {
  4942. schema: objOfOnly([required$1('target')]),
  4943. onReceive: (sandbox, data) => {
  4944. if (Sandboxing.isOpen(sandbox)) {
  4945. const isPart = Sandboxing.isPartOf(sandbox, data.target) || detail.isExtraPart(sandbox, data.target);
  4946. if (!isPart) {
  4947. detail.fireEventInstead.fold(() => Sandboxing.close(sandbox), fe => emit(sandbox, fe.event));
  4948. }
  4949. }
  4950. }
  4951. }
  4952. };
  4953. };
  4954. const schema$w = objOfOnly([
  4955. optionObjOf('fireEventInstead', [defaulted('event', repositionRequested())]),
  4956. requiredFunction('doReposition')
  4957. ]);
  4958. const receivingChannel = rawSpec => {
  4959. const detail = asRawOrDie$1('Reposition', schema$w, rawSpec);
  4960. return {
  4961. [repositionPopups()]: {
  4962. onReceive: sandbox => {
  4963. if (Sandboxing.isOpen(sandbox)) {
  4964. detail.fireEventInstead.fold(() => detail.doReposition(sandbox), fe => emit(sandbox, fe.event));
  4965. }
  4966. }
  4967. }
  4968. };
  4969. };
  4970. const onLoad$5 = (component, repConfig, repState) => {
  4971. repConfig.store.manager.onLoad(component, repConfig, repState);
  4972. };
  4973. const onUnload$2 = (component, repConfig, repState) => {
  4974. repConfig.store.manager.onUnload(component, repConfig, repState);
  4975. };
  4976. const setValue$3 = (component, repConfig, repState, data) => {
  4977. repConfig.store.manager.setValue(component, repConfig, repState, data);
  4978. };
  4979. const getValue$3 = (component, repConfig, repState) => repConfig.store.manager.getValue(component, repConfig, repState);
  4980. const getState$1 = (component, repConfig, repState) => repState;
  4981. var RepresentApis = /*#__PURE__*/Object.freeze({
  4982. __proto__: null,
  4983. onLoad: onLoad$5,
  4984. onUnload: onUnload$2,
  4985. setValue: setValue$3,
  4986. getValue: getValue$3,
  4987. getState: getState$1
  4988. });
  4989. const events$f = (repConfig, repState) => {
  4990. const es = repConfig.resetOnDom ? [
  4991. runOnAttached((comp, _se) => {
  4992. onLoad$5(comp, repConfig, repState);
  4993. }),
  4994. runOnDetached((comp, _se) => {
  4995. onUnload$2(comp, repConfig, repState);
  4996. })
  4997. ] : [loadEvent(repConfig, repState, onLoad$5)];
  4998. return derive$2(es);
  4999. };
  5000. var ActiveRepresenting = /*#__PURE__*/Object.freeze({
  5001. __proto__: null,
  5002. events: events$f
  5003. });
  5004. const memory$1 = () => {
  5005. const data = Cell(null);
  5006. const readState = () => ({
  5007. mode: 'memory',
  5008. value: data.get()
  5009. });
  5010. const isNotSet = () => data.get() === null;
  5011. const clear = () => {
  5012. data.set(null);
  5013. };
  5014. return nu$8({
  5015. set: data.set,
  5016. get: data.get,
  5017. isNotSet,
  5018. clear,
  5019. readState
  5020. });
  5021. };
  5022. const manual = () => {
  5023. const readState = noop;
  5024. return nu$8({ readState });
  5025. };
  5026. const dataset = () => {
  5027. const dataByValue = Cell({});
  5028. const dataByText = Cell({});
  5029. const readState = () => ({
  5030. mode: 'dataset',
  5031. dataByValue: dataByValue.get(),
  5032. dataByText: dataByText.get()
  5033. });
  5034. const clear = () => {
  5035. dataByValue.set({});
  5036. dataByText.set({});
  5037. };
  5038. const lookup = itemString => get$g(dataByValue.get(), itemString).orThunk(() => get$g(dataByText.get(), itemString));
  5039. const update = items => {
  5040. const currentDataByValue = dataByValue.get();
  5041. const currentDataByText = dataByText.get();
  5042. const newDataByValue = {};
  5043. const newDataByText = {};
  5044. each$1(items, item => {
  5045. newDataByValue[item.value] = item;
  5046. get$g(item, 'meta').each(meta => {
  5047. get$g(meta, 'text').each(text => {
  5048. newDataByText[text] = item;
  5049. });
  5050. });
  5051. });
  5052. dataByValue.set({
  5053. ...currentDataByValue,
  5054. ...newDataByValue
  5055. });
  5056. dataByText.set({
  5057. ...currentDataByText,
  5058. ...newDataByText
  5059. });
  5060. };
  5061. return nu$8({
  5062. readState,
  5063. lookup,
  5064. update,
  5065. clear
  5066. });
  5067. };
  5068. const init$e = spec => spec.store.manager.state(spec);
  5069. var RepresentState = /*#__PURE__*/Object.freeze({
  5070. __proto__: null,
  5071. memory: memory$1,
  5072. dataset: dataset,
  5073. manual: manual,
  5074. init: init$e
  5075. });
  5076. const setValue$2 = (component, repConfig, repState, data) => {
  5077. const store = repConfig.store;
  5078. repState.update([data]);
  5079. store.setValue(component, data);
  5080. repConfig.onSetValue(component, data);
  5081. };
  5082. const getValue$2 = (component, repConfig, repState) => {
  5083. const store = repConfig.store;
  5084. const key = store.getDataKey(component);
  5085. return repState.lookup(key).getOrThunk(() => store.getFallbackEntry(key));
  5086. };
  5087. const onLoad$4 = (component, repConfig, repState) => {
  5088. const store = repConfig.store;
  5089. store.initialValue.each(data => {
  5090. setValue$2(component, repConfig, repState, data);
  5091. });
  5092. };
  5093. const onUnload$1 = (component, repConfig, repState) => {
  5094. repState.clear();
  5095. };
  5096. var DatasetStore = [
  5097. option$3('initialValue'),
  5098. required$1('getFallbackEntry'),
  5099. required$1('getDataKey'),
  5100. required$1('setValue'),
  5101. output$1('manager', {
  5102. setValue: setValue$2,
  5103. getValue: getValue$2,
  5104. onLoad: onLoad$4,
  5105. onUnload: onUnload$1,
  5106. state: dataset
  5107. })
  5108. ];
  5109. const getValue$1 = (component, repConfig, _repState) => repConfig.store.getValue(component);
  5110. const setValue$1 = (component, repConfig, _repState, data) => {
  5111. repConfig.store.setValue(component, data);
  5112. repConfig.onSetValue(component, data);
  5113. };
  5114. const onLoad$3 = (component, repConfig, _repState) => {
  5115. repConfig.store.initialValue.each(data => {
  5116. repConfig.store.setValue(component, data);
  5117. });
  5118. };
  5119. var ManualStore = [
  5120. required$1('getValue'),
  5121. defaulted('setValue', noop),
  5122. option$3('initialValue'),
  5123. output$1('manager', {
  5124. setValue: setValue$1,
  5125. getValue: getValue$1,
  5126. onLoad: onLoad$3,
  5127. onUnload: noop,
  5128. state: NoState.init
  5129. })
  5130. ];
  5131. const setValue = (component, repConfig, repState, data) => {
  5132. repState.set(data);
  5133. repConfig.onSetValue(component, data);
  5134. };
  5135. const getValue = (component, repConfig, repState) => repState.get();
  5136. const onLoad$2 = (component, repConfig, repState) => {
  5137. repConfig.store.initialValue.each(initVal => {
  5138. if (repState.isNotSet()) {
  5139. repState.set(initVal);
  5140. }
  5141. });
  5142. };
  5143. const onUnload = (component, repConfig, repState) => {
  5144. repState.clear();
  5145. };
  5146. var MemoryStore = [
  5147. option$3('initialValue'),
  5148. output$1('manager', {
  5149. setValue,
  5150. getValue,
  5151. onLoad: onLoad$2,
  5152. onUnload,
  5153. state: memory$1
  5154. })
  5155. ];
  5156. var RepresentSchema = [
  5157. defaultedOf('store', { mode: 'memory' }, choose$1('mode', {
  5158. memory: MemoryStore,
  5159. manual: ManualStore,
  5160. dataset: DatasetStore
  5161. })),
  5162. onHandler('onSetValue'),
  5163. defaulted('resetOnDom', false)
  5164. ];
  5165. const Representing = create$4({
  5166. fields: RepresentSchema,
  5167. name: 'representing',
  5168. active: ActiveRepresenting,
  5169. apis: RepresentApis,
  5170. extra: {
  5171. setValueFrom: (component, source) => {
  5172. const value = Representing.getValue(source);
  5173. Representing.setValue(component, value);
  5174. }
  5175. },
  5176. state: RepresentState
  5177. });
  5178. const field = (name, forbidden) => defaultedObjOf(name, {}, map$2(forbidden, f => forbid(f.name(), 'Cannot configure ' + f.name() + ' for ' + name)).concat([customField('dump', identity)]));
  5179. const get$3 = data => data.dump;
  5180. const augment = (data, original) => ({
  5181. ...derive$1(original),
  5182. ...data.dump
  5183. });
  5184. const SketchBehaviours = {
  5185. field,
  5186. augment,
  5187. get: get$3
  5188. };
  5189. const _placeholder = 'placeholder';
  5190. const adt$3 = Adt.generate([
  5191. {
  5192. single: [
  5193. 'required',
  5194. 'valueThunk'
  5195. ]
  5196. },
  5197. {
  5198. multiple: [
  5199. 'required',
  5200. 'valueThunks'
  5201. ]
  5202. }
  5203. ]);
  5204. const isSubstituted = spec => has$2(spec, 'uiType');
  5205. const subPlaceholder = (owner, detail, compSpec, placeholders) => {
  5206. if (owner.exists(o => o !== compSpec.owner)) {
  5207. return adt$3.single(true, constant$1(compSpec));
  5208. }
  5209. return get$g(placeholders, compSpec.name).fold(() => {
  5210. throw new Error('Unknown placeholder component: ' + compSpec.name + '\nKnown: [' + keys(placeholders) + ']\nNamespace: ' + owner.getOr('none') + '\nSpec: ' + JSON.stringify(compSpec, null, 2));
  5211. }, newSpec => newSpec.replace());
  5212. };
  5213. const scan = (owner, detail, compSpec, placeholders) => {
  5214. if (isSubstituted(compSpec) && compSpec.uiType === _placeholder) {
  5215. return subPlaceholder(owner, detail, compSpec, placeholders);
  5216. } else {
  5217. return adt$3.single(false, constant$1(compSpec));
  5218. }
  5219. };
  5220. const substitute = (owner, detail, compSpec, placeholders) => {
  5221. const base = scan(owner, detail, compSpec, placeholders);
  5222. return base.fold((req, valueThunk) => {
  5223. const value = isSubstituted(compSpec) ? valueThunk(detail, compSpec.config, compSpec.validated) : valueThunk(detail);
  5224. const childSpecs = get$g(value, 'components').getOr([]);
  5225. const substituted = bind$3(childSpecs, c => substitute(owner, detail, c, placeholders));
  5226. return [{
  5227. ...value,
  5228. components: substituted
  5229. }];
  5230. }, (req, valuesThunk) => {
  5231. if (isSubstituted(compSpec)) {
  5232. const values = valuesThunk(detail, compSpec.config, compSpec.validated);
  5233. const preprocessor = compSpec.validated.preprocess.getOr(identity);
  5234. return preprocessor(values);
  5235. } else {
  5236. return valuesThunk(detail);
  5237. }
  5238. });
  5239. };
  5240. const substituteAll = (owner, detail, components, placeholders) => bind$3(components, c => substitute(owner, detail, c, placeholders));
  5241. const oneReplace = (label, replacements) => {
  5242. let called = false;
  5243. const used = () => called;
  5244. const replace = () => {
  5245. if (called) {
  5246. throw new Error('Trying to use the same placeholder more than once: ' + label);
  5247. }
  5248. called = true;
  5249. return replacements;
  5250. };
  5251. const required = () => replacements.fold((req, _) => req, (req, _) => req);
  5252. return {
  5253. name: constant$1(label),
  5254. required,
  5255. used,
  5256. replace
  5257. };
  5258. };
  5259. const substitutePlaces = (owner, detail, components, placeholders) => {
  5260. const ps = map$1(placeholders, (ph, name) => oneReplace(name, ph));
  5261. const outcome = substituteAll(owner, detail, components, ps);
  5262. each(ps, p => {
  5263. if (p.used() === false && p.required()) {
  5264. throw new Error('Placeholder: ' + p.name() + ' was not found in components list\nNamespace: ' + owner.getOr('none') + '\nComponents: ' + JSON.stringify(detail.components, null, 2));
  5265. }
  5266. });
  5267. return outcome;
  5268. };
  5269. const single$2 = adt$3.single;
  5270. const multiple = adt$3.multiple;
  5271. const placeholder = constant$1(_placeholder);
  5272. const adt$2 = Adt.generate([
  5273. { required: ['data'] },
  5274. { external: ['data'] },
  5275. { optional: ['data'] },
  5276. { group: ['data'] }
  5277. ]);
  5278. const fFactory = defaulted('factory', { sketch: identity });
  5279. const fSchema = defaulted('schema', []);
  5280. const fName = required$1('name');
  5281. const fPname = field$1('pname', 'pname', defaultedThunk(typeSpec => '<alloy.' + generate$6(typeSpec.name) + '>'), anyValue());
  5282. const fGroupSchema = customField('schema', () => [option$3('preprocess')]);
  5283. const fDefaults = defaulted('defaults', constant$1({}));
  5284. const fOverrides = defaulted('overrides', constant$1({}));
  5285. const requiredSpec = objOf([
  5286. fFactory,
  5287. fSchema,
  5288. fName,
  5289. fPname,
  5290. fDefaults,
  5291. fOverrides
  5292. ]);
  5293. const externalSpec = objOf([
  5294. fFactory,
  5295. fSchema,
  5296. fName,
  5297. fDefaults,
  5298. fOverrides
  5299. ]);
  5300. const optionalSpec = objOf([
  5301. fFactory,
  5302. fSchema,
  5303. fName,
  5304. fPname,
  5305. fDefaults,
  5306. fOverrides
  5307. ]);
  5308. const groupSpec = objOf([
  5309. fFactory,
  5310. fGroupSchema,
  5311. fName,
  5312. required$1('unit'),
  5313. fPname,
  5314. fDefaults,
  5315. fOverrides
  5316. ]);
  5317. const asNamedPart = part => {
  5318. return part.fold(Optional.some, Optional.none, Optional.some, Optional.some);
  5319. };
  5320. const name$2 = part => {
  5321. const get = data => data.name;
  5322. return part.fold(get, get, get, get);
  5323. };
  5324. const asCommon = part => {
  5325. return part.fold(identity, identity, identity, identity);
  5326. };
  5327. const convert = (adtConstructor, partSchema) => spec => {
  5328. const data = asRawOrDie$1('Converting part type', partSchema, spec);
  5329. return adtConstructor(data);
  5330. };
  5331. const required = convert(adt$2.required, requiredSpec);
  5332. const external = convert(adt$2.external, externalSpec);
  5333. const optional = convert(adt$2.optional, optionalSpec);
  5334. const group = convert(adt$2.group, groupSpec);
  5335. const original = constant$1('entirety');
  5336. var PartType = /*#__PURE__*/Object.freeze({
  5337. __proto__: null,
  5338. required: required,
  5339. external: external,
  5340. optional: optional,
  5341. group: group,
  5342. asNamedPart: asNamedPart,
  5343. name: name$2,
  5344. asCommon: asCommon,
  5345. original: original
  5346. });
  5347. const combine = (detail, data, partSpec, partValidated) => deepMerge(data.defaults(detail, partSpec, partValidated), partSpec, { uid: detail.partUids[data.name] }, data.overrides(detail, partSpec, partValidated));
  5348. const subs = (owner, detail, parts) => {
  5349. const internals = {};
  5350. const externals = {};
  5351. each$1(parts, part => {
  5352. part.fold(data => {
  5353. internals[data.pname] = single$2(true, (detail, partSpec, partValidated) => data.factory.sketch(combine(detail, data, partSpec, partValidated)));
  5354. }, data => {
  5355. const partSpec = detail.parts[data.name];
  5356. externals[data.name] = constant$1(data.factory.sketch(combine(detail, data, partSpec[original()]), partSpec));
  5357. }, data => {
  5358. internals[data.pname] = single$2(false, (detail, partSpec, partValidated) => data.factory.sketch(combine(detail, data, partSpec, partValidated)));
  5359. }, data => {
  5360. internals[data.pname] = multiple(true, (detail, _partSpec, _partValidated) => {
  5361. const units = detail[data.name];
  5362. return map$2(units, u => data.factory.sketch(deepMerge(data.defaults(detail, u, _partValidated), u, data.overrides(detail, u))));
  5363. });
  5364. });
  5365. });
  5366. return {
  5367. internals: constant$1(internals),
  5368. externals: constant$1(externals)
  5369. };
  5370. };
  5371. const generate$3 = (owner, parts) => {
  5372. const r = {};
  5373. each$1(parts, part => {
  5374. asNamedPart(part).each(np => {
  5375. const g = doGenerateOne(owner, np.pname);
  5376. r[np.name] = config => {
  5377. const validated = asRawOrDie$1('Part: ' + np.name + ' in ' + owner, objOf(np.schema), config);
  5378. return {
  5379. ...g,
  5380. config,
  5381. validated
  5382. };
  5383. };
  5384. });
  5385. });
  5386. return r;
  5387. };
  5388. const doGenerateOne = (owner, pname) => ({
  5389. uiType: placeholder(),
  5390. owner,
  5391. name: pname
  5392. });
  5393. const generateOne$1 = (owner, pname, config) => ({
  5394. uiType: placeholder(),
  5395. owner,
  5396. name: pname,
  5397. config,
  5398. validated: {}
  5399. });
  5400. const schemas = parts => bind$3(parts, part => part.fold(Optional.none, Optional.some, Optional.none, Optional.none).map(data => requiredObjOf(data.name, data.schema.concat([snapshot(original())]))).toArray());
  5401. const names = parts => map$2(parts, name$2);
  5402. const substitutes = (owner, detail, parts) => subs(owner, detail, parts);
  5403. const components$1 = (owner, detail, internals) => substitutePlaces(Optional.some(owner), detail, detail.components, internals);
  5404. const getPart = (component, detail, partKey) => {
  5405. const uid = detail.partUids[partKey];
  5406. return component.getSystem().getByUid(uid).toOptional();
  5407. };
  5408. const getPartOrDie = (component, detail, partKey) => getPart(component, detail, partKey).getOrDie('Could not find part: ' + partKey);
  5409. const getParts = (component, detail, partKeys) => {
  5410. const r = {};
  5411. const uids = detail.partUids;
  5412. const system = component.getSystem();
  5413. each$1(partKeys, pk => {
  5414. r[pk] = constant$1(system.getByUid(uids[pk]));
  5415. });
  5416. return r;
  5417. };
  5418. const getAllParts = (component, detail) => {
  5419. const system = component.getSystem();
  5420. return map$1(detail.partUids, (pUid, _k) => constant$1(system.getByUid(pUid)));
  5421. };
  5422. const getAllPartNames = detail => keys(detail.partUids);
  5423. const getPartsOrDie = (component, detail, partKeys) => {
  5424. const r = {};
  5425. const uids = detail.partUids;
  5426. const system = component.getSystem();
  5427. each$1(partKeys, pk => {
  5428. r[pk] = constant$1(system.getByUid(uids[pk]).getOrDie());
  5429. });
  5430. return r;
  5431. };
  5432. const defaultUids = (baseUid, partTypes) => {
  5433. const partNames = names(partTypes);
  5434. return wrapAll(map$2(partNames, pn => ({
  5435. key: pn,
  5436. value: baseUid + '-' + pn
  5437. })));
  5438. };
  5439. const defaultUidsSchema = partTypes => field$1('partUids', 'partUids', mergeWithThunk(spec => defaultUids(spec.uid, partTypes)), anyValue());
  5440. var AlloyParts = /*#__PURE__*/Object.freeze({
  5441. __proto__: null,
  5442. generate: generate$3,
  5443. generateOne: generateOne$1,
  5444. schemas: schemas,
  5445. names: names,
  5446. substitutes: substitutes,
  5447. components: components$1,
  5448. defaultUids: defaultUids,
  5449. defaultUidsSchema: defaultUidsSchema,
  5450. getAllParts: getAllParts,
  5451. getAllPartNames: getAllPartNames,
  5452. getPart: getPart,
  5453. getPartOrDie: getPartOrDie,
  5454. getParts: getParts,
  5455. getPartsOrDie: getPartsOrDie
  5456. });
  5457. const base = (partSchemas, partUidsSchemas) => {
  5458. const ps = partSchemas.length > 0 ? [requiredObjOf('parts', partSchemas)] : [];
  5459. return ps.concat([
  5460. required$1('uid'),
  5461. defaulted('dom', {}),
  5462. defaulted('components', []),
  5463. snapshot('originalSpec'),
  5464. defaulted('debug.sketcher', {})
  5465. ]).concat(partUidsSchemas);
  5466. };
  5467. const asRawOrDie = (label, schema, spec, partSchemas, partUidsSchemas) => {
  5468. const baseS = base(partSchemas, partUidsSchemas);
  5469. return asRawOrDie$1(label + ' [SpecSchema]', objOfOnly(baseS.concat(schema)), spec);
  5470. };
  5471. const single$1 = (owner, schema, factory, spec) => {
  5472. const specWithUid = supplyUid(spec);
  5473. const detail = asRawOrDie(owner, schema, specWithUid, [], []);
  5474. return factory(detail, specWithUid);
  5475. };
  5476. const composite$1 = (owner, schema, partTypes, factory, spec) => {
  5477. const specWithUid = supplyUid(spec);
  5478. const partSchemas = schemas(partTypes);
  5479. const partUidsSchema = defaultUidsSchema(partTypes);
  5480. const detail = asRawOrDie(owner, schema, specWithUid, partSchemas, [partUidsSchema]);
  5481. const subs = substitutes(owner, detail, partTypes);
  5482. const components = components$1(owner, detail, subs.internals());
  5483. return factory(detail, components, specWithUid, subs.externals());
  5484. };
  5485. const hasUid = spec => has$2(spec, 'uid');
  5486. const supplyUid = spec => {
  5487. return hasUid(spec) ? spec : {
  5488. ...spec,
  5489. uid: generate$5('uid')
  5490. };
  5491. };
  5492. const isSketchSpec = spec => {
  5493. return spec.uid !== undefined;
  5494. };
  5495. const singleSchema = objOfOnly([
  5496. required$1('name'),
  5497. required$1('factory'),
  5498. required$1('configFields'),
  5499. defaulted('apis', {}),
  5500. defaulted('extraApis', {})
  5501. ]);
  5502. const compositeSchema = objOfOnly([
  5503. required$1('name'),
  5504. required$1('factory'),
  5505. required$1('configFields'),
  5506. required$1('partFields'),
  5507. defaulted('apis', {}),
  5508. defaulted('extraApis', {})
  5509. ]);
  5510. const single = rawConfig => {
  5511. const config = asRawOrDie$1('Sketcher for ' + rawConfig.name, singleSchema, rawConfig);
  5512. const sketch = spec => single$1(config.name, config.configFields, config.factory, spec);
  5513. const apis = map$1(config.apis, makeApi);
  5514. const extraApis = map$1(config.extraApis, (f, k) => markAsExtraApi(f, k));
  5515. return {
  5516. name: config.name,
  5517. configFields: config.configFields,
  5518. sketch,
  5519. ...apis,
  5520. ...extraApis
  5521. };
  5522. };
  5523. const composite = rawConfig => {
  5524. const config = asRawOrDie$1('Sketcher for ' + rawConfig.name, compositeSchema, rawConfig);
  5525. const sketch = spec => composite$1(config.name, config.configFields, config.partFields, config.factory, spec);
  5526. const parts = generate$3(config.name, config.partFields);
  5527. const apis = map$1(config.apis, makeApi);
  5528. const extraApis = map$1(config.extraApis, (f, k) => markAsExtraApi(f, k));
  5529. return {
  5530. name: config.name,
  5531. partFields: config.partFields,
  5532. configFields: config.configFields,
  5533. sketch,
  5534. parts,
  5535. ...apis,
  5536. ...extraApis
  5537. };
  5538. };
  5539. const inside = target => isTag('input')(target) && get$f(target, 'type') !== 'radio' || isTag('textarea')(target);
  5540. const getCurrent = (component, composeConfig, _composeState) => composeConfig.find(component);
  5541. var ComposeApis = /*#__PURE__*/Object.freeze({
  5542. __proto__: null,
  5543. getCurrent: getCurrent
  5544. });
  5545. const ComposeSchema = [required$1('find')];
  5546. const Composing = create$4({
  5547. fields: ComposeSchema,
  5548. name: 'composing',
  5549. apis: ComposeApis
  5550. });
  5551. const nativeDisabled = [
  5552. 'input',
  5553. 'button',
  5554. 'textarea',
  5555. 'select'
  5556. ];
  5557. const onLoad$1 = (component, disableConfig, disableState) => {
  5558. const f = disableConfig.disabled() ? disable : enable;
  5559. f(component, disableConfig);
  5560. };
  5561. const hasNative = (component, config) => config.useNative === true && contains$2(nativeDisabled, name$3(component.element));
  5562. const nativeIsDisabled = component => has$1(component.element, 'disabled');
  5563. const nativeDisable = component => {
  5564. set$9(component.element, 'disabled', 'disabled');
  5565. };
  5566. const nativeEnable = component => {
  5567. remove$7(component.element, 'disabled');
  5568. };
  5569. const ariaIsDisabled = component => get$f(component.element, 'aria-disabled') === 'true';
  5570. const ariaDisable = component => {
  5571. set$9(component.element, 'aria-disabled', 'true');
  5572. };
  5573. const ariaEnable = component => {
  5574. set$9(component.element, 'aria-disabled', 'false');
  5575. };
  5576. const disable = (component, disableConfig, _disableState) => {
  5577. disableConfig.disableClass.each(disableClass => {
  5578. add$2(component.element, disableClass);
  5579. });
  5580. const f = hasNative(component, disableConfig) ? nativeDisable : ariaDisable;
  5581. f(component);
  5582. disableConfig.onDisabled(component);
  5583. };
  5584. const enable = (component, disableConfig, _disableState) => {
  5585. disableConfig.disableClass.each(disableClass => {
  5586. remove$2(component.element, disableClass);
  5587. });
  5588. const f = hasNative(component, disableConfig) ? nativeEnable : ariaEnable;
  5589. f(component);
  5590. disableConfig.onEnabled(component);
  5591. };
  5592. const isDisabled = (component, disableConfig) => hasNative(component, disableConfig) ? nativeIsDisabled(component) : ariaIsDisabled(component);
  5593. const set$4 = (component, disableConfig, disableState, disabled) => {
  5594. const f = disabled ? disable : enable;
  5595. f(component, disableConfig);
  5596. };
  5597. var DisableApis = /*#__PURE__*/Object.freeze({
  5598. __proto__: null,
  5599. enable: enable,
  5600. disable: disable,
  5601. isDisabled: isDisabled,
  5602. onLoad: onLoad$1,
  5603. set: set$4
  5604. });
  5605. const exhibit$5 = (base, disableConfig) => nu$7({ classes: disableConfig.disabled() ? disableConfig.disableClass.toArray() : [] });
  5606. const events$e = (disableConfig, disableState) => derive$2([
  5607. abort(execute$5(), (component, _simulatedEvent) => isDisabled(component, disableConfig)),
  5608. loadEvent(disableConfig, disableState, onLoad$1)
  5609. ]);
  5610. var ActiveDisable = /*#__PURE__*/Object.freeze({
  5611. __proto__: null,
  5612. exhibit: exhibit$5,
  5613. events: events$e
  5614. });
  5615. var DisableSchema = [
  5616. defaultedFunction('disabled', never),
  5617. defaulted('useNative', true),
  5618. option$3('disableClass'),
  5619. onHandler('onDisabled'),
  5620. onHandler('onEnabled')
  5621. ];
  5622. const Disabling = create$4({
  5623. fields: DisableSchema,
  5624. name: 'disabling',
  5625. active: ActiveDisable,
  5626. apis: DisableApis
  5627. });
  5628. const dehighlightAllExcept = (component, hConfig, hState, skip) => {
  5629. const highlighted = descendants(component.element, '.' + hConfig.highlightClass);
  5630. each$1(highlighted, h => {
  5631. const shouldSkip = exists(skip, skipComp => eq(skipComp.element, h));
  5632. if (!shouldSkip) {
  5633. remove$2(h, hConfig.highlightClass);
  5634. component.getSystem().getByDom(h).each(target => {
  5635. hConfig.onDehighlight(component, target);
  5636. emit(target, dehighlight$1());
  5637. });
  5638. }
  5639. });
  5640. };
  5641. const dehighlightAll = (component, hConfig, hState) => dehighlightAllExcept(component, hConfig, hState, []);
  5642. const dehighlight = (component, hConfig, hState, target) => {
  5643. if (isHighlighted(component, hConfig, hState, target)) {
  5644. remove$2(target.element, hConfig.highlightClass);
  5645. hConfig.onDehighlight(component, target);
  5646. emit(target, dehighlight$1());
  5647. }
  5648. };
  5649. const highlight = (component, hConfig, hState, target) => {
  5650. dehighlightAllExcept(component, hConfig, hState, [target]);
  5651. if (!isHighlighted(component, hConfig, hState, target)) {
  5652. add$2(target.element, hConfig.highlightClass);
  5653. hConfig.onHighlight(component, target);
  5654. emit(target, highlight$1());
  5655. }
  5656. };
  5657. const highlightFirst = (component, hConfig, hState) => {
  5658. getFirst(component, hConfig).each(firstComp => {
  5659. highlight(component, hConfig, hState, firstComp);
  5660. });
  5661. };
  5662. const highlightLast = (component, hConfig, hState) => {
  5663. getLast(component, hConfig).each(lastComp => {
  5664. highlight(component, hConfig, hState, lastComp);
  5665. });
  5666. };
  5667. const highlightAt = (component, hConfig, hState, index) => {
  5668. getByIndex(component, hConfig, hState, index).fold(err => {
  5669. throw err;
  5670. }, firstComp => {
  5671. highlight(component, hConfig, hState, firstComp);
  5672. });
  5673. };
  5674. const highlightBy = (component, hConfig, hState, predicate) => {
  5675. const candidates = getCandidates(component, hConfig);
  5676. const targetComp = find$5(candidates, predicate);
  5677. targetComp.each(c => {
  5678. highlight(component, hConfig, hState, c);
  5679. });
  5680. };
  5681. const isHighlighted = (component, hConfig, hState, queryTarget) => has(queryTarget.element, hConfig.highlightClass);
  5682. const getHighlighted = (component, hConfig, _hState) => descendant(component.element, '.' + hConfig.highlightClass).bind(e => component.getSystem().getByDom(e).toOptional());
  5683. const getByIndex = (component, hConfig, hState, index) => {
  5684. const items = descendants(component.element, '.' + hConfig.itemClass);
  5685. return Optional.from(items[index]).fold(() => Result.error(new Error('No element found with index ' + index)), component.getSystem().getByDom);
  5686. };
  5687. const getFirst = (component, hConfig, _hState) => descendant(component.element, '.' + hConfig.itemClass).bind(e => component.getSystem().getByDom(e).toOptional());
  5688. const getLast = (component, hConfig, _hState) => {
  5689. const items = descendants(component.element, '.' + hConfig.itemClass);
  5690. const last = items.length > 0 ? Optional.some(items[items.length - 1]) : Optional.none();
  5691. return last.bind(c => component.getSystem().getByDom(c).toOptional());
  5692. };
  5693. const getDelta$2 = (component, hConfig, hState, delta) => {
  5694. const items = descendants(component.element, '.' + hConfig.itemClass);
  5695. const current = findIndex$1(items, item => has(item, hConfig.highlightClass));
  5696. return current.bind(selected => {
  5697. const dest = cycleBy(selected, delta, 0, items.length - 1);
  5698. return component.getSystem().getByDom(items[dest]).toOptional();
  5699. });
  5700. };
  5701. const getPrevious = (component, hConfig, hState) => getDelta$2(component, hConfig, hState, -1);
  5702. const getNext = (component, hConfig, hState) => getDelta$2(component, hConfig, hState, +1);
  5703. const getCandidates = (component, hConfig, _hState) => {
  5704. const items = descendants(component.element, '.' + hConfig.itemClass);
  5705. return cat(map$2(items, i => component.getSystem().getByDom(i).toOptional()));
  5706. };
  5707. var HighlightApis = /*#__PURE__*/Object.freeze({
  5708. __proto__: null,
  5709. dehighlightAll: dehighlightAll,
  5710. dehighlight: dehighlight,
  5711. highlight: highlight,
  5712. highlightFirst: highlightFirst,
  5713. highlightLast: highlightLast,
  5714. highlightAt: highlightAt,
  5715. highlightBy: highlightBy,
  5716. isHighlighted: isHighlighted,
  5717. getHighlighted: getHighlighted,
  5718. getFirst: getFirst,
  5719. getLast: getLast,
  5720. getPrevious: getPrevious,
  5721. getNext: getNext,
  5722. getCandidates: getCandidates
  5723. });
  5724. var HighlightSchema = [
  5725. required$1('highlightClass'),
  5726. required$1('itemClass'),
  5727. onHandler('onHighlight'),
  5728. onHandler('onDehighlight')
  5729. ];
  5730. const Highlighting = create$4({
  5731. fields: HighlightSchema,
  5732. name: 'highlighting',
  5733. apis: HighlightApis
  5734. });
  5735. const BACKSPACE = [8];
  5736. const TAB = [9];
  5737. const ENTER = [13];
  5738. const ESCAPE = [27];
  5739. const SPACE = [32];
  5740. const LEFT = [37];
  5741. const UP = [38];
  5742. const RIGHT = [39];
  5743. const DOWN = [40];
  5744. const cyclePrev = (values, index, predicate) => {
  5745. const before = reverse(values.slice(0, index));
  5746. const after = reverse(values.slice(index + 1));
  5747. return find$5(before.concat(after), predicate);
  5748. };
  5749. const tryPrev = (values, index, predicate) => {
  5750. const before = reverse(values.slice(0, index));
  5751. return find$5(before, predicate);
  5752. };
  5753. const cycleNext = (values, index, predicate) => {
  5754. const before = values.slice(0, index);
  5755. const after = values.slice(index + 1);
  5756. return find$5(after.concat(before), predicate);
  5757. };
  5758. const tryNext = (values, index, predicate) => {
  5759. const after = values.slice(index + 1);
  5760. return find$5(after, predicate);
  5761. };
  5762. const inSet = keys => event => {
  5763. const raw = event.raw;
  5764. return contains$2(keys, raw.which);
  5765. };
  5766. const and = preds => event => forall(preds, pred => pred(event));
  5767. const isShift = event => {
  5768. const raw = event.raw;
  5769. return raw.shiftKey === true;
  5770. };
  5771. const isControl = event => {
  5772. const raw = event.raw;
  5773. return raw.ctrlKey === true;
  5774. };
  5775. const isNotShift = not(isShift);
  5776. const rule = (matches, action) => ({
  5777. matches,
  5778. classification: action
  5779. });
  5780. const choose = (transitions, event) => {
  5781. const transition = find$5(transitions, t => t.matches(event));
  5782. return transition.map(t => t.classification);
  5783. };
  5784. const reportFocusShifting = (component, prevFocus, newFocus) => {
  5785. const noChange = prevFocus.exists(p => newFocus.exists(n => eq(n, p)));
  5786. if (!noChange) {
  5787. emitWith(component, focusShifted(), {
  5788. prevFocus,
  5789. newFocus
  5790. });
  5791. }
  5792. };
  5793. const dom$2 = () => {
  5794. const get = component => search(component.element);
  5795. const set = (component, focusee) => {
  5796. const prevFocus = get(component);
  5797. component.getSystem().triggerFocus(focusee, component.element);
  5798. const newFocus = get(component);
  5799. reportFocusShifting(component, prevFocus, newFocus);
  5800. };
  5801. return {
  5802. get,
  5803. set
  5804. };
  5805. };
  5806. const highlights = () => {
  5807. const get = component => Highlighting.getHighlighted(component).map(item => item.element);
  5808. const set = (component, element) => {
  5809. const prevFocus = get(component);
  5810. component.getSystem().getByDom(element).fold(noop, item => {
  5811. Highlighting.highlight(component, item);
  5812. });
  5813. const newFocus = get(component);
  5814. reportFocusShifting(component, prevFocus, newFocus);
  5815. };
  5816. return {
  5817. get,
  5818. set
  5819. };
  5820. };
  5821. var FocusInsideModes;
  5822. (function (FocusInsideModes) {
  5823. FocusInsideModes['OnFocusMode'] = 'onFocus';
  5824. FocusInsideModes['OnEnterOrSpaceMode'] = 'onEnterOrSpace';
  5825. FocusInsideModes['OnApiMode'] = 'onApi';
  5826. }(FocusInsideModes || (FocusInsideModes = {})));
  5827. const typical = (infoSchema, stateInit, getKeydownRules, getKeyupRules, optFocusIn) => {
  5828. const schema = () => infoSchema.concat([
  5829. defaulted('focusManager', dom$2()),
  5830. defaultedOf('focusInside', 'onFocus', valueOf(val => contains$2([
  5831. 'onFocus',
  5832. 'onEnterOrSpace',
  5833. 'onApi'
  5834. ], val) ? Result.value(val) : Result.error('Invalid value for focusInside'))),
  5835. output$1('handler', me),
  5836. output$1('state', stateInit),
  5837. output$1('sendFocusIn', optFocusIn)
  5838. ]);
  5839. const processKey = (component, simulatedEvent, getRules, keyingConfig, keyingState) => {
  5840. const rules = getRules(component, simulatedEvent, keyingConfig, keyingState);
  5841. return choose(rules, simulatedEvent.event).bind(rule => rule(component, simulatedEvent, keyingConfig, keyingState));
  5842. };
  5843. const toEvents = (keyingConfig, keyingState) => {
  5844. const onFocusHandler = keyingConfig.focusInside !== FocusInsideModes.OnFocusMode ? Optional.none() : optFocusIn(keyingConfig).map(focusIn => run$1(focus$4(), (component, simulatedEvent) => {
  5845. focusIn(component, keyingConfig, keyingState);
  5846. simulatedEvent.stop();
  5847. }));
  5848. const tryGoInsideComponent = (component, simulatedEvent) => {
  5849. const isEnterOrSpace = inSet(SPACE.concat(ENTER))(simulatedEvent.event);
  5850. if (keyingConfig.focusInside === FocusInsideModes.OnEnterOrSpaceMode && isEnterOrSpace && isSource(component, simulatedEvent)) {
  5851. optFocusIn(keyingConfig).each(focusIn => {
  5852. focusIn(component, keyingConfig, keyingState);
  5853. simulatedEvent.stop();
  5854. });
  5855. }
  5856. };
  5857. const keyboardEvents = [
  5858. run$1(keydown(), (component, simulatedEvent) => {
  5859. processKey(component, simulatedEvent, getKeydownRules, keyingConfig, keyingState).fold(() => {
  5860. tryGoInsideComponent(component, simulatedEvent);
  5861. }, _ => {
  5862. simulatedEvent.stop();
  5863. });
  5864. }),
  5865. run$1(keyup(), (component, simulatedEvent) => {
  5866. processKey(component, simulatedEvent, getKeyupRules, keyingConfig, keyingState).each(_ => {
  5867. simulatedEvent.stop();
  5868. });
  5869. })
  5870. ];
  5871. return derive$2(onFocusHandler.toArray().concat(keyboardEvents));
  5872. };
  5873. const me = {
  5874. schema,
  5875. processKey,
  5876. toEvents
  5877. };
  5878. return me;
  5879. };
  5880. const create$2 = cyclicField => {
  5881. const schema = [
  5882. option$3('onEscape'),
  5883. option$3('onEnter'),
  5884. defaulted('selector', '[data-alloy-tabstop="true"]:not(:disabled)'),
  5885. defaulted('firstTabstop', 0),
  5886. defaulted('useTabstopAt', always),
  5887. option$3('visibilitySelector')
  5888. ].concat([cyclicField]);
  5889. const isVisible = (tabbingConfig, element) => {
  5890. const target = tabbingConfig.visibilitySelector.bind(sel => closest$1(element, sel)).getOr(element);
  5891. return get$d(target) > 0;
  5892. };
  5893. const findInitial = (component, tabbingConfig) => {
  5894. const tabstops = descendants(component.element, tabbingConfig.selector);
  5895. const visibles = filter$2(tabstops, elem => isVisible(tabbingConfig, elem));
  5896. return Optional.from(visibles[tabbingConfig.firstTabstop]);
  5897. };
  5898. const findCurrent = (component, tabbingConfig) => tabbingConfig.focusManager.get(component).bind(elem => closest$1(elem, tabbingConfig.selector));
  5899. const isTabstop = (tabbingConfig, element) => isVisible(tabbingConfig, element) && tabbingConfig.useTabstopAt(element);
  5900. const focusIn = (component, tabbingConfig, _tabbingState) => {
  5901. findInitial(component, tabbingConfig).each(target => {
  5902. tabbingConfig.focusManager.set(component, target);
  5903. });
  5904. };
  5905. const goFromTabstop = (component, tabstops, stopIndex, tabbingConfig, cycle) => cycle(tabstops, stopIndex, elem => isTabstop(tabbingConfig, elem)).fold(() => tabbingConfig.cyclic ? Optional.some(true) : Optional.none(), target => {
  5906. tabbingConfig.focusManager.set(component, target);
  5907. return Optional.some(true);
  5908. });
  5909. const go = (component, _simulatedEvent, tabbingConfig, cycle) => {
  5910. const tabstops = descendants(component.element, tabbingConfig.selector);
  5911. return findCurrent(component, tabbingConfig).bind(tabstop => {
  5912. const optStopIndex = findIndex$1(tabstops, curry(eq, tabstop));
  5913. return optStopIndex.bind(stopIndex => goFromTabstop(component, tabstops, stopIndex, tabbingConfig, cycle));
  5914. });
  5915. };
  5916. const goBackwards = (component, simulatedEvent, tabbingConfig) => {
  5917. const navigate = tabbingConfig.cyclic ? cyclePrev : tryPrev;
  5918. return go(component, simulatedEvent, tabbingConfig, navigate);
  5919. };
  5920. const goForwards = (component, simulatedEvent, tabbingConfig) => {
  5921. const navigate = tabbingConfig.cyclic ? cycleNext : tryNext;
  5922. return go(component, simulatedEvent, tabbingConfig, navigate);
  5923. };
  5924. const execute = (component, simulatedEvent, tabbingConfig) => tabbingConfig.onEnter.bind(f => f(component, simulatedEvent));
  5925. const exit = (component, simulatedEvent, tabbingConfig) => tabbingConfig.onEscape.bind(f => f(component, simulatedEvent));
  5926. const getKeydownRules = constant$1([
  5927. rule(and([
  5928. isShift,
  5929. inSet(TAB)
  5930. ]), goBackwards),
  5931. rule(inSet(TAB), goForwards),
  5932. rule(and([
  5933. isNotShift,
  5934. inSet(ENTER)
  5935. ]), execute)
  5936. ]);
  5937. const getKeyupRules = constant$1([rule(inSet(ESCAPE), exit)]);
  5938. return typical(schema, NoState.init, getKeydownRules, getKeyupRules, () => Optional.some(focusIn));
  5939. };
  5940. var AcyclicType = create$2(customField('cyclic', never));
  5941. var CyclicType = create$2(customField('cyclic', always));
  5942. const doDefaultExecute = (component, _simulatedEvent, focused) => {
  5943. dispatch(component, focused, execute$5());
  5944. return Optional.some(true);
  5945. };
  5946. const defaultExecute = (component, simulatedEvent, focused) => {
  5947. const isComplex = inside(focused) && inSet(SPACE)(simulatedEvent.event);
  5948. return isComplex ? Optional.none() : doDefaultExecute(component, simulatedEvent, focused);
  5949. };
  5950. const stopEventForFirefox = (_component, _simulatedEvent) => Optional.some(true);
  5951. const schema$v = [
  5952. defaulted('execute', defaultExecute),
  5953. defaulted('useSpace', false),
  5954. defaulted('useEnter', true),
  5955. defaulted('useControlEnter', false),
  5956. defaulted('useDown', false)
  5957. ];
  5958. const execute$4 = (component, simulatedEvent, executeConfig) => executeConfig.execute(component, simulatedEvent, component.element);
  5959. const getKeydownRules$5 = (component, _simulatedEvent, executeConfig, _executeState) => {
  5960. const spaceExec = executeConfig.useSpace && !inside(component.element) ? SPACE : [];
  5961. const enterExec = executeConfig.useEnter ? ENTER : [];
  5962. const downExec = executeConfig.useDown ? DOWN : [];
  5963. const execKeys = spaceExec.concat(enterExec).concat(downExec);
  5964. return [rule(inSet(execKeys), execute$4)].concat(executeConfig.useControlEnter ? [rule(and([
  5965. isControl,
  5966. inSet(ENTER)
  5967. ]), execute$4)] : []);
  5968. };
  5969. const getKeyupRules$5 = (component, _simulatedEvent, executeConfig, _executeState) => executeConfig.useSpace && !inside(component.element) ? [rule(inSet(SPACE), stopEventForFirefox)] : [];
  5970. var ExecutionType = typical(schema$v, NoState.init, getKeydownRules$5, getKeyupRules$5, () => Optional.none());
  5971. const flatgrid$1 = () => {
  5972. const dimensions = value$2();
  5973. const setGridSize = (numRows, numColumns) => {
  5974. dimensions.set({
  5975. numRows,
  5976. numColumns
  5977. });
  5978. };
  5979. const getNumRows = () => dimensions.get().map(d => d.numRows);
  5980. const getNumColumns = () => dimensions.get().map(d => d.numColumns);
  5981. return nu$8({
  5982. readState: () => dimensions.get().map(d => ({
  5983. numRows: String(d.numRows),
  5984. numColumns: String(d.numColumns)
  5985. })).getOr({
  5986. numRows: '?',
  5987. numColumns: '?'
  5988. }),
  5989. setGridSize,
  5990. getNumRows,
  5991. getNumColumns
  5992. });
  5993. };
  5994. const init$d = spec => spec.state(spec);
  5995. var KeyingState = /*#__PURE__*/Object.freeze({
  5996. __proto__: null,
  5997. flatgrid: flatgrid$1,
  5998. init: init$d
  5999. });
  6000. const useH = movement => (component, simulatedEvent, config, state) => {
  6001. const move = movement(component.element);
  6002. return use(move, component, simulatedEvent, config, state);
  6003. };
  6004. const west$1 = (moveLeft, moveRight) => {
  6005. const movement = onDirection(moveLeft, moveRight);
  6006. return useH(movement);
  6007. };
  6008. const east$1 = (moveLeft, moveRight) => {
  6009. const movement = onDirection(moveRight, moveLeft);
  6010. return useH(movement);
  6011. };
  6012. const useV = move => (component, simulatedEvent, config, state) => use(move, component, simulatedEvent, config, state);
  6013. const use = (move, component, simulatedEvent, config, state) => {
  6014. const outcome = config.focusManager.get(component).bind(focused => move(component.element, focused, config, state));
  6015. return outcome.map(newFocus => {
  6016. config.focusManager.set(component, newFocus);
  6017. return true;
  6018. });
  6019. };
  6020. const north$1 = useV;
  6021. const south$1 = useV;
  6022. const move$1 = useV;
  6023. const isHidden$1 = dom => dom.offsetWidth <= 0 && dom.offsetHeight <= 0;
  6024. const isVisible = element => !isHidden$1(element.dom);
  6025. const locate = (candidates, predicate) => findIndex$1(candidates, predicate).map(index => ({
  6026. index,
  6027. candidates
  6028. }));
  6029. const locateVisible = (container, current, selector) => {
  6030. const predicate = x => eq(x, current);
  6031. const candidates = descendants(container, selector);
  6032. const visible = filter$2(candidates, isVisible);
  6033. return locate(visible, predicate);
  6034. };
  6035. const findIndex = (elements, target) => findIndex$1(elements, elem => eq(target, elem));
  6036. const withGrid = (values, index, numCols, f) => {
  6037. const oldRow = Math.floor(index / numCols);
  6038. const oldColumn = index % numCols;
  6039. return f(oldRow, oldColumn).bind(address => {
  6040. const newIndex = address.row * numCols + address.column;
  6041. return newIndex >= 0 && newIndex < values.length ? Optional.some(values[newIndex]) : Optional.none();
  6042. });
  6043. };
  6044. const cycleHorizontal$1 = (values, index, numRows, numCols, delta) => withGrid(values, index, numCols, (oldRow, oldColumn) => {
  6045. const onLastRow = oldRow === numRows - 1;
  6046. const colsInRow = onLastRow ? values.length - oldRow * numCols : numCols;
  6047. const newColumn = cycleBy(oldColumn, delta, 0, colsInRow - 1);
  6048. return Optional.some({
  6049. row: oldRow,
  6050. column: newColumn
  6051. });
  6052. });
  6053. const cycleVertical$1 = (values, index, numRows, numCols, delta) => withGrid(values, index, numCols, (oldRow, oldColumn) => {
  6054. const newRow = cycleBy(oldRow, delta, 0, numRows - 1);
  6055. const onLastRow = newRow === numRows - 1;
  6056. const colsInRow = onLastRow ? values.length - newRow * numCols : numCols;
  6057. const newCol = clamp(oldColumn, 0, colsInRow - 1);
  6058. return Optional.some({
  6059. row: newRow,
  6060. column: newCol
  6061. });
  6062. });
  6063. const cycleRight$1 = (values, index, numRows, numCols) => cycleHorizontal$1(values, index, numRows, numCols, +1);
  6064. const cycleLeft$1 = (values, index, numRows, numCols) => cycleHorizontal$1(values, index, numRows, numCols, -1);
  6065. const cycleUp$1 = (values, index, numRows, numCols) => cycleVertical$1(values, index, numRows, numCols, -1);
  6066. const cycleDown$1 = (values, index, numRows, numCols) => cycleVertical$1(values, index, numRows, numCols, +1);
  6067. const schema$u = [
  6068. required$1('selector'),
  6069. defaulted('execute', defaultExecute),
  6070. onKeyboardHandler('onEscape'),
  6071. defaulted('captureTab', false),
  6072. initSize()
  6073. ];
  6074. const focusIn$3 = (component, gridConfig, _gridState) => {
  6075. descendant(component.element, gridConfig.selector).each(first => {
  6076. gridConfig.focusManager.set(component, first);
  6077. });
  6078. };
  6079. const findCurrent$1 = (component, gridConfig) => gridConfig.focusManager.get(component).bind(elem => closest$1(elem, gridConfig.selector));
  6080. const execute$3 = (component, simulatedEvent, gridConfig, _gridState) => findCurrent$1(component, gridConfig).bind(focused => gridConfig.execute(component, simulatedEvent, focused));
  6081. const doMove$2 = cycle => (element, focused, gridConfig, gridState) => locateVisible(element, focused, gridConfig.selector).bind(identified => cycle(identified.candidates, identified.index, gridState.getNumRows().getOr(gridConfig.initSize.numRows), gridState.getNumColumns().getOr(gridConfig.initSize.numColumns)));
  6082. const handleTab = (_component, _simulatedEvent, gridConfig) => gridConfig.captureTab ? Optional.some(true) : Optional.none();
  6083. const doEscape$1 = (component, simulatedEvent, gridConfig) => gridConfig.onEscape(component, simulatedEvent);
  6084. const moveLeft$3 = doMove$2(cycleLeft$1);
  6085. const moveRight$3 = doMove$2(cycleRight$1);
  6086. const moveNorth$1 = doMove$2(cycleUp$1);
  6087. const moveSouth$1 = doMove$2(cycleDown$1);
  6088. const getKeydownRules$4 = constant$1([
  6089. rule(inSet(LEFT), west$1(moveLeft$3, moveRight$3)),
  6090. rule(inSet(RIGHT), east$1(moveLeft$3, moveRight$3)),
  6091. rule(inSet(UP), north$1(moveNorth$1)),
  6092. rule(inSet(DOWN), south$1(moveSouth$1)),
  6093. rule(and([
  6094. isShift,
  6095. inSet(TAB)
  6096. ]), handleTab),
  6097. rule(and([
  6098. isNotShift,
  6099. inSet(TAB)
  6100. ]), handleTab),
  6101. rule(inSet(SPACE.concat(ENTER)), execute$3)
  6102. ]);
  6103. const getKeyupRules$4 = constant$1([
  6104. rule(inSet(ESCAPE), doEscape$1),
  6105. rule(inSet(SPACE), stopEventForFirefox)
  6106. ]);
  6107. var FlatgridType = typical(schema$u, flatgrid$1, getKeydownRules$4, getKeyupRules$4, () => Optional.some(focusIn$3));
  6108. const horizontal = (container, selector, current, delta) => {
  6109. const isDisabledButton = candidate => name$3(candidate) === 'button' && get$f(candidate, 'disabled') === 'disabled';
  6110. const tryCycle = (initial, index, candidates) => {
  6111. const newIndex = cycleBy(index, delta, 0, candidates.length - 1);
  6112. if (newIndex === initial) {
  6113. return Optional.none();
  6114. } else {
  6115. return isDisabledButton(candidates[newIndex]) ? tryCycle(initial, newIndex, candidates) : Optional.from(candidates[newIndex]);
  6116. }
  6117. };
  6118. return locateVisible(container, current, selector).bind(identified => {
  6119. const index = identified.index;
  6120. const candidates = identified.candidates;
  6121. return tryCycle(index, index, candidates);
  6122. });
  6123. };
  6124. const schema$t = [
  6125. required$1('selector'),
  6126. defaulted('getInitial', Optional.none),
  6127. defaulted('execute', defaultExecute),
  6128. onKeyboardHandler('onEscape'),
  6129. defaulted('executeOnMove', false),
  6130. defaulted('allowVertical', true)
  6131. ];
  6132. const findCurrent = (component, flowConfig) => flowConfig.focusManager.get(component).bind(elem => closest$1(elem, flowConfig.selector));
  6133. const execute$2 = (component, simulatedEvent, flowConfig) => findCurrent(component, flowConfig).bind(focused => flowConfig.execute(component, simulatedEvent, focused));
  6134. const focusIn$2 = (component, flowConfig, _state) => {
  6135. flowConfig.getInitial(component).orThunk(() => descendant(component.element, flowConfig.selector)).each(first => {
  6136. flowConfig.focusManager.set(component, first);
  6137. });
  6138. };
  6139. const moveLeft$2 = (element, focused, info) => horizontal(element, info.selector, focused, -1);
  6140. const moveRight$2 = (element, focused, info) => horizontal(element, info.selector, focused, +1);
  6141. const doMove$1 = movement => (component, simulatedEvent, flowConfig, flowState) => movement(component, simulatedEvent, flowConfig, flowState).bind(() => flowConfig.executeOnMove ? execute$2(component, simulatedEvent, flowConfig) : Optional.some(true));
  6142. const doEscape = (component, simulatedEvent, flowConfig) => flowConfig.onEscape(component, simulatedEvent);
  6143. const getKeydownRules$3 = (_component, _se, flowConfig, _flowState) => {
  6144. const westMovers = LEFT.concat(flowConfig.allowVertical ? UP : []);
  6145. const eastMovers = RIGHT.concat(flowConfig.allowVertical ? DOWN : []);
  6146. return [
  6147. rule(inSet(westMovers), doMove$1(west$1(moveLeft$2, moveRight$2))),
  6148. rule(inSet(eastMovers), doMove$1(east$1(moveLeft$2, moveRight$2))),
  6149. rule(inSet(ENTER), execute$2),
  6150. rule(inSet(SPACE), execute$2)
  6151. ];
  6152. };
  6153. const getKeyupRules$3 = constant$1([
  6154. rule(inSet(SPACE), stopEventForFirefox),
  6155. rule(inSet(ESCAPE), doEscape)
  6156. ]);
  6157. var FlowType = typical(schema$t, NoState.init, getKeydownRules$3, getKeyupRules$3, () => Optional.some(focusIn$2));
  6158. const toCell = (matrix, rowIndex, columnIndex) => Optional.from(matrix[rowIndex]).bind(row => Optional.from(row[columnIndex]).map(cell => ({
  6159. rowIndex,
  6160. columnIndex,
  6161. cell
  6162. })));
  6163. const cycleHorizontal = (matrix, rowIndex, startCol, deltaCol) => {
  6164. const row = matrix[rowIndex];
  6165. const colsInRow = row.length;
  6166. const newColIndex = cycleBy(startCol, deltaCol, 0, colsInRow - 1);
  6167. return toCell(matrix, rowIndex, newColIndex);
  6168. };
  6169. const cycleVertical = (matrix, colIndex, startRow, deltaRow) => {
  6170. const nextRowIndex = cycleBy(startRow, deltaRow, 0, matrix.length - 1);
  6171. const colsInNextRow = matrix[nextRowIndex].length;
  6172. const nextColIndex = clamp(colIndex, 0, colsInNextRow - 1);
  6173. return toCell(matrix, nextRowIndex, nextColIndex);
  6174. };
  6175. const moveHorizontal = (matrix, rowIndex, startCol, deltaCol) => {
  6176. const row = matrix[rowIndex];
  6177. const colsInRow = row.length;
  6178. const newColIndex = clamp(startCol + deltaCol, 0, colsInRow - 1);
  6179. return toCell(matrix, rowIndex, newColIndex);
  6180. };
  6181. const moveVertical = (matrix, colIndex, startRow, deltaRow) => {
  6182. const nextRowIndex = clamp(startRow + deltaRow, 0, matrix.length - 1);
  6183. const colsInNextRow = matrix[nextRowIndex].length;
  6184. const nextColIndex = clamp(colIndex, 0, colsInNextRow - 1);
  6185. return toCell(matrix, nextRowIndex, nextColIndex);
  6186. };
  6187. const cycleRight = (matrix, startRow, startCol) => cycleHorizontal(matrix, startRow, startCol, +1);
  6188. const cycleLeft = (matrix, startRow, startCol) => cycleHorizontal(matrix, startRow, startCol, -1);
  6189. const cycleUp = (matrix, startRow, startCol) => cycleVertical(matrix, startCol, startRow, -1);
  6190. const cycleDown = (matrix, startRow, startCol) => cycleVertical(matrix, startCol, startRow, +1);
  6191. const moveLeft$1 = (matrix, startRow, startCol) => moveHorizontal(matrix, startRow, startCol, -1);
  6192. const moveRight$1 = (matrix, startRow, startCol) => moveHorizontal(matrix, startRow, startCol, +1);
  6193. const moveUp$1 = (matrix, startRow, startCol) => moveVertical(matrix, startCol, startRow, -1);
  6194. const moveDown$1 = (matrix, startRow, startCol) => moveVertical(matrix, startCol, startRow, +1);
  6195. const schema$s = [
  6196. requiredObjOf('selectors', [
  6197. required$1('row'),
  6198. required$1('cell')
  6199. ]),
  6200. defaulted('cycles', true),
  6201. defaulted('previousSelector', Optional.none),
  6202. defaulted('execute', defaultExecute)
  6203. ];
  6204. const focusIn$1 = (component, matrixConfig, _state) => {
  6205. const focused = matrixConfig.previousSelector(component).orThunk(() => {
  6206. const selectors = matrixConfig.selectors;
  6207. return descendant(component.element, selectors.cell);
  6208. });
  6209. focused.each(cell => {
  6210. matrixConfig.focusManager.set(component, cell);
  6211. });
  6212. };
  6213. const execute$1 = (component, simulatedEvent, matrixConfig) => search(component.element).bind(focused => matrixConfig.execute(component, simulatedEvent, focused));
  6214. const toMatrix = (rows, matrixConfig) => map$2(rows, row => descendants(row, matrixConfig.selectors.cell));
  6215. const doMove = (ifCycle, ifMove) => (element, focused, matrixConfig) => {
  6216. const move = matrixConfig.cycles ? ifCycle : ifMove;
  6217. return closest$1(focused, matrixConfig.selectors.row).bind(inRow => {
  6218. const cellsInRow = descendants(inRow, matrixConfig.selectors.cell);
  6219. return findIndex(cellsInRow, focused).bind(colIndex => {
  6220. const allRows = descendants(element, matrixConfig.selectors.row);
  6221. return findIndex(allRows, inRow).bind(rowIndex => {
  6222. const matrix = toMatrix(allRows, matrixConfig);
  6223. return move(matrix, rowIndex, colIndex).map(next => next.cell);
  6224. });
  6225. });
  6226. });
  6227. };
  6228. const moveLeft = doMove(cycleLeft, moveLeft$1);
  6229. const moveRight = doMove(cycleRight, moveRight$1);
  6230. const moveNorth = doMove(cycleUp, moveUp$1);
  6231. const moveSouth = doMove(cycleDown, moveDown$1);
  6232. const getKeydownRules$2 = constant$1([
  6233. rule(inSet(LEFT), west$1(moveLeft, moveRight)),
  6234. rule(inSet(RIGHT), east$1(moveLeft, moveRight)),
  6235. rule(inSet(UP), north$1(moveNorth)),
  6236. rule(inSet(DOWN), south$1(moveSouth)),
  6237. rule(inSet(SPACE.concat(ENTER)), execute$1)
  6238. ]);
  6239. const getKeyupRules$2 = constant$1([rule(inSet(SPACE), stopEventForFirefox)]);
  6240. var MatrixType = typical(schema$s, NoState.init, getKeydownRules$2, getKeyupRules$2, () => Optional.some(focusIn$1));
  6241. const schema$r = [
  6242. required$1('selector'),
  6243. defaulted('execute', defaultExecute),
  6244. defaulted('moveOnTab', false)
  6245. ];
  6246. const execute = (component, simulatedEvent, menuConfig) => menuConfig.focusManager.get(component).bind(focused => menuConfig.execute(component, simulatedEvent, focused));
  6247. const focusIn = (component, menuConfig, _state) => {
  6248. descendant(component.element, menuConfig.selector).each(first => {
  6249. menuConfig.focusManager.set(component, first);
  6250. });
  6251. };
  6252. const moveUp = (element, focused, info) => horizontal(element, info.selector, focused, -1);
  6253. const moveDown = (element, focused, info) => horizontal(element, info.selector, focused, +1);
  6254. const fireShiftTab = (component, simulatedEvent, menuConfig, menuState) => menuConfig.moveOnTab ? move$1(moveUp)(component, simulatedEvent, menuConfig, menuState) : Optional.none();
  6255. const fireTab = (component, simulatedEvent, menuConfig, menuState) => menuConfig.moveOnTab ? move$1(moveDown)(component, simulatedEvent, menuConfig, menuState) : Optional.none();
  6256. const getKeydownRules$1 = constant$1([
  6257. rule(inSet(UP), move$1(moveUp)),
  6258. rule(inSet(DOWN), move$1(moveDown)),
  6259. rule(and([
  6260. isShift,
  6261. inSet(TAB)
  6262. ]), fireShiftTab),
  6263. rule(and([
  6264. isNotShift,
  6265. inSet(TAB)
  6266. ]), fireTab),
  6267. rule(inSet(ENTER), execute),
  6268. rule(inSet(SPACE), execute)
  6269. ]);
  6270. const getKeyupRules$1 = constant$1([rule(inSet(SPACE), stopEventForFirefox)]);
  6271. var MenuType = typical(schema$r, NoState.init, getKeydownRules$1, getKeyupRules$1, () => Optional.some(focusIn));
  6272. const schema$q = [
  6273. onKeyboardHandler('onSpace'),
  6274. onKeyboardHandler('onEnter'),
  6275. onKeyboardHandler('onShiftEnter'),
  6276. onKeyboardHandler('onLeft'),
  6277. onKeyboardHandler('onRight'),
  6278. onKeyboardHandler('onTab'),
  6279. onKeyboardHandler('onShiftTab'),
  6280. onKeyboardHandler('onUp'),
  6281. onKeyboardHandler('onDown'),
  6282. onKeyboardHandler('onEscape'),
  6283. defaulted('stopSpaceKeyup', false),
  6284. option$3('focusIn')
  6285. ];
  6286. const getKeydownRules = (component, simulatedEvent, specialInfo) => [
  6287. rule(inSet(SPACE), specialInfo.onSpace),
  6288. rule(and([
  6289. isNotShift,
  6290. inSet(ENTER)
  6291. ]), specialInfo.onEnter),
  6292. rule(and([
  6293. isShift,
  6294. inSet(ENTER)
  6295. ]), specialInfo.onShiftEnter),
  6296. rule(and([
  6297. isShift,
  6298. inSet(TAB)
  6299. ]), specialInfo.onShiftTab),
  6300. rule(and([
  6301. isNotShift,
  6302. inSet(TAB)
  6303. ]), specialInfo.onTab),
  6304. rule(inSet(UP), specialInfo.onUp),
  6305. rule(inSet(DOWN), specialInfo.onDown),
  6306. rule(inSet(LEFT), specialInfo.onLeft),
  6307. rule(inSet(RIGHT), specialInfo.onRight),
  6308. rule(inSet(SPACE), specialInfo.onSpace)
  6309. ];
  6310. const getKeyupRules = (component, simulatedEvent, specialInfo) => [
  6311. ...specialInfo.stopSpaceKeyup ? [rule(inSet(SPACE), stopEventForFirefox)] : [],
  6312. rule(inSet(ESCAPE), specialInfo.onEscape)
  6313. ];
  6314. var SpecialType = typical(schema$q, NoState.init, getKeydownRules, getKeyupRules, specialInfo => specialInfo.focusIn);
  6315. const acyclic = AcyclicType.schema();
  6316. const cyclic = CyclicType.schema();
  6317. const flow = FlowType.schema();
  6318. const flatgrid = FlatgridType.schema();
  6319. const matrix = MatrixType.schema();
  6320. const execution = ExecutionType.schema();
  6321. const menu = MenuType.schema();
  6322. const special = SpecialType.schema();
  6323. var KeyboardBranches = /*#__PURE__*/Object.freeze({
  6324. __proto__: null,
  6325. acyclic: acyclic,
  6326. cyclic: cyclic,
  6327. flow: flow,
  6328. flatgrid: flatgrid,
  6329. matrix: matrix,
  6330. execution: execution,
  6331. menu: menu,
  6332. special: special
  6333. });
  6334. const isFlatgridState = keyState => hasNonNullableKey(keyState, 'setGridSize');
  6335. const Keying = createModes({
  6336. branchKey: 'mode',
  6337. branches: KeyboardBranches,
  6338. name: 'keying',
  6339. active: {
  6340. events: (keyingConfig, keyingState) => {
  6341. const handler = keyingConfig.handler;
  6342. return handler.toEvents(keyingConfig, keyingState);
  6343. }
  6344. },
  6345. apis: {
  6346. focusIn: (component, keyConfig, keyState) => {
  6347. keyConfig.sendFocusIn(keyConfig).fold(() => {
  6348. component.getSystem().triggerFocus(component.element, component.element);
  6349. }, sendFocusIn => {
  6350. sendFocusIn(component, keyConfig, keyState);
  6351. });
  6352. },
  6353. setGridSize: (component, keyConfig, keyState, numRows, numColumns) => {
  6354. if (!isFlatgridState(keyState)) {
  6355. console.error('Layout does not support setGridSize');
  6356. } else {
  6357. keyState.setGridSize(numRows, numColumns);
  6358. }
  6359. }
  6360. },
  6361. state: KeyingState
  6362. });
  6363. const withoutReuse = (parent, data) => {
  6364. preserve$1(() => {
  6365. replaceChildren(parent, data, () => map$2(data, parent.getSystem().build));
  6366. }, parent.element);
  6367. };
  6368. const withReuse = (parent, data) => {
  6369. preserve$1(() => {
  6370. virtualReplaceChildren(parent, data, () => {
  6371. return patchSpecChildren(parent.element, data, parent.getSystem().buildOrPatch);
  6372. });
  6373. }, parent.element);
  6374. };
  6375. const virtualReplace = (component, replacee, replaceeIndex, childSpec) => {
  6376. virtualDetach(replacee);
  6377. const child = patchSpecChild(component.element, replaceeIndex, childSpec, component.getSystem().buildOrPatch);
  6378. virtualAttach(component, child);
  6379. component.syncComponents();
  6380. };
  6381. const insert = (component, insertion, childSpec) => {
  6382. const child = component.getSystem().build(childSpec);
  6383. attachWith(component, child, insertion);
  6384. };
  6385. const replace = (component, replacee, replaceeIndex, childSpec) => {
  6386. detach(replacee);
  6387. insert(component, (p, c) => appendAt(p, c, replaceeIndex), childSpec);
  6388. };
  6389. const set$3 = (component, replaceConfig, replaceState, data) => {
  6390. const replacer = replaceConfig.reuseDom ? withReuse : withoutReuse;
  6391. return replacer(component, data);
  6392. };
  6393. const append = (component, replaceConfig, replaceState, appendee) => {
  6394. insert(component, append$2, appendee);
  6395. };
  6396. const prepend = (component, replaceConfig, replaceState, prependee) => {
  6397. insert(component, prepend$1, prependee);
  6398. };
  6399. const remove = (component, replaceConfig, replaceState, removee) => {
  6400. const children = contents(component);
  6401. const foundChild = find$5(children, child => eq(removee.element, child.element));
  6402. foundChild.each(detach);
  6403. };
  6404. const contents = (component, _replaceConfig) => component.components();
  6405. const replaceAt = (component, replaceConfig, replaceState, replaceeIndex, replacer) => {
  6406. const children = contents(component);
  6407. return Optional.from(children[replaceeIndex]).map(replacee => {
  6408. replacer.fold(() => detach(replacee), r => {
  6409. const replacer = replaceConfig.reuseDom ? virtualReplace : replace;
  6410. replacer(component, replacee, replaceeIndex, r);
  6411. });
  6412. return replacee;
  6413. });
  6414. };
  6415. const replaceBy = (component, replaceConfig, replaceState, replaceePred, replacer) => {
  6416. const children = contents(component);
  6417. return findIndex$1(children, replaceePred).bind(replaceeIndex => replaceAt(component, replaceConfig, replaceState, replaceeIndex, replacer));
  6418. };
  6419. var ReplaceApis = /*#__PURE__*/Object.freeze({
  6420. __proto__: null,
  6421. append: append,
  6422. prepend: prepend,
  6423. remove: remove,
  6424. replaceAt: replaceAt,
  6425. replaceBy: replaceBy,
  6426. set: set$3,
  6427. contents: contents
  6428. });
  6429. const Replacing = create$4({
  6430. fields: [defaultedBoolean('reuseDom', true)],
  6431. name: 'replacing',
  6432. apis: ReplaceApis
  6433. });
  6434. const events$d = (name, eventHandlers) => {
  6435. const events = derive$2(eventHandlers);
  6436. return create$4({
  6437. fields: [required$1('enabled')],
  6438. name,
  6439. active: { events: constant$1(events) }
  6440. });
  6441. };
  6442. const config = (name, eventHandlers) => {
  6443. const me = events$d(name, eventHandlers);
  6444. return {
  6445. key: name,
  6446. value: {
  6447. config: {},
  6448. me,
  6449. configAsRaw: constant$1({}),
  6450. initialConfig: {},
  6451. state: NoState
  6452. }
  6453. };
  6454. };
  6455. const focus$2 = (component, focusConfig) => {
  6456. if (!focusConfig.ignore) {
  6457. focus$3(component.element);
  6458. focusConfig.onFocus(component);
  6459. }
  6460. };
  6461. const blur = (component, focusConfig) => {
  6462. if (!focusConfig.ignore) {
  6463. blur$1(component.element);
  6464. }
  6465. };
  6466. const isFocused = component => hasFocus(component.element);
  6467. var FocusApis = /*#__PURE__*/Object.freeze({
  6468. __proto__: null,
  6469. focus: focus$2,
  6470. blur: blur,
  6471. isFocused: isFocused
  6472. });
  6473. const exhibit$4 = (base, focusConfig) => {
  6474. const mod = focusConfig.ignore ? {} : { attributes: { tabindex: '-1' } };
  6475. return nu$7(mod);
  6476. };
  6477. const events$c = focusConfig => derive$2([run$1(focus$4(), (component, simulatedEvent) => {
  6478. focus$2(component, focusConfig);
  6479. simulatedEvent.stop();
  6480. })].concat(focusConfig.stopMousedown ? [run$1(mousedown(), (_, simulatedEvent) => {
  6481. simulatedEvent.event.prevent();
  6482. })] : []));
  6483. var ActiveFocus = /*#__PURE__*/Object.freeze({
  6484. __proto__: null,
  6485. exhibit: exhibit$4,
  6486. events: events$c
  6487. });
  6488. var FocusSchema = [
  6489. onHandler('onFocus'),
  6490. defaulted('stopMousedown', false),
  6491. defaulted('ignore', false)
  6492. ];
  6493. const Focusing = create$4({
  6494. fields: FocusSchema,
  6495. name: 'focusing',
  6496. active: ActiveFocus,
  6497. apis: FocusApis
  6498. });
  6499. const SetupBehaviourCellState = initialState => {
  6500. const init = () => {
  6501. const cell = Cell(initialState);
  6502. const get = () => cell.get();
  6503. const set = newState => cell.set(newState);
  6504. const clear = () => cell.set(initialState);
  6505. const readState = () => cell.get();
  6506. return {
  6507. get,
  6508. set,
  6509. clear,
  6510. readState
  6511. };
  6512. };
  6513. return { init };
  6514. };
  6515. const updateAriaState = (component, toggleConfig, toggleState) => {
  6516. const ariaInfo = toggleConfig.aria;
  6517. ariaInfo.update(component, ariaInfo, toggleState.get());
  6518. };
  6519. const updateClass = (component, toggleConfig, toggleState) => {
  6520. toggleConfig.toggleClass.each(toggleClass => {
  6521. if (toggleState.get()) {
  6522. add$2(component.element, toggleClass);
  6523. } else {
  6524. remove$2(component.element, toggleClass);
  6525. }
  6526. });
  6527. };
  6528. const set$2 = (component, toggleConfig, toggleState, state) => {
  6529. const initialState = toggleState.get();
  6530. toggleState.set(state);
  6531. updateClass(component, toggleConfig, toggleState);
  6532. updateAriaState(component, toggleConfig, toggleState);
  6533. if (initialState !== state) {
  6534. toggleConfig.onToggled(component, state);
  6535. }
  6536. };
  6537. const toggle$2 = (component, toggleConfig, toggleState) => {
  6538. set$2(component, toggleConfig, toggleState, !toggleState.get());
  6539. };
  6540. const on = (component, toggleConfig, toggleState) => {
  6541. set$2(component, toggleConfig, toggleState, true);
  6542. };
  6543. const off = (component, toggleConfig, toggleState) => {
  6544. set$2(component, toggleConfig, toggleState, false);
  6545. };
  6546. const isOn = (component, toggleConfig, toggleState) => toggleState.get();
  6547. const onLoad = (component, toggleConfig, toggleState) => {
  6548. set$2(component, toggleConfig, toggleState, toggleConfig.selected);
  6549. };
  6550. var ToggleApis = /*#__PURE__*/Object.freeze({
  6551. __proto__: null,
  6552. onLoad: onLoad,
  6553. toggle: toggle$2,
  6554. isOn: isOn,
  6555. on: on,
  6556. off: off,
  6557. set: set$2
  6558. });
  6559. const exhibit$3 = () => nu$7({});
  6560. const events$b = (toggleConfig, toggleState) => {
  6561. const execute = executeEvent(toggleConfig, toggleState, toggle$2);
  6562. const load = loadEvent(toggleConfig, toggleState, onLoad);
  6563. return derive$2(flatten([
  6564. toggleConfig.toggleOnExecute ? [execute] : [],
  6565. [load]
  6566. ]));
  6567. };
  6568. var ActiveToggle = /*#__PURE__*/Object.freeze({
  6569. __proto__: null,
  6570. exhibit: exhibit$3,
  6571. events: events$b
  6572. });
  6573. const updatePressed = (component, ariaInfo, status) => {
  6574. set$9(component.element, 'aria-pressed', status);
  6575. if (ariaInfo.syncWithExpanded) {
  6576. updateExpanded(component, ariaInfo, status);
  6577. }
  6578. };
  6579. const updateSelected = (component, ariaInfo, status) => {
  6580. set$9(component.element, 'aria-selected', status);
  6581. };
  6582. const updateChecked = (component, ariaInfo, status) => {
  6583. set$9(component.element, 'aria-checked', status);
  6584. };
  6585. const updateExpanded = (component, ariaInfo, status) => {
  6586. set$9(component.element, 'aria-expanded', status);
  6587. };
  6588. var ToggleSchema = [
  6589. defaulted('selected', false),
  6590. option$3('toggleClass'),
  6591. defaulted('toggleOnExecute', true),
  6592. onHandler('onToggled'),
  6593. defaultedOf('aria', { mode: 'none' }, choose$1('mode', {
  6594. pressed: [
  6595. defaulted('syncWithExpanded', false),
  6596. output$1('update', updatePressed)
  6597. ],
  6598. checked: [output$1('update', updateChecked)],
  6599. expanded: [output$1('update', updateExpanded)],
  6600. selected: [output$1('update', updateSelected)],
  6601. none: [output$1('update', noop)]
  6602. }))
  6603. ];
  6604. const Toggling = create$4({
  6605. fields: ToggleSchema,
  6606. name: 'toggling',
  6607. active: ActiveToggle,
  6608. apis: ToggleApis,
  6609. state: SetupBehaviourCellState(false)
  6610. });
  6611. const pointerEvents = () => {
  6612. const onClick = (component, simulatedEvent) => {
  6613. simulatedEvent.stop();
  6614. emitExecute(component);
  6615. };
  6616. return [
  6617. run$1(click(), onClick),
  6618. run$1(tap(), onClick),
  6619. cutter(touchstart()),
  6620. cutter(mousedown())
  6621. ];
  6622. };
  6623. const events$a = optAction => {
  6624. const executeHandler = action => runOnExecute$1((component, simulatedEvent) => {
  6625. action(component);
  6626. simulatedEvent.stop();
  6627. });
  6628. return derive$2(flatten([
  6629. optAction.map(executeHandler).toArray(),
  6630. pointerEvents()
  6631. ]));
  6632. };
  6633. const hoverEvent = 'alloy.item-hover';
  6634. const focusEvent = 'alloy.item-focus';
  6635. const toggledEvent = 'alloy.item-toggled';
  6636. const onHover = item => {
  6637. if (search(item.element).isNone() || Focusing.isFocused(item)) {
  6638. if (!Focusing.isFocused(item)) {
  6639. Focusing.focus(item);
  6640. }
  6641. emitWith(item, hoverEvent, { item });
  6642. }
  6643. };
  6644. const onFocus$1 = item => {
  6645. emitWith(item, focusEvent, { item });
  6646. };
  6647. const onToggled = (item, state) => {
  6648. emitWith(item, toggledEvent, {
  6649. item,
  6650. state
  6651. });
  6652. };
  6653. const hover = constant$1(hoverEvent);
  6654. const focus$1 = constant$1(focusEvent);
  6655. const toggled = constant$1(toggledEvent);
  6656. const getItemRole = detail => detail.toggling.map(toggling => toggling.exclusive ? 'menuitemradio' : 'menuitemcheckbox').getOr('menuitem');
  6657. const getTogglingSpec = tConfig => ({
  6658. aria: { mode: 'checked' },
  6659. ...filter$1(tConfig, (_value, name) => name !== 'exclusive'),
  6660. onToggled: (component, state) => {
  6661. if (isFunction(tConfig.onToggled)) {
  6662. tConfig.onToggled(component, state);
  6663. }
  6664. onToggled(component, state);
  6665. }
  6666. });
  6667. const builder$2 = detail => ({
  6668. dom: detail.dom,
  6669. domModification: {
  6670. ...detail.domModification,
  6671. attributes: {
  6672. 'role': getItemRole(detail),
  6673. ...detail.domModification.attributes,
  6674. 'aria-haspopup': detail.hasSubmenu,
  6675. ...detail.hasSubmenu ? { 'aria-expanded': false } : {}
  6676. }
  6677. },
  6678. behaviours: SketchBehaviours.augment(detail.itemBehaviours, [
  6679. detail.toggling.fold(Toggling.revoke, tConfig => Toggling.config(getTogglingSpec(tConfig))),
  6680. Focusing.config({
  6681. ignore: detail.ignoreFocus,
  6682. stopMousedown: detail.ignoreFocus,
  6683. onFocus: component => {
  6684. onFocus$1(component);
  6685. }
  6686. }),
  6687. Keying.config({ mode: 'execution' }),
  6688. Representing.config({
  6689. store: {
  6690. mode: 'memory',
  6691. initialValue: detail.data
  6692. }
  6693. }),
  6694. config('item-type-events', [
  6695. ...pointerEvents(),
  6696. run$1(mouseover(), onHover),
  6697. run$1(focusItem(), Focusing.focus)
  6698. ])
  6699. ]),
  6700. components: detail.components,
  6701. eventOrder: detail.eventOrder
  6702. });
  6703. const schema$p = [
  6704. required$1('data'),
  6705. required$1('components'),
  6706. required$1('dom'),
  6707. defaulted('hasSubmenu', false),
  6708. option$3('toggling'),
  6709. SketchBehaviours.field('itemBehaviours', [
  6710. Toggling,
  6711. Focusing,
  6712. Keying,
  6713. Representing
  6714. ]),
  6715. defaulted('ignoreFocus', false),
  6716. defaulted('domModification', {}),
  6717. output$1('builder', builder$2),
  6718. defaulted('eventOrder', {})
  6719. ];
  6720. const builder$1 = detail => ({
  6721. dom: detail.dom,
  6722. components: detail.components,
  6723. events: derive$2([stopper(focusItem())])
  6724. });
  6725. const schema$o = [
  6726. required$1('dom'),
  6727. required$1('components'),
  6728. output$1('builder', builder$1)
  6729. ];
  6730. const owner$2 = constant$1('item-widget');
  6731. const parts$h = constant$1([required({
  6732. name: 'widget',
  6733. overrides: detail => {
  6734. return {
  6735. behaviours: derive$1([Representing.config({
  6736. store: {
  6737. mode: 'manual',
  6738. getValue: _component => {
  6739. return detail.data;
  6740. },
  6741. setValue: noop
  6742. }
  6743. })])
  6744. };
  6745. }
  6746. })]);
  6747. const builder = detail => {
  6748. const subs = substitutes(owner$2(), detail, parts$h());
  6749. const components = components$1(owner$2(), detail, subs.internals());
  6750. const focusWidget = component => getPart(component, detail, 'widget').map(widget => {
  6751. Keying.focusIn(widget);
  6752. return widget;
  6753. });
  6754. const onHorizontalArrow = (component, simulatedEvent) => inside(simulatedEvent.event.target) ? Optional.none() : (() => {
  6755. if (detail.autofocus) {
  6756. simulatedEvent.setSource(component.element);
  6757. return Optional.none();
  6758. } else {
  6759. return Optional.none();
  6760. }
  6761. })();
  6762. return {
  6763. dom: detail.dom,
  6764. components,
  6765. domModification: detail.domModification,
  6766. events: derive$2([
  6767. runOnExecute$1((component, simulatedEvent) => {
  6768. focusWidget(component).each(_widget => {
  6769. simulatedEvent.stop();
  6770. });
  6771. }),
  6772. run$1(mouseover(), onHover),
  6773. run$1(focusItem(), (component, _simulatedEvent) => {
  6774. if (detail.autofocus) {
  6775. focusWidget(component);
  6776. } else {
  6777. Focusing.focus(component);
  6778. }
  6779. })
  6780. ]),
  6781. behaviours: SketchBehaviours.augment(detail.widgetBehaviours, [
  6782. Representing.config({
  6783. store: {
  6784. mode: 'memory',
  6785. initialValue: detail.data
  6786. }
  6787. }),
  6788. Focusing.config({
  6789. ignore: detail.ignoreFocus,
  6790. onFocus: component => {
  6791. onFocus$1(component);
  6792. }
  6793. }),
  6794. Keying.config({
  6795. mode: 'special',
  6796. focusIn: detail.autofocus ? component => {
  6797. focusWidget(component);
  6798. } : revoke(),
  6799. onLeft: onHorizontalArrow,
  6800. onRight: onHorizontalArrow,
  6801. onEscape: (component, simulatedEvent) => {
  6802. if (!Focusing.isFocused(component) && !detail.autofocus) {
  6803. Focusing.focus(component);
  6804. return Optional.some(true);
  6805. } else if (detail.autofocus) {
  6806. simulatedEvent.setSource(component.element);
  6807. return Optional.none();
  6808. } else {
  6809. return Optional.none();
  6810. }
  6811. }
  6812. })
  6813. ])
  6814. };
  6815. };
  6816. const schema$n = [
  6817. required$1('uid'),
  6818. required$1('data'),
  6819. required$1('components'),
  6820. required$1('dom'),
  6821. defaulted('autofocus', false),
  6822. defaulted('ignoreFocus', false),
  6823. SketchBehaviours.field('widgetBehaviours', [
  6824. Representing,
  6825. Focusing,
  6826. Keying
  6827. ]),
  6828. defaulted('domModification', {}),
  6829. defaultUidsSchema(parts$h()),
  6830. output$1('builder', builder)
  6831. ];
  6832. const itemSchema$2 = choose$1('type', {
  6833. widget: schema$n,
  6834. item: schema$p,
  6835. separator: schema$o
  6836. });
  6837. const configureGrid = (detail, movementInfo) => ({
  6838. mode: 'flatgrid',
  6839. selector: '.' + detail.markers.item,
  6840. initSize: {
  6841. numColumns: movementInfo.initSize.numColumns,
  6842. numRows: movementInfo.initSize.numRows
  6843. },
  6844. focusManager: detail.focusManager
  6845. });
  6846. const configureMatrix = (detail, movementInfo) => ({
  6847. mode: 'matrix',
  6848. selectors: {
  6849. row: movementInfo.rowSelector,
  6850. cell: '.' + detail.markers.item
  6851. },
  6852. previousSelector: movementInfo.previousSelector,
  6853. focusManager: detail.focusManager
  6854. });
  6855. const configureMenu = (detail, movementInfo) => ({
  6856. mode: 'menu',
  6857. selector: '.' + detail.markers.item,
  6858. moveOnTab: movementInfo.moveOnTab,
  6859. focusManager: detail.focusManager
  6860. });
  6861. const parts$g = constant$1([group({
  6862. factory: {
  6863. sketch: spec => {
  6864. const itemInfo = asRawOrDie$1('menu.spec item', itemSchema$2, spec);
  6865. return itemInfo.builder(itemInfo);
  6866. }
  6867. },
  6868. name: 'items',
  6869. unit: 'item',
  6870. defaults: (detail, u) => {
  6871. return has$2(u, 'uid') ? u : {
  6872. ...u,
  6873. uid: generate$5('item')
  6874. };
  6875. },
  6876. overrides: (detail, u) => {
  6877. return {
  6878. type: u.type,
  6879. ignoreFocus: detail.fakeFocus,
  6880. domModification: { classes: [detail.markers.item] }
  6881. };
  6882. }
  6883. })]);
  6884. const schema$m = constant$1([
  6885. required$1('value'),
  6886. required$1('items'),
  6887. required$1('dom'),
  6888. required$1('components'),
  6889. defaulted('eventOrder', {}),
  6890. field('menuBehaviours', [
  6891. Highlighting,
  6892. Representing,
  6893. Composing,
  6894. Keying
  6895. ]),
  6896. defaultedOf('movement', {
  6897. mode: 'menu',
  6898. moveOnTab: true
  6899. }, choose$1('mode', {
  6900. grid: [
  6901. initSize(),
  6902. output$1('config', configureGrid)
  6903. ],
  6904. matrix: [
  6905. output$1('config', configureMatrix),
  6906. required$1('rowSelector'),
  6907. defaulted('previousSelector', Optional.none)
  6908. ],
  6909. menu: [
  6910. defaulted('moveOnTab', true),
  6911. output$1('config', configureMenu)
  6912. ]
  6913. })),
  6914. itemMarkers(),
  6915. defaulted('fakeFocus', false),
  6916. defaulted('focusManager', dom$2()),
  6917. onHandler('onHighlight'),
  6918. onHandler('onDehighlight')
  6919. ]);
  6920. const focus = constant$1('alloy.menu-focus');
  6921. const deselectOtherRadioItems = (menu, item) => {
  6922. const checkedRadioItems = descendants(menu.element, '[role="menuitemradio"][aria-checked="true"]');
  6923. each$1(checkedRadioItems, ele => {
  6924. if (!eq(ele, item.element)) {
  6925. menu.getSystem().getByDom(ele).each(c => {
  6926. Toggling.off(c);
  6927. });
  6928. }
  6929. });
  6930. };
  6931. const make$7 = (detail, components, _spec, _externals) => ({
  6932. uid: detail.uid,
  6933. dom: detail.dom,
  6934. markers: detail.markers,
  6935. behaviours: augment(detail.menuBehaviours, [
  6936. Highlighting.config({
  6937. highlightClass: detail.markers.selectedItem,
  6938. itemClass: detail.markers.item,
  6939. onHighlight: detail.onHighlight,
  6940. onDehighlight: detail.onDehighlight
  6941. }),
  6942. Representing.config({
  6943. store: {
  6944. mode: 'memory',
  6945. initialValue: detail.value
  6946. }
  6947. }),
  6948. Composing.config({ find: Optional.some }),
  6949. Keying.config(detail.movement.config(detail, detail.movement))
  6950. ]),
  6951. events: derive$2([
  6952. run$1(focus$1(), (menu, simulatedEvent) => {
  6953. const event = simulatedEvent.event;
  6954. menu.getSystem().getByDom(event.target).each(item => {
  6955. Highlighting.highlight(menu, item);
  6956. simulatedEvent.stop();
  6957. emitWith(menu, focus(), {
  6958. menu,
  6959. item
  6960. });
  6961. });
  6962. }),
  6963. run$1(hover(), (menu, simulatedEvent) => {
  6964. const item = simulatedEvent.event.item;
  6965. Highlighting.highlight(menu, item);
  6966. }),
  6967. run$1(toggled(), (menu, simulatedEvent) => {
  6968. const {item, state} = simulatedEvent.event;
  6969. if (state && get$f(item.element, 'role') === 'menuitemradio') {
  6970. deselectOtherRadioItems(menu, item);
  6971. }
  6972. })
  6973. ]),
  6974. components,
  6975. eventOrder: detail.eventOrder,
  6976. domModification: { attributes: { role: 'menu' } }
  6977. });
  6978. const Menu = composite({
  6979. name: 'Menu',
  6980. configFields: schema$m(),
  6981. partFields: parts$g(),
  6982. factory: make$7
  6983. });
  6984. const transpose$1 = obj => tupleMap(obj, (v, k) => ({
  6985. k: v,
  6986. v: k
  6987. }));
  6988. const trace = (items, byItem, byMenu, finish) => get$g(byMenu, finish).bind(triggerItem => get$g(items, triggerItem).bind(triggerMenu => {
  6989. const rest = trace(items, byItem, byMenu, triggerMenu);
  6990. return Optional.some([triggerMenu].concat(rest));
  6991. })).getOr([]);
  6992. const generate$2 = (menus, expansions) => {
  6993. const items = {};
  6994. each(menus, (menuItems, menu) => {
  6995. each$1(menuItems, item => {
  6996. items[item] = menu;
  6997. });
  6998. });
  6999. const byItem = expansions;
  7000. const byMenu = transpose$1(expansions);
  7001. const menuPaths = map$1(byMenu, (_triggerItem, submenu) => [submenu].concat(trace(items, byItem, byMenu, submenu)));
  7002. return map$1(items, menu => get$g(menuPaths, menu).getOr([menu]));
  7003. };
  7004. const init$c = () => {
  7005. const expansions = Cell({});
  7006. const menus = Cell({});
  7007. const paths = Cell({});
  7008. const primary = value$2();
  7009. const directory = Cell({});
  7010. const clear = () => {
  7011. expansions.set({});
  7012. menus.set({});
  7013. paths.set({});
  7014. primary.clear();
  7015. };
  7016. const isClear = () => primary.get().isNone();
  7017. const setMenuBuilt = (menuName, built) => {
  7018. menus.set({
  7019. ...menus.get(),
  7020. [menuName]: {
  7021. type: 'prepared',
  7022. menu: built
  7023. }
  7024. });
  7025. };
  7026. const setContents = (sPrimary, sMenus, sExpansions, dir) => {
  7027. primary.set(sPrimary);
  7028. expansions.set(sExpansions);
  7029. menus.set(sMenus);
  7030. directory.set(dir);
  7031. const sPaths = generate$2(dir, sExpansions);
  7032. paths.set(sPaths);
  7033. };
  7034. const getTriggeringItem = menuValue => find$4(expansions.get(), (v, _k) => v === menuValue);
  7035. const getTriggerData = (menuValue, getItemByValue, path) => getPreparedMenu(menuValue).bind(menu => getTriggeringItem(menuValue).bind(triggeringItemValue => getItemByValue(triggeringItemValue).map(triggeredItem => ({
  7036. triggeredMenu: menu,
  7037. triggeringItem: triggeredItem,
  7038. triggeringPath: path
  7039. }))));
  7040. const getTriggeringPath = (itemValue, getItemByValue) => {
  7041. const extraPath = filter$2(lookupItem(itemValue).toArray(), menuValue => getPreparedMenu(menuValue).isSome());
  7042. return get$g(paths.get(), itemValue).bind(path => {
  7043. const revPath = reverse(extraPath.concat(path));
  7044. const triggers = bind$3(revPath, (menuValue, menuIndex) => getTriggerData(menuValue, getItemByValue, revPath.slice(0, menuIndex + 1)).fold(() => is$1(primary.get(), menuValue) ? [] : [Optional.none()], data => [Optional.some(data)]));
  7045. return sequence(triggers);
  7046. });
  7047. };
  7048. const expand = itemValue => get$g(expansions.get(), itemValue).map(menu => {
  7049. const current = get$g(paths.get(), itemValue).getOr([]);
  7050. return [menu].concat(current);
  7051. });
  7052. const collapse = itemValue => get$g(paths.get(), itemValue).bind(path => path.length > 1 ? Optional.some(path.slice(1)) : Optional.none());
  7053. const refresh = itemValue => get$g(paths.get(), itemValue);
  7054. const getPreparedMenu = menuValue => lookupMenu(menuValue).bind(extractPreparedMenu);
  7055. const lookupMenu = menuValue => get$g(menus.get(), menuValue);
  7056. const lookupItem = itemValue => get$g(expansions.get(), itemValue);
  7057. const otherMenus = path => {
  7058. const menuValues = directory.get();
  7059. return difference(keys(menuValues), path);
  7060. };
  7061. const getPrimary = () => primary.get().bind(getPreparedMenu);
  7062. const getMenus = () => menus.get();
  7063. return {
  7064. setMenuBuilt,
  7065. setContents,
  7066. expand,
  7067. refresh,
  7068. collapse,
  7069. lookupMenu,
  7070. lookupItem,
  7071. otherMenus,
  7072. getPrimary,
  7073. getMenus,
  7074. clear,
  7075. isClear,
  7076. getTriggeringPath
  7077. };
  7078. };
  7079. const extractPreparedMenu = prep => prep.type === 'prepared' ? Optional.some(prep.menu) : Optional.none();
  7080. const LayeredState = {
  7081. init: init$c,
  7082. extractPreparedMenu
  7083. };
  7084. const onMenuItemHighlightedEvent = generate$6('tiered-menu-item-highlight');
  7085. const onMenuItemDehighlightedEvent = generate$6('tiered-menu-item-dehighlight');
  7086. var HighlightOnOpen;
  7087. (function (HighlightOnOpen) {
  7088. HighlightOnOpen[HighlightOnOpen['HighlightMenuAndItem'] = 0] = 'HighlightMenuAndItem';
  7089. HighlightOnOpen[HighlightOnOpen['HighlightJustMenu'] = 1] = 'HighlightJustMenu';
  7090. HighlightOnOpen[HighlightOnOpen['HighlightNone'] = 2] = 'HighlightNone';
  7091. }(HighlightOnOpen || (HighlightOnOpen = {})));
  7092. const make$6 = (detail, _rawUiSpec) => {
  7093. const submenuParentItems = value$2();
  7094. const buildMenus = (container, primaryName, menus) => map$1(menus, (spec, name) => {
  7095. const makeSketch = () => Menu.sketch({
  7096. ...spec,
  7097. value: name,
  7098. markers: detail.markers,
  7099. fakeFocus: detail.fakeFocus,
  7100. onHighlight: (menuComp, itemComp) => {
  7101. const highlightData = {
  7102. menuComp,
  7103. itemComp
  7104. };
  7105. emitWith(menuComp, onMenuItemHighlightedEvent, highlightData);
  7106. },
  7107. onDehighlight: (menuComp, itemComp) => {
  7108. const dehighlightData = {
  7109. menuComp,
  7110. itemComp
  7111. };
  7112. emitWith(menuComp, onMenuItemDehighlightedEvent, dehighlightData);
  7113. },
  7114. focusManager: detail.fakeFocus ? highlights() : dom$2()
  7115. });
  7116. return name === primaryName ? {
  7117. type: 'prepared',
  7118. menu: container.getSystem().build(makeSketch())
  7119. } : {
  7120. type: 'notbuilt',
  7121. nbMenu: makeSketch
  7122. };
  7123. });
  7124. const layeredState = LayeredState.init();
  7125. const setup = container => {
  7126. const componentMap = buildMenus(container, detail.data.primary, detail.data.menus);
  7127. const directory = toDirectory();
  7128. layeredState.setContents(detail.data.primary, componentMap, detail.data.expansions, directory);
  7129. return layeredState.getPrimary();
  7130. };
  7131. const getItemValue = item => Representing.getValue(item).value;
  7132. const getItemByValue = (_container, menus, itemValue) => findMap(menus, menu => {
  7133. if (!menu.getSystem().isConnected()) {
  7134. return Optional.none();
  7135. }
  7136. const candidates = Highlighting.getCandidates(menu);
  7137. return find$5(candidates, c => getItemValue(c) === itemValue);
  7138. });
  7139. const toDirectory = _container => map$1(detail.data.menus, (data, _menuName) => bind$3(data.items, item => item.type === 'separator' ? [] : [item.data.value]));
  7140. const setActiveMenu = Highlighting.highlight;
  7141. const setActiveMenuAndItem = (container, menu) => {
  7142. setActiveMenu(container, menu);
  7143. Highlighting.getHighlighted(menu).orThunk(() => Highlighting.getFirst(menu)).each(item => {
  7144. if (detail.fakeFocus) {
  7145. Highlighting.highlight(menu, item);
  7146. } else {
  7147. dispatch(container, item.element, focusItem());
  7148. }
  7149. });
  7150. };
  7151. const getMenus = (state, menuValues) => cat(map$2(menuValues, mv => state.lookupMenu(mv).bind(prep => prep.type === 'prepared' ? Optional.some(prep.menu) : Optional.none())));
  7152. const closeOthers = (container, state, path) => {
  7153. const others = getMenus(state, state.otherMenus(path));
  7154. each$1(others, o => {
  7155. remove$1(o.element, [detail.markers.backgroundMenu]);
  7156. if (!detail.stayInDom) {
  7157. Replacing.remove(container, o);
  7158. }
  7159. });
  7160. };
  7161. const getSubmenuParents = container => submenuParentItems.get().getOrThunk(() => {
  7162. const r = {};
  7163. const items = descendants(container.element, `.${ detail.markers.item }`);
  7164. const parentItems = filter$2(items, i => get$f(i, 'aria-haspopup') === 'true');
  7165. each$1(parentItems, i => {
  7166. container.getSystem().getByDom(i).each(itemComp => {
  7167. const key = getItemValue(itemComp);
  7168. r[key] = itemComp;
  7169. });
  7170. });
  7171. submenuParentItems.set(r);
  7172. return r;
  7173. });
  7174. const updateAriaExpansions = (container, path) => {
  7175. const parentItems = getSubmenuParents(container);
  7176. each(parentItems, (v, k) => {
  7177. const expanded = contains$2(path, k);
  7178. set$9(v.element, 'aria-expanded', expanded);
  7179. });
  7180. };
  7181. const updateMenuPath = (container, state, path) => Optional.from(path[0]).bind(latestMenuName => state.lookupMenu(latestMenuName).bind(menuPrep => {
  7182. if (menuPrep.type === 'notbuilt') {
  7183. return Optional.none();
  7184. } else {
  7185. const activeMenu = menuPrep.menu;
  7186. const rest = getMenus(state, path.slice(1));
  7187. each$1(rest, r => {
  7188. add$2(r.element, detail.markers.backgroundMenu);
  7189. });
  7190. if (!inBody(activeMenu.element)) {
  7191. Replacing.append(container, premade(activeMenu));
  7192. }
  7193. remove$1(activeMenu.element, [detail.markers.backgroundMenu]);
  7194. setActiveMenuAndItem(container, activeMenu);
  7195. closeOthers(container, state, path);
  7196. return Optional.some(activeMenu);
  7197. }
  7198. }));
  7199. let ExpandHighlightDecision;
  7200. (function (ExpandHighlightDecision) {
  7201. ExpandHighlightDecision[ExpandHighlightDecision['HighlightSubmenu'] = 0] = 'HighlightSubmenu';
  7202. ExpandHighlightDecision[ExpandHighlightDecision['HighlightParent'] = 1] = 'HighlightParent';
  7203. }(ExpandHighlightDecision || (ExpandHighlightDecision = {})));
  7204. const buildIfRequired = (container, menuName, menuPrep) => {
  7205. if (menuPrep.type === 'notbuilt') {
  7206. const menu = container.getSystem().build(menuPrep.nbMenu());
  7207. layeredState.setMenuBuilt(menuName, menu);
  7208. return menu;
  7209. } else {
  7210. return menuPrep.menu;
  7211. }
  7212. };
  7213. const expandRight = (container, item, decision = ExpandHighlightDecision.HighlightSubmenu) => {
  7214. if (item.hasConfigured(Disabling) && Disabling.isDisabled(item)) {
  7215. return Optional.some(item);
  7216. } else {
  7217. const value = getItemValue(item);
  7218. return layeredState.expand(value).bind(path => {
  7219. updateAriaExpansions(container, path);
  7220. return Optional.from(path[0]).bind(menuName => layeredState.lookupMenu(menuName).bind(activeMenuPrep => {
  7221. const activeMenu = buildIfRequired(container, menuName, activeMenuPrep);
  7222. if (!inBody(activeMenu.element)) {
  7223. Replacing.append(container, premade(activeMenu));
  7224. }
  7225. detail.onOpenSubmenu(container, item, activeMenu, reverse(path));
  7226. if (decision === ExpandHighlightDecision.HighlightSubmenu) {
  7227. Highlighting.highlightFirst(activeMenu);
  7228. return updateMenuPath(container, layeredState, path);
  7229. } else {
  7230. Highlighting.dehighlightAll(activeMenu);
  7231. return Optional.some(item);
  7232. }
  7233. }));
  7234. });
  7235. }
  7236. };
  7237. const collapseLeft = (container, item) => {
  7238. const value = getItemValue(item);
  7239. return layeredState.collapse(value).bind(path => {
  7240. updateAriaExpansions(container, path);
  7241. return updateMenuPath(container, layeredState, path).map(activeMenu => {
  7242. detail.onCollapseMenu(container, item, activeMenu);
  7243. return activeMenu;
  7244. });
  7245. });
  7246. };
  7247. const updateView = (container, item) => {
  7248. const value = getItemValue(item);
  7249. return layeredState.refresh(value).bind(path => {
  7250. updateAriaExpansions(container, path);
  7251. return updateMenuPath(container, layeredState, path);
  7252. });
  7253. };
  7254. const onRight = (container, item) => inside(item.element) ? Optional.none() : expandRight(container, item, ExpandHighlightDecision.HighlightSubmenu);
  7255. const onLeft = (container, item) => inside(item.element) ? Optional.none() : collapseLeft(container, item);
  7256. const onEscape = (container, item) => collapseLeft(container, item).orThunk(() => detail.onEscape(container, item).map(() => container));
  7257. const keyOnItem = f => (container, simulatedEvent) => {
  7258. return closest$1(simulatedEvent.getSource(), `.${ detail.markers.item }`).bind(target => container.getSystem().getByDom(target).toOptional().bind(item => f(container, item).map(always)));
  7259. };
  7260. const events = derive$2([
  7261. run$1(focus(), (tmenu, simulatedEvent) => {
  7262. const item = simulatedEvent.event.item;
  7263. layeredState.lookupItem(getItemValue(item)).each(() => {
  7264. const menu = simulatedEvent.event.menu;
  7265. Highlighting.highlight(tmenu, menu);
  7266. const value = getItemValue(simulatedEvent.event.item);
  7267. layeredState.refresh(value).each(path => closeOthers(tmenu, layeredState, path));
  7268. });
  7269. }),
  7270. runOnExecute$1((component, simulatedEvent) => {
  7271. const target = simulatedEvent.event.target;
  7272. component.getSystem().getByDom(target).each(item => {
  7273. const itemValue = getItemValue(item);
  7274. if (itemValue.indexOf('collapse-item') === 0) {
  7275. collapseLeft(component, item);
  7276. }
  7277. expandRight(component, item, ExpandHighlightDecision.HighlightSubmenu).fold(() => {
  7278. detail.onExecute(component, item);
  7279. }, noop);
  7280. });
  7281. }),
  7282. runOnAttached((container, _simulatedEvent) => {
  7283. setup(container).each(primary => {
  7284. Replacing.append(container, premade(primary));
  7285. detail.onOpenMenu(container, primary);
  7286. if (detail.highlightOnOpen === HighlightOnOpen.HighlightMenuAndItem) {
  7287. setActiveMenuAndItem(container, primary);
  7288. } else if (detail.highlightOnOpen === HighlightOnOpen.HighlightJustMenu) {
  7289. setActiveMenu(container, primary);
  7290. }
  7291. });
  7292. }),
  7293. run$1(onMenuItemHighlightedEvent, (tmenuComp, se) => {
  7294. detail.onHighlightItem(tmenuComp, se.event.menuComp, se.event.itemComp);
  7295. }),
  7296. run$1(onMenuItemDehighlightedEvent, (tmenuComp, se) => {
  7297. detail.onDehighlightItem(tmenuComp, se.event.menuComp, se.event.itemComp);
  7298. }),
  7299. ...detail.navigateOnHover ? [run$1(hover(), (tmenu, simulatedEvent) => {
  7300. const item = simulatedEvent.event.item;
  7301. updateView(tmenu, item);
  7302. expandRight(tmenu, item, ExpandHighlightDecision.HighlightParent);
  7303. detail.onHover(tmenu, item);
  7304. })] : []
  7305. ]);
  7306. const getActiveItem = container => Highlighting.getHighlighted(container).bind(Highlighting.getHighlighted);
  7307. const collapseMenuApi = container => {
  7308. getActiveItem(container).each(currentItem => {
  7309. collapseLeft(container, currentItem);
  7310. });
  7311. };
  7312. const highlightPrimary = container => {
  7313. layeredState.getPrimary().each(primary => {
  7314. setActiveMenuAndItem(container, primary);
  7315. });
  7316. };
  7317. const extractMenuFromContainer = container => Optional.from(container.components()[0]).filter(comp => get$f(comp.element, 'role') === 'menu');
  7318. const repositionMenus = container => {
  7319. const maybeActivePrimary = layeredState.getPrimary().bind(primary => getActiveItem(container).bind(currentItem => {
  7320. const itemValue = getItemValue(currentItem);
  7321. const allMenus = values(layeredState.getMenus());
  7322. const preparedMenus = cat(map$2(allMenus, LayeredState.extractPreparedMenu));
  7323. return layeredState.getTriggeringPath(itemValue, v => getItemByValue(container, preparedMenus, v));
  7324. }).map(triggeringPath => ({
  7325. primary,
  7326. triggeringPath
  7327. })));
  7328. maybeActivePrimary.fold(() => {
  7329. extractMenuFromContainer(container).each(primaryMenu => {
  7330. detail.onRepositionMenu(container, primaryMenu, []);
  7331. });
  7332. }, ({primary, triggeringPath}) => {
  7333. detail.onRepositionMenu(container, primary, triggeringPath);
  7334. });
  7335. };
  7336. const apis = {
  7337. collapseMenu: collapseMenuApi,
  7338. highlightPrimary,
  7339. repositionMenus
  7340. };
  7341. return {
  7342. uid: detail.uid,
  7343. dom: detail.dom,
  7344. markers: detail.markers,
  7345. behaviours: augment(detail.tmenuBehaviours, [
  7346. Keying.config({
  7347. mode: 'special',
  7348. onRight: keyOnItem(onRight),
  7349. onLeft: keyOnItem(onLeft),
  7350. onEscape: keyOnItem(onEscape),
  7351. focusIn: (container, _keyInfo) => {
  7352. layeredState.getPrimary().each(primary => {
  7353. dispatch(container, primary.element, focusItem());
  7354. });
  7355. }
  7356. }),
  7357. Highlighting.config({
  7358. highlightClass: detail.markers.selectedMenu,
  7359. itemClass: detail.markers.menu
  7360. }),
  7361. Composing.config({
  7362. find: container => {
  7363. return Highlighting.getHighlighted(container);
  7364. }
  7365. }),
  7366. Replacing.config({})
  7367. ]),
  7368. eventOrder: detail.eventOrder,
  7369. apis,
  7370. events
  7371. };
  7372. };
  7373. const collapseItem$1 = constant$1('collapse-item');
  7374. const tieredData = (primary, menus, expansions) => ({
  7375. primary,
  7376. menus,
  7377. expansions
  7378. });
  7379. const singleData = (name, menu) => ({
  7380. primary: name,
  7381. menus: wrap$1(name, menu),
  7382. expansions: {}
  7383. });
  7384. const collapseItem = text => ({
  7385. value: generate$6(collapseItem$1()),
  7386. meta: { text }
  7387. });
  7388. const tieredMenu = single({
  7389. name: 'TieredMenu',
  7390. configFields: [
  7391. onStrictKeyboardHandler('onExecute'),
  7392. onStrictKeyboardHandler('onEscape'),
  7393. onStrictHandler('onOpenMenu'),
  7394. onStrictHandler('onOpenSubmenu'),
  7395. onHandler('onRepositionMenu'),
  7396. onHandler('onCollapseMenu'),
  7397. defaulted('highlightOnOpen', HighlightOnOpen.HighlightMenuAndItem),
  7398. requiredObjOf('data', [
  7399. required$1('primary'),
  7400. required$1('menus'),
  7401. required$1('expansions')
  7402. ]),
  7403. defaulted('fakeFocus', false),
  7404. onHandler('onHighlightItem'),
  7405. onHandler('onDehighlightItem'),
  7406. onHandler('onHover'),
  7407. tieredMenuMarkers(),
  7408. required$1('dom'),
  7409. defaulted('navigateOnHover', true),
  7410. defaulted('stayInDom', false),
  7411. field('tmenuBehaviours', [
  7412. Keying,
  7413. Highlighting,
  7414. Composing,
  7415. Replacing
  7416. ]),
  7417. defaulted('eventOrder', {})
  7418. ],
  7419. apis: {
  7420. collapseMenu: (apis, tmenu) => {
  7421. apis.collapseMenu(tmenu);
  7422. },
  7423. highlightPrimary: (apis, tmenu) => {
  7424. apis.highlightPrimary(tmenu);
  7425. },
  7426. repositionMenus: (apis, tmenu) => {
  7427. apis.repositionMenus(tmenu);
  7428. }
  7429. },
  7430. factory: make$6,
  7431. extraApis: {
  7432. tieredData,
  7433. singleData,
  7434. collapseItem
  7435. }
  7436. });
  7437. const makeMenu = (detail, menuSandbox, placementSpec, menuSpec, getBounds) => {
  7438. const lazySink = () => detail.lazySink(menuSandbox);
  7439. const layouts = menuSpec.type === 'horizontal' ? {
  7440. layouts: {
  7441. onLtr: () => belowOrAbove(),
  7442. onRtl: () => belowOrAboveRtl()
  7443. }
  7444. } : {};
  7445. const isFirstTierSubmenu = triggeringPaths => triggeringPaths.length === 2;
  7446. const getSubmenuLayouts = triggeringPaths => isFirstTierSubmenu(triggeringPaths) ? layouts : {};
  7447. return tieredMenu.sketch({
  7448. dom: { tag: 'div' },
  7449. data: menuSpec.data,
  7450. markers: menuSpec.menu.markers,
  7451. highlightOnOpen: menuSpec.menu.highlightOnOpen,
  7452. fakeFocus: menuSpec.menu.fakeFocus,
  7453. onEscape: () => {
  7454. Sandboxing.close(menuSandbox);
  7455. detail.onEscape.map(handler => handler(menuSandbox));
  7456. return Optional.some(true);
  7457. },
  7458. onExecute: () => {
  7459. return Optional.some(true);
  7460. },
  7461. onOpenMenu: (tmenu, menu) => {
  7462. Positioning.positionWithinBounds(lazySink().getOrDie(), menu, placementSpec, getBounds());
  7463. },
  7464. onOpenSubmenu: (tmenu, item, submenu, triggeringPaths) => {
  7465. const sink = lazySink().getOrDie();
  7466. Positioning.position(sink, submenu, {
  7467. anchor: {
  7468. type: 'submenu',
  7469. item,
  7470. ...getSubmenuLayouts(triggeringPaths)
  7471. }
  7472. });
  7473. },
  7474. onRepositionMenu: (tmenu, primaryMenu, submenuTriggers) => {
  7475. const sink = lazySink().getOrDie();
  7476. Positioning.positionWithinBounds(sink, primaryMenu, placementSpec, getBounds());
  7477. each$1(submenuTriggers, st => {
  7478. const submenuLayouts = getSubmenuLayouts(st.triggeringPath);
  7479. Positioning.position(sink, st.triggeredMenu, {
  7480. anchor: {
  7481. type: 'submenu',
  7482. item: st.triggeringItem,
  7483. ...submenuLayouts
  7484. }
  7485. });
  7486. });
  7487. }
  7488. });
  7489. };
  7490. const factory$o = (detail, spec) => {
  7491. const isPartOfRelated = (sandbox, queryElem) => {
  7492. const related = detail.getRelated(sandbox);
  7493. return related.exists(rel => isPartOf$1(rel, queryElem));
  7494. };
  7495. const setContent = (sandbox, thing) => {
  7496. Sandboxing.setContent(sandbox, thing);
  7497. };
  7498. const showAt = (sandbox, thing, placementSpec) => {
  7499. showWithin(sandbox, thing, placementSpec, Optional.none());
  7500. };
  7501. const showWithin = (sandbox, thing, placementSpec, boxElement) => {
  7502. showWithinBounds(sandbox, thing, placementSpec, () => boxElement.map(elem => box$1(elem)));
  7503. };
  7504. const showWithinBounds = (sandbox, thing, placementSpec, getBounds) => {
  7505. const sink = detail.lazySink(sandbox).getOrDie();
  7506. Sandboxing.openWhileCloaked(sandbox, thing, () => Positioning.positionWithinBounds(sink, sandbox, placementSpec, getBounds()));
  7507. Representing.setValue(sandbox, Optional.some({
  7508. mode: 'position',
  7509. config: placementSpec,
  7510. getBounds
  7511. }));
  7512. };
  7513. const showMenuAt = (sandbox, placementSpec, menuSpec) => {
  7514. showMenuWithinBounds(sandbox, placementSpec, menuSpec, Optional.none);
  7515. };
  7516. const showMenuWithinBounds = (sandbox, placementSpec, menuSpec, getBounds) => {
  7517. const menu = makeMenu(detail, sandbox, placementSpec, menuSpec, getBounds);
  7518. Sandboxing.open(sandbox, menu);
  7519. Representing.setValue(sandbox, Optional.some({
  7520. mode: 'menu',
  7521. menu
  7522. }));
  7523. };
  7524. const hide = sandbox => {
  7525. if (Sandboxing.isOpen(sandbox)) {
  7526. Representing.setValue(sandbox, Optional.none());
  7527. Sandboxing.close(sandbox);
  7528. }
  7529. };
  7530. const getContent = sandbox => Sandboxing.getState(sandbox);
  7531. const reposition = sandbox => {
  7532. if (Sandboxing.isOpen(sandbox)) {
  7533. Representing.getValue(sandbox).each(state => {
  7534. switch (state.mode) {
  7535. case 'menu':
  7536. Sandboxing.getState(sandbox).each(tieredMenu.repositionMenus);
  7537. break;
  7538. case 'position':
  7539. const sink = detail.lazySink(sandbox).getOrDie();
  7540. Positioning.positionWithinBounds(sink, sandbox, state.config, state.getBounds());
  7541. break;
  7542. }
  7543. });
  7544. }
  7545. };
  7546. const apis = {
  7547. setContent,
  7548. showAt,
  7549. showWithin,
  7550. showWithinBounds,
  7551. showMenuAt,
  7552. showMenuWithinBounds,
  7553. hide,
  7554. getContent,
  7555. reposition,
  7556. isOpen: Sandboxing.isOpen
  7557. };
  7558. return {
  7559. uid: detail.uid,
  7560. dom: detail.dom,
  7561. behaviours: augment(detail.inlineBehaviours, [
  7562. Sandboxing.config({
  7563. isPartOf: (sandbox, data, queryElem) => {
  7564. return isPartOf$1(data, queryElem) || isPartOfRelated(sandbox, queryElem);
  7565. },
  7566. getAttachPoint: sandbox => {
  7567. return detail.lazySink(sandbox).getOrDie();
  7568. },
  7569. onOpen: sandbox => {
  7570. detail.onShow(sandbox);
  7571. },
  7572. onClose: sandbox => {
  7573. detail.onHide(sandbox);
  7574. }
  7575. }),
  7576. Representing.config({
  7577. store: {
  7578. mode: 'memory',
  7579. initialValue: Optional.none()
  7580. }
  7581. }),
  7582. Receiving.config({
  7583. channels: {
  7584. ...receivingChannel$1({
  7585. isExtraPart: spec.isExtraPart,
  7586. ...detail.fireDismissalEventInstead.map(fe => ({ fireEventInstead: { event: fe.event } })).getOr({})
  7587. }),
  7588. ...receivingChannel({
  7589. ...detail.fireRepositionEventInstead.map(fe => ({ fireEventInstead: { event: fe.event } })).getOr({}),
  7590. doReposition: reposition
  7591. })
  7592. }
  7593. })
  7594. ]),
  7595. eventOrder: detail.eventOrder,
  7596. apis
  7597. };
  7598. };
  7599. const InlineView = single({
  7600. name: 'InlineView',
  7601. configFields: [
  7602. required$1('lazySink'),
  7603. onHandler('onShow'),
  7604. onHandler('onHide'),
  7605. optionFunction('onEscape'),
  7606. field('inlineBehaviours', [
  7607. Sandboxing,
  7608. Representing,
  7609. Receiving
  7610. ]),
  7611. optionObjOf('fireDismissalEventInstead', [defaulted('event', dismissRequested())]),
  7612. optionObjOf('fireRepositionEventInstead', [defaulted('event', repositionRequested())]),
  7613. defaulted('getRelated', Optional.none),
  7614. defaulted('isExtraPart', never),
  7615. defaulted('eventOrder', Optional.none)
  7616. ],
  7617. factory: factory$o,
  7618. apis: {
  7619. showAt: (apis, component, anchor, thing) => {
  7620. apis.showAt(component, anchor, thing);
  7621. },
  7622. showWithin: (apis, component, anchor, thing, boxElement) => {
  7623. apis.showWithin(component, anchor, thing, boxElement);
  7624. },
  7625. showWithinBounds: (apis, component, anchor, thing, bounds) => {
  7626. apis.showWithinBounds(component, anchor, thing, bounds);
  7627. },
  7628. showMenuAt: (apis, component, anchor, menuSpec) => {
  7629. apis.showMenuAt(component, anchor, menuSpec);
  7630. },
  7631. showMenuWithinBounds: (apis, component, anchor, menuSpec, bounds) => {
  7632. apis.showMenuWithinBounds(component, anchor, menuSpec, bounds);
  7633. },
  7634. hide: (apis, component) => {
  7635. apis.hide(component);
  7636. },
  7637. isOpen: (apis, component) => apis.isOpen(component),
  7638. getContent: (apis, component) => apis.getContent(component),
  7639. setContent: (apis, component, thing) => {
  7640. apis.setContent(component, thing);
  7641. },
  7642. reposition: (apis, component) => {
  7643. apis.reposition(component);
  7644. }
  7645. }
  7646. });
  7647. var global$9 = tinymce.util.Tools.resolve('tinymce.util.Delay');
  7648. const factory$n = detail => {
  7649. const events = events$a(detail.action);
  7650. const tag = detail.dom.tag;
  7651. const lookupAttr = attr => get$g(detail.dom, 'attributes').bind(attrs => get$g(attrs, attr));
  7652. const getModAttributes = () => {
  7653. if (tag === 'button') {
  7654. const type = lookupAttr('type').getOr('button');
  7655. const roleAttrs = lookupAttr('role').map(role => ({ role })).getOr({});
  7656. return {
  7657. type,
  7658. ...roleAttrs
  7659. };
  7660. } else {
  7661. const role = lookupAttr('role').getOr('button');
  7662. return { role };
  7663. }
  7664. };
  7665. return {
  7666. uid: detail.uid,
  7667. dom: detail.dom,
  7668. components: detail.components,
  7669. events,
  7670. behaviours: SketchBehaviours.augment(detail.buttonBehaviours, [
  7671. Focusing.config({}),
  7672. Keying.config({
  7673. mode: 'execution',
  7674. useSpace: true,
  7675. useEnter: true
  7676. })
  7677. ]),
  7678. domModification: { attributes: getModAttributes() },
  7679. eventOrder: detail.eventOrder
  7680. };
  7681. };
  7682. const Button = single({
  7683. name: 'Button',
  7684. factory: factory$n,
  7685. configFields: [
  7686. defaulted('uid', undefined),
  7687. required$1('dom'),
  7688. defaulted('components', []),
  7689. SketchBehaviours.field('buttonBehaviours', [
  7690. Focusing,
  7691. Keying
  7692. ]),
  7693. option$3('action'),
  7694. option$3('role'),
  7695. defaulted('eventOrder', {})
  7696. ]
  7697. });
  7698. const record = spec => {
  7699. const uid = isSketchSpec(spec) && hasNonNullableKey(spec, 'uid') ? spec.uid : generate$5('memento');
  7700. const get = anyInSystem => anyInSystem.getSystem().getByUid(uid).getOrDie();
  7701. const getOpt = anyInSystem => anyInSystem.getSystem().getByUid(uid).toOptional();
  7702. const asSpec = () => ({
  7703. ...spec,
  7704. uid
  7705. });
  7706. return {
  7707. get,
  7708. getOpt,
  7709. asSpec
  7710. };
  7711. };
  7712. var global$8 = tinymce.util.Tools.resolve('tinymce.util.I18n');
  7713. const rtlTransform = {
  7714. 'indent': true,
  7715. 'outdent': true,
  7716. 'table-insert-column-after': true,
  7717. 'table-insert-column-before': true,
  7718. 'paste-column-after': true,
  7719. 'paste-column-before': true,
  7720. 'unordered-list': true,
  7721. 'list-bull-circle': true,
  7722. 'list-bull-default': true,
  7723. 'list-bull-square': true
  7724. };
  7725. const defaultIconName = 'temporary-placeholder';
  7726. const defaultIcon = icons => () => get$g(icons, defaultIconName).getOr('!not found!');
  7727. const getIconName = (name, icons) => {
  7728. const lcName = name.toLowerCase();
  7729. if (global$8.isRtl()) {
  7730. const rtlName = ensureTrailing(lcName, '-rtl');
  7731. return has$2(icons, rtlName) ? rtlName : lcName;
  7732. } else {
  7733. return lcName;
  7734. }
  7735. };
  7736. const lookupIcon = (name, icons) => get$g(icons, getIconName(name, icons));
  7737. const get$2 = (name, iconProvider) => {
  7738. const icons = iconProvider();
  7739. return lookupIcon(name, icons).getOrThunk(defaultIcon(icons));
  7740. };
  7741. const getOr = (name, iconProvider, fallbackIcon) => {
  7742. const icons = iconProvider();
  7743. return lookupIcon(name, icons).or(fallbackIcon).getOrThunk(defaultIcon(icons));
  7744. };
  7745. const needsRtlTransform = iconName => global$8.isRtl() ? has$2(rtlTransform, iconName) : false;
  7746. const addFocusableBehaviour = () => config('add-focusable', [runOnAttached(comp => {
  7747. child(comp.element, 'svg').each(svg => set$9(svg, 'focusable', 'false'));
  7748. })]);
  7749. const renderIcon$2 = (spec, iconName, icons, fallbackIcon) => {
  7750. var _a, _b;
  7751. const rtlIconClasses = needsRtlTransform(iconName) ? ['tox-icon--flip'] : [];
  7752. const iconHtml = get$g(icons, getIconName(iconName, icons)).or(fallbackIcon).getOrThunk(defaultIcon(icons));
  7753. return {
  7754. dom: {
  7755. tag: spec.tag,
  7756. attributes: (_a = spec.attributes) !== null && _a !== void 0 ? _a : {},
  7757. classes: spec.classes.concat(rtlIconClasses),
  7758. innerHtml: iconHtml
  7759. },
  7760. behaviours: derive$1([
  7761. ...(_b = spec.behaviours) !== null && _b !== void 0 ? _b : [],
  7762. addFocusableBehaviour()
  7763. ])
  7764. };
  7765. };
  7766. const render$3 = (iconName, spec, iconProvider, fallbackIcon = Optional.none()) => renderIcon$2(spec, iconName, iconProvider(), fallbackIcon);
  7767. const renderFirst = (iconNames, spec, iconProvider) => {
  7768. const icons = iconProvider();
  7769. const iconName = find$5(iconNames, name => has$2(icons, getIconName(name, icons)));
  7770. return renderIcon$2(spec, iconName.getOr(defaultIconName), icons, Optional.none());
  7771. };
  7772. const notificationIconMap = {
  7773. success: 'checkmark',
  7774. error: 'warning',
  7775. err: 'error',
  7776. warning: 'warning',
  7777. warn: 'warning',
  7778. info: 'info'
  7779. };
  7780. const factory$m = detail => {
  7781. const memBannerText = record({
  7782. dom: {
  7783. tag: 'p',
  7784. innerHtml: detail.translationProvider(detail.text)
  7785. },
  7786. behaviours: derive$1([Replacing.config({})])
  7787. });
  7788. const renderPercentBar = percent => ({
  7789. dom: {
  7790. tag: 'div',
  7791. classes: ['tox-bar'],
  7792. styles: { width: `${ percent }%` }
  7793. }
  7794. });
  7795. const renderPercentText = percent => ({
  7796. dom: {
  7797. tag: 'div',
  7798. classes: ['tox-text'],
  7799. innerHtml: `${ percent }%`
  7800. }
  7801. });
  7802. const memBannerProgress = record({
  7803. dom: {
  7804. tag: 'div',
  7805. classes: detail.progress ? [
  7806. 'tox-progress-bar',
  7807. 'tox-progress-indicator'
  7808. ] : ['tox-progress-bar']
  7809. },
  7810. components: [
  7811. {
  7812. dom: {
  7813. tag: 'div',
  7814. classes: ['tox-bar-container']
  7815. },
  7816. components: [renderPercentBar(0)]
  7817. },
  7818. renderPercentText(0)
  7819. ],
  7820. behaviours: derive$1([Replacing.config({})])
  7821. });
  7822. const updateProgress = (comp, percent) => {
  7823. if (comp.getSystem().isConnected()) {
  7824. memBannerProgress.getOpt(comp).each(progress => {
  7825. Replacing.set(progress, [
  7826. {
  7827. dom: {
  7828. tag: 'div',
  7829. classes: ['tox-bar-container']
  7830. },
  7831. components: [renderPercentBar(percent)]
  7832. },
  7833. renderPercentText(percent)
  7834. ]);
  7835. });
  7836. }
  7837. };
  7838. const updateText = (comp, text) => {
  7839. if (comp.getSystem().isConnected()) {
  7840. const banner = memBannerText.get(comp);
  7841. Replacing.set(banner, [text$2(text)]);
  7842. }
  7843. };
  7844. const apis = {
  7845. updateProgress,
  7846. updateText
  7847. };
  7848. const iconChoices = flatten([
  7849. detail.icon.toArray(),
  7850. detail.level.toArray(),
  7851. detail.level.bind(level => Optional.from(notificationIconMap[level])).toArray()
  7852. ]);
  7853. const memButton = record(Button.sketch({
  7854. dom: {
  7855. tag: 'button',
  7856. classes: [
  7857. 'tox-notification__dismiss',
  7858. 'tox-button',
  7859. 'tox-button--naked',
  7860. 'tox-button--icon'
  7861. ]
  7862. },
  7863. components: [render$3('close', {
  7864. tag: 'div',
  7865. classes: ['tox-icon'],
  7866. attributes: { 'aria-label': detail.translationProvider('Close') }
  7867. }, detail.iconProvider)],
  7868. action: comp => {
  7869. detail.onAction(comp);
  7870. }
  7871. }));
  7872. const notificationIconSpec = renderFirst(iconChoices, {
  7873. tag: 'div',
  7874. classes: ['tox-notification__icon']
  7875. }, detail.iconProvider);
  7876. const notificationBodySpec = {
  7877. dom: {
  7878. tag: 'div',
  7879. classes: ['tox-notification__body']
  7880. },
  7881. components: [memBannerText.asSpec()],
  7882. behaviours: derive$1([Replacing.config({})])
  7883. };
  7884. const components = [
  7885. notificationIconSpec,
  7886. notificationBodySpec
  7887. ];
  7888. return {
  7889. uid: detail.uid,
  7890. dom: {
  7891. tag: 'div',
  7892. attributes: { role: 'alert' },
  7893. classes: detail.level.map(level => [
  7894. 'tox-notification',
  7895. 'tox-notification--in',
  7896. `tox-notification--${ level }`
  7897. ]).getOr([
  7898. 'tox-notification',
  7899. 'tox-notification--in'
  7900. ])
  7901. },
  7902. behaviours: derive$1([
  7903. Focusing.config({}),
  7904. config('notification-events', [run$1(focusin(), comp => {
  7905. memButton.getOpt(comp).each(Focusing.focus);
  7906. })])
  7907. ]),
  7908. components: components.concat(detail.progress ? [memBannerProgress.asSpec()] : []).concat(!detail.closeButton ? [] : [memButton.asSpec()]),
  7909. apis
  7910. };
  7911. };
  7912. const Notification = single({
  7913. name: 'Notification',
  7914. factory: factory$m,
  7915. configFields: [
  7916. option$3('level'),
  7917. required$1('progress'),
  7918. option$3('icon'),
  7919. required$1('onAction'),
  7920. required$1('text'),
  7921. required$1('iconProvider'),
  7922. required$1('translationProvider'),
  7923. defaultedBoolean('closeButton', true)
  7924. ],
  7925. apis: {
  7926. updateProgress: (apis, comp, percent) => {
  7927. apis.updateProgress(comp, percent);
  7928. },
  7929. updateText: (apis, comp, text) => {
  7930. apis.updateText(comp, text);
  7931. }
  7932. }
  7933. });
  7934. var NotificationManagerImpl = (editor, extras, uiMothership) => {
  7935. const sharedBackstage = extras.backstage.shared;
  7936. const getBounds = () => {
  7937. const contentArea = box$1(SugarElement.fromDom(editor.getContentAreaContainer()));
  7938. const win$1 = win();
  7939. const x = clamp(win$1.x, contentArea.x, contentArea.right);
  7940. const y = clamp(win$1.y, contentArea.y, contentArea.bottom);
  7941. const right = Math.max(contentArea.right, win$1.right);
  7942. const bottom = Math.max(contentArea.bottom, win$1.bottom);
  7943. return Optional.some(bounds(x, y, right - x, bottom - y));
  7944. };
  7945. const open = (settings, closeCallback) => {
  7946. const close = () => {
  7947. closeCallback();
  7948. InlineView.hide(notificationWrapper);
  7949. };
  7950. const notification = build$1(Notification.sketch({
  7951. text: settings.text,
  7952. level: contains$2([
  7953. 'success',
  7954. 'error',
  7955. 'warning',
  7956. 'warn',
  7957. 'info'
  7958. ], settings.type) ? settings.type : undefined,
  7959. progress: settings.progressBar === true,
  7960. icon: settings.icon,
  7961. closeButton: settings.closeButton,
  7962. onAction: close,
  7963. iconProvider: sharedBackstage.providers.icons,
  7964. translationProvider: sharedBackstage.providers.translate
  7965. }));
  7966. const notificationWrapper = build$1(InlineView.sketch({
  7967. dom: {
  7968. tag: 'div',
  7969. classes: ['tox-notifications-container']
  7970. },
  7971. lazySink: sharedBackstage.getSink,
  7972. fireDismissalEventInstead: {},
  7973. ...sharedBackstage.header.isPositionedAtTop() ? {} : { fireRepositionEventInstead: {} }
  7974. }));
  7975. uiMothership.add(notificationWrapper);
  7976. if (isNumber(settings.timeout) && settings.timeout > 0) {
  7977. global$9.setEditorTimeout(editor, () => {
  7978. close();
  7979. }, settings.timeout);
  7980. }
  7981. const reposition = () => {
  7982. const notificationSpec = premade(notification);
  7983. const anchorOverrides = { maxHeightFunction: expandable$1() };
  7984. const allNotifications = editor.notificationManager.getNotifications();
  7985. if (allNotifications[0] === thisNotification) {
  7986. const anchor = {
  7987. ...sharedBackstage.anchors.banner(),
  7988. overrides: anchorOverrides
  7989. };
  7990. InlineView.showWithinBounds(notificationWrapper, notificationSpec, { anchor }, getBounds);
  7991. } else {
  7992. indexOf(allNotifications, thisNotification).each(idx => {
  7993. const previousNotification = allNotifications[idx - 1].getEl();
  7994. const nodeAnchor = {
  7995. type: 'node',
  7996. root: body(),
  7997. node: Optional.some(SugarElement.fromDom(previousNotification)),
  7998. overrides: anchorOverrides,
  7999. layouts: {
  8000. onRtl: () => [south$2],
  8001. onLtr: () => [south$2]
  8002. }
  8003. };
  8004. InlineView.showWithinBounds(notificationWrapper, notificationSpec, { anchor: nodeAnchor }, getBounds);
  8005. });
  8006. }
  8007. };
  8008. const thisNotification = {
  8009. close,
  8010. reposition,
  8011. text: nuText => {
  8012. Notification.updateText(notification, nuText);
  8013. },
  8014. settings,
  8015. getEl: () => notification.element.dom,
  8016. progressBar: {
  8017. value: percent => {
  8018. Notification.updateProgress(notification, percent);
  8019. }
  8020. }
  8021. };
  8022. return thisNotification;
  8023. };
  8024. const close = notification => {
  8025. notification.close();
  8026. };
  8027. const getArgs = notification => {
  8028. return notification.settings;
  8029. };
  8030. return {
  8031. open,
  8032. close,
  8033. getArgs
  8034. };
  8035. };
  8036. var global$7 = tinymce.util.Tools.resolve('tinymce.dom.DOMUtils');
  8037. var global$6 = tinymce.util.Tools.resolve('tinymce.EditorManager');
  8038. var global$5 = tinymce.util.Tools.resolve('tinymce.Env');
  8039. var ToolbarMode$1;
  8040. (function (ToolbarMode) {
  8041. ToolbarMode['default'] = 'wrap';
  8042. ToolbarMode['floating'] = 'floating';
  8043. ToolbarMode['sliding'] = 'sliding';
  8044. ToolbarMode['scrolling'] = 'scrolling';
  8045. }(ToolbarMode$1 || (ToolbarMode$1 = {})));
  8046. var ToolbarLocation$1;
  8047. (function (ToolbarLocation) {
  8048. ToolbarLocation['auto'] = 'auto';
  8049. ToolbarLocation['top'] = 'top';
  8050. ToolbarLocation['bottom'] = 'bottom';
  8051. }(ToolbarLocation$1 || (ToolbarLocation$1 = {})));
  8052. const option$2 = name => editor => editor.options.get(name);
  8053. const wrapOptional = fn => editor => Optional.from(fn(editor));
  8054. const register$e = editor => {
  8055. const isPhone = global$5.deviceType.isPhone();
  8056. const isMobile = global$5.deviceType.isTablet() || isPhone;
  8057. const registerOption = editor.options.register;
  8058. const stringOrFalseProcessor = value => isString(value) || value === false;
  8059. const stringOrNumberProcessor = value => isString(value) || isNumber(value);
  8060. registerOption('skin', {
  8061. processor: value => isString(value) || value === false,
  8062. default: 'oxide'
  8063. });
  8064. registerOption('skin_url', { processor: 'string' });
  8065. registerOption('height', {
  8066. processor: stringOrNumberProcessor,
  8067. default: Math.max(editor.getElement().offsetHeight, 400)
  8068. });
  8069. registerOption('width', {
  8070. processor: stringOrNumberProcessor,
  8071. default: global$7.DOM.getStyle(editor.getElement(), 'width')
  8072. });
  8073. registerOption('min_height', {
  8074. processor: 'number',
  8075. default: 100
  8076. });
  8077. registerOption('min_width', { processor: 'number' });
  8078. registerOption('max_height', { processor: 'number' });
  8079. registerOption('max_width', { processor: 'number' });
  8080. registerOption('style_formats', { processor: 'object[]' });
  8081. registerOption('style_formats_merge', {
  8082. processor: 'boolean',
  8083. default: false
  8084. });
  8085. registerOption('style_formats_autohide', {
  8086. processor: 'boolean',
  8087. default: false
  8088. });
  8089. registerOption('line_height_formats', {
  8090. processor: 'string',
  8091. default: '1 1.1 1.2 1.3 1.4 1.5 2'
  8092. });
  8093. registerOption('font_family_formats', {
  8094. processor: 'string',
  8095. default: 'Andale Mono=andale mono,monospace;' + 'Arial=arial,helvetica,sans-serif;' + 'Arial Black=arial black,sans-serif;' + 'Book Antiqua=book antiqua,palatino,serif;' + 'Comic Sans MS=comic sans ms,sans-serif;' + 'Courier New=courier new,courier,monospace;' + 'Georgia=georgia,palatino,serif;' + 'Helvetica=helvetica,arial,sans-serif;' + 'Impact=impact,sans-serif;' + 'Symbol=symbol;' + 'Tahoma=tahoma,arial,helvetica,sans-serif;' + 'Terminal=terminal,monaco,monospace;' + 'Times New Roman=times new roman,times,serif;' + 'Trebuchet MS=trebuchet ms,geneva,sans-serif;' + 'Verdana=verdana,geneva,sans-serif;' + 'Webdings=webdings;' + 'Wingdings=wingdings,zapf dingbats'
  8096. });
  8097. registerOption('font_size_formats', {
  8098. processor: 'string',
  8099. default: '8pt 10pt 12pt 14pt 18pt 24pt 36pt'
  8100. });
  8101. registerOption('block_formats', {
  8102. processor: 'string',
  8103. default: 'Paragraph=p;' + 'Heading 1=h1;' + 'Heading 2=h2;' + 'Heading 3=h3;' + 'Heading 4=h4;' + 'Heading 5=h5;' + 'Heading 6=h6;' + 'Preformatted=pre'
  8104. });
  8105. registerOption('content_langs', { processor: 'object[]' });
  8106. registerOption('removed_menuitems', {
  8107. processor: 'string',
  8108. default: ''
  8109. });
  8110. registerOption('menubar', {
  8111. processor: value => isString(value) || isBoolean(value),
  8112. default: !isPhone
  8113. });
  8114. registerOption('menu', {
  8115. processor: 'object',
  8116. default: {}
  8117. });
  8118. registerOption('toolbar', {
  8119. processor: value => {
  8120. if (isBoolean(value) || isString(value) || isArray(value)) {
  8121. return {
  8122. value,
  8123. valid: true
  8124. };
  8125. } else {
  8126. return {
  8127. valid: false,
  8128. message: 'Must be a boolean, string or array.'
  8129. };
  8130. }
  8131. },
  8132. default: true
  8133. });
  8134. range$2(9, num => {
  8135. registerOption('toolbar' + (num + 1), { processor: 'string' });
  8136. });
  8137. registerOption('toolbar_mode', {
  8138. processor: 'string',
  8139. default: isMobile ? 'scrolling' : 'floating'
  8140. });
  8141. registerOption('toolbar_groups', {
  8142. processor: 'object',
  8143. default: {}
  8144. });
  8145. registerOption('toolbar_location', {
  8146. processor: 'string',
  8147. default: ToolbarLocation$1.auto
  8148. });
  8149. registerOption('toolbar_persist', {
  8150. processor: 'boolean',
  8151. default: false
  8152. });
  8153. registerOption('toolbar_sticky', {
  8154. processor: 'boolean',
  8155. default: editor.inline
  8156. });
  8157. registerOption('toolbar_sticky_offset', {
  8158. processor: 'number',
  8159. default: 0
  8160. });
  8161. registerOption('fixed_toolbar_container', {
  8162. processor: 'string',
  8163. default: ''
  8164. });
  8165. registerOption('fixed_toolbar_container_target', { processor: 'object' });
  8166. registerOption('file_picker_callback', { processor: 'function' });
  8167. registerOption('file_picker_validator_handler', { processor: 'function' });
  8168. registerOption('file_picker_types', { processor: 'string' });
  8169. registerOption('typeahead_urls', {
  8170. processor: 'boolean',
  8171. default: true
  8172. });
  8173. registerOption('anchor_top', {
  8174. processor: stringOrFalseProcessor,
  8175. default: '#top'
  8176. });
  8177. registerOption('anchor_bottom', {
  8178. processor: stringOrFalseProcessor,
  8179. default: '#bottom'
  8180. });
  8181. registerOption('draggable_modal', {
  8182. processor: 'boolean',
  8183. default: false
  8184. });
  8185. registerOption('statusbar', {
  8186. processor: 'boolean',
  8187. default: true
  8188. });
  8189. registerOption('elementpath', {
  8190. processor: 'boolean',
  8191. default: true
  8192. });
  8193. registerOption('branding', {
  8194. processor: 'boolean',
  8195. default: true
  8196. });
  8197. registerOption('promotion', {
  8198. processor: 'boolean',
  8199. default: true
  8200. });
  8201. registerOption('resize', {
  8202. processor: value => value === 'both' || isBoolean(value),
  8203. default: !global$5.deviceType.isTouch()
  8204. });
  8205. registerOption('sidebar_show', { processor: 'string' });
  8206. };
  8207. const isReadOnly = option$2('readonly');
  8208. const getHeightOption = option$2('height');
  8209. const getWidthOption = option$2('width');
  8210. const getMinWidthOption = wrapOptional(option$2('min_width'));
  8211. const getMinHeightOption = wrapOptional(option$2('min_height'));
  8212. const getMaxWidthOption = wrapOptional(option$2('max_width'));
  8213. const getMaxHeightOption = wrapOptional(option$2('max_height'));
  8214. const getUserStyleFormats = wrapOptional(option$2('style_formats'));
  8215. const shouldMergeStyleFormats = option$2('style_formats_merge');
  8216. const shouldAutoHideStyleFormats = option$2('style_formats_autohide');
  8217. const getContentLanguages = option$2('content_langs');
  8218. const getRemovedMenuItems = option$2('removed_menuitems');
  8219. const getToolbarMode = option$2('toolbar_mode');
  8220. const getToolbarGroups = option$2('toolbar_groups');
  8221. const getToolbarLocation = option$2('toolbar_location');
  8222. const fixedContainerSelector = option$2('fixed_toolbar_container');
  8223. const fixedToolbarContainerTarget = option$2('fixed_toolbar_container_target');
  8224. const isToolbarPersist = option$2('toolbar_persist');
  8225. const getStickyToolbarOffset = option$2('toolbar_sticky_offset');
  8226. const getMenubar = option$2('menubar');
  8227. const getToolbar = option$2('toolbar');
  8228. const getFilePickerCallback = option$2('file_picker_callback');
  8229. const getFilePickerValidatorHandler = option$2('file_picker_validator_handler');
  8230. const getFilePickerTypes = option$2('file_picker_types');
  8231. const useTypeaheadUrls = option$2('typeahead_urls');
  8232. const getAnchorTop = option$2('anchor_top');
  8233. const getAnchorBottom = option$2('anchor_bottom');
  8234. const isDraggableModal$1 = option$2('draggable_modal');
  8235. const useStatusBar = option$2('statusbar');
  8236. const useElementPath = option$2('elementpath');
  8237. const useBranding = option$2('branding');
  8238. const getResize = option$2('resize');
  8239. const getPasteAsText = option$2('paste_as_text');
  8240. const getSidebarShow = option$2('sidebar_show');
  8241. const promotionEnabled = option$2('promotion');
  8242. const isSkinDisabled = editor => editor.options.get('skin') === false;
  8243. const isMenubarEnabled = editor => editor.options.get('menubar') !== false;
  8244. const getSkinUrl = editor => {
  8245. const skinUrl = editor.options.get('skin_url');
  8246. if (isSkinDisabled(editor)) {
  8247. return skinUrl;
  8248. } else {
  8249. if (skinUrl) {
  8250. return editor.documentBaseURI.toAbsolute(skinUrl);
  8251. } else {
  8252. const skin = editor.options.get('skin');
  8253. return global$6.baseURL + '/skins/ui/' + skin;
  8254. }
  8255. }
  8256. };
  8257. const getLineHeightFormats = editor => editor.options.get('line_height_formats').split(' ');
  8258. const isToolbarEnabled = editor => {
  8259. const toolbar = getToolbar(editor);
  8260. const isToolbarString = isString(toolbar);
  8261. const isToolbarObjectArray = isArray(toolbar) && toolbar.length > 0;
  8262. return !isMultipleToolbars(editor) && (isToolbarObjectArray || isToolbarString || toolbar === true);
  8263. };
  8264. const getMultipleToolbarsOption = editor => {
  8265. const toolbars = range$2(9, num => editor.options.get('toolbar' + (num + 1)));
  8266. const toolbarArray = filter$2(toolbars, isString);
  8267. return someIf(toolbarArray.length > 0, toolbarArray);
  8268. };
  8269. const isMultipleToolbars = editor => getMultipleToolbarsOption(editor).fold(() => {
  8270. const toolbar = getToolbar(editor);
  8271. return isArrayOf(toolbar, isString) && toolbar.length > 0;
  8272. }, always);
  8273. const isToolbarLocationBottom = editor => getToolbarLocation(editor) === ToolbarLocation$1.bottom;
  8274. const fixedContainerTarget = editor => {
  8275. var _a;
  8276. if (!editor.inline) {
  8277. return Optional.none();
  8278. }
  8279. const selector = (_a = fixedContainerSelector(editor)) !== null && _a !== void 0 ? _a : '';
  8280. if (selector.length > 0) {
  8281. return descendant(body(), selector);
  8282. }
  8283. const element = fixedToolbarContainerTarget(editor);
  8284. if (isNonNullable(element)) {
  8285. return Optional.some(SugarElement.fromDom(element));
  8286. }
  8287. return Optional.none();
  8288. };
  8289. const useFixedContainer = editor => editor.inline && fixedContainerTarget(editor).isSome();
  8290. const getUiContainer = editor => {
  8291. const fixedContainer = fixedContainerTarget(editor);
  8292. return fixedContainer.getOrThunk(() => getContentContainer(getRootNode(SugarElement.fromDom(editor.getElement()))));
  8293. };
  8294. const isDistractionFree = editor => editor.inline && !isMenubarEnabled(editor) && !isToolbarEnabled(editor) && !isMultipleToolbars(editor);
  8295. const isStickyToolbar = editor => {
  8296. const isStickyToolbar = editor.options.get('toolbar_sticky');
  8297. return (isStickyToolbar || editor.inline) && !useFixedContainer(editor) && !isDistractionFree(editor);
  8298. };
  8299. const getMenus = editor => {
  8300. const menu = editor.options.get('menu');
  8301. return map$1(menu, menu => ({
  8302. ...menu,
  8303. items: menu.items
  8304. }));
  8305. };
  8306. var Options = /*#__PURE__*/Object.freeze({
  8307. __proto__: null,
  8308. get ToolbarMode () { return ToolbarMode$1; },
  8309. get ToolbarLocation () { return ToolbarLocation$1; },
  8310. register: register$e,
  8311. getSkinUrl: getSkinUrl,
  8312. isReadOnly: isReadOnly,
  8313. isSkinDisabled: isSkinDisabled,
  8314. getHeightOption: getHeightOption,
  8315. getWidthOption: getWidthOption,
  8316. getMinWidthOption: getMinWidthOption,
  8317. getMinHeightOption: getMinHeightOption,
  8318. getMaxWidthOption: getMaxWidthOption,
  8319. getMaxHeightOption: getMaxHeightOption,
  8320. getUserStyleFormats: getUserStyleFormats,
  8321. shouldMergeStyleFormats: shouldMergeStyleFormats,
  8322. shouldAutoHideStyleFormats: shouldAutoHideStyleFormats,
  8323. getLineHeightFormats: getLineHeightFormats,
  8324. getContentLanguages: getContentLanguages,
  8325. getRemovedMenuItems: getRemovedMenuItems,
  8326. isMenubarEnabled: isMenubarEnabled,
  8327. isMultipleToolbars: isMultipleToolbars,
  8328. isToolbarEnabled: isToolbarEnabled,
  8329. isToolbarPersist: isToolbarPersist,
  8330. getMultipleToolbarsOption: getMultipleToolbarsOption,
  8331. getUiContainer: getUiContainer,
  8332. useFixedContainer: useFixedContainer,
  8333. getToolbarMode: getToolbarMode,
  8334. isDraggableModal: isDraggableModal$1,
  8335. isDistractionFree: isDistractionFree,
  8336. isStickyToolbar: isStickyToolbar,
  8337. getStickyToolbarOffset: getStickyToolbarOffset,
  8338. getToolbarLocation: getToolbarLocation,
  8339. isToolbarLocationBottom: isToolbarLocationBottom,
  8340. getToolbarGroups: getToolbarGroups,
  8341. getMenus: getMenus,
  8342. getMenubar: getMenubar,
  8343. getToolbar: getToolbar,
  8344. getFilePickerCallback: getFilePickerCallback,
  8345. getFilePickerTypes: getFilePickerTypes,
  8346. useTypeaheadUrls: useTypeaheadUrls,
  8347. getAnchorTop: getAnchorTop,
  8348. getAnchorBottom: getAnchorBottom,
  8349. getFilePickerValidatorHandler: getFilePickerValidatorHandler,
  8350. useStatusBar: useStatusBar,
  8351. useElementPath: useElementPath,
  8352. promotionEnabled: promotionEnabled,
  8353. useBranding: useBranding,
  8354. getResize: getResize,
  8355. getPasteAsText: getPasteAsText,
  8356. getSidebarShow: getSidebarShow
  8357. });
  8358. const autocompleteSelector = '[data-mce-autocompleter]';
  8359. const detect = elm => closest$1(elm, autocompleteSelector);
  8360. const findIn = elm => descendant(elm, autocompleteSelector);
  8361. const setup$e = (api, editor) => {
  8362. const redirectKeyToItem = (item, e) => {
  8363. emitWith(item, keydown(), { raw: e });
  8364. };
  8365. const getItem = () => api.getMenu().bind(Highlighting.getHighlighted);
  8366. editor.on('keydown', e => {
  8367. const keyCode = e.which;
  8368. if (!api.isActive()) {
  8369. return;
  8370. }
  8371. if (api.isMenuOpen()) {
  8372. if (keyCode === 13) {
  8373. getItem().each(emitExecute);
  8374. e.preventDefault();
  8375. } else if (keyCode === 40) {
  8376. getItem().fold(() => {
  8377. api.getMenu().each(Highlighting.highlightFirst);
  8378. }, item => {
  8379. redirectKeyToItem(item, e);
  8380. });
  8381. e.preventDefault();
  8382. e.stopImmediatePropagation();
  8383. } else if (keyCode === 37 || keyCode === 38 || keyCode === 39) {
  8384. getItem().each(item => {
  8385. redirectKeyToItem(item, e);
  8386. e.preventDefault();
  8387. e.stopImmediatePropagation();
  8388. });
  8389. }
  8390. } else {
  8391. if (keyCode === 13 || keyCode === 38 || keyCode === 40) {
  8392. api.cancelIfNecessary();
  8393. }
  8394. }
  8395. });
  8396. editor.on('NodeChange', e => {
  8397. if (api.isActive() && !api.isProcessingAction() && detect(SugarElement.fromDom(e.element)).isNone()) {
  8398. api.cancelIfNecessary();
  8399. }
  8400. });
  8401. };
  8402. const AutocompleterEditorEvents = { setup: setup$e };
  8403. var ItemResponse;
  8404. (function (ItemResponse) {
  8405. ItemResponse[ItemResponse['CLOSE_ON_EXECUTE'] = 0] = 'CLOSE_ON_EXECUTE';
  8406. ItemResponse[ItemResponse['BUBBLE_TO_SANDBOX'] = 1] = 'BUBBLE_TO_SANDBOX';
  8407. }(ItemResponse || (ItemResponse = {})));
  8408. var ItemResponse$1 = ItemResponse;
  8409. const navClass = 'tox-menu-nav__js';
  8410. const selectableClass = 'tox-collection__item';
  8411. const colorClass = 'tox-swatch';
  8412. const presetClasses = {
  8413. normal: navClass,
  8414. color: colorClass
  8415. };
  8416. const tickedClass = 'tox-collection__item--enabled';
  8417. const groupHeadingClass = 'tox-collection__group-heading';
  8418. const iconClass = 'tox-collection__item-icon';
  8419. const textClass = 'tox-collection__item-label';
  8420. const accessoryClass = 'tox-collection__item-accessory';
  8421. const caretClass = 'tox-collection__item-caret';
  8422. const checkmarkClass = 'tox-collection__item-checkmark';
  8423. const activeClass = 'tox-collection__item--active';
  8424. const containerClass = 'tox-collection__item-container';
  8425. const containerColumnClass = 'tox-collection__item-container--column';
  8426. const containerRowClass = 'tox-collection__item-container--row';
  8427. const containerAlignRightClass = 'tox-collection__item-container--align-right';
  8428. const containerAlignLeftClass = 'tox-collection__item-container--align-left';
  8429. const containerValignTopClass = 'tox-collection__item-container--valign-top';
  8430. const containerValignMiddleClass = 'tox-collection__item-container--valign-middle';
  8431. const containerValignBottomClass = 'tox-collection__item-container--valign-bottom';
  8432. const classForPreset = presets => get$g(presetClasses, presets).getOr(navClass);
  8433. const forMenu = presets => {
  8434. if (presets === 'color') {
  8435. return 'tox-swatches';
  8436. } else {
  8437. return 'tox-menu';
  8438. }
  8439. };
  8440. const classes = presets => ({
  8441. backgroundMenu: 'tox-background-menu',
  8442. selectedMenu: 'tox-selected-menu',
  8443. selectedItem: 'tox-collection__item--active',
  8444. hasIcons: 'tox-menu--has-icons',
  8445. menu: forMenu(presets),
  8446. tieredMenu: 'tox-tiered-menu'
  8447. });
  8448. const markers = presets => {
  8449. const menuClasses = classes(presets);
  8450. return {
  8451. backgroundMenu: menuClasses.backgroundMenu,
  8452. selectedMenu: menuClasses.selectedMenu,
  8453. menu: menuClasses.menu,
  8454. selectedItem: menuClasses.selectedItem,
  8455. item: classForPreset(presets)
  8456. };
  8457. };
  8458. const dom$1 = (hasIcons, columns, presets) => {
  8459. const menuClasses = classes(presets);
  8460. return {
  8461. tag: 'div',
  8462. classes: flatten([
  8463. [
  8464. menuClasses.menu,
  8465. `tox-menu-${ columns }-column`
  8466. ],
  8467. hasIcons ? [menuClasses.hasIcons] : []
  8468. ])
  8469. };
  8470. };
  8471. const components = [Menu.parts.items({})];
  8472. const part = (hasIcons, columns, presets) => {
  8473. const menuClasses = classes(presets);
  8474. const d = {
  8475. tag: 'div',
  8476. classes: flatten([[menuClasses.tieredMenu]])
  8477. };
  8478. return {
  8479. dom: d,
  8480. markers: markers(presets)
  8481. };
  8482. };
  8483. const schema$l = constant$1([
  8484. option$3('data'),
  8485. defaulted('inputAttributes', {}),
  8486. defaulted('inputStyles', {}),
  8487. defaulted('tag', 'input'),
  8488. defaulted('inputClasses', []),
  8489. onHandler('onSetValue'),
  8490. defaulted('styles', {}),
  8491. defaulted('eventOrder', {}),
  8492. field('inputBehaviours', [
  8493. Representing,
  8494. Focusing
  8495. ]),
  8496. defaulted('selectOnFocus', true)
  8497. ]);
  8498. const focusBehaviours = detail => derive$1([Focusing.config({
  8499. onFocus: !detail.selectOnFocus ? noop : component => {
  8500. const input = component.element;
  8501. const value = get$6(input);
  8502. input.dom.setSelectionRange(0, value.length);
  8503. }
  8504. })]);
  8505. const behaviours = detail => ({
  8506. ...focusBehaviours(detail),
  8507. ...augment(detail.inputBehaviours, [Representing.config({
  8508. store: {
  8509. mode: 'manual',
  8510. ...detail.data.map(data => ({ initialValue: data })).getOr({}),
  8511. getValue: input => {
  8512. return get$6(input.element);
  8513. },
  8514. setValue: (input, data) => {
  8515. const current = get$6(input.element);
  8516. if (current !== data) {
  8517. set$5(input.element, data);
  8518. }
  8519. }
  8520. },
  8521. onSetValue: detail.onSetValue
  8522. })])
  8523. });
  8524. const dom = detail => ({
  8525. tag: detail.tag,
  8526. attributes: {
  8527. type: 'text',
  8528. ...detail.inputAttributes
  8529. },
  8530. styles: detail.inputStyles,
  8531. classes: detail.inputClasses
  8532. });
  8533. const factory$l = (detail, _spec) => ({
  8534. uid: detail.uid,
  8535. dom: dom(detail),
  8536. components: [],
  8537. behaviours: behaviours(detail),
  8538. eventOrder: detail.eventOrder
  8539. });
  8540. const Input = single({
  8541. name: 'Input',
  8542. configFields: schema$l(),
  8543. factory: factory$l
  8544. });
  8545. const refetchTriggerEvent = generate$6('refetch-trigger-event');
  8546. const redirectMenuItemInteractionEvent = generate$6('redirect-menu-item-interaction');
  8547. const menuSearcherClass = 'tox-menu__searcher';
  8548. const findWithinSandbox = sandboxComp => {
  8549. return descendant(sandboxComp.element, `.${ menuSearcherClass }`).bind(inputElem => sandboxComp.getSystem().getByDom(inputElem).toOptional());
  8550. };
  8551. const findWithinMenu = findWithinSandbox;
  8552. const restoreState = (inputComp, searcherState) => {
  8553. Representing.setValue(inputComp, searcherState.fetchPattern);
  8554. inputComp.element.dom.selectionStart = searcherState.selectionStart;
  8555. inputComp.element.dom.selectionEnd = searcherState.selectionEnd;
  8556. };
  8557. const saveState = inputComp => {
  8558. const fetchPattern = Representing.getValue(inputComp);
  8559. const selectionStart = inputComp.element.dom.selectionStart;
  8560. const selectionEnd = inputComp.element.dom.selectionEnd;
  8561. return {
  8562. fetchPattern,
  8563. selectionStart,
  8564. selectionEnd
  8565. };
  8566. };
  8567. const setActiveDescendant = (inputComp, active) => {
  8568. getOpt(active.element, 'id').each(id => set$9(inputComp.element, 'aria-activedescendant', id));
  8569. };
  8570. const renderMenuSearcher = spec => {
  8571. const handleByBrowser = (comp, se) => {
  8572. se.cut();
  8573. return Optional.none();
  8574. };
  8575. const handleByHighlightedItem = (comp, se) => {
  8576. const eventData = {
  8577. interactionEvent: se.event,
  8578. eventType: se.event.raw.type
  8579. };
  8580. emitWith(comp, redirectMenuItemInteractionEvent, eventData);
  8581. return Optional.some(true);
  8582. };
  8583. const customSearcherEventsName = 'searcher-events';
  8584. return {
  8585. dom: {
  8586. tag: 'div',
  8587. classes: [selectableClass]
  8588. },
  8589. components: [Input.sketch({
  8590. inputClasses: [
  8591. menuSearcherClass,
  8592. 'tox-textfield'
  8593. ],
  8594. inputAttributes: {
  8595. ...spec.placeholder.map(placeholder => ({ placeholder: spec.i18n(placeholder) })).getOr({}),
  8596. 'type': 'search',
  8597. 'aria-autocomplete': 'list'
  8598. },
  8599. inputBehaviours: derive$1([
  8600. config(customSearcherEventsName, [
  8601. run$1(input(), inputComp => {
  8602. emit(inputComp, refetchTriggerEvent);
  8603. }),
  8604. run$1(keydown(), (inputComp, se) => {
  8605. if (se.event.raw.key === 'Escape') {
  8606. se.stop();
  8607. }
  8608. })
  8609. ]),
  8610. Keying.config({
  8611. mode: 'special',
  8612. onLeft: handleByBrowser,
  8613. onRight: handleByBrowser,
  8614. onSpace: handleByBrowser,
  8615. onEnter: handleByHighlightedItem,
  8616. onEscape: handleByHighlightedItem,
  8617. onUp: handleByHighlightedItem,
  8618. onDown: handleByHighlightedItem
  8619. })
  8620. ]),
  8621. eventOrder: {
  8622. keydown: [
  8623. customSearcherEventsName,
  8624. Keying.name()
  8625. ]
  8626. }
  8627. })]
  8628. };
  8629. };
  8630. const searchResultsClass = 'tox-collection--results__js';
  8631. const augmentWithAria = item => {
  8632. var _a;
  8633. if (item.dom) {
  8634. return {
  8635. ...item,
  8636. dom: {
  8637. ...item.dom,
  8638. attributes: {
  8639. ...(_a = item.dom.attributes) !== null && _a !== void 0 ? _a : {},
  8640. 'id': generate$6('aria-item-search-result-id'),
  8641. 'aria-selected': 'false'
  8642. }
  8643. }
  8644. };
  8645. } else {
  8646. return item;
  8647. }
  8648. };
  8649. const chunk = (rowDom, numColumns) => items => {
  8650. const chunks = chunk$1(items, numColumns);
  8651. return map$2(chunks, c => ({
  8652. dom: rowDom,
  8653. components: c
  8654. }));
  8655. };
  8656. const forSwatch = columns => ({
  8657. dom: {
  8658. tag: 'div',
  8659. classes: [
  8660. 'tox-menu',
  8661. 'tox-swatches-menu'
  8662. ]
  8663. },
  8664. components: [{
  8665. dom: {
  8666. tag: 'div',
  8667. classes: ['tox-swatches']
  8668. },
  8669. components: [Menu.parts.items({
  8670. preprocess: columns !== 'auto' ? chunk({
  8671. tag: 'div',
  8672. classes: ['tox-swatches__row']
  8673. }, columns) : identity
  8674. })]
  8675. }]
  8676. });
  8677. const forToolbar = columns => ({
  8678. dom: {
  8679. tag: 'div',
  8680. classes: [
  8681. 'tox-menu',
  8682. 'tox-collection',
  8683. 'tox-collection--toolbar',
  8684. 'tox-collection--toolbar-lg'
  8685. ]
  8686. },
  8687. components: [Menu.parts.items({
  8688. preprocess: chunk({
  8689. tag: 'div',
  8690. classes: ['tox-collection__group']
  8691. }, columns)
  8692. })]
  8693. });
  8694. const preprocessCollection = (items, isSeparator) => {
  8695. const allSplits = [];
  8696. let currentSplit = [];
  8697. each$1(items, (item, i) => {
  8698. if (isSeparator(item, i)) {
  8699. if (currentSplit.length > 0) {
  8700. allSplits.push(currentSplit);
  8701. }
  8702. currentSplit = [];
  8703. if (has$2(item.dom, 'innerHtml') || item.components && item.components.length > 0) {
  8704. currentSplit.push(item);
  8705. }
  8706. } else {
  8707. currentSplit.push(item);
  8708. }
  8709. });
  8710. if (currentSplit.length > 0) {
  8711. allSplits.push(currentSplit);
  8712. }
  8713. return map$2(allSplits, s => ({
  8714. dom: {
  8715. tag: 'div',
  8716. classes: ['tox-collection__group']
  8717. },
  8718. components: s
  8719. }));
  8720. };
  8721. const insertItemsPlaceholder = (columns, initItems, onItem) => {
  8722. return Menu.parts.items({
  8723. preprocess: rawItems => {
  8724. const enrichedItems = map$2(rawItems, onItem);
  8725. if (columns !== 'auto' && columns > 1) {
  8726. return chunk({
  8727. tag: 'div',
  8728. classes: ['tox-collection__group']
  8729. }, columns)(enrichedItems);
  8730. } else {
  8731. return preprocessCollection(enrichedItems, (_item, i) => initItems[i].type === 'separator');
  8732. }
  8733. }
  8734. });
  8735. };
  8736. const forCollection = (columns, initItems, _hasIcons = true) => ({
  8737. dom: {
  8738. tag: 'div',
  8739. classes: [
  8740. 'tox-menu',
  8741. 'tox-collection'
  8742. ].concat(columns === 1 ? ['tox-collection--list'] : ['tox-collection--grid'])
  8743. },
  8744. components: [insertItemsPlaceholder(columns, initItems, identity)]
  8745. });
  8746. const forCollectionWithSearchResults = (columns, initItems, _hasIcons = true) => {
  8747. const ariaControlsSearchResults = generate$6('aria-controls-search-results');
  8748. return {
  8749. dom: {
  8750. tag: 'div',
  8751. classes: [
  8752. 'tox-menu',
  8753. 'tox-collection',
  8754. searchResultsClass
  8755. ].concat(columns === 1 ? ['tox-collection--list'] : ['tox-collection--grid']),
  8756. attributes: { id: ariaControlsSearchResults }
  8757. },
  8758. components: [insertItemsPlaceholder(columns, initItems, augmentWithAria)]
  8759. };
  8760. };
  8761. const forCollectionWithSearchField = (columns, initItems, searchField) => {
  8762. const ariaControlsSearchResults = generate$6('aria-controls-search-results');
  8763. return {
  8764. dom: {
  8765. tag: 'div',
  8766. classes: [
  8767. 'tox-menu',
  8768. 'tox-collection'
  8769. ].concat(columns === 1 ? ['tox-collection--list'] : ['tox-collection--grid'])
  8770. },
  8771. components: [
  8772. renderMenuSearcher({
  8773. i18n: global$8.translate,
  8774. placeholder: searchField.placeholder
  8775. }),
  8776. {
  8777. dom: {
  8778. tag: 'div',
  8779. classes: [
  8780. ...columns === 1 ? ['tox-collection--list'] : ['tox-collection--grid'],
  8781. searchResultsClass
  8782. ],
  8783. attributes: { id: ariaControlsSearchResults }
  8784. },
  8785. components: [insertItemsPlaceholder(columns, initItems, augmentWithAria)]
  8786. }
  8787. ]
  8788. };
  8789. };
  8790. const forHorizontalCollection = (initItems, _hasIcons = true) => ({
  8791. dom: {
  8792. tag: 'div',
  8793. classes: [
  8794. 'tox-collection',
  8795. 'tox-collection--horizontal'
  8796. ]
  8797. },
  8798. components: [Menu.parts.items({ preprocess: items => preprocessCollection(items, (_item, i) => initItems[i].type === 'separator') })]
  8799. });
  8800. const menuHasIcons = xs => exists(xs, item => 'icon' in item && item.icon !== undefined);
  8801. const handleError = error => {
  8802. console.error(formatError(error));
  8803. console.log(error);
  8804. return Optional.none();
  8805. };
  8806. const createHorizontalPartialMenuWithAlloyItems = (value, _hasIcons, items, _columns, _menuLayout) => {
  8807. const structure = forHorizontalCollection(items);
  8808. return {
  8809. value,
  8810. dom: structure.dom,
  8811. components: structure.components,
  8812. items
  8813. };
  8814. };
  8815. const createPartialMenuWithAlloyItems = (value, hasIcons, items, columns, menuLayout) => {
  8816. const getNormalStructure = () => {
  8817. if (menuLayout.menuType !== 'searchable') {
  8818. return forCollection(columns, items);
  8819. } else {
  8820. return menuLayout.searchMode.searchMode === 'search-with-field' ? forCollectionWithSearchField(columns, items, menuLayout.searchMode) : forCollectionWithSearchResults(columns, items);
  8821. }
  8822. };
  8823. if (menuLayout.menuType === 'color') {
  8824. const structure = forSwatch(columns);
  8825. return {
  8826. value,
  8827. dom: structure.dom,
  8828. components: structure.components,
  8829. items
  8830. };
  8831. } else if (menuLayout.menuType === 'normal' && columns === 'auto') {
  8832. const structure = forCollection(columns, items);
  8833. return {
  8834. value,
  8835. dom: structure.dom,
  8836. components: structure.components,
  8837. items
  8838. };
  8839. } else if (menuLayout.menuType === 'normal' || menuLayout.menuType === 'searchable') {
  8840. const structure = getNormalStructure();
  8841. return {
  8842. value,
  8843. dom: structure.dom,
  8844. components: structure.components,
  8845. items
  8846. };
  8847. } else if (menuLayout.menuType === 'listpreview' && columns !== 'auto') {
  8848. const structure = forToolbar(columns);
  8849. return {
  8850. value,
  8851. dom: structure.dom,
  8852. components: structure.components,
  8853. items
  8854. };
  8855. } else {
  8856. return {
  8857. value,
  8858. dom: dom$1(hasIcons, columns, menuLayout.menuType),
  8859. components: components,
  8860. items
  8861. };
  8862. }
  8863. };
  8864. const type = requiredString('type');
  8865. const name$1 = requiredString('name');
  8866. const label = requiredString('label');
  8867. const text$1 = requiredString('text');
  8868. const title = requiredString('title');
  8869. const icon = requiredString('icon');
  8870. const value$1 = requiredString('value');
  8871. const fetch$1 = requiredFunction('fetch');
  8872. const getSubmenuItems = requiredFunction('getSubmenuItems');
  8873. const onAction = requiredFunction('onAction');
  8874. const onItemAction = requiredFunction('onItemAction');
  8875. const onSetup = defaultedFunction('onSetup', () => noop);
  8876. const optionalName = optionString('name');
  8877. const optionalText = optionString('text');
  8878. const optionalIcon = optionString('icon');
  8879. const optionalTooltip = optionString('tooltip');
  8880. const optionalLabel = optionString('label');
  8881. const optionalShortcut = optionString('shortcut');
  8882. const optionalSelect = optionFunction('select');
  8883. const active = defaultedBoolean('active', false);
  8884. const borderless = defaultedBoolean('borderless', false);
  8885. const enabled = defaultedBoolean('enabled', true);
  8886. const primary = defaultedBoolean('primary', false);
  8887. const defaultedColumns = num => defaulted('columns', num);
  8888. const defaultedMeta = defaulted('meta', {});
  8889. const defaultedOnAction = defaultedFunction('onAction', noop);
  8890. const defaultedType = type => defaultedString('type', type);
  8891. const generatedName = namePrefix => field$1('name', 'name', defaultedThunk(() => generate$6(`${ namePrefix }-name`)), string);
  8892. const generatedValue = valuePrefix => field$1('value', 'value', defaultedThunk(() => generate$6(`${ valuePrefix }-value`)), anyValue());
  8893. const separatorMenuItemSchema = objOf([
  8894. type,
  8895. optionalText
  8896. ]);
  8897. const createSeparatorMenuItem = spec => asRaw('separatormenuitem', separatorMenuItemSchema, spec);
  8898. const autocompleterItemSchema = objOf([
  8899. defaultedType('autocompleteitem'),
  8900. active,
  8901. enabled,
  8902. defaultedMeta,
  8903. value$1,
  8904. optionalText,
  8905. optionalIcon
  8906. ]);
  8907. const createSeparatorItem = spec => asRaw('Autocompleter.Separator', separatorMenuItemSchema, spec);
  8908. const createAutocompleterItem = spec => asRaw('Autocompleter.Item', autocompleterItemSchema, spec);
  8909. const baseToolbarButtonFields = [
  8910. enabled,
  8911. optionalTooltip,
  8912. optionalIcon,
  8913. optionalText,
  8914. onSetup
  8915. ];
  8916. const toolbarButtonSchema = objOf([
  8917. type,
  8918. onAction
  8919. ].concat(baseToolbarButtonFields));
  8920. const createToolbarButton = spec => asRaw('toolbarbutton', toolbarButtonSchema, spec);
  8921. const baseToolbarToggleButtonFields = [active].concat(baseToolbarButtonFields);
  8922. const toggleButtonSchema = objOf(baseToolbarToggleButtonFields.concat([
  8923. type,
  8924. onAction
  8925. ]));
  8926. const createToggleButton = spec => asRaw('ToggleButton', toggleButtonSchema, spec);
  8927. const contextBarFields = [
  8928. defaultedFunction('predicate', never),
  8929. defaultedStringEnum('scope', 'node', [
  8930. 'node',
  8931. 'editor'
  8932. ]),
  8933. defaultedStringEnum('position', 'selection', [
  8934. 'node',
  8935. 'selection',
  8936. 'line'
  8937. ])
  8938. ];
  8939. const contextButtonFields = baseToolbarButtonFields.concat([
  8940. defaultedType('contextformbutton'),
  8941. primary,
  8942. onAction,
  8943. customField('original', identity)
  8944. ]);
  8945. const contextToggleButtonFields = baseToolbarToggleButtonFields.concat([
  8946. defaultedType('contextformbutton'),
  8947. primary,
  8948. onAction,
  8949. customField('original', identity)
  8950. ]);
  8951. const launchButtonFields = baseToolbarButtonFields.concat([defaultedType('contextformbutton')]);
  8952. const launchToggleButtonFields = baseToolbarToggleButtonFields.concat([defaultedType('contextformtogglebutton')]);
  8953. const toggleOrNormal = choose$1('type', {
  8954. contextformbutton: contextButtonFields,
  8955. contextformtogglebutton: contextToggleButtonFields
  8956. });
  8957. const contextFormSchema = objOf([
  8958. defaultedType('contextform'),
  8959. defaultedFunction('initValue', constant$1('')),
  8960. optionalLabel,
  8961. requiredArrayOf('commands', toggleOrNormal),
  8962. optionOf('launch', choose$1('type', {
  8963. contextformbutton: launchButtonFields,
  8964. contextformtogglebutton: launchToggleButtonFields
  8965. }))
  8966. ].concat(contextBarFields));
  8967. const createContextForm = spec => asRaw('ContextForm', contextFormSchema, spec);
  8968. const contextToolbarSchema = objOf([
  8969. defaultedType('contexttoolbar'),
  8970. requiredString('items')
  8971. ].concat(contextBarFields));
  8972. const createContextToolbar = spec => asRaw('ContextToolbar', contextToolbarSchema, spec);
  8973. const cardImageFields = [
  8974. type,
  8975. requiredString('src'),
  8976. optionString('alt'),
  8977. defaultedArrayOf('classes', [], string)
  8978. ];
  8979. const cardImageSchema = objOf(cardImageFields);
  8980. const cardTextFields = [
  8981. type,
  8982. text$1,
  8983. optionalName,
  8984. defaultedArrayOf('classes', ['tox-collection__item-label'], string)
  8985. ];
  8986. const cardTextSchema = objOf(cardTextFields);
  8987. const itemSchema$1 = valueThunk(() => choose$2('type', {
  8988. cardimage: cardImageSchema,
  8989. cardtext: cardTextSchema,
  8990. cardcontainer: cardContainerSchema
  8991. }));
  8992. const cardContainerSchema = objOf([
  8993. type,
  8994. defaultedString('direction', 'horizontal'),
  8995. defaultedString('align', 'left'),
  8996. defaultedString('valign', 'middle'),
  8997. requiredArrayOf('items', itemSchema$1)
  8998. ]);
  8999. const commonMenuItemFields = [
  9000. enabled,
  9001. optionalText,
  9002. optionalShortcut,
  9003. generatedValue('menuitem'),
  9004. defaultedMeta
  9005. ];
  9006. const cardMenuItemSchema = objOf([
  9007. type,
  9008. optionalLabel,
  9009. requiredArrayOf('items', itemSchema$1),
  9010. onSetup,
  9011. defaultedOnAction
  9012. ].concat(commonMenuItemFields));
  9013. const createCardMenuItem = spec => asRaw('cardmenuitem', cardMenuItemSchema, spec);
  9014. const choiceMenuItemSchema = objOf([
  9015. type,
  9016. active,
  9017. optionalIcon
  9018. ].concat(commonMenuItemFields));
  9019. const createChoiceMenuItem = spec => asRaw('choicemenuitem', choiceMenuItemSchema, spec);
  9020. const baseFields = [
  9021. type,
  9022. requiredString('fancytype'),
  9023. defaultedOnAction
  9024. ];
  9025. const insertTableFields = [defaulted('initData', {})].concat(baseFields);
  9026. const colorSwatchFields = [defaultedObjOf('initData', {}, [
  9027. defaultedBoolean('allowCustomColors', true),
  9028. defaultedString('storageKey', 'default'),
  9029. optionArrayOf('colors', anyValue())
  9030. ])].concat(baseFields);
  9031. const fancyMenuItemSchema = choose$1('fancytype', {
  9032. inserttable: insertTableFields,
  9033. colorswatch: colorSwatchFields
  9034. });
  9035. const createFancyMenuItem = spec => asRaw('fancymenuitem', fancyMenuItemSchema, spec);
  9036. const menuItemSchema = objOf([
  9037. type,
  9038. onSetup,
  9039. defaultedOnAction,
  9040. optionalIcon
  9041. ].concat(commonMenuItemFields));
  9042. const createMenuItem = spec => asRaw('menuitem', menuItemSchema, spec);
  9043. const nestedMenuItemSchema = objOf([
  9044. type,
  9045. getSubmenuItems,
  9046. onSetup,
  9047. optionalIcon
  9048. ].concat(commonMenuItemFields));
  9049. const createNestedMenuItem = spec => asRaw('nestedmenuitem', nestedMenuItemSchema, spec);
  9050. const toggleMenuItemSchema = objOf([
  9051. type,
  9052. optionalIcon,
  9053. active,
  9054. onSetup,
  9055. onAction
  9056. ].concat(commonMenuItemFields));
  9057. const createToggleMenuItem = spec => asRaw('togglemenuitem', toggleMenuItemSchema, spec);
  9058. const detectSize = (comp, margin, selectorClass) => {
  9059. const descendants$1 = descendants(comp.element, '.' + selectorClass);
  9060. if (descendants$1.length > 0) {
  9061. const columnLength = findIndex$1(descendants$1, c => {
  9062. const thisTop = c.dom.getBoundingClientRect().top;
  9063. const cTop = descendants$1[0].dom.getBoundingClientRect().top;
  9064. return Math.abs(thisTop - cTop) > margin;
  9065. }).getOr(descendants$1.length);
  9066. return Optional.some({
  9067. numColumns: columnLength,
  9068. numRows: Math.ceil(descendants$1.length / columnLength)
  9069. });
  9070. } else {
  9071. return Optional.none();
  9072. }
  9073. };
  9074. const namedEvents = (name, handlers) => derive$1([config(name, handlers)]);
  9075. const unnamedEvents = handlers => namedEvents(generate$6('unnamed-events'), handlers);
  9076. const SimpleBehaviours = {
  9077. namedEvents,
  9078. unnamedEvents
  9079. };
  9080. const ExclusivityChannel = generate$6('tooltip.exclusive');
  9081. const ShowTooltipEvent = generate$6('tooltip.show');
  9082. const HideTooltipEvent = generate$6('tooltip.hide');
  9083. const hideAllExclusive = (component, _tConfig, _tState) => {
  9084. component.getSystem().broadcastOn([ExclusivityChannel], {});
  9085. };
  9086. const setComponents = (component, tConfig, tState, specs) => {
  9087. tState.getTooltip().each(tooltip => {
  9088. if (tooltip.getSystem().isConnected()) {
  9089. Replacing.set(tooltip, specs);
  9090. }
  9091. });
  9092. };
  9093. var TooltippingApis = /*#__PURE__*/Object.freeze({
  9094. __proto__: null,
  9095. hideAllExclusive: hideAllExclusive,
  9096. setComponents: setComponents
  9097. });
  9098. const events$9 = (tooltipConfig, state) => {
  9099. const hide = comp => {
  9100. state.getTooltip().each(p => {
  9101. detach(p);
  9102. tooltipConfig.onHide(comp, p);
  9103. state.clearTooltip();
  9104. });
  9105. state.clearTimer();
  9106. };
  9107. const show = comp => {
  9108. if (!state.isShowing()) {
  9109. hideAllExclusive(comp);
  9110. const sink = tooltipConfig.lazySink(comp).getOrDie();
  9111. const popup = comp.getSystem().build({
  9112. dom: tooltipConfig.tooltipDom,
  9113. components: tooltipConfig.tooltipComponents,
  9114. events: derive$2(tooltipConfig.mode === 'normal' ? [
  9115. run$1(mouseover(), _ => {
  9116. emit(comp, ShowTooltipEvent);
  9117. }),
  9118. run$1(mouseout(), _ => {
  9119. emit(comp, HideTooltipEvent);
  9120. })
  9121. ] : []),
  9122. behaviours: derive$1([Replacing.config({})])
  9123. });
  9124. state.setTooltip(popup);
  9125. attach(sink, popup);
  9126. tooltipConfig.onShow(comp, popup);
  9127. Positioning.position(sink, popup, { anchor: tooltipConfig.anchor(comp) });
  9128. }
  9129. };
  9130. return derive$2(flatten([
  9131. [
  9132. run$1(ShowTooltipEvent, comp => {
  9133. state.resetTimer(() => {
  9134. show(comp);
  9135. }, tooltipConfig.delay);
  9136. }),
  9137. run$1(HideTooltipEvent, comp => {
  9138. state.resetTimer(() => {
  9139. hide(comp);
  9140. }, tooltipConfig.delay);
  9141. }),
  9142. run$1(receive(), (comp, message) => {
  9143. const receivingData = message;
  9144. if (!receivingData.universal) {
  9145. if (contains$2(receivingData.channels, ExclusivityChannel)) {
  9146. hide(comp);
  9147. }
  9148. }
  9149. }),
  9150. runOnDetached(comp => {
  9151. hide(comp);
  9152. })
  9153. ],
  9154. tooltipConfig.mode === 'normal' ? [
  9155. run$1(focusin(), comp => {
  9156. emit(comp, ShowTooltipEvent);
  9157. }),
  9158. run$1(postBlur(), comp => {
  9159. emit(comp, HideTooltipEvent);
  9160. }),
  9161. run$1(mouseover(), comp => {
  9162. emit(comp, ShowTooltipEvent);
  9163. }),
  9164. run$1(mouseout(), comp => {
  9165. emit(comp, HideTooltipEvent);
  9166. })
  9167. ] : [
  9168. run$1(highlight$1(), (comp, _se) => {
  9169. emit(comp, ShowTooltipEvent);
  9170. }),
  9171. run$1(dehighlight$1(), comp => {
  9172. emit(comp, HideTooltipEvent);
  9173. })
  9174. ]
  9175. ]));
  9176. };
  9177. var ActiveTooltipping = /*#__PURE__*/Object.freeze({
  9178. __proto__: null,
  9179. events: events$9
  9180. });
  9181. var TooltippingSchema = [
  9182. required$1('lazySink'),
  9183. required$1('tooltipDom'),
  9184. defaulted('exclusive', true),
  9185. defaulted('tooltipComponents', []),
  9186. defaulted('delay', 300),
  9187. defaultedStringEnum('mode', 'normal', [
  9188. 'normal',
  9189. 'follow-highlight'
  9190. ]),
  9191. defaulted('anchor', comp => ({
  9192. type: 'hotspot',
  9193. hotspot: comp,
  9194. layouts: {
  9195. onLtr: constant$1([
  9196. south$2,
  9197. north$2,
  9198. southeast$2,
  9199. northeast$2,
  9200. southwest$2,
  9201. northwest$2
  9202. ]),
  9203. onRtl: constant$1([
  9204. south$2,
  9205. north$2,
  9206. southeast$2,
  9207. northeast$2,
  9208. southwest$2,
  9209. northwest$2
  9210. ])
  9211. }
  9212. })),
  9213. onHandler('onHide'),
  9214. onHandler('onShow')
  9215. ];
  9216. const init$b = () => {
  9217. const timer = value$2();
  9218. const popup = value$2();
  9219. const clearTimer = () => {
  9220. timer.on(clearTimeout);
  9221. };
  9222. const resetTimer = (f, delay) => {
  9223. clearTimer();
  9224. timer.set(setTimeout(f, delay));
  9225. };
  9226. const readState = constant$1('not-implemented');
  9227. return nu$8({
  9228. getTooltip: popup.get,
  9229. isShowing: popup.isSet,
  9230. setTooltip: popup.set,
  9231. clearTooltip: popup.clear,
  9232. clearTimer,
  9233. resetTimer,
  9234. readState
  9235. });
  9236. };
  9237. var TooltippingState = /*#__PURE__*/Object.freeze({
  9238. __proto__: null,
  9239. init: init$b
  9240. });
  9241. const Tooltipping = create$4({
  9242. fields: TooltippingSchema,
  9243. name: 'tooltipping',
  9244. active: ActiveTooltipping,
  9245. state: TooltippingState,
  9246. apis: TooltippingApis
  9247. });
  9248. const escape = text => text.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
  9249. const ReadOnlyChannel = 'silver.readonly';
  9250. const ReadOnlyDataSchema = objOf([requiredBoolean('readonly')]);
  9251. const broadcastReadonly = (uiRefs, readonly) => {
  9252. const outerContainer = uiRefs.mainUi.outerContainer;
  9253. const target = outerContainer.element;
  9254. const motherships = [
  9255. uiRefs.mainUi.mothership,
  9256. ...uiRefs.uiMotherships
  9257. ];
  9258. if (readonly) {
  9259. each$1(motherships, m => {
  9260. m.broadcastOn([dismissPopups()], { target });
  9261. });
  9262. }
  9263. each$1(motherships, m => {
  9264. m.broadcastOn([ReadOnlyChannel], { readonly });
  9265. });
  9266. };
  9267. const setupReadonlyModeSwitch = (editor, uiRefs) => {
  9268. editor.on('init', () => {
  9269. if (editor.mode.isReadOnly()) {
  9270. broadcastReadonly(uiRefs, true);
  9271. }
  9272. });
  9273. editor.on('SwitchMode', () => broadcastReadonly(uiRefs, editor.mode.isReadOnly()));
  9274. if (isReadOnly(editor)) {
  9275. editor.mode.set('readonly');
  9276. }
  9277. };
  9278. const receivingConfig = () => Receiving.config({
  9279. channels: {
  9280. [ReadOnlyChannel]: {
  9281. schema: ReadOnlyDataSchema,
  9282. onReceive: (comp, data) => {
  9283. Disabling.set(comp, data.readonly);
  9284. }
  9285. }
  9286. }
  9287. });
  9288. const item = disabled => Disabling.config({
  9289. disabled,
  9290. disableClass: 'tox-collection__item--state-disabled'
  9291. });
  9292. const button = disabled => Disabling.config({ disabled });
  9293. const splitButton = disabled => Disabling.config({
  9294. disabled,
  9295. disableClass: 'tox-tbtn--disabled'
  9296. });
  9297. const toolbarButton = disabled => Disabling.config({
  9298. disabled,
  9299. disableClass: 'tox-tbtn--disabled',
  9300. useNative: false
  9301. });
  9302. const DisablingConfigs = {
  9303. item,
  9304. button,
  9305. splitButton,
  9306. toolbarButton
  9307. };
  9308. const runWithApi = (info, comp) => {
  9309. const api = info.getApi(comp);
  9310. return f => {
  9311. f(api);
  9312. };
  9313. };
  9314. const onControlAttached = (info, editorOffCell) => runOnAttached(comp => {
  9315. const run = runWithApi(info, comp);
  9316. run(api => {
  9317. const onDestroy = info.onSetup(api);
  9318. if (isFunction(onDestroy)) {
  9319. editorOffCell.set(onDestroy);
  9320. }
  9321. });
  9322. });
  9323. const onControlDetached = (getApi, editorOffCell) => runOnDetached(comp => runWithApi(getApi, comp)(editorOffCell.get()));
  9324. const onMenuItemExecute = (info, itemResponse) => runOnExecute$1((comp, simulatedEvent) => {
  9325. runWithApi(info, comp)(info.onAction);
  9326. if (!info.triggersSubmenu && itemResponse === ItemResponse$1.CLOSE_ON_EXECUTE) {
  9327. if (comp.getSystem().isConnected()) {
  9328. emit(comp, sandboxClose());
  9329. }
  9330. simulatedEvent.stop();
  9331. }
  9332. });
  9333. const menuItemEventOrder = {
  9334. [execute$5()]: [
  9335. 'disabling',
  9336. 'alloy.base.behaviour',
  9337. 'toggling',
  9338. 'item-events'
  9339. ]
  9340. };
  9341. const componentRenderPipeline = cat;
  9342. const renderCommonItem = (spec, structure, itemResponse, providersBackstage) => {
  9343. const editorOffCell = Cell(noop);
  9344. return {
  9345. type: 'item',
  9346. dom: structure.dom,
  9347. components: componentRenderPipeline(structure.optComponents),
  9348. data: spec.data,
  9349. eventOrder: menuItemEventOrder,
  9350. hasSubmenu: spec.triggersSubmenu,
  9351. itemBehaviours: derive$1([
  9352. config('item-events', [
  9353. onMenuItemExecute(spec, itemResponse),
  9354. onControlAttached(spec, editorOffCell),
  9355. onControlDetached(spec, editorOffCell)
  9356. ]),
  9357. DisablingConfigs.item(() => !spec.enabled || providersBackstage.isDisabled()),
  9358. receivingConfig(),
  9359. Replacing.config({})
  9360. ].concat(spec.itemBehaviours))
  9361. };
  9362. };
  9363. const buildData = source => ({
  9364. value: source.value,
  9365. meta: {
  9366. text: source.text.getOr(''),
  9367. ...source.meta
  9368. }
  9369. });
  9370. const convertText = source => {
  9371. const isMac = global$5.os.isMacOS() || global$5.os.isiOS();
  9372. const mac = {
  9373. alt: '\u2325',
  9374. ctrl: '\u2303',
  9375. shift: '\u21E7',
  9376. meta: '\u2318',
  9377. access: '\u2303\u2325'
  9378. };
  9379. const other = {
  9380. meta: 'Ctrl',
  9381. access: 'Shift+Alt'
  9382. };
  9383. const replace = isMac ? mac : other;
  9384. const shortcut = source.split('+');
  9385. const updated = map$2(shortcut, segment => {
  9386. const search = segment.toLowerCase().trim();
  9387. return has$2(replace, search) ? replace[search] : segment;
  9388. });
  9389. return isMac ? updated.join('') : updated.join('+');
  9390. };
  9391. const renderIcon$1 = (name, icons, classes = [iconClass]) => render$3(name, {
  9392. tag: 'div',
  9393. classes
  9394. }, icons);
  9395. const renderText = text => ({
  9396. dom: {
  9397. tag: 'div',
  9398. classes: [textClass]
  9399. },
  9400. components: [text$2(global$8.translate(text))]
  9401. });
  9402. const renderHtml = (html, classes) => ({
  9403. dom: {
  9404. tag: 'div',
  9405. classes,
  9406. innerHtml: html
  9407. }
  9408. });
  9409. const renderStyledText = (style, text) => ({
  9410. dom: {
  9411. tag: 'div',
  9412. classes: [textClass]
  9413. },
  9414. components: [{
  9415. dom: {
  9416. tag: style.tag,
  9417. styles: style.styles
  9418. },
  9419. components: [text$2(global$8.translate(text))]
  9420. }]
  9421. });
  9422. const renderShortcut = shortcut => ({
  9423. dom: {
  9424. tag: 'div',
  9425. classes: [accessoryClass]
  9426. },
  9427. components: [text$2(convertText(shortcut))]
  9428. });
  9429. const renderCheckmark = icons => renderIcon$1('checkmark', icons, [checkmarkClass]);
  9430. const renderSubmenuCaret = icons => renderIcon$1('chevron-right', icons, [caretClass]);
  9431. const renderDownwardsCaret = icons => renderIcon$1('chevron-down', icons, [caretClass]);
  9432. const renderContainer = (container, components) => {
  9433. const directionClass = container.direction === 'vertical' ? containerColumnClass : containerRowClass;
  9434. const alignClass = container.align === 'left' ? containerAlignLeftClass : containerAlignRightClass;
  9435. const getValignClass = () => {
  9436. switch (container.valign) {
  9437. case 'top':
  9438. return containerValignTopClass;
  9439. case 'middle':
  9440. return containerValignMiddleClass;
  9441. case 'bottom':
  9442. return containerValignBottomClass;
  9443. }
  9444. };
  9445. return {
  9446. dom: {
  9447. tag: 'div',
  9448. classes: [
  9449. containerClass,
  9450. directionClass,
  9451. alignClass,
  9452. getValignClass()
  9453. ]
  9454. },
  9455. components
  9456. };
  9457. };
  9458. const renderImage = (src, classes, alt) => ({
  9459. dom: {
  9460. tag: 'img',
  9461. classes,
  9462. attributes: {
  9463. src,
  9464. alt: alt.getOr('')
  9465. }
  9466. }
  9467. });
  9468. const renderColorStructure = (item, providerBackstage, fallbackIcon) => {
  9469. const colorPickerCommand = 'custom';
  9470. const removeColorCommand = 'remove';
  9471. const itemText = item.ariaLabel;
  9472. const itemValue = item.value;
  9473. const iconSvg = item.iconContent.map(name => getOr(name, providerBackstage.icons, fallbackIcon));
  9474. const getDom = () => {
  9475. const common = colorClass;
  9476. const icon = iconSvg.getOr('');
  9477. const attributes = itemText.map(text => ({ title: providerBackstage.translate(text) })).getOr({});
  9478. const baseDom = {
  9479. tag: 'div',
  9480. attributes,
  9481. classes: [common]
  9482. };
  9483. if (itemValue === colorPickerCommand) {
  9484. return {
  9485. ...baseDom,
  9486. tag: 'button',
  9487. classes: [
  9488. ...baseDom.classes,
  9489. 'tox-swatches__picker-btn'
  9490. ],
  9491. innerHtml: icon
  9492. };
  9493. } else if (itemValue === removeColorCommand) {
  9494. return {
  9495. ...baseDom,
  9496. classes: [
  9497. ...baseDom.classes,
  9498. 'tox-swatch--remove'
  9499. ],
  9500. innerHtml: icon
  9501. };
  9502. } else if (isNonNullable(itemValue)) {
  9503. return {
  9504. ...baseDom,
  9505. attributes: {
  9506. ...baseDom.attributes,
  9507. 'data-mce-color': itemValue
  9508. },
  9509. styles: { 'background-color': itemValue },
  9510. innerHtml: icon
  9511. };
  9512. } else {
  9513. return baseDom;
  9514. }
  9515. };
  9516. return {
  9517. dom: getDom(),
  9518. optComponents: []
  9519. };
  9520. };
  9521. const renderItemDomStructure = ariaLabel => {
  9522. const domTitle = ariaLabel.map(label => ({ attributes: { title: global$8.translate(label) } })).getOr({});
  9523. return {
  9524. tag: 'div',
  9525. classes: [
  9526. navClass,
  9527. selectableClass
  9528. ],
  9529. ...domTitle
  9530. };
  9531. };
  9532. const renderNormalItemStructure = (info, providersBackstage, renderIcons, fallbackIcon) => {
  9533. const iconSpec = {
  9534. tag: 'div',
  9535. classes: [iconClass]
  9536. };
  9537. const renderIcon = iconName => render$3(iconName, iconSpec, providersBackstage.icons, fallbackIcon);
  9538. const renderEmptyIcon = () => Optional.some({ dom: iconSpec });
  9539. const leftIcon = renderIcons ? info.iconContent.map(renderIcon).orThunk(renderEmptyIcon) : Optional.none();
  9540. const checkmark = info.checkMark;
  9541. const textRender = Optional.from(info.meta).fold(() => renderText, meta => has$2(meta, 'style') ? curry(renderStyledText, meta.style) : renderText);
  9542. const content = info.htmlContent.fold(() => info.textContent.map(textRender), html => Optional.some(renderHtml(html, [textClass])));
  9543. const menuItem = {
  9544. dom: renderItemDomStructure(info.ariaLabel),
  9545. optComponents: [
  9546. leftIcon,
  9547. content,
  9548. info.shortcutContent.map(renderShortcut),
  9549. checkmark,
  9550. info.caret
  9551. ]
  9552. };
  9553. return menuItem;
  9554. };
  9555. const renderItemStructure = (info, providersBackstage, renderIcons, fallbackIcon = Optional.none()) => {
  9556. if (info.presets === 'color') {
  9557. return renderColorStructure(info, providersBackstage, fallbackIcon);
  9558. } else {
  9559. return renderNormalItemStructure(info, providersBackstage, renderIcons, fallbackIcon);
  9560. }
  9561. };
  9562. const tooltipBehaviour = (meta, sharedBackstage) => get$g(meta, 'tooltipWorker').map(tooltipWorker => [Tooltipping.config({
  9563. lazySink: sharedBackstage.getSink,
  9564. tooltipDom: {
  9565. tag: 'div',
  9566. classes: ['tox-tooltip-worker-container']
  9567. },
  9568. tooltipComponents: [],
  9569. anchor: comp => ({
  9570. type: 'submenu',
  9571. item: comp,
  9572. overrides: { maxHeightFunction: expandable$1 }
  9573. }),
  9574. mode: 'follow-highlight',
  9575. onShow: (component, _tooltip) => {
  9576. tooltipWorker(elm => {
  9577. Tooltipping.setComponents(component, [external$1({ element: SugarElement.fromDom(elm) })]);
  9578. });
  9579. }
  9580. })]).getOr([]);
  9581. const encodeText = text => global$7.DOM.encode(text);
  9582. const replaceText = (text, matchText) => {
  9583. const translated = global$8.translate(text);
  9584. const encoded = encodeText(translated);
  9585. if (matchText.length > 0) {
  9586. const escapedMatchRegex = new RegExp(escape(matchText), 'gi');
  9587. return encoded.replace(escapedMatchRegex, match => `<span class="tox-autocompleter-highlight">${ match }</span>`);
  9588. } else {
  9589. return encoded;
  9590. }
  9591. };
  9592. const renderAutocompleteItem = (spec, matchText, useText, presets, onItemValueHandler, itemResponse, sharedBackstage, renderIcons = true) => {
  9593. const structure = renderItemStructure({
  9594. presets,
  9595. textContent: Optional.none(),
  9596. htmlContent: useText ? spec.text.map(text => replaceText(text, matchText)) : Optional.none(),
  9597. ariaLabel: spec.text,
  9598. iconContent: spec.icon,
  9599. shortcutContent: Optional.none(),
  9600. checkMark: Optional.none(),
  9601. caret: Optional.none(),
  9602. value: spec.value
  9603. }, sharedBackstage.providers, renderIcons, spec.icon);
  9604. return renderCommonItem({
  9605. data: buildData(spec),
  9606. enabled: spec.enabled,
  9607. getApi: constant$1({}),
  9608. onAction: _api => onItemValueHandler(spec.value, spec.meta),
  9609. onSetup: constant$1(noop),
  9610. triggersSubmenu: false,
  9611. itemBehaviours: tooltipBehaviour(spec.meta, sharedBackstage)
  9612. }, structure, itemResponse, sharedBackstage.providers);
  9613. };
  9614. const render$2 = (items, extras) => map$2(items, item => {
  9615. switch (item.type) {
  9616. case 'cardcontainer':
  9617. return renderContainer(item, render$2(item.items, extras));
  9618. case 'cardimage':
  9619. return renderImage(item.src, item.classes, item.alt);
  9620. case 'cardtext':
  9621. const shouldHighlight = item.name.exists(name => contains$2(extras.cardText.highlightOn, name));
  9622. const matchText = shouldHighlight ? Optional.from(extras.cardText.matchText).getOr('') : '';
  9623. return renderHtml(replaceText(item.text, matchText), item.classes);
  9624. }
  9625. });
  9626. const renderCardMenuItem = (spec, itemResponse, sharedBackstage, extras) => {
  9627. const getApi = component => ({
  9628. isEnabled: () => !Disabling.isDisabled(component),
  9629. setEnabled: state => {
  9630. Disabling.set(component, !state);
  9631. each$1(descendants(component.element, '*'), elm => {
  9632. component.getSystem().getByDom(elm).each(comp => {
  9633. if (comp.hasConfigured(Disabling)) {
  9634. Disabling.set(comp, !state);
  9635. }
  9636. });
  9637. });
  9638. }
  9639. });
  9640. const structure = {
  9641. dom: renderItemDomStructure(spec.label),
  9642. optComponents: [Optional.some({
  9643. dom: {
  9644. tag: 'div',
  9645. classes: [
  9646. containerClass,
  9647. containerRowClass
  9648. ]
  9649. },
  9650. components: render$2(spec.items, extras)
  9651. })]
  9652. };
  9653. return renderCommonItem({
  9654. data: buildData({
  9655. text: Optional.none(),
  9656. ...spec
  9657. }),
  9658. enabled: spec.enabled,
  9659. getApi,
  9660. onAction: spec.onAction,
  9661. onSetup: spec.onSetup,
  9662. triggersSubmenu: false,
  9663. itemBehaviours: Optional.from(extras.itemBehaviours).getOr([])
  9664. }, structure, itemResponse, sharedBackstage.providers);
  9665. };
  9666. const renderChoiceItem = (spec, useText, presets, onItemValueHandler, isSelected, itemResponse, providersBackstage, renderIcons = true) => {
  9667. const getApi = component => ({
  9668. setActive: state => {
  9669. Toggling.set(component, state);
  9670. },
  9671. isActive: () => Toggling.isOn(component),
  9672. isEnabled: () => !Disabling.isDisabled(component),
  9673. setEnabled: state => Disabling.set(component, !state)
  9674. });
  9675. const structure = renderItemStructure({
  9676. presets,
  9677. textContent: useText ? spec.text : Optional.none(),
  9678. htmlContent: Optional.none(),
  9679. ariaLabel: spec.text,
  9680. iconContent: spec.icon,
  9681. shortcutContent: useText ? spec.shortcut : Optional.none(),
  9682. checkMark: useText ? Optional.some(renderCheckmark(providersBackstage.icons)) : Optional.none(),
  9683. caret: Optional.none(),
  9684. value: spec.value
  9685. }, providersBackstage, renderIcons);
  9686. return deepMerge(renderCommonItem({
  9687. data: buildData(spec),
  9688. enabled: spec.enabled,
  9689. getApi,
  9690. onAction: _api => onItemValueHandler(spec.value),
  9691. onSetup: api => {
  9692. api.setActive(isSelected);
  9693. return noop;
  9694. },
  9695. triggersSubmenu: false,
  9696. itemBehaviours: []
  9697. }, structure, itemResponse, providersBackstage), {
  9698. toggling: {
  9699. toggleClass: tickedClass,
  9700. toggleOnExecute: false,
  9701. selected: spec.active,
  9702. exclusive: true
  9703. }
  9704. });
  9705. };
  9706. const parts$f = generate$3(owner$2(), parts$h());
  9707. const hexColour = value => ({ value });
  9708. const shorthandRegex = /^#?([a-f\d])([a-f\d])([a-f\d])$/i;
  9709. const longformRegex = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i;
  9710. const isHexString = hex => shorthandRegex.test(hex) || longformRegex.test(hex);
  9711. const normalizeHex = hex => removeLeading(hex, '#').toUpperCase();
  9712. const fromString$1 = hex => isHexString(hex) ? Optional.some({ value: normalizeHex(hex) }) : Optional.none();
  9713. const getLongForm = hex => {
  9714. const hexString = hex.value.replace(shorthandRegex, (m, r, g, b) => r + r + g + g + b + b);
  9715. return { value: hexString };
  9716. };
  9717. const extractValues = hex => {
  9718. const longForm = getLongForm(hex);
  9719. const splitForm = longformRegex.exec(longForm.value);
  9720. return splitForm === null ? [
  9721. 'FFFFFF',
  9722. 'FF',
  9723. 'FF',
  9724. 'FF'
  9725. ] : splitForm;
  9726. };
  9727. const toHex = component => {
  9728. const hex = component.toString(16);
  9729. return (hex.length === 1 ? '0' + hex : hex).toUpperCase();
  9730. };
  9731. const fromRgba = rgbaColour => {
  9732. const value = toHex(rgbaColour.red) + toHex(rgbaColour.green) + toHex(rgbaColour.blue);
  9733. return hexColour(value);
  9734. };
  9735. const min = Math.min;
  9736. const max = Math.max;
  9737. const round$1 = Math.round;
  9738. const rgbRegex = /^\s*rgb\s*\(\s*(\d+)\s*,\s*(\d+)\s*,\s*(\d+)\s*\)\s*$/i;
  9739. const rgbaRegex = /^\s*rgba\s*\(\s*(\d+)\s*,\s*(\d+)\s*,\s*(\d+)\s*,\s*(\d?(?:\.\d+)?)\s*\)\s*$/i;
  9740. const rgbaColour = (red, green, blue, alpha) => ({
  9741. red,
  9742. green,
  9743. blue,
  9744. alpha
  9745. });
  9746. const isRgbaComponent = value => {
  9747. const num = parseInt(value, 10);
  9748. return num.toString() === value && num >= 0 && num <= 255;
  9749. };
  9750. const fromHsv = hsv => {
  9751. let r;
  9752. let g;
  9753. let b;
  9754. const hue = (hsv.hue || 0) % 360;
  9755. let saturation = hsv.saturation / 100;
  9756. let brightness = hsv.value / 100;
  9757. saturation = max(0, min(saturation, 1));
  9758. brightness = max(0, min(brightness, 1));
  9759. if (saturation === 0) {
  9760. r = g = b = round$1(255 * brightness);
  9761. return rgbaColour(r, g, b, 1);
  9762. }
  9763. const side = hue / 60;
  9764. const chroma = brightness * saturation;
  9765. const x = chroma * (1 - Math.abs(side % 2 - 1));
  9766. const match = brightness - chroma;
  9767. switch (Math.floor(side)) {
  9768. case 0:
  9769. r = chroma;
  9770. g = x;
  9771. b = 0;
  9772. break;
  9773. case 1:
  9774. r = x;
  9775. g = chroma;
  9776. b = 0;
  9777. break;
  9778. case 2:
  9779. r = 0;
  9780. g = chroma;
  9781. b = x;
  9782. break;
  9783. case 3:
  9784. r = 0;
  9785. g = x;
  9786. b = chroma;
  9787. break;
  9788. case 4:
  9789. r = x;
  9790. g = 0;
  9791. b = chroma;
  9792. break;
  9793. case 5:
  9794. r = chroma;
  9795. g = 0;
  9796. b = x;
  9797. break;
  9798. default:
  9799. r = g = b = 0;
  9800. }
  9801. r = round$1(255 * (r + match));
  9802. g = round$1(255 * (g + match));
  9803. b = round$1(255 * (b + match));
  9804. return rgbaColour(r, g, b, 1);
  9805. };
  9806. const fromHex = hexColour => {
  9807. const result = extractValues(hexColour);
  9808. const red = parseInt(result[1], 16);
  9809. const green = parseInt(result[2], 16);
  9810. const blue = parseInt(result[3], 16);
  9811. return rgbaColour(red, green, blue, 1);
  9812. };
  9813. const fromStringValues = (red, green, blue, alpha) => {
  9814. const r = parseInt(red, 10);
  9815. const g = parseInt(green, 10);
  9816. const b = parseInt(blue, 10);
  9817. const a = parseFloat(alpha);
  9818. return rgbaColour(r, g, b, a);
  9819. };
  9820. const fromString = rgbaString => {
  9821. if (rgbaString === 'transparent') {
  9822. return Optional.some(rgbaColour(0, 0, 0, 0));
  9823. }
  9824. const rgbMatch = rgbRegex.exec(rgbaString);
  9825. if (rgbMatch !== null) {
  9826. return Optional.some(fromStringValues(rgbMatch[1], rgbMatch[2], rgbMatch[3], '1'));
  9827. }
  9828. const rgbaMatch = rgbaRegex.exec(rgbaString);
  9829. if (rgbaMatch !== null) {
  9830. return Optional.some(fromStringValues(rgbaMatch[1], rgbaMatch[2], rgbaMatch[3], rgbaMatch[4]));
  9831. }
  9832. return Optional.none();
  9833. };
  9834. const toString = rgba => `rgba(${ rgba.red },${ rgba.green },${ rgba.blue },${ rgba.alpha })`;
  9835. const red = rgbaColour(255, 0, 0, 1);
  9836. const fireSkinLoaded$1 = editor => {
  9837. editor.dispatch('SkinLoaded');
  9838. };
  9839. const fireSkinLoadError$1 = (editor, error) => {
  9840. editor.dispatch('SkinLoadError', error);
  9841. };
  9842. const fireResizeEditor = editor => {
  9843. editor.dispatch('ResizeEditor');
  9844. };
  9845. const fireResizeContent = (editor, e) => {
  9846. editor.dispatch('ResizeContent', e);
  9847. };
  9848. const fireScrollContent = (editor, e) => {
  9849. editor.dispatch('ScrollContent', e);
  9850. };
  9851. const fireTextColorChange = (editor, data) => {
  9852. editor.dispatch('TextColorChange', data);
  9853. };
  9854. const fireAfterProgressState = (editor, state) => {
  9855. editor.dispatch('AfterProgressState', { state });
  9856. };
  9857. const fireResolveName = (editor, node) => editor.dispatch('ResolveName', {
  9858. name: node.nodeName.toLowerCase(),
  9859. target: node
  9860. });
  9861. const fireToggleToolbarDrawer = (editor, state) => {
  9862. editor.dispatch('ToggleToolbarDrawer', { state });
  9863. };
  9864. var global$4 = tinymce.util.Tools.resolve('tinymce.util.LocalStorage');
  9865. const cacheStorage = {};
  9866. const ColorCache = (storageId, max = 10) => {
  9867. const storageString = global$4.getItem(storageId);
  9868. const localstorage = isString(storageString) ? JSON.parse(storageString) : [];
  9869. const prune = list => {
  9870. const diff = max - list.length;
  9871. return diff < 0 ? list.slice(0, max) : list;
  9872. };
  9873. const cache = prune(localstorage);
  9874. const add = key => {
  9875. indexOf(cache, key).each(remove);
  9876. cache.unshift(key);
  9877. if (cache.length > max) {
  9878. cache.pop();
  9879. }
  9880. global$4.setItem(storageId, JSON.stringify(cache));
  9881. };
  9882. const remove = idx => {
  9883. cache.splice(idx, 1);
  9884. };
  9885. const state = () => cache.slice(0);
  9886. return {
  9887. add,
  9888. state
  9889. };
  9890. };
  9891. const getCacheForId = id => get$g(cacheStorage, id).getOrThunk(() => {
  9892. const storageId = `tinymce-custom-colors-${ id }`;
  9893. const currentData = global$4.getItem(storageId);
  9894. if (isNullable(currentData)) {
  9895. const legacyDefault = global$4.getItem('tinymce-custom-colors');
  9896. global$4.setItem(storageId, isNonNullable(legacyDefault) ? legacyDefault : '[]');
  9897. }
  9898. const storage = ColorCache(storageId, 10);
  9899. cacheStorage[id] = storage;
  9900. return storage;
  9901. });
  9902. const getCurrentColors = id => map$2(getCacheForId(id).state(), color => ({
  9903. type: 'choiceitem',
  9904. text: color,
  9905. icon: 'checkmark',
  9906. value: color
  9907. }));
  9908. const addColor = (id, color) => {
  9909. getCacheForId(id).add(color);
  9910. };
  9911. const hsvColour = (hue, saturation, value) => ({
  9912. hue,
  9913. saturation,
  9914. value
  9915. });
  9916. const fromRgb = rgbaColour => {
  9917. let h = 0;
  9918. let s = 0;
  9919. let v = 0;
  9920. const r = rgbaColour.red / 255;
  9921. const g = rgbaColour.green / 255;
  9922. const b = rgbaColour.blue / 255;
  9923. const minRGB = Math.min(r, Math.min(g, b));
  9924. const maxRGB = Math.max(r, Math.max(g, b));
  9925. if (minRGB === maxRGB) {
  9926. v = minRGB;
  9927. return hsvColour(0, 0, v * 100);
  9928. }
  9929. const d = r === minRGB ? g - b : b === minRGB ? r - g : b - r;
  9930. h = r === minRGB ? 3 : b === minRGB ? 1 : 5;
  9931. h = 60 * (h - d / (maxRGB - minRGB));
  9932. s = (maxRGB - minRGB) / maxRGB;
  9933. v = maxRGB;
  9934. return hsvColour(Math.round(h), Math.round(s * 100), Math.round(v * 100));
  9935. };
  9936. const hexToHsv = hex => fromRgb(fromHex(hex));
  9937. const hsvToHex = hsv => fromRgba(fromHsv(hsv));
  9938. const anyToHex = color => fromString$1(color).orThunk(() => fromString(color).map(fromRgba)).getOrThunk(() => {
  9939. const canvas = document.createElement('canvas');
  9940. canvas.height = 1;
  9941. canvas.width = 1;
  9942. const canvasContext = canvas.getContext('2d');
  9943. canvasContext.clearRect(0, 0, canvas.width, canvas.height);
  9944. canvasContext.fillStyle = '#FFFFFF';
  9945. canvasContext.fillStyle = color;
  9946. canvasContext.fillRect(0, 0, 1, 1);
  9947. const rgba = canvasContext.getImageData(0, 0, 1, 1).data;
  9948. const r = rgba[0];
  9949. const g = rgba[1];
  9950. const b = rgba[2];
  9951. const a = rgba[3];
  9952. return fromRgba(rgbaColour(r, g, b, a));
  9953. });
  9954. const foregroundId = 'forecolor';
  9955. const backgroundId = 'hilitecolor';
  9956. const calcCols = colors => Math.max(5, Math.ceil(Math.sqrt(colors)));
  9957. const mapColors = colorMap => {
  9958. const colors = [];
  9959. for (let i = 0; i < colorMap.length; i += 2) {
  9960. colors.push({
  9961. text: colorMap[i + 1],
  9962. value: '#' + anyToHex(colorMap[i]).value,
  9963. icon: 'checkmark',
  9964. type: 'choiceitem'
  9965. });
  9966. }
  9967. return colors;
  9968. };
  9969. const option$1 = name => editor => editor.options.get(name);
  9970. const fallbackColor = '#000000';
  9971. const register$d = editor => {
  9972. const registerOption = editor.options.register;
  9973. const colorProcessor = value => {
  9974. if (isArrayOf(value, isString)) {
  9975. return {
  9976. value: mapColors(value),
  9977. valid: true
  9978. };
  9979. } else {
  9980. return {
  9981. valid: false,
  9982. message: 'Must be an array of strings.'
  9983. };
  9984. }
  9985. };
  9986. registerOption('color_map', {
  9987. processor: colorProcessor,
  9988. default: [
  9989. '#BFEDD2',
  9990. 'Light Green',
  9991. '#FBEEB8',
  9992. 'Light Yellow',
  9993. '#F8CAC6',
  9994. 'Light Red',
  9995. '#ECCAFA',
  9996. 'Light Purple',
  9997. '#C2E0F4',
  9998. 'Light Blue',
  9999. '#2DC26B',
  10000. 'Green',
  10001. '#F1C40F',
  10002. 'Yellow',
  10003. '#E03E2D',
  10004. 'Red',
  10005. '#B96AD9',
  10006. 'Purple',
  10007. '#3598DB',
  10008. 'Blue',
  10009. '#169179',
  10010. 'Dark Turquoise',
  10011. '#E67E23',
  10012. 'Orange',
  10013. '#BA372A',
  10014. 'Dark Red',
  10015. '#843FA1',
  10016. 'Dark Purple',
  10017. '#236FA1',
  10018. 'Dark Blue',
  10019. '#ECF0F1',
  10020. 'Light Gray',
  10021. '#CED4D9',
  10022. 'Medium Gray',
  10023. '#95A5A6',
  10024. 'Gray',
  10025. '#7E8C8D',
  10026. 'Dark Gray',
  10027. '#34495E',
  10028. 'Navy Blue',
  10029. '#000000',
  10030. 'Black',
  10031. '#ffffff',
  10032. 'White'
  10033. ]
  10034. });
  10035. registerOption('color_map_background', { processor: colorProcessor });
  10036. registerOption('color_map_foreground', { processor: colorProcessor });
  10037. registerOption('color_cols', {
  10038. processor: 'number',
  10039. default: calcCols(getColors$2(editor, 'default').length)
  10040. });
  10041. registerOption('color_cols_foreground', {
  10042. processor: 'number',
  10043. default: calcCols(getColors$2(editor, foregroundId).length)
  10044. });
  10045. registerOption('color_cols_background', {
  10046. processor: 'number',
  10047. default: calcCols(getColors$2(editor, backgroundId).length)
  10048. });
  10049. registerOption('custom_colors', {
  10050. processor: 'boolean',
  10051. default: true
  10052. });
  10053. registerOption('color_default_foreground', {
  10054. processor: 'string',
  10055. default: fallbackColor
  10056. });
  10057. registerOption('color_default_background', {
  10058. processor: 'string',
  10059. default: fallbackColor
  10060. });
  10061. };
  10062. const getColorCols$1 = (editor, id) => {
  10063. if (id === foregroundId) {
  10064. return option$1('color_cols_foreground')(editor);
  10065. } else if (id === backgroundId) {
  10066. return option$1('color_cols_background')(editor);
  10067. } else {
  10068. return option$1('color_cols')(editor);
  10069. }
  10070. };
  10071. const hasCustomColors$1 = option$1('custom_colors');
  10072. const getColors$2 = (editor, id) => {
  10073. if (id === foregroundId && editor.options.isSet('color_map_foreground')) {
  10074. return option$1('color_map_foreground')(editor);
  10075. } else if (id === backgroundId && editor.options.isSet('color_map_background')) {
  10076. return option$1('color_map_background')(editor);
  10077. } else {
  10078. return option$1('color_map')(editor);
  10079. }
  10080. };
  10081. const getDefaultForegroundColor = option$1('color_default_foreground');
  10082. const getDefaultBackgroundColor = option$1('color_default_background');
  10083. const getCurrentColor = (editor, format) => {
  10084. const cssRgbValue = get$e(SugarElement.fromDom(editor.selection.getStart()), format === 'hilitecolor' ? 'background-color' : 'color');
  10085. return fromString(cssRgbValue).map(rgba => '#' + fromRgba(rgba).value);
  10086. };
  10087. const applyFormat = (editor, format, value) => {
  10088. editor.undoManager.transact(() => {
  10089. editor.focus();
  10090. editor.formatter.apply(format, { value });
  10091. editor.nodeChanged();
  10092. });
  10093. };
  10094. const removeFormat = (editor, format) => {
  10095. editor.undoManager.transact(() => {
  10096. editor.focus();
  10097. editor.formatter.remove(format, { value: null }, undefined, true);
  10098. editor.nodeChanged();
  10099. });
  10100. };
  10101. const registerCommands = editor => {
  10102. editor.addCommand('mceApplyTextcolor', (format, value) => {
  10103. applyFormat(editor, format, value);
  10104. });
  10105. editor.addCommand('mceRemoveTextcolor', format => {
  10106. removeFormat(editor, format);
  10107. });
  10108. };
  10109. const getAdditionalColors = hasCustom => {
  10110. const type = 'choiceitem';
  10111. const remove = {
  10112. type,
  10113. text: 'Remove color',
  10114. icon: 'color-swatch-remove-color',
  10115. value: 'remove'
  10116. };
  10117. const custom = {
  10118. type,
  10119. text: 'Custom color',
  10120. icon: 'color-picker',
  10121. value: 'custom'
  10122. };
  10123. return hasCustom ? [
  10124. remove,
  10125. custom
  10126. ] : [remove];
  10127. };
  10128. const applyColor = (editor, format, value, onChoice) => {
  10129. if (value === 'custom') {
  10130. const dialog = colorPickerDialog(editor);
  10131. dialog(colorOpt => {
  10132. colorOpt.each(color => {
  10133. addColor(format, color);
  10134. editor.execCommand('mceApplyTextcolor', format, color);
  10135. onChoice(color);
  10136. });
  10137. }, getCurrentColor(editor, format).getOr(fallbackColor));
  10138. } else if (value === 'remove') {
  10139. onChoice('');
  10140. editor.execCommand('mceRemoveTextcolor', format);
  10141. } else {
  10142. onChoice(value);
  10143. editor.execCommand('mceApplyTextcolor', format, value);
  10144. }
  10145. };
  10146. const getColors$1 = (colors, id, hasCustom) => colors.concat(getCurrentColors(id).concat(getAdditionalColors(hasCustom)));
  10147. const getFetch$1 = (colors, id, hasCustom) => callback => {
  10148. callback(getColors$1(colors, id, hasCustom));
  10149. };
  10150. const setIconColor = (splitButtonApi, name, newColor) => {
  10151. const id = name === 'forecolor' ? 'tox-icon-text-color__color' : 'tox-icon-highlight-bg-color__color';
  10152. splitButtonApi.setIconFill(id, newColor);
  10153. };
  10154. const registerTextColorButton = (editor, name, format, tooltip, lastColor) => {
  10155. editor.ui.registry.addSplitButton(name, {
  10156. tooltip,
  10157. presets: 'color',
  10158. icon: name === 'forecolor' ? 'text-color' : 'highlight-bg-color',
  10159. select: value => {
  10160. const optCurrentHex = getCurrentColor(editor, format);
  10161. return is$1(optCurrentHex, value.toUpperCase());
  10162. },
  10163. columns: getColorCols$1(editor, format),
  10164. fetch: getFetch$1(getColors$2(editor, format), format, hasCustomColors$1(editor)),
  10165. onAction: _splitButtonApi => {
  10166. applyColor(editor, format, lastColor.get(), noop);
  10167. },
  10168. onItemAction: (_splitButtonApi, value) => {
  10169. applyColor(editor, format, value, newColor => {
  10170. lastColor.set(newColor);
  10171. fireTextColorChange(editor, {
  10172. name,
  10173. color: newColor
  10174. });
  10175. });
  10176. },
  10177. onSetup: splitButtonApi => {
  10178. setIconColor(splitButtonApi, name, lastColor.get());
  10179. const handler = e => {
  10180. if (e.name === name) {
  10181. setIconColor(splitButtonApi, e.name, e.color);
  10182. }
  10183. };
  10184. editor.on('TextColorChange', handler);
  10185. return () => {
  10186. editor.off('TextColorChange', handler);
  10187. };
  10188. }
  10189. });
  10190. };
  10191. const registerTextColorMenuItem = (editor, name, format, text) => {
  10192. editor.ui.registry.addNestedMenuItem(name, {
  10193. text,
  10194. icon: name === 'forecolor' ? 'text-color' : 'highlight-bg-color',
  10195. getSubmenuItems: () => [{
  10196. type: 'fancymenuitem',
  10197. fancytype: 'colorswatch',
  10198. initData: { storageKey: format },
  10199. onAction: data => {
  10200. applyColor(editor, format, data.value, noop);
  10201. }
  10202. }]
  10203. });
  10204. };
  10205. const colorPickerDialog = editor => (callback, value) => {
  10206. let isValid = false;
  10207. const onSubmit = api => {
  10208. const data = api.getData();
  10209. const hex = data.colorpicker;
  10210. if (isValid) {
  10211. callback(Optional.from(hex));
  10212. api.close();
  10213. } else {
  10214. editor.windowManager.alert(editor.translate([
  10215. 'Invalid hex color code: {0}',
  10216. hex
  10217. ]));
  10218. }
  10219. };
  10220. const onAction = (_api, details) => {
  10221. if (details.name === 'hex-valid') {
  10222. isValid = details.value;
  10223. }
  10224. };
  10225. const initialData = { colorpicker: value };
  10226. editor.windowManager.open({
  10227. title: 'Color Picker',
  10228. size: 'normal',
  10229. body: {
  10230. type: 'panel',
  10231. items: [{
  10232. type: 'colorpicker',
  10233. name: 'colorpicker',
  10234. label: 'Color'
  10235. }]
  10236. },
  10237. buttons: [
  10238. {
  10239. type: 'cancel',
  10240. name: 'cancel',
  10241. text: 'Cancel'
  10242. },
  10243. {
  10244. type: 'submit',
  10245. name: 'save',
  10246. text: 'Save',
  10247. primary: true
  10248. }
  10249. ],
  10250. initialData,
  10251. onAction,
  10252. onSubmit,
  10253. onClose: noop,
  10254. onCancel: () => {
  10255. callback(Optional.none());
  10256. }
  10257. });
  10258. };
  10259. const register$c = editor => {
  10260. registerCommands(editor);
  10261. const fallbackColorForeground = getDefaultForegroundColor(editor);
  10262. const fallbackColorBackground = getDefaultBackgroundColor(editor);
  10263. const lastForeColor = Cell(fallbackColorForeground);
  10264. const lastBackColor = Cell(fallbackColorBackground);
  10265. registerTextColorButton(editor, 'forecolor', 'forecolor', 'Text color', lastForeColor);
  10266. registerTextColorButton(editor, 'backcolor', 'hilitecolor', 'Background color', lastBackColor);
  10267. registerTextColorMenuItem(editor, 'forecolor', 'forecolor', 'Text color');
  10268. registerTextColorMenuItem(editor, 'backcolor', 'hilitecolor', 'Background color');
  10269. };
  10270. const createPartialChoiceMenu = (value, items, onItemValueHandler, columns, presets, itemResponse, select, providersBackstage) => {
  10271. const hasIcons = menuHasIcons(items);
  10272. const presetItemTypes = presets !== 'color' ? 'normal' : 'color';
  10273. const alloyItems = createChoiceItems(items, onItemValueHandler, columns, presetItemTypes, itemResponse, select, providersBackstage);
  10274. const menuLayout = { menuType: presets };
  10275. return createPartialMenuWithAlloyItems(value, hasIcons, alloyItems, columns, menuLayout);
  10276. };
  10277. const createChoiceItems = (items, onItemValueHandler, columns, itemPresets, itemResponse, select, providersBackstage) => cat(map$2(items, item => {
  10278. if (item.type === 'choiceitem') {
  10279. return createChoiceMenuItem(item).fold(handleError, d => Optional.some(renderChoiceItem(d, columns === 1, itemPresets, onItemValueHandler, select(d.value), itemResponse, providersBackstage, menuHasIcons(items))));
  10280. } else {
  10281. return Optional.none();
  10282. }
  10283. }));
  10284. const deriveMenuMovement = (columns, presets) => {
  10285. const menuMarkers = markers(presets);
  10286. if (columns === 1) {
  10287. return {
  10288. mode: 'menu',
  10289. moveOnTab: true
  10290. };
  10291. } else if (columns === 'auto') {
  10292. return {
  10293. mode: 'grid',
  10294. selector: '.' + menuMarkers.item,
  10295. initSize: {
  10296. numColumns: 1,
  10297. numRows: 1
  10298. }
  10299. };
  10300. } else {
  10301. const rowClass = presets === 'color' ? 'tox-swatches__row' : 'tox-collection__group';
  10302. return {
  10303. mode: 'matrix',
  10304. rowSelector: '.' + rowClass,
  10305. previousSelector: menu => {
  10306. return presets === 'color' ? descendant(menu.element, '[aria-checked=true]') : Optional.none();
  10307. }
  10308. };
  10309. }
  10310. };
  10311. const deriveCollectionMovement = (columns, presets) => {
  10312. if (columns === 1) {
  10313. return {
  10314. mode: 'menu',
  10315. moveOnTab: false,
  10316. selector: '.tox-collection__item'
  10317. };
  10318. } else if (columns === 'auto') {
  10319. return {
  10320. mode: 'flatgrid',
  10321. selector: '.' + 'tox-collection__item',
  10322. initSize: {
  10323. numColumns: 1,
  10324. numRows: 1
  10325. }
  10326. };
  10327. } else {
  10328. return {
  10329. mode: 'matrix',
  10330. selectors: {
  10331. row: presets === 'color' ? '.tox-swatches__row' : '.tox-collection__group',
  10332. cell: presets === 'color' ? `.${ colorClass }` : `.${ selectableClass }`
  10333. }
  10334. };
  10335. }
  10336. };
  10337. const renderColorSwatchItem = (spec, backstage) => {
  10338. const items = getColorItems(spec, backstage);
  10339. const columns = backstage.colorinput.getColorCols(spec.initData.storageKey);
  10340. const presets = 'color';
  10341. const menuSpec = createPartialChoiceMenu(generate$6('menu-value'), items, value => {
  10342. spec.onAction({ value });
  10343. }, columns, presets, ItemResponse$1.CLOSE_ON_EXECUTE, never, backstage.shared.providers);
  10344. const widgetSpec = {
  10345. ...menuSpec,
  10346. markers: markers(presets),
  10347. movement: deriveMenuMovement(columns, presets)
  10348. };
  10349. return {
  10350. type: 'widget',
  10351. data: { value: generate$6('widget-id') },
  10352. dom: {
  10353. tag: 'div',
  10354. classes: ['tox-fancymenuitem']
  10355. },
  10356. autofocus: true,
  10357. components: [parts$f.widget(Menu.sketch(widgetSpec))]
  10358. };
  10359. };
  10360. const getColorItems = (spec, backstage) => {
  10361. const useCustomColors = spec.initData.allowCustomColors && backstage.colorinput.hasCustomColors();
  10362. return spec.initData.colors.fold(() => getColors$1(backstage.colorinput.getColors(spec.initData.storageKey), spec.initData.storageKey, useCustomColors), colors => colors.concat(getAdditionalColors(useCustomColors)));
  10363. };
  10364. const cellOverEvent = generate$6('cell-over');
  10365. const cellExecuteEvent = generate$6('cell-execute');
  10366. const makeCell = (row, col, labelId) => {
  10367. const emitCellOver = c => emitWith(c, cellOverEvent, {
  10368. row,
  10369. col
  10370. });
  10371. const emitExecute = c => emitWith(c, cellExecuteEvent, {
  10372. row,
  10373. col
  10374. });
  10375. const onClick = (c, se) => {
  10376. se.stop();
  10377. emitExecute(c);
  10378. };
  10379. return build$1({
  10380. dom: {
  10381. tag: 'div',
  10382. attributes: {
  10383. role: 'button',
  10384. ['aria-labelledby']: labelId
  10385. }
  10386. },
  10387. behaviours: derive$1([
  10388. config('insert-table-picker-cell', [
  10389. run$1(mouseover(), Focusing.focus),
  10390. run$1(execute$5(), emitExecute),
  10391. run$1(click(), onClick),
  10392. run$1(tap(), onClick)
  10393. ]),
  10394. Toggling.config({
  10395. toggleClass: 'tox-insert-table-picker__selected',
  10396. toggleOnExecute: false
  10397. }),
  10398. Focusing.config({ onFocus: emitCellOver })
  10399. ])
  10400. });
  10401. };
  10402. const makeCells = (labelId, numRows, numCols) => {
  10403. const cells = [];
  10404. for (let i = 0; i < numRows; i++) {
  10405. const row = [];
  10406. for (let j = 0; j < numCols; j++) {
  10407. row.push(makeCell(i, j, labelId));
  10408. }
  10409. cells.push(row);
  10410. }
  10411. return cells;
  10412. };
  10413. const selectCells = (cells, selectedRow, selectedColumn, numRows, numColumns) => {
  10414. for (let i = 0; i < numRows; i++) {
  10415. for (let j = 0; j < numColumns; j++) {
  10416. Toggling.set(cells[i][j], i <= selectedRow && j <= selectedColumn);
  10417. }
  10418. }
  10419. };
  10420. const makeComponents = cells => bind$3(cells, cellRow => map$2(cellRow, premade));
  10421. const makeLabelText = (row, col) => text$2(`${ col }x${ row }`);
  10422. const renderInsertTableMenuItem = spec => {
  10423. const numRows = 10;
  10424. const numColumns = 10;
  10425. const sizeLabelId = generate$6('size-label');
  10426. const cells = makeCells(sizeLabelId, numRows, numColumns);
  10427. const emptyLabelText = makeLabelText(0, 0);
  10428. const memLabel = record({
  10429. dom: {
  10430. tag: 'span',
  10431. classes: ['tox-insert-table-picker__label'],
  10432. attributes: { id: sizeLabelId }
  10433. },
  10434. components: [emptyLabelText],
  10435. behaviours: derive$1([Replacing.config({})])
  10436. });
  10437. return {
  10438. type: 'widget',
  10439. data: { value: generate$6('widget-id') },
  10440. dom: {
  10441. tag: 'div',
  10442. classes: ['tox-fancymenuitem']
  10443. },
  10444. autofocus: true,
  10445. components: [parts$f.widget({
  10446. dom: {
  10447. tag: 'div',
  10448. classes: ['tox-insert-table-picker']
  10449. },
  10450. components: makeComponents(cells).concat(memLabel.asSpec()),
  10451. behaviours: derive$1([
  10452. config('insert-table-picker', [
  10453. runOnAttached(c => {
  10454. Replacing.set(memLabel.get(c), [emptyLabelText]);
  10455. }),
  10456. runWithTarget(cellOverEvent, (c, t, e) => {
  10457. const {row, col} = e.event;
  10458. selectCells(cells, row, col, numRows, numColumns);
  10459. Replacing.set(memLabel.get(c), [makeLabelText(row + 1, col + 1)]);
  10460. }),
  10461. runWithTarget(cellExecuteEvent, (c, _, e) => {
  10462. const {row, col} = e.event;
  10463. spec.onAction({
  10464. numRows: row + 1,
  10465. numColumns: col + 1
  10466. });
  10467. emit(c, sandboxClose());
  10468. })
  10469. ]),
  10470. Keying.config({
  10471. initSize: {
  10472. numRows,
  10473. numColumns
  10474. },
  10475. mode: 'flatgrid',
  10476. selector: '[role="button"]'
  10477. })
  10478. ])
  10479. })]
  10480. };
  10481. };
  10482. const fancyMenuItems = {
  10483. inserttable: renderInsertTableMenuItem,
  10484. colorswatch: renderColorSwatchItem
  10485. };
  10486. const renderFancyMenuItem = (spec, backstage) => get$g(fancyMenuItems, spec.fancytype).map(render => render(spec, backstage));
  10487. const renderNestedItem = (spec, itemResponse, providersBackstage, renderIcons = true, downwardsCaret = false) => {
  10488. const caret = downwardsCaret ? renderDownwardsCaret(providersBackstage.icons) : renderSubmenuCaret(providersBackstage.icons);
  10489. const getApi = component => ({
  10490. isEnabled: () => !Disabling.isDisabled(component),
  10491. setEnabled: state => Disabling.set(component, !state)
  10492. });
  10493. const structure = renderItemStructure({
  10494. presets: 'normal',
  10495. iconContent: spec.icon,
  10496. textContent: spec.text,
  10497. htmlContent: Optional.none(),
  10498. ariaLabel: spec.text,
  10499. caret: Optional.some(caret),
  10500. checkMark: Optional.none(),
  10501. shortcutContent: spec.shortcut
  10502. }, providersBackstage, renderIcons);
  10503. return renderCommonItem({
  10504. data: buildData(spec),
  10505. getApi,
  10506. enabled: spec.enabled,
  10507. onAction: noop,
  10508. onSetup: spec.onSetup,
  10509. triggersSubmenu: true,
  10510. itemBehaviours: []
  10511. }, structure, itemResponse, providersBackstage);
  10512. };
  10513. const renderNormalItem = (spec, itemResponse, providersBackstage, renderIcons = true) => {
  10514. const getApi = component => ({
  10515. isEnabled: () => !Disabling.isDisabled(component),
  10516. setEnabled: state => Disabling.set(component, !state)
  10517. });
  10518. const structure = renderItemStructure({
  10519. presets: 'normal',
  10520. iconContent: spec.icon,
  10521. textContent: spec.text,
  10522. htmlContent: Optional.none(),
  10523. ariaLabel: spec.text,
  10524. caret: Optional.none(),
  10525. checkMark: Optional.none(),
  10526. shortcutContent: spec.shortcut
  10527. }, providersBackstage, renderIcons);
  10528. return renderCommonItem({
  10529. data: buildData(spec),
  10530. getApi,
  10531. enabled: spec.enabled,
  10532. onAction: spec.onAction,
  10533. onSetup: spec.onSetup,
  10534. triggersSubmenu: false,
  10535. itemBehaviours: []
  10536. }, structure, itemResponse, providersBackstage);
  10537. };
  10538. const renderSeparatorItem = spec => ({
  10539. type: 'separator',
  10540. dom: {
  10541. tag: 'div',
  10542. classes: [
  10543. selectableClass,
  10544. groupHeadingClass
  10545. ]
  10546. },
  10547. components: spec.text.map(text$2).toArray()
  10548. });
  10549. const renderToggleMenuItem = (spec, itemResponse, providersBackstage, renderIcons = true) => {
  10550. const getApi = component => ({
  10551. setActive: state => {
  10552. Toggling.set(component, state);
  10553. },
  10554. isActive: () => Toggling.isOn(component),
  10555. isEnabled: () => !Disabling.isDisabled(component),
  10556. setEnabled: state => Disabling.set(component, !state)
  10557. });
  10558. const structure = renderItemStructure({
  10559. iconContent: spec.icon,
  10560. textContent: spec.text,
  10561. htmlContent: Optional.none(),
  10562. ariaLabel: spec.text,
  10563. checkMark: Optional.some(renderCheckmark(providersBackstage.icons)),
  10564. caret: Optional.none(),
  10565. shortcutContent: spec.shortcut,
  10566. presets: 'normal',
  10567. meta: spec.meta
  10568. }, providersBackstage, renderIcons);
  10569. return deepMerge(renderCommonItem({
  10570. data: buildData(spec),
  10571. enabled: spec.enabled,
  10572. getApi,
  10573. onAction: spec.onAction,
  10574. onSetup: spec.onSetup,
  10575. triggersSubmenu: false,
  10576. itemBehaviours: []
  10577. }, structure, itemResponse, providersBackstage), {
  10578. toggling: {
  10579. toggleClass: tickedClass,
  10580. toggleOnExecute: false,
  10581. selected: spec.active
  10582. }
  10583. });
  10584. };
  10585. const autocomplete = renderAutocompleteItem;
  10586. const separator$3 = renderSeparatorItem;
  10587. const normal = renderNormalItem;
  10588. const nested = renderNestedItem;
  10589. const toggle$1 = renderToggleMenuItem;
  10590. const fancy = renderFancyMenuItem;
  10591. const card = renderCardMenuItem;
  10592. const getCoupled = (component, coupleConfig, coupleState, name) => coupleState.getOrCreate(component, coupleConfig, name);
  10593. const getExistingCoupled = (component, coupleConfig, coupleState, name) => coupleState.getExisting(component, coupleConfig, name);
  10594. var CouplingApis = /*#__PURE__*/Object.freeze({
  10595. __proto__: null,
  10596. getCoupled: getCoupled,
  10597. getExistingCoupled: getExistingCoupled
  10598. });
  10599. var CouplingSchema = [requiredOf('others', setOf(Result.value, anyValue()))];
  10600. const init$a = () => {
  10601. const coupled = {};
  10602. const lookupCoupled = (coupleConfig, coupledName) => {
  10603. const available = keys(coupleConfig.others);
  10604. if (available.length === 0) {
  10605. throw new Error('Cannot find any known coupled components');
  10606. } else {
  10607. return get$g(coupled, coupledName);
  10608. }
  10609. };
  10610. const getOrCreate = (component, coupleConfig, name) => {
  10611. return lookupCoupled(coupleConfig, name).getOrThunk(() => {
  10612. const builder = get$g(coupleConfig.others, name).getOrDie('No information found for coupled component: ' + name);
  10613. const spec = builder(component);
  10614. const built = component.getSystem().build(spec);
  10615. coupled[name] = built;
  10616. return built;
  10617. });
  10618. };
  10619. const getExisting = (component, coupleConfig, name) => {
  10620. return lookupCoupled(coupleConfig, name).orThunk(() => {
  10621. get$g(coupleConfig.others, name).getOrDie('No information found for coupled component: ' + name);
  10622. return Optional.none();
  10623. });
  10624. };
  10625. const readState = constant$1({});
  10626. return nu$8({
  10627. readState,
  10628. getExisting,
  10629. getOrCreate
  10630. });
  10631. };
  10632. var CouplingState = /*#__PURE__*/Object.freeze({
  10633. __proto__: null,
  10634. init: init$a
  10635. });
  10636. const Coupling = create$4({
  10637. fields: CouplingSchema,
  10638. name: 'coupling',
  10639. apis: CouplingApis,
  10640. state: CouplingState
  10641. });
  10642. const nu$3 = baseFn => {
  10643. let data = Optional.none();
  10644. let callbacks = [];
  10645. const map = f => nu$3(nCallback => {
  10646. get(data => {
  10647. nCallback(f(data));
  10648. });
  10649. });
  10650. const get = nCallback => {
  10651. if (isReady()) {
  10652. call(nCallback);
  10653. } else {
  10654. callbacks.push(nCallback);
  10655. }
  10656. };
  10657. const set = x => {
  10658. if (!isReady()) {
  10659. data = Optional.some(x);
  10660. run(callbacks);
  10661. callbacks = [];
  10662. }
  10663. };
  10664. const isReady = () => data.isSome();
  10665. const run = cbs => {
  10666. each$1(cbs, call);
  10667. };
  10668. const call = cb => {
  10669. data.each(x => {
  10670. setTimeout(() => {
  10671. cb(x);
  10672. }, 0);
  10673. });
  10674. };
  10675. baseFn(set);
  10676. return {
  10677. get,
  10678. map,
  10679. isReady
  10680. };
  10681. };
  10682. const pure$1 = a => nu$3(callback => {
  10683. callback(a);
  10684. });
  10685. const LazyValue = {
  10686. nu: nu$3,
  10687. pure: pure$1
  10688. };
  10689. const errorReporter = err => {
  10690. setTimeout(() => {
  10691. throw err;
  10692. }, 0);
  10693. };
  10694. const make$5 = run => {
  10695. const get = callback => {
  10696. run().then(callback, errorReporter);
  10697. };
  10698. const map = fab => {
  10699. return make$5(() => run().then(fab));
  10700. };
  10701. const bind = aFutureB => {
  10702. return make$5(() => run().then(v => aFutureB(v).toPromise()));
  10703. };
  10704. const anonBind = futureB => {
  10705. return make$5(() => run().then(() => futureB.toPromise()));
  10706. };
  10707. const toLazy = () => {
  10708. return LazyValue.nu(get);
  10709. };
  10710. const toCached = () => {
  10711. let cache = null;
  10712. return make$5(() => {
  10713. if (cache === null) {
  10714. cache = run();
  10715. }
  10716. return cache;
  10717. });
  10718. };
  10719. const toPromise = run;
  10720. return {
  10721. map,
  10722. bind,
  10723. anonBind,
  10724. toLazy,
  10725. toCached,
  10726. toPromise,
  10727. get
  10728. };
  10729. };
  10730. const nu$2 = baseFn => {
  10731. return make$5(() => new Promise(baseFn));
  10732. };
  10733. const pure = a => {
  10734. return make$5(() => Promise.resolve(a));
  10735. };
  10736. const Future = {
  10737. nu: nu$2,
  10738. pure
  10739. };
  10740. const suffix = constant$1('sink');
  10741. const partType$1 = constant$1(optional({
  10742. name: suffix(),
  10743. overrides: constant$1({
  10744. dom: { tag: 'div' },
  10745. behaviours: derive$1([Positioning.config({ useFixed: always })]),
  10746. events: derive$2([
  10747. cutter(keydown()),
  10748. cutter(mousedown()),
  10749. cutter(click())
  10750. ])
  10751. })
  10752. }));
  10753. const getAnchor = (detail, component) => {
  10754. const hotspot = detail.getHotspot(component).getOr(component);
  10755. const type = 'hotspot';
  10756. const overrides = detail.getAnchorOverrides();
  10757. return detail.layouts.fold(() => ({
  10758. type,
  10759. hotspot,
  10760. overrides
  10761. }), layouts => ({
  10762. type,
  10763. hotspot,
  10764. overrides,
  10765. layouts
  10766. }));
  10767. };
  10768. const fetch = (detail, mapFetch, component) => {
  10769. const fetcher = detail.fetch;
  10770. return fetcher(component).map(mapFetch);
  10771. };
  10772. const openF = (detail, mapFetch, anchor, component, sandbox, externals, highlightOnOpen) => {
  10773. const futureData = fetch(detail, mapFetch, component);
  10774. const getLazySink = getSink(component, detail);
  10775. return futureData.map(tdata => tdata.bind(data => Optional.from(tieredMenu.sketch({
  10776. ...externals.menu(),
  10777. uid: generate$5(''),
  10778. data,
  10779. highlightOnOpen,
  10780. onOpenMenu: (tmenu, menu) => {
  10781. const sink = getLazySink().getOrDie();
  10782. Positioning.position(sink, menu, { anchor });
  10783. Sandboxing.decloak(sandbox);
  10784. },
  10785. onOpenSubmenu: (tmenu, item, submenu) => {
  10786. const sink = getLazySink().getOrDie();
  10787. Positioning.position(sink, submenu, {
  10788. anchor: {
  10789. type: 'submenu',
  10790. item
  10791. }
  10792. });
  10793. Sandboxing.decloak(sandbox);
  10794. },
  10795. onRepositionMenu: (tmenu, primaryMenu, submenuTriggers) => {
  10796. const sink = getLazySink().getOrDie();
  10797. Positioning.position(sink, primaryMenu, { anchor });
  10798. each$1(submenuTriggers, st => {
  10799. Positioning.position(sink, st.triggeredMenu, {
  10800. anchor: {
  10801. type: 'submenu',
  10802. item: st.triggeringItem
  10803. }
  10804. });
  10805. });
  10806. },
  10807. onEscape: () => {
  10808. Focusing.focus(component);
  10809. Sandboxing.close(sandbox);
  10810. return Optional.some(true);
  10811. }
  10812. }))));
  10813. };
  10814. const open = (detail, mapFetch, hotspot, sandbox, externals, onOpenSync, highlightOnOpen) => {
  10815. const anchor = getAnchor(detail, hotspot);
  10816. const processed = openF(detail, mapFetch, anchor, hotspot, sandbox, externals, highlightOnOpen);
  10817. return processed.map(tdata => {
  10818. tdata.fold(() => {
  10819. if (Sandboxing.isOpen(sandbox)) {
  10820. Sandboxing.close(sandbox);
  10821. }
  10822. }, data => {
  10823. Sandboxing.cloak(sandbox);
  10824. Sandboxing.open(sandbox, data);
  10825. onOpenSync(sandbox);
  10826. });
  10827. return sandbox;
  10828. });
  10829. };
  10830. const close = (detail, mapFetch, component, sandbox, _externals, _onOpenSync, _highlightOnOpen) => {
  10831. Sandboxing.close(sandbox);
  10832. return Future.pure(sandbox);
  10833. };
  10834. const togglePopup = (detail, mapFetch, hotspot, externals, onOpenSync, highlightOnOpen) => {
  10835. const sandbox = Coupling.getCoupled(hotspot, 'sandbox');
  10836. const showing = Sandboxing.isOpen(sandbox);
  10837. const action = showing ? close : open;
  10838. return action(detail, mapFetch, hotspot, sandbox, externals, onOpenSync, highlightOnOpen);
  10839. };
  10840. const matchWidth = (hotspot, container, useMinWidth) => {
  10841. const menu = Composing.getCurrent(container).getOr(container);
  10842. const buttonWidth = get$c(hotspot.element);
  10843. if (useMinWidth) {
  10844. set$8(menu.element, 'min-width', buttonWidth + 'px');
  10845. } else {
  10846. set$7(menu.element, buttonWidth);
  10847. }
  10848. };
  10849. const getSink = (anyInSystem, sinkDetail) => anyInSystem.getSystem().getByUid(sinkDetail.uid + '-' + suffix()).map(internalSink => () => Result.value(internalSink)).getOrThunk(() => sinkDetail.lazySink.fold(() => () => Result.error(new Error('No internal sink is specified, nor could an external sink be found')), lazySinkFn => () => lazySinkFn(anyInSystem)));
  10850. const doRepositionMenus = sandbox => {
  10851. Sandboxing.getState(sandbox).each(tmenu => {
  10852. tieredMenu.repositionMenus(tmenu);
  10853. });
  10854. };
  10855. const makeSandbox$1 = (detail, hotspot, extras) => {
  10856. const ariaControls = manager();
  10857. const onOpen = (component, menu) => {
  10858. const anchor = getAnchor(detail, hotspot);
  10859. ariaControls.link(hotspot.element);
  10860. if (detail.matchWidth) {
  10861. matchWidth(anchor.hotspot, menu, detail.useMinWidth);
  10862. }
  10863. detail.onOpen(anchor, component, menu);
  10864. if (extras !== undefined && extras.onOpen !== undefined) {
  10865. extras.onOpen(component, menu);
  10866. }
  10867. };
  10868. const onClose = (component, menu) => {
  10869. ariaControls.unlink(hotspot.element);
  10870. if (extras !== undefined && extras.onClose !== undefined) {
  10871. extras.onClose(component, menu);
  10872. }
  10873. };
  10874. const lazySink = getSink(hotspot, detail);
  10875. return {
  10876. dom: {
  10877. tag: 'div',
  10878. classes: detail.sandboxClasses,
  10879. attributes: {
  10880. id: ariaControls.id,
  10881. role: 'listbox'
  10882. }
  10883. },
  10884. behaviours: SketchBehaviours.augment(detail.sandboxBehaviours, [
  10885. Representing.config({
  10886. store: {
  10887. mode: 'memory',
  10888. initialValue: hotspot
  10889. }
  10890. }),
  10891. Sandboxing.config({
  10892. onOpen,
  10893. onClose,
  10894. isPartOf: (container, data, queryElem) => {
  10895. return isPartOf$1(data, queryElem) || isPartOf$1(hotspot, queryElem);
  10896. },
  10897. getAttachPoint: () => {
  10898. return lazySink().getOrDie();
  10899. }
  10900. }),
  10901. Composing.config({
  10902. find: sandbox => {
  10903. return Sandboxing.getState(sandbox).bind(menu => Composing.getCurrent(menu));
  10904. }
  10905. }),
  10906. Receiving.config({
  10907. channels: {
  10908. ...receivingChannel$1({ isExtraPart: never }),
  10909. ...receivingChannel({ doReposition: doRepositionMenus })
  10910. }
  10911. })
  10912. ])
  10913. };
  10914. };
  10915. const repositionMenus = comp => {
  10916. const sandbox = Coupling.getCoupled(comp, 'sandbox');
  10917. doRepositionMenus(sandbox);
  10918. };
  10919. const sandboxFields = () => [
  10920. defaulted('sandboxClasses', []),
  10921. SketchBehaviours.field('sandboxBehaviours', [
  10922. Composing,
  10923. Receiving,
  10924. Sandboxing,
  10925. Representing
  10926. ])
  10927. ];
  10928. const schema$k = constant$1([
  10929. required$1('dom'),
  10930. required$1('fetch'),
  10931. onHandler('onOpen'),
  10932. onKeyboardHandler('onExecute'),
  10933. defaulted('getHotspot', Optional.some),
  10934. defaulted('getAnchorOverrides', constant$1({})),
  10935. schema$y(),
  10936. field('dropdownBehaviours', [
  10937. Toggling,
  10938. Coupling,
  10939. Keying,
  10940. Focusing
  10941. ]),
  10942. required$1('toggleClass'),
  10943. defaulted('eventOrder', {}),
  10944. option$3('lazySink'),
  10945. defaulted('matchWidth', false),
  10946. defaulted('useMinWidth', false),
  10947. option$3('role')
  10948. ].concat(sandboxFields()));
  10949. const parts$e = constant$1([
  10950. external({
  10951. schema: [
  10952. tieredMenuMarkers(),
  10953. defaulted('fakeFocus', false)
  10954. ],
  10955. name: 'menu',
  10956. defaults: detail => {
  10957. return { onExecute: detail.onExecute };
  10958. }
  10959. }),
  10960. partType$1()
  10961. ]);
  10962. const factory$k = (detail, components, _spec, externals) => {
  10963. const lookupAttr = attr => get$g(detail.dom, 'attributes').bind(attrs => get$g(attrs, attr));
  10964. const switchToMenu = sandbox => {
  10965. Sandboxing.getState(sandbox).each(tmenu => {
  10966. tieredMenu.highlightPrimary(tmenu);
  10967. });
  10968. };
  10969. const togglePopup$1 = (dropdownComp, onOpenSync, highlightOnOpen) => {
  10970. return togglePopup(detail, identity, dropdownComp, externals, onOpenSync, highlightOnOpen);
  10971. };
  10972. const action = component => {
  10973. const onOpenSync = switchToMenu;
  10974. togglePopup$1(component, onOpenSync, HighlightOnOpen.HighlightMenuAndItem).get(noop);
  10975. };
  10976. const apis = {
  10977. expand: comp => {
  10978. if (!Toggling.isOn(comp)) {
  10979. togglePopup$1(comp, noop, HighlightOnOpen.HighlightNone).get(noop);
  10980. }
  10981. },
  10982. open: comp => {
  10983. if (!Toggling.isOn(comp)) {
  10984. togglePopup$1(comp, noop, HighlightOnOpen.HighlightMenuAndItem).get(noop);
  10985. }
  10986. },
  10987. refetch: comp => {
  10988. const optSandbox = Coupling.getExistingCoupled(comp, 'sandbox');
  10989. return optSandbox.fold(() => {
  10990. return togglePopup$1(comp, noop, HighlightOnOpen.HighlightMenuAndItem).map(noop);
  10991. }, sandboxComp => {
  10992. return open(detail, identity, comp, sandboxComp, externals, noop, HighlightOnOpen.HighlightMenuAndItem).map(noop);
  10993. });
  10994. },
  10995. isOpen: Toggling.isOn,
  10996. close: comp => {
  10997. if (Toggling.isOn(comp)) {
  10998. togglePopup$1(comp, noop, HighlightOnOpen.HighlightMenuAndItem).get(noop);
  10999. }
  11000. },
  11001. repositionMenus: comp => {
  11002. if (Toggling.isOn(comp)) {
  11003. repositionMenus(comp);
  11004. }
  11005. }
  11006. };
  11007. const triggerExecute = (comp, _se) => {
  11008. emitExecute(comp);
  11009. return Optional.some(true);
  11010. };
  11011. return {
  11012. uid: detail.uid,
  11013. dom: detail.dom,
  11014. components,
  11015. behaviours: augment(detail.dropdownBehaviours, [
  11016. Toggling.config({
  11017. toggleClass: detail.toggleClass,
  11018. aria: { mode: 'expanded' }
  11019. }),
  11020. Coupling.config({
  11021. others: {
  11022. sandbox: hotspot => {
  11023. return makeSandbox$1(detail, hotspot, {
  11024. onOpen: () => Toggling.on(hotspot),
  11025. onClose: () => Toggling.off(hotspot)
  11026. });
  11027. }
  11028. }
  11029. }),
  11030. Keying.config({
  11031. mode: 'special',
  11032. onSpace: triggerExecute,
  11033. onEnter: triggerExecute,
  11034. onDown: (comp, _se) => {
  11035. if (Dropdown.isOpen(comp)) {
  11036. const sandbox = Coupling.getCoupled(comp, 'sandbox');
  11037. switchToMenu(sandbox);
  11038. } else {
  11039. Dropdown.open(comp);
  11040. }
  11041. return Optional.some(true);
  11042. },
  11043. onEscape: (comp, _se) => {
  11044. if (Dropdown.isOpen(comp)) {
  11045. Dropdown.close(comp);
  11046. return Optional.some(true);
  11047. } else {
  11048. return Optional.none();
  11049. }
  11050. }
  11051. }),
  11052. Focusing.config({})
  11053. ]),
  11054. events: events$a(Optional.some(action)),
  11055. eventOrder: {
  11056. ...detail.eventOrder,
  11057. [execute$5()]: [
  11058. 'disabling',
  11059. 'toggling',
  11060. 'alloy.base.behaviour'
  11061. ]
  11062. },
  11063. apis,
  11064. domModification: {
  11065. attributes: {
  11066. 'aria-haspopup': 'true',
  11067. ...detail.role.fold(() => ({}), role => ({ role })),
  11068. ...detail.dom.tag === 'button' ? { type: lookupAttr('type').getOr('button') } : {}
  11069. }
  11070. }
  11071. };
  11072. };
  11073. const Dropdown = composite({
  11074. name: 'Dropdown',
  11075. configFields: schema$k(),
  11076. partFields: parts$e(),
  11077. factory: factory$k,
  11078. apis: {
  11079. open: (apis, comp) => apis.open(comp),
  11080. refetch: (apis, comp) => apis.refetch(comp),
  11081. expand: (apis, comp) => apis.expand(comp),
  11082. close: (apis, comp) => apis.close(comp),
  11083. isOpen: (apis, comp) => apis.isOpen(comp),
  11084. repositionMenus: (apis, comp) => apis.repositionMenus(comp)
  11085. }
  11086. });
  11087. const identifyMenuLayout = searchMode => {
  11088. switch (searchMode.searchMode) {
  11089. case 'no-search': {
  11090. return { menuType: 'normal' };
  11091. }
  11092. default: {
  11093. return {
  11094. menuType: 'searchable',
  11095. searchMode
  11096. };
  11097. }
  11098. }
  11099. };
  11100. const handleRefetchTrigger = originalSandboxComp => {
  11101. const dropdown = Representing.getValue(originalSandboxComp);
  11102. const optSearcherState = findWithinSandbox(originalSandboxComp).map(saveState);
  11103. Dropdown.refetch(dropdown).get(() => {
  11104. const newSandboxComp = Coupling.getCoupled(dropdown, 'sandbox');
  11105. optSearcherState.each(searcherState => findWithinSandbox(newSandboxComp).each(inputComp => restoreState(inputComp, searcherState)));
  11106. });
  11107. };
  11108. const handleRedirectToMenuItem = (sandboxComp, se) => {
  11109. getActiveMenuItemFrom(sandboxComp).each(activeItem => {
  11110. retargetAndDispatchWith(sandboxComp, activeItem.element, se.event.eventType, se.event.interactionEvent);
  11111. });
  11112. };
  11113. const getActiveMenuItemFrom = sandboxComp => {
  11114. return Sandboxing.getState(sandboxComp).bind(Highlighting.getHighlighted).bind(Highlighting.getHighlighted);
  11115. };
  11116. const getSearchResults = activeMenuComp => {
  11117. return has(activeMenuComp.element, searchResultsClass) ? Optional.some(activeMenuComp.element) : descendant(activeMenuComp.element, '.' + searchResultsClass);
  11118. };
  11119. const updateAriaOnHighlight = (tmenuComp, menuComp, itemComp) => {
  11120. findWithinMenu(tmenuComp).each(inputComp => {
  11121. setActiveDescendant(inputComp, itemComp);
  11122. const optActiveResults = getSearchResults(menuComp);
  11123. optActiveResults.each(resultsElem => {
  11124. getOpt(resultsElem, 'id').each(controlledId => set$9(inputComp.element, 'aria-controls', controlledId));
  11125. });
  11126. });
  11127. set$9(itemComp.element, 'aria-selected', 'true');
  11128. };
  11129. const updateAriaOnDehighlight = (tmenuComp, menuComp, itemComp) => {
  11130. set$9(itemComp.element, 'aria-selected', 'false');
  11131. };
  11132. const focusSearchField = tmenuComp => {
  11133. findWithinMenu(tmenuComp).each(searcherComp => Focusing.focus(searcherComp));
  11134. };
  11135. const getSearchPattern = dropdownComp => {
  11136. const optSandboxComp = Coupling.getExistingCoupled(dropdownComp, 'sandbox');
  11137. return optSandboxComp.bind(findWithinSandbox).map(saveState).map(state => state.fetchPattern).getOr('');
  11138. };
  11139. var FocusMode;
  11140. (function (FocusMode) {
  11141. FocusMode[FocusMode['ContentFocus'] = 0] = 'ContentFocus';
  11142. FocusMode[FocusMode['UiFocus'] = 1] = 'UiFocus';
  11143. }(FocusMode || (FocusMode = {})));
  11144. const createMenuItemFromBridge = (item, itemResponse, backstage, menuHasIcons, isHorizontalMenu) => {
  11145. const providersBackstage = backstage.shared.providers;
  11146. const parseForHorizontalMenu = menuitem => !isHorizontalMenu ? menuitem : {
  11147. ...menuitem,
  11148. shortcut: Optional.none(),
  11149. icon: menuitem.text.isSome() ? Optional.none() : menuitem.icon
  11150. };
  11151. switch (item.type) {
  11152. case 'menuitem':
  11153. return createMenuItem(item).fold(handleError, d => Optional.some(normal(parseForHorizontalMenu(d), itemResponse, providersBackstage, menuHasIcons)));
  11154. case 'nestedmenuitem':
  11155. return createNestedMenuItem(item).fold(handleError, d => Optional.some(nested(parseForHorizontalMenu(d), itemResponse, providersBackstage, menuHasIcons, isHorizontalMenu)));
  11156. case 'togglemenuitem':
  11157. return createToggleMenuItem(item).fold(handleError, d => Optional.some(toggle$1(parseForHorizontalMenu(d), itemResponse, providersBackstage, menuHasIcons)));
  11158. case 'separator':
  11159. return createSeparatorMenuItem(item).fold(handleError, d => Optional.some(separator$3(d)));
  11160. case 'fancymenuitem':
  11161. return createFancyMenuItem(item).fold(handleError, d => fancy(d, backstage));
  11162. default: {
  11163. console.error('Unknown item in general menu', item);
  11164. return Optional.none();
  11165. }
  11166. }
  11167. };
  11168. const createAutocompleteItems = (items, matchText, onItemValueHandler, columns, itemResponse, sharedBackstage, highlightOn) => {
  11169. const renderText = columns === 1;
  11170. const renderIcons = !renderText || menuHasIcons(items);
  11171. return cat(map$2(items, item => {
  11172. switch (item.type) {
  11173. case 'separator':
  11174. return createSeparatorItem(item).fold(handleError, d => Optional.some(separator$3(d)));
  11175. case 'cardmenuitem':
  11176. return createCardMenuItem(item).fold(handleError, d => Optional.some(card({
  11177. ...d,
  11178. onAction: api => {
  11179. d.onAction(api);
  11180. onItemValueHandler(d.value, d.meta);
  11181. }
  11182. }, itemResponse, sharedBackstage, {
  11183. itemBehaviours: tooltipBehaviour(d.meta, sharedBackstage),
  11184. cardText: {
  11185. matchText,
  11186. highlightOn
  11187. }
  11188. })));
  11189. case 'autocompleteitem':
  11190. default:
  11191. return createAutocompleterItem(item).fold(handleError, d => Optional.some(autocomplete(d, matchText, renderText, 'normal', onItemValueHandler, itemResponse, sharedBackstage, renderIcons)));
  11192. }
  11193. }));
  11194. };
  11195. const createPartialMenu = (value, items, itemResponse, backstage, isHorizontalMenu, searchMode) => {
  11196. const hasIcons = menuHasIcons(items);
  11197. const alloyItems = cat(map$2(items, item => {
  11198. const itemHasIcon = i => isHorizontalMenu ? !has$2(i, 'text') : hasIcons;
  11199. const createItem = i => createMenuItemFromBridge(i, itemResponse, backstage, itemHasIcon(i), isHorizontalMenu);
  11200. if (item.type === 'nestedmenuitem' && item.getSubmenuItems().length <= 0) {
  11201. return createItem({
  11202. ...item,
  11203. enabled: false
  11204. });
  11205. } else {
  11206. return createItem(item);
  11207. }
  11208. }));
  11209. const menuLayout = identifyMenuLayout(searchMode);
  11210. const createPartial = isHorizontalMenu ? createHorizontalPartialMenuWithAlloyItems : createPartialMenuWithAlloyItems;
  11211. return createPartial(value, hasIcons, alloyItems, 1, menuLayout);
  11212. };
  11213. const createTieredDataFrom = partialMenu => tieredMenu.singleData(partialMenu.value, partialMenu);
  11214. const createInlineMenuFrom = (partialMenu, columns, focusMode, presets) => {
  11215. const movement = deriveMenuMovement(columns, presets);
  11216. const menuMarkers = markers(presets);
  11217. return {
  11218. data: createTieredDataFrom({
  11219. ...partialMenu,
  11220. movement,
  11221. menuBehaviours: SimpleBehaviours.unnamedEvents(columns !== 'auto' ? [] : [runOnAttached((comp, _se) => {
  11222. detectSize(comp, 4, menuMarkers.item).each(({numColumns, numRows}) => {
  11223. Keying.setGridSize(comp, numRows, numColumns);
  11224. });
  11225. })])
  11226. }),
  11227. menu: {
  11228. markers: markers(presets),
  11229. fakeFocus: focusMode === FocusMode.ContentFocus
  11230. }
  11231. };
  11232. };
  11233. const getAutocompleterRange = (dom, initRange) => {
  11234. return detect(SugarElement.fromDom(initRange.startContainer)).map(elm => {
  11235. const range = dom.createRng();
  11236. range.selectNode(elm.dom);
  11237. return range;
  11238. });
  11239. };
  11240. const register$b = (editor, sharedBackstage) => {
  11241. const processingAction = Cell(false);
  11242. const activeState = Cell(false);
  11243. const autocompleter = build$1(InlineView.sketch({
  11244. dom: {
  11245. tag: 'div',
  11246. classes: ['tox-autocompleter']
  11247. },
  11248. components: [],
  11249. fireDismissalEventInstead: {},
  11250. inlineBehaviours: derive$1([config('dismissAutocompleter', [run$1(dismissRequested(), () => cancelIfNecessary())])]),
  11251. lazySink: sharedBackstage.getSink
  11252. }));
  11253. const isMenuOpen = () => InlineView.isOpen(autocompleter);
  11254. const isActive = activeState.get;
  11255. const hideIfNecessary = () => {
  11256. if (isMenuOpen()) {
  11257. InlineView.hide(autocompleter);
  11258. }
  11259. };
  11260. const getMenu = () => InlineView.getContent(autocompleter).bind(tmenu => {
  11261. return get$h(tmenu.components(), 0);
  11262. });
  11263. const cancelIfNecessary = () => editor.execCommand('mceAutocompleterClose');
  11264. const getCombinedItems = matches => {
  11265. const columns = findMap(matches, m => Optional.from(m.columns)).getOr(1);
  11266. return bind$3(matches, match => {
  11267. const choices = match.items;
  11268. return createAutocompleteItems(choices, match.matchText, (itemValue, itemMeta) => {
  11269. const nr = editor.selection.getRng();
  11270. getAutocompleterRange(editor.dom, nr).each(range => {
  11271. const autocompleterApi = {
  11272. hide: () => cancelIfNecessary(),
  11273. reload: fetchOptions => {
  11274. hideIfNecessary();
  11275. editor.execCommand('mceAutocompleterReload', false, { fetchOptions });
  11276. }
  11277. };
  11278. processingAction.set(true);
  11279. match.onAction(autocompleterApi, range, itemValue, itemMeta);
  11280. processingAction.set(false);
  11281. });
  11282. }, columns, ItemResponse$1.BUBBLE_TO_SANDBOX, sharedBackstage, match.highlightOn);
  11283. });
  11284. };
  11285. const display = (lookupData, items) => {
  11286. findIn(SugarElement.fromDom(editor.getBody())).each(element => {
  11287. const columns = findMap(lookupData, ld => Optional.from(ld.columns)).getOr(1);
  11288. InlineView.showMenuAt(autocompleter, {
  11289. anchor: {
  11290. type: 'node',
  11291. root: SugarElement.fromDom(editor.getBody()),
  11292. node: Optional.from(element)
  11293. }
  11294. }, createInlineMenuFrom(createPartialMenuWithAlloyItems('autocompleter-value', true, items, columns, { menuType: 'normal' }), columns, FocusMode.ContentFocus, 'normal'));
  11295. });
  11296. getMenu().each(Highlighting.highlightFirst);
  11297. };
  11298. const updateDisplay = lookupData => {
  11299. const combinedItems = getCombinedItems(lookupData);
  11300. if (combinedItems.length > 0) {
  11301. display(lookupData, combinedItems);
  11302. } else {
  11303. hideIfNecessary();
  11304. }
  11305. };
  11306. editor.on('AutocompleterStart', ({lookupData}) => {
  11307. activeState.set(true);
  11308. processingAction.set(false);
  11309. updateDisplay(lookupData);
  11310. });
  11311. editor.on('AutocompleterUpdate', ({lookupData}) => updateDisplay(lookupData));
  11312. editor.on('AutocompleterEnd', () => {
  11313. hideIfNecessary();
  11314. activeState.set(false);
  11315. processingAction.set(false);
  11316. });
  11317. const autocompleterUiApi = {
  11318. cancelIfNecessary,
  11319. isMenuOpen,
  11320. isActive,
  11321. isProcessingAction: processingAction.get,
  11322. getMenu
  11323. };
  11324. AutocompleterEditorEvents.setup(autocompleterUiApi, editor);
  11325. };
  11326. const Autocompleter = { register: register$b };
  11327. const closest = (scope, selector, isRoot) => closest$1(scope, selector, isRoot).isSome();
  11328. const DelayedFunction = (fun, delay) => {
  11329. let ref = null;
  11330. const schedule = (...args) => {
  11331. ref = setTimeout(() => {
  11332. fun.apply(null, args);
  11333. ref = null;
  11334. }, delay);
  11335. };
  11336. const cancel = () => {
  11337. if (ref !== null) {
  11338. clearTimeout(ref);
  11339. ref = null;
  11340. }
  11341. };
  11342. return {
  11343. cancel,
  11344. schedule
  11345. };
  11346. };
  11347. const SIGNIFICANT_MOVE = 5;
  11348. const LONGPRESS_DELAY = 400;
  11349. const getTouch = event => {
  11350. const raw = event.raw;
  11351. if (raw.touches === undefined || raw.touches.length !== 1) {
  11352. return Optional.none();
  11353. }
  11354. return Optional.some(raw.touches[0]);
  11355. };
  11356. const isFarEnough = (touch, data) => {
  11357. const distX = Math.abs(touch.clientX - data.x);
  11358. const distY = Math.abs(touch.clientY - data.y);
  11359. return distX > SIGNIFICANT_MOVE || distY > SIGNIFICANT_MOVE;
  11360. };
  11361. const monitor = settings => {
  11362. const startData = value$2();
  11363. const longpressFired = Cell(false);
  11364. const longpress$1 = DelayedFunction(event => {
  11365. settings.triggerEvent(longpress(), event);
  11366. longpressFired.set(true);
  11367. }, LONGPRESS_DELAY);
  11368. const handleTouchstart = event => {
  11369. getTouch(event).each(touch => {
  11370. longpress$1.cancel();
  11371. const data = {
  11372. x: touch.clientX,
  11373. y: touch.clientY,
  11374. target: event.target
  11375. };
  11376. longpress$1.schedule(event);
  11377. longpressFired.set(false);
  11378. startData.set(data);
  11379. });
  11380. return Optional.none();
  11381. };
  11382. const handleTouchmove = event => {
  11383. longpress$1.cancel();
  11384. getTouch(event).each(touch => {
  11385. startData.on(data => {
  11386. if (isFarEnough(touch, data)) {
  11387. startData.clear();
  11388. }
  11389. });
  11390. });
  11391. return Optional.none();
  11392. };
  11393. const handleTouchend = event => {
  11394. longpress$1.cancel();
  11395. const isSame = data => eq(data.target, event.target);
  11396. return startData.get().filter(isSame).map(_data => {
  11397. if (longpressFired.get()) {
  11398. event.prevent();
  11399. return false;
  11400. } else {
  11401. return settings.triggerEvent(tap(), event);
  11402. }
  11403. });
  11404. };
  11405. const handlers = wrapAll([
  11406. {
  11407. key: touchstart(),
  11408. value: handleTouchstart
  11409. },
  11410. {
  11411. key: touchmove(),
  11412. value: handleTouchmove
  11413. },
  11414. {
  11415. key: touchend(),
  11416. value: handleTouchend
  11417. }
  11418. ]);
  11419. const fireIfReady = (event, type) => get$g(handlers, type).bind(handler => handler(event));
  11420. return { fireIfReady };
  11421. };
  11422. const isDangerous = event => {
  11423. const keyEv = event.raw;
  11424. return keyEv.which === BACKSPACE[0] && !contains$2([
  11425. 'input',
  11426. 'textarea'
  11427. ], name$3(event.target)) && !closest(event.target, '[contenteditable="true"]');
  11428. };
  11429. const setup$d = (container, rawSettings) => {
  11430. const settings = {
  11431. stopBackspace: true,
  11432. ...rawSettings
  11433. };
  11434. const pointerEvents = [
  11435. 'touchstart',
  11436. 'touchmove',
  11437. 'touchend',
  11438. 'touchcancel',
  11439. 'gesturestart',
  11440. 'mousedown',
  11441. 'mouseup',
  11442. 'mouseover',
  11443. 'mousemove',
  11444. 'mouseout',
  11445. 'click'
  11446. ];
  11447. const tapEvent = monitor(settings);
  11448. const simpleEvents = map$2(pointerEvents.concat([
  11449. 'selectstart',
  11450. 'input',
  11451. 'contextmenu',
  11452. 'change',
  11453. 'transitionend',
  11454. 'transitioncancel',
  11455. 'drag',
  11456. 'dragstart',
  11457. 'dragend',
  11458. 'dragenter',
  11459. 'dragleave',
  11460. 'dragover',
  11461. 'drop',
  11462. 'keyup'
  11463. ]), type => bind(container, type, event => {
  11464. tapEvent.fireIfReady(event, type).each(tapStopped => {
  11465. if (tapStopped) {
  11466. event.kill();
  11467. }
  11468. });
  11469. const stopped = settings.triggerEvent(type, event);
  11470. if (stopped) {
  11471. event.kill();
  11472. }
  11473. }));
  11474. const pasteTimeout = value$2();
  11475. const onPaste = bind(container, 'paste', event => {
  11476. tapEvent.fireIfReady(event, 'paste').each(tapStopped => {
  11477. if (tapStopped) {
  11478. event.kill();
  11479. }
  11480. });
  11481. const stopped = settings.triggerEvent('paste', event);
  11482. if (stopped) {
  11483. event.kill();
  11484. }
  11485. pasteTimeout.set(setTimeout(() => {
  11486. settings.triggerEvent(postPaste(), event);
  11487. }, 0));
  11488. });
  11489. const onKeydown = bind(container, 'keydown', event => {
  11490. const stopped = settings.triggerEvent('keydown', event);
  11491. if (stopped) {
  11492. event.kill();
  11493. } else if (settings.stopBackspace && isDangerous(event)) {
  11494. event.prevent();
  11495. }
  11496. });
  11497. const onFocusIn = bind(container, 'focusin', event => {
  11498. const stopped = settings.triggerEvent('focusin', event);
  11499. if (stopped) {
  11500. event.kill();
  11501. }
  11502. });
  11503. const focusoutTimeout = value$2();
  11504. const onFocusOut = bind(container, 'focusout', event => {
  11505. const stopped = settings.triggerEvent('focusout', event);
  11506. if (stopped) {
  11507. event.kill();
  11508. }
  11509. focusoutTimeout.set(setTimeout(() => {
  11510. settings.triggerEvent(postBlur(), event);
  11511. }, 0));
  11512. });
  11513. const unbind = () => {
  11514. each$1(simpleEvents, e => {
  11515. e.unbind();
  11516. });
  11517. onKeydown.unbind();
  11518. onFocusIn.unbind();
  11519. onFocusOut.unbind();
  11520. onPaste.unbind();
  11521. pasteTimeout.on(clearTimeout);
  11522. focusoutTimeout.on(clearTimeout);
  11523. };
  11524. return { unbind };
  11525. };
  11526. const derive = (rawEvent, rawTarget) => {
  11527. const source = get$g(rawEvent, 'target').getOr(rawTarget);
  11528. return Cell(source);
  11529. };
  11530. const fromSource = (event, source) => {
  11531. const stopper = Cell(false);
  11532. const cutter = Cell(false);
  11533. const stop = () => {
  11534. stopper.set(true);
  11535. };
  11536. const cut = () => {
  11537. cutter.set(true);
  11538. };
  11539. return {
  11540. stop,
  11541. cut,
  11542. isStopped: stopper.get,
  11543. isCut: cutter.get,
  11544. event,
  11545. setSource: source.set,
  11546. getSource: source.get
  11547. };
  11548. };
  11549. const fromExternal = event => {
  11550. const stopper = Cell(false);
  11551. const stop = () => {
  11552. stopper.set(true);
  11553. };
  11554. return {
  11555. stop,
  11556. cut: noop,
  11557. isStopped: stopper.get,
  11558. isCut: never,
  11559. event,
  11560. setSource: die('Cannot set source of a broadcasted event'),
  11561. getSource: die('Cannot get source of a broadcasted event')
  11562. };
  11563. };
  11564. const adt$1 = Adt.generate([
  11565. { stopped: [] },
  11566. { resume: ['element'] },
  11567. { complete: [] }
  11568. ]);
  11569. const doTriggerHandler = (lookup, eventType, rawEvent, target, source, logger) => {
  11570. const handler = lookup(eventType, target);
  11571. const simulatedEvent = fromSource(rawEvent, source);
  11572. return handler.fold(() => {
  11573. logger.logEventNoHandlers(eventType, target);
  11574. return adt$1.complete();
  11575. }, handlerInfo => {
  11576. const descHandler = handlerInfo.descHandler;
  11577. const eventHandler = getCurried(descHandler);
  11578. eventHandler(simulatedEvent);
  11579. if (simulatedEvent.isStopped()) {
  11580. logger.logEventStopped(eventType, handlerInfo.element, descHandler.purpose);
  11581. return adt$1.stopped();
  11582. } else if (simulatedEvent.isCut()) {
  11583. logger.logEventCut(eventType, handlerInfo.element, descHandler.purpose);
  11584. return adt$1.complete();
  11585. } else {
  11586. return parent(handlerInfo.element).fold(() => {
  11587. logger.logNoParent(eventType, handlerInfo.element, descHandler.purpose);
  11588. return adt$1.complete();
  11589. }, parent => {
  11590. logger.logEventResponse(eventType, handlerInfo.element, descHandler.purpose);
  11591. return adt$1.resume(parent);
  11592. });
  11593. }
  11594. });
  11595. };
  11596. const doTriggerOnUntilStopped = (lookup, eventType, rawEvent, rawTarget, source, logger) => doTriggerHandler(lookup, eventType, rawEvent, rawTarget, source, logger).fold(always, parent => doTriggerOnUntilStopped(lookup, eventType, rawEvent, parent, source, logger), never);
  11597. const triggerHandler = (lookup, eventType, rawEvent, target, logger) => {
  11598. const source = derive(rawEvent, target);
  11599. return doTriggerHandler(lookup, eventType, rawEvent, target, source, logger);
  11600. };
  11601. const broadcast = (listeners, rawEvent, _logger) => {
  11602. const simulatedEvent = fromExternal(rawEvent);
  11603. each$1(listeners, listener => {
  11604. const descHandler = listener.descHandler;
  11605. const handler = getCurried(descHandler);
  11606. handler(simulatedEvent);
  11607. });
  11608. return simulatedEvent.isStopped();
  11609. };
  11610. const triggerUntilStopped = (lookup, eventType, rawEvent, logger) => triggerOnUntilStopped(lookup, eventType, rawEvent, rawEvent.target, logger);
  11611. const triggerOnUntilStopped = (lookup, eventType, rawEvent, rawTarget, logger) => {
  11612. const source = derive(rawEvent, rawTarget);
  11613. return doTriggerOnUntilStopped(lookup, eventType, rawEvent, rawTarget, source, logger);
  11614. };
  11615. const eventHandler = (element, descHandler) => ({
  11616. element,
  11617. descHandler
  11618. });
  11619. const broadcastHandler = (id, handler) => ({
  11620. id,
  11621. descHandler: handler
  11622. });
  11623. const EventRegistry = () => {
  11624. const registry = {};
  11625. const registerId = (extraArgs, id, events) => {
  11626. each(events, (v, k) => {
  11627. const handlers = registry[k] !== undefined ? registry[k] : {};
  11628. handlers[id] = curryArgs(v, extraArgs);
  11629. registry[k] = handlers;
  11630. });
  11631. };
  11632. const findHandler = (handlers, elem) => read$1(elem).bind(id => get$g(handlers, id)).map(descHandler => eventHandler(elem, descHandler));
  11633. const filterByType = type => get$g(registry, type).map(handlers => mapToArray(handlers, (f, id) => broadcastHandler(id, f))).getOr([]);
  11634. const find = (isAboveRoot, type, target) => get$g(registry, type).bind(handlers => closest$4(target, elem => findHandler(handlers, elem), isAboveRoot));
  11635. const unregisterId = id => {
  11636. each(registry, (handlersById, _eventName) => {
  11637. if (has$2(handlersById, id)) {
  11638. delete handlersById[id];
  11639. }
  11640. });
  11641. };
  11642. return {
  11643. registerId,
  11644. unregisterId,
  11645. filterByType,
  11646. find
  11647. };
  11648. };
  11649. const Registry = () => {
  11650. const events = EventRegistry();
  11651. const components = {};
  11652. const readOrTag = component => {
  11653. const elem = component.element;
  11654. return read$1(elem).getOrThunk(() => write('uid-', component.element));
  11655. };
  11656. const failOnDuplicate = (component, tagId) => {
  11657. const conflict = components[tagId];
  11658. if (conflict === component) {
  11659. unregister(component);
  11660. } else {
  11661. throw new Error('The tagId "' + tagId + '" is already used by: ' + element(conflict.element) + '\nCannot use it for: ' + element(component.element) + '\n' + 'The conflicting element is' + (inBody(conflict.element) ? ' ' : ' not ') + 'already in the DOM');
  11662. }
  11663. };
  11664. const register = component => {
  11665. const tagId = readOrTag(component);
  11666. if (hasNonNullableKey(components, tagId)) {
  11667. failOnDuplicate(component, tagId);
  11668. }
  11669. const extraArgs = [component];
  11670. events.registerId(extraArgs, tagId, component.events);
  11671. components[tagId] = component;
  11672. };
  11673. const unregister = component => {
  11674. read$1(component.element).each(tagId => {
  11675. delete components[tagId];
  11676. events.unregisterId(tagId);
  11677. });
  11678. };
  11679. const filter = type => events.filterByType(type);
  11680. const find = (isAboveRoot, type, target) => events.find(isAboveRoot, type, target);
  11681. const getById = id => get$g(components, id);
  11682. return {
  11683. find,
  11684. filter,
  11685. register,
  11686. unregister,
  11687. getById
  11688. };
  11689. };
  11690. const factory$j = detail => {
  11691. const {attributes, ...domWithoutAttributes} = detail.dom;
  11692. return {
  11693. uid: detail.uid,
  11694. dom: {
  11695. tag: 'div',
  11696. attributes: {
  11697. role: 'presentation',
  11698. ...attributes
  11699. },
  11700. ...domWithoutAttributes
  11701. },
  11702. components: detail.components,
  11703. behaviours: get$3(detail.containerBehaviours),
  11704. events: detail.events,
  11705. domModification: detail.domModification,
  11706. eventOrder: detail.eventOrder
  11707. };
  11708. };
  11709. const Container = single({
  11710. name: 'Container',
  11711. factory: factory$j,
  11712. configFields: [
  11713. defaulted('components', []),
  11714. field('containerBehaviours', []),
  11715. defaulted('events', {}),
  11716. defaulted('domModification', {}),
  11717. defaulted('eventOrder', {})
  11718. ]
  11719. });
  11720. const takeover = root => {
  11721. const isAboveRoot = el => parent(root.element).fold(always, parent => eq(el, parent));
  11722. const registry = Registry();
  11723. const lookup = (eventName, target) => registry.find(isAboveRoot, eventName, target);
  11724. const domEvents = setup$d(root.element, {
  11725. triggerEvent: (eventName, event) => {
  11726. return monitorEvent(eventName, event.target, logger => triggerUntilStopped(lookup, eventName, event, logger));
  11727. }
  11728. });
  11729. const systemApi = {
  11730. debugInfo: constant$1('real'),
  11731. triggerEvent: (eventName, target, data) => {
  11732. monitorEvent(eventName, target, logger => triggerOnUntilStopped(lookup, eventName, data, target, logger));
  11733. },
  11734. triggerFocus: (target, originator) => {
  11735. read$1(target).fold(() => {
  11736. focus$3(target);
  11737. }, _alloyId => {
  11738. monitorEvent(focus$4(), target, logger => {
  11739. triggerHandler(lookup, focus$4(), {
  11740. originator,
  11741. kill: noop,
  11742. prevent: noop,
  11743. target
  11744. }, target, logger);
  11745. return false;
  11746. });
  11747. });
  11748. },
  11749. triggerEscape: (comp, simulatedEvent) => {
  11750. systemApi.triggerEvent('keydown', comp.element, simulatedEvent.event);
  11751. },
  11752. getByUid: uid => {
  11753. return getByUid(uid);
  11754. },
  11755. getByDom: elem => {
  11756. return getByDom(elem);
  11757. },
  11758. build: build$1,
  11759. buildOrPatch: buildOrPatch,
  11760. addToGui: c => {
  11761. add(c);
  11762. },
  11763. removeFromGui: c => {
  11764. remove(c);
  11765. },
  11766. addToWorld: c => {
  11767. addToWorld(c);
  11768. },
  11769. removeFromWorld: c => {
  11770. removeFromWorld(c);
  11771. },
  11772. broadcast: message => {
  11773. broadcast$1(message);
  11774. },
  11775. broadcastOn: (channels, message) => {
  11776. broadcastOn(channels, message);
  11777. },
  11778. broadcastEvent: (eventName, event) => {
  11779. broadcastEvent(eventName, event);
  11780. },
  11781. isConnected: always
  11782. };
  11783. const addToWorld = component => {
  11784. component.connect(systemApi);
  11785. if (!isText(component.element)) {
  11786. registry.register(component);
  11787. each$1(component.components(), addToWorld);
  11788. systemApi.triggerEvent(systemInit(), component.element, { target: component.element });
  11789. }
  11790. };
  11791. const removeFromWorld = component => {
  11792. if (!isText(component.element)) {
  11793. each$1(component.components(), removeFromWorld);
  11794. registry.unregister(component);
  11795. }
  11796. component.disconnect();
  11797. };
  11798. const add = component => {
  11799. attach(root, component);
  11800. };
  11801. const remove = component => {
  11802. detach(component);
  11803. };
  11804. const destroy = () => {
  11805. domEvents.unbind();
  11806. remove$5(root.element);
  11807. };
  11808. const broadcastData = data => {
  11809. const receivers = registry.filter(receive());
  11810. each$1(receivers, receiver => {
  11811. const descHandler = receiver.descHandler;
  11812. const handler = getCurried(descHandler);
  11813. handler(data);
  11814. });
  11815. };
  11816. const broadcast$1 = message => {
  11817. broadcastData({
  11818. universal: true,
  11819. data: message
  11820. });
  11821. };
  11822. const broadcastOn = (channels, message) => {
  11823. broadcastData({
  11824. universal: false,
  11825. channels,
  11826. data: message
  11827. });
  11828. };
  11829. const broadcastEvent = (eventName, event) => {
  11830. const listeners = registry.filter(eventName);
  11831. return broadcast(listeners, event);
  11832. };
  11833. const getByUid = uid => registry.getById(uid).fold(() => Result.error(new Error('Could not find component with uid: "' + uid + '" in system.')), Result.value);
  11834. const getByDom = elem => {
  11835. const uid = read$1(elem).getOr('not found');
  11836. return getByUid(uid);
  11837. };
  11838. addToWorld(root);
  11839. return {
  11840. root,
  11841. element: root.element,
  11842. destroy,
  11843. add,
  11844. remove,
  11845. getByUid,
  11846. getByDom,
  11847. addToWorld,
  11848. removeFromWorld,
  11849. broadcast: broadcast$1,
  11850. broadcastOn,
  11851. broadcastEvent
  11852. };
  11853. };
  11854. const renderBar = (spec, backstage) => ({
  11855. dom: {
  11856. tag: 'div',
  11857. classes: [
  11858. 'tox-bar',
  11859. 'tox-form__controls-h-stack'
  11860. ]
  11861. },
  11862. components: map$2(spec.items, backstage.interpreter)
  11863. });
  11864. const schema$j = constant$1([
  11865. defaulted('prefix', 'form-field'),
  11866. field('fieldBehaviours', [
  11867. Composing,
  11868. Representing
  11869. ])
  11870. ]);
  11871. const parts$d = constant$1([
  11872. optional({
  11873. schema: [required$1('dom')],
  11874. name: 'label'
  11875. }),
  11876. optional({
  11877. factory: {
  11878. sketch: spec => {
  11879. return {
  11880. uid: spec.uid,
  11881. dom: {
  11882. tag: 'span',
  11883. styles: { display: 'none' },
  11884. attributes: { 'aria-hidden': 'true' },
  11885. innerHtml: spec.text
  11886. }
  11887. };
  11888. }
  11889. },
  11890. schema: [required$1('text')],
  11891. name: 'aria-descriptor'
  11892. }),
  11893. required({
  11894. factory: {
  11895. sketch: spec => {
  11896. const excludeFactory = exclude(spec, ['factory']);
  11897. return spec.factory.sketch(excludeFactory);
  11898. }
  11899. },
  11900. schema: [required$1('factory')],
  11901. name: 'field'
  11902. })
  11903. ]);
  11904. const factory$i = (detail, components, _spec, _externals) => {
  11905. const behaviours = augment(detail.fieldBehaviours, [
  11906. Composing.config({
  11907. find: container => {
  11908. return getPart(container, detail, 'field');
  11909. }
  11910. }),
  11911. Representing.config({
  11912. store: {
  11913. mode: 'manual',
  11914. getValue: field => {
  11915. return Composing.getCurrent(field).bind(Representing.getValue);
  11916. },
  11917. setValue: (field, value) => {
  11918. Composing.getCurrent(field).each(current => {
  11919. Representing.setValue(current, value);
  11920. });
  11921. }
  11922. }
  11923. })
  11924. ]);
  11925. const events = derive$2([runOnAttached((component, _simulatedEvent) => {
  11926. const ps = getParts(component, detail, [
  11927. 'label',
  11928. 'field',
  11929. 'aria-descriptor'
  11930. ]);
  11931. ps.field().each(field => {
  11932. const id = generate$6(detail.prefix);
  11933. ps.label().each(label => {
  11934. set$9(label.element, 'for', id);
  11935. set$9(field.element, 'id', id);
  11936. });
  11937. ps['aria-descriptor']().each(descriptor => {
  11938. const descriptorId = generate$6(detail.prefix);
  11939. set$9(descriptor.element, 'id', descriptorId);
  11940. set$9(field.element, 'aria-describedby', descriptorId);
  11941. });
  11942. });
  11943. })]);
  11944. const apis = {
  11945. getField: container => getPart(container, detail, 'field'),
  11946. getLabel: container => getPart(container, detail, 'label')
  11947. };
  11948. return {
  11949. uid: detail.uid,
  11950. dom: detail.dom,
  11951. components,
  11952. behaviours,
  11953. events,
  11954. apis
  11955. };
  11956. };
  11957. const FormField = composite({
  11958. name: 'FormField',
  11959. configFields: schema$j(),
  11960. partFields: parts$d(),
  11961. factory: factory$i,
  11962. apis: {
  11963. getField: (apis, comp) => apis.getField(comp),
  11964. getLabel: (apis, comp) => apis.getLabel(comp)
  11965. }
  11966. });
  11967. const exhibit$2 = (base, tabConfig) => nu$7({
  11968. attributes: wrapAll([{
  11969. key: tabConfig.tabAttr,
  11970. value: 'true'
  11971. }])
  11972. });
  11973. var ActiveTabstopping = /*#__PURE__*/Object.freeze({
  11974. __proto__: null,
  11975. exhibit: exhibit$2
  11976. });
  11977. var TabstopSchema = [defaulted('tabAttr', 'data-alloy-tabstop')];
  11978. const Tabstopping = create$4({
  11979. fields: TabstopSchema,
  11980. name: 'tabstopping',
  11981. active: ActiveTabstopping
  11982. });
  11983. var global$3 = tinymce.util.Tools.resolve('tinymce.html.Entities');
  11984. const renderFormFieldWith = (pLabel, pField, extraClasses, extraBehaviours) => {
  11985. const spec = renderFormFieldSpecWith(pLabel, pField, extraClasses, extraBehaviours);
  11986. return FormField.sketch(spec);
  11987. };
  11988. const renderFormField = (pLabel, pField) => renderFormFieldWith(pLabel, pField, [], []);
  11989. const renderFormFieldSpecWith = (pLabel, pField, extraClasses, extraBehaviours) => ({
  11990. dom: renderFormFieldDomWith(extraClasses),
  11991. components: pLabel.toArray().concat([pField]),
  11992. fieldBehaviours: derive$1(extraBehaviours)
  11993. });
  11994. const renderFormFieldDom = () => renderFormFieldDomWith([]);
  11995. const renderFormFieldDomWith = extraClasses => ({
  11996. tag: 'div',
  11997. classes: ['tox-form__group'].concat(extraClasses)
  11998. });
  11999. const renderLabel$2 = (label, providersBackstage) => FormField.parts.label({
  12000. dom: {
  12001. tag: 'label',
  12002. classes: ['tox-label']
  12003. },
  12004. components: [text$2(providersBackstage.translate(label))]
  12005. });
  12006. const formChangeEvent = generate$6('form-component-change');
  12007. const formCloseEvent = generate$6('form-close');
  12008. const formCancelEvent = generate$6('form-cancel');
  12009. const formActionEvent = generate$6('form-action');
  12010. const formSubmitEvent = generate$6('form-submit');
  12011. const formBlockEvent = generate$6('form-block');
  12012. const formUnblockEvent = generate$6('form-unblock');
  12013. const formTabChangeEvent = generate$6('form-tabchange');
  12014. const formResizeEvent = generate$6('form-resize');
  12015. const renderCollection = (spec, providersBackstage, initialData) => {
  12016. const pLabel = spec.label.map(label => renderLabel$2(label, providersBackstage));
  12017. const runOnItem = f => (comp, se) => {
  12018. closest$1(se.event.target, '[data-collection-item-value]').each(target => {
  12019. f(comp, se, target, get$f(target, 'data-collection-item-value'));
  12020. });
  12021. };
  12022. const setContents = (comp, items) => {
  12023. const htmlLines = map$2(items, item => {
  12024. const itemText = global$8.translate(item.text);
  12025. const textContent = spec.columns === 1 ? `<div class="tox-collection__item-label">${ itemText }</div>` : '';
  12026. const iconContent = `<div class="tox-collection__item-icon">${ item.icon }</div>`;
  12027. const mapItemName = {
  12028. '_': ' ',
  12029. ' - ': ' ',
  12030. '-': ' '
  12031. };
  12032. const ariaLabel = itemText.replace(/\_| \- |\-/g, match => mapItemName[match]);
  12033. const disabledClass = providersBackstage.isDisabled() ? ' tox-collection__item--state-disabled' : '';
  12034. return `<div class="tox-collection__item${ disabledClass }" tabindex="-1" data-collection-item-value="${ global$3.encodeAllRaw(item.value) }" title="${ ariaLabel }" aria-label="${ ariaLabel }">${ iconContent }${ textContent }</div>`;
  12035. });
  12036. const chunks = spec.columns !== 'auto' && spec.columns > 1 ? chunk$1(htmlLines, spec.columns) : [htmlLines];
  12037. const html = map$2(chunks, ch => `<div class="tox-collection__group">${ ch.join('') }</div>`);
  12038. set$6(comp.element, html.join(''));
  12039. };
  12040. const onClick = runOnItem((comp, se, tgt, itemValue) => {
  12041. se.stop();
  12042. if (!providersBackstage.isDisabled()) {
  12043. emitWith(comp, formActionEvent, {
  12044. name: spec.name,
  12045. value: itemValue
  12046. });
  12047. }
  12048. });
  12049. const collectionEvents = [
  12050. run$1(mouseover(), runOnItem((comp, se, tgt) => {
  12051. focus$3(tgt);
  12052. })),
  12053. run$1(click(), onClick),
  12054. run$1(tap(), onClick),
  12055. run$1(focusin(), runOnItem((comp, se, tgt) => {
  12056. descendant(comp.element, '.' + activeClass).each(currentActive => {
  12057. remove$2(currentActive, activeClass);
  12058. });
  12059. add$2(tgt, activeClass);
  12060. })),
  12061. run$1(focusout(), runOnItem(comp => {
  12062. descendant(comp.element, '.' + activeClass).each(currentActive => {
  12063. remove$2(currentActive, activeClass);
  12064. });
  12065. })),
  12066. runOnExecute$1(runOnItem((comp, se, tgt, itemValue) => {
  12067. emitWith(comp, formActionEvent, {
  12068. name: spec.name,
  12069. value: itemValue
  12070. });
  12071. }))
  12072. ];
  12073. const iterCollectionItems = (comp, applyAttributes) => map$2(descendants(comp.element, '.tox-collection__item'), applyAttributes);
  12074. const pField = FormField.parts.field({
  12075. dom: {
  12076. tag: 'div',
  12077. classes: ['tox-collection'].concat(spec.columns !== 1 ? ['tox-collection--grid'] : ['tox-collection--list'])
  12078. },
  12079. components: [],
  12080. factory: { sketch: identity },
  12081. behaviours: derive$1([
  12082. Disabling.config({
  12083. disabled: providersBackstage.isDisabled,
  12084. onDisabled: comp => {
  12085. iterCollectionItems(comp, childElm => {
  12086. add$2(childElm, 'tox-collection__item--state-disabled');
  12087. set$9(childElm, 'aria-disabled', true);
  12088. });
  12089. },
  12090. onEnabled: comp => {
  12091. iterCollectionItems(comp, childElm => {
  12092. remove$2(childElm, 'tox-collection__item--state-disabled');
  12093. remove$7(childElm, 'aria-disabled');
  12094. });
  12095. }
  12096. }),
  12097. receivingConfig(),
  12098. Replacing.config({}),
  12099. Representing.config({
  12100. store: {
  12101. mode: 'memory',
  12102. initialValue: initialData.getOr([])
  12103. },
  12104. onSetValue: (comp, items) => {
  12105. setContents(comp, items);
  12106. if (spec.columns === 'auto') {
  12107. detectSize(comp, 5, 'tox-collection__item').each(({numRows, numColumns}) => {
  12108. Keying.setGridSize(comp, numRows, numColumns);
  12109. });
  12110. }
  12111. emit(comp, formResizeEvent);
  12112. }
  12113. }),
  12114. Tabstopping.config({}),
  12115. Keying.config(deriveCollectionMovement(spec.columns, 'normal')),
  12116. config('collection-events', collectionEvents)
  12117. ]),
  12118. eventOrder: {
  12119. [execute$5()]: [
  12120. 'disabling',
  12121. 'alloy.base.behaviour',
  12122. 'collection-events'
  12123. ]
  12124. }
  12125. });
  12126. const extraClasses = ['tox-form__group--collection'];
  12127. return renderFormFieldWith(pLabel, pField, extraClasses, []);
  12128. };
  12129. const ariaElements = [
  12130. 'input',
  12131. 'textarea'
  12132. ];
  12133. const isAriaElement = elem => {
  12134. const name = name$3(elem);
  12135. return contains$2(ariaElements, name);
  12136. };
  12137. const markValid = (component, invalidConfig) => {
  12138. const elem = invalidConfig.getRoot(component).getOr(component.element);
  12139. remove$2(elem, invalidConfig.invalidClass);
  12140. invalidConfig.notify.each(notifyInfo => {
  12141. if (isAriaElement(component.element)) {
  12142. set$9(component.element, 'aria-invalid', false);
  12143. }
  12144. notifyInfo.getContainer(component).each(container => {
  12145. set$6(container, notifyInfo.validHtml);
  12146. });
  12147. notifyInfo.onValid(component);
  12148. });
  12149. };
  12150. const markInvalid = (component, invalidConfig, invalidState, text) => {
  12151. const elem = invalidConfig.getRoot(component).getOr(component.element);
  12152. add$2(elem, invalidConfig.invalidClass);
  12153. invalidConfig.notify.each(notifyInfo => {
  12154. if (isAriaElement(component.element)) {
  12155. set$9(component.element, 'aria-invalid', true);
  12156. }
  12157. notifyInfo.getContainer(component).each(container => {
  12158. set$6(container, text);
  12159. });
  12160. notifyInfo.onInvalid(component, text);
  12161. });
  12162. };
  12163. const query = (component, invalidConfig, _invalidState) => invalidConfig.validator.fold(() => Future.pure(Result.value(true)), validatorInfo => validatorInfo.validate(component));
  12164. const run = (component, invalidConfig, invalidState) => {
  12165. invalidConfig.notify.each(notifyInfo => {
  12166. notifyInfo.onValidate(component);
  12167. });
  12168. return query(component, invalidConfig).map(valid => {
  12169. if (component.getSystem().isConnected()) {
  12170. return valid.fold(err => {
  12171. markInvalid(component, invalidConfig, invalidState, err);
  12172. return Result.error(err);
  12173. }, v => {
  12174. markValid(component, invalidConfig);
  12175. return Result.value(v);
  12176. });
  12177. } else {
  12178. return Result.error('No longer in system');
  12179. }
  12180. });
  12181. };
  12182. const isInvalid = (component, invalidConfig) => {
  12183. const elem = invalidConfig.getRoot(component).getOr(component.element);
  12184. return has(elem, invalidConfig.invalidClass);
  12185. };
  12186. var InvalidateApis = /*#__PURE__*/Object.freeze({
  12187. __proto__: null,
  12188. markValid: markValid,
  12189. markInvalid: markInvalid,
  12190. query: query,
  12191. run: run,
  12192. isInvalid: isInvalid
  12193. });
  12194. const events$8 = (invalidConfig, invalidState) => invalidConfig.validator.map(validatorInfo => derive$2([run$1(validatorInfo.onEvent, component => {
  12195. run(component, invalidConfig, invalidState).get(identity);
  12196. })].concat(validatorInfo.validateOnLoad ? [runOnAttached(component => {
  12197. run(component, invalidConfig, invalidState).get(noop);
  12198. })] : []))).getOr({});
  12199. var ActiveInvalidate = /*#__PURE__*/Object.freeze({
  12200. __proto__: null,
  12201. events: events$8
  12202. });
  12203. var InvalidateSchema = [
  12204. required$1('invalidClass'),
  12205. defaulted('getRoot', Optional.none),
  12206. optionObjOf('notify', [
  12207. defaulted('aria', 'alert'),
  12208. defaulted('getContainer', Optional.none),
  12209. defaulted('validHtml', ''),
  12210. onHandler('onValid'),
  12211. onHandler('onInvalid'),
  12212. onHandler('onValidate')
  12213. ]),
  12214. optionObjOf('validator', [
  12215. required$1('validate'),
  12216. defaulted('onEvent', 'input'),
  12217. defaulted('validateOnLoad', true)
  12218. ])
  12219. ];
  12220. const Invalidating = create$4({
  12221. fields: InvalidateSchema,
  12222. name: 'invalidating',
  12223. active: ActiveInvalidate,
  12224. apis: InvalidateApis,
  12225. extra: {
  12226. validation: validator => {
  12227. return component => {
  12228. const v = Representing.getValue(component);
  12229. return Future.pure(validator(v));
  12230. };
  12231. }
  12232. }
  12233. });
  12234. const exhibit$1 = () => nu$7({
  12235. styles: {
  12236. '-webkit-user-select': 'none',
  12237. 'user-select': 'none',
  12238. '-ms-user-select': 'none',
  12239. '-moz-user-select': '-moz-none'
  12240. },
  12241. attributes: { unselectable: 'on' }
  12242. });
  12243. const events$7 = () => derive$2([abort(selectstart(), always)]);
  12244. var ActiveUnselecting = /*#__PURE__*/Object.freeze({
  12245. __proto__: null,
  12246. events: events$7,
  12247. exhibit: exhibit$1
  12248. });
  12249. const Unselecting = create$4({
  12250. fields: [],
  12251. name: 'unselecting',
  12252. active: ActiveUnselecting
  12253. });
  12254. const renderPanelButton = (spec, sharedBackstage) => Dropdown.sketch({
  12255. dom: spec.dom,
  12256. components: spec.components,
  12257. toggleClass: 'mce-active',
  12258. dropdownBehaviours: derive$1([
  12259. DisablingConfigs.button(sharedBackstage.providers.isDisabled),
  12260. receivingConfig(),
  12261. Unselecting.config({}),
  12262. Tabstopping.config({})
  12263. ]),
  12264. layouts: spec.layouts,
  12265. sandboxClasses: ['tox-dialog__popups'],
  12266. lazySink: sharedBackstage.getSink,
  12267. fetch: comp => Future.nu(callback => spec.fetch(callback)).map(items => Optional.from(createTieredDataFrom(deepMerge(createPartialChoiceMenu(generate$6('menu-value'), items, value => {
  12268. spec.onItemAction(comp, value);
  12269. }, spec.columns, spec.presets, ItemResponse$1.CLOSE_ON_EXECUTE, never, sharedBackstage.providers), { movement: deriveMenuMovement(spec.columns, spec.presets) })))),
  12270. parts: { menu: part(false, 1, spec.presets) }
  12271. });
  12272. const colorInputChangeEvent = generate$6('color-input-change');
  12273. const colorSwatchChangeEvent = generate$6('color-swatch-change');
  12274. const colorPickerCancelEvent = generate$6('color-picker-cancel');
  12275. const renderColorInput = (spec, sharedBackstage, colorInputBackstage, initialData) => {
  12276. const pField = FormField.parts.field({
  12277. factory: Input,
  12278. inputClasses: ['tox-textfield'],
  12279. data: initialData,
  12280. onSetValue: c => Invalidating.run(c).get(noop),
  12281. inputBehaviours: derive$1([
  12282. Disabling.config({ disabled: sharedBackstage.providers.isDisabled }),
  12283. receivingConfig(),
  12284. Tabstopping.config({}),
  12285. Invalidating.config({
  12286. invalidClass: 'tox-textbox-field-invalid',
  12287. getRoot: comp => parentElement(comp.element),
  12288. notify: {
  12289. onValid: comp => {
  12290. const val = Representing.getValue(comp);
  12291. emitWith(comp, colorInputChangeEvent, { color: val });
  12292. }
  12293. },
  12294. validator: {
  12295. validateOnLoad: false,
  12296. validate: input => {
  12297. const inputValue = Representing.getValue(input);
  12298. if (inputValue.length === 0) {
  12299. return Future.pure(Result.value(true));
  12300. } else {
  12301. const span = SugarElement.fromTag('span');
  12302. set$8(span, 'background-color', inputValue);
  12303. const res = getRaw(span, 'background-color').fold(() => Result.error('blah'), _ => Result.value(inputValue));
  12304. return Future.pure(res);
  12305. }
  12306. }
  12307. }
  12308. })
  12309. ]),
  12310. selectOnFocus: false
  12311. });
  12312. const pLabel = spec.label.map(label => renderLabel$2(label, sharedBackstage.providers));
  12313. const emitSwatchChange = (colorBit, value) => {
  12314. emitWith(colorBit, colorSwatchChangeEvent, { value });
  12315. };
  12316. const onItemAction = (comp, value) => {
  12317. memColorButton.getOpt(comp).each(colorBit => {
  12318. if (value === 'custom') {
  12319. colorInputBackstage.colorPicker(valueOpt => {
  12320. valueOpt.fold(() => emit(colorBit, colorPickerCancelEvent), value => {
  12321. emitSwatchChange(colorBit, value);
  12322. addColor(spec.storageKey, value);
  12323. });
  12324. }, '#ffffff');
  12325. } else if (value === 'remove') {
  12326. emitSwatchChange(colorBit, '');
  12327. } else {
  12328. emitSwatchChange(colorBit, value);
  12329. }
  12330. });
  12331. };
  12332. const memColorButton = record(renderPanelButton({
  12333. dom: {
  12334. tag: 'span',
  12335. attributes: { 'aria-label': sharedBackstage.providers.translate('Color swatch') }
  12336. },
  12337. layouts: {
  12338. onRtl: () => [
  12339. southwest$2,
  12340. southeast$2,
  12341. south$2
  12342. ],
  12343. onLtr: () => [
  12344. southeast$2,
  12345. southwest$2,
  12346. south$2
  12347. ]
  12348. },
  12349. components: [],
  12350. fetch: getFetch$1(colorInputBackstage.getColors(spec.storageKey), spec.storageKey, colorInputBackstage.hasCustomColors()),
  12351. columns: colorInputBackstage.getColorCols(spec.storageKey),
  12352. presets: 'color',
  12353. onItemAction
  12354. }, sharedBackstage));
  12355. return FormField.sketch({
  12356. dom: {
  12357. tag: 'div',
  12358. classes: ['tox-form__group']
  12359. },
  12360. components: pLabel.toArray().concat([{
  12361. dom: {
  12362. tag: 'div',
  12363. classes: ['tox-color-input']
  12364. },
  12365. components: [
  12366. pField,
  12367. memColorButton.asSpec()
  12368. ]
  12369. }]),
  12370. fieldBehaviours: derive$1([config('form-field-events', [
  12371. run$1(colorInputChangeEvent, (comp, se) => {
  12372. memColorButton.getOpt(comp).each(colorButton => {
  12373. set$8(colorButton.element, 'background-color', se.event.color);
  12374. });
  12375. emitWith(comp, formChangeEvent, { name: spec.name });
  12376. }),
  12377. run$1(colorSwatchChangeEvent, (comp, se) => {
  12378. FormField.getField(comp).each(field => {
  12379. Representing.setValue(field, se.event.value);
  12380. Composing.getCurrent(comp).each(Focusing.focus);
  12381. });
  12382. }),
  12383. run$1(colorPickerCancelEvent, (comp, _se) => {
  12384. FormField.getField(comp).each(_field => {
  12385. Composing.getCurrent(comp).each(Focusing.focus);
  12386. });
  12387. })
  12388. ])])
  12389. });
  12390. };
  12391. const labelPart = optional({
  12392. schema: [required$1('dom')],
  12393. name: 'label'
  12394. });
  12395. const edgePart = name => optional({
  12396. name: '' + name + '-edge',
  12397. overrides: detail => {
  12398. const action = detail.model.manager.edgeActions[name];
  12399. return action.fold(() => ({}), a => ({
  12400. events: derive$2([
  12401. runActionExtra(touchstart(), (comp, se, d) => a(comp, d), [detail]),
  12402. runActionExtra(mousedown(), (comp, se, d) => a(comp, d), [detail]),
  12403. runActionExtra(mousemove(), (comp, se, det) => {
  12404. if (det.mouseIsDown.get()) {
  12405. a(comp, det);
  12406. }
  12407. }, [detail])
  12408. ])
  12409. }));
  12410. }
  12411. });
  12412. const tlEdgePart = edgePart('top-left');
  12413. const tedgePart = edgePart('top');
  12414. const trEdgePart = edgePart('top-right');
  12415. const redgePart = edgePart('right');
  12416. const brEdgePart = edgePart('bottom-right');
  12417. const bedgePart = edgePart('bottom');
  12418. const blEdgePart = edgePart('bottom-left');
  12419. const ledgePart = edgePart('left');
  12420. const thumbPart = required({
  12421. name: 'thumb',
  12422. defaults: constant$1({ dom: { styles: { position: 'absolute' } } }),
  12423. overrides: detail => {
  12424. return {
  12425. events: derive$2([
  12426. redirectToPart(touchstart(), detail, 'spectrum'),
  12427. redirectToPart(touchmove(), detail, 'spectrum'),
  12428. redirectToPart(touchend(), detail, 'spectrum'),
  12429. redirectToPart(mousedown(), detail, 'spectrum'),
  12430. redirectToPart(mousemove(), detail, 'spectrum'),
  12431. redirectToPart(mouseup(), detail, 'spectrum')
  12432. ])
  12433. };
  12434. }
  12435. });
  12436. const spectrumPart = required({
  12437. schema: [customField('mouseIsDown', () => Cell(false))],
  12438. name: 'spectrum',
  12439. overrides: detail => {
  12440. const modelDetail = detail.model;
  12441. const model = modelDetail.manager;
  12442. const setValueFrom = (component, simulatedEvent) => model.getValueFromEvent(simulatedEvent).map(value => model.setValueFrom(component, detail, value));
  12443. return {
  12444. behaviours: derive$1([
  12445. Keying.config({
  12446. mode: 'special',
  12447. onLeft: spectrum => model.onLeft(spectrum, detail),
  12448. onRight: spectrum => model.onRight(spectrum, detail),
  12449. onUp: spectrum => model.onUp(spectrum, detail),
  12450. onDown: spectrum => model.onDown(spectrum, detail)
  12451. }),
  12452. Focusing.config({})
  12453. ]),
  12454. events: derive$2([
  12455. run$1(touchstart(), setValueFrom),
  12456. run$1(touchmove(), setValueFrom),
  12457. run$1(mousedown(), setValueFrom),
  12458. run$1(mousemove(), (spectrum, se) => {
  12459. if (detail.mouseIsDown.get()) {
  12460. setValueFrom(spectrum, se);
  12461. }
  12462. })
  12463. ])
  12464. };
  12465. }
  12466. });
  12467. var SliderParts = [
  12468. labelPart,
  12469. ledgePart,
  12470. redgePart,
  12471. tedgePart,
  12472. bedgePart,
  12473. tlEdgePart,
  12474. trEdgePart,
  12475. blEdgePart,
  12476. brEdgePart,
  12477. thumbPart,
  12478. spectrumPart
  12479. ];
  12480. const _sliderChangeEvent = 'slider.change.value';
  12481. const sliderChangeEvent = constant$1(_sliderChangeEvent);
  12482. const isTouchEvent$2 = evt => evt.type.indexOf('touch') !== -1;
  12483. const getEventSource = simulatedEvent => {
  12484. const evt = simulatedEvent.event.raw;
  12485. if (isTouchEvent$2(evt)) {
  12486. const touchEvent = evt;
  12487. return touchEvent.touches !== undefined && touchEvent.touches.length === 1 ? Optional.some(touchEvent.touches[0]).map(t => SugarPosition(t.clientX, t.clientY)) : Optional.none();
  12488. } else {
  12489. const mouseEvent = evt;
  12490. return mouseEvent.clientX !== undefined ? Optional.some(mouseEvent).map(me => SugarPosition(me.clientX, me.clientY)) : Optional.none();
  12491. }
  12492. };
  12493. const t = 'top', r = 'right', b = 'bottom', l = 'left';
  12494. const minX = detail => detail.model.minX;
  12495. const minY = detail => detail.model.minY;
  12496. const min1X = detail => detail.model.minX - 1;
  12497. const min1Y = detail => detail.model.minY - 1;
  12498. const maxX = detail => detail.model.maxX;
  12499. const maxY = detail => detail.model.maxY;
  12500. const max1X = detail => detail.model.maxX + 1;
  12501. const max1Y = detail => detail.model.maxY + 1;
  12502. const range = (detail, max, min) => max(detail) - min(detail);
  12503. const xRange = detail => range(detail, maxX, minX);
  12504. const yRange = detail => range(detail, maxY, minY);
  12505. const halfX = detail => xRange(detail) / 2;
  12506. const halfY = detail => yRange(detail) / 2;
  12507. const step = detail => detail.stepSize;
  12508. const snap = detail => detail.snapToGrid;
  12509. const snapStart = detail => detail.snapStart;
  12510. const rounded = detail => detail.rounded;
  12511. const hasEdge = (detail, edgeName) => detail[edgeName + '-edge'] !== undefined;
  12512. const hasLEdge = detail => hasEdge(detail, l);
  12513. const hasREdge = detail => hasEdge(detail, r);
  12514. const hasTEdge = detail => hasEdge(detail, t);
  12515. const hasBEdge = detail => hasEdge(detail, b);
  12516. const currentValue = detail => detail.model.value.get();
  12517. const xyValue = (x, y) => ({
  12518. x,
  12519. y
  12520. });
  12521. const fireSliderChange$3 = (component, value) => {
  12522. emitWith(component, sliderChangeEvent(), { value });
  12523. };
  12524. const setToTLEdgeXY = (edge, detail) => {
  12525. fireSliderChange$3(edge, xyValue(min1X(detail), min1Y(detail)));
  12526. };
  12527. const setToTEdge = (edge, detail) => {
  12528. fireSliderChange$3(edge, min1Y(detail));
  12529. };
  12530. const setToTEdgeXY = (edge, detail) => {
  12531. fireSliderChange$3(edge, xyValue(halfX(detail), min1Y(detail)));
  12532. };
  12533. const setToTREdgeXY = (edge, detail) => {
  12534. fireSliderChange$3(edge, xyValue(max1X(detail), min1Y(detail)));
  12535. };
  12536. const setToREdge = (edge, detail) => {
  12537. fireSliderChange$3(edge, max1X(detail));
  12538. };
  12539. const setToREdgeXY = (edge, detail) => {
  12540. fireSliderChange$3(edge, xyValue(max1X(detail), halfY(detail)));
  12541. };
  12542. const setToBREdgeXY = (edge, detail) => {
  12543. fireSliderChange$3(edge, xyValue(max1X(detail), max1Y(detail)));
  12544. };
  12545. const setToBEdge = (edge, detail) => {
  12546. fireSliderChange$3(edge, max1Y(detail));
  12547. };
  12548. const setToBEdgeXY = (edge, detail) => {
  12549. fireSliderChange$3(edge, xyValue(halfX(detail), max1Y(detail)));
  12550. };
  12551. const setToBLEdgeXY = (edge, detail) => {
  12552. fireSliderChange$3(edge, xyValue(min1X(detail), max1Y(detail)));
  12553. };
  12554. const setToLEdge = (edge, detail) => {
  12555. fireSliderChange$3(edge, min1X(detail));
  12556. };
  12557. const setToLEdgeXY = (edge, detail) => {
  12558. fireSliderChange$3(edge, xyValue(min1X(detail), halfY(detail)));
  12559. };
  12560. const reduceBy = (value, min, max, step) => {
  12561. if (value < min) {
  12562. return value;
  12563. } else if (value > max) {
  12564. return max;
  12565. } else if (value === min) {
  12566. return min - 1;
  12567. } else {
  12568. return Math.max(min, value - step);
  12569. }
  12570. };
  12571. const increaseBy = (value, min, max, step) => {
  12572. if (value > max) {
  12573. return value;
  12574. } else if (value < min) {
  12575. return min;
  12576. } else if (value === max) {
  12577. return max + 1;
  12578. } else {
  12579. return Math.min(max, value + step);
  12580. }
  12581. };
  12582. const capValue = (value, min, max) => Math.max(min, Math.min(max, value));
  12583. const snapValueOf = (value, min, max, step, snapStart) => snapStart.fold(() => {
  12584. const initValue = value - min;
  12585. const extraValue = Math.round(initValue / step) * step;
  12586. return capValue(min + extraValue, min - 1, max + 1);
  12587. }, start => {
  12588. const remainder = (value - start) % step;
  12589. const adjustment = Math.round(remainder / step);
  12590. const rawSteps = Math.floor((value - start) / step);
  12591. const maxSteps = Math.floor((max - start) / step);
  12592. const numSteps = Math.min(maxSteps, rawSteps + adjustment);
  12593. const r = start + numSteps * step;
  12594. return Math.max(start, r);
  12595. });
  12596. const findOffsetOf = (value, min, max) => Math.min(max, Math.max(value, min)) - min;
  12597. const findValueOf = args => {
  12598. const {min, max, range, value, step, snap, snapStart, rounded, hasMinEdge, hasMaxEdge, minBound, maxBound, screenRange} = args;
  12599. const capMin = hasMinEdge ? min - 1 : min;
  12600. const capMax = hasMaxEdge ? max + 1 : max;
  12601. if (value < minBound) {
  12602. return capMin;
  12603. } else if (value > maxBound) {
  12604. return capMax;
  12605. } else {
  12606. const offset = findOffsetOf(value, minBound, maxBound);
  12607. const newValue = capValue(offset / screenRange * range + min, capMin, capMax);
  12608. if (snap && newValue >= min && newValue <= max) {
  12609. return snapValueOf(newValue, min, max, step, snapStart);
  12610. } else if (rounded) {
  12611. return Math.round(newValue);
  12612. } else {
  12613. return newValue;
  12614. }
  12615. }
  12616. };
  12617. const findOffsetOfValue$2 = args => {
  12618. const {min, max, range, value, hasMinEdge, hasMaxEdge, maxBound, maxOffset, centerMinEdge, centerMaxEdge} = args;
  12619. if (value < min) {
  12620. return hasMinEdge ? 0 : centerMinEdge;
  12621. } else if (value > max) {
  12622. return hasMaxEdge ? maxBound : centerMaxEdge;
  12623. } else {
  12624. return (value - min) / range * maxOffset;
  12625. }
  12626. };
  12627. const top = 'top', right = 'right', bottom = 'bottom', left = 'left', width = 'width', height = 'height';
  12628. const getBounds = component => component.element.dom.getBoundingClientRect();
  12629. const getBoundsProperty = (bounds, property) => bounds[property];
  12630. const getMinXBounds = component => {
  12631. const bounds = getBounds(component);
  12632. return getBoundsProperty(bounds, left);
  12633. };
  12634. const getMaxXBounds = component => {
  12635. const bounds = getBounds(component);
  12636. return getBoundsProperty(bounds, right);
  12637. };
  12638. const getMinYBounds = component => {
  12639. const bounds = getBounds(component);
  12640. return getBoundsProperty(bounds, top);
  12641. };
  12642. const getMaxYBounds = component => {
  12643. const bounds = getBounds(component);
  12644. return getBoundsProperty(bounds, bottom);
  12645. };
  12646. const getXScreenRange = component => {
  12647. const bounds = getBounds(component);
  12648. return getBoundsProperty(bounds, width);
  12649. };
  12650. const getYScreenRange = component => {
  12651. const bounds = getBounds(component);
  12652. return getBoundsProperty(bounds, height);
  12653. };
  12654. const getCenterOffsetOf = (componentMinEdge, componentMaxEdge, spectrumMinEdge) => (componentMinEdge + componentMaxEdge) / 2 - spectrumMinEdge;
  12655. const getXCenterOffSetOf = (component, spectrum) => {
  12656. const componentBounds = getBounds(component);
  12657. const spectrumBounds = getBounds(spectrum);
  12658. const componentMinEdge = getBoundsProperty(componentBounds, left);
  12659. const componentMaxEdge = getBoundsProperty(componentBounds, right);
  12660. const spectrumMinEdge = getBoundsProperty(spectrumBounds, left);
  12661. return getCenterOffsetOf(componentMinEdge, componentMaxEdge, spectrumMinEdge);
  12662. };
  12663. const getYCenterOffSetOf = (component, spectrum) => {
  12664. const componentBounds = getBounds(component);
  12665. const spectrumBounds = getBounds(spectrum);
  12666. const componentMinEdge = getBoundsProperty(componentBounds, top);
  12667. const componentMaxEdge = getBoundsProperty(componentBounds, bottom);
  12668. const spectrumMinEdge = getBoundsProperty(spectrumBounds, top);
  12669. return getCenterOffsetOf(componentMinEdge, componentMaxEdge, spectrumMinEdge);
  12670. };
  12671. const fireSliderChange$2 = (spectrum, value) => {
  12672. emitWith(spectrum, sliderChangeEvent(), { value });
  12673. };
  12674. const findValueOfOffset$1 = (spectrum, detail, left) => {
  12675. const args = {
  12676. min: minX(detail),
  12677. max: maxX(detail),
  12678. range: xRange(detail),
  12679. value: left,
  12680. step: step(detail),
  12681. snap: snap(detail),
  12682. snapStart: snapStart(detail),
  12683. rounded: rounded(detail),
  12684. hasMinEdge: hasLEdge(detail),
  12685. hasMaxEdge: hasREdge(detail),
  12686. minBound: getMinXBounds(spectrum),
  12687. maxBound: getMaxXBounds(spectrum),
  12688. screenRange: getXScreenRange(spectrum)
  12689. };
  12690. return findValueOf(args);
  12691. };
  12692. const setValueFrom$2 = (spectrum, detail, value) => {
  12693. const xValue = findValueOfOffset$1(spectrum, detail, value);
  12694. const sliderVal = xValue;
  12695. fireSliderChange$2(spectrum, sliderVal);
  12696. return xValue;
  12697. };
  12698. const setToMin$2 = (spectrum, detail) => {
  12699. const min = minX(detail);
  12700. fireSliderChange$2(spectrum, min);
  12701. };
  12702. const setToMax$2 = (spectrum, detail) => {
  12703. const max = maxX(detail);
  12704. fireSliderChange$2(spectrum, max);
  12705. };
  12706. const moveBy$2 = (direction, spectrum, detail) => {
  12707. const f = direction > 0 ? increaseBy : reduceBy;
  12708. const xValue = f(currentValue(detail), minX(detail), maxX(detail), step(detail));
  12709. fireSliderChange$2(spectrum, xValue);
  12710. return Optional.some(xValue);
  12711. };
  12712. const handleMovement$2 = direction => (spectrum, detail) => moveBy$2(direction, spectrum, detail).map(always);
  12713. const getValueFromEvent$2 = simulatedEvent => {
  12714. const pos = getEventSource(simulatedEvent);
  12715. return pos.map(p => p.left);
  12716. };
  12717. const findOffsetOfValue$1 = (spectrum, detail, value, minEdge, maxEdge) => {
  12718. const minOffset = 0;
  12719. const maxOffset = getXScreenRange(spectrum);
  12720. const centerMinEdge = minEdge.bind(edge => Optional.some(getXCenterOffSetOf(edge, spectrum))).getOr(minOffset);
  12721. const centerMaxEdge = maxEdge.bind(edge => Optional.some(getXCenterOffSetOf(edge, spectrum))).getOr(maxOffset);
  12722. const args = {
  12723. min: minX(detail),
  12724. max: maxX(detail),
  12725. range: xRange(detail),
  12726. value,
  12727. hasMinEdge: hasLEdge(detail),
  12728. hasMaxEdge: hasREdge(detail),
  12729. minBound: getMinXBounds(spectrum),
  12730. minOffset,
  12731. maxBound: getMaxXBounds(spectrum),
  12732. maxOffset,
  12733. centerMinEdge,
  12734. centerMaxEdge
  12735. };
  12736. return findOffsetOfValue$2(args);
  12737. };
  12738. const findPositionOfValue$1 = (slider, spectrum, value, minEdge, maxEdge, detail) => {
  12739. const offset = findOffsetOfValue$1(spectrum, detail, value, minEdge, maxEdge);
  12740. return getMinXBounds(spectrum) - getMinXBounds(slider) + offset;
  12741. };
  12742. const setPositionFromValue$2 = (slider, thumb, detail, edges) => {
  12743. const value = currentValue(detail);
  12744. const pos = findPositionOfValue$1(slider, edges.getSpectrum(slider), value, edges.getLeftEdge(slider), edges.getRightEdge(slider), detail);
  12745. const thumbRadius = get$c(thumb.element) / 2;
  12746. set$8(thumb.element, 'left', pos - thumbRadius + 'px');
  12747. };
  12748. const onLeft$2 = handleMovement$2(-1);
  12749. const onRight$2 = handleMovement$2(1);
  12750. const onUp$2 = Optional.none;
  12751. const onDown$2 = Optional.none;
  12752. const edgeActions$2 = {
  12753. 'top-left': Optional.none(),
  12754. 'top': Optional.none(),
  12755. 'top-right': Optional.none(),
  12756. 'right': Optional.some(setToREdge),
  12757. 'bottom-right': Optional.none(),
  12758. 'bottom': Optional.none(),
  12759. 'bottom-left': Optional.none(),
  12760. 'left': Optional.some(setToLEdge)
  12761. };
  12762. var HorizontalModel = /*#__PURE__*/Object.freeze({
  12763. __proto__: null,
  12764. setValueFrom: setValueFrom$2,
  12765. setToMin: setToMin$2,
  12766. setToMax: setToMax$2,
  12767. findValueOfOffset: findValueOfOffset$1,
  12768. getValueFromEvent: getValueFromEvent$2,
  12769. findPositionOfValue: findPositionOfValue$1,
  12770. setPositionFromValue: setPositionFromValue$2,
  12771. onLeft: onLeft$2,
  12772. onRight: onRight$2,
  12773. onUp: onUp$2,
  12774. onDown: onDown$2,
  12775. edgeActions: edgeActions$2
  12776. });
  12777. const fireSliderChange$1 = (spectrum, value) => {
  12778. emitWith(spectrum, sliderChangeEvent(), { value });
  12779. };
  12780. const findValueOfOffset = (spectrum, detail, top) => {
  12781. const args = {
  12782. min: minY(detail),
  12783. max: maxY(detail),
  12784. range: yRange(detail),
  12785. value: top,
  12786. step: step(detail),
  12787. snap: snap(detail),
  12788. snapStart: snapStart(detail),
  12789. rounded: rounded(detail),
  12790. hasMinEdge: hasTEdge(detail),
  12791. hasMaxEdge: hasBEdge(detail),
  12792. minBound: getMinYBounds(spectrum),
  12793. maxBound: getMaxYBounds(spectrum),
  12794. screenRange: getYScreenRange(spectrum)
  12795. };
  12796. return findValueOf(args);
  12797. };
  12798. const setValueFrom$1 = (spectrum, detail, value) => {
  12799. const yValue = findValueOfOffset(spectrum, detail, value);
  12800. const sliderVal = yValue;
  12801. fireSliderChange$1(spectrum, sliderVal);
  12802. return yValue;
  12803. };
  12804. const setToMin$1 = (spectrum, detail) => {
  12805. const min = minY(detail);
  12806. fireSliderChange$1(spectrum, min);
  12807. };
  12808. const setToMax$1 = (spectrum, detail) => {
  12809. const max = maxY(detail);
  12810. fireSliderChange$1(spectrum, max);
  12811. };
  12812. const moveBy$1 = (direction, spectrum, detail) => {
  12813. const f = direction > 0 ? increaseBy : reduceBy;
  12814. const yValue = f(currentValue(detail), minY(detail), maxY(detail), step(detail));
  12815. fireSliderChange$1(spectrum, yValue);
  12816. return Optional.some(yValue);
  12817. };
  12818. const handleMovement$1 = direction => (spectrum, detail) => moveBy$1(direction, spectrum, detail).map(always);
  12819. const getValueFromEvent$1 = simulatedEvent => {
  12820. const pos = getEventSource(simulatedEvent);
  12821. return pos.map(p => {
  12822. return p.top;
  12823. });
  12824. };
  12825. const findOffsetOfValue = (spectrum, detail, value, minEdge, maxEdge) => {
  12826. const minOffset = 0;
  12827. const maxOffset = getYScreenRange(spectrum);
  12828. const centerMinEdge = minEdge.bind(edge => Optional.some(getYCenterOffSetOf(edge, spectrum))).getOr(minOffset);
  12829. const centerMaxEdge = maxEdge.bind(edge => Optional.some(getYCenterOffSetOf(edge, spectrum))).getOr(maxOffset);
  12830. const args = {
  12831. min: minY(detail),
  12832. max: maxY(detail),
  12833. range: yRange(detail),
  12834. value,
  12835. hasMinEdge: hasTEdge(detail),
  12836. hasMaxEdge: hasBEdge(detail),
  12837. minBound: getMinYBounds(spectrum),
  12838. minOffset,
  12839. maxBound: getMaxYBounds(spectrum),
  12840. maxOffset,
  12841. centerMinEdge,
  12842. centerMaxEdge
  12843. };
  12844. return findOffsetOfValue$2(args);
  12845. };
  12846. const findPositionOfValue = (slider, spectrum, value, minEdge, maxEdge, detail) => {
  12847. const offset = findOffsetOfValue(spectrum, detail, value, minEdge, maxEdge);
  12848. return getMinYBounds(spectrum) - getMinYBounds(slider) + offset;
  12849. };
  12850. const setPositionFromValue$1 = (slider, thumb, detail, edges) => {
  12851. const value = currentValue(detail);
  12852. const pos = findPositionOfValue(slider, edges.getSpectrum(slider), value, edges.getTopEdge(slider), edges.getBottomEdge(slider), detail);
  12853. const thumbRadius = get$d(thumb.element) / 2;
  12854. set$8(thumb.element, 'top', pos - thumbRadius + 'px');
  12855. };
  12856. const onLeft$1 = Optional.none;
  12857. const onRight$1 = Optional.none;
  12858. const onUp$1 = handleMovement$1(-1);
  12859. const onDown$1 = handleMovement$1(1);
  12860. const edgeActions$1 = {
  12861. 'top-left': Optional.none(),
  12862. 'top': Optional.some(setToTEdge),
  12863. 'top-right': Optional.none(),
  12864. 'right': Optional.none(),
  12865. 'bottom-right': Optional.none(),
  12866. 'bottom': Optional.some(setToBEdge),
  12867. 'bottom-left': Optional.none(),
  12868. 'left': Optional.none()
  12869. };
  12870. var VerticalModel = /*#__PURE__*/Object.freeze({
  12871. __proto__: null,
  12872. setValueFrom: setValueFrom$1,
  12873. setToMin: setToMin$1,
  12874. setToMax: setToMax$1,
  12875. findValueOfOffset: findValueOfOffset,
  12876. getValueFromEvent: getValueFromEvent$1,
  12877. findPositionOfValue: findPositionOfValue,
  12878. setPositionFromValue: setPositionFromValue$1,
  12879. onLeft: onLeft$1,
  12880. onRight: onRight$1,
  12881. onUp: onUp$1,
  12882. onDown: onDown$1,
  12883. edgeActions: edgeActions$1
  12884. });
  12885. const fireSliderChange = (spectrum, value) => {
  12886. emitWith(spectrum, sliderChangeEvent(), { value });
  12887. };
  12888. const sliderValue = (x, y) => ({
  12889. x,
  12890. y
  12891. });
  12892. const setValueFrom = (spectrum, detail, value) => {
  12893. const xValue = findValueOfOffset$1(spectrum, detail, value.left);
  12894. const yValue = findValueOfOffset(spectrum, detail, value.top);
  12895. const val = sliderValue(xValue, yValue);
  12896. fireSliderChange(spectrum, val);
  12897. return val;
  12898. };
  12899. const moveBy = (direction, isVerticalMovement, spectrum, detail) => {
  12900. const f = direction > 0 ? increaseBy : reduceBy;
  12901. const xValue = isVerticalMovement ? currentValue(detail).x : f(currentValue(detail).x, minX(detail), maxX(detail), step(detail));
  12902. const yValue = !isVerticalMovement ? currentValue(detail).y : f(currentValue(detail).y, minY(detail), maxY(detail), step(detail));
  12903. fireSliderChange(spectrum, sliderValue(xValue, yValue));
  12904. return Optional.some(xValue);
  12905. };
  12906. const handleMovement = (direction, isVerticalMovement) => (spectrum, detail) => moveBy(direction, isVerticalMovement, spectrum, detail).map(always);
  12907. const setToMin = (spectrum, detail) => {
  12908. const mX = minX(detail);
  12909. const mY = minY(detail);
  12910. fireSliderChange(spectrum, sliderValue(mX, mY));
  12911. };
  12912. const setToMax = (spectrum, detail) => {
  12913. const mX = maxX(detail);
  12914. const mY = maxY(detail);
  12915. fireSliderChange(spectrum, sliderValue(mX, mY));
  12916. };
  12917. const getValueFromEvent = simulatedEvent => getEventSource(simulatedEvent);
  12918. const setPositionFromValue = (slider, thumb, detail, edges) => {
  12919. const value = currentValue(detail);
  12920. const xPos = findPositionOfValue$1(slider, edges.getSpectrum(slider), value.x, edges.getLeftEdge(slider), edges.getRightEdge(slider), detail);
  12921. const yPos = findPositionOfValue(slider, edges.getSpectrum(slider), value.y, edges.getTopEdge(slider), edges.getBottomEdge(slider), detail);
  12922. const thumbXRadius = get$c(thumb.element) / 2;
  12923. const thumbYRadius = get$d(thumb.element) / 2;
  12924. set$8(thumb.element, 'left', xPos - thumbXRadius + 'px');
  12925. set$8(thumb.element, 'top', yPos - thumbYRadius + 'px');
  12926. };
  12927. const onLeft = handleMovement(-1, false);
  12928. const onRight = handleMovement(1, false);
  12929. const onUp = handleMovement(-1, true);
  12930. const onDown = handleMovement(1, true);
  12931. const edgeActions = {
  12932. 'top-left': Optional.some(setToTLEdgeXY),
  12933. 'top': Optional.some(setToTEdgeXY),
  12934. 'top-right': Optional.some(setToTREdgeXY),
  12935. 'right': Optional.some(setToREdgeXY),
  12936. 'bottom-right': Optional.some(setToBREdgeXY),
  12937. 'bottom': Optional.some(setToBEdgeXY),
  12938. 'bottom-left': Optional.some(setToBLEdgeXY),
  12939. 'left': Optional.some(setToLEdgeXY)
  12940. };
  12941. var TwoDModel = /*#__PURE__*/Object.freeze({
  12942. __proto__: null,
  12943. setValueFrom: setValueFrom,
  12944. setToMin: setToMin,
  12945. setToMax: setToMax,
  12946. getValueFromEvent: getValueFromEvent,
  12947. setPositionFromValue: setPositionFromValue,
  12948. onLeft: onLeft,
  12949. onRight: onRight,
  12950. onUp: onUp,
  12951. onDown: onDown,
  12952. edgeActions: edgeActions
  12953. });
  12954. const SliderSchema = [
  12955. defaulted('stepSize', 1),
  12956. defaulted('onChange', noop),
  12957. defaulted('onChoose', noop),
  12958. defaulted('onInit', noop),
  12959. defaulted('onDragStart', noop),
  12960. defaulted('onDragEnd', noop),
  12961. defaulted('snapToGrid', false),
  12962. defaulted('rounded', true),
  12963. option$3('snapStart'),
  12964. requiredOf('model', choose$1('mode', {
  12965. x: [
  12966. defaulted('minX', 0),
  12967. defaulted('maxX', 100),
  12968. customField('value', spec => Cell(spec.mode.minX)),
  12969. required$1('getInitialValue'),
  12970. output$1('manager', HorizontalModel)
  12971. ],
  12972. y: [
  12973. defaulted('minY', 0),
  12974. defaulted('maxY', 100),
  12975. customField('value', spec => Cell(spec.mode.minY)),
  12976. required$1('getInitialValue'),
  12977. output$1('manager', VerticalModel)
  12978. ],
  12979. xy: [
  12980. defaulted('minX', 0),
  12981. defaulted('maxX', 100),
  12982. defaulted('minY', 0),
  12983. defaulted('maxY', 100),
  12984. customField('value', spec => Cell({
  12985. x: spec.mode.minX,
  12986. y: spec.mode.minY
  12987. })),
  12988. required$1('getInitialValue'),
  12989. output$1('manager', TwoDModel)
  12990. ]
  12991. })),
  12992. field('sliderBehaviours', [
  12993. Keying,
  12994. Representing
  12995. ]),
  12996. customField('mouseIsDown', () => Cell(false))
  12997. ];
  12998. const sketch$2 = (detail, components, _spec, _externals) => {
  12999. const getThumb = component => getPartOrDie(component, detail, 'thumb');
  13000. const getSpectrum = component => getPartOrDie(component, detail, 'spectrum');
  13001. const getLeftEdge = component => getPart(component, detail, 'left-edge');
  13002. const getRightEdge = component => getPart(component, detail, 'right-edge');
  13003. const getTopEdge = component => getPart(component, detail, 'top-edge');
  13004. const getBottomEdge = component => getPart(component, detail, 'bottom-edge');
  13005. const modelDetail = detail.model;
  13006. const model = modelDetail.manager;
  13007. const refresh = (slider, thumb) => {
  13008. model.setPositionFromValue(slider, thumb, detail, {
  13009. getLeftEdge,
  13010. getRightEdge,
  13011. getTopEdge,
  13012. getBottomEdge,
  13013. getSpectrum
  13014. });
  13015. };
  13016. const setValue = (slider, newValue) => {
  13017. modelDetail.value.set(newValue);
  13018. const thumb = getThumb(slider);
  13019. refresh(slider, thumb);
  13020. };
  13021. const changeValue = (slider, newValue) => {
  13022. setValue(slider, newValue);
  13023. const thumb = getThumb(slider);
  13024. detail.onChange(slider, thumb, newValue);
  13025. return Optional.some(true);
  13026. };
  13027. const resetToMin = slider => {
  13028. model.setToMin(slider, detail);
  13029. };
  13030. const resetToMax = slider => {
  13031. model.setToMax(slider, detail);
  13032. };
  13033. const choose = slider => {
  13034. const fireOnChoose = () => {
  13035. getPart(slider, detail, 'thumb').each(thumb => {
  13036. const value = modelDetail.value.get();
  13037. detail.onChoose(slider, thumb, value);
  13038. });
  13039. };
  13040. const wasDown = detail.mouseIsDown.get();
  13041. detail.mouseIsDown.set(false);
  13042. if (wasDown) {
  13043. fireOnChoose();
  13044. }
  13045. };
  13046. const onDragStart = (slider, simulatedEvent) => {
  13047. simulatedEvent.stop();
  13048. detail.mouseIsDown.set(true);
  13049. detail.onDragStart(slider, getThumb(slider));
  13050. };
  13051. const onDragEnd = (slider, simulatedEvent) => {
  13052. simulatedEvent.stop();
  13053. detail.onDragEnd(slider, getThumb(slider));
  13054. choose(slider);
  13055. };
  13056. return {
  13057. uid: detail.uid,
  13058. dom: detail.dom,
  13059. components,
  13060. behaviours: augment(detail.sliderBehaviours, [
  13061. Keying.config({
  13062. mode: 'special',
  13063. focusIn: slider => {
  13064. return getPart(slider, detail, 'spectrum').map(Keying.focusIn).map(always);
  13065. }
  13066. }),
  13067. Representing.config({
  13068. store: {
  13069. mode: 'manual',
  13070. getValue: _ => {
  13071. return modelDetail.value.get();
  13072. },
  13073. setValue
  13074. }
  13075. }),
  13076. Receiving.config({ channels: { [mouseReleased()]: { onReceive: choose } } })
  13077. ]),
  13078. events: derive$2([
  13079. run$1(sliderChangeEvent(), (slider, simulatedEvent) => {
  13080. changeValue(slider, simulatedEvent.event.value);
  13081. }),
  13082. runOnAttached((slider, _simulatedEvent) => {
  13083. const getInitial = modelDetail.getInitialValue();
  13084. modelDetail.value.set(getInitial);
  13085. const thumb = getThumb(slider);
  13086. refresh(slider, thumb);
  13087. const spectrum = getSpectrum(slider);
  13088. detail.onInit(slider, thumb, spectrum, modelDetail.value.get());
  13089. }),
  13090. run$1(touchstart(), onDragStart),
  13091. run$1(touchend(), onDragEnd),
  13092. run$1(mousedown(), onDragStart),
  13093. run$1(mouseup(), onDragEnd)
  13094. ]),
  13095. apis: {
  13096. resetToMin,
  13097. resetToMax,
  13098. setValue,
  13099. refresh
  13100. },
  13101. domModification: { styles: { position: 'relative' } }
  13102. };
  13103. };
  13104. const Slider = composite({
  13105. name: 'Slider',
  13106. configFields: SliderSchema,
  13107. partFields: SliderParts,
  13108. factory: sketch$2,
  13109. apis: {
  13110. setValue: (apis, slider, value) => {
  13111. apis.setValue(slider, value);
  13112. },
  13113. resetToMin: (apis, slider) => {
  13114. apis.resetToMin(slider);
  13115. },
  13116. resetToMax: (apis, slider) => {
  13117. apis.resetToMax(slider);
  13118. },
  13119. refresh: (apis, slider) => {
  13120. apis.refresh(slider);
  13121. }
  13122. }
  13123. });
  13124. const fieldsUpdate = generate$6('rgb-hex-update');
  13125. const sliderUpdate = generate$6('slider-update');
  13126. const paletteUpdate = generate$6('palette-update');
  13127. const sliderFactory = (translate, getClass) => {
  13128. const spectrum = Slider.parts.spectrum({
  13129. dom: {
  13130. tag: 'div',
  13131. classes: [getClass('hue-slider-spectrum')],
  13132. attributes: { role: 'presentation' }
  13133. }
  13134. });
  13135. const thumb = Slider.parts.thumb({
  13136. dom: {
  13137. tag: 'div',
  13138. classes: [getClass('hue-slider-thumb')],
  13139. attributes: { role: 'presentation' }
  13140. }
  13141. });
  13142. return Slider.sketch({
  13143. dom: {
  13144. tag: 'div',
  13145. classes: [getClass('hue-slider')],
  13146. attributes: { role: 'presentation' }
  13147. },
  13148. rounded: false,
  13149. model: {
  13150. mode: 'y',
  13151. getInitialValue: constant$1(0)
  13152. },
  13153. components: [
  13154. spectrum,
  13155. thumb
  13156. ],
  13157. sliderBehaviours: derive$1([Focusing.config({})]),
  13158. onChange: (slider, _thumb, value) => {
  13159. emitWith(slider, sliderUpdate, { value });
  13160. }
  13161. });
  13162. };
  13163. const owner$1 = 'form';
  13164. const schema$i = [field('formBehaviours', [Representing])];
  13165. const getPartName$1 = name => '<alloy.field.' + name + '>';
  13166. const sketch$1 = fSpec => {
  13167. const parts = (() => {
  13168. const record = [];
  13169. const field = (name, config) => {
  13170. record.push(name);
  13171. return generateOne$1(owner$1, getPartName$1(name), config);
  13172. };
  13173. return {
  13174. field,
  13175. record: constant$1(record)
  13176. };
  13177. })();
  13178. const spec = fSpec(parts);
  13179. const partNames = parts.record();
  13180. const fieldParts = map$2(partNames, n => required({
  13181. name: n,
  13182. pname: getPartName$1(n)
  13183. }));
  13184. return composite$1(owner$1, schema$i, fieldParts, make$4, spec);
  13185. };
  13186. const toResult = (o, e) => o.fold(() => Result.error(e), Result.value);
  13187. const make$4 = (detail, components) => ({
  13188. uid: detail.uid,
  13189. dom: detail.dom,
  13190. components,
  13191. behaviours: augment(detail.formBehaviours, [Representing.config({
  13192. store: {
  13193. mode: 'manual',
  13194. getValue: form => {
  13195. const resPs = getAllParts(form, detail);
  13196. return map$1(resPs, (resPThunk, pName) => resPThunk().bind(v => {
  13197. const opt = Composing.getCurrent(v);
  13198. return toResult(opt, new Error(`Cannot find a current component to extract the value from for form part '${ pName }': ` + element(v.element)));
  13199. }).map(Representing.getValue));
  13200. },
  13201. setValue: (form, values) => {
  13202. each(values, (newValue, key) => {
  13203. getPart(form, detail, key).each(wrapper => {
  13204. Composing.getCurrent(wrapper).each(field => {
  13205. Representing.setValue(field, newValue);
  13206. });
  13207. });
  13208. });
  13209. }
  13210. }
  13211. })]),
  13212. apis: {
  13213. getField: (form, key) => {
  13214. return getPart(form, detail, key).bind(Composing.getCurrent);
  13215. }
  13216. }
  13217. });
  13218. const Form = {
  13219. getField: makeApi((apis, component, key) => apis.getField(component, key)),
  13220. sketch: sketch$1
  13221. };
  13222. const validInput = generate$6('valid-input');
  13223. const invalidInput = generate$6('invalid-input');
  13224. const validatingInput = generate$6('validating-input');
  13225. const translatePrefix = 'colorcustom.rgb.';
  13226. const rgbFormFactory = (translate, getClass, onValidHexx, onInvalidHexx) => {
  13227. const invalidation = (label, isValid) => Invalidating.config({
  13228. invalidClass: getClass('invalid'),
  13229. notify: {
  13230. onValidate: comp => {
  13231. emitWith(comp, validatingInput, { type: label });
  13232. },
  13233. onValid: comp => {
  13234. emitWith(comp, validInput, {
  13235. type: label,
  13236. value: Representing.getValue(comp)
  13237. });
  13238. },
  13239. onInvalid: comp => {
  13240. emitWith(comp, invalidInput, {
  13241. type: label,
  13242. value: Representing.getValue(comp)
  13243. });
  13244. }
  13245. },
  13246. validator: {
  13247. validate: comp => {
  13248. const value = Representing.getValue(comp);
  13249. const res = isValid(value) ? Result.value(true) : Result.error(translate('aria.input.invalid'));
  13250. return Future.pure(res);
  13251. },
  13252. validateOnLoad: false
  13253. }
  13254. });
  13255. const renderTextField = (isValid, name, label, description, data) => {
  13256. const helptext = translate(translatePrefix + 'range');
  13257. const pLabel = FormField.parts.label({
  13258. dom: {
  13259. tag: 'label',
  13260. attributes: { 'aria-label': description }
  13261. },
  13262. components: [text$2(label)]
  13263. });
  13264. const pField = FormField.parts.field({
  13265. data,
  13266. factory: Input,
  13267. inputAttributes: {
  13268. type: 'text',
  13269. ...name === 'hex' ? { 'aria-live': 'polite' } : {}
  13270. },
  13271. inputClasses: [getClass('textfield')],
  13272. inputBehaviours: derive$1([
  13273. invalidation(name, isValid),
  13274. Tabstopping.config({})
  13275. ]),
  13276. onSetValue: input => {
  13277. if (Invalidating.isInvalid(input)) {
  13278. const run = Invalidating.run(input);
  13279. run.get(noop);
  13280. }
  13281. }
  13282. });
  13283. const comps = [
  13284. pLabel,
  13285. pField
  13286. ];
  13287. const concats = name !== 'hex' ? [FormField.parts['aria-descriptor']({ text: helptext })] : [];
  13288. const components = comps.concat(concats);
  13289. return {
  13290. dom: {
  13291. tag: 'div',
  13292. attributes: { role: 'presentation' }
  13293. },
  13294. components
  13295. };
  13296. };
  13297. const copyRgbToHex = (form, rgba) => {
  13298. const hex = fromRgba(rgba);
  13299. Form.getField(form, 'hex').each(hexField => {
  13300. if (!Focusing.isFocused(hexField)) {
  13301. Representing.setValue(form, { hex: hex.value });
  13302. }
  13303. });
  13304. return hex;
  13305. };
  13306. const copyRgbToForm = (form, rgb) => {
  13307. const red = rgb.red;
  13308. const green = rgb.green;
  13309. const blue = rgb.blue;
  13310. Representing.setValue(form, {
  13311. red,
  13312. green,
  13313. blue
  13314. });
  13315. };
  13316. const memPreview = record({
  13317. dom: {
  13318. tag: 'div',
  13319. classes: [getClass('rgba-preview')],
  13320. styles: { 'background-color': 'white' },
  13321. attributes: { role: 'presentation' }
  13322. }
  13323. });
  13324. const updatePreview = (anyInSystem, hex) => {
  13325. memPreview.getOpt(anyInSystem).each(preview => {
  13326. set$8(preview.element, 'background-color', '#' + hex.value);
  13327. });
  13328. };
  13329. const factory = () => {
  13330. const state = {
  13331. red: Cell(Optional.some(255)),
  13332. green: Cell(Optional.some(255)),
  13333. blue: Cell(Optional.some(255)),
  13334. hex: Cell(Optional.some('ffffff'))
  13335. };
  13336. const copyHexToRgb = (form, hex) => {
  13337. const rgb = fromHex(hex);
  13338. copyRgbToForm(form, rgb);
  13339. setValueRgb(rgb);
  13340. };
  13341. const get = prop => state[prop].get();
  13342. const set = (prop, value) => {
  13343. state[prop].set(value);
  13344. };
  13345. const getValueRgb = () => get('red').bind(red => get('green').bind(green => get('blue').map(blue => rgbaColour(red, green, blue, 1))));
  13346. const setValueRgb = rgb => {
  13347. const red = rgb.red;
  13348. const green = rgb.green;
  13349. const blue = rgb.blue;
  13350. set('red', Optional.some(red));
  13351. set('green', Optional.some(green));
  13352. set('blue', Optional.some(blue));
  13353. };
  13354. const onInvalidInput = (form, simulatedEvent) => {
  13355. const data = simulatedEvent.event;
  13356. if (data.type !== 'hex') {
  13357. set(data.type, Optional.none());
  13358. } else {
  13359. onInvalidHexx(form);
  13360. }
  13361. };
  13362. const onValidHex = (form, value) => {
  13363. onValidHexx(form);
  13364. const hex = hexColour(value);
  13365. set('hex', Optional.some(value));
  13366. const rgb = fromHex(hex);
  13367. copyRgbToForm(form, rgb);
  13368. setValueRgb(rgb);
  13369. emitWith(form, fieldsUpdate, { hex });
  13370. updatePreview(form, hex);
  13371. };
  13372. const onValidRgb = (form, prop, value) => {
  13373. const val = parseInt(value, 10);
  13374. set(prop, Optional.some(val));
  13375. getValueRgb().each(rgb => {
  13376. const hex = copyRgbToHex(form, rgb);
  13377. emitWith(form, fieldsUpdate, { hex });
  13378. updatePreview(form, hex);
  13379. });
  13380. };
  13381. const isHexInputEvent = data => data.type === 'hex';
  13382. const onValidInput = (form, simulatedEvent) => {
  13383. const data = simulatedEvent.event;
  13384. if (isHexInputEvent(data)) {
  13385. onValidHex(form, data.value);
  13386. } else {
  13387. onValidRgb(form, data.type, data.value);
  13388. }
  13389. };
  13390. const formPartStrings = key => ({
  13391. label: translate(translatePrefix + key + '.label'),
  13392. description: translate(translatePrefix + key + '.description')
  13393. });
  13394. const redStrings = formPartStrings('red');
  13395. const greenStrings = formPartStrings('green');
  13396. const blueStrings = formPartStrings('blue');
  13397. const hexStrings = formPartStrings('hex');
  13398. return deepMerge(Form.sketch(parts => ({
  13399. dom: {
  13400. tag: 'form',
  13401. classes: [getClass('rgb-form')],
  13402. attributes: { 'aria-label': translate('aria.color.picker') }
  13403. },
  13404. components: [
  13405. parts.field('red', FormField.sketch(renderTextField(isRgbaComponent, 'red', redStrings.label, redStrings.description, 255))),
  13406. parts.field('green', FormField.sketch(renderTextField(isRgbaComponent, 'green', greenStrings.label, greenStrings.description, 255))),
  13407. parts.field('blue', FormField.sketch(renderTextField(isRgbaComponent, 'blue', blueStrings.label, blueStrings.description, 255))),
  13408. parts.field('hex', FormField.sketch(renderTextField(isHexString, 'hex', hexStrings.label, hexStrings.description, 'ffffff'))),
  13409. memPreview.asSpec()
  13410. ],
  13411. formBehaviours: derive$1([
  13412. Invalidating.config({ invalidClass: getClass('form-invalid') }),
  13413. config('rgb-form-events', [
  13414. run$1(validInput, onValidInput),
  13415. run$1(invalidInput, onInvalidInput),
  13416. run$1(validatingInput, onInvalidInput)
  13417. ])
  13418. ])
  13419. })), {
  13420. apis: {
  13421. updateHex: (form, hex) => {
  13422. Representing.setValue(form, { hex: hex.value });
  13423. copyHexToRgb(form, hex);
  13424. updatePreview(form, hex);
  13425. }
  13426. }
  13427. });
  13428. };
  13429. const rgbFormSketcher = single({
  13430. factory,
  13431. name: 'RgbForm',
  13432. configFields: [],
  13433. apis: {
  13434. updateHex: (apis, form, hex) => {
  13435. apis.updateHex(form, hex);
  13436. }
  13437. },
  13438. extraApis: {}
  13439. });
  13440. return rgbFormSketcher;
  13441. };
  13442. const paletteFactory = (_translate, getClass) => {
  13443. const spectrumPart = Slider.parts.spectrum({
  13444. dom: {
  13445. tag: 'canvas',
  13446. attributes: { role: 'presentation' },
  13447. classes: [getClass('sv-palette-spectrum')]
  13448. }
  13449. });
  13450. const thumbPart = Slider.parts.thumb({
  13451. dom: {
  13452. tag: 'div',
  13453. attributes: { role: 'presentation' },
  13454. classes: [getClass('sv-palette-thumb')],
  13455. innerHtml: `<div class=${ getClass('sv-palette-inner-thumb') } role="presentation"></div>`
  13456. }
  13457. });
  13458. const setColour = (canvas, rgba) => {
  13459. const {width, height} = canvas;
  13460. const ctx = canvas.getContext('2d');
  13461. if (ctx === null) {
  13462. return;
  13463. }
  13464. ctx.fillStyle = rgba;
  13465. ctx.fillRect(0, 0, width, height);
  13466. const grdWhite = ctx.createLinearGradient(0, 0, width, 0);
  13467. grdWhite.addColorStop(0, 'rgba(255,255,255,1)');
  13468. grdWhite.addColorStop(1, 'rgba(255,255,255,0)');
  13469. ctx.fillStyle = grdWhite;
  13470. ctx.fillRect(0, 0, width, height);
  13471. const grdBlack = ctx.createLinearGradient(0, 0, 0, height);
  13472. grdBlack.addColorStop(0, 'rgba(0,0,0,0)');
  13473. grdBlack.addColorStop(1, 'rgba(0,0,0,1)');
  13474. ctx.fillStyle = grdBlack;
  13475. ctx.fillRect(0, 0, width, height);
  13476. };
  13477. const setPaletteHue = (slider, hue) => {
  13478. const canvas = slider.components()[0].element.dom;
  13479. const hsv = hsvColour(hue, 100, 100);
  13480. const rgba = fromHsv(hsv);
  13481. setColour(canvas, toString(rgba));
  13482. };
  13483. const setPaletteThumb = (slider, hex) => {
  13484. const hsv = fromRgb(fromHex(hex));
  13485. Slider.setValue(slider, {
  13486. x: hsv.saturation,
  13487. y: 100 - hsv.value
  13488. });
  13489. };
  13490. const factory = _detail => {
  13491. const getInitialValue = constant$1({
  13492. x: 0,
  13493. y: 0
  13494. });
  13495. const onChange = (slider, _thumb, value) => {
  13496. emitWith(slider, paletteUpdate, { value });
  13497. };
  13498. const onInit = (_slider, _thumb, spectrum, _value) => {
  13499. setColour(spectrum.element.dom, toString(red));
  13500. };
  13501. const sliderBehaviours = derive$1([
  13502. Composing.config({ find: Optional.some }),
  13503. Focusing.config({})
  13504. ]);
  13505. return Slider.sketch({
  13506. dom: {
  13507. tag: 'div',
  13508. attributes: { role: 'presentation' },
  13509. classes: [getClass('sv-palette')]
  13510. },
  13511. model: {
  13512. mode: 'xy',
  13513. getInitialValue
  13514. },
  13515. rounded: false,
  13516. components: [
  13517. spectrumPart,
  13518. thumbPart
  13519. ],
  13520. onChange,
  13521. onInit,
  13522. sliderBehaviours
  13523. });
  13524. };
  13525. const saturationBrightnessPaletteSketcher = single({
  13526. factory,
  13527. name: 'SaturationBrightnessPalette',
  13528. configFields: [],
  13529. apis: {
  13530. setHue: (_apis, slider, hue) => {
  13531. setPaletteHue(slider, hue);
  13532. },
  13533. setThumb: (_apis, slider, hex) => {
  13534. setPaletteThumb(slider, hex);
  13535. }
  13536. },
  13537. extraApis: {}
  13538. });
  13539. return saturationBrightnessPaletteSketcher;
  13540. };
  13541. const makeFactory = (translate, getClass) => {
  13542. const factory = detail => {
  13543. const rgbForm = rgbFormFactory(translate, getClass, detail.onValidHex, detail.onInvalidHex);
  13544. const sbPalette = paletteFactory(translate, getClass);
  13545. const hueSliderToDegrees = hue => (100 - hue) / 100 * 360;
  13546. const hueDegreesToSlider = hue => 100 - hue / 360 * 100;
  13547. const state = {
  13548. paletteRgba: Cell(red),
  13549. paletteHue: Cell(0)
  13550. };
  13551. const memSlider = record(sliderFactory(translate, getClass));
  13552. const memPalette = record(sbPalette.sketch({}));
  13553. const memRgb = record(rgbForm.sketch({}));
  13554. const updatePalette = (anyInSystem, _hex, hue) => {
  13555. memPalette.getOpt(anyInSystem).each(palette => {
  13556. sbPalette.setHue(palette, hue);
  13557. });
  13558. };
  13559. const updateFields = (anyInSystem, hex) => {
  13560. memRgb.getOpt(anyInSystem).each(form => {
  13561. rgbForm.updateHex(form, hex);
  13562. });
  13563. };
  13564. const updateSlider = (anyInSystem, _hex, hue) => {
  13565. memSlider.getOpt(anyInSystem).each(slider => {
  13566. Slider.setValue(slider, hueDegreesToSlider(hue));
  13567. });
  13568. };
  13569. const updatePaletteThumb = (anyInSystem, hex) => {
  13570. memPalette.getOpt(anyInSystem).each(palette => {
  13571. sbPalette.setThumb(palette, hex);
  13572. });
  13573. };
  13574. const updateState = (hex, hue) => {
  13575. const rgba = fromHex(hex);
  13576. state.paletteRgba.set(rgba);
  13577. state.paletteHue.set(hue);
  13578. };
  13579. const runUpdates = (anyInSystem, hex, hue, updates) => {
  13580. updateState(hex, hue);
  13581. each$1(updates, update => {
  13582. update(anyInSystem, hex, hue);
  13583. });
  13584. };
  13585. const onPaletteUpdate = () => {
  13586. const updates = [updateFields];
  13587. return (form, simulatedEvent) => {
  13588. const value = simulatedEvent.event.value;
  13589. const oldHue = state.paletteHue.get();
  13590. const newHsv = hsvColour(oldHue, value.x, 100 - value.y);
  13591. const newHex = hsvToHex(newHsv);
  13592. runUpdates(form, newHex, oldHue, updates);
  13593. };
  13594. };
  13595. const onSliderUpdate = () => {
  13596. const updates = [
  13597. updatePalette,
  13598. updateFields
  13599. ];
  13600. return (form, simulatedEvent) => {
  13601. const hue = hueSliderToDegrees(simulatedEvent.event.value);
  13602. const oldRgb = state.paletteRgba.get();
  13603. const oldHsv = fromRgb(oldRgb);
  13604. const newHsv = hsvColour(hue, oldHsv.saturation, oldHsv.value);
  13605. const newHex = hsvToHex(newHsv);
  13606. runUpdates(form, newHex, hue, updates);
  13607. };
  13608. };
  13609. const onFieldsUpdate = () => {
  13610. const updates = [
  13611. updatePalette,
  13612. updateSlider,
  13613. updatePaletteThumb
  13614. ];
  13615. return (form, simulatedEvent) => {
  13616. const hex = simulatedEvent.event.hex;
  13617. const hsv = hexToHsv(hex);
  13618. runUpdates(form, hex, hsv.hue, updates);
  13619. };
  13620. };
  13621. return {
  13622. uid: detail.uid,
  13623. dom: detail.dom,
  13624. components: [
  13625. memPalette.asSpec(),
  13626. memSlider.asSpec(),
  13627. memRgb.asSpec()
  13628. ],
  13629. behaviours: derive$1([
  13630. config('colour-picker-events', [
  13631. run$1(fieldsUpdate, onFieldsUpdate()),
  13632. run$1(paletteUpdate, onPaletteUpdate()),
  13633. run$1(sliderUpdate, onSliderUpdate())
  13634. ]),
  13635. Composing.config({ find: comp => memRgb.getOpt(comp) }),
  13636. Keying.config({ mode: 'acyclic' })
  13637. ])
  13638. };
  13639. };
  13640. const colourPickerSketcher = single({
  13641. name: 'ColourPicker',
  13642. configFields: [
  13643. required$1('dom'),
  13644. defaulted('onValidHex', noop),
  13645. defaulted('onInvalidHex', noop)
  13646. ],
  13647. factory
  13648. });
  13649. return colourPickerSketcher;
  13650. };
  13651. const self = () => Composing.config({ find: Optional.some });
  13652. const memento$1 = mem => Composing.config({ find: mem.getOpt });
  13653. const childAt = index => Composing.config({ find: comp => child$2(comp.element, index).bind(element => comp.getSystem().getByDom(element).toOptional()) });
  13654. const ComposingConfigs = {
  13655. self,
  13656. memento: memento$1,
  13657. childAt
  13658. };
  13659. const processors = objOf([
  13660. defaulted('preprocess', identity),
  13661. defaulted('postprocess', identity)
  13662. ]);
  13663. const memento = (mem, rawProcessors) => {
  13664. const ps = asRawOrDie$1('RepresentingConfigs.memento processors', processors, rawProcessors);
  13665. return Representing.config({
  13666. store: {
  13667. mode: 'manual',
  13668. getValue: comp => {
  13669. const other = mem.get(comp);
  13670. const rawValue = Representing.getValue(other);
  13671. return ps.postprocess(rawValue);
  13672. },
  13673. setValue: (comp, rawValue) => {
  13674. const newValue = ps.preprocess(rawValue);
  13675. const other = mem.get(comp);
  13676. Representing.setValue(other, newValue);
  13677. }
  13678. }
  13679. });
  13680. };
  13681. const withComp = (optInitialValue, getter, setter) => Representing.config({
  13682. store: {
  13683. mode: 'manual',
  13684. ...optInitialValue.map(initialValue => ({ initialValue })).getOr({}),
  13685. getValue: getter,
  13686. setValue: setter
  13687. }
  13688. });
  13689. const withElement = (initialValue, getter, setter) => withComp(initialValue, c => getter(c.element), (c, v) => setter(c.element, v));
  13690. const domValue = optInitialValue => withElement(optInitialValue, get$6, set$5);
  13691. const domHtml = optInitialValue => withElement(optInitialValue, get$9, set$6);
  13692. const memory = initialValue => Representing.config({
  13693. store: {
  13694. mode: 'memory',
  13695. initialValue
  13696. }
  13697. });
  13698. const RepresentingConfigs = {
  13699. memento,
  13700. withElement,
  13701. withComp,
  13702. domValue,
  13703. domHtml,
  13704. memory
  13705. };
  13706. const english = {
  13707. 'colorcustom.rgb.red.label': 'R',
  13708. 'colorcustom.rgb.red.description': 'Red component',
  13709. 'colorcustom.rgb.green.label': 'G',
  13710. 'colorcustom.rgb.green.description': 'Green component',
  13711. 'colorcustom.rgb.blue.label': 'B',
  13712. 'colorcustom.rgb.blue.description': 'Blue component',
  13713. 'colorcustom.rgb.hex.label': '#',
  13714. 'colorcustom.rgb.hex.description': 'Hex color code',
  13715. 'colorcustom.rgb.range': 'Range 0 to 255',
  13716. 'aria.color.picker': 'Color Picker',
  13717. 'aria.input.invalid': 'Invalid input'
  13718. };
  13719. const translate$1 = providerBackstage => key => {
  13720. return providerBackstage.translate(english[key]);
  13721. };
  13722. const renderColorPicker = (_spec, providerBackstage, initialData) => {
  13723. const getClass = key => 'tox-' + key;
  13724. const colourPickerFactory = makeFactory(translate$1(providerBackstage), getClass);
  13725. const onValidHex = form => {
  13726. emitWith(form, formActionEvent, {
  13727. name: 'hex-valid',
  13728. value: true
  13729. });
  13730. };
  13731. const onInvalidHex = form => {
  13732. emitWith(form, formActionEvent, {
  13733. name: 'hex-valid',
  13734. value: false
  13735. });
  13736. };
  13737. const memPicker = record(colourPickerFactory.sketch({
  13738. dom: {
  13739. tag: 'div',
  13740. classes: [getClass('color-picker-container')],
  13741. attributes: { role: 'presentation' }
  13742. },
  13743. onValidHex,
  13744. onInvalidHex
  13745. }));
  13746. return {
  13747. dom: { tag: 'div' },
  13748. components: [memPicker.asSpec()],
  13749. behaviours: derive$1([
  13750. RepresentingConfigs.withComp(initialData, comp => {
  13751. const picker = memPicker.get(comp);
  13752. const optRgbForm = Composing.getCurrent(picker);
  13753. const optHex = optRgbForm.bind(rgbForm => {
  13754. const formValues = Representing.getValue(rgbForm);
  13755. return formValues.hex;
  13756. });
  13757. return optHex.map(hex => '#' + hex).getOr('');
  13758. }, (comp, newValue) => {
  13759. const pattern = /^#([a-fA-F0-9]{3}(?:[a-fA-F0-9]{3})?)/;
  13760. const valOpt = Optional.from(pattern.exec(newValue)).bind(matches => get$h(matches, 1));
  13761. const picker = memPicker.get(comp);
  13762. const optRgbForm = Composing.getCurrent(picker);
  13763. optRgbForm.fold(() => {
  13764. console.log('Can not find form');
  13765. }, rgbForm => {
  13766. Representing.setValue(rgbForm, { hex: valOpt.getOr('') });
  13767. Form.getField(rgbForm, 'hex').each(hexField => {
  13768. emit(hexField, input());
  13769. });
  13770. });
  13771. }),
  13772. ComposingConfigs.self()
  13773. ])
  13774. };
  13775. };
  13776. var global$2 = tinymce.util.Tools.resolve('tinymce.Resource');
  13777. const isOldCustomEditor = spec => has$2(spec, 'init');
  13778. const renderCustomEditor = spec => {
  13779. const editorApi = value$2();
  13780. const memReplaced = record({ dom: { tag: spec.tag } });
  13781. const initialValue = value$2();
  13782. return {
  13783. dom: {
  13784. tag: 'div',
  13785. classes: ['tox-custom-editor']
  13786. },
  13787. behaviours: derive$1([
  13788. config('custom-editor-events', [runOnAttached(component => {
  13789. memReplaced.getOpt(component).each(ta => {
  13790. (isOldCustomEditor(spec) ? spec.init(ta.element.dom) : global$2.load(spec.scriptId, spec.scriptUrl).then(init => init(ta.element.dom, spec.settings))).then(ea => {
  13791. initialValue.on(cvalue => {
  13792. ea.setValue(cvalue);
  13793. });
  13794. initialValue.clear();
  13795. editorApi.set(ea);
  13796. });
  13797. });
  13798. })]),
  13799. RepresentingConfigs.withComp(Optional.none(), () => editorApi.get().fold(() => initialValue.get().getOr(''), ed => ed.getValue()), (component, value) => {
  13800. editorApi.get().fold(() => initialValue.set(value), ed => ed.setValue(value));
  13801. }),
  13802. ComposingConfigs.self()
  13803. ]),
  13804. components: [memReplaced.asSpec()]
  13805. };
  13806. };
  13807. var global$1 = tinymce.util.Tools.resolve('tinymce.util.Tools');
  13808. const filterByExtension = (files, providersBackstage) => {
  13809. const allowedImageFileTypes = global$1.explode(providersBackstage.getOption('images_file_types'));
  13810. const isFileInAllowedTypes = file => exists(allowedImageFileTypes, type => endsWith(file.name.toLowerCase(), `.${ type.toLowerCase() }`));
  13811. return filter$2(from(files), isFileInAllowedTypes);
  13812. };
  13813. const renderDropZone = (spec, providersBackstage, initialData) => {
  13814. const stopper = (_, se) => {
  13815. se.stop();
  13816. };
  13817. const sequence = actions => (comp, se) => {
  13818. each$1(actions, a => {
  13819. a(comp, se);
  13820. });
  13821. };
  13822. const onDrop = (comp, se) => {
  13823. var _a;
  13824. if (!Disabling.isDisabled(comp)) {
  13825. const transferEvent = se.event.raw;
  13826. handleFiles(comp, (_a = transferEvent.dataTransfer) === null || _a === void 0 ? void 0 : _a.files);
  13827. }
  13828. };
  13829. const onSelect = (component, simulatedEvent) => {
  13830. const input = simulatedEvent.event.raw.target;
  13831. handleFiles(component, input.files);
  13832. };
  13833. const handleFiles = (component, files) => {
  13834. if (files) {
  13835. Representing.setValue(component, filterByExtension(files, providersBackstage));
  13836. emitWith(component, formChangeEvent, { name: spec.name });
  13837. }
  13838. };
  13839. const memInput = record({
  13840. dom: {
  13841. tag: 'input',
  13842. attributes: {
  13843. type: 'file',
  13844. accept: 'image/*'
  13845. },
  13846. styles: { display: 'none' }
  13847. },
  13848. behaviours: derive$1([config('input-file-events', [
  13849. cutter(click()),
  13850. cutter(tap())
  13851. ])])
  13852. });
  13853. const renderField = s => ({
  13854. uid: s.uid,
  13855. dom: {
  13856. tag: 'div',
  13857. classes: ['tox-dropzone-container']
  13858. },
  13859. behaviours: derive$1([
  13860. RepresentingConfigs.memory(initialData.getOr([])),
  13861. ComposingConfigs.self(),
  13862. Disabling.config({}),
  13863. Toggling.config({
  13864. toggleClass: 'dragenter',
  13865. toggleOnExecute: false
  13866. }),
  13867. config('dropzone-events', [
  13868. run$1('dragenter', sequence([
  13869. stopper,
  13870. Toggling.toggle
  13871. ])),
  13872. run$1('dragleave', sequence([
  13873. stopper,
  13874. Toggling.toggle
  13875. ])),
  13876. run$1('dragover', stopper),
  13877. run$1('drop', sequence([
  13878. stopper,
  13879. onDrop
  13880. ])),
  13881. run$1(change(), onSelect)
  13882. ])
  13883. ]),
  13884. components: [{
  13885. dom: {
  13886. tag: 'div',
  13887. classes: ['tox-dropzone'],
  13888. styles: {}
  13889. },
  13890. components: [
  13891. {
  13892. dom: { tag: 'p' },
  13893. components: [text$2(providersBackstage.translate('Drop an image here'))]
  13894. },
  13895. Button.sketch({
  13896. dom: {
  13897. tag: 'button',
  13898. styles: { position: 'relative' },
  13899. classes: [
  13900. 'tox-button',
  13901. 'tox-button--secondary'
  13902. ]
  13903. },
  13904. components: [
  13905. text$2(providersBackstage.translate('Browse for an image')),
  13906. memInput.asSpec()
  13907. ],
  13908. action: comp => {
  13909. const inputComp = memInput.get(comp);
  13910. inputComp.element.dom.click();
  13911. },
  13912. buttonBehaviours: derive$1([
  13913. Tabstopping.config({}),
  13914. DisablingConfigs.button(providersBackstage.isDisabled),
  13915. receivingConfig()
  13916. ])
  13917. })
  13918. ]
  13919. }]
  13920. });
  13921. const pLabel = spec.label.map(label => renderLabel$2(label, providersBackstage));
  13922. const pField = FormField.parts.field({ factory: { sketch: renderField } });
  13923. return renderFormFieldWith(pLabel, pField, ['tox-form__group--stretched'], []);
  13924. };
  13925. const renderGrid = (spec, backstage) => ({
  13926. dom: {
  13927. tag: 'div',
  13928. classes: [
  13929. 'tox-form__grid',
  13930. `tox-form__grid--${ spec.columns }col`
  13931. ]
  13932. },
  13933. components: map$2(spec.items, backstage.interpreter)
  13934. });
  13935. const beforeObject = generate$6('alloy-fake-before-tabstop');
  13936. const afterObject = generate$6('alloy-fake-after-tabstop');
  13937. const craftWithClasses = classes => {
  13938. return {
  13939. dom: {
  13940. tag: 'div',
  13941. styles: {
  13942. width: '1px',
  13943. height: '1px',
  13944. outline: 'none'
  13945. },
  13946. attributes: { tabindex: '0' },
  13947. classes
  13948. },
  13949. behaviours: derive$1([
  13950. Focusing.config({ ignore: true }),
  13951. Tabstopping.config({})
  13952. ])
  13953. };
  13954. };
  13955. const craft = spec => {
  13956. return {
  13957. dom: {
  13958. tag: 'div',
  13959. classes: ['tox-navobj']
  13960. },
  13961. components: [
  13962. craftWithClasses([beforeObject]),
  13963. spec,
  13964. craftWithClasses([afterObject])
  13965. ],
  13966. behaviours: derive$1([ComposingConfigs.childAt(1)])
  13967. };
  13968. };
  13969. const triggerTab = (placeholder, shiftKey) => {
  13970. emitWith(placeholder, keydown(), {
  13971. raw: {
  13972. which: 9,
  13973. shiftKey
  13974. }
  13975. });
  13976. };
  13977. const onFocus = (container, targetComp) => {
  13978. const target = targetComp.element;
  13979. if (has(target, beforeObject)) {
  13980. triggerTab(container, true);
  13981. } else if (has(target, afterObject)) {
  13982. triggerTab(container, false);
  13983. }
  13984. };
  13985. const isPseudoStop = element => {
  13986. return closest(element, [
  13987. '.' + beforeObject,
  13988. '.' + afterObject
  13989. ].join(','), never);
  13990. };
  13991. const getDynamicSource = initialData => {
  13992. const cachedValue = Cell(initialData.getOr(''));
  13993. return {
  13994. getValue: _frameComponent => cachedValue.get(),
  13995. setValue: (frameComponent, html) => {
  13996. if (cachedValue.get() !== html) {
  13997. set$9(frameComponent.element, 'srcdoc', html);
  13998. }
  13999. cachedValue.set(html);
  14000. }
  14001. };
  14002. };
  14003. const renderIFrame = (spec, providersBackstage, initialData) => {
  14004. const isSandbox = spec.sandboxed;
  14005. const isTransparent = spec.transparent;
  14006. const baseClass = 'tox-dialog__iframe';
  14007. const attributes = {
  14008. ...spec.label.map(title => ({ title })).getOr({}),
  14009. ...initialData.map(html => ({ srcdoc: html })).getOr({}),
  14010. ...isSandbox ? { sandbox: 'allow-scripts allow-same-origin' } : {}
  14011. };
  14012. const sourcing = getDynamicSource(initialData);
  14013. const pLabel = spec.label.map(label => renderLabel$2(label, providersBackstage));
  14014. const factory = newSpec => craft({
  14015. uid: newSpec.uid,
  14016. dom: {
  14017. tag: 'iframe',
  14018. attributes,
  14019. classes: isTransparent ? [baseClass] : [
  14020. baseClass,
  14021. `${ baseClass }--opaque`
  14022. ]
  14023. },
  14024. behaviours: derive$1([
  14025. Tabstopping.config({}),
  14026. Focusing.config({}),
  14027. RepresentingConfigs.withComp(initialData, sourcing.getValue, sourcing.setValue)
  14028. ])
  14029. });
  14030. const pField = FormField.parts.field({ factory: { sketch: factory } });
  14031. return renderFormFieldWith(pLabel, pField, ['tox-form__group--stretched'], []);
  14032. };
  14033. const image = image => new Promise((resolve, reject) => {
  14034. const loaded = () => {
  14035. destroy();
  14036. resolve(image);
  14037. };
  14038. const listeners = [
  14039. bind(image, 'load', loaded),
  14040. bind(image, 'error', () => {
  14041. destroy();
  14042. reject('Unable to load data from image: ' + image.dom.src);
  14043. })
  14044. ];
  14045. const destroy = () => each$1(listeners, l => l.unbind());
  14046. if (image.dom.complete) {
  14047. loaded();
  14048. }
  14049. });
  14050. const calculateImagePosition = (panelWidth, panelHeight, imageWidth, imageHeight, zoom) => {
  14051. const width = imageWidth * zoom;
  14052. const height = imageHeight * zoom;
  14053. const left = Math.max(0, panelWidth / 2 - width / 2);
  14054. const top = Math.max(0, panelHeight / 2 - height / 2);
  14055. return {
  14056. left: left.toString() + 'px',
  14057. top: top.toString() + 'px',
  14058. width: width.toString() + 'px',
  14059. height: height.toString() + 'px'
  14060. };
  14061. };
  14062. const zoomToFit = (panel, width, height) => {
  14063. const panelW = get$c(panel);
  14064. const panelH = get$d(panel);
  14065. return Math.min(panelW / width, panelH / height, 1);
  14066. };
  14067. const renderImagePreview = (spec, initialData) => {
  14068. const cachedData = Cell(initialData.getOr({ url: '' }));
  14069. const memImage = record({
  14070. dom: {
  14071. tag: 'img',
  14072. classes: ['tox-imagepreview__image'],
  14073. attributes: initialData.map(data => ({ src: data.url })).getOr({})
  14074. }
  14075. });
  14076. const memContainer = record({
  14077. dom: {
  14078. tag: 'div',
  14079. classes: ['tox-imagepreview__container'],
  14080. attributes: { role: 'presentation' }
  14081. },
  14082. components: [memImage.asSpec()]
  14083. });
  14084. const setValue = (frameComponent, data) => {
  14085. const translatedData = { url: data.url };
  14086. data.zoom.each(z => translatedData.zoom = z);
  14087. data.cachedWidth.each(z => translatedData.cachedWidth = z);
  14088. data.cachedHeight.each(z => translatedData.cachedHeight = z);
  14089. cachedData.set(translatedData);
  14090. const applyFramePositioning = () => {
  14091. const {cachedWidth, cachedHeight, zoom} = translatedData;
  14092. if (!isUndefined(cachedWidth) && !isUndefined(cachedHeight)) {
  14093. if (isUndefined(zoom)) {
  14094. const z = zoomToFit(frameComponent.element, cachedWidth, cachedHeight);
  14095. translatedData.zoom = z;
  14096. }
  14097. const position = calculateImagePosition(get$c(frameComponent.element), get$d(frameComponent.element), cachedWidth, cachedHeight, translatedData.zoom);
  14098. memContainer.getOpt(frameComponent).each(container => {
  14099. setAll(container.element, position);
  14100. });
  14101. }
  14102. };
  14103. memImage.getOpt(frameComponent).each(imageComponent => {
  14104. const img = imageComponent.element;
  14105. if (data.url !== get$f(img, 'src')) {
  14106. set$9(img, 'src', data.url);
  14107. remove$2(frameComponent.element, 'tox-imagepreview__loaded');
  14108. }
  14109. applyFramePositioning();
  14110. image(img).then(img => {
  14111. if (frameComponent.getSystem().isConnected()) {
  14112. add$2(frameComponent.element, 'tox-imagepreview__loaded');
  14113. translatedData.cachedWidth = img.dom.naturalWidth;
  14114. translatedData.cachedHeight = img.dom.naturalHeight;
  14115. applyFramePositioning();
  14116. }
  14117. });
  14118. });
  14119. };
  14120. const styles = {};
  14121. spec.height.each(h => styles.height = h);
  14122. const fakeValidatedData = initialData.map(d => ({
  14123. url: d.url,
  14124. zoom: Optional.from(d.zoom),
  14125. cachedWidth: Optional.from(d.cachedWidth),
  14126. cachedHeight: Optional.from(d.cachedHeight)
  14127. }));
  14128. return {
  14129. dom: {
  14130. tag: 'div',
  14131. classes: ['tox-imagepreview'],
  14132. styles,
  14133. attributes: { role: 'presentation' }
  14134. },
  14135. components: [memContainer.asSpec()],
  14136. behaviours: derive$1([
  14137. ComposingConfigs.self(),
  14138. RepresentingConfigs.withComp(fakeValidatedData, () => cachedData.get(), setValue)
  14139. ])
  14140. };
  14141. };
  14142. const renderLabel$1 = (spec, backstageShared) => {
  14143. const label = {
  14144. dom: {
  14145. tag: 'label',
  14146. classes: ['tox-label']
  14147. },
  14148. components: [text$2(backstageShared.providers.translate(spec.label))]
  14149. };
  14150. const comps = map$2(spec.items, backstageShared.interpreter);
  14151. return {
  14152. dom: {
  14153. tag: 'div',
  14154. classes: ['tox-form__group']
  14155. },
  14156. components: [
  14157. label,
  14158. ...comps
  14159. ],
  14160. behaviours: derive$1([
  14161. ComposingConfigs.self(),
  14162. Replacing.config({}),
  14163. RepresentingConfigs.domHtml(Optional.none()),
  14164. Keying.config({ mode: 'acyclic' })
  14165. ])
  14166. };
  14167. };
  14168. const internalToolbarButtonExecute = generate$6('toolbar.button.execute');
  14169. const onToolbarButtonExecute = info => runOnExecute$1((comp, _simulatedEvent) => {
  14170. runWithApi(info, comp)(itemApi => {
  14171. emitWith(comp, internalToolbarButtonExecute, { buttonApi: itemApi });
  14172. info.onAction(itemApi);
  14173. });
  14174. });
  14175. const toolbarButtonEventOrder = {
  14176. [execute$5()]: [
  14177. 'disabling',
  14178. 'alloy.base.behaviour',
  14179. 'toggling',
  14180. 'toolbar-button-events'
  14181. ]
  14182. };
  14183. const renderIcon = (iconName, iconsProvider, behaviours) => render$3(iconName, {
  14184. tag: 'span',
  14185. classes: [
  14186. 'tox-icon',
  14187. 'tox-tbtn__icon-wrap'
  14188. ],
  14189. behaviours
  14190. }, iconsProvider);
  14191. const renderIconFromPack = (iconName, iconsProvider) => renderIcon(iconName, iconsProvider, []);
  14192. const renderReplaceableIconFromPack = (iconName, iconsProvider) => renderIcon(iconName, iconsProvider, [Replacing.config({})]);
  14193. const renderLabel = (text, prefix, providersBackstage) => ({
  14194. dom: {
  14195. tag: 'span',
  14196. classes: [`${ prefix }__select-label`]
  14197. },
  14198. components: [text$2(providersBackstage.translate(text))],
  14199. behaviours: derive$1([Replacing.config({})])
  14200. });
  14201. const updateMenuText = generate$6('update-menu-text');
  14202. const updateMenuIcon = generate$6('update-menu-icon');
  14203. const renderCommonDropdown = (spec, prefix, sharedBackstage) => {
  14204. const editorOffCell = Cell(noop);
  14205. const optMemDisplayText = spec.text.map(text => record(renderLabel(text, prefix, sharedBackstage.providers)));
  14206. const optMemDisplayIcon = spec.icon.map(iconName => record(renderReplaceableIconFromPack(iconName, sharedBackstage.providers.icons)));
  14207. const onLeftOrRightInMenu = (comp, se) => {
  14208. const dropdown = Representing.getValue(comp);
  14209. Focusing.focus(dropdown);
  14210. emitWith(dropdown, 'keydown', { raw: se.event.raw });
  14211. Dropdown.close(dropdown);
  14212. return Optional.some(true);
  14213. };
  14214. const role = spec.role.fold(() => ({}), role => ({ role }));
  14215. const tooltipAttributes = spec.tooltip.fold(() => ({}), tooltip => {
  14216. const translatedTooltip = sharedBackstage.providers.translate(tooltip);
  14217. return {
  14218. 'title': translatedTooltip,
  14219. 'aria-label': translatedTooltip
  14220. };
  14221. });
  14222. const iconSpec = render$3('chevron-down', {
  14223. tag: 'div',
  14224. classes: [`${ prefix }__select-chevron`]
  14225. }, sharedBackstage.providers.icons);
  14226. const memDropdown = record(Dropdown.sketch({
  14227. ...spec.uid ? { uid: spec.uid } : {},
  14228. ...role,
  14229. dom: {
  14230. tag: 'button',
  14231. classes: [
  14232. prefix,
  14233. `${ prefix }--select`
  14234. ].concat(map$2(spec.classes, c => `${ prefix }--${ c }`)),
  14235. attributes: { ...tooltipAttributes }
  14236. },
  14237. components: componentRenderPipeline([
  14238. optMemDisplayIcon.map(mem => mem.asSpec()),
  14239. optMemDisplayText.map(mem => mem.asSpec()),
  14240. Optional.some(iconSpec)
  14241. ]),
  14242. matchWidth: true,
  14243. useMinWidth: true,
  14244. onOpen: (anchor, dropdownComp, tmenuComp) => {
  14245. if (spec.searchable) {
  14246. focusSearchField(tmenuComp);
  14247. }
  14248. },
  14249. dropdownBehaviours: derive$1([
  14250. ...spec.dropdownBehaviours,
  14251. DisablingConfigs.button(() => spec.disabled || sharedBackstage.providers.isDisabled()),
  14252. receivingConfig(),
  14253. Unselecting.config({}),
  14254. Replacing.config({}),
  14255. config('dropdown-events', [
  14256. onControlAttached(spec, editorOffCell),
  14257. onControlDetached(spec, editorOffCell)
  14258. ]),
  14259. config('menubutton-update-display-text', [
  14260. run$1(updateMenuText, (comp, se) => {
  14261. optMemDisplayText.bind(mem => mem.getOpt(comp)).each(displayText => {
  14262. Replacing.set(displayText, [text$2(sharedBackstage.providers.translate(se.event.text))]);
  14263. });
  14264. }),
  14265. run$1(updateMenuIcon, (comp, se) => {
  14266. optMemDisplayIcon.bind(mem => mem.getOpt(comp)).each(displayIcon => {
  14267. Replacing.set(displayIcon, [renderReplaceableIconFromPack(se.event.icon, sharedBackstage.providers.icons)]);
  14268. });
  14269. })
  14270. ])
  14271. ]),
  14272. eventOrder: deepMerge(toolbarButtonEventOrder, {
  14273. mousedown: [
  14274. 'focusing',
  14275. 'alloy.base.behaviour',
  14276. 'item-type-events',
  14277. 'normal-dropdown-events'
  14278. ]
  14279. }),
  14280. sandboxBehaviours: derive$1([
  14281. Keying.config({
  14282. mode: 'special',
  14283. onLeft: onLeftOrRightInMenu,
  14284. onRight: onLeftOrRightInMenu
  14285. }),
  14286. config('dropdown-sandbox-events', [
  14287. run$1(refetchTriggerEvent, (originalSandboxComp, se) => {
  14288. handleRefetchTrigger(originalSandboxComp);
  14289. se.stop();
  14290. }),
  14291. run$1(redirectMenuItemInteractionEvent, (sandboxComp, se) => {
  14292. handleRedirectToMenuItem(sandboxComp, se);
  14293. se.stop();
  14294. })
  14295. ])
  14296. ]),
  14297. lazySink: sharedBackstage.getSink,
  14298. toggleClass: `${ prefix }--active`,
  14299. parts: {
  14300. menu: {
  14301. ...part(false, spec.columns, spec.presets),
  14302. fakeFocus: spec.searchable,
  14303. onHighlightItem: updateAriaOnHighlight,
  14304. onCollapseMenu: (tmenuComp, itemCompCausingCollapse, nowActiveMenuComp) => {
  14305. Highlighting.getHighlighted(nowActiveMenuComp).each(itemComp => {
  14306. updateAriaOnHighlight(tmenuComp, nowActiveMenuComp, itemComp);
  14307. });
  14308. },
  14309. onDehighlightItem: updateAriaOnDehighlight
  14310. }
  14311. },
  14312. fetch: comp => Future.nu(curry(spec.fetch, comp))
  14313. }));
  14314. return memDropdown.asSpec();
  14315. };
  14316. const isMenuItemReference = item => isString(item);
  14317. const isSeparator$2 = item => item.type === 'separator';
  14318. const isExpandingMenuItem = item => has$2(item, 'getSubmenuItems');
  14319. const separator$2 = { type: 'separator' };
  14320. const unwrapReferences = (items, menuItems) => {
  14321. const realItems = foldl(items, (acc, item) => {
  14322. if (isMenuItemReference(item)) {
  14323. if (item === '') {
  14324. return acc;
  14325. } else if (item === '|') {
  14326. return acc.length > 0 && !isSeparator$2(acc[acc.length - 1]) ? acc.concat([separator$2]) : acc;
  14327. } else if (has$2(menuItems, item.toLowerCase())) {
  14328. return acc.concat([menuItems[item.toLowerCase()]]);
  14329. } else {
  14330. return acc;
  14331. }
  14332. } else {
  14333. return acc.concat([item]);
  14334. }
  14335. }, []);
  14336. if (realItems.length > 0 && isSeparator$2(realItems[realItems.length - 1])) {
  14337. realItems.pop();
  14338. }
  14339. return realItems;
  14340. };
  14341. const getFromExpandingItem = (item, menuItems) => {
  14342. const submenuItems = item.getSubmenuItems();
  14343. const rest = expand(submenuItems, menuItems);
  14344. const newMenus = deepMerge(rest.menus, { [item.value]: rest.items });
  14345. const newExpansions = deepMerge(rest.expansions, { [item.value]: item.value });
  14346. return {
  14347. item,
  14348. menus: newMenus,
  14349. expansions: newExpansions
  14350. };
  14351. };
  14352. const generateValueIfRequired = item => {
  14353. const itemValue = get$g(item, 'value').getOrThunk(() => generate$6('generated-menu-item'));
  14354. return deepMerge({ value: itemValue }, item);
  14355. };
  14356. const expand = (items, menuItems) => {
  14357. const realItems = unwrapReferences(isString(items) ? items.split(' ') : items, menuItems);
  14358. return foldr(realItems, (acc, item) => {
  14359. if (isExpandingMenuItem(item)) {
  14360. const itemWithValue = generateValueIfRequired(item);
  14361. const newData = getFromExpandingItem(itemWithValue, menuItems);
  14362. return {
  14363. menus: deepMerge(acc.menus, newData.menus),
  14364. items: [
  14365. newData.item,
  14366. ...acc.items
  14367. ],
  14368. expansions: deepMerge(acc.expansions, newData.expansions)
  14369. };
  14370. } else {
  14371. return {
  14372. ...acc,
  14373. items: [
  14374. item,
  14375. ...acc.items
  14376. ]
  14377. };
  14378. }
  14379. }, {
  14380. menus: {},
  14381. expansions: {},
  14382. items: []
  14383. });
  14384. };
  14385. const getSearchModeForField = settings => {
  14386. return settings.search.fold(() => ({ searchMode: 'no-search' }), searchSettings => ({
  14387. searchMode: 'search-with-field',
  14388. placeholder: searchSettings.placeholder
  14389. }));
  14390. };
  14391. const getSearchModeForResults = settings => {
  14392. return settings.search.fold(() => ({ searchMode: 'no-search' }), _ => ({ searchMode: 'search-with-results' }));
  14393. };
  14394. const build = (items, itemResponse, backstage, settings) => {
  14395. const primary = generate$6('primary-menu');
  14396. const data = expand(items, backstage.shared.providers.menuItems());
  14397. if (data.items.length === 0) {
  14398. return Optional.none();
  14399. }
  14400. const mainMenuSearchMode = getSearchModeForField(settings);
  14401. const mainMenu = createPartialMenu(primary, data.items, itemResponse, backstage, settings.isHorizontalMenu, mainMenuSearchMode);
  14402. const submenuSearchMode = getSearchModeForResults(settings);
  14403. const submenus = map$1(data.menus, (menuItems, menuName) => createPartialMenu(menuName, menuItems, itemResponse, backstage, false, submenuSearchMode));
  14404. const menus = deepMerge(submenus, wrap$1(primary, mainMenu));
  14405. return Optional.from(tieredMenu.tieredData(primary, menus, data.expansions));
  14406. };
  14407. const isSingleListItem = item => !has$2(item, 'items');
  14408. const dataAttribute = 'data-value';
  14409. const fetchItems = (dropdownComp, name, items, selectedValue) => map$2(items, item => {
  14410. if (!isSingleListItem(item)) {
  14411. return {
  14412. type: 'nestedmenuitem',
  14413. text: item.text,
  14414. getSubmenuItems: () => fetchItems(dropdownComp, name, item.items, selectedValue)
  14415. };
  14416. } else {
  14417. return {
  14418. type: 'togglemenuitem',
  14419. text: item.text,
  14420. value: item.value,
  14421. active: item.value === selectedValue,
  14422. onAction: () => {
  14423. Representing.setValue(dropdownComp, item.value);
  14424. emitWith(dropdownComp, formChangeEvent, { name });
  14425. Focusing.focus(dropdownComp);
  14426. }
  14427. };
  14428. }
  14429. });
  14430. const findItemByValue = (items, value) => findMap(items, item => {
  14431. if (!isSingleListItem(item)) {
  14432. return findItemByValue(item.items, value);
  14433. } else {
  14434. return someIf(item.value === value, item);
  14435. }
  14436. });
  14437. const renderListBox = (spec, backstage, initialData) => {
  14438. const providersBackstage = backstage.shared.providers;
  14439. const initialItem = initialData.bind(value => findItemByValue(spec.items, value)).orThunk(() => head(spec.items).filter(isSingleListItem));
  14440. const pLabel = spec.label.map(label => renderLabel$2(label, providersBackstage));
  14441. const pField = FormField.parts.field({
  14442. dom: {},
  14443. factory: {
  14444. sketch: sketchSpec => renderCommonDropdown({
  14445. uid: sketchSpec.uid,
  14446. text: initialItem.map(item => item.text),
  14447. icon: Optional.none(),
  14448. tooltip: spec.label,
  14449. role: Optional.none(),
  14450. fetch: (comp, callback) => {
  14451. const items = fetchItems(comp, spec.name, spec.items, Representing.getValue(comp));
  14452. callback(build(items, ItemResponse$1.CLOSE_ON_EXECUTE, backstage, {
  14453. isHorizontalMenu: false,
  14454. search: Optional.none()
  14455. }));
  14456. },
  14457. onSetup: constant$1(noop),
  14458. getApi: constant$1({}),
  14459. columns: 1,
  14460. presets: 'normal',
  14461. classes: [],
  14462. dropdownBehaviours: [
  14463. Tabstopping.config({}),
  14464. RepresentingConfigs.withComp(initialItem.map(item => item.value), comp => get$f(comp.element, dataAttribute), (comp, data) => {
  14465. findItemByValue(spec.items, data).each(item => {
  14466. set$9(comp.element, dataAttribute, item.value);
  14467. emitWith(comp, updateMenuText, { text: item.text });
  14468. });
  14469. })
  14470. ]
  14471. }, 'tox-listbox', backstage.shared)
  14472. }
  14473. });
  14474. const listBoxWrap = {
  14475. dom: {
  14476. tag: 'div',
  14477. classes: ['tox-listboxfield']
  14478. },
  14479. components: [pField]
  14480. };
  14481. return FormField.sketch({
  14482. dom: {
  14483. tag: 'div',
  14484. classes: ['tox-form__group']
  14485. },
  14486. components: flatten([
  14487. pLabel.toArray(),
  14488. [listBoxWrap]
  14489. ]),
  14490. fieldBehaviours: derive$1([Disabling.config({
  14491. disabled: constant$1(!spec.enabled),
  14492. onDisabled: comp => {
  14493. FormField.getField(comp).each(Disabling.disable);
  14494. },
  14495. onEnabled: comp => {
  14496. FormField.getField(comp).each(Disabling.enable);
  14497. }
  14498. })])
  14499. });
  14500. };
  14501. const renderPanel = (spec, backstage) => ({
  14502. dom: {
  14503. tag: 'div',
  14504. classes: spec.classes
  14505. },
  14506. components: map$2(spec.items, backstage.shared.interpreter)
  14507. });
  14508. const factory$h = (detail, _spec) => {
  14509. const options = map$2(detail.options, option => ({
  14510. dom: {
  14511. tag: 'option',
  14512. value: option.value,
  14513. innerHtml: option.text
  14514. }
  14515. }));
  14516. const initialValues = detail.data.map(v => wrap$1('initialValue', v)).getOr({});
  14517. return {
  14518. uid: detail.uid,
  14519. dom: {
  14520. tag: 'select',
  14521. classes: detail.selectClasses,
  14522. attributes: detail.selectAttributes
  14523. },
  14524. components: options,
  14525. behaviours: augment(detail.selectBehaviours, [
  14526. Focusing.config({}),
  14527. Representing.config({
  14528. store: {
  14529. mode: 'manual',
  14530. getValue: select => {
  14531. return get$6(select.element);
  14532. },
  14533. setValue: (select, newValue) => {
  14534. const found = find$5(detail.options, opt => opt.value === newValue);
  14535. if (found.isSome()) {
  14536. set$5(select.element, newValue);
  14537. }
  14538. },
  14539. ...initialValues
  14540. }
  14541. })
  14542. ])
  14543. };
  14544. };
  14545. const HtmlSelect = single({
  14546. name: 'HtmlSelect',
  14547. configFields: [
  14548. required$1('options'),
  14549. field('selectBehaviours', [
  14550. Focusing,
  14551. Representing
  14552. ]),
  14553. defaulted('selectClasses', []),
  14554. defaulted('selectAttributes', {}),
  14555. option$3('data')
  14556. ],
  14557. factory: factory$h
  14558. });
  14559. const renderSelectBox = (spec, providersBackstage, initialData) => {
  14560. const translatedOptions = map$2(spec.items, item => ({
  14561. text: providersBackstage.translate(item.text),
  14562. value: item.value
  14563. }));
  14564. const pLabel = spec.label.map(label => renderLabel$2(label, providersBackstage));
  14565. const pField = FormField.parts.field({
  14566. dom: {},
  14567. ...initialData.map(data => ({ data })).getOr({}),
  14568. selectAttributes: { size: spec.size },
  14569. options: translatedOptions,
  14570. factory: HtmlSelect,
  14571. selectBehaviours: derive$1([
  14572. Disabling.config({ disabled: () => !spec.enabled || providersBackstage.isDisabled() }),
  14573. Tabstopping.config({}),
  14574. config('selectbox-change', [run$1(change(), (component, _) => {
  14575. emitWith(component, formChangeEvent, { name: spec.name });
  14576. })])
  14577. ])
  14578. });
  14579. const chevron = spec.size > 1 ? Optional.none() : Optional.some(render$3('chevron-down', {
  14580. tag: 'div',
  14581. classes: ['tox-selectfield__icon-js']
  14582. }, providersBackstage.icons));
  14583. const selectWrap = {
  14584. dom: {
  14585. tag: 'div',
  14586. classes: ['tox-selectfield']
  14587. },
  14588. components: flatten([
  14589. [pField],
  14590. chevron.toArray()
  14591. ])
  14592. };
  14593. return FormField.sketch({
  14594. dom: {
  14595. tag: 'div',
  14596. classes: ['tox-form__group']
  14597. },
  14598. components: flatten([
  14599. pLabel.toArray(),
  14600. [selectWrap]
  14601. ]),
  14602. fieldBehaviours: derive$1([
  14603. Disabling.config({
  14604. disabled: () => !spec.enabled || providersBackstage.isDisabled(),
  14605. onDisabled: comp => {
  14606. FormField.getField(comp).each(Disabling.disable);
  14607. },
  14608. onEnabled: comp => {
  14609. FormField.getField(comp).each(Disabling.enable);
  14610. }
  14611. }),
  14612. receivingConfig()
  14613. ])
  14614. });
  14615. };
  14616. const schema$h = constant$1([
  14617. defaulted('field1Name', 'field1'),
  14618. defaulted('field2Name', 'field2'),
  14619. onStrictHandler('onLockedChange'),
  14620. markers$1(['lockClass']),
  14621. defaulted('locked', false),
  14622. SketchBehaviours.field('coupledFieldBehaviours', [
  14623. Composing,
  14624. Representing
  14625. ])
  14626. ]);
  14627. const getField = (comp, detail, partName) => getPart(comp, detail, partName).bind(Composing.getCurrent);
  14628. const coupledPart = (selfName, otherName) => required({
  14629. factory: FormField,
  14630. name: selfName,
  14631. overrides: detail => {
  14632. return {
  14633. fieldBehaviours: derive$1([config('coupled-input-behaviour', [run$1(input(), me => {
  14634. getField(me, detail, otherName).each(other => {
  14635. getPart(me, detail, 'lock').each(lock => {
  14636. if (Toggling.isOn(lock)) {
  14637. detail.onLockedChange(me, other, lock);
  14638. }
  14639. });
  14640. });
  14641. })])])
  14642. };
  14643. }
  14644. });
  14645. const parts$c = constant$1([
  14646. coupledPart('field1', 'field2'),
  14647. coupledPart('field2', 'field1'),
  14648. required({
  14649. factory: Button,
  14650. schema: [required$1('dom')],
  14651. name: 'lock',
  14652. overrides: detail => {
  14653. return {
  14654. buttonBehaviours: derive$1([Toggling.config({
  14655. selected: detail.locked,
  14656. toggleClass: detail.markers.lockClass,
  14657. aria: { mode: 'pressed' }
  14658. })])
  14659. };
  14660. }
  14661. })
  14662. ]);
  14663. const factory$g = (detail, components, _spec, _externals) => ({
  14664. uid: detail.uid,
  14665. dom: detail.dom,
  14666. components,
  14667. behaviours: SketchBehaviours.augment(detail.coupledFieldBehaviours, [
  14668. Composing.config({ find: Optional.some }),
  14669. Representing.config({
  14670. store: {
  14671. mode: 'manual',
  14672. getValue: comp => {
  14673. const parts = getPartsOrDie(comp, detail, [
  14674. 'field1',
  14675. 'field2'
  14676. ]);
  14677. return {
  14678. [detail.field1Name]: Representing.getValue(parts.field1()),
  14679. [detail.field2Name]: Representing.getValue(parts.field2())
  14680. };
  14681. },
  14682. setValue: (comp, value) => {
  14683. const parts = getPartsOrDie(comp, detail, [
  14684. 'field1',
  14685. 'field2'
  14686. ]);
  14687. if (hasNonNullableKey(value, detail.field1Name)) {
  14688. Representing.setValue(parts.field1(), value[detail.field1Name]);
  14689. }
  14690. if (hasNonNullableKey(value, detail.field2Name)) {
  14691. Representing.setValue(parts.field2(), value[detail.field2Name]);
  14692. }
  14693. }
  14694. }
  14695. })
  14696. ]),
  14697. apis: {
  14698. getField1: component => getPart(component, detail, 'field1'),
  14699. getField2: component => getPart(component, detail, 'field2'),
  14700. getLock: component => getPart(component, detail, 'lock')
  14701. }
  14702. });
  14703. const FormCoupledInputs = composite({
  14704. name: 'FormCoupledInputs',
  14705. configFields: schema$h(),
  14706. partFields: parts$c(),
  14707. factory: factory$g,
  14708. apis: {
  14709. getField1: (apis, component) => apis.getField1(component),
  14710. getField2: (apis, component) => apis.getField2(component),
  14711. getLock: (apis, component) => apis.getLock(component)
  14712. }
  14713. });
  14714. const formatSize = size => {
  14715. const unitDec = {
  14716. '': 0,
  14717. 'px': 0,
  14718. 'pt': 1,
  14719. 'mm': 1,
  14720. 'pc': 2,
  14721. 'ex': 2,
  14722. 'em': 2,
  14723. 'ch': 2,
  14724. 'rem': 2,
  14725. 'cm': 3,
  14726. 'in': 4,
  14727. '%': 4
  14728. };
  14729. const maxDecimal = unit => unit in unitDec ? unitDec[unit] : 1;
  14730. let numText = size.value.toFixed(maxDecimal(size.unit));
  14731. if (numText.indexOf('.') !== -1) {
  14732. numText = numText.replace(/\.?0*$/, '');
  14733. }
  14734. return numText + size.unit;
  14735. };
  14736. const parseSize = sizeText => {
  14737. const numPattern = /^\s*(\d+(?:\.\d+)?)\s*(|cm|mm|in|px|pt|pc|em|ex|ch|rem|vw|vh|vmin|vmax|%)\s*$/;
  14738. const match = numPattern.exec(sizeText);
  14739. if (match !== null) {
  14740. const value = parseFloat(match[1]);
  14741. const unit = match[2];
  14742. return Result.value({
  14743. value,
  14744. unit
  14745. });
  14746. } else {
  14747. return Result.error(sizeText);
  14748. }
  14749. };
  14750. const convertUnit = (size, unit) => {
  14751. const inInch = {
  14752. '': 96,
  14753. 'px': 96,
  14754. 'pt': 72,
  14755. 'cm': 2.54,
  14756. 'pc': 12,
  14757. 'mm': 25.4,
  14758. 'in': 1
  14759. };
  14760. const supported = u => has$2(inInch, u);
  14761. if (size.unit === unit) {
  14762. return Optional.some(size.value);
  14763. } else if (supported(size.unit) && supported(unit)) {
  14764. if (inInch[size.unit] === inInch[unit]) {
  14765. return Optional.some(size.value);
  14766. } else {
  14767. return Optional.some(size.value / inInch[size.unit] * inInch[unit]);
  14768. }
  14769. } else {
  14770. return Optional.none();
  14771. }
  14772. };
  14773. const noSizeConversion = _input => Optional.none();
  14774. const ratioSizeConversion = (scale, unit) => size => convertUnit(size, unit).map(value => ({
  14775. value: value * scale,
  14776. unit
  14777. }));
  14778. const makeRatioConverter = (currentFieldText, otherFieldText) => {
  14779. const cValue = parseSize(currentFieldText).toOptional();
  14780. const oValue = parseSize(otherFieldText).toOptional();
  14781. return lift2(cValue, oValue, (cSize, oSize) => convertUnit(cSize, oSize.unit).map(val => oSize.value / val).map(r => ratioSizeConversion(r, oSize.unit)).getOr(noSizeConversion)).getOr(noSizeConversion);
  14782. };
  14783. const renderSizeInput = (spec, providersBackstage) => {
  14784. let converter = noSizeConversion;
  14785. const ratioEvent = generate$6('ratio-event');
  14786. const makeIcon = iconName => render$3(iconName, {
  14787. tag: 'span',
  14788. classes: [
  14789. 'tox-icon',
  14790. 'tox-lock-icon__' + iconName
  14791. ]
  14792. }, providersBackstage.icons);
  14793. const pLock = FormCoupledInputs.parts.lock({
  14794. dom: {
  14795. tag: 'button',
  14796. classes: [
  14797. 'tox-lock',
  14798. 'tox-button',
  14799. 'tox-button--naked',
  14800. 'tox-button--icon'
  14801. ],
  14802. attributes: { title: providersBackstage.translate(spec.label.getOr('Constrain proportions')) }
  14803. },
  14804. components: [
  14805. makeIcon('lock'),
  14806. makeIcon('unlock')
  14807. ],
  14808. buttonBehaviours: derive$1([
  14809. Disabling.config({ disabled: () => !spec.enabled || providersBackstage.isDisabled() }),
  14810. receivingConfig(),
  14811. Tabstopping.config({})
  14812. ])
  14813. });
  14814. const formGroup = components => ({
  14815. dom: {
  14816. tag: 'div',
  14817. classes: ['tox-form__group']
  14818. },
  14819. components
  14820. });
  14821. const getFieldPart = isField1 => FormField.parts.field({
  14822. factory: Input,
  14823. inputClasses: ['tox-textfield'],
  14824. inputBehaviours: derive$1([
  14825. Disabling.config({ disabled: () => !spec.enabled || providersBackstage.isDisabled() }),
  14826. receivingConfig(),
  14827. Tabstopping.config({}),
  14828. config('size-input-events', [
  14829. run$1(focusin(), (component, _simulatedEvent) => {
  14830. emitWith(component, ratioEvent, { isField1 });
  14831. }),
  14832. run$1(change(), (component, _simulatedEvent) => {
  14833. emitWith(component, formChangeEvent, { name: spec.name });
  14834. })
  14835. ])
  14836. ]),
  14837. selectOnFocus: false
  14838. });
  14839. const getLabel = label => ({
  14840. dom: {
  14841. tag: 'label',
  14842. classes: ['tox-label']
  14843. },
  14844. components: [text$2(providersBackstage.translate(label))]
  14845. });
  14846. const widthField = FormCoupledInputs.parts.field1(formGroup([
  14847. FormField.parts.label(getLabel('Width')),
  14848. getFieldPart(true)
  14849. ]));
  14850. const heightField = FormCoupledInputs.parts.field2(formGroup([
  14851. FormField.parts.label(getLabel('Height')),
  14852. getFieldPart(false)
  14853. ]));
  14854. return FormCoupledInputs.sketch({
  14855. dom: {
  14856. tag: 'div',
  14857. classes: ['tox-form__group']
  14858. },
  14859. components: [{
  14860. dom: {
  14861. tag: 'div',
  14862. classes: ['tox-form__controls-h-stack']
  14863. },
  14864. components: [
  14865. widthField,
  14866. heightField,
  14867. formGroup([
  14868. getLabel(nbsp),
  14869. pLock
  14870. ])
  14871. ]
  14872. }],
  14873. field1Name: 'width',
  14874. field2Name: 'height',
  14875. locked: true,
  14876. markers: { lockClass: 'tox-locked' },
  14877. onLockedChange: (current, other, _lock) => {
  14878. parseSize(Representing.getValue(current)).each(size => {
  14879. converter(size).each(newSize => {
  14880. Representing.setValue(other, formatSize(newSize));
  14881. });
  14882. });
  14883. },
  14884. coupledFieldBehaviours: derive$1([
  14885. Disabling.config({
  14886. disabled: () => !spec.enabled || providersBackstage.isDisabled(),
  14887. onDisabled: comp => {
  14888. FormCoupledInputs.getField1(comp).bind(FormField.getField).each(Disabling.disable);
  14889. FormCoupledInputs.getField2(comp).bind(FormField.getField).each(Disabling.disable);
  14890. FormCoupledInputs.getLock(comp).each(Disabling.disable);
  14891. },
  14892. onEnabled: comp => {
  14893. FormCoupledInputs.getField1(comp).bind(FormField.getField).each(Disabling.enable);
  14894. FormCoupledInputs.getField2(comp).bind(FormField.getField).each(Disabling.enable);
  14895. FormCoupledInputs.getLock(comp).each(Disabling.enable);
  14896. }
  14897. }),
  14898. receivingConfig(),
  14899. config('size-input-events2', [run$1(ratioEvent, (component, simulatedEvent) => {
  14900. const isField1 = simulatedEvent.event.isField1;
  14901. const optCurrent = isField1 ? FormCoupledInputs.getField1(component) : FormCoupledInputs.getField2(component);
  14902. const optOther = isField1 ? FormCoupledInputs.getField2(component) : FormCoupledInputs.getField1(component);
  14903. const value1 = optCurrent.map(Representing.getValue).getOr('');
  14904. const value2 = optOther.map(Representing.getValue).getOr('');
  14905. converter = makeRatioConverter(value1, value2);
  14906. })])
  14907. ])
  14908. });
  14909. };
  14910. const renderSlider = (spec, providerBackstage, initialData) => {
  14911. const labelPart = Slider.parts.label({
  14912. dom: {
  14913. tag: 'label',
  14914. classes: ['tox-label']
  14915. },
  14916. components: [text$2(providerBackstage.translate(spec.label))]
  14917. });
  14918. const spectrum = Slider.parts.spectrum({
  14919. dom: {
  14920. tag: 'div',
  14921. classes: ['tox-slider__rail'],
  14922. attributes: { role: 'presentation' }
  14923. }
  14924. });
  14925. const thumb = Slider.parts.thumb({
  14926. dom: {
  14927. tag: 'div',
  14928. classes: ['tox-slider__handle'],
  14929. attributes: { role: 'presentation' }
  14930. }
  14931. });
  14932. return Slider.sketch({
  14933. dom: {
  14934. tag: 'div',
  14935. classes: ['tox-slider'],
  14936. attributes: { role: 'presentation' }
  14937. },
  14938. model: {
  14939. mode: 'x',
  14940. minX: spec.min,
  14941. maxX: spec.max,
  14942. getInitialValue: constant$1(initialData.getOrThunk(() => (Math.abs(spec.max) - Math.abs(spec.min)) / 2))
  14943. },
  14944. components: [
  14945. labelPart,
  14946. spectrum,
  14947. thumb
  14948. ],
  14949. sliderBehaviours: derive$1([
  14950. ComposingConfigs.self(),
  14951. Focusing.config({})
  14952. ]),
  14953. onChoose: (component, thumb, value) => {
  14954. emitWith(component, formChangeEvent, {
  14955. name: spec.name,
  14956. value
  14957. });
  14958. }
  14959. });
  14960. };
  14961. const renderTable = (spec, providersBackstage) => {
  14962. const renderTh = text => ({
  14963. dom: {
  14964. tag: 'th',
  14965. innerHtml: providersBackstage.translate(text)
  14966. }
  14967. });
  14968. const renderHeader = header => ({
  14969. dom: { tag: 'thead' },
  14970. components: [{
  14971. dom: { tag: 'tr' },
  14972. components: map$2(header, renderTh)
  14973. }]
  14974. });
  14975. const renderTd = text => ({
  14976. dom: {
  14977. tag: 'td',
  14978. innerHtml: providersBackstage.translate(text)
  14979. }
  14980. });
  14981. const renderTr = row => ({
  14982. dom: { tag: 'tr' },
  14983. components: map$2(row, renderTd)
  14984. });
  14985. const renderRows = rows => ({
  14986. dom: { tag: 'tbody' },
  14987. components: map$2(rows, renderTr)
  14988. });
  14989. return {
  14990. dom: {
  14991. tag: 'table',
  14992. classes: ['tox-dialog__table']
  14993. },
  14994. components: [
  14995. renderHeader(spec.header),
  14996. renderRows(spec.cells)
  14997. ],
  14998. behaviours: derive$1([
  14999. Tabstopping.config({}),
  15000. Focusing.config({})
  15001. ])
  15002. };
  15003. };
  15004. const renderTextField = (spec, providersBackstage) => {
  15005. const pLabel = spec.label.map(label => renderLabel$2(label, providersBackstage));
  15006. const baseInputBehaviours = [
  15007. Disabling.config({ disabled: () => spec.disabled || providersBackstage.isDisabled() }),
  15008. receivingConfig(),
  15009. Keying.config({
  15010. mode: 'execution',
  15011. useEnter: spec.multiline !== true,
  15012. useControlEnter: spec.multiline === true,
  15013. execute: comp => {
  15014. emit(comp, formSubmitEvent);
  15015. return Optional.some(true);
  15016. }
  15017. }),
  15018. config('textfield-change', [
  15019. run$1(input(), (component, _) => {
  15020. emitWith(component, formChangeEvent, { name: spec.name });
  15021. }),
  15022. run$1(postPaste(), (component, _) => {
  15023. emitWith(component, formChangeEvent, { name: spec.name });
  15024. })
  15025. ]),
  15026. Tabstopping.config({})
  15027. ];
  15028. const validatingBehaviours = spec.validation.map(vl => Invalidating.config({
  15029. getRoot: input => {
  15030. return parentElement(input.element);
  15031. },
  15032. invalidClass: 'tox-invalid',
  15033. validator: {
  15034. validate: input => {
  15035. const v = Representing.getValue(input);
  15036. const result = vl.validator(v);
  15037. return Future.pure(result === true ? Result.value(v) : Result.error(result));
  15038. },
  15039. validateOnLoad: vl.validateOnLoad
  15040. }
  15041. })).toArray();
  15042. const placeholder = spec.placeholder.fold(constant$1({}), p => ({ placeholder: providersBackstage.translate(p) }));
  15043. const inputMode = spec.inputMode.fold(constant$1({}), mode => ({ inputmode: mode }));
  15044. const inputAttributes = {
  15045. ...placeholder,
  15046. ...inputMode
  15047. };
  15048. const pField = FormField.parts.field({
  15049. tag: spec.multiline === true ? 'textarea' : 'input',
  15050. ...spec.data.map(data => ({ data })).getOr({}),
  15051. inputAttributes,
  15052. inputClasses: [spec.classname],
  15053. inputBehaviours: derive$1(flatten([
  15054. baseInputBehaviours,
  15055. validatingBehaviours
  15056. ])),
  15057. selectOnFocus: false,
  15058. factory: Input
  15059. });
  15060. const extraClasses = spec.flex ? ['tox-form__group--stretched'] : [];
  15061. const extraClasses2 = extraClasses.concat(spec.maximized ? ['tox-form-group--maximize'] : []);
  15062. const extraBehaviours = [
  15063. Disabling.config({
  15064. disabled: () => spec.disabled || providersBackstage.isDisabled(),
  15065. onDisabled: comp => {
  15066. FormField.getField(comp).each(Disabling.disable);
  15067. },
  15068. onEnabled: comp => {
  15069. FormField.getField(comp).each(Disabling.enable);
  15070. }
  15071. }),
  15072. receivingConfig()
  15073. ];
  15074. return renderFormFieldWith(pLabel, pField, extraClasses2, extraBehaviours);
  15075. };
  15076. const renderInput = (spec, providersBackstage, initialData) => renderTextField({
  15077. name: spec.name,
  15078. multiline: false,
  15079. label: spec.label,
  15080. inputMode: spec.inputMode,
  15081. placeholder: spec.placeholder,
  15082. flex: false,
  15083. disabled: !spec.enabled,
  15084. classname: 'tox-textfield',
  15085. validation: Optional.none(),
  15086. maximized: spec.maximized,
  15087. data: initialData
  15088. }, providersBackstage);
  15089. const renderTextarea = (spec, providersBackstage, initialData) => renderTextField({
  15090. name: spec.name,
  15091. multiline: true,
  15092. label: spec.label,
  15093. inputMode: Optional.none(),
  15094. placeholder: spec.placeholder,
  15095. flex: true,
  15096. disabled: !spec.enabled,
  15097. classname: 'tox-textarea',
  15098. validation: Optional.none(),
  15099. maximized: spec.maximized,
  15100. data: initialData
  15101. }, providersBackstage);
  15102. const events$6 = (streamConfig, streamState) => {
  15103. const streams = streamConfig.stream.streams;
  15104. const processor = streams.setup(streamConfig, streamState);
  15105. return derive$2([
  15106. run$1(streamConfig.event, processor),
  15107. runOnDetached(() => streamState.cancel())
  15108. ].concat(streamConfig.cancelEvent.map(e => [run$1(e, () => streamState.cancel())]).getOr([])));
  15109. };
  15110. var ActiveStreaming = /*#__PURE__*/Object.freeze({
  15111. __proto__: null,
  15112. events: events$6
  15113. });
  15114. const first = (fn, rate) => {
  15115. let timer = null;
  15116. const cancel = () => {
  15117. if (!isNull(timer)) {
  15118. clearTimeout(timer);
  15119. timer = null;
  15120. }
  15121. };
  15122. const throttle = (...args) => {
  15123. if (isNull(timer)) {
  15124. timer = setTimeout(() => {
  15125. timer = null;
  15126. fn.apply(null, args);
  15127. }, rate);
  15128. }
  15129. };
  15130. return {
  15131. cancel,
  15132. throttle
  15133. };
  15134. };
  15135. const last = (fn, rate) => {
  15136. let timer = null;
  15137. const cancel = () => {
  15138. if (!isNull(timer)) {
  15139. clearTimeout(timer);
  15140. timer = null;
  15141. }
  15142. };
  15143. const throttle = (...args) => {
  15144. cancel();
  15145. timer = setTimeout(() => {
  15146. timer = null;
  15147. fn.apply(null, args);
  15148. }, rate);
  15149. };
  15150. return {
  15151. cancel,
  15152. throttle
  15153. };
  15154. };
  15155. const throttle = _config => {
  15156. const state = Cell(null);
  15157. const readState = () => ({ timer: state.get() !== null ? 'set' : 'unset' });
  15158. const setTimer = t => {
  15159. state.set(t);
  15160. };
  15161. const cancel = () => {
  15162. const t = state.get();
  15163. if (t !== null) {
  15164. t.cancel();
  15165. }
  15166. };
  15167. return nu$8({
  15168. readState,
  15169. setTimer,
  15170. cancel
  15171. });
  15172. };
  15173. const init$9 = spec => spec.stream.streams.state(spec);
  15174. var StreamingState = /*#__PURE__*/Object.freeze({
  15175. __proto__: null,
  15176. throttle: throttle,
  15177. init: init$9
  15178. });
  15179. const setup$c = (streamInfo, streamState) => {
  15180. const sInfo = streamInfo.stream;
  15181. const throttler = last(streamInfo.onStream, sInfo.delay);
  15182. streamState.setTimer(throttler);
  15183. return (component, simulatedEvent) => {
  15184. throttler.throttle(component, simulatedEvent);
  15185. if (sInfo.stopEvent) {
  15186. simulatedEvent.stop();
  15187. }
  15188. };
  15189. };
  15190. var StreamingSchema = [
  15191. requiredOf('stream', choose$1('mode', {
  15192. throttle: [
  15193. required$1('delay'),
  15194. defaulted('stopEvent', true),
  15195. output$1('streams', {
  15196. setup: setup$c,
  15197. state: throttle
  15198. })
  15199. ]
  15200. })),
  15201. defaulted('event', 'input'),
  15202. option$3('cancelEvent'),
  15203. onStrictHandler('onStream')
  15204. ];
  15205. const Streaming = create$4({
  15206. fields: StreamingSchema,
  15207. name: 'streaming',
  15208. active: ActiveStreaming,
  15209. state: StreamingState
  15210. });
  15211. const setValueFromItem = (model, input, item) => {
  15212. const itemData = Representing.getValue(item);
  15213. Representing.setValue(input, itemData);
  15214. setCursorAtEnd(input);
  15215. };
  15216. const setSelectionOn = (input, f) => {
  15217. const el = input.element;
  15218. const value = get$6(el);
  15219. const node = el.dom;
  15220. if (get$f(el, 'type') !== 'number') {
  15221. f(node, value);
  15222. }
  15223. };
  15224. const setCursorAtEnd = input => {
  15225. setSelectionOn(input, (node, value) => node.setSelectionRange(value.length, value.length));
  15226. };
  15227. const setSelectionToEnd = (input, startOffset) => {
  15228. setSelectionOn(input, (node, value) => node.setSelectionRange(startOffset, value.length));
  15229. };
  15230. const attemptSelectOver = (model, input, item) => {
  15231. if (!model.selectsOver) {
  15232. return Optional.none();
  15233. } else {
  15234. const currentValue = Representing.getValue(input);
  15235. const inputDisplay = model.getDisplayText(currentValue);
  15236. const itemValue = Representing.getValue(item);
  15237. const itemDisplay = model.getDisplayText(itemValue);
  15238. return itemDisplay.indexOf(inputDisplay) === 0 ? Optional.some(() => {
  15239. setValueFromItem(model, input, item);
  15240. setSelectionToEnd(input, inputDisplay.length);
  15241. }) : Optional.none();
  15242. }
  15243. };
  15244. const itemExecute = constant$1('alloy.typeahead.itemexecute');
  15245. const make$3 = (detail, components, spec, externals) => {
  15246. const navigateList = (comp, simulatedEvent, highlighter) => {
  15247. detail.previewing.set(false);
  15248. const sandbox = Coupling.getCoupled(comp, 'sandbox');
  15249. if (Sandboxing.isOpen(sandbox)) {
  15250. Composing.getCurrent(sandbox).each(menu => {
  15251. Highlighting.getHighlighted(menu).fold(() => {
  15252. highlighter(menu);
  15253. }, () => {
  15254. dispatchEvent(sandbox, menu.element, 'keydown', simulatedEvent);
  15255. });
  15256. });
  15257. } else {
  15258. const onOpenSync = sandbox => {
  15259. Composing.getCurrent(sandbox).each(highlighter);
  15260. };
  15261. open(detail, mapFetch(comp), comp, sandbox, externals, onOpenSync, HighlightOnOpen.HighlightMenuAndItem).get(noop);
  15262. }
  15263. };
  15264. const focusBehaviours$1 = focusBehaviours(detail);
  15265. const mapFetch = comp => tdata => tdata.map(data => {
  15266. const menus = values(data.menus);
  15267. const items = bind$3(menus, menu => filter$2(menu.items, item => item.type === 'item'));
  15268. const repState = Representing.getState(comp);
  15269. repState.update(map$2(items, item => item.data));
  15270. return data;
  15271. });
  15272. const getActiveMenu = sandboxComp => Composing.getCurrent(sandboxComp);
  15273. const typeaheadCustomEvents = 'typeaheadevents';
  15274. const behaviours = [
  15275. Focusing.config({}),
  15276. Representing.config({
  15277. onSetValue: detail.onSetValue,
  15278. store: {
  15279. mode: 'dataset',
  15280. getDataKey: comp => get$6(comp.element),
  15281. getFallbackEntry: itemString => ({
  15282. value: itemString,
  15283. meta: {}
  15284. }),
  15285. setValue: (comp, data) => {
  15286. set$5(comp.element, detail.model.getDisplayText(data));
  15287. },
  15288. ...detail.initialData.map(d => wrap$1('initialValue', d)).getOr({})
  15289. }
  15290. }),
  15291. Streaming.config({
  15292. stream: {
  15293. mode: 'throttle',
  15294. delay: detail.responseTime,
  15295. stopEvent: false
  15296. },
  15297. onStream: (component, _simulatedEvent) => {
  15298. const sandbox = Coupling.getCoupled(component, 'sandbox');
  15299. const focusInInput = Focusing.isFocused(component);
  15300. if (focusInInput) {
  15301. if (get$6(component.element).length >= detail.minChars) {
  15302. const previousValue = getActiveMenu(sandbox).bind(activeMenu => Highlighting.getHighlighted(activeMenu).map(Representing.getValue));
  15303. detail.previewing.set(true);
  15304. const onOpenSync = _sandbox => {
  15305. getActiveMenu(sandbox).each(activeMenu => {
  15306. previousValue.fold(() => {
  15307. if (detail.model.selectsOver) {
  15308. Highlighting.highlightFirst(activeMenu);
  15309. }
  15310. }, pv => {
  15311. Highlighting.highlightBy(activeMenu, item => {
  15312. const itemData = Representing.getValue(item);
  15313. return itemData.value === pv.value;
  15314. });
  15315. Highlighting.getHighlighted(activeMenu).orThunk(() => {
  15316. Highlighting.highlightFirst(activeMenu);
  15317. return Optional.none();
  15318. });
  15319. });
  15320. });
  15321. };
  15322. open(detail, mapFetch(component), component, sandbox, externals, onOpenSync, HighlightOnOpen.HighlightJustMenu).get(noop);
  15323. }
  15324. }
  15325. },
  15326. cancelEvent: typeaheadCancel()
  15327. }),
  15328. Keying.config({
  15329. mode: 'special',
  15330. onDown: (comp, simulatedEvent) => {
  15331. navigateList(comp, simulatedEvent, Highlighting.highlightFirst);
  15332. return Optional.some(true);
  15333. },
  15334. onEscape: comp => {
  15335. const sandbox = Coupling.getCoupled(comp, 'sandbox');
  15336. if (Sandboxing.isOpen(sandbox)) {
  15337. Sandboxing.close(sandbox);
  15338. return Optional.some(true);
  15339. }
  15340. return Optional.none();
  15341. },
  15342. onUp: (comp, simulatedEvent) => {
  15343. navigateList(comp, simulatedEvent, Highlighting.highlightLast);
  15344. return Optional.some(true);
  15345. },
  15346. onEnter: comp => {
  15347. const sandbox = Coupling.getCoupled(comp, 'sandbox');
  15348. const sandboxIsOpen = Sandboxing.isOpen(sandbox);
  15349. if (sandboxIsOpen && !detail.previewing.get()) {
  15350. return getActiveMenu(sandbox).bind(activeMenu => Highlighting.getHighlighted(activeMenu)).map(item => {
  15351. emitWith(comp, itemExecute(), { item });
  15352. return true;
  15353. });
  15354. } else {
  15355. const currentValue = Representing.getValue(comp);
  15356. emit(comp, typeaheadCancel());
  15357. detail.onExecute(sandbox, comp, currentValue);
  15358. if (sandboxIsOpen) {
  15359. Sandboxing.close(sandbox);
  15360. }
  15361. return Optional.some(true);
  15362. }
  15363. }
  15364. }),
  15365. Toggling.config({
  15366. toggleClass: detail.markers.openClass,
  15367. aria: { mode: 'expanded' }
  15368. }),
  15369. Coupling.config({
  15370. others: {
  15371. sandbox: hotspot => {
  15372. return makeSandbox$1(detail, hotspot, {
  15373. onOpen: () => Toggling.on(hotspot),
  15374. onClose: () => Toggling.off(hotspot)
  15375. });
  15376. }
  15377. }
  15378. }),
  15379. config(typeaheadCustomEvents, [
  15380. runOnAttached(typeaheadComp => {
  15381. detail.lazyTypeaheadComp.set(Optional.some(typeaheadComp));
  15382. }),
  15383. runOnDetached(_typeaheadComp => {
  15384. detail.lazyTypeaheadComp.set(Optional.none());
  15385. }),
  15386. runOnExecute$1(comp => {
  15387. const onOpenSync = noop;
  15388. togglePopup(detail, mapFetch(comp), comp, externals, onOpenSync, HighlightOnOpen.HighlightMenuAndItem).get(noop);
  15389. }),
  15390. run$1(itemExecute(), (comp, se) => {
  15391. const sandbox = Coupling.getCoupled(comp, 'sandbox');
  15392. setValueFromItem(detail.model, comp, se.event.item);
  15393. emit(comp, typeaheadCancel());
  15394. detail.onItemExecute(comp, sandbox, se.event.item, Representing.getValue(comp));
  15395. Sandboxing.close(sandbox);
  15396. setCursorAtEnd(comp);
  15397. })
  15398. ].concat(detail.dismissOnBlur ? [run$1(postBlur(), typeahead => {
  15399. const sandbox = Coupling.getCoupled(typeahead, 'sandbox');
  15400. if (search(sandbox.element).isNone()) {
  15401. Sandboxing.close(sandbox);
  15402. }
  15403. })] : []))
  15404. ];
  15405. const eventOrder = {
  15406. [detachedFromDom()]: [
  15407. Representing.name(),
  15408. Streaming.name(),
  15409. typeaheadCustomEvents
  15410. ],
  15411. ...detail.eventOrder
  15412. };
  15413. return {
  15414. uid: detail.uid,
  15415. dom: dom(deepMerge(detail, {
  15416. inputAttributes: {
  15417. 'role': 'combobox',
  15418. 'aria-autocomplete': 'list',
  15419. 'aria-haspopup': 'true'
  15420. }
  15421. })),
  15422. behaviours: {
  15423. ...focusBehaviours$1,
  15424. ...augment(detail.typeaheadBehaviours, behaviours)
  15425. },
  15426. eventOrder
  15427. };
  15428. };
  15429. const schema$g = constant$1([
  15430. option$3('lazySink'),
  15431. required$1('fetch'),
  15432. defaulted('minChars', 5),
  15433. defaulted('responseTime', 1000),
  15434. onHandler('onOpen'),
  15435. defaulted('getHotspot', Optional.some),
  15436. defaulted('getAnchorOverrides', constant$1({})),
  15437. defaulted('layouts', Optional.none()),
  15438. defaulted('eventOrder', {}),
  15439. defaultedObjOf('model', {}, [
  15440. defaulted('getDisplayText', itemData => itemData.meta !== undefined && itemData.meta.text !== undefined ? itemData.meta.text : itemData.value),
  15441. defaulted('selectsOver', true),
  15442. defaulted('populateFromBrowse', true)
  15443. ]),
  15444. onHandler('onSetValue'),
  15445. onKeyboardHandler('onExecute'),
  15446. onHandler('onItemExecute'),
  15447. defaulted('inputClasses', []),
  15448. defaulted('inputAttributes', {}),
  15449. defaulted('inputStyles', {}),
  15450. defaulted('matchWidth', true),
  15451. defaulted('useMinWidth', false),
  15452. defaulted('dismissOnBlur', true),
  15453. markers$1(['openClass']),
  15454. option$3('initialData'),
  15455. field('typeaheadBehaviours', [
  15456. Focusing,
  15457. Representing,
  15458. Streaming,
  15459. Keying,
  15460. Toggling,
  15461. Coupling
  15462. ]),
  15463. customField('lazyTypeaheadComp', () => Cell(Optional.none)),
  15464. customField('previewing', () => Cell(true))
  15465. ].concat(schema$l()).concat(sandboxFields()));
  15466. const parts$b = constant$1([external({
  15467. schema: [tieredMenuMarkers()],
  15468. name: 'menu',
  15469. overrides: detail => {
  15470. return {
  15471. fakeFocus: true,
  15472. onHighlightItem: (_tmenu, menu, item) => {
  15473. if (!detail.previewing.get()) {
  15474. detail.lazyTypeaheadComp.get().each(input => {
  15475. if (detail.model.populateFromBrowse) {
  15476. setValueFromItem(detail.model, input, item);
  15477. }
  15478. });
  15479. } else {
  15480. detail.lazyTypeaheadComp.get().each(input => {
  15481. attemptSelectOver(detail.model, input, item).fold(() => {
  15482. if (detail.model.selectsOver) {
  15483. Highlighting.dehighlight(menu, item);
  15484. detail.previewing.set(true);
  15485. } else {
  15486. detail.previewing.set(false);
  15487. }
  15488. }, selectOverTextInInput => {
  15489. selectOverTextInInput();
  15490. detail.previewing.set(false);
  15491. });
  15492. });
  15493. }
  15494. },
  15495. onExecute: (_menu, item) => {
  15496. return detail.lazyTypeaheadComp.get().map(typeahead => {
  15497. emitWith(typeahead, itemExecute(), { item });
  15498. return true;
  15499. });
  15500. },
  15501. onHover: (menu, item) => {
  15502. detail.previewing.set(false);
  15503. detail.lazyTypeaheadComp.get().each(input => {
  15504. if (detail.model.populateFromBrowse) {
  15505. setValueFromItem(detail.model, input, item);
  15506. }
  15507. });
  15508. }
  15509. };
  15510. }
  15511. })]);
  15512. const Typeahead = composite({
  15513. name: 'Typeahead',
  15514. configFields: schema$g(),
  15515. partFields: parts$b(),
  15516. factory: make$3
  15517. });
  15518. const wrap = delegate => {
  15519. const toCached = () => {
  15520. return wrap(delegate.toCached());
  15521. };
  15522. const bindFuture = f => {
  15523. return wrap(delegate.bind(resA => resA.fold(err => Future.pure(Result.error(err)), a => f(a))));
  15524. };
  15525. const bindResult = f => {
  15526. return wrap(delegate.map(resA => resA.bind(f)));
  15527. };
  15528. const mapResult = f => {
  15529. return wrap(delegate.map(resA => resA.map(f)));
  15530. };
  15531. const mapError = f => {
  15532. return wrap(delegate.map(resA => resA.mapError(f)));
  15533. };
  15534. const foldResult = (whenError, whenValue) => {
  15535. return delegate.map(res => res.fold(whenError, whenValue));
  15536. };
  15537. const withTimeout = (timeout, errorThunk) => {
  15538. return wrap(Future.nu(callback => {
  15539. let timedOut = false;
  15540. const timer = setTimeout(() => {
  15541. timedOut = true;
  15542. callback(Result.error(errorThunk()));
  15543. }, timeout);
  15544. delegate.get(result => {
  15545. if (!timedOut) {
  15546. clearTimeout(timer);
  15547. callback(result);
  15548. }
  15549. });
  15550. }));
  15551. };
  15552. return {
  15553. ...delegate,
  15554. toCached,
  15555. bindFuture,
  15556. bindResult,
  15557. mapResult,
  15558. mapError,
  15559. foldResult,
  15560. withTimeout
  15561. };
  15562. };
  15563. const nu$1 = worker => {
  15564. return wrap(Future.nu(worker));
  15565. };
  15566. const value = value => {
  15567. return wrap(Future.pure(Result.value(value)));
  15568. };
  15569. const error = error => {
  15570. return wrap(Future.pure(Result.error(error)));
  15571. };
  15572. const fromResult = result => {
  15573. return wrap(Future.pure(result));
  15574. };
  15575. const fromFuture = future => {
  15576. return wrap(future.map(Result.value));
  15577. };
  15578. const fromPromise = promise => {
  15579. return nu$1(completer => {
  15580. promise.then(value => {
  15581. completer(Result.value(value));
  15582. }, error => {
  15583. completer(Result.error(error));
  15584. });
  15585. });
  15586. };
  15587. const FutureResult = {
  15588. nu: nu$1,
  15589. wrap,
  15590. pure: value,
  15591. value,
  15592. error,
  15593. fromResult,
  15594. fromFuture,
  15595. fromPromise
  15596. };
  15597. const getMenuButtonApi = component => ({
  15598. isEnabled: () => !Disabling.isDisabled(component),
  15599. setEnabled: state => Disabling.set(component, !state),
  15600. setActive: state => {
  15601. const elm = component.element;
  15602. if (state) {
  15603. add$2(elm, 'tox-tbtn--enabled');
  15604. set$9(elm, 'aria-pressed', true);
  15605. } else {
  15606. remove$2(elm, 'tox-tbtn--enabled');
  15607. remove$7(elm, 'aria-pressed');
  15608. }
  15609. },
  15610. isActive: () => has(component.element, 'tox-tbtn--enabled')
  15611. });
  15612. const renderMenuButton = (spec, prefix, backstage, role) => {
  15613. return renderCommonDropdown({
  15614. text: spec.text,
  15615. icon: spec.icon,
  15616. tooltip: spec.tooltip,
  15617. searchable: spec.search.isSome(),
  15618. role,
  15619. fetch: (dropdownComp, callback) => {
  15620. const fetchContext = { pattern: spec.search.isSome() ? getSearchPattern(dropdownComp) : '' };
  15621. spec.fetch(items => {
  15622. callback(build(items, ItemResponse$1.CLOSE_ON_EXECUTE, backstage, {
  15623. isHorizontalMenu: false,
  15624. search: spec.search
  15625. }));
  15626. }, fetchContext);
  15627. },
  15628. onSetup: spec.onSetup,
  15629. getApi: getMenuButtonApi,
  15630. columns: 1,
  15631. presets: 'normal',
  15632. classes: [],
  15633. dropdownBehaviours: [Tabstopping.config({})]
  15634. }, prefix, backstage.shared);
  15635. };
  15636. const getFetch = (items, getButton, backstage) => {
  15637. const getMenuItemAction = item => api => {
  15638. const newValue = !api.isActive();
  15639. api.setActive(newValue);
  15640. item.storage.set(newValue);
  15641. backstage.shared.getSink().each(sink => {
  15642. getButton().getOpt(sink).each(orig => {
  15643. focus$3(orig.element);
  15644. emitWith(orig, formActionEvent, {
  15645. name: item.name,
  15646. value: item.storage.get()
  15647. });
  15648. });
  15649. });
  15650. };
  15651. const getMenuItemSetup = item => api => {
  15652. api.setActive(item.storage.get());
  15653. };
  15654. return success => {
  15655. success(map$2(items, item => {
  15656. const text = item.text.fold(() => ({}), text => ({ text }));
  15657. return {
  15658. type: item.type,
  15659. active: false,
  15660. ...text,
  15661. onAction: getMenuItemAction(item),
  15662. onSetup: getMenuItemSetup(item)
  15663. };
  15664. }));
  15665. };
  15666. };
  15667. const renderCommonSpec = (spec, actionOpt, extraBehaviours = [], dom, components, providersBackstage) => {
  15668. const action = actionOpt.fold(() => ({}), action => ({ action }));
  15669. const common = {
  15670. buttonBehaviours: derive$1([
  15671. DisablingConfigs.button(() => !spec.enabled || providersBackstage.isDisabled()),
  15672. receivingConfig(),
  15673. Tabstopping.config({}),
  15674. config('button press', [
  15675. preventDefault('click'),
  15676. preventDefault('mousedown')
  15677. ])
  15678. ].concat(extraBehaviours)),
  15679. eventOrder: {
  15680. click: [
  15681. 'button press',
  15682. 'alloy.base.behaviour'
  15683. ],
  15684. mousedown: [
  15685. 'button press',
  15686. 'alloy.base.behaviour'
  15687. ]
  15688. },
  15689. ...action
  15690. };
  15691. const domFinal = deepMerge(common, { dom });
  15692. return deepMerge(domFinal, { components });
  15693. };
  15694. const renderIconButtonSpec = (spec, action, providersBackstage, extraBehaviours = []) => {
  15695. const tooltipAttributes = spec.tooltip.map(tooltip => ({
  15696. 'aria-label': providersBackstage.translate(tooltip),
  15697. 'title': providersBackstage.translate(tooltip)
  15698. })).getOr({});
  15699. const dom = {
  15700. tag: 'button',
  15701. classes: ['tox-tbtn'],
  15702. attributes: tooltipAttributes
  15703. };
  15704. const icon = spec.icon.map(iconName => renderIconFromPack(iconName, providersBackstage.icons));
  15705. const components = componentRenderPipeline([icon]);
  15706. return renderCommonSpec(spec, action, extraBehaviours, dom, components, providersBackstage);
  15707. };
  15708. const calculateClassesFromButtonType = buttonType => {
  15709. switch (buttonType) {
  15710. case 'primary':
  15711. return ['tox-button'];
  15712. case 'toolbar':
  15713. return ['tox-tbtn'];
  15714. case 'secondary':
  15715. default:
  15716. return [
  15717. 'tox-button',
  15718. 'tox-button--secondary'
  15719. ];
  15720. }
  15721. };
  15722. const renderButtonSpec = (spec, action, providersBackstage, extraBehaviours = [], extraClasses = []) => {
  15723. const translatedText = providersBackstage.translate(spec.text);
  15724. const icon = spec.icon.map(iconName => renderIconFromPack(iconName, providersBackstage.icons));
  15725. const components = [icon.getOrThunk(() => text$2(translatedText))];
  15726. const buttonType = spec.buttonType.getOr(!spec.primary && !spec.borderless ? 'secondary' : 'primary');
  15727. const baseClasses = calculateClassesFromButtonType(buttonType);
  15728. const classes = [
  15729. ...baseClasses,
  15730. ...icon.isSome() ? ['tox-button--icon'] : [],
  15731. ...spec.borderless ? ['tox-button--naked'] : [],
  15732. ...extraClasses
  15733. ];
  15734. const dom = {
  15735. tag: 'button',
  15736. classes,
  15737. attributes: { title: translatedText }
  15738. };
  15739. return renderCommonSpec(spec, action, extraBehaviours, dom, components, providersBackstage);
  15740. };
  15741. const renderButton = (spec, action, providersBackstage, extraBehaviours = [], extraClasses = []) => {
  15742. const buttonSpec = renderButtonSpec(spec, Optional.some(action), providersBackstage, extraBehaviours, extraClasses);
  15743. return Button.sketch(buttonSpec);
  15744. };
  15745. const getAction = (name, buttonType) => comp => {
  15746. if (buttonType === 'custom') {
  15747. emitWith(comp, formActionEvent, {
  15748. name,
  15749. value: {}
  15750. });
  15751. } else if (buttonType === 'submit') {
  15752. emit(comp, formSubmitEvent);
  15753. } else if (buttonType === 'cancel') {
  15754. emit(comp, formCancelEvent);
  15755. } else {
  15756. console.error('Unknown button type: ', buttonType);
  15757. }
  15758. };
  15759. const isMenuFooterButtonSpec = (spec, buttonType) => buttonType === 'menu';
  15760. const isNormalFooterButtonSpec = (spec, buttonType) => buttonType === 'custom' || buttonType === 'cancel' || buttonType === 'submit';
  15761. const renderFooterButton = (spec, buttonType, backstage) => {
  15762. if (isMenuFooterButtonSpec(spec, buttonType)) {
  15763. const getButton = () => memButton;
  15764. const menuButtonSpec = spec;
  15765. const fixedSpec = {
  15766. ...spec,
  15767. type: 'menubutton',
  15768. search: Optional.none(),
  15769. onSetup: api => {
  15770. api.setEnabled(spec.enabled);
  15771. return noop;
  15772. },
  15773. fetch: getFetch(menuButtonSpec.items, getButton, backstage)
  15774. };
  15775. const memButton = record(renderMenuButton(fixedSpec, 'tox-tbtn', backstage, Optional.none()));
  15776. return memButton.asSpec();
  15777. } else if (isNormalFooterButtonSpec(spec, buttonType)) {
  15778. const action = getAction(spec.name, buttonType);
  15779. const buttonSpec = {
  15780. ...spec,
  15781. borderless: false
  15782. };
  15783. return renderButton(buttonSpec, action, backstage.shared.providers, []);
  15784. } else {
  15785. console.error('Unknown footer button type: ', buttonType);
  15786. throw new Error('Unknown footer button type');
  15787. }
  15788. };
  15789. const renderDialogButton = (spec, providersBackstage) => {
  15790. const action = getAction(spec.name, 'custom');
  15791. return renderFormField(Optional.none(), FormField.parts.field({
  15792. factory: Button,
  15793. ...renderButtonSpec(spec, Optional.some(action), providersBackstage, [
  15794. RepresentingConfigs.memory(''),
  15795. ComposingConfigs.self()
  15796. ])
  15797. }));
  15798. };
  15799. const separator$1 = { type: 'separator' };
  15800. const toMenuItem = target => ({
  15801. type: 'menuitem',
  15802. value: target.url,
  15803. text: target.title,
  15804. meta: { attach: target.attach },
  15805. onAction: noop
  15806. });
  15807. const staticMenuItem = (title, url) => ({
  15808. type: 'menuitem',
  15809. value: url,
  15810. text: title,
  15811. meta: { attach: undefined },
  15812. onAction: noop
  15813. });
  15814. const toMenuItems = targets => map$2(targets, toMenuItem);
  15815. const filterLinkTargets = (type, targets) => filter$2(targets, target => target.type === type);
  15816. const filteredTargets = (type, targets) => toMenuItems(filterLinkTargets(type, targets));
  15817. const headerTargets = linkInfo => filteredTargets('header', linkInfo.targets);
  15818. const anchorTargets = linkInfo => filteredTargets('anchor', linkInfo.targets);
  15819. const anchorTargetTop = linkInfo => Optional.from(linkInfo.anchorTop).map(url => staticMenuItem('<top>', url)).toArray();
  15820. const anchorTargetBottom = linkInfo => Optional.from(linkInfo.anchorBottom).map(url => staticMenuItem('<bottom>', url)).toArray();
  15821. const historyTargets = history => map$2(history, url => staticMenuItem(url, url));
  15822. const joinMenuLists = items => {
  15823. return foldl(items, (a, b) => {
  15824. const bothEmpty = a.length === 0 || b.length === 0;
  15825. return bothEmpty ? a.concat(b) : a.concat(separator$1, b);
  15826. }, []);
  15827. };
  15828. const filterByQuery = (term, menuItems) => {
  15829. const lowerCaseTerm = term.toLowerCase();
  15830. return filter$2(menuItems, item => {
  15831. var _a;
  15832. const text = item.meta !== undefined && item.meta.text !== undefined ? item.meta.text : item.text;
  15833. const value = (_a = item.value) !== null && _a !== void 0 ? _a : '';
  15834. return contains$1(text.toLowerCase(), lowerCaseTerm) || contains$1(value.toLowerCase(), lowerCaseTerm);
  15835. });
  15836. };
  15837. const getItems = (fileType, input, urlBackstage) => {
  15838. const urlInputValue = Representing.getValue(input);
  15839. const term = urlInputValue.meta.text !== undefined ? urlInputValue.meta.text : urlInputValue.value;
  15840. const info = urlBackstage.getLinkInformation();
  15841. return info.fold(() => [], linkInfo => {
  15842. const history = filterByQuery(term, historyTargets(urlBackstage.getHistory(fileType)));
  15843. return fileType === 'file' ? joinMenuLists([
  15844. history,
  15845. filterByQuery(term, headerTargets(linkInfo)),
  15846. filterByQuery(term, flatten([
  15847. anchorTargetTop(linkInfo),
  15848. anchorTargets(linkInfo),
  15849. anchorTargetBottom(linkInfo)
  15850. ]))
  15851. ]) : history;
  15852. });
  15853. };
  15854. const errorId = generate$6('aria-invalid');
  15855. const renderUrlInput = (spec, backstage, urlBackstage, initialData) => {
  15856. const providersBackstage = backstage.shared.providers;
  15857. const updateHistory = component => {
  15858. const urlEntry = Representing.getValue(component);
  15859. urlBackstage.addToHistory(urlEntry.value, spec.filetype);
  15860. };
  15861. const typeaheadSpec = {
  15862. ...initialData.map(initialData => ({ initialData })).getOr({}),
  15863. dismissOnBlur: true,
  15864. inputClasses: ['tox-textfield'],
  15865. sandboxClasses: ['tox-dialog__popups'],
  15866. inputAttributes: {
  15867. 'aria-errormessage': errorId,
  15868. 'type': 'url'
  15869. },
  15870. minChars: 0,
  15871. responseTime: 0,
  15872. fetch: input => {
  15873. const items = getItems(spec.filetype, input, urlBackstage);
  15874. const tdata = build(items, ItemResponse$1.BUBBLE_TO_SANDBOX, backstage, {
  15875. isHorizontalMenu: false,
  15876. search: Optional.none()
  15877. });
  15878. return Future.pure(tdata);
  15879. },
  15880. getHotspot: comp => memUrlBox.getOpt(comp),
  15881. onSetValue: (comp, _newValue) => {
  15882. if (comp.hasConfigured(Invalidating)) {
  15883. Invalidating.run(comp).get(noop);
  15884. }
  15885. },
  15886. typeaheadBehaviours: derive$1([
  15887. ...urlBackstage.getValidationHandler().map(handler => Invalidating.config({
  15888. getRoot: comp => parentElement(comp.element),
  15889. invalidClass: 'tox-control-wrap--status-invalid',
  15890. notify: {
  15891. onInvalid: (comp, err) => {
  15892. memInvalidIcon.getOpt(comp).each(invalidComp => {
  15893. set$9(invalidComp.element, 'title', providersBackstage.translate(err));
  15894. });
  15895. }
  15896. },
  15897. validator: {
  15898. validate: input => {
  15899. const urlEntry = Representing.getValue(input);
  15900. return FutureResult.nu(completer => {
  15901. handler({
  15902. type: spec.filetype,
  15903. url: urlEntry.value
  15904. }, validation => {
  15905. if (validation.status === 'invalid') {
  15906. const err = Result.error(validation.message);
  15907. completer(err);
  15908. } else {
  15909. const val = Result.value(validation.message);
  15910. completer(val);
  15911. }
  15912. });
  15913. });
  15914. },
  15915. validateOnLoad: false
  15916. }
  15917. })).toArray(),
  15918. Disabling.config({ disabled: () => !spec.enabled || providersBackstage.isDisabled() }),
  15919. Tabstopping.config({}),
  15920. config('urlinput-events', [
  15921. run$1(input(), comp => {
  15922. const currentValue = get$6(comp.element);
  15923. const trimmedValue = currentValue.trim();
  15924. if (trimmedValue !== currentValue) {
  15925. set$5(comp.element, trimmedValue);
  15926. }
  15927. if (spec.filetype === 'file') {
  15928. emitWith(comp, formChangeEvent, { name: spec.name });
  15929. }
  15930. }),
  15931. run$1(change(), comp => {
  15932. emitWith(comp, formChangeEvent, { name: spec.name });
  15933. updateHistory(comp);
  15934. }),
  15935. run$1(postPaste(), comp => {
  15936. emitWith(comp, formChangeEvent, { name: spec.name });
  15937. updateHistory(comp);
  15938. })
  15939. ])
  15940. ]),
  15941. eventOrder: {
  15942. [input()]: [
  15943. 'streaming',
  15944. 'urlinput-events',
  15945. 'invalidating'
  15946. ]
  15947. },
  15948. model: {
  15949. getDisplayText: itemData => itemData.value,
  15950. selectsOver: false,
  15951. populateFromBrowse: false
  15952. },
  15953. markers: { openClass: 'tox-textfield--popup-open' },
  15954. lazySink: backstage.shared.getSink,
  15955. parts: { menu: part(false, 1, 'normal') },
  15956. onExecute: (_menu, component, _entry) => {
  15957. emitWith(component, formSubmitEvent, {});
  15958. },
  15959. onItemExecute: (typeahead, _sandbox, _item, _value) => {
  15960. updateHistory(typeahead);
  15961. emitWith(typeahead, formChangeEvent, { name: spec.name });
  15962. }
  15963. };
  15964. const pField = FormField.parts.field({
  15965. ...typeaheadSpec,
  15966. factory: Typeahead
  15967. });
  15968. const pLabel = spec.label.map(label => renderLabel$2(label, providersBackstage));
  15969. const makeIcon = (name, errId, icon = name, label = name) => render$3(icon, {
  15970. tag: 'div',
  15971. classes: [
  15972. 'tox-icon',
  15973. 'tox-control-wrap__status-icon-' + name
  15974. ],
  15975. attributes: {
  15976. 'title': providersBackstage.translate(label),
  15977. 'aria-live': 'polite',
  15978. ...errId.fold(() => ({}), id => ({ id }))
  15979. }
  15980. }, providersBackstage.icons);
  15981. const memInvalidIcon = record(makeIcon('invalid', Optional.some(errorId), 'warning'));
  15982. const memStatus = record({
  15983. dom: {
  15984. tag: 'div',
  15985. classes: ['tox-control-wrap__status-icon-wrap']
  15986. },
  15987. components: [memInvalidIcon.asSpec()]
  15988. });
  15989. const optUrlPicker = urlBackstage.getUrlPicker(spec.filetype);
  15990. const browseUrlEvent = generate$6('browser.url.event');
  15991. const memUrlBox = record({
  15992. dom: {
  15993. tag: 'div',
  15994. classes: ['tox-control-wrap']
  15995. },
  15996. components: [
  15997. pField,
  15998. memStatus.asSpec()
  15999. ],
  16000. behaviours: derive$1([Disabling.config({ disabled: () => !spec.enabled || providersBackstage.isDisabled() })])
  16001. });
  16002. const memUrlPickerButton = record(renderButton({
  16003. name: spec.name,
  16004. icon: Optional.some('browse'),
  16005. text: spec.label.getOr(''),
  16006. enabled: spec.enabled,
  16007. primary: false,
  16008. buttonType: Optional.none(),
  16009. borderless: true
  16010. }, component => emit(component, browseUrlEvent), providersBackstage, [], ['tox-browse-url']));
  16011. const controlHWrapper = () => ({
  16012. dom: {
  16013. tag: 'div',
  16014. classes: ['tox-form__controls-h-stack']
  16015. },
  16016. components: flatten([
  16017. [memUrlBox.asSpec()],
  16018. optUrlPicker.map(() => memUrlPickerButton.asSpec()).toArray()
  16019. ])
  16020. });
  16021. const openUrlPicker = comp => {
  16022. Composing.getCurrent(comp).each(field => {
  16023. const componentData = Representing.getValue(field);
  16024. const urlData = {
  16025. fieldname: spec.name,
  16026. ...componentData
  16027. };
  16028. optUrlPicker.each(picker => {
  16029. picker(urlData).get(chosenData => {
  16030. Representing.setValue(field, chosenData);
  16031. emitWith(comp, formChangeEvent, { name: spec.name });
  16032. });
  16033. });
  16034. });
  16035. };
  16036. return FormField.sketch({
  16037. dom: renderFormFieldDom(),
  16038. components: pLabel.toArray().concat([controlHWrapper()]),
  16039. fieldBehaviours: derive$1([
  16040. Disabling.config({
  16041. disabled: () => !spec.enabled || providersBackstage.isDisabled(),
  16042. onDisabled: comp => {
  16043. FormField.getField(comp).each(Disabling.disable);
  16044. memUrlPickerButton.getOpt(comp).each(Disabling.disable);
  16045. },
  16046. onEnabled: comp => {
  16047. FormField.getField(comp).each(Disabling.enable);
  16048. memUrlPickerButton.getOpt(comp).each(Disabling.enable);
  16049. }
  16050. }),
  16051. receivingConfig(),
  16052. config('url-input-events', [run$1(browseUrlEvent, openUrlPicker)])
  16053. ])
  16054. });
  16055. };
  16056. const renderAlertBanner = (spec, providersBackstage) => Container.sketch({
  16057. dom: {
  16058. tag: 'div',
  16059. attributes: { role: 'alert' },
  16060. classes: [
  16061. 'tox-notification',
  16062. 'tox-notification--in',
  16063. `tox-notification--${ spec.level }`
  16064. ]
  16065. },
  16066. components: [
  16067. {
  16068. dom: {
  16069. tag: 'div',
  16070. classes: ['tox-notification__icon']
  16071. },
  16072. components: [Button.sketch({
  16073. dom: {
  16074. tag: 'button',
  16075. classes: [
  16076. 'tox-button',
  16077. 'tox-button--naked',
  16078. 'tox-button--icon'
  16079. ],
  16080. innerHtml: get$2(spec.icon, providersBackstage.icons),
  16081. attributes: { title: providersBackstage.translate(spec.iconTooltip) }
  16082. },
  16083. action: comp => {
  16084. emitWith(comp, formActionEvent, {
  16085. name: 'alert-banner',
  16086. value: spec.url
  16087. });
  16088. },
  16089. buttonBehaviours: derive$1([addFocusableBehaviour()])
  16090. })]
  16091. },
  16092. {
  16093. dom: {
  16094. tag: 'div',
  16095. classes: ['tox-notification__body'],
  16096. innerHtml: providersBackstage.translate(spec.text)
  16097. }
  16098. }
  16099. ]
  16100. });
  16101. const set$1 = (element, status) => {
  16102. element.dom.checked = status;
  16103. };
  16104. const get$1 = element => element.dom.checked;
  16105. const renderCheckbox = (spec, providerBackstage, initialData) => {
  16106. const toggleCheckboxHandler = comp => {
  16107. comp.element.dom.click();
  16108. return Optional.some(true);
  16109. };
  16110. const pField = FormField.parts.field({
  16111. factory: { sketch: identity },
  16112. dom: {
  16113. tag: 'input',
  16114. classes: ['tox-checkbox__input'],
  16115. attributes: { type: 'checkbox' }
  16116. },
  16117. behaviours: derive$1([
  16118. ComposingConfigs.self(),
  16119. Disabling.config({ disabled: () => !spec.enabled || providerBackstage.isDisabled() }),
  16120. Tabstopping.config({}),
  16121. Focusing.config({}),
  16122. RepresentingConfigs.withElement(initialData, get$1, set$1),
  16123. Keying.config({
  16124. mode: 'special',
  16125. onEnter: toggleCheckboxHandler,
  16126. onSpace: toggleCheckboxHandler,
  16127. stopSpaceKeyup: true
  16128. }),
  16129. config('checkbox-events', [run$1(change(), (component, _) => {
  16130. emitWith(component, formChangeEvent, { name: spec.name });
  16131. })])
  16132. ])
  16133. });
  16134. const pLabel = FormField.parts.label({
  16135. dom: {
  16136. tag: 'span',
  16137. classes: ['tox-checkbox__label']
  16138. },
  16139. components: [text$2(providerBackstage.translate(spec.label))],
  16140. behaviours: derive$1([Unselecting.config({})])
  16141. });
  16142. const makeIcon = className => {
  16143. const iconName = className === 'checked' ? 'selected' : 'unselected';
  16144. return render$3(iconName, {
  16145. tag: 'span',
  16146. classes: [
  16147. 'tox-icon',
  16148. 'tox-checkbox-icon__' + className
  16149. ]
  16150. }, providerBackstage.icons);
  16151. };
  16152. const memIcons = record({
  16153. dom: {
  16154. tag: 'div',
  16155. classes: ['tox-checkbox__icons']
  16156. },
  16157. components: [
  16158. makeIcon('checked'),
  16159. makeIcon('unchecked')
  16160. ]
  16161. });
  16162. return FormField.sketch({
  16163. dom: {
  16164. tag: 'label',
  16165. classes: ['tox-checkbox']
  16166. },
  16167. components: [
  16168. pField,
  16169. memIcons.asSpec(),
  16170. pLabel
  16171. ],
  16172. fieldBehaviours: derive$1([
  16173. Disabling.config({
  16174. disabled: () => !spec.enabled || providerBackstage.isDisabled(),
  16175. disableClass: 'tox-checkbox--disabled',
  16176. onDisabled: comp => {
  16177. FormField.getField(comp).each(Disabling.disable);
  16178. },
  16179. onEnabled: comp => {
  16180. FormField.getField(comp).each(Disabling.enable);
  16181. }
  16182. }),
  16183. receivingConfig()
  16184. ])
  16185. });
  16186. };
  16187. const renderHtmlPanel = spec => {
  16188. if (spec.presets === 'presentation') {
  16189. return Container.sketch({
  16190. dom: {
  16191. tag: 'div',
  16192. classes: ['tox-form__group'],
  16193. innerHtml: spec.html
  16194. }
  16195. });
  16196. } else {
  16197. return Container.sketch({
  16198. dom: {
  16199. tag: 'div',
  16200. classes: ['tox-form__group'],
  16201. innerHtml: spec.html,
  16202. attributes: { role: 'document' }
  16203. },
  16204. containerBehaviours: derive$1([
  16205. Tabstopping.config({}),
  16206. Focusing.config({})
  16207. ])
  16208. });
  16209. }
  16210. };
  16211. const make$2 = render => {
  16212. return (parts, spec, dialogData, backstage) => get$g(spec, 'name').fold(() => render(spec, backstage, Optional.none()), fieldName => parts.field(fieldName, render(spec, backstage, get$g(dialogData, fieldName))));
  16213. };
  16214. const makeIframe = render => (parts, spec, dialogData, backstage) => {
  16215. const iframeSpec = deepMerge(spec, { source: 'dynamic' });
  16216. return make$2(render)(parts, iframeSpec, dialogData, backstage);
  16217. };
  16218. const factories = {
  16219. bar: make$2((spec, backstage) => renderBar(spec, backstage.shared)),
  16220. collection: make$2((spec, backstage, data) => renderCollection(spec, backstage.shared.providers, data)),
  16221. alertbanner: make$2((spec, backstage) => renderAlertBanner(spec, backstage.shared.providers)),
  16222. input: make$2((spec, backstage, data) => renderInput(spec, backstage.shared.providers, data)),
  16223. textarea: make$2((spec, backstage, data) => renderTextarea(spec, backstage.shared.providers, data)),
  16224. label: make$2((spec, backstage) => renderLabel$1(spec, backstage.shared)),
  16225. iframe: makeIframe((spec, backstage, data) => renderIFrame(spec, backstage.shared.providers, data)),
  16226. button: make$2((spec, backstage) => renderDialogButton(spec, backstage.shared.providers)),
  16227. checkbox: make$2((spec, backstage, data) => renderCheckbox(spec, backstage.shared.providers, data)),
  16228. colorinput: make$2((spec, backstage, data) => renderColorInput(spec, backstage.shared, backstage.colorinput, data)),
  16229. colorpicker: make$2((spec, backstage, data) => renderColorPicker(spec, backstage.shared.providers, data)),
  16230. dropzone: make$2((spec, backstage, data) => renderDropZone(spec, backstage.shared.providers, data)),
  16231. grid: make$2((spec, backstage) => renderGrid(spec, backstage.shared)),
  16232. listbox: make$2((spec, backstage, data) => renderListBox(spec, backstage, data)),
  16233. selectbox: make$2((spec, backstage, data) => renderSelectBox(spec, backstage.shared.providers, data)),
  16234. sizeinput: make$2((spec, backstage) => renderSizeInput(spec, backstage.shared.providers)),
  16235. slider: make$2((spec, backstage, data) => renderSlider(spec, backstage.shared.providers, data)),
  16236. urlinput: make$2((spec, backstage, data) => renderUrlInput(spec, backstage, backstage.urlinput, data)),
  16237. customeditor: make$2(renderCustomEditor),
  16238. htmlpanel: make$2(renderHtmlPanel),
  16239. imagepreview: make$2((spec, _, data) => renderImagePreview(spec, data)),
  16240. table: make$2((spec, backstage) => renderTable(spec, backstage.shared.providers)),
  16241. panel: make$2((spec, backstage) => renderPanel(spec, backstage))
  16242. };
  16243. const noFormParts = {
  16244. field: (_name, spec) => spec,
  16245. record: constant$1([])
  16246. };
  16247. const interpretInForm = (parts, spec, dialogData, oldBackstage) => {
  16248. const newBackstage = deepMerge(oldBackstage, { shared: { interpreter: childSpec => interpretParts(parts, childSpec, dialogData, newBackstage) } });
  16249. return interpretParts(parts, spec, dialogData, newBackstage);
  16250. };
  16251. const interpretParts = (parts, spec, dialogData, backstage) => get$g(factories, spec.type).fold(() => {
  16252. console.error(`Unknown factory type "${ spec.type }", defaulting to container: `, spec);
  16253. return spec;
  16254. }, factory => factory(parts, spec, dialogData, backstage));
  16255. const interpretWithoutForm = (spec, dialogData, backstage) => interpretParts(noFormParts, spec, dialogData, backstage);
  16256. const labelPrefix = 'layout-inset';
  16257. const westEdgeX = anchor => anchor.x;
  16258. const middleX = (anchor, element) => anchor.x + anchor.width / 2 - element.width / 2;
  16259. const eastEdgeX = (anchor, element) => anchor.x + anchor.width - element.width;
  16260. const northY = anchor => anchor.y;
  16261. const southY = (anchor, element) => anchor.y + anchor.height - element.height;
  16262. const centreY = (anchor, element) => anchor.y + anchor.height / 2 - element.height / 2;
  16263. const southwest = (anchor, element, bubbles) => nu$6(eastEdgeX(anchor, element), southY(anchor, element), bubbles.insetSouthwest(), northwest$3(), 'southwest', boundsRestriction(anchor, {
  16264. right: 0,
  16265. bottom: 3
  16266. }), labelPrefix);
  16267. const southeast = (anchor, element, bubbles) => nu$6(westEdgeX(anchor), southY(anchor, element), bubbles.insetSoutheast(), northeast$3(), 'southeast', boundsRestriction(anchor, {
  16268. left: 1,
  16269. bottom: 3
  16270. }), labelPrefix);
  16271. const northwest = (anchor, element, bubbles) => nu$6(eastEdgeX(anchor, element), northY(anchor), bubbles.insetNorthwest(), southwest$3(), 'northwest', boundsRestriction(anchor, {
  16272. right: 0,
  16273. top: 2
  16274. }), labelPrefix);
  16275. const northeast = (anchor, element, bubbles) => nu$6(westEdgeX(anchor), northY(anchor), bubbles.insetNortheast(), southeast$3(), 'northeast', boundsRestriction(anchor, {
  16276. left: 1,
  16277. top: 2
  16278. }), labelPrefix);
  16279. const north = (anchor, element, bubbles) => nu$6(middleX(anchor, element), northY(anchor), bubbles.insetNorth(), south$3(), 'north', boundsRestriction(anchor, { top: 2 }), labelPrefix);
  16280. const south = (anchor, element, bubbles) => nu$6(middleX(anchor, element), southY(anchor, element), bubbles.insetSouth(), north$3(), 'south', boundsRestriction(anchor, { bottom: 3 }), labelPrefix);
  16281. const east = (anchor, element, bubbles) => nu$6(eastEdgeX(anchor, element), centreY(anchor, element), bubbles.insetEast(), west$3(), 'east', boundsRestriction(anchor, { right: 0 }), labelPrefix);
  16282. const west = (anchor, element, bubbles) => nu$6(westEdgeX(anchor), centreY(anchor, element), bubbles.insetWest(), east$3(), 'west', boundsRestriction(anchor, { left: 1 }), labelPrefix);
  16283. const lookupPreserveLayout = lastPlacement => {
  16284. switch (lastPlacement) {
  16285. case 'north':
  16286. return north;
  16287. case 'northeast':
  16288. return northeast;
  16289. case 'northwest':
  16290. return northwest;
  16291. case 'south':
  16292. return south;
  16293. case 'southeast':
  16294. return southeast;
  16295. case 'southwest':
  16296. return southwest;
  16297. case 'east':
  16298. return east;
  16299. case 'west':
  16300. return west;
  16301. }
  16302. };
  16303. const preserve = (anchor, element, bubbles, placee, bounds) => {
  16304. const layout = getPlacement(placee).map(lookupPreserveLayout).getOr(north);
  16305. return layout(anchor, element, bubbles, placee, bounds);
  16306. };
  16307. const lookupFlippedLayout = lastPlacement => {
  16308. switch (lastPlacement) {
  16309. case 'north':
  16310. return south;
  16311. case 'northeast':
  16312. return southeast;
  16313. case 'northwest':
  16314. return southwest;
  16315. case 'south':
  16316. return north;
  16317. case 'southeast':
  16318. return northeast;
  16319. case 'southwest':
  16320. return northwest;
  16321. case 'east':
  16322. return west;
  16323. case 'west':
  16324. return east;
  16325. }
  16326. };
  16327. const flip = (anchor, element, bubbles, placee, bounds) => {
  16328. const layout = getPlacement(placee).map(lookupFlippedLayout).getOr(north);
  16329. return layout(anchor, element, bubbles, placee, bounds);
  16330. };
  16331. const bubbleAlignments$2 = {
  16332. valignCentre: [],
  16333. alignCentre: [],
  16334. alignLeft: [],
  16335. alignRight: [],
  16336. right: [],
  16337. left: [],
  16338. bottom: [],
  16339. top: []
  16340. };
  16341. const getInlineDialogAnchor = (contentAreaElement, lazyAnchorbar, lazyUseEditableAreaAnchor) => {
  16342. const bubbleSize = 12;
  16343. const overrides = { maxHeightFunction: expandable$1() };
  16344. const editableAreaAnchor = () => ({
  16345. type: 'node',
  16346. root: getContentContainer(getRootNode(contentAreaElement())),
  16347. node: Optional.from(contentAreaElement()),
  16348. bubble: nu$5(bubbleSize, bubbleSize, bubbleAlignments$2),
  16349. layouts: {
  16350. onRtl: () => [northeast],
  16351. onLtr: () => [northwest]
  16352. },
  16353. overrides
  16354. });
  16355. const standardAnchor = () => ({
  16356. type: 'hotspot',
  16357. hotspot: lazyAnchorbar(),
  16358. bubble: nu$5(-bubbleSize, bubbleSize, bubbleAlignments$2),
  16359. layouts: {
  16360. onRtl: () => [southeast$2],
  16361. onLtr: () => [southwest$2]
  16362. },
  16363. overrides
  16364. });
  16365. return () => lazyUseEditableAreaAnchor() ? editableAreaAnchor() : standardAnchor();
  16366. };
  16367. const getBannerAnchor = (contentAreaElement, lazyAnchorbar, lazyUseEditableAreaAnchor) => {
  16368. const editableAreaAnchor = () => ({
  16369. type: 'node',
  16370. root: getContentContainer(getRootNode(contentAreaElement())),
  16371. node: Optional.from(contentAreaElement()),
  16372. layouts: {
  16373. onRtl: () => [north],
  16374. onLtr: () => [north]
  16375. }
  16376. });
  16377. const standardAnchor = () => ({
  16378. type: 'hotspot',
  16379. hotspot: lazyAnchorbar(),
  16380. layouts: {
  16381. onRtl: () => [south$2],
  16382. onLtr: () => [south$2]
  16383. }
  16384. });
  16385. return () => lazyUseEditableAreaAnchor() ? editableAreaAnchor() : standardAnchor();
  16386. };
  16387. const getCursorAnchor = (editor, bodyElement) => () => ({
  16388. type: 'selection',
  16389. root: bodyElement(),
  16390. getSelection: () => {
  16391. const rng = editor.selection.getRng();
  16392. return Optional.some(SimSelection.range(SugarElement.fromDom(rng.startContainer), rng.startOffset, SugarElement.fromDom(rng.endContainer), rng.endOffset));
  16393. }
  16394. });
  16395. const getNodeAnchor$1 = bodyElement => element => ({
  16396. type: 'node',
  16397. root: bodyElement(),
  16398. node: element
  16399. });
  16400. const getAnchors = (editor, lazyAnchorbar, isToolbarTop) => {
  16401. const useFixedToolbarContainer = useFixedContainer(editor);
  16402. const bodyElement = () => SugarElement.fromDom(editor.getBody());
  16403. const contentAreaElement = () => SugarElement.fromDom(editor.getContentAreaContainer());
  16404. const lazyUseEditableAreaAnchor = () => useFixedToolbarContainer || !isToolbarTop();
  16405. return {
  16406. inlineDialog: getInlineDialogAnchor(contentAreaElement, lazyAnchorbar, lazyUseEditableAreaAnchor),
  16407. banner: getBannerAnchor(contentAreaElement, lazyAnchorbar, lazyUseEditableAreaAnchor),
  16408. cursor: getCursorAnchor(editor, bodyElement),
  16409. node: getNodeAnchor$1(bodyElement)
  16410. };
  16411. };
  16412. const colorPicker = editor => (callback, value) => {
  16413. const dialog = colorPickerDialog(editor);
  16414. dialog(callback, value);
  16415. };
  16416. const hasCustomColors = editor => () => hasCustomColors$1(editor);
  16417. const getColors = editor => id => getColors$2(editor, id);
  16418. const getColorCols = editor => id => getColorCols$1(editor, id);
  16419. const ColorInputBackstage = editor => ({
  16420. colorPicker: colorPicker(editor),
  16421. hasCustomColors: hasCustomColors(editor),
  16422. getColors: getColors(editor),
  16423. getColorCols: getColorCols(editor)
  16424. });
  16425. const isDraggableModal = editor => () => isDraggableModal$1(editor);
  16426. const DialogBackstage = editor => ({ isDraggableModal: isDraggableModal(editor) });
  16427. const HeaderBackstage = editor => {
  16428. const mode = Cell(isToolbarLocationBottom(editor) ? 'bottom' : 'top');
  16429. return {
  16430. isPositionedAtTop: () => mode.get() === 'top',
  16431. getDockingMode: mode.get,
  16432. setDockingMode: mode.set
  16433. };
  16434. };
  16435. const isNestedFormat = format => hasNonNullableKey(format, 'items');
  16436. const isFormatReference = format => hasNonNullableKey(format, 'format');
  16437. const defaultStyleFormats = [
  16438. {
  16439. title: 'Headings',
  16440. items: [
  16441. {
  16442. title: 'Heading 1',
  16443. format: 'h1'
  16444. },
  16445. {
  16446. title: 'Heading 2',
  16447. format: 'h2'
  16448. },
  16449. {
  16450. title: 'Heading 3',
  16451. format: 'h3'
  16452. },
  16453. {
  16454. title: 'Heading 4',
  16455. format: 'h4'
  16456. },
  16457. {
  16458. title: 'Heading 5',
  16459. format: 'h5'
  16460. },
  16461. {
  16462. title: 'Heading 6',
  16463. format: 'h6'
  16464. }
  16465. ]
  16466. },
  16467. {
  16468. title: 'Inline',
  16469. items: [
  16470. {
  16471. title: 'Bold',
  16472. format: 'bold'
  16473. },
  16474. {
  16475. title: 'Italic',
  16476. format: 'italic'
  16477. },
  16478. {
  16479. title: 'Underline',
  16480. format: 'underline'
  16481. },
  16482. {
  16483. title: 'Strikethrough',
  16484. format: 'strikethrough'
  16485. },
  16486. {
  16487. title: 'Superscript',
  16488. format: 'superscript'
  16489. },
  16490. {
  16491. title: 'Subscript',
  16492. format: 'subscript'
  16493. },
  16494. {
  16495. title: 'Code',
  16496. format: 'code'
  16497. }
  16498. ]
  16499. },
  16500. {
  16501. title: 'Blocks',
  16502. items: [
  16503. {
  16504. title: 'Paragraph',
  16505. format: 'p'
  16506. },
  16507. {
  16508. title: 'Blockquote',
  16509. format: 'blockquote'
  16510. },
  16511. {
  16512. title: 'Div',
  16513. format: 'div'
  16514. },
  16515. {
  16516. title: 'Pre',
  16517. format: 'pre'
  16518. }
  16519. ]
  16520. },
  16521. {
  16522. title: 'Align',
  16523. items: [
  16524. {
  16525. title: 'Left',
  16526. format: 'alignleft'
  16527. },
  16528. {
  16529. title: 'Center',
  16530. format: 'aligncenter'
  16531. },
  16532. {
  16533. title: 'Right',
  16534. format: 'alignright'
  16535. },
  16536. {
  16537. title: 'Justify',
  16538. format: 'alignjustify'
  16539. }
  16540. ]
  16541. }
  16542. ];
  16543. const isNestedFormats = format => has$2(format, 'items');
  16544. const isBlockFormat = format => has$2(format, 'block');
  16545. const isInlineFormat = format => has$2(format, 'inline');
  16546. const isSelectorFormat = format => has$2(format, 'selector');
  16547. const mapFormats = userFormats => foldl(userFormats, (acc, fmt) => {
  16548. if (isNestedFormats(fmt)) {
  16549. const result = mapFormats(fmt.items);
  16550. return {
  16551. customFormats: acc.customFormats.concat(result.customFormats),
  16552. formats: acc.formats.concat([{
  16553. title: fmt.title,
  16554. items: result.formats
  16555. }])
  16556. };
  16557. } else if (isInlineFormat(fmt) || isBlockFormat(fmt) || isSelectorFormat(fmt)) {
  16558. const formatName = isString(fmt.name) ? fmt.name : fmt.title.toLowerCase();
  16559. const formatNameWithPrefix = `custom-${ formatName }`;
  16560. return {
  16561. customFormats: acc.customFormats.concat([{
  16562. name: formatNameWithPrefix,
  16563. format: fmt
  16564. }]),
  16565. formats: acc.formats.concat([{
  16566. title: fmt.title,
  16567. format: formatNameWithPrefix,
  16568. icon: fmt.icon
  16569. }])
  16570. };
  16571. } else {
  16572. return {
  16573. ...acc,
  16574. formats: acc.formats.concat(fmt)
  16575. };
  16576. }
  16577. }, {
  16578. customFormats: [],
  16579. formats: []
  16580. });
  16581. const registerCustomFormats = (editor, userFormats) => {
  16582. const result = mapFormats(userFormats);
  16583. const registerFormats = customFormats => {
  16584. each$1(customFormats, fmt => {
  16585. if (!editor.formatter.has(fmt.name)) {
  16586. editor.formatter.register(fmt.name, fmt.format);
  16587. }
  16588. });
  16589. };
  16590. if (editor.formatter) {
  16591. registerFormats(result.customFormats);
  16592. } else {
  16593. editor.on('init', () => {
  16594. registerFormats(result.customFormats);
  16595. });
  16596. }
  16597. return result.formats;
  16598. };
  16599. const getStyleFormats = editor => getUserStyleFormats(editor).map(userFormats => {
  16600. const registeredUserFormats = registerCustomFormats(editor, userFormats);
  16601. return shouldMergeStyleFormats(editor) ? defaultStyleFormats.concat(registeredUserFormats) : registeredUserFormats;
  16602. }).getOr(defaultStyleFormats);
  16603. const isSeparator$1 = format => {
  16604. const keys$1 = keys(format);
  16605. return keys$1.length === 1 && contains$2(keys$1, 'title');
  16606. };
  16607. const processBasic = (item, isSelectedFor, getPreviewFor) => ({
  16608. ...item,
  16609. type: 'formatter',
  16610. isSelected: isSelectedFor(item.format),
  16611. getStylePreview: getPreviewFor(item.format)
  16612. });
  16613. const register$a = (editor, formats, isSelectedFor, getPreviewFor) => {
  16614. const enrichSupported = item => processBasic(item, isSelectedFor, getPreviewFor);
  16615. const enrichMenu = item => {
  16616. const newItems = doEnrich(item.items);
  16617. return {
  16618. ...item,
  16619. type: 'submenu',
  16620. getStyleItems: constant$1(newItems)
  16621. };
  16622. };
  16623. const enrichCustom = item => {
  16624. const formatName = isString(item.name) ? item.name : generate$6(item.title);
  16625. const formatNameWithPrefix = `custom-${ formatName }`;
  16626. const newItem = {
  16627. ...item,
  16628. type: 'formatter',
  16629. format: formatNameWithPrefix,
  16630. isSelected: isSelectedFor(formatNameWithPrefix),
  16631. getStylePreview: getPreviewFor(formatNameWithPrefix)
  16632. };
  16633. editor.formatter.register(formatName, newItem);
  16634. return newItem;
  16635. };
  16636. const doEnrich = items => map$2(items, item => {
  16637. if (isNestedFormat(item)) {
  16638. return enrichMenu(item);
  16639. } else if (isFormatReference(item)) {
  16640. return enrichSupported(item);
  16641. } else if (isSeparator$1(item)) {
  16642. return {
  16643. ...item,
  16644. type: 'separator'
  16645. };
  16646. } else {
  16647. return enrichCustom(item);
  16648. }
  16649. });
  16650. return doEnrich(formats);
  16651. };
  16652. const init$8 = editor => {
  16653. const isSelectedFor = format => () => editor.formatter.match(format);
  16654. const getPreviewFor = format => () => {
  16655. const fmt = editor.formatter.get(format);
  16656. return fmt !== undefined ? Optional.some({
  16657. tag: fmt.length > 0 ? fmt[0].inline || fmt[0].block || 'div' : 'div',
  16658. styles: editor.dom.parseStyle(editor.formatter.getCssText(format))
  16659. }) : Optional.none();
  16660. };
  16661. const settingsFormats = Cell([]);
  16662. const eventsFormats = Cell([]);
  16663. const replaceSettings = Cell(false);
  16664. editor.on('PreInit', _e => {
  16665. const formats = getStyleFormats(editor);
  16666. const enriched = register$a(editor, formats, isSelectedFor, getPreviewFor);
  16667. settingsFormats.set(enriched);
  16668. });
  16669. editor.on('addStyleModifications', e => {
  16670. const modifications = register$a(editor, e.items, isSelectedFor, getPreviewFor);
  16671. eventsFormats.set(modifications);
  16672. replaceSettings.set(e.replace);
  16673. });
  16674. const getData = () => {
  16675. const fromSettings = replaceSettings.get() ? [] : settingsFormats.get();
  16676. const fromEvents = eventsFormats.get();
  16677. return fromSettings.concat(fromEvents);
  16678. };
  16679. return { getData };
  16680. };
  16681. const isElement = node => isNonNullable(node) && node.nodeType === 1;
  16682. const trim = global$1.trim;
  16683. const hasContentEditableState = value => {
  16684. return node => {
  16685. if (isElement(node)) {
  16686. if (node.contentEditable === value) {
  16687. return true;
  16688. }
  16689. if (node.getAttribute('data-mce-contenteditable') === value) {
  16690. return true;
  16691. }
  16692. }
  16693. return false;
  16694. };
  16695. };
  16696. const isContentEditableTrue = hasContentEditableState('true');
  16697. const isContentEditableFalse = hasContentEditableState('false');
  16698. const create$1 = (type, title, url, level, attach) => ({
  16699. type,
  16700. title,
  16701. url,
  16702. level,
  16703. attach
  16704. });
  16705. const isChildOfContentEditableTrue = node => {
  16706. let tempNode = node;
  16707. while (tempNode = tempNode.parentNode) {
  16708. const value = tempNode.contentEditable;
  16709. if (value && value !== 'inherit') {
  16710. return isContentEditableTrue(tempNode);
  16711. }
  16712. }
  16713. return false;
  16714. };
  16715. const select = (selector, root) => {
  16716. return map$2(descendants(SugarElement.fromDom(root), selector), element => {
  16717. return element.dom;
  16718. });
  16719. };
  16720. const getElementText = elm => {
  16721. return elm.innerText || elm.textContent;
  16722. };
  16723. const getOrGenerateId = elm => {
  16724. return elm.id ? elm.id : generate$6('h');
  16725. };
  16726. const isAnchor = elm => {
  16727. return elm && elm.nodeName === 'A' && (elm.id || elm.name) !== undefined;
  16728. };
  16729. const isValidAnchor = elm => {
  16730. return isAnchor(elm) && isEditable(elm);
  16731. };
  16732. const isHeader = elm => {
  16733. return elm && /^(H[1-6])$/.test(elm.nodeName);
  16734. };
  16735. const isEditable = elm => {
  16736. return isChildOfContentEditableTrue(elm) && !isContentEditableFalse(elm);
  16737. };
  16738. const isValidHeader = elm => {
  16739. return isHeader(elm) && isEditable(elm);
  16740. };
  16741. const getLevel = elm => {
  16742. return isHeader(elm) ? parseInt(elm.nodeName.substr(1), 10) : 0;
  16743. };
  16744. const headerTarget = elm => {
  16745. var _a;
  16746. const headerId = getOrGenerateId(elm);
  16747. const attach = () => {
  16748. elm.id = headerId;
  16749. };
  16750. return create$1('header', (_a = getElementText(elm)) !== null && _a !== void 0 ? _a : '', '#' + headerId, getLevel(elm), attach);
  16751. };
  16752. const anchorTarget = elm => {
  16753. const anchorId = elm.id || elm.name;
  16754. const anchorText = getElementText(elm);
  16755. return create$1('anchor', anchorText ? anchorText : '#' + anchorId, '#' + anchorId, 0, noop);
  16756. };
  16757. const getHeaderTargets = elms => {
  16758. return map$2(filter$2(elms, isValidHeader), headerTarget);
  16759. };
  16760. const getAnchorTargets = elms => {
  16761. return map$2(filter$2(elms, isValidAnchor), anchorTarget);
  16762. };
  16763. const getTargetElements = elm => {
  16764. const elms = select('h1,h2,h3,h4,h5,h6,a:not([href])', elm);
  16765. return elms;
  16766. };
  16767. const hasTitle = target => {
  16768. return trim(target.title).length > 0;
  16769. };
  16770. const find = elm => {
  16771. const elms = getTargetElements(elm);
  16772. return filter$2(getHeaderTargets(elms).concat(getAnchorTargets(elms)), hasTitle);
  16773. };
  16774. const LinkTargets = { find };
  16775. const STORAGE_KEY = 'tinymce-url-history';
  16776. const HISTORY_LENGTH = 5;
  16777. const isHttpUrl = url => isString(url) && /^https?/.test(url);
  16778. const isArrayOfUrl = a => isArray(a) && a.length <= HISTORY_LENGTH && forall(a, isHttpUrl);
  16779. const isRecordOfUrlArray = r => isObject(r) && find$4(r, value => !isArrayOfUrl(value)).isNone();
  16780. const getAllHistory = () => {
  16781. const unparsedHistory = global$4.getItem(STORAGE_KEY);
  16782. if (unparsedHistory === null) {
  16783. return {};
  16784. }
  16785. let history;
  16786. try {
  16787. history = JSON.parse(unparsedHistory);
  16788. } catch (e) {
  16789. if (e instanceof SyntaxError) {
  16790. console.log('Local storage ' + STORAGE_KEY + ' was not valid JSON', e);
  16791. return {};
  16792. }
  16793. throw e;
  16794. }
  16795. if (!isRecordOfUrlArray(history)) {
  16796. console.log('Local storage ' + STORAGE_KEY + ' was not valid format', history);
  16797. return {};
  16798. }
  16799. return history;
  16800. };
  16801. const setAllHistory = history => {
  16802. if (!isRecordOfUrlArray(history)) {
  16803. throw new Error('Bad format for history:\n' + JSON.stringify(history));
  16804. }
  16805. global$4.setItem(STORAGE_KEY, JSON.stringify(history));
  16806. };
  16807. const getHistory = fileType => {
  16808. const history = getAllHistory();
  16809. return get$g(history, fileType).getOr([]);
  16810. };
  16811. const addToHistory = (url, fileType) => {
  16812. if (!isHttpUrl(url)) {
  16813. return;
  16814. }
  16815. const history = getAllHistory();
  16816. const items = get$g(history, fileType).getOr([]);
  16817. const itemsWithoutUrl = filter$2(items, item => item !== url);
  16818. history[fileType] = [url].concat(itemsWithoutUrl).slice(0, HISTORY_LENGTH);
  16819. setAllHistory(history);
  16820. };
  16821. const isTruthy = value => !!value;
  16822. const makeMap = value => map$1(global$1.makeMap(value, /[, ]/), isTruthy);
  16823. const getPicker = editor => Optional.from(getFilePickerCallback(editor));
  16824. const getPickerTypes = editor => {
  16825. const optFileTypes = Optional.from(getFilePickerTypes(editor)).filter(isTruthy).map(makeMap);
  16826. return getPicker(editor).fold(never, _picker => optFileTypes.fold(always, types => keys(types).length > 0 ? types : false));
  16827. };
  16828. const getPickerSetting = (editor, filetype) => {
  16829. const pickerTypes = getPickerTypes(editor);
  16830. if (isBoolean(pickerTypes)) {
  16831. return pickerTypes ? getPicker(editor) : Optional.none();
  16832. } else {
  16833. return pickerTypes[filetype] ? getPicker(editor) : Optional.none();
  16834. }
  16835. };
  16836. const getUrlPicker = (editor, filetype) => getPickerSetting(editor, filetype).map(picker => entry => Future.nu(completer => {
  16837. const handler = (value, meta) => {
  16838. if (!isString(value)) {
  16839. throw new Error('Expected value to be string');
  16840. }
  16841. if (meta !== undefined && !isObject(meta)) {
  16842. throw new Error('Expected meta to be a object');
  16843. }
  16844. const r = {
  16845. value,
  16846. meta
  16847. };
  16848. completer(r);
  16849. };
  16850. const meta = {
  16851. filetype,
  16852. fieldname: entry.fieldname,
  16853. ...Optional.from(entry.meta).getOr({})
  16854. };
  16855. picker.call(editor, handler, entry.value, meta);
  16856. }));
  16857. const getTextSetting = value => Optional.from(value).filter(isString).getOrUndefined();
  16858. const getLinkInformation = editor => {
  16859. if (!useTypeaheadUrls(editor)) {
  16860. return Optional.none();
  16861. }
  16862. return Optional.some({
  16863. targets: LinkTargets.find(editor.getBody()),
  16864. anchorTop: getTextSetting(getAnchorTop(editor)),
  16865. anchorBottom: getTextSetting(getAnchorBottom(editor))
  16866. });
  16867. };
  16868. const getValidationHandler = editor => Optional.from(getFilePickerValidatorHandler(editor));
  16869. const UrlInputBackstage = editor => ({
  16870. getHistory,
  16871. addToHistory,
  16872. getLinkInformation: () => getLinkInformation(editor),
  16873. getValidationHandler: () => getValidationHandler(editor),
  16874. getUrlPicker: filetype => getUrlPicker(editor, filetype)
  16875. });
  16876. const init$7 = (lazySinks, editor, lazyAnchorbar) => {
  16877. const contextMenuState = Cell(false);
  16878. const toolbar = HeaderBackstage(editor);
  16879. const providers = {
  16880. icons: () => editor.ui.registry.getAll().icons,
  16881. menuItems: () => editor.ui.registry.getAll().menuItems,
  16882. translate: global$8.translate,
  16883. isDisabled: () => editor.mode.isReadOnly() || !editor.ui.isEnabled(),
  16884. getOption: editor.options.get
  16885. };
  16886. const urlinput = UrlInputBackstage(editor);
  16887. const styles = init$8(editor);
  16888. const colorinput = ColorInputBackstage(editor);
  16889. const dialogSettings = DialogBackstage(editor);
  16890. const isContextMenuOpen = () => contextMenuState.get();
  16891. const setContextMenuState = state => contextMenuState.set(state);
  16892. const commonBackstage = {
  16893. shared: {
  16894. providers,
  16895. anchors: getAnchors(editor, lazyAnchorbar, toolbar.isPositionedAtTop),
  16896. header: toolbar
  16897. },
  16898. urlinput,
  16899. styles,
  16900. colorinput,
  16901. dialog: dialogSettings,
  16902. isContextMenuOpen,
  16903. setContextMenuState
  16904. };
  16905. const popupBackstage = {
  16906. ...commonBackstage,
  16907. shared: {
  16908. ...commonBackstage.shared,
  16909. interpreter: s => interpretWithoutForm(s, {}, popupBackstage),
  16910. getSink: lazySinks.popup
  16911. }
  16912. };
  16913. const dialogBackstage = {
  16914. ...commonBackstage,
  16915. shared: {
  16916. ...commonBackstage.shared,
  16917. interpreter: s => interpretWithoutForm(s, {}, dialogBackstage),
  16918. getSink: lazySinks.dialog
  16919. }
  16920. };
  16921. return {
  16922. popup: popupBackstage,
  16923. dialog: dialogBackstage
  16924. };
  16925. };
  16926. const setup$b = (editor, mothership, uiMotherships) => {
  16927. const broadcastEvent = (name, evt) => {
  16928. each$1([
  16929. mothership,
  16930. ...uiMotherships
  16931. ], m => {
  16932. m.broadcastEvent(name, evt);
  16933. });
  16934. };
  16935. const broadcastOn = (channel, message) => {
  16936. each$1([
  16937. mothership,
  16938. ...uiMotherships
  16939. ], m => {
  16940. m.broadcastOn([channel], message);
  16941. });
  16942. };
  16943. const fireDismissPopups = evt => broadcastOn(dismissPopups(), { target: evt.target });
  16944. const doc = getDocument();
  16945. const onTouchstart = bind(doc, 'touchstart', fireDismissPopups);
  16946. const onTouchmove = bind(doc, 'touchmove', evt => broadcastEvent(documentTouchmove(), evt));
  16947. const onTouchend = bind(doc, 'touchend', evt => broadcastEvent(documentTouchend(), evt));
  16948. const onMousedown = bind(doc, 'mousedown', fireDismissPopups);
  16949. const onMouseup = bind(doc, 'mouseup', evt => {
  16950. if (evt.raw.button === 0) {
  16951. broadcastOn(mouseReleased(), { target: evt.target });
  16952. }
  16953. });
  16954. const onContentClick = raw => broadcastOn(dismissPopups(), { target: SugarElement.fromDom(raw.target) });
  16955. const onContentMouseup = raw => {
  16956. if (raw.button === 0) {
  16957. broadcastOn(mouseReleased(), { target: SugarElement.fromDom(raw.target) });
  16958. }
  16959. };
  16960. const onContentMousedown = () => {
  16961. each$1(editor.editorManager.get(), loopEditor => {
  16962. if (editor !== loopEditor) {
  16963. loopEditor.dispatch('DismissPopups', { relatedTarget: editor });
  16964. }
  16965. });
  16966. };
  16967. const onWindowScroll = evt => broadcastEvent(windowScroll(), fromRawEvent(evt));
  16968. const onWindowResize = evt => {
  16969. broadcastOn(repositionPopups(), {});
  16970. broadcastEvent(windowResize(), fromRawEvent(evt));
  16971. };
  16972. const onEditorResize = () => broadcastOn(repositionPopups(), {});
  16973. const onEditorProgress = evt => {
  16974. if (evt.state) {
  16975. broadcastOn(dismissPopups(), { target: SugarElement.fromDom(editor.getContainer()) });
  16976. }
  16977. };
  16978. const onDismissPopups = event => {
  16979. broadcastOn(dismissPopups(), { target: SugarElement.fromDom(event.relatedTarget.getContainer()) });
  16980. };
  16981. editor.on('PostRender', () => {
  16982. editor.on('click', onContentClick);
  16983. editor.on('tap', onContentClick);
  16984. editor.on('mouseup', onContentMouseup);
  16985. editor.on('mousedown', onContentMousedown);
  16986. editor.on('ScrollWindow', onWindowScroll);
  16987. editor.on('ResizeWindow', onWindowResize);
  16988. editor.on('ResizeEditor', onEditorResize);
  16989. editor.on('AfterProgressState', onEditorProgress);
  16990. editor.on('DismissPopups', onDismissPopups);
  16991. });
  16992. editor.on('remove', () => {
  16993. editor.off('click', onContentClick);
  16994. editor.off('tap', onContentClick);
  16995. editor.off('mouseup', onContentMouseup);
  16996. editor.off('mousedown', onContentMousedown);
  16997. editor.off('ScrollWindow', onWindowScroll);
  16998. editor.off('ResizeWindow', onWindowResize);
  16999. editor.off('ResizeEditor', onEditorResize);
  17000. editor.off('AfterProgressState', onEditorProgress);
  17001. editor.off('DismissPopups', onDismissPopups);
  17002. onMousedown.unbind();
  17003. onTouchstart.unbind();
  17004. onTouchmove.unbind();
  17005. onTouchend.unbind();
  17006. onMouseup.unbind();
  17007. });
  17008. editor.on('detach', () => {
  17009. each$1([
  17010. mothership,
  17011. ...uiMotherships
  17012. ], detachSystem);
  17013. each$1([
  17014. mothership,
  17015. ...uiMotherships
  17016. ], m => m.destroy());
  17017. });
  17018. };
  17019. const parts$a = AlloyParts;
  17020. const partType = PartType;
  17021. const schema$f = constant$1([
  17022. defaulted('shell', false),
  17023. required$1('makeItem'),
  17024. defaulted('setupItem', noop),
  17025. SketchBehaviours.field('listBehaviours', [Replacing])
  17026. ]);
  17027. const customListDetail = () => ({ behaviours: derive$1([Replacing.config({})]) });
  17028. const itemsPart = optional({
  17029. name: 'items',
  17030. overrides: customListDetail
  17031. });
  17032. const parts$9 = constant$1([itemsPart]);
  17033. const name = constant$1('CustomList');
  17034. const factory$f = (detail, components, _spec, _external) => {
  17035. const setItems = (list, items) => {
  17036. getListContainer(list).fold(() => {
  17037. console.error('Custom List was defined to not be a shell, but no item container was specified in components');
  17038. throw new Error('Custom List was defined to not be a shell, but no item container was specified in components');
  17039. }, container => {
  17040. const itemComps = Replacing.contents(container);
  17041. const numListsRequired = items.length;
  17042. const numListsToAdd = numListsRequired - itemComps.length;
  17043. const itemsToAdd = numListsToAdd > 0 ? range$2(numListsToAdd, () => detail.makeItem()) : [];
  17044. const itemsToRemove = itemComps.slice(numListsRequired);
  17045. each$1(itemsToRemove, item => Replacing.remove(container, item));
  17046. each$1(itemsToAdd, item => Replacing.append(container, item));
  17047. const builtLists = Replacing.contents(container);
  17048. each$1(builtLists, (item, i) => {
  17049. detail.setupItem(list, item, items[i], i);
  17050. });
  17051. });
  17052. };
  17053. const extra = detail.shell ? {
  17054. behaviours: [Replacing.config({})],
  17055. components: []
  17056. } : {
  17057. behaviours: [],
  17058. components
  17059. };
  17060. const getListContainer = component => detail.shell ? Optional.some(component) : getPart(component, detail, 'items');
  17061. return {
  17062. uid: detail.uid,
  17063. dom: detail.dom,
  17064. components: extra.components,
  17065. behaviours: augment(detail.listBehaviours, extra.behaviours),
  17066. apis: { setItems }
  17067. };
  17068. };
  17069. const CustomList = composite({
  17070. name: name(),
  17071. configFields: schema$f(),
  17072. partFields: parts$9(),
  17073. factory: factory$f,
  17074. apis: {
  17075. setItems: (apis, list, items) => {
  17076. apis.setItems(list, items);
  17077. }
  17078. }
  17079. });
  17080. const schema$e = constant$1([
  17081. required$1('dom'),
  17082. defaulted('shell', true),
  17083. field('toolbarBehaviours', [Replacing])
  17084. ]);
  17085. const enhanceGroups = () => ({ behaviours: derive$1([Replacing.config({})]) });
  17086. const parts$8 = constant$1([optional({
  17087. name: 'groups',
  17088. overrides: enhanceGroups
  17089. })]);
  17090. const factory$e = (detail, components, _spec, _externals) => {
  17091. const setGroups = (toolbar, groups) => {
  17092. getGroupContainer(toolbar).fold(() => {
  17093. console.error('Toolbar was defined to not be a shell, but no groups container was specified in components');
  17094. throw new Error('Toolbar was defined to not be a shell, but no groups container was specified in components');
  17095. }, container => {
  17096. Replacing.set(container, groups);
  17097. });
  17098. };
  17099. const getGroupContainer = component => detail.shell ? Optional.some(component) : getPart(component, detail, 'groups');
  17100. const extra = detail.shell ? {
  17101. behaviours: [Replacing.config({})],
  17102. components: []
  17103. } : {
  17104. behaviours: [],
  17105. components
  17106. };
  17107. return {
  17108. uid: detail.uid,
  17109. dom: detail.dom,
  17110. components: extra.components,
  17111. behaviours: augment(detail.toolbarBehaviours, extra.behaviours),
  17112. apis: { setGroups },
  17113. domModification: { attributes: { role: 'group' } }
  17114. };
  17115. };
  17116. const Toolbar = composite({
  17117. name: 'Toolbar',
  17118. configFields: schema$e(),
  17119. partFields: parts$8(),
  17120. factory: factory$e,
  17121. apis: {
  17122. setGroups: (apis, toolbar, groups) => {
  17123. apis.setGroups(toolbar, groups);
  17124. }
  17125. }
  17126. });
  17127. const setup$a = noop;
  17128. const isDocked$2 = never;
  17129. const getBehaviours$1 = constant$1([]);
  17130. var StaticHeader = /*#__PURE__*/Object.freeze({
  17131. __proto__: null,
  17132. setup: setup$a,
  17133. isDocked: isDocked$2,
  17134. getBehaviours: getBehaviours$1
  17135. });
  17136. const getOffsetParent = element => {
  17137. const isFixed = is$1(getRaw(element, 'position'), 'fixed');
  17138. const offsetParent$1 = isFixed ? Optional.none() : offsetParent(element);
  17139. return offsetParent$1.orThunk(() => {
  17140. const marker = SugarElement.fromTag('span');
  17141. return parent(element).bind(parent => {
  17142. append$2(parent, marker);
  17143. const offsetParent$1 = offsetParent(marker);
  17144. remove$5(marker);
  17145. return offsetParent$1;
  17146. });
  17147. });
  17148. };
  17149. const getOrigin = element => getOffsetParent(element).map(absolute$3).getOrThunk(() => SugarPosition(0, 0));
  17150. const morphAdt = Adt.generate([
  17151. { static: [] },
  17152. { absolute: ['positionCss'] },
  17153. { fixed: ['positionCss'] }
  17154. ]);
  17155. const appear = (component, contextualInfo) => {
  17156. const elem = component.element;
  17157. add$2(elem, contextualInfo.transitionClass);
  17158. remove$2(elem, contextualInfo.fadeOutClass);
  17159. add$2(elem, contextualInfo.fadeInClass);
  17160. contextualInfo.onShow(component);
  17161. };
  17162. const disappear = (component, contextualInfo) => {
  17163. const elem = component.element;
  17164. add$2(elem, contextualInfo.transitionClass);
  17165. remove$2(elem, contextualInfo.fadeInClass);
  17166. add$2(elem, contextualInfo.fadeOutClass);
  17167. contextualInfo.onHide(component);
  17168. };
  17169. const isPartiallyVisible = (box, viewport) => box.y < viewport.bottom && box.bottom > viewport.y;
  17170. const isTopCompletelyVisible = (box, viewport) => box.y >= viewport.y;
  17171. const isBottomCompletelyVisible = (box, viewport) => box.bottom <= viewport.bottom;
  17172. const isVisibleForModes = (modes, box, viewport) => forall(modes, mode => {
  17173. switch (mode) {
  17174. case 'bottom':
  17175. return isBottomCompletelyVisible(box, viewport);
  17176. case 'top':
  17177. return isTopCompletelyVisible(box, viewport);
  17178. }
  17179. });
  17180. const getPrior = (elem, state) => state.getInitialPos().map(pos => bounds(pos.bounds.x, pos.bounds.y, get$c(elem), get$d(elem)));
  17181. const storePrior = (elem, box, state) => {
  17182. state.setInitialPos({
  17183. style: getAllRaw(elem),
  17184. position: get$e(elem, 'position') || 'static',
  17185. bounds: box
  17186. });
  17187. };
  17188. const revertToOriginal = (elem, box, state) => state.getInitialPos().bind(position => {
  17189. state.clearInitialPos();
  17190. switch (position.position) {
  17191. case 'static':
  17192. return Optional.some(morphAdt.static());
  17193. case 'absolute':
  17194. const offsetBox = getOffsetParent(elem).map(box$1).getOrThunk(() => box$1(body()));
  17195. return Optional.some(morphAdt.absolute(NuPositionCss('absolute', get$g(position.style, 'left').map(_left => box.x - offsetBox.x), get$g(position.style, 'top').map(_top => box.y - offsetBox.y), get$g(position.style, 'right').map(_right => offsetBox.right - box.right), get$g(position.style, 'bottom').map(_bottom => offsetBox.bottom - box.bottom))));
  17196. default:
  17197. return Optional.none();
  17198. }
  17199. });
  17200. const morphToOriginal = (elem, viewport, state) => getPrior(elem, state).filter(box => isVisibleForModes(state.getModes(), box, viewport)).bind(box => revertToOriginal(elem, box, state));
  17201. const morphToFixed = (elem, viewport, state) => {
  17202. const box = box$1(elem);
  17203. if (!isVisibleForModes(state.getModes(), box, viewport)) {
  17204. storePrior(elem, box, state);
  17205. const winBox = win();
  17206. const left = box.x - winBox.x;
  17207. const top = viewport.y - winBox.y;
  17208. const bottom = winBox.bottom - viewport.bottom;
  17209. const isTop = box.y <= viewport.y;
  17210. return Optional.some(morphAdt.fixed(NuPositionCss('fixed', Optional.some(left), isTop ? Optional.some(top) : Optional.none(), Optional.none(), !isTop ? Optional.some(bottom) : Optional.none())));
  17211. } else {
  17212. return Optional.none();
  17213. }
  17214. };
  17215. const getMorph = (component, viewport, state) => {
  17216. const elem = component.element;
  17217. const isDocked = is$1(getRaw(elem, 'position'), 'fixed');
  17218. return isDocked ? morphToOriginal(elem, viewport, state) : morphToFixed(elem, viewport, state);
  17219. };
  17220. const getMorphToOriginal = (component, state) => {
  17221. const elem = component.element;
  17222. return getPrior(elem, state).bind(box => revertToOriginal(elem, box, state));
  17223. };
  17224. const morphToStatic = (component, config, state) => {
  17225. state.setDocked(false);
  17226. each$1([
  17227. 'left',
  17228. 'right',
  17229. 'top',
  17230. 'bottom',
  17231. 'position'
  17232. ], prop => remove$6(component.element, prop));
  17233. config.onUndocked(component);
  17234. };
  17235. const morphToCoord = (component, config, state, position) => {
  17236. const isDocked = position.position === 'fixed';
  17237. state.setDocked(isDocked);
  17238. applyPositionCss(component.element, position);
  17239. const method = isDocked ? config.onDocked : config.onUndocked;
  17240. method(component);
  17241. };
  17242. const updateVisibility = (component, config, state, viewport, morphToDocked = false) => {
  17243. config.contextual.each(contextInfo => {
  17244. contextInfo.lazyContext(component).each(box => {
  17245. const isVisible = isPartiallyVisible(box, viewport);
  17246. if (isVisible !== state.isVisible()) {
  17247. state.setVisible(isVisible);
  17248. if (morphToDocked && !isVisible) {
  17249. add$1(component.element, [contextInfo.fadeOutClass]);
  17250. contextInfo.onHide(component);
  17251. } else {
  17252. const method = isVisible ? appear : disappear;
  17253. method(component, contextInfo);
  17254. }
  17255. }
  17256. });
  17257. });
  17258. };
  17259. const refreshInternal = (component, config, state) => {
  17260. const viewport = config.lazyViewport(component);
  17261. const isDocked = state.isDocked();
  17262. if (isDocked) {
  17263. updateVisibility(component, config, state, viewport);
  17264. }
  17265. getMorph(component, viewport, state).each(morph => {
  17266. morph.fold(() => morphToStatic(component, config, state), position => morphToCoord(component, config, state, position), position => {
  17267. updateVisibility(component, config, state, viewport, true);
  17268. morphToCoord(component, config, state, position);
  17269. });
  17270. });
  17271. };
  17272. const resetInternal = (component, config, state) => {
  17273. const elem = component.element;
  17274. state.setDocked(false);
  17275. getMorphToOriginal(component, state).each(morph => {
  17276. morph.fold(() => morphToStatic(component, config, state), position => morphToCoord(component, config, state, position), noop);
  17277. });
  17278. state.setVisible(true);
  17279. config.contextual.each(contextInfo => {
  17280. remove$1(elem, [
  17281. contextInfo.fadeInClass,
  17282. contextInfo.fadeOutClass,
  17283. contextInfo.transitionClass
  17284. ]);
  17285. contextInfo.onShow(component);
  17286. });
  17287. refresh$4(component, config, state);
  17288. };
  17289. const refresh$4 = (component, config, state) => {
  17290. if (component.getSystem().isConnected()) {
  17291. refreshInternal(component, config, state);
  17292. }
  17293. };
  17294. const reset = (component, config, state) => {
  17295. if (state.isDocked()) {
  17296. resetInternal(component, config, state);
  17297. }
  17298. };
  17299. const isDocked$1 = (component, config, state) => state.isDocked();
  17300. const setModes = (component, config, state, modes) => state.setModes(modes);
  17301. const getModes = (component, config, state) => state.getModes();
  17302. var DockingApis = /*#__PURE__*/Object.freeze({
  17303. __proto__: null,
  17304. refresh: refresh$4,
  17305. reset: reset,
  17306. isDocked: isDocked$1,
  17307. getModes: getModes,
  17308. setModes: setModes
  17309. });
  17310. const events$5 = (dockInfo, dockState) => derive$2([
  17311. runOnSource(transitionend(), (component, simulatedEvent) => {
  17312. dockInfo.contextual.each(contextInfo => {
  17313. if (has(component.element, contextInfo.transitionClass)) {
  17314. remove$1(component.element, [
  17315. contextInfo.transitionClass,
  17316. contextInfo.fadeInClass
  17317. ]);
  17318. const notify = dockState.isVisible() ? contextInfo.onShown : contextInfo.onHidden;
  17319. notify(component);
  17320. }
  17321. simulatedEvent.stop();
  17322. });
  17323. }),
  17324. run$1(windowScroll(), (component, _) => {
  17325. refresh$4(component, dockInfo, dockState);
  17326. }),
  17327. run$1(windowResize(), (component, _) => {
  17328. reset(component, dockInfo, dockState);
  17329. })
  17330. ]);
  17331. var ActiveDocking = /*#__PURE__*/Object.freeze({
  17332. __proto__: null,
  17333. events: events$5
  17334. });
  17335. var DockingSchema = [
  17336. optionObjOf('contextual', [
  17337. requiredString('fadeInClass'),
  17338. requiredString('fadeOutClass'),
  17339. requiredString('transitionClass'),
  17340. requiredFunction('lazyContext'),
  17341. onHandler('onShow'),
  17342. onHandler('onShown'),
  17343. onHandler('onHide'),
  17344. onHandler('onHidden')
  17345. ]),
  17346. defaultedFunction('lazyViewport', win),
  17347. defaultedArrayOf('modes', [
  17348. 'top',
  17349. 'bottom'
  17350. ], string),
  17351. onHandler('onDocked'),
  17352. onHandler('onUndocked')
  17353. ];
  17354. const init$6 = spec => {
  17355. const docked = Cell(false);
  17356. const visible = Cell(true);
  17357. const initialBounds = value$2();
  17358. const modes = Cell(spec.modes);
  17359. const readState = () => `docked: ${ docked.get() }, visible: ${ visible.get() }, modes: ${ modes.get().join(',') }`;
  17360. return nu$8({
  17361. isDocked: docked.get,
  17362. setDocked: docked.set,
  17363. getInitialPos: initialBounds.get,
  17364. setInitialPos: initialBounds.set,
  17365. clearInitialPos: initialBounds.clear,
  17366. isVisible: visible.get,
  17367. setVisible: visible.set,
  17368. getModes: modes.get,
  17369. setModes: modes.set,
  17370. readState
  17371. });
  17372. };
  17373. var DockingState = /*#__PURE__*/Object.freeze({
  17374. __proto__: null,
  17375. init: init$6
  17376. });
  17377. const Docking = create$4({
  17378. fields: DockingSchema,
  17379. name: 'docking',
  17380. active: ActiveDocking,
  17381. apis: DockingApis,
  17382. state: DockingState
  17383. });
  17384. const toolbarHeightChange = constant$1(generate$6('toolbar-height-change'));
  17385. const visibility = {
  17386. fadeInClass: 'tox-editor-dock-fadein',
  17387. fadeOutClass: 'tox-editor-dock-fadeout',
  17388. transitionClass: 'tox-editor-dock-transition'
  17389. };
  17390. const editorStickyOnClass = 'tox-tinymce--toolbar-sticky-on';
  17391. const editorStickyOffClass = 'tox-tinymce--toolbar-sticky-off';
  17392. const scrollFromBehindHeader = (e, containerHeader) => {
  17393. const doc = owner$4(containerHeader);
  17394. const win = defaultView(containerHeader);
  17395. const viewHeight = win.dom.innerHeight;
  17396. const scrollPos = get$b(doc);
  17397. const markerElement = SugarElement.fromDom(e.elm);
  17398. const markerPos = absolute$2(markerElement);
  17399. const markerHeight = get$d(markerElement);
  17400. const markerTop = markerPos.y;
  17401. const markerBottom = markerTop + markerHeight;
  17402. const editorHeaderPos = absolute$3(containerHeader);
  17403. const editorHeaderHeight = get$d(containerHeader);
  17404. const editorHeaderTop = editorHeaderPos.top;
  17405. const editorHeaderBottom = editorHeaderTop + editorHeaderHeight;
  17406. const editorHeaderDockedAtTop = Math.abs(editorHeaderTop - scrollPos.top) < 2;
  17407. const editorHeaderDockedAtBottom = Math.abs(editorHeaderBottom - (scrollPos.top + viewHeight)) < 2;
  17408. if (editorHeaderDockedAtTop && markerTop < editorHeaderBottom) {
  17409. to(scrollPos.left, markerTop - editorHeaderHeight, doc);
  17410. } else if (editorHeaderDockedAtBottom && markerBottom > editorHeaderTop) {
  17411. const y = markerTop - viewHeight + markerHeight + editorHeaderHeight;
  17412. to(scrollPos.left, y, doc);
  17413. }
  17414. };
  17415. const isDockedMode = (header, mode) => contains$2(Docking.getModes(header), mode);
  17416. const updateIframeContentFlow = header => {
  17417. const getOccupiedHeight = elm => getOuter$2(elm) + (parseInt(get$e(elm, 'margin-top'), 10) || 0) + (parseInt(get$e(elm, 'margin-bottom'), 10) || 0);
  17418. const elm = header.element;
  17419. parentElement(elm).each(parentElem => {
  17420. const padding = 'padding-' + Docking.getModes(header)[0];
  17421. if (Docking.isDocked(header)) {
  17422. const parentWidth = get$c(parentElem);
  17423. set$8(elm, 'width', parentWidth + 'px');
  17424. set$8(parentElem, padding, getOccupiedHeight(elm) + 'px');
  17425. } else {
  17426. remove$6(elm, 'width');
  17427. remove$6(parentElem, padding);
  17428. }
  17429. });
  17430. };
  17431. const updateSinkVisibility = (sinkElem, visible) => {
  17432. if (visible) {
  17433. remove$2(sinkElem, visibility.fadeOutClass);
  17434. add$1(sinkElem, [
  17435. visibility.transitionClass,
  17436. visibility.fadeInClass
  17437. ]);
  17438. } else {
  17439. remove$2(sinkElem, visibility.fadeInClass);
  17440. add$1(sinkElem, [
  17441. visibility.fadeOutClass,
  17442. visibility.transitionClass
  17443. ]);
  17444. }
  17445. };
  17446. const updateEditorClasses = (editor, docked) => {
  17447. const editorContainer = SugarElement.fromDom(editor.getContainer());
  17448. if (docked) {
  17449. add$2(editorContainer, editorStickyOnClass);
  17450. remove$2(editorContainer, editorStickyOffClass);
  17451. } else {
  17452. add$2(editorContainer, editorStickyOffClass);
  17453. remove$2(editorContainer, editorStickyOnClass);
  17454. }
  17455. };
  17456. const restoreFocus = (headerElem, focusedElem) => {
  17457. const ownerDoc = owner$4(focusedElem);
  17458. active$1(ownerDoc).filter(activeElm => !eq(focusedElem, activeElm)).filter(activeElm => eq(activeElm, SugarElement.fromDom(ownerDoc.dom.body)) || contains(headerElem, activeElm)).each(() => focus$3(focusedElem));
  17459. };
  17460. const findFocusedElem = (rootElm, lazySink) => search(rootElm).orThunk(() => lazySink().toOptional().bind(sink => search(sink.element)));
  17461. const setup$9 = (editor, sharedBackstage, lazyHeader) => {
  17462. if (!editor.inline) {
  17463. if (!sharedBackstage.header.isPositionedAtTop()) {
  17464. editor.on('ResizeEditor', () => {
  17465. lazyHeader().each(Docking.reset);
  17466. });
  17467. }
  17468. editor.on('ResizeWindow ResizeEditor', () => {
  17469. lazyHeader().each(updateIframeContentFlow);
  17470. });
  17471. editor.on('SkinLoaded', () => {
  17472. lazyHeader().each(comp => {
  17473. Docking.isDocked(comp) ? Docking.reset(comp) : Docking.refresh(comp);
  17474. });
  17475. });
  17476. editor.on('FullscreenStateChanged', () => {
  17477. lazyHeader().each(Docking.reset);
  17478. });
  17479. }
  17480. editor.on('AfterScrollIntoView', e => {
  17481. lazyHeader().each(header => {
  17482. Docking.refresh(header);
  17483. const headerElem = header.element;
  17484. if (isVisible(headerElem)) {
  17485. scrollFromBehindHeader(e, headerElem);
  17486. }
  17487. });
  17488. });
  17489. editor.on('PostRender', () => {
  17490. updateEditorClasses(editor, false);
  17491. });
  17492. };
  17493. const isDocked = lazyHeader => lazyHeader().map(Docking.isDocked).getOr(false);
  17494. const getIframeBehaviours = () => [Receiving.config({ channels: { [toolbarHeightChange()]: { onReceive: updateIframeContentFlow } } })];
  17495. const getBehaviours = (editor, sharedBackstage) => {
  17496. const focusedElm = value$2();
  17497. const lazySink = sharedBackstage.getSink;
  17498. const runOnSinkElement = f => {
  17499. lazySink().each(sink => f(sink.element));
  17500. };
  17501. const onDockingSwitch = comp => {
  17502. if (!editor.inline) {
  17503. updateIframeContentFlow(comp);
  17504. }
  17505. updateEditorClasses(editor, Docking.isDocked(comp));
  17506. comp.getSystem().broadcastOn([repositionPopups()], {});
  17507. lazySink().each(sink => sink.getSystem().broadcastOn([repositionPopups()], {}));
  17508. };
  17509. const additionalBehaviours = editor.inline ? [] : getIframeBehaviours();
  17510. return [
  17511. Focusing.config({}),
  17512. Docking.config({
  17513. contextual: {
  17514. lazyContext: comp => {
  17515. const headerHeight = getOuter$2(comp.element);
  17516. const container = editor.inline ? editor.getContentAreaContainer() : editor.getContainer();
  17517. const box = box$1(SugarElement.fromDom(container));
  17518. const boxHeight = box.height - headerHeight;
  17519. const topBound = box.y + (isDockedMode(comp, 'top') ? 0 : headerHeight);
  17520. return Optional.some(bounds(box.x, topBound, box.width, boxHeight));
  17521. },
  17522. onShow: () => {
  17523. runOnSinkElement(elem => updateSinkVisibility(elem, true));
  17524. },
  17525. onShown: comp => {
  17526. runOnSinkElement(elem => remove$1(elem, [
  17527. visibility.transitionClass,
  17528. visibility.fadeInClass
  17529. ]));
  17530. focusedElm.get().each(elem => {
  17531. restoreFocus(comp.element, elem);
  17532. focusedElm.clear();
  17533. });
  17534. },
  17535. onHide: comp => {
  17536. findFocusedElem(comp.element, lazySink).fold(focusedElm.clear, focusedElm.set);
  17537. runOnSinkElement(elem => updateSinkVisibility(elem, false));
  17538. },
  17539. onHidden: () => {
  17540. runOnSinkElement(elem => remove$1(elem, [visibility.transitionClass]));
  17541. },
  17542. ...visibility
  17543. },
  17544. lazyViewport: comp => {
  17545. const win$1 = win();
  17546. const offset = getStickyToolbarOffset(editor);
  17547. const top = win$1.y + (isDockedMode(comp, 'top') ? offset : 0);
  17548. const height = win$1.height - (isDockedMode(comp, 'bottom') ? offset : 0);
  17549. return bounds(win$1.x, top, win$1.width, height);
  17550. },
  17551. modes: [sharedBackstage.header.getDockingMode()],
  17552. onDocked: onDockingSwitch,
  17553. onUndocked: onDockingSwitch
  17554. }),
  17555. ...additionalBehaviours
  17556. ];
  17557. };
  17558. var StickyHeader = /*#__PURE__*/Object.freeze({
  17559. __proto__: null,
  17560. setup: setup$9,
  17561. isDocked: isDocked,
  17562. getBehaviours: getBehaviours
  17563. });
  17564. const renderHeader = spec => {
  17565. const editor = spec.editor;
  17566. const getBehaviours$2 = spec.sticky ? getBehaviours : getBehaviours$1;
  17567. return {
  17568. uid: spec.uid,
  17569. dom: spec.dom,
  17570. components: spec.components,
  17571. behaviours: derive$1(getBehaviours$2(editor, spec.sharedBackstage))
  17572. };
  17573. };
  17574. const groupToolbarButtonSchema = objOf([
  17575. type,
  17576. requiredOf('items', oneOf([
  17577. arrOfObj([
  17578. name$1,
  17579. requiredArrayOf('items', string)
  17580. ]),
  17581. string
  17582. ]))
  17583. ].concat(baseToolbarButtonFields));
  17584. const createGroupToolbarButton = spec => asRaw('GroupToolbarButton', groupToolbarButtonSchema, spec);
  17585. const baseMenuButtonFields = [
  17586. optionString('text'),
  17587. optionString('tooltip'),
  17588. optionString('icon'),
  17589. defaultedOf('search', false, oneOf([
  17590. boolean,
  17591. objOf([optionString('placeholder')])
  17592. ], x => {
  17593. if (isBoolean(x)) {
  17594. return x ? Optional.some({ placeholder: Optional.none() }) : Optional.none();
  17595. } else {
  17596. return Optional.some(x);
  17597. }
  17598. })),
  17599. requiredFunction('fetch'),
  17600. defaultedFunction('onSetup', () => noop)
  17601. ];
  17602. const MenuButtonSchema = objOf([
  17603. type,
  17604. ...baseMenuButtonFields
  17605. ]);
  17606. const createMenuButton = spec => asRaw('menubutton', MenuButtonSchema, spec);
  17607. const splitButtonSchema = objOf([
  17608. type,
  17609. optionalTooltip,
  17610. optionalIcon,
  17611. optionalText,
  17612. optionalSelect,
  17613. fetch$1,
  17614. onSetup,
  17615. defaultedStringEnum('presets', 'normal', [
  17616. 'normal',
  17617. 'color',
  17618. 'listpreview'
  17619. ]),
  17620. defaultedColumns(1),
  17621. onAction,
  17622. onItemAction
  17623. ]);
  17624. const createSplitButton = spec => asRaw('SplitButton', splitButtonSchema, spec);
  17625. const factory$d = (detail, spec) => {
  17626. const setMenus = (comp, menus) => {
  17627. const newMenus = map$2(menus, m => {
  17628. const buttonSpec = {
  17629. type: 'menubutton',
  17630. text: m.text,
  17631. fetch: callback => {
  17632. callback(m.getItems());
  17633. }
  17634. };
  17635. const internal = createMenuButton(buttonSpec).mapError(errInfo => formatError(errInfo)).getOrDie();
  17636. return renderMenuButton(internal, 'tox-mbtn', spec.backstage, Optional.some('menuitem'));
  17637. });
  17638. Replacing.set(comp, newMenus);
  17639. };
  17640. const apis = {
  17641. focus: Keying.focusIn,
  17642. setMenus
  17643. };
  17644. return {
  17645. uid: detail.uid,
  17646. dom: detail.dom,
  17647. components: [],
  17648. behaviours: derive$1([
  17649. Replacing.config({}),
  17650. config('menubar-events', [
  17651. runOnAttached(component => {
  17652. detail.onSetup(component);
  17653. }),
  17654. run$1(mouseover(), (comp, se) => {
  17655. descendant(comp.element, '.' + 'tox-mbtn--active').each(activeButton => {
  17656. closest$1(se.event.target, '.' + 'tox-mbtn').each(hoveredButton => {
  17657. if (!eq(activeButton, hoveredButton)) {
  17658. comp.getSystem().getByDom(activeButton).each(activeComp => {
  17659. comp.getSystem().getByDom(hoveredButton).each(hoveredComp => {
  17660. Dropdown.expand(hoveredComp);
  17661. Dropdown.close(activeComp);
  17662. Focusing.focus(hoveredComp);
  17663. });
  17664. });
  17665. }
  17666. });
  17667. });
  17668. }),
  17669. run$1(focusShifted(), (comp, se) => {
  17670. se.event.prevFocus.bind(prev => comp.getSystem().getByDom(prev).toOptional()).each(prev => {
  17671. se.event.newFocus.bind(nu => comp.getSystem().getByDom(nu).toOptional()).each(nu => {
  17672. if (Dropdown.isOpen(prev)) {
  17673. Dropdown.expand(nu);
  17674. Dropdown.close(prev);
  17675. }
  17676. });
  17677. });
  17678. })
  17679. ]),
  17680. Keying.config({
  17681. mode: 'flow',
  17682. selector: '.' + 'tox-mbtn',
  17683. onEscape: comp => {
  17684. detail.onEscape(comp);
  17685. return Optional.some(true);
  17686. }
  17687. }),
  17688. Tabstopping.config({})
  17689. ]),
  17690. apis,
  17691. domModification: { attributes: { role: 'menubar' } }
  17692. };
  17693. };
  17694. var SilverMenubar = single({
  17695. factory: factory$d,
  17696. name: 'silver.Menubar',
  17697. configFields: [
  17698. required$1('dom'),
  17699. required$1('uid'),
  17700. required$1('onEscape'),
  17701. required$1('backstage'),
  17702. defaulted('onSetup', noop)
  17703. ],
  17704. apis: {
  17705. focus: (apis, comp) => {
  17706. apis.focus(comp);
  17707. },
  17708. setMenus: (apis, comp, menus) => {
  17709. apis.setMenus(comp, menus);
  17710. }
  17711. }
  17712. });
  17713. const promotionMessage = '\u26A1\ufe0fUpgrade';
  17714. const promotionLink = 'https://www.tiny.cloud/tinymce-self-hosted-premium-features/?utm_source=TinyMCE&utm_medium=SPAP&utm_campaign=SPAP&utm_id=editorreferral';
  17715. const renderPromotion = spec => {
  17716. return {
  17717. uid: spec.uid,
  17718. dom: spec.dom,
  17719. components: [{
  17720. dom: {
  17721. tag: 'a',
  17722. attributes: {
  17723. 'href': promotionLink,
  17724. 'rel': 'noopener',
  17725. 'target': '_blank',
  17726. 'aria-hidden': 'true'
  17727. },
  17728. classes: ['tox-promotion-link'],
  17729. innerHtml: promotionMessage
  17730. }
  17731. }]
  17732. };
  17733. };
  17734. const getAnimationRoot = (component, slideConfig) => slideConfig.getAnimationRoot.fold(() => component.element, get => get(component));
  17735. const getDimensionProperty = slideConfig => slideConfig.dimension.property;
  17736. const getDimension = (slideConfig, elem) => slideConfig.dimension.getDimension(elem);
  17737. const disableTransitions = (component, slideConfig) => {
  17738. const root = getAnimationRoot(component, slideConfig);
  17739. remove$1(root, [
  17740. slideConfig.shrinkingClass,
  17741. slideConfig.growingClass
  17742. ]);
  17743. };
  17744. const setShrunk = (component, slideConfig) => {
  17745. remove$2(component.element, slideConfig.openClass);
  17746. add$2(component.element, slideConfig.closedClass);
  17747. set$8(component.element, getDimensionProperty(slideConfig), '0px');
  17748. reflow(component.element);
  17749. };
  17750. const setGrown = (component, slideConfig) => {
  17751. remove$2(component.element, slideConfig.closedClass);
  17752. add$2(component.element, slideConfig.openClass);
  17753. remove$6(component.element, getDimensionProperty(slideConfig));
  17754. };
  17755. const doImmediateShrink = (component, slideConfig, slideState, _calculatedSize) => {
  17756. slideState.setCollapsed();
  17757. set$8(component.element, getDimensionProperty(slideConfig), getDimension(slideConfig, component.element));
  17758. disableTransitions(component, slideConfig);
  17759. setShrunk(component, slideConfig);
  17760. slideConfig.onStartShrink(component);
  17761. slideConfig.onShrunk(component);
  17762. };
  17763. const doStartShrink = (component, slideConfig, slideState, calculatedSize) => {
  17764. const size = calculatedSize.getOrThunk(() => getDimension(slideConfig, component.element));
  17765. slideState.setCollapsed();
  17766. set$8(component.element, getDimensionProperty(slideConfig), size);
  17767. reflow(component.element);
  17768. const root = getAnimationRoot(component, slideConfig);
  17769. remove$2(root, slideConfig.growingClass);
  17770. add$2(root, slideConfig.shrinkingClass);
  17771. setShrunk(component, slideConfig);
  17772. slideConfig.onStartShrink(component);
  17773. };
  17774. const doStartSmartShrink = (component, slideConfig, slideState) => {
  17775. const size = getDimension(slideConfig, component.element);
  17776. const shrinker = size === '0px' ? doImmediateShrink : doStartShrink;
  17777. shrinker(component, slideConfig, slideState, Optional.some(size));
  17778. };
  17779. const doStartGrow = (component, slideConfig, slideState) => {
  17780. const root = getAnimationRoot(component, slideConfig);
  17781. const wasShrinking = has(root, slideConfig.shrinkingClass);
  17782. const beforeSize = getDimension(slideConfig, component.element);
  17783. setGrown(component, slideConfig);
  17784. const fullSize = getDimension(slideConfig, component.element);
  17785. const startPartialGrow = () => {
  17786. set$8(component.element, getDimensionProperty(slideConfig), beforeSize);
  17787. reflow(component.element);
  17788. };
  17789. const startCompleteGrow = () => {
  17790. setShrunk(component, slideConfig);
  17791. };
  17792. const setStartSize = wasShrinking ? startPartialGrow : startCompleteGrow;
  17793. setStartSize();
  17794. remove$2(root, slideConfig.shrinkingClass);
  17795. add$2(root, slideConfig.growingClass);
  17796. setGrown(component, slideConfig);
  17797. set$8(component.element, getDimensionProperty(slideConfig), fullSize);
  17798. slideState.setExpanded();
  17799. slideConfig.onStartGrow(component);
  17800. };
  17801. const refresh$3 = (component, slideConfig, slideState) => {
  17802. if (slideState.isExpanded()) {
  17803. remove$6(component.element, getDimensionProperty(slideConfig));
  17804. const fullSize = getDimension(slideConfig, component.element);
  17805. set$8(component.element, getDimensionProperty(slideConfig), fullSize);
  17806. }
  17807. };
  17808. const grow = (component, slideConfig, slideState) => {
  17809. if (!slideState.isExpanded()) {
  17810. doStartGrow(component, slideConfig, slideState);
  17811. }
  17812. };
  17813. const shrink = (component, slideConfig, slideState) => {
  17814. if (slideState.isExpanded()) {
  17815. doStartSmartShrink(component, slideConfig, slideState);
  17816. }
  17817. };
  17818. const immediateShrink = (component, slideConfig, slideState) => {
  17819. if (slideState.isExpanded()) {
  17820. doImmediateShrink(component, slideConfig, slideState);
  17821. }
  17822. };
  17823. const hasGrown = (component, slideConfig, slideState) => slideState.isExpanded();
  17824. const hasShrunk = (component, slideConfig, slideState) => slideState.isCollapsed();
  17825. const isGrowing = (component, slideConfig, _slideState) => {
  17826. const root = getAnimationRoot(component, slideConfig);
  17827. return has(root, slideConfig.growingClass) === true;
  17828. };
  17829. const isShrinking = (component, slideConfig, _slideState) => {
  17830. const root = getAnimationRoot(component, slideConfig);
  17831. return has(root, slideConfig.shrinkingClass) === true;
  17832. };
  17833. const isTransitioning = (component, slideConfig, slideState) => isGrowing(component, slideConfig) || isShrinking(component, slideConfig);
  17834. const toggleGrow = (component, slideConfig, slideState) => {
  17835. const f = slideState.isExpanded() ? doStartSmartShrink : doStartGrow;
  17836. f(component, slideConfig, slideState);
  17837. };
  17838. const immediateGrow = (component, slideConfig, slideState) => {
  17839. if (!slideState.isExpanded()) {
  17840. setGrown(component, slideConfig);
  17841. set$8(component.element, getDimensionProperty(slideConfig), getDimension(slideConfig, component.element));
  17842. disableTransitions(component, slideConfig);
  17843. slideState.setExpanded();
  17844. slideConfig.onStartGrow(component);
  17845. slideConfig.onGrown(component);
  17846. }
  17847. };
  17848. var SlidingApis = /*#__PURE__*/Object.freeze({
  17849. __proto__: null,
  17850. refresh: refresh$3,
  17851. grow: grow,
  17852. shrink: shrink,
  17853. immediateShrink: immediateShrink,
  17854. hasGrown: hasGrown,
  17855. hasShrunk: hasShrunk,
  17856. isGrowing: isGrowing,
  17857. isShrinking: isShrinking,
  17858. isTransitioning: isTransitioning,
  17859. toggleGrow: toggleGrow,
  17860. disableTransitions: disableTransitions,
  17861. immediateGrow: immediateGrow
  17862. });
  17863. const exhibit = (base, slideConfig, _slideState) => {
  17864. const expanded = slideConfig.expanded;
  17865. return expanded ? nu$7({
  17866. classes: [slideConfig.openClass],
  17867. styles: {}
  17868. }) : nu$7({
  17869. classes: [slideConfig.closedClass],
  17870. styles: wrap$1(slideConfig.dimension.property, '0px')
  17871. });
  17872. };
  17873. const events$4 = (slideConfig, slideState) => derive$2([runOnSource(transitionend(), (component, simulatedEvent) => {
  17874. const raw = simulatedEvent.event.raw;
  17875. if (raw.propertyName === slideConfig.dimension.property) {
  17876. disableTransitions(component, slideConfig);
  17877. if (slideState.isExpanded()) {
  17878. remove$6(component.element, slideConfig.dimension.property);
  17879. }
  17880. const notify = slideState.isExpanded() ? slideConfig.onGrown : slideConfig.onShrunk;
  17881. notify(component);
  17882. }
  17883. })]);
  17884. var ActiveSliding = /*#__PURE__*/Object.freeze({
  17885. __proto__: null,
  17886. exhibit: exhibit,
  17887. events: events$4
  17888. });
  17889. var SlidingSchema = [
  17890. required$1('closedClass'),
  17891. required$1('openClass'),
  17892. required$1('shrinkingClass'),
  17893. required$1('growingClass'),
  17894. option$3('getAnimationRoot'),
  17895. onHandler('onShrunk'),
  17896. onHandler('onStartShrink'),
  17897. onHandler('onGrown'),
  17898. onHandler('onStartGrow'),
  17899. defaulted('expanded', false),
  17900. requiredOf('dimension', choose$1('property', {
  17901. width: [
  17902. output$1('property', 'width'),
  17903. output$1('getDimension', elem => get$c(elem) + 'px')
  17904. ],
  17905. height: [
  17906. output$1('property', 'height'),
  17907. output$1('getDimension', elem => get$d(elem) + 'px')
  17908. ]
  17909. }))
  17910. ];
  17911. const init$5 = spec => {
  17912. const state = Cell(spec.expanded);
  17913. const readState = () => 'expanded: ' + state.get();
  17914. return nu$8({
  17915. isExpanded: () => state.get() === true,
  17916. isCollapsed: () => state.get() === false,
  17917. setCollapsed: curry(state.set, false),
  17918. setExpanded: curry(state.set, true),
  17919. readState
  17920. });
  17921. };
  17922. var SlidingState = /*#__PURE__*/Object.freeze({
  17923. __proto__: null,
  17924. init: init$5
  17925. });
  17926. const Sliding = create$4({
  17927. fields: SlidingSchema,
  17928. name: 'sliding',
  17929. active: ActiveSliding,
  17930. apis: SlidingApis,
  17931. state: SlidingState
  17932. });
  17933. const owner = 'container';
  17934. const schema$d = [field('slotBehaviours', [])];
  17935. const getPartName = name => '<alloy.field.' + name + '>';
  17936. const sketch = sSpec => {
  17937. const parts = (() => {
  17938. const record = [];
  17939. const slot = (name, config) => {
  17940. record.push(name);
  17941. return generateOne$1(owner, getPartName(name), config);
  17942. };
  17943. return {
  17944. slot,
  17945. record: constant$1(record)
  17946. };
  17947. })();
  17948. const spec = sSpec(parts);
  17949. const partNames = parts.record();
  17950. const fieldParts = map$2(partNames, n => required({
  17951. name: n,
  17952. pname: getPartName(n)
  17953. }));
  17954. return composite$1(owner, schema$d, fieldParts, make$1, spec);
  17955. };
  17956. const make$1 = (detail, components) => {
  17957. const getSlotNames = _ => getAllPartNames(detail);
  17958. const getSlot = (container, key) => getPart(container, detail, key);
  17959. const onSlot = (f, def) => (container, key) => getPart(container, detail, key).map(slot => f(slot, key)).getOr(def);
  17960. const onSlots = f => (container, keys) => {
  17961. each$1(keys, key => f(container, key));
  17962. };
  17963. const doShowing = (comp, _key) => get$f(comp.element, 'aria-hidden') !== 'true';
  17964. const doShow = (comp, key) => {
  17965. if (!doShowing(comp)) {
  17966. const element = comp.element;
  17967. remove$6(element, 'display');
  17968. remove$7(element, 'aria-hidden');
  17969. emitWith(comp, slotVisibility(), {
  17970. name: key,
  17971. visible: true
  17972. });
  17973. }
  17974. };
  17975. const doHide = (comp, key) => {
  17976. if (doShowing(comp)) {
  17977. const element = comp.element;
  17978. set$8(element, 'display', 'none');
  17979. set$9(element, 'aria-hidden', 'true');
  17980. emitWith(comp, slotVisibility(), {
  17981. name: key,
  17982. visible: false
  17983. });
  17984. }
  17985. };
  17986. const isShowing = onSlot(doShowing, false);
  17987. const hideSlot = onSlot(doHide);
  17988. const hideSlots = onSlots(hideSlot);
  17989. const hideAllSlots = container => hideSlots(container, getSlotNames());
  17990. const showSlot = onSlot(doShow);
  17991. const apis = {
  17992. getSlotNames,
  17993. getSlot,
  17994. isShowing,
  17995. hideSlot,
  17996. hideAllSlots,
  17997. showSlot
  17998. };
  17999. return {
  18000. uid: detail.uid,
  18001. dom: detail.dom,
  18002. components,
  18003. behaviours: get$3(detail.slotBehaviours),
  18004. apis
  18005. };
  18006. };
  18007. const slotApis = map$1({
  18008. getSlotNames: (apis, c) => apis.getSlotNames(c),
  18009. getSlot: (apis, c, key) => apis.getSlot(c, key),
  18010. isShowing: (apis, c, key) => apis.isShowing(c, key),
  18011. hideSlot: (apis, c, key) => apis.hideSlot(c, key),
  18012. hideAllSlots: (apis, c) => apis.hideAllSlots(c),
  18013. showSlot: (apis, c, key) => apis.showSlot(c, key)
  18014. }, value => makeApi(value));
  18015. const SlotContainer = {
  18016. ...slotApis,
  18017. ...{ sketch }
  18018. };
  18019. const sidebarSchema = objOf([
  18020. optionalIcon,
  18021. optionalTooltip,
  18022. defaultedFunction('onShow', noop),
  18023. defaultedFunction('onHide', noop),
  18024. onSetup
  18025. ]);
  18026. const createSidebar = spec => asRaw('sidebar', sidebarSchema, spec);
  18027. const setup$8 = editor => {
  18028. const {sidebars} = editor.ui.registry.getAll();
  18029. each$1(keys(sidebars), name => {
  18030. const spec = sidebars[name];
  18031. const isActive = () => is$1(Optional.from(editor.queryCommandValue('ToggleSidebar')), name);
  18032. editor.ui.registry.addToggleButton(name, {
  18033. icon: spec.icon,
  18034. tooltip: spec.tooltip,
  18035. onAction: buttonApi => {
  18036. editor.execCommand('ToggleSidebar', false, name);
  18037. buttonApi.setActive(isActive());
  18038. },
  18039. onSetup: buttonApi => {
  18040. buttonApi.setActive(isActive());
  18041. const handleToggle = () => buttonApi.setActive(isActive());
  18042. editor.on('ToggleSidebar', handleToggle);
  18043. return () => {
  18044. editor.off('ToggleSidebar', handleToggle);
  18045. };
  18046. }
  18047. });
  18048. });
  18049. };
  18050. const getApi = comp => ({ element: () => comp.element.dom });
  18051. const makePanels = (parts, panelConfigs) => {
  18052. const specs = map$2(keys(panelConfigs), name => {
  18053. const spec = panelConfigs[name];
  18054. const bridged = getOrDie(createSidebar(spec));
  18055. return {
  18056. name,
  18057. getApi,
  18058. onSetup: bridged.onSetup,
  18059. onShow: bridged.onShow,
  18060. onHide: bridged.onHide
  18061. };
  18062. });
  18063. return map$2(specs, spec => {
  18064. const editorOffCell = Cell(noop);
  18065. return parts.slot(spec.name, {
  18066. dom: {
  18067. tag: 'div',
  18068. classes: ['tox-sidebar__pane']
  18069. },
  18070. behaviours: SimpleBehaviours.unnamedEvents([
  18071. onControlAttached(spec, editorOffCell),
  18072. onControlDetached(spec, editorOffCell),
  18073. run$1(slotVisibility(), (sidepanel, se) => {
  18074. const data = se.event;
  18075. const optSidePanelSpec = find$5(specs, config => config.name === data.name);
  18076. optSidePanelSpec.each(sidePanelSpec => {
  18077. const handler = data.visible ? sidePanelSpec.onShow : sidePanelSpec.onHide;
  18078. handler(sidePanelSpec.getApi(sidepanel));
  18079. });
  18080. })
  18081. ])
  18082. });
  18083. });
  18084. };
  18085. const makeSidebar = panelConfigs => SlotContainer.sketch(parts => ({
  18086. dom: {
  18087. tag: 'div',
  18088. classes: ['tox-sidebar__pane-container']
  18089. },
  18090. components: makePanels(parts, panelConfigs),
  18091. slotBehaviours: SimpleBehaviours.unnamedEvents([runOnAttached(slotContainer => SlotContainer.hideAllSlots(slotContainer))])
  18092. }));
  18093. const setSidebar = (sidebar, panelConfigs, showSidebar) => {
  18094. const optSlider = Composing.getCurrent(sidebar);
  18095. optSlider.each(slider => {
  18096. Replacing.set(slider, [makeSidebar(panelConfigs)]);
  18097. const configKey = showSidebar === null || showSidebar === void 0 ? void 0 : showSidebar.toLowerCase();
  18098. if (isString(configKey) && has$2(panelConfigs, configKey)) {
  18099. Composing.getCurrent(slider).each(slotContainer => {
  18100. SlotContainer.showSlot(slotContainer, configKey);
  18101. Sliding.immediateGrow(slider);
  18102. remove$6(slider.element, 'width');
  18103. });
  18104. }
  18105. });
  18106. };
  18107. const toggleSidebar = (sidebar, name) => {
  18108. const optSlider = Composing.getCurrent(sidebar);
  18109. optSlider.each(slider => {
  18110. const optSlotContainer = Composing.getCurrent(slider);
  18111. optSlotContainer.each(slotContainer => {
  18112. if (Sliding.hasGrown(slider)) {
  18113. if (SlotContainer.isShowing(slotContainer, name)) {
  18114. Sliding.shrink(slider);
  18115. } else {
  18116. SlotContainer.hideAllSlots(slotContainer);
  18117. SlotContainer.showSlot(slotContainer, name);
  18118. }
  18119. } else {
  18120. SlotContainer.hideAllSlots(slotContainer);
  18121. SlotContainer.showSlot(slotContainer, name);
  18122. Sliding.grow(slider);
  18123. }
  18124. });
  18125. });
  18126. };
  18127. const whichSidebar = sidebar => {
  18128. const optSlider = Composing.getCurrent(sidebar);
  18129. return optSlider.bind(slider => {
  18130. const sidebarOpen = Sliding.isGrowing(slider) || Sliding.hasGrown(slider);
  18131. if (sidebarOpen) {
  18132. const optSlotContainer = Composing.getCurrent(slider);
  18133. return optSlotContainer.bind(slotContainer => find$5(SlotContainer.getSlotNames(slotContainer), name => SlotContainer.isShowing(slotContainer, name)));
  18134. } else {
  18135. return Optional.none();
  18136. }
  18137. });
  18138. };
  18139. const fixSize = generate$6('FixSizeEvent');
  18140. const autoSize = generate$6('AutoSizeEvent');
  18141. const renderSidebar = spec => ({
  18142. uid: spec.uid,
  18143. dom: {
  18144. tag: 'div',
  18145. classes: ['tox-sidebar'],
  18146. attributes: { role: 'complementary' }
  18147. },
  18148. components: [{
  18149. dom: {
  18150. tag: 'div',
  18151. classes: ['tox-sidebar__slider']
  18152. },
  18153. components: [],
  18154. behaviours: derive$1([
  18155. Tabstopping.config({}),
  18156. Focusing.config({}),
  18157. Sliding.config({
  18158. dimension: { property: 'width' },
  18159. closedClass: 'tox-sidebar--sliding-closed',
  18160. openClass: 'tox-sidebar--sliding-open',
  18161. shrinkingClass: 'tox-sidebar--sliding-shrinking',
  18162. growingClass: 'tox-sidebar--sliding-growing',
  18163. onShrunk: slider => {
  18164. const optSlotContainer = Composing.getCurrent(slider);
  18165. optSlotContainer.each(SlotContainer.hideAllSlots);
  18166. emit(slider, autoSize);
  18167. },
  18168. onGrown: slider => {
  18169. emit(slider, autoSize);
  18170. },
  18171. onStartGrow: slider => {
  18172. emitWith(slider, fixSize, { width: getRaw(slider.element, 'width').getOr('') });
  18173. },
  18174. onStartShrink: slider => {
  18175. emitWith(slider, fixSize, { width: get$c(slider.element) + 'px' });
  18176. }
  18177. }),
  18178. Replacing.config({}),
  18179. Composing.config({
  18180. find: comp => {
  18181. const children = Replacing.contents(comp);
  18182. return head(children);
  18183. }
  18184. })
  18185. ])
  18186. }],
  18187. behaviours: derive$1([
  18188. ComposingConfigs.childAt(0),
  18189. config('sidebar-sliding-events', [
  18190. run$1(fixSize, (comp, se) => {
  18191. set$8(comp.element, 'width', se.event.width);
  18192. }),
  18193. run$1(autoSize, (comp, _se) => {
  18194. remove$6(comp.element, 'width');
  18195. })
  18196. ])
  18197. ])
  18198. });
  18199. const block = (component, config, state, getBusySpec) => {
  18200. set$9(component.element, 'aria-busy', true);
  18201. const root = config.getRoot(component).getOr(component);
  18202. const blockerBehaviours = derive$1([
  18203. Keying.config({
  18204. mode: 'special',
  18205. onTab: () => Optional.some(true),
  18206. onShiftTab: () => Optional.some(true)
  18207. }),
  18208. Focusing.config({})
  18209. ]);
  18210. const blockSpec = getBusySpec(root, blockerBehaviours);
  18211. const blocker = root.getSystem().build(blockSpec);
  18212. Replacing.append(root, premade(blocker));
  18213. if (blocker.hasConfigured(Keying) && config.focus) {
  18214. Keying.focusIn(blocker);
  18215. }
  18216. if (!state.isBlocked()) {
  18217. config.onBlock(component);
  18218. }
  18219. state.blockWith(() => Replacing.remove(root, blocker));
  18220. };
  18221. const unblock = (component, config, state) => {
  18222. remove$7(component.element, 'aria-busy');
  18223. if (state.isBlocked()) {
  18224. config.onUnblock(component);
  18225. }
  18226. state.clear();
  18227. };
  18228. var BlockingApis = /*#__PURE__*/Object.freeze({
  18229. __proto__: null,
  18230. block: block,
  18231. unblock: unblock
  18232. });
  18233. var BlockingSchema = [
  18234. defaultedFunction('getRoot', Optional.none),
  18235. defaultedBoolean('focus', true),
  18236. onHandler('onBlock'),
  18237. onHandler('onUnblock')
  18238. ];
  18239. const init$4 = () => {
  18240. const blocker = destroyable();
  18241. const blockWith = destroy => {
  18242. blocker.set({ destroy });
  18243. };
  18244. return nu$8({
  18245. readState: blocker.isSet,
  18246. blockWith,
  18247. clear: blocker.clear,
  18248. isBlocked: blocker.isSet
  18249. });
  18250. };
  18251. var BlockingState = /*#__PURE__*/Object.freeze({
  18252. __proto__: null,
  18253. init: init$4
  18254. });
  18255. const Blocking = create$4({
  18256. fields: BlockingSchema,
  18257. name: 'blocking',
  18258. apis: BlockingApis,
  18259. state: BlockingState
  18260. });
  18261. const getAttrs = elem => {
  18262. const attributes = elem.dom.attributes !== undefined ? elem.dom.attributes : [];
  18263. return foldl(attributes, (b, attr) => {
  18264. if (attr.name === 'class') {
  18265. return b;
  18266. } else {
  18267. return {
  18268. ...b,
  18269. [attr.name]: attr.value
  18270. };
  18271. }
  18272. }, {});
  18273. };
  18274. const getClasses = elem => Array.prototype.slice.call(elem.dom.classList, 0);
  18275. const fromHtml = html => {
  18276. const elem = SugarElement.fromHtml(html);
  18277. const children$1 = children(elem);
  18278. const attrs = getAttrs(elem);
  18279. const classes = getClasses(elem);
  18280. const contents = children$1.length === 0 ? {} : { innerHtml: get$9(elem) };
  18281. return {
  18282. tag: name$3(elem),
  18283. classes,
  18284. attributes: attrs,
  18285. ...contents
  18286. };
  18287. };
  18288. const getBusySpec$1 = providerBackstage => (_root, _behaviours) => ({
  18289. dom: {
  18290. tag: 'div',
  18291. attributes: {
  18292. 'aria-label': providerBackstage.translate('Loading...'),
  18293. 'tabindex': '0'
  18294. },
  18295. classes: ['tox-throbber__busy-spinner']
  18296. },
  18297. components: [{ dom: fromHtml('<div class="tox-spinner"><div></div><div></div><div></div></div>') }]
  18298. });
  18299. const focusBusyComponent = throbber => Composing.getCurrent(throbber).each(comp => focus$3(comp.element));
  18300. const toggleEditorTabIndex = (editor, state) => {
  18301. const tabIndexAttr = 'tabindex';
  18302. const dataTabIndexAttr = `data-mce-${ tabIndexAttr }`;
  18303. Optional.from(editor.iframeElement).map(SugarElement.fromDom).each(iframe => {
  18304. if (state) {
  18305. getOpt(iframe, tabIndexAttr).each(tabIndex => set$9(iframe, dataTabIndexAttr, tabIndex));
  18306. set$9(iframe, tabIndexAttr, -1);
  18307. } else {
  18308. remove$7(iframe, tabIndexAttr);
  18309. getOpt(iframe, dataTabIndexAttr).each(tabIndex => {
  18310. set$9(iframe, tabIndexAttr, tabIndex);
  18311. remove$7(iframe, dataTabIndexAttr);
  18312. });
  18313. }
  18314. });
  18315. };
  18316. const toggleThrobber = (editor, comp, state, providerBackstage) => {
  18317. const element = comp.element;
  18318. toggleEditorTabIndex(editor, state);
  18319. if (state) {
  18320. Blocking.block(comp, getBusySpec$1(providerBackstage));
  18321. remove$6(element, 'display');
  18322. remove$7(element, 'aria-hidden');
  18323. if (editor.hasFocus()) {
  18324. focusBusyComponent(comp);
  18325. }
  18326. } else {
  18327. const throbberFocus = Composing.getCurrent(comp).exists(busyComp => hasFocus(busyComp.element));
  18328. Blocking.unblock(comp);
  18329. set$8(element, 'display', 'none');
  18330. set$9(element, 'aria-hidden', 'true');
  18331. if (throbberFocus) {
  18332. editor.focus();
  18333. }
  18334. }
  18335. };
  18336. const renderThrobber = spec => ({
  18337. uid: spec.uid,
  18338. dom: {
  18339. tag: 'div',
  18340. attributes: { 'aria-hidden': 'true' },
  18341. classes: ['tox-throbber'],
  18342. styles: { display: 'none' }
  18343. },
  18344. behaviours: derive$1([
  18345. Replacing.config({}),
  18346. Blocking.config({ focus: false }),
  18347. Composing.config({ find: comp => head(comp.components()) })
  18348. ]),
  18349. components: []
  18350. });
  18351. const isFocusEvent = event => event.type === 'focusin';
  18352. const isPasteBinTarget = event => {
  18353. if (isFocusEvent(event)) {
  18354. const node = event.composed ? head(event.composedPath()) : Optional.from(event.target);
  18355. return node.map(SugarElement.fromDom).filter(isElement$1).exists(targetElm => has(targetElm, 'mce-pastebin'));
  18356. } else {
  18357. return false;
  18358. }
  18359. };
  18360. const setup$7 = (editor, lazyThrobber, sharedBackstage) => {
  18361. const throbberState = Cell(false);
  18362. const timer = value$2();
  18363. const stealFocus = e => {
  18364. if (throbberState.get() && !isPasteBinTarget(e)) {
  18365. e.preventDefault();
  18366. focusBusyComponent(lazyThrobber());
  18367. editor.editorManager.setActive(editor);
  18368. }
  18369. };
  18370. if (!editor.inline) {
  18371. editor.on('PreInit', () => {
  18372. editor.dom.bind(editor.getWin(), 'focusin', stealFocus);
  18373. editor.on('BeforeExecCommand', e => {
  18374. if (e.command.toLowerCase() === 'mcefocus' && e.value !== true) {
  18375. stealFocus(e);
  18376. }
  18377. });
  18378. });
  18379. }
  18380. const toggle = state => {
  18381. if (state !== throbberState.get()) {
  18382. throbberState.set(state);
  18383. toggleThrobber(editor, lazyThrobber(), state, sharedBackstage.providers);
  18384. fireAfterProgressState(editor, state);
  18385. }
  18386. };
  18387. editor.on('ProgressState', e => {
  18388. timer.on(clearTimeout);
  18389. if (isNumber(e.time)) {
  18390. const timerId = global$9.setEditorTimeout(editor, () => toggle(e.state), e.time);
  18391. timer.set(timerId);
  18392. } else {
  18393. toggle(e.state);
  18394. timer.clear();
  18395. }
  18396. });
  18397. };
  18398. const generate$1 = (xs, f) => {
  18399. const init = {
  18400. len: 0,
  18401. list: []
  18402. };
  18403. const r = foldl(xs, (b, a) => {
  18404. const value = f(a, b.len);
  18405. return value.fold(constant$1(b), v => ({
  18406. len: v.finish,
  18407. list: b.list.concat([v])
  18408. }));
  18409. }, init);
  18410. return r.list;
  18411. };
  18412. const output = (within, extra, withinWidth) => ({
  18413. within,
  18414. extra,
  18415. withinWidth
  18416. });
  18417. const apportion = (units, total, len) => {
  18418. const parray = generate$1(units, (unit, current) => {
  18419. const width = len(unit);
  18420. return Optional.some({
  18421. element: unit,
  18422. start: current,
  18423. finish: current + width,
  18424. width
  18425. });
  18426. });
  18427. const within = filter$2(parray, unit => unit.finish <= total);
  18428. const withinWidth = foldr(within, (acc, el) => acc + el.width, 0);
  18429. const extra = parray.slice(within.length);
  18430. return {
  18431. within,
  18432. extra,
  18433. withinWidth
  18434. };
  18435. };
  18436. const toUnit = parray => map$2(parray, unit => unit.element);
  18437. const fitLast = (within, extra, withinWidth) => {
  18438. const fits = toUnit(within.concat(extra));
  18439. return output(fits, [], withinWidth);
  18440. };
  18441. const overflow = (within, extra, overflower, withinWidth) => {
  18442. const fits = toUnit(within).concat([overflower]);
  18443. return output(fits, toUnit(extra), withinWidth);
  18444. };
  18445. const fitAll = (within, extra, withinWidth) => output(toUnit(within), [], withinWidth);
  18446. const tryFit = (total, units, len) => {
  18447. const divide = apportion(units, total, len);
  18448. return divide.extra.length === 0 ? Optional.some(divide) : Optional.none();
  18449. };
  18450. const partition = (total, units, len, overflower) => {
  18451. const divide = tryFit(total, units, len).getOrThunk(() => apportion(units, total - len(overflower), len));
  18452. const within = divide.within;
  18453. const extra = divide.extra;
  18454. const withinWidth = divide.withinWidth;
  18455. if (extra.length === 1 && extra[0].width <= len(overflower)) {
  18456. return fitLast(within, extra, withinWidth);
  18457. } else if (extra.length >= 1) {
  18458. return overflow(within, extra, overflower, withinWidth);
  18459. } else {
  18460. return fitAll(within, extra, withinWidth);
  18461. }
  18462. };
  18463. const setGroups$1 = (toolbar, storedGroups) => {
  18464. const bGroups = map$2(storedGroups, g => premade(g));
  18465. Toolbar.setGroups(toolbar, bGroups);
  18466. };
  18467. const findFocusedComp = comps => findMap(comps, comp => search(comp.element).bind(focusedElm => comp.getSystem().getByDom(focusedElm).toOptional()));
  18468. const refresh$2 = (toolbar, detail, setOverflow) => {
  18469. const builtGroups = detail.builtGroups.get();
  18470. if (builtGroups.length === 0) {
  18471. return;
  18472. }
  18473. const primary = getPartOrDie(toolbar, detail, 'primary');
  18474. const overflowGroup = Coupling.getCoupled(toolbar, 'overflowGroup');
  18475. set$8(primary.element, 'visibility', 'hidden');
  18476. const groups = builtGroups.concat([overflowGroup]);
  18477. const focusedComp = findFocusedComp(groups);
  18478. setOverflow([]);
  18479. setGroups$1(primary, groups);
  18480. const availableWidth = get$c(primary.element);
  18481. const overflows = partition(availableWidth, detail.builtGroups.get(), comp => get$c(comp.element), overflowGroup);
  18482. if (overflows.extra.length === 0) {
  18483. Replacing.remove(primary, overflowGroup);
  18484. setOverflow([]);
  18485. } else {
  18486. setGroups$1(primary, overflows.within);
  18487. setOverflow(overflows.extra);
  18488. }
  18489. remove$6(primary.element, 'visibility');
  18490. reflow(primary.element);
  18491. focusedComp.each(Focusing.focus);
  18492. };
  18493. const schema$c = constant$1([
  18494. field('splitToolbarBehaviours', [Coupling]),
  18495. customField('builtGroups', () => Cell([]))
  18496. ]);
  18497. const schema$b = constant$1([
  18498. markers$1(['overflowToggledClass']),
  18499. optionFunction('getOverflowBounds'),
  18500. required$1('lazySink'),
  18501. customField('overflowGroups', () => Cell([])),
  18502. onHandler('onOpened'),
  18503. onHandler('onClosed')
  18504. ].concat(schema$c()));
  18505. const parts$7 = constant$1([
  18506. required({
  18507. factory: Toolbar,
  18508. schema: schema$e(),
  18509. name: 'primary'
  18510. }),
  18511. external({
  18512. schema: schema$e(),
  18513. name: 'overflow'
  18514. }),
  18515. external({ name: 'overflow-button' }),
  18516. external({ name: 'overflow-group' })
  18517. ]);
  18518. const expandable = constant$1((element, available) => {
  18519. setMax(element, Math.floor(available));
  18520. });
  18521. const schema$a = constant$1([
  18522. markers$1(['toggledClass']),
  18523. required$1('lazySink'),
  18524. requiredFunction('fetch'),
  18525. optionFunction('getBounds'),
  18526. optionObjOf('fireDismissalEventInstead', [defaulted('event', dismissRequested())]),
  18527. schema$y(),
  18528. onHandler('onToggled')
  18529. ]);
  18530. const parts$6 = constant$1([
  18531. external({
  18532. name: 'button',
  18533. overrides: detail => ({
  18534. dom: { attributes: { 'aria-haspopup': 'true' } },
  18535. buttonBehaviours: derive$1([Toggling.config({
  18536. toggleClass: detail.markers.toggledClass,
  18537. aria: { mode: 'expanded' },
  18538. toggleOnExecute: false,
  18539. onToggled: detail.onToggled
  18540. })])
  18541. })
  18542. }),
  18543. external({
  18544. factory: Toolbar,
  18545. schema: schema$e(),
  18546. name: 'toolbar',
  18547. overrides: detail => {
  18548. return {
  18549. toolbarBehaviours: derive$1([Keying.config({
  18550. mode: 'cyclic',
  18551. onEscape: comp => {
  18552. getPart(comp, detail, 'button').each(Focusing.focus);
  18553. return Optional.none();
  18554. }
  18555. })])
  18556. };
  18557. }
  18558. })
  18559. ]);
  18560. const toggle = (button, externals) => {
  18561. const toolbarSandbox = Coupling.getCoupled(button, 'toolbarSandbox');
  18562. if (Sandboxing.isOpen(toolbarSandbox)) {
  18563. Sandboxing.close(toolbarSandbox);
  18564. } else {
  18565. Sandboxing.open(toolbarSandbox, externals.toolbar());
  18566. }
  18567. };
  18568. const position = (button, toolbar, detail, layouts) => {
  18569. const bounds = detail.getBounds.map(bounder => bounder());
  18570. const sink = detail.lazySink(button).getOrDie();
  18571. Positioning.positionWithinBounds(sink, toolbar, {
  18572. anchor: {
  18573. type: 'hotspot',
  18574. hotspot: button,
  18575. layouts,
  18576. overrides: { maxWidthFunction: expandable() }
  18577. }
  18578. }, bounds);
  18579. };
  18580. const setGroups = (button, toolbar, detail, layouts, groups) => {
  18581. Toolbar.setGroups(toolbar, groups);
  18582. position(button, toolbar, detail, layouts);
  18583. Toggling.on(button);
  18584. };
  18585. const makeSandbox = (button, spec, detail) => {
  18586. const ariaControls = manager();
  18587. const onOpen = (sandbox, toolbar) => {
  18588. detail.fetch().get(groups => {
  18589. setGroups(button, toolbar, detail, spec.layouts, groups);
  18590. ariaControls.link(button.element);
  18591. Keying.focusIn(toolbar);
  18592. });
  18593. };
  18594. const onClose = () => {
  18595. Toggling.off(button);
  18596. Focusing.focus(button);
  18597. ariaControls.unlink(button.element);
  18598. };
  18599. return {
  18600. dom: {
  18601. tag: 'div',
  18602. attributes: { id: ariaControls.id }
  18603. },
  18604. behaviours: derive$1([
  18605. Keying.config({
  18606. mode: 'special',
  18607. onEscape: comp => {
  18608. Sandboxing.close(comp);
  18609. return Optional.some(true);
  18610. }
  18611. }),
  18612. Sandboxing.config({
  18613. onOpen,
  18614. onClose,
  18615. isPartOf: (container, data, queryElem) => {
  18616. return isPartOf$1(data, queryElem) || isPartOf$1(button, queryElem);
  18617. },
  18618. getAttachPoint: () => {
  18619. return detail.lazySink(button).getOrDie();
  18620. }
  18621. }),
  18622. Receiving.config({
  18623. channels: {
  18624. ...receivingChannel$1({
  18625. isExtraPart: never,
  18626. ...detail.fireDismissalEventInstead.map(fe => ({ fireEventInstead: { event: fe.event } })).getOr({})
  18627. }),
  18628. ...receivingChannel({
  18629. doReposition: () => {
  18630. Sandboxing.getState(Coupling.getCoupled(button, 'toolbarSandbox')).each(toolbar => {
  18631. position(button, toolbar, detail, spec.layouts);
  18632. });
  18633. }
  18634. })
  18635. }
  18636. })
  18637. ])
  18638. };
  18639. };
  18640. const factory$c = (detail, components, spec, externals) => ({
  18641. ...Button.sketch({
  18642. ...externals.button(),
  18643. action: button => {
  18644. toggle(button, externals);
  18645. },
  18646. buttonBehaviours: SketchBehaviours.augment({ dump: externals.button().buttonBehaviours }, [Coupling.config({
  18647. others: {
  18648. toolbarSandbox: button => {
  18649. return makeSandbox(button, spec, detail);
  18650. }
  18651. }
  18652. })])
  18653. }),
  18654. apis: {
  18655. setGroups: (button, groups) => {
  18656. Sandboxing.getState(Coupling.getCoupled(button, 'toolbarSandbox')).each(toolbar => {
  18657. setGroups(button, toolbar, detail, spec.layouts, groups);
  18658. });
  18659. },
  18660. reposition: button => {
  18661. Sandboxing.getState(Coupling.getCoupled(button, 'toolbarSandbox')).each(toolbar => {
  18662. position(button, toolbar, detail, spec.layouts);
  18663. });
  18664. },
  18665. toggle: button => {
  18666. toggle(button, externals);
  18667. },
  18668. getToolbar: button => {
  18669. return Sandboxing.getState(Coupling.getCoupled(button, 'toolbarSandbox'));
  18670. },
  18671. isOpen: button => {
  18672. return Sandboxing.isOpen(Coupling.getCoupled(button, 'toolbarSandbox'));
  18673. }
  18674. }
  18675. });
  18676. const FloatingToolbarButton = composite({
  18677. name: 'FloatingToolbarButton',
  18678. factory: factory$c,
  18679. configFields: schema$a(),
  18680. partFields: parts$6(),
  18681. apis: {
  18682. setGroups: (apis, button, groups) => {
  18683. apis.setGroups(button, groups);
  18684. },
  18685. reposition: (apis, button) => {
  18686. apis.reposition(button);
  18687. },
  18688. toggle: (apis, button) => {
  18689. apis.toggle(button);
  18690. },
  18691. getToolbar: (apis, button) => apis.getToolbar(button),
  18692. isOpen: (apis, button) => apis.isOpen(button)
  18693. }
  18694. });
  18695. const schema$9 = constant$1([
  18696. required$1('items'),
  18697. markers$1(['itemSelector']),
  18698. field('tgroupBehaviours', [Keying])
  18699. ]);
  18700. const parts$5 = constant$1([group({
  18701. name: 'items',
  18702. unit: 'item'
  18703. })]);
  18704. const factory$b = (detail, components, _spec, _externals) => ({
  18705. uid: detail.uid,
  18706. dom: detail.dom,
  18707. components,
  18708. behaviours: augment(detail.tgroupBehaviours, [Keying.config({
  18709. mode: 'flow',
  18710. selector: detail.markers.itemSelector
  18711. })]),
  18712. domModification: { attributes: { role: 'toolbar' } }
  18713. });
  18714. const ToolbarGroup = composite({
  18715. name: 'ToolbarGroup',
  18716. configFields: schema$9(),
  18717. partFields: parts$5(),
  18718. factory: factory$b
  18719. });
  18720. const buildGroups = comps => map$2(comps, g => premade(g));
  18721. const refresh$1 = (toolbar, memFloatingToolbarButton, detail) => {
  18722. refresh$2(toolbar, detail, overflowGroups => {
  18723. detail.overflowGroups.set(overflowGroups);
  18724. memFloatingToolbarButton.getOpt(toolbar).each(floatingToolbarButton => {
  18725. FloatingToolbarButton.setGroups(floatingToolbarButton, buildGroups(overflowGroups));
  18726. });
  18727. });
  18728. };
  18729. const factory$a = (detail, components, spec, externals) => {
  18730. const memFloatingToolbarButton = record(FloatingToolbarButton.sketch({
  18731. fetch: () => Future.nu(resolve => {
  18732. resolve(buildGroups(detail.overflowGroups.get()));
  18733. }),
  18734. layouts: {
  18735. onLtr: () => [
  18736. southwest$2,
  18737. southeast$2
  18738. ],
  18739. onRtl: () => [
  18740. southeast$2,
  18741. southwest$2
  18742. ],
  18743. onBottomLtr: () => [
  18744. northwest$2,
  18745. northeast$2
  18746. ],
  18747. onBottomRtl: () => [
  18748. northeast$2,
  18749. northwest$2
  18750. ]
  18751. },
  18752. getBounds: spec.getOverflowBounds,
  18753. lazySink: detail.lazySink,
  18754. fireDismissalEventInstead: {},
  18755. markers: { toggledClass: detail.markers.overflowToggledClass },
  18756. parts: {
  18757. button: externals['overflow-button'](),
  18758. toolbar: externals.overflow()
  18759. },
  18760. onToggled: (comp, state) => detail[state ? 'onOpened' : 'onClosed'](comp)
  18761. }));
  18762. return {
  18763. uid: detail.uid,
  18764. dom: detail.dom,
  18765. components,
  18766. behaviours: augment(detail.splitToolbarBehaviours, [Coupling.config({
  18767. others: {
  18768. overflowGroup: () => {
  18769. return ToolbarGroup.sketch({
  18770. ...externals['overflow-group'](),
  18771. items: [memFloatingToolbarButton.asSpec()]
  18772. });
  18773. }
  18774. }
  18775. })]),
  18776. apis: {
  18777. setGroups: (toolbar, groups) => {
  18778. detail.builtGroups.set(map$2(groups, toolbar.getSystem().build));
  18779. refresh$1(toolbar, memFloatingToolbarButton, detail);
  18780. },
  18781. refresh: toolbar => refresh$1(toolbar, memFloatingToolbarButton, detail),
  18782. toggle: toolbar => {
  18783. memFloatingToolbarButton.getOpt(toolbar).each(floatingToolbarButton => {
  18784. FloatingToolbarButton.toggle(floatingToolbarButton);
  18785. });
  18786. },
  18787. isOpen: toolbar => memFloatingToolbarButton.getOpt(toolbar).map(FloatingToolbarButton.isOpen).getOr(false),
  18788. reposition: toolbar => {
  18789. memFloatingToolbarButton.getOpt(toolbar).each(floatingToolbarButton => {
  18790. FloatingToolbarButton.reposition(floatingToolbarButton);
  18791. });
  18792. },
  18793. getOverflow: toolbar => memFloatingToolbarButton.getOpt(toolbar).bind(FloatingToolbarButton.getToolbar)
  18794. },
  18795. domModification: { attributes: { role: 'group' } }
  18796. };
  18797. };
  18798. const SplitFloatingToolbar = composite({
  18799. name: 'SplitFloatingToolbar',
  18800. configFields: schema$b(),
  18801. partFields: parts$7(),
  18802. factory: factory$a,
  18803. apis: {
  18804. setGroups: (apis, toolbar, groups) => {
  18805. apis.setGroups(toolbar, groups);
  18806. },
  18807. refresh: (apis, toolbar) => {
  18808. apis.refresh(toolbar);
  18809. },
  18810. reposition: (apis, toolbar) => {
  18811. apis.reposition(toolbar);
  18812. },
  18813. toggle: (apis, toolbar) => {
  18814. apis.toggle(toolbar);
  18815. },
  18816. isOpen: (apis, toolbar) => apis.isOpen(toolbar),
  18817. getOverflow: (apis, toolbar) => apis.getOverflow(toolbar)
  18818. }
  18819. });
  18820. const schema$8 = constant$1([
  18821. markers$1([
  18822. 'closedClass',
  18823. 'openClass',
  18824. 'shrinkingClass',
  18825. 'growingClass',
  18826. 'overflowToggledClass'
  18827. ]),
  18828. onHandler('onOpened'),
  18829. onHandler('onClosed')
  18830. ].concat(schema$c()));
  18831. const parts$4 = constant$1([
  18832. required({
  18833. factory: Toolbar,
  18834. schema: schema$e(),
  18835. name: 'primary'
  18836. }),
  18837. required({
  18838. factory: Toolbar,
  18839. schema: schema$e(),
  18840. name: 'overflow',
  18841. overrides: detail => {
  18842. return {
  18843. toolbarBehaviours: derive$1([
  18844. Sliding.config({
  18845. dimension: { property: 'height' },
  18846. closedClass: detail.markers.closedClass,
  18847. openClass: detail.markers.openClass,
  18848. shrinkingClass: detail.markers.shrinkingClass,
  18849. growingClass: detail.markers.growingClass,
  18850. onShrunk: comp => {
  18851. getPart(comp, detail, 'overflow-button').each(button => {
  18852. Toggling.off(button);
  18853. Focusing.focus(button);
  18854. });
  18855. detail.onClosed(comp);
  18856. },
  18857. onGrown: comp => {
  18858. Keying.focusIn(comp);
  18859. detail.onOpened(comp);
  18860. },
  18861. onStartGrow: comp => {
  18862. getPart(comp, detail, 'overflow-button').each(Toggling.on);
  18863. }
  18864. }),
  18865. Keying.config({
  18866. mode: 'acyclic',
  18867. onEscape: comp => {
  18868. getPart(comp, detail, 'overflow-button').each(Focusing.focus);
  18869. return Optional.some(true);
  18870. }
  18871. })
  18872. ])
  18873. };
  18874. }
  18875. }),
  18876. external({
  18877. name: 'overflow-button',
  18878. overrides: detail => ({
  18879. buttonBehaviours: derive$1([Toggling.config({
  18880. toggleClass: detail.markers.overflowToggledClass,
  18881. aria: { mode: 'pressed' },
  18882. toggleOnExecute: false
  18883. })])
  18884. })
  18885. }),
  18886. external({ name: 'overflow-group' })
  18887. ]);
  18888. const isOpen = (toolbar, detail) => getPart(toolbar, detail, 'overflow').map(Sliding.hasGrown).getOr(false);
  18889. const toggleToolbar = (toolbar, detail) => {
  18890. getPart(toolbar, detail, 'overflow-button').bind(() => getPart(toolbar, detail, 'overflow')).each(overf => {
  18891. refresh(toolbar, detail);
  18892. Sliding.toggleGrow(overf);
  18893. });
  18894. };
  18895. const refresh = (toolbar, detail) => {
  18896. getPart(toolbar, detail, 'overflow').each(overflow => {
  18897. refresh$2(toolbar, detail, groups => {
  18898. const builtGroups = map$2(groups, g => premade(g));
  18899. Toolbar.setGroups(overflow, builtGroups);
  18900. });
  18901. getPart(toolbar, detail, 'overflow-button').each(button => {
  18902. if (Sliding.hasGrown(overflow)) {
  18903. Toggling.on(button);
  18904. }
  18905. });
  18906. Sliding.refresh(overflow);
  18907. });
  18908. };
  18909. const factory$9 = (detail, components, spec, externals) => {
  18910. const toolbarToggleEvent = 'alloy.toolbar.toggle';
  18911. const doSetGroups = (toolbar, groups) => {
  18912. const built = map$2(groups, toolbar.getSystem().build);
  18913. detail.builtGroups.set(built);
  18914. };
  18915. return {
  18916. uid: detail.uid,
  18917. dom: detail.dom,
  18918. components,
  18919. behaviours: augment(detail.splitToolbarBehaviours, [
  18920. Coupling.config({
  18921. others: {
  18922. overflowGroup: toolbar => {
  18923. return ToolbarGroup.sketch({
  18924. ...externals['overflow-group'](),
  18925. items: [Button.sketch({
  18926. ...externals['overflow-button'](),
  18927. action: _button => {
  18928. emit(toolbar, toolbarToggleEvent);
  18929. }
  18930. })]
  18931. });
  18932. }
  18933. }
  18934. }),
  18935. config('toolbar-toggle-events', [run$1(toolbarToggleEvent, toolbar => {
  18936. toggleToolbar(toolbar, detail);
  18937. })])
  18938. ]),
  18939. apis: {
  18940. setGroups: (toolbar, groups) => {
  18941. doSetGroups(toolbar, groups);
  18942. refresh(toolbar, detail);
  18943. },
  18944. refresh: toolbar => refresh(toolbar, detail),
  18945. toggle: toolbar => toggleToolbar(toolbar, detail),
  18946. isOpen: toolbar => isOpen(toolbar, detail)
  18947. },
  18948. domModification: { attributes: { role: 'group' } }
  18949. };
  18950. };
  18951. const SplitSlidingToolbar = composite({
  18952. name: 'SplitSlidingToolbar',
  18953. configFields: schema$8(),
  18954. partFields: parts$4(),
  18955. factory: factory$9,
  18956. apis: {
  18957. setGroups: (apis, toolbar, groups) => {
  18958. apis.setGroups(toolbar, groups);
  18959. },
  18960. refresh: (apis, toolbar) => {
  18961. apis.refresh(toolbar);
  18962. },
  18963. toggle: (apis, toolbar) => {
  18964. apis.toggle(toolbar);
  18965. },
  18966. isOpen: (apis, toolbar) => apis.isOpen(toolbar)
  18967. }
  18968. });
  18969. const renderToolbarGroupCommon = toolbarGroup => {
  18970. const attributes = toolbarGroup.title.fold(() => ({}), title => ({ attributes: { title } }));
  18971. return {
  18972. dom: {
  18973. tag: 'div',
  18974. classes: ['tox-toolbar__group'],
  18975. ...attributes
  18976. },
  18977. components: [ToolbarGroup.parts.items({})],
  18978. items: toolbarGroup.items,
  18979. markers: { itemSelector: '*:not(.tox-split-button) > .tox-tbtn:not([disabled]), ' + '.tox-split-button:not([disabled]), ' + '.tox-toolbar-nav-js:not([disabled])' },
  18980. tgroupBehaviours: derive$1([
  18981. Tabstopping.config({}),
  18982. Focusing.config({})
  18983. ])
  18984. };
  18985. };
  18986. const renderToolbarGroup = toolbarGroup => ToolbarGroup.sketch(renderToolbarGroupCommon(toolbarGroup));
  18987. const getToolbarBehaviours = (toolbarSpec, modeName) => {
  18988. const onAttached = runOnAttached(component => {
  18989. const groups = map$2(toolbarSpec.initGroups, renderToolbarGroup);
  18990. Toolbar.setGroups(component, groups);
  18991. });
  18992. return derive$1([
  18993. DisablingConfigs.toolbarButton(toolbarSpec.providers.isDisabled),
  18994. receivingConfig(),
  18995. Keying.config({
  18996. mode: modeName,
  18997. onEscape: toolbarSpec.onEscape,
  18998. selector: '.tox-toolbar__group'
  18999. }),
  19000. config('toolbar-events', [onAttached])
  19001. ]);
  19002. };
  19003. const renderMoreToolbarCommon = toolbarSpec => {
  19004. const modeName = toolbarSpec.cyclicKeying ? 'cyclic' : 'acyclic';
  19005. return {
  19006. uid: toolbarSpec.uid,
  19007. dom: {
  19008. tag: 'div',
  19009. classes: ['tox-toolbar-overlord']
  19010. },
  19011. parts: {
  19012. 'overflow-group': renderToolbarGroupCommon({
  19013. title: Optional.none(),
  19014. items: []
  19015. }),
  19016. 'overflow-button': renderIconButtonSpec({
  19017. name: 'more',
  19018. icon: Optional.some('more-drawer'),
  19019. enabled: true,
  19020. tooltip: Optional.some('More...'),
  19021. primary: false,
  19022. buttonType: Optional.none(),
  19023. borderless: false
  19024. }, Optional.none(), toolbarSpec.providers)
  19025. },
  19026. splitToolbarBehaviours: getToolbarBehaviours(toolbarSpec, modeName)
  19027. };
  19028. };
  19029. const renderFloatingMoreToolbar = toolbarSpec => {
  19030. const baseSpec = renderMoreToolbarCommon(toolbarSpec);
  19031. const overflowXOffset = 4;
  19032. const primary = SplitFloatingToolbar.parts.primary({
  19033. dom: {
  19034. tag: 'div',
  19035. classes: ['tox-toolbar__primary']
  19036. }
  19037. });
  19038. return SplitFloatingToolbar.sketch({
  19039. ...baseSpec,
  19040. lazySink: toolbarSpec.getSink,
  19041. getOverflowBounds: () => {
  19042. const headerElem = toolbarSpec.moreDrawerData.lazyHeader().element;
  19043. const headerBounds = absolute$2(headerElem);
  19044. const docElem = documentElement(headerElem);
  19045. const docBounds = absolute$2(docElem);
  19046. const height = Math.max(docElem.dom.scrollHeight, docBounds.height);
  19047. return bounds(headerBounds.x + overflowXOffset, docBounds.y, headerBounds.width - overflowXOffset * 2, height);
  19048. },
  19049. parts: {
  19050. ...baseSpec.parts,
  19051. overflow: {
  19052. dom: {
  19053. tag: 'div',
  19054. classes: ['tox-toolbar__overflow'],
  19055. attributes: toolbarSpec.attributes
  19056. }
  19057. }
  19058. },
  19059. components: [primary],
  19060. markers: { overflowToggledClass: 'tox-tbtn--enabled' },
  19061. onOpened: comp => toolbarSpec.onToggled(comp, true),
  19062. onClosed: comp => toolbarSpec.onToggled(comp, false)
  19063. });
  19064. };
  19065. const renderSlidingMoreToolbar = toolbarSpec => {
  19066. const primary = SplitSlidingToolbar.parts.primary({
  19067. dom: {
  19068. tag: 'div',
  19069. classes: ['tox-toolbar__primary']
  19070. }
  19071. });
  19072. const overflow = SplitSlidingToolbar.parts.overflow({
  19073. dom: {
  19074. tag: 'div',
  19075. classes: ['tox-toolbar__overflow']
  19076. }
  19077. });
  19078. const baseSpec = renderMoreToolbarCommon(toolbarSpec);
  19079. return SplitSlidingToolbar.sketch({
  19080. ...baseSpec,
  19081. components: [
  19082. primary,
  19083. overflow
  19084. ],
  19085. markers: {
  19086. openClass: 'tox-toolbar__overflow--open',
  19087. closedClass: 'tox-toolbar__overflow--closed',
  19088. growingClass: 'tox-toolbar__overflow--growing',
  19089. shrinkingClass: 'tox-toolbar__overflow--shrinking',
  19090. overflowToggledClass: 'tox-tbtn--enabled'
  19091. },
  19092. onOpened: comp => {
  19093. comp.getSystem().broadcastOn([toolbarHeightChange()], { type: 'opened' });
  19094. toolbarSpec.onToggled(comp, true);
  19095. },
  19096. onClosed: comp => {
  19097. comp.getSystem().broadcastOn([toolbarHeightChange()], { type: 'closed' });
  19098. toolbarSpec.onToggled(comp, false);
  19099. }
  19100. });
  19101. };
  19102. const renderToolbar = toolbarSpec => {
  19103. const modeName = toolbarSpec.cyclicKeying ? 'cyclic' : 'acyclic';
  19104. return Toolbar.sketch({
  19105. uid: toolbarSpec.uid,
  19106. dom: {
  19107. tag: 'div',
  19108. classes: ['tox-toolbar'].concat(toolbarSpec.type === ToolbarMode$1.scrolling ? ['tox-toolbar--scrolling'] : [])
  19109. },
  19110. components: [Toolbar.parts.groups({})],
  19111. toolbarBehaviours: getToolbarBehaviours(toolbarSpec, modeName)
  19112. });
  19113. };
  19114. const normalButtonFields = [
  19115. requiredStringEnum('type', ['button']),
  19116. text$1,
  19117. defaultedStringEnum('buttonType', 'secondary', [
  19118. 'primary',
  19119. 'secondary'
  19120. ]),
  19121. requiredFunction('onAction')
  19122. ];
  19123. const viewButtonSchema = choose$1('type', { button: normalButtonFields });
  19124. const viewSchema = objOf([
  19125. defaultedArrayOf('buttons', [], viewButtonSchema),
  19126. requiredFunction('onShow'),
  19127. requiredFunction('onHide')
  19128. ]);
  19129. const createView = spec => asRaw('view', viewSchema, spec);
  19130. const renderViewButton = (spec, providers) => {
  19131. return renderButton({
  19132. text: spec.text,
  19133. enabled: true,
  19134. primary: false,
  19135. name: 'name',
  19136. icon: Optional.none(),
  19137. borderless: false,
  19138. buttonType: Optional.some(spec.buttonType)
  19139. }, _comp => {
  19140. spec.onAction();
  19141. }, providers);
  19142. };
  19143. const renderViewHeader = spec => {
  19144. const endButtons = map$2(spec.buttons, btnspec => renderViewButton(btnspec, spec.providers));
  19145. return {
  19146. uid: spec.uid,
  19147. dom: {
  19148. tag: 'div',
  19149. classes: ['tox-view__header']
  19150. },
  19151. components: [
  19152. Container.sketch({
  19153. dom: {
  19154. tag: 'div',
  19155. classes: ['tox-view__header-start']
  19156. },
  19157. components: []
  19158. }),
  19159. Container.sketch({
  19160. dom: {
  19161. tag: 'div',
  19162. classes: ['tox-view__header-end']
  19163. },
  19164. components: endButtons
  19165. })
  19166. ]
  19167. };
  19168. };
  19169. const renderViewPane = spec => {
  19170. return {
  19171. uid: spec.uid,
  19172. dom: {
  19173. tag: 'div',
  19174. classes: ['tox-view__pane']
  19175. }
  19176. };
  19177. };
  19178. const factory$8 = (detail, components, _spec, _externals) => {
  19179. const apis = {
  19180. getPane: comp => parts$a.getPart(comp, detail, 'pane'),
  19181. getOnShow: _comp => detail.viewConfig.onShow,
  19182. getOnHide: _comp => detail.viewConfig.onHide
  19183. };
  19184. return {
  19185. uid: detail.uid,
  19186. dom: detail.dom,
  19187. components,
  19188. apis
  19189. };
  19190. };
  19191. var View = composite({
  19192. name: 'silver.View',
  19193. configFields: [required$1('viewConfig')],
  19194. partFields: [
  19195. optional({
  19196. factory: { sketch: renderViewHeader },
  19197. schema: [
  19198. required$1('buttons'),
  19199. required$1('providers')
  19200. ],
  19201. name: 'header'
  19202. }),
  19203. optional({
  19204. factory: { sketch: renderViewPane },
  19205. schema: [],
  19206. name: 'pane'
  19207. })
  19208. ],
  19209. factory: factory$8,
  19210. apis: {
  19211. getPane: (apis, comp) => apis.getPane(comp),
  19212. getOnShow: (apis, comp) => apis.getOnShow(comp),
  19213. getOnHide: (apis, comp) => apis.getOnHide(comp)
  19214. }
  19215. });
  19216. const makeViews = (parts, viewConfigs, providers) => {
  19217. return mapToArray(viewConfigs, (config, name) => {
  19218. const internalViewConfig = getOrDie(createView(config));
  19219. return parts.slot(name, View.sketch({
  19220. dom: {
  19221. tag: 'div',
  19222. classes: ['tox-view']
  19223. },
  19224. viewConfig: internalViewConfig,
  19225. components: [
  19226. ...internalViewConfig.buttons.length > 0 ? [View.parts.header({
  19227. buttons: internalViewConfig.buttons,
  19228. providers
  19229. })] : [],
  19230. View.parts.pane({})
  19231. ]
  19232. }));
  19233. });
  19234. };
  19235. const makeSlotContainer = (viewConfigs, providers) => SlotContainer.sketch(parts => ({
  19236. dom: {
  19237. tag: 'div',
  19238. classes: ['tox-view-wrap__slot-container']
  19239. },
  19240. components: makeViews(parts, viewConfigs, providers),
  19241. slotBehaviours: SimpleBehaviours.unnamedEvents([runOnAttached(slotContainer => SlotContainer.hideAllSlots(slotContainer))])
  19242. }));
  19243. const getCurrentName = slotContainer => {
  19244. return find$5(SlotContainer.getSlotNames(slotContainer), name => SlotContainer.isShowing(slotContainer, name));
  19245. };
  19246. const hideContainer = comp => {
  19247. const element = comp.element;
  19248. set$8(element, 'display', 'none');
  19249. set$9(element, 'aria-hidden', 'true');
  19250. };
  19251. const showContainer = comp => {
  19252. const element = comp.element;
  19253. remove$6(element, 'display');
  19254. remove$7(element, 'aria-hidden');
  19255. };
  19256. const makeViewInstanceApi = slot => ({ getContainer: constant$1(slot) });
  19257. const runOnPaneWithInstanceApi = (slotContainer, name, get) => {
  19258. SlotContainer.getSlot(slotContainer, name).each(view => {
  19259. View.getPane(view).each(pane => {
  19260. const onCallback = get(view);
  19261. onCallback(makeViewInstanceApi(pane.element.dom));
  19262. });
  19263. });
  19264. };
  19265. const runOnShow = (slotContainer, name) => runOnPaneWithInstanceApi(slotContainer, name, View.getOnShow);
  19266. const runOnHide = (slotContainer, name) => runOnPaneWithInstanceApi(slotContainer, name, View.getOnHide);
  19267. const factory$7 = (detail, spec) => {
  19268. const setViews = (comp, viewConfigs) => {
  19269. Replacing.set(comp, [makeSlotContainer(viewConfigs, spec.backstage.shared.providers)]);
  19270. };
  19271. const whichView = comp => {
  19272. return Composing.getCurrent(comp).bind(getCurrentName);
  19273. };
  19274. const toggleView = (comp, showMainView, hideMainView, name) => {
  19275. return Composing.getCurrent(comp).exists(slotContainer => {
  19276. const optCurrentSlotName = getCurrentName(slotContainer);
  19277. const isTogglingCurrentView = optCurrentSlotName.exists(current => name === current);
  19278. const exists = SlotContainer.getSlot(slotContainer, name).isSome();
  19279. if (exists) {
  19280. SlotContainer.hideAllSlots(slotContainer);
  19281. if (!isTogglingCurrentView) {
  19282. hideMainView();
  19283. showContainer(comp);
  19284. SlotContainer.showSlot(slotContainer, name);
  19285. runOnShow(slotContainer, name);
  19286. } else {
  19287. hideContainer(comp);
  19288. showMainView();
  19289. }
  19290. optCurrentSlotName.each(prevName => runOnHide(slotContainer, prevName));
  19291. }
  19292. return exists;
  19293. });
  19294. };
  19295. const apis = {
  19296. setViews,
  19297. whichView,
  19298. toggleView
  19299. };
  19300. return {
  19301. uid: detail.uid,
  19302. dom: {
  19303. tag: 'div',
  19304. classes: ['tox-view-wrap'],
  19305. attributes: { 'aria-hidden': 'true' },
  19306. styles: { display: 'none' }
  19307. },
  19308. components: [],
  19309. behaviours: derive$1([
  19310. Replacing.config({}),
  19311. Composing.config({
  19312. find: comp => {
  19313. const children = Replacing.contents(comp);
  19314. return head(children);
  19315. }
  19316. })
  19317. ]),
  19318. apis
  19319. };
  19320. };
  19321. var ViewWrapper = single({
  19322. factory: factory$7,
  19323. name: 'silver.ViewWrapper',
  19324. configFields: [required$1('backstage')],
  19325. apis: {
  19326. setViews: (apis, comp, views) => apis.setViews(comp, views),
  19327. toggleView: (apis, comp, outerContainer, editorCont, name) => apis.toggleView(comp, outerContainer, editorCont, name),
  19328. whichView: (apis, comp) => apis.whichView(comp)
  19329. }
  19330. });
  19331. const factory$6 = (detail, components, _spec) => {
  19332. let toolbarDrawerOpenState = false;
  19333. const apis = {
  19334. getSocket: comp => {
  19335. return parts$a.getPart(comp, detail, 'socket');
  19336. },
  19337. setSidebar: (comp, panelConfigs, showSidebar) => {
  19338. parts$a.getPart(comp, detail, 'sidebar').each(sidebar => setSidebar(sidebar, panelConfigs, showSidebar));
  19339. },
  19340. toggleSidebar: (comp, name) => {
  19341. parts$a.getPart(comp, detail, 'sidebar').each(sidebar => toggleSidebar(sidebar, name));
  19342. },
  19343. whichSidebar: comp => {
  19344. return parts$a.getPart(comp, detail, 'sidebar').bind(whichSidebar).getOrNull();
  19345. },
  19346. getHeader: comp => {
  19347. return parts$a.getPart(comp, detail, 'header');
  19348. },
  19349. getToolbar: comp => {
  19350. return parts$a.getPart(comp, detail, 'toolbar');
  19351. },
  19352. setToolbar: (comp, groups) => {
  19353. parts$a.getPart(comp, detail, 'toolbar').each(toolbar => {
  19354. const renderedGroups = map$2(groups, renderToolbarGroup);
  19355. toolbar.getApis().setGroups(toolbar, renderedGroups);
  19356. });
  19357. },
  19358. setToolbars: (comp, toolbars) => {
  19359. parts$a.getPart(comp, detail, 'multiple-toolbar').each(mToolbar => {
  19360. const renderedToolbars = map$2(toolbars, g => map$2(g, renderToolbarGroup));
  19361. CustomList.setItems(mToolbar, renderedToolbars);
  19362. });
  19363. },
  19364. refreshToolbar: comp => {
  19365. const toolbar = parts$a.getPart(comp, detail, 'toolbar');
  19366. toolbar.each(toolbar => toolbar.getApis().refresh(toolbar));
  19367. },
  19368. toggleToolbarDrawer: comp => {
  19369. parts$a.getPart(comp, detail, 'toolbar').each(toolbar => {
  19370. mapFrom(toolbar.getApis().toggle, toggle => toggle(toolbar));
  19371. });
  19372. },
  19373. isToolbarDrawerToggled: comp => {
  19374. return parts$a.getPart(comp, detail, 'toolbar').bind(toolbar => Optional.from(toolbar.getApis().isOpen).map(isOpen => isOpen(toolbar))).getOr(false);
  19375. },
  19376. getThrobber: comp => {
  19377. return parts$a.getPart(comp, detail, 'throbber');
  19378. },
  19379. focusToolbar: comp => {
  19380. const optToolbar = parts$a.getPart(comp, detail, 'toolbar').orThunk(() => parts$a.getPart(comp, detail, 'multiple-toolbar'));
  19381. optToolbar.each(toolbar => {
  19382. Keying.focusIn(toolbar);
  19383. });
  19384. },
  19385. setMenubar: (comp, menus) => {
  19386. parts$a.getPart(comp, detail, 'menubar').each(menubar => {
  19387. SilverMenubar.setMenus(menubar, menus);
  19388. });
  19389. },
  19390. focusMenubar: comp => {
  19391. parts$a.getPart(comp, detail, 'menubar').each(menubar => {
  19392. SilverMenubar.focus(menubar);
  19393. });
  19394. },
  19395. setViews: (comp, viewConfigs) => {
  19396. parts$a.getPart(comp, detail, 'viewWrapper').each(wrapper => {
  19397. ViewWrapper.setViews(wrapper, viewConfigs);
  19398. });
  19399. },
  19400. toggleView: (comp, name) => {
  19401. return parts$a.getPart(comp, detail, 'viewWrapper').exists(wrapper => ViewWrapper.toggleView(wrapper, () => apis.showMainView(comp), () => apis.hideMainView(comp), name));
  19402. },
  19403. whichView: comp => {
  19404. return parts$a.getPart(comp, detail, 'viewWrapper').bind(ViewWrapper.whichView).getOrNull();
  19405. },
  19406. hideMainView: comp => {
  19407. toolbarDrawerOpenState = apis.isToolbarDrawerToggled(comp);
  19408. if (toolbarDrawerOpenState) {
  19409. apis.toggleToolbarDrawer(comp);
  19410. }
  19411. parts$a.getPart(comp, detail, 'editorContainer').each(editorContainer => {
  19412. const element = editorContainer.element;
  19413. set$8(element, 'display', 'none');
  19414. set$9(element, 'aria-hidden', 'true');
  19415. });
  19416. },
  19417. showMainView: comp => {
  19418. if (toolbarDrawerOpenState) {
  19419. apis.toggleToolbarDrawer(comp);
  19420. }
  19421. parts$a.getPart(comp, detail, 'editorContainer').each(editorContainer => {
  19422. const element = editorContainer.element;
  19423. remove$6(element, 'display');
  19424. remove$7(element, 'aria-hidden');
  19425. });
  19426. }
  19427. };
  19428. return {
  19429. uid: detail.uid,
  19430. dom: detail.dom,
  19431. components,
  19432. apis,
  19433. behaviours: detail.behaviours
  19434. };
  19435. };
  19436. const partMenubar = partType.optional({
  19437. factory: SilverMenubar,
  19438. name: 'menubar',
  19439. schema: [required$1('backstage')]
  19440. });
  19441. const toolbarFactory = spec => {
  19442. if (spec.type === ToolbarMode$1.sliding) {
  19443. return renderSlidingMoreToolbar;
  19444. } else if (spec.type === ToolbarMode$1.floating) {
  19445. return renderFloatingMoreToolbar;
  19446. } else {
  19447. return renderToolbar;
  19448. }
  19449. };
  19450. const partMultipleToolbar = partType.optional({
  19451. factory: {
  19452. sketch: spec => CustomList.sketch({
  19453. uid: spec.uid,
  19454. dom: spec.dom,
  19455. listBehaviours: derive$1([Keying.config({
  19456. mode: 'acyclic',
  19457. selector: '.tox-toolbar'
  19458. })]),
  19459. makeItem: () => renderToolbar({
  19460. type: spec.type,
  19461. uid: generate$6('multiple-toolbar-item'),
  19462. cyclicKeying: false,
  19463. initGroups: [],
  19464. providers: spec.providers,
  19465. onEscape: () => {
  19466. spec.onEscape();
  19467. return Optional.some(true);
  19468. }
  19469. }),
  19470. setupItem: (_mToolbar, tc, data, _index) => {
  19471. Toolbar.setGroups(tc, data);
  19472. },
  19473. shell: true
  19474. })
  19475. },
  19476. name: 'multiple-toolbar',
  19477. schema: [
  19478. required$1('dom'),
  19479. required$1('onEscape')
  19480. ]
  19481. });
  19482. const partToolbar = partType.optional({
  19483. factory: {
  19484. sketch: spec => {
  19485. const renderer = toolbarFactory(spec);
  19486. const toolbarSpec = {
  19487. type: spec.type,
  19488. uid: spec.uid,
  19489. onEscape: () => {
  19490. spec.onEscape();
  19491. return Optional.some(true);
  19492. },
  19493. onToggled: (_comp, state) => spec.onToolbarToggled(state),
  19494. cyclicKeying: false,
  19495. initGroups: [],
  19496. getSink: spec.getSink,
  19497. providers: spec.providers,
  19498. moreDrawerData: {
  19499. lazyToolbar: spec.lazyToolbar,
  19500. lazyMoreButton: spec.lazyMoreButton,
  19501. lazyHeader: spec.lazyHeader
  19502. },
  19503. attributes: spec.attributes
  19504. };
  19505. return renderer(toolbarSpec);
  19506. }
  19507. },
  19508. name: 'toolbar',
  19509. schema: [
  19510. required$1('dom'),
  19511. required$1('onEscape'),
  19512. required$1('getSink')
  19513. ]
  19514. });
  19515. const partHeader = partType.optional({
  19516. factory: { sketch: renderHeader },
  19517. name: 'header',
  19518. schema: [required$1('dom')]
  19519. });
  19520. const partPromotion = partType.optional({
  19521. factory: { sketch: renderPromotion },
  19522. name: 'promotion',
  19523. schema: [required$1('dom')]
  19524. });
  19525. const partSocket = partType.optional({
  19526. name: 'socket',
  19527. schema: [required$1('dom')]
  19528. });
  19529. const partSidebar = partType.optional({
  19530. factory: { sketch: renderSidebar },
  19531. name: 'sidebar',
  19532. schema: [required$1('dom')]
  19533. });
  19534. const partThrobber = partType.optional({
  19535. factory: { sketch: renderThrobber },
  19536. name: 'throbber',
  19537. schema: [required$1('dom')]
  19538. });
  19539. const partViewWrapper = partType.optional({
  19540. factory: ViewWrapper,
  19541. name: 'viewWrapper',
  19542. schema: [required$1('backstage')]
  19543. });
  19544. const renderEditorContainer = spec => ({
  19545. uid: spec.uid,
  19546. dom: {
  19547. tag: 'div',
  19548. classes: ['tox-editor-container']
  19549. },
  19550. components: spec.components
  19551. });
  19552. const partEditorContainer = partType.optional({
  19553. factory: { sketch: renderEditorContainer },
  19554. name: 'editorContainer',
  19555. schema: []
  19556. });
  19557. var OuterContainer = composite({
  19558. name: 'OuterContainer',
  19559. factory: factory$6,
  19560. configFields: [
  19561. required$1('dom'),
  19562. required$1('behaviours')
  19563. ],
  19564. partFields: [
  19565. partHeader,
  19566. partMenubar,
  19567. partToolbar,
  19568. partMultipleToolbar,
  19569. partSocket,
  19570. partSidebar,
  19571. partPromotion,
  19572. partThrobber,
  19573. partViewWrapper,
  19574. partEditorContainer
  19575. ],
  19576. apis: {
  19577. getSocket: (apis, comp) => {
  19578. return apis.getSocket(comp);
  19579. },
  19580. setSidebar: (apis, comp, panelConfigs, showSidebar) => {
  19581. apis.setSidebar(comp, panelConfigs, showSidebar);
  19582. },
  19583. toggleSidebar: (apis, comp, name) => {
  19584. apis.toggleSidebar(comp, name);
  19585. },
  19586. whichSidebar: (apis, comp) => {
  19587. return apis.whichSidebar(comp);
  19588. },
  19589. getHeader: (apis, comp) => {
  19590. return apis.getHeader(comp);
  19591. },
  19592. getToolbar: (apis, comp) => {
  19593. return apis.getToolbar(comp);
  19594. },
  19595. setToolbar: (apis, comp, groups) => {
  19596. apis.setToolbar(comp, groups);
  19597. },
  19598. setToolbars: (apis, comp, toolbars) => {
  19599. apis.setToolbars(comp, toolbars);
  19600. },
  19601. refreshToolbar: (apis, comp) => {
  19602. return apis.refreshToolbar(comp);
  19603. },
  19604. toggleToolbarDrawer: (apis, comp) => {
  19605. apis.toggleToolbarDrawer(comp);
  19606. },
  19607. isToolbarDrawerToggled: (apis, comp) => {
  19608. return apis.isToolbarDrawerToggled(comp);
  19609. },
  19610. getThrobber: (apis, comp) => {
  19611. return apis.getThrobber(comp);
  19612. },
  19613. setMenubar: (apis, comp, menus) => {
  19614. apis.setMenubar(comp, menus);
  19615. },
  19616. focusMenubar: (apis, comp) => {
  19617. apis.focusMenubar(comp);
  19618. },
  19619. focusToolbar: (apis, comp) => {
  19620. apis.focusToolbar(comp);
  19621. },
  19622. setViews: (apis, comp, views) => {
  19623. apis.setViews(comp, views);
  19624. },
  19625. toggleView: (apis, comp, name) => {
  19626. return apis.toggleView(comp, name);
  19627. },
  19628. whichView: (apis, comp) => {
  19629. return apis.whichView(comp);
  19630. }
  19631. }
  19632. });
  19633. const defaultMenubar = 'file edit view insert format tools table help';
  19634. const defaultMenus = {
  19635. file: {
  19636. title: 'File',
  19637. items: 'newdocument restoredraft | preview | export print | deleteallconversations'
  19638. },
  19639. edit: {
  19640. title: 'Edit',
  19641. items: 'undo redo | cut copy paste pastetext | selectall | searchreplace'
  19642. },
  19643. view: {
  19644. title: 'View',
  19645. items: 'code | visualaid visualchars visualblocks | spellchecker | preview fullscreen | showcomments'
  19646. },
  19647. insert: {
  19648. title: 'Insert',
  19649. items: 'image link media addcomment pageembed template codesample inserttable | charmap emoticons hr | pagebreak nonbreaking anchor tableofcontents footnotes | mergetags | insertdatetime'
  19650. },
  19651. format: {
  19652. title: 'Format',
  19653. items: 'bold italic underline strikethrough superscript subscript codeformat | styles blocks fontfamily fontsize align lineheight | forecolor backcolor | language | removeformat'
  19654. },
  19655. tools: {
  19656. title: 'Tools',
  19657. items: 'spellchecker spellcheckerlanguage | autocorrect capitalization | a11ycheck code wordcount'
  19658. },
  19659. table: {
  19660. title: 'Table',
  19661. items: 'inserttable | cell row column | advtablesort | tableprops deletetable'
  19662. },
  19663. help: {
  19664. title: 'Help',
  19665. items: 'help'
  19666. }
  19667. };
  19668. const make = (menu, registry, editor) => {
  19669. const removedMenuItems = getRemovedMenuItems(editor).split(/[ ,]/);
  19670. return {
  19671. text: menu.title,
  19672. getItems: () => bind$3(menu.items, i => {
  19673. const itemName = i.toLowerCase();
  19674. if (itemName.trim().length === 0) {
  19675. return [];
  19676. } else if (exists(removedMenuItems, removedMenuItem => removedMenuItem === itemName)) {
  19677. return [];
  19678. } else if (itemName === 'separator' || itemName === '|') {
  19679. return [{ type: 'separator' }];
  19680. } else if (registry.menuItems[itemName]) {
  19681. return [registry.menuItems[itemName]];
  19682. } else {
  19683. return [];
  19684. }
  19685. })
  19686. };
  19687. };
  19688. const parseItemsString = items => {
  19689. return items.split(' ');
  19690. };
  19691. const identifyMenus = (editor, registry) => {
  19692. const rawMenuData = {
  19693. ...defaultMenus,
  19694. ...registry.menus
  19695. };
  19696. const userDefinedMenus = keys(registry.menus).length > 0;
  19697. const menubar = registry.menubar === undefined || registry.menubar === true ? parseItemsString(defaultMenubar) : parseItemsString(registry.menubar === false ? '' : registry.menubar);
  19698. const validMenus = filter$2(menubar, menuName => {
  19699. const isDefaultMenu = has$2(defaultMenus, menuName);
  19700. if (userDefinedMenus) {
  19701. return isDefaultMenu || get$g(registry.menus, menuName).exists(menu => has$2(menu, 'items'));
  19702. } else {
  19703. return isDefaultMenu;
  19704. }
  19705. });
  19706. const menus = map$2(validMenus, menuName => {
  19707. const menuData = rawMenuData[menuName];
  19708. return make({
  19709. title: menuData.title,
  19710. items: parseItemsString(menuData.items)
  19711. }, registry, editor);
  19712. });
  19713. return filter$2(menus, menu => {
  19714. const isNotSeparator = item => isString(item) || item.type !== 'separator';
  19715. return menu.getItems().length > 0 && exists(menu.getItems(), isNotSeparator);
  19716. });
  19717. };
  19718. const fireSkinLoaded = editor => {
  19719. const done = () => {
  19720. editor._skinLoaded = true;
  19721. fireSkinLoaded$1(editor);
  19722. };
  19723. return () => {
  19724. if (editor.initialized) {
  19725. done();
  19726. } else {
  19727. editor.on('init', done);
  19728. }
  19729. };
  19730. };
  19731. const fireSkinLoadError = (editor, err) => () => fireSkinLoadError$1(editor, { message: err });
  19732. const loadStylesheet = (editor, stylesheetUrl, styleSheetLoader) => {
  19733. editor.on('remove', () => styleSheetLoader.unload(stylesheetUrl));
  19734. return styleSheetLoader.load(stylesheetUrl);
  19735. };
  19736. const loadUiSkins = (editor, skinUrl) => {
  19737. const skinUiCss = skinUrl + '/skin.min.css';
  19738. return loadStylesheet(editor, skinUiCss, editor.ui.styleSheetLoader);
  19739. };
  19740. const loadShadowDomUiSkins = (editor, skinUrl) => {
  19741. const isInShadowRoot$1 = isInShadowRoot(SugarElement.fromDom(editor.getElement()));
  19742. if (isInShadowRoot$1) {
  19743. const shadowDomSkinCss = skinUrl + '/skin.shadowdom.min.css';
  19744. return loadStylesheet(editor, shadowDomSkinCss, global$7.DOM.styleSheetLoader);
  19745. } else {
  19746. return Promise.resolve();
  19747. }
  19748. };
  19749. const loadSkin = (isInline, editor) => {
  19750. const skinUrl = getSkinUrl(editor);
  19751. if (skinUrl) {
  19752. editor.contentCSS.push(skinUrl + (isInline ? '/content.inline' : '/content') + '.min.css');
  19753. }
  19754. if (!isSkinDisabled(editor) && isString(skinUrl)) {
  19755. Promise.all([
  19756. loadUiSkins(editor, skinUrl),
  19757. loadShadowDomUiSkins(editor, skinUrl)
  19758. ]).then(fireSkinLoaded(editor), fireSkinLoadError(editor, 'Skin could not be loaded'));
  19759. } else {
  19760. fireSkinLoaded(editor)();
  19761. }
  19762. };
  19763. const iframe = curry(loadSkin, false);
  19764. const inline = curry(loadSkin, true);
  19765. const onSetupFormatToggle = (editor, name) => api => {
  19766. const boundCallback = unbindable();
  19767. const init = () => {
  19768. api.setActive(editor.formatter.match(name));
  19769. const binding = editor.formatter.formatChanged(name, api.setActive);
  19770. boundCallback.set(binding);
  19771. };
  19772. editor.initialized ? init() : editor.once('init', init);
  19773. return () => {
  19774. editor.off('init', init);
  19775. boundCallback.clear();
  19776. };
  19777. };
  19778. const onSetupEvent = (editor, event, f) => api => {
  19779. const handleEvent = () => f(api);
  19780. const init = () => {
  19781. f(api);
  19782. editor.on(event, handleEvent);
  19783. };
  19784. editor.initialized ? init() : editor.once('init', init);
  19785. return () => {
  19786. editor.off('init', init);
  19787. editor.off(event, handleEvent);
  19788. };
  19789. };
  19790. const onActionToggleFormat$1 = editor => rawItem => () => {
  19791. editor.undoManager.transact(() => {
  19792. editor.focus();
  19793. editor.execCommand('mceToggleFormat', false, rawItem.format);
  19794. });
  19795. };
  19796. const onActionExecCommand = (editor, command) => () => editor.execCommand(command);
  19797. const generateSelectItems = (_editor, backstage, spec) => {
  19798. const generateItem = (rawItem, response, invalid, value) => {
  19799. const translatedText = backstage.shared.providers.translate(rawItem.title);
  19800. if (rawItem.type === 'separator') {
  19801. return Optional.some({
  19802. type: 'separator',
  19803. text: translatedText
  19804. });
  19805. } else if (rawItem.type === 'submenu') {
  19806. const items = bind$3(rawItem.getStyleItems(), si => validate(si, response, value));
  19807. if (response === 0 && items.length <= 0) {
  19808. return Optional.none();
  19809. } else {
  19810. return Optional.some({
  19811. type: 'nestedmenuitem',
  19812. text: translatedText,
  19813. enabled: items.length > 0,
  19814. getSubmenuItems: () => bind$3(rawItem.getStyleItems(), si => validate(si, response, value))
  19815. });
  19816. }
  19817. } else {
  19818. return Optional.some({
  19819. type: 'togglemenuitem',
  19820. text: translatedText,
  19821. icon: rawItem.icon,
  19822. active: rawItem.isSelected(value),
  19823. enabled: !invalid,
  19824. onAction: spec.onAction(rawItem),
  19825. ...rawItem.getStylePreview().fold(() => ({}), preview => ({ meta: { style: preview } }))
  19826. });
  19827. }
  19828. };
  19829. const validate = (item, response, value) => {
  19830. const invalid = item.type === 'formatter' && spec.isInvalid(item);
  19831. if (response === 0) {
  19832. return invalid ? [] : generateItem(item, response, false, value).toArray();
  19833. } else {
  19834. return generateItem(item, response, invalid, value).toArray();
  19835. }
  19836. };
  19837. const validateItems = preItems => {
  19838. const value = spec.getCurrentValue();
  19839. const response = spec.shouldHide ? 0 : 1;
  19840. return bind$3(preItems, item => validate(item, response, value));
  19841. };
  19842. const getFetch = (backstage, getStyleItems) => (comp, callback) => {
  19843. const preItems = getStyleItems();
  19844. const items = validateItems(preItems);
  19845. const menu = build(items, ItemResponse$1.CLOSE_ON_EXECUTE, backstage, {
  19846. isHorizontalMenu: false,
  19847. search: Optional.none()
  19848. });
  19849. callback(menu);
  19850. };
  19851. return {
  19852. validateItems,
  19853. getFetch
  19854. };
  19855. };
  19856. const createMenuItems = (editor, backstage, spec) => {
  19857. const dataset = spec.dataset;
  19858. const getStyleItems = dataset.type === 'basic' ? () => map$2(dataset.data, d => processBasic(d, spec.isSelectedFor, spec.getPreviewFor)) : dataset.getData;
  19859. return {
  19860. items: generateSelectItems(editor, backstage, spec),
  19861. getStyleItems
  19862. };
  19863. };
  19864. const createSelectButton = (editor, backstage, spec) => {
  19865. const {items, getStyleItems} = createMenuItems(editor, backstage, spec);
  19866. const getApi = comp => ({ getComponent: constant$1(comp) });
  19867. const onSetup = onSetupEvent(editor, 'NodeChange', api => {
  19868. const comp = api.getComponent();
  19869. spec.updateText(comp);
  19870. });
  19871. return renderCommonDropdown({
  19872. text: spec.icon.isSome() ? Optional.none() : spec.text,
  19873. icon: spec.icon,
  19874. tooltip: Optional.from(spec.tooltip),
  19875. role: Optional.none(),
  19876. fetch: items.getFetch(backstage, getStyleItems),
  19877. onSetup,
  19878. getApi,
  19879. columns: 1,
  19880. presets: 'normal',
  19881. classes: spec.icon.isSome() ? [] : ['bespoke'],
  19882. dropdownBehaviours: []
  19883. }, 'tox-tbtn', backstage.shared);
  19884. };
  19885. const process = rawFormats => map$2(rawFormats, item => {
  19886. let title = item, format = item;
  19887. const values = item.split('=');
  19888. if (values.length > 1) {
  19889. title = values[0];
  19890. format = values[1];
  19891. }
  19892. return {
  19893. title,
  19894. format
  19895. };
  19896. });
  19897. const buildBasicStaticDataset = data => ({
  19898. type: 'basic',
  19899. data
  19900. });
  19901. var Delimiter;
  19902. (function (Delimiter) {
  19903. Delimiter[Delimiter['SemiColon'] = 0] = 'SemiColon';
  19904. Delimiter[Delimiter['Space'] = 1] = 'Space';
  19905. }(Delimiter || (Delimiter = {})));
  19906. const split = (rawFormats, delimiter) => {
  19907. if (delimiter === Delimiter.SemiColon) {
  19908. return rawFormats.replace(/;$/, '').split(';');
  19909. } else {
  19910. return rawFormats.split(' ');
  19911. }
  19912. };
  19913. const buildBasicSettingsDataset = (editor, settingName, delimiter) => {
  19914. const rawFormats = editor.options.get(settingName);
  19915. const data = process(split(rawFormats, delimiter));
  19916. return {
  19917. type: 'basic',
  19918. data
  19919. };
  19920. };
  19921. const alignMenuItems = [
  19922. {
  19923. title: 'Left',
  19924. icon: 'align-left',
  19925. format: 'alignleft',
  19926. command: 'JustifyLeft'
  19927. },
  19928. {
  19929. title: 'Center',
  19930. icon: 'align-center',
  19931. format: 'aligncenter',
  19932. command: 'JustifyCenter'
  19933. },
  19934. {
  19935. title: 'Right',
  19936. icon: 'align-right',
  19937. format: 'alignright',
  19938. command: 'JustifyRight'
  19939. },
  19940. {
  19941. title: 'Justify',
  19942. icon: 'align-justify',
  19943. format: 'alignjustify',
  19944. command: 'JustifyFull'
  19945. }
  19946. ];
  19947. const getSpec$4 = editor => {
  19948. const getMatchingValue = () => find$5(alignMenuItems, item => editor.formatter.match(item.format));
  19949. const isSelectedFor = format => () => editor.formatter.match(format);
  19950. const getPreviewFor = _format => Optional.none;
  19951. const updateSelectMenuIcon = comp => {
  19952. const match = getMatchingValue();
  19953. const alignment = match.fold(constant$1('left'), item => item.title.toLowerCase());
  19954. emitWith(comp, updateMenuIcon, { icon: `align-${ alignment }` });
  19955. };
  19956. const dataset = buildBasicStaticDataset(alignMenuItems);
  19957. const onAction = rawItem => () => find$5(alignMenuItems, item => item.format === rawItem.format).each(item => editor.execCommand(item.command));
  19958. return {
  19959. tooltip: 'Align',
  19960. text: Optional.none(),
  19961. icon: Optional.some('align-left'),
  19962. isSelectedFor,
  19963. getCurrentValue: Optional.none,
  19964. getPreviewFor,
  19965. onAction,
  19966. updateText: updateSelectMenuIcon,
  19967. dataset,
  19968. shouldHide: false,
  19969. isInvalid: item => !editor.formatter.canApply(item.format)
  19970. };
  19971. };
  19972. const createAlignButton = (editor, backstage) => createSelectButton(editor, backstage, getSpec$4(editor));
  19973. const createAlignMenu = (editor, backstage) => {
  19974. const menuItems = createMenuItems(editor, backstage, getSpec$4(editor));
  19975. editor.ui.registry.addNestedMenuItem('align', {
  19976. text: backstage.shared.providers.translate('Align'),
  19977. getSubmenuItems: () => menuItems.items.validateItems(menuItems.getStyleItems())
  19978. });
  19979. };
  19980. const findNearest = (editor, getStyles) => {
  19981. const styles = getStyles();
  19982. const formats = map$2(styles, style => style.format);
  19983. return Optional.from(editor.formatter.closest(formats)).bind(fmt => find$5(styles, data => data.format === fmt)).orThunk(() => someIf(editor.formatter.match('p'), {
  19984. title: 'Paragraph',
  19985. format: 'p'
  19986. }));
  19987. };
  19988. const getSpec$3 = editor => {
  19989. const fallbackFormat = 'Paragraph';
  19990. const isSelectedFor = format => () => editor.formatter.match(format);
  19991. const getPreviewFor = format => () => {
  19992. const fmt = editor.formatter.get(format);
  19993. if (fmt) {
  19994. return Optional.some({
  19995. tag: fmt.length > 0 ? fmt[0].inline || fmt[0].block || 'div' : 'div',
  19996. styles: editor.dom.parseStyle(editor.formatter.getCssText(format))
  19997. });
  19998. } else {
  19999. return Optional.none();
  20000. }
  20001. };
  20002. const updateSelectMenuText = comp => {
  20003. const detectedFormat = findNearest(editor, () => dataset.data);
  20004. const text = detectedFormat.fold(constant$1(fallbackFormat), fmt => fmt.title);
  20005. emitWith(comp, updateMenuText, { text });
  20006. };
  20007. const dataset = buildBasicSettingsDataset(editor, 'block_formats', Delimiter.SemiColon);
  20008. return {
  20009. tooltip: 'Blocks',
  20010. text: Optional.some(fallbackFormat),
  20011. icon: Optional.none(),
  20012. isSelectedFor,
  20013. getCurrentValue: Optional.none,
  20014. getPreviewFor,
  20015. onAction: onActionToggleFormat$1(editor),
  20016. updateText: updateSelectMenuText,
  20017. dataset,
  20018. shouldHide: false,
  20019. isInvalid: item => !editor.formatter.canApply(item.format)
  20020. };
  20021. };
  20022. const createBlocksButton = (editor, backstage) => createSelectButton(editor, backstage, getSpec$3(editor));
  20023. const createBlocksMenu = (editor, backstage) => {
  20024. const menuItems = createMenuItems(editor, backstage, getSpec$3(editor));
  20025. editor.ui.registry.addNestedMenuItem('blocks', {
  20026. text: 'Blocks',
  20027. getSubmenuItems: () => menuItems.items.validateItems(menuItems.getStyleItems())
  20028. });
  20029. };
  20030. const systemStackFonts = [
  20031. '-apple-system',
  20032. 'Segoe UI',
  20033. 'Roboto',
  20034. 'Helvetica Neue',
  20035. 'sans-serif'
  20036. ];
  20037. const splitFonts = fontFamily => {
  20038. const fonts = fontFamily.split(/\s*,\s*/);
  20039. return map$2(fonts, font => font.replace(/^['"]+|['"]+$/g, ''));
  20040. };
  20041. const isSystemFontStack = fontFamily => {
  20042. const matchesSystemStack = () => {
  20043. const fonts = splitFonts(fontFamily.toLowerCase());
  20044. return forall(systemStackFonts, font => fonts.indexOf(font.toLowerCase()) > -1);
  20045. };
  20046. return fontFamily.indexOf('-apple-system') === 0 && matchesSystemStack();
  20047. };
  20048. const getSpec$2 = editor => {
  20049. const systemFont = 'System Font';
  20050. const getMatchingValue = () => {
  20051. const getFirstFont = fontFamily => fontFamily ? splitFonts(fontFamily)[0] : '';
  20052. const fontFamily = editor.queryCommandValue('FontName');
  20053. const items = dataset.data;
  20054. const font = fontFamily ? fontFamily.toLowerCase() : '';
  20055. const matchOpt = find$5(items, item => {
  20056. const format = item.format;
  20057. return format.toLowerCase() === font || getFirstFont(format).toLowerCase() === getFirstFont(font).toLowerCase();
  20058. }).orThunk(() => {
  20059. return someIf(isSystemFontStack(font), {
  20060. title: systemFont,
  20061. format: font
  20062. });
  20063. });
  20064. return {
  20065. matchOpt,
  20066. font: fontFamily
  20067. };
  20068. };
  20069. const isSelectedFor = item => valueOpt => valueOpt.exists(value => value.format === item);
  20070. const getCurrentValue = () => {
  20071. const {matchOpt} = getMatchingValue();
  20072. return matchOpt;
  20073. };
  20074. const getPreviewFor = item => () => Optional.some({
  20075. tag: 'div',
  20076. styles: item.indexOf('dings') === -1 ? { 'font-family': item } : {}
  20077. });
  20078. const onAction = rawItem => () => {
  20079. editor.undoManager.transact(() => {
  20080. editor.focus();
  20081. editor.execCommand('FontName', false, rawItem.format);
  20082. });
  20083. };
  20084. const updateSelectMenuText = comp => {
  20085. const {matchOpt, font} = getMatchingValue();
  20086. const text = matchOpt.fold(constant$1(font), item => item.title);
  20087. emitWith(comp, updateMenuText, { text });
  20088. };
  20089. const dataset = buildBasicSettingsDataset(editor, 'font_family_formats', Delimiter.SemiColon);
  20090. return {
  20091. tooltip: 'Fonts',
  20092. text: Optional.some(systemFont),
  20093. icon: Optional.none(),
  20094. isSelectedFor,
  20095. getCurrentValue,
  20096. getPreviewFor,
  20097. onAction,
  20098. updateText: updateSelectMenuText,
  20099. dataset,
  20100. shouldHide: false,
  20101. isInvalid: never
  20102. };
  20103. };
  20104. const createFontFamilyButton = (editor, backstage) => createSelectButton(editor, backstage, getSpec$2(editor));
  20105. const createFontFamilyMenu = (editor, backstage) => {
  20106. const menuItems = createMenuItems(editor, backstage, getSpec$2(editor));
  20107. editor.ui.registry.addNestedMenuItem('fontfamily', {
  20108. text: backstage.shared.providers.translate('Fonts'),
  20109. getSubmenuItems: () => menuItems.items.validateItems(menuItems.getStyleItems())
  20110. });
  20111. };
  20112. const legacyFontSizes = {
  20113. '8pt': '1',
  20114. '10pt': '2',
  20115. '12pt': '3',
  20116. '14pt': '4',
  20117. '18pt': '5',
  20118. '24pt': '6',
  20119. '36pt': '7'
  20120. };
  20121. const keywordFontSizes = {
  20122. 'xx-small': '7pt',
  20123. 'x-small': '8pt',
  20124. 'small': '10pt',
  20125. 'medium': '12pt',
  20126. 'large': '14pt',
  20127. 'x-large': '18pt',
  20128. 'xx-large': '24pt'
  20129. };
  20130. const round = (number, precision) => {
  20131. const factor = Math.pow(10, precision);
  20132. return Math.round(number * factor) / factor;
  20133. };
  20134. const toPt = (fontSize, precision) => {
  20135. if (/[0-9.]+px$/.test(fontSize)) {
  20136. return round(parseInt(fontSize, 10) * 72 / 96, precision || 0) + 'pt';
  20137. } else {
  20138. return get$g(keywordFontSizes, fontSize).getOr(fontSize);
  20139. }
  20140. };
  20141. const toLegacy = fontSize => get$g(legacyFontSizes, fontSize).getOr('');
  20142. const getSpec$1 = editor => {
  20143. const getMatchingValue = () => {
  20144. let matchOpt = Optional.none();
  20145. const items = dataset.data;
  20146. const fontSize = editor.queryCommandValue('FontSize');
  20147. if (fontSize) {
  20148. for (let precision = 3; matchOpt.isNone() && precision >= 0; precision--) {
  20149. const pt = toPt(fontSize, precision);
  20150. const legacy = toLegacy(pt);
  20151. matchOpt = find$5(items, item => item.format === fontSize || item.format === pt || item.format === legacy);
  20152. }
  20153. }
  20154. return {
  20155. matchOpt,
  20156. size: fontSize
  20157. };
  20158. };
  20159. const isSelectedFor = item => valueOpt => valueOpt.exists(value => value.format === item);
  20160. const getCurrentValue = () => {
  20161. const {matchOpt} = getMatchingValue();
  20162. return matchOpt;
  20163. };
  20164. const getPreviewFor = constant$1(Optional.none);
  20165. const onAction = rawItem => () => {
  20166. editor.undoManager.transact(() => {
  20167. editor.focus();
  20168. editor.execCommand('FontSize', false, rawItem.format);
  20169. });
  20170. };
  20171. const updateSelectMenuText = comp => {
  20172. const {matchOpt, size} = getMatchingValue();
  20173. const text = matchOpt.fold(constant$1(size), match => match.title);
  20174. emitWith(comp, updateMenuText, { text });
  20175. };
  20176. const dataset = buildBasicSettingsDataset(editor, 'font_size_formats', Delimiter.Space);
  20177. return {
  20178. tooltip: 'Font sizes',
  20179. text: Optional.some('12pt'),
  20180. icon: Optional.none(),
  20181. isSelectedFor,
  20182. getPreviewFor,
  20183. getCurrentValue,
  20184. onAction,
  20185. updateText: updateSelectMenuText,
  20186. dataset,
  20187. shouldHide: false,
  20188. isInvalid: never
  20189. };
  20190. };
  20191. const createFontSizeButton = (editor, backstage) => createSelectButton(editor, backstage, getSpec$1(editor));
  20192. const createFontSizeMenu = (editor, backstage) => {
  20193. const menuItems = createMenuItems(editor, backstage, getSpec$1(editor));
  20194. editor.ui.registry.addNestedMenuItem('fontsize', {
  20195. text: 'Font sizes',
  20196. getSubmenuItems: () => menuItems.items.validateItems(menuItems.getStyleItems())
  20197. });
  20198. };
  20199. const getSpec = (editor, dataset) => {
  20200. const fallbackFormat = 'Paragraph';
  20201. const isSelectedFor = format => () => editor.formatter.match(format);
  20202. const getPreviewFor = format => () => {
  20203. const fmt = editor.formatter.get(format);
  20204. return fmt !== undefined ? Optional.some({
  20205. tag: fmt.length > 0 ? fmt[0].inline || fmt[0].block || 'div' : 'div',
  20206. styles: editor.dom.parseStyle(editor.formatter.getCssText(format))
  20207. }) : Optional.none();
  20208. };
  20209. const updateSelectMenuText = comp => {
  20210. const getFormatItems = fmt => {
  20211. if (isNestedFormat(fmt)) {
  20212. return bind$3(fmt.items, getFormatItems);
  20213. } else if (isFormatReference(fmt)) {
  20214. return [{
  20215. title: fmt.title,
  20216. format: fmt.format
  20217. }];
  20218. } else {
  20219. return [];
  20220. }
  20221. };
  20222. const flattenedItems = bind$3(getStyleFormats(editor), getFormatItems);
  20223. const detectedFormat = findNearest(editor, constant$1(flattenedItems));
  20224. const text = detectedFormat.fold(constant$1(fallbackFormat), fmt => fmt.title);
  20225. emitWith(comp, updateMenuText, { text });
  20226. };
  20227. return {
  20228. tooltip: 'Formats',
  20229. text: Optional.some(fallbackFormat),
  20230. icon: Optional.none(),
  20231. isSelectedFor,
  20232. getCurrentValue: Optional.none,
  20233. getPreviewFor,
  20234. onAction: onActionToggleFormat$1(editor),
  20235. updateText: updateSelectMenuText,
  20236. shouldHide: shouldAutoHideStyleFormats(editor),
  20237. isInvalid: item => !editor.formatter.canApply(item.format),
  20238. dataset
  20239. };
  20240. };
  20241. const createStylesButton = (editor, backstage) => {
  20242. const dataset = {
  20243. type: 'advanced',
  20244. ...backstage.styles
  20245. };
  20246. return createSelectButton(editor, backstage, getSpec(editor, dataset));
  20247. };
  20248. const createStylesMenu = (editor, backstage) => {
  20249. const dataset = {
  20250. type: 'advanced',
  20251. ...backstage.styles
  20252. };
  20253. const menuItems = createMenuItems(editor, backstage, getSpec(editor, dataset));
  20254. editor.ui.registry.addNestedMenuItem('styles', {
  20255. text: 'Formats',
  20256. getSubmenuItems: () => menuItems.items.validateItems(menuItems.getStyleItems())
  20257. });
  20258. };
  20259. const events$3 = (reflectingConfig, reflectingState) => {
  20260. const update = (component, data) => {
  20261. reflectingConfig.updateState.each(updateState => {
  20262. const newState = updateState(component, data);
  20263. reflectingState.set(newState);
  20264. });
  20265. reflectingConfig.renderComponents.each(renderComponents => {
  20266. const newComponents = renderComponents(data, reflectingState.get());
  20267. const replacer = reflectingConfig.reuseDom ? withReuse : withoutReuse;
  20268. replacer(component, newComponents);
  20269. });
  20270. };
  20271. return derive$2([
  20272. run$1(receive(), (component, message) => {
  20273. const receivingData = message;
  20274. if (!receivingData.universal) {
  20275. const channel = reflectingConfig.channel;
  20276. if (contains$2(receivingData.channels, channel)) {
  20277. update(component, receivingData.data);
  20278. }
  20279. }
  20280. }),
  20281. runOnAttached((comp, _se) => {
  20282. reflectingConfig.initialData.each(rawData => {
  20283. update(comp, rawData);
  20284. });
  20285. })
  20286. ]);
  20287. };
  20288. var ActiveReflecting = /*#__PURE__*/Object.freeze({
  20289. __proto__: null,
  20290. events: events$3
  20291. });
  20292. const getState = (component, replaceConfig, reflectState) => reflectState;
  20293. var ReflectingApis = /*#__PURE__*/Object.freeze({
  20294. __proto__: null,
  20295. getState: getState
  20296. });
  20297. var ReflectingSchema = [
  20298. required$1('channel'),
  20299. option$3('renderComponents'),
  20300. option$3('updateState'),
  20301. option$3('initialData'),
  20302. defaultedBoolean('reuseDom', true)
  20303. ];
  20304. const init$3 = () => {
  20305. const cell = Cell(Optional.none());
  20306. const clear = () => cell.set(Optional.none());
  20307. const readState = () => cell.get().getOr('none');
  20308. return {
  20309. readState,
  20310. get: cell.get,
  20311. set: cell.set,
  20312. clear
  20313. };
  20314. };
  20315. var ReflectingState = /*#__PURE__*/Object.freeze({
  20316. __proto__: null,
  20317. init: init$3
  20318. });
  20319. const Reflecting = create$4({
  20320. fields: ReflectingSchema,
  20321. name: 'reflecting',
  20322. active: ActiveReflecting,
  20323. apis: ReflectingApis,
  20324. state: ReflectingState
  20325. });
  20326. const schema$7 = constant$1([
  20327. required$1('toggleClass'),
  20328. required$1('fetch'),
  20329. onStrictHandler('onExecute'),
  20330. defaulted('getHotspot', Optional.some),
  20331. defaulted('getAnchorOverrides', constant$1({})),
  20332. schema$y(),
  20333. onStrictHandler('onItemExecute'),
  20334. option$3('lazySink'),
  20335. required$1('dom'),
  20336. onHandler('onOpen'),
  20337. field('splitDropdownBehaviours', [
  20338. Coupling,
  20339. Keying,
  20340. Focusing
  20341. ]),
  20342. defaulted('matchWidth', false),
  20343. defaulted('useMinWidth', false),
  20344. defaulted('eventOrder', {}),
  20345. option$3('role')
  20346. ].concat(sandboxFields()));
  20347. const arrowPart = required({
  20348. factory: Button,
  20349. schema: [required$1('dom')],
  20350. name: 'arrow',
  20351. defaults: () => {
  20352. return { buttonBehaviours: derive$1([Focusing.revoke()]) };
  20353. },
  20354. overrides: detail => {
  20355. return {
  20356. dom: {
  20357. tag: 'span',
  20358. attributes: { role: 'presentation' }
  20359. },
  20360. action: arrow => {
  20361. arrow.getSystem().getByUid(detail.uid).each(emitExecute);
  20362. },
  20363. buttonBehaviours: derive$1([Toggling.config({
  20364. toggleOnExecute: false,
  20365. toggleClass: detail.toggleClass
  20366. })])
  20367. };
  20368. }
  20369. });
  20370. const buttonPart = required({
  20371. factory: Button,
  20372. schema: [required$1('dom')],
  20373. name: 'button',
  20374. defaults: () => {
  20375. return { buttonBehaviours: derive$1([Focusing.revoke()]) };
  20376. },
  20377. overrides: detail => {
  20378. return {
  20379. dom: {
  20380. tag: 'span',
  20381. attributes: { role: 'presentation' }
  20382. },
  20383. action: btn => {
  20384. btn.getSystem().getByUid(detail.uid).each(splitDropdown => {
  20385. detail.onExecute(splitDropdown, btn);
  20386. });
  20387. }
  20388. };
  20389. }
  20390. });
  20391. const parts$3 = constant$1([
  20392. arrowPart,
  20393. buttonPart,
  20394. optional({
  20395. factory: {
  20396. sketch: spec => {
  20397. return {
  20398. uid: spec.uid,
  20399. dom: {
  20400. tag: 'span',
  20401. styles: { display: 'none' },
  20402. attributes: { 'aria-hidden': 'true' },
  20403. innerHtml: spec.text
  20404. }
  20405. };
  20406. }
  20407. },
  20408. schema: [required$1('text')],
  20409. name: 'aria-descriptor'
  20410. }),
  20411. external({
  20412. schema: [tieredMenuMarkers()],
  20413. name: 'menu',
  20414. defaults: detail => {
  20415. return {
  20416. onExecute: (tmenu, item) => {
  20417. tmenu.getSystem().getByUid(detail.uid).each(splitDropdown => {
  20418. detail.onItemExecute(splitDropdown, tmenu, item);
  20419. });
  20420. }
  20421. };
  20422. }
  20423. }),
  20424. partType$1()
  20425. ]);
  20426. const factory$5 = (detail, components, spec, externals) => {
  20427. const switchToMenu = sandbox => {
  20428. Composing.getCurrent(sandbox).each(current => {
  20429. Highlighting.highlightFirst(current);
  20430. Keying.focusIn(current);
  20431. });
  20432. };
  20433. const action = component => {
  20434. const onOpenSync = switchToMenu;
  20435. togglePopup(detail, identity, component, externals, onOpenSync, HighlightOnOpen.HighlightMenuAndItem).get(noop);
  20436. };
  20437. const openMenu = comp => {
  20438. action(comp);
  20439. return Optional.some(true);
  20440. };
  20441. const executeOnButton = comp => {
  20442. const button = getPartOrDie(comp, detail, 'button');
  20443. emitExecute(button);
  20444. return Optional.some(true);
  20445. };
  20446. const buttonEvents = {
  20447. ...derive$2([runOnAttached((component, _simulatedEvent) => {
  20448. const ariaDescriptor = getPart(component, detail, 'aria-descriptor');
  20449. ariaDescriptor.each(descriptor => {
  20450. const descriptorId = generate$6('aria');
  20451. set$9(descriptor.element, 'id', descriptorId);
  20452. set$9(component.element, 'aria-describedby', descriptorId);
  20453. });
  20454. })]),
  20455. ...events$a(Optional.some(action))
  20456. };
  20457. const apis = {
  20458. repositionMenus: comp => {
  20459. if (Toggling.isOn(comp)) {
  20460. repositionMenus(comp);
  20461. }
  20462. }
  20463. };
  20464. return {
  20465. uid: detail.uid,
  20466. dom: detail.dom,
  20467. components,
  20468. apis,
  20469. eventOrder: {
  20470. ...detail.eventOrder,
  20471. [execute$5()]: [
  20472. 'disabling',
  20473. 'toggling',
  20474. 'alloy.base.behaviour'
  20475. ]
  20476. },
  20477. events: buttonEvents,
  20478. behaviours: augment(detail.splitDropdownBehaviours, [
  20479. Coupling.config({
  20480. others: {
  20481. sandbox: hotspot => {
  20482. const arrow = getPartOrDie(hotspot, detail, 'arrow');
  20483. const extras = {
  20484. onOpen: () => {
  20485. Toggling.on(arrow);
  20486. Toggling.on(hotspot);
  20487. },
  20488. onClose: () => {
  20489. Toggling.off(arrow);
  20490. Toggling.off(hotspot);
  20491. }
  20492. };
  20493. return makeSandbox$1(detail, hotspot, extras);
  20494. }
  20495. }
  20496. }),
  20497. Keying.config({
  20498. mode: 'special',
  20499. onSpace: executeOnButton,
  20500. onEnter: executeOnButton,
  20501. onDown: openMenu
  20502. }),
  20503. Focusing.config({}),
  20504. Toggling.config({
  20505. toggleOnExecute: false,
  20506. aria: { mode: 'expanded' }
  20507. })
  20508. ]),
  20509. domModification: {
  20510. attributes: {
  20511. 'role': detail.role.getOr('button'),
  20512. 'aria-haspopup': true
  20513. }
  20514. }
  20515. };
  20516. };
  20517. const SplitDropdown = composite({
  20518. name: 'SplitDropdown',
  20519. configFields: schema$7(),
  20520. partFields: parts$3(),
  20521. factory: factory$5,
  20522. apis: { repositionMenus: (apis, comp) => apis.repositionMenus(comp) }
  20523. });
  20524. const getButtonApi = component => ({
  20525. isEnabled: () => !Disabling.isDisabled(component),
  20526. setEnabled: state => Disabling.set(component, !state)
  20527. });
  20528. const getToggleApi = component => ({
  20529. setActive: state => {
  20530. Toggling.set(component, state);
  20531. },
  20532. isActive: () => Toggling.isOn(component),
  20533. isEnabled: () => !Disabling.isDisabled(component),
  20534. setEnabled: state => Disabling.set(component, !state)
  20535. });
  20536. const getTooltipAttributes = (tooltip, providersBackstage) => tooltip.map(tooltip => ({
  20537. 'aria-label': providersBackstage.translate(tooltip),
  20538. 'title': providersBackstage.translate(tooltip)
  20539. })).getOr({});
  20540. const focusButtonEvent = generate$6('focus-button');
  20541. const renderCommonStructure = (icon, text, tooltip, receiver, behaviours, providersBackstage) => {
  20542. return {
  20543. dom: {
  20544. tag: 'button',
  20545. classes: ['tox-tbtn'].concat(text.isSome() ? ['tox-tbtn--select'] : []),
  20546. attributes: getTooltipAttributes(tooltip, providersBackstage)
  20547. },
  20548. components: componentRenderPipeline([
  20549. icon.map(iconName => renderIconFromPack(iconName, providersBackstage.icons)),
  20550. text.map(text => renderLabel(text, 'tox-tbtn', providersBackstage))
  20551. ]),
  20552. eventOrder: {
  20553. [mousedown()]: [
  20554. 'focusing',
  20555. 'alloy.base.behaviour',
  20556. 'common-button-display-events'
  20557. ]
  20558. },
  20559. buttonBehaviours: derive$1([
  20560. DisablingConfigs.toolbarButton(providersBackstage.isDisabled),
  20561. receivingConfig(),
  20562. config('common-button-display-events', [run$1(mousedown(), (button, se) => {
  20563. se.event.prevent();
  20564. emit(button, focusButtonEvent);
  20565. })])
  20566. ].concat(receiver.map(r => Reflecting.config({
  20567. channel: r,
  20568. initialData: {
  20569. icon,
  20570. text
  20571. },
  20572. renderComponents: (data, _state) => componentRenderPipeline([
  20573. data.icon.map(iconName => renderIconFromPack(iconName, providersBackstage.icons)),
  20574. data.text.map(text => renderLabel(text, 'tox-tbtn', providersBackstage))
  20575. ])
  20576. })).toArray()).concat(behaviours.getOr([])))
  20577. };
  20578. };
  20579. const renderFloatingToolbarButton = (spec, backstage, identifyButtons, attributes) => {
  20580. const sharedBackstage = backstage.shared;
  20581. return FloatingToolbarButton.sketch({
  20582. lazySink: sharedBackstage.getSink,
  20583. fetch: () => Future.nu(resolve => {
  20584. resolve(map$2(identifyButtons(spec.items), renderToolbarGroup));
  20585. }),
  20586. markers: { toggledClass: 'tox-tbtn--enabled' },
  20587. parts: {
  20588. button: renderCommonStructure(spec.icon, spec.text, spec.tooltip, Optional.none(), Optional.none(), sharedBackstage.providers),
  20589. toolbar: {
  20590. dom: {
  20591. tag: 'div',
  20592. classes: ['tox-toolbar__overflow'],
  20593. attributes
  20594. }
  20595. }
  20596. }
  20597. });
  20598. };
  20599. const renderCommonToolbarButton = (spec, specialisation, providersBackstage) => {
  20600. const editorOffCell = Cell(noop);
  20601. const structure = renderCommonStructure(spec.icon, spec.text, spec.tooltip, Optional.none(), Optional.none(), providersBackstage);
  20602. return Button.sketch({
  20603. dom: structure.dom,
  20604. components: structure.components,
  20605. eventOrder: toolbarButtonEventOrder,
  20606. buttonBehaviours: derive$1([
  20607. config('toolbar-button-events', [
  20608. onToolbarButtonExecute({
  20609. onAction: spec.onAction,
  20610. getApi: specialisation.getApi
  20611. }),
  20612. onControlAttached(specialisation, editorOffCell),
  20613. onControlDetached(specialisation, editorOffCell)
  20614. ]),
  20615. DisablingConfigs.toolbarButton(() => !spec.enabled || providersBackstage.isDisabled()),
  20616. receivingConfig()
  20617. ].concat(specialisation.toolbarButtonBehaviours))
  20618. });
  20619. };
  20620. const renderToolbarButton = (spec, providersBackstage) => renderToolbarButtonWith(spec, providersBackstage, []);
  20621. const renderToolbarButtonWith = (spec, providersBackstage, bonusEvents) => renderCommonToolbarButton(spec, {
  20622. toolbarButtonBehaviours: bonusEvents.length > 0 ? [config('toolbarButtonWith', bonusEvents)] : [],
  20623. getApi: getButtonApi,
  20624. onSetup: spec.onSetup
  20625. }, providersBackstage);
  20626. const renderToolbarToggleButton = (spec, providersBackstage) => renderToolbarToggleButtonWith(spec, providersBackstage, []);
  20627. const renderToolbarToggleButtonWith = (spec, providersBackstage, bonusEvents) => renderCommonToolbarButton(spec, {
  20628. toolbarButtonBehaviours: [
  20629. Replacing.config({}),
  20630. Toggling.config({
  20631. toggleClass: 'tox-tbtn--enabled',
  20632. aria: { mode: 'pressed' },
  20633. toggleOnExecute: false
  20634. })
  20635. ].concat(bonusEvents.length > 0 ? [config('toolbarToggleButtonWith', bonusEvents)] : []),
  20636. getApi: getToggleApi,
  20637. onSetup: spec.onSetup
  20638. }, providersBackstage);
  20639. const fetchChoices = (getApi, spec, providersBackstage) => comp => Future.nu(callback => spec.fetch(callback)).map(items => Optional.from(createTieredDataFrom(deepMerge(createPartialChoiceMenu(generate$6('menu-value'), items, value => {
  20640. spec.onItemAction(getApi(comp), value);
  20641. }, spec.columns, spec.presets, ItemResponse$1.CLOSE_ON_EXECUTE, spec.select.getOr(never), providersBackstage), {
  20642. movement: deriveMenuMovement(spec.columns, spec.presets),
  20643. menuBehaviours: SimpleBehaviours.unnamedEvents(spec.columns !== 'auto' ? [] : [runOnAttached((comp, _se) => {
  20644. detectSize(comp, 4, classForPreset(spec.presets)).each(({numRows, numColumns}) => {
  20645. Keying.setGridSize(comp, numRows, numColumns);
  20646. });
  20647. })])
  20648. }))));
  20649. const renderSplitButton = (spec, sharedBackstage) => {
  20650. const displayChannel = generate$6('channel-update-split-dropdown-display');
  20651. const getApi = comp => ({
  20652. isEnabled: () => !Disabling.isDisabled(comp),
  20653. setEnabled: state => Disabling.set(comp, !state),
  20654. setIconFill: (id, value) => {
  20655. descendant(comp.element, 'svg path[id="' + id + '"], rect[id="' + id + '"]').each(underlinePath => {
  20656. set$9(underlinePath, 'fill', value);
  20657. });
  20658. },
  20659. setActive: state => {
  20660. set$9(comp.element, 'aria-pressed', state);
  20661. descendant(comp.element, 'span').each(button => {
  20662. comp.getSystem().getByDom(button).each(buttonComp => Toggling.set(buttonComp, state));
  20663. });
  20664. },
  20665. isActive: () => descendant(comp.element, 'span').exists(button => comp.getSystem().getByDom(button).exists(Toggling.isOn))
  20666. });
  20667. const editorOffCell = Cell(noop);
  20668. const specialisation = {
  20669. getApi,
  20670. onSetup: spec.onSetup
  20671. };
  20672. return SplitDropdown.sketch({
  20673. dom: {
  20674. tag: 'div',
  20675. classes: ['tox-split-button'],
  20676. attributes: {
  20677. 'aria-pressed': false,
  20678. ...getTooltipAttributes(spec.tooltip, sharedBackstage.providers)
  20679. }
  20680. },
  20681. onExecute: button => {
  20682. spec.onAction(getApi(button));
  20683. },
  20684. onItemExecute: (_a, _b, _c) => {
  20685. },
  20686. splitDropdownBehaviours: derive$1([
  20687. DisablingConfigs.splitButton(sharedBackstage.providers.isDisabled),
  20688. receivingConfig(),
  20689. config('split-dropdown-events', [
  20690. run$1(focusButtonEvent, Focusing.focus),
  20691. onControlAttached(specialisation, editorOffCell),
  20692. onControlDetached(specialisation, editorOffCell)
  20693. ]),
  20694. Unselecting.config({})
  20695. ]),
  20696. eventOrder: {
  20697. [attachedToDom()]: [
  20698. 'alloy.base.behaviour',
  20699. 'split-dropdown-events'
  20700. ]
  20701. },
  20702. toggleClass: 'tox-tbtn--enabled',
  20703. lazySink: sharedBackstage.getSink,
  20704. fetch: fetchChoices(getApi, spec, sharedBackstage.providers),
  20705. parts: { menu: part(false, spec.columns, spec.presets) },
  20706. components: [
  20707. SplitDropdown.parts.button(renderCommonStructure(spec.icon, spec.text, Optional.none(), Optional.some(displayChannel), Optional.some([Toggling.config({
  20708. toggleClass: 'tox-tbtn--enabled',
  20709. toggleOnExecute: false
  20710. })]), sharedBackstage.providers)),
  20711. SplitDropdown.parts.arrow({
  20712. dom: {
  20713. tag: 'button',
  20714. classes: [
  20715. 'tox-tbtn',
  20716. 'tox-split-button__chevron'
  20717. ],
  20718. innerHtml: get$2('chevron-down', sharedBackstage.providers.icons)
  20719. },
  20720. buttonBehaviours: derive$1([
  20721. DisablingConfigs.splitButton(sharedBackstage.providers.isDisabled),
  20722. receivingConfig(),
  20723. addFocusableBehaviour()
  20724. ])
  20725. }),
  20726. SplitDropdown.parts['aria-descriptor']({ text: sharedBackstage.providers.translate('To open the popup, press Shift+Enter') })
  20727. ]
  20728. });
  20729. };
  20730. const defaultToolbar = [
  20731. {
  20732. name: 'history',
  20733. items: [
  20734. 'undo',
  20735. 'redo'
  20736. ]
  20737. },
  20738. {
  20739. name: 'styles',
  20740. items: ['styles']
  20741. },
  20742. {
  20743. name: 'formatting',
  20744. items: [
  20745. 'bold',
  20746. 'italic'
  20747. ]
  20748. },
  20749. {
  20750. name: 'alignment',
  20751. items: [
  20752. 'alignleft',
  20753. 'aligncenter',
  20754. 'alignright',
  20755. 'alignjustify'
  20756. ]
  20757. },
  20758. {
  20759. name: 'indentation',
  20760. items: [
  20761. 'outdent',
  20762. 'indent'
  20763. ]
  20764. },
  20765. {
  20766. name: 'permanent pen',
  20767. items: ['permanentpen']
  20768. },
  20769. {
  20770. name: 'comments',
  20771. items: ['addcomment']
  20772. }
  20773. ];
  20774. const renderFromBridge = (bridgeBuilder, render) => (spec, backstage, editor) => {
  20775. const internal = bridgeBuilder(spec).mapError(errInfo => formatError(errInfo)).getOrDie();
  20776. return render(internal, backstage, editor);
  20777. };
  20778. const types = {
  20779. button: renderFromBridge(createToolbarButton, (s, backstage) => renderToolbarButton(s, backstage.shared.providers)),
  20780. togglebutton: renderFromBridge(createToggleButton, (s, backstage) => renderToolbarToggleButton(s, backstage.shared.providers)),
  20781. menubutton: renderFromBridge(createMenuButton, (s, backstage) => renderMenuButton(s, 'tox-tbtn', backstage, Optional.none())),
  20782. splitbutton: renderFromBridge(createSplitButton, (s, backstage) => renderSplitButton(s, backstage.shared)),
  20783. grouptoolbarbutton: renderFromBridge(createGroupToolbarButton, (s, backstage, editor) => {
  20784. const buttons = editor.ui.registry.getAll().buttons;
  20785. const identify = toolbar => identifyButtons(editor, {
  20786. buttons,
  20787. toolbar,
  20788. allowToolbarGroups: false
  20789. }, backstage, Optional.none());
  20790. const attributes = { [Attribute]: backstage.shared.header.isPositionedAtTop() ? AttributeValue.TopToBottom : AttributeValue.BottomToTop };
  20791. switch (getToolbarMode(editor)) {
  20792. case ToolbarMode$1.floating:
  20793. return renderFloatingToolbarButton(s, backstage, identify, attributes);
  20794. default:
  20795. throw new Error('Toolbar groups are only supported when using floating toolbar mode');
  20796. }
  20797. })
  20798. };
  20799. const extractFrom = (spec, backstage, editor) => get$g(types, spec.type).fold(() => {
  20800. console.error('skipping button defined by', spec);
  20801. return Optional.none();
  20802. }, render => Optional.some(render(spec, backstage, editor)));
  20803. const bespokeButtons = {
  20804. styles: createStylesButton,
  20805. fontsize: createFontSizeButton,
  20806. fontfamily: createFontFamilyButton,
  20807. blocks: createBlocksButton,
  20808. align: createAlignButton
  20809. };
  20810. const removeUnusedDefaults = buttons => {
  20811. const filteredItemGroups = map$2(defaultToolbar, group => {
  20812. const items = filter$2(group.items, subItem => has$2(buttons, subItem) || has$2(bespokeButtons, subItem));
  20813. return {
  20814. name: group.name,
  20815. items
  20816. };
  20817. });
  20818. return filter$2(filteredItemGroups, group => group.items.length > 0);
  20819. };
  20820. const convertStringToolbar = strToolbar => {
  20821. const groupsStrings = strToolbar.split('|');
  20822. return map$2(groupsStrings, g => ({ items: g.trim().split(' ') }));
  20823. };
  20824. const isToolbarGroupSettingArray = toolbar => isArrayOf(toolbar, t => has$2(t, 'name') && has$2(t, 'items'));
  20825. const createToolbar = toolbarConfig => {
  20826. const toolbar = toolbarConfig.toolbar;
  20827. const buttons = toolbarConfig.buttons;
  20828. if (toolbar === false) {
  20829. return [];
  20830. } else if (toolbar === undefined || toolbar === true) {
  20831. return removeUnusedDefaults(buttons);
  20832. } else if (isString(toolbar)) {
  20833. return convertStringToolbar(toolbar);
  20834. } else if (isToolbarGroupSettingArray(toolbar)) {
  20835. return toolbar;
  20836. } else {
  20837. console.error('Toolbar type should be string, string[], boolean or ToolbarGroup[]');
  20838. return [];
  20839. }
  20840. };
  20841. const lookupButton = (editor, buttons, toolbarItem, allowToolbarGroups, backstage, prefixes) => get$g(buttons, toolbarItem.toLowerCase()).orThunk(() => prefixes.bind(ps => findMap(ps, prefix => get$g(buttons, prefix + toolbarItem.toLowerCase())))).fold(() => get$g(bespokeButtons, toolbarItem.toLowerCase()).map(r => r(editor, backstage)), spec => {
  20842. if (spec.type === 'grouptoolbarbutton' && !allowToolbarGroups) {
  20843. console.warn(`Ignoring the '${ toolbarItem }' toolbar button. Group toolbar buttons are only supported when using floating toolbar mode and cannot be nested.`);
  20844. return Optional.none();
  20845. } else {
  20846. return extractFrom(spec, backstage, editor);
  20847. }
  20848. });
  20849. const identifyButtons = (editor, toolbarConfig, backstage, prefixes) => {
  20850. const toolbarGroups = createToolbar(toolbarConfig);
  20851. const groups = map$2(toolbarGroups, group => {
  20852. const items = bind$3(group.items, toolbarItem => {
  20853. return toolbarItem.trim().length === 0 ? [] : lookupButton(editor, toolbarConfig.buttons, toolbarItem, toolbarConfig.allowToolbarGroups, backstage, prefixes).toArray();
  20854. });
  20855. return {
  20856. title: Optional.from(editor.translate(group.name)),
  20857. items
  20858. };
  20859. });
  20860. return filter$2(groups, group => group.items.length > 0);
  20861. };
  20862. const setToolbar = (editor, uiRefs, rawUiConfig, backstage) => {
  20863. const outerContainer = uiRefs.mainUi.outerContainer;
  20864. const toolbarConfig = rawUiConfig.toolbar;
  20865. const toolbarButtonsConfig = rawUiConfig.buttons;
  20866. if (isArrayOf(toolbarConfig, isString)) {
  20867. const toolbars = toolbarConfig.map(t => {
  20868. const config = {
  20869. toolbar: t,
  20870. buttons: toolbarButtonsConfig,
  20871. allowToolbarGroups: rawUiConfig.allowToolbarGroups
  20872. };
  20873. return identifyButtons(editor, config, backstage, Optional.none());
  20874. });
  20875. OuterContainer.setToolbars(outerContainer, toolbars);
  20876. } else {
  20877. OuterContainer.setToolbar(outerContainer, identifyButtons(editor, rawUiConfig, backstage, Optional.none()));
  20878. }
  20879. };
  20880. const detection = detect$1();
  20881. const isiOS12 = detection.os.isiOS() && detection.os.version.major <= 12;
  20882. const setupEvents$1 = (editor, uiRefs) => {
  20883. const {uiMotherships} = uiRefs;
  20884. const dom = editor.dom;
  20885. let contentWindow = editor.getWin();
  20886. const initialDocEle = editor.getDoc().documentElement;
  20887. const lastWindowDimensions = Cell(SugarPosition(contentWindow.innerWidth, contentWindow.innerHeight));
  20888. const lastDocumentDimensions = Cell(SugarPosition(initialDocEle.offsetWidth, initialDocEle.offsetHeight));
  20889. const resizeWindow = () => {
  20890. const outer = lastWindowDimensions.get();
  20891. if (outer.left !== contentWindow.innerWidth || outer.top !== contentWindow.innerHeight) {
  20892. lastWindowDimensions.set(SugarPosition(contentWindow.innerWidth, contentWindow.innerHeight));
  20893. fireResizeContent(editor);
  20894. }
  20895. };
  20896. const resizeDocument = () => {
  20897. const docEle = editor.getDoc().documentElement;
  20898. const inner = lastDocumentDimensions.get();
  20899. if (inner.left !== docEle.offsetWidth || inner.top !== docEle.offsetHeight) {
  20900. lastDocumentDimensions.set(SugarPosition(docEle.offsetWidth, docEle.offsetHeight));
  20901. fireResizeContent(editor);
  20902. }
  20903. };
  20904. const scroll = e => {
  20905. fireScrollContent(editor, e);
  20906. };
  20907. dom.bind(contentWindow, 'resize', resizeWindow);
  20908. dom.bind(contentWindow, 'scroll', scroll);
  20909. const elementLoad = capture(SugarElement.fromDom(editor.getBody()), 'load', resizeDocument);
  20910. editor.on('hide', () => {
  20911. each$1(uiMotherships, m => {
  20912. set$8(m.element, 'display', 'none');
  20913. });
  20914. });
  20915. editor.on('show', () => {
  20916. each$1(uiMotherships, m => {
  20917. remove$6(m.element, 'display');
  20918. });
  20919. });
  20920. editor.on('NodeChange', resizeDocument);
  20921. editor.on('remove', () => {
  20922. elementLoad.unbind();
  20923. dom.unbind(contentWindow, 'resize', resizeWindow);
  20924. dom.unbind(contentWindow, 'scroll', scroll);
  20925. contentWindow = null;
  20926. });
  20927. };
  20928. const attachUiMotherships$1 = (uiRoot, uiRefs) => {
  20929. attachSystem(uiRoot, uiRefs.dialogUi.mothership);
  20930. };
  20931. const render$1 = (editor, uiRefs, rawUiConfig, backstage, args) => {
  20932. const {mainUi, uiMotherships} = uiRefs;
  20933. const lastToolbarWidth = Cell(0);
  20934. const outerContainer = mainUi.outerContainer;
  20935. iframe(editor);
  20936. const eTargetNode = SugarElement.fromDom(args.targetNode);
  20937. const uiRoot = getContentContainer(getRootNode(eTargetNode));
  20938. attachSystemAfter(eTargetNode, mainUi.mothership);
  20939. attachUiMotherships$1(uiRoot, uiRefs);
  20940. editor.on('PostRender', () => {
  20941. OuterContainer.setSidebar(outerContainer, rawUiConfig.sidebar, getSidebarShow(editor));
  20942. setToolbar(editor, uiRefs, rawUiConfig, backstage);
  20943. lastToolbarWidth.set(editor.getWin().innerWidth);
  20944. OuterContainer.setMenubar(outerContainer, identifyMenus(editor, rawUiConfig));
  20945. OuterContainer.setViews(outerContainer, rawUiConfig.views);
  20946. setupEvents$1(editor, uiRefs);
  20947. });
  20948. const socket = OuterContainer.getSocket(outerContainer).getOrDie('Could not find expected socket element');
  20949. if (isiOS12) {
  20950. setAll(socket.element, {
  20951. 'overflow': 'scroll',
  20952. '-webkit-overflow-scrolling': 'touch'
  20953. });
  20954. const limit = first(() => {
  20955. editor.dispatch('ScrollContent');
  20956. }, 20);
  20957. const unbinder = bind(socket.element, 'scroll', limit.throttle);
  20958. editor.on('remove', unbinder.unbind);
  20959. }
  20960. setupReadonlyModeSwitch(editor, uiRefs);
  20961. editor.addCommand('ToggleSidebar', (_ui, value) => {
  20962. OuterContainer.toggleSidebar(outerContainer, value);
  20963. editor.dispatch('ToggleSidebar');
  20964. });
  20965. editor.addQueryValueHandler('ToggleSidebar', () => {
  20966. var _a;
  20967. return (_a = OuterContainer.whichSidebar(outerContainer)) !== null && _a !== void 0 ? _a : '';
  20968. });
  20969. editor.addCommand('ToggleView', (_ui, value) => {
  20970. if (OuterContainer.toggleView(outerContainer, value)) {
  20971. const target = outerContainer.element;
  20972. mainUi.mothership.broadcastOn([dismissPopups()], { target });
  20973. each$1(uiMotherships, m => {
  20974. m.broadcastOn([dismissPopups()], { target });
  20975. });
  20976. if (isNull(OuterContainer.whichView(outerContainer))) {
  20977. editor.focus();
  20978. editor.nodeChanged();
  20979. }
  20980. }
  20981. });
  20982. editor.addQueryValueHandler('ToggleView', () => {
  20983. var _a;
  20984. return (_a = OuterContainer.whichView(outerContainer)) !== null && _a !== void 0 ? _a : '';
  20985. });
  20986. const toolbarMode = getToolbarMode(editor);
  20987. const refreshDrawer = () => {
  20988. OuterContainer.refreshToolbar(uiRefs.mainUi.outerContainer);
  20989. };
  20990. if (toolbarMode === ToolbarMode$1.sliding || toolbarMode === ToolbarMode$1.floating) {
  20991. editor.on('ResizeWindow ResizeEditor ResizeContent', () => {
  20992. const width = editor.getWin().innerWidth;
  20993. if (width !== lastToolbarWidth.get()) {
  20994. refreshDrawer();
  20995. lastToolbarWidth.set(width);
  20996. }
  20997. });
  20998. }
  20999. const api = {
  21000. setEnabled: state => {
  21001. broadcastReadonly(uiRefs, !state);
  21002. },
  21003. isEnabled: () => !Disabling.isDisabled(outerContainer)
  21004. };
  21005. return {
  21006. iframeContainer: socket.element.dom,
  21007. editorContainer: outerContainer.element.dom,
  21008. api
  21009. };
  21010. };
  21011. var Iframe = /*#__PURE__*/Object.freeze({
  21012. __proto__: null,
  21013. render: render$1
  21014. });
  21015. const parseToInt = val => {
  21016. const re = /^[0-9\.]+(|px)$/i;
  21017. if (re.test('' + val)) {
  21018. return Optional.some(parseInt('' + val, 10));
  21019. }
  21020. return Optional.none();
  21021. };
  21022. const numToPx = val => isNumber(val) ? val + 'px' : val;
  21023. const calcCappedSize = (size, minSize, maxSize) => {
  21024. const minOverride = minSize.filter(min => size < min);
  21025. const maxOverride = maxSize.filter(max => size > max);
  21026. return minOverride.or(maxOverride).getOr(size);
  21027. };
  21028. const getHeight = editor => {
  21029. const baseHeight = getHeightOption(editor);
  21030. const minHeight = getMinHeightOption(editor);
  21031. const maxHeight = getMaxHeightOption(editor);
  21032. return parseToInt(baseHeight).map(height => calcCappedSize(height, minHeight, maxHeight));
  21033. };
  21034. const getHeightWithFallback = editor => {
  21035. const height = getHeight(editor);
  21036. return height.getOr(getHeightOption(editor));
  21037. };
  21038. const getWidth = editor => {
  21039. const baseWidth = getWidthOption(editor);
  21040. const minWidth = getMinWidthOption(editor);
  21041. const maxWidth = getMaxWidthOption(editor);
  21042. return parseToInt(baseWidth).map(width => calcCappedSize(width, minWidth, maxWidth));
  21043. };
  21044. const getWidthWithFallback = editor => {
  21045. const width = getWidth(editor);
  21046. return width.getOr(getWidthOption(editor));
  21047. };
  21048. const {ToolbarLocation, ToolbarMode} = Options;
  21049. const InlineHeader = (editor, targetElm, uiRefs, backstage, floatContainer) => {
  21050. const {mainUi, uiMotherships} = uiRefs;
  21051. const DOM = global$7.DOM;
  21052. const useFixedToolbarContainer = useFixedContainer(editor);
  21053. const isSticky = isStickyToolbar(editor);
  21054. const editorMaxWidthOpt = getMaxWidthOption(editor).or(getWidth(editor));
  21055. const headerBackstage = backstage.shared.header;
  21056. const isPositionedAtTop = headerBackstage.isPositionedAtTop;
  21057. const toolbarMode = getToolbarMode(editor);
  21058. const isSplitToolbar = toolbarMode === ToolbarMode.sliding || toolbarMode === ToolbarMode.floating;
  21059. const visible = Cell(false);
  21060. const isVisible = () => visible.get() && !editor.removed;
  21061. const calcToolbarOffset = toolbar => isSplitToolbar ? toolbar.fold(constant$1(0), tbar => tbar.components().length > 1 ? get$d(tbar.components()[1].element) : 0) : 0;
  21062. const calcMode = container => {
  21063. switch (getToolbarLocation(editor)) {
  21064. case ToolbarLocation.auto:
  21065. const toolbar = OuterContainer.getToolbar(mainUi.outerContainer);
  21066. const offset = calcToolbarOffset(toolbar);
  21067. const toolbarHeight = get$d(container.element) - offset;
  21068. const targetBounds = box$1(targetElm);
  21069. const roomAtTop = targetBounds.y > toolbarHeight;
  21070. if (roomAtTop) {
  21071. return 'top';
  21072. } else {
  21073. const doc = documentElement(targetElm);
  21074. const docHeight = Math.max(doc.dom.scrollHeight, get$d(doc));
  21075. const roomAtBottom = targetBounds.bottom < docHeight - toolbarHeight;
  21076. if (roomAtBottom) {
  21077. return 'bottom';
  21078. } else {
  21079. const winBounds = win();
  21080. const isRoomAtBottomViewport = winBounds.bottom < targetBounds.bottom - toolbarHeight;
  21081. return isRoomAtBottomViewport ? 'bottom' : 'top';
  21082. }
  21083. }
  21084. case ToolbarLocation.bottom:
  21085. return 'bottom';
  21086. case ToolbarLocation.top:
  21087. default:
  21088. return 'top';
  21089. }
  21090. };
  21091. const setupMode = mode => {
  21092. floatContainer.on(container => {
  21093. Docking.setModes(container, [mode]);
  21094. headerBackstage.setDockingMode(mode);
  21095. const verticalDir = isPositionedAtTop() ? AttributeValue.TopToBottom : AttributeValue.BottomToTop;
  21096. set$9(container.element, Attribute, verticalDir);
  21097. });
  21098. };
  21099. const updateChromeWidth = () => {
  21100. floatContainer.on(container => {
  21101. const maxWidth = editorMaxWidthOpt.getOrThunk(() => {
  21102. const bodyMargin = parseToInt(get$e(body(), 'margin-left')).getOr(0);
  21103. return get$c(body()) - absolute$3(targetElm).left + bodyMargin;
  21104. });
  21105. set$8(container.element, 'max-width', maxWidth + 'px');
  21106. });
  21107. };
  21108. const updateChromePosition = () => {
  21109. floatContainer.on(container => {
  21110. const toolbar = OuterContainer.getToolbar(mainUi.outerContainer);
  21111. const offset = calcToolbarOffset(toolbar);
  21112. const targetBounds = box$1(targetElm);
  21113. const top = isPositionedAtTop() ? Math.max(targetBounds.y - get$d(container.element) + offset, 0) : targetBounds.bottom;
  21114. setAll(mainUi.outerContainer.element, {
  21115. position: 'absolute',
  21116. top: Math.round(top) + 'px',
  21117. left: Math.round(targetBounds.x) + 'px'
  21118. });
  21119. });
  21120. };
  21121. const repositionPopups$1 = () => {
  21122. each$1(uiMotherships, m => {
  21123. m.broadcastOn([repositionPopups()], {});
  21124. });
  21125. };
  21126. const updateChromeUi = (resetDocking = false) => {
  21127. if (!isVisible()) {
  21128. return;
  21129. }
  21130. if (!useFixedToolbarContainer) {
  21131. updateChromeWidth();
  21132. }
  21133. if (isSplitToolbar) {
  21134. OuterContainer.refreshToolbar(mainUi.outerContainer);
  21135. }
  21136. if (!useFixedToolbarContainer) {
  21137. updateChromePosition();
  21138. }
  21139. if (isSticky) {
  21140. const action = resetDocking ? Docking.reset : Docking.refresh;
  21141. floatContainer.on(action);
  21142. }
  21143. repositionPopups$1();
  21144. };
  21145. const updateMode = (updateUi = true) => {
  21146. if (useFixedToolbarContainer || !isSticky || !isVisible()) {
  21147. return;
  21148. }
  21149. floatContainer.on(container => {
  21150. const currentMode = headerBackstage.getDockingMode();
  21151. const newMode = calcMode(container);
  21152. if (newMode !== currentMode) {
  21153. setupMode(newMode);
  21154. if (updateUi) {
  21155. updateChromeUi(true);
  21156. }
  21157. }
  21158. });
  21159. };
  21160. const show = () => {
  21161. visible.set(true);
  21162. set$8(mainUi.outerContainer.element, 'display', 'flex');
  21163. DOM.addClass(editor.getBody(), 'mce-edit-focus');
  21164. each$1(uiMotherships, m => {
  21165. remove$6(m.element, 'display');
  21166. });
  21167. updateMode(false);
  21168. updateChromeUi();
  21169. };
  21170. const hide = () => {
  21171. visible.set(false);
  21172. set$8(mainUi.outerContainer.element, 'display', 'none');
  21173. DOM.removeClass(editor.getBody(), 'mce-edit-focus');
  21174. each$1(uiMotherships, m => {
  21175. set$8(m.element, 'display', 'none');
  21176. });
  21177. };
  21178. return {
  21179. isVisible,
  21180. isPositionedAtTop,
  21181. show,
  21182. hide,
  21183. update: updateChromeUi,
  21184. updateMode,
  21185. repositionPopups: repositionPopups$1
  21186. };
  21187. };
  21188. const getTargetPosAndBounds = (targetElm, isToolbarTop) => {
  21189. const bounds = box$1(targetElm);
  21190. return {
  21191. pos: isToolbarTop ? bounds.y : bounds.bottom,
  21192. bounds
  21193. };
  21194. };
  21195. const setupEvents = (editor, targetElm, ui, toolbarPersist) => {
  21196. const prevPosAndBounds = Cell(getTargetPosAndBounds(targetElm, ui.isPositionedAtTop()));
  21197. const resizeContent = e => {
  21198. const {pos, bounds} = getTargetPosAndBounds(targetElm, ui.isPositionedAtTop());
  21199. const {
  21200. pos: prevPos,
  21201. bounds: prevBounds
  21202. } = prevPosAndBounds.get();
  21203. const hasResized = bounds.height !== prevBounds.height || bounds.width !== prevBounds.width;
  21204. prevPosAndBounds.set({
  21205. pos,
  21206. bounds
  21207. });
  21208. if (hasResized) {
  21209. fireResizeContent(editor, e);
  21210. }
  21211. if (ui.isVisible()) {
  21212. if (prevPos !== pos) {
  21213. ui.update(true);
  21214. } else if (hasResized) {
  21215. ui.updateMode();
  21216. ui.repositionPopups();
  21217. }
  21218. }
  21219. };
  21220. if (!toolbarPersist) {
  21221. editor.on('activate', ui.show);
  21222. editor.on('deactivate', ui.hide);
  21223. }
  21224. editor.on('SkinLoaded ResizeWindow', () => ui.update(true));
  21225. editor.on('NodeChange keydown', e => {
  21226. requestAnimationFrame(() => resizeContent(e));
  21227. });
  21228. editor.on('ScrollWindow', () => ui.updateMode());
  21229. const elementLoad = unbindable();
  21230. elementLoad.set(capture(SugarElement.fromDom(editor.getBody()), 'load', e => resizeContent(e.raw)));
  21231. editor.on('remove', () => {
  21232. elementLoad.clear();
  21233. });
  21234. };
  21235. const attachUiMotherships = (uiRoot, uiRefs) => {
  21236. attachSystem(uiRoot, uiRefs.dialogUi.mothership);
  21237. };
  21238. const render = (editor, uiRefs, rawUiConfig, backstage, args) => {
  21239. const {mainUi} = uiRefs;
  21240. const floatContainer = value$2();
  21241. const targetElm = SugarElement.fromDom(args.targetNode);
  21242. const ui = InlineHeader(editor, targetElm, uiRefs, backstage, floatContainer);
  21243. const toolbarPersist = isToolbarPersist(editor);
  21244. inline(editor);
  21245. const render = () => {
  21246. if (floatContainer.isSet()) {
  21247. ui.show();
  21248. return;
  21249. }
  21250. floatContainer.set(OuterContainer.getHeader(mainUi.outerContainer).getOrDie());
  21251. const uiContainer = getUiContainer(editor);
  21252. attachSystem(uiContainer, mainUi.mothership);
  21253. attachUiMotherships(uiContainer, uiRefs);
  21254. setToolbar(editor, uiRefs, rawUiConfig, backstage);
  21255. OuterContainer.setMenubar(mainUi.outerContainer, identifyMenus(editor, rawUiConfig));
  21256. ui.show();
  21257. setupEvents(editor, targetElm, ui, toolbarPersist);
  21258. editor.nodeChanged();
  21259. };
  21260. editor.on('show', render);
  21261. editor.on('hide', ui.hide);
  21262. if (!toolbarPersist) {
  21263. editor.on('focus', render);
  21264. editor.on('blur', ui.hide);
  21265. }
  21266. editor.on('init', () => {
  21267. if (editor.hasFocus() || toolbarPersist) {
  21268. render();
  21269. }
  21270. });
  21271. setupReadonlyModeSwitch(editor, uiRefs);
  21272. const api = {
  21273. show: render,
  21274. hide: ui.hide,
  21275. setEnabled: state => {
  21276. broadcastReadonly(uiRefs, !state);
  21277. },
  21278. isEnabled: () => !Disabling.isDisabled(mainUi.outerContainer)
  21279. };
  21280. return {
  21281. editorContainer: mainUi.outerContainer.element.dom,
  21282. api
  21283. };
  21284. };
  21285. var Inline = /*#__PURE__*/Object.freeze({
  21286. __proto__: null,
  21287. render: render
  21288. });
  21289. const LazyUiReferences = () => {
  21290. const dialogUi = value$2();
  21291. const popupUi = value$2();
  21292. const mainUi = value$2();
  21293. const setupDialogUi = ui => {
  21294. dialogUi.set(ui);
  21295. };
  21296. const lazyGetInOuterOrDie = (label, f) => () => mainUi.get().bind(oc => f(oc.outerContainer)).getOrDie(`Could not find ${ label } element in OuterContainer`);
  21297. return {
  21298. dialogUi,
  21299. popupUi,
  21300. mainUi,
  21301. getUiMotherships: () => [...dialogUi.get().map(e => e.mothership).toArray()],
  21302. setupDialogUi,
  21303. lazyGetInOuterOrDie
  21304. };
  21305. };
  21306. const showContextToolbarEvent = 'contexttoolbar-show';
  21307. const hideContextToolbarEvent = 'contexttoolbar-hide';
  21308. const getFormApi = input => ({
  21309. hide: () => emit(input, sandboxClose()),
  21310. getValue: () => Representing.getValue(input)
  21311. });
  21312. const runOnExecute = (memInput, original) => run$1(internalToolbarButtonExecute, (comp, se) => {
  21313. const input = memInput.get(comp);
  21314. const formApi = getFormApi(input);
  21315. original.onAction(formApi, se.event.buttonApi);
  21316. });
  21317. const renderContextButton = (memInput, button, providers) => {
  21318. const {primary, ...rest} = button.original;
  21319. const bridged = getOrDie(createToolbarButton({
  21320. ...rest,
  21321. type: 'button',
  21322. onAction: noop
  21323. }));
  21324. return renderToolbarButtonWith(bridged, providers, [runOnExecute(memInput, button)]);
  21325. };
  21326. const renderContextToggleButton = (memInput, button, providers) => {
  21327. const {primary, ...rest} = button.original;
  21328. const bridged = getOrDie(createToggleButton({
  21329. ...rest,
  21330. type: 'togglebutton',
  21331. onAction: noop
  21332. }));
  21333. return renderToolbarToggleButtonWith(bridged, providers, [runOnExecute(memInput, button)]);
  21334. };
  21335. const isToggleButton = button => button.type === 'contextformtogglebutton';
  21336. const generateOne = (memInput, button, providersBackstage) => {
  21337. if (isToggleButton(button)) {
  21338. return renderContextToggleButton(memInput, button, providersBackstage);
  21339. } else {
  21340. return renderContextButton(memInput, button, providersBackstage);
  21341. }
  21342. };
  21343. const generate = (memInput, buttons, providersBackstage) => {
  21344. const mementos = map$2(buttons, button => record(generateOne(memInput, button, providersBackstage)));
  21345. const asSpecs = () => map$2(mementos, mem => mem.asSpec());
  21346. const findPrimary = compInSystem => findMap(buttons, (button, i) => {
  21347. if (button.primary) {
  21348. return Optional.from(mementos[i]).bind(mem => mem.getOpt(compInSystem)).filter(not(Disabling.isDisabled));
  21349. } else {
  21350. return Optional.none();
  21351. }
  21352. });
  21353. return {
  21354. asSpecs,
  21355. findPrimary
  21356. };
  21357. };
  21358. const buildInitGroups = (ctx, providers) => {
  21359. const inputAttributes = ctx.label.fold(() => ({}), label => ({ 'aria-label': label }));
  21360. const memInput = record(Input.sketch({
  21361. inputClasses: [
  21362. 'tox-toolbar-textfield',
  21363. 'tox-toolbar-nav-js'
  21364. ],
  21365. data: ctx.initValue(),
  21366. inputAttributes,
  21367. selectOnFocus: true,
  21368. inputBehaviours: derive$1([Keying.config({
  21369. mode: 'special',
  21370. onEnter: input => commands.findPrimary(input).map(primary => {
  21371. emitExecute(primary);
  21372. return true;
  21373. }),
  21374. onLeft: (comp, se) => {
  21375. se.cut();
  21376. return Optional.none();
  21377. },
  21378. onRight: (comp, se) => {
  21379. se.cut();
  21380. return Optional.none();
  21381. }
  21382. })])
  21383. }));
  21384. const commands = generate(memInput, ctx.commands, providers);
  21385. return [
  21386. {
  21387. title: Optional.none(),
  21388. items: [memInput.asSpec()]
  21389. },
  21390. {
  21391. title: Optional.none(),
  21392. items: commands.asSpecs()
  21393. }
  21394. ];
  21395. };
  21396. const renderContextForm = (toolbarType, ctx, providers) => renderToolbar({
  21397. type: toolbarType,
  21398. uid: generate$6('context-toolbar'),
  21399. initGroups: buildInitGroups(ctx, providers),
  21400. onEscape: Optional.none,
  21401. cyclicKeying: true,
  21402. providers
  21403. });
  21404. const ContextForm = {
  21405. renderContextForm,
  21406. buildInitGroups
  21407. };
  21408. const isVerticalOverlap = (a, b, threshold) => b.bottom - a.y >= threshold && a.bottom - b.y >= threshold;
  21409. const getRangeRect = rng => {
  21410. const rect = rng.getBoundingClientRect();
  21411. if (rect.height <= 0 && rect.width <= 0) {
  21412. const leaf$1 = leaf(SugarElement.fromDom(rng.startContainer), rng.startOffset).element;
  21413. const elm = isText(leaf$1) ? parent(leaf$1) : Optional.some(leaf$1);
  21414. return elm.filter(isElement$1).map(e => e.dom.getBoundingClientRect()).getOr(rect);
  21415. } else {
  21416. return rect;
  21417. }
  21418. };
  21419. const getSelectionBounds = editor => {
  21420. const rng = editor.selection.getRng();
  21421. const rect = getRangeRect(rng);
  21422. if (editor.inline) {
  21423. const scroll = get$b();
  21424. return bounds(scroll.left + rect.left, scroll.top + rect.top, rect.width, rect.height);
  21425. } else {
  21426. const bodyPos = absolute$2(SugarElement.fromDom(editor.getBody()));
  21427. return bounds(bodyPos.x + rect.left, bodyPos.y + rect.top, rect.width, rect.height);
  21428. }
  21429. };
  21430. const getAnchorElementBounds = (editor, lastElement) => lastElement.filter(elem => inBody(elem) && isHTMLElement(elem)).map(absolute$2).getOrThunk(() => getSelectionBounds(editor));
  21431. const getHorizontalBounds = (contentAreaBox, viewportBounds, margin) => {
  21432. const x = Math.max(contentAreaBox.x + margin, viewportBounds.x);
  21433. const right = Math.min(contentAreaBox.right - margin, viewportBounds.right);
  21434. return {
  21435. x,
  21436. width: right - x
  21437. };
  21438. };
  21439. const getVerticalBounds = (editor, contentAreaBox, viewportBounds, isToolbarLocationTop, toolbarType, margin) => {
  21440. const container = SugarElement.fromDom(editor.getContainer());
  21441. const header = descendant(container, '.tox-editor-header').getOr(container);
  21442. const headerBox = box$1(header);
  21443. const isToolbarBelowContentArea = headerBox.y >= contentAreaBox.bottom;
  21444. const isToolbarAbove = isToolbarLocationTop && !isToolbarBelowContentArea;
  21445. if (editor.inline && isToolbarAbove) {
  21446. return {
  21447. y: Math.max(headerBox.bottom + margin, viewportBounds.y),
  21448. bottom: viewportBounds.bottom
  21449. };
  21450. }
  21451. if (editor.inline && !isToolbarAbove) {
  21452. return {
  21453. y: viewportBounds.y,
  21454. bottom: Math.min(headerBox.y - margin, viewportBounds.bottom)
  21455. };
  21456. }
  21457. const containerBounds = toolbarType === 'line' ? box$1(container) : contentAreaBox;
  21458. if (isToolbarAbove) {
  21459. return {
  21460. y: Math.max(headerBox.bottom + margin, viewportBounds.y),
  21461. bottom: Math.min(containerBounds.bottom - margin, viewportBounds.bottom)
  21462. };
  21463. }
  21464. return {
  21465. y: Math.max(containerBounds.y + margin, viewportBounds.y),
  21466. bottom: Math.min(headerBox.y - margin, viewportBounds.bottom)
  21467. };
  21468. };
  21469. const getContextToolbarBounds = (editor, sharedBackstage, toolbarType, margin = 0) => {
  21470. const viewportBounds = getBounds$3(window);
  21471. const contentAreaBox = box$1(SugarElement.fromDom(editor.getContentAreaContainer()));
  21472. const toolbarOrMenubarEnabled = isMenubarEnabled(editor) || isToolbarEnabled(editor) || isMultipleToolbars(editor);
  21473. const {x, width} = getHorizontalBounds(contentAreaBox, viewportBounds, margin);
  21474. if (editor.inline && !toolbarOrMenubarEnabled) {
  21475. return bounds(x, viewportBounds.y, width, viewportBounds.height);
  21476. } else {
  21477. const isToolbarTop = sharedBackstage.header.isPositionedAtTop();
  21478. const {y, bottom} = getVerticalBounds(editor, contentAreaBox, viewportBounds, isToolbarTop, toolbarType, margin);
  21479. return bounds(x, y, width, bottom - y);
  21480. }
  21481. };
  21482. const bubbleSize$1 = 12;
  21483. const bubbleAlignments$1 = {
  21484. valignCentre: [],
  21485. alignCentre: [],
  21486. alignLeft: ['tox-pop--align-left'],
  21487. alignRight: ['tox-pop--align-right'],
  21488. right: ['tox-pop--right'],
  21489. left: ['tox-pop--left'],
  21490. bottom: ['tox-pop--bottom'],
  21491. top: ['tox-pop--top'],
  21492. inset: ['tox-pop--inset']
  21493. };
  21494. const anchorOverrides = {
  21495. maxHeightFunction: expandable$1(),
  21496. maxWidthFunction: expandable()
  21497. };
  21498. const isEntireElementSelected = (editor, elem) => {
  21499. const rng = editor.selection.getRng();
  21500. const leaf$1 = leaf(SugarElement.fromDom(rng.startContainer), rng.startOffset);
  21501. return rng.startContainer === rng.endContainer && rng.startOffset === rng.endOffset - 1 && eq(leaf$1.element, elem);
  21502. };
  21503. const preservePosition = (elem, position, f) => {
  21504. const currentPosition = getRaw(elem, 'position');
  21505. set$8(elem, 'position', position);
  21506. const result = f(elem);
  21507. currentPosition.each(pos => set$8(elem, 'position', pos));
  21508. return result;
  21509. };
  21510. const shouldUseInsetLayouts = position => position === 'node';
  21511. const determineInsetLayout = (editor, contextbar, elem, data, bounds) => {
  21512. const selectionBounds = getSelectionBounds(editor);
  21513. const isSameAnchorElement = data.lastElement().exists(prev => eq(elem, prev));
  21514. if (isEntireElementSelected(editor, elem)) {
  21515. return isSameAnchorElement ? preserve : north;
  21516. } else if (isSameAnchorElement) {
  21517. return preservePosition(contextbar, data.getMode(), () => {
  21518. const isOverlapping = isVerticalOverlap(selectionBounds, box$1(contextbar), -20);
  21519. return isOverlapping && !data.isReposition() ? flip : preserve;
  21520. });
  21521. } else {
  21522. const yBounds = data.getMode() === 'fixed' ? bounds.y + get$b().top : bounds.y;
  21523. const contextbarHeight = get$d(contextbar) + bubbleSize$1;
  21524. return yBounds + contextbarHeight <= selectionBounds.y ? north : south;
  21525. }
  21526. };
  21527. const getAnchorSpec$2 = (editor, mobile, data, position) => {
  21528. const smartInsetLayout = elem => (anchor, element, bubbles, placee, bounds) => {
  21529. const layout = determineInsetLayout(editor, placee, elem, data, bounds);
  21530. const newAnchor = {
  21531. ...anchor,
  21532. y: bounds.y,
  21533. height: bounds.height
  21534. };
  21535. return {
  21536. ...layout(newAnchor, element, bubbles, placee, bounds),
  21537. alwaysFit: true
  21538. };
  21539. };
  21540. const getInsetLayouts = elem => shouldUseInsetLayouts(position) ? [smartInsetLayout(elem)] : [];
  21541. const desktopAnchorSpecLayouts = {
  21542. onLtr: elem => [
  21543. north$2,
  21544. south$2,
  21545. northeast$2,
  21546. southeast$2,
  21547. northwest$2,
  21548. southwest$2
  21549. ].concat(getInsetLayouts(elem)),
  21550. onRtl: elem => [
  21551. north$2,
  21552. south$2,
  21553. northwest$2,
  21554. southwest$2,
  21555. northeast$2,
  21556. southeast$2
  21557. ].concat(getInsetLayouts(elem))
  21558. };
  21559. const mobileAnchorSpecLayouts = {
  21560. onLtr: elem => [
  21561. south$2,
  21562. southeast$2,
  21563. southwest$2,
  21564. northeast$2,
  21565. northwest$2,
  21566. north$2
  21567. ].concat(getInsetLayouts(elem)),
  21568. onRtl: elem => [
  21569. south$2,
  21570. southwest$2,
  21571. southeast$2,
  21572. northwest$2,
  21573. northeast$2,
  21574. north$2
  21575. ].concat(getInsetLayouts(elem))
  21576. };
  21577. return mobile ? mobileAnchorSpecLayouts : desktopAnchorSpecLayouts;
  21578. };
  21579. const getAnchorLayout = (editor, position, isTouch, data) => {
  21580. if (position === 'line') {
  21581. return {
  21582. bubble: nu$5(bubbleSize$1, 0, bubbleAlignments$1),
  21583. layouts: {
  21584. onLtr: () => [east$2],
  21585. onRtl: () => [west$2]
  21586. },
  21587. overrides: anchorOverrides
  21588. };
  21589. } else {
  21590. return {
  21591. bubble: nu$5(0, bubbleSize$1, bubbleAlignments$1, 1 / bubbleSize$1),
  21592. layouts: getAnchorSpec$2(editor, isTouch, data, position),
  21593. overrides: anchorOverrides
  21594. };
  21595. }
  21596. };
  21597. const matchTargetWith = (elem, candidates) => {
  21598. const ctxs = filter$2(candidates, toolbarApi => toolbarApi.predicate(elem.dom));
  21599. const {pass, fail} = partition$3(ctxs, t => t.type === 'contexttoolbar');
  21600. return {
  21601. contextToolbars: pass,
  21602. contextForms: fail
  21603. };
  21604. };
  21605. const filterByPositionForStartNode = toolbars => {
  21606. if (toolbars.length <= 1) {
  21607. return toolbars;
  21608. } else {
  21609. const doesPositionExist = value => exists(toolbars, t => t.position === value);
  21610. const filterToolbarsByPosition = value => filter$2(toolbars, t => t.position === value);
  21611. const hasSelectionToolbars = doesPositionExist('selection');
  21612. const hasNodeToolbars = doesPositionExist('node');
  21613. if (hasSelectionToolbars || hasNodeToolbars) {
  21614. if (hasNodeToolbars && hasSelectionToolbars) {
  21615. const nodeToolbars = filterToolbarsByPosition('node');
  21616. const selectionToolbars = map$2(filterToolbarsByPosition('selection'), t => ({
  21617. ...t,
  21618. position: 'node'
  21619. }));
  21620. return nodeToolbars.concat(selectionToolbars);
  21621. } else {
  21622. return hasSelectionToolbars ? filterToolbarsByPosition('selection') : filterToolbarsByPosition('node');
  21623. }
  21624. } else {
  21625. return filterToolbarsByPosition('line');
  21626. }
  21627. }
  21628. };
  21629. const filterByPositionForAncestorNode = toolbars => {
  21630. if (toolbars.length <= 1) {
  21631. return toolbars;
  21632. } else {
  21633. const findPosition = value => find$5(toolbars, t => t.position === value);
  21634. const basePosition = findPosition('selection').orThunk(() => findPosition('node')).orThunk(() => findPosition('line')).map(t => t.position);
  21635. return basePosition.fold(() => [], pos => filter$2(toolbars, t => t.position === pos));
  21636. }
  21637. };
  21638. const matchStartNode = (elem, nodeCandidates, editorCandidates) => {
  21639. const nodeMatches = matchTargetWith(elem, nodeCandidates);
  21640. if (nodeMatches.contextForms.length > 0) {
  21641. return Optional.some({
  21642. elem,
  21643. toolbars: [nodeMatches.contextForms[0]]
  21644. });
  21645. } else {
  21646. const editorMatches = matchTargetWith(elem, editorCandidates);
  21647. if (editorMatches.contextForms.length > 0) {
  21648. return Optional.some({
  21649. elem,
  21650. toolbars: [editorMatches.contextForms[0]]
  21651. });
  21652. } else if (nodeMatches.contextToolbars.length > 0 || editorMatches.contextToolbars.length > 0) {
  21653. const toolbars = filterByPositionForStartNode(nodeMatches.contextToolbars.concat(editorMatches.contextToolbars));
  21654. return Optional.some({
  21655. elem,
  21656. toolbars
  21657. });
  21658. } else {
  21659. return Optional.none();
  21660. }
  21661. }
  21662. };
  21663. const matchAncestor = (isRoot, startNode, scopes) => {
  21664. if (isRoot(startNode)) {
  21665. return Optional.none();
  21666. } else {
  21667. return ancestor$2(startNode, ancestorElem => {
  21668. if (isElement$1(ancestorElem)) {
  21669. const {contextToolbars, contextForms} = matchTargetWith(ancestorElem, scopes.inNodeScope);
  21670. const toolbars = contextForms.length > 0 ? contextForms : filterByPositionForAncestorNode(contextToolbars);
  21671. return toolbars.length > 0 ? Optional.some({
  21672. elem: ancestorElem,
  21673. toolbars
  21674. }) : Optional.none();
  21675. } else {
  21676. return Optional.none();
  21677. }
  21678. }, isRoot);
  21679. }
  21680. };
  21681. const lookup$1 = (scopes, editor) => {
  21682. const rootElem = SugarElement.fromDom(editor.getBody());
  21683. const isRoot = elem => eq(elem, rootElem);
  21684. const isOutsideRoot = startNode => !isRoot(startNode) && !contains(rootElem, startNode);
  21685. const startNode = SugarElement.fromDom(editor.selection.getNode());
  21686. if (isOutsideRoot(startNode)) {
  21687. return Optional.none();
  21688. }
  21689. return matchStartNode(startNode, scopes.inNodeScope, scopes.inEditorScope).orThunk(() => matchAncestor(isRoot, startNode, scopes));
  21690. };
  21691. const categorise = (contextToolbars, navigate) => {
  21692. const forms = {};
  21693. const inNodeScope = [];
  21694. const inEditorScope = [];
  21695. const formNavigators = {};
  21696. const lookupTable = {};
  21697. const registerForm = (key, toolbarSpec) => {
  21698. const contextForm = getOrDie(createContextForm(toolbarSpec));
  21699. forms[key] = contextForm;
  21700. contextForm.launch.map(launch => {
  21701. formNavigators['form:' + key + ''] = {
  21702. ...toolbarSpec.launch,
  21703. type: launch.type === 'contextformtogglebutton' ? 'togglebutton' : 'button',
  21704. onAction: () => {
  21705. navigate(contextForm);
  21706. }
  21707. };
  21708. });
  21709. if (contextForm.scope === 'editor') {
  21710. inEditorScope.push(contextForm);
  21711. } else {
  21712. inNodeScope.push(contextForm);
  21713. }
  21714. lookupTable[key] = contextForm;
  21715. };
  21716. const registerToolbar = (key, toolbarSpec) => {
  21717. createContextToolbar(toolbarSpec).each(contextToolbar => {
  21718. if (toolbarSpec.scope === 'editor') {
  21719. inEditorScope.push(contextToolbar);
  21720. } else {
  21721. inNodeScope.push(contextToolbar);
  21722. }
  21723. lookupTable[key] = contextToolbar;
  21724. });
  21725. };
  21726. const keys$1 = keys(contextToolbars);
  21727. each$1(keys$1, key => {
  21728. const toolbarApi = contextToolbars[key];
  21729. if (toolbarApi.type === 'contextform') {
  21730. registerForm(key, toolbarApi);
  21731. } else if (toolbarApi.type === 'contexttoolbar') {
  21732. registerToolbar(key, toolbarApi);
  21733. }
  21734. });
  21735. return {
  21736. forms,
  21737. inNodeScope,
  21738. inEditorScope,
  21739. lookupTable,
  21740. formNavigators
  21741. };
  21742. };
  21743. const forwardSlideEvent = generate$6('forward-slide');
  21744. const backSlideEvent = generate$6('backward-slide');
  21745. const changeSlideEvent = generate$6('change-slide-event');
  21746. const resizingClass = 'tox-pop--resizing';
  21747. const renderContextToolbar = spec => {
  21748. const stack = Cell([]);
  21749. return InlineView.sketch({
  21750. dom: {
  21751. tag: 'div',
  21752. classes: ['tox-pop']
  21753. },
  21754. fireDismissalEventInstead: { event: 'doNotDismissYet' },
  21755. onShow: comp => {
  21756. stack.set([]);
  21757. InlineView.getContent(comp).each(c => {
  21758. remove$6(c.element, 'visibility');
  21759. });
  21760. remove$2(comp.element, resizingClass);
  21761. remove$6(comp.element, 'width');
  21762. },
  21763. inlineBehaviours: derive$1([
  21764. config('context-toolbar-events', [
  21765. runOnSource(transitionend(), (comp, se) => {
  21766. if (se.event.raw.propertyName === 'width') {
  21767. remove$2(comp.element, resizingClass);
  21768. remove$6(comp.element, 'width');
  21769. }
  21770. }),
  21771. run$1(changeSlideEvent, (comp, se) => {
  21772. const elem = comp.element;
  21773. remove$6(elem, 'width');
  21774. const currentWidth = get$c(elem);
  21775. InlineView.setContent(comp, se.event.contents);
  21776. add$2(elem, resizingClass);
  21777. const newWidth = get$c(elem);
  21778. set$8(elem, 'width', currentWidth + 'px');
  21779. InlineView.getContent(comp).each(newContents => {
  21780. se.event.focus.bind(f => {
  21781. focus$3(f);
  21782. return search(elem);
  21783. }).orThunk(() => {
  21784. Keying.focusIn(newContents);
  21785. return active$1(getRootNode(elem));
  21786. });
  21787. });
  21788. setTimeout(() => {
  21789. set$8(comp.element, 'width', newWidth + 'px');
  21790. }, 0);
  21791. }),
  21792. run$1(forwardSlideEvent, (comp, se) => {
  21793. InlineView.getContent(comp).each(oldContents => {
  21794. stack.set(stack.get().concat([{
  21795. bar: oldContents,
  21796. focus: active$1(getRootNode(comp.element))
  21797. }]));
  21798. });
  21799. emitWith(comp, changeSlideEvent, {
  21800. contents: se.event.forwardContents,
  21801. focus: Optional.none()
  21802. });
  21803. }),
  21804. run$1(backSlideEvent, (comp, _se) => {
  21805. last$1(stack.get()).each(last => {
  21806. stack.set(stack.get().slice(0, stack.get().length - 1));
  21807. emitWith(comp, changeSlideEvent, {
  21808. contents: premade(last.bar),
  21809. focus: last.focus
  21810. });
  21811. });
  21812. })
  21813. ]),
  21814. Keying.config({
  21815. mode: 'special',
  21816. onEscape: comp => last$1(stack.get()).fold(() => spec.onEscape(), _ => {
  21817. emit(comp, backSlideEvent);
  21818. return Optional.some(true);
  21819. })
  21820. })
  21821. ]),
  21822. lazySink: () => Result.value(spec.sink)
  21823. });
  21824. };
  21825. const transitionClass = 'tox-pop--transition';
  21826. const register$9 = (editor, registryContextToolbars, sink, extras) => {
  21827. const backstage = extras.backstage;
  21828. const sharedBackstage = backstage.shared;
  21829. const isTouch = detect$1().deviceType.isTouch;
  21830. const lastElement = value$2();
  21831. const lastTrigger = value$2();
  21832. const lastContextPosition = value$2();
  21833. const contextbar = build$1(renderContextToolbar({
  21834. sink,
  21835. onEscape: () => {
  21836. editor.focus();
  21837. return Optional.some(true);
  21838. }
  21839. }));
  21840. const getBounds = () => {
  21841. const position = lastContextPosition.get().getOr('node');
  21842. const margin = shouldUseInsetLayouts(position) ? 1 : 0;
  21843. return getContextToolbarBounds(editor, sharedBackstage, position, margin);
  21844. };
  21845. const canLaunchToolbar = () => {
  21846. return !editor.removed && !(isTouch() && backstage.isContextMenuOpen());
  21847. };
  21848. const isSameLaunchElement = elem => is$1(lift2(elem, lastElement.get(), eq), true);
  21849. const shouldContextToolbarHide = () => {
  21850. if (!canLaunchToolbar()) {
  21851. return true;
  21852. } else {
  21853. const contextToolbarBounds = getBounds();
  21854. const anchorBounds = is$1(lastContextPosition.get(), 'node') ? getAnchorElementBounds(editor, lastElement.get()) : getSelectionBounds(editor);
  21855. return contextToolbarBounds.height <= 0 || !isVerticalOverlap(anchorBounds, contextToolbarBounds, 0.01);
  21856. }
  21857. };
  21858. const close = () => {
  21859. lastElement.clear();
  21860. lastTrigger.clear();
  21861. lastContextPosition.clear();
  21862. InlineView.hide(contextbar);
  21863. };
  21864. const hideOrRepositionIfNecessary = () => {
  21865. if (InlineView.isOpen(contextbar)) {
  21866. const contextBarEle = contextbar.element;
  21867. remove$6(contextBarEle, 'display');
  21868. if (shouldContextToolbarHide()) {
  21869. set$8(contextBarEle, 'display', 'none');
  21870. } else {
  21871. lastTrigger.set(0);
  21872. InlineView.reposition(contextbar);
  21873. }
  21874. }
  21875. };
  21876. const wrapInPopDialog = toolbarSpec => ({
  21877. dom: {
  21878. tag: 'div',
  21879. classes: ['tox-pop__dialog']
  21880. },
  21881. components: [toolbarSpec],
  21882. behaviours: derive$1([
  21883. Keying.config({ mode: 'acyclic' }),
  21884. config('pop-dialog-wrap-events', [
  21885. runOnAttached(comp => {
  21886. editor.shortcuts.add('ctrl+F9', 'focus statusbar', () => Keying.focusIn(comp));
  21887. }),
  21888. runOnDetached(_comp => {
  21889. editor.shortcuts.remove('ctrl+F9');
  21890. })
  21891. ])
  21892. ])
  21893. });
  21894. const getScopes = cached(() => categorise(registryContextToolbars, toolbarApi => {
  21895. const alloySpec = buildToolbar([toolbarApi]);
  21896. emitWith(contextbar, forwardSlideEvent, { forwardContents: wrapInPopDialog(alloySpec) });
  21897. }));
  21898. const buildContextToolbarGroups = (allButtons, ctx) => identifyButtons(editor, {
  21899. buttons: allButtons,
  21900. toolbar: ctx.items,
  21901. allowToolbarGroups: false
  21902. }, extras.backstage, Optional.some(['form:']));
  21903. const buildContextFormGroups = (ctx, providers) => ContextForm.buildInitGroups(ctx, providers);
  21904. const buildToolbar = toolbars => {
  21905. const {buttons} = editor.ui.registry.getAll();
  21906. const scopes = getScopes();
  21907. const allButtons = {
  21908. ...buttons,
  21909. ...scopes.formNavigators
  21910. };
  21911. const toolbarType = getToolbarMode(editor) === ToolbarMode$1.scrolling ? ToolbarMode$1.scrolling : ToolbarMode$1.default;
  21912. const initGroups = flatten(map$2(toolbars, ctx => ctx.type === 'contexttoolbar' ? buildContextToolbarGroups(allButtons, ctx) : buildContextFormGroups(ctx, sharedBackstage.providers)));
  21913. return renderToolbar({
  21914. type: toolbarType,
  21915. uid: generate$6('context-toolbar'),
  21916. initGroups,
  21917. onEscape: Optional.none,
  21918. cyclicKeying: true,
  21919. providers: sharedBackstage.providers
  21920. });
  21921. };
  21922. const getAnchor = (position, element) => {
  21923. const anchorage = position === 'node' ? sharedBackstage.anchors.node(element) : sharedBackstage.anchors.cursor();
  21924. const anchorLayout = getAnchorLayout(editor, position, isTouch(), {
  21925. lastElement: lastElement.get,
  21926. isReposition: () => is$1(lastTrigger.get(), 0),
  21927. getMode: () => Positioning.getMode(sink)
  21928. });
  21929. return deepMerge(anchorage, anchorLayout);
  21930. };
  21931. const launchContext = (toolbarApi, elem) => {
  21932. launchContextToolbar.cancel();
  21933. if (!canLaunchToolbar()) {
  21934. return;
  21935. }
  21936. const toolbarSpec = buildToolbar(toolbarApi);
  21937. const position = toolbarApi[0].position;
  21938. const anchor = getAnchor(position, elem);
  21939. lastContextPosition.set(position);
  21940. lastTrigger.set(1);
  21941. const contextBarEle = contextbar.element;
  21942. remove$6(contextBarEle, 'display');
  21943. if (!isSameLaunchElement(elem)) {
  21944. remove$2(contextBarEle, transitionClass);
  21945. Positioning.reset(sink, contextbar);
  21946. }
  21947. InlineView.showWithinBounds(contextbar, wrapInPopDialog(toolbarSpec), {
  21948. anchor,
  21949. transition: {
  21950. classes: [transitionClass],
  21951. mode: 'placement'
  21952. }
  21953. }, () => Optional.some(getBounds()));
  21954. elem.fold(lastElement.clear, lastElement.set);
  21955. if (shouldContextToolbarHide()) {
  21956. set$8(contextBarEle, 'display', 'none');
  21957. }
  21958. };
  21959. const launchContextToolbar = last(() => {
  21960. if (!editor.hasFocus() || editor.removed) {
  21961. return;
  21962. }
  21963. if (has(contextbar.element, transitionClass)) {
  21964. launchContextToolbar.throttle();
  21965. } else {
  21966. const scopes = getScopes();
  21967. lookup$1(scopes, editor).fold(close, info => {
  21968. launchContext(info.toolbars, Optional.some(info.elem));
  21969. });
  21970. }
  21971. }, 17);
  21972. editor.on('init', () => {
  21973. editor.on('remove', close);
  21974. editor.on('ScrollContent ScrollWindow ObjectResized ResizeEditor longpress', hideOrRepositionIfNecessary);
  21975. editor.on('click keyup focus SetContent', launchContextToolbar.throttle);
  21976. editor.on(hideContextToolbarEvent, close);
  21977. editor.on(showContextToolbarEvent, e => {
  21978. const scopes = getScopes();
  21979. get$g(scopes.lookupTable, e.toolbarKey).each(ctx => {
  21980. launchContext([ctx], someIf(e.target !== editor, e.target));
  21981. InlineView.getContent(contextbar).each(Keying.focusIn);
  21982. });
  21983. });
  21984. editor.on('focusout', _e => {
  21985. global$9.setEditorTimeout(editor, () => {
  21986. if (search(sink.element).isNone() && search(contextbar.element).isNone()) {
  21987. close();
  21988. }
  21989. }, 0);
  21990. });
  21991. editor.on('SwitchMode', () => {
  21992. if (editor.mode.isReadOnly()) {
  21993. close();
  21994. }
  21995. });
  21996. editor.on('AfterProgressState', event => {
  21997. if (event.state) {
  21998. close();
  21999. } else if (editor.hasFocus()) {
  22000. launchContextToolbar.throttle();
  22001. }
  22002. });
  22003. editor.on('NodeChange', _e => {
  22004. search(contextbar.element).fold(launchContextToolbar.throttle, noop);
  22005. });
  22006. });
  22007. };
  22008. const register$8 = editor => {
  22009. const alignToolbarButtons = [
  22010. {
  22011. name: 'alignleft',
  22012. text: 'Align left',
  22013. cmd: 'JustifyLeft',
  22014. icon: 'align-left'
  22015. },
  22016. {
  22017. name: 'aligncenter',
  22018. text: 'Align center',
  22019. cmd: 'JustifyCenter',
  22020. icon: 'align-center'
  22021. },
  22022. {
  22023. name: 'alignright',
  22024. text: 'Align right',
  22025. cmd: 'JustifyRight',
  22026. icon: 'align-right'
  22027. },
  22028. {
  22029. name: 'alignjustify',
  22030. text: 'Justify',
  22031. cmd: 'JustifyFull',
  22032. icon: 'align-justify'
  22033. }
  22034. ];
  22035. each$1(alignToolbarButtons, item => {
  22036. editor.ui.registry.addToggleButton(item.name, {
  22037. tooltip: item.text,
  22038. icon: item.icon,
  22039. onAction: onActionExecCommand(editor, item.cmd),
  22040. onSetup: onSetupFormatToggle(editor, item.name)
  22041. });
  22042. });
  22043. editor.ui.registry.addButton('alignnone', {
  22044. tooltip: 'No alignment',
  22045. icon: 'align-none',
  22046. onAction: onActionExecCommand(editor, 'JustifyNone')
  22047. });
  22048. };
  22049. const units = {
  22050. unsupportedLength: [
  22051. 'em',
  22052. 'ex',
  22053. 'cap',
  22054. 'ch',
  22055. 'ic',
  22056. 'rem',
  22057. 'lh',
  22058. 'rlh',
  22059. 'vw',
  22060. 'vh',
  22061. 'vi',
  22062. 'vb',
  22063. 'vmin',
  22064. 'vmax',
  22065. 'cm',
  22066. 'mm',
  22067. 'Q',
  22068. 'in',
  22069. 'pc',
  22070. 'pt',
  22071. 'px'
  22072. ],
  22073. fixed: [
  22074. 'px',
  22075. 'pt'
  22076. ],
  22077. relative: ['%'],
  22078. empty: ['']
  22079. };
  22080. const pattern = (() => {
  22081. const decimalDigits = '[0-9]+';
  22082. const signedInteger = '[+-]?' + decimalDigits;
  22083. const exponentPart = '[eE]' + signedInteger;
  22084. const dot = '\\.';
  22085. const opt = input => `(?:${ input })?`;
  22086. const unsignedDecimalLiteral = [
  22087. 'Infinity',
  22088. decimalDigits + dot + opt(decimalDigits) + opt(exponentPart),
  22089. dot + decimalDigits + opt(exponentPart),
  22090. decimalDigits + opt(exponentPart)
  22091. ].join('|');
  22092. const float = `[+-]?(?:${ unsignedDecimalLiteral })`;
  22093. return new RegExp(`^(${ float })(.*)$`);
  22094. })();
  22095. const isUnit = (unit, accepted) => exists(accepted, acc => exists(units[acc], check => unit === check));
  22096. const parse = (input, accepted) => {
  22097. const match = Optional.from(pattern.exec(input));
  22098. return match.bind(array => {
  22099. const value = Number(array[1]);
  22100. const unitRaw = array[2];
  22101. if (isUnit(unitRaw, accepted)) {
  22102. return Optional.some({
  22103. value,
  22104. unit: unitRaw
  22105. });
  22106. } else {
  22107. return Optional.none();
  22108. }
  22109. });
  22110. };
  22111. const normalise = (input, accepted) => parse(input, accepted).map(({value, unit}) => value + unit);
  22112. const registerController = (editor, spec) => {
  22113. const getMenuItems = () => {
  22114. const options = spec.getOptions(editor);
  22115. const initial = spec.getCurrent(editor).map(spec.hash);
  22116. const current = value$2();
  22117. return map$2(options, value => ({
  22118. type: 'togglemenuitem',
  22119. text: spec.display(value),
  22120. onSetup: api => {
  22121. const setActive = active => {
  22122. if (active) {
  22123. current.on(oldApi => oldApi.setActive(false));
  22124. current.set(api);
  22125. }
  22126. api.setActive(active);
  22127. };
  22128. setActive(is$1(initial, spec.hash(value)));
  22129. const unbindWatcher = spec.watcher(editor, value, setActive);
  22130. return () => {
  22131. current.clear();
  22132. unbindWatcher();
  22133. };
  22134. },
  22135. onAction: () => spec.setCurrent(editor, value)
  22136. }));
  22137. };
  22138. editor.ui.registry.addMenuButton(spec.name, {
  22139. tooltip: spec.text,
  22140. icon: spec.icon,
  22141. fetch: callback => callback(getMenuItems()),
  22142. onSetup: spec.onToolbarSetup
  22143. });
  22144. editor.ui.registry.addNestedMenuItem(spec.name, {
  22145. type: 'nestedmenuitem',
  22146. text: spec.text,
  22147. getSubmenuItems: getMenuItems,
  22148. onSetup: spec.onMenuSetup
  22149. });
  22150. };
  22151. const lineHeightSpec = {
  22152. name: 'lineheight',
  22153. text: 'Line height',
  22154. icon: 'line-height',
  22155. getOptions: getLineHeightFormats,
  22156. hash: input => normalise(input, [
  22157. 'fixed',
  22158. 'relative',
  22159. 'empty'
  22160. ]).getOr(input),
  22161. display: identity,
  22162. watcher: (editor, value, callback) => editor.formatter.formatChanged('lineheight', callback, false, { value }).unbind,
  22163. getCurrent: editor => Optional.from(editor.queryCommandValue('LineHeight')),
  22164. setCurrent: (editor, value) => editor.execCommand('LineHeight', false, value)
  22165. };
  22166. const languageSpec = editor => {
  22167. const settingsOpt = Optional.from(getContentLanguages(editor));
  22168. return settingsOpt.map(settings => ({
  22169. name: 'language',
  22170. text: 'Language',
  22171. icon: 'language',
  22172. getOptions: constant$1(settings),
  22173. hash: input => isUndefined(input.customCode) ? input.code : `${ input.code }/${ input.customCode }`,
  22174. display: input => input.title,
  22175. watcher: (editor, value, callback) => {
  22176. var _a;
  22177. return editor.formatter.formatChanged('lang', callback, false, {
  22178. value: value.code,
  22179. customValue: (_a = value.customCode) !== null && _a !== void 0 ? _a : null
  22180. }).unbind;
  22181. },
  22182. getCurrent: editor => {
  22183. const node = SugarElement.fromDom(editor.selection.getNode());
  22184. return closest$4(node, n => Optional.some(n).filter(isElement$1).bind(ele => {
  22185. const codeOpt = getOpt(ele, 'lang');
  22186. return codeOpt.map(code => {
  22187. const customCode = getOpt(ele, 'data-mce-lang').getOrUndefined();
  22188. return {
  22189. code,
  22190. customCode,
  22191. title: ''
  22192. };
  22193. });
  22194. }));
  22195. },
  22196. setCurrent: (editor, lang) => editor.execCommand('Lang', false, lang),
  22197. onToolbarSetup: api => {
  22198. const unbinder = unbindable();
  22199. api.setActive(editor.formatter.match('lang', {}, undefined, true));
  22200. unbinder.set(editor.formatter.formatChanged('lang', api.setActive, true));
  22201. return unbinder.clear;
  22202. }
  22203. }));
  22204. };
  22205. const register$7 = editor => {
  22206. registerController(editor, lineHeightSpec);
  22207. languageSpec(editor).each(spec => registerController(editor, spec));
  22208. };
  22209. const register$6 = (editor, backstage) => {
  22210. createAlignMenu(editor, backstage);
  22211. createFontFamilyMenu(editor, backstage);
  22212. createStylesMenu(editor, backstage);
  22213. createBlocksMenu(editor, backstage);
  22214. createFontSizeMenu(editor, backstage);
  22215. };
  22216. const onSetupOutdentState = editor => onSetupEvent(editor, 'NodeChange', api => {
  22217. api.setEnabled(editor.queryCommandState('outdent'));
  22218. });
  22219. const registerButtons$2 = editor => {
  22220. editor.ui.registry.addButton('outdent', {
  22221. tooltip: 'Decrease indent',
  22222. icon: 'outdent',
  22223. onSetup: onSetupOutdentState(editor),
  22224. onAction: onActionExecCommand(editor, 'outdent')
  22225. });
  22226. editor.ui.registry.addButton('indent', {
  22227. tooltip: 'Increase indent',
  22228. icon: 'indent',
  22229. onAction: onActionExecCommand(editor, 'indent')
  22230. });
  22231. };
  22232. const register$5 = editor => {
  22233. registerButtons$2(editor);
  22234. };
  22235. const makeSetupHandler = (editor, pasteAsText) => api => {
  22236. api.setActive(pasteAsText.get());
  22237. const pastePlainTextToggleHandler = e => {
  22238. pasteAsText.set(e.state);
  22239. api.setActive(e.state);
  22240. };
  22241. editor.on('PastePlainTextToggle', pastePlainTextToggleHandler);
  22242. return () => editor.off('PastePlainTextToggle', pastePlainTextToggleHandler);
  22243. };
  22244. const register$4 = editor => {
  22245. const pasteAsText = Cell(getPasteAsText(editor));
  22246. const onAction = () => editor.execCommand('mceTogglePlainTextPaste');
  22247. editor.ui.registry.addToggleButton('pastetext', {
  22248. active: false,
  22249. icon: 'paste-text',
  22250. tooltip: 'Paste as text',
  22251. onAction,
  22252. onSetup: makeSetupHandler(editor, pasteAsText)
  22253. });
  22254. editor.ui.registry.addToggleMenuItem('pastetext', {
  22255. text: 'Paste as text',
  22256. icon: 'paste-text',
  22257. onAction,
  22258. onSetup: makeSetupHandler(editor, pasteAsText)
  22259. });
  22260. };
  22261. const onActionToggleFormat = (editor, fmt) => () => {
  22262. editor.execCommand('mceToggleFormat', false, fmt);
  22263. };
  22264. const registerFormatButtons = editor => {
  22265. global$1.each([
  22266. {
  22267. name: 'bold',
  22268. text: 'Bold',
  22269. icon: 'bold'
  22270. },
  22271. {
  22272. name: 'italic',
  22273. text: 'Italic',
  22274. icon: 'italic'
  22275. },
  22276. {
  22277. name: 'underline',
  22278. text: 'Underline',
  22279. icon: 'underline'
  22280. },
  22281. {
  22282. name: 'strikethrough',
  22283. text: 'Strikethrough',
  22284. icon: 'strike-through'
  22285. },
  22286. {
  22287. name: 'subscript',
  22288. text: 'Subscript',
  22289. icon: 'subscript'
  22290. },
  22291. {
  22292. name: 'superscript',
  22293. text: 'Superscript',
  22294. icon: 'superscript'
  22295. }
  22296. ], (btn, _idx) => {
  22297. editor.ui.registry.addToggleButton(btn.name, {
  22298. tooltip: btn.text,
  22299. icon: btn.icon,
  22300. onSetup: onSetupFormatToggle(editor, btn.name),
  22301. onAction: onActionToggleFormat(editor, btn.name)
  22302. });
  22303. });
  22304. for (let i = 1; i <= 6; i++) {
  22305. const name = 'h' + i;
  22306. editor.ui.registry.addToggleButton(name, {
  22307. text: name.toUpperCase(),
  22308. tooltip: 'Heading ' + i,
  22309. onSetup: onSetupFormatToggle(editor, name),
  22310. onAction: onActionToggleFormat(editor, name)
  22311. });
  22312. }
  22313. };
  22314. const registerCommandButtons = editor => {
  22315. global$1.each([
  22316. {
  22317. name: 'cut',
  22318. text: 'Cut',
  22319. action: 'Cut',
  22320. icon: 'cut'
  22321. },
  22322. {
  22323. name: 'copy',
  22324. text: 'Copy',
  22325. action: 'Copy',
  22326. icon: 'copy'
  22327. },
  22328. {
  22329. name: 'paste',
  22330. text: 'Paste',
  22331. action: 'Paste',
  22332. icon: 'paste'
  22333. },
  22334. {
  22335. name: 'help',
  22336. text: 'Help',
  22337. action: 'mceHelp',
  22338. icon: 'help'
  22339. },
  22340. {
  22341. name: 'selectall',
  22342. text: 'Select all',
  22343. action: 'SelectAll',
  22344. icon: 'select-all'
  22345. },
  22346. {
  22347. name: 'newdocument',
  22348. text: 'New document',
  22349. action: 'mceNewDocument',
  22350. icon: 'new-document'
  22351. },
  22352. {
  22353. name: 'removeformat',
  22354. text: 'Clear formatting',
  22355. action: 'RemoveFormat',
  22356. icon: 'remove-formatting'
  22357. },
  22358. {
  22359. name: 'remove',
  22360. text: 'Remove',
  22361. action: 'Delete',
  22362. icon: 'remove'
  22363. },
  22364. {
  22365. name: 'print',
  22366. text: 'Print',
  22367. action: 'mcePrint',
  22368. icon: 'print'
  22369. },
  22370. {
  22371. name: 'hr',
  22372. text: 'Horizontal line',
  22373. action: 'InsertHorizontalRule',
  22374. icon: 'horizontal-rule'
  22375. }
  22376. ], btn => {
  22377. editor.ui.registry.addButton(btn.name, {
  22378. tooltip: btn.text,
  22379. icon: btn.icon,
  22380. onAction: onActionExecCommand(editor, btn.action)
  22381. });
  22382. });
  22383. };
  22384. const registerCommandToggleButtons = editor => {
  22385. global$1.each([{
  22386. name: 'blockquote',
  22387. text: 'Blockquote',
  22388. action: 'mceBlockQuote',
  22389. icon: 'quote'
  22390. }], btn => {
  22391. editor.ui.registry.addToggleButton(btn.name, {
  22392. tooltip: btn.text,
  22393. icon: btn.icon,
  22394. onAction: onActionExecCommand(editor, btn.action),
  22395. onSetup: onSetupFormatToggle(editor, btn.name)
  22396. });
  22397. });
  22398. };
  22399. const registerButtons$1 = editor => {
  22400. registerFormatButtons(editor);
  22401. registerCommandButtons(editor);
  22402. registerCommandToggleButtons(editor);
  22403. };
  22404. const registerMenuItems$2 = editor => {
  22405. global$1.each([
  22406. {
  22407. name: 'bold',
  22408. text: 'Bold',
  22409. action: 'Bold',
  22410. icon: 'bold',
  22411. shortcut: 'Meta+B'
  22412. },
  22413. {
  22414. name: 'italic',
  22415. text: 'Italic',
  22416. action: 'Italic',
  22417. icon: 'italic',
  22418. shortcut: 'Meta+I'
  22419. },
  22420. {
  22421. name: 'underline',
  22422. text: 'Underline',
  22423. action: 'Underline',
  22424. icon: 'underline',
  22425. shortcut: 'Meta+U'
  22426. },
  22427. {
  22428. name: 'strikethrough',
  22429. text: 'Strikethrough',
  22430. action: 'Strikethrough',
  22431. icon: 'strike-through'
  22432. },
  22433. {
  22434. name: 'subscript',
  22435. text: 'Subscript',
  22436. action: 'Subscript',
  22437. icon: 'subscript'
  22438. },
  22439. {
  22440. name: 'superscript',
  22441. text: 'Superscript',
  22442. action: 'Superscript',
  22443. icon: 'superscript'
  22444. },
  22445. {
  22446. name: 'removeformat',
  22447. text: 'Clear formatting',
  22448. action: 'RemoveFormat',
  22449. icon: 'remove-formatting'
  22450. },
  22451. {
  22452. name: 'newdocument',
  22453. text: 'New document',
  22454. action: 'mceNewDocument',
  22455. icon: 'new-document'
  22456. },
  22457. {
  22458. name: 'cut',
  22459. text: 'Cut',
  22460. action: 'Cut',
  22461. icon: 'cut',
  22462. shortcut: 'Meta+X'
  22463. },
  22464. {
  22465. name: 'copy',
  22466. text: 'Copy',
  22467. action: 'Copy',
  22468. icon: 'copy',
  22469. shortcut: 'Meta+C'
  22470. },
  22471. {
  22472. name: 'paste',
  22473. text: 'Paste',
  22474. action: 'Paste',
  22475. icon: 'paste',
  22476. shortcut: 'Meta+V'
  22477. },
  22478. {
  22479. name: 'selectall',
  22480. text: 'Select all',
  22481. action: 'SelectAll',
  22482. icon: 'select-all',
  22483. shortcut: 'Meta+A'
  22484. },
  22485. {
  22486. name: 'print',
  22487. text: 'Print...',
  22488. action: 'mcePrint',
  22489. icon: 'print',
  22490. shortcut: 'Meta+P'
  22491. },
  22492. {
  22493. name: 'hr',
  22494. text: 'Horizontal line',
  22495. action: 'InsertHorizontalRule',
  22496. icon: 'horizontal-rule'
  22497. }
  22498. ], menuitem => {
  22499. editor.ui.registry.addMenuItem(menuitem.name, {
  22500. text: menuitem.text,
  22501. icon: menuitem.icon,
  22502. shortcut: menuitem.shortcut,
  22503. onAction: onActionExecCommand(editor, menuitem.action)
  22504. });
  22505. });
  22506. editor.ui.registry.addMenuItem('codeformat', {
  22507. text: 'Code',
  22508. icon: 'sourcecode',
  22509. onAction: onActionToggleFormat(editor, 'code')
  22510. });
  22511. };
  22512. const register$3 = editor => {
  22513. registerButtons$1(editor);
  22514. registerMenuItems$2(editor);
  22515. };
  22516. const onSetupUndoRedoState = (editor, type) => onSetupEvent(editor, 'Undo Redo AddUndo TypingUndo ClearUndos SwitchMode', api => {
  22517. api.setEnabled(!editor.mode.isReadOnly() && editor.undoManager[type]());
  22518. });
  22519. const registerMenuItems$1 = editor => {
  22520. editor.ui.registry.addMenuItem('undo', {
  22521. text: 'Undo',
  22522. icon: 'undo',
  22523. shortcut: 'Meta+Z',
  22524. onSetup: onSetupUndoRedoState(editor, 'hasUndo'),
  22525. onAction: onActionExecCommand(editor, 'undo')
  22526. });
  22527. editor.ui.registry.addMenuItem('redo', {
  22528. text: 'Redo',
  22529. icon: 'redo',
  22530. shortcut: 'Meta+Y',
  22531. onSetup: onSetupUndoRedoState(editor, 'hasRedo'),
  22532. onAction: onActionExecCommand(editor, 'redo')
  22533. });
  22534. };
  22535. const registerButtons = editor => {
  22536. editor.ui.registry.addButton('undo', {
  22537. tooltip: 'Undo',
  22538. icon: 'undo',
  22539. enabled: false,
  22540. onSetup: onSetupUndoRedoState(editor, 'hasUndo'),
  22541. onAction: onActionExecCommand(editor, 'undo')
  22542. });
  22543. editor.ui.registry.addButton('redo', {
  22544. tooltip: 'Redo',
  22545. icon: 'redo',
  22546. enabled: false,
  22547. onSetup: onSetupUndoRedoState(editor, 'hasRedo'),
  22548. onAction: onActionExecCommand(editor, 'redo')
  22549. });
  22550. };
  22551. const register$2 = editor => {
  22552. registerMenuItems$1(editor);
  22553. registerButtons(editor);
  22554. };
  22555. const onSetupVisualAidState = editor => onSetupEvent(editor, 'VisualAid', api => {
  22556. api.setActive(editor.hasVisual);
  22557. });
  22558. const registerMenuItems = editor => {
  22559. editor.ui.registry.addToggleMenuItem('visualaid', {
  22560. text: 'Visual aids',
  22561. onSetup: onSetupVisualAidState(editor),
  22562. onAction: onActionExecCommand(editor, 'mceToggleVisualAid')
  22563. });
  22564. };
  22565. const registerToolbarButton = editor => {
  22566. editor.ui.registry.addButton('visualaid', {
  22567. tooltip: 'Visual aids',
  22568. text: 'Visual aids',
  22569. onAction: onActionExecCommand(editor, 'mceToggleVisualAid')
  22570. });
  22571. };
  22572. const register$1 = editor => {
  22573. registerToolbarButton(editor);
  22574. registerMenuItems(editor);
  22575. };
  22576. const setup$6 = (editor, backstage) => {
  22577. register$8(editor);
  22578. register$3(editor);
  22579. register$6(editor, backstage);
  22580. register$2(editor);
  22581. register$c(editor);
  22582. register$1(editor);
  22583. register$5(editor);
  22584. register$7(editor);
  22585. register$4(editor);
  22586. };
  22587. const patchPipeConfig = config => isString(config) ? config.split(/[ ,]/) : config;
  22588. const option = name => editor => editor.options.get(name);
  22589. const register = editor => {
  22590. const registerOption = editor.options.register;
  22591. registerOption('contextmenu_avoid_overlap', {
  22592. processor: 'string',
  22593. default: ''
  22594. });
  22595. registerOption('contextmenu_never_use_native', {
  22596. processor: 'boolean',
  22597. default: false
  22598. });
  22599. registerOption('contextmenu', {
  22600. processor: value => {
  22601. if (value === false) {
  22602. return {
  22603. value: [],
  22604. valid: true
  22605. };
  22606. } else if (isString(value) || isArrayOf(value, isString)) {
  22607. return {
  22608. value: patchPipeConfig(value),
  22609. valid: true
  22610. };
  22611. } else {
  22612. return {
  22613. valid: false,
  22614. message: 'Must be false or a string.'
  22615. };
  22616. }
  22617. },
  22618. default: 'link linkchecker image editimage table spellchecker configurepermanentpen'
  22619. });
  22620. };
  22621. const shouldNeverUseNative = option('contextmenu_never_use_native');
  22622. const getAvoidOverlapSelector = option('contextmenu_avoid_overlap');
  22623. const isContextMenuDisabled = editor => getContextMenu(editor).length === 0;
  22624. const getContextMenu = editor => {
  22625. const contextMenus = editor.ui.registry.getAll().contextMenus;
  22626. const contextMenu = editor.options.get('contextmenu');
  22627. if (editor.options.isSet('contextmenu')) {
  22628. return contextMenu;
  22629. } else {
  22630. return filter$2(contextMenu, item => has$2(contextMenus, item));
  22631. }
  22632. };
  22633. const nu = (x, y) => ({
  22634. type: 'makeshift',
  22635. x,
  22636. y
  22637. });
  22638. const transpose = (pos, dx, dy) => {
  22639. return nu(pos.x + dx, pos.y + dy);
  22640. };
  22641. const isTouchEvent$1 = e => e.type === 'longpress' || e.type.indexOf('touch') === 0;
  22642. const fromPageXY = e => {
  22643. if (isTouchEvent$1(e)) {
  22644. const touch = e.touches[0];
  22645. return nu(touch.pageX, touch.pageY);
  22646. } else {
  22647. return nu(e.pageX, e.pageY);
  22648. }
  22649. };
  22650. const fromClientXY = e => {
  22651. if (isTouchEvent$1(e)) {
  22652. const touch = e.touches[0];
  22653. return nu(touch.clientX, touch.clientY);
  22654. } else {
  22655. return nu(e.clientX, e.clientY);
  22656. }
  22657. };
  22658. const transposeContentAreaContainer = (element, pos) => {
  22659. const containerPos = global$7.DOM.getPos(element);
  22660. return transpose(pos, containerPos.x, containerPos.y);
  22661. };
  22662. const getPointAnchor = (editor, e) => {
  22663. if (e.type === 'contextmenu' || e.type === 'longpress') {
  22664. if (editor.inline) {
  22665. return fromPageXY(e);
  22666. } else {
  22667. return transposeContentAreaContainer(editor.getContentAreaContainer(), fromClientXY(e));
  22668. }
  22669. } else {
  22670. return getSelectionAnchor(editor);
  22671. }
  22672. };
  22673. const getSelectionAnchor = editor => {
  22674. return {
  22675. type: 'selection',
  22676. root: SugarElement.fromDom(editor.selection.getNode())
  22677. };
  22678. };
  22679. const getNodeAnchor = editor => ({
  22680. type: 'node',
  22681. node: Optional.some(SugarElement.fromDom(editor.selection.getNode())),
  22682. root: SugarElement.fromDom(editor.getBody())
  22683. });
  22684. const getAnchorSpec$1 = (editor, e, anchorType) => {
  22685. switch (anchorType) {
  22686. case 'node':
  22687. return getNodeAnchor(editor);
  22688. case 'point':
  22689. return getPointAnchor(editor, e);
  22690. case 'selection':
  22691. return getSelectionAnchor(editor);
  22692. }
  22693. };
  22694. const initAndShow$1 = (editor, e, buildMenu, backstage, contextmenu, anchorType) => {
  22695. const items = buildMenu();
  22696. const anchorSpec = getAnchorSpec$1(editor, e, anchorType);
  22697. build(items, ItemResponse$1.CLOSE_ON_EXECUTE, backstage, {
  22698. isHorizontalMenu: false,
  22699. search: Optional.none()
  22700. }).map(menuData => {
  22701. e.preventDefault();
  22702. InlineView.showMenuAt(contextmenu, { anchor: anchorSpec }, {
  22703. menu: { markers: markers('normal') },
  22704. data: menuData
  22705. });
  22706. });
  22707. };
  22708. const layouts = {
  22709. onLtr: () => [
  22710. south$2,
  22711. southeast$2,
  22712. southwest$2,
  22713. northeast$2,
  22714. northwest$2,
  22715. north$2,
  22716. north,
  22717. south,
  22718. northeast,
  22719. southeast,
  22720. northwest,
  22721. southwest
  22722. ],
  22723. onRtl: () => [
  22724. south$2,
  22725. southwest$2,
  22726. southeast$2,
  22727. northwest$2,
  22728. northeast$2,
  22729. north$2,
  22730. north,
  22731. south,
  22732. northwest,
  22733. southwest,
  22734. northeast,
  22735. southeast
  22736. ]
  22737. };
  22738. const bubbleSize = 12;
  22739. const bubbleAlignments = {
  22740. valignCentre: [],
  22741. alignCentre: [],
  22742. alignLeft: ['tox-pop--align-left'],
  22743. alignRight: ['tox-pop--align-right'],
  22744. right: ['tox-pop--right'],
  22745. left: ['tox-pop--left'],
  22746. bottom: ['tox-pop--bottom'],
  22747. top: ['tox-pop--top']
  22748. };
  22749. const isTouchWithinSelection = (editor, e) => {
  22750. const selection = editor.selection;
  22751. if (selection.isCollapsed() || e.touches.length < 1) {
  22752. return false;
  22753. } else {
  22754. const touch = e.touches[0];
  22755. const rng = selection.getRng();
  22756. const rngRectOpt = getFirstRect(editor.getWin(), SimSelection.domRange(rng));
  22757. return rngRectOpt.exists(rngRect => rngRect.left <= touch.clientX && rngRect.right >= touch.clientX && rngRect.top <= touch.clientY && rngRect.bottom >= touch.clientY);
  22758. }
  22759. };
  22760. const setupiOSOverrides = editor => {
  22761. const originalSelection = editor.selection.getRng();
  22762. const selectionReset = () => {
  22763. global$9.setEditorTimeout(editor, () => {
  22764. editor.selection.setRng(originalSelection);
  22765. }, 10);
  22766. unbindEventListeners();
  22767. };
  22768. editor.once('touchend', selectionReset);
  22769. const preventMousedown = e => {
  22770. e.preventDefault();
  22771. e.stopImmediatePropagation();
  22772. };
  22773. editor.on('mousedown', preventMousedown, true);
  22774. const clearSelectionReset = () => unbindEventListeners();
  22775. editor.once('longpresscancel', clearSelectionReset);
  22776. const unbindEventListeners = () => {
  22777. editor.off('touchend', selectionReset);
  22778. editor.off('longpresscancel', clearSelectionReset);
  22779. editor.off('mousedown', preventMousedown);
  22780. };
  22781. };
  22782. const getAnchorSpec = (editor, e, anchorType) => {
  22783. const anchorSpec = getAnchorSpec$1(editor, e, anchorType);
  22784. const bubbleYOffset = anchorType === 'point' ? bubbleSize : 0;
  22785. return {
  22786. bubble: nu$5(0, bubbleYOffset, bubbleAlignments),
  22787. layouts,
  22788. overrides: {
  22789. maxWidthFunction: expandable(),
  22790. maxHeightFunction: expandable$1()
  22791. },
  22792. ...anchorSpec
  22793. };
  22794. };
  22795. const show = (editor, e, items, backstage, contextmenu, anchorType, highlightImmediately) => {
  22796. const anchorSpec = getAnchorSpec(editor, e, anchorType);
  22797. build(items, ItemResponse$1.CLOSE_ON_EXECUTE, backstage, {
  22798. isHorizontalMenu: true,
  22799. search: Optional.none()
  22800. }).map(menuData => {
  22801. e.preventDefault();
  22802. const highlightOnOpen = highlightImmediately ? HighlightOnOpen.HighlightMenuAndItem : HighlightOnOpen.HighlightNone;
  22803. InlineView.showMenuWithinBounds(contextmenu, { anchor: anchorSpec }, {
  22804. menu: {
  22805. markers: markers('normal'),
  22806. highlightOnOpen
  22807. },
  22808. data: menuData,
  22809. type: 'horizontal'
  22810. }, () => Optional.some(getContextToolbarBounds(editor, backstage.shared, anchorType === 'node' ? 'node' : 'selection')));
  22811. editor.dispatch(hideContextToolbarEvent);
  22812. });
  22813. };
  22814. const initAndShow = (editor, e, buildMenu, backstage, contextmenu, anchorType) => {
  22815. const detection = detect$1();
  22816. const isiOS = detection.os.isiOS();
  22817. const isMacOS = detection.os.isMacOS();
  22818. const isAndroid = detection.os.isAndroid();
  22819. const isTouch = detection.deviceType.isTouch();
  22820. const shouldHighlightImmediately = () => !(isAndroid || isiOS || isMacOS && isTouch);
  22821. const open = () => {
  22822. const items = buildMenu();
  22823. show(editor, e, items, backstage, contextmenu, anchorType, shouldHighlightImmediately());
  22824. };
  22825. if ((isMacOS || isiOS) && anchorType !== 'node') {
  22826. const openiOS = () => {
  22827. setupiOSOverrides(editor);
  22828. open();
  22829. };
  22830. if (isTouchWithinSelection(editor, e)) {
  22831. openiOS();
  22832. } else {
  22833. editor.once('selectionchange', openiOS);
  22834. editor.once('touchend', () => editor.off('selectionchange', openiOS));
  22835. }
  22836. } else {
  22837. open();
  22838. }
  22839. };
  22840. const isSeparator = item => isString(item) ? item === '|' : item.type === 'separator';
  22841. const separator = { type: 'separator' };
  22842. const makeContextItem = item => {
  22843. const commonMenuItem = item => ({
  22844. text: item.text,
  22845. icon: item.icon,
  22846. enabled: item.enabled,
  22847. shortcut: item.shortcut
  22848. });
  22849. if (isString(item)) {
  22850. return item;
  22851. } else {
  22852. switch (item.type) {
  22853. case 'separator':
  22854. return separator;
  22855. case 'submenu':
  22856. return {
  22857. type: 'nestedmenuitem',
  22858. ...commonMenuItem(item),
  22859. getSubmenuItems: () => {
  22860. const items = item.getSubmenuItems();
  22861. if (isString(items)) {
  22862. return items;
  22863. } else {
  22864. return map$2(items, makeContextItem);
  22865. }
  22866. }
  22867. };
  22868. default:
  22869. const commonItem = item;
  22870. return {
  22871. type: 'menuitem',
  22872. ...commonMenuItem(commonItem),
  22873. onAction: noarg(commonItem.onAction)
  22874. };
  22875. }
  22876. }
  22877. };
  22878. const addContextMenuGroup = (xs, groupItems) => {
  22879. if (groupItems.length === 0) {
  22880. return xs;
  22881. }
  22882. const lastMenuItem = last$1(xs).filter(item => !isSeparator(item));
  22883. const before = lastMenuItem.fold(() => [], _ => [separator]);
  22884. return xs.concat(before).concat(groupItems).concat([separator]);
  22885. };
  22886. const generateContextMenu = (contextMenus, menuConfig, selectedElement) => {
  22887. const sections = foldl(menuConfig, (acc, name) => {
  22888. return get$g(contextMenus, name.toLowerCase()).map(menu => {
  22889. const items = menu.update(selectedElement);
  22890. if (isString(items)) {
  22891. return addContextMenuGroup(acc, items.split(' '));
  22892. } else if (items.length > 0) {
  22893. const allItems = map$2(items, makeContextItem);
  22894. return addContextMenuGroup(acc, allItems);
  22895. } else {
  22896. return acc;
  22897. }
  22898. }).getOrThunk(() => acc.concat([name]));
  22899. }, []);
  22900. if (sections.length > 0 && isSeparator(sections[sections.length - 1])) {
  22901. sections.pop();
  22902. }
  22903. return sections;
  22904. };
  22905. const isNativeOverrideKeyEvent = (editor, e) => e.ctrlKey && !shouldNeverUseNative(editor);
  22906. const isTouchEvent = e => e.type === 'longpress' || has$2(e, 'touches');
  22907. const isTriggeredByKeyboard = (editor, e) => !isTouchEvent(e) && (e.button !== 2 || e.target === editor.getBody() && e.pointerType === '');
  22908. const getSelectedElement = (editor, e) => isTriggeredByKeyboard(editor, e) ? editor.selection.getStart(true) : e.target;
  22909. const getAnchorType = (editor, e) => {
  22910. const selector = getAvoidOverlapSelector(editor);
  22911. const anchorType = isTriggeredByKeyboard(editor, e) ? 'selection' : 'point';
  22912. if (isNotEmpty(selector)) {
  22913. const target = getSelectedElement(editor, e);
  22914. const selectorExists = closest(SugarElement.fromDom(target), selector);
  22915. return selectorExists ? 'node' : anchorType;
  22916. } else {
  22917. return anchorType;
  22918. }
  22919. };
  22920. const setup$5 = (editor, lazySink, backstage) => {
  22921. const detection = detect$1();
  22922. const isTouch = detection.deviceType.isTouch;
  22923. const contextmenu = build$1(InlineView.sketch({
  22924. dom: { tag: 'div' },
  22925. lazySink,
  22926. onEscape: () => editor.focus(),
  22927. onShow: () => backstage.setContextMenuState(true),
  22928. onHide: () => backstage.setContextMenuState(false),
  22929. fireDismissalEventInstead: {},
  22930. inlineBehaviours: derive$1([config('dismissContextMenu', [run$1(dismissRequested(), (comp, _se) => {
  22931. Sandboxing.close(comp);
  22932. editor.focus();
  22933. })])])
  22934. }));
  22935. const hideContextMenu = () => InlineView.hide(contextmenu);
  22936. const showContextMenu = e => {
  22937. if (shouldNeverUseNative(editor)) {
  22938. e.preventDefault();
  22939. }
  22940. if (isNativeOverrideKeyEvent(editor, e) || isContextMenuDisabled(editor)) {
  22941. return;
  22942. }
  22943. const anchorType = getAnchorType(editor, e);
  22944. const buildMenu = () => {
  22945. const selectedElement = getSelectedElement(editor, e);
  22946. const registry = editor.ui.registry.getAll();
  22947. const menuConfig = getContextMenu(editor);
  22948. return generateContextMenu(registry.contextMenus, menuConfig, selectedElement);
  22949. };
  22950. const initAndShow$2 = isTouch() ? initAndShow : initAndShow$1;
  22951. initAndShow$2(editor, e, buildMenu, backstage, contextmenu, anchorType);
  22952. };
  22953. editor.on('init', () => {
  22954. const hideEvents = 'ResizeEditor ScrollContent ScrollWindow longpresscancel' + (isTouch() ? '' : ' ResizeWindow');
  22955. editor.on(hideEvents, hideContextMenu);
  22956. editor.on('longpress contextmenu', showContextMenu);
  22957. });
  22958. };
  22959. const adt = Adt.generate([
  22960. {
  22961. offset: [
  22962. 'x',
  22963. 'y'
  22964. ]
  22965. },
  22966. {
  22967. absolute: [
  22968. 'x',
  22969. 'y'
  22970. ]
  22971. },
  22972. {
  22973. fixed: [
  22974. 'x',
  22975. 'y'
  22976. ]
  22977. }
  22978. ]);
  22979. const subtract = change => point => point.translate(-change.left, -change.top);
  22980. const add = change => point => point.translate(change.left, change.top);
  22981. const transform = changes => (x, y) => foldl(changes, (rest, f) => f(rest), SugarPosition(x, y));
  22982. const asFixed = (coord, scroll, origin) => coord.fold(transform([
  22983. add(origin),
  22984. subtract(scroll)
  22985. ]), transform([subtract(scroll)]), transform([]));
  22986. const asAbsolute = (coord, scroll, origin) => coord.fold(transform([add(origin)]), transform([]), transform([add(scroll)]));
  22987. const asOffset = (coord, scroll, origin) => coord.fold(transform([]), transform([subtract(origin)]), transform([
  22988. add(scroll),
  22989. subtract(origin)
  22990. ]));
  22991. const withinRange = (coord1, coord2, xRange, yRange, scroll, origin) => {
  22992. const a1 = asAbsolute(coord1, scroll, origin);
  22993. const a2 = asAbsolute(coord2, scroll, origin);
  22994. return Math.abs(a1.left - a2.left) <= xRange && Math.abs(a1.top - a2.top) <= yRange;
  22995. };
  22996. const getDeltas = (coord1, coord2, xRange, yRange, scroll, origin) => {
  22997. const a1 = asAbsolute(coord1, scroll, origin);
  22998. const a2 = asAbsolute(coord2, scroll, origin);
  22999. const left = Math.abs(a1.left - a2.left);
  23000. const top = Math.abs(a1.top - a2.top);
  23001. return SugarPosition(left, top);
  23002. };
  23003. const toStyles = (coord, scroll, origin) => {
  23004. const stylesOpt = coord.fold((x, y) => ({
  23005. position: Optional.some('absolute'),
  23006. left: Optional.some(x + 'px'),
  23007. top: Optional.some(y + 'px')
  23008. }), (x, y) => ({
  23009. position: Optional.some('absolute'),
  23010. left: Optional.some(x - origin.left + 'px'),
  23011. top: Optional.some(y - origin.top + 'px')
  23012. }), (x, y) => ({
  23013. position: Optional.some('fixed'),
  23014. left: Optional.some(x + 'px'),
  23015. top: Optional.some(y + 'px')
  23016. }));
  23017. return {
  23018. right: Optional.none(),
  23019. bottom: Optional.none(),
  23020. ...stylesOpt
  23021. };
  23022. };
  23023. const translate = (coord, deltaX, deltaY) => coord.fold((x, y) => offset(x + deltaX, y + deltaY), (x, y) => absolute(x + deltaX, y + deltaY), (x, y) => fixed(x + deltaX, y + deltaY));
  23024. const absorb = (partialCoord, originalCoord, scroll, origin) => {
  23025. const absorbOne = (stencil, nu) => (optX, optY) => {
  23026. const original = stencil(originalCoord, scroll, origin);
  23027. return nu(optX.getOr(original.left), optY.getOr(original.top));
  23028. };
  23029. return partialCoord.fold(absorbOne(asOffset, offset), absorbOne(asAbsolute, absolute), absorbOne(asFixed, fixed));
  23030. };
  23031. const offset = adt.offset;
  23032. const absolute = adt.absolute;
  23033. const fixed = adt.fixed;
  23034. const parseAttrToInt = (element, name) => {
  23035. const value = get$f(element, name);
  23036. return isUndefined(value) ? NaN : parseInt(value, 10);
  23037. };
  23038. const get = (component, snapsInfo) => {
  23039. const element = component.element;
  23040. const x = parseAttrToInt(element, snapsInfo.leftAttr);
  23041. const y = parseAttrToInt(element, snapsInfo.topAttr);
  23042. return isNaN(x) || isNaN(y) ? Optional.none() : Optional.some(SugarPosition(x, y));
  23043. };
  23044. const set = (component, snapsInfo, pt) => {
  23045. const element = component.element;
  23046. set$9(element, snapsInfo.leftAttr, pt.left + 'px');
  23047. set$9(element, snapsInfo.topAttr, pt.top + 'px');
  23048. };
  23049. const clear = (component, snapsInfo) => {
  23050. const element = component.element;
  23051. remove$7(element, snapsInfo.leftAttr);
  23052. remove$7(element, snapsInfo.topAttr);
  23053. };
  23054. const getCoords = (component, snapInfo, coord, delta) => get(component, snapInfo).fold(() => coord, fixed$1 => fixed(fixed$1.left + delta.left, fixed$1.top + delta.top));
  23055. const moveOrSnap = (component, snapInfo, coord, delta, scroll, origin) => {
  23056. const newCoord = getCoords(component, snapInfo, coord, delta);
  23057. const snap = snapInfo.mustSnap ? findClosestSnap(component, snapInfo, newCoord, scroll, origin) : findSnap(component, snapInfo, newCoord, scroll, origin);
  23058. const fixedCoord = asFixed(newCoord, scroll, origin);
  23059. set(component, snapInfo, fixedCoord);
  23060. return snap.fold(() => ({
  23061. coord: fixed(fixedCoord.left, fixedCoord.top),
  23062. extra: Optional.none()
  23063. }), spanned => ({
  23064. coord: spanned.output,
  23065. extra: spanned.extra
  23066. }));
  23067. };
  23068. const stopDrag = (component, snapInfo) => {
  23069. clear(component, snapInfo);
  23070. };
  23071. const findMatchingSnap = (snaps, newCoord, scroll, origin) => findMap(snaps, snap => {
  23072. const sensor = snap.sensor;
  23073. const inRange = withinRange(newCoord, sensor, snap.range.left, snap.range.top, scroll, origin);
  23074. return inRange ? Optional.some({
  23075. output: absorb(snap.output, newCoord, scroll, origin),
  23076. extra: snap.extra
  23077. }) : Optional.none();
  23078. });
  23079. const findClosestSnap = (component, snapInfo, newCoord, scroll, origin) => {
  23080. const snaps = snapInfo.getSnapPoints(component);
  23081. const matchSnap = findMatchingSnap(snaps, newCoord, scroll, origin);
  23082. return matchSnap.orThunk(() => {
  23083. const bestSnap = foldl(snaps, (acc, snap) => {
  23084. const sensor = snap.sensor;
  23085. const deltas = getDeltas(newCoord, sensor, snap.range.left, snap.range.top, scroll, origin);
  23086. return acc.deltas.fold(() => ({
  23087. deltas: Optional.some(deltas),
  23088. snap: Optional.some(snap)
  23089. }), bestDeltas => {
  23090. const currAvg = (deltas.left + deltas.top) / 2;
  23091. const bestAvg = (bestDeltas.left + bestDeltas.top) / 2;
  23092. if (currAvg <= bestAvg) {
  23093. return {
  23094. deltas: Optional.some(deltas),
  23095. snap: Optional.some(snap)
  23096. };
  23097. } else {
  23098. return acc;
  23099. }
  23100. });
  23101. }, {
  23102. deltas: Optional.none(),
  23103. snap: Optional.none()
  23104. });
  23105. return bestSnap.snap.map(snap => ({
  23106. output: absorb(snap.output, newCoord, scroll, origin),
  23107. extra: snap.extra
  23108. }));
  23109. });
  23110. };
  23111. const findSnap = (component, snapInfo, newCoord, scroll, origin) => {
  23112. const snaps = snapInfo.getSnapPoints(component);
  23113. return findMatchingSnap(snaps, newCoord, scroll, origin);
  23114. };
  23115. const snapTo$1 = (snap, scroll, origin) => ({
  23116. coord: absorb(snap.output, snap.output, scroll, origin),
  23117. extra: snap.extra
  23118. });
  23119. const snapTo = (component, dragConfig, _state, snap) => {
  23120. const target = dragConfig.getTarget(component.element);
  23121. if (dragConfig.repositionTarget) {
  23122. const doc = owner$4(component.element);
  23123. const scroll = get$b(doc);
  23124. const origin = getOrigin(target);
  23125. const snapPin = snapTo$1(snap, scroll, origin);
  23126. const styles = toStyles(snapPin.coord, scroll, origin);
  23127. setOptions(target, styles);
  23128. }
  23129. };
  23130. var DraggingApis = /*#__PURE__*/Object.freeze({
  23131. __proto__: null,
  23132. snapTo: snapTo
  23133. });
  23134. const initialAttribute = 'data-initial-z-index';
  23135. const resetZIndex = blocker => {
  23136. parent(blocker.element).filter(isElement$1).each(root => {
  23137. getOpt(root, initialAttribute).fold(() => remove$6(root, 'z-index'), zIndex => set$8(root, 'z-index', zIndex));
  23138. remove$7(root, initialAttribute);
  23139. });
  23140. };
  23141. const changeZIndex = blocker => {
  23142. parent(blocker.element).filter(isElement$1).each(root => {
  23143. getRaw(root, 'z-index').each(zindex => {
  23144. set$9(root, initialAttribute, zindex);
  23145. });
  23146. set$8(root, 'z-index', get$e(blocker.element, 'z-index'));
  23147. });
  23148. };
  23149. const instigate = (anyComponent, blocker) => {
  23150. anyComponent.getSystem().addToGui(blocker);
  23151. changeZIndex(blocker);
  23152. };
  23153. const discard = blocker => {
  23154. resetZIndex(blocker);
  23155. blocker.getSystem().removeFromGui(blocker);
  23156. };
  23157. const createComponent = (component, blockerClass, blockerEvents) => component.getSystem().build(Container.sketch({
  23158. dom: {
  23159. styles: {
  23160. 'left': '0px',
  23161. 'top': '0px',
  23162. 'width': '100%',
  23163. 'height': '100%',
  23164. 'position': 'fixed',
  23165. 'z-index': '1000000000000000'
  23166. },
  23167. classes: [blockerClass]
  23168. },
  23169. events: blockerEvents
  23170. }));
  23171. var SnapSchema = optionObjOf('snaps', [
  23172. required$1('getSnapPoints'),
  23173. onHandler('onSensor'),
  23174. required$1('leftAttr'),
  23175. required$1('topAttr'),
  23176. defaulted('lazyViewport', win),
  23177. defaulted('mustSnap', false)
  23178. ]);
  23179. const schema$6 = [
  23180. defaulted('useFixed', never),
  23181. required$1('blockerClass'),
  23182. defaulted('getTarget', identity),
  23183. defaulted('onDrag', noop),
  23184. defaulted('repositionTarget', true),
  23185. defaulted('onDrop', noop),
  23186. defaultedFunction('getBounds', win),
  23187. SnapSchema
  23188. ];
  23189. const getCurrentCoord = target => lift3(getRaw(target, 'left'), getRaw(target, 'top'), getRaw(target, 'position'), (left, top, position) => {
  23190. const nu = position === 'fixed' ? fixed : offset;
  23191. return nu(parseInt(left, 10), parseInt(top, 10));
  23192. }).getOrThunk(() => {
  23193. const location = absolute$3(target);
  23194. return absolute(location.left, location.top);
  23195. });
  23196. const clampCoords = (component, coords, scroll, origin, startData) => {
  23197. const bounds = startData.bounds;
  23198. const absoluteCoord = asAbsolute(coords, scroll, origin);
  23199. const newX = clamp(absoluteCoord.left, bounds.x, bounds.x + bounds.width - startData.width);
  23200. const newY = clamp(absoluteCoord.top, bounds.y, bounds.y + bounds.height - startData.height);
  23201. const newCoords = absolute(newX, newY);
  23202. return coords.fold(() => {
  23203. const offset$1 = asOffset(newCoords, scroll, origin);
  23204. return offset(offset$1.left, offset$1.top);
  23205. }, constant$1(newCoords), () => {
  23206. const fixed$1 = asFixed(newCoords, scroll, origin);
  23207. return fixed(fixed$1.left, fixed$1.top);
  23208. });
  23209. };
  23210. const calcNewCoord = (component, optSnaps, currentCoord, scroll, origin, delta, startData) => {
  23211. const newCoord = optSnaps.fold(() => {
  23212. const translated = translate(currentCoord, delta.left, delta.top);
  23213. const fixedCoord = asFixed(translated, scroll, origin);
  23214. return fixed(fixedCoord.left, fixedCoord.top);
  23215. }, snapInfo => {
  23216. const snapping = moveOrSnap(component, snapInfo, currentCoord, delta, scroll, origin);
  23217. snapping.extra.each(extra => {
  23218. snapInfo.onSensor(component, extra);
  23219. });
  23220. return snapping.coord;
  23221. });
  23222. return clampCoords(component, newCoord, scroll, origin, startData);
  23223. };
  23224. const dragBy = (component, dragConfig, startData, delta) => {
  23225. const target = dragConfig.getTarget(component.element);
  23226. if (dragConfig.repositionTarget) {
  23227. const doc = owner$4(component.element);
  23228. const scroll = get$b(doc);
  23229. const origin = getOrigin(target);
  23230. const currentCoord = getCurrentCoord(target);
  23231. const newCoord = calcNewCoord(component, dragConfig.snaps, currentCoord, scroll, origin, delta, startData);
  23232. const styles = toStyles(newCoord, scroll, origin);
  23233. setOptions(target, styles);
  23234. }
  23235. dragConfig.onDrag(component, target, delta);
  23236. };
  23237. const calcStartData = (dragConfig, comp) => ({
  23238. bounds: dragConfig.getBounds(),
  23239. height: getOuter$2(comp.element),
  23240. width: getOuter$1(comp.element)
  23241. });
  23242. const move = (component, dragConfig, dragState, dragMode, event) => {
  23243. const delta = dragState.update(dragMode, event);
  23244. const dragStartData = dragState.getStartData().getOrThunk(() => calcStartData(dragConfig, component));
  23245. delta.each(dlt => {
  23246. dragBy(component, dragConfig, dragStartData, dlt);
  23247. });
  23248. };
  23249. const stop = (component, blocker, dragConfig, dragState) => {
  23250. blocker.each(discard);
  23251. dragConfig.snaps.each(snapInfo => {
  23252. stopDrag(component, snapInfo);
  23253. });
  23254. const target = dragConfig.getTarget(component.element);
  23255. dragState.reset();
  23256. dragConfig.onDrop(component, target);
  23257. };
  23258. const handlers = events => (dragConfig, dragState) => {
  23259. const updateStartState = comp => {
  23260. dragState.setStartData(calcStartData(dragConfig, comp));
  23261. };
  23262. return derive$2([
  23263. run$1(windowScroll(), comp => {
  23264. dragState.getStartData().each(() => updateStartState(comp));
  23265. }),
  23266. ...events(dragConfig, dragState, updateStartState)
  23267. ]);
  23268. };
  23269. const init$2 = dragApi => derive$2([
  23270. run$1(mousedown(), dragApi.forceDrop),
  23271. run$1(mouseup(), dragApi.drop),
  23272. run$1(mousemove(), (comp, simulatedEvent) => {
  23273. dragApi.move(simulatedEvent.event);
  23274. }),
  23275. run$1(mouseout(), dragApi.delayDrop)
  23276. ]);
  23277. const getData$1 = event => Optional.from(SugarPosition(event.x, event.y));
  23278. const getDelta$1 = (old, nu) => SugarPosition(nu.left - old.left, nu.top - old.top);
  23279. var MouseData = /*#__PURE__*/Object.freeze({
  23280. __proto__: null,
  23281. getData: getData$1,
  23282. getDelta: getDelta$1
  23283. });
  23284. const events$2 = (dragConfig, dragState, updateStartState) => [run$1(mousedown(), (component, simulatedEvent) => {
  23285. const raw = simulatedEvent.event.raw;
  23286. if (raw.button !== 0) {
  23287. return;
  23288. }
  23289. simulatedEvent.stop();
  23290. const stop$1 = () => stop(component, Optional.some(blocker), dragConfig, dragState);
  23291. const delayDrop = DelayedFunction(stop$1, 200);
  23292. const dragApi = {
  23293. drop: stop$1,
  23294. delayDrop: delayDrop.schedule,
  23295. forceDrop: stop$1,
  23296. move: event => {
  23297. delayDrop.cancel();
  23298. move(component, dragConfig, dragState, MouseData, event);
  23299. }
  23300. };
  23301. const blocker = createComponent(component, dragConfig.blockerClass, init$2(dragApi));
  23302. const start = () => {
  23303. updateStartState(component);
  23304. instigate(component, blocker);
  23305. };
  23306. start();
  23307. })];
  23308. const schema$5 = [
  23309. ...schema$6,
  23310. output$1('dragger', { handlers: handlers(events$2) })
  23311. ];
  23312. const init$1 = dragApi => derive$2([
  23313. run$1(touchstart(), dragApi.forceDrop),
  23314. run$1(touchend(), dragApi.drop),
  23315. run$1(touchcancel(), dragApi.drop),
  23316. run$1(touchmove(), (comp, simulatedEvent) => {
  23317. dragApi.move(simulatedEvent.event);
  23318. })
  23319. ]);
  23320. const getDataFrom = touches => {
  23321. const touch = touches[0];
  23322. return Optional.some(SugarPosition(touch.clientX, touch.clientY));
  23323. };
  23324. const getData = event => {
  23325. const raw = event.raw;
  23326. const touches = raw.touches;
  23327. return touches.length === 1 ? getDataFrom(touches) : Optional.none();
  23328. };
  23329. const getDelta = (old, nu) => SugarPosition(nu.left - old.left, nu.top - old.top);
  23330. var TouchData = /*#__PURE__*/Object.freeze({
  23331. __proto__: null,
  23332. getData: getData,
  23333. getDelta: getDelta
  23334. });
  23335. const events$1 = (dragConfig, dragState, updateStartState) => {
  23336. const blockerSingleton = value$2();
  23337. const stopBlocking = component => {
  23338. stop(component, blockerSingleton.get(), dragConfig, dragState);
  23339. blockerSingleton.clear();
  23340. };
  23341. return [
  23342. run$1(touchstart(), (component, simulatedEvent) => {
  23343. simulatedEvent.stop();
  23344. const stop = () => stopBlocking(component);
  23345. const dragApi = {
  23346. drop: stop,
  23347. delayDrop: noop,
  23348. forceDrop: stop,
  23349. move: event => {
  23350. move(component, dragConfig, dragState, TouchData, event);
  23351. }
  23352. };
  23353. const blocker = createComponent(component, dragConfig.blockerClass, init$1(dragApi));
  23354. blockerSingleton.set(blocker);
  23355. const start = () => {
  23356. updateStartState(component);
  23357. instigate(component, blocker);
  23358. };
  23359. start();
  23360. }),
  23361. run$1(touchmove(), (component, simulatedEvent) => {
  23362. simulatedEvent.stop();
  23363. move(component, dragConfig, dragState, TouchData, simulatedEvent.event);
  23364. }),
  23365. run$1(touchend(), (component, simulatedEvent) => {
  23366. simulatedEvent.stop();
  23367. stopBlocking(component);
  23368. }),
  23369. run$1(touchcancel(), stopBlocking)
  23370. ];
  23371. };
  23372. const schema$4 = [
  23373. ...schema$6,
  23374. output$1('dragger', { handlers: handlers(events$1) })
  23375. ];
  23376. const events = (dragConfig, dragState, updateStartState) => [
  23377. ...events$2(dragConfig, dragState, updateStartState),
  23378. ...events$1(dragConfig, dragState, updateStartState)
  23379. ];
  23380. const schema$3 = [
  23381. ...schema$6,
  23382. output$1('dragger', { handlers: handlers(events) })
  23383. ];
  23384. const mouse = schema$5;
  23385. const touch = schema$4;
  23386. const mouseOrTouch = schema$3;
  23387. var DraggingBranches = /*#__PURE__*/Object.freeze({
  23388. __proto__: null,
  23389. mouse: mouse,
  23390. touch: touch,
  23391. mouseOrTouch: mouseOrTouch
  23392. });
  23393. const init = () => {
  23394. let previous = Optional.none();
  23395. let startData = Optional.none();
  23396. const reset = () => {
  23397. previous = Optional.none();
  23398. startData = Optional.none();
  23399. };
  23400. const calculateDelta = (mode, nu) => {
  23401. const result = previous.map(old => mode.getDelta(old, nu));
  23402. previous = Optional.some(nu);
  23403. return result;
  23404. };
  23405. const update = (mode, dragEvent) => mode.getData(dragEvent).bind(nuData => calculateDelta(mode, nuData));
  23406. const setStartData = data => {
  23407. startData = Optional.some(data);
  23408. };
  23409. const getStartData = () => startData;
  23410. const readState = constant$1({});
  23411. return nu$8({
  23412. readState,
  23413. reset,
  23414. update,
  23415. getStartData,
  23416. setStartData
  23417. });
  23418. };
  23419. var DragState = /*#__PURE__*/Object.freeze({
  23420. __proto__: null,
  23421. init: init
  23422. });
  23423. const Dragging = createModes({
  23424. branchKey: 'mode',
  23425. branches: DraggingBranches,
  23426. name: 'dragging',
  23427. active: {
  23428. events: (dragConfig, dragState) => {
  23429. const dragger = dragConfig.dragger;
  23430. return dragger.handlers(dragConfig, dragState);
  23431. }
  23432. },
  23433. extra: {
  23434. snap: sConfig => ({
  23435. sensor: sConfig.sensor,
  23436. range: sConfig.range,
  23437. output: sConfig.output,
  23438. extra: Optional.from(sConfig.extra)
  23439. })
  23440. },
  23441. state: DragState,
  23442. apis: DraggingApis
  23443. });
  23444. const snapWidth = 40;
  23445. const snapOffset = snapWidth / 2;
  23446. const calcSnap = (selectorOpt, td, x, y, width, height) => selectorOpt.fold(() => Dragging.snap({
  23447. sensor: absolute(x - snapOffset, y - snapOffset),
  23448. range: SugarPosition(width, height),
  23449. output: absolute(Optional.some(x), Optional.some(y)),
  23450. extra: { td }
  23451. }), selectorHandle => {
  23452. const sensorLeft = x - snapOffset;
  23453. const sensorTop = y - snapOffset;
  23454. const sensorWidth = snapWidth;
  23455. const sensorHeight = snapWidth;
  23456. const rect = selectorHandle.element.dom.getBoundingClientRect();
  23457. return Dragging.snap({
  23458. sensor: absolute(sensorLeft, sensorTop),
  23459. range: SugarPosition(sensorWidth, sensorHeight),
  23460. output: absolute(Optional.some(x - rect.width / 2), Optional.some(y - rect.height / 2)),
  23461. extra: { td }
  23462. });
  23463. });
  23464. const getSnapsConfig = (getSnapPoints, cell, onChange) => {
  23465. const isSameCell = (cellOpt, td) => cellOpt.exists(currentTd => eq(currentTd, td));
  23466. return {
  23467. getSnapPoints,
  23468. leftAttr: 'data-drag-left',
  23469. topAttr: 'data-drag-top',
  23470. onSensor: (component, extra) => {
  23471. const td = extra.td;
  23472. if (!isSameCell(cell.get(), td)) {
  23473. cell.set(td);
  23474. onChange(td);
  23475. }
  23476. },
  23477. mustSnap: true
  23478. };
  23479. };
  23480. const createSelector = snaps => record(Button.sketch({
  23481. dom: {
  23482. tag: 'div',
  23483. classes: ['tox-selector']
  23484. },
  23485. buttonBehaviours: derive$1([
  23486. Dragging.config({
  23487. mode: 'mouseOrTouch',
  23488. blockerClass: 'blocker',
  23489. snaps
  23490. }),
  23491. Unselecting.config({})
  23492. ]),
  23493. eventOrder: {
  23494. mousedown: [
  23495. 'dragging',
  23496. 'alloy.base.behaviour'
  23497. ],
  23498. touchstart: [
  23499. 'dragging',
  23500. 'alloy.base.behaviour'
  23501. ]
  23502. }
  23503. }));
  23504. const setup$4 = (editor, sink) => {
  23505. const tlTds = Cell([]);
  23506. const brTds = Cell([]);
  23507. const isVisible = Cell(false);
  23508. const startCell = value$2();
  23509. const finishCell = value$2();
  23510. const getTopLeftSnap = td => {
  23511. const box = absolute$2(td);
  23512. return calcSnap(memTopLeft.getOpt(sink), td, box.x, box.y, box.width, box.height);
  23513. };
  23514. const getTopLeftSnaps = () => map$2(tlTds.get(), td => getTopLeftSnap(td));
  23515. const getBottomRightSnap = td => {
  23516. const box = absolute$2(td);
  23517. return calcSnap(memBottomRight.getOpt(sink), td, box.right, box.bottom, box.width, box.height);
  23518. };
  23519. const getBottomRightSnaps = () => map$2(brTds.get(), td => getBottomRightSnap(td));
  23520. const topLeftSnaps = getSnapsConfig(getTopLeftSnaps, startCell, start => {
  23521. finishCell.get().each(finish => {
  23522. editor.dispatch('TableSelectorChange', {
  23523. start,
  23524. finish
  23525. });
  23526. });
  23527. });
  23528. const bottomRightSnaps = getSnapsConfig(getBottomRightSnaps, finishCell, finish => {
  23529. startCell.get().each(start => {
  23530. editor.dispatch('TableSelectorChange', {
  23531. start,
  23532. finish
  23533. });
  23534. });
  23535. });
  23536. const memTopLeft = createSelector(topLeftSnaps);
  23537. const memBottomRight = createSelector(bottomRightSnaps);
  23538. const topLeft = build$1(memTopLeft.asSpec());
  23539. const bottomRight = build$1(memBottomRight.asSpec());
  23540. const showOrHideHandle = (selector, cell, isAbove, isBelow) => {
  23541. const cellRect = cell.dom.getBoundingClientRect();
  23542. remove$6(selector.element, 'display');
  23543. const viewportHeight = defaultView(SugarElement.fromDom(editor.getBody())).dom.innerHeight;
  23544. const aboveViewport = isAbove(cellRect);
  23545. const belowViewport = isBelow(cellRect, viewportHeight);
  23546. if (aboveViewport || belowViewport) {
  23547. set$8(selector.element, 'display', 'none');
  23548. }
  23549. };
  23550. const snapTo = (selector, cell, getSnapConfig, pos) => {
  23551. const snap = getSnapConfig(cell);
  23552. Dragging.snapTo(selector, snap);
  23553. const isAbove = rect => rect[pos] < 0;
  23554. const isBelow = (rect, viewportHeight) => rect[pos] > viewportHeight;
  23555. showOrHideHandle(selector, cell, isAbove, isBelow);
  23556. };
  23557. const snapTopLeft = cell => snapTo(topLeft, cell, getTopLeftSnap, 'top');
  23558. const snapLastTopLeft = () => startCell.get().each(snapTopLeft);
  23559. const snapBottomRight = cell => snapTo(bottomRight, cell, getBottomRightSnap, 'bottom');
  23560. const snapLastBottomRight = () => finishCell.get().each(snapBottomRight);
  23561. if (detect$1().deviceType.isTouch()) {
  23562. editor.on('TableSelectionChange', e => {
  23563. if (!isVisible.get()) {
  23564. attach(sink, topLeft);
  23565. attach(sink, bottomRight);
  23566. isVisible.set(true);
  23567. }
  23568. startCell.set(e.start);
  23569. finishCell.set(e.finish);
  23570. e.otherCells.each(otherCells => {
  23571. tlTds.set(otherCells.upOrLeftCells);
  23572. brTds.set(otherCells.downOrRightCells);
  23573. snapTopLeft(e.start);
  23574. snapBottomRight(e.finish);
  23575. });
  23576. });
  23577. editor.on('ResizeEditor ResizeWindow ScrollContent', () => {
  23578. snapLastTopLeft();
  23579. snapLastBottomRight();
  23580. });
  23581. editor.on('TableSelectionClear', () => {
  23582. if (isVisible.get()) {
  23583. detach(topLeft);
  23584. detach(bottomRight);
  23585. isVisible.set(false);
  23586. }
  23587. startCell.clear();
  23588. finishCell.clear();
  23589. });
  23590. }
  23591. };
  23592. var Logo = "<svg width=\"50px\" height=\"16px\" viewBox=\"0 0 50 16\" xmlns=\"http://www.w3.org/2000/svg\">\n <path fill-rule=\"evenodd\" clip-rule=\"evenodd\" d=\"M10.143 0c2.608.015 5.186 2.178 5.186 5.331 0 0 .077 3.812-.084 4.87-.361 2.41-2.164 4.074-4.65 4.496-1.453.284-2.523.49-3.212.623-.373.071-.634.122-.785.152-.184.038-.997.145-1.35.145-2.732 0-5.21-2.04-5.248-5.33 0 0 0-3.514.03-4.442.093-2.4 1.758-4.342 4.926-4.963 0 0 3.875-.752 4.036-.782.368-.07.775-.1 1.15-.1Zm1.826 2.8L5.83 3.989v2.393l-2.455.475v5.968l6.137-1.189V9.243l2.456-.476V2.8ZM5.83 6.382l3.682-.713v3.574l-3.682.713V6.382Zm27.173-1.64-.084-1.066h-2.226v9.132h2.456V7.743c-.008-1.151.998-2.064 2.149-2.072 1.15-.008 1.987.92 1.995 2.072v5.065h2.455V7.359c-.015-2.18-1.657-3.929-3.837-3.913a3.993 3.993 0 0 0-2.908 1.296Zm-6.3-4.266L29.16 0v2.387l-2.456.475V.476Zm0 3.2v9.132h2.456V3.676h-2.456Zm18.179 11.787L49.11 3.676H46.58l-1.612 4.527-.46 1.382-.384-1.382-1.611-4.527H39.98l3.3 9.132L42.15 16l2.732-.537ZM22.867 9.738c0 .752.568 1.075.921 1.075.353 0 .668-.047.998-.154l.537 1.765c-.23.154-.92.537-2.225.537-1.305 0-2.655-.997-2.686-2.686a136.877 136.877 0 0 1 0-4.374H18.8V3.676h1.612v-1.98l2.455-.476v2.456h2.302V5.9h-2.302v3.837Z\"/>\n</svg>\n";
  23593. const isHidden = elm => elm.nodeName === 'BR' || !!elm.getAttribute('data-mce-bogus') || elm.getAttribute('data-mce-type') === 'bookmark';
  23594. const renderElementPath = (editor, settings, providersBackstage) => {
  23595. var _a;
  23596. const delimiter = (_a = settings.delimiter) !== null && _a !== void 0 ? _a : '\u203A';
  23597. const renderElement = (name, element, index) => Button.sketch({
  23598. dom: {
  23599. tag: 'div',
  23600. classes: ['tox-statusbar__path-item'],
  23601. attributes: {
  23602. 'data-index': index,
  23603. 'aria-level': index + 1
  23604. }
  23605. },
  23606. components: [text$2(name)],
  23607. action: _btn => {
  23608. editor.focus();
  23609. editor.selection.select(element);
  23610. editor.nodeChanged();
  23611. },
  23612. buttonBehaviours: derive$1([
  23613. DisablingConfigs.button(providersBackstage.isDisabled),
  23614. receivingConfig()
  23615. ])
  23616. });
  23617. const renderDivider = () => ({
  23618. dom: {
  23619. tag: 'div',
  23620. classes: ['tox-statusbar__path-divider'],
  23621. attributes: { 'aria-hidden': true }
  23622. },
  23623. components: [text$2(` ${ delimiter } `)]
  23624. });
  23625. const renderPathData = data => foldl(data, (acc, path, index) => {
  23626. const element = renderElement(path.name, path.element, index);
  23627. if (index === 0) {
  23628. return acc.concat([element]);
  23629. } else {
  23630. return acc.concat([
  23631. renderDivider(),
  23632. element
  23633. ]);
  23634. }
  23635. }, []);
  23636. const updatePath = parents => {
  23637. const newPath = [];
  23638. let i = parents.length;
  23639. while (i-- > 0) {
  23640. const parent = parents[i];
  23641. if (parent.nodeType === 1 && !isHidden(parent)) {
  23642. const args = fireResolveName(editor, parent);
  23643. if (!args.isDefaultPrevented()) {
  23644. newPath.push({
  23645. name: args.name,
  23646. element: parent
  23647. });
  23648. }
  23649. if (args.isPropagationStopped()) {
  23650. break;
  23651. }
  23652. }
  23653. }
  23654. return newPath;
  23655. };
  23656. return {
  23657. dom: {
  23658. tag: 'div',
  23659. classes: ['tox-statusbar__path'],
  23660. attributes: { role: 'navigation' }
  23661. },
  23662. behaviours: derive$1([
  23663. Keying.config({
  23664. mode: 'flow',
  23665. selector: 'div[role=button]'
  23666. }),
  23667. Disabling.config({ disabled: providersBackstage.isDisabled }),
  23668. receivingConfig(),
  23669. Tabstopping.config({}),
  23670. Replacing.config({}),
  23671. config('elementPathEvents', [runOnAttached((comp, _e) => {
  23672. editor.shortcuts.add('alt+F11', 'focus statusbar elementpath', () => Keying.focusIn(comp));
  23673. editor.on('NodeChange', e => {
  23674. const newPath = updatePath(e.parents);
  23675. const newChildren = newPath.length > 0 ? renderPathData(newPath) : [];
  23676. Replacing.set(comp, newChildren);
  23677. });
  23678. })])
  23679. ]),
  23680. components: []
  23681. };
  23682. };
  23683. var ResizeTypes;
  23684. (function (ResizeTypes) {
  23685. ResizeTypes[ResizeTypes['None'] = 0] = 'None';
  23686. ResizeTypes[ResizeTypes['Both'] = 1] = 'Both';
  23687. ResizeTypes[ResizeTypes['Vertical'] = 2] = 'Vertical';
  23688. }(ResizeTypes || (ResizeTypes = {})));
  23689. const getDimensions = (editor, deltas, resizeType, originalHeight, originalWidth) => {
  23690. const dimensions = { height: calcCappedSize(originalHeight + deltas.top, getMinHeightOption(editor), getMaxHeightOption(editor)) };
  23691. if (resizeType === ResizeTypes.Both) {
  23692. dimensions.width = calcCappedSize(originalWidth + deltas.left, getMinWidthOption(editor), getMaxWidthOption(editor));
  23693. }
  23694. return dimensions;
  23695. };
  23696. const resize = (editor, deltas, resizeType) => {
  23697. const container = SugarElement.fromDom(editor.getContainer());
  23698. const dimensions = getDimensions(editor, deltas, resizeType, get$d(container), get$c(container));
  23699. each(dimensions, (val, dim) => {
  23700. if (isNumber(val)) {
  23701. set$8(container, dim, numToPx(val));
  23702. }
  23703. });
  23704. fireResizeEditor(editor);
  23705. };
  23706. const getResizeType = editor => {
  23707. const resize = getResize(editor);
  23708. if (resize === false) {
  23709. return ResizeTypes.None;
  23710. } else if (resize === 'both') {
  23711. return ResizeTypes.Both;
  23712. } else {
  23713. return ResizeTypes.Vertical;
  23714. }
  23715. };
  23716. const keyboardHandler = (editor, resizeType, x, y) => {
  23717. const scale = 20;
  23718. const delta = SugarPosition(x * scale, y * scale);
  23719. resize(editor, delta, resizeType);
  23720. return Optional.some(true);
  23721. };
  23722. const renderResizeHandler = (editor, providersBackstage) => {
  23723. const resizeType = getResizeType(editor);
  23724. if (resizeType === ResizeTypes.None) {
  23725. return Optional.none();
  23726. }
  23727. return Optional.some(render$3('resize-handle', {
  23728. tag: 'div',
  23729. classes: ['tox-statusbar__resize-handle'],
  23730. attributes: { title: providersBackstage.translate('Resize') },
  23731. behaviours: [
  23732. Dragging.config({
  23733. mode: 'mouse',
  23734. repositionTarget: false,
  23735. onDrag: (_comp, _target, delta) => resize(editor, delta, resizeType),
  23736. blockerClass: 'tox-blocker'
  23737. }),
  23738. Keying.config({
  23739. mode: 'special',
  23740. onLeft: () => keyboardHandler(editor, resizeType, -1, 0),
  23741. onRight: () => keyboardHandler(editor, resizeType, 1, 0),
  23742. onUp: () => keyboardHandler(editor, resizeType, 0, -1),
  23743. onDown: () => keyboardHandler(editor, resizeType, 0, 1)
  23744. }),
  23745. Tabstopping.config({}),
  23746. Focusing.config({})
  23747. ]
  23748. }, providersBackstage.icons));
  23749. };
  23750. const renderWordCount = (editor, providersBackstage) => {
  23751. const replaceCountText = (comp, count, mode) => Replacing.set(comp, [text$2(providersBackstage.translate([
  23752. '{0} ' + mode,
  23753. count[mode]
  23754. ]))]);
  23755. return Button.sketch({
  23756. dom: {
  23757. tag: 'button',
  23758. classes: ['tox-statusbar__wordcount']
  23759. },
  23760. components: [],
  23761. buttonBehaviours: derive$1([
  23762. DisablingConfigs.button(providersBackstage.isDisabled),
  23763. receivingConfig(),
  23764. Tabstopping.config({}),
  23765. Replacing.config({}),
  23766. Representing.config({
  23767. store: {
  23768. mode: 'memory',
  23769. initialValue: {
  23770. mode: 'words',
  23771. count: {
  23772. words: 0,
  23773. characters: 0
  23774. }
  23775. }
  23776. }
  23777. }),
  23778. config('wordcount-events', [
  23779. runOnExecute$1(comp => {
  23780. const currentVal = Representing.getValue(comp);
  23781. const newMode = currentVal.mode === 'words' ? 'characters' : 'words';
  23782. Representing.setValue(comp, {
  23783. mode: newMode,
  23784. count: currentVal.count
  23785. });
  23786. replaceCountText(comp, currentVal.count, newMode);
  23787. }),
  23788. runOnAttached(comp => {
  23789. editor.on('wordCountUpdate', e => {
  23790. const {mode} = Representing.getValue(comp);
  23791. Representing.setValue(comp, {
  23792. mode,
  23793. count: e.wordCount
  23794. });
  23795. replaceCountText(comp, e.wordCount, mode);
  23796. });
  23797. })
  23798. ])
  23799. ]),
  23800. eventOrder: {
  23801. [execute$5()]: [
  23802. 'disabling',
  23803. 'alloy.base.behaviour',
  23804. 'wordcount-events'
  23805. ]
  23806. }
  23807. });
  23808. };
  23809. const renderStatusbar = (editor, providersBackstage) => {
  23810. const renderBranding = () => {
  23811. return {
  23812. dom: {
  23813. tag: 'span',
  23814. classes: ['tox-statusbar__branding']
  23815. },
  23816. components: [{
  23817. dom: {
  23818. tag: 'a',
  23819. attributes: {
  23820. 'href': 'https://www.tiny.cloud/powered-by-tiny?utm_campaign=editor_referral&utm_medium=poweredby&utm_source=tinymce&utm_content=v6',
  23821. 'rel': 'noopener',
  23822. 'target': '_blank',
  23823. 'aria-label': global$8.translate([
  23824. 'Powered by {0}',
  23825. 'Tiny'
  23826. ])
  23827. },
  23828. innerHtml: Logo.trim()
  23829. },
  23830. behaviours: derive$1([Focusing.config({})])
  23831. }]
  23832. };
  23833. };
  23834. const getTextComponents = () => {
  23835. const components = [];
  23836. if (useElementPath(editor)) {
  23837. components.push(renderElementPath(editor, {}, providersBackstage));
  23838. }
  23839. if (editor.hasPlugin('wordcount')) {
  23840. components.push(renderWordCount(editor, providersBackstage));
  23841. }
  23842. if (useBranding(editor)) {
  23843. components.push(renderBranding());
  23844. }
  23845. if (components.length > 0) {
  23846. return [{
  23847. dom: {
  23848. tag: 'div',
  23849. classes: ['tox-statusbar__text-container']
  23850. },
  23851. components
  23852. }];
  23853. }
  23854. return [];
  23855. };
  23856. const getComponents = () => {
  23857. const components = getTextComponents();
  23858. const resizeHandler = renderResizeHandler(editor, providersBackstage);
  23859. return components.concat(resizeHandler.toArray());
  23860. };
  23861. return {
  23862. dom: {
  23863. tag: 'div',
  23864. classes: ['tox-statusbar']
  23865. },
  23866. components: getComponents()
  23867. };
  23868. };
  23869. const getLazyMothership = (label, singleton) => singleton.get().getOrDie(`UI for ${ label } has not been rendered`);
  23870. const setup$3 = editor => {
  23871. const isInline = editor.inline;
  23872. const mode = isInline ? Inline : Iframe;
  23873. const header = isStickyToolbar(editor) ? StickyHeader : StaticHeader;
  23874. const lazyUiRefs = LazyUiReferences();
  23875. const lazyMothership = value$2();
  23876. const lazyDialogMothership = value$2();
  23877. const platform = detect$1();
  23878. const isTouch = platform.deviceType.isTouch();
  23879. const touchPlatformClass = 'tox-platform-touch';
  23880. const deviceClasses = isTouch ? [touchPlatformClass] : [];
  23881. const isToolbarBottom = isToolbarLocationBottom(editor);
  23882. const toolbarMode = getToolbarMode(editor);
  23883. const memAnchorBar = record({
  23884. dom: {
  23885. tag: 'div',
  23886. classes: ['tox-anchorbar']
  23887. }
  23888. });
  23889. const lazyHeader = () => lazyUiRefs.mainUi.get().map(ui => ui.outerContainer).bind(OuterContainer.getHeader);
  23890. const lazyDialogSinkResult = () => Result.fromOption(lazyUiRefs.dialogUi.get().map(ui => ui.sink), 'UI has not been rendered');
  23891. const lazyPopupSinkResult = () => Result.fromOption(lazyUiRefs.popupUi.get().map(ui => ui.sink), '(popup) UI has not been rendered');
  23892. const lazyAnchorBar = lazyUiRefs.lazyGetInOuterOrDie('anchor bar', memAnchorBar.getOpt);
  23893. const lazyToolbar = lazyUiRefs.lazyGetInOuterOrDie('toolbar', OuterContainer.getToolbar);
  23894. const lazyThrobber = lazyUiRefs.lazyGetInOuterOrDie('throbber', OuterContainer.getThrobber);
  23895. const backstages = init$7({
  23896. popup: lazyPopupSinkResult,
  23897. dialog: lazyDialogSinkResult
  23898. }, editor, lazyAnchorBar);
  23899. const makeHeaderPart = () => {
  23900. const verticalDirAttributes = { attributes: { [Attribute]: isToolbarBottom ? AttributeValue.BottomToTop : AttributeValue.TopToBottom } };
  23901. const partMenubar = OuterContainer.parts.menubar({
  23902. dom: {
  23903. tag: 'div',
  23904. classes: ['tox-menubar']
  23905. },
  23906. backstage: backstages.popup,
  23907. onEscape: () => {
  23908. editor.focus();
  23909. }
  23910. });
  23911. const partToolbar = OuterContainer.parts.toolbar({
  23912. dom: {
  23913. tag: 'div',
  23914. classes: ['tox-toolbar']
  23915. },
  23916. getSink: backstages.popup.shared.getSink,
  23917. providers: backstages.popup.shared.providers,
  23918. onEscape: () => {
  23919. editor.focus();
  23920. },
  23921. onToolbarToggled: state => {
  23922. fireToggleToolbarDrawer(editor, state);
  23923. },
  23924. type: toolbarMode,
  23925. lazyToolbar,
  23926. lazyHeader: () => lazyHeader().getOrDie('Could not find header element'),
  23927. ...verticalDirAttributes
  23928. });
  23929. const partMultipleToolbar = OuterContainer.parts['multiple-toolbar']({
  23930. dom: {
  23931. tag: 'div',
  23932. classes: ['tox-toolbar-overlord']
  23933. },
  23934. providers: backstages.popup.shared.providers,
  23935. onEscape: () => {
  23936. editor.focus();
  23937. },
  23938. type: toolbarMode
  23939. });
  23940. const hasMultipleToolbar = isMultipleToolbars(editor);
  23941. const hasToolbar = isToolbarEnabled(editor);
  23942. const hasMenubar = isMenubarEnabled(editor);
  23943. const shouldHavePromotion = promotionEnabled(editor);
  23944. const partPromotion = makePromotion();
  23945. const hasAnyContents = hasMultipleToolbar || hasToolbar || hasMenubar;
  23946. const getPartToolbar = () => {
  23947. if (hasMultipleToolbar) {
  23948. return [partMultipleToolbar];
  23949. } else if (hasToolbar) {
  23950. return [partToolbar];
  23951. } else {
  23952. return [];
  23953. }
  23954. };
  23955. const menubarCollection = shouldHavePromotion ? [
  23956. partPromotion,
  23957. partMenubar
  23958. ] : [partMenubar];
  23959. return OuterContainer.parts.header({
  23960. dom: {
  23961. tag: 'div',
  23962. classes: ['tox-editor-header'].concat(hasAnyContents ? [] : ['tox-editor-header--empty']),
  23963. ...verticalDirAttributes
  23964. },
  23965. components: flatten([
  23966. hasMenubar ? menubarCollection : [],
  23967. getPartToolbar(),
  23968. useFixedContainer(editor) ? [] : [memAnchorBar.asSpec()]
  23969. ]),
  23970. sticky: isStickyToolbar(editor),
  23971. editor,
  23972. sharedBackstage: backstages.popup.shared
  23973. });
  23974. };
  23975. const makePromotion = () => {
  23976. return OuterContainer.parts.promotion({
  23977. dom: {
  23978. tag: 'div',
  23979. classes: ['tox-promotion']
  23980. }
  23981. });
  23982. };
  23983. const makeSidebarDefinition = () => {
  23984. const partSocket = OuterContainer.parts.socket({
  23985. dom: {
  23986. tag: 'div',
  23987. classes: ['tox-edit-area']
  23988. }
  23989. });
  23990. const partSidebar = OuterContainer.parts.sidebar({
  23991. dom: {
  23992. tag: 'div',
  23993. classes: ['tox-sidebar']
  23994. }
  23995. });
  23996. return {
  23997. dom: {
  23998. tag: 'div',
  23999. classes: ['tox-sidebar-wrap']
  24000. },
  24001. components: [
  24002. partSocket,
  24003. partSidebar
  24004. ]
  24005. };
  24006. };
  24007. const renderDialogUi = () => {
  24008. const uiContainer = getUiContainer(editor);
  24009. const isGridUiContainer = eq(body(), uiContainer) && get$e(uiContainer, 'display') === 'grid';
  24010. const sinkSpec = {
  24011. dom: {
  24012. tag: 'div',
  24013. classes: [
  24014. 'tox',
  24015. 'tox-silver-sink',
  24016. 'tox-tinymce-aux'
  24017. ].concat(deviceClasses),
  24018. attributes: { ...global$8.isRtl() ? { dir: 'rtl' } : {} }
  24019. },
  24020. behaviours: derive$1([Positioning.config({ useFixed: () => header.isDocked(lazyHeader) })])
  24021. };
  24022. const reactiveWidthSpec = {
  24023. dom: { styles: { width: document.body.clientWidth + 'px' } },
  24024. events: derive$2([run$1(windowResize(), comp => {
  24025. set$8(comp.element, 'width', document.body.clientWidth + 'px');
  24026. })])
  24027. };
  24028. const sink = build$1(deepMerge(sinkSpec, isGridUiContainer ? reactiveWidthSpec : {}));
  24029. const uiMothership = takeover(sink);
  24030. lazyDialogMothership.set(uiMothership);
  24031. return {
  24032. sink,
  24033. mothership: uiMothership
  24034. };
  24035. };
  24036. const renderPopupUi = identity;
  24037. const renderMainUi = () => {
  24038. const partHeader = makeHeaderPart();
  24039. const sidebarContainer = makeSidebarDefinition();
  24040. const partThrobber = OuterContainer.parts.throbber({
  24041. dom: {
  24042. tag: 'div',
  24043. classes: ['tox-throbber']
  24044. },
  24045. backstage: backstages.popup
  24046. });
  24047. const partViewWrapper = OuterContainer.parts.viewWrapper({ backstage: backstages.popup });
  24048. const statusbar = useStatusBar(editor) && !isInline ? Optional.some(renderStatusbar(editor, backstages.popup.shared.providers)) : Optional.none();
  24049. const editorComponents = flatten([
  24050. isToolbarBottom ? [] : [partHeader],
  24051. isInline ? [] : [sidebarContainer],
  24052. isToolbarBottom ? [partHeader] : []
  24053. ]);
  24054. const editorContainer = OuterContainer.parts.editorContainer({
  24055. components: flatten([
  24056. editorComponents,
  24057. isInline ? [] : statusbar.toArray()
  24058. ])
  24059. });
  24060. const isHidden = isDistractionFree(editor);
  24061. const attributes = {
  24062. role: 'application',
  24063. ...global$8.isRtl() ? { dir: 'rtl' } : {},
  24064. ...isHidden ? { 'aria-hidden': 'true' } : {}
  24065. };
  24066. const outerContainer = build$1(OuterContainer.sketch({
  24067. dom: {
  24068. tag: 'div',
  24069. classes: [
  24070. 'tox',
  24071. 'tox-tinymce'
  24072. ].concat(isInline ? ['tox-tinymce-inline'] : []).concat(isToolbarBottom ? ['tox-tinymce--toolbar-bottom'] : []).concat(deviceClasses),
  24073. styles: {
  24074. visibility: 'hidden',
  24075. ...isHidden ? {
  24076. opacity: '0',
  24077. border: '0'
  24078. } : {}
  24079. },
  24080. attributes
  24081. },
  24082. components: [
  24083. editorContainer,
  24084. ...isInline ? [] : [partViewWrapper],
  24085. partThrobber
  24086. ],
  24087. behaviours: derive$1([
  24088. receivingConfig(),
  24089. Disabling.config({ disableClass: 'tox-tinymce--disabled' }),
  24090. Keying.config({
  24091. mode: 'cyclic',
  24092. selector: '.tox-menubar, .tox-toolbar, .tox-toolbar__primary, .tox-toolbar__overflow--open, .tox-sidebar__overflow--open, .tox-statusbar__path, .tox-statusbar__wordcount, .tox-statusbar__branding a, .tox-statusbar__resize-handle'
  24093. })
  24094. ])
  24095. }));
  24096. const mothership = takeover(outerContainer);
  24097. lazyMothership.set(mothership);
  24098. return {
  24099. mothership,
  24100. outerContainer
  24101. };
  24102. };
  24103. const setEditorSize = outerContainer => {
  24104. const parsedHeight = numToPx(getHeightWithFallback(editor));
  24105. const parsedWidth = numToPx(getWidthWithFallback(editor));
  24106. if (!editor.inline) {
  24107. if (isValidValue('div', 'width', parsedWidth)) {
  24108. set$8(outerContainer.element, 'width', parsedWidth);
  24109. }
  24110. if (isValidValue('div', 'height', parsedHeight)) {
  24111. set$8(outerContainer.element, 'height', parsedHeight);
  24112. } else {
  24113. set$8(outerContainer.element, 'height', '400px');
  24114. }
  24115. }
  24116. return parsedHeight;
  24117. };
  24118. const setupShortcutsAndCommands = outerContainer => {
  24119. editor.addShortcut('alt+F9', 'focus menubar', () => {
  24120. OuterContainer.focusMenubar(outerContainer);
  24121. });
  24122. editor.addShortcut('alt+F10', 'focus toolbar', () => {
  24123. OuterContainer.focusToolbar(outerContainer);
  24124. });
  24125. editor.addCommand('ToggleToolbarDrawer', () => {
  24126. OuterContainer.toggleToolbarDrawer(outerContainer);
  24127. });
  24128. editor.addQueryStateHandler('ToggleToolbarDrawer', () => OuterContainer.isToolbarDrawerToggled(outerContainer));
  24129. };
  24130. const renderUIWithRefs = uiRefs => {
  24131. const {mainUi, popupUi, uiMotherships} = uiRefs;
  24132. map$1(getToolbarGroups(editor), (toolbarGroupButtonConfig, name) => {
  24133. editor.ui.registry.addGroupToolbarButton(name, toolbarGroupButtonConfig);
  24134. });
  24135. const {buttons, menuItems, contextToolbars, sidebars, views} = editor.ui.registry.getAll();
  24136. const toolbarOpt = getMultipleToolbarsOption(editor);
  24137. const rawUiConfig = {
  24138. menuItems,
  24139. menus: getMenus(editor),
  24140. menubar: getMenubar(editor),
  24141. toolbar: toolbarOpt.getOrThunk(() => getToolbar(editor)),
  24142. allowToolbarGroups: toolbarMode === ToolbarMode$1.floating,
  24143. buttons,
  24144. sidebar: sidebars,
  24145. views
  24146. };
  24147. setupShortcutsAndCommands(mainUi.outerContainer);
  24148. setup$b(editor, mainUi.mothership, uiMotherships);
  24149. header.setup(editor, backstages.popup.shared, lazyHeader);
  24150. setup$6(editor, backstages.popup);
  24151. setup$5(editor, backstages.popup.shared.getSink, backstages.popup);
  24152. setup$8(editor);
  24153. setup$7(editor, lazyThrobber, backstages.popup.shared);
  24154. register$9(editor, contextToolbars, popupUi.sink, { backstage: backstages.popup });
  24155. setup$4(editor, popupUi.sink);
  24156. const elm = editor.getElement();
  24157. const height = setEditorSize(mainUi.outerContainer);
  24158. const args = {
  24159. targetNode: elm,
  24160. height
  24161. };
  24162. return mode.render(editor, uiRefs, rawUiConfig, backstages.popup, args);
  24163. };
  24164. const renderUI = () => {
  24165. const mainUi = renderMainUi();
  24166. const dialogUi = renderDialogUi();
  24167. const popupUi = renderPopupUi(dialogUi);
  24168. lazyUiRefs.dialogUi.set(dialogUi);
  24169. lazyUiRefs.popupUi.set(popupUi);
  24170. lazyUiRefs.mainUi.set(mainUi);
  24171. const uiRefs = {
  24172. popupUi,
  24173. dialogUi,
  24174. mainUi,
  24175. uiMotherships: lazyUiRefs.getUiMotherships()
  24176. };
  24177. return renderUIWithRefs(uiRefs);
  24178. };
  24179. return {
  24180. popups: {
  24181. backstage: backstages.popup,
  24182. getMothership: () => getLazyMothership('popups', lazyDialogMothership)
  24183. },
  24184. dialogs: {
  24185. backstage: backstages.dialog,
  24186. getMothership: () => getLazyMothership('dialogs', lazyDialogMothership)
  24187. },
  24188. renderUI
  24189. };
  24190. };
  24191. const describedBy = (describedElement, describeElement) => {
  24192. const describeId = Optional.from(get$f(describedElement, 'id')).fold(() => {
  24193. const id = generate$6('dialog-describe');
  24194. set$9(describeElement, 'id', id);
  24195. return id;
  24196. }, identity);
  24197. set$9(describedElement, 'aria-describedby', describeId);
  24198. };
  24199. const labelledBy = (labelledElement, labelElement) => {
  24200. const labelId = getOpt(labelledElement, 'id').fold(() => {
  24201. const id = generate$6('dialog-label');
  24202. set$9(labelElement, 'id', id);
  24203. return id;
  24204. }, identity);
  24205. set$9(labelledElement, 'aria-labelledby', labelId);
  24206. };
  24207. const schema$2 = constant$1([
  24208. required$1('lazySink'),
  24209. option$3('dragBlockClass'),
  24210. defaultedFunction('getBounds', win),
  24211. defaulted('useTabstopAt', always),
  24212. defaulted('eventOrder', {}),
  24213. field('modalBehaviours', [Keying]),
  24214. onKeyboardHandler('onExecute'),
  24215. onStrictKeyboardHandler('onEscape')
  24216. ]);
  24217. const basic = { sketch: identity };
  24218. const parts$2 = constant$1([
  24219. optional({
  24220. name: 'draghandle',
  24221. overrides: (detail, spec) => {
  24222. return {
  24223. behaviours: derive$1([Dragging.config({
  24224. mode: 'mouse',
  24225. getTarget: handle => {
  24226. return ancestor(handle, '[role="dialog"]').getOr(handle);
  24227. },
  24228. blockerClass: detail.dragBlockClass.getOrDie(new Error('The drag blocker class was not specified for a dialog with a drag handle: \n' + JSON.stringify(spec, null, 2)).message),
  24229. getBounds: detail.getDragBounds
  24230. })])
  24231. };
  24232. }
  24233. }),
  24234. required({
  24235. schema: [required$1('dom')],
  24236. name: 'title'
  24237. }),
  24238. required({
  24239. factory: basic,
  24240. schema: [required$1('dom')],
  24241. name: 'close'
  24242. }),
  24243. required({
  24244. factory: basic,
  24245. schema: [required$1('dom')],
  24246. name: 'body'
  24247. }),
  24248. optional({
  24249. factory: basic,
  24250. schema: [required$1('dom')],
  24251. name: 'footer'
  24252. }),
  24253. external({
  24254. factory: {
  24255. sketch: (spec, detail) => ({
  24256. ...spec,
  24257. dom: detail.dom,
  24258. components: detail.components
  24259. })
  24260. },
  24261. schema: [
  24262. defaulted('dom', {
  24263. tag: 'div',
  24264. styles: {
  24265. position: 'fixed',
  24266. left: '0px',
  24267. top: '0px',
  24268. right: '0px',
  24269. bottom: '0px'
  24270. }
  24271. }),
  24272. defaulted('components', [])
  24273. ],
  24274. name: 'blocker'
  24275. })
  24276. ]);
  24277. const factory$4 = (detail, components, spec, externals) => {
  24278. const dialogComp = value$2();
  24279. const showDialog = dialog => {
  24280. dialogComp.set(dialog);
  24281. const sink = detail.lazySink(dialog).getOrDie();
  24282. const externalBlocker = externals.blocker();
  24283. const blocker = sink.getSystem().build({
  24284. ...externalBlocker,
  24285. components: externalBlocker.components.concat([premade(dialog)]),
  24286. behaviours: derive$1([
  24287. Focusing.config({}),
  24288. config('dialog-blocker-events', [runOnSource(focusin(), () => {
  24289. Keying.focusIn(dialog);
  24290. })])
  24291. ])
  24292. });
  24293. attach(sink, blocker);
  24294. Keying.focusIn(dialog);
  24295. };
  24296. const hideDialog = dialog => {
  24297. dialogComp.clear();
  24298. parent(dialog.element).each(blockerDom => {
  24299. dialog.getSystem().getByDom(blockerDom).each(blocker => {
  24300. detach(blocker);
  24301. });
  24302. });
  24303. };
  24304. const getDialogBody = dialog => getPartOrDie(dialog, detail, 'body');
  24305. const getDialogFooter = dialog => getPartOrDie(dialog, detail, 'footer');
  24306. const setBusy = (dialog, getBusySpec) => {
  24307. Blocking.block(dialog, getBusySpec);
  24308. };
  24309. const setIdle = dialog => {
  24310. Blocking.unblock(dialog);
  24311. };
  24312. const modalEventsId = generate$6('modal-events');
  24313. const eventOrder = {
  24314. ...detail.eventOrder,
  24315. [attachedToDom()]: [modalEventsId].concat(detail.eventOrder['alloy.system.attached'] || [])
  24316. };
  24317. return {
  24318. uid: detail.uid,
  24319. dom: detail.dom,
  24320. components,
  24321. apis: {
  24322. show: showDialog,
  24323. hide: hideDialog,
  24324. getBody: getDialogBody,
  24325. getFooter: getDialogFooter,
  24326. setIdle,
  24327. setBusy
  24328. },
  24329. eventOrder,
  24330. domModification: {
  24331. attributes: {
  24332. 'role': 'dialog',
  24333. 'aria-modal': 'true'
  24334. }
  24335. },
  24336. behaviours: augment(detail.modalBehaviours, [
  24337. Replacing.config({}),
  24338. Keying.config({
  24339. mode: 'cyclic',
  24340. onEnter: detail.onExecute,
  24341. onEscape: detail.onEscape,
  24342. useTabstopAt: detail.useTabstopAt
  24343. }),
  24344. Blocking.config({ getRoot: dialogComp.get }),
  24345. config(modalEventsId, [runOnAttached(c => {
  24346. labelledBy(c.element, getPartOrDie(c, detail, 'title').element);
  24347. describedBy(c.element, getPartOrDie(c, detail, 'body').element);
  24348. })])
  24349. ])
  24350. };
  24351. };
  24352. const ModalDialog = composite({
  24353. name: 'ModalDialog',
  24354. configFields: schema$2(),
  24355. partFields: parts$2(),
  24356. factory: factory$4,
  24357. apis: {
  24358. show: (apis, dialog) => {
  24359. apis.show(dialog);
  24360. },
  24361. hide: (apis, dialog) => {
  24362. apis.hide(dialog);
  24363. },
  24364. getBody: (apis, dialog) => apis.getBody(dialog),
  24365. getFooter: (apis, dialog) => apis.getFooter(dialog),
  24366. setBusy: (apis, dialog, getBusySpec) => {
  24367. apis.setBusy(dialog, getBusySpec);
  24368. },
  24369. setIdle: (apis, dialog) => {
  24370. apis.setIdle(dialog);
  24371. }
  24372. }
  24373. });
  24374. const dialogToggleMenuItemSchema = objOf([
  24375. type,
  24376. name$1
  24377. ].concat(commonMenuItemFields));
  24378. const dialogToggleMenuItemDataProcessor = boolean;
  24379. const baseFooterButtonFields = [
  24380. generatedName('button'),
  24381. optionalIcon,
  24382. defaultedStringEnum('align', 'end', [
  24383. 'start',
  24384. 'end'
  24385. ]),
  24386. primary,
  24387. enabled,
  24388. optionStringEnum('buttonType', [
  24389. 'primary',
  24390. 'secondary'
  24391. ])
  24392. ];
  24393. const dialogFooterButtonFields = [
  24394. ...baseFooterButtonFields,
  24395. text$1
  24396. ];
  24397. const normalFooterButtonFields = [
  24398. requiredStringEnum('type', [
  24399. 'submit',
  24400. 'cancel',
  24401. 'custom'
  24402. ]),
  24403. ...dialogFooterButtonFields
  24404. ];
  24405. const menuFooterButtonFields = [
  24406. requiredStringEnum('type', ['menu']),
  24407. optionalText,
  24408. optionalTooltip,
  24409. optionalIcon,
  24410. requiredArrayOf('items', dialogToggleMenuItemSchema),
  24411. ...baseFooterButtonFields
  24412. ];
  24413. const dialogFooterButtonSchema = choose$1('type', {
  24414. submit: normalFooterButtonFields,
  24415. cancel: normalFooterButtonFields,
  24416. custom: normalFooterButtonFields,
  24417. menu: menuFooterButtonFields
  24418. });
  24419. const alertBannerFields = [
  24420. type,
  24421. text$1,
  24422. requiredStringEnum('level', [
  24423. 'info',
  24424. 'warn',
  24425. 'error',
  24426. 'success'
  24427. ]),
  24428. icon,
  24429. defaulted('url', '')
  24430. ];
  24431. const alertBannerSchema = objOf(alertBannerFields);
  24432. const createBarFields = itemsField => [
  24433. type,
  24434. itemsField
  24435. ];
  24436. const buttonFields = [
  24437. type,
  24438. text$1,
  24439. enabled,
  24440. generatedName('button'),
  24441. optionalIcon,
  24442. borderless,
  24443. optionStringEnum('buttonType', [
  24444. 'primary',
  24445. 'secondary',
  24446. 'toolbar'
  24447. ]),
  24448. primary
  24449. ];
  24450. const buttonSchema = objOf(buttonFields);
  24451. const formComponentFields = [
  24452. type,
  24453. name$1
  24454. ];
  24455. const formComponentWithLabelFields = formComponentFields.concat([optionalLabel]);
  24456. const checkboxFields = formComponentFields.concat([
  24457. label,
  24458. enabled
  24459. ]);
  24460. const checkboxSchema = objOf(checkboxFields);
  24461. const checkboxDataProcessor = boolean;
  24462. const collectionFields = formComponentWithLabelFields.concat([defaultedColumns('auto')]);
  24463. const collectionSchema = objOf(collectionFields);
  24464. const collectionDataProcessor = arrOfObj([
  24465. value$1,
  24466. text$1,
  24467. icon
  24468. ]);
  24469. const colorInputFields = formComponentWithLabelFields.concat([defaultedString('storageKey', 'default')]);
  24470. const colorInputSchema = objOf(colorInputFields);
  24471. const colorInputDataProcessor = string;
  24472. const colorPickerFields = formComponentWithLabelFields;
  24473. const colorPickerSchema = objOf(colorPickerFields);
  24474. const colorPickerDataProcessor = string;
  24475. const customEditorFields = formComponentFields.concat([
  24476. defaultedString('tag', 'textarea'),
  24477. requiredString('scriptId'),
  24478. requiredString('scriptUrl'),
  24479. defaultedPostMsg('settings', undefined)
  24480. ]);
  24481. const customEditorFieldsOld = formComponentFields.concat([
  24482. defaultedString('tag', 'textarea'),
  24483. requiredFunction('init')
  24484. ]);
  24485. const customEditorSchema = valueOf(v => asRaw('customeditor.old', objOfOnly(customEditorFieldsOld), v).orThunk(() => asRaw('customeditor.new', objOfOnly(customEditorFields), v)));
  24486. const customEditorDataProcessor = string;
  24487. const dropZoneFields = formComponentWithLabelFields;
  24488. const dropZoneSchema = objOf(dropZoneFields);
  24489. const dropZoneDataProcessor = arrOfVal();
  24490. const createGridFields = itemsField => [
  24491. type,
  24492. requiredNumber('columns'),
  24493. itemsField
  24494. ];
  24495. const htmlPanelFields = [
  24496. type,
  24497. requiredString('html'),
  24498. defaultedStringEnum('presets', 'presentation', [
  24499. 'presentation',
  24500. 'document'
  24501. ])
  24502. ];
  24503. const htmlPanelSchema = objOf(htmlPanelFields);
  24504. const iframeFields = formComponentWithLabelFields.concat([
  24505. defaultedBoolean('sandboxed', true),
  24506. defaultedBoolean('transparent', true)
  24507. ]);
  24508. const iframeSchema = objOf(iframeFields);
  24509. const iframeDataProcessor = string;
  24510. const imagePreviewSchema = objOf(formComponentFields.concat([optionString('height')]));
  24511. const imagePreviewDataProcessor = objOf([
  24512. requiredString('url'),
  24513. optionNumber('zoom'),
  24514. optionNumber('cachedWidth'),
  24515. optionNumber('cachedHeight')
  24516. ]);
  24517. const inputFields = formComponentWithLabelFields.concat([
  24518. optionString('inputMode'),
  24519. optionString('placeholder'),
  24520. defaultedBoolean('maximized', false),
  24521. enabled
  24522. ]);
  24523. const inputSchema = objOf(inputFields);
  24524. const inputDataProcessor = string;
  24525. const createLabelFields = itemsField => [
  24526. type,
  24527. label,
  24528. itemsField
  24529. ];
  24530. const listBoxSingleItemFields = [
  24531. text$1,
  24532. value$1
  24533. ];
  24534. const listBoxNestedItemFields = [
  24535. text$1,
  24536. requiredArrayOf('items', thunkOf('items', () => listBoxItemSchema))
  24537. ];
  24538. const listBoxItemSchema = oneOf([
  24539. objOf(listBoxSingleItemFields),
  24540. objOf(listBoxNestedItemFields)
  24541. ]);
  24542. const listBoxFields = formComponentWithLabelFields.concat([
  24543. requiredArrayOf('items', listBoxItemSchema),
  24544. enabled
  24545. ]);
  24546. const listBoxSchema = objOf(listBoxFields);
  24547. const listBoxDataProcessor = string;
  24548. const selectBoxFields = formComponentWithLabelFields.concat([
  24549. requiredArrayOfObj('items', [
  24550. text$1,
  24551. value$1
  24552. ]),
  24553. defaultedNumber('size', 1),
  24554. enabled
  24555. ]);
  24556. const selectBoxSchema = objOf(selectBoxFields);
  24557. const selectBoxDataProcessor = string;
  24558. const sizeInputFields = formComponentWithLabelFields.concat([
  24559. defaultedBoolean('constrain', true),
  24560. enabled
  24561. ]);
  24562. const sizeInputSchema = objOf(sizeInputFields);
  24563. const sizeInputDataProcessor = objOf([
  24564. requiredString('width'),
  24565. requiredString('height')
  24566. ]);
  24567. const sliderFields = formComponentFields.concat([
  24568. label,
  24569. defaultedNumber('min', 0),
  24570. defaultedNumber('max', 0)
  24571. ]);
  24572. const sliderSchema = objOf(sliderFields);
  24573. const sliderInputDataProcessor = number;
  24574. const tableFields = [
  24575. type,
  24576. requiredArrayOf('header', string),
  24577. requiredArrayOf('cells', arrOf(string))
  24578. ];
  24579. const tableSchema = objOf(tableFields);
  24580. const textAreaFields = formComponentWithLabelFields.concat([
  24581. optionString('placeholder'),
  24582. defaultedBoolean('maximized', false),
  24583. enabled
  24584. ]);
  24585. const textAreaSchema = objOf(textAreaFields);
  24586. const textAreaDataProcessor = string;
  24587. const urlInputFields = formComponentWithLabelFields.concat([
  24588. defaultedStringEnum('filetype', 'file', [
  24589. 'image',
  24590. 'media',
  24591. 'file'
  24592. ]),
  24593. enabled
  24594. ]);
  24595. const urlInputSchema = objOf(urlInputFields);
  24596. const urlInputDataProcessor = objOf([
  24597. value$1,
  24598. defaultedMeta
  24599. ]);
  24600. const createItemsField = name => field$1('items', 'items', required$2(), arrOf(valueOf(v => asRaw(`Checking item of ${ name }`, itemSchema, v).fold(sErr => Result.error(formatError(sErr)), passValue => Result.value(passValue)))));
  24601. const itemSchema = valueThunk(() => choose$2('type', {
  24602. alertbanner: alertBannerSchema,
  24603. bar: objOf(createBarFields(createItemsField('bar'))),
  24604. button: buttonSchema,
  24605. checkbox: checkboxSchema,
  24606. colorinput: colorInputSchema,
  24607. colorpicker: colorPickerSchema,
  24608. dropzone: dropZoneSchema,
  24609. grid: objOf(createGridFields(createItemsField('grid'))),
  24610. iframe: iframeSchema,
  24611. input: inputSchema,
  24612. listbox: listBoxSchema,
  24613. selectbox: selectBoxSchema,
  24614. sizeinput: sizeInputSchema,
  24615. slider: sliderSchema,
  24616. textarea: textAreaSchema,
  24617. urlinput: urlInputSchema,
  24618. customeditor: customEditorSchema,
  24619. htmlpanel: htmlPanelSchema,
  24620. imagepreview: imagePreviewSchema,
  24621. collection: collectionSchema,
  24622. label: objOf(createLabelFields(createItemsField('label'))),
  24623. table: tableSchema,
  24624. panel: panelSchema
  24625. }));
  24626. const panelFields = [
  24627. type,
  24628. defaulted('classes', []),
  24629. requiredArrayOf('items', itemSchema)
  24630. ];
  24631. const panelSchema = objOf(panelFields);
  24632. const tabFields = [
  24633. generatedName('tab'),
  24634. title,
  24635. requiredArrayOf('items', itemSchema)
  24636. ];
  24637. const tabPanelFields = [
  24638. type,
  24639. requiredArrayOfObj('tabs', tabFields)
  24640. ];
  24641. const tabPanelSchema = objOf(tabPanelFields);
  24642. const dialogButtonFields = dialogFooterButtonFields;
  24643. const dialogButtonSchema = dialogFooterButtonSchema;
  24644. const dialogSchema = objOf([
  24645. requiredString('title'),
  24646. requiredOf('body', choose$2('type', {
  24647. panel: panelSchema,
  24648. tabpanel: tabPanelSchema
  24649. })),
  24650. defaultedString('size', 'normal'),
  24651. requiredArrayOf('buttons', dialogButtonSchema),
  24652. defaulted('initialData', {}),
  24653. defaultedFunction('onAction', noop),
  24654. defaultedFunction('onChange', noop),
  24655. defaultedFunction('onSubmit', noop),
  24656. defaultedFunction('onClose', noop),
  24657. defaultedFunction('onCancel', noop),
  24658. defaultedFunction('onTabChange', noop)
  24659. ]);
  24660. const createDialog = spec => asRaw('dialog', dialogSchema, spec);
  24661. const urlDialogButtonSchema = objOf([
  24662. requiredStringEnum('type', [
  24663. 'cancel',
  24664. 'custom'
  24665. ]),
  24666. ...dialogButtonFields
  24667. ]);
  24668. const urlDialogSchema = objOf([
  24669. requiredString('title'),
  24670. requiredString('url'),
  24671. optionNumber('height'),
  24672. optionNumber('width'),
  24673. optionArrayOf('buttons', urlDialogButtonSchema),
  24674. defaultedFunction('onAction', noop),
  24675. defaultedFunction('onCancel', noop),
  24676. defaultedFunction('onClose', noop),
  24677. defaultedFunction('onMessage', noop)
  24678. ]);
  24679. const createUrlDialog = spec => asRaw('dialog', urlDialogSchema, spec);
  24680. const getAllObjects = obj => {
  24681. if (isObject(obj)) {
  24682. return [obj].concat(bind$3(values(obj), getAllObjects));
  24683. } else if (isArray(obj)) {
  24684. return bind$3(obj, getAllObjects);
  24685. } else {
  24686. return [];
  24687. }
  24688. };
  24689. const isNamedItem = obj => isString(obj.type) && isString(obj.name);
  24690. const dataProcessors = {
  24691. checkbox: checkboxDataProcessor,
  24692. colorinput: colorInputDataProcessor,
  24693. colorpicker: colorPickerDataProcessor,
  24694. dropzone: dropZoneDataProcessor,
  24695. input: inputDataProcessor,
  24696. iframe: iframeDataProcessor,
  24697. imagepreview: imagePreviewDataProcessor,
  24698. selectbox: selectBoxDataProcessor,
  24699. sizeinput: sizeInputDataProcessor,
  24700. slider: sliderInputDataProcessor,
  24701. listbox: listBoxDataProcessor,
  24702. size: sizeInputDataProcessor,
  24703. textarea: textAreaDataProcessor,
  24704. urlinput: urlInputDataProcessor,
  24705. customeditor: customEditorDataProcessor,
  24706. collection: collectionDataProcessor,
  24707. togglemenuitem: dialogToggleMenuItemDataProcessor
  24708. };
  24709. const getDataProcessor = item => Optional.from(dataProcessors[item.type]);
  24710. const getNamedItems = structure => filter$2(getAllObjects(structure), isNamedItem);
  24711. const createDataValidator = structure => {
  24712. const namedItems = getNamedItems(structure);
  24713. const fields = bind$3(namedItems, item => getDataProcessor(item).fold(() => [], schema => [requiredOf(item.name, schema)]));
  24714. return objOf(fields);
  24715. };
  24716. const extract = structure => {
  24717. var _a;
  24718. const internalDialog = getOrDie(createDialog(structure));
  24719. const dataValidator = createDataValidator(structure);
  24720. const initialData = (_a = structure.initialData) !== null && _a !== void 0 ? _a : {};
  24721. return {
  24722. internalDialog,
  24723. dataValidator,
  24724. initialData
  24725. };
  24726. };
  24727. const DialogManager = {
  24728. open: (factory, structure) => {
  24729. const extraction = extract(structure);
  24730. return factory(extraction.internalDialog, extraction.initialData, extraction.dataValidator);
  24731. },
  24732. openUrl: (factory, structure) => {
  24733. const internalDialog = getOrDie(createUrlDialog(structure));
  24734. return factory(internalDialog);
  24735. },
  24736. redial: structure => extract(structure)
  24737. };
  24738. const toValidValues = values => {
  24739. const errors = [];
  24740. const result = {};
  24741. each(values, (value, name) => {
  24742. value.fold(() => {
  24743. errors.push(name);
  24744. }, v => {
  24745. result[name] = v;
  24746. });
  24747. });
  24748. return errors.length > 0 ? Result.error(errors) : Result.value(result);
  24749. };
  24750. const renderBodyPanel = (spec, dialogData, backstage) => {
  24751. const memForm = record(Form.sketch(parts => ({
  24752. dom: {
  24753. tag: 'div',
  24754. classes: ['tox-form'].concat(spec.classes)
  24755. },
  24756. components: map$2(spec.items, item => interpretInForm(parts, item, dialogData, backstage))
  24757. })));
  24758. return {
  24759. dom: {
  24760. tag: 'div',
  24761. classes: ['tox-dialog__body']
  24762. },
  24763. components: [{
  24764. dom: {
  24765. tag: 'div',
  24766. classes: ['tox-dialog__body-content']
  24767. },
  24768. components: [memForm.asSpec()]
  24769. }],
  24770. behaviours: derive$1([
  24771. Keying.config({
  24772. mode: 'acyclic',
  24773. useTabstopAt: not(isPseudoStop)
  24774. }),
  24775. ComposingConfigs.memento(memForm),
  24776. RepresentingConfigs.memento(memForm, {
  24777. postprocess: formValue => toValidValues(formValue).fold(err => {
  24778. console.error(err);
  24779. return {};
  24780. }, identity)
  24781. })
  24782. ])
  24783. };
  24784. };
  24785. const factory$3 = (detail, _spec) => ({
  24786. uid: detail.uid,
  24787. dom: detail.dom,
  24788. components: detail.components,
  24789. events: events$a(detail.action),
  24790. behaviours: augment(detail.tabButtonBehaviours, [
  24791. Focusing.config({}),
  24792. Keying.config({
  24793. mode: 'execution',
  24794. useSpace: true,
  24795. useEnter: true
  24796. }),
  24797. Representing.config({
  24798. store: {
  24799. mode: 'memory',
  24800. initialValue: detail.value
  24801. }
  24802. })
  24803. ]),
  24804. domModification: detail.domModification
  24805. });
  24806. const TabButton = single({
  24807. name: 'TabButton',
  24808. configFields: [
  24809. defaulted('uid', undefined),
  24810. required$1('value'),
  24811. field$1('dom', 'dom', mergeWithThunk(() => ({
  24812. attributes: {
  24813. 'role': 'tab',
  24814. 'id': generate$6('aria'),
  24815. 'aria-selected': 'false'
  24816. }
  24817. })), anyValue()),
  24818. option$3('action'),
  24819. defaulted('domModification', {}),
  24820. field('tabButtonBehaviours', [
  24821. Focusing,
  24822. Keying,
  24823. Representing
  24824. ]),
  24825. required$1('view')
  24826. ],
  24827. factory: factory$3
  24828. });
  24829. const schema$1 = constant$1([
  24830. required$1('tabs'),
  24831. required$1('dom'),
  24832. defaulted('clickToDismiss', false),
  24833. field('tabbarBehaviours', [
  24834. Highlighting,
  24835. Keying
  24836. ]),
  24837. markers$1([
  24838. 'tabClass',
  24839. 'selectedClass'
  24840. ])
  24841. ]);
  24842. const tabsPart = group({
  24843. factory: TabButton,
  24844. name: 'tabs',
  24845. unit: 'tab',
  24846. overrides: barDetail => {
  24847. const dismissTab$1 = (tabbar, button) => {
  24848. Highlighting.dehighlight(tabbar, button);
  24849. emitWith(tabbar, dismissTab(), {
  24850. tabbar,
  24851. button
  24852. });
  24853. };
  24854. const changeTab$1 = (tabbar, button) => {
  24855. Highlighting.highlight(tabbar, button);
  24856. emitWith(tabbar, changeTab(), {
  24857. tabbar,
  24858. button
  24859. });
  24860. };
  24861. return {
  24862. action: button => {
  24863. const tabbar = button.getSystem().getByUid(barDetail.uid).getOrDie();
  24864. const activeButton = Highlighting.isHighlighted(tabbar, button);
  24865. const response = (() => {
  24866. if (activeButton && barDetail.clickToDismiss) {
  24867. return dismissTab$1;
  24868. } else if (!activeButton) {
  24869. return changeTab$1;
  24870. } else {
  24871. return noop;
  24872. }
  24873. })();
  24874. response(tabbar, button);
  24875. },
  24876. domModification: { classes: [barDetail.markers.tabClass] }
  24877. };
  24878. }
  24879. });
  24880. const parts$1 = constant$1([tabsPart]);
  24881. const factory$2 = (detail, components, _spec, _externals) => ({
  24882. 'uid': detail.uid,
  24883. 'dom': detail.dom,
  24884. components,
  24885. 'debug.sketcher': 'Tabbar',
  24886. 'domModification': { attributes: { role: 'tablist' } },
  24887. 'behaviours': augment(detail.tabbarBehaviours, [
  24888. Highlighting.config({
  24889. highlightClass: detail.markers.selectedClass,
  24890. itemClass: detail.markers.tabClass,
  24891. onHighlight: (tabbar, tab) => {
  24892. set$9(tab.element, 'aria-selected', 'true');
  24893. },
  24894. onDehighlight: (tabbar, tab) => {
  24895. set$9(tab.element, 'aria-selected', 'false');
  24896. }
  24897. }),
  24898. Keying.config({
  24899. mode: 'flow',
  24900. getInitial: tabbar => {
  24901. return Highlighting.getHighlighted(tabbar).map(tab => tab.element);
  24902. },
  24903. selector: '.' + detail.markers.tabClass,
  24904. executeOnMove: true
  24905. })
  24906. ])
  24907. });
  24908. const Tabbar = composite({
  24909. name: 'Tabbar',
  24910. configFields: schema$1(),
  24911. partFields: parts$1(),
  24912. factory: factory$2
  24913. });
  24914. const factory$1 = (detail, _spec) => ({
  24915. uid: detail.uid,
  24916. dom: detail.dom,
  24917. behaviours: augment(detail.tabviewBehaviours, [Replacing.config({})]),
  24918. domModification: { attributes: { role: 'tabpanel' } }
  24919. });
  24920. const Tabview = single({
  24921. name: 'Tabview',
  24922. configFields: [field('tabviewBehaviours', [Replacing])],
  24923. factory: factory$1
  24924. });
  24925. const schema = constant$1([
  24926. defaulted('selectFirst', true),
  24927. onHandler('onChangeTab'),
  24928. onHandler('onDismissTab'),
  24929. defaulted('tabs', []),
  24930. field('tabSectionBehaviours', [])
  24931. ]);
  24932. const barPart = required({
  24933. factory: Tabbar,
  24934. schema: [
  24935. required$1('dom'),
  24936. requiredObjOf('markers', [
  24937. required$1('tabClass'),
  24938. required$1('selectedClass')
  24939. ])
  24940. ],
  24941. name: 'tabbar',
  24942. defaults: detail => {
  24943. return { tabs: detail.tabs };
  24944. }
  24945. });
  24946. const viewPart = required({
  24947. factory: Tabview,
  24948. name: 'tabview'
  24949. });
  24950. const parts = constant$1([
  24951. barPart,
  24952. viewPart
  24953. ]);
  24954. const factory = (detail, components, _spec, _externals) => {
  24955. const changeTab$1 = button => {
  24956. const tabValue = Representing.getValue(button);
  24957. getPart(button, detail, 'tabview').each(tabview => {
  24958. const tabWithValue = find$5(detail.tabs, t => t.value === tabValue);
  24959. tabWithValue.each(tabData => {
  24960. const panel = tabData.view();
  24961. getOpt(button.element, 'id').each(id => {
  24962. set$9(tabview.element, 'aria-labelledby', id);
  24963. });
  24964. Replacing.set(tabview, panel);
  24965. detail.onChangeTab(tabview, button, panel);
  24966. });
  24967. });
  24968. };
  24969. const changeTabBy = (section, byPred) => {
  24970. getPart(section, detail, 'tabbar').each(tabbar => {
  24971. byPred(tabbar).each(emitExecute);
  24972. });
  24973. };
  24974. return {
  24975. uid: detail.uid,
  24976. dom: detail.dom,
  24977. components,
  24978. behaviours: get$3(detail.tabSectionBehaviours),
  24979. events: derive$2(flatten([
  24980. detail.selectFirst ? [runOnAttached((section, _simulatedEvent) => {
  24981. changeTabBy(section, Highlighting.getFirst);
  24982. })] : [],
  24983. [
  24984. run$1(changeTab(), (section, simulatedEvent) => {
  24985. const button = simulatedEvent.event.button;
  24986. changeTab$1(button);
  24987. }),
  24988. run$1(dismissTab(), (section, simulatedEvent) => {
  24989. const button = simulatedEvent.event.button;
  24990. detail.onDismissTab(section, button);
  24991. })
  24992. ]
  24993. ])),
  24994. apis: {
  24995. getViewItems: section => {
  24996. return getPart(section, detail, 'tabview').map(tabview => Replacing.contents(tabview)).getOr([]);
  24997. },
  24998. showTab: (section, tabKey) => {
  24999. const getTabIfNotActive = tabbar => {
  25000. const candidates = Highlighting.getCandidates(tabbar);
  25001. const optTab = find$5(candidates, c => Representing.getValue(c) === tabKey);
  25002. return optTab.filter(tab => !Highlighting.isHighlighted(tabbar, tab));
  25003. };
  25004. changeTabBy(section, getTabIfNotActive);
  25005. }
  25006. }
  25007. };
  25008. };
  25009. const TabSection = composite({
  25010. name: 'TabSection',
  25011. configFields: schema(),
  25012. partFields: parts(),
  25013. factory,
  25014. apis: {
  25015. getViewItems: (apis, component) => apis.getViewItems(component),
  25016. showTab: (apis, component, tabKey) => {
  25017. apis.showTab(component, tabKey);
  25018. }
  25019. }
  25020. });
  25021. const measureHeights = (allTabs, tabview, tabviewComp) => map$2(allTabs, (_tab, i) => {
  25022. Replacing.set(tabviewComp, allTabs[i].view());
  25023. const rect = tabview.dom.getBoundingClientRect();
  25024. Replacing.set(tabviewComp, []);
  25025. return rect.height;
  25026. });
  25027. const getMaxHeight = heights => head(sort(heights, (a, b) => {
  25028. if (a > b) {
  25029. return -1;
  25030. } else if (a < b) {
  25031. return +1;
  25032. } else {
  25033. return 0;
  25034. }
  25035. }));
  25036. const getMaxTabviewHeight = (dialog, tabview, tablist) => {
  25037. const documentElement$1 = documentElement(dialog).dom;
  25038. const rootElm = ancestor(dialog, '.tox-dialog-wrap').getOr(dialog);
  25039. const isFixed = get$e(rootElm, 'position') === 'fixed';
  25040. let maxHeight;
  25041. if (isFixed) {
  25042. maxHeight = Math.max(documentElement$1.clientHeight, window.innerHeight);
  25043. } else {
  25044. maxHeight = Math.max(documentElement$1.offsetHeight, documentElement$1.scrollHeight);
  25045. }
  25046. const tabviewHeight = get$d(tabview);
  25047. const isTabListBeside = tabview.dom.offsetLeft >= tablist.dom.offsetLeft + get$c(tablist);
  25048. const currentTabHeight = isTabListBeside ? Math.max(get$d(tablist), tabviewHeight) : tabviewHeight;
  25049. const dialogTopMargin = parseInt(get$e(dialog, 'margin-top'), 10) || 0;
  25050. const dialogBottomMargin = parseInt(get$e(dialog, 'margin-bottom'), 10) || 0;
  25051. const dialogHeight = get$d(dialog) + dialogTopMargin + dialogBottomMargin;
  25052. const chromeHeight = dialogHeight - currentTabHeight;
  25053. return maxHeight - chromeHeight;
  25054. };
  25055. const showTab = (allTabs, comp) => {
  25056. head(allTabs).each(tab => TabSection.showTab(comp, tab.value));
  25057. };
  25058. const setTabviewHeight = (tabview, height) => {
  25059. set$8(tabview, 'height', height + 'px');
  25060. set$8(tabview, 'flex-basis', height + 'px');
  25061. };
  25062. const updateTabviewHeight = (dialogBody, tabview, maxTabHeight) => {
  25063. ancestor(dialogBody, '[role="dialog"]').each(dialog => {
  25064. descendant(dialog, '[role="tablist"]').each(tablist => {
  25065. maxTabHeight.get().map(height => {
  25066. set$8(tabview, 'height', '0');
  25067. set$8(tabview, 'flex-basis', '0');
  25068. return Math.min(height, getMaxTabviewHeight(dialog, tabview, tablist));
  25069. }).each(height => {
  25070. setTabviewHeight(tabview, height);
  25071. });
  25072. });
  25073. });
  25074. };
  25075. const getTabview = dialog => descendant(dialog, '[role="tabpanel"]');
  25076. const smartMode = allTabs => {
  25077. const maxTabHeight = value$2();
  25078. const extraEvents = [
  25079. runOnAttached(comp => {
  25080. const dialog = comp.element;
  25081. getTabview(dialog).each(tabview => {
  25082. set$8(tabview, 'visibility', 'hidden');
  25083. comp.getSystem().getByDom(tabview).toOptional().each(tabviewComp => {
  25084. const heights = measureHeights(allTabs, tabview, tabviewComp);
  25085. const maxTabHeightOpt = getMaxHeight(heights);
  25086. maxTabHeightOpt.fold(maxTabHeight.clear, maxTabHeight.set);
  25087. });
  25088. updateTabviewHeight(dialog, tabview, maxTabHeight);
  25089. remove$6(tabview, 'visibility');
  25090. showTab(allTabs, comp);
  25091. requestAnimationFrame(() => {
  25092. updateTabviewHeight(dialog, tabview, maxTabHeight);
  25093. });
  25094. });
  25095. }),
  25096. run$1(windowResize(), comp => {
  25097. const dialog = comp.element;
  25098. getTabview(dialog).each(tabview => {
  25099. updateTabviewHeight(dialog, tabview, maxTabHeight);
  25100. });
  25101. }),
  25102. run$1(formResizeEvent, (comp, _se) => {
  25103. const dialog = comp.element;
  25104. getTabview(dialog).each(tabview => {
  25105. const oldFocus = active$1(getRootNode(tabview));
  25106. set$8(tabview, 'visibility', 'hidden');
  25107. const oldHeight = getRaw(tabview, 'height').map(h => parseInt(h, 10));
  25108. remove$6(tabview, 'height');
  25109. remove$6(tabview, 'flex-basis');
  25110. const newHeight = tabview.dom.getBoundingClientRect().height;
  25111. const hasGrown = oldHeight.forall(h => newHeight > h);
  25112. if (hasGrown) {
  25113. maxTabHeight.set(newHeight);
  25114. updateTabviewHeight(dialog, tabview, maxTabHeight);
  25115. } else {
  25116. oldHeight.each(h => {
  25117. setTabviewHeight(tabview, h);
  25118. });
  25119. }
  25120. remove$6(tabview, 'visibility');
  25121. oldFocus.each(focus$3);
  25122. });
  25123. })
  25124. ];
  25125. const selectFirst = false;
  25126. return {
  25127. extraEvents,
  25128. selectFirst
  25129. };
  25130. };
  25131. const SendDataToSectionChannel = 'send-data-to-section';
  25132. const SendDataToViewChannel = 'send-data-to-view';
  25133. const renderTabPanel = (spec, dialogData, backstage) => {
  25134. const storedValue = Cell({});
  25135. const updateDataWithForm = form => {
  25136. const formData = Representing.getValue(form);
  25137. const validData = toValidValues(formData).getOr({});
  25138. const currentData = storedValue.get();
  25139. const newData = deepMerge(currentData, validData);
  25140. storedValue.set(newData);
  25141. };
  25142. const setDataOnForm = form => {
  25143. const tabData = storedValue.get();
  25144. Representing.setValue(form, tabData);
  25145. };
  25146. const oldTab = Cell(null);
  25147. const allTabs = map$2(spec.tabs, tab => {
  25148. return {
  25149. value: tab.name,
  25150. dom: {
  25151. tag: 'div',
  25152. classes: ['tox-dialog__body-nav-item']
  25153. },
  25154. components: [text$2(backstage.shared.providers.translate(tab.title))],
  25155. view: () => {
  25156. return [Form.sketch(parts => ({
  25157. dom: {
  25158. tag: 'div',
  25159. classes: ['tox-form']
  25160. },
  25161. components: map$2(tab.items, item => interpretInForm(parts, item, dialogData, backstage)),
  25162. formBehaviours: derive$1([
  25163. Keying.config({
  25164. mode: 'acyclic',
  25165. useTabstopAt: not(isPseudoStop)
  25166. }),
  25167. config('TabView.form.events', [
  25168. runOnAttached(setDataOnForm),
  25169. runOnDetached(updateDataWithForm)
  25170. ]),
  25171. Receiving.config({
  25172. channels: wrapAll([
  25173. {
  25174. key: SendDataToSectionChannel,
  25175. value: { onReceive: updateDataWithForm }
  25176. },
  25177. {
  25178. key: SendDataToViewChannel,
  25179. value: { onReceive: setDataOnForm }
  25180. }
  25181. ])
  25182. })
  25183. ])
  25184. }))];
  25185. }
  25186. };
  25187. });
  25188. const tabMode = smartMode(allTabs);
  25189. return TabSection.sketch({
  25190. dom: {
  25191. tag: 'div',
  25192. classes: ['tox-dialog__body']
  25193. },
  25194. onChangeTab: (section, button, _viewItems) => {
  25195. const name = Representing.getValue(button);
  25196. emitWith(section, formTabChangeEvent, {
  25197. name,
  25198. oldName: oldTab.get()
  25199. });
  25200. oldTab.set(name);
  25201. },
  25202. tabs: allTabs,
  25203. components: [
  25204. TabSection.parts.tabbar({
  25205. dom: {
  25206. tag: 'div',
  25207. classes: ['tox-dialog__body-nav']
  25208. },
  25209. components: [Tabbar.parts.tabs({})],
  25210. markers: {
  25211. tabClass: 'tox-tab',
  25212. selectedClass: 'tox-dialog__body-nav-item--active'
  25213. },
  25214. tabbarBehaviours: derive$1([Tabstopping.config({})])
  25215. }),
  25216. TabSection.parts.tabview({
  25217. dom: {
  25218. tag: 'div',
  25219. classes: ['tox-dialog__body-content']
  25220. }
  25221. })
  25222. ],
  25223. selectFirst: tabMode.selectFirst,
  25224. tabSectionBehaviours: derive$1([
  25225. config('tabpanel', tabMode.extraEvents),
  25226. Keying.config({ mode: 'acyclic' }),
  25227. Composing.config({ find: comp => head(TabSection.getViewItems(comp)) }),
  25228. RepresentingConfigs.withComp(Optional.none(), tsection => {
  25229. tsection.getSystem().broadcastOn([SendDataToSectionChannel], {});
  25230. return storedValue.get();
  25231. }, (tsection, value) => {
  25232. storedValue.set(value);
  25233. tsection.getSystem().broadcastOn([SendDataToViewChannel], {});
  25234. })
  25235. ])
  25236. });
  25237. };
  25238. const dialogChannel = generate$6('update-dialog');
  25239. const titleChannel = generate$6('update-title');
  25240. const bodyChannel = generate$6('update-body');
  25241. const footerChannel = generate$6('update-footer');
  25242. const bodySendMessageChannel = generate$6('body-send-message');
  25243. const renderBody = (spec, dialogId, contentId, backstage, ariaAttrs) => {
  25244. const renderComponents = incoming => {
  25245. const body = incoming.body;
  25246. switch (body.type) {
  25247. case 'tabpanel': {
  25248. return [renderTabPanel(body, incoming.initialData, backstage)];
  25249. }
  25250. default: {
  25251. return [renderBodyPanel(body, incoming.initialData, backstage)];
  25252. }
  25253. }
  25254. };
  25255. const updateState = (_comp, incoming) => Optional.some({ isTabPanel: () => incoming.body.type === 'tabpanel' });
  25256. const ariaAttributes = { 'aria-live': 'polite' };
  25257. return {
  25258. dom: {
  25259. tag: 'div',
  25260. classes: ['tox-dialog__content-js'],
  25261. attributes: {
  25262. ...contentId.map(x => ({ id: x })).getOr({}),
  25263. ...ariaAttrs ? ariaAttributes : {}
  25264. }
  25265. },
  25266. components: [],
  25267. behaviours: derive$1([
  25268. ComposingConfigs.childAt(0),
  25269. Reflecting.config({
  25270. channel: `${ bodyChannel }-${ dialogId }`,
  25271. updateState,
  25272. renderComponents,
  25273. initialData: spec
  25274. })
  25275. ])
  25276. };
  25277. };
  25278. const renderInlineBody = (spec, dialogId, contentId, backstage, ariaAttrs) => renderBody(spec, dialogId, Optional.some(contentId), backstage, ariaAttrs);
  25279. const renderModalBody = (spec, dialogId, backstage) => {
  25280. const bodySpec = renderBody(spec, dialogId, Optional.none(), backstage, false);
  25281. return ModalDialog.parts.body(bodySpec);
  25282. };
  25283. const renderIframeBody = spec => {
  25284. const bodySpec = {
  25285. dom: {
  25286. tag: 'div',
  25287. classes: ['tox-dialog__content-js']
  25288. },
  25289. components: [{
  25290. dom: {
  25291. tag: 'div',
  25292. classes: ['tox-dialog__body-iframe']
  25293. },
  25294. components: [craft({
  25295. dom: {
  25296. tag: 'iframe',
  25297. attributes: { src: spec.url }
  25298. },
  25299. behaviours: derive$1([
  25300. Tabstopping.config({}),
  25301. Focusing.config({})
  25302. ])
  25303. })]
  25304. }],
  25305. behaviours: derive$1([Keying.config({
  25306. mode: 'acyclic',
  25307. useTabstopAt: not(isPseudoStop)
  25308. })])
  25309. };
  25310. return ModalDialog.parts.body(bodySpec);
  25311. };
  25312. function _typeof(obj) {
  25313. '@babel/helpers - typeof';
  25314. return _typeof = 'function' == typeof Symbol && 'symbol' == typeof Symbol.iterator ? function (obj) {
  25315. return typeof obj;
  25316. } : function (obj) {
  25317. return obj && 'function' == typeof Symbol && obj.constructor === Symbol && obj !== Symbol.prototype ? 'symbol' : typeof obj;
  25318. }, _typeof(obj);
  25319. }
  25320. function _setPrototypeOf(o, p) {
  25321. _setPrototypeOf = Object.setPrototypeOf || function _setPrototypeOf(o, p) {
  25322. o.__proto__ = p;
  25323. return o;
  25324. };
  25325. return _setPrototypeOf(o, p);
  25326. }
  25327. function _isNativeReflectConstruct() {
  25328. if (typeof Reflect === 'undefined' || !Reflect.construct)
  25329. return false;
  25330. if (Reflect.construct.sham)
  25331. return false;
  25332. if (typeof Proxy === 'function')
  25333. return true;
  25334. try {
  25335. Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {
  25336. }));
  25337. return true;
  25338. } catch (e) {
  25339. return false;
  25340. }
  25341. }
  25342. function _construct(Parent, args, Class) {
  25343. if (_isNativeReflectConstruct()) {
  25344. _construct = Reflect.construct;
  25345. } else {
  25346. _construct = function _construct(Parent, args, Class) {
  25347. var a = [null];
  25348. a.push.apply(a, args);
  25349. var Constructor = Function.bind.apply(Parent, a);
  25350. var instance = new Constructor();
  25351. if (Class)
  25352. _setPrototypeOf(instance, Class.prototype);
  25353. return instance;
  25354. };
  25355. }
  25356. return _construct.apply(null, arguments);
  25357. }
  25358. function _toConsumableArray(arr) {
  25359. return _arrayWithoutHoles(arr) || _iterableToArray(arr) || _unsupportedIterableToArray(arr) || _nonIterableSpread();
  25360. }
  25361. function _arrayWithoutHoles(arr) {
  25362. if (Array.isArray(arr))
  25363. return _arrayLikeToArray(arr);
  25364. }
  25365. function _iterableToArray(iter) {
  25366. if (typeof Symbol !== 'undefined' && iter[Symbol.iterator] != null || iter['@@iterator'] != null)
  25367. return Array.from(iter);
  25368. }
  25369. function _unsupportedIterableToArray(o, minLen) {
  25370. if (!o)
  25371. return;
  25372. if (typeof o === 'string')
  25373. return _arrayLikeToArray(o, minLen);
  25374. var n = Object.prototype.toString.call(o).slice(8, -1);
  25375. if (n === 'Object' && o.constructor)
  25376. n = o.constructor.name;
  25377. if (n === 'Map' || n === 'Set')
  25378. return Array.from(o);
  25379. if (n === 'Arguments' || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n))
  25380. return _arrayLikeToArray(o, minLen);
  25381. }
  25382. function _arrayLikeToArray(arr, len) {
  25383. if (len == null || len > arr.length)
  25384. len = arr.length;
  25385. for (var i = 0, arr2 = new Array(len); i < len; i++)
  25386. arr2[i] = arr[i];
  25387. return arr2;
  25388. }
  25389. function _nonIterableSpread() {
  25390. throw new TypeError('Invalid attempt to spread non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.');
  25391. }
  25392. var hasOwnProperty = Object.hasOwnProperty, setPrototypeOf = Object.setPrototypeOf, isFrozen = Object.isFrozen, getPrototypeOf = Object.getPrototypeOf, getOwnPropertyDescriptor = Object.getOwnPropertyDescriptor;
  25393. var freeze = Object.freeze, seal = Object.seal, create = Object.create;
  25394. var _ref = typeof Reflect !== 'undefined' && Reflect, apply = _ref.apply, construct = _ref.construct;
  25395. if (!apply) {
  25396. apply = function apply(fun, thisValue, args) {
  25397. return fun.apply(thisValue, args);
  25398. };
  25399. }
  25400. if (!freeze) {
  25401. freeze = function freeze(x) {
  25402. return x;
  25403. };
  25404. }
  25405. if (!seal) {
  25406. seal = function seal(x) {
  25407. return x;
  25408. };
  25409. }
  25410. if (!construct) {
  25411. construct = function construct(Func, args) {
  25412. return _construct(Func, _toConsumableArray(args));
  25413. };
  25414. }
  25415. var arrayForEach = unapply(Array.prototype.forEach);
  25416. var arrayPop = unapply(Array.prototype.pop);
  25417. var arrayPush = unapply(Array.prototype.push);
  25418. var stringToLowerCase = unapply(String.prototype.toLowerCase);
  25419. var stringMatch = unapply(String.prototype.match);
  25420. var stringReplace = unapply(String.prototype.replace);
  25421. var stringIndexOf = unapply(String.prototype.indexOf);
  25422. var stringTrim = unapply(String.prototype.trim);
  25423. var regExpTest = unapply(RegExp.prototype.test);
  25424. var typeErrorCreate = unconstruct(TypeError);
  25425. function unapply(func) {
  25426. return function (thisArg) {
  25427. for (var _len = arguments.length, args = new Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) {
  25428. args[_key - 1] = arguments[_key];
  25429. }
  25430. return apply(func, thisArg, args);
  25431. };
  25432. }
  25433. function unconstruct(func) {
  25434. return function () {
  25435. for (var _len2 = arguments.length, args = new Array(_len2), _key2 = 0; _key2 < _len2; _key2++) {
  25436. args[_key2] = arguments[_key2];
  25437. }
  25438. return construct(func, args);
  25439. };
  25440. }
  25441. function addToSet(set, array) {
  25442. if (setPrototypeOf) {
  25443. setPrototypeOf(set, null);
  25444. }
  25445. var l = array.length;
  25446. while (l--) {
  25447. var element = array[l];
  25448. if (typeof element === 'string') {
  25449. var lcElement = stringToLowerCase(element);
  25450. if (lcElement !== element) {
  25451. if (!isFrozen(array)) {
  25452. array[l] = lcElement;
  25453. }
  25454. element = lcElement;
  25455. }
  25456. }
  25457. set[element] = true;
  25458. }
  25459. return set;
  25460. }
  25461. function clone(object) {
  25462. var newObject = create(null);
  25463. var property;
  25464. for (property in object) {
  25465. if (apply(hasOwnProperty, object, [property])) {
  25466. newObject[property] = object[property];
  25467. }
  25468. }
  25469. return newObject;
  25470. }
  25471. function lookupGetter(object, prop) {
  25472. while (object !== null) {
  25473. var desc = getOwnPropertyDescriptor(object, prop);
  25474. if (desc) {
  25475. if (desc.get) {
  25476. return unapply(desc.get);
  25477. }
  25478. if (typeof desc.value === 'function') {
  25479. return unapply(desc.value);
  25480. }
  25481. }
  25482. object = getPrototypeOf(object);
  25483. }
  25484. function fallbackValue(element) {
  25485. console.warn('fallback value for', element);
  25486. return null;
  25487. }
  25488. return fallbackValue;
  25489. }
  25490. var html$1 = freeze([
  25491. 'a',
  25492. 'abbr',
  25493. 'acronym',
  25494. 'address',
  25495. 'area',
  25496. 'article',
  25497. 'aside',
  25498. 'audio',
  25499. 'b',
  25500. 'bdi',
  25501. 'bdo',
  25502. 'big',
  25503. 'blink',
  25504. 'blockquote',
  25505. 'body',
  25506. 'br',
  25507. 'button',
  25508. 'canvas',
  25509. 'caption',
  25510. 'center',
  25511. 'cite',
  25512. 'code',
  25513. 'col',
  25514. 'colgroup',
  25515. 'content',
  25516. 'data',
  25517. 'datalist',
  25518. 'dd',
  25519. 'decorator',
  25520. 'del',
  25521. 'details',
  25522. 'dfn',
  25523. 'dialog',
  25524. 'dir',
  25525. 'div',
  25526. 'dl',
  25527. 'dt',
  25528. 'element',
  25529. 'em',
  25530. 'fieldset',
  25531. 'figcaption',
  25532. 'figure',
  25533. 'font',
  25534. 'footer',
  25535. 'form',
  25536. 'h1',
  25537. 'h2',
  25538. 'h3',
  25539. 'h4',
  25540. 'h5',
  25541. 'h6',
  25542. 'head',
  25543. 'header',
  25544. 'hgroup',
  25545. 'hr',
  25546. 'html',
  25547. 'i',
  25548. 'img',
  25549. 'input',
  25550. 'ins',
  25551. 'kbd',
  25552. 'label',
  25553. 'legend',
  25554. 'li',
  25555. 'main',
  25556. 'map',
  25557. 'mark',
  25558. 'marquee',
  25559. 'menu',
  25560. 'menuitem',
  25561. 'meter',
  25562. 'nav',
  25563. 'nobr',
  25564. 'ol',
  25565. 'optgroup',
  25566. 'option',
  25567. 'output',
  25568. 'p',
  25569. 'picture',
  25570. 'pre',
  25571. 'progress',
  25572. 'q',
  25573. 'rp',
  25574. 'rt',
  25575. 'ruby',
  25576. 's',
  25577. 'samp',
  25578. 'section',
  25579. 'select',
  25580. 'shadow',
  25581. 'small',
  25582. 'source',
  25583. 'spacer',
  25584. 'span',
  25585. 'strike',
  25586. 'strong',
  25587. 'style',
  25588. 'sub',
  25589. 'summary',
  25590. 'sup',
  25591. 'table',
  25592. 'tbody',
  25593. 'td',
  25594. 'template',
  25595. 'textarea',
  25596. 'tfoot',
  25597. 'th',
  25598. 'thead',
  25599. 'time',
  25600. 'tr',
  25601. 'track',
  25602. 'tt',
  25603. 'u',
  25604. 'ul',
  25605. 'var',
  25606. 'video',
  25607. 'wbr'
  25608. ]);
  25609. var svg$1 = freeze([
  25610. 'svg',
  25611. 'a',
  25612. 'altglyph',
  25613. 'altglyphdef',
  25614. 'altglyphitem',
  25615. 'animatecolor',
  25616. 'animatemotion',
  25617. 'animatetransform',
  25618. 'circle',
  25619. 'clippath',
  25620. 'defs',
  25621. 'desc',
  25622. 'ellipse',
  25623. 'filter',
  25624. 'font',
  25625. 'g',
  25626. 'glyph',
  25627. 'glyphref',
  25628. 'hkern',
  25629. 'image',
  25630. 'line',
  25631. 'lineargradient',
  25632. 'marker',
  25633. 'mask',
  25634. 'metadata',
  25635. 'mpath',
  25636. 'path',
  25637. 'pattern',
  25638. 'polygon',
  25639. 'polyline',
  25640. 'radialgradient',
  25641. 'rect',
  25642. 'stop',
  25643. 'style',
  25644. 'switch',
  25645. 'symbol',
  25646. 'text',
  25647. 'textpath',
  25648. 'title',
  25649. 'tref',
  25650. 'tspan',
  25651. 'view',
  25652. 'vkern'
  25653. ]);
  25654. var svgFilters = freeze([
  25655. 'feBlend',
  25656. 'feColorMatrix',
  25657. 'feComponentTransfer',
  25658. 'feComposite',
  25659. 'feConvolveMatrix',
  25660. 'feDiffuseLighting',
  25661. 'feDisplacementMap',
  25662. 'feDistantLight',
  25663. 'feFlood',
  25664. 'feFuncA',
  25665. 'feFuncB',
  25666. 'feFuncG',
  25667. 'feFuncR',
  25668. 'feGaussianBlur',
  25669. 'feImage',
  25670. 'feMerge',
  25671. 'feMergeNode',
  25672. 'feMorphology',
  25673. 'feOffset',
  25674. 'fePointLight',
  25675. 'feSpecularLighting',
  25676. 'feSpotLight',
  25677. 'feTile',
  25678. 'feTurbulence'
  25679. ]);
  25680. var svgDisallowed = freeze([
  25681. 'animate',
  25682. 'color-profile',
  25683. 'cursor',
  25684. 'discard',
  25685. 'fedropshadow',
  25686. 'font-face',
  25687. 'font-face-format',
  25688. 'font-face-name',
  25689. 'font-face-src',
  25690. 'font-face-uri',
  25691. 'foreignobject',
  25692. 'hatch',
  25693. 'hatchpath',
  25694. 'mesh',
  25695. 'meshgradient',
  25696. 'meshpatch',
  25697. 'meshrow',
  25698. 'missing-glyph',
  25699. 'script',
  25700. 'set',
  25701. 'solidcolor',
  25702. 'unknown',
  25703. 'use'
  25704. ]);
  25705. var mathMl$1 = freeze([
  25706. 'math',
  25707. 'menclose',
  25708. 'merror',
  25709. 'mfenced',
  25710. 'mfrac',
  25711. 'mglyph',
  25712. 'mi',
  25713. 'mlabeledtr',
  25714. 'mmultiscripts',
  25715. 'mn',
  25716. 'mo',
  25717. 'mover',
  25718. 'mpadded',
  25719. 'mphantom',
  25720. 'mroot',
  25721. 'mrow',
  25722. 'ms',
  25723. 'mspace',
  25724. 'msqrt',
  25725. 'mstyle',
  25726. 'msub',
  25727. 'msup',
  25728. 'msubsup',
  25729. 'mtable',
  25730. 'mtd',
  25731. 'mtext',
  25732. 'mtr',
  25733. 'munder',
  25734. 'munderover'
  25735. ]);
  25736. var mathMlDisallowed = freeze([
  25737. 'maction',
  25738. 'maligngroup',
  25739. 'malignmark',
  25740. 'mlongdiv',
  25741. 'mscarries',
  25742. 'mscarry',
  25743. 'msgroup',
  25744. 'mstack',
  25745. 'msline',
  25746. 'msrow',
  25747. 'semantics',
  25748. 'annotation',
  25749. 'annotation-xml',
  25750. 'mprescripts',
  25751. 'none'
  25752. ]);
  25753. var text = freeze(['#text']);
  25754. var html = freeze([
  25755. 'accept',
  25756. 'action',
  25757. 'align',
  25758. 'alt',
  25759. 'autocapitalize',
  25760. 'autocomplete',
  25761. 'autopictureinpicture',
  25762. 'autoplay',
  25763. 'background',
  25764. 'bgcolor',
  25765. 'border',
  25766. 'capture',
  25767. 'cellpadding',
  25768. 'cellspacing',
  25769. 'checked',
  25770. 'cite',
  25771. 'class',
  25772. 'clear',
  25773. 'color',
  25774. 'cols',
  25775. 'colspan',
  25776. 'controls',
  25777. 'controlslist',
  25778. 'coords',
  25779. 'crossorigin',
  25780. 'datetime',
  25781. 'decoding',
  25782. 'default',
  25783. 'dir',
  25784. 'disabled',
  25785. 'disablepictureinpicture',
  25786. 'disableremoteplayback',
  25787. 'download',
  25788. 'draggable',
  25789. 'enctype',
  25790. 'enterkeyhint',
  25791. 'face',
  25792. 'for',
  25793. 'headers',
  25794. 'height',
  25795. 'hidden',
  25796. 'high',
  25797. 'href',
  25798. 'hreflang',
  25799. 'id',
  25800. 'inputmode',
  25801. 'integrity',
  25802. 'ismap',
  25803. 'kind',
  25804. 'label',
  25805. 'lang',
  25806. 'list',
  25807. 'loading',
  25808. 'loop',
  25809. 'low',
  25810. 'max',
  25811. 'maxlength',
  25812. 'media',
  25813. 'method',
  25814. 'min',
  25815. 'minlength',
  25816. 'multiple',
  25817. 'muted',
  25818. 'name',
  25819. 'nonce',
  25820. 'noshade',
  25821. 'novalidate',
  25822. 'nowrap',
  25823. 'open',
  25824. 'optimum',
  25825. 'pattern',
  25826. 'placeholder',
  25827. 'playsinline',
  25828. 'poster',
  25829. 'preload',
  25830. 'pubdate',
  25831. 'radiogroup',
  25832. 'readonly',
  25833. 'rel',
  25834. 'required',
  25835. 'rev',
  25836. 'reversed',
  25837. 'role',
  25838. 'rows',
  25839. 'rowspan',
  25840. 'spellcheck',
  25841. 'scope',
  25842. 'selected',
  25843. 'shape',
  25844. 'size',
  25845. 'sizes',
  25846. 'span',
  25847. 'srclang',
  25848. 'start',
  25849. 'src',
  25850. 'srcset',
  25851. 'step',
  25852. 'style',
  25853. 'summary',
  25854. 'tabindex',
  25855. 'title',
  25856. 'translate',
  25857. 'type',
  25858. 'usemap',
  25859. 'valign',
  25860. 'value',
  25861. 'width',
  25862. 'xmlns',
  25863. 'slot'
  25864. ]);
  25865. var svg = freeze([
  25866. 'accent-height',
  25867. 'accumulate',
  25868. 'additive',
  25869. 'alignment-baseline',
  25870. 'ascent',
  25871. 'attributename',
  25872. 'attributetype',
  25873. 'azimuth',
  25874. 'basefrequency',
  25875. 'baseline-shift',
  25876. 'begin',
  25877. 'bias',
  25878. 'by',
  25879. 'class',
  25880. 'clip',
  25881. 'clippathunits',
  25882. 'clip-path',
  25883. 'clip-rule',
  25884. 'color',
  25885. 'color-interpolation',
  25886. 'color-interpolation-filters',
  25887. 'color-profile',
  25888. 'color-rendering',
  25889. 'cx',
  25890. 'cy',
  25891. 'd',
  25892. 'dx',
  25893. 'dy',
  25894. 'diffuseconstant',
  25895. 'direction',
  25896. 'display',
  25897. 'divisor',
  25898. 'dur',
  25899. 'edgemode',
  25900. 'elevation',
  25901. 'end',
  25902. 'fill',
  25903. 'fill-opacity',
  25904. 'fill-rule',
  25905. 'filter',
  25906. 'filterunits',
  25907. 'flood-color',
  25908. 'flood-opacity',
  25909. 'font-family',
  25910. 'font-size',
  25911. 'font-size-adjust',
  25912. 'font-stretch',
  25913. 'font-style',
  25914. 'font-variant',
  25915. 'font-weight',
  25916. 'fx',
  25917. 'fy',
  25918. 'g1',
  25919. 'g2',
  25920. 'glyph-name',
  25921. 'glyphref',
  25922. 'gradientunits',
  25923. 'gradienttransform',
  25924. 'height',
  25925. 'href',
  25926. 'id',
  25927. 'image-rendering',
  25928. 'in',
  25929. 'in2',
  25930. 'k',
  25931. 'k1',
  25932. 'k2',
  25933. 'k3',
  25934. 'k4',
  25935. 'kerning',
  25936. 'keypoints',
  25937. 'keysplines',
  25938. 'keytimes',
  25939. 'lang',
  25940. 'lengthadjust',
  25941. 'letter-spacing',
  25942. 'kernelmatrix',
  25943. 'kernelunitlength',
  25944. 'lighting-color',
  25945. 'local',
  25946. 'marker-end',
  25947. 'marker-mid',
  25948. 'marker-start',
  25949. 'markerheight',
  25950. 'markerunits',
  25951. 'markerwidth',
  25952. 'maskcontentunits',
  25953. 'maskunits',
  25954. 'max',
  25955. 'mask',
  25956. 'media',
  25957. 'method',
  25958. 'mode',
  25959. 'min',
  25960. 'name',
  25961. 'numoctaves',
  25962. 'offset',
  25963. 'operator',
  25964. 'opacity',
  25965. 'order',
  25966. 'orient',
  25967. 'orientation',
  25968. 'origin',
  25969. 'overflow',
  25970. 'paint-order',
  25971. 'path',
  25972. 'pathlength',
  25973. 'patterncontentunits',
  25974. 'patterntransform',
  25975. 'patternunits',
  25976. 'points',
  25977. 'preservealpha',
  25978. 'preserveaspectratio',
  25979. 'primitiveunits',
  25980. 'r',
  25981. 'rx',
  25982. 'ry',
  25983. 'radius',
  25984. 'refx',
  25985. 'refy',
  25986. 'repeatcount',
  25987. 'repeatdur',
  25988. 'restart',
  25989. 'result',
  25990. 'rotate',
  25991. 'scale',
  25992. 'seed',
  25993. 'shape-rendering',
  25994. 'specularconstant',
  25995. 'specularexponent',
  25996. 'spreadmethod',
  25997. 'startoffset',
  25998. 'stddeviation',
  25999. 'stitchtiles',
  26000. 'stop-color',
  26001. 'stop-opacity',
  26002. 'stroke-dasharray',
  26003. 'stroke-dashoffset',
  26004. 'stroke-linecap',
  26005. 'stroke-linejoin',
  26006. 'stroke-miterlimit',
  26007. 'stroke-opacity',
  26008. 'stroke',
  26009. 'stroke-width',
  26010. 'style',
  26011. 'surfacescale',
  26012. 'systemlanguage',
  26013. 'tabindex',
  26014. 'targetx',
  26015. 'targety',
  26016. 'transform',
  26017. 'transform-origin',
  26018. 'text-anchor',
  26019. 'text-decoration',
  26020. 'text-rendering',
  26021. 'textlength',
  26022. 'type',
  26023. 'u1',
  26024. 'u2',
  26025. 'unicode',
  26026. 'values',
  26027. 'viewbox',
  26028. 'visibility',
  26029. 'version',
  26030. 'vert-adv-y',
  26031. 'vert-origin-x',
  26032. 'vert-origin-y',
  26033. 'width',
  26034. 'word-spacing',
  26035. 'wrap',
  26036. 'writing-mode',
  26037. 'xchannelselector',
  26038. 'ychannelselector',
  26039. 'x',
  26040. 'x1',
  26041. 'x2',
  26042. 'xmlns',
  26043. 'y',
  26044. 'y1',
  26045. 'y2',
  26046. 'z',
  26047. 'zoomandpan'
  26048. ]);
  26049. var mathMl = freeze([
  26050. 'accent',
  26051. 'accentunder',
  26052. 'align',
  26053. 'bevelled',
  26054. 'close',
  26055. 'columnsalign',
  26056. 'columnlines',
  26057. 'columnspan',
  26058. 'denomalign',
  26059. 'depth',
  26060. 'dir',
  26061. 'display',
  26062. 'displaystyle',
  26063. 'encoding',
  26064. 'fence',
  26065. 'frame',
  26066. 'height',
  26067. 'href',
  26068. 'id',
  26069. 'largeop',
  26070. 'length',
  26071. 'linethickness',
  26072. 'lspace',
  26073. 'lquote',
  26074. 'mathbackground',
  26075. 'mathcolor',
  26076. 'mathsize',
  26077. 'mathvariant',
  26078. 'maxsize',
  26079. 'minsize',
  26080. 'movablelimits',
  26081. 'notation',
  26082. 'numalign',
  26083. 'open',
  26084. 'rowalign',
  26085. 'rowlines',
  26086. 'rowspacing',
  26087. 'rowspan',
  26088. 'rspace',
  26089. 'rquote',
  26090. 'scriptlevel',
  26091. 'scriptminsize',
  26092. 'scriptsizemultiplier',
  26093. 'selection',
  26094. 'separator',
  26095. 'separators',
  26096. 'stretchy',
  26097. 'subscriptshift',
  26098. 'supscriptshift',
  26099. 'symmetric',
  26100. 'voffset',
  26101. 'width',
  26102. 'xmlns'
  26103. ]);
  26104. var xml = freeze([
  26105. 'xlink:href',
  26106. 'xml:id',
  26107. 'xlink:title',
  26108. 'xml:space',
  26109. 'xmlns:xlink'
  26110. ]);
  26111. var MUSTACHE_EXPR = seal(/\{\{[\w\W]*|[\w\W]*\}\}/gm);
  26112. var ERB_EXPR = seal(/<%[\w\W]*|[\w\W]*%>/gm);
  26113. var DATA_ATTR = seal(/^data-[\-\w.\u00B7-\uFFFF]/);
  26114. var ARIA_ATTR = seal(/^aria-[\-\w]+$/);
  26115. var IS_ALLOWED_URI = seal(/^(?:(?:(?:f|ht)tps?|mailto|tel|callto|cid|xmpp):|[^a-z]|[a-z+.\-]+(?:[^a-z+.\-:]|$))/i);
  26116. var IS_SCRIPT_OR_DATA = seal(/^(?:\w+script|data):/i);
  26117. var ATTR_WHITESPACE = seal(/[\u0000-\u0020\u00A0\u1680\u180E\u2000-\u2029\u205F\u3000]/g);
  26118. var DOCTYPE_NAME = seal(/^html$/i);
  26119. var getGlobal = function getGlobal() {
  26120. return typeof window === 'undefined' ? null : window;
  26121. };
  26122. var _createTrustedTypesPolicy = function _createTrustedTypesPolicy(trustedTypes, document) {
  26123. if (_typeof(trustedTypes) !== 'object' || typeof trustedTypes.createPolicy !== 'function') {
  26124. return null;
  26125. }
  26126. var suffix = null;
  26127. var ATTR_NAME = 'data-tt-policy-suffix';
  26128. if (document.currentScript && document.currentScript.hasAttribute(ATTR_NAME)) {
  26129. suffix = document.currentScript.getAttribute(ATTR_NAME);
  26130. }
  26131. var policyName = 'dompurify' + (suffix ? '#' + suffix : '');
  26132. try {
  26133. return trustedTypes.createPolicy(policyName, {
  26134. createHTML: function createHTML(html) {
  26135. return html;
  26136. }
  26137. });
  26138. } catch (_) {
  26139. console.warn('TrustedTypes policy ' + policyName + ' could not be created.');
  26140. return null;
  26141. }
  26142. };
  26143. function createDOMPurify() {
  26144. var window = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : getGlobal();
  26145. var DOMPurify = function DOMPurify(root) {
  26146. return createDOMPurify(root);
  26147. };
  26148. DOMPurify.version = '2.3.8';
  26149. DOMPurify.removed = [];
  26150. if (!window || !window.document || window.document.nodeType !== 9) {
  26151. DOMPurify.isSupported = false;
  26152. return DOMPurify;
  26153. }
  26154. var originalDocument = window.document;
  26155. var document = window.document;
  26156. var DocumentFragment = window.DocumentFragment, HTMLTemplateElement = window.HTMLTemplateElement, Node = window.Node, Element = window.Element, NodeFilter = window.NodeFilter, _window$NamedNodeMap = window.NamedNodeMap, NamedNodeMap = _window$NamedNodeMap === void 0 ? window.NamedNodeMap || window.MozNamedAttrMap : _window$NamedNodeMap, HTMLFormElement = window.HTMLFormElement, DOMParser = window.DOMParser, trustedTypes = window.trustedTypes;
  26157. var ElementPrototype = Element.prototype;
  26158. var cloneNode = lookupGetter(ElementPrototype, 'cloneNode');
  26159. var getNextSibling = lookupGetter(ElementPrototype, 'nextSibling');
  26160. var getChildNodes = lookupGetter(ElementPrototype, 'childNodes');
  26161. var getParentNode = lookupGetter(ElementPrototype, 'parentNode');
  26162. if (typeof HTMLTemplateElement === 'function') {
  26163. var template = document.createElement('template');
  26164. if (template.content && template.content.ownerDocument) {
  26165. document = template.content.ownerDocument;
  26166. }
  26167. }
  26168. var trustedTypesPolicy = _createTrustedTypesPolicy(trustedTypes, originalDocument);
  26169. var emptyHTML = trustedTypesPolicy ? trustedTypesPolicy.createHTML('') : '';
  26170. var _document = document, implementation = _document.implementation, createNodeIterator = _document.createNodeIterator, createDocumentFragment = _document.createDocumentFragment, getElementsByTagName = _document.getElementsByTagName;
  26171. var importNode = originalDocument.importNode;
  26172. var documentMode = {};
  26173. try {
  26174. documentMode = clone(document).documentMode ? document.documentMode : {};
  26175. } catch (_) {
  26176. }
  26177. var hooks = {};
  26178. DOMPurify.isSupported = typeof getParentNode === 'function' && implementation && typeof implementation.createHTMLDocument !== 'undefined' && documentMode !== 9;
  26179. var MUSTACHE_EXPR$1 = MUSTACHE_EXPR, ERB_EXPR$1 = ERB_EXPR, DATA_ATTR$1 = DATA_ATTR, ARIA_ATTR$1 = ARIA_ATTR, IS_SCRIPT_OR_DATA$1 = IS_SCRIPT_OR_DATA, ATTR_WHITESPACE$1 = ATTR_WHITESPACE;
  26180. var IS_ALLOWED_URI$1 = IS_ALLOWED_URI;
  26181. var ALLOWED_TAGS = null;
  26182. var DEFAULT_ALLOWED_TAGS = addToSet({}, [].concat(_toConsumableArray(html$1), _toConsumableArray(svg$1), _toConsumableArray(svgFilters), _toConsumableArray(mathMl$1), _toConsumableArray(text)));
  26183. var ALLOWED_ATTR = null;
  26184. var DEFAULT_ALLOWED_ATTR = addToSet({}, [].concat(_toConsumableArray(html), _toConsumableArray(svg), _toConsumableArray(mathMl), _toConsumableArray(xml)));
  26185. var CUSTOM_ELEMENT_HANDLING = Object.seal(Object.create(null, {
  26186. tagNameCheck: {
  26187. writable: true,
  26188. configurable: false,
  26189. enumerable: true,
  26190. value: null
  26191. },
  26192. attributeNameCheck: {
  26193. writable: true,
  26194. configurable: false,
  26195. enumerable: true,
  26196. value: null
  26197. },
  26198. allowCustomizedBuiltInElements: {
  26199. writable: true,
  26200. configurable: false,
  26201. enumerable: true,
  26202. value: false
  26203. }
  26204. }));
  26205. var FORBID_TAGS = null;
  26206. var FORBID_ATTR = null;
  26207. var ALLOW_ARIA_ATTR = true;
  26208. var ALLOW_DATA_ATTR = true;
  26209. var ALLOW_UNKNOWN_PROTOCOLS = false;
  26210. var SAFE_FOR_TEMPLATES = false;
  26211. var WHOLE_DOCUMENT = false;
  26212. var SET_CONFIG = false;
  26213. var FORCE_BODY = false;
  26214. var RETURN_DOM = false;
  26215. var RETURN_DOM_FRAGMENT = false;
  26216. var RETURN_TRUSTED_TYPE = false;
  26217. var SANITIZE_DOM = true;
  26218. var KEEP_CONTENT = true;
  26219. var IN_PLACE = false;
  26220. var USE_PROFILES = {};
  26221. var FORBID_CONTENTS = null;
  26222. var DEFAULT_FORBID_CONTENTS = addToSet({}, [
  26223. 'annotation-xml',
  26224. 'audio',
  26225. 'colgroup',
  26226. 'desc',
  26227. 'foreignobject',
  26228. 'head',
  26229. 'iframe',
  26230. 'math',
  26231. 'mi',
  26232. 'mn',
  26233. 'mo',
  26234. 'ms',
  26235. 'mtext',
  26236. 'noembed',
  26237. 'noframes',
  26238. 'noscript',
  26239. 'plaintext',
  26240. 'script',
  26241. 'style',
  26242. 'svg',
  26243. 'template',
  26244. 'thead',
  26245. 'title',
  26246. 'video',
  26247. 'xmp'
  26248. ]);
  26249. var DATA_URI_TAGS = null;
  26250. var DEFAULT_DATA_URI_TAGS = addToSet({}, [
  26251. 'audio',
  26252. 'video',
  26253. 'img',
  26254. 'source',
  26255. 'image',
  26256. 'track'
  26257. ]);
  26258. var URI_SAFE_ATTRIBUTES = null;
  26259. var DEFAULT_URI_SAFE_ATTRIBUTES = addToSet({}, [
  26260. 'alt',
  26261. 'class',
  26262. 'for',
  26263. 'id',
  26264. 'label',
  26265. 'name',
  26266. 'pattern',
  26267. 'placeholder',
  26268. 'role',
  26269. 'summary',
  26270. 'title',
  26271. 'value',
  26272. 'style',
  26273. 'xmlns'
  26274. ]);
  26275. var MATHML_NAMESPACE = 'http://www.w3.org/1998/Math/MathML';
  26276. var SVG_NAMESPACE = 'http://www.w3.org/2000/svg';
  26277. var HTML_NAMESPACE = 'http://www.w3.org/1999/xhtml';
  26278. var NAMESPACE = HTML_NAMESPACE;
  26279. var IS_EMPTY_INPUT = false;
  26280. var PARSER_MEDIA_TYPE;
  26281. var SUPPORTED_PARSER_MEDIA_TYPES = [
  26282. 'application/xhtml+xml',
  26283. 'text/html'
  26284. ];
  26285. var DEFAULT_PARSER_MEDIA_TYPE = 'text/html';
  26286. var transformCaseFunc;
  26287. var CONFIG = null;
  26288. var formElement = document.createElement('form');
  26289. var isRegexOrFunction = function isRegexOrFunction(testValue) {
  26290. return testValue instanceof RegExp || testValue instanceof Function;
  26291. };
  26292. var _parseConfig = function _parseConfig(cfg) {
  26293. if (CONFIG && CONFIG === cfg) {
  26294. return;
  26295. }
  26296. if (!cfg || _typeof(cfg) !== 'object') {
  26297. cfg = {};
  26298. }
  26299. cfg = clone(cfg);
  26300. ALLOWED_TAGS = 'ALLOWED_TAGS' in cfg ? addToSet({}, cfg.ALLOWED_TAGS) : DEFAULT_ALLOWED_TAGS;
  26301. ALLOWED_ATTR = 'ALLOWED_ATTR' in cfg ? addToSet({}, cfg.ALLOWED_ATTR) : DEFAULT_ALLOWED_ATTR;
  26302. URI_SAFE_ATTRIBUTES = 'ADD_URI_SAFE_ATTR' in cfg ? addToSet(clone(DEFAULT_URI_SAFE_ATTRIBUTES), cfg.ADD_URI_SAFE_ATTR) : DEFAULT_URI_SAFE_ATTRIBUTES;
  26303. DATA_URI_TAGS = 'ADD_DATA_URI_TAGS' in cfg ? addToSet(clone(DEFAULT_DATA_URI_TAGS), cfg.ADD_DATA_URI_TAGS) : DEFAULT_DATA_URI_TAGS;
  26304. FORBID_CONTENTS = 'FORBID_CONTENTS' in cfg ? addToSet({}, cfg.FORBID_CONTENTS) : DEFAULT_FORBID_CONTENTS;
  26305. FORBID_TAGS = 'FORBID_TAGS' in cfg ? addToSet({}, cfg.FORBID_TAGS) : {};
  26306. FORBID_ATTR = 'FORBID_ATTR' in cfg ? addToSet({}, cfg.FORBID_ATTR) : {};
  26307. USE_PROFILES = 'USE_PROFILES' in cfg ? cfg.USE_PROFILES : false;
  26308. ALLOW_ARIA_ATTR = cfg.ALLOW_ARIA_ATTR !== false;
  26309. ALLOW_DATA_ATTR = cfg.ALLOW_DATA_ATTR !== false;
  26310. ALLOW_UNKNOWN_PROTOCOLS = cfg.ALLOW_UNKNOWN_PROTOCOLS || false;
  26311. SAFE_FOR_TEMPLATES = cfg.SAFE_FOR_TEMPLATES || false;
  26312. WHOLE_DOCUMENT = cfg.WHOLE_DOCUMENT || false;
  26313. RETURN_DOM = cfg.RETURN_DOM || false;
  26314. RETURN_DOM_FRAGMENT = cfg.RETURN_DOM_FRAGMENT || false;
  26315. RETURN_TRUSTED_TYPE = cfg.RETURN_TRUSTED_TYPE || false;
  26316. FORCE_BODY = cfg.FORCE_BODY || false;
  26317. SANITIZE_DOM = cfg.SANITIZE_DOM !== false;
  26318. KEEP_CONTENT = cfg.KEEP_CONTENT !== false;
  26319. IN_PLACE = cfg.IN_PLACE || false;
  26320. IS_ALLOWED_URI$1 = cfg.ALLOWED_URI_REGEXP || IS_ALLOWED_URI$1;
  26321. NAMESPACE = cfg.NAMESPACE || HTML_NAMESPACE;
  26322. if (cfg.CUSTOM_ELEMENT_HANDLING && isRegexOrFunction(cfg.CUSTOM_ELEMENT_HANDLING.tagNameCheck)) {
  26323. CUSTOM_ELEMENT_HANDLING.tagNameCheck = cfg.CUSTOM_ELEMENT_HANDLING.tagNameCheck;
  26324. }
  26325. if (cfg.CUSTOM_ELEMENT_HANDLING && isRegexOrFunction(cfg.CUSTOM_ELEMENT_HANDLING.attributeNameCheck)) {
  26326. CUSTOM_ELEMENT_HANDLING.attributeNameCheck = cfg.CUSTOM_ELEMENT_HANDLING.attributeNameCheck;
  26327. }
  26328. if (cfg.CUSTOM_ELEMENT_HANDLING && typeof cfg.CUSTOM_ELEMENT_HANDLING.allowCustomizedBuiltInElements === 'boolean') {
  26329. CUSTOM_ELEMENT_HANDLING.allowCustomizedBuiltInElements = cfg.CUSTOM_ELEMENT_HANDLING.allowCustomizedBuiltInElements;
  26330. }
  26331. PARSER_MEDIA_TYPE = SUPPORTED_PARSER_MEDIA_TYPES.indexOf(cfg.PARSER_MEDIA_TYPE) === -1 ? PARSER_MEDIA_TYPE = DEFAULT_PARSER_MEDIA_TYPE : PARSER_MEDIA_TYPE = cfg.PARSER_MEDIA_TYPE;
  26332. transformCaseFunc = PARSER_MEDIA_TYPE === 'application/xhtml+xml' ? function (x) {
  26333. return x;
  26334. } : stringToLowerCase;
  26335. if (SAFE_FOR_TEMPLATES) {
  26336. ALLOW_DATA_ATTR = false;
  26337. }
  26338. if (RETURN_DOM_FRAGMENT) {
  26339. RETURN_DOM = true;
  26340. }
  26341. if (USE_PROFILES) {
  26342. ALLOWED_TAGS = addToSet({}, _toConsumableArray(text));
  26343. ALLOWED_ATTR = [];
  26344. if (USE_PROFILES.html === true) {
  26345. addToSet(ALLOWED_TAGS, html$1);
  26346. addToSet(ALLOWED_ATTR, html);
  26347. }
  26348. if (USE_PROFILES.svg === true) {
  26349. addToSet(ALLOWED_TAGS, svg$1);
  26350. addToSet(ALLOWED_ATTR, svg);
  26351. addToSet(ALLOWED_ATTR, xml);
  26352. }
  26353. if (USE_PROFILES.svgFilters === true) {
  26354. addToSet(ALLOWED_TAGS, svgFilters);
  26355. addToSet(ALLOWED_ATTR, svg);
  26356. addToSet(ALLOWED_ATTR, xml);
  26357. }
  26358. if (USE_PROFILES.mathMl === true) {
  26359. addToSet(ALLOWED_TAGS, mathMl$1);
  26360. addToSet(ALLOWED_ATTR, mathMl);
  26361. addToSet(ALLOWED_ATTR, xml);
  26362. }
  26363. }
  26364. if (cfg.ADD_TAGS) {
  26365. if (ALLOWED_TAGS === DEFAULT_ALLOWED_TAGS) {
  26366. ALLOWED_TAGS = clone(ALLOWED_TAGS);
  26367. }
  26368. addToSet(ALLOWED_TAGS, cfg.ADD_TAGS);
  26369. }
  26370. if (cfg.ADD_ATTR) {
  26371. if (ALLOWED_ATTR === DEFAULT_ALLOWED_ATTR) {
  26372. ALLOWED_ATTR = clone(ALLOWED_ATTR);
  26373. }
  26374. addToSet(ALLOWED_ATTR, cfg.ADD_ATTR);
  26375. }
  26376. if (cfg.ADD_URI_SAFE_ATTR) {
  26377. addToSet(URI_SAFE_ATTRIBUTES, cfg.ADD_URI_SAFE_ATTR);
  26378. }
  26379. if (cfg.FORBID_CONTENTS) {
  26380. if (FORBID_CONTENTS === DEFAULT_FORBID_CONTENTS) {
  26381. FORBID_CONTENTS = clone(FORBID_CONTENTS);
  26382. }
  26383. addToSet(FORBID_CONTENTS, cfg.FORBID_CONTENTS);
  26384. }
  26385. if (KEEP_CONTENT) {
  26386. ALLOWED_TAGS['#text'] = true;
  26387. }
  26388. if (WHOLE_DOCUMENT) {
  26389. addToSet(ALLOWED_TAGS, [
  26390. 'html',
  26391. 'head',
  26392. 'body'
  26393. ]);
  26394. }
  26395. if (ALLOWED_TAGS.table) {
  26396. addToSet(ALLOWED_TAGS, ['tbody']);
  26397. delete FORBID_TAGS.tbody;
  26398. }
  26399. if (freeze) {
  26400. freeze(cfg);
  26401. }
  26402. CONFIG = cfg;
  26403. };
  26404. var MATHML_TEXT_INTEGRATION_POINTS = addToSet({}, [
  26405. 'mi',
  26406. 'mo',
  26407. 'mn',
  26408. 'ms',
  26409. 'mtext'
  26410. ]);
  26411. var HTML_INTEGRATION_POINTS = addToSet({}, [
  26412. 'foreignobject',
  26413. 'desc',
  26414. 'title',
  26415. 'annotation-xml'
  26416. ]);
  26417. var COMMON_SVG_AND_HTML_ELEMENTS = addToSet({}, [
  26418. 'title',
  26419. 'style',
  26420. 'font',
  26421. 'a',
  26422. 'script'
  26423. ]);
  26424. var ALL_SVG_TAGS = addToSet({}, svg$1);
  26425. addToSet(ALL_SVG_TAGS, svgFilters);
  26426. addToSet(ALL_SVG_TAGS, svgDisallowed);
  26427. var ALL_MATHML_TAGS = addToSet({}, mathMl$1);
  26428. addToSet(ALL_MATHML_TAGS, mathMlDisallowed);
  26429. var _checkValidNamespace = function _checkValidNamespace(element) {
  26430. var parent = getParentNode(element);
  26431. if (!parent || !parent.tagName) {
  26432. parent = {
  26433. namespaceURI: HTML_NAMESPACE,
  26434. tagName: 'template'
  26435. };
  26436. }
  26437. var tagName = stringToLowerCase(element.tagName);
  26438. var parentTagName = stringToLowerCase(parent.tagName);
  26439. if (element.namespaceURI === SVG_NAMESPACE) {
  26440. if (parent.namespaceURI === HTML_NAMESPACE) {
  26441. return tagName === 'svg';
  26442. }
  26443. if (parent.namespaceURI === MATHML_NAMESPACE) {
  26444. return tagName === 'svg' && (parentTagName === 'annotation-xml' || MATHML_TEXT_INTEGRATION_POINTS[parentTagName]);
  26445. }
  26446. return Boolean(ALL_SVG_TAGS[tagName]);
  26447. }
  26448. if (element.namespaceURI === MATHML_NAMESPACE) {
  26449. if (parent.namespaceURI === HTML_NAMESPACE) {
  26450. return tagName === 'math';
  26451. }
  26452. if (parent.namespaceURI === SVG_NAMESPACE) {
  26453. return tagName === 'math' && HTML_INTEGRATION_POINTS[parentTagName];
  26454. }
  26455. return Boolean(ALL_MATHML_TAGS[tagName]);
  26456. }
  26457. if (element.namespaceURI === HTML_NAMESPACE) {
  26458. if (parent.namespaceURI === SVG_NAMESPACE && !HTML_INTEGRATION_POINTS[parentTagName]) {
  26459. return false;
  26460. }
  26461. if (parent.namespaceURI === MATHML_NAMESPACE && !MATHML_TEXT_INTEGRATION_POINTS[parentTagName]) {
  26462. return false;
  26463. }
  26464. return !ALL_MATHML_TAGS[tagName] && (COMMON_SVG_AND_HTML_ELEMENTS[tagName] || !ALL_SVG_TAGS[tagName]);
  26465. }
  26466. return false;
  26467. };
  26468. var _forceRemove = function _forceRemove(node) {
  26469. arrayPush(DOMPurify.removed, { element: node });
  26470. try {
  26471. node.parentNode.removeChild(node);
  26472. } catch (_) {
  26473. try {
  26474. node.outerHTML = emptyHTML;
  26475. } catch (_) {
  26476. node.remove();
  26477. }
  26478. }
  26479. };
  26480. var _removeAttribute = function _removeAttribute(name, node) {
  26481. try {
  26482. arrayPush(DOMPurify.removed, {
  26483. attribute: node.getAttributeNode(name),
  26484. from: node
  26485. });
  26486. } catch (_) {
  26487. arrayPush(DOMPurify.removed, {
  26488. attribute: null,
  26489. from: node
  26490. });
  26491. }
  26492. node.removeAttribute(name);
  26493. if (name === 'is' && !ALLOWED_ATTR[name]) {
  26494. if (RETURN_DOM || RETURN_DOM_FRAGMENT) {
  26495. try {
  26496. _forceRemove(node);
  26497. } catch (_) {
  26498. }
  26499. } else {
  26500. try {
  26501. node.setAttribute(name, '');
  26502. } catch (_) {
  26503. }
  26504. }
  26505. }
  26506. };
  26507. var _initDocument = function _initDocument(dirty) {
  26508. var doc;
  26509. var leadingWhitespace;
  26510. if (FORCE_BODY) {
  26511. dirty = '<remove></remove>' + dirty;
  26512. } else {
  26513. var matches = stringMatch(dirty, /^[\r\n\t ]+/);
  26514. leadingWhitespace = matches && matches[0];
  26515. }
  26516. if (PARSER_MEDIA_TYPE === 'application/xhtml+xml') {
  26517. dirty = '<html xmlns="http://www.w3.org/1999/xhtml"><head></head><body>' + dirty + '</body></html>';
  26518. }
  26519. var dirtyPayload = trustedTypesPolicy ? trustedTypesPolicy.createHTML(dirty) : dirty;
  26520. if (NAMESPACE === HTML_NAMESPACE) {
  26521. try {
  26522. doc = new DOMParser().parseFromString(dirtyPayload, PARSER_MEDIA_TYPE);
  26523. } catch (_) {
  26524. }
  26525. }
  26526. if (!doc || !doc.documentElement) {
  26527. doc = implementation.createDocument(NAMESPACE, 'template', null);
  26528. try {
  26529. doc.documentElement.innerHTML = IS_EMPTY_INPUT ? '' : dirtyPayload;
  26530. } catch (_) {
  26531. }
  26532. }
  26533. var body = doc.body || doc.documentElement;
  26534. if (dirty && leadingWhitespace) {
  26535. body.insertBefore(document.createTextNode(leadingWhitespace), body.childNodes[0] || null);
  26536. }
  26537. if (NAMESPACE === HTML_NAMESPACE) {
  26538. return getElementsByTagName.call(doc, WHOLE_DOCUMENT ? 'html' : 'body')[0];
  26539. }
  26540. return WHOLE_DOCUMENT ? doc.documentElement : body;
  26541. };
  26542. var _createIterator = function _createIterator(root) {
  26543. return createNodeIterator.call(root.ownerDocument || root, root, NodeFilter.SHOW_ELEMENT | NodeFilter.SHOW_COMMENT | NodeFilter.SHOW_TEXT, null, false);
  26544. };
  26545. var _isClobbered = function _isClobbered(elm) {
  26546. return elm instanceof HTMLFormElement && (typeof elm.nodeName !== 'string' || typeof elm.textContent !== 'string' || typeof elm.removeChild !== 'function' || !(elm.attributes instanceof NamedNodeMap) || typeof elm.removeAttribute !== 'function' || typeof elm.setAttribute !== 'function' || typeof elm.namespaceURI !== 'string' || typeof elm.insertBefore !== 'function');
  26547. };
  26548. var _isNode = function _isNode(object) {
  26549. return _typeof(Node) === 'object' ? object instanceof Node : object && _typeof(object) === 'object' && typeof object.nodeType === 'number' && typeof object.nodeName === 'string';
  26550. };
  26551. var _executeHook = function _executeHook(entryPoint, currentNode, data) {
  26552. if (!hooks[entryPoint]) {
  26553. return;
  26554. }
  26555. arrayForEach(hooks[entryPoint], function (hook) {
  26556. hook.call(DOMPurify, currentNode, data, CONFIG);
  26557. });
  26558. };
  26559. var _sanitizeElements = function _sanitizeElements(currentNode) {
  26560. var content;
  26561. _executeHook('beforeSanitizeElements', currentNode, null);
  26562. if (_isClobbered(currentNode)) {
  26563. _forceRemove(currentNode);
  26564. return true;
  26565. }
  26566. if (regExpTest(/[\u0080-\uFFFF]/, currentNode.nodeName)) {
  26567. _forceRemove(currentNode);
  26568. return true;
  26569. }
  26570. var tagName = transformCaseFunc(currentNode.nodeName);
  26571. _executeHook('uponSanitizeElement', currentNode, {
  26572. tagName: tagName,
  26573. allowedTags: ALLOWED_TAGS
  26574. });
  26575. if (currentNode.hasChildNodes() && !_isNode(currentNode.firstElementChild) && (!_isNode(currentNode.content) || !_isNode(currentNode.content.firstElementChild)) && regExpTest(/<[/\w]/g, currentNode.innerHTML) && regExpTest(/<[/\w]/g, currentNode.textContent)) {
  26576. _forceRemove(currentNode);
  26577. return true;
  26578. }
  26579. if (tagName === 'select' && regExpTest(/<template/i, currentNode.innerHTML)) {
  26580. _forceRemove(currentNode);
  26581. return true;
  26582. }
  26583. if (!ALLOWED_TAGS[tagName] || FORBID_TAGS[tagName]) {
  26584. if (!FORBID_TAGS[tagName] && _basicCustomElementTest(tagName)) {
  26585. if (CUSTOM_ELEMENT_HANDLING.tagNameCheck instanceof RegExp && regExpTest(CUSTOM_ELEMENT_HANDLING.tagNameCheck, tagName))
  26586. return false;
  26587. if (CUSTOM_ELEMENT_HANDLING.tagNameCheck instanceof Function && CUSTOM_ELEMENT_HANDLING.tagNameCheck(tagName))
  26588. return false;
  26589. }
  26590. if (KEEP_CONTENT && !FORBID_CONTENTS[tagName]) {
  26591. var parentNode = getParentNode(currentNode) || currentNode.parentNode;
  26592. var childNodes = getChildNodes(currentNode) || currentNode.childNodes;
  26593. if (childNodes && parentNode) {
  26594. var childCount = childNodes.length;
  26595. for (var i = childCount - 1; i >= 0; --i) {
  26596. parentNode.insertBefore(cloneNode(childNodes[i], true), getNextSibling(currentNode));
  26597. }
  26598. }
  26599. }
  26600. _forceRemove(currentNode);
  26601. return true;
  26602. }
  26603. if (currentNode instanceof Element && !_checkValidNamespace(currentNode)) {
  26604. _forceRemove(currentNode);
  26605. return true;
  26606. }
  26607. if ((tagName === 'noscript' || tagName === 'noembed') && regExpTest(/<\/no(script|embed)/i, currentNode.innerHTML)) {
  26608. _forceRemove(currentNode);
  26609. return true;
  26610. }
  26611. if (SAFE_FOR_TEMPLATES && currentNode.nodeType === 3) {
  26612. content = currentNode.textContent;
  26613. content = stringReplace(content, MUSTACHE_EXPR$1, ' ');
  26614. content = stringReplace(content, ERB_EXPR$1, ' ');
  26615. if (currentNode.textContent !== content) {
  26616. arrayPush(DOMPurify.removed, { element: currentNode.cloneNode() });
  26617. currentNode.textContent = content;
  26618. }
  26619. }
  26620. _executeHook('afterSanitizeElements', currentNode, null);
  26621. return false;
  26622. };
  26623. var _isValidAttribute = function _isValidAttribute(lcTag, lcName, value) {
  26624. if (SANITIZE_DOM && (lcName === 'id' || lcName === 'name') && (value in document || value in formElement)) {
  26625. return false;
  26626. }
  26627. if (ALLOW_DATA_ATTR && !FORBID_ATTR[lcName] && regExpTest(DATA_ATTR$1, lcName));
  26628. else if (ALLOW_ARIA_ATTR && regExpTest(ARIA_ATTR$1, lcName));
  26629. else if (!ALLOWED_ATTR[lcName] || FORBID_ATTR[lcName]) {
  26630. if (_basicCustomElementTest(lcTag) && (CUSTOM_ELEMENT_HANDLING.tagNameCheck instanceof RegExp && regExpTest(CUSTOM_ELEMENT_HANDLING.tagNameCheck, lcTag) || CUSTOM_ELEMENT_HANDLING.tagNameCheck instanceof Function && CUSTOM_ELEMENT_HANDLING.tagNameCheck(lcTag)) && (CUSTOM_ELEMENT_HANDLING.attributeNameCheck instanceof RegExp && regExpTest(CUSTOM_ELEMENT_HANDLING.attributeNameCheck, lcName) || CUSTOM_ELEMENT_HANDLING.attributeNameCheck instanceof Function && CUSTOM_ELEMENT_HANDLING.attributeNameCheck(lcName)) || lcName === 'is' && CUSTOM_ELEMENT_HANDLING.allowCustomizedBuiltInElements && (CUSTOM_ELEMENT_HANDLING.tagNameCheck instanceof RegExp && regExpTest(CUSTOM_ELEMENT_HANDLING.tagNameCheck, value) || CUSTOM_ELEMENT_HANDLING.tagNameCheck instanceof Function && CUSTOM_ELEMENT_HANDLING.tagNameCheck(value)));
  26631. else {
  26632. return false;
  26633. }
  26634. } else if (URI_SAFE_ATTRIBUTES[lcName]);
  26635. else if (regExpTest(IS_ALLOWED_URI$1, stringReplace(value, ATTR_WHITESPACE$1, '')));
  26636. else if ((lcName === 'src' || lcName === 'xlink:href' || lcName === 'href') && lcTag !== 'script' && stringIndexOf(value, 'data:') === 0 && DATA_URI_TAGS[lcTag]);
  26637. else if (ALLOW_UNKNOWN_PROTOCOLS && !regExpTest(IS_SCRIPT_OR_DATA$1, stringReplace(value, ATTR_WHITESPACE$1, '')));
  26638. else if (!value);
  26639. else {
  26640. return false;
  26641. }
  26642. return true;
  26643. };
  26644. var _basicCustomElementTest = function _basicCustomElementTest(tagName) {
  26645. return tagName.indexOf('-') > 0;
  26646. };
  26647. var _sanitizeAttributes = function _sanitizeAttributes(currentNode) {
  26648. var attr;
  26649. var value;
  26650. var lcName;
  26651. var l;
  26652. _executeHook('beforeSanitizeAttributes', currentNode, null);
  26653. var attributes = currentNode.attributes;
  26654. if (!attributes) {
  26655. return;
  26656. }
  26657. var hookEvent = {
  26658. attrName: '',
  26659. attrValue: '',
  26660. keepAttr: true,
  26661. allowedAttributes: ALLOWED_ATTR
  26662. };
  26663. l = attributes.length;
  26664. while (l--) {
  26665. attr = attributes[l];
  26666. var _attr = attr, name = _attr.name, namespaceURI = _attr.namespaceURI;
  26667. value = name === 'value' ? attr.value : stringTrim(attr.value);
  26668. lcName = transformCaseFunc(name);
  26669. var initValue = value;
  26670. hookEvent.attrName = lcName;
  26671. hookEvent.attrValue = value;
  26672. hookEvent.keepAttr = true;
  26673. hookEvent.forceKeepAttr = undefined;
  26674. _executeHook('uponSanitizeAttribute', currentNode, hookEvent);
  26675. value = hookEvent.attrValue;
  26676. if (hookEvent.forceKeepAttr) {
  26677. continue;
  26678. }
  26679. if (!hookEvent.keepAttr) {
  26680. _removeAttribute(name, currentNode);
  26681. continue;
  26682. }
  26683. if (regExpTest(/\/>/i, value)) {
  26684. _removeAttribute(name, currentNode);
  26685. continue;
  26686. }
  26687. if (SAFE_FOR_TEMPLATES) {
  26688. value = stringReplace(value, MUSTACHE_EXPR$1, ' ');
  26689. value = stringReplace(value, ERB_EXPR$1, ' ');
  26690. }
  26691. var lcTag = transformCaseFunc(currentNode.nodeName);
  26692. if (!_isValidAttribute(lcTag, lcName, value)) {
  26693. _removeAttribute(name, currentNode);
  26694. continue;
  26695. }
  26696. if (value !== initValue) {
  26697. try {
  26698. if (namespaceURI) {
  26699. currentNode.setAttributeNS(namespaceURI, name, value);
  26700. } else {
  26701. currentNode.setAttribute(name, value);
  26702. }
  26703. } catch (_) {
  26704. _removeAttribute(name, currentNode);
  26705. }
  26706. }
  26707. }
  26708. _executeHook('afterSanitizeAttributes', currentNode, null);
  26709. };
  26710. var _sanitizeShadowDOM = function _sanitizeShadowDOM(fragment) {
  26711. var shadowNode;
  26712. var shadowIterator = _createIterator(fragment);
  26713. _executeHook('beforeSanitizeShadowDOM', fragment, null);
  26714. while (shadowNode = shadowIterator.nextNode()) {
  26715. _executeHook('uponSanitizeShadowNode', shadowNode, null);
  26716. if (_sanitizeElements(shadowNode)) {
  26717. continue;
  26718. }
  26719. if (shadowNode.content instanceof DocumentFragment) {
  26720. _sanitizeShadowDOM(shadowNode.content);
  26721. }
  26722. _sanitizeAttributes(shadowNode);
  26723. }
  26724. _executeHook('afterSanitizeShadowDOM', fragment, null);
  26725. };
  26726. DOMPurify.sanitize = function (dirty, cfg) {
  26727. var body;
  26728. var importedNode;
  26729. var currentNode;
  26730. var oldNode;
  26731. var returnNode;
  26732. IS_EMPTY_INPUT = !dirty;
  26733. if (IS_EMPTY_INPUT) {
  26734. dirty = '<!-->';
  26735. }
  26736. if (typeof dirty !== 'string' && !_isNode(dirty)) {
  26737. if (typeof dirty.toString !== 'function') {
  26738. throw typeErrorCreate('toString is not a function');
  26739. } else {
  26740. dirty = dirty.toString();
  26741. if (typeof dirty !== 'string') {
  26742. throw typeErrorCreate('dirty is not a string, aborting');
  26743. }
  26744. }
  26745. }
  26746. if (!DOMPurify.isSupported) {
  26747. if (_typeof(window.toStaticHTML) === 'object' || typeof window.toStaticHTML === 'function') {
  26748. if (typeof dirty === 'string') {
  26749. return window.toStaticHTML(dirty);
  26750. }
  26751. if (_isNode(dirty)) {
  26752. return window.toStaticHTML(dirty.outerHTML);
  26753. }
  26754. }
  26755. return dirty;
  26756. }
  26757. if (!SET_CONFIG) {
  26758. _parseConfig(cfg);
  26759. }
  26760. DOMPurify.removed = [];
  26761. if (typeof dirty === 'string') {
  26762. IN_PLACE = false;
  26763. }
  26764. if (IN_PLACE) {
  26765. if (dirty.nodeName) {
  26766. var tagName = transformCaseFunc(dirty.nodeName);
  26767. if (!ALLOWED_TAGS[tagName] || FORBID_TAGS[tagName]) {
  26768. throw typeErrorCreate('root node is forbidden and cannot be sanitized in-place');
  26769. }
  26770. }
  26771. } else if (dirty instanceof Node) {
  26772. body = _initDocument('<!---->');
  26773. importedNode = body.ownerDocument.importNode(dirty, true);
  26774. if (importedNode.nodeType === 1 && importedNode.nodeName === 'BODY') {
  26775. body = importedNode;
  26776. } else if (importedNode.nodeName === 'HTML') {
  26777. body = importedNode;
  26778. } else {
  26779. body.appendChild(importedNode);
  26780. }
  26781. } else {
  26782. if (!RETURN_DOM && !SAFE_FOR_TEMPLATES && !WHOLE_DOCUMENT && dirty.indexOf('<') === -1) {
  26783. return trustedTypesPolicy && RETURN_TRUSTED_TYPE ? trustedTypesPolicy.createHTML(dirty) : dirty;
  26784. }
  26785. body = _initDocument(dirty);
  26786. if (!body) {
  26787. return RETURN_DOM ? null : RETURN_TRUSTED_TYPE ? emptyHTML : '';
  26788. }
  26789. }
  26790. if (body && FORCE_BODY) {
  26791. _forceRemove(body.firstChild);
  26792. }
  26793. var nodeIterator = _createIterator(IN_PLACE ? dirty : body);
  26794. while (currentNode = nodeIterator.nextNode()) {
  26795. if (currentNode.nodeType === 3 && currentNode === oldNode) {
  26796. continue;
  26797. }
  26798. if (_sanitizeElements(currentNode)) {
  26799. continue;
  26800. }
  26801. if (currentNode.content instanceof DocumentFragment) {
  26802. _sanitizeShadowDOM(currentNode.content);
  26803. }
  26804. _sanitizeAttributes(currentNode);
  26805. oldNode = currentNode;
  26806. }
  26807. oldNode = null;
  26808. if (IN_PLACE) {
  26809. return dirty;
  26810. }
  26811. if (RETURN_DOM) {
  26812. if (RETURN_DOM_FRAGMENT) {
  26813. returnNode = createDocumentFragment.call(body.ownerDocument);
  26814. while (body.firstChild) {
  26815. returnNode.appendChild(body.firstChild);
  26816. }
  26817. } else {
  26818. returnNode = body;
  26819. }
  26820. if (ALLOWED_ATTR.shadowroot) {
  26821. returnNode = importNode.call(originalDocument, returnNode, true);
  26822. }
  26823. return returnNode;
  26824. }
  26825. var serializedHTML = WHOLE_DOCUMENT ? body.outerHTML : body.innerHTML;
  26826. if (WHOLE_DOCUMENT && ALLOWED_TAGS['!doctype'] && body.ownerDocument && body.ownerDocument.doctype && body.ownerDocument.doctype.name && regExpTest(DOCTYPE_NAME, body.ownerDocument.doctype.name)) {
  26827. serializedHTML = '<!DOCTYPE ' + body.ownerDocument.doctype.name + '>\n' + serializedHTML;
  26828. }
  26829. if (SAFE_FOR_TEMPLATES) {
  26830. serializedHTML = stringReplace(serializedHTML, MUSTACHE_EXPR$1, ' ');
  26831. serializedHTML = stringReplace(serializedHTML, ERB_EXPR$1, ' ');
  26832. }
  26833. return trustedTypesPolicy && RETURN_TRUSTED_TYPE ? trustedTypesPolicy.createHTML(serializedHTML) : serializedHTML;
  26834. };
  26835. DOMPurify.setConfig = function (cfg) {
  26836. _parseConfig(cfg);
  26837. SET_CONFIG = true;
  26838. };
  26839. DOMPurify.clearConfig = function () {
  26840. CONFIG = null;
  26841. SET_CONFIG = false;
  26842. };
  26843. DOMPurify.isValidAttribute = function (tag, attr, value) {
  26844. if (!CONFIG) {
  26845. _parseConfig({});
  26846. }
  26847. var lcTag = transformCaseFunc(tag);
  26848. var lcName = transformCaseFunc(attr);
  26849. return _isValidAttribute(lcTag, lcName, value);
  26850. };
  26851. DOMPurify.addHook = function (entryPoint, hookFunction) {
  26852. if (typeof hookFunction !== 'function') {
  26853. return;
  26854. }
  26855. hooks[entryPoint] = hooks[entryPoint] || [];
  26856. arrayPush(hooks[entryPoint], hookFunction);
  26857. };
  26858. DOMPurify.removeHook = function (entryPoint) {
  26859. if (hooks[entryPoint]) {
  26860. return arrayPop(hooks[entryPoint]);
  26861. }
  26862. };
  26863. DOMPurify.removeHooks = function (entryPoint) {
  26864. if (hooks[entryPoint]) {
  26865. hooks[entryPoint] = [];
  26866. }
  26867. };
  26868. DOMPurify.removeAllHooks = function () {
  26869. hooks = {};
  26870. };
  26871. return DOMPurify;
  26872. }
  26873. var purify = createDOMPurify();
  26874. const sanitizeHtmlString = html => purify().sanitize(html);
  26875. const isTouch = global$5.deviceType.isTouch();
  26876. const hiddenHeader = (title, close) => ({
  26877. dom: {
  26878. tag: 'div',
  26879. styles: { display: 'none' },
  26880. classes: ['tox-dialog__header']
  26881. },
  26882. components: [
  26883. title,
  26884. close
  26885. ]
  26886. });
  26887. const pClose = (onClose, providersBackstage) => ModalDialog.parts.close(Button.sketch({
  26888. dom: {
  26889. tag: 'button',
  26890. classes: [
  26891. 'tox-button',
  26892. 'tox-button--icon',
  26893. 'tox-button--naked'
  26894. ],
  26895. attributes: {
  26896. 'type': 'button',
  26897. 'aria-label': providersBackstage.translate('Close')
  26898. }
  26899. },
  26900. action: onClose,
  26901. buttonBehaviours: derive$1([Tabstopping.config({})])
  26902. }));
  26903. const pUntitled = () => ModalDialog.parts.title({
  26904. dom: {
  26905. tag: 'div',
  26906. classes: ['tox-dialog__title'],
  26907. innerHtml: '',
  26908. styles: { display: 'none' }
  26909. }
  26910. });
  26911. const pBodyMessage = (message, providersBackstage) => ModalDialog.parts.body({
  26912. dom: {
  26913. tag: 'div',
  26914. classes: ['tox-dialog__body']
  26915. },
  26916. components: [{
  26917. dom: {
  26918. tag: 'div',
  26919. classes: ['tox-dialog__body-content']
  26920. },
  26921. components: [{ dom: fromHtml(`<p>${ sanitizeHtmlString(providersBackstage.translate(message)) }</p>`) }]
  26922. }]
  26923. });
  26924. const pFooter = buttons => ModalDialog.parts.footer({
  26925. dom: {
  26926. tag: 'div',
  26927. classes: ['tox-dialog__footer']
  26928. },
  26929. components: buttons
  26930. });
  26931. const pFooterGroup = (startButtons, endButtons) => [
  26932. Container.sketch({
  26933. dom: {
  26934. tag: 'div',
  26935. classes: ['tox-dialog__footer-start']
  26936. },
  26937. components: startButtons
  26938. }),
  26939. Container.sketch({
  26940. dom: {
  26941. tag: 'div',
  26942. classes: ['tox-dialog__footer-end']
  26943. },
  26944. components: endButtons
  26945. })
  26946. ];
  26947. const renderDialog$1 = spec => {
  26948. const dialogClass = 'tox-dialog';
  26949. const blockerClass = dialogClass + '-wrap';
  26950. const blockerBackdropClass = blockerClass + '__backdrop';
  26951. const scrollLockClass = dialogClass + '__disable-scroll';
  26952. return ModalDialog.sketch({
  26953. lazySink: spec.lazySink,
  26954. onEscape: comp => {
  26955. spec.onEscape(comp);
  26956. return Optional.some(true);
  26957. },
  26958. useTabstopAt: elem => !isPseudoStop(elem),
  26959. dom: {
  26960. tag: 'div',
  26961. classes: [dialogClass].concat(spec.extraClasses),
  26962. styles: {
  26963. position: 'relative',
  26964. ...spec.extraStyles
  26965. }
  26966. },
  26967. components: [
  26968. spec.header,
  26969. spec.body,
  26970. ...spec.footer.toArray()
  26971. ],
  26972. parts: {
  26973. blocker: {
  26974. dom: fromHtml(`<div class="${ blockerClass }"></div>`),
  26975. components: [{
  26976. dom: {
  26977. tag: 'div',
  26978. classes: isTouch ? [
  26979. blockerBackdropClass,
  26980. blockerBackdropClass + '--opaque'
  26981. ] : [blockerBackdropClass]
  26982. }
  26983. }]
  26984. }
  26985. },
  26986. dragBlockClass: blockerClass,
  26987. modalBehaviours: derive$1([
  26988. Focusing.config({}),
  26989. config('dialog-events', spec.dialogEvents.concat([runOnSource(focusin(), (comp, _se) => {
  26990. Keying.focusIn(comp);
  26991. })])),
  26992. config('scroll-lock', [
  26993. runOnAttached(() => {
  26994. add$2(body(), scrollLockClass);
  26995. }),
  26996. runOnDetached(() => {
  26997. remove$2(body(), scrollLockClass);
  26998. })
  26999. ]),
  27000. ...spec.extraBehaviours
  27001. ]),
  27002. eventOrder: {
  27003. [execute$5()]: ['dialog-events'],
  27004. [attachedToDom()]: [
  27005. 'scroll-lock',
  27006. 'dialog-events',
  27007. 'alloy.base.behaviour'
  27008. ],
  27009. [detachedFromDom()]: [
  27010. 'alloy.base.behaviour',
  27011. 'dialog-events',
  27012. 'scroll-lock'
  27013. ],
  27014. ...spec.eventOrder
  27015. }
  27016. });
  27017. };
  27018. const renderClose = providersBackstage => Button.sketch({
  27019. dom: {
  27020. tag: 'button',
  27021. classes: [
  27022. 'tox-button',
  27023. 'tox-button--icon',
  27024. 'tox-button--naked'
  27025. ],
  27026. attributes: {
  27027. 'type': 'button',
  27028. 'aria-label': providersBackstage.translate('Close'),
  27029. 'title': providersBackstage.translate('Close')
  27030. }
  27031. },
  27032. components: [render$3('close', {
  27033. tag: 'div',
  27034. classes: ['tox-icon']
  27035. }, providersBackstage.icons)],
  27036. action: comp => {
  27037. emit(comp, formCancelEvent);
  27038. }
  27039. });
  27040. const renderTitle = (spec, dialogId, titleId, providersBackstage) => {
  27041. const renderComponents = data => [text$2(providersBackstage.translate(data.title))];
  27042. return {
  27043. dom: {
  27044. tag: 'div',
  27045. classes: ['tox-dialog__title'],
  27046. attributes: { ...titleId.map(x => ({ id: x })).getOr({}) }
  27047. },
  27048. components: [],
  27049. behaviours: derive$1([Reflecting.config({
  27050. channel: `${ titleChannel }-${ dialogId }`,
  27051. initialData: spec,
  27052. renderComponents
  27053. })])
  27054. };
  27055. };
  27056. const renderDragHandle = () => ({ dom: fromHtml('<div class="tox-dialog__draghandle"></div>') });
  27057. const renderInlineHeader = (spec, dialogId, titleId, providersBackstage) => Container.sketch({
  27058. dom: fromHtml('<div class="tox-dialog__header"></div>'),
  27059. components: [
  27060. renderTitle(spec, dialogId, Optional.some(titleId), providersBackstage),
  27061. renderDragHandle(),
  27062. renderClose(providersBackstage)
  27063. ],
  27064. containerBehaviours: derive$1([Dragging.config({
  27065. mode: 'mouse',
  27066. blockerClass: 'blocker',
  27067. getTarget: handle => {
  27068. return closest$1(handle, '[role="dialog"]').getOrDie();
  27069. },
  27070. snaps: {
  27071. getSnapPoints: () => [],
  27072. leftAttr: 'data-drag-left',
  27073. topAttr: 'data-drag-top'
  27074. }
  27075. })])
  27076. });
  27077. const renderModalHeader = (spec, dialogId, providersBackstage) => {
  27078. const pTitle = ModalDialog.parts.title(renderTitle(spec, dialogId, Optional.none(), providersBackstage));
  27079. const pHandle = ModalDialog.parts.draghandle(renderDragHandle());
  27080. const pClose = ModalDialog.parts.close(renderClose(providersBackstage));
  27081. const components = [pTitle].concat(spec.draggable ? [pHandle] : []).concat([pClose]);
  27082. return Container.sketch({
  27083. dom: fromHtml('<div class="tox-dialog__header"></div>'),
  27084. components
  27085. });
  27086. };
  27087. const getHeader = (title, dialogId, backstage) => renderModalHeader({
  27088. title: backstage.shared.providers.translate(title),
  27089. draggable: backstage.dialog.isDraggableModal()
  27090. }, dialogId, backstage.shared.providers);
  27091. const getBusySpec = (message, bs, providers) => ({
  27092. dom: {
  27093. tag: 'div',
  27094. classes: ['tox-dialog__busy-spinner'],
  27095. attributes: { 'aria-label': providers.translate(message) },
  27096. styles: {
  27097. left: '0px',
  27098. right: '0px',
  27099. bottom: '0px',
  27100. top: '0px',
  27101. position: 'absolute'
  27102. }
  27103. },
  27104. behaviours: bs,
  27105. components: [{ dom: fromHtml('<div class="tox-spinner"><div></div><div></div><div></div></div>') }]
  27106. });
  27107. const getEventExtras = (lazyDialog, providers, extra) => ({
  27108. onClose: () => extra.closeWindow(),
  27109. onBlock: blockEvent => {
  27110. ModalDialog.setBusy(lazyDialog(), (_comp, bs) => getBusySpec(blockEvent.message, bs, providers));
  27111. },
  27112. onUnblock: () => {
  27113. ModalDialog.setIdle(lazyDialog());
  27114. }
  27115. });
  27116. const renderModalDialog = (spec, initialData, dialogEvents, backstage) => {
  27117. const updateState = (_comp, incoming) => Optional.some(incoming);
  27118. return build$1(renderDialog$1({
  27119. ...spec,
  27120. lazySink: backstage.shared.getSink,
  27121. extraBehaviours: [
  27122. Reflecting.config({
  27123. channel: `${ dialogChannel }-${ spec.id }`,
  27124. updateState,
  27125. initialData
  27126. }),
  27127. RepresentingConfigs.memory({}),
  27128. ...spec.extraBehaviours
  27129. ],
  27130. onEscape: comp => {
  27131. emit(comp, formCancelEvent);
  27132. },
  27133. dialogEvents,
  27134. eventOrder: {
  27135. [receive()]: [
  27136. Reflecting.name(),
  27137. Receiving.name()
  27138. ],
  27139. [attachedToDom()]: [
  27140. 'scroll-lock',
  27141. Reflecting.name(),
  27142. 'messages',
  27143. 'dialog-events',
  27144. 'alloy.base.behaviour'
  27145. ],
  27146. [detachedFromDom()]: [
  27147. 'alloy.base.behaviour',
  27148. 'dialog-events',
  27149. 'messages',
  27150. Reflecting.name(),
  27151. 'scroll-lock'
  27152. ]
  27153. }
  27154. }));
  27155. };
  27156. const mapMenuButtons = buttons => {
  27157. const mapItems = button => {
  27158. const items = map$2(button.items, item => {
  27159. const cell = Cell(false);
  27160. return {
  27161. ...item,
  27162. storage: cell
  27163. };
  27164. });
  27165. return {
  27166. ...button,
  27167. items
  27168. };
  27169. };
  27170. return map$2(buttons, button => {
  27171. return button.type === 'menu' ? mapItems(button) : button;
  27172. });
  27173. };
  27174. const extractCellsToObject = buttons => foldl(buttons, (acc, button) => {
  27175. if (button.type === 'menu') {
  27176. const menuButton = button;
  27177. return foldl(menuButton.items, (innerAcc, item) => {
  27178. innerAcc[item.name] = item.storage;
  27179. return innerAcc;
  27180. }, acc);
  27181. }
  27182. return acc;
  27183. }, {});
  27184. const initCommonEvents = (fireApiEvent, extras) => [
  27185. runWithTarget(focusin(), onFocus),
  27186. fireApiEvent(formCloseEvent, (_api, spec) => {
  27187. extras.onClose();
  27188. spec.onClose();
  27189. }),
  27190. fireApiEvent(formCancelEvent, (api, spec, _event, self) => {
  27191. spec.onCancel(api);
  27192. emit(self, formCloseEvent);
  27193. }),
  27194. run$1(formUnblockEvent, (_c, _se) => extras.onUnblock()),
  27195. run$1(formBlockEvent, (_c, se) => extras.onBlock(se.event))
  27196. ];
  27197. const initUrlDialog = (getInstanceApi, extras) => {
  27198. const fireApiEvent = (eventName, f) => run$1(eventName, (c, se) => {
  27199. withSpec(c, (spec, _c) => {
  27200. f(getInstanceApi(), spec, se.event, c);
  27201. });
  27202. });
  27203. const withSpec = (c, f) => {
  27204. Reflecting.getState(c).get().each(currentDialog => {
  27205. f(currentDialog, c);
  27206. });
  27207. };
  27208. return [
  27209. ...initCommonEvents(fireApiEvent, extras),
  27210. fireApiEvent(formActionEvent, (api, spec, event) => {
  27211. spec.onAction(api, { name: event.name });
  27212. })
  27213. ];
  27214. };
  27215. const initDialog = (getInstanceApi, extras, getSink) => {
  27216. const fireApiEvent = (eventName, f) => run$1(eventName, (c, se) => {
  27217. withSpec(c, (spec, _c) => {
  27218. f(getInstanceApi(), spec, se.event, c);
  27219. });
  27220. });
  27221. const withSpec = (c, f) => {
  27222. Reflecting.getState(c).get().each(currentDialogInit => {
  27223. f(currentDialogInit.internalDialog, c);
  27224. });
  27225. };
  27226. return [
  27227. ...initCommonEvents(fireApiEvent, extras),
  27228. fireApiEvent(formSubmitEvent, (api, spec) => spec.onSubmit(api)),
  27229. fireApiEvent(formChangeEvent, (api, spec, event) => {
  27230. spec.onChange(api, { name: event.name });
  27231. }),
  27232. fireApiEvent(formActionEvent, (api, spec, event, component) => {
  27233. const focusIn = () => Keying.focusIn(component);
  27234. const isDisabled = focused => has$1(focused, 'disabled') || getOpt(focused, 'aria-disabled').exists(val => val === 'true');
  27235. const rootNode = getRootNode(component.element);
  27236. const current = active$1(rootNode);
  27237. spec.onAction(api, {
  27238. name: event.name,
  27239. value: event.value
  27240. });
  27241. active$1(rootNode).fold(focusIn, focused => {
  27242. if (isDisabled(focused)) {
  27243. focusIn();
  27244. } else if (current.exists(cur => contains(focused, cur) && isDisabled(cur))) {
  27245. focusIn();
  27246. } else {
  27247. getSink().toOptional().filter(sink => !contains(sink.element, focused)).each(focusIn);
  27248. }
  27249. });
  27250. }),
  27251. fireApiEvent(formTabChangeEvent, (api, spec, event) => {
  27252. spec.onTabChange(api, {
  27253. newTabName: event.name,
  27254. oldTabName: event.oldName
  27255. });
  27256. }),
  27257. runOnDetached(component => {
  27258. const api = getInstanceApi();
  27259. Representing.setValue(component, api.getData());
  27260. })
  27261. ];
  27262. };
  27263. const SilverDialogEvents = {
  27264. initUrlDialog,
  27265. initDialog
  27266. };
  27267. const makeButton = (button, backstage) => renderFooterButton(button, button.type, backstage);
  27268. const lookup = (compInSystem, footerButtons, buttonName) => find$5(footerButtons, button => button.name === buttonName).bind(memButton => memButton.memento.getOpt(compInSystem));
  27269. const renderComponents = (_data, state) => {
  27270. const footerButtons = state.map(s => s.footerButtons).getOr([]);
  27271. const buttonGroups = partition$3(footerButtons, button => button.align === 'start');
  27272. const makeGroup = (edge, buttons) => Container.sketch({
  27273. dom: {
  27274. tag: 'div',
  27275. classes: [`tox-dialog__footer-${ edge }`]
  27276. },
  27277. components: map$2(buttons, button => button.memento.asSpec())
  27278. });
  27279. const startButtons = makeGroup('start', buttonGroups.pass);
  27280. const endButtons = makeGroup('end', buttonGroups.fail);
  27281. return [
  27282. startButtons,
  27283. endButtons
  27284. ];
  27285. };
  27286. const renderFooter = (initSpec, dialogId, backstage) => {
  27287. const updateState = (comp, data) => {
  27288. const footerButtons = map$2(data.buttons, button => {
  27289. const memButton = record(makeButton(button, backstage));
  27290. return {
  27291. name: button.name,
  27292. align: button.align,
  27293. memento: memButton
  27294. };
  27295. });
  27296. const lookupByName = buttonName => lookup(comp, footerButtons, buttonName);
  27297. return Optional.some({
  27298. lookupByName,
  27299. footerButtons
  27300. });
  27301. };
  27302. return {
  27303. dom: fromHtml('<div class="tox-dialog__footer"></div>'),
  27304. components: [],
  27305. behaviours: derive$1([Reflecting.config({
  27306. channel: `${ footerChannel }-${ dialogId }`,
  27307. initialData: initSpec,
  27308. updateState,
  27309. renderComponents
  27310. })])
  27311. };
  27312. };
  27313. const renderInlineFooter = (initSpec, dialogId, backstage) => renderFooter(initSpec, dialogId, backstage);
  27314. const renderModalFooter = (initSpec, dialogId, backstage) => ModalDialog.parts.footer(renderFooter(initSpec, dialogId, backstage));
  27315. const getCompByName = (access, name) => {
  27316. const root = access.getRoot();
  27317. if (root.getSystem().isConnected()) {
  27318. const form = Composing.getCurrent(access.getFormWrapper()).getOr(access.getFormWrapper());
  27319. return Form.getField(form, name).orThunk(() => {
  27320. const footer = access.getFooter();
  27321. const footerState = Reflecting.getState(footer).get();
  27322. return footerState.bind(f => f.lookupByName(name));
  27323. });
  27324. } else {
  27325. return Optional.none();
  27326. }
  27327. };
  27328. const validateData$1 = (access, data) => {
  27329. const root = access.getRoot();
  27330. return Reflecting.getState(root).get().map(dialogState => getOrDie(asRaw('data', dialogState.dataValidator, data))).getOr(data);
  27331. };
  27332. const getDialogApi = (access, doRedial, menuItemStates) => {
  27333. const withRoot = f => {
  27334. const root = access.getRoot();
  27335. if (root.getSystem().isConnected()) {
  27336. f(root);
  27337. }
  27338. };
  27339. const getData = () => {
  27340. const root = access.getRoot();
  27341. const valueComp = root.getSystem().isConnected() ? access.getFormWrapper() : root;
  27342. const representedValues = Representing.getValue(valueComp);
  27343. const menuItemCurrentState = map$1(menuItemStates, cell => cell.get());
  27344. return {
  27345. ...representedValues,
  27346. ...menuItemCurrentState
  27347. };
  27348. };
  27349. const setData = newData => {
  27350. withRoot(_ => {
  27351. const prevData = instanceApi.getData();
  27352. const mergedData = deepMerge(prevData, newData);
  27353. const newInternalData = validateData$1(access, mergedData);
  27354. const form = access.getFormWrapper();
  27355. Representing.setValue(form, newInternalData);
  27356. each(menuItemStates, (v, k) => {
  27357. if (has$2(mergedData, k)) {
  27358. v.set(mergedData[k]);
  27359. }
  27360. });
  27361. });
  27362. };
  27363. const setEnabled = (name, state) => {
  27364. getCompByName(access, name).each(state ? Disabling.enable : Disabling.disable);
  27365. };
  27366. const focus = name => {
  27367. getCompByName(access, name).each(Focusing.focus);
  27368. };
  27369. const block = message => {
  27370. if (!isString(message)) {
  27371. throw new Error('The dialogInstanceAPI.block function should be passed a blocking message of type string as an argument');
  27372. }
  27373. withRoot(root => {
  27374. emitWith(root, formBlockEvent, { message });
  27375. });
  27376. };
  27377. const unblock = () => {
  27378. withRoot(root => {
  27379. emit(root, formUnblockEvent);
  27380. });
  27381. };
  27382. const showTab = name => {
  27383. withRoot(_ => {
  27384. const body = access.getBody();
  27385. const bodyState = Reflecting.getState(body);
  27386. if (bodyState.get().exists(b => b.isTabPanel())) {
  27387. Composing.getCurrent(body).each(tabSection => {
  27388. TabSection.showTab(tabSection, name);
  27389. });
  27390. }
  27391. });
  27392. };
  27393. const redial = d => {
  27394. withRoot(root => {
  27395. const id = access.getId();
  27396. const dialogInit = doRedial(d);
  27397. root.getSystem().broadcastOn([`${ dialogChannel }-${ id }`], dialogInit);
  27398. root.getSystem().broadcastOn([`${ titleChannel }-${ id }`], dialogInit.internalDialog);
  27399. root.getSystem().broadcastOn([`${ bodyChannel }-${ id }`], dialogInit.internalDialog);
  27400. root.getSystem().broadcastOn([`${ footerChannel }-${ id }`], dialogInit.internalDialog);
  27401. instanceApi.setData(dialogInit.initialData);
  27402. });
  27403. };
  27404. const close = () => {
  27405. withRoot(root => {
  27406. emit(root, formCloseEvent);
  27407. });
  27408. };
  27409. const instanceApi = {
  27410. getData,
  27411. setData,
  27412. setEnabled,
  27413. focus,
  27414. block,
  27415. unblock,
  27416. showTab,
  27417. redial,
  27418. close
  27419. };
  27420. return instanceApi;
  27421. };
  27422. const getDialogSizeClasses = size => {
  27423. switch (size) {
  27424. case 'large':
  27425. return ['tox-dialog--width-lg'];
  27426. case 'medium':
  27427. return ['tox-dialog--width-md'];
  27428. default:
  27429. return [];
  27430. }
  27431. };
  27432. const renderDialog = (dialogInit, extra, backstage) => {
  27433. const dialogId = generate$6('dialog');
  27434. const internalDialog = dialogInit.internalDialog;
  27435. const header = getHeader(internalDialog.title, dialogId, backstage);
  27436. const body = renderModalBody({
  27437. body: internalDialog.body,
  27438. initialData: internalDialog.initialData
  27439. }, dialogId, backstage);
  27440. const storedMenuButtons = mapMenuButtons(internalDialog.buttons);
  27441. const objOfCells = extractCellsToObject(storedMenuButtons);
  27442. const footer = renderModalFooter({ buttons: storedMenuButtons }, dialogId, backstage);
  27443. const dialogEvents = SilverDialogEvents.initDialog(() => instanceApi, getEventExtras(() => dialog, backstage.shared.providers, extra), backstage.shared.getSink);
  27444. const dialogSize = getDialogSizeClasses(internalDialog.size);
  27445. const spec = {
  27446. id: dialogId,
  27447. header,
  27448. body,
  27449. footer: Optional.some(footer),
  27450. extraClasses: dialogSize,
  27451. extraBehaviours: [],
  27452. extraStyles: {}
  27453. };
  27454. const dialog = renderModalDialog(spec, dialogInit, dialogEvents, backstage);
  27455. const modalAccess = (() => {
  27456. const getForm = () => {
  27457. const outerForm = ModalDialog.getBody(dialog);
  27458. return Composing.getCurrent(outerForm).getOr(outerForm);
  27459. };
  27460. return {
  27461. getId: constant$1(dialogId),
  27462. getRoot: constant$1(dialog),
  27463. getBody: () => ModalDialog.getBody(dialog),
  27464. getFooter: () => ModalDialog.getFooter(dialog),
  27465. getFormWrapper: getForm
  27466. };
  27467. })();
  27468. const instanceApi = getDialogApi(modalAccess, extra.redial, objOfCells);
  27469. return {
  27470. dialog,
  27471. instanceApi
  27472. };
  27473. };
  27474. const renderInlineDialog = (dialogInit, extra, backstage, ariaAttrs) => {
  27475. const dialogId = generate$6('dialog');
  27476. const dialogLabelId = generate$6('dialog-label');
  27477. const dialogContentId = generate$6('dialog-content');
  27478. const internalDialog = dialogInit.internalDialog;
  27479. const updateState = (_comp, incoming) => Optional.some(incoming);
  27480. const memHeader = record(renderInlineHeader({
  27481. title: internalDialog.title,
  27482. draggable: true
  27483. }, dialogId, dialogLabelId, backstage.shared.providers));
  27484. const memBody = record(renderInlineBody({
  27485. body: internalDialog.body,
  27486. initialData: internalDialog.initialData
  27487. }, dialogId, dialogContentId, backstage, ariaAttrs));
  27488. const storagedMenuButtons = mapMenuButtons(internalDialog.buttons);
  27489. const objOfCells = extractCellsToObject(storagedMenuButtons);
  27490. const memFooter = record(renderInlineFooter({ buttons: storagedMenuButtons }, dialogId, backstage));
  27491. const dialogEvents = SilverDialogEvents.initDialog(() => instanceApi, {
  27492. onBlock: event => {
  27493. Blocking.block(dialog, (_comp, bs) => getBusySpec(event.message, bs, backstage.shared.providers));
  27494. },
  27495. onUnblock: () => {
  27496. Blocking.unblock(dialog);
  27497. },
  27498. onClose: () => extra.closeWindow()
  27499. }, backstage.shared.getSink);
  27500. const dialog = build$1({
  27501. dom: {
  27502. tag: 'div',
  27503. classes: [
  27504. 'tox-dialog',
  27505. 'tox-dialog-inline'
  27506. ],
  27507. attributes: {
  27508. role: 'dialog',
  27509. ['aria-labelledby']: dialogLabelId,
  27510. ['aria-describedby']: dialogContentId
  27511. }
  27512. },
  27513. eventOrder: {
  27514. [receive()]: [
  27515. Reflecting.name(),
  27516. Receiving.name()
  27517. ],
  27518. [execute$5()]: ['execute-on-form'],
  27519. [attachedToDom()]: [
  27520. 'reflecting',
  27521. 'execute-on-form'
  27522. ]
  27523. },
  27524. behaviours: derive$1([
  27525. Keying.config({
  27526. mode: 'cyclic',
  27527. onEscape: c => {
  27528. emit(c, formCloseEvent);
  27529. return Optional.some(true);
  27530. },
  27531. useTabstopAt: elem => !isPseudoStop(elem) && (name$3(elem) !== 'button' || get$f(elem, 'disabled') !== 'disabled')
  27532. }),
  27533. Reflecting.config({
  27534. channel: `${ dialogChannel }-${ dialogId }`,
  27535. updateState,
  27536. initialData: dialogInit
  27537. }),
  27538. Focusing.config({}),
  27539. config('execute-on-form', dialogEvents.concat([runOnSource(focusin(), (comp, _se) => {
  27540. Keying.focusIn(comp);
  27541. })])),
  27542. Blocking.config({ getRoot: () => Optional.some(dialog) }),
  27543. Replacing.config({}),
  27544. RepresentingConfigs.memory({})
  27545. ]),
  27546. components: [
  27547. memHeader.asSpec(),
  27548. memBody.asSpec(),
  27549. memFooter.asSpec()
  27550. ]
  27551. });
  27552. const instanceApi = getDialogApi({
  27553. getId: constant$1(dialogId),
  27554. getRoot: constant$1(dialog),
  27555. getFooter: () => memFooter.get(dialog),
  27556. getBody: () => memBody.get(dialog),
  27557. getFormWrapper: () => {
  27558. const body = memBody.get(dialog);
  27559. return Composing.getCurrent(body).getOr(body);
  27560. }
  27561. }, extra.redial, objOfCells);
  27562. return {
  27563. dialog,
  27564. instanceApi
  27565. };
  27566. };
  27567. var global = tinymce.util.Tools.resolve('tinymce.util.URI');
  27568. const getUrlDialogApi = root => {
  27569. const withRoot = f => {
  27570. if (root.getSystem().isConnected()) {
  27571. f(root);
  27572. }
  27573. };
  27574. const block = message => {
  27575. if (!isString(message)) {
  27576. throw new Error('The urlDialogInstanceAPI.block function should be passed a blocking message of type string as an argument');
  27577. }
  27578. withRoot(root => {
  27579. emitWith(root, formBlockEvent, { message });
  27580. });
  27581. };
  27582. const unblock = () => {
  27583. withRoot(root => {
  27584. emit(root, formUnblockEvent);
  27585. });
  27586. };
  27587. const close = () => {
  27588. withRoot(root => {
  27589. emit(root, formCloseEvent);
  27590. });
  27591. };
  27592. const sendMessage = data => {
  27593. withRoot(root => {
  27594. root.getSystem().broadcastOn([bodySendMessageChannel], data);
  27595. });
  27596. };
  27597. return {
  27598. block,
  27599. unblock,
  27600. close,
  27601. sendMessage
  27602. };
  27603. };
  27604. const SUPPORTED_MESSAGE_ACTIONS = [
  27605. 'insertContent',
  27606. 'setContent',
  27607. 'execCommand',
  27608. 'close',
  27609. 'block',
  27610. 'unblock'
  27611. ];
  27612. const isSupportedMessage = data => isObject(data) && SUPPORTED_MESSAGE_ACTIONS.indexOf(data.mceAction) !== -1;
  27613. const isCustomMessage = data => !isSupportedMessage(data) && isObject(data) && has$2(data, 'mceAction');
  27614. const handleMessage = (editor, api, data) => {
  27615. switch (data.mceAction) {
  27616. case 'insertContent':
  27617. editor.insertContent(data.content);
  27618. break;
  27619. case 'setContent':
  27620. editor.setContent(data.content);
  27621. break;
  27622. case 'execCommand':
  27623. const ui = isBoolean(data.ui) ? data.ui : false;
  27624. editor.execCommand(data.cmd, ui, data.value);
  27625. break;
  27626. case 'close':
  27627. api.close();
  27628. break;
  27629. case 'block':
  27630. api.block(data.message);
  27631. break;
  27632. case 'unblock':
  27633. api.unblock();
  27634. break;
  27635. }
  27636. };
  27637. const renderUrlDialog = (internalDialog, extra, editor, backstage) => {
  27638. const dialogId = generate$6('dialog');
  27639. const header = getHeader(internalDialog.title, dialogId, backstage);
  27640. const body = renderIframeBody(internalDialog);
  27641. const footer = internalDialog.buttons.bind(buttons => {
  27642. if (buttons.length === 0) {
  27643. return Optional.none();
  27644. } else {
  27645. return Optional.some(renderModalFooter({ buttons }, dialogId, backstage));
  27646. }
  27647. });
  27648. const dialogEvents = SilverDialogEvents.initUrlDialog(() => instanceApi, getEventExtras(() => dialog, backstage.shared.providers, extra));
  27649. const styles = {
  27650. ...internalDialog.height.fold(() => ({}), height => ({
  27651. 'height': height + 'px',
  27652. 'max-height': height + 'px'
  27653. })),
  27654. ...internalDialog.width.fold(() => ({}), width => ({
  27655. 'width': width + 'px',
  27656. 'max-width': width + 'px'
  27657. }))
  27658. };
  27659. const classes = internalDialog.width.isNone() && internalDialog.height.isNone() ? ['tox-dialog--width-lg'] : [];
  27660. const iframeUri = new global(internalDialog.url, { base_uri: new global(window.location.href) });
  27661. const iframeDomain = `${ iframeUri.protocol }://${ iframeUri.host }${ iframeUri.port ? ':' + iframeUri.port : '' }`;
  27662. const messageHandlerUnbinder = unbindable();
  27663. const extraBehaviours = [
  27664. config('messages', [
  27665. runOnAttached(() => {
  27666. const unbind = bind(SugarElement.fromDom(window), 'message', e => {
  27667. if (iframeUri.isSameOrigin(new global(e.raw.origin))) {
  27668. const data = e.raw.data;
  27669. if (isSupportedMessage(data)) {
  27670. handleMessage(editor, instanceApi, data);
  27671. } else if (isCustomMessage(data)) {
  27672. internalDialog.onMessage(instanceApi, data);
  27673. }
  27674. }
  27675. });
  27676. messageHandlerUnbinder.set(unbind);
  27677. }),
  27678. runOnDetached(messageHandlerUnbinder.clear)
  27679. ]),
  27680. Receiving.config({
  27681. channels: {
  27682. [bodySendMessageChannel]: {
  27683. onReceive: (comp, data) => {
  27684. descendant(comp.element, 'iframe').each(iframeEle => {
  27685. const iframeWin = iframeEle.dom.contentWindow;
  27686. if (isNonNullable(iframeWin)) {
  27687. iframeWin.postMessage(data, iframeDomain);
  27688. }
  27689. });
  27690. }
  27691. }
  27692. }
  27693. })
  27694. ];
  27695. const spec = {
  27696. id: dialogId,
  27697. header,
  27698. body,
  27699. footer,
  27700. extraClasses: classes,
  27701. extraBehaviours,
  27702. extraStyles: styles
  27703. };
  27704. const dialog = renderModalDialog(spec, internalDialog, dialogEvents, backstage);
  27705. const instanceApi = getUrlDialogApi(dialog);
  27706. return {
  27707. dialog,
  27708. instanceApi
  27709. };
  27710. };
  27711. const setup$2 = backstage => {
  27712. const sharedBackstage = backstage.shared;
  27713. const open = (message, callback) => {
  27714. const closeDialog = () => {
  27715. ModalDialog.hide(alertDialog);
  27716. callback();
  27717. };
  27718. const memFooterClose = record(renderFooterButton({
  27719. name: 'close-alert',
  27720. text: 'OK',
  27721. primary: true,
  27722. buttonType: Optional.some('primary'),
  27723. align: 'end',
  27724. enabled: true,
  27725. icon: Optional.none()
  27726. }, 'cancel', backstage));
  27727. const titleSpec = pUntitled();
  27728. const closeSpec = pClose(closeDialog, sharedBackstage.providers);
  27729. const alertDialog = build$1(renderDialog$1({
  27730. lazySink: () => sharedBackstage.getSink(),
  27731. header: hiddenHeader(titleSpec, closeSpec),
  27732. body: pBodyMessage(message, sharedBackstage.providers),
  27733. footer: Optional.some(pFooter(pFooterGroup([], [memFooterClose.asSpec()]))),
  27734. onEscape: closeDialog,
  27735. extraClasses: ['tox-alert-dialog'],
  27736. extraBehaviours: [],
  27737. extraStyles: {},
  27738. dialogEvents: [run$1(formCancelEvent, closeDialog)],
  27739. eventOrder: {}
  27740. }));
  27741. ModalDialog.show(alertDialog);
  27742. const footerCloseButton = memFooterClose.get(alertDialog);
  27743. Focusing.focus(footerCloseButton);
  27744. };
  27745. return { open };
  27746. };
  27747. const setup$1 = backstage => {
  27748. const sharedBackstage = backstage.shared;
  27749. const open = (message, callback) => {
  27750. const closeDialog = state => {
  27751. ModalDialog.hide(confirmDialog);
  27752. callback(state);
  27753. };
  27754. const memFooterYes = record(renderFooterButton({
  27755. name: 'yes',
  27756. text: 'Yes',
  27757. primary: true,
  27758. buttonType: Optional.some('primary'),
  27759. align: 'end',
  27760. enabled: true,
  27761. icon: Optional.none()
  27762. }, 'submit', backstage));
  27763. const footerNo = renderFooterButton({
  27764. name: 'no',
  27765. text: 'No',
  27766. primary: false,
  27767. buttonType: Optional.some('secondary'),
  27768. align: 'end',
  27769. enabled: true,
  27770. icon: Optional.none()
  27771. }, 'cancel', backstage);
  27772. const titleSpec = pUntitled();
  27773. const closeSpec = pClose(() => closeDialog(false), sharedBackstage.providers);
  27774. const confirmDialog = build$1(renderDialog$1({
  27775. lazySink: () => sharedBackstage.getSink(),
  27776. header: hiddenHeader(titleSpec, closeSpec),
  27777. body: pBodyMessage(message, sharedBackstage.providers),
  27778. footer: Optional.some(pFooter(pFooterGroup([], [
  27779. footerNo,
  27780. memFooterYes.asSpec()
  27781. ]))),
  27782. onEscape: () => closeDialog(false),
  27783. extraClasses: ['tox-confirm-dialog'],
  27784. extraBehaviours: [],
  27785. extraStyles: {},
  27786. dialogEvents: [
  27787. run$1(formCancelEvent, () => closeDialog(false)),
  27788. run$1(formSubmitEvent, () => closeDialog(true))
  27789. ],
  27790. eventOrder: {}
  27791. }));
  27792. ModalDialog.show(confirmDialog);
  27793. const footerYesButton = memFooterYes.get(confirmDialog);
  27794. Focusing.focus(footerYesButton);
  27795. };
  27796. return { open };
  27797. };
  27798. const validateData = (data, validator) => getOrDie(asRaw('data', validator, data));
  27799. const isAlertOrConfirmDialog = target => closest(target, '.tox-alert-dialog') || closest(target, '.tox-confirm-dialog');
  27800. const inlineAdditionalBehaviours = (editor, isStickyToolbar, isToolbarLocationTop) => {
  27801. if (isStickyToolbar && isToolbarLocationTop) {
  27802. return [];
  27803. } else {
  27804. return [Docking.config({
  27805. contextual: {
  27806. lazyContext: () => Optional.some(box$1(SugarElement.fromDom(editor.getContentAreaContainer()))),
  27807. fadeInClass: 'tox-dialog-dock-fadein',
  27808. fadeOutClass: 'tox-dialog-dock-fadeout',
  27809. transitionClass: 'tox-dialog-dock-transition'
  27810. },
  27811. modes: ['top']
  27812. })];
  27813. }
  27814. };
  27815. const setup = extras => {
  27816. const editor = extras.editor;
  27817. const isStickyToolbar$1 = isStickyToolbar(editor);
  27818. const alertDialog = setup$2(extras.backstages.dialog);
  27819. const confirmDialog = setup$1(extras.backstages.dialog);
  27820. const open = (config, params, closeWindow) => {
  27821. if (params !== undefined && params.inline === 'toolbar') {
  27822. return openInlineDialog(config, extras.backstages.popup.shared.anchors.inlineDialog(), closeWindow, params.ariaAttrs);
  27823. } else if (params !== undefined && params.inline === 'cursor') {
  27824. return openInlineDialog(config, extras.backstages.popup.shared.anchors.cursor(), closeWindow, params.ariaAttrs);
  27825. } else {
  27826. return openModalDialog(config, closeWindow);
  27827. }
  27828. };
  27829. const openUrl = (config, closeWindow) => openModalUrlDialog(config, closeWindow);
  27830. const openModalUrlDialog = (config, closeWindow) => {
  27831. const factory = contents => {
  27832. const dialog = renderUrlDialog(contents, {
  27833. closeWindow: () => {
  27834. ModalDialog.hide(dialog.dialog);
  27835. closeWindow(dialog.instanceApi);
  27836. }
  27837. }, editor, extras.backstages.dialog);
  27838. ModalDialog.show(dialog.dialog);
  27839. return dialog.instanceApi;
  27840. };
  27841. return DialogManager.openUrl(factory, config);
  27842. };
  27843. const openModalDialog = (config, closeWindow) => {
  27844. const factory = (contents, internalInitialData, dataValidator) => {
  27845. const initialData = internalInitialData;
  27846. const dialogInit = {
  27847. dataValidator,
  27848. initialData,
  27849. internalDialog: contents
  27850. };
  27851. const dialog = renderDialog(dialogInit, {
  27852. redial: DialogManager.redial,
  27853. closeWindow: () => {
  27854. ModalDialog.hide(dialog.dialog);
  27855. closeWindow(dialog.instanceApi);
  27856. }
  27857. }, extras.backstages.dialog);
  27858. ModalDialog.show(dialog.dialog);
  27859. dialog.instanceApi.setData(initialData);
  27860. return dialog.instanceApi;
  27861. };
  27862. return DialogManager.open(factory, config);
  27863. };
  27864. const openInlineDialog = (config$1, anchor, closeWindow, ariaAttrs = false) => {
  27865. const factory = (contents, internalInitialData, dataValidator) => {
  27866. const initialData = validateData(internalInitialData, dataValidator);
  27867. const inlineDialog = value$2();
  27868. const isToolbarLocationTop = extras.backstages.popup.shared.header.isPositionedAtTop();
  27869. const dialogInit = {
  27870. dataValidator,
  27871. initialData,
  27872. internalDialog: contents
  27873. };
  27874. const refreshDocking = () => inlineDialog.on(dialog => {
  27875. InlineView.reposition(dialog);
  27876. Docking.refresh(dialog);
  27877. });
  27878. const dialogUi = renderInlineDialog(dialogInit, {
  27879. redial: DialogManager.redial,
  27880. closeWindow: () => {
  27881. inlineDialog.on(InlineView.hide);
  27882. editor.off('ResizeEditor', refreshDocking);
  27883. inlineDialog.clear();
  27884. closeWindow(dialogUi.instanceApi);
  27885. }
  27886. }, extras.backstages.popup, ariaAttrs);
  27887. const inlineDialogComp = build$1(InlineView.sketch({
  27888. lazySink: extras.backstages.popup.shared.getSink,
  27889. dom: {
  27890. tag: 'div',
  27891. classes: []
  27892. },
  27893. fireDismissalEventInstead: {},
  27894. ...isToolbarLocationTop ? {} : { fireRepositionEventInstead: {} },
  27895. inlineBehaviours: derive$1([
  27896. config('window-manager-inline-events', [run$1(dismissRequested(), (_comp, _se) => {
  27897. emit(dialogUi.dialog, formCancelEvent);
  27898. })]),
  27899. ...inlineAdditionalBehaviours(editor, isStickyToolbar$1, isToolbarLocationTop)
  27900. ]),
  27901. isExtraPart: (_comp, target) => isAlertOrConfirmDialog(target)
  27902. }));
  27903. inlineDialog.set(inlineDialogComp);
  27904. InlineView.showWithin(inlineDialogComp, premade(dialogUi.dialog), { anchor }, Optional.some(body()));
  27905. if (!isStickyToolbar$1 || !isToolbarLocationTop) {
  27906. Docking.refresh(inlineDialogComp);
  27907. editor.on('ResizeEditor', refreshDocking);
  27908. }
  27909. dialogUi.instanceApi.setData(initialData);
  27910. Keying.focusIn(dialogUi.dialog);
  27911. return dialogUi.instanceApi;
  27912. };
  27913. return DialogManager.open(factory, config$1);
  27914. };
  27915. const confirm = (message, callback) => {
  27916. confirmDialog.open(message, callback);
  27917. };
  27918. const alert = (message, callback) => {
  27919. alertDialog.open(message, callback);
  27920. };
  27921. const close = instanceApi => {
  27922. instanceApi.close();
  27923. };
  27924. return {
  27925. open,
  27926. openUrl,
  27927. alert,
  27928. close,
  27929. confirm
  27930. };
  27931. };
  27932. const registerOptions = editor => {
  27933. register$e(editor);
  27934. register$d(editor);
  27935. register(editor);
  27936. };
  27937. var Theme = () => {
  27938. global$a.add('silver', editor => {
  27939. registerOptions(editor);
  27940. const {dialogs, popups, renderUI} = setup$3(editor);
  27941. Autocompleter.register(editor, popups.backstage.shared);
  27942. const windowMgr = setup({
  27943. editor,
  27944. backstages: {
  27945. popup: popups.backstage,
  27946. dialog: dialogs.backstage
  27947. }
  27948. });
  27949. const getNotificationManagerImpl = () => NotificationManagerImpl(editor, { backstage: popups.backstage }, popups.getMothership());
  27950. return {
  27951. renderUI,
  27952. getWindowManagerImpl: constant$1(windowMgr),
  27953. getNotificationManagerImpl
  27954. };
  27955. });
  27956. };
  27957. Theme();
  27958. })();