theme.js 1.0 MB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353235423552356235723582359236023612362236323642365236623672368236923702371237223732374237523762377237823792380238123822383238423852386238723882389239023912392239323942395239623972398239924002401240224032404240524062407240824092410241124122413241424152416241724182419242024212422242324242425242624272428242924302431243224332434243524362437243824392440244124422443244424452446244724482449245024512452245324542455245624572458245924602461246224632464246524662467246824692470247124722473247424752476247724782479248024812482248324842485248624872488248924902491249224932494249524962497249824992500250125022503250425052506250725082509251025112512251325142515251625172518251925202521252225232524252525262527252825292530253125322533253425352536253725382539254025412542254325442545254625472548254925502551255225532554255525562557255825592560256125622563256425652566256725682569257025712572257325742575257625772578257925802581258225832584258525862587258825892590259125922593259425952596259725982599260026012602260326042605260626072608260926102611261226132614261526162617261826192620262126222623262426252626262726282629263026312632263326342635263626372638263926402641264226432644264526462647264826492650265126522653265426552656265726582659266026612662266326642665266626672668266926702671267226732674267526762677267826792680268126822683268426852686268726882689269026912692269326942695269626972698269927002701270227032704270527062707270827092710271127122713271427152716271727182719272027212722272327242725272627272728272927302731273227332734273527362737273827392740274127422743274427452746274727482749275027512752275327542755275627572758275927602761276227632764276527662767276827692770277127722773277427752776277727782779278027812782278327842785278627872788278927902791279227932794279527962797279827992800280128022803280428052806280728082809281028112812281328142815281628172818281928202821282228232824282528262827282828292830283128322833283428352836283728382839284028412842284328442845284628472848284928502851285228532854285528562857285828592860286128622863286428652866286728682869287028712872287328742875287628772878287928802881288228832884288528862887288828892890289128922893289428952896289728982899290029012902290329042905290629072908290929102911291229132914291529162917291829192920292129222923292429252926292729282929293029312932293329342935293629372938293929402941294229432944294529462947294829492950295129522953295429552956295729582959296029612962296329642965296629672968296929702971297229732974297529762977297829792980298129822983298429852986298729882989299029912992299329942995299629972998299930003001300230033004300530063007300830093010301130123013301430153016301730183019302030213022302330243025302630273028302930303031303230333034303530363037303830393040304130423043304430453046304730483049305030513052305330543055305630573058305930603061306230633064306530663067306830693070307130723073307430753076307730783079308030813082308330843085308630873088308930903091309230933094309530963097309830993100310131023103310431053106310731083109311031113112311331143115311631173118311931203121312231233124312531263127312831293130313131323133313431353136313731383139314031413142314331443145314631473148314931503151315231533154315531563157315831593160316131623163316431653166316731683169317031713172317331743175317631773178317931803181318231833184318531863187318831893190319131923193319431953196319731983199320032013202320332043205320632073208320932103211321232133214321532163217321832193220322132223223322432253226322732283229323032313232323332343235323632373238323932403241324232433244324532463247324832493250325132523253325432553256325732583259326032613262326332643265326632673268326932703271327232733274327532763277327832793280328132823283328432853286328732883289329032913292329332943295329632973298329933003301330233033304330533063307330833093310331133123313331433153316331733183319332033213322332333243325332633273328332933303331333233333334333533363337333833393340334133423343334433453346334733483349335033513352335333543355335633573358335933603361336233633364336533663367336833693370337133723373337433753376337733783379338033813382338333843385338633873388338933903391339233933394339533963397339833993400340134023403340434053406340734083409341034113412341334143415341634173418341934203421342234233424342534263427342834293430343134323433343434353436343734383439344034413442344334443445344634473448344934503451345234533454345534563457345834593460346134623463346434653466346734683469347034713472347334743475347634773478347934803481348234833484348534863487348834893490349134923493349434953496349734983499350035013502350335043505350635073508350935103511351235133514351535163517351835193520352135223523352435253526352735283529353035313532353335343535353635373538353935403541354235433544354535463547354835493550355135523553355435553556355735583559356035613562356335643565356635673568356935703571357235733574357535763577357835793580358135823583358435853586358735883589359035913592359335943595359635973598359936003601360236033604360536063607360836093610361136123613361436153616361736183619362036213622362336243625362636273628362936303631363236333634363536363637363836393640364136423643364436453646364736483649365036513652365336543655365636573658365936603661366236633664366536663667366836693670367136723673367436753676367736783679368036813682368336843685368636873688368936903691369236933694369536963697369836993700370137023703370437053706370737083709371037113712371337143715371637173718371937203721372237233724372537263727372837293730373137323733373437353736373737383739374037413742374337443745374637473748374937503751375237533754375537563757375837593760376137623763376437653766376737683769377037713772377337743775377637773778377937803781378237833784378537863787378837893790379137923793379437953796379737983799380038013802380338043805380638073808380938103811381238133814381538163817381838193820382138223823382438253826382738283829383038313832383338343835383638373838383938403841384238433844384538463847384838493850385138523853385438553856385738583859386038613862386338643865386638673868386938703871387238733874387538763877387838793880388138823883388438853886388738883889389038913892389338943895389638973898389939003901390239033904390539063907390839093910391139123913391439153916391739183919392039213922392339243925392639273928392939303931393239333934393539363937393839393940394139423943394439453946394739483949395039513952395339543955395639573958395939603961396239633964396539663967396839693970397139723973397439753976397739783979398039813982398339843985398639873988398939903991399239933994399539963997399839994000400140024003400440054006400740084009401040114012401340144015401640174018401940204021402240234024402540264027402840294030403140324033403440354036403740384039404040414042404340444045404640474048404940504051405240534054405540564057405840594060406140624063406440654066406740684069407040714072407340744075407640774078407940804081408240834084408540864087408840894090409140924093409440954096409740984099410041014102410341044105410641074108410941104111411241134114411541164117411841194120412141224123412441254126412741284129413041314132413341344135413641374138413941404141414241434144414541464147414841494150415141524153415441554156415741584159416041614162416341644165416641674168416941704171417241734174417541764177417841794180418141824183418441854186418741884189419041914192419341944195419641974198419942004201420242034204420542064207420842094210421142124213421442154216421742184219422042214222422342244225422642274228422942304231423242334234423542364237423842394240424142424243424442454246424742484249425042514252425342544255425642574258425942604261426242634264426542664267426842694270427142724273427442754276427742784279428042814282428342844285428642874288428942904291429242934294429542964297429842994300430143024303430443054306430743084309431043114312431343144315431643174318431943204321432243234324432543264327432843294330433143324333433443354336433743384339434043414342434343444345434643474348434943504351435243534354435543564357435843594360436143624363436443654366436743684369437043714372437343744375437643774378437943804381438243834384438543864387438843894390439143924393439443954396439743984399440044014402440344044405440644074408440944104411441244134414441544164417441844194420442144224423442444254426442744284429443044314432443344344435443644374438443944404441444244434444444544464447444844494450445144524453445444554456445744584459446044614462446344644465446644674468446944704471447244734474447544764477447844794480448144824483448444854486448744884489449044914492449344944495449644974498449945004501450245034504450545064507450845094510451145124513451445154516451745184519452045214522452345244525452645274528452945304531453245334534453545364537453845394540454145424543454445454546454745484549455045514552455345544555455645574558455945604561456245634564456545664567456845694570457145724573457445754576457745784579458045814582458345844585458645874588458945904591459245934594459545964597459845994600460146024603460446054606460746084609461046114612461346144615461646174618461946204621462246234624462546264627462846294630463146324633463446354636463746384639464046414642464346444645464646474648464946504651465246534654465546564657465846594660466146624663466446654666466746684669467046714672467346744675467646774678467946804681468246834684468546864687468846894690469146924693469446954696469746984699470047014702470347044705470647074708470947104711471247134714471547164717471847194720472147224723472447254726472747284729473047314732473347344735473647374738473947404741474247434744474547464747474847494750475147524753475447554756475747584759476047614762476347644765476647674768476947704771477247734774477547764777477847794780478147824783478447854786478747884789479047914792479347944795479647974798479948004801480248034804480548064807480848094810481148124813481448154816481748184819482048214822482348244825482648274828482948304831483248334834483548364837483848394840484148424843484448454846484748484849485048514852485348544855485648574858485948604861486248634864486548664867486848694870487148724873487448754876487748784879488048814882488348844885488648874888488948904891489248934894489548964897489848994900490149024903490449054906490749084909491049114912491349144915491649174918491949204921492249234924492549264927492849294930493149324933493449354936493749384939494049414942494349444945494649474948494949504951495249534954495549564957495849594960496149624963496449654966496749684969497049714972497349744975497649774978497949804981498249834984498549864987498849894990499149924993499449954996499749984999500050015002500350045005500650075008500950105011501250135014501550165017501850195020502150225023502450255026502750285029503050315032503350345035503650375038503950405041504250435044504550465047504850495050505150525053505450555056505750585059506050615062506350645065506650675068506950705071507250735074507550765077507850795080508150825083508450855086508750885089509050915092509350945095509650975098509951005101510251035104510551065107510851095110511151125113511451155116511751185119512051215122512351245125512651275128512951305131513251335134513551365137513851395140514151425143514451455146514751485149515051515152515351545155515651575158515951605161516251635164516551665167516851695170517151725173517451755176517751785179518051815182518351845185518651875188518951905191519251935194519551965197519851995200520152025203520452055206520752085209521052115212521352145215521652175218521952205221522252235224522552265227522852295230523152325233523452355236523752385239524052415242524352445245524652475248524952505251525252535254525552565257525852595260526152625263526452655266526752685269527052715272527352745275527652775278527952805281528252835284528552865287528852895290529152925293529452955296529752985299530053015302530353045305530653075308530953105311531253135314531553165317531853195320532153225323532453255326532753285329533053315332533353345335533653375338533953405341534253435344534553465347534853495350535153525353535453555356535753585359536053615362536353645365536653675368536953705371537253735374537553765377537853795380538153825383538453855386538753885389539053915392539353945395539653975398539954005401540254035404540554065407540854095410541154125413541454155416541754185419542054215422542354245425542654275428542954305431543254335434543554365437543854395440544154425443544454455446544754485449545054515452545354545455545654575458545954605461546254635464546554665467546854695470547154725473547454755476547754785479548054815482548354845485548654875488548954905491549254935494549554965497549854995500550155025503550455055506550755085509551055115512551355145515551655175518551955205521552255235524552555265527552855295530553155325533553455355536553755385539554055415542554355445545554655475548554955505551555255535554555555565557555855595560556155625563556455655566556755685569557055715572557355745575557655775578557955805581558255835584558555865587558855895590559155925593559455955596559755985599560056015602560356045605560656075608560956105611561256135614561556165617561856195620562156225623562456255626562756285629563056315632563356345635563656375638563956405641564256435644564556465647564856495650565156525653565456555656565756585659566056615662566356645665566656675668566956705671567256735674567556765677567856795680568156825683568456855686568756885689569056915692569356945695569656975698569957005701570257035704570557065707570857095710571157125713571457155716571757185719572057215722572357245725572657275728572957305731573257335734573557365737573857395740574157425743574457455746574757485749575057515752575357545755575657575758575957605761576257635764576557665767576857695770577157725773577457755776577757785779578057815782578357845785578657875788578957905791579257935794579557965797579857995800580158025803580458055806580758085809581058115812581358145815581658175818581958205821582258235824582558265827582858295830583158325833583458355836583758385839584058415842584358445845584658475848584958505851585258535854585558565857585858595860586158625863586458655866586758685869587058715872587358745875587658775878587958805881588258835884588558865887588858895890589158925893589458955896589758985899590059015902590359045905590659075908590959105911591259135914591559165917591859195920592159225923592459255926592759285929593059315932593359345935593659375938593959405941594259435944594559465947594859495950595159525953595459555956595759585959596059615962596359645965596659675968596959705971597259735974597559765977597859795980598159825983598459855986598759885989599059915992599359945995599659975998599960006001600260036004600560066007600860096010601160126013601460156016601760186019602060216022602360246025602660276028602960306031603260336034603560366037603860396040604160426043604460456046604760486049605060516052605360546055605660576058605960606061606260636064606560666067606860696070607160726073607460756076607760786079608060816082608360846085608660876088608960906091609260936094609560966097609860996100610161026103610461056106610761086109611061116112611361146115611661176118611961206121612261236124612561266127612861296130613161326133613461356136613761386139614061416142614361446145614661476148614961506151615261536154615561566157615861596160616161626163616461656166616761686169617061716172617361746175617661776178617961806181618261836184618561866187618861896190619161926193619461956196619761986199620062016202620362046205620662076208620962106211621262136214621562166217621862196220622162226223622462256226622762286229623062316232623362346235623662376238623962406241624262436244624562466247624862496250625162526253625462556256625762586259626062616262626362646265626662676268626962706271627262736274627562766277627862796280628162826283628462856286628762886289629062916292629362946295629662976298629963006301630263036304630563066307630863096310631163126313631463156316631763186319632063216322632363246325632663276328632963306331633263336334633563366337633863396340634163426343634463456346634763486349635063516352635363546355635663576358635963606361636263636364636563666367636863696370637163726373637463756376637763786379638063816382638363846385638663876388638963906391639263936394639563966397639863996400640164026403640464056406640764086409641064116412641364146415641664176418641964206421642264236424642564266427642864296430643164326433643464356436643764386439644064416442644364446445644664476448644964506451645264536454645564566457645864596460646164626463646464656466646764686469647064716472647364746475647664776478647964806481648264836484648564866487648864896490649164926493649464956496649764986499650065016502650365046505650665076508650965106511651265136514651565166517651865196520652165226523652465256526652765286529653065316532653365346535653665376538653965406541654265436544654565466547654865496550655165526553655465556556655765586559656065616562656365646565656665676568656965706571657265736574657565766577657865796580658165826583658465856586658765886589659065916592659365946595659665976598659966006601660266036604660566066607660866096610661166126613661466156616661766186619662066216622662366246625662666276628662966306631663266336634663566366637663866396640664166426643664466456646664766486649665066516652665366546655665666576658665966606661666266636664666566666667666866696670667166726673667466756676667766786679668066816682668366846685668666876688668966906691669266936694669566966697669866996700670167026703670467056706670767086709671067116712671367146715671667176718671967206721672267236724672567266727672867296730673167326733673467356736673767386739674067416742674367446745674667476748674967506751675267536754675567566757675867596760676167626763676467656766676767686769677067716772677367746775677667776778677967806781678267836784678567866787678867896790679167926793679467956796679767986799680068016802680368046805680668076808680968106811681268136814681568166817681868196820682168226823682468256826682768286829683068316832683368346835683668376838683968406841684268436844684568466847684868496850685168526853685468556856685768586859686068616862686368646865686668676868686968706871687268736874687568766877687868796880688168826883688468856886688768886889689068916892689368946895689668976898689969006901690269036904690569066907690869096910691169126913691469156916691769186919692069216922692369246925692669276928692969306931693269336934693569366937693869396940694169426943694469456946694769486949695069516952695369546955695669576958695969606961696269636964696569666967696869696970697169726973697469756976697769786979698069816982698369846985698669876988698969906991699269936994699569966997699869997000700170027003700470057006700770087009701070117012701370147015701670177018701970207021702270237024702570267027702870297030703170327033703470357036703770387039704070417042704370447045704670477048704970507051705270537054705570567057705870597060706170627063706470657066706770687069707070717072707370747075707670777078707970807081708270837084708570867087708870897090709170927093709470957096709770987099710071017102710371047105710671077108710971107111711271137114711571167117711871197120712171227123712471257126712771287129713071317132713371347135713671377138713971407141714271437144714571467147714871497150715171527153715471557156715771587159716071617162716371647165716671677168716971707171717271737174717571767177717871797180718171827183718471857186718771887189719071917192719371947195719671977198719972007201720272037204720572067207720872097210721172127213721472157216721772187219722072217222722372247225722672277228722972307231723272337234723572367237723872397240724172427243724472457246724772487249725072517252725372547255725672577258725972607261726272637264726572667267726872697270727172727273727472757276727772787279728072817282728372847285728672877288728972907291729272937294729572967297729872997300730173027303730473057306730773087309731073117312731373147315731673177318731973207321732273237324732573267327732873297330733173327333733473357336733773387339734073417342734373447345734673477348734973507351735273537354735573567357735873597360736173627363736473657366736773687369737073717372737373747375737673777378737973807381738273837384738573867387738873897390739173927393739473957396739773987399740074017402740374047405740674077408740974107411741274137414741574167417741874197420742174227423742474257426742774287429743074317432743374347435743674377438743974407441744274437444744574467447744874497450745174527453745474557456745774587459746074617462746374647465746674677468746974707471747274737474747574767477747874797480748174827483748474857486748774887489749074917492749374947495749674977498749975007501750275037504750575067507750875097510751175127513751475157516751775187519752075217522752375247525752675277528752975307531753275337534753575367537753875397540754175427543754475457546754775487549755075517552755375547555755675577558755975607561756275637564756575667567756875697570757175727573757475757576757775787579758075817582758375847585758675877588758975907591759275937594759575967597759875997600760176027603760476057606760776087609761076117612761376147615761676177618761976207621762276237624762576267627762876297630763176327633763476357636763776387639764076417642764376447645764676477648764976507651765276537654765576567657765876597660766176627663766476657666766776687669767076717672767376747675767676777678767976807681768276837684768576867687768876897690769176927693769476957696769776987699770077017702770377047705770677077708770977107711771277137714771577167717771877197720772177227723772477257726772777287729773077317732773377347735773677377738773977407741774277437744774577467747774877497750775177527753775477557756775777587759776077617762776377647765776677677768776977707771777277737774777577767777777877797780778177827783778477857786778777887789779077917792779377947795779677977798779978007801780278037804780578067807780878097810781178127813781478157816781778187819782078217822782378247825782678277828782978307831783278337834783578367837783878397840784178427843784478457846784778487849785078517852785378547855785678577858785978607861786278637864786578667867786878697870787178727873787478757876787778787879788078817882788378847885788678877888788978907891789278937894789578967897789878997900790179027903790479057906790779087909791079117912791379147915791679177918791979207921792279237924792579267927792879297930793179327933793479357936793779387939794079417942794379447945794679477948794979507951795279537954795579567957795879597960796179627963796479657966796779687969797079717972797379747975797679777978797979807981798279837984798579867987798879897990799179927993799479957996799779987999800080018002800380048005800680078008800980108011801280138014801580168017801880198020802180228023802480258026802780288029803080318032803380348035803680378038803980408041804280438044804580468047804880498050805180528053805480558056805780588059806080618062806380648065806680678068806980708071807280738074807580768077807880798080808180828083808480858086808780888089809080918092809380948095809680978098809981008101810281038104810581068107810881098110811181128113811481158116811781188119812081218122812381248125812681278128812981308131813281338134813581368137813881398140814181428143814481458146814781488149815081518152815381548155815681578158815981608161816281638164816581668167816881698170817181728173817481758176817781788179818081818182818381848185818681878188818981908191819281938194819581968197819881998200820182028203820482058206820782088209821082118212821382148215821682178218821982208221822282238224822582268227822882298230823182328233823482358236823782388239824082418242824382448245824682478248824982508251825282538254825582568257825882598260826182628263826482658266826782688269827082718272827382748275827682778278827982808281828282838284828582868287828882898290829182928293829482958296829782988299830083018302830383048305830683078308830983108311831283138314831583168317831883198320832183228323832483258326832783288329833083318332833383348335833683378338833983408341834283438344834583468347834883498350835183528353835483558356835783588359836083618362836383648365836683678368836983708371837283738374837583768377837883798380838183828383838483858386838783888389839083918392839383948395839683978398839984008401840284038404840584068407840884098410841184128413841484158416841784188419842084218422842384248425842684278428842984308431843284338434843584368437843884398440844184428443844484458446844784488449845084518452845384548455845684578458845984608461846284638464846584668467846884698470847184728473847484758476847784788479848084818482848384848485848684878488848984908491849284938494849584968497849884998500850185028503850485058506850785088509851085118512851385148515851685178518851985208521852285238524852585268527852885298530853185328533853485358536853785388539854085418542854385448545854685478548854985508551855285538554855585568557855885598560856185628563856485658566856785688569857085718572857385748575857685778578857985808581858285838584858585868587858885898590859185928593859485958596859785988599860086018602860386048605860686078608860986108611861286138614861586168617861886198620862186228623862486258626862786288629863086318632863386348635863686378638863986408641864286438644864586468647864886498650865186528653865486558656865786588659866086618662866386648665866686678668866986708671867286738674867586768677867886798680868186828683868486858686868786888689869086918692869386948695869686978698869987008701870287038704870587068707870887098710871187128713871487158716871787188719872087218722872387248725872687278728872987308731873287338734873587368737873887398740874187428743874487458746874787488749875087518752875387548755875687578758875987608761876287638764876587668767876887698770877187728773877487758776877787788779878087818782878387848785878687878788878987908791879287938794879587968797879887998800880188028803880488058806880788088809881088118812881388148815881688178818881988208821882288238824882588268827882888298830883188328833883488358836883788388839884088418842884388448845884688478848884988508851885288538854885588568857885888598860886188628863886488658866886788688869887088718872887388748875887688778878887988808881888288838884888588868887888888898890889188928893889488958896889788988899890089018902890389048905890689078908890989108911891289138914891589168917891889198920892189228923892489258926892789288929893089318932893389348935893689378938893989408941894289438944894589468947894889498950895189528953895489558956895789588959896089618962896389648965896689678968896989708971897289738974897589768977897889798980898189828983898489858986898789888989899089918992899389948995899689978998899990009001900290039004900590069007900890099010901190129013901490159016901790189019902090219022902390249025902690279028902990309031903290339034903590369037903890399040904190429043904490459046904790489049905090519052905390549055905690579058905990609061906290639064906590669067906890699070907190729073907490759076907790789079908090819082908390849085908690879088908990909091909290939094909590969097909890999100910191029103910491059106910791089109911091119112911391149115911691179118911991209121912291239124912591269127912891299130913191329133913491359136913791389139914091419142914391449145914691479148914991509151915291539154915591569157915891599160916191629163916491659166916791689169917091719172917391749175917691779178917991809181918291839184918591869187918891899190919191929193919491959196919791989199920092019202920392049205920692079208920992109211921292139214921592169217921892199220922192229223922492259226922792289229923092319232923392349235923692379238923992409241924292439244924592469247924892499250925192529253925492559256925792589259926092619262926392649265926692679268926992709271927292739274927592769277927892799280928192829283928492859286928792889289929092919292929392949295929692979298929993009301930293039304930593069307930893099310931193129313931493159316931793189319932093219322932393249325932693279328932993309331933293339334933593369337933893399340934193429343934493459346934793489349935093519352935393549355935693579358935993609361936293639364936593669367936893699370937193729373937493759376937793789379938093819382938393849385938693879388938993909391939293939394939593969397939893999400940194029403940494059406940794089409941094119412941394149415941694179418941994209421942294239424942594269427942894299430943194329433943494359436943794389439944094419442944394449445944694479448944994509451945294539454945594569457945894599460946194629463946494659466946794689469947094719472947394749475947694779478947994809481948294839484948594869487948894899490949194929493949494959496949794989499950095019502950395049505950695079508950995109511951295139514951595169517951895199520952195229523952495259526952795289529953095319532953395349535953695379538953995409541954295439544954595469547954895499550955195529553955495559556955795589559956095619562956395649565956695679568956995709571957295739574957595769577957895799580958195829583958495859586958795889589959095919592959395949595959695979598959996009601960296039604960596069607960896099610961196129613961496159616961796189619962096219622962396249625962696279628962996309631963296339634963596369637963896399640964196429643964496459646964796489649965096519652965396549655965696579658965996609661966296639664966596669667966896699670967196729673967496759676967796789679968096819682968396849685968696879688968996909691969296939694969596969697969896999700970197029703970497059706970797089709971097119712971397149715971697179718971997209721972297239724972597269727972897299730973197329733973497359736973797389739974097419742974397449745974697479748974997509751975297539754975597569757975897599760976197629763976497659766976797689769977097719772977397749775977697779778977997809781978297839784978597869787978897899790979197929793979497959796979797989799980098019802980398049805980698079808980998109811981298139814981598169817981898199820982198229823982498259826982798289829983098319832983398349835983698379838983998409841984298439844984598469847984898499850985198529853985498559856985798589859986098619862986398649865986698679868986998709871987298739874987598769877987898799880988198829883988498859886988798889889989098919892989398949895989698979898989999009901990299039904990599069907990899099910991199129913991499159916991799189919992099219922992399249925992699279928992999309931993299339934993599369937993899399940994199429943994499459946994799489949995099519952995399549955995699579958995999609961996299639964996599669967996899699970997199729973997499759976997799789979998099819982998399849985998699879988998999909991999299939994999599969997999899991000010001100021000310004100051000610007100081000910010100111001210013100141001510016100171001810019100201002110022100231002410025100261002710028100291003010031100321003310034100351003610037100381003910040100411004210043100441004510046100471004810049100501005110052100531005410055100561005710058100591006010061100621006310064100651006610067100681006910070100711007210073100741007510076100771007810079100801008110082100831008410085100861008710088100891009010091100921009310094100951009610097100981009910100101011010210103101041010510106101071010810109101101011110112101131011410115101161011710118101191012010121101221012310124101251012610127101281012910130101311013210133101341013510136101371013810139101401014110142101431014410145101461014710148101491015010151101521015310154101551015610157101581015910160101611016210163101641016510166101671016810169101701017110172101731017410175101761017710178101791018010181101821018310184101851018610187101881018910190101911019210193101941019510196101971019810199102001020110202102031020410205102061020710208102091021010211102121021310214102151021610217102181021910220102211022210223102241022510226102271022810229102301023110232102331023410235102361023710238102391024010241102421024310244102451024610247102481024910250102511025210253102541025510256102571025810259102601026110262102631026410265102661026710268102691027010271102721027310274102751027610277102781027910280102811028210283102841028510286102871028810289102901029110292102931029410295102961029710298102991030010301103021030310304103051030610307103081030910310103111031210313103141031510316103171031810319103201032110322103231032410325103261032710328103291033010331103321033310334103351033610337103381033910340103411034210343103441034510346103471034810349103501035110352103531035410355103561035710358103591036010361103621036310364103651036610367103681036910370103711037210373103741037510376103771037810379103801038110382103831038410385103861038710388103891039010391103921039310394103951039610397103981039910400104011040210403104041040510406104071040810409104101041110412104131041410415104161041710418104191042010421104221042310424104251042610427104281042910430104311043210433104341043510436104371043810439104401044110442104431044410445104461044710448104491045010451104521045310454104551045610457104581045910460104611046210463104641046510466104671046810469104701047110472104731047410475104761047710478104791048010481104821048310484104851048610487104881048910490104911049210493104941049510496104971049810499105001050110502105031050410505105061050710508105091051010511105121051310514105151051610517105181051910520105211052210523105241052510526105271052810529105301053110532105331053410535105361053710538105391054010541105421054310544105451054610547105481054910550105511055210553105541055510556105571055810559105601056110562105631056410565105661056710568105691057010571105721057310574105751057610577105781057910580105811058210583105841058510586105871058810589105901059110592105931059410595105961059710598105991060010601106021060310604106051060610607106081060910610106111061210613106141061510616106171061810619106201062110622106231062410625106261062710628106291063010631106321063310634106351063610637106381063910640106411064210643106441064510646106471064810649106501065110652106531065410655106561065710658106591066010661106621066310664106651066610667106681066910670106711067210673106741067510676106771067810679106801068110682106831068410685106861068710688106891069010691106921069310694106951069610697106981069910700107011070210703107041070510706107071070810709107101071110712107131071410715107161071710718107191072010721107221072310724107251072610727107281072910730107311073210733107341073510736107371073810739107401074110742107431074410745107461074710748107491075010751107521075310754107551075610757107581075910760107611076210763107641076510766107671076810769107701077110772107731077410775107761077710778107791078010781107821078310784107851078610787107881078910790107911079210793107941079510796107971079810799108001080110802108031080410805108061080710808108091081010811108121081310814108151081610817108181081910820108211082210823108241082510826108271082810829108301083110832108331083410835108361083710838108391084010841108421084310844108451084610847108481084910850108511085210853108541085510856108571085810859108601086110862108631086410865108661086710868108691087010871108721087310874108751087610877108781087910880108811088210883108841088510886108871088810889108901089110892108931089410895108961089710898108991090010901109021090310904109051090610907109081090910910109111091210913109141091510916109171091810919109201092110922109231092410925109261092710928109291093010931109321093310934109351093610937109381093910940109411094210943109441094510946109471094810949109501095110952109531095410955109561095710958109591096010961109621096310964109651096610967109681096910970109711097210973109741097510976109771097810979109801098110982109831098410985109861098710988109891099010991109921099310994109951099610997109981099911000110011100211003110041100511006110071100811009110101101111012110131101411015110161101711018110191102011021110221102311024110251102611027110281102911030110311103211033110341103511036110371103811039110401104111042110431104411045110461104711048110491105011051110521105311054110551105611057110581105911060110611106211063110641106511066110671106811069110701107111072110731107411075110761107711078110791108011081110821108311084110851108611087110881108911090110911109211093110941109511096110971109811099111001110111102111031110411105111061110711108111091111011111111121111311114111151111611117111181111911120111211112211123111241112511126111271112811129111301113111132111331113411135111361113711138111391114011141111421114311144111451114611147111481114911150111511115211153111541115511156111571115811159111601116111162111631116411165111661116711168111691117011171111721117311174111751117611177111781117911180111811118211183111841118511186111871118811189111901119111192111931119411195111961119711198111991120011201112021120311204112051120611207112081120911210112111121211213112141121511216112171121811219112201122111222112231122411225112261122711228112291123011231112321123311234112351123611237112381123911240112411124211243112441124511246112471124811249112501125111252112531125411255112561125711258112591126011261112621126311264112651126611267112681126911270112711127211273112741127511276112771127811279112801128111282112831128411285112861128711288112891129011291112921129311294112951129611297112981129911300113011130211303113041130511306113071130811309113101131111312113131131411315113161131711318113191132011321113221132311324113251132611327113281132911330113311133211333113341133511336113371133811339113401134111342113431134411345113461134711348113491135011351113521135311354113551135611357113581135911360113611136211363113641136511366113671136811369113701137111372113731137411375113761137711378113791138011381113821138311384113851138611387113881138911390113911139211393113941139511396113971139811399114001140111402114031140411405114061140711408114091141011411114121141311414114151141611417114181141911420114211142211423114241142511426114271142811429114301143111432114331143411435114361143711438114391144011441114421144311444114451144611447114481144911450114511145211453114541145511456114571145811459114601146111462114631146411465114661146711468114691147011471114721147311474114751147611477114781147911480114811148211483114841148511486114871148811489114901149111492114931149411495114961149711498114991150011501115021150311504115051150611507115081150911510115111151211513115141151511516115171151811519115201152111522115231152411525115261152711528115291153011531115321153311534115351153611537115381153911540115411154211543115441154511546115471154811549115501155111552115531155411555115561155711558115591156011561115621156311564115651156611567115681156911570115711157211573115741157511576115771157811579115801158111582115831158411585115861158711588115891159011591115921159311594115951159611597115981159911600116011160211603116041160511606116071160811609116101161111612116131161411615116161161711618116191162011621116221162311624116251162611627116281162911630116311163211633116341163511636116371163811639116401164111642116431164411645116461164711648116491165011651116521165311654116551165611657116581165911660116611166211663116641166511666116671166811669116701167111672116731167411675116761167711678116791168011681116821168311684116851168611687116881168911690116911169211693116941169511696116971169811699117001170111702117031170411705117061170711708117091171011711117121171311714117151171611717117181171911720117211172211723117241172511726117271172811729117301173111732117331173411735117361173711738117391174011741117421174311744117451174611747117481174911750117511175211753117541175511756117571175811759117601176111762117631176411765117661176711768117691177011771117721177311774117751177611777117781177911780117811178211783117841178511786117871178811789117901179111792117931179411795117961179711798117991180011801118021180311804118051180611807118081180911810118111181211813118141181511816118171181811819118201182111822118231182411825118261182711828118291183011831118321183311834118351183611837118381183911840118411184211843118441184511846118471184811849118501185111852118531185411855118561185711858118591186011861118621186311864118651186611867118681186911870118711187211873118741187511876118771187811879118801188111882118831188411885118861188711888118891189011891118921189311894118951189611897118981189911900119011190211903119041190511906119071190811909119101191111912119131191411915119161191711918119191192011921119221192311924119251192611927119281192911930119311193211933119341193511936119371193811939119401194111942119431194411945119461194711948119491195011951119521195311954119551195611957119581195911960119611196211963119641196511966119671196811969119701197111972119731197411975119761197711978119791198011981119821198311984119851198611987119881198911990119911199211993119941199511996119971199811999120001200112002120031200412005120061200712008120091201012011120121201312014120151201612017120181201912020120211202212023120241202512026120271202812029120301203112032120331203412035120361203712038120391204012041120421204312044120451204612047120481204912050120511205212053120541205512056120571205812059120601206112062120631206412065120661206712068120691207012071120721207312074120751207612077120781207912080120811208212083120841208512086120871208812089120901209112092120931209412095120961209712098120991210012101121021210312104121051210612107121081210912110121111211212113121141211512116121171211812119121201212112122121231212412125121261212712128121291213012131121321213312134121351213612137121381213912140121411214212143121441214512146121471214812149121501215112152121531215412155121561215712158121591216012161121621216312164121651216612167121681216912170121711217212173121741217512176121771217812179121801218112182121831218412185121861218712188121891219012191121921219312194121951219612197121981219912200122011220212203122041220512206122071220812209122101221112212122131221412215122161221712218122191222012221122221222312224122251222612227122281222912230122311223212233122341223512236122371223812239122401224112242122431224412245122461224712248122491225012251122521225312254122551225612257122581225912260122611226212263122641226512266122671226812269122701227112272122731227412275122761227712278122791228012281122821228312284122851228612287122881228912290122911229212293122941229512296122971229812299123001230112302123031230412305123061230712308123091231012311123121231312314123151231612317123181231912320123211232212323123241232512326123271232812329123301233112332123331233412335123361233712338123391234012341123421234312344123451234612347123481234912350123511235212353123541235512356123571235812359123601236112362123631236412365123661236712368123691237012371123721237312374123751237612377123781237912380123811238212383123841238512386123871238812389123901239112392123931239412395123961239712398123991240012401124021240312404124051240612407124081240912410124111241212413124141241512416124171241812419124201242112422124231242412425124261242712428124291243012431124321243312434124351243612437124381243912440124411244212443124441244512446124471244812449124501245112452124531245412455124561245712458124591246012461124621246312464124651246612467124681246912470124711247212473124741247512476124771247812479124801248112482124831248412485124861248712488124891249012491124921249312494124951249612497124981249912500125011250212503125041250512506125071250812509125101251112512125131251412515125161251712518125191252012521125221252312524125251252612527125281252912530125311253212533125341253512536125371253812539125401254112542125431254412545125461254712548125491255012551125521255312554125551255612557125581255912560125611256212563125641256512566125671256812569125701257112572125731257412575125761257712578125791258012581125821258312584125851258612587125881258912590125911259212593125941259512596125971259812599126001260112602126031260412605126061260712608126091261012611126121261312614126151261612617126181261912620126211262212623126241262512626126271262812629126301263112632126331263412635126361263712638126391264012641126421264312644126451264612647126481264912650126511265212653126541265512656126571265812659126601266112662126631266412665126661266712668126691267012671126721267312674126751267612677126781267912680126811268212683126841268512686126871268812689126901269112692126931269412695126961269712698126991270012701127021270312704127051270612707127081270912710127111271212713127141271512716127171271812719127201272112722127231272412725127261272712728127291273012731127321273312734127351273612737127381273912740127411274212743127441274512746127471274812749127501275112752127531275412755127561275712758127591276012761127621276312764127651276612767127681276912770127711277212773127741277512776127771277812779127801278112782127831278412785127861278712788127891279012791127921279312794127951279612797127981279912800128011280212803128041280512806128071280812809128101281112812128131281412815128161281712818128191282012821128221282312824128251282612827128281282912830128311283212833128341283512836128371283812839128401284112842128431284412845128461284712848128491285012851128521285312854128551285612857128581285912860128611286212863128641286512866128671286812869128701287112872128731287412875128761287712878128791288012881128821288312884128851288612887128881288912890128911289212893128941289512896128971289812899129001290112902129031290412905129061290712908129091291012911129121291312914129151291612917129181291912920129211292212923129241292512926129271292812929129301293112932129331293412935129361293712938129391294012941129421294312944129451294612947129481294912950129511295212953129541295512956129571295812959129601296112962129631296412965129661296712968129691297012971129721297312974129751297612977129781297912980129811298212983129841298512986129871298812989129901299112992129931299412995129961299712998129991300013001130021300313004130051300613007130081300913010130111301213013130141301513016130171301813019130201302113022130231302413025130261302713028130291303013031130321303313034130351303613037130381303913040130411304213043130441304513046130471304813049130501305113052130531305413055130561305713058130591306013061130621306313064130651306613067130681306913070130711307213073130741307513076130771307813079130801308113082130831308413085130861308713088130891309013091130921309313094130951309613097130981309913100131011310213103131041310513106131071310813109131101311113112131131311413115131161311713118131191312013121131221312313124131251312613127131281312913130131311313213133131341313513136131371313813139131401314113142131431314413145131461314713148131491315013151131521315313154131551315613157131581315913160131611316213163131641316513166131671316813169131701317113172131731317413175131761317713178131791318013181131821318313184131851318613187131881318913190131911319213193131941319513196131971319813199132001320113202132031320413205132061320713208132091321013211132121321313214132151321613217132181321913220132211322213223132241322513226132271322813229132301323113232132331323413235132361323713238132391324013241132421324313244132451324613247132481324913250132511325213253132541325513256132571325813259132601326113262132631326413265132661326713268132691327013271132721327313274132751327613277132781327913280132811328213283132841328513286132871328813289132901329113292132931329413295132961329713298132991330013301133021330313304133051330613307133081330913310133111331213313133141331513316133171331813319133201332113322133231332413325133261332713328133291333013331133321333313334133351333613337133381333913340133411334213343133441334513346133471334813349133501335113352133531335413355133561335713358133591336013361133621336313364133651336613367133681336913370133711337213373133741337513376133771337813379133801338113382133831338413385133861338713388133891339013391133921339313394133951339613397133981339913400134011340213403134041340513406134071340813409134101341113412134131341413415134161341713418134191342013421134221342313424134251342613427134281342913430134311343213433134341343513436134371343813439134401344113442134431344413445134461344713448134491345013451134521345313454134551345613457134581345913460134611346213463134641346513466134671346813469134701347113472134731347413475134761347713478134791348013481134821348313484134851348613487134881348913490134911349213493134941349513496134971349813499135001350113502135031350413505135061350713508135091351013511135121351313514135151351613517135181351913520135211352213523135241352513526135271352813529135301353113532135331353413535135361353713538135391354013541135421354313544135451354613547135481354913550135511355213553135541355513556135571355813559135601356113562135631356413565135661356713568135691357013571135721357313574135751357613577135781357913580135811358213583135841358513586135871358813589135901359113592135931359413595135961359713598135991360013601136021360313604136051360613607136081360913610136111361213613136141361513616136171361813619136201362113622136231362413625136261362713628136291363013631136321363313634136351363613637136381363913640136411364213643136441364513646136471364813649136501365113652136531365413655136561365713658136591366013661136621366313664136651366613667136681366913670136711367213673136741367513676136771367813679136801368113682136831368413685136861368713688136891369013691136921369313694136951369613697136981369913700137011370213703137041370513706137071370813709137101371113712137131371413715137161371713718137191372013721137221372313724137251372613727137281372913730137311373213733137341373513736137371373813739137401374113742137431374413745137461374713748137491375013751137521375313754137551375613757137581375913760137611376213763137641376513766137671376813769137701377113772137731377413775137761377713778137791378013781137821378313784137851378613787137881378913790137911379213793137941379513796137971379813799138001380113802138031380413805138061380713808138091381013811138121381313814138151381613817138181381913820138211382213823138241382513826138271382813829138301383113832138331383413835138361383713838138391384013841138421384313844138451384613847138481384913850138511385213853138541385513856138571385813859138601386113862138631386413865138661386713868138691387013871138721387313874138751387613877138781387913880138811388213883138841388513886138871388813889138901389113892138931389413895138961389713898138991390013901139021390313904139051390613907139081390913910139111391213913139141391513916139171391813919139201392113922139231392413925139261392713928139291393013931139321393313934139351393613937139381393913940139411394213943139441394513946139471394813949139501395113952139531395413955139561395713958139591396013961139621396313964139651396613967139681396913970139711397213973139741397513976139771397813979139801398113982139831398413985139861398713988139891399013991139921399313994139951399613997139981399914000140011400214003140041400514006140071400814009140101401114012140131401414015140161401714018140191402014021140221402314024140251402614027140281402914030140311403214033140341403514036140371403814039140401404114042140431404414045140461404714048140491405014051140521405314054140551405614057140581405914060140611406214063140641406514066140671406814069140701407114072140731407414075140761407714078140791408014081140821408314084140851408614087140881408914090140911409214093140941409514096140971409814099141001410114102141031410414105141061410714108141091411014111141121411314114141151411614117141181411914120141211412214123141241412514126141271412814129141301413114132141331413414135141361413714138141391414014141141421414314144141451414614147141481414914150141511415214153141541415514156141571415814159141601416114162141631416414165141661416714168141691417014171141721417314174141751417614177141781417914180141811418214183141841418514186141871418814189141901419114192141931419414195141961419714198141991420014201142021420314204142051420614207142081420914210142111421214213142141421514216142171421814219142201422114222142231422414225142261422714228142291423014231142321423314234142351423614237142381423914240142411424214243142441424514246142471424814249142501425114252142531425414255142561425714258142591426014261142621426314264142651426614267142681426914270142711427214273142741427514276142771427814279142801428114282142831428414285142861428714288142891429014291142921429314294142951429614297142981429914300143011430214303143041430514306143071430814309143101431114312143131431414315143161431714318143191432014321143221432314324143251432614327143281432914330143311433214333143341433514336143371433814339143401434114342143431434414345143461434714348143491435014351143521435314354143551435614357143581435914360143611436214363143641436514366143671436814369143701437114372143731437414375143761437714378143791438014381143821438314384143851438614387143881438914390143911439214393143941439514396143971439814399144001440114402144031440414405144061440714408144091441014411144121441314414144151441614417144181441914420144211442214423144241442514426144271442814429144301443114432144331443414435144361443714438144391444014441144421444314444144451444614447144481444914450144511445214453144541445514456144571445814459144601446114462144631446414465144661446714468144691447014471144721447314474144751447614477144781447914480144811448214483144841448514486144871448814489144901449114492144931449414495144961449714498144991450014501145021450314504145051450614507145081450914510145111451214513145141451514516145171451814519145201452114522145231452414525145261452714528145291453014531145321453314534145351453614537145381453914540145411454214543145441454514546145471454814549145501455114552145531455414555145561455714558145591456014561145621456314564145651456614567145681456914570145711457214573145741457514576145771457814579145801458114582145831458414585145861458714588145891459014591145921459314594145951459614597145981459914600146011460214603146041460514606146071460814609146101461114612146131461414615146161461714618146191462014621146221462314624146251462614627146281462914630146311463214633146341463514636146371463814639146401464114642146431464414645146461464714648146491465014651146521465314654146551465614657146581465914660146611466214663146641466514666146671466814669146701467114672146731467414675146761467714678146791468014681146821468314684146851468614687146881468914690146911469214693146941469514696146971469814699147001470114702147031470414705147061470714708147091471014711147121471314714147151471614717147181471914720147211472214723147241472514726147271472814729147301473114732147331473414735147361473714738147391474014741147421474314744147451474614747147481474914750147511475214753147541475514756147571475814759147601476114762147631476414765147661476714768147691477014771147721477314774147751477614777147781477914780147811478214783147841478514786147871478814789147901479114792147931479414795147961479714798147991480014801148021480314804148051480614807148081480914810148111481214813148141481514816148171481814819148201482114822148231482414825148261482714828148291483014831148321483314834148351483614837148381483914840148411484214843148441484514846148471484814849148501485114852148531485414855148561485714858148591486014861148621486314864148651486614867148681486914870148711487214873148741487514876148771487814879148801488114882148831488414885148861488714888148891489014891148921489314894148951489614897148981489914900149011490214903149041490514906149071490814909149101491114912149131491414915149161491714918149191492014921149221492314924149251492614927149281492914930149311493214933149341493514936149371493814939149401494114942149431494414945149461494714948149491495014951149521495314954149551495614957149581495914960149611496214963149641496514966149671496814969149701497114972149731497414975149761497714978149791498014981149821498314984149851498614987149881498914990149911499214993149941499514996149971499814999150001500115002150031500415005150061500715008150091501015011150121501315014150151501615017150181501915020150211502215023150241502515026150271502815029150301503115032150331503415035150361503715038150391504015041150421504315044150451504615047150481504915050150511505215053150541505515056150571505815059150601506115062150631506415065150661506715068150691507015071150721507315074150751507615077150781507915080150811508215083150841508515086150871508815089150901509115092150931509415095150961509715098150991510015101151021510315104151051510615107151081510915110151111511215113151141511515116151171511815119151201512115122151231512415125151261512715128151291513015131151321513315134151351513615137151381513915140151411514215143151441514515146151471514815149151501515115152151531515415155151561515715158151591516015161151621516315164151651516615167151681516915170151711517215173151741517515176151771517815179151801518115182151831518415185151861518715188151891519015191151921519315194151951519615197151981519915200152011520215203152041520515206152071520815209152101521115212152131521415215152161521715218152191522015221152221522315224152251522615227152281522915230152311523215233152341523515236152371523815239152401524115242152431524415245152461524715248152491525015251152521525315254152551525615257152581525915260152611526215263152641526515266152671526815269152701527115272152731527415275152761527715278152791528015281152821528315284152851528615287152881528915290152911529215293152941529515296152971529815299153001530115302153031530415305153061530715308153091531015311153121531315314153151531615317153181531915320153211532215323153241532515326153271532815329153301533115332153331533415335153361533715338153391534015341153421534315344153451534615347153481534915350153511535215353153541535515356153571535815359153601536115362153631536415365153661536715368153691537015371153721537315374153751537615377153781537915380153811538215383153841538515386153871538815389153901539115392153931539415395153961539715398153991540015401154021540315404154051540615407154081540915410154111541215413154141541515416154171541815419154201542115422154231542415425154261542715428154291543015431154321543315434154351543615437154381543915440154411544215443154441544515446154471544815449154501545115452154531545415455154561545715458154591546015461154621546315464154651546615467154681546915470154711547215473154741547515476154771547815479154801548115482154831548415485154861548715488154891549015491154921549315494154951549615497154981549915500155011550215503155041550515506155071550815509155101551115512155131551415515155161551715518155191552015521155221552315524155251552615527155281552915530155311553215533155341553515536155371553815539155401554115542155431554415545155461554715548155491555015551155521555315554155551555615557155581555915560155611556215563155641556515566155671556815569155701557115572155731557415575155761557715578155791558015581155821558315584155851558615587155881558915590155911559215593155941559515596155971559815599156001560115602156031560415605156061560715608156091561015611156121561315614156151561615617156181561915620156211562215623156241562515626156271562815629156301563115632156331563415635156361563715638156391564015641156421564315644156451564615647156481564915650156511565215653156541565515656156571565815659156601566115662156631566415665156661566715668156691567015671156721567315674156751567615677156781567915680156811568215683156841568515686156871568815689156901569115692156931569415695156961569715698156991570015701157021570315704157051570615707157081570915710157111571215713157141571515716157171571815719157201572115722157231572415725157261572715728157291573015731157321573315734157351573615737157381573915740157411574215743157441574515746157471574815749157501575115752157531575415755157561575715758157591576015761157621576315764157651576615767157681576915770157711577215773157741577515776157771577815779157801578115782157831578415785157861578715788157891579015791157921579315794157951579615797157981579915800158011580215803158041580515806158071580815809158101581115812158131581415815158161581715818158191582015821158221582315824158251582615827158281582915830158311583215833158341583515836158371583815839158401584115842158431584415845158461584715848158491585015851158521585315854158551585615857158581585915860158611586215863158641586515866158671586815869158701587115872158731587415875158761587715878158791588015881158821588315884158851588615887158881588915890158911589215893158941589515896158971589815899159001590115902159031590415905159061590715908159091591015911159121591315914159151591615917159181591915920159211592215923159241592515926159271592815929159301593115932159331593415935159361593715938159391594015941159421594315944159451594615947159481594915950159511595215953159541595515956159571595815959159601596115962159631596415965159661596715968159691597015971159721597315974159751597615977159781597915980159811598215983159841598515986159871598815989159901599115992159931599415995159961599715998159991600016001160021600316004160051600616007160081600916010160111601216013160141601516016160171601816019160201602116022160231602416025160261602716028160291603016031160321603316034160351603616037160381603916040160411604216043160441604516046160471604816049160501605116052160531605416055160561605716058160591606016061160621606316064160651606616067160681606916070160711607216073160741607516076160771607816079160801608116082160831608416085160861608716088160891609016091160921609316094160951609616097160981609916100161011610216103161041610516106161071610816109161101611116112161131611416115161161611716118161191612016121161221612316124161251612616127161281612916130161311613216133161341613516136161371613816139161401614116142161431614416145161461614716148161491615016151161521615316154161551615616157161581615916160161611616216163161641616516166161671616816169161701617116172161731617416175161761617716178161791618016181161821618316184161851618616187161881618916190161911619216193161941619516196161971619816199162001620116202162031620416205162061620716208162091621016211162121621316214162151621616217162181621916220162211622216223162241622516226162271622816229162301623116232162331623416235162361623716238162391624016241162421624316244162451624616247162481624916250162511625216253162541625516256162571625816259162601626116262162631626416265162661626716268162691627016271162721627316274162751627616277162781627916280162811628216283162841628516286162871628816289162901629116292162931629416295162961629716298162991630016301163021630316304163051630616307163081630916310163111631216313163141631516316163171631816319163201632116322163231632416325163261632716328163291633016331163321633316334163351633616337163381633916340163411634216343163441634516346163471634816349163501635116352163531635416355163561635716358163591636016361163621636316364163651636616367163681636916370163711637216373163741637516376163771637816379163801638116382163831638416385163861638716388163891639016391163921639316394163951639616397163981639916400164011640216403164041640516406164071640816409164101641116412164131641416415164161641716418164191642016421164221642316424164251642616427164281642916430164311643216433164341643516436164371643816439164401644116442164431644416445164461644716448164491645016451164521645316454164551645616457164581645916460164611646216463164641646516466164671646816469164701647116472164731647416475164761647716478164791648016481164821648316484164851648616487164881648916490164911649216493164941649516496164971649816499165001650116502165031650416505165061650716508165091651016511165121651316514165151651616517165181651916520165211652216523165241652516526165271652816529165301653116532165331653416535165361653716538165391654016541165421654316544165451654616547165481654916550165511655216553165541655516556165571655816559165601656116562165631656416565165661656716568165691657016571165721657316574165751657616577165781657916580165811658216583165841658516586165871658816589165901659116592165931659416595165961659716598165991660016601166021660316604166051660616607166081660916610166111661216613166141661516616166171661816619166201662116622166231662416625166261662716628166291663016631166321663316634166351663616637166381663916640166411664216643166441664516646166471664816649166501665116652166531665416655166561665716658166591666016661166621666316664166651666616667166681666916670166711667216673166741667516676166771667816679166801668116682166831668416685166861668716688166891669016691166921669316694166951669616697166981669916700167011670216703167041670516706167071670816709167101671116712167131671416715167161671716718167191672016721167221672316724167251672616727167281672916730167311673216733167341673516736167371673816739167401674116742167431674416745167461674716748167491675016751167521675316754167551675616757167581675916760167611676216763167641676516766167671676816769167701677116772167731677416775167761677716778167791678016781167821678316784167851678616787167881678916790167911679216793167941679516796167971679816799168001680116802168031680416805168061680716808168091681016811168121681316814168151681616817168181681916820168211682216823168241682516826168271682816829168301683116832168331683416835168361683716838168391684016841168421684316844168451684616847168481684916850168511685216853168541685516856168571685816859168601686116862168631686416865168661686716868168691687016871168721687316874168751687616877168781687916880168811688216883168841688516886168871688816889168901689116892168931689416895168961689716898168991690016901169021690316904169051690616907169081690916910169111691216913169141691516916169171691816919169201692116922169231692416925169261692716928169291693016931169321693316934169351693616937169381693916940169411694216943169441694516946169471694816949169501695116952169531695416955169561695716958169591696016961169621696316964169651696616967169681696916970169711697216973169741697516976169771697816979169801698116982169831698416985169861698716988169891699016991169921699316994169951699616997169981699917000170011700217003170041700517006170071700817009170101701117012170131701417015170161701717018170191702017021170221702317024170251702617027170281702917030170311703217033170341703517036170371703817039170401704117042170431704417045170461704717048170491705017051170521705317054170551705617057170581705917060170611706217063170641706517066170671706817069170701707117072170731707417075170761707717078170791708017081170821708317084170851708617087170881708917090170911709217093170941709517096170971709817099171001710117102171031710417105171061710717108171091711017111171121711317114171151711617117171181711917120171211712217123171241712517126171271712817129171301713117132171331713417135171361713717138171391714017141171421714317144171451714617147171481714917150171511715217153171541715517156171571715817159171601716117162171631716417165171661716717168171691717017171171721717317174171751717617177171781717917180171811718217183171841718517186171871718817189171901719117192171931719417195171961719717198171991720017201172021720317204172051720617207172081720917210172111721217213172141721517216172171721817219172201722117222172231722417225172261722717228172291723017231172321723317234172351723617237172381723917240172411724217243172441724517246172471724817249172501725117252172531725417255172561725717258172591726017261172621726317264172651726617267172681726917270172711727217273172741727517276172771727817279172801728117282172831728417285172861728717288172891729017291172921729317294172951729617297172981729917300173011730217303173041730517306173071730817309173101731117312173131731417315173161731717318173191732017321173221732317324173251732617327173281732917330173311733217333173341733517336173371733817339173401734117342173431734417345173461734717348173491735017351173521735317354173551735617357173581735917360173611736217363173641736517366173671736817369173701737117372173731737417375173761737717378173791738017381173821738317384173851738617387173881738917390173911739217393173941739517396173971739817399174001740117402174031740417405174061740717408174091741017411174121741317414174151741617417174181741917420174211742217423174241742517426174271742817429174301743117432174331743417435174361743717438174391744017441174421744317444174451744617447174481744917450174511745217453174541745517456174571745817459174601746117462174631746417465174661746717468174691747017471174721747317474174751747617477174781747917480174811748217483174841748517486174871748817489174901749117492174931749417495174961749717498174991750017501175021750317504175051750617507175081750917510175111751217513175141751517516175171751817519175201752117522175231752417525175261752717528175291753017531175321753317534175351753617537175381753917540175411754217543175441754517546175471754817549175501755117552175531755417555175561755717558175591756017561175621756317564175651756617567175681756917570175711757217573175741757517576175771757817579175801758117582175831758417585175861758717588175891759017591175921759317594175951759617597175981759917600176011760217603176041760517606176071760817609176101761117612176131761417615176161761717618176191762017621176221762317624176251762617627176281762917630176311763217633176341763517636176371763817639176401764117642176431764417645176461764717648176491765017651176521765317654176551765617657176581765917660176611766217663176641766517666176671766817669176701767117672176731767417675176761767717678176791768017681176821768317684176851768617687176881768917690176911769217693176941769517696176971769817699177001770117702177031770417705177061770717708177091771017711177121771317714177151771617717177181771917720177211772217723177241772517726177271772817729177301773117732177331773417735177361773717738177391774017741177421774317744177451774617747177481774917750177511775217753177541775517756177571775817759177601776117762177631776417765177661776717768177691777017771177721777317774177751777617777177781777917780177811778217783177841778517786177871778817789177901779117792177931779417795177961779717798177991780017801178021780317804178051780617807178081780917810178111781217813178141781517816178171781817819178201782117822178231782417825178261782717828178291783017831178321783317834178351783617837178381783917840178411784217843178441784517846178471784817849178501785117852178531785417855178561785717858178591786017861178621786317864178651786617867178681786917870178711787217873178741787517876178771787817879178801788117882178831788417885178861788717888178891789017891178921789317894178951789617897178981789917900179011790217903179041790517906179071790817909179101791117912179131791417915179161791717918179191792017921179221792317924179251792617927179281792917930179311793217933179341793517936179371793817939179401794117942179431794417945179461794717948179491795017951179521795317954179551795617957179581795917960179611796217963179641796517966179671796817969179701797117972179731797417975179761797717978179791798017981179821798317984179851798617987179881798917990179911799217993179941799517996179971799817999180001800118002180031800418005180061800718008180091801018011180121801318014180151801618017180181801918020180211802218023180241802518026180271802818029180301803118032180331803418035180361803718038180391804018041180421804318044180451804618047180481804918050180511805218053180541805518056180571805818059180601806118062180631806418065180661806718068180691807018071180721807318074180751807618077180781807918080180811808218083180841808518086180871808818089180901809118092180931809418095180961809718098180991810018101181021810318104181051810618107181081810918110181111811218113181141811518116181171811818119181201812118122181231812418125181261812718128181291813018131181321813318134181351813618137181381813918140181411814218143181441814518146181471814818149181501815118152181531815418155181561815718158181591816018161181621816318164181651816618167181681816918170181711817218173181741817518176181771817818179181801818118182181831818418185181861818718188181891819018191181921819318194181951819618197181981819918200182011820218203182041820518206182071820818209182101821118212182131821418215182161821718218182191822018221182221822318224182251822618227182281822918230182311823218233182341823518236182371823818239182401824118242182431824418245182461824718248182491825018251182521825318254182551825618257182581825918260182611826218263182641826518266182671826818269182701827118272182731827418275182761827718278182791828018281182821828318284182851828618287182881828918290182911829218293182941829518296182971829818299183001830118302183031830418305183061830718308183091831018311183121831318314183151831618317183181831918320183211832218323183241832518326183271832818329183301833118332183331833418335183361833718338183391834018341183421834318344183451834618347183481834918350183511835218353183541835518356183571835818359183601836118362183631836418365183661836718368183691837018371183721837318374183751837618377183781837918380183811838218383183841838518386183871838818389183901839118392183931839418395183961839718398183991840018401184021840318404184051840618407184081840918410184111841218413184141841518416184171841818419184201842118422184231842418425184261842718428184291843018431184321843318434184351843618437184381843918440184411844218443184441844518446184471844818449184501845118452184531845418455184561845718458184591846018461184621846318464184651846618467184681846918470184711847218473184741847518476184771847818479184801848118482184831848418485184861848718488184891849018491184921849318494184951849618497184981849918500185011850218503185041850518506185071850818509185101851118512185131851418515185161851718518185191852018521185221852318524185251852618527185281852918530185311853218533185341853518536185371853818539185401854118542185431854418545185461854718548185491855018551185521855318554185551855618557185581855918560185611856218563185641856518566185671856818569185701857118572185731857418575185761857718578185791858018581185821858318584185851858618587185881858918590185911859218593185941859518596185971859818599186001860118602186031860418605186061860718608186091861018611186121861318614186151861618617186181861918620186211862218623186241862518626186271862818629186301863118632186331863418635186361863718638186391864018641186421864318644186451864618647186481864918650186511865218653186541865518656186571865818659186601866118662186631866418665186661866718668186691867018671186721867318674186751867618677186781867918680186811868218683186841868518686186871868818689186901869118692186931869418695186961869718698186991870018701187021870318704187051870618707187081870918710187111871218713187141871518716187171871818719187201872118722187231872418725187261872718728187291873018731187321873318734187351873618737187381873918740187411874218743187441874518746187471874818749187501875118752187531875418755187561875718758187591876018761187621876318764187651876618767187681876918770187711877218773187741877518776187771877818779187801878118782187831878418785187861878718788187891879018791187921879318794187951879618797187981879918800188011880218803188041880518806188071880818809188101881118812188131881418815188161881718818188191882018821188221882318824188251882618827188281882918830188311883218833188341883518836188371883818839188401884118842188431884418845188461884718848188491885018851188521885318854188551885618857188581885918860188611886218863188641886518866188671886818869188701887118872188731887418875188761887718878188791888018881188821888318884188851888618887188881888918890188911889218893188941889518896188971889818899189001890118902189031890418905189061890718908189091891018911189121891318914189151891618917189181891918920189211892218923189241892518926189271892818929189301893118932189331893418935189361893718938189391894018941189421894318944189451894618947189481894918950189511895218953189541895518956189571895818959189601896118962189631896418965189661896718968189691897018971189721897318974189751897618977189781897918980189811898218983189841898518986189871898818989189901899118992189931899418995189961899718998189991900019001190021900319004190051900619007190081900919010190111901219013190141901519016190171901819019190201902119022190231902419025190261902719028190291903019031190321903319034190351903619037190381903919040190411904219043190441904519046190471904819049190501905119052190531905419055190561905719058190591906019061190621906319064190651906619067190681906919070190711907219073190741907519076190771907819079190801908119082190831908419085190861908719088190891909019091190921909319094190951909619097190981909919100191011910219103191041910519106191071910819109191101911119112191131911419115191161911719118191191912019121191221912319124191251912619127191281912919130191311913219133191341913519136191371913819139191401914119142191431914419145191461914719148191491915019151191521915319154191551915619157191581915919160191611916219163191641916519166191671916819169191701917119172191731917419175191761917719178191791918019181191821918319184191851918619187191881918919190191911919219193191941919519196191971919819199192001920119202192031920419205192061920719208192091921019211192121921319214192151921619217192181921919220192211922219223192241922519226192271922819229192301923119232192331923419235192361923719238192391924019241192421924319244192451924619247192481924919250192511925219253192541925519256192571925819259192601926119262192631926419265192661926719268192691927019271192721927319274192751927619277192781927919280192811928219283192841928519286192871928819289192901929119292192931929419295192961929719298192991930019301193021930319304193051930619307193081930919310193111931219313193141931519316193171931819319193201932119322193231932419325193261932719328193291933019331193321933319334193351933619337193381933919340193411934219343193441934519346193471934819349193501935119352193531935419355193561935719358193591936019361193621936319364193651936619367193681936919370193711937219373193741937519376193771937819379193801938119382193831938419385193861938719388193891939019391193921939319394193951939619397193981939919400194011940219403194041940519406194071940819409194101941119412194131941419415194161941719418194191942019421194221942319424194251942619427194281942919430194311943219433194341943519436194371943819439194401944119442194431944419445194461944719448194491945019451194521945319454194551945619457194581945919460194611946219463194641946519466194671946819469194701947119472194731947419475194761947719478194791948019481194821948319484194851948619487194881948919490194911949219493194941949519496194971949819499195001950119502195031950419505195061950719508195091951019511195121951319514195151951619517195181951919520195211952219523195241952519526195271952819529195301953119532195331953419535195361953719538195391954019541195421954319544195451954619547195481954919550195511955219553195541955519556195571955819559195601956119562195631956419565195661956719568195691957019571195721957319574195751957619577195781957919580195811958219583195841958519586195871958819589195901959119592195931959419595195961959719598195991960019601196021960319604196051960619607196081960919610196111961219613196141961519616196171961819619196201962119622196231962419625196261962719628196291963019631196321963319634196351963619637196381963919640196411964219643196441964519646196471964819649196501965119652196531965419655196561965719658196591966019661196621966319664196651966619667196681966919670196711967219673196741967519676196771967819679196801968119682196831968419685196861968719688196891969019691196921969319694196951969619697196981969919700197011970219703197041970519706197071970819709197101971119712197131971419715197161971719718197191972019721197221972319724197251972619727197281972919730197311973219733197341973519736197371973819739197401974119742197431974419745197461974719748197491975019751197521975319754197551975619757197581975919760197611976219763197641976519766197671976819769197701977119772197731977419775197761977719778197791978019781197821978319784197851978619787197881978919790197911979219793197941979519796197971979819799198001980119802198031980419805198061980719808198091981019811198121981319814198151981619817198181981919820198211982219823198241982519826198271982819829198301983119832198331983419835198361983719838198391984019841198421984319844198451984619847198481984919850198511985219853198541985519856198571985819859198601986119862198631986419865198661986719868198691987019871198721987319874198751987619877198781987919880198811988219883198841988519886198871988819889198901989119892198931989419895198961989719898198991990019901199021990319904199051990619907199081990919910199111991219913199141991519916199171991819919199201992119922199231992419925199261992719928199291993019931199321993319934199351993619937199381993919940199411994219943199441994519946199471994819949199501995119952199531995419955199561995719958199591996019961199621996319964199651996619967199681996919970199711997219973199741997519976199771997819979199801998119982199831998419985199861998719988199891999019991199921999319994199951999619997199981999920000200012000220003200042000520006200072000820009200102001120012200132001420015200162001720018200192002020021200222002320024200252002620027200282002920030200312003220033200342003520036200372003820039200402004120042200432004420045200462004720048200492005020051200522005320054200552005620057200582005920060200612006220063200642006520066200672006820069200702007120072200732007420075200762007720078200792008020081200822008320084200852008620087200882008920090200912009220093200942009520096200972009820099201002010120102201032010420105201062010720108201092011020111201122011320114201152011620117201182011920120201212012220123201242012520126201272012820129201302013120132201332013420135201362013720138201392014020141201422014320144201452014620147201482014920150201512015220153201542015520156201572015820159201602016120162201632016420165201662016720168201692017020171201722017320174201752017620177201782017920180201812018220183201842018520186201872018820189201902019120192201932019420195201962019720198201992020020201202022020320204202052020620207202082020920210202112021220213202142021520216202172021820219202202022120222202232022420225202262022720228202292023020231202322023320234202352023620237202382023920240202412024220243202442024520246202472024820249202502025120252202532025420255202562025720258202592026020261202622026320264202652026620267202682026920270202712027220273202742027520276202772027820279202802028120282202832028420285202862028720288202892029020291202922029320294202952029620297202982029920300203012030220303203042030520306203072030820309203102031120312203132031420315203162031720318203192032020321203222032320324203252032620327203282032920330203312033220333203342033520336203372033820339203402034120342203432034420345203462034720348203492035020351203522035320354203552035620357203582035920360203612036220363203642036520366203672036820369203702037120372203732037420375203762037720378203792038020381203822038320384203852038620387203882038920390203912039220393203942039520396203972039820399204002040120402204032040420405204062040720408204092041020411204122041320414204152041620417204182041920420204212042220423204242042520426204272042820429204302043120432204332043420435204362043720438204392044020441204422044320444204452044620447204482044920450204512045220453204542045520456204572045820459204602046120462204632046420465204662046720468204692047020471204722047320474204752047620477204782047920480204812048220483204842048520486204872048820489204902049120492204932049420495204962049720498204992050020501205022050320504205052050620507205082050920510205112051220513205142051520516205172051820519205202052120522205232052420525205262052720528205292053020531205322053320534205352053620537205382053920540205412054220543205442054520546205472054820549205502055120552205532055420555205562055720558205592056020561205622056320564205652056620567205682056920570205712057220573205742057520576205772057820579205802058120582205832058420585205862058720588205892059020591205922059320594205952059620597205982059920600206012060220603206042060520606206072060820609206102061120612206132061420615206162061720618206192062020621206222062320624206252062620627206282062920630206312063220633206342063520636206372063820639206402064120642206432064420645206462064720648206492065020651206522065320654206552065620657206582065920660206612066220663206642066520666206672066820669206702067120672206732067420675206762067720678206792068020681206822068320684206852068620687206882068920690206912069220693206942069520696206972069820699207002070120702207032070420705207062070720708207092071020711207122071320714207152071620717207182071920720207212072220723207242072520726207272072820729207302073120732207332073420735207362073720738207392074020741207422074320744207452074620747207482074920750207512075220753207542075520756207572075820759207602076120762207632076420765207662076720768207692077020771207722077320774207752077620777207782077920780207812078220783207842078520786207872078820789207902079120792207932079420795207962079720798207992080020801208022080320804208052080620807208082080920810208112081220813208142081520816208172081820819208202082120822208232082420825208262082720828208292083020831208322083320834208352083620837208382083920840208412084220843208442084520846208472084820849208502085120852208532085420855208562085720858208592086020861208622086320864208652086620867208682086920870208712087220873208742087520876208772087820879208802088120882208832088420885208862088720888208892089020891208922089320894208952089620897208982089920900209012090220903209042090520906209072090820909209102091120912209132091420915209162091720918209192092020921209222092320924209252092620927209282092920930209312093220933209342093520936209372093820939209402094120942209432094420945209462094720948209492095020951209522095320954209552095620957209582095920960209612096220963209642096520966209672096820969209702097120972209732097420975209762097720978209792098020981209822098320984209852098620987209882098920990209912099220993209942099520996209972099820999210002100121002210032100421005210062100721008210092101021011210122101321014210152101621017210182101921020210212102221023210242102521026210272102821029210302103121032210332103421035210362103721038210392104021041210422104321044210452104621047210482104921050210512105221053210542105521056210572105821059210602106121062210632106421065210662106721068210692107021071210722107321074210752107621077210782107921080210812108221083210842108521086210872108821089210902109121092210932109421095210962109721098210992110021101211022110321104211052110621107211082110921110211112111221113211142111521116211172111821119211202112121122211232112421125211262112721128211292113021131211322113321134211352113621137211382113921140211412114221143211442114521146211472114821149211502115121152211532115421155211562115721158211592116021161211622116321164211652116621167211682116921170211712117221173211742117521176211772117821179211802118121182211832118421185211862118721188211892119021191211922119321194211952119621197211982119921200212012120221203212042120521206212072120821209212102121121212212132121421215212162121721218212192122021221212222122321224212252122621227212282122921230212312123221233212342123521236212372123821239212402124121242212432124421245212462124721248212492125021251212522125321254212552125621257212582125921260212612126221263212642126521266212672126821269212702127121272212732127421275212762127721278212792128021281212822128321284212852128621287212882128921290212912129221293212942129521296212972129821299213002130121302213032130421305213062130721308213092131021311213122131321314213152131621317213182131921320213212132221323213242132521326213272132821329213302133121332213332133421335213362133721338213392134021341213422134321344213452134621347213482134921350213512135221353213542135521356213572135821359213602136121362213632136421365213662136721368213692137021371213722137321374213752137621377213782137921380213812138221383213842138521386213872138821389213902139121392213932139421395213962139721398213992140021401214022140321404214052140621407214082140921410214112141221413214142141521416214172141821419214202142121422214232142421425214262142721428214292143021431214322143321434214352143621437214382143921440214412144221443214442144521446214472144821449214502145121452214532145421455214562145721458214592146021461214622146321464214652146621467214682146921470214712147221473214742147521476214772147821479214802148121482214832148421485214862148721488214892149021491214922149321494214952149621497214982149921500215012150221503215042150521506215072150821509215102151121512215132151421515215162151721518215192152021521215222152321524215252152621527215282152921530215312153221533215342153521536215372153821539215402154121542215432154421545215462154721548215492155021551215522155321554215552155621557215582155921560215612156221563215642156521566215672156821569215702157121572215732157421575215762157721578215792158021581215822158321584215852158621587215882158921590215912159221593215942159521596215972159821599216002160121602216032160421605216062160721608216092161021611216122161321614216152161621617216182161921620216212162221623216242162521626216272162821629216302163121632216332163421635216362163721638216392164021641216422164321644216452164621647216482164921650216512165221653216542165521656216572165821659216602166121662216632166421665216662166721668216692167021671216722167321674216752167621677216782167921680216812168221683216842168521686216872168821689216902169121692216932169421695216962169721698216992170021701217022170321704217052170621707217082170921710217112171221713217142171521716217172171821719217202172121722217232172421725217262172721728217292173021731217322173321734217352173621737217382173921740217412174221743217442174521746217472174821749217502175121752217532175421755217562175721758217592176021761217622176321764217652176621767217682176921770217712177221773217742177521776217772177821779217802178121782217832178421785217862178721788217892179021791217922179321794217952179621797217982179921800218012180221803218042180521806218072180821809218102181121812218132181421815218162181721818218192182021821218222182321824218252182621827218282182921830218312183221833218342183521836218372183821839218402184121842218432184421845218462184721848218492185021851218522185321854218552185621857218582185921860218612186221863218642186521866218672186821869218702187121872218732187421875218762187721878218792188021881218822188321884218852188621887218882188921890218912189221893218942189521896218972189821899219002190121902219032190421905219062190721908219092191021911219122191321914219152191621917219182191921920219212192221923219242192521926219272192821929219302193121932219332193421935219362193721938219392194021941219422194321944219452194621947219482194921950219512195221953219542195521956219572195821959219602196121962219632196421965219662196721968219692197021971219722197321974219752197621977219782197921980219812198221983219842198521986219872198821989219902199121992219932199421995219962199721998219992200022001220022200322004220052200622007220082200922010220112201222013220142201522016220172201822019220202202122022220232202422025220262202722028220292203022031220322203322034220352203622037220382203922040220412204222043220442204522046220472204822049220502205122052220532205422055220562205722058220592206022061220622206322064220652206622067220682206922070220712207222073220742207522076220772207822079220802208122082220832208422085220862208722088220892209022091220922209322094220952209622097220982209922100221012210222103221042210522106221072210822109221102211122112221132211422115221162211722118221192212022121221222212322124221252212622127221282212922130221312213222133221342213522136221372213822139221402214122142221432214422145221462214722148221492215022151221522215322154221552215622157221582215922160221612216222163221642216522166221672216822169221702217122172221732217422175221762217722178221792218022181221822218322184221852218622187221882218922190221912219222193221942219522196221972219822199222002220122202222032220422205222062220722208222092221022211222122221322214222152221622217222182221922220222212222222223222242222522226222272222822229222302223122232222332223422235222362223722238222392224022241222422224322244222452224622247222482224922250222512225222253222542225522256222572225822259222602226122262222632226422265222662226722268222692227022271222722227322274222752227622277222782227922280222812228222283222842228522286222872228822289222902229122292222932229422295222962229722298222992230022301223022230322304223052230622307223082230922310223112231222313223142231522316223172231822319223202232122322223232232422325223262232722328223292233022331223322233322334223352233622337223382233922340223412234222343223442234522346223472234822349223502235122352223532235422355223562235722358223592236022361223622236322364223652236622367223682236922370223712237222373223742237522376223772237822379223802238122382223832238422385223862238722388223892239022391223922239322394223952239622397223982239922400224012240222403224042240522406224072240822409224102241122412224132241422415224162241722418224192242022421224222242322424224252242622427224282242922430224312243222433224342243522436224372243822439224402244122442224432244422445224462244722448224492245022451224522245322454224552245622457224582245922460224612246222463224642246522466224672246822469224702247122472224732247422475224762247722478224792248022481224822248322484224852248622487224882248922490224912249222493224942249522496224972249822499225002250122502225032250422505225062250722508225092251022511225122251322514225152251622517225182251922520225212252222523225242252522526225272252822529225302253122532225332253422535225362253722538225392254022541225422254322544225452254622547225482254922550225512255222553225542255522556225572255822559225602256122562225632256422565225662256722568225692257022571225722257322574225752257622577225782257922580225812258222583225842258522586225872258822589225902259122592225932259422595225962259722598225992260022601226022260322604226052260622607226082260922610226112261222613226142261522616226172261822619226202262122622226232262422625226262262722628226292263022631226322263322634226352263622637226382263922640226412264222643226442264522646226472264822649226502265122652226532265422655226562265722658226592266022661226622266322664226652266622667226682266922670226712267222673226742267522676226772267822679226802268122682226832268422685226862268722688226892269022691226922269322694226952269622697226982269922700227012270222703227042270522706227072270822709227102271122712227132271422715227162271722718227192272022721227222272322724227252272622727227282272922730227312273222733227342273522736227372273822739227402274122742227432274422745227462274722748227492275022751227522275322754227552275622757227582275922760227612276222763227642276522766227672276822769227702277122772227732277422775227762277722778227792278022781227822278322784227852278622787227882278922790227912279222793227942279522796227972279822799228002280122802228032280422805228062280722808228092281022811228122281322814228152281622817228182281922820228212282222823228242282522826228272282822829228302283122832228332283422835228362283722838228392284022841228422284322844228452284622847228482284922850228512285222853228542285522856228572285822859228602286122862228632286422865228662286722868228692287022871228722287322874228752287622877228782287922880228812288222883228842288522886228872288822889228902289122892228932289422895228962289722898228992290022901229022290322904229052290622907229082290922910229112291222913229142291522916229172291822919229202292122922229232292422925229262292722928229292293022931229322293322934229352293622937229382293922940229412294222943229442294522946229472294822949229502295122952229532295422955229562295722958229592296022961229622296322964229652296622967229682296922970229712297222973229742297522976229772297822979229802298122982229832298422985229862298722988229892299022991229922299322994229952299622997229982299923000230012300223003230042300523006230072300823009230102301123012230132301423015230162301723018230192302023021230222302323024230252302623027230282302923030230312303223033230342303523036230372303823039230402304123042230432304423045230462304723048230492305023051230522305323054230552305623057230582305923060230612306223063230642306523066230672306823069230702307123072230732307423075230762307723078230792308023081230822308323084230852308623087230882308923090230912309223093230942309523096230972309823099231002310123102231032310423105231062310723108231092311023111231122311323114231152311623117231182311923120231212312223123231242312523126231272312823129231302313123132231332313423135231362313723138231392314023141231422314323144231452314623147231482314923150231512315223153231542315523156231572315823159231602316123162231632316423165231662316723168231692317023171231722317323174231752317623177231782317923180231812318223183231842318523186231872318823189231902319123192231932319423195231962319723198231992320023201232022320323204232052320623207232082320923210232112321223213232142321523216232172321823219232202322123222232232322423225232262322723228232292323023231232322323323234232352323623237232382323923240232412324223243232442324523246232472324823249232502325123252232532325423255232562325723258232592326023261232622326323264232652326623267232682326923270232712327223273232742327523276232772327823279232802328123282232832328423285232862328723288232892329023291232922329323294232952329623297232982329923300233012330223303233042330523306233072330823309233102331123312233132331423315233162331723318233192332023321233222332323324233252332623327233282332923330233312333223333233342333523336233372333823339233402334123342233432334423345233462334723348233492335023351233522335323354233552335623357233582335923360233612336223363233642336523366233672336823369233702337123372233732337423375233762337723378233792338023381233822338323384233852338623387233882338923390233912339223393233942339523396233972339823399234002340123402234032340423405234062340723408234092341023411234122341323414234152341623417234182341923420234212342223423234242342523426234272342823429234302343123432234332343423435234362343723438234392344023441234422344323444234452344623447234482344923450234512345223453234542345523456234572345823459234602346123462234632346423465234662346723468234692347023471234722347323474234752347623477234782347923480234812348223483234842348523486234872348823489234902349123492234932349423495234962349723498234992350023501235022350323504235052350623507235082350923510235112351223513235142351523516235172351823519235202352123522235232352423525235262352723528235292353023531235322353323534235352353623537235382353923540235412354223543235442354523546235472354823549235502355123552235532355423555235562355723558235592356023561235622356323564235652356623567235682356923570235712357223573235742357523576235772357823579235802358123582235832358423585235862358723588235892359023591235922359323594235952359623597235982359923600236012360223603236042360523606236072360823609236102361123612236132361423615236162361723618236192362023621236222362323624236252362623627236282362923630236312363223633236342363523636236372363823639236402364123642236432364423645236462364723648236492365023651236522365323654236552365623657236582365923660236612366223663236642366523666236672366823669236702367123672236732367423675236762367723678236792368023681236822368323684236852368623687236882368923690236912369223693236942369523696236972369823699237002370123702237032370423705237062370723708237092371023711237122371323714237152371623717237182371923720237212372223723237242372523726237272372823729237302373123732237332373423735237362373723738237392374023741237422374323744237452374623747237482374923750237512375223753237542375523756237572375823759237602376123762237632376423765237662376723768237692377023771237722377323774237752377623777237782377923780237812378223783237842378523786237872378823789237902379123792237932379423795237962379723798237992380023801238022380323804238052380623807238082380923810238112381223813238142381523816238172381823819238202382123822238232382423825238262382723828238292383023831238322383323834238352383623837238382383923840238412384223843238442384523846238472384823849238502385123852238532385423855238562385723858238592386023861238622386323864238652386623867238682386923870238712387223873238742387523876238772387823879238802388123882238832388423885238862388723888238892389023891238922389323894238952389623897238982389923900239012390223903239042390523906239072390823909239102391123912239132391423915239162391723918239192392023921239222392323924239252392623927239282392923930239312393223933239342393523936239372393823939239402394123942239432394423945239462394723948239492395023951239522395323954239552395623957239582395923960239612396223963239642396523966239672396823969239702397123972239732397423975239762397723978239792398023981239822398323984239852398623987239882398923990239912399223993239942399523996239972399823999240002400124002240032400424005240062400724008240092401024011240122401324014240152401624017240182401924020240212402224023240242402524026240272402824029240302403124032240332403424035240362403724038240392404024041240422404324044240452404624047240482404924050240512405224053240542405524056240572405824059240602406124062240632406424065240662406724068240692407024071240722407324074240752407624077240782407924080240812408224083240842408524086240872408824089240902409124092240932409424095240962409724098240992410024101241022410324104241052410624107241082410924110241112411224113241142411524116241172411824119241202412124122241232412424125241262412724128241292413024131241322413324134241352413624137241382413924140241412414224143241442414524146241472414824149241502415124152241532415424155241562415724158241592416024161241622416324164241652416624167241682416924170241712417224173241742417524176241772417824179241802418124182241832418424185241862418724188241892419024191241922419324194241952419624197241982419924200242012420224203242042420524206242072420824209242102421124212242132421424215242162421724218242192422024221242222422324224242252422624227242282422924230242312423224233242342423524236242372423824239242402424124242242432424424245242462424724248242492425024251242522425324254242552425624257242582425924260242612426224263242642426524266242672426824269242702427124272242732427424275242762427724278242792428024281242822428324284242852428624287242882428924290242912429224293242942429524296242972429824299243002430124302243032430424305243062430724308243092431024311243122431324314243152431624317243182431924320243212432224323243242432524326243272432824329243302433124332243332433424335243362433724338243392434024341243422434324344243452434624347243482434924350243512435224353243542435524356243572435824359243602436124362243632436424365243662436724368243692437024371243722437324374243752437624377243782437924380243812438224383243842438524386243872438824389243902439124392243932439424395243962439724398243992440024401244022440324404244052440624407244082440924410244112441224413244142441524416244172441824419244202442124422244232442424425244262442724428244292443024431244322443324434244352443624437244382443924440244412444224443244442444524446244472444824449244502445124452244532445424455244562445724458244592446024461244622446324464244652446624467244682446924470244712447224473244742447524476244772447824479244802448124482244832448424485244862448724488244892449024491244922449324494244952449624497244982449924500245012450224503245042450524506245072450824509245102451124512245132451424515245162451724518245192452024521245222452324524245252452624527245282452924530245312453224533245342453524536245372453824539245402454124542245432454424545245462454724548245492455024551245522455324554245552455624557245582455924560245612456224563245642456524566245672456824569245702457124572245732457424575245762457724578245792458024581245822458324584245852458624587245882458924590245912459224593245942459524596245972459824599246002460124602246032460424605246062460724608246092461024611246122461324614246152461624617246182461924620246212462224623246242462524626246272462824629246302463124632246332463424635246362463724638246392464024641246422464324644246452464624647246482464924650246512465224653246542465524656246572465824659246602466124662246632466424665246662466724668246692467024671246722467324674246752467624677246782467924680246812468224683246842468524686246872468824689246902469124692246932469424695246962469724698246992470024701247022470324704247052470624707247082470924710247112471224713247142471524716247172471824719247202472124722247232472424725247262472724728247292473024731247322473324734247352473624737247382473924740247412474224743247442474524746247472474824749247502475124752247532475424755247562475724758247592476024761247622476324764247652476624767247682476924770247712477224773247742477524776247772477824779247802478124782247832478424785247862478724788247892479024791247922479324794247952479624797247982479924800248012480224803248042480524806248072480824809248102481124812248132481424815248162481724818248192482024821248222482324824248252482624827248282482924830248312483224833248342483524836248372483824839248402484124842248432484424845248462484724848248492485024851248522485324854248552485624857248582485924860248612486224863248642486524866248672486824869248702487124872248732487424875248762487724878248792488024881248822488324884248852488624887248882488924890248912489224893248942489524896248972489824899249002490124902249032490424905249062490724908249092491024911249122491324914249152491624917249182491924920249212492224923249242492524926249272492824929249302493124932249332493424935249362493724938249392494024941249422494324944249452494624947249482494924950249512495224953249542495524956249572495824959249602496124962249632496424965249662496724968249692497024971249722497324974249752497624977249782497924980249812498224983249842498524986249872498824989249902499124992249932499424995249962499724998249992500025001250022500325004250052500625007250082500925010250112501225013250142501525016250172501825019250202502125022250232502425025250262502725028250292503025031250322503325034250352503625037250382503925040250412504225043250442504525046250472504825049250502505125052250532505425055250562505725058250592506025061250622506325064250652506625067250682506925070250712507225073250742507525076250772507825079250802508125082250832508425085250862508725088250892509025091250922509325094250952509625097250982509925100251012510225103251042510525106251072510825109251102511125112251132511425115251162511725118251192512025121251222512325124251252512625127251282512925130251312513225133251342513525136251372513825139251402514125142251432514425145251462514725148251492515025151251522515325154251552515625157251582515925160251612516225163251642516525166251672516825169251702517125172251732517425175251762517725178251792518025181251822518325184251852518625187251882518925190251912519225193251942519525196251972519825199252002520125202252032520425205252062520725208252092521025211252122521325214252152521625217252182521925220252212522225223252242522525226252272522825229252302523125232252332523425235252362523725238252392524025241252422524325244252452524625247252482524925250252512525225253252542525525256252572525825259252602526125262252632526425265252662526725268252692527025271252722527325274252752527625277252782527925280252812528225283252842528525286252872528825289252902529125292252932529425295252962529725298252992530025301253022530325304253052530625307253082530925310253112531225313253142531525316253172531825319253202532125322253232532425325253262532725328253292533025331253322533325334253352533625337253382533925340253412534225343253442534525346253472534825349253502535125352253532535425355253562535725358253592536025361253622536325364253652536625367253682536925370253712537225373253742537525376253772537825379253802538125382253832538425385253862538725388253892539025391253922539325394253952539625397253982539925400254012540225403254042540525406254072540825409254102541125412254132541425415254162541725418254192542025421254222542325424254252542625427254282542925430254312543225433254342543525436254372543825439254402544125442254432544425445254462544725448254492545025451254522545325454254552545625457254582545925460254612546225463254642546525466254672546825469254702547125472254732547425475254762547725478254792548025481254822548325484254852548625487254882548925490254912549225493254942549525496254972549825499255002550125502255032550425505255062550725508255092551025511255122551325514255152551625517255182551925520255212552225523255242552525526255272552825529255302553125532255332553425535255362553725538255392554025541255422554325544255452554625547255482554925550255512555225553255542555525556255572555825559255602556125562255632556425565255662556725568255692557025571255722557325574255752557625577255782557925580255812558225583255842558525586255872558825589255902559125592255932559425595255962559725598255992560025601256022560325604256052560625607256082560925610256112561225613256142561525616256172561825619256202562125622256232562425625256262562725628256292563025631256322563325634256352563625637256382563925640256412564225643256442564525646256472564825649256502565125652256532565425655256562565725658256592566025661256622566325664256652566625667256682566925670256712567225673256742567525676256772567825679256802568125682256832568425685256862568725688256892569025691256922569325694256952569625697256982569925700257012570225703257042570525706257072570825709257102571125712257132571425715257162571725718257192572025721257222572325724257252572625727257282572925730257312573225733257342573525736257372573825739257402574125742257432574425745257462574725748257492575025751257522575325754257552575625757257582575925760257612576225763257642576525766257672576825769257702577125772257732577425775257762577725778257792578025781257822578325784257852578625787257882578925790257912579225793257942579525796257972579825799258002580125802258032580425805258062580725808258092581025811258122581325814258152581625817258182581925820258212582225823258242582525826258272582825829258302583125832258332583425835258362583725838258392584025841258422584325844258452584625847258482584925850258512585225853258542585525856258572585825859258602586125862258632586425865258662586725868258692587025871258722587325874258752587625877258782587925880258812588225883258842588525886258872588825889258902589125892258932589425895258962589725898258992590025901259022590325904259052590625907259082590925910259112591225913259142591525916259172591825919259202592125922259232592425925259262592725928259292593025931259322593325934259352593625937259382593925940259412594225943259442594525946259472594825949259502595125952259532595425955259562595725958259592596025961259622596325964259652596625967259682596925970259712597225973259742597525976259772597825979259802598125982259832598425985259862598725988259892599025991259922599325994259952599625997259982599926000260012600226003260042600526006260072600826009260102601126012260132601426015260162601726018260192602026021260222602326024260252602626027260282602926030260312603226033260342603526036260372603826039260402604126042260432604426045260462604726048260492605026051260522605326054260552605626057260582605926060260612606226063260642606526066260672606826069260702607126072260732607426075260762607726078260792608026081260822608326084260852608626087260882608926090260912609226093260942609526096260972609826099261002610126102261032610426105261062610726108261092611026111261122611326114261152611626117261182611926120261212612226123261242612526126261272612826129261302613126132261332613426135261362613726138261392614026141261422614326144261452614626147261482614926150261512615226153261542615526156261572615826159261602616126162261632616426165261662616726168261692617026171261722617326174261752617626177261782617926180261812618226183261842618526186261872618826189261902619126192261932619426195261962619726198261992620026201262022620326204262052620626207262082620926210262112621226213262142621526216262172621826219262202622126222262232622426225262262622726228262292623026231262322623326234262352623626237262382623926240262412624226243262442624526246262472624826249262502625126252262532625426255262562625726258262592626026261262622626326264262652626626267262682626926270262712627226273262742627526276262772627826279262802628126282262832628426285262862628726288262892629026291262922629326294262952629626297262982629926300263012630226303263042630526306263072630826309263102631126312263132631426315263162631726318263192632026321263222632326324263252632626327263282632926330263312633226333263342633526336263372633826339263402634126342263432634426345263462634726348263492635026351263522635326354263552635626357263582635926360263612636226363263642636526366263672636826369263702637126372263732637426375263762637726378263792638026381263822638326384263852638626387263882638926390263912639226393263942639526396263972639826399264002640126402264032640426405264062640726408264092641026411264122641326414264152641626417264182641926420264212642226423264242642526426264272642826429264302643126432264332643426435264362643726438264392644026441264422644326444264452644626447264482644926450264512645226453264542645526456264572645826459264602646126462264632646426465264662646726468264692647026471264722647326474264752647626477264782647926480264812648226483264842648526486264872648826489264902649126492264932649426495264962649726498264992650026501265022650326504265052650626507265082650926510265112651226513265142651526516265172651826519265202652126522265232652426525265262652726528265292653026531265322653326534265352653626537265382653926540265412654226543265442654526546265472654826549265502655126552265532655426555265562655726558265592656026561265622656326564265652656626567265682656926570265712657226573265742657526576265772657826579265802658126582265832658426585265862658726588265892659026591265922659326594265952659626597265982659926600266012660226603266042660526606266072660826609266102661126612266132661426615266162661726618266192662026621266222662326624266252662626627266282662926630266312663226633266342663526636266372663826639266402664126642266432664426645266462664726648266492665026651266522665326654266552665626657266582665926660266612666226663266642666526666266672666826669266702667126672266732667426675266762667726678266792668026681266822668326684266852668626687266882668926690266912669226693266942669526696266972669826699267002670126702267032670426705267062670726708267092671026711267122671326714267152671626717267182671926720267212672226723267242672526726267272672826729267302673126732267332673426735267362673726738267392674026741267422674326744267452674626747267482674926750267512675226753267542675526756267572675826759267602676126762267632676426765267662676726768267692677026771267722677326774267752677626777267782677926780267812678226783267842678526786267872678826789267902679126792267932679426795267962679726798267992680026801268022680326804268052680626807268082680926810268112681226813268142681526816268172681826819268202682126822268232682426825268262682726828268292683026831268322683326834268352683626837268382683926840268412684226843268442684526846268472684826849268502685126852268532685426855268562685726858268592686026861268622686326864268652686626867268682686926870268712687226873268742687526876268772687826879268802688126882268832688426885268862688726888268892689026891268922689326894268952689626897268982689926900269012690226903269042690526906269072690826909269102691126912269132691426915269162691726918269192692026921269222692326924269252692626927269282692926930269312693226933269342693526936269372693826939269402694126942269432694426945269462694726948269492695026951269522695326954269552695626957269582695926960269612696226963269642696526966269672696826969269702697126972269732697426975269762697726978269792698026981269822698326984269852698626987269882698926990269912699226993269942699526996269972699826999270002700127002270032700427005270062700727008270092701027011270122701327014270152701627017270182701927020270212702227023270242702527026270272702827029270302703127032270332703427035270362703727038270392704027041270422704327044270452704627047270482704927050270512705227053270542705527056270572705827059270602706127062270632706427065270662706727068270692707027071270722707327074270752707627077270782707927080270812708227083270842708527086270872708827089270902709127092270932709427095270962709727098270992710027101271022710327104271052710627107271082710927110271112711227113271142711527116271172711827119271202712127122271232712427125271262712727128271292713027131271322713327134271352713627137271382713927140271412714227143271442714527146271472714827149271502715127152271532715427155271562715727158271592716027161271622716327164271652716627167271682716927170271712717227173271742717527176271772717827179271802718127182271832718427185271862718727188271892719027191271922719327194271952719627197271982719927200272012720227203272042720527206272072720827209272102721127212272132721427215272162721727218272192722027221272222722327224272252722627227272282722927230272312723227233272342723527236272372723827239272402724127242272432724427245272462724727248272492725027251272522725327254272552725627257272582725927260272612726227263272642726527266272672726827269272702727127272272732727427275272762727727278272792728027281272822728327284272852728627287272882728927290272912729227293272942729527296272972729827299273002730127302273032730427305273062730727308273092731027311273122731327314273152731627317273182731927320273212732227323273242732527326273272732827329273302733127332273332733427335273362733727338273392734027341273422734327344273452734627347273482734927350273512735227353273542735527356273572735827359273602736127362273632736427365273662736727368273692737027371273722737327374273752737627377273782737927380273812738227383273842738527386273872738827389273902739127392273932739427395273962739727398273992740027401274022740327404274052740627407274082740927410274112741227413274142741527416274172741827419274202742127422274232742427425274262742727428274292743027431274322743327434274352743627437274382743927440274412744227443274442744527446274472744827449274502745127452274532745427455274562745727458274592746027461274622746327464274652746627467274682746927470274712747227473274742747527476274772747827479274802748127482274832748427485274862748727488274892749027491274922749327494274952749627497274982749927500275012750227503275042750527506275072750827509275102751127512275132751427515275162751727518275192752027521275222752327524275252752627527275282752927530275312753227533275342753527536275372753827539275402754127542275432754427545275462754727548275492755027551275522755327554275552755627557275582755927560275612756227563275642756527566275672756827569275702757127572275732757427575275762757727578275792758027581275822758327584275852758627587275882758927590275912759227593275942759527596275972759827599276002760127602276032760427605276062760727608276092761027611276122761327614276152761627617276182761927620276212762227623276242762527626276272762827629276302763127632276332763427635276362763727638276392764027641276422764327644276452764627647276482764927650276512765227653276542765527656276572765827659276602766127662276632766427665276662766727668276692767027671276722767327674276752767627677276782767927680276812768227683276842768527686276872768827689276902769127692276932769427695276962769727698276992770027701277022770327704277052770627707277082770927710277112771227713277142771527716277172771827719277202772127722277232772427725277262772727728277292773027731277322773327734277352773627737277382773927740277412774227743277442774527746277472774827749277502775127752277532775427755277562775727758277592776027761277622776327764277652776627767277682776927770277712777227773277742777527776277772777827779277802778127782277832778427785277862778727788277892779027791277922779327794277952779627797277982779927800278012780227803278042780527806278072780827809278102781127812278132781427815278162781727818278192782027821278222782327824278252782627827278282782927830278312783227833278342783527836278372783827839278402784127842278432784427845278462784727848278492785027851278522785327854278552785627857278582785927860278612786227863278642786527866278672786827869278702787127872278732787427875278762787727878278792788027881278822788327884278852788627887278882788927890278912789227893278942789527896278972789827899279002790127902279032790427905279062790727908279092791027911279122791327914279152791627917279182791927920279212792227923279242792527926279272792827929279302793127932279332793427935279362793727938279392794027941279422794327944279452794627947279482794927950279512795227953279542795527956279572795827959279602796127962279632796427965279662796727968279692797027971279722797327974279752797627977279782797927980279812798227983279842798527986279872798827989279902799127992279932799427995279962799727998279992800028001280022800328004280052800628007280082800928010280112801228013280142801528016280172801828019280202802128022280232802428025280262802728028280292803028031280322803328034280352803628037280382803928040280412804228043280442804528046280472804828049280502805128052280532805428055280562805728058280592806028061280622806328064280652806628067280682806928070280712807228073280742807528076280772807828079280802808128082280832808428085280862808728088280892809028091280922809328094280952809628097280982809928100281012810228103281042810528106281072810828109281102811128112281132811428115281162811728118281192812028121281222812328124281252812628127281282812928130281312813228133281342813528136281372813828139281402814128142281432814428145281462814728148281492815028151281522815328154281552815628157281582815928160281612816228163281642816528166281672816828169281702817128172281732817428175281762817728178281792818028181281822818328184281852818628187281882818928190281912819228193281942819528196281972819828199282002820128202282032820428205282062820728208282092821028211282122821328214282152821628217282182821928220282212822228223282242822528226282272822828229282302823128232282332823428235282362823728238282392824028241282422824328244282452824628247282482824928250282512825228253282542825528256282572825828259282602826128262282632826428265282662826728268282692827028271282722827328274282752827628277282782827928280282812828228283282842828528286282872828828289282902829128292282932829428295282962829728298282992830028301283022830328304283052830628307283082830928310283112831228313283142831528316283172831828319283202832128322283232832428325283262832728328283292833028331283322833328334283352833628337283382833928340283412834228343283442834528346283472834828349283502835128352283532835428355283562835728358283592836028361283622836328364283652836628367283682836928370283712837228373283742837528376283772837828379283802838128382283832838428385283862838728388283892839028391283922839328394283952839628397283982839928400284012840228403284042840528406284072840828409284102841128412284132841428415284162841728418284192842028421284222842328424284252842628427284282842928430284312843228433284342843528436284372843828439284402844128442284432844428445284462844728448284492845028451284522845328454284552845628457284582845928460284612846228463284642846528466284672846828469284702847128472284732847428475284762847728478284792848028481284822848328484284852848628487284882848928490284912849228493284942849528496284972849828499285002850128502285032850428505285062850728508285092851028511285122851328514285152851628517285182851928520285212852228523285242852528526285272852828529285302853128532285332853428535285362853728538285392854028541285422854328544285452854628547285482854928550285512855228553285542855528556285572855828559285602856128562285632856428565285662856728568285692857028571285722857328574285752857628577285782857928580285812858228583285842858528586285872858828589285902859128592285932859428595285962859728598285992860028601286022860328604286052860628607286082860928610286112861228613286142861528616286172861828619286202862128622286232862428625286262862728628286292863028631286322863328634286352863628637286382863928640286412864228643286442864528646286472864828649286502865128652286532865428655286562865728658286592866028661286622866328664286652866628667286682866928670286712867228673286742867528676286772867828679286802868128682286832868428685286862868728688286892869028691286922869328694286952869628697286982869928700287012870228703287042870528706287072870828709287102871128712287132871428715287162871728718287192872028721287222872328724287252872628727287282872928730287312873228733287342873528736287372873828739287402874128742287432874428745287462874728748287492875028751287522875328754287552875628757287582875928760287612876228763287642876528766287672876828769287702877128772287732877428775287762877728778287792878028781287822878328784287852878628787287882878928790287912879228793287942879528796287972879828799288002880128802288032880428805288062880728808288092881028811288122881328814288152881628817288182881928820288212882228823288242882528826288272882828829288302883128832288332883428835288362883728838288392884028841288422884328844288452884628847288482884928850288512885228853288542885528856288572885828859288602886128862288632886428865288662886728868288692887028871288722887328874288752887628877288782887928880288812888228883288842888528886288872888828889288902889128892288932889428895288962889728898288992890028901289022890328904289052890628907289082890928910289112891228913289142891528916289172891828919289202892128922289232892428925289262892728928289292893028931289322893328934289352893628937289382893928940289412894228943289442894528946289472894828949289502895128952289532895428955289562895728958289592896028961289622896328964289652896628967289682896928970289712897228973289742897528976289772897828979289802898128982289832898428985289862898728988289892899028991289922899328994289952899628997289982899929000290012900229003290042900529006290072900829009290102901129012290132901429015290162901729018290192902029021290222902329024290252902629027290282902929030290312903229033290342903529036290372903829039290402904129042290432904429045290462904729048290492905029051290522905329054290552905629057290582905929060290612906229063290642906529066290672906829069290702907129072290732907429075290762907729078290792908029081290822908329084290852908629087290882908929090290912909229093290942909529096290972909829099291002910129102291032910429105291062910729108291092911029111291122911329114291152911629117291182911929120291212912229123291242912529126291272912829129291302913129132291332913429135291362913729138291392914029141291422914329144291452914629147291482914929150291512915229153291542915529156291572915829159291602916129162291632916429165291662916729168291692917029171291722917329174291752917629177291782917929180291812918229183291842918529186291872918829189291902919129192291932919429195291962919729198291992920029201292022920329204292052920629207292082920929210292112921229213292142921529216292172921829219292202922129222292232922429225292262922729228292292923029231292322923329234292352923629237292382923929240292412924229243292442924529246292472924829249292502925129252292532925429255292562925729258292592926029261292622926329264292652926629267292682926929270292712927229273292742927529276292772927829279292802928129282292832928429285292862928729288292892929029291292922929329294292952929629297292982929929300293012930229303293042930529306293072930829309293102931129312293132931429315293162931729318293192932029321293222932329324293252932629327293282932929330293312933229333293342933529336293372933829339293402934129342293432934429345293462934729348293492935029351293522935329354293552935629357293582935929360293612936229363293642936529366293672936829369293702937129372293732937429375293762937729378293792938029381293822938329384293852938629387293882938929390293912939229393293942939529396293972939829399294002940129402294032940429405294062940729408294092941029411294122941329414294152941629417294182941929420294212942229423294242942529426294272942829429294302943129432294332943429435294362943729438294392944029441294422944329444294452944629447294482944929450294512945229453294542945529456294572945829459294602946129462294632946429465294662946729468294692947029471294722947329474294752947629477294782947929480294812948229483294842948529486294872948829489294902949129492294932949429495294962949729498294992950029501295022950329504295052950629507295082950929510295112951229513295142951529516295172951829519295202952129522295232952429525295262952729528295292953029531295322953329534295352953629537295382953929540295412954229543295442954529546295472954829549295502955129552295532955429555295562955729558295592956029561295622956329564295652956629567295682956929570295712957229573295742957529576295772957829579295802958129582295832958429585295862958729588295892959029591295922959329594295952959629597295982959929600296012960229603296042960529606296072960829609296102961129612296132961429615296162961729618296192962029621296222962329624296252962629627296282962929630296312963229633296342963529636296372963829639296402964129642296432964429645296462964729648296492965029651296522965329654296552965629657296582965929660296612966229663296642966529666296672966829669296702967129672296732967429675296762967729678296792968029681296822968329684296852968629687296882968929690296912969229693296942969529696296972969829699297002970129702297032970429705297062970729708297092971029711297122971329714297152971629717297182971929720297212972229723297242972529726297272972829729297302973129732297332973429735297362973729738297392974029741297422974329744297452974629747297482974929750297512975229753297542975529756297572975829759297602976129762297632976429765297662976729768297692977029771297722977329774297752977629777297782977929780297812978229783297842978529786297872978829789297902979129792297932979429795297962979729798297992980029801298022980329804298052980629807298082980929810298112981229813298142981529816298172981829819298202982129822298232982429825298262982729828298292983029831298322983329834298352983629837298382983929840298412984229843298442984529846298472984829849298502985129852298532985429855298562985729858298592986029861298622986329864298652986629867298682986929870298712987229873298742987529876298772987829879298802988129882298832988429885298862988729888298892989029891298922989329894298952989629897298982989929900299012990229903299042990529906299072990829909299102991129912299132991429915299162991729918299192992029921299222992329924299252992629927299282992929930299312993229933299342993529936299372993829939299402994129942299432994429945299462994729948299492995029951299522995329954299552995629957299582995929960299612996229963299642996529966299672996829969299702997129972299732997429975299762997729978299792998029981299822998329984299852998629987299882998929990299912999229993299942999529996
  1. /**
  2. * TinyMCE version 6.4.2 (2023-04-26)
  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. class Optional {
  91. constructor(tag, value) {
  92. this.tag = tag;
  93. this.value = value;
  94. }
  95. static some(value) {
  96. return new Optional(true, value);
  97. }
  98. static none() {
  99. return Optional.singletonNone;
  100. }
  101. fold(onNone, onSome) {
  102. if (this.tag) {
  103. return onSome(this.value);
  104. } else {
  105. return onNone();
  106. }
  107. }
  108. isSome() {
  109. return this.tag;
  110. }
  111. isNone() {
  112. return !this.tag;
  113. }
  114. map(mapper) {
  115. if (this.tag) {
  116. return Optional.some(mapper(this.value));
  117. } else {
  118. return Optional.none();
  119. }
  120. }
  121. bind(binder) {
  122. if (this.tag) {
  123. return binder(this.value);
  124. } else {
  125. return Optional.none();
  126. }
  127. }
  128. exists(predicate) {
  129. return this.tag && predicate(this.value);
  130. }
  131. forall(predicate) {
  132. return !this.tag || predicate(this.value);
  133. }
  134. filter(predicate) {
  135. if (!this.tag || predicate(this.value)) {
  136. return this;
  137. } else {
  138. return Optional.none();
  139. }
  140. }
  141. getOr(replacement) {
  142. return this.tag ? this.value : replacement;
  143. }
  144. or(replacement) {
  145. return this.tag ? this : replacement;
  146. }
  147. getOrThunk(thunk) {
  148. return this.tag ? this.value : thunk();
  149. }
  150. orThunk(thunk) {
  151. return this.tag ? this : thunk();
  152. }
  153. getOrDie(message) {
  154. if (!this.tag) {
  155. throw new Error(message !== null && message !== void 0 ? message : 'Called getOrDie on None');
  156. } else {
  157. return this.value;
  158. }
  159. }
  160. static from(value) {
  161. return isNonNullable(value) ? Optional.some(value) : Optional.none();
  162. }
  163. getOrNull() {
  164. return this.tag ? this.value : null;
  165. }
  166. getOrUndefined() {
  167. return this.value;
  168. }
  169. each(worker) {
  170. if (this.tag) {
  171. worker(this.value);
  172. }
  173. }
  174. toArray() {
  175. return this.tag ? [this.value] : [];
  176. }
  177. toString() {
  178. return this.tag ? `some(${ this.value })` : 'none()';
  179. }
  180. }
  181. Optional.singletonNone = new Optional(false);
  182. const nativeSlice = Array.prototype.slice;
  183. const nativeIndexOf = Array.prototype.indexOf;
  184. const nativePush = Array.prototype.push;
  185. const rawIndexOf = (ts, t) => nativeIndexOf.call(ts, t);
  186. const indexOf = (xs, x) => {
  187. const r = rawIndexOf(xs, x);
  188. return r === -1 ? Optional.none() : Optional.some(r);
  189. };
  190. const contains$2 = (xs, x) => rawIndexOf(xs, x) > -1;
  191. const exists = (xs, pred) => {
  192. for (let i = 0, len = xs.length; i < len; i++) {
  193. const x = xs[i];
  194. if (pred(x, i)) {
  195. return true;
  196. }
  197. }
  198. return false;
  199. };
  200. const range$2 = (num, f) => {
  201. const r = [];
  202. for (let i = 0; i < num; i++) {
  203. r.push(f(i));
  204. }
  205. return r;
  206. };
  207. const chunk$1 = (array, size) => {
  208. const r = [];
  209. for (let i = 0; i < array.length; i += size) {
  210. const s = nativeSlice.call(array, i, i + size);
  211. r.push(s);
  212. }
  213. return r;
  214. };
  215. const map$2 = (xs, f) => {
  216. const len = xs.length;
  217. const r = new Array(len);
  218. for (let i = 0; i < len; i++) {
  219. const x = xs[i];
  220. r[i] = f(x, i);
  221. }
  222. return r;
  223. };
  224. const each$1 = (xs, f) => {
  225. for (let i = 0, len = xs.length; i < len; i++) {
  226. const x = xs[i];
  227. f(x, i);
  228. }
  229. };
  230. const eachr = (xs, f) => {
  231. for (let i = xs.length - 1; i >= 0; i--) {
  232. const x = xs[i];
  233. f(x, i);
  234. }
  235. };
  236. const partition$3 = (xs, pred) => {
  237. const pass = [];
  238. const fail = [];
  239. for (let i = 0, len = xs.length; i < len; i++) {
  240. const x = xs[i];
  241. const arr = pred(x, i) ? pass : fail;
  242. arr.push(x);
  243. }
  244. return {
  245. pass,
  246. fail
  247. };
  248. };
  249. const filter$2 = (xs, pred) => {
  250. const r = [];
  251. for (let i = 0, len = xs.length; i < len; i++) {
  252. const x = xs[i];
  253. if (pred(x, i)) {
  254. r.push(x);
  255. }
  256. }
  257. return r;
  258. };
  259. const foldr = (xs, f, acc) => {
  260. eachr(xs, (x, i) => {
  261. acc = f(acc, x, i);
  262. });
  263. return acc;
  264. };
  265. const foldl = (xs, f, acc) => {
  266. each$1(xs, (x, i) => {
  267. acc = f(acc, x, i);
  268. });
  269. return acc;
  270. };
  271. const findUntil = (xs, pred, until) => {
  272. for (let i = 0, len = xs.length; i < len; i++) {
  273. const x = xs[i];
  274. if (pred(x, i)) {
  275. return Optional.some(x);
  276. } else if (until(x, i)) {
  277. break;
  278. }
  279. }
  280. return Optional.none();
  281. };
  282. const find$5 = (xs, pred) => {
  283. return findUntil(xs, pred, never);
  284. };
  285. const findIndex$1 = (xs, pred) => {
  286. for (let i = 0, len = xs.length; i < len; i++) {
  287. const x = xs[i];
  288. if (pred(x, i)) {
  289. return Optional.some(i);
  290. }
  291. }
  292. return Optional.none();
  293. };
  294. const flatten = xs => {
  295. const r = [];
  296. for (let i = 0, len = xs.length; i < len; ++i) {
  297. if (!isArray(xs[i])) {
  298. throw new Error('Arr.flatten item ' + i + ' was not an array, input: ' + xs);
  299. }
  300. nativePush.apply(r, xs[i]);
  301. }
  302. return r;
  303. };
  304. const bind$3 = (xs, f) => flatten(map$2(xs, f));
  305. const forall = (xs, pred) => {
  306. for (let i = 0, len = xs.length; i < len; ++i) {
  307. const x = xs[i];
  308. if (pred(x, i) !== true) {
  309. return false;
  310. }
  311. }
  312. return true;
  313. };
  314. const reverse = xs => {
  315. const r = nativeSlice.call(xs, 0);
  316. r.reverse();
  317. return r;
  318. };
  319. const difference = (a1, a2) => filter$2(a1, x => !contains$2(a2, x));
  320. const mapToObject = (xs, f) => {
  321. const r = {};
  322. for (let i = 0, len = xs.length; i < len; i++) {
  323. const x = xs[i];
  324. r[String(x)] = f(x, i);
  325. }
  326. return r;
  327. };
  328. const pure$2 = x => [x];
  329. const sort = (xs, comparator) => {
  330. const copy = nativeSlice.call(xs, 0);
  331. copy.sort(comparator);
  332. return copy;
  333. };
  334. const get$h = (xs, i) => i >= 0 && i < xs.length ? Optional.some(xs[i]) : Optional.none();
  335. const head = xs => get$h(xs, 0);
  336. const last$1 = xs => get$h(xs, xs.length - 1);
  337. const from = isFunction(Array.from) ? Array.from : x => nativeSlice.call(x);
  338. const findMap = (arr, f) => {
  339. for (let i = 0; i < arr.length; i++) {
  340. const r = f(arr[i], i);
  341. if (r.isSome()) {
  342. return r;
  343. }
  344. }
  345. return Optional.none();
  346. };
  347. const keys = Object.keys;
  348. const hasOwnProperty$1 = Object.hasOwnProperty;
  349. const each = (obj, f) => {
  350. const props = keys(obj);
  351. for (let k = 0, len = props.length; k < len; k++) {
  352. const i = props[k];
  353. const x = obj[i];
  354. f(x, i);
  355. }
  356. };
  357. const map$1 = (obj, f) => {
  358. return tupleMap(obj, (x, i) => ({
  359. k: i,
  360. v: f(x, i)
  361. }));
  362. };
  363. const tupleMap = (obj, f) => {
  364. const r = {};
  365. each(obj, (x, i) => {
  366. const tuple = f(x, i);
  367. r[tuple.k] = tuple.v;
  368. });
  369. return r;
  370. };
  371. const objAcc = r => (x, i) => {
  372. r[i] = x;
  373. };
  374. const internalFilter = (obj, pred, onTrue, onFalse) => {
  375. each(obj, (x, i) => {
  376. (pred(x, i) ? onTrue : onFalse)(x, i);
  377. });
  378. };
  379. const bifilter = (obj, pred) => {
  380. const t = {};
  381. const f = {};
  382. internalFilter(obj, pred, objAcc(t), objAcc(f));
  383. return {
  384. t,
  385. f
  386. };
  387. };
  388. const filter$1 = (obj, pred) => {
  389. const t = {};
  390. internalFilter(obj, pred, objAcc(t), noop);
  391. return t;
  392. };
  393. const mapToArray = (obj, f) => {
  394. const r = [];
  395. each(obj, (value, name) => {
  396. r.push(f(value, name));
  397. });
  398. return r;
  399. };
  400. const find$4 = (obj, pred) => {
  401. const props = keys(obj);
  402. for (let k = 0, len = props.length; k < len; k++) {
  403. const i = props[k];
  404. const x = obj[i];
  405. if (pred(x, i, obj)) {
  406. return Optional.some(x);
  407. }
  408. }
  409. return Optional.none();
  410. };
  411. const values = obj => {
  412. return mapToArray(obj, identity);
  413. };
  414. const get$g = (obj, key) => {
  415. return has$2(obj, key) ? Optional.from(obj[key]) : Optional.none();
  416. };
  417. const has$2 = (obj, key) => hasOwnProperty$1.call(obj, key);
  418. const hasNonNullableKey = (obj, key) => has$2(obj, key) && obj[key] !== undefined && obj[key] !== null;
  419. const is$1 = (lhs, rhs, comparator = tripleEquals) => lhs.exists(left => comparator(left, rhs));
  420. const equals = (lhs, rhs, comparator = tripleEquals) => lift2(lhs, rhs, comparator).getOr(lhs.isNone() && rhs.isNone());
  421. const cat = arr => {
  422. const r = [];
  423. const push = x => {
  424. r.push(x);
  425. };
  426. for (let i = 0; i < arr.length; i++) {
  427. arr[i].each(push);
  428. }
  429. return r;
  430. };
  431. const sequence = arr => {
  432. const r = [];
  433. for (let i = 0; i < arr.length; i++) {
  434. const x = arr[i];
  435. if (x.isSome()) {
  436. r.push(x.getOrDie());
  437. } else {
  438. return Optional.none();
  439. }
  440. }
  441. return Optional.some(r);
  442. };
  443. const lift2 = (oa, ob, f) => oa.isSome() && ob.isSome() ? Optional.some(f(oa.getOrDie(), ob.getOrDie())) : Optional.none();
  444. const lift3 = (oa, ob, oc, f) => oa.isSome() && ob.isSome() && oc.isSome() ? Optional.some(f(oa.getOrDie(), ob.getOrDie(), oc.getOrDie())) : Optional.none();
  445. const mapFrom = (a, f) => a !== undefined && a !== null ? Optional.some(f(a)) : Optional.none();
  446. const someIf = (b, a) => b ? Optional.some(a) : Optional.none();
  447. const addToEnd = (str, suffix) => {
  448. return str + suffix;
  449. };
  450. const removeFromStart = (str, numChars) => {
  451. return str.substring(numChars);
  452. };
  453. const checkRange = (str, substr, start) => substr === '' || str.length >= substr.length && str.substr(start, start + substr.length) === substr;
  454. const removeLeading = (str, prefix) => {
  455. return startsWith(str, prefix) ? removeFromStart(str, prefix.length) : str;
  456. };
  457. const ensureTrailing = (str, suffix) => {
  458. return endsWith(str, suffix) ? str : addToEnd(str, suffix);
  459. };
  460. const contains$1 = (str, substr, start = 0, end) => {
  461. const idx = str.indexOf(substr, start);
  462. if (idx !== -1) {
  463. return isUndefined(end) ? true : idx + substr.length <= end;
  464. } else {
  465. return false;
  466. }
  467. };
  468. const startsWith = (str, prefix) => {
  469. return checkRange(str, prefix, 0);
  470. };
  471. const endsWith = (str, suffix) => {
  472. return checkRange(str, suffix, str.length - suffix.length);
  473. };
  474. const blank = r => s => s.replace(r, '');
  475. const trim$1 = blank(/^\s+|\s+$/g);
  476. const isNotEmpty = s => s.length > 0;
  477. const isEmpty = s => !isNotEmpty(s);
  478. const isSupported$1 = dom => dom.style !== undefined && isFunction(dom.style.getPropertyValue);
  479. const fromHtml$2 = (html, scope) => {
  480. const doc = scope || document;
  481. const div = doc.createElement('div');
  482. div.innerHTML = html;
  483. if (!div.hasChildNodes() || div.childNodes.length > 1) {
  484. const message = 'HTML does not have a single root node';
  485. console.error(message, html);
  486. throw new Error(message);
  487. }
  488. return fromDom(div.childNodes[0]);
  489. };
  490. const fromTag = (tag, scope) => {
  491. const doc = scope || document;
  492. const node = doc.createElement(tag);
  493. return fromDom(node);
  494. };
  495. const fromText = (text, scope) => {
  496. const doc = scope || document;
  497. const node = doc.createTextNode(text);
  498. return fromDom(node);
  499. };
  500. const fromDom = node => {
  501. if (node === null || node === undefined) {
  502. throw new Error('Node cannot be null or undefined');
  503. }
  504. return { dom: node };
  505. };
  506. const fromPoint = (docElm, x, y) => Optional.from(docElm.dom.elementFromPoint(x, y)).map(fromDom);
  507. const SugarElement = {
  508. fromHtml: fromHtml$2,
  509. fromTag,
  510. fromText,
  511. fromDom,
  512. fromPoint
  513. };
  514. const Global = typeof window !== 'undefined' ? window : Function('return this;')();
  515. const path$1 = (parts, scope) => {
  516. let o = scope !== undefined && scope !== null ? scope : Global;
  517. for (let i = 0; i < parts.length && o !== undefined && o !== null; ++i) {
  518. o = o[parts[i]];
  519. }
  520. return o;
  521. };
  522. const resolve = (p, scope) => {
  523. const parts = p.split('.');
  524. return path$1(parts, scope);
  525. };
  526. const unsafe = (name, scope) => {
  527. return resolve(name, scope);
  528. };
  529. const getOrDie$1 = (name, scope) => {
  530. const actual = unsafe(name, scope);
  531. if (actual === undefined || actual === null) {
  532. throw new Error(name + ' not available on this browser');
  533. }
  534. return actual;
  535. };
  536. const getPrototypeOf$1 = Object.getPrototypeOf;
  537. const sandHTMLElement = scope => {
  538. return getOrDie$1('HTMLElement', scope);
  539. };
  540. const isPrototypeOf = x => {
  541. const scope = resolve('ownerDocument.defaultView', x);
  542. return isObject(x) && (sandHTMLElement(scope).prototype.isPrototypeOf(x) || /^HTML\w*Element$/.test(getPrototypeOf$1(x).constructor.name));
  543. };
  544. const DOCUMENT = 9;
  545. const DOCUMENT_FRAGMENT = 11;
  546. const ELEMENT = 1;
  547. const TEXT = 3;
  548. const name$3 = element => {
  549. const r = element.dom.nodeName;
  550. return r.toLowerCase();
  551. };
  552. const type$1 = element => element.dom.nodeType;
  553. const isType = t => element => type$1(element) === t;
  554. const isHTMLElement = element => isElement$1(element) && isPrototypeOf(element.dom);
  555. const isElement$1 = isType(ELEMENT);
  556. const isText = isType(TEXT);
  557. const isDocument = isType(DOCUMENT);
  558. const isDocumentFragment = isType(DOCUMENT_FRAGMENT);
  559. const isTag = tag => e => isElement$1(e) && name$3(e) === tag;
  560. const is = (element, selector) => {
  561. const dom = element.dom;
  562. if (dom.nodeType !== ELEMENT) {
  563. return false;
  564. } else {
  565. const elem = dom;
  566. if (elem.matches !== undefined) {
  567. return elem.matches(selector);
  568. } else if (elem.msMatchesSelector !== undefined) {
  569. return elem.msMatchesSelector(selector);
  570. } else if (elem.webkitMatchesSelector !== undefined) {
  571. return elem.webkitMatchesSelector(selector);
  572. } else if (elem.mozMatchesSelector !== undefined) {
  573. return elem.mozMatchesSelector(selector);
  574. } else {
  575. throw new Error('Browser lacks native selectors');
  576. }
  577. }
  578. };
  579. const bypassSelector = dom => dom.nodeType !== ELEMENT && dom.nodeType !== DOCUMENT && dom.nodeType !== DOCUMENT_FRAGMENT || dom.childElementCount === 0;
  580. const all$3 = (selector, scope) => {
  581. const base = scope === undefined ? document : scope.dom;
  582. return bypassSelector(base) ? [] : map$2(base.querySelectorAll(selector), SugarElement.fromDom);
  583. };
  584. const one = (selector, scope) => {
  585. const base = scope === undefined ? document : scope.dom;
  586. return bypassSelector(base) ? Optional.none() : Optional.from(base.querySelector(selector)).map(SugarElement.fromDom);
  587. };
  588. const eq = (e1, e2) => e1.dom === e2.dom;
  589. const contains = (e1, e2) => {
  590. const d1 = e1.dom;
  591. const d2 = e2.dom;
  592. return d1 === d2 ? false : d1.contains(d2);
  593. };
  594. const owner$4 = element => SugarElement.fromDom(element.dom.ownerDocument);
  595. const documentOrOwner = dos => isDocument(dos) ? dos : owner$4(dos);
  596. const documentElement = element => SugarElement.fromDom(documentOrOwner(element).dom.documentElement);
  597. const defaultView = element => SugarElement.fromDom(documentOrOwner(element).dom.defaultView);
  598. const parent = element => Optional.from(element.dom.parentNode).map(SugarElement.fromDom);
  599. const parentElement = element => Optional.from(element.dom.parentElement).map(SugarElement.fromDom);
  600. const parents = (element, isRoot) => {
  601. const stop = isFunction(isRoot) ? isRoot : never;
  602. let dom = element.dom;
  603. const ret = [];
  604. while (dom.parentNode !== null && dom.parentNode !== undefined) {
  605. const rawParent = dom.parentNode;
  606. const p = SugarElement.fromDom(rawParent);
  607. ret.push(p);
  608. if (stop(p) === true) {
  609. break;
  610. } else {
  611. dom = rawParent;
  612. }
  613. }
  614. return ret;
  615. };
  616. const offsetParent = element => Optional.from(element.dom.offsetParent).map(SugarElement.fromDom);
  617. const nextSibling = element => Optional.from(element.dom.nextSibling).map(SugarElement.fromDom);
  618. const children = element => map$2(element.dom.childNodes, SugarElement.fromDom);
  619. const child$2 = (element, index) => {
  620. const cs = element.dom.childNodes;
  621. return Optional.from(cs[index]).map(SugarElement.fromDom);
  622. };
  623. const firstChild = element => child$2(element, 0);
  624. const spot = (element, offset) => ({
  625. element,
  626. offset
  627. });
  628. const leaf = (element, offset) => {
  629. const cs = children(element);
  630. return cs.length > 0 && offset < cs.length ? spot(cs[offset], 0) : spot(element, offset);
  631. };
  632. const isShadowRoot = dos => isDocumentFragment(dos) && isNonNullable(dos.dom.host);
  633. const supported = isFunction(Element.prototype.attachShadow) && isFunction(Node.prototype.getRootNode);
  634. const isSupported = constant$1(supported);
  635. const getRootNode = supported ? e => SugarElement.fromDom(e.dom.getRootNode()) : documentOrOwner;
  636. const getContentContainer = dos => isShadowRoot(dos) ? dos : SugarElement.fromDom(documentOrOwner(dos).dom.body);
  637. const isInShadowRoot = e => getShadowRoot(e).isSome();
  638. const getShadowRoot = e => {
  639. const r = getRootNode(e);
  640. return isShadowRoot(r) ? Optional.some(r) : Optional.none();
  641. };
  642. const getShadowHost = e => SugarElement.fromDom(e.dom.host);
  643. const getOriginalEventTarget = event => {
  644. if (isSupported() && isNonNullable(event.target)) {
  645. const el = SugarElement.fromDom(event.target);
  646. if (isElement$1(el) && isOpenShadowHost(el)) {
  647. if (event.composed && event.composedPath) {
  648. const composedPath = event.composedPath();
  649. if (composedPath) {
  650. return head(composedPath);
  651. }
  652. }
  653. }
  654. }
  655. return Optional.from(event.target);
  656. };
  657. const isOpenShadowHost = element => isNonNullable(element.dom.shadowRoot);
  658. const inBody = element => {
  659. const dom = isText(element) ? element.dom.parentNode : element.dom;
  660. if (dom === undefined || dom === null || dom.ownerDocument === null) {
  661. return false;
  662. }
  663. const doc = dom.ownerDocument;
  664. return getShadowRoot(SugarElement.fromDom(dom)).fold(() => doc.body.contains(dom), compose1(inBody, getShadowHost));
  665. };
  666. const body = () => getBody(SugarElement.fromDom(document));
  667. const getBody = doc => {
  668. const b = doc.dom.body;
  669. if (b === null || b === undefined) {
  670. throw new Error('Body is not available yet');
  671. }
  672. return SugarElement.fromDom(b);
  673. };
  674. const rawSet = (dom, key, value) => {
  675. if (isString(value) || isBoolean(value) || isNumber(value)) {
  676. dom.setAttribute(key, value + '');
  677. } else {
  678. console.error('Invalid call to Attribute.set. Key ', key, ':: Value ', value, ':: Element ', dom);
  679. throw new Error('Attribute value was not simple');
  680. }
  681. };
  682. const set$9 = (element, key, value) => {
  683. rawSet(element.dom, key, value);
  684. };
  685. const setAll$1 = (element, attrs) => {
  686. const dom = element.dom;
  687. each(attrs, (v, k) => {
  688. rawSet(dom, k, v);
  689. });
  690. };
  691. const get$f = (element, key) => {
  692. const v = element.dom.getAttribute(key);
  693. return v === null ? undefined : v;
  694. };
  695. const getOpt = (element, key) => Optional.from(get$f(element, key));
  696. const has$1 = (element, key) => {
  697. const dom = element.dom;
  698. return dom && dom.hasAttribute ? dom.hasAttribute(key) : false;
  699. };
  700. const remove$7 = (element, key) => {
  701. element.dom.removeAttribute(key);
  702. };
  703. const clone$2 = element => foldl(element.dom.attributes, (acc, attr) => {
  704. acc[attr.name] = attr.value;
  705. return acc;
  706. }, {});
  707. const internalSet = (dom, property, value) => {
  708. if (!isString(value)) {
  709. console.error('Invalid call to CSS.set. Property ', property, ':: Value ', value, ':: Element ', dom);
  710. throw new Error('CSS value must be a string: ' + value);
  711. }
  712. if (isSupported$1(dom)) {
  713. dom.style.setProperty(property, value);
  714. }
  715. };
  716. const internalRemove = (dom, property) => {
  717. if (isSupported$1(dom)) {
  718. dom.style.removeProperty(property);
  719. }
  720. };
  721. const set$8 = (element, property, value) => {
  722. const dom = element.dom;
  723. internalSet(dom, property, value);
  724. };
  725. const setAll = (element, css) => {
  726. const dom = element.dom;
  727. each(css, (v, k) => {
  728. internalSet(dom, k, v);
  729. });
  730. };
  731. const setOptions = (element, css) => {
  732. const dom = element.dom;
  733. each(css, (v, k) => {
  734. v.fold(() => {
  735. internalRemove(dom, k);
  736. }, value => {
  737. internalSet(dom, k, value);
  738. });
  739. });
  740. };
  741. const get$e = (element, property) => {
  742. const dom = element.dom;
  743. const styles = window.getComputedStyle(dom);
  744. const r = styles.getPropertyValue(property);
  745. return r === '' && !inBody(element) ? getUnsafeProperty(dom, property) : r;
  746. };
  747. const getUnsafeProperty = (dom, property) => isSupported$1(dom) ? dom.style.getPropertyValue(property) : '';
  748. const getRaw = (element, property) => {
  749. const dom = element.dom;
  750. const raw = getUnsafeProperty(dom, property);
  751. return Optional.from(raw).filter(r => r.length > 0);
  752. };
  753. const getAllRaw = element => {
  754. const css = {};
  755. const dom = element.dom;
  756. if (isSupported$1(dom)) {
  757. for (let i = 0; i < dom.style.length; i++) {
  758. const ruleName = dom.style.item(i);
  759. css[ruleName] = dom.style[ruleName];
  760. }
  761. }
  762. return css;
  763. };
  764. const isValidValue$1 = (tag, property, value) => {
  765. const element = SugarElement.fromTag(tag);
  766. set$8(element, property, value);
  767. const style = getRaw(element, property);
  768. return style.isSome();
  769. };
  770. const remove$6 = (element, property) => {
  771. const dom = element.dom;
  772. internalRemove(dom, property);
  773. if (is$1(getOpt(element, 'style').map(trim$1), '')) {
  774. remove$7(element, 'style');
  775. }
  776. };
  777. const reflow = e => e.dom.offsetWidth;
  778. const Dimension = (name, getOffset) => {
  779. const set = (element, h) => {
  780. if (!isNumber(h) && !h.match(/^[0-9]+$/)) {
  781. throw new Error(name + '.set accepts only positive integer values. Value was ' + h);
  782. }
  783. const dom = element.dom;
  784. if (isSupported$1(dom)) {
  785. dom.style[name] = h + 'px';
  786. }
  787. };
  788. const get = element => {
  789. const r = getOffset(element);
  790. if (r <= 0 || r === null) {
  791. const css = get$e(element, name);
  792. return parseFloat(css) || 0;
  793. }
  794. return r;
  795. };
  796. const getOuter = get;
  797. const aggregate = (element, properties) => foldl(properties, (acc, property) => {
  798. const val = get$e(element, property);
  799. const value = val === undefined ? 0 : parseInt(val, 10);
  800. return isNaN(value) ? acc : acc + value;
  801. }, 0);
  802. const max = (element, value, properties) => {
  803. const cumulativeInclusions = aggregate(element, properties);
  804. const absoluteMax = value > cumulativeInclusions ? value - cumulativeInclusions : 0;
  805. return absoluteMax;
  806. };
  807. return {
  808. set,
  809. get,
  810. getOuter,
  811. aggregate,
  812. max
  813. };
  814. };
  815. const api$2 = Dimension('height', element => {
  816. const dom = element.dom;
  817. return inBody(element) ? dom.getBoundingClientRect().height : dom.offsetHeight;
  818. });
  819. const get$d = element => api$2.get(element);
  820. const getOuter$2 = element => api$2.getOuter(element);
  821. const setMax$1 = (element, value) => {
  822. const inclusions = [
  823. 'margin-top',
  824. 'border-top-width',
  825. 'padding-top',
  826. 'padding-bottom',
  827. 'border-bottom-width',
  828. 'margin-bottom'
  829. ];
  830. const absMax = api$2.max(element, value, inclusions);
  831. set$8(element, 'max-height', absMax + 'px');
  832. };
  833. const r$1 = (left, top) => {
  834. const translate = (x, y) => r$1(left + x, top + y);
  835. return {
  836. left,
  837. top,
  838. translate
  839. };
  840. };
  841. const SugarPosition = r$1;
  842. const boxPosition = dom => {
  843. const box = dom.getBoundingClientRect();
  844. return SugarPosition(box.left, box.top);
  845. };
  846. const firstDefinedOrZero = (a, b) => {
  847. if (a !== undefined) {
  848. return a;
  849. } else {
  850. return b !== undefined ? b : 0;
  851. }
  852. };
  853. const absolute$3 = element => {
  854. const doc = element.dom.ownerDocument;
  855. const body = doc.body;
  856. const win = doc.defaultView;
  857. const html = doc.documentElement;
  858. if (body === element.dom) {
  859. return SugarPosition(body.offsetLeft, body.offsetTop);
  860. }
  861. const scrollTop = firstDefinedOrZero(win === null || win === void 0 ? void 0 : win.pageYOffset, html.scrollTop);
  862. const scrollLeft = firstDefinedOrZero(win === null || win === void 0 ? void 0 : win.pageXOffset, html.scrollLeft);
  863. const clientTop = firstDefinedOrZero(html.clientTop, body.clientTop);
  864. const clientLeft = firstDefinedOrZero(html.clientLeft, body.clientLeft);
  865. return viewport$1(element).translate(scrollLeft - clientLeft, scrollTop - clientTop);
  866. };
  867. const viewport$1 = element => {
  868. const dom = element.dom;
  869. const doc = dom.ownerDocument;
  870. const body = doc.body;
  871. if (body === dom) {
  872. return SugarPosition(body.offsetLeft, body.offsetTop);
  873. }
  874. if (!inBody(element)) {
  875. return SugarPosition(0, 0);
  876. }
  877. return boxPosition(dom);
  878. };
  879. const api$1 = Dimension('width', element => element.dom.offsetWidth);
  880. const set$7 = (element, h) => api$1.set(element, h);
  881. const get$c = element => api$1.get(element);
  882. const getOuter$1 = element => api$1.getOuter(element);
  883. const setMax = (element, value) => {
  884. const inclusions = [
  885. 'margin-left',
  886. 'border-left-width',
  887. 'padding-left',
  888. 'padding-right',
  889. 'border-right-width',
  890. 'margin-right'
  891. ];
  892. const absMax = api$1.max(element, value, inclusions);
  893. set$8(element, 'max-width', absMax + 'px');
  894. };
  895. const cached = f => {
  896. let called = false;
  897. let r;
  898. return (...args) => {
  899. if (!called) {
  900. called = true;
  901. r = f.apply(null, args);
  902. }
  903. return r;
  904. };
  905. };
  906. const DeviceType = (os, browser, userAgent, mediaMatch) => {
  907. const isiPad = os.isiOS() && /ipad/i.test(userAgent) === true;
  908. const isiPhone = os.isiOS() && !isiPad;
  909. const isMobile = os.isiOS() || os.isAndroid();
  910. const isTouch = isMobile || mediaMatch('(pointer:coarse)');
  911. const isTablet = isiPad || !isiPhone && isMobile && mediaMatch('(min-device-width:768px)');
  912. const isPhone = isiPhone || isMobile && !isTablet;
  913. const iOSwebview = browser.isSafari() && os.isiOS() && /safari/i.test(userAgent) === false;
  914. const isDesktop = !isPhone && !isTablet && !iOSwebview;
  915. return {
  916. isiPad: constant$1(isiPad),
  917. isiPhone: constant$1(isiPhone),
  918. isTablet: constant$1(isTablet),
  919. isPhone: constant$1(isPhone),
  920. isTouch: constant$1(isTouch),
  921. isAndroid: os.isAndroid,
  922. isiOS: os.isiOS,
  923. isWebView: constant$1(iOSwebview),
  924. isDesktop: constant$1(isDesktop)
  925. };
  926. };
  927. const firstMatch = (regexes, s) => {
  928. for (let i = 0; i < regexes.length; i++) {
  929. const x = regexes[i];
  930. if (x.test(s)) {
  931. return x;
  932. }
  933. }
  934. return undefined;
  935. };
  936. const find$3 = (regexes, agent) => {
  937. const r = firstMatch(regexes, agent);
  938. if (!r) {
  939. return {
  940. major: 0,
  941. minor: 0
  942. };
  943. }
  944. const group = i => {
  945. return Number(agent.replace(r, '$' + i));
  946. };
  947. return nu$d(group(1), group(2));
  948. };
  949. const detect$5 = (versionRegexes, agent) => {
  950. const cleanedAgent = String(agent).toLowerCase();
  951. if (versionRegexes.length === 0) {
  952. return unknown$3();
  953. }
  954. return find$3(versionRegexes, cleanedAgent);
  955. };
  956. const unknown$3 = () => {
  957. return nu$d(0, 0);
  958. };
  959. const nu$d = (major, minor) => {
  960. return {
  961. major,
  962. minor
  963. };
  964. };
  965. const Version = {
  966. nu: nu$d,
  967. detect: detect$5,
  968. unknown: unknown$3
  969. };
  970. const detectBrowser$1 = (browsers, userAgentData) => {
  971. return findMap(userAgentData.brands, uaBrand => {
  972. const lcBrand = uaBrand.brand.toLowerCase();
  973. return find$5(browsers, browser => {
  974. var _a;
  975. return lcBrand === ((_a = browser.brand) === null || _a === void 0 ? void 0 : _a.toLowerCase());
  976. }).map(info => ({
  977. current: info.name,
  978. version: Version.nu(parseInt(uaBrand.version, 10), 0)
  979. }));
  980. });
  981. };
  982. const detect$4 = (candidates, userAgent) => {
  983. const agent = String(userAgent).toLowerCase();
  984. return find$5(candidates, candidate => {
  985. return candidate.search(agent);
  986. });
  987. };
  988. const detectBrowser = (browsers, userAgent) => {
  989. return detect$4(browsers, userAgent).map(browser => {
  990. const version = Version.detect(browser.versionRegexes, userAgent);
  991. return {
  992. current: browser.name,
  993. version
  994. };
  995. });
  996. };
  997. const detectOs = (oses, userAgent) => {
  998. return detect$4(oses, userAgent).map(os => {
  999. const version = Version.detect(os.versionRegexes, userAgent);
  1000. return {
  1001. current: os.name,
  1002. version
  1003. };
  1004. });
  1005. };
  1006. const normalVersionRegex = /.*?version\/\ ?([0-9]+)\.([0-9]+).*/;
  1007. const checkContains = target => {
  1008. return uastring => {
  1009. return contains$1(uastring, target);
  1010. };
  1011. };
  1012. const browsers = [
  1013. {
  1014. name: 'Edge',
  1015. versionRegexes: [/.*?edge\/ ?([0-9]+)\.([0-9]+)$/],
  1016. search: uastring => {
  1017. return contains$1(uastring, 'edge/') && contains$1(uastring, 'chrome') && contains$1(uastring, 'safari') && contains$1(uastring, 'applewebkit');
  1018. }
  1019. },
  1020. {
  1021. name: 'Chromium',
  1022. brand: 'Chromium',
  1023. versionRegexes: [
  1024. /.*?chrome\/([0-9]+)\.([0-9]+).*/,
  1025. normalVersionRegex
  1026. ],
  1027. search: uastring => {
  1028. return contains$1(uastring, 'chrome') && !contains$1(uastring, 'chromeframe');
  1029. }
  1030. },
  1031. {
  1032. name: 'IE',
  1033. versionRegexes: [
  1034. /.*?msie\ ?([0-9]+)\.([0-9]+).*/,
  1035. /.*?rv:([0-9]+)\.([0-9]+).*/
  1036. ],
  1037. search: uastring => {
  1038. return contains$1(uastring, 'msie') || contains$1(uastring, 'trident');
  1039. }
  1040. },
  1041. {
  1042. name: 'Opera',
  1043. versionRegexes: [
  1044. normalVersionRegex,
  1045. /.*?opera\/([0-9]+)\.([0-9]+).*/
  1046. ],
  1047. search: checkContains('opera')
  1048. },
  1049. {
  1050. name: 'Firefox',
  1051. versionRegexes: [/.*?firefox\/\ ?([0-9]+)\.([0-9]+).*/],
  1052. search: checkContains('firefox')
  1053. },
  1054. {
  1055. name: 'Safari',
  1056. versionRegexes: [
  1057. normalVersionRegex,
  1058. /.*?cpu os ([0-9]+)_([0-9]+).*/
  1059. ],
  1060. search: uastring => {
  1061. return (contains$1(uastring, 'safari') || contains$1(uastring, 'mobile/')) && contains$1(uastring, 'applewebkit');
  1062. }
  1063. }
  1064. ];
  1065. const oses = [
  1066. {
  1067. name: 'Windows',
  1068. search: checkContains('win'),
  1069. versionRegexes: [/.*?windows\ nt\ ?([0-9]+)\.([0-9]+).*/]
  1070. },
  1071. {
  1072. name: 'iOS',
  1073. search: uastring => {
  1074. return contains$1(uastring, 'iphone') || contains$1(uastring, 'ipad');
  1075. },
  1076. versionRegexes: [
  1077. /.*?version\/\ ?([0-9]+)\.([0-9]+).*/,
  1078. /.*cpu os ([0-9]+)_([0-9]+).*/,
  1079. /.*cpu iphone os ([0-9]+)_([0-9]+).*/
  1080. ]
  1081. },
  1082. {
  1083. name: 'Android',
  1084. search: checkContains('android'),
  1085. versionRegexes: [/.*?android\ ?([0-9]+)\.([0-9]+).*/]
  1086. },
  1087. {
  1088. name: 'macOS',
  1089. search: checkContains('mac os x'),
  1090. versionRegexes: [/.*?mac\ os\ x\ ?([0-9]+)_([0-9]+).*/]
  1091. },
  1092. {
  1093. name: 'Linux',
  1094. search: checkContains('linux'),
  1095. versionRegexes: []
  1096. },
  1097. {
  1098. name: 'Solaris',
  1099. search: checkContains('sunos'),
  1100. versionRegexes: []
  1101. },
  1102. {
  1103. name: 'FreeBSD',
  1104. search: checkContains('freebsd'),
  1105. versionRegexes: []
  1106. },
  1107. {
  1108. name: 'ChromeOS',
  1109. search: checkContains('cros'),
  1110. versionRegexes: [/.*?chrome\/([0-9]+)\.([0-9]+).*/]
  1111. }
  1112. ];
  1113. const PlatformInfo = {
  1114. browsers: constant$1(browsers),
  1115. oses: constant$1(oses)
  1116. };
  1117. const edge = 'Edge';
  1118. const chromium = 'Chromium';
  1119. const ie = 'IE';
  1120. const opera = 'Opera';
  1121. const firefox = 'Firefox';
  1122. const safari = 'Safari';
  1123. const unknown$2 = () => {
  1124. return nu$c({
  1125. current: undefined,
  1126. version: Version.unknown()
  1127. });
  1128. };
  1129. const nu$c = info => {
  1130. const current = info.current;
  1131. const version = info.version;
  1132. const isBrowser = name => () => current === name;
  1133. return {
  1134. current,
  1135. version,
  1136. isEdge: isBrowser(edge),
  1137. isChromium: isBrowser(chromium),
  1138. isIE: isBrowser(ie),
  1139. isOpera: isBrowser(opera),
  1140. isFirefox: isBrowser(firefox),
  1141. isSafari: isBrowser(safari)
  1142. };
  1143. };
  1144. const Browser = {
  1145. unknown: unknown$2,
  1146. nu: nu$c,
  1147. edge: constant$1(edge),
  1148. chromium: constant$1(chromium),
  1149. ie: constant$1(ie),
  1150. opera: constant$1(opera),
  1151. firefox: constant$1(firefox),
  1152. safari: constant$1(safari)
  1153. };
  1154. const windows = 'Windows';
  1155. const ios = 'iOS';
  1156. const android = 'Android';
  1157. const linux = 'Linux';
  1158. const macos = 'macOS';
  1159. const solaris = 'Solaris';
  1160. const freebsd = 'FreeBSD';
  1161. const chromeos = 'ChromeOS';
  1162. const unknown$1 = () => {
  1163. return nu$b({
  1164. current: undefined,
  1165. version: Version.unknown()
  1166. });
  1167. };
  1168. const nu$b = info => {
  1169. const current = info.current;
  1170. const version = info.version;
  1171. const isOS = name => () => current === name;
  1172. return {
  1173. current,
  1174. version,
  1175. isWindows: isOS(windows),
  1176. isiOS: isOS(ios),
  1177. isAndroid: isOS(android),
  1178. isMacOS: isOS(macos),
  1179. isLinux: isOS(linux),
  1180. isSolaris: isOS(solaris),
  1181. isFreeBSD: isOS(freebsd),
  1182. isChromeOS: isOS(chromeos)
  1183. };
  1184. };
  1185. const OperatingSystem = {
  1186. unknown: unknown$1,
  1187. nu: nu$b,
  1188. windows: constant$1(windows),
  1189. ios: constant$1(ios),
  1190. android: constant$1(android),
  1191. linux: constant$1(linux),
  1192. macos: constant$1(macos),
  1193. solaris: constant$1(solaris),
  1194. freebsd: constant$1(freebsd),
  1195. chromeos: constant$1(chromeos)
  1196. };
  1197. const detect$3 = (userAgent, userAgentDataOpt, mediaMatch) => {
  1198. const browsers = PlatformInfo.browsers();
  1199. const oses = PlatformInfo.oses();
  1200. const browser = userAgentDataOpt.bind(userAgentData => detectBrowser$1(browsers, userAgentData)).orThunk(() => detectBrowser(browsers, userAgent)).fold(Browser.unknown, Browser.nu);
  1201. const os = detectOs(oses, userAgent).fold(OperatingSystem.unknown, OperatingSystem.nu);
  1202. const deviceType = DeviceType(os, browser, userAgent, mediaMatch);
  1203. return {
  1204. browser,
  1205. os,
  1206. deviceType
  1207. };
  1208. };
  1209. const PlatformDetection = { detect: detect$3 };
  1210. const mediaMatch = query => window.matchMedia(query).matches;
  1211. let platform = cached(() => PlatformDetection.detect(navigator.userAgent, Optional.from(navigator.userAgentData), mediaMatch));
  1212. const detect$2 = () => platform();
  1213. const mkEvent = (target, x, y, stop, prevent, kill, raw) => ({
  1214. target,
  1215. x,
  1216. y,
  1217. stop,
  1218. prevent,
  1219. kill,
  1220. raw
  1221. });
  1222. const fromRawEvent$1 = rawEvent => {
  1223. const target = SugarElement.fromDom(getOriginalEventTarget(rawEvent).getOr(rawEvent.target));
  1224. const stop = () => rawEvent.stopPropagation();
  1225. const prevent = () => rawEvent.preventDefault();
  1226. const kill = compose(prevent, stop);
  1227. return mkEvent(target, rawEvent.clientX, rawEvent.clientY, stop, prevent, kill, rawEvent);
  1228. };
  1229. const handle = (filter, handler) => rawEvent => {
  1230. if (filter(rawEvent)) {
  1231. handler(fromRawEvent$1(rawEvent));
  1232. }
  1233. };
  1234. const binder = (element, event, filter, handler, useCapture) => {
  1235. const wrapped = handle(filter, handler);
  1236. element.dom.addEventListener(event, wrapped, useCapture);
  1237. return { unbind: curry(unbind, element, event, wrapped, useCapture) };
  1238. };
  1239. const bind$2 = (element, event, filter, handler) => binder(element, event, filter, handler, false);
  1240. const capture$1 = (element, event, filter, handler) => binder(element, event, filter, handler, true);
  1241. const unbind = (element, event, handler, useCapture) => {
  1242. element.dom.removeEventListener(event, handler, useCapture);
  1243. };
  1244. const before$1 = (marker, element) => {
  1245. const parent$1 = parent(marker);
  1246. parent$1.each(v => {
  1247. v.dom.insertBefore(element.dom, marker.dom);
  1248. });
  1249. };
  1250. const after$2 = (marker, element) => {
  1251. const sibling = nextSibling(marker);
  1252. sibling.fold(() => {
  1253. const parent$1 = parent(marker);
  1254. parent$1.each(v => {
  1255. append$2(v, element);
  1256. });
  1257. }, v => {
  1258. before$1(v, element);
  1259. });
  1260. };
  1261. const prepend$1 = (parent, element) => {
  1262. const firstChild$1 = firstChild(parent);
  1263. firstChild$1.fold(() => {
  1264. append$2(parent, element);
  1265. }, v => {
  1266. parent.dom.insertBefore(element.dom, v.dom);
  1267. });
  1268. };
  1269. const append$2 = (parent, element) => {
  1270. parent.dom.appendChild(element.dom);
  1271. };
  1272. const appendAt = (parent, element, index) => {
  1273. child$2(parent, index).fold(() => {
  1274. append$2(parent, element);
  1275. }, v => {
  1276. before$1(v, element);
  1277. });
  1278. };
  1279. const append$1 = (parent, elements) => {
  1280. each$1(elements, x => {
  1281. append$2(parent, x);
  1282. });
  1283. };
  1284. const empty = element => {
  1285. element.dom.textContent = '';
  1286. each$1(children(element), rogue => {
  1287. remove$5(rogue);
  1288. });
  1289. };
  1290. const remove$5 = element => {
  1291. const dom = element.dom;
  1292. if (dom.parentNode !== null) {
  1293. dom.parentNode.removeChild(dom);
  1294. }
  1295. };
  1296. const get$b = _DOC => {
  1297. const doc = _DOC !== undefined ? _DOC.dom : document;
  1298. const x = doc.body.scrollLeft || doc.documentElement.scrollLeft;
  1299. const y = doc.body.scrollTop || doc.documentElement.scrollTop;
  1300. return SugarPosition(x, y);
  1301. };
  1302. const to = (x, y, _DOC) => {
  1303. const doc = _DOC !== undefined ? _DOC.dom : document;
  1304. const win = doc.defaultView;
  1305. if (win) {
  1306. win.scrollTo(x, y);
  1307. }
  1308. };
  1309. const get$a = _win => {
  1310. const win = _win === undefined ? window : _win;
  1311. if (detect$2().browser.isFirefox()) {
  1312. return Optional.none();
  1313. } else {
  1314. return Optional.from(win.visualViewport);
  1315. }
  1316. };
  1317. const bounds$1 = (x, y, width, height) => ({
  1318. x,
  1319. y,
  1320. width,
  1321. height,
  1322. right: x + width,
  1323. bottom: y + height
  1324. });
  1325. const getBounds$3 = _win => {
  1326. const win = _win === undefined ? window : _win;
  1327. const doc = win.document;
  1328. const scroll = get$b(SugarElement.fromDom(doc));
  1329. return get$a(win).fold(() => {
  1330. const html = win.document.documentElement;
  1331. const width = html.clientWidth;
  1332. const height = html.clientHeight;
  1333. return bounds$1(scroll.left, scroll.top, width, height);
  1334. }, visualViewport => bounds$1(Math.max(visualViewport.pageLeft, scroll.left), Math.max(visualViewport.pageTop, scroll.top), visualViewport.width, visualViewport.height));
  1335. };
  1336. const getDocument = () => SugarElement.fromDom(document);
  1337. const walkUp = (navigation, doc) => {
  1338. const frame = navigation.view(doc);
  1339. return frame.fold(constant$1([]), f => {
  1340. const parent = navigation.owner(f);
  1341. const rest = walkUp(navigation, parent);
  1342. return [f].concat(rest);
  1343. });
  1344. };
  1345. const pathTo = (element, navigation) => {
  1346. const d = navigation.owner(element);
  1347. const paths = walkUp(navigation, d);
  1348. return Optional.some(paths);
  1349. };
  1350. const view = doc => {
  1351. var _a;
  1352. const element = doc.dom === document ? Optional.none() : Optional.from((_a = doc.dom.defaultView) === null || _a === void 0 ? void 0 : _a.frameElement);
  1353. return element.map(SugarElement.fromDom);
  1354. };
  1355. const owner$3 = element => owner$4(element);
  1356. var Navigation = /*#__PURE__*/Object.freeze({
  1357. __proto__: null,
  1358. view: view,
  1359. owner: owner$3
  1360. });
  1361. const find$2 = element => {
  1362. const doc = getDocument();
  1363. const scroll = get$b(doc);
  1364. const path = pathTo(element, Navigation);
  1365. return path.fold(curry(absolute$3, element), frames => {
  1366. const offset = viewport$1(element);
  1367. const r = foldr(frames, (b, a) => {
  1368. const loc = viewport$1(a);
  1369. return {
  1370. left: b.left + loc.left,
  1371. top: b.top + loc.top
  1372. };
  1373. }, {
  1374. left: 0,
  1375. top: 0
  1376. });
  1377. return SugarPosition(r.left + offset.left + scroll.left, r.top + offset.top + scroll.top);
  1378. });
  1379. };
  1380. const pointed = (point, width, height) => ({
  1381. point,
  1382. width,
  1383. height
  1384. });
  1385. const rect = (x, y, width, height) => ({
  1386. x,
  1387. y,
  1388. width,
  1389. height
  1390. });
  1391. const bounds = (x, y, width, height) => ({
  1392. x,
  1393. y,
  1394. width,
  1395. height,
  1396. right: x + width,
  1397. bottom: y + height
  1398. });
  1399. const box$1 = element => {
  1400. const xy = absolute$3(element);
  1401. const w = getOuter$1(element);
  1402. const h = getOuter$2(element);
  1403. return bounds(xy.left, xy.top, w, h);
  1404. };
  1405. const absolute$2 = element => {
  1406. const position = find$2(element);
  1407. const width = getOuter$1(element);
  1408. const height = getOuter$2(element);
  1409. return bounds(position.left, position.top, width, height);
  1410. };
  1411. const constrain = (original, constraint) => {
  1412. const left = Math.max(original.x, constraint.x);
  1413. const top = Math.max(original.y, constraint.y);
  1414. const right = Math.min(original.right, constraint.right);
  1415. const bottom = Math.min(original.bottom, constraint.bottom);
  1416. const width = right - left;
  1417. const height = bottom - top;
  1418. return bounds(left, top, width, height);
  1419. };
  1420. const constrainByMany = (original, constraints) => {
  1421. return foldl(constraints, (acc, c) => constrain(acc, c), original);
  1422. };
  1423. const win = () => getBounds$3(window);
  1424. var global$a = tinymce.util.Tools.resolve('tinymce.ThemeManager');
  1425. const value$4 = value => {
  1426. const applyHelper = fn => fn(value);
  1427. const constHelper = constant$1(value);
  1428. const outputHelper = () => output;
  1429. const output = {
  1430. tag: true,
  1431. inner: value,
  1432. fold: (_onError, onValue) => onValue(value),
  1433. isValue: always,
  1434. isError: never,
  1435. map: mapper => Result.value(mapper(value)),
  1436. mapError: outputHelper,
  1437. bind: applyHelper,
  1438. exists: applyHelper,
  1439. forall: applyHelper,
  1440. getOr: constHelper,
  1441. or: outputHelper,
  1442. getOrThunk: constHelper,
  1443. orThunk: outputHelper,
  1444. getOrDie: constHelper,
  1445. each: fn => {
  1446. fn(value);
  1447. },
  1448. toOptional: () => Optional.some(value)
  1449. };
  1450. return output;
  1451. };
  1452. const error$1 = error => {
  1453. const outputHelper = () => output;
  1454. const output = {
  1455. tag: false,
  1456. inner: error,
  1457. fold: (onError, _onValue) => onError(error),
  1458. isValue: never,
  1459. isError: always,
  1460. map: outputHelper,
  1461. mapError: mapper => Result.error(mapper(error)),
  1462. bind: outputHelper,
  1463. exists: never,
  1464. forall: always,
  1465. getOr: identity,
  1466. or: identity,
  1467. getOrThunk: apply$1,
  1468. orThunk: apply$1,
  1469. getOrDie: die(String(error)),
  1470. each: noop,
  1471. toOptional: Optional.none
  1472. };
  1473. return output;
  1474. };
  1475. const fromOption = (optional, err) => optional.fold(() => error$1(err), value$4);
  1476. const Result = {
  1477. value: value$4,
  1478. error: error$1,
  1479. fromOption
  1480. };
  1481. var SimpleResultType;
  1482. (function (SimpleResultType) {
  1483. SimpleResultType[SimpleResultType['Error'] = 0] = 'Error';
  1484. SimpleResultType[SimpleResultType['Value'] = 1] = 'Value';
  1485. }(SimpleResultType || (SimpleResultType = {})));
  1486. const fold$1 = (res, onError, onValue) => res.stype === SimpleResultType.Error ? onError(res.serror) : onValue(res.svalue);
  1487. const partition$2 = results => {
  1488. const values = [];
  1489. const errors = [];
  1490. each$1(results, obj => {
  1491. fold$1(obj, err => errors.push(err), val => values.push(val));
  1492. });
  1493. return {
  1494. values,
  1495. errors
  1496. };
  1497. };
  1498. const mapError = (res, f) => {
  1499. if (res.stype === SimpleResultType.Error) {
  1500. return {
  1501. stype: SimpleResultType.Error,
  1502. serror: f(res.serror)
  1503. };
  1504. } else {
  1505. return res;
  1506. }
  1507. };
  1508. const map = (res, f) => {
  1509. if (res.stype === SimpleResultType.Value) {
  1510. return {
  1511. stype: SimpleResultType.Value,
  1512. svalue: f(res.svalue)
  1513. };
  1514. } else {
  1515. return res;
  1516. }
  1517. };
  1518. const bind$1 = (res, f) => {
  1519. if (res.stype === SimpleResultType.Value) {
  1520. return f(res.svalue);
  1521. } else {
  1522. return res;
  1523. }
  1524. };
  1525. const bindError = (res, f) => {
  1526. if (res.stype === SimpleResultType.Error) {
  1527. return f(res.serror);
  1528. } else {
  1529. return res;
  1530. }
  1531. };
  1532. const svalue = v => ({
  1533. stype: SimpleResultType.Value,
  1534. svalue: v
  1535. });
  1536. const serror = e => ({
  1537. stype: SimpleResultType.Error,
  1538. serror: e
  1539. });
  1540. const toResult$1 = res => fold$1(res, Result.error, Result.value);
  1541. const fromResult$1 = res => res.fold(serror, svalue);
  1542. const SimpleResult = {
  1543. fromResult: fromResult$1,
  1544. toResult: toResult$1,
  1545. svalue,
  1546. partition: partition$2,
  1547. serror,
  1548. bind: bind$1,
  1549. bindError,
  1550. map,
  1551. mapError,
  1552. fold: fold$1
  1553. };
  1554. const field$2 = (key, newKey, presence, prop) => ({
  1555. tag: 'field',
  1556. key,
  1557. newKey,
  1558. presence,
  1559. prop
  1560. });
  1561. const customField$1 = (newKey, instantiator) => ({
  1562. tag: 'custom',
  1563. newKey,
  1564. instantiator
  1565. });
  1566. const fold = (value, ifField, ifCustom) => {
  1567. switch (value.tag) {
  1568. case 'field':
  1569. return ifField(value.key, value.newKey, value.presence, value.prop);
  1570. case 'custom':
  1571. return ifCustom(value.newKey, value.instantiator);
  1572. }
  1573. };
  1574. const shallow$1 = (old, nu) => {
  1575. return nu;
  1576. };
  1577. const deep = (old, nu) => {
  1578. const bothObjects = isPlainObject(old) && isPlainObject(nu);
  1579. return bothObjects ? deepMerge(old, nu) : nu;
  1580. };
  1581. const baseMerge = merger => {
  1582. return (...objects) => {
  1583. if (objects.length === 0) {
  1584. throw new Error(`Can't merge zero objects`);
  1585. }
  1586. const ret = {};
  1587. for (let j = 0; j < objects.length; j++) {
  1588. const curObject = objects[j];
  1589. for (const key in curObject) {
  1590. if (has$2(curObject, key)) {
  1591. ret[key] = merger(ret[key], curObject[key]);
  1592. }
  1593. }
  1594. }
  1595. return ret;
  1596. };
  1597. };
  1598. const deepMerge = baseMerge(deep);
  1599. const merge$1 = baseMerge(shallow$1);
  1600. const required$2 = () => ({
  1601. tag: 'required',
  1602. process: {}
  1603. });
  1604. const defaultedThunk = fallbackThunk => ({
  1605. tag: 'defaultedThunk',
  1606. process: fallbackThunk
  1607. });
  1608. const defaulted$1 = fallback => defaultedThunk(constant$1(fallback));
  1609. const asOption = () => ({
  1610. tag: 'option',
  1611. process: {}
  1612. });
  1613. const mergeWithThunk = baseThunk => ({
  1614. tag: 'mergeWithThunk',
  1615. process: baseThunk
  1616. });
  1617. const mergeWith = base => mergeWithThunk(constant$1(base));
  1618. const mergeValues$1 = (values, base) => values.length > 0 ? SimpleResult.svalue(deepMerge(base, merge$1.apply(undefined, values))) : SimpleResult.svalue(base);
  1619. const mergeErrors$1 = errors => compose(SimpleResult.serror, flatten)(errors);
  1620. const consolidateObj = (objects, base) => {
  1621. const partition = SimpleResult.partition(objects);
  1622. return partition.errors.length > 0 ? mergeErrors$1(partition.errors) : mergeValues$1(partition.values, base);
  1623. };
  1624. const consolidateArr = objects => {
  1625. const partitions = SimpleResult.partition(objects);
  1626. return partitions.errors.length > 0 ? mergeErrors$1(partitions.errors) : SimpleResult.svalue(partitions.values);
  1627. };
  1628. const ResultCombine = {
  1629. consolidateObj,
  1630. consolidateArr
  1631. };
  1632. const formatObj = input => {
  1633. return isObject(input) && keys(input).length > 100 ? ' removed due to size' : JSON.stringify(input, null, 2);
  1634. };
  1635. const formatErrors = errors => {
  1636. const es = errors.length > 10 ? errors.slice(0, 10).concat([{
  1637. path: [],
  1638. getErrorInfo: constant$1('... (only showing first ten failures)')
  1639. }]) : errors;
  1640. return map$2(es, e => {
  1641. return 'Failed path: (' + e.path.join(' > ') + ')\n' + e.getErrorInfo();
  1642. });
  1643. };
  1644. const nu$a = (path, getErrorInfo) => {
  1645. return SimpleResult.serror([{
  1646. path,
  1647. getErrorInfo
  1648. }]);
  1649. };
  1650. const missingRequired = (path, key, obj) => nu$a(path, () => 'Could not find valid *required* value for "' + key + '" in ' + formatObj(obj));
  1651. const missingKey = (path, key) => nu$a(path, () => 'Choice schema did not contain choice key: "' + key + '"');
  1652. const missingBranch = (path, branches, branch) => nu$a(path, () => 'The chosen schema: "' + branch + '" did not exist in branches: ' + formatObj(branches));
  1653. const unsupportedFields = (path, unsupported) => nu$a(path, () => 'There are unsupported fields: [' + unsupported.join(', ') + '] specified');
  1654. const custom = (path, err) => nu$a(path, constant$1(err));
  1655. const value$3 = validator => {
  1656. const extract = (path, val) => {
  1657. return SimpleResult.bindError(validator(val), err => custom(path, err));
  1658. };
  1659. const toString = constant$1('val');
  1660. return {
  1661. extract,
  1662. toString
  1663. };
  1664. };
  1665. const anyValue$1 = value$3(SimpleResult.svalue);
  1666. const requiredAccess = (path, obj, key, bundle) => get$g(obj, key).fold(() => missingRequired(path, key, obj), bundle);
  1667. const fallbackAccess = (obj, key, fallback, bundle) => {
  1668. const v = get$g(obj, key).getOrThunk(() => fallback(obj));
  1669. return bundle(v);
  1670. };
  1671. const optionAccess = (obj, key, bundle) => bundle(get$g(obj, key));
  1672. const optionDefaultedAccess = (obj, key, fallback, bundle) => {
  1673. const opt = get$g(obj, key).map(val => val === true ? fallback(obj) : val);
  1674. return bundle(opt);
  1675. };
  1676. const extractField = (field, path, obj, key, prop) => {
  1677. const bundle = av => prop.extract(path.concat([key]), av);
  1678. const bundleAsOption = optValue => optValue.fold(() => SimpleResult.svalue(Optional.none()), ov => {
  1679. const result = prop.extract(path.concat([key]), ov);
  1680. return SimpleResult.map(result, Optional.some);
  1681. });
  1682. switch (field.tag) {
  1683. case 'required':
  1684. return requiredAccess(path, obj, key, bundle);
  1685. case 'defaultedThunk':
  1686. return fallbackAccess(obj, key, field.process, bundle);
  1687. case 'option':
  1688. return optionAccess(obj, key, bundleAsOption);
  1689. case 'defaultedOptionThunk':
  1690. return optionDefaultedAccess(obj, key, field.process, bundleAsOption);
  1691. case 'mergeWithThunk': {
  1692. return fallbackAccess(obj, key, constant$1({}), v => {
  1693. const result = deepMerge(field.process(obj), v);
  1694. return bundle(result);
  1695. });
  1696. }
  1697. }
  1698. };
  1699. const extractFields = (path, obj, fields) => {
  1700. const success = {};
  1701. const errors = [];
  1702. for (const field of fields) {
  1703. fold(field, (key, newKey, presence, prop) => {
  1704. const result = extractField(presence, path, obj, key, prop);
  1705. SimpleResult.fold(result, err => {
  1706. errors.push(...err);
  1707. }, res => {
  1708. success[newKey] = res;
  1709. });
  1710. }, (newKey, instantiator) => {
  1711. success[newKey] = instantiator(obj);
  1712. });
  1713. }
  1714. return errors.length > 0 ? SimpleResult.serror(errors) : SimpleResult.svalue(success);
  1715. };
  1716. const valueThunk = getDelegate => {
  1717. const extract = (path, val) => getDelegate().extract(path, val);
  1718. const toString = () => getDelegate().toString();
  1719. return {
  1720. extract,
  1721. toString
  1722. };
  1723. };
  1724. const getSetKeys = obj => keys(filter$1(obj, isNonNullable));
  1725. const objOfOnly = fields => {
  1726. const delegate = objOf(fields);
  1727. const fieldNames = foldr(fields, (acc, value) => {
  1728. return fold(value, key => deepMerge(acc, { [key]: true }), constant$1(acc));
  1729. }, {});
  1730. const extract = (path, o) => {
  1731. const keys = isBoolean(o) ? [] : getSetKeys(o);
  1732. const extra = filter$2(keys, k => !hasNonNullableKey(fieldNames, k));
  1733. return extra.length === 0 ? delegate.extract(path, o) : unsupportedFields(path, extra);
  1734. };
  1735. return {
  1736. extract,
  1737. toString: delegate.toString
  1738. };
  1739. };
  1740. const objOf = values => {
  1741. const extract = (path, o) => extractFields(path, o, values);
  1742. const toString = () => {
  1743. const fieldStrings = map$2(values, value => fold(value, (key, _okey, _presence, prop) => key + ' -> ' + prop.toString(), (newKey, _instantiator) => 'state(' + newKey + ')'));
  1744. return 'obj{\n' + fieldStrings.join('\n') + '}';
  1745. };
  1746. return {
  1747. extract,
  1748. toString
  1749. };
  1750. };
  1751. const arrOf = prop => {
  1752. const extract = (path, array) => {
  1753. const results = map$2(array, (a, i) => prop.extract(path.concat(['[' + i + ']']), a));
  1754. return ResultCombine.consolidateArr(results);
  1755. };
  1756. const toString = () => 'array(' + prop.toString() + ')';
  1757. return {
  1758. extract,
  1759. toString
  1760. };
  1761. };
  1762. const oneOf = (props, rawF) => {
  1763. const f = rawF !== undefined ? rawF : identity;
  1764. const extract = (path, val) => {
  1765. const errors = [];
  1766. for (const prop of props) {
  1767. const res = prop.extract(path, val);
  1768. if (res.stype === SimpleResultType.Value) {
  1769. return {
  1770. stype: SimpleResultType.Value,
  1771. svalue: f(res.svalue)
  1772. };
  1773. }
  1774. errors.push(res);
  1775. }
  1776. return ResultCombine.consolidateArr(errors);
  1777. };
  1778. const toString = () => 'oneOf(' + map$2(props, prop => prop.toString()).join(', ') + ')';
  1779. return {
  1780. extract,
  1781. toString
  1782. };
  1783. };
  1784. const setOf$1 = (validator, prop) => {
  1785. const validateKeys = (path, keys) => arrOf(value$3(validator)).extract(path, keys);
  1786. const extract = (path, o) => {
  1787. const keys$1 = keys(o);
  1788. const validatedKeys = validateKeys(path, keys$1);
  1789. return SimpleResult.bind(validatedKeys, validKeys => {
  1790. const schema = map$2(validKeys, vk => {
  1791. return field$2(vk, vk, required$2(), prop);
  1792. });
  1793. return objOf(schema).extract(path, o);
  1794. });
  1795. };
  1796. const toString = () => 'setOf(' + prop.toString() + ')';
  1797. return {
  1798. extract,
  1799. toString
  1800. };
  1801. };
  1802. const thunk = (_desc, processor) => {
  1803. const getP = cached(processor);
  1804. const extract = (path, val) => getP().extract(path, val);
  1805. const toString = () => getP().toString();
  1806. return {
  1807. extract,
  1808. toString
  1809. };
  1810. };
  1811. const arrOfObj = compose(arrOf, objOf);
  1812. const anyValue = constant$1(anyValue$1);
  1813. const typedValue = (validator, expectedType) => value$3(a => {
  1814. const actualType = typeof a;
  1815. return validator(a) ? SimpleResult.svalue(a) : SimpleResult.serror(`Expected type: ${ expectedType } but got: ${ actualType }`);
  1816. });
  1817. const number = typedValue(isNumber, 'number');
  1818. const string = typedValue(isString, 'string');
  1819. const boolean = typedValue(isBoolean, 'boolean');
  1820. const functionProcessor = typedValue(isFunction, 'function');
  1821. const isPostMessageable = val => {
  1822. if (Object(val) !== val) {
  1823. return true;
  1824. }
  1825. switch ({}.toString.call(val).slice(8, -1)) {
  1826. case 'Boolean':
  1827. case 'Number':
  1828. case 'String':
  1829. case 'Date':
  1830. case 'RegExp':
  1831. case 'Blob':
  1832. case 'FileList':
  1833. case 'ImageData':
  1834. case 'ImageBitmap':
  1835. case 'ArrayBuffer':
  1836. return true;
  1837. case 'Array':
  1838. case 'Object':
  1839. return Object.keys(val).every(prop => isPostMessageable(val[prop]));
  1840. default:
  1841. return false;
  1842. }
  1843. };
  1844. const postMessageable = value$3(a => {
  1845. if (isPostMessageable(a)) {
  1846. return SimpleResult.svalue(a);
  1847. } else {
  1848. return SimpleResult.serror('Expected value to be acceptable for sending via postMessage');
  1849. }
  1850. });
  1851. const chooseFrom = (path, input, branches, ch) => {
  1852. const fields = get$g(branches, ch);
  1853. return fields.fold(() => missingBranch(path, branches, ch), vp => vp.extract(path.concat(['branch: ' + ch]), input));
  1854. };
  1855. const choose$2 = (key, branches) => {
  1856. const extract = (path, input) => {
  1857. const choice = get$g(input, key);
  1858. return choice.fold(() => missingKey(path, key), chosen => chooseFrom(path, input, branches, chosen));
  1859. };
  1860. const toString = () => 'chooseOn(' + key + '). Possible values: ' + keys(branches);
  1861. return {
  1862. extract,
  1863. toString
  1864. };
  1865. };
  1866. const arrOfVal = () => arrOf(anyValue$1);
  1867. const valueOf = validator => value$3(v => validator(v).fold(SimpleResult.serror, SimpleResult.svalue));
  1868. const setOf = (validator, prop) => setOf$1(v => SimpleResult.fromResult(validator(v)), prop);
  1869. const extractValue = (label, prop, obj) => {
  1870. const res = prop.extract([label], obj);
  1871. return SimpleResult.mapError(res, errs => ({
  1872. input: obj,
  1873. errors: errs
  1874. }));
  1875. };
  1876. const asRaw = (label, prop, obj) => SimpleResult.toResult(extractValue(label, prop, obj));
  1877. const getOrDie = extraction => {
  1878. return extraction.fold(errInfo => {
  1879. throw new Error(formatError(errInfo));
  1880. }, identity);
  1881. };
  1882. const asRawOrDie$1 = (label, prop, obj) => getOrDie(asRaw(label, prop, obj));
  1883. const formatError = errInfo => {
  1884. return 'Errors: \n' + formatErrors(errInfo.errors).join('\n') + '\n\nInput object: ' + formatObj(errInfo.input);
  1885. };
  1886. const choose$1 = (key, branches) => choose$2(key, map$1(branches, objOf));
  1887. const thunkOf = (desc, schema) => thunk(desc, schema);
  1888. const field$1 = field$2;
  1889. const customField = customField$1;
  1890. const validateEnum = values => valueOf(value => contains$2(values, value) ? Result.value(value) : Result.error(`Unsupported value: "${ value }", choose one of "${ values.join(', ') }".`));
  1891. const required$1 = key => field$1(key, key, required$2(), anyValue());
  1892. const requiredOf = (key, schema) => field$1(key, key, required$2(), schema);
  1893. const requiredNumber = key => requiredOf(key, number);
  1894. const requiredString = key => requiredOf(key, string);
  1895. const requiredStringEnum = (key, values) => field$1(key, key, required$2(), validateEnum(values));
  1896. const requiredBoolean = key => requiredOf(key, boolean);
  1897. const requiredFunction = key => requiredOf(key, functionProcessor);
  1898. const forbid = (key, message) => field$1(key, key, asOption(), value$3(_v => SimpleResult.serror('The field: ' + key + ' is forbidden. ' + message)));
  1899. const requiredObjOf = (key, objSchema) => field$1(key, key, required$2(), objOf(objSchema));
  1900. const requiredArrayOfObj = (key, objFields) => field$1(key, key, required$2(), arrOfObj(objFields));
  1901. const requiredArrayOf = (key, schema) => field$1(key, key, required$2(), arrOf(schema));
  1902. const option$3 = key => field$1(key, key, asOption(), anyValue());
  1903. const optionOf = (key, schema) => field$1(key, key, asOption(), schema);
  1904. const optionNumber = key => optionOf(key, number);
  1905. const optionString = key => optionOf(key, string);
  1906. const optionStringEnum = (key, values) => optionOf(key, validateEnum(values));
  1907. const optionFunction = key => optionOf(key, functionProcessor);
  1908. const optionArrayOf = (key, schema) => optionOf(key, arrOf(schema));
  1909. const optionObjOf = (key, objSchema) => optionOf(key, objOf(objSchema));
  1910. const optionObjOfOnly = (key, objSchema) => optionOf(key, objOfOnly(objSchema));
  1911. const defaulted = (key, fallback) => field$1(key, key, defaulted$1(fallback), anyValue());
  1912. const defaultedOf = (key, fallback, schema) => field$1(key, key, defaulted$1(fallback), schema);
  1913. const defaultedNumber = (key, fallback) => defaultedOf(key, fallback, number);
  1914. const defaultedString = (key, fallback) => defaultedOf(key, fallback, string);
  1915. const defaultedStringEnum = (key, fallback, values) => defaultedOf(key, fallback, validateEnum(values));
  1916. const defaultedBoolean = (key, fallback) => defaultedOf(key, fallback, boolean);
  1917. const defaultedFunction = (key, fallback) => defaultedOf(key, fallback, functionProcessor);
  1918. const defaultedPostMsg = (key, fallback) => defaultedOf(key, fallback, postMessageable);
  1919. const defaultedArrayOf = (key, fallback, schema) => defaultedOf(key, fallback, arrOf(schema));
  1920. const defaultedObjOf = (key, fallback, objSchema) => defaultedOf(key, fallback, objOf(objSchema));
  1921. const Cell = initial => {
  1922. let value = initial;
  1923. const get = () => {
  1924. return value;
  1925. };
  1926. const set = v => {
  1927. value = v;
  1928. };
  1929. return {
  1930. get,
  1931. set
  1932. };
  1933. };
  1934. const generate$7 = cases => {
  1935. if (!isArray(cases)) {
  1936. throw new Error('cases must be an array');
  1937. }
  1938. if (cases.length === 0) {
  1939. throw new Error('there must be at least one case');
  1940. }
  1941. const constructors = [];
  1942. const adt = {};
  1943. each$1(cases, (acase, count) => {
  1944. const keys$1 = keys(acase);
  1945. if (keys$1.length !== 1) {
  1946. throw new Error('one and only one name per case');
  1947. }
  1948. const key = keys$1[0];
  1949. const value = acase[key];
  1950. if (adt[key] !== undefined) {
  1951. throw new Error('duplicate key detected:' + key);
  1952. } else if (key === 'cata') {
  1953. throw new Error('cannot have a case named cata (sorry)');
  1954. } else if (!isArray(value)) {
  1955. throw new Error('case arguments must be an array');
  1956. }
  1957. constructors.push(key);
  1958. adt[key] = (...args) => {
  1959. const argLength = args.length;
  1960. if (argLength !== value.length) {
  1961. throw new Error('Wrong number of arguments to case ' + key + '. Expected ' + value.length + ' (' + value + '), got ' + argLength);
  1962. }
  1963. const match = branches => {
  1964. const branchKeys = keys(branches);
  1965. if (constructors.length !== branchKeys.length) {
  1966. throw new Error('Wrong number of arguments to match. Expected: ' + constructors.join(',') + '\nActual: ' + branchKeys.join(','));
  1967. }
  1968. const allReqd = forall(constructors, reqKey => {
  1969. return contains$2(branchKeys, reqKey);
  1970. });
  1971. if (!allReqd) {
  1972. throw new Error('Not all branches were specified when using match. Specified: ' + branchKeys.join(', ') + '\nRequired: ' + constructors.join(', '));
  1973. }
  1974. return branches[key].apply(null, args);
  1975. };
  1976. return {
  1977. fold: (...foldArgs) => {
  1978. if (foldArgs.length !== cases.length) {
  1979. throw new Error('Wrong number of arguments to fold. Expected ' + cases.length + ', got ' + foldArgs.length);
  1980. }
  1981. const target = foldArgs[count];
  1982. return target.apply(null, args);
  1983. },
  1984. match,
  1985. log: label => {
  1986. console.log(label, {
  1987. constructors,
  1988. constructor: key,
  1989. params: args
  1990. });
  1991. }
  1992. };
  1993. };
  1994. });
  1995. return adt;
  1996. };
  1997. const Adt = { generate: generate$7 };
  1998. Adt.generate([
  1999. {
  2000. bothErrors: [
  2001. 'error1',
  2002. 'error2'
  2003. ]
  2004. },
  2005. {
  2006. firstError: [
  2007. 'error1',
  2008. 'value2'
  2009. ]
  2010. },
  2011. {
  2012. secondError: [
  2013. 'value1',
  2014. 'error2'
  2015. ]
  2016. },
  2017. {
  2018. bothValues: [
  2019. 'value1',
  2020. 'value2'
  2021. ]
  2022. }
  2023. ]);
  2024. const partition$1 = results => {
  2025. const errors = [];
  2026. const values = [];
  2027. each$1(results, result => {
  2028. result.fold(err => {
  2029. errors.push(err);
  2030. }, value => {
  2031. values.push(value);
  2032. });
  2033. });
  2034. return {
  2035. errors,
  2036. values
  2037. };
  2038. };
  2039. const exclude$1 = (obj, fields) => {
  2040. const r = {};
  2041. each(obj, (v, k) => {
  2042. if (!contains$2(fields, k)) {
  2043. r[k] = v;
  2044. }
  2045. });
  2046. return r;
  2047. };
  2048. const wrap$2 = (key, value) => ({ [key]: value });
  2049. const wrapAll$1 = keyvalues => {
  2050. const r = {};
  2051. each$1(keyvalues, kv => {
  2052. r[kv.key] = kv.value;
  2053. });
  2054. return r;
  2055. };
  2056. const exclude = (obj, fields) => exclude$1(obj, fields);
  2057. const wrap$1 = (key, value) => wrap$2(key, value);
  2058. const wrapAll = keyvalues => wrapAll$1(keyvalues);
  2059. const mergeValues = (values, base) => {
  2060. return values.length === 0 ? Result.value(base) : Result.value(deepMerge(base, merge$1.apply(undefined, values)));
  2061. };
  2062. const mergeErrors = errors => Result.error(flatten(errors));
  2063. const consolidate = (objs, base) => {
  2064. const partitions = partition$1(objs);
  2065. return partitions.errors.length > 0 ? mergeErrors(partitions.errors) : mergeValues(partitions.values, base);
  2066. };
  2067. const ensureIsRoot = isRoot => isFunction(isRoot) ? isRoot : never;
  2068. const ancestor$2 = (scope, transform, isRoot) => {
  2069. let element = scope.dom;
  2070. const stop = ensureIsRoot(isRoot);
  2071. while (element.parentNode) {
  2072. element = element.parentNode;
  2073. const el = SugarElement.fromDom(element);
  2074. const transformed = transform(el);
  2075. if (transformed.isSome()) {
  2076. return transformed;
  2077. } else if (stop(el)) {
  2078. break;
  2079. }
  2080. }
  2081. return Optional.none();
  2082. };
  2083. const closest$4 = (scope, transform, isRoot) => {
  2084. const current = transform(scope);
  2085. const stop = ensureIsRoot(isRoot);
  2086. return current.orThunk(() => stop(scope) ? Optional.none() : ancestor$2(scope, transform, stop));
  2087. };
  2088. const isSource = (component, simulatedEvent) => eq(component.element, simulatedEvent.event.target);
  2089. const defaultEventHandler = {
  2090. can: always,
  2091. abort: never,
  2092. run: noop
  2093. };
  2094. const nu$9 = parts => {
  2095. if (!hasNonNullableKey(parts, 'can') && !hasNonNullableKey(parts, 'abort') && !hasNonNullableKey(parts, 'run')) {
  2096. throw new Error('EventHandler defined by: ' + JSON.stringify(parts, null, 2) + ' does not have can, abort, or run!');
  2097. }
  2098. return {
  2099. ...defaultEventHandler,
  2100. ...parts
  2101. };
  2102. };
  2103. const all$2 = (handlers, f) => (...args) => foldl(handlers, (acc, handler) => acc && f(handler).apply(undefined, args), true);
  2104. const any = (handlers, f) => (...args) => foldl(handlers, (acc, handler) => acc || f(handler).apply(undefined, args), false);
  2105. const read$2 = handler => isFunction(handler) ? {
  2106. can: always,
  2107. abort: never,
  2108. run: handler
  2109. } : handler;
  2110. const fuse$1 = handlers => {
  2111. const can = all$2(handlers, handler => handler.can);
  2112. const abort = any(handlers, handler => handler.abort);
  2113. const run = (...args) => {
  2114. each$1(handlers, handler => {
  2115. handler.run.apply(undefined, args);
  2116. });
  2117. };
  2118. return {
  2119. can,
  2120. abort,
  2121. run
  2122. };
  2123. };
  2124. const constant = constant$1;
  2125. const touchstart = constant('touchstart');
  2126. const touchmove = constant('touchmove');
  2127. const touchend = constant('touchend');
  2128. const touchcancel = constant('touchcancel');
  2129. const mousedown = constant('mousedown');
  2130. const mousemove = constant('mousemove');
  2131. const mouseout = constant('mouseout');
  2132. const mouseup = constant('mouseup');
  2133. const mouseover = constant('mouseover');
  2134. const focusin = constant('focusin');
  2135. const focusout = constant('focusout');
  2136. const keydown = constant('keydown');
  2137. const keyup = constant('keyup');
  2138. const input = constant('input');
  2139. const change = constant('change');
  2140. const click = constant('click');
  2141. const transitioncancel = constant('transitioncancel');
  2142. const transitionend = constant('transitionend');
  2143. const transitionstart = constant('transitionstart');
  2144. const selectstart = constant('selectstart');
  2145. const prefixName = name => constant$1('alloy.' + name);
  2146. const alloy = { tap: prefixName('tap') };
  2147. const focus$4 = prefixName('focus');
  2148. const postBlur = prefixName('blur.post');
  2149. const postPaste = prefixName('paste.post');
  2150. const receive = prefixName('receive');
  2151. const execute$5 = prefixName('execute');
  2152. const focusItem = prefixName('focus.item');
  2153. const tap = alloy.tap;
  2154. const longpress = prefixName('longpress');
  2155. const sandboxClose = prefixName('sandbox.close');
  2156. const typeaheadCancel = prefixName('typeahead.cancel');
  2157. const systemInit = prefixName('system.init');
  2158. const documentTouchmove = prefixName('system.touchmove');
  2159. const documentTouchend = prefixName('system.touchend');
  2160. const windowScroll = prefixName('system.scroll');
  2161. const windowResize = prefixName('system.resize');
  2162. const attachedToDom = prefixName('system.attached');
  2163. const detachedFromDom = prefixName('system.detached');
  2164. const dismissRequested = prefixName('system.dismissRequested');
  2165. const repositionRequested = prefixName('system.repositionRequested');
  2166. const focusShifted = prefixName('focusmanager.shifted');
  2167. const slotVisibility = prefixName('slotcontainer.visibility');
  2168. const externalElementScroll = prefixName('system.external.element.scroll');
  2169. const changeTab = prefixName('change.tab');
  2170. const dismissTab = prefixName('dismiss.tab');
  2171. const highlight$1 = prefixName('highlight');
  2172. const dehighlight$1 = prefixName('dehighlight');
  2173. const emit = (component, event) => {
  2174. dispatchWith(component, component.element, event, {});
  2175. };
  2176. const emitWith = (component, event, properties) => {
  2177. dispatchWith(component, component.element, event, properties);
  2178. };
  2179. const emitExecute = component => {
  2180. emit(component, execute$5());
  2181. };
  2182. const dispatch = (component, target, event) => {
  2183. dispatchWith(component, target, event, {});
  2184. };
  2185. const dispatchWith = (component, target, event, properties) => {
  2186. const data = {
  2187. target,
  2188. ...properties
  2189. };
  2190. component.getSystem().triggerEvent(event, target, data);
  2191. };
  2192. const retargetAndDispatchWith = (component, target, eventName, properties) => {
  2193. const data = {
  2194. ...properties,
  2195. target
  2196. };
  2197. component.getSystem().triggerEvent(eventName, target, data);
  2198. };
  2199. const dispatchEvent = (component, target, event, simulatedEvent) => {
  2200. component.getSystem().triggerEvent(event, target, simulatedEvent.event);
  2201. };
  2202. const derive$2 = configs => wrapAll(configs);
  2203. const abort = (name, predicate) => {
  2204. return {
  2205. key: name,
  2206. value: nu$9({ abort: predicate })
  2207. };
  2208. };
  2209. const can = (name, predicate) => {
  2210. return {
  2211. key: name,
  2212. value: nu$9({ can: predicate })
  2213. };
  2214. };
  2215. const preventDefault = name => {
  2216. return {
  2217. key: name,
  2218. value: nu$9({
  2219. run: (component, simulatedEvent) => {
  2220. simulatedEvent.event.prevent();
  2221. }
  2222. })
  2223. };
  2224. };
  2225. const run$1 = (name, handler) => {
  2226. return {
  2227. key: name,
  2228. value: nu$9({ run: handler })
  2229. };
  2230. };
  2231. const runActionExtra = (name, action, extra) => {
  2232. return {
  2233. key: name,
  2234. value: nu$9({
  2235. run: (component, simulatedEvent) => {
  2236. action.apply(undefined, [
  2237. component,
  2238. simulatedEvent
  2239. ].concat(extra));
  2240. }
  2241. })
  2242. };
  2243. };
  2244. const runOnName = name => {
  2245. return handler => run$1(name, handler);
  2246. };
  2247. const runOnSourceName = name => {
  2248. return handler => ({
  2249. key: name,
  2250. value: nu$9({
  2251. run: (component, simulatedEvent) => {
  2252. if (isSource(component, simulatedEvent)) {
  2253. handler(component, simulatedEvent);
  2254. }
  2255. }
  2256. })
  2257. });
  2258. };
  2259. const redirectToUid = (name, uid) => {
  2260. return run$1(name, (component, simulatedEvent) => {
  2261. component.getSystem().getByUid(uid).each(redirectee => {
  2262. dispatchEvent(redirectee, redirectee.element, name, simulatedEvent);
  2263. });
  2264. });
  2265. };
  2266. const redirectToPart = (name, detail, partName) => {
  2267. const uid = detail.partUids[partName];
  2268. return redirectToUid(name, uid);
  2269. };
  2270. const runWithTarget = (name, f) => {
  2271. return run$1(name, (component, simulatedEvent) => {
  2272. const ev = simulatedEvent.event;
  2273. const target = component.getSystem().getByDom(ev.target).getOrThunk(() => {
  2274. const closest = closest$4(ev.target, el => component.getSystem().getByDom(el).toOptional(), never);
  2275. return closest.getOr(component);
  2276. });
  2277. f(component, target, simulatedEvent);
  2278. });
  2279. };
  2280. const cutter = name => {
  2281. return run$1(name, (component, simulatedEvent) => {
  2282. simulatedEvent.cut();
  2283. });
  2284. };
  2285. const stopper = name => {
  2286. return run$1(name, (component, simulatedEvent) => {
  2287. simulatedEvent.stop();
  2288. });
  2289. };
  2290. const runOnSource = (name, f) => {
  2291. return runOnSourceName(name)(f);
  2292. };
  2293. const runOnAttached = runOnSourceName(attachedToDom());
  2294. const runOnDetached = runOnSourceName(detachedFromDom());
  2295. const runOnInit = runOnSourceName(systemInit());
  2296. const runOnExecute$1 = runOnName(execute$5());
  2297. const fromHtml$1 = (html, scope) => {
  2298. const doc = scope || document;
  2299. const div = doc.createElement('div');
  2300. div.innerHTML = html;
  2301. return children(SugarElement.fromDom(div));
  2302. };
  2303. const get$9 = element => element.dom.innerHTML;
  2304. const set$6 = (element, content) => {
  2305. const owner = owner$4(element);
  2306. const docDom = owner.dom;
  2307. const fragment = SugarElement.fromDom(docDom.createDocumentFragment());
  2308. const contentElements = fromHtml$1(content, docDom);
  2309. append$1(fragment, contentElements);
  2310. empty(element);
  2311. append$2(element, fragment);
  2312. };
  2313. const getOuter = element => {
  2314. const container = SugarElement.fromTag('div');
  2315. const clone = SugarElement.fromDom(element.dom.cloneNode(true));
  2316. append$2(container, clone);
  2317. return get$9(container);
  2318. };
  2319. const clone$1 = (original, isDeep) => SugarElement.fromDom(original.dom.cloneNode(isDeep));
  2320. const shallow = original => clone$1(original, false);
  2321. const getHtml = element => {
  2322. if (isShadowRoot(element)) {
  2323. return '#shadow-root';
  2324. } else {
  2325. const clone = shallow(element);
  2326. return getOuter(clone);
  2327. }
  2328. };
  2329. const element = elem => getHtml(elem);
  2330. const isRecursive = (component, originator, target) => eq(originator, component.element) && !eq(originator, target);
  2331. const events$i = derive$2([can(focus$4(), (component, simulatedEvent) => {
  2332. const event = simulatedEvent.event;
  2333. const originator = event.originator;
  2334. const target = event.target;
  2335. if (isRecursive(component, originator, target)) {
  2336. console.warn(focus$4() + ' did not get interpreted by the desired target. ' + '\nOriginator: ' + element(originator) + '\nTarget: ' + element(target) + '\nCheck the ' + focus$4() + ' event handlers');
  2337. return false;
  2338. } else {
  2339. return true;
  2340. }
  2341. })]);
  2342. var DefaultEvents = /*#__PURE__*/Object.freeze({
  2343. __proto__: null,
  2344. events: events$i
  2345. });
  2346. let unique = 0;
  2347. const generate$6 = prefix => {
  2348. const date = new Date();
  2349. const time = date.getTime();
  2350. const random = Math.floor(Math.random() * 1000000000);
  2351. unique++;
  2352. return prefix + '_' + random + unique + String(time);
  2353. };
  2354. const prefix$1 = constant$1('alloy-id-');
  2355. const idAttr$1 = constant$1('data-alloy-id');
  2356. const prefix = prefix$1();
  2357. const idAttr = idAttr$1();
  2358. const write = (label, elem) => {
  2359. const id = generate$6(prefix + label);
  2360. writeOnly(elem, id);
  2361. return id;
  2362. };
  2363. const writeOnly = (elem, uid) => {
  2364. Object.defineProperty(elem.dom, idAttr, {
  2365. value: uid,
  2366. writable: true
  2367. });
  2368. };
  2369. const read$1 = elem => {
  2370. const id = isElement$1(elem) ? elem.dom[idAttr] : null;
  2371. return Optional.from(id);
  2372. };
  2373. const generate$5 = prefix => generate$6(prefix);
  2374. const make$8 = identity;
  2375. const NoContextApi = getComp => {
  2376. const getMessage = event => `The component must be in a context to execute: ${ event }` + (getComp ? '\n' + element(getComp().element) + ' is not in context.' : '');
  2377. const fail = event => () => {
  2378. throw new Error(getMessage(event));
  2379. };
  2380. const warn = event => () => {
  2381. console.warn(getMessage(event));
  2382. };
  2383. return {
  2384. debugInfo: constant$1('fake'),
  2385. triggerEvent: warn('triggerEvent'),
  2386. triggerFocus: warn('triggerFocus'),
  2387. triggerEscape: warn('triggerEscape'),
  2388. broadcast: warn('broadcast'),
  2389. broadcastOn: warn('broadcastOn'),
  2390. broadcastEvent: warn('broadcastEvent'),
  2391. build: fail('build'),
  2392. buildOrPatch: fail('buildOrPatch'),
  2393. addToWorld: fail('addToWorld'),
  2394. removeFromWorld: fail('removeFromWorld'),
  2395. addToGui: fail('addToGui'),
  2396. removeFromGui: fail('removeFromGui'),
  2397. getByUid: fail('getByUid'),
  2398. getByDom: fail('getByDom'),
  2399. isConnected: never
  2400. };
  2401. };
  2402. const singleton$1 = NoContextApi();
  2403. const markAsBehaviourApi = (f, apiName, apiFunction) => {
  2404. const delegate = apiFunction.toString();
  2405. const endIndex = delegate.indexOf(')') + 1;
  2406. const openBracketIndex = delegate.indexOf('(');
  2407. const parameters = delegate.substring(openBracketIndex + 1, endIndex - 1).split(/,\s*/);
  2408. f.toFunctionAnnotation = () => ({
  2409. name: apiName,
  2410. parameters: cleanParameters(parameters.slice(0, 1).concat(parameters.slice(3)))
  2411. });
  2412. return f;
  2413. };
  2414. const cleanParameters = parameters => map$2(parameters, p => endsWith(p, '/*') ? p.substring(0, p.length - '/*'.length) : p);
  2415. const markAsExtraApi = (f, extraName) => {
  2416. const delegate = f.toString();
  2417. const endIndex = delegate.indexOf(')') + 1;
  2418. const openBracketIndex = delegate.indexOf('(');
  2419. const parameters = delegate.substring(openBracketIndex + 1, endIndex - 1).split(/,\s*/);
  2420. f.toFunctionAnnotation = () => ({
  2421. name: extraName,
  2422. parameters: cleanParameters(parameters)
  2423. });
  2424. return f;
  2425. };
  2426. const markAsSketchApi = (f, apiFunction) => {
  2427. const delegate = apiFunction.toString();
  2428. const endIndex = delegate.indexOf(')') + 1;
  2429. const openBracketIndex = delegate.indexOf('(');
  2430. const parameters = delegate.substring(openBracketIndex + 1, endIndex - 1).split(/,\s*/);
  2431. f.toFunctionAnnotation = () => ({
  2432. name: 'OVERRIDE',
  2433. parameters: cleanParameters(parameters.slice(1))
  2434. });
  2435. return f;
  2436. };
  2437. const premadeTag = generate$6('alloy-premade');
  2438. const premade$1 = comp => {
  2439. Object.defineProperty(comp.element.dom, premadeTag, {
  2440. value: comp.uid,
  2441. writable: true
  2442. });
  2443. return wrap$1(premadeTag, comp);
  2444. };
  2445. const isPremade = element => has$2(element.dom, premadeTag);
  2446. const getPremade = spec => get$g(spec, premadeTag);
  2447. const makeApi = f => markAsSketchApi((component, ...rest) => f(component.getApis(), component, ...rest), f);
  2448. const NoState = { init: () => nu$8({ readState: constant$1('No State required') }) };
  2449. const nu$8 = spec => spec;
  2450. const generateFrom$1 = (spec, all) => {
  2451. const schema = map$2(all, a => optionObjOf(a.name(), [
  2452. required$1('config'),
  2453. defaulted('state', NoState)
  2454. ]));
  2455. const validated = asRaw('component.behaviours', objOf(schema), spec.behaviours).fold(errInfo => {
  2456. throw new Error(formatError(errInfo) + '\nComplete spec:\n' + JSON.stringify(spec, null, 2));
  2457. }, identity);
  2458. return {
  2459. list: all,
  2460. data: map$1(validated, optBlobThunk => {
  2461. const output = optBlobThunk.map(blob => ({
  2462. config: blob.config,
  2463. state: blob.state.init(blob.config)
  2464. }));
  2465. return constant$1(output);
  2466. })
  2467. };
  2468. };
  2469. const getBehaviours$3 = bData => bData.list;
  2470. const getData$2 = bData => bData.data;
  2471. const byInnerKey = (data, tuple) => {
  2472. const r = {};
  2473. each(data, (detail, key) => {
  2474. each(detail, (value, indexKey) => {
  2475. const chain = get$g(r, indexKey).getOr([]);
  2476. r[indexKey] = chain.concat([tuple(key, value)]);
  2477. });
  2478. });
  2479. return r;
  2480. };
  2481. const nu$7 = s => ({
  2482. classes: isUndefined(s.classes) ? [] : s.classes,
  2483. attributes: isUndefined(s.attributes) ? {} : s.attributes,
  2484. styles: isUndefined(s.styles) ? {} : s.styles
  2485. });
  2486. const merge = (defnA, mod) => ({
  2487. ...defnA,
  2488. attributes: {
  2489. ...defnA.attributes,
  2490. ...mod.attributes
  2491. },
  2492. styles: {
  2493. ...defnA.styles,
  2494. ...mod.styles
  2495. },
  2496. classes: defnA.classes.concat(mod.classes)
  2497. });
  2498. const combine$2 = (info, baseMod, behaviours, base) => {
  2499. const modsByBehaviour = { ...baseMod };
  2500. each$1(behaviours, behaviour => {
  2501. modsByBehaviour[behaviour.name()] = behaviour.exhibit(info, base);
  2502. });
  2503. const byAspect = byInnerKey(modsByBehaviour, (name, modification) => ({
  2504. name,
  2505. modification
  2506. }));
  2507. const combineObjects = objects => foldr(objects, (b, a) => ({
  2508. ...a.modification,
  2509. ...b
  2510. }), {});
  2511. const combinedClasses = foldr(byAspect.classes, (b, a) => a.modification.concat(b), []);
  2512. const combinedAttributes = combineObjects(byAspect.attributes);
  2513. const combinedStyles = combineObjects(byAspect.styles);
  2514. return nu$7({
  2515. classes: combinedClasses,
  2516. attributes: combinedAttributes,
  2517. styles: combinedStyles
  2518. });
  2519. };
  2520. const sortKeys = (label, keyName, array, order) => {
  2521. try {
  2522. const sorted = sort(array, (a, b) => {
  2523. const aKey = a[keyName];
  2524. const bKey = b[keyName];
  2525. const aIndex = order.indexOf(aKey);
  2526. const bIndex = order.indexOf(bKey);
  2527. if (aIndex === -1) {
  2528. throw new Error('The ordering for ' + label + ' does not have an entry for ' + aKey + '.\nOrder specified: ' + JSON.stringify(order, null, 2));
  2529. }
  2530. if (bIndex === -1) {
  2531. throw new Error('The ordering for ' + label + ' does not have an entry for ' + bKey + '.\nOrder specified: ' + JSON.stringify(order, null, 2));
  2532. }
  2533. if (aIndex < bIndex) {
  2534. return -1;
  2535. } else if (bIndex < aIndex) {
  2536. return 1;
  2537. } else {
  2538. return 0;
  2539. }
  2540. });
  2541. return Result.value(sorted);
  2542. } catch (err) {
  2543. return Result.error([err]);
  2544. }
  2545. };
  2546. const uncurried = (handler, purpose) => ({
  2547. handler,
  2548. purpose
  2549. });
  2550. const curried = (handler, purpose) => ({
  2551. cHandler: handler,
  2552. purpose
  2553. });
  2554. const curryArgs = (descHandler, extraArgs) => curried(curry.apply(undefined, [descHandler.handler].concat(extraArgs)), descHandler.purpose);
  2555. const getCurried = descHandler => descHandler.cHandler;
  2556. const behaviourTuple = (name, handler) => ({
  2557. name,
  2558. handler
  2559. });
  2560. const nameToHandlers = (behaviours, info) => {
  2561. const r = {};
  2562. each$1(behaviours, behaviour => {
  2563. r[behaviour.name()] = behaviour.handlers(info);
  2564. });
  2565. return r;
  2566. };
  2567. const groupByEvents = (info, behaviours, base) => {
  2568. const behaviourEvents = {
  2569. ...base,
  2570. ...nameToHandlers(behaviours, info)
  2571. };
  2572. return byInnerKey(behaviourEvents, behaviourTuple);
  2573. };
  2574. const combine$1 = (info, eventOrder, behaviours, base) => {
  2575. const byEventName = groupByEvents(info, behaviours, base);
  2576. return combineGroups(byEventName, eventOrder);
  2577. };
  2578. const assemble = rawHandler => {
  2579. const handler = read$2(rawHandler);
  2580. return (component, simulatedEvent, ...rest) => {
  2581. const args = [
  2582. component,
  2583. simulatedEvent
  2584. ].concat(rest);
  2585. if (handler.abort.apply(undefined, args)) {
  2586. simulatedEvent.stop();
  2587. } else if (handler.can.apply(undefined, args)) {
  2588. handler.run.apply(undefined, args);
  2589. }
  2590. };
  2591. };
  2592. 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)]);
  2593. const fuse = (tuples, eventOrder, eventName) => {
  2594. const order = eventOrder[eventName];
  2595. if (!order) {
  2596. return missingOrderError(eventName, tuples);
  2597. } else {
  2598. return sortKeys('Event: ' + eventName, 'name', tuples, order).map(sortedTuples => {
  2599. const handlers = map$2(sortedTuples, tuple => tuple.handler);
  2600. return fuse$1(handlers);
  2601. });
  2602. }
  2603. };
  2604. const combineGroups = (byEventName, eventOrder) => {
  2605. const r = mapToArray(byEventName, (tuples, eventName) => {
  2606. const combined = tuples.length === 1 ? Result.value(tuples[0].handler) : fuse(tuples, eventOrder, eventName);
  2607. return combined.map(handler => {
  2608. const assembled = assemble(handler);
  2609. const purpose = tuples.length > 1 ? filter$2(eventOrder[eventName], o => exists(tuples, t => t.name === o)).join(' > ') : tuples[0].name;
  2610. return wrap$1(eventName, uncurried(assembled, purpose));
  2611. });
  2612. });
  2613. return consolidate(r, {});
  2614. };
  2615. const baseBehaviour = 'alloy.base.behaviour';
  2616. const schema$z = objOf([
  2617. field$1('dom', 'dom', required$2(), objOf([
  2618. required$1('tag'),
  2619. defaulted('styles', {}),
  2620. defaulted('classes', []),
  2621. defaulted('attributes', {}),
  2622. option$3('value'),
  2623. option$3('innerHtml')
  2624. ])),
  2625. required$1('components'),
  2626. required$1('uid'),
  2627. defaulted('events', {}),
  2628. defaulted('apis', {}),
  2629. field$1('eventOrder', 'eventOrder', mergeWith({
  2630. [execute$5()]: [
  2631. 'disabling',
  2632. baseBehaviour,
  2633. 'toggling',
  2634. 'typeaheadevents'
  2635. ],
  2636. [focus$4()]: [
  2637. baseBehaviour,
  2638. 'focusing',
  2639. 'keying'
  2640. ],
  2641. [systemInit()]: [
  2642. baseBehaviour,
  2643. 'disabling',
  2644. 'toggling',
  2645. 'representing'
  2646. ],
  2647. [input()]: [
  2648. baseBehaviour,
  2649. 'representing',
  2650. 'streaming',
  2651. 'invalidating'
  2652. ],
  2653. [detachedFromDom()]: [
  2654. baseBehaviour,
  2655. 'representing',
  2656. 'item-events',
  2657. 'tooltipping'
  2658. ],
  2659. [mousedown()]: [
  2660. 'focusing',
  2661. baseBehaviour,
  2662. 'item-type-events'
  2663. ],
  2664. [touchstart()]: [
  2665. 'focusing',
  2666. baseBehaviour,
  2667. 'item-type-events'
  2668. ],
  2669. [mouseover()]: [
  2670. 'item-type-events',
  2671. 'tooltipping'
  2672. ],
  2673. [receive()]: [
  2674. 'receiving',
  2675. 'reflecting',
  2676. 'tooltipping'
  2677. ]
  2678. }), anyValue()),
  2679. option$3('domModification')
  2680. ]);
  2681. const toInfo = spec => asRaw('custom.definition', schema$z, spec);
  2682. const toDefinition = detail => ({
  2683. ...detail.dom,
  2684. uid: detail.uid,
  2685. domChildren: map$2(detail.components, comp => comp.element)
  2686. });
  2687. const toModification = detail => detail.domModification.fold(() => nu$7({}), nu$7);
  2688. const toEvents = info => info.events;
  2689. const read = (element, attr) => {
  2690. const value = get$f(element, attr);
  2691. return value === undefined || value === '' ? [] : value.split(' ');
  2692. };
  2693. const add$4 = (element, attr, id) => {
  2694. const old = read(element, attr);
  2695. const nu = old.concat([id]);
  2696. set$9(element, attr, nu.join(' '));
  2697. return true;
  2698. };
  2699. const remove$4 = (element, attr, id) => {
  2700. const nu = filter$2(read(element, attr), v => v !== id);
  2701. if (nu.length > 0) {
  2702. set$9(element, attr, nu.join(' '));
  2703. } else {
  2704. remove$7(element, attr);
  2705. }
  2706. return false;
  2707. };
  2708. const supports = element => element.dom.classList !== undefined;
  2709. const get$8 = element => read(element, 'class');
  2710. const add$3 = (element, clazz) => add$4(element, 'class', clazz);
  2711. const remove$3 = (element, clazz) => remove$4(element, 'class', clazz);
  2712. const add$2 = (element, clazz) => {
  2713. if (supports(element)) {
  2714. element.dom.classList.add(clazz);
  2715. } else {
  2716. add$3(element, clazz);
  2717. }
  2718. };
  2719. const cleanClass = element => {
  2720. const classList = supports(element) ? element.dom.classList : get$8(element);
  2721. if (classList.length === 0) {
  2722. remove$7(element, 'class');
  2723. }
  2724. };
  2725. const remove$2 = (element, clazz) => {
  2726. if (supports(element)) {
  2727. const classList = element.dom.classList;
  2728. classList.remove(clazz);
  2729. } else {
  2730. remove$3(element, clazz);
  2731. }
  2732. cleanClass(element);
  2733. };
  2734. const has = (element, clazz) => supports(element) && element.dom.classList.contains(clazz);
  2735. const add$1 = (element, classes) => {
  2736. each$1(classes, x => {
  2737. add$2(element, x);
  2738. });
  2739. };
  2740. const remove$1 = (element, classes) => {
  2741. each$1(classes, x => {
  2742. remove$2(element, x);
  2743. });
  2744. };
  2745. const hasAll = (element, classes) => forall(classes, clazz => has(element, clazz));
  2746. const getNative = element => {
  2747. const classList = element.dom.classList;
  2748. const r = new Array(classList.length);
  2749. for (let i = 0; i < classList.length; i++) {
  2750. const item = classList.item(i);
  2751. if (item !== null) {
  2752. r[i] = item;
  2753. }
  2754. }
  2755. return r;
  2756. };
  2757. const get$7 = element => supports(element) ? getNative(element) : get$8(element);
  2758. const get$6 = element => element.dom.value;
  2759. const set$5 = (element, value) => {
  2760. if (value === undefined) {
  2761. throw new Error('Value.set was undefined');
  2762. }
  2763. element.dom.value = value;
  2764. };
  2765. const determineObsoleted = (parent, index, oldObsoleted) => {
  2766. const newObsoleted = child$2(parent, index);
  2767. return newObsoleted.map(newObs => {
  2768. const elemChanged = oldObsoleted.exists(o => !eq(o, newObs));
  2769. if (elemChanged) {
  2770. const oldTag = oldObsoleted.map(name$3).getOr('span');
  2771. const marker = SugarElement.fromTag(oldTag);
  2772. before$1(newObs, marker);
  2773. return marker;
  2774. } else {
  2775. return newObs;
  2776. }
  2777. });
  2778. };
  2779. const ensureInDom = (parent, child, obsoleted) => {
  2780. obsoleted.fold(() => append$2(parent, child), obs => {
  2781. if (!eq(obs, child)) {
  2782. before$1(obs, child);
  2783. remove$5(obs);
  2784. }
  2785. });
  2786. };
  2787. const patchChildrenWith = (parent, nu, f) => {
  2788. const builtChildren = map$2(nu, f);
  2789. const currentChildren = children(parent);
  2790. each$1(currentChildren.slice(builtChildren.length), remove$5);
  2791. return builtChildren;
  2792. };
  2793. const patchSpecChild = (parent, index, spec, build) => {
  2794. const oldObsoleted = child$2(parent, index);
  2795. const childComp = build(spec, oldObsoleted);
  2796. const obsoleted = determineObsoleted(parent, index, oldObsoleted);
  2797. ensureInDom(parent, childComp.element, obsoleted);
  2798. return childComp;
  2799. };
  2800. const patchSpecChildren = (parent, specs, build) => patchChildrenWith(parent, specs, (spec, index) => patchSpecChild(parent, index, spec, build));
  2801. const patchDomChildren = (parent, nodes) => patchChildrenWith(parent, nodes, (node, index) => {
  2802. const optObsoleted = child$2(parent, index);
  2803. ensureInDom(parent, node, optObsoleted);
  2804. return node;
  2805. });
  2806. const diffKeyValueSet = (newObj, oldObj) => {
  2807. const newKeys = keys(newObj);
  2808. const oldKeys = keys(oldObj);
  2809. const toRemove = difference(oldKeys, newKeys);
  2810. const toSet = bifilter(newObj, (v, k) => {
  2811. return !has$2(oldObj, k) || v !== oldObj[k];
  2812. }).t;
  2813. return {
  2814. toRemove,
  2815. toSet
  2816. };
  2817. };
  2818. const reconcileToDom = (definition, obsoleted) => {
  2819. const {
  2820. class: clazz,
  2821. style,
  2822. ...existingAttributes
  2823. } = clone$2(obsoleted);
  2824. const {
  2825. toSet: attrsToSet,
  2826. toRemove: attrsToRemove
  2827. } = diffKeyValueSet(definition.attributes, existingAttributes);
  2828. const updateAttrs = () => {
  2829. each$1(attrsToRemove, a => remove$7(obsoleted, a));
  2830. setAll$1(obsoleted, attrsToSet);
  2831. };
  2832. const existingStyles = getAllRaw(obsoleted);
  2833. const {
  2834. toSet: stylesToSet,
  2835. toRemove: stylesToRemove
  2836. } = diffKeyValueSet(definition.styles, existingStyles);
  2837. const updateStyles = () => {
  2838. each$1(stylesToRemove, s => remove$6(obsoleted, s));
  2839. setAll(obsoleted, stylesToSet);
  2840. };
  2841. const existingClasses = get$7(obsoleted);
  2842. const classesToRemove = difference(existingClasses, definition.classes);
  2843. const classesToAdd = difference(definition.classes, existingClasses);
  2844. const updateClasses = () => {
  2845. add$1(obsoleted, classesToAdd);
  2846. remove$1(obsoleted, classesToRemove);
  2847. };
  2848. const updateHtml = html => {
  2849. set$6(obsoleted, html);
  2850. };
  2851. const updateChildren = () => {
  2852. const children = definition.domChildren;
  2853. patchDomChildren(obsoleted, children);
  2854. };
  2855. const updateValue = () => {
  2856. const valueElement = obsoleted;
  2857. const value = definition.value.getOrUndefined();
  2858. if (value !== get$6(valueElement)) {
  2859. set$5(valueElement, value !== null && value !== void 0 ? value : '');
  2860. }
  2861. };
  2862. updateAttrs();
  2863. updateClasses();
  2864. updateStyles();
  2865. definition.innerHtml.fold(updateChildren, updateHtml);
  2866. updateValue();
  2867. return obsoleted;
  2868. };
  2869. const introduceToDom = definition => {
  2870. const subject = SugarElement.fromTag(definition.tag);
  2871. setAll$1(subject, definition.attributes);
  2872. add$1(subject, definition.classes);
  2873. setAll(subject, definition.styles);
  2874. definition.innerHtml.each(html => set$6(subject, html));
  2875. const children = definition.domChildren;
  2876. append$1(subject, children);
  2877. definition.value.each(value => {
  2878. set$5(subject, value);
  2879. });
  2880. return subject;
  2881. };
  2882. const attemptPatch = (definition, obsoleted) => {
  2883. try {
  2884. const e = reconcileToDom(definition, obsoleted);
  2885. return Optional.some(e);
  2886. } catch (err) {
  2887. return Optional.none();
  2888. }
  2889. };
  2890. const hasMixedChildren = definition => definition.innerHtml.isSome() && definition.domChildren.length > 0;
  2891. const renderToDom = (definition, optObsoleted) => {
  2892. const canBePatched = candidate => name$3(candidate) === definition.tag && !hasMixedChildren(definition) && !isPremade(candidate);
  2893. const elem = optObsoleted.filter(canBePatched).bind(obsoleted => attemptPatch(definition, obsoleted)).getOrThunk(() => introduceToDom(definition));
  2894. writeOnly(elem, definition.uid);
  2895. return elem;
  2896. };
  2897. const getBehaviours$2 = spec => {
  2898. const behaviours = get$g(spec, 'behaviours').getOr({});
  2899. return bind$3(keys(behaviours), name => {
  2900. const behaviour = behaviours[name];
  2901. return isNonNullable(behaviour) ? [behaviour.me] : [];
  2902. });
  2903. };
  2904. const generateFrom = (spec, all) => generateFrom$1(spec, all);
  2905. const generate$4 = spec => {
  2906. const all = getBehaviours$2(spec);
  2907. return generateFrom(spec, all);
  2908. };
  2909. const getDomDefinition = (info, bList, bData) => {
  2910. const definition = toDefinition(info);
  2911. const infoModification = toModification(info);
  2912. const baseModification = { 'alloy.base.modification': infoModification };
  2913. const modification = bList.length > 0 ? combine$2(bData, baseModification, bList, definition) : infoModification;
  2914. return merge(definition, modification);
  2915. };
  2916. const getEvents = (info, bList, bData) => {
  2917. const baseEvents = { 'alloy.base.behaviour': toEvents(info) };
  2918. return combine$1(bData, info.eventOrder, bList, baseEvents).getOrDie();
  2919. };
  2920. const build$2 = (spec, obsoleted) => {
  2921. const getMe = () => me;
  2922. const systemApi = Cell(singleton$1);
  2923. const info = getOrDie(toInfo(spec));
  2924. const bBlob = generate$4(spec);
  2925. const bList = getBehaviours$3(bBlob);
  2926. const bData = getData$2(bBlob);
  2927. const modDefinition = getDomDefinition(info, bList, bData);
  2928. const item = renderToDom(modDefinition, obsoleted);
  2929. const events = getEvents(info, bList, bData);
  2930. const subcomponents = Cell(info.components);
  2931. const connect = newApi => {
  2932. systemApi.set(newApi);
  2933. };
  2934. const disconnect = () => {
  2935. systemApi.set(NoContextApi(getMe));
  2936. };
  2937. const syncComponents = () => {
  2938. const children$1 = children(item);
  2939. const subs = bind$3(children$1, child => systemApi.get().getByDom(child).fold(() => [], pure$2));
  2940. subcomponents.set(subs);
  2941. };
  2942. const config = behaviour => {
  2943. const b = bData;
  2944. const f = isFunction(b[behaviour.name()]) ? b[behaviour.name()] : () => {
  2945. throw new Error('Could not find ' + behaviour.name() + ' in ' + JSON.stringify(spec, null, 2));
  2946. };
  2947. return f();
  2948. };
  2949. const hasConfigured = behaviour => isFunction(bData[behaviour.name()]);
  2950. const getApis = () => info.apis;
  2951. const readState = behaviourName => bData[behaviourName]().map(b => b.state.readState()).getOr('not enabled');
  2952. const me = {
  2953. uid: spec.uid,
  2954. getSystem: systemApi.get,
  2955. config,
  2956. hasConfigured,
  2957. spec,
  2958. readState,
  2959. getApis,
  2960. connect,
  2961. disconnect,
  2962. element: item,
  2963. syncComponents,
  2964. components: subcomponents.get,
  2965. events
  2966. };
  2967. return me;
  2968. };
  2969. const buildSubcomponents = (spec, obsoleted) => {
  2970. const components = get$g(spec, 'components').getOr([]);
  2971. return obsoleted.fold(() => map$2(components, build$1), obs => map$2(components, (c, i) => {
  2972. return buildOrPatch(c, child$2(obs, i));
  2973. }));
  2974. };
  2975. const buildFromSpec = (userSpec, obsoleted) => {
  2976. const {
  2977. events: specEvents,
  2978. ...spec
  2979. } = make$8(userSpec);
  2980. const components = buildSubcomponents(spec, obsoleted);
  2981. const completeSpec = {
  2982. ...spec,
  2983. events: {
  2984. ...DefaultEvents,
  2985. ...specEvents
  2986. },
  2987. components
  2988. };
  2989. return Result.value(build$2(completeSpec, obsoleted));
  2990. };
  2991. const text$2 = textContent => {
  2992. const element = SugarElement.fromText(textContent);
  2993. return external$1({ element });
  2994. };
  2995. const external$1 = spec => {
  2996. const extSpec = asRawOrDie$1('external.component', objOfOnly([
  2997. required$1('element'),
  2998. option$3('uid')
  2999. ]), spec);
  3000. const systemApi = Cell(NoContextApi());
  3001. const connect = newApi => {
  3002. systemApi.set(newApi);
  3003. };
  3004. const disconnect = () => {
  3005. systemApi.set(NoContextApi(() => me));
  3006. };
  3007. const uid = extSpec.uid.getOrThunk(() => generate$5('external'));
  3008. writeOnly(extSpec.element, uid);
  3009. const me = {
  3010. uid,
  3011. getSystem: systemApi.get,
  3012. config: Optional.none,
  3013. hasConfigured: never,
  3014. connect,
  3015. disconnect,
  3016. getApis: () => ({}),
  3017. element: extSpec.element,
  3018. spec,
  3019. readState: constant$1('No state'),
  3020. syncComponents: noop,
  3021. components: constant$1([]),
  3022. events: {}
  3023. };
  3024. return premade$1(me);
  3025. };
  3026. const uids = generate$5;
  3027. const isSketchSpec$1 = spec => has$2(spec, 'uid');
  3028. const buildOrPatch = (spec, obsoleted) => getPremade(spec).getOrThunk(() => {
  3029. const userSpecWithUid = isSketchSpec$1(spec) ? spec : {
  3030. uid: uids(''),
  3031. ...spec
  3032. };
  3033. return buildFromSpec(userSpecWithUid, obsoleted).getOrDie();
  3034. });
  3035. const build$1 = spec => buildOrPatch(spec, Optional.none());
  3036. const premade = premade$1;
  3037. var ClosestOrAncestor = (is, ancestor, scope, a, isRoot) => {
  3038. if (is(scope, a)) {
  3039. return Optional.some(scope);
  3040. } else if (isFunction(isRoot) && isRoot(scope)) {
  3041. return Optional.none();
  3042. } else {
  3043. return ancestor(scope, a, isRoot);
  3044. }
  3045. };
  3046. const ancestor$1 = (scope, predicate, isRoot) => {
  3047. let element = scope.dom;
  3048. const stop = isFunction(isRoot) ? isRoot : never;
  3049. while (element.parentNode) {
  3050. element = element.parentNode;
  3051. const el = SugarElement.fromDom(element);
  3052. if (predicate(el)) {
  3053. return Optional.some(el);
  3054. } else if (stop(el)) {
  3055. break;
  3056. }
  3057. }
  3058. return Optional.none();
  3059. };
  3060. const closest$3 = (scope, predicate, isRoot) => {
  3061. const is = (s, test) => test(s);
  3062. return ClosestOrAncestor(is, ancestor$1, scope, predicate, isRoot);
  3063. };
  3064. const child$1 = (scope, predicate) => {
  3065. const pred = node => predicate(SugarElement.fromDom(node));
  3066. const result = find$5(scope.dom.childNodes, pred);
  3067. return result.map(SugarElement.fromDom);
  3068. };
  3069. const descendant$1 = (scope, predicate) => {
  3070. const descend = node => {
  3071. for (let i = 0; i < node.childNodes.length; i++) {
  3072. const child = SugarElement.fromDom(node.childNodes[i]);
  3073. if (predicate(child)) {
  3074. return Optional.some(child);
  3075. }
  3076. const res = descend(node.childNodes[i]);
  3077. if (res.isSome()) {
  3078. return res;
  3079. }
  3080. }
  3081. return Optional.none();
  3082. };
  3083. return descend(scope.dom);
  3084. };
  3085. const closest$2 = (scope, predicate, isRoot) => closest$3(scope, predicate, isRoot).isSome();
  3086. const ancestor = (scope, selector, isRoot) => ancestor$1(scope, e => is(e, selector), isRoot);
  3087. const child = (scope, selector) => child$1(scope, e => is(e, selector));
  3088. const descendant = (scope, selector) => one(selector, scope);
  3089. const closest$1 = (scope, selector, isRoot) => {
  3090. const is$1 = (element, selector) => is(element, selector);
  3091. return ClosestOrAncestor(is$1, ancestor, scope, selector, isRoot);
  3092. };
  3093. const attribute = 'aria-controls';
  3094. const find$1 = queryElem => {
  3095. const dependent = closest$3(queryElem, elem => {
  3096. if (!isElement$1(elem)) {
  3097. return false;
  3098. }
  3099. const id = get$f(elem, 'id');
  3100. return id !== undefined && id.indexOf(attribute) > -1;
  3101. });
  3102. return dependent.bind(dep => {
  3103. const id = get$f(dep, 'id');
  3104. const dos = getRootNode(dep);
  3105. return descendant(dos, `[${ attribute }="${ id }"]`);
  3106. });
  3107. };
  3108. const manager = () => {
  3109. const ariaId = generate$6(attribute);
  3110. const link = elem => {
  3111. set$9(elem, attribute, ariaId);
  3112. };
  3113. const unlink = elem => {
  3114. remove$7(elem, attribute);
  3115. };
  3116. return {
  3117. id: ariaId,
  3118. link,
  3119. unlink
  3120. };
  3121. };
  3122. const isAriaPartOf = (component, queryElem) => find$1(queryElem).exists(owner => isPartOf$1(component, owner));
  3123. const isPartOf$1 = (component, queryElem) => closest$2(queryElem, el => eq(el, component.element), never) || isAriaPartOf(component, queryElem);
  3124. const unknown = 'unknown';
  3125. var EventConfiguration;
  3126. (function (EventConfiguration) {
  3127. EventConfiguration[EventConfiguration['STOP'] = 0] = 'STOP';
  3128. EventConfiguration[EventConfiguration['NORMAL'] = 1] = 'NORMAL';
  3129. EventConfiguration[EventConfiguration['LOGGING'] = 2] = 'LOGGING';
  3130. }(EventConfiguration || (EventConfiguration = {})));
  3131. const eventConfig = Cell({});
  3132. const makeEventLogger = (eventName, initialTarget) => {
  3133. const sequence = [];
  3134. const startTime = new Date().getTime();
  3135. return {
  3136. logEventCut: (_name, target, purpose) => {
  3137. sequence.push({
  3138. outcome: 'cut',
  3139. target,
  3140. purpose
  3141. });
  3142. },
  3143. logEventStopped: (_name, target, purpose) => {
  3144. sequence.push({
  3145. outcome: 'stopped',
  3146. target,
  3147. purpose
  3148. });
  3149. },
  3150. logNoParent: (_name, target, purpose) => {
  3151. sequence.push({
  3152. outcome: 'no-parent',
  3153. target,
  3154. purpose
  3155. });
  3156. },
  3157. logEventNoHandlers: (_name, target) => {
  3158. sequence.push({
  3159. outcome: 'no-handlers-left',
  3160. target
  3161. });
  3162. },
  3163. logEventResponse: (_name, target, purpose) => {
  3164. sequence.push({
  3165. outcome: 'response',
  3166. purpose,
  3167. target
  3168. });
  3169. },
  3170. write: () => {
  3171. const finishTime = new Date().getTime();
  3172. if (contains$2([
  3173. 'mousemove',
  3174. 'mouseover',
  3175. 'mouseout',
  3176. systemInit()
  3177. ], eventName)) {
  3178. return;
  3179. }
  3180. console.log(eventName, {
  3181. event: eventName,
  3182. time: finishTime - startTime,
  3183. target: initialTarget.dom,
  3184. sequence: map$2(sequence, s => {
  3185. if (!contains$2([
  3186. 'cut',
  3187. 'stopped',
  3188. 'response'
  3189. ], s.outcome)) {
  3190. return s.outcome;
  3191. } else {
  3192. return '{' + s.purpose + '} ' + s.outcome + ' at (' + element(s.target) + ')';
  3193. }
  3194. })
  3195. });
  3196. }
  3197. };
  3198. };
  3199. const processEvent = (eventName, initialTarget, f) => {
  3200. const status = get$g(eventConfig.get(), eventName).orThunk(() => {
  3201. const patterns = keys(eventConfig.get());
  3202. return findMap(patterns, p => eventName.indexOf(p) > -1 ? Optional.some(eventConfig.get()[p]) : Optional.none());
  3203. }).getOr(EventConfiguration.NORMAL);
  3204. switch (status) {
  3205. case EventConfiguration.NORMAL:
  3206. return f(noLogger());
  3207. case EventConfiguration.LOGGING: {
  3208. const logger = makeEventLogger(eventName, initialTarget);
  3209. const output = f(logger);
  3210. logger.write();
  3211. return output;
  3212. }
  3213. case EventConfiguration.STOP:
  3214. return true;
  3215. }
  3216. };
  3217. const path = [
  3218. 'alloy/data/Fields',
  3219. 'alloy/debugging/Debugging'
  3220. ];
  3221. const getTrace = () => {
  3222. const err = new Error();
  3223. if (err.stack !== undefined) {
  3224. const lines = err.stack.split('\n');
  3225. return find$5(lines, line => line.indexOf('alloy') > 0 && !exists(path, p => line.indexOf(p) > -1)).getOr(unknown);
  3226. } else {
  3227. return unknown;
  3228. }
  3229. };
  3230. const ignoreEvent = {
  3231. logEventCut: noop,
  3232. logEventStopped: noop,
  3233. logNoParent: noop,
  3234. logEventNoHandlers: noop,
  3235. logEventResponse: noop,
  3236. write: noop
  3237. };
  3238. const monitorEvent = (eventName, initialTarget, f) => processEvent(eventName, initialTarget, f);
  3239. const noLogger = constant$1(ignoreEvent);
  3240. const menuFields = constant$1([
  3241. required$1('menu'),
  3242. required$1('selectedMenu')
  3243. ]);
  3244. const itemFields = constant$1([
  3245. required$1('item'),
  3246. required$1('selectedItem')
  3247. ]);
  3248. constant$1(objOf(itemFields().concat(menuFields())));
  3249. const itemSchema$3 = constant$1(objOf(itemFields()));
  3250. const _initSize = requiredObjOf('initSize', [
  3251. required$1('numColumns'),
  3252. required$1('numRows')
  3253. ]);
  3254. const itemMarkers = () => requiredOf('markers', itemSchema$3());
  3255. const tieredMenuMarkers = () => requiredObjOf('markers', [required$1('backgroundMenu')].concat(menuFields()).concat(itemFields()));
  3256. const markers$1 = required => requiredObjOf('markers', map$2(required, required$1));
  3257. const onPresenceHandler = (label, fieldName, presence) => {
  3258. getTrace();
  3259. return field$1(fieldName, fieldName, presence, valueOf(f => Result.value((...args) => {
  3260. return f.apply(undefined, args);
  3261. })));
  3262. };
  3263. const onHandler = fieldName => onPresenceHandler('onHandler', fieldName, defaulted$1(noop));
  3264. const onKeyboardHandler = fieldName => onPresenceHandler('onKeyboardHandler', fieldName, defaulted$1(Optional.none));
  3265. const onStrictHandler = fieldName => onPresenceHandler('onHandler', fieldName, required$2());
  3266. const onStrictKeyboardHandler = fieldName => onPresenceHandler('onKeyboardHandler', fieldName, required$2());
  3267. const output$1 = (name, value) => customField(name, constant$1(value));
  3268. const snapshot = name => customField(name, identity);
  3269. const initSize = constant$1(_initSize);
  3270. const nu$6 = (x, y, bubble, direction, placement, boundsRestriction, labelPrefix, alwaysFit = false) => ({
  3271. x,
  3272. y,
  3273. bubble,
  3274. direction,
  3275. placement,
  3276. restriction: boundsRestriction,
  3277. label: `${ labelPrefix }-${ placement }`,
  3278. alwaysFit
  3279. });
  3280. const adt$a = Adt.generate([
  3281. { southeast: [] },
  3282. { southwest: [] },
  3283. { northeast: [] },
  3284. { northwest: [] },
  3285. { south: [] },
  3286. { north: [] },
  3287. { east: [] },
  3288. { west: [] }
  3289. ]);
  3290. const cata$2 = (subject, southeast, southwest, northeast, northwest, south, north, east, west) => subject.fold(southeast, southwest, northeast, northwest, south, north, east, west);
  3291. const cataVertical = (subject, south, middle, north) => subject.fold(south, south, north, north, south, north, middle, middle);
  3292. const cataHorizontal = (subject, east, middle, west) => subject.fold(east, west, east, west, middle, middle, east, west);
  3293. const southeast$3 = adt$a.southeast;
  3294. const southwest$3 = adt$a.southwest;
  3295. const northeast$3 = adt$a.northeast;
  3296. const northwest$3 = adt$a.northwest;
  3297. const south$3 = adt$a.south;
  3298. const north$3 = adt$a.north;
  3299. const east$3 = adt$a.east;
  3300. const west$3 = adt$a.west;
  3301. const cycleBy = (value, delta, min, max) => {
  3302. const r = value + delta;
  3303. if (r > max) {
  3304. return min;
  3305. } else if (r < min) {
  3306. return max;
  3307. } else {
  3308. return r;
  3309. }
  3310. };
  3311. const clamp = (value, min, max) => Math.min(Math.max(value, min), max);
  3312. const getRestriction = (anchor, restriction) => {
  3313. switch (restriction) {
  3314. case 1:
  3315. return anchor.x;
  3316. case 0:
  3317. return anchor.x + anchor.width;
  3318. case 2:
  3319. return anchor.y;
  3320. case 3:
  3321. return anchor.y + anchor.height;
  3322. }
  3323. };
  3324. const boundsRestriction = (anchor, restrictions) => mapToObject([
  3325. 'left',
  3326. 'right',
  3327. 'top',
  3328. 'bottom'
  3329. ], dir => get$g(restrictions, dir).map(restriction => getRestriction(anchor, restriction)));
  3330. const adjustBounds = (bounds$1, restriction, bubbleOffset) => {
  3331. const applyRestriction = (dir, current) => restriction[dir].map(pos => {
  3332. const isVerticalAxis = dir === 'top' || dir === 'bottom';
  3333. const offset = isVerticalAxis ? bubbleOffset.top : bubbleOffset.left;
  3334. const comparator = dir === 'left' || dir === 'top' ? Math.max : Math.min;
  3335. const newPos = comparator(pos, current) + offset;
  3336. return isVerticalAxis ? clamp(newPos, bounds$1.y, bounds$1.bottom) : clamp(newPos, bounds$1.x, bounds$1.right);
  3337. }).getOr(current);
  3338. const adjustedLeft = applyRestriction('left', bounds$1.x);
  3339. const adjustedTop = applyRestriction('top', bounds$1.y);
  3340. const adjustedRight = applyRestriction('right', bounds$1.right);
  3341. const adjustedBottom = applyRestriction('bottom', bounds$1.bottom);
  3342. return bounds(adjustedLeft, adjustedTop, adjustedRight - adjustedLeft, adjustedBottom - adjustedTop);
  3343. };
  3344. const labelPrefix$2 = 'layout';
  3345. const eastX$1 = anchor => anchor.x;
  3346. const middleX$1 = (anchor, element) => anchor.x + anchor.width / 2 - element.width / 2;
  3347. const westX$1 = (anchor, element) => anchor.x + anchor.width - element.width;
  3348. const northY$2 = (anchor, element) => anchor.y - element.height;
  3349. const southY$2 = anchor => anchor.y + anchor.height;
  3350. const centreY$1 = (anchor, element) => anchor.y + anchor.height / 2 - element.height / 2;
  3351. const eastEdgeX$1 = anchor => anchor.x + anchor.width;
  3352. const westEdgeX$1 = (anchor, element) => anchor.x - element.width;
  3353. const southeast$2 = (anchor, element, bubbles) => nu$6(eastX$1(anchor), southY$2(anchor), bubbles.southeast(), southeast$3(), 'southeast', boundsRestriction(anchor, {
  3354. left: 1,
  3355. top: 3
  3356. }), labelPrefix$2);
  3357. const southwest$2 = (anchor, element, bubbles) => nu$6(westX$1(anchor, element), southY$2(anchor), bubbles.southwest(), southwest$3(), 'southwest', boundsRestriction(anchor, {
  3358. right: 0,
  3359. top: 3
  3360. }), labelPrefix$2);
  3361. const northeast$2 = (anchor, element, bubbles) => nu$6(eastX$1(anchor), northY$2(anchor, element), bubbles.northeast(), northeast$3(), 'northeast', boundsRestriction(anchor, {
  3362. left: 1,
  3363. bottom: 2
  3364. }), labelPrefix$2);
  3365. const northwest$2 = (anchor, element, bubbles) => nu$6(westX$1(anchor, element), northY$2(anchor, element), bubbles.northwest(), northwest$3(), 'northwest', boundsRestriction(anchor, {
  3366. right: 0,
  3367. bottom: 2
  3368. }), labelPrefix$2);
  3369. 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);
  3370. 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);
  3371. 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);
  3372. 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);
  3373. const all$1 = () => [
  3374. southeast$2,
  3375. southwest$2,
  3376. northeast$2,
  3377. northwest$2,
  3378. south$2,
  3379. north$2,
  3380. east$2,
  3381. west$2
  3382. ];
  3383. const allRtl$1 = () => [
  3384. southwest$2,
  3385. southeast$2,
  3386. northwest$2,
  3387. northeast$2,
  3388. south$2,
  3389. north$2,
  3390. east$2,
  3391. west$2
  3392. ];
  3393. const aboveOrBelow = () => [
  3394. northeast$2,
  3395. northwest$2,
  3396. southeast$2,
  3397. southwest$2,
  3398. north$2,
  3399. south$2
  3400. ];
  3401. const aboveOrBelowRtl = () => [
  3402. northwest$2,
  3403. northeast$2,
  3404. southwest$2,
  3405. southeast$2,
  3406. north$2,
  3407. south$2
  3408. ];
  3409. const belowOrAbove = () => [
  3410. southeast$2,
  3411. southwest$2,
  3412. northeast$2,
  3413. northwest$2,
  3414. south$2,
  3415. north$2
  3416. ];
  3417. const belowOrAboveRtl = () => [
  3418. southwest$2,
  3419. southeast$2,
  3420. northwest$2,
  3421. northeast$2,
  3422. south$2,
  3423. north$2
  3424. ];
  3425. const chooseChannels = (channels, message) => message.universal ? channels : filter$2(channels, ch => contains$2(message.channels, ch));
  3426. const events$h = receiveConfig => derive$2([run$1(receive(), (component, message) => {
  3427. const channelMap = receiveConfig.channels;
  3428. const channels = keys(channelMap);
  3429. const receivingData = message;
  3430. const targetChannels = chooseChannels(channels, receivingData);
  3431. each$1(targetChannels, ch => {
  3432. const channelInfo = channelMap[ch];
  3433. const channelSchema = channelInfo.schema;
  3434. const data = asRawOrDie$1('channel[' + ch + '] data\nReceiver: ' + element(component.element), channelSchema, receivingData.data);
  3435. channelInfo.onReceive(component, data);
  3436. });
  3437. })]);
  3438. var ActiveReceiving = /*#__PURE__*/Object.freeze({
  3439. __proto__: null,
  3440. events: events$h
  3441. });
  3442. var ReceivingSchema = [requiredOf('channels', setOf(Result.value, objOfOnly([
  3443. onStrictHandler('onReceive'),
  3444. defaulted('schema', anyValue())
  3445. ])))];
  3446. const executeEvent = (bConfig, bState, executor) => runOnExecute$1(component => {
  3447. executor(component, bConfig, bState);
  3448. });
  3449. const loadEvent = (bConfig, bState, f) => runOnInit((component, _simulatedEvent) => {
  3450. f(component, bConfig, bState);
  3451. });
  3452. const create$5 = (schema, name, active, apis, extra, state) => {
  3453. const configSchema = objOfOnly(schema);
  3454. const schemaSchema = optionObjOf(name, [optionObjOfOnly('config', schema)]);
  3455. return doCreate(configSchema, schemaSchema, name, active, apis, extra, state);
  3456. };
  3457. const createModes$1 = (modes, name, active, apis, extra, state) => {
  3458. const configSchema = modes;
  3459. const schemaSchema = optionObjOf(name, [optionOf('config', modes)]);
  3460. return doCreate(configSchema, schemaSchema, name, active, apis, extra, state);
  3461. };
  3462. const wrapApi = (bName, apiFunction, apiName) => {
  3463. const f = (component, ...rest) => {
  3464. const args = [component].concat(rest);
  3465. return component.config({ name: constant$1(bName) }).fold(() => {
  3466. throw new Error('We could not find any behaviour configuration for: ' + bName + '. Using API: ' + apiName);
  3467. }, info => {
  3468. const rest = Array.prototype.slice.call(args, 1);
  3469. return apiFunction.apply(undefined, [
  3470. component,
  3471. info.config,
  3472. info.state
  3473. ].concat(rest));
  3474. });
  3475. };
  3476. return markAsBehaviourApi(f, apiName, apiFunction);
  3477. };
  3478. const revokeBehaviour = name => ({
  3479. key: name,
  3480. value: undefined
  3481. });
  3482. const doCreate = (configSchema, schemaSchema, name, active, apis, extra, state) => {
  3483. const getConfig = info => hasNonNullableKey(info, name) ? info[name]() : Optional.none();
  3484. const wrappedApis = map$1(apis, (apiF, apiName) => wrapApi(name, apiF, apiName));
  3485. const wrappedExtra = map$1(extra, (extraF, extraName) => markAsExtraApi(extraF, extraName));
  3486. const me = {
  3487. ...wrappedExtra,
  3488. ...wrappedApis,
  3489. revoke: curry(revokeBehaviour, name),
  3490. config: spec => {
  3491. const prepared = asRawOrDie$1(name + '-config', configSchema, spec);
  3492. return {
  3493. key: name,
  3494. value: {
  3495. config: prepared,
  3496. me,
  3497. configAsRaw: cached(() => asRawOrDie$1(name + '-config', configSchema, spec)),
  3498. initialConfig: spec,
  3499. state
  3500. }
  3501. };
  3502. },
  3503. schema: constant$1(schemaSchema),
  3504. exhibit: (info, base) => {
  3505. return lift2(getConfig(info), get$g(active, 'exhibit'), (behaviourInfo, exhibitor) => {
  3506. return exhibitor(base, behaviourInfo.config, behaviourInfo.state);
  3507. }).getOrThunk(() => nu$7({}));
  3508. },
  3509. name: constant$1(name),
  3510. handlers: info => {
  3511. return getConfig(info).map(behaviourInfo => {
  3512. const getEvents = get$g(active, 'events').getOr(() => ({}));
  3513. return getEvents(behaviourInfo.config, behaviourInfo.state);
  3514. }).getOr({});
  3515. }
  3516. };
  3517. return me;
  3518. };
  3519. const derive$1 = capabilities => wrapAll(capabilities);
  3520. const simpleSchema = objOfOnly([
  3521. required$1('fields'),
  3522. required$1('name'),
  3523. defaulted('active', {}),
  3524. defaulted('apis', {}),
  3525. defaulted('state', NoState),
  3526. defaulted('extra', {})
  3527. ]);
  3528. const create$4 = data => {
  3529. const value = asRawOrDie$1('Creating behaviour: ' + data.name, simpleSchema, data);
  3530. return create$5(value.fields, value.name, value.active, value.apis, value.extra, value.state);
  3531. };
  3532. const modeSchema = objOfOnly([
  3533. required$1('branchKey'),
  3534. required$1('branches'),
  3535. required$1('name'),
  3536. defaulted('active', {}),
  3537. defaulted('apis', {}),
  3538. defaulted('state', NoState),
  3539. defaulted('extra', {})
  3540. ]);
  3541. const createModes = data => {
  3542. const value = asRawOrDie$1('Creating behaviour: ' + data.name, modeSchema, data);
  3543. return createModes$1(choose$1(value.branchKey, value.branches), value.name, value.active, value.apis, value.extra, value.state);
  3544. };
  3545. const revoke = constant$1(undefined);
  3546. const Receiving = create$4({
  3547. fields: ReceivingSchema,
  3548. name: 'receiving',
  3549. active: ActiveReceiving
  3550. });
  3551. const exhibit$6 = (base, posConfig) => nu$7({
  3552. classes: [],
  3553. styles: posConfig.useFixed() ? {} : { position: 'relative' }
  3554. });
  3555. var ActivePosition = /*#__PURE__*/Object.freeze({
  3556. __proto__: null,
  3557. exhibit: exhibit$6
  3558. });
  3559. const focus$3 = element => element.dom.focus();
  3560. const blur$1 = element => element.dom.blur();
  3561. const hasFocus = element => {
  3562. const root = getRootNode(element).dom;
  3563. return element.dom === root.activeElement;
  3564. };
  3565. const active$1 = (root = getDocument()) => Optional.from(root.dom.activeElement).map(SugarElement.fromDom);
  3566. const search = element => active$1(getRootNode(element)).filter(e => element.dom.contains(e.dom));
  3567. const preserve$1 = (f, container) => {
  3568. const dos = getRootNode(container);
  3569. const refocus = active$1(dos).bind(focused => {
  3570. const hasFocus = elem => eq(focused, elem);
  3571. return hasFocus(container) ? Optional.some(container) : descendant$1(container, hasFocus);
  3572. });
  3573. const result = f(container);
  3574. refocus.each(oldFocus => {
  3575. active$1(dos).filter(newFocus => eq(newFocus, oldFocus)).fold(() => {
  3576. focus$3(oldFocus);
  3577. }, noop);
  3578. });
  3579. return result;
  3580. };
  3581. const NuPositionCss = (position, left, top, right, bottom) => {
  3582. const toPx = num => num + 'px';
  3583. return {
  3584. position,
  3585. left: left.map(toPx),
  3586. top: top.map(toPx),
  3587. right: right.map(toPx),
  3588. bottom: bottom.map(toPx)
  3589. };
  3590. };
  3591. const toOptions = position => ({
  3592. ...position,
  3593. position: Optional.some(position.position)
  3594. });
  3595. const applyPositionCss = (element, position) => {
  3596. setOptions(element, toOptions(position));
  3597. };
  3598. const adt$9 = Adt.generate([
  3599. { none: [] },
  3600. {
  3601. relative: [
  3602. 'x',
  3603. 'y',
  3604. 'width',
  3605. 'height'
  3606. ]
  3607. },
  3608. {
  3609. fixed: [
  3610. 'x',
  3611. 'y',
  3612. 'width',
  3613. 'height'
  3614. ]
  3615. }
  3616. ]);
  3617. const positionWithDirection = (posName, decision, x, y, width, height) => {
  3618. const decisionRect = decision.rect;
  3619. const decisionX = decisionRect.x - x;
  3620. const decisionY = decisionRect.y - y;
  3621. const decisionWidth = decisionRect.width;
  3622. const decisionHeight = decisionRect.height;
  3623. const decisionRight = width - (decisionX + decisionWidth);
  3624. const decisionBottom = height - (decisionY + decisionHeight);
  3625. const left = Optional.some(decisionX);
  3626. const top = Optional.some(decisionY);
  3627. const right = Optional.some(decisionRight);
  3628. const bottom = Optional.some(decisionBottom);
  3629. const none = Optional.none();
  3630. 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));
  3631. };
  3632. const reposition = (origin, decision) => origin.fold(() => {
  3633. const decisionRect = decision.rect;
  3634. return NuPositionCss('absolute', Optional.some(decisionRect.x), Optional.some(decisionRect.y), Optional.none(), Optional.none());
  3635. }, (x, y, width, height) => {
  3636. return positionWithDirection('absolute', decision, x, y, width, height);
  3637. }, (x, y, width, height) => {
  3638. return positionWithDirection('fixed', decision, x, y, width, height);
  3639. });
  3640. const toBox = (origin, element) => {
  3641. const rel = curry(find$2, element);
  3642. const position = origin.fold(rel, rel, () => {
  3643. const scroll = get$b();
  3644. return find$2(element).translate(-scroll.left, -scroll.top);
  3645. });
  3646. const width = getOuter$1(element);
  3647. const height = getOuter$2(element);
  3648. return bounds(position.left, position.top, width, height);
  3649. };
  3650. const viewport = (origin, optBounds) => optBounds.fold(() => origin.fold(win, win, bounds), bounds$1 => origin.fold(constant$1(bounds$1), constant$1(bounds$1), () => {
  3651. const pos = translate$2(origin, bounds$1.x, bounds$1.y);
  3652. return bounds(pos.left, pos.top, bounds$1.width, bounds$1.height);
  3653. }));
  3654. const translate$2 = (origin, x, y) => {
  3655. const pos = SugarPosition(x, y);
  3656. const removeScroll = () => {
  3657. const outerScroll = get$b();
  3658. return pos.translate(-outerScroll.left, -outerScroll.top);
  3659. };
  3660. return origin.fold(constant$1(pos), constant$1(pos), removeScroll);
  3661. };
  3662. const cata$1 = (subject, onNone, onRelative, onFixed) => subject.fold(onNone, onRelative, onFixed);
  3663. adt$9.none;
  3664. const relative$1 = adt$9.relative;
  3665. const fixed$1 = adt$9.fixed;
  3666. const anchor = (anchorBox, origin) => ({
  3667. anchorBox,
  3668. origin
  3669. });
  3670. const box = (anchorBox, origin) => anchor(anchorBox, origin);
  3671. const placementAttribute = 'data-alloy-placement';
  3672. const setPlacement$1 = (element, placement) => {
  3673. set$9(element, placementAttribute, placement);
  3674. };
  3675. const getPlacement = element => getOpt(element, placementAttribute);
  3676. const reset$2 = element => remove$7(element, placementAttribute);
  3677. const adt$8 = Adt.generate([
  3678. { fit: ['reposition'] },
  3679. {
  3680. nofit: [
  3681. 'reposition',
  3682. 'visibleW',
  3683. 'visibleH',
  3684. 'isVisible'
  3685. ]
  3686. }
  3687. ]);
  3688. const determinePosition = (box, bounds) => {
  3689. const {
  3690. x: boundsX,
  3691. y: boundsY,
  3692. right: boundsRight,
  3693. bottom: boundsBottom
  3694. } = bounds;
  3695. const {x, y, right, bottom, width, height} = box;
  3696. const xInBounds = x >= boundsX && x <= boundsRight;
  3697. const yInBounds = y >= boundsY && y <= boundsBottom;
  3698. const originInBounds = xInBounds && yInBounds;
  3699. const rightInBounds = right <= boundsRight && right >= boundsX;
  3700. const bottomInBounds = bottom <= boundsBottom && bottom >= boundsY;
  3701. const sizeInBounds = rightInBounds && bottomInBounds;
  3702. const visibleW = Math.min(width, x >= boundsX ? boundsRight - x : right - boundsX);
  3703. const visibleH = Math.min(height, y >= boundsY ? boundsBottom - y : bottom - boundsY);
  3704. return {
  3705. originInBounds,
  3706. sizeInBounds,
  3707. visibleW,
  3708. visibleH
  3709. };
  3710. };
  3711. const calcReposition = (box, bounds$1) => {
  3712. const {
  3713. x: boundsX,
  3714. y: boundsY,
  3715. right: boundsRight,
  3716. bottom: boundsBottom
  3717. } = bounds$1;
  3718. const {x, y, width, height} = box;
  3719. const maxX = Math.max(boundsX, boundsRight - width);
  3720. const maxY = Math.max(boundsY, boundsBottom - height);
  3721. const restrictedX = clamp(x, boundsX, maxX);
  3722. const restrictedY = clamp(y, boundsY, maxY);
  3723. const restrictedWidth = Math.min(restrictedX + width, boundsRight) - restrictedX;
  3724. const restrictedHeight = Math.min(restrictedY + height, boundsBottom) - restrictedY;
  3725. return bounds(restrictedX, restrictedY, restrictedWidth, restrictedHeight);
  3726. };
  3727. const calcMaxSizes = (direction, box, bounds) => {
  3728. const upAvailable = constant$1(box.bottom - bounds.y);
  3729. const downAvailable = constant$1(bounds.bottom - box.y);
  3730. const maxHeight = cataVertical(direction, downAvailable, downAvailable, upAvailable);
  3731. const westAvailable = constant$1(box.right - bounds.x);
  3732. const eastAvailable = constant$1(bounds.right - box.x);
  3733. const maxWidth = cataHorizontal(direction, eastAvailable, eastAvailable, westAvailable);
  3734. return {
  3735. maxWidth,
  3736. maxHeight
  3737. };
  3738. };
  3739. const attempt = (candidate, width, height, bounds$1) => {
  3740. const bubble = candidate.bubble;
  3741. const bubbleOffset = bubble.offset;
  3742. const adjustedBounds = adjustBounds(bounds$1, candidate.restriction, bubbleOffset);
  3743. const newX = candidate.x + bubbleOffset.left;
  3744. const newY = candidate.y + bubbleOffset.top;
  3745. const box = bounds(newX, newY, width, height);
  3746. const {originInBounds, sizeInBounds, visibleW, visibleH} = determinePosition(box, adjustedBounds);
  3747. const fits = originInBounds && sizeInBounds;
  3748. const fittedBox = fits ? box : calcReposition(box, adjustedBounds);
  3749. const isPartlyVisible = fittedBox.width > 0 && fittedBox.height > 0;
  3750. const {maxWidth, maxHeight} = calcMaxSizes(candidate.direction, fittedBox, bounds$1);
  3751. const reposition = {
  3752. rect: fittedBox,
  3753. maxHeight,
  3754. maxWidth,
  3755. direction: candidate.direction,
  3756. placement: candidate.placement,
  3757. classes: {
  3758. on: bubble.classesOn,
  3759. off: bubble.classesOff
  3760. },
  3761. layout: candidate.label,
  3762. testY: newY
  3763. };
  3764. return fits || candidate.alwaysFit ? adt$8.fit(reposition) : adt$8.nofit(reposition, visibleW, visibleH, isPartlyVisible);
  3765. };
  3766. const attempts = (element, candidates, anchorBox, elementBox, bubbles, bounds) => {
  3767. const panelWidth = elementBox.width;
  3768. const panelHeight = elementBox.height;
  3769. const attemptBestFit = (layout, reposition, visibleW, visibleH, isVisible) => {
  3770. const next = layout(anchorBox, elementBox, bubbles, element, bounds);
  3771. const attemptLayout = attempt(next, panelWidth, panelHeight, bounds);
  3772. return attemptLayout.fold(constant$1(attemptLayout), (newReposition, newVisibleW, newVisibleH, newIsVisible) => {
  3773. const improved = isVisible === newIsVisible ? newVisibleH > visibleH || newVisibleW > visibleW : !isVisible && newIsVisible;
  3774. return improved ? attemptLayout : adt$8.nofit(reposition, visibleW, visibleH, isVisible);
  3775. });
  3776. };
  3777. const abc = foldl(candidates, (b, a) => {
  3778. const bestNext = curry(attemptBestFit, a);
  3779. return b.fold(constant$1(b), bestNext);
  3780. }, adt$8.nofit({
  3781. rect: anchorBox,
  3782. maxHeight: elementBox.height,
  3783. maxWidth: elementBox.width,
  3784. direction: southeast$3(),
  3785. placement: 'southeast',
  3786. classes: {
  3787. on: [],
  3788. off: []
  3789. },
  3790. layout: 'none',
  3791. testY: anchorBox.y
  3792. }, -1, -1, false));
  3793. return abc.fold(identity, identity);
  3794. };
  3795. const singleton = doRevoke => {
  3796. const subject = Cell(Optional.none());
  3797. const revoke = () => subject.get().each(doRevoke);
  3798. const clear = () => {
  3799. revoke();
  3800. subject.set(Optional.none());
  3801. };
  3802. const isSet = () => subject.get().isSome();
  3803. const get = () => subject.get();
  3804. const set = s => {
  3805. revoke();
  3806. subject.set(Optional.some(s));
  3807. };
  3808. return {
  3809. clear,
  3810. isSet,
  3811. get,
  3812. set
  3813. };
  3814. };
  3815. const destroyable = () => singleton(s => s.destroy());
  3816. const unbindable = () => singleton(s => s.unbind());
  3817. const value$2 = () => {
  3818. const subject = singleton(noop);
  3819. const on = f => subject.get().each(f);
  3820. return {
  3821. ...subject,
  3822. on
  3823. };
  3824. };
  3825. const filter = always;
  3826. const bind = (element, event, handler) => bind$2(element, event, filter, handler);
  3827. const capture = (element, event, handler) => capture$1(element, event, filter, handler);
  3828. const fromRawEvent = fromRawEvent$1;
  3829. const properties = [
  3830. 'top',
  3831. 'bottom',
  3832. 'right',
  3833. 'left'
  3834. ];
  3835. const timerAttr = 'data-alloy-transition-timer';
  3836. const isTransitioning$1 = (element, transition) => hasAll(element, transition.classes);
  3837. const shouldApplyTransitionCss = (transition, decision, lastPlacement) => {
  3838. return lastPlacement.exists(placer => {
  3839. const mode = transition.mode;
  3840. return mode === 'all' ? true : placer[mode] !== decision[mode];
  3841. });
  3842. };
  3843. const hasChanges = (position, intermediate) => {
  3844. const round = value => parseFloat(value).toFixed(3);
  3845. return find$4(intermediate, (value, key) => {
  3846. const newValue = position[key].map(round);
  3847. const val = value.map(round);
  3848. return !equals(newValue, val);
  3849. }).isSome();
  3850. };
  3851. const getTransitionDuration = element => {
  3852. const get = name => {
  3853. const style = get$e(element, name);
  3854. const times = style.split(/\s*,\s*/);
  3855. return filter$2(times, isNotEmpty);
  3856. };
  3857. const parse = value => {
  3858. if (isString(value) && /^[\d.]+/.test(value)) {
  3859. const num = parseFloat(value);
  3860. return endsWith(value, 'ms') ? num : num * 1000;
  3861. } else {
  3862. return 0;
  3863. }
  3864. };
  3865. const delay = get('transition-delay');
  3866. const duration = get('transition-duration');
  3867. return foldl(duration, (acc, dur, i) => {
  3868. const time = parse(delay[i]) + parse(dur);
  3869. return Math.max(acc, time);
  3870. }, 0);
  3871. };
  3872. const setupTransitionListeners = (element, transition) => {
  3873. const transitionEnd = unbindable();
  3874. const transitionCancel = unbindable();
  3875. let timer;
  3876. const isSourceTransition = e => {
  3877. var _a;
  3878. const pseudoElement = (_a = e.raw.pseudoElement) !== null && _a !== void 0 ? _a : '';
  3879. return eq(e.target, element) && isEmpty(pseudoElement) && contains$2(properties, e.raw.propertyName);
  3880. };
  3881. const transitionDone = e => {
  3882. if (isNullable(e) || isSourceTransition(e)) {
  3883. transitionEnd.clear();
  3884. transitionCancel.clear();
  3885. const type = e === null || e === void 0 ? void 0 : e.raw.type;
  3886. if (isNullable(type) || type === transitionend()) {
  3887. clearTimeout(timer);
  3888. remove$7(element, timerAttr);
  3889. remove$1(element, transition.classes);
  3890. }
  3891. }
  3892. };
  3893. const transitionStart = bind(element, transitionstart(), e => {
  3894. if (isSourceTransition(e)) {
  3895. transitionStart.unbind();
  3896. transitionEnd.set(bind(element, transitionend(), transitionDone));
  3897. transitionCancel.set(bind(element, transitioncancel(), transitionDone));
  3898. }
  3899. });
  3900. const duration = getTransitionDuration(element);
  3901. requestAnimationFrame(() => {
  3902. timer = setTimeout(transitionDone, duration + 17);
  3903. set$9(element, timerAttr, timer);
  3904. });
  3905. };
  3906. const startTransitioning = (element, transition) => {
  3907. add$1(element, transition.classes);
  3908. getOpt(element, timerAttr).each(timerId => {
  3909. clearTimeout(parseInt(timerId, 10));
  3910. remove$7(element, timerAttr);
  3911. });
  3912. setupTransitionListeners(element, transition);
  3913. };
  3914. const applyTransitionCss = (element, origin, position, transition, decision, lastPlacement) => {
  3915. const shouldTransition = shouldApplyTransitionCss(transition, decision, lastPlacement);
  3916. if (shouldTransition || isTransitioning$1(element, transition)) {
  3917. set$8(element, 'position', position.position);
  3918. const rect = toBox(origin, element);
  3919. const intermediatePosition = reposition(origin, {
  3920. ...decision,
  3921. rect
  3922. });
  3923. const intermediateCssOptions = mapToObject(properties, prop => intermediatePosition[prop]);
  3924. if (hasChanges(position, intermediateCssOptions)) {
  3925. setOptions(element, intermediateCssOptions);
  3926. if (shouldTransition) {
  3927. startTransitioning(element, transition);
  3928. }
  3929. reflow(element);
  3930. }
  3931. } else {
  3932. remove$1(element, transition.classes);
  3933. }
  3934. };
  3935. const elementSize = p => ({
  3936. width: getOuter$1(p),
  3937. height: getOuter$2(p)
  3938. });
  3939. const layout = (anchorBox, element, bubbles, options) => {
  3940. remove$6(element, 'max-height');
  3941. remove$6(element, 'max-width');
  3942. const elementBox = elementSize(element);
  3943. return attempts(element, options.preference, anchorBox, elementBox, bubbles, options.bounds);
  3944. };
  3945. const setClasses = (element, decision) => {
  3946. const classInfo = decision.classes;
  3947. remove$1(element, classInfo.off);
  3948. add$1(element, classInfo.on);
  3949. };
  3950. const setHeight = (element, decision, options) => {
  3951. const maxHeightFunction = options.maxHeightFunction;
  3952. maxHeightFunction(element, decision.maxHeight);
  3953. };
  3954. const setWidth = (element, decision, options) => {
  3955. const maxWidthFunction = options.maxWidthFunction;
  3956. maxWidthFunction(element, decision.maxWidth);
  3957. };
  3958. const position$2 = (element, decision, options) => {
  3959. const positionCss = reposition(options.origin, decision);
  3960. options.transition.each(transition => {
  3961. applyTransitionCss(element, options.origin, positionCss, transition, decision, options.lastPlacement);
  3962. });
  3963. applyPositionCss(element, positionCss);
  3964. };
  3965. const setPlacement = (element, decision) => {
  3966. setPlacement$1(element, decision.placement);
  3967. };
  3968. const setMaxHeight = (element, maxHeight) => {
  3969. setMax$1(element, Math.floor(maxHeight));
  3970. };
  3971. const anchored = constant$1((element, available) => {
  3972. setMaxHeight(element, available);
  3973. setAll(element, {
  3974. 'overflow-x': 'hidden',
  3975. 'overflow-y': 'auto'
  3976. });
  3977. });
  3978. const expandable$1 = constant$1((element, available) => {
  3979. setMaxHeight(element, available);
  3980. });
  3981. const defaultOr = (options, key, dephault) => options[key] === undefined ? dephault : options[key];
  3982. const simple = (anchor, element, bubble, layouts, lastPlacement, optBounds, overrideOptions, transition) => {
  3983. const maxHeightFunction = defaultOr(overrideOptions, 'maxHeightFunction', anchored());
  3984. const maxWidthFunction = defaultOr(overrideOptions, 'maxWidthFunction', noop);
  3985. const anchorBox = anchor.anchorBox;
  3986. const origin = anchor.origin;
  3987. const options = {
  3988. bounds: viewport(origin, optBounds),
  3989. origin,
  3990. preference: layouts,
  3991. maxHeightFunction,
  3992. maxWidthFunction,
  3993. lastPlacement,
  3994. transition
  3995. };
  3996. return go(anchorBox, element, bubble, options);
  3997. };
  3998. const go = (anchorBox, element, bubble, options) => {
  3999. const decision = layout(anchorBox, element, bubble, options);
  4000. position$2(element, decision, options);
  4001. setPlacement(element, decision);
  4002. setClasses(element, decision);
  4003. setHeight(element, decision, options);
  4004. setWidth(element, decision, options);
  4005. return {
  4006. layout: decision.layout,
  4007. placement: decision.placement
  4008. };
  4009. };
  4010. const allAlignments = [
  4011. 'valignCentre',
  4012. 'alignLeft',
  4013. 'alignRight',
  4014. 'alignCentre',
  4015. 'top',
  4016. 'bottom',
  4017. 'left',
  4018. 'right',
  4019. 'inset'
  4020. ];
  4021. const nu$5 = (xOffset, yOffset, classes, insetModifier = 1) => {
  4022. const insetXOffset = xOffset * insetModifier;
  4023. const insetYOffset = yOffset * insetModifier;
  4024. const getClasses = prop => get$g(classes, prop).getOr([]);
  4025. const make = (xDelta, yDelta, alignmentsOn) => {
  4026. const alignmentsOff = difference(allAlignments, alignmentsOn);
  4027. return {
  4028. offset: SugarPosition(xDelta, yDelta),
  4029. classesOn: bind$3(alignmentsOn, getClasses),
  4030. classesOff: bind$3(alignmentsOff, getClasses)
  4031. };
  4032. };
  4033. return {
  4034. southeast: () => make(-xOffset, yOffset, [
  4035. 'top',
  4036. 'alignLeft'
  4037. ]),
  4038. southwest: () => make(xOffset, yOffset, [
  4039. 'top',
  4040. 'alignRight'
  4041. ]),
  4042. south: () => make(-xOffset / 2, yOffset, [
  4043. 'top',
  4044. 'alignCentre'
  4045. ]),
  4046. northeast: () => make(-xOffset, -yOffset, [
  4047. 'bottom',
  4048. 'alignLeft'
  4049. ]),
  4050. northwest: () => make(xOffset, -yOffset, [
  4051. 'bottom',
  4052. 'alignRight'
  4053. ]),
  4054. north: () => make(-xOffset / 2, -yOffset, [
  4055. 'bottom',
  4056. 'alignCentre'
  4057. ]),
  4058. east: () => make(xOffset, -yOffset / 2, [
  4059. 'valignCentre',
  4060. 'left'
  4061. ]),
  4062. west: () => make(-xOffset, -yOffset / 2, [
  4063. 'valignCentre',
  4064. 'right'
  4065. ]),
  4066. insetNortheast: () => make(insetXOffset, insetYOffset, [
  4067. 'top',
  4068. 'alignLeft',
  4069. 'inset'
  4070. ]),
  4071. insetNorthwest: () => make(-insetXOffset, insetYOffset, [
  4072. 'top',
  4073. 'alignRight',
  4074. 'inset'
  4075. ]),
  4076. insetNorth: () => make(-insetXOffset / 2, insetYOffset, [
  4077. 'top',
  4078. 'alignCentre',
  4079. 'inset'
  4080. ]),
  4081. insetSoutheast: () => make(insetXOffset, -insetYOffset, [
  4082. 'bottom',
  4083. 'alignLeft',
  4084. 'inset'
  4085. ]),
  4086. insetSouthwest: () => make(-insetXOffset, -insetYOffset, [
  4087. 'bottom',
  4088. 'alignRight',
  4089. 'inset'
  4090. ]),
  4091. insetSouth: () => make(-insetXOffset / 2, -insetYOffset, [
  4092. 'bottom',
  4093. 'alignCentre',
  4094. 'inset'
  4095. ]),
  4096. insetEast: () => make(-insetXOffset, -insetYOffset / 2, [
  4097. 'valignCentre',
  4098. 'right',
  4099. 'inset'
  4100. ]),
  4101. insetWest: () => make(insetXOffset, -insetYOffset / 2, [
  4102. 'valignCentre',
  4103. 'left',
  4104. 'inset'
  4105. ])
  4106. };
  4107. };
  4108. const fallback = () => nu$5(0, 0, {});
  4109. const nu$4 = identity;
  4110. const onDirection = (isLtr, isRtl) => element => getDirection(element) === 'rtl' ? isRtl : isLtr;
  4111. const getDirection = element => get$e(element, 'direction') === 'rtl' ? 'rtl' : 'ltr';
  4112. var AttributeValue;
  4113. (function (AttributeValue) {
  4114. AttributeValue['TopToBottom'] = 'toptobottom';
  4115. AttributeValue['BottomToTop'] = 'bottomtotop';
  4116. }(AttributeValue || (AttributeValue = {})));
  4117. const Attribute = 'data-alloy-vertical-dir';
  4118. const isBottomToTopDir = el => closest$2(el, current => isElement$1(current) && get$f(current, 'data-alloy-vertical-dir') === AttributeValue.BottomToTop);
  4119. const schema$y = () => optionObjOf('layouts', [
  4120. required$1('onLtr'),
  4121. required$1('onRtl'),
  4122. option$3('onBottomLtr'),
  4123. option$3('onBottomRtl')
  4124. ]);
  4125. const get$5 = (elem, info, defaultLtr, defaultRtl, defaultBottomLtr, defaultBottomRtl, dirElement) => {
  4126. const isBottomToTop = dirElement.map(isBottomToTopDir).getOr(false);
  4127. const customLtr = info.layouts.map(ls => ls.onLtr(elem));
  4128. const customRtl = info.layouts.map(ls => ls.onRtl(elem));
  4129. const ltr = isBottomToTop ? info.layouts.bind(ls => ls.onBottomLtr.map(f => f(elem))).or(customLtr).getOr(defaultBottomLtr) : customLtr.getOr(defaultLtr);
  4130. const rtl = isBottomToTop ? info.layouts.bind(ls => ls.onBottomRtl.map(f => f(elem))).or(customRtl).getOr(defaultBottomRtl) : customRtl.getOr(defaultRtl);
  4131. const f = onDirection(ltr, rtl);
  4132. return f(elem);
  4133. };
  4134. const placement$4 = (component, anchorInfo, origin) => {
  4135. const hotspot = anchorInfo.hotspot;
  4136. const anchorBox = toBox(origin, hotspot.element);
  4137. const layouts = get$5(component.element, anchorInfo, belowOrAbove(), belowOrAboveRtl(), aboveOrBelow(), aboveOrBelowRtl(), Optional.some(anchorInfo.hotspot.element));
  4138. return Optional.some(nu$4({
  4139. anchorBox,
  4140. bubble: anchorInfo.bubble.getOr(fallback()),
  4141. overrides: anchorInfo.overrides,
  4142. layouts
  4143. }));
  4144. };
  4145. var HotspotAnchor = [
  4146. required$1('hotspot'),
  4147. option$3('bubble'),
  4148. defaulted('overrides', {}),
  4149. schema$y(),
  4150. output$1('placement', placement$4)
  4151. ];
  4152. const placement$3 = (component, anchorInfo, origin) => {
  4153. const pos = translate$2(origin, anchorInfo.x, anchorInfo.y);
  4154. const anchorBox = bounds(pos.left, pos.top, anchorInfo.width, anchorInfo.height);
  4155. const layouts = get$5(component.element, anchorInfo, all$1(), allRtl$1(), all$1(), allRtl$1(), Optional.none());
  4156. return Optional.some(nu$4({
  4157. anchorBox,
  4158. bubble: anchorInfo.bubble,
  4159. overrides: anchorInfo.overrides,
  4160. layouts
  4161. }));
  4162. };
  4163. var MakeshiftAnchor = [
  4164. required$1('x'),
  4165. required$1('y'),
  4166. defaulted('height', 0),
  4167. defaulted('width', 0),
  4168. defaulted('bubble', fallback()),
  4169. defaulted('overrides', {}),
  4170. schema$y(),
  4171. output$1('placement', placement$3)
  4172. ];
  4173. const adt$7 = Adt.generate([
  4174. { screen: ['point'] },
  4175. {
  4176. absolute: [
  4177. 'point',
  4178. 'scrollLeft',
  4179. 'scrollTop'
  4180. ]
  4181. }
  4182. ]);
  4183. const toFixed = pos => pos.fold(identity, (point, scrollLeft, scrollTop) => point.translate(-scrollLeft, -scrollTop));
  4184. const toAbsolute = pos => pos.fold(identity, identity);
  4185. const sum = points => foldl(points, (b, a) => b.translate(a.left, a.top), SugarPosition(0, 0));
  4186. const sumAsFixed = positions => {
  4187. const points = map$2(positions, toFixed);
  4188. return sum(points);
  4189. };
  4190. const sumAsAbsolute = positions => {
  4191. const points = map$2(positions, toAbsolute);
  4192. return sum(points);
  4193. };
  4194. const screen = adt$7.screen;
  4195. const absolute$1 = adt$7.absolute;
  4196. const getOffset = (component, origin, anchorInfo) => {
  4197. const win = defaultView(anchorInfo.root).dom;
  4198. const hasSameOwner = frame => {
  4199. const frameOwner = owner$4(frame);
  4200. const compOwner = owner$4(component.element);
  4201. return eq(frameOwner, compOwner);
  4202. };
  4203. return Optional.from(win.frameElement).map(SugarElement.fromDom).filter(hasSameOwner).map(absolute$3);
  4204. };
  4205. const getRootPoint = (component, origin, anchorInfo) => {
  4206. const doc = owner$4(component.element);
  4207. const outerScroll = get$b(doc);
  4208. const offset = getOffset(component, origin, anchorInfo).getOr(outerScroll);
  4209. return absolute$1(offset, outerScroll.left, outerScroll.top);
  4210. };
  4211. const getBox = (left, top, width, height) => {
  4212. const point = screen(SugarPosition(left, top));
  4213. return Optional.some(pointed(point, width, height));
  4214. };
  4215. const calcNewAnchor = (optBox, rootPoint, anchorInfo, origin, elem) => optBox.map(box => {
  4216. const points = [
  4217. rootPoint,
  4218. box.point
  4219. ];
  4220. const topLeft = cata$1(origin, () => sumAsAbsolute(points), () => sumAsAbsolute(points), () => sumAsFixed(points));
  4221. const anchorBox = rect(topLeft.left, topLeft.top, box.width, box.height);
  4222. const layoutsLtr = anchorInfo.showAbove ? aboveOrBelow() : belowOrAbove();
  4223. const layoutsRtl = anchorInfo.showAbove ? aboveOrBelowRtl() : belowOrAboveRtl();
  4224. const layouts = get$5(elem, anchorInfo, layoutsLtr, layoutsRtl, layoutsLtr, layoutsRtl, Optional.none());
  4225. return nu$4({
  4226. anchorBox,
  4227. bubble: anchorInfo.bubble.getOr(fallback()),
  4228. overrides: anchorInfo.overrides,
  4229. layouts
  4230. });
  4231. });
  4232. const placement$2 = (component, anchorInfo, origin) => {
  4233. const rootPoint = getRootPoint(component, origin, anchorInfo);
  4234. return anchorInfo.node.filter(inBody).bind(target => {
  4235. const rect = target.dom.getBoundingClientRect();
  4236. const nodeBox = getBox(rect.left, rect.top, rect.width, rect.height);
  4237. const elem = anchorInfo.node.getOr(component.element);
  4238. return calcNewAnchor(nodeBox, rootPoint, anchorInfo, origin, elem);
  4239. });
  4240. };
  4241. var NodeAnchor = [
  4242. required$1('node'),
  4243. required$1('root'),
  4244. option$3('bubble'),
  4245. schema$y(),
  4246. defaulted('overrides', {}),
  4247. defaulted('showAbove', false),
  4248. output$1('placement', placement$2)
  4249. ];
  4250. const zeroWidth = '\uFEFF';
  4251. const nbsp = '\xA0';
  4252. const create$3 = (start, soffset, finish, foffset) => ({
  4253. start,
  4254. soffset,
  4255. finish,
  4256. foffset
  4257. });
  4258. const SimRange = { create: create$3 };
  4259. const adt$6 = Adt.generate([
  4260. { before: ['element'] },
  4261. {
  4262. on: [
  4263. 'element',
  4264. 'offset'
  4265. ]
  4266. },
  4267. { after: ['element'] }
  4268. ]);
  4269. const cata = (subject, onBefore, onOn, onAfter) => subject.fold(onBefore, onOn, onAfter);
  4270. const getStart$1 = situ => situ.fold(identity, identity, identity);
  4271. const before = adt$6.before;
  4272. const on$1 = adt$6.on;
  4273. const after$1 = adt$6.after;
  4274. const Situ = {
  4275. before,
  4276. on: on$1,
  4277. after: after$1,
  4278. cata,
  4279. getStart: getStart$1
  4280. };
  4281. const adt$5 = Adt.generate([
  4282. { domRange: ['rng'] },
  4283. {
  4284. relative: [
  4285. 'startSitu',
  4286. 'finishSitu'
  4287. ]
  4288. },
  4289. {
  4290. exact: [
  4291. 'start',
  4292. 'soffset',
  4293. 'finish',
  4294. 'foffset'
  4295. ]
  4296. }
  4297. ]);
  4298. const exactFromRange = simRange => adt$5.exact(simRange.start, simRange.soffset, simRange.finish, simRange.foffset);
  4299. const getStart = selection => selection.match({
  4300. domRange: rng => SugarElement.fromDom(rng.startContainer),
  4301. relative: (startSitu, _finishSitu) => Situ.getStart(startSitu),
  4302. exact: (start, _soffset, _finish, _foffset) => start
  4303. });
  4304. const domRange = adt$5.domRange;
  4305. const relative = adt$5.relative;
  4306. const exact = adt$5.exact;
  4307. const getWin = selection => {
  4308. const start = getStart(selection);
  4309. return defaultView(start);
  4310. };
  4311. const range$1 = SimRange.create;
  4312. const SimSelection = {
  4313. domRange,
  4314. relative,
  4315. exact,
  4316. exactFromRange,
  4317. getWin,
  4318. range: range$1
  4319. };
  4320. const setStart = (rng, situ) => {
  4321. situ.fold(e => {
  4322. rng.setStartBefore(e.dom);
  4323. }, (e, o) => {
  4324. rng.setStart(e.dom, o);
  4325. }, e => {
  4326. rng.setStartAfter(e.dom);
  4327. });
  4328. };
  4329. const setFinish = (rng, situ) => {
  4330. situ.fold(e => {
  4331. rng.setEndBefore(e.dom);
  4332. }, (e, o) => {
  4333. rng.setEnd(e.dom, o);
  4334. }, e => {
  4335. rng.setEndAfter(e.dom);
  4336. });
  4337. };
  4338. const relativeToNative = (win, startSitu, finishSitu) => {
  4339. const range = win.document.createRange();
  4340. setStart(range, startSitu);
  4341. setFinish(range, finishSitu);
  4342. return range;
  4343. };
  4344. const exactToNative = (win, start, soffset, finish, foffset) => {
  4345. const rng = win.document.createRange();
  4346. rng.setStart(start.dom, soffset);
  4347. rng.setEnd(finish.dom, foffset);
  4348. return rng;
  4349. };
  4350. const toRect = rect => ({
  4351. left: rect.left,
  4352. top: rect.top,
  4353. right: rect.right,
  4354. bottom: rect.bottom,
  4355. width: rect.width,
  4356. height: rect.height
  4357. });
  4358. const getFirstRect$1 = rng => {
  4359. const rects = rng.getClientRects();
  4360. const rect = rects.length > 0 ? rects[0] : rng.getBoundingClientRect();
  4361. return rect.width > 0 || rect.height > 0 ? Optional.some(rect).map(toRect) : Optional.none();
  4362. };
  4363. const getBounds$2 = rng => {
  4364. const rect = rng.getBoundingClientRect();
  4365. return rect.width > 0 || rect.height > 0 ? Optional.some(rect).map(toRect) : Optional.none();
  4366. };
  4367. const adt$4 = Adt.generate([
  4368. {
  4369. ltr: [
  4370. 'start',
  4371. 'soffset',
  4372. 'finish',
  4373. 'foffset'
  4374. ]
  4375. },
  4376. {
  4377. rtl: [
  4378. 'start',
  4379. 'soffset',
  4380. 'finish',
  4381. 'foffset'
  4382. ]
  4383. }
  4384. ]);
  4385. const fromRange = (win, type, range) => type(SugarElement.fromDom(range.startContainer), range.startOffset, SugarElement.fromDom(range.endContainer), range.endOffset);
  4386. const getRanges = (win, selection) => selection.match({
  4387. domRange: rng => {
  4388. return {
  4389. ltr: constant$1(rng),
  4390. rtl: Optional.none
  4391. };
  4392. },
  4393. relative: (startSitu, finishSitu) => {
  4394. return {
  4395. ltr: cached(() => relativeToNative(win, startSitu, finishSitu)),
  4396. rtl: cached(() => Optional.some(relativeToNative(win, finishSitu, startSitu)))
  4397. };
  4398. },
  4399. exact: (start, soffset, finish, foffset) => {
  4400. return {
  4401. ltr: cached(() => exactToNative(win, start, soffset, finish, foffset)),
  4402. rtl: cached(() => Optional.some(exactToNative(win, finish, foffset, start, soffset)))
  4403. };
  4404. }
  4405. });
  4406. const doDiagnose = (win, ranges) => {
  4407. const rng = ranges.ltr();
  4408. if (rng.collapsed) {
  4409. const reversed = ranges.rtl().filter(rev => rev.collapsed === false);
  4410. 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));
  4411. } else {
  4412. return fromRange(win, adt$4.ltr, rng);
  4413. }
  4414. };
  4415. const diagnose = (win, selection) => {
  4416. const ranges = getRanges(win, selection);
  4417. return doDiagnose(win, ranges);
  4418. };
  4419. const asLtrRange = (win, selection) => {
  4420. const diagnosis = diagnose(win, selection);
  4421. return diagnosis.match({
  4422. ltr: (start, soffset, finish, foffset) => {
  4423. const rng = win.document.createRange();
  4424. rng.setStart(start.dom, soffset);
  4425. rng.setEnd(finish.dom, foffset);
  4426. return rng;
  4427. },
  4428. rtl: (start, soffset, finish, foffset) => {
  4429. const rng = win.document.createRange();
  4430. rng.setStart(finish.dom, foffset);
  4431. rng.setEnd(start.dom, soffset);
  4432. return rng;
  4433. }
  4434. });
  4435. };
  4436. adt$4.ltr;
  4437. adt$4.rtl;
  4438. const ancestors = (scope, predicate, isRoot) => filter$2(parents(scope, isRoot), predicate);
  4439. const descendants = (scope, selector) => all$3(selector, scope);
  4440. const makeRange = (start, soffset, finish, foffset) => {
  4441. const doc = owner$4(start);
  4442. const rng = doc.dom.createRange();
  4443. rng.setStart(start.dom, soffset);
  4444. rng.setEnd(finish.dom, foffset);
  4445. return rng;
  4446. };
  4447. const after = (start, soffset, finish, foffset) => {
  4448. const r = makeRange(start, soffset, finish, foffset);
  4449. const same = eq(start, finish) && soffset === foffset;
  4450. return r.collapsed && !same;
  4451. };
  4452. const getNativeSelection = win => Optional.from(win.getSelection());
  4453. const readRange = selection => {
  4454. if (selection.rangeCount > 0) {
  4455. const firstRng = selection.getRangeAt(0);
  4456. const lastRng = selection.getRangeAt(selection.rangeCount - 1);
  4457. return Optional.some(SimRange.create(SugarElement.fromDom(firstRng.startContainer), firstRng.startOffset, SugarElement.fromDom(lastRng.endContainer), lastRng.endOffset));
  4458. } else {
  4459. return Optional.none();
  4460. }
  4461. };
  4462. const doGetExact = selection => {
  4463. if (selection.anchorNode === null || selection.focusNode === null) {
  4464. return readRange(selection);
  4465. } else {
  4466. const anchor = SugarElement.fromDom(selection.anchorNode);
  4467. const focus = SugarElement.fromDom(selection.focusNode);
  4468. return after(anchor, selection.anchorOffset, focus, selection.focusOffset) ? Optional.some(SimRange.create(anchor, selection.anchorOffset, focus, selection.focusOffset)) : readRange(selection);
  4469. }
  4470. };
  4471. const getExact = win => getNativeSelection(win).filter(sel => sel.rangeCount > 0).bind(doGetExact);
  4472. const getFirstRect = (win, selection) => {
  4473. const rng = asLtrRange(win, selection);
  4474. return getFirstRect$1(rng);
  4475. };
  4476. const getBounds$1 = (win, selection) => {
  4477. const rng = asLtrRange(win, selection);
  4478. return getBounds$2(rng);
  4479. };
  4480. const NodeValue = (is, name) => {
  4481. const get = element => {
  4482. if (!is(element)) {
  4483. throw new Error('Can only get ' + name + ' value of a ' + name + ' node');
  4484. }
  4485. return getOption(element).getOr('');
  4486. };
  4487. const getOption = element => is(element) ? Optional.from(element.dom.nodeValue) : Optional.none();
  4488. const set = (element, value) => {
  4489. if (!is(element)) {
  4490. throw new Error('Can only set raw ' + name + ' value of a ' + name + ' node');
  4491. }
  4492. element.dom.nodeValue = value;
  4493. };
  4494. return {
  4495. get,
  4496. getOption,
  4497. set
  4498. };
  4499. };
  4500. const api = NodeValue(isText, 'text');
  4501. const get$4 = element => api.get(element);
  4502. const point = (element, offset) => ({
  4503. element,
  4504. offset
  4505. });
  4506. const descendOnce$1 = (element, offset) => {
  4507. const children$1 = children(element);
  4508. if (children$1.length === 0) {
  4509. return point(element, offset);
  4510. } else if (offset < children$1.length) {
  4511. return point(children$1[offset], 0);
  4512. } else {
  4513. const last = children$1[children$1.length - 1];
  4514. const len = isText(last) ? get$4(last).length : children(last).length;
  4515. return point(last, len);
  4516. }
  4517. };
  4518. const descendOnce = (element, offset) => isText(element) ? point(element, offset) : descendOnce$1(element, offset);
  4519. const getAnchorSelection = (win, anchorInfo) => {
  4520. const getSelection = anchorInfo.getSelection.getOrThunk(() => () => getExact(win));
  4521. return getSelection().map(sel => {
  4522. const modStart = descendOnce(sel.start, sel.soffset);
  4523. const modFinish = descendOnce(sel.finish, sel.foffset);
  4524. return SimSelection.range(modStart.element, modStart.offset, modFinish.element, modFinish.offset);
  4525. });
  4526. };
  4527. const placement$1 = (component, anchorInfo, origin) => {
  4528. const win = defaultView(anchorInfo.root).dom;
  4529. const rootPoint = getRootPoint(component, origin, anchorInfo);
  4530. const selectionBox = getAnchorSelection(win, anchorInfo).bind(sel => {
  4531. const optRect = getBounds$1(win, SimSelection.exactFromRange(sel)).orThunk(() => {
  4532. const x = SugarElement.fromText(zeroWidth);
  4533. before$1(sel.start, x);
  4534. const rect = getFirstRect(win, SimSelection.exact(x, 0, x, 1));
  4535. remove$5(x);
  4536. return rect;
  4537. });
  4538. return optRect.bind(rawRect => getBox(rawRect.left, rawRect.top, rawRect.width, rawRect.height));
  4539. });
  4540. const targetElement = getAnchorSelection(win, anchorInfo).bind(sel => isElement$1(sel.start) ? Optional.some(sel.start) : parentElement(sel.start));
  4541. const elem = targetElement.getOr(component.element);
  4542. return calcNewAnchor(selectionBox, rootPoint, anchorInfo, origin, elem);
  4543. };
  4544. var SelectionAnchor = [
  4545. option$3('getSelection'),
  4546. required$1('root'),
  4547. option$3('bubble'),
  4548. schema$y(),
  4549. defaulted('overrides', {}),
  4550. defaulted('showAbove', false),
  4551. output$1('placement', placement$1)
  4552. ];
  4553. const labelPrefix$1 = 'link-layout';
  4554. const eastX = anchor => anchor.x + anchor.width;
  4555. const westX = (anchor, element) => anchor.x - element.width;
  4556. const northY$1 = (anchor, element) => anchor.y - element.height + anchor.height;
  4557. const southY$1 = anchor => anchor.y;
  4558. const southeast$1 = (anchor, element, bubbles) => nu$6(eastX(anchor), southY$1(anchor), bubbles.southeast(), southeast$3(), 'southeast', boundsRestriction(anchor, {
  4559. left: 0,
  4560. top: 2
  4561. }), labelPrefix$1);
  4562. const southwest$1 = (anchor, element, bubbles) => nu$6(westX(anchor, element), southY$1(anchor), bubbles.southwest(), southwest$3(), 'southwest', boundsRestriction(anchor, {
  4563. right: 1,
  4564. top: 2
  4565. }), labelPrefix$1);
  4566. const northeast$1 = (anchor, element, bubbles) => nu$6(eastX(anchor), northY$1(anchor, element), bubbles.northeast(), northeast$3(), 'northeast', boundsRestriction(anchor, {
  4567. left: 0,
  4568. bottom: 3
  4569. }), labelPrefix$1);
  4570. const northwest$1 = (anchor, element, bubbles) => nu$6(westX(anchor, element), northY$1(anchor, element), bubbles.northwest(), northwest$3(), 'northwest', boundsRestriction(anchor, {
  4571. right: 1,
  4572. bottom: 3
  4573. }), labelPrefix$1);
  4574. const all = () => [
  4575. southeast$1,
  4576. southwest$1,
  4577. northeast$1,
  4578. northwest$1
  4579. ];
  4580. const allRtl = () => [
  4581. southwest$1,
  4582. southeast$1,
  4583. northwest$1,
  4584. northeast$1
  4585. ];
  4586. const placement = (component, submenuInfo, origin) => {
  4587. const anchorBox = toBox(origin, submenuInfo.item.element);
  4588. const layouts = get$5(component.element, submenuInfo, all(), allRtl(), all(), allRtl(), Optional.none());
  4589. return Optional.some(nu$4({
  4590. anchorBox,
  4591. bubble: fallback(),
  4592. overrides: submenuInfo.overrides,
  4593. layouts
  4594. }));
  4595. };
  4596. var SubmenuAnchor = [
  4597. required$1('item'),
  4598. schema$y(),
  4599. defaulted('overrides', {}),
  4600. output$1('placement', placement)
  4601. ];
  4602. var AnchorSchema = choose$1('type', {
  4603. selection: SelectionAnchor,
  4604. node: NodeAnchor,
  4605. hotspot: HotspotAnchor,
  4606. submenu: SubmenuAnchor,
  4607. makeshift: MakeshiftAnchor
  4608. });
  4609. const TransitionSchema = [
  4610. requiredArrayOf('classes', string),
  4611. defaultedStringEnum('mode', 'all', [
  4612. 'all',
  4613. 'layout',
  4614. 'placement'
  4615. ])
  4616. ];
  4617. const PositionSchema = [
  4618. defaulted('useFixed', never),
  4619. option$3('getBounds')
  4620. ];
  4621. const PlacementSchema = [
  4622. requiredOf('anchor', AnchorSchema),
  4623. optionObjOf('transition', TransitionSchema)
  4624. ];
  4625. const getFixedOrigin = () => {
  4626. const html = document.documentElement;
  4627. return fixed$1(0, 0, html.clientWidth, html.clientHeight);
  4628. };
  4629. const getRelativeOrigin = component => {
  4630. const position = absolute$3(component.element);
  4631. const bounds = component.element.dom.getBoundingClientRect();
  4632. return relative$1(position.left, position.top, bounds.width, bounds.height);
  4633. };
  4634. const place = (origin, anchoring, optBounds, placee, lastPlace, transition) => {
  4635. const anchor = box(anchoring.anchorBox, origin);
  4636. return simple(anchor, placee.element, anchoring.bubble, anchoring.layouts, lastPlace, optBounds, anchoring.overrides, transition);
  4637. };
  4638. const position$1 = (component, posConfig, posState, placee, placementSpec) => {
  4639. const optWithinBounds = Optional.none();
  4640. positionWithinBounds(component, posConfig, posState, placee, placementSpec, optWithinBounds);
  4641. };
  4642. const positionWithinBounds = (component, posConfig, posState, placee, placementSpec, optWithinBounds) => {
  4643. const placeeDetail = asRawOrDie$1('placement.info', objOf(PlacementSchema), placementSpec);
  4644. const anchorage = placeeDetail.anchor;
  4645. const element = placee.element;
  4646. const placeeState = posState.get(placee.uid);
  4647. preserve$1(() => {
  4648. set$8(element, 'position', 'fixed');
  4649. const oldVisibility = getRaw(element, 'visibility');
  4650. set$8(element, 'visibility', 'hidden');
  4651. const origin = posConfig.useFixed() ? getFixedOrigin() : getRelativeOrigin(component);
  4652. anchorage.placement(component, anchorage, origin).each(anchoring => {
  4653. const optBounds = optWithinBounds.orThunk(() => posConfig.getBounds.map(apply$1));
  4654. const newState = place(origin, anchoring, optBounds, placee, placeeState, placeeDetail.transition);
  4655. posState.set(placee.uid, newState);
  4656. });
  4657. oldVisibility.fold(() => {
  4658. remove$6(element, 'visibility');
  4659. }, vis => {
  4660. set$8(element, 'visibility', vis);
  4661. });
  4662. if (getRaw(element, 'left').isNone() && getRaw(element, 'top').isNone() && getRaw(element, 'right').isNone() && getRaw(element, 'bottom').isNone() && is$1(getRaw(element, 'position'), 'fixed')) {
  4663. remove$6(element, 'position');
  4664. }
  4665. }, element);
  4666. };
  4667. const getMode = (component, pConfig, _pState) => pConfig.useFixed() ? 'fixed' : 'absolute';
  4668. const reset$1 = (component, pConfig, posState, placee) => {
  4669. const element = placee.element;
  4670. each$1([
  4671. 'position',
  4672. 'left',
  4673. 'right',
  4674. 'top',
  4675. 'bottom'
  4676. ], prop => remove$6(element, prop));
  4677. reset$2(element);
  4678. posState.clear(placee.uid);
  4679. };
  4680. var PositionApis = /*#__PURE__*/Object.freeze({
  4681. __proto__: null,
  4682. position: position$1,
  4683. positionWithinBounds: positionWithinBounds,
  4684. getMode: getMode,
  4685. reset: reset$1
  4686. });
  4687. const init$g = () => {
  4688. let state = {};
  4689. const set = (id, data) => {
  4690. state[id] = data;
  4691. };
  4692. const get = id => get$g(state, id);
  4693. const clear = id => {
  4694. if (isNonNullable(id)) {
  4695. delete state[id];
  4696. } else {
  4697. state = {};
  4698. }
  4699. };
  4700. return nu$8({
  4701. readState: () => state,
  4702. clear,
  4703. set,
  4704. get
  4705. });
  4706. };
  4707. var PositioningState = /*#__PURE__*/Object.freeze({
  4708. __proto__: null,
  4709. init: init$g
  4710. });
  4711. const Positioning = create$4({
  4712. fields: PositionSchema,
  4713. name: 'positioning',
  4714. active: ActivePosition,
  4715. apis: PositionApis,
  4716. state: PositioningState
  4717. });
  4718. const isConnected = comp => comp.getSystem().isConnected();
  4719. const fireDetaching = component => {
  4720. emit(component, detachedFromDom());
  4721. const children = component.components();
  4722. each$1(children, fireDetaching);
  4723. };
  4724. const fireAttaching = component => {
  4725. const children = component.components();
  4726. each$1(children, fireAttaching);
  4727. emit(component, attachedToDom());
  4728. };
  4729. const virtualAttach = (parent, child) => {
  4730. parent.getSystem().addToWorld(child);
  4731. if (inBody(parent.element)) {
  4732. fireAttaching(child);
  4733. }
  4734. };
  4735. const virtualDetach = comp => {
  4736. fireDetaching(comp);
  4737. comp.getSystem().removeFromWorld(comp);
  4738. };
  4739. const attach$1 = (parent, child) => {
  4740. append$2(parent.element, child.element);
  4741. };
  4742. const detachChildren$1 = component => {
  4743. each$1(component.components(), childComp => remove$5(childComp.element));
  4744. empty(component.element);
  4745. component.syncComponents();
  4746. };
  4747. const replaceChildren = (component, newSpecs, buildNewChildren) => {
  4748. const subs = component.components();
  4749. detachChildren$1(component);
  4750. const newChildren = buildNewChildren(newSpecs);
  4751. const deleted = difference(subs, newChildren);
  4752. each$1(deleted, comp => {
  4753. fireDetaching(comp);
  4754. component.getSystem().removeFromWorld(comp);
  4755. });
  4756. each$1(newChildren, childComp => {
  4757. if (!isConnected(childComp)) {
  4758. component.getSystem().addToWorld(childComp);
  4759. attach$1(component, childComp);
  4760. if (inBody(component.element)) {
  4761. fireAttaching(childComp);
  4762. }
  4763. } else {
  4764. attach$1(component, childComp);
  4765. }
  4766. });
  4767. component.syncComponents();
  4768. };
  4769. const virtualReplaceChildren = (component, newSpecs, buildNewChildren) => {
  4770. const subs = component.components();
  4771. const existingComps = bind$3(newSpecs, spec => getPremade(spec).toArray());
  4772. each$1(subs, childComp => {
  4773. if (!contains$2(existingComps, childComp)) {
  4774. virtualDetach(childComp);
  4775. }
  4776. });
  4777. const newChildren = buildNewChildren(newSpecs);
  4778. const deleted = difference(subs, newChildren);
  4779. each$1(deleted, deletedComp => {
  4780. if (isConnected(deletedComp)) {
  4781. virtualDetach(deletedComp);
  4782. }
  4783. });
  4784. each$1(newChildren, childComp => {
  4785. if (!isConnected(childComp)) {
  4786. virtualAttach(component, childComp);
  4787. }
  4788. });
  4789. component.syncComponents();
  4790. };
  4791. const attach = (parent, child) => {
  4792. attachWith(parent, child, append$2);
  4793. };
  4794. const attachWith = (parent, child, insertion) => {
  4795. parent.getSystem().addToWorld(child);
  4796. insertion(parent.element, child.element);
  4797. if (inBody(parent.element)) {
  4798. fireAttaching(child);
  4799. }
  4800. parent.syncComponents();
  4801. };
  4802. const doDetach = component => {
  4803. fireDetaching(component);
  4804. remove$5(component.element);
  4805. component.getSystem().removeFromWorld(component);
  4806. };
  4807. const detach = component => {
  4808. const parent$1 = parent(component.element).bind(p => component.getSystem().getByDom(p).toOptional());
  4809. doDetach(component);
  4810. parent$1.each(p => {
  4811. p.syncComponents();
  4812. });
  4813. };
  4814. const detachChildren = component => {
  4815. const subs = component.components();
  4816. each$1(subs, doDetach);
  4817. empty(component.element);
  4818. component.syncComponents();
  4819. };
  4820. const attachSystem = (element, guiSystem) => {
  4821. attachSystemWith(element, guiSystem, append$2);
  4822. };
  4823. const attachSystemAfter = (element, guiSystem) => {
  4824. attachSystemWith(element, guiSystem, after$2);
  4825. };
  4826. const attachSystemWith = (element, guiSystem, inserter) => {
  4827. inserter(element, guiSystem.element);
  4828. const children$1 = children(guiSystem.element);
  4829. each$1(children$1, child => {
  4830. guiSystem.getByDom(child).each(fireAttaching);
  4831. });
  4832. };
  4833. const detachSystem = guiSystem => {
  4834. const children$1 = children(guiSystem.element);
  4835. each$1(children$1, child => {
  4836. guiSystem.getByDom(child).each(fireDetaching);
  4837. });
  4838. remove$5(guiSystem.element);
  4839. };
  4840. const rebuild = (sandbox, sConfig, sState, data) => {
  4841. sState.get().each(_data => {
  4842. detachChildren(sandbox);
  4843. });
  4844. const point = sConfig.getAttachPoint(sandbox);
  4845. attach(point, sandbox);
  4846. const built = sandbox.getSystem().build(data);
  4847. attach(sandbox, built);
  4848. sState.set(built);
  4849. return built;
  4850. };
  4851. const open$1 = (sandbox, sConfig, sState, data) => {
  4852. const newState = rebuild(sandbox, sConfig, sState, data);
  4853. sConfig.onOpen(sandbox, newState);
  4854. return newState;
  4855. };
  4856. const setContent = (sandbox, sConfig, sState, data) => sState.get().map(() => rebuild(sandbox, sConfig, sState, data));
  4857. const openWhileCloaked = (sandbox, sConfig, sState, data, transaction) => {
  4858. cloak(sandbox, sConfig);
  4859. open$1(sandbox, sConfig, sState, data);
  4860. transaction();
  4861. decloak(sandbox, sConfig);
  4862. };
  4863. const close$1 = (sandbox, sConfig, sState) => {
  4864. sState.get().each(data => {
  4865. detachChildren(sandbox);
  4866. detach(sandbox);
  4867. sConfig.onClose(sandbox, data);
  4868. sState.clear();
  4869. });
  4870. };
  4871. const isOpen$1 = (_sandbox, _sConfig, sState) => sState.isOpen();
  4872. const isPartOf = (sandbox, sConfig, sState, queryElem) => isOpen$1(sandbox, sConfig, sState) && sState.get().exists(data => sConfig.isPartOf(sandbox, data, queryElem));
  4873. const getState$2 = (_sandbox, _sConfig, sState) => sState.get();
  4874. const store = (sandbox, cssKey, attr, newValue) => {
  4875. getRaw(sandbox.element, cssKey).fold(() => {
  4876. remove$7(sandbox.element, attr);
  4877. }, v => {
  4878. set$9(sandbox.element, attr, v);
  4879. });
  4880. set$8(sandbox.element, cssKey, newValue);
  4881. };
  4882. const restore = (sandbox, cssKey, attr) => {
  4883. getOpt(sandbox.element, attr).fold(() => remove$6(sandbox.element, cssKey), oldValue => set$8(sandbox.element, cssKey, oldValue));
  4884. };
  4885. const cloak = (sandbox, sConfig, _sState) => {
  4886. const sink = sConfig.getAttachPoint(sandbox);
  4887. set$8(sandbox.element, 'position', Positioning.getMode(sink));
  4888. store(sandbox, 'visibility', sConfig.cloakVisibilityAttr, 'hidden');
  4889. };
  4890. const hasPosition = element => exists([
  4891. 'top',
  4892. 'left',
  4893. 'right',
  4894. 'bottom'
  4895. ], pos => getRaw(element, pos).isSome());
  4896. const decloak = (sandbox, sConfig, _sState) => {
  4897. if (!hasPosition(sandbox.element)) {
  4898. remove$6(sandbox.element, 'position');
  4899. }
  4900. restore(sandbox, 'visibility', sConfig.cloakVisibilityAttr);
  4901. };
  4902. var SandboxApis = /*#__PURE__*/Object.freeze({
  4903. __proto__: null,
  4904. cloak: cloak,
  4905. decloak: decloak,
  4906. open: open$1,
  4907. openWhileCloaked: openWhileCloaked,
  4908. close: close$1,
  4909. isOpen: isOpen$1,
  4910. isPartOf: isPartOf,
  4911. getState: getState$2,
  4912. setContent: setContent
  4913. });
  4914. const events$g = (sandboxConfig, sandboxState) => derive$2([run$1(sandboxClose(), (sandbox, _simulatedEvent) => {
  4915. close$1(sandbox, sandboxConfig, sandboxState);
  4916. })]);
  4917. var ActiveSandbox = /*#__PURE__*/Object.freeze({
  4918. __proto__: null,
  4919. events: events$g
  4920. });
  4921. var SandboxSchema = [
  4922. onHandler('onOpen'),
  4923. onHandler('onClose'),
  4924. required$1('isPartOf'),
  4925. required$1('getAttachPoint'),
  4926. defaulted('cloakVisibilityAttr', 'data-precloak-visibility')
  4927. ];
  4928. const init$f = () => {
  4929. const contents = value$2();
  4930. const readState = constant$1('not-implemented');
  4931. return nu$8({
  4932. readState,
  4933. isOpen: contents.isSet,
  4934. clear: contents.clear,
  4935. set: contents.set,
  4936. get: contents.get
  4937. });
  4938. };
  4939. var SandboxState = /*#__PURE__*/Object.freeze({
  4940. __proto__: null,
  4941. init: init$f
  4942. });
  4943. const Sandboxing = create$4({
  4944. fields: SandboxSchema,
  4945. name: 'sandboxing',
  4946. active: ActiveSandbox,
  4947. apis: SandboxApis,
  4948. state: SandboxState
  4949. });
  4950. const dismissPopups = constant$1('dismiss.popups');
  4951. const repositionPopups = constant$1('reposition.popups');
  4952. const mouseReleased = constant$1('mouse.released');
  4953. const schema$x = objOfOnly([
  4954. defaulted('isExtraPart', never),
  4955. optionObjOf('fireEventInstead', [defaulted('event', dismissRequested())])
  4956. ]);
  4957. const receivingChannel$1 = rawSpec => {
  4958. const detail = asRawOrDie$1('Dismissal', schema$x, rawSpec);
  4959. return {
  4960. [dismissPopups()]: {
  4961. schema: objOfOnly([required$1('target')]),
  4962. onReceive: (sandbox, data) => {
  4963. if (Sandboxing.isOpen(sandbox)) {
  4964. const isPart = Sandboxing.isPartOf(sandbox, data.target) || detail.isExtraPart(sandbox, data.target);
  4965. if (!isPart) {
  4966. detail.fireEventInstead.fold(() => Sandboxing.close(sandbox), fe => emit(sandbox, fe.event));
  4967. }
  4968. }
  4969. }
  4970. }
  4971. };
  4972. };
  4973. const schema$w = objOfOnly([
  4974. optionObjOf('fireEventInstead', [defaulted('event', repositionRequested())]),
  4975. requiredFunction('doReposition')
  4976. ]);
  4977. const receivingChannel = rawSpec => {
  4978. const detail = asRawOrDie$1('Reposition', schema$w, rawSpec);
  4979. return {
  4980. [repositionPopups()]: {
  4981. onReceive: sandbox => {
  4982. if (Sandboxing.isOpen(sandbox)) {
  4983. detail.fireEventInstead.fold(() => detail.doReposition(sandbox), fe => emit(sandbox, fe.event));
  4984. }
  4985. }
  4986. }
  4987. };
  4988. };
  4989. const onLoad$5 = (component, repConfig, repState) => {
  4990. repConfig.store.manager.onLoad(component, repConfig, repState);
  4991. };
  4992. const onUnload$2 = (component, repConfig, repState) => {
  4993. repConfig.store.manager.onUnload(component, repConfig, repState);
  4994. };
  4995. const setValue$3 = (component, repConfig, repState, data) => {
  4996. repConfig.store.manager.setValue(component, repConfig, repState, data);
  4997. };
  4998. const getValue$3 = (component, repConfig, repState) => repConfig.store.manager.getValue(component, repConfig, repState);
  4999. const getState$1 = (component, repConfig, repState) => repState;
  5000. var RepresentApis = /*#__PURE__*/Object.freeze({
  5001. __proto__: null,
  5002. onLoad: onLoad$5,
  5003. onUnload: onUnload$2,
  5004. setValue: setValue$3,
  5005. getValue: getValue$3,
  5006. getState: getState$1
  5007. });
  5008. const events$f = (repConfig, repState) => {
  5009. const es = repConfig.resetOnDom ? [
  5010. runOnAttached((comp, _se) => {
  5011. onLoad$5(comp, repConfig, repState);
  5012. }),
  5013. runOnDetached((comp, _se) => {
  5014. onUnload$2(comp, repConfig, repState);
  5015. })
  5016. ] : [loadEvent(repConfig, repState, onLoad$5)];
  5017. return derive$2(es);
  5018. };
  5019. var ActiveRepresenting = /*#__PURE__*/Object.freeze({
  5020. __proto__: null,
  5021. events: events$f
  5022. });
  5023. const memory$1 = () => {
  5024. const data = Cell(null);
  5025. const readState = () => ({
  5026. mode: 'memory',
  5027. value: data.get()
  5028. });
  5029. const isNotSet = () => data.get() === null;
  5030. const clear = () => {
  5031. data.set(null);
  5032. };
  5033. return nu$8({
  5034. set: data.set,
  5035. get: data.get,
  5036. isNotSet,
  5037. clear,
  5038. readState
  5039. });
  5040. };
  5041. const manual = () => {
  5042. const readState = noop;
  5043. return nu$8({ readState });
  5044. };
  5045. const dataset = () => {
  5046. const dataByValue = Cell({});
  5047. const dataByText = Cell({});
  5048. const readState = () => ({
  5049. mode: 'dataset',
  5050. dataByValue: dataByValue.get(),
  5051. dataByText: dataByText.get()
  5052. });
  5053. const clear = () => {
  5054. dataByValue.set({});
  5055. dataByText.set({});
  5056. };
  5057. const lookup = itemString => get$g(dataByValue.get(), itemString).orThunk(() => get$g(dataByText.get(), itemString));
  5058. const update = items => {
  5059. const currentDataByValue = dataByValue.get();
  5060. const currentDataByText = dataByText.get();
  5061. const newDataByValue = {};
  5062. const newDataByText = {};
  5063. each$1(items, item => {
  5064. newDataByValue[item.value] = item;
  5065. get$g(item, 'meta').each(meta => {
  5066. get$g(meta, 'text').each(text => {
  5067. newDataByText[text] = item;
  5068. });
  5069. });
  5070. });
  5071. dataByValue.set({
  5072. ...currentDataByValue,
  5073. ...newDataByValue
  5074. });
  5075. dataByText.set({
  5076. ...currentDataByText,
  5077. ...newDataByText
  5078. });
  5079. };
  5080. return nu$8({
  5081. readState,
  5082. lookup,
  5083. update,
  5084. clear
  5085. });
  5086. };
  5087. const init$e = spec => spec.store.manager.state(spec);
  5088. var RepresentState = /*#__PURE__*/Object.freeze({
  5089. __proto__: null,
  5090. memory: memory$1,
  5091. dataset: dataset,
  5092. manual: manual,
  5093. init: init$e
  5094. });
  5095. const setValue$2 = (component, repConfig, repState, data) => {
  5096. const store = repConfig.store;
  5097. repState.update([data]);
  5098. store.setValue(component, data);
  5099. repConfig.onSetValue(component, data);
  5100. };
  5101. const getValue$2 = (component, repConfig, repState) => {
  5102. const store = repConfig.store;
  5103. const key = store.getDataKey(component);
  5104. return repState.lookup(key).getOrThunk(() => store.getFallbackEntry(key));
  5105. };
  5106. const onLoad$4 = (component, repConfig, repState) => {
  5107. const store = repConfig.store;
  5108. store.initialValue.each(data => {
  5109. setValue$2(component, repConfig, repState, data);
  5110. });
  5111. };
  5112. const onUnload$1 = (component, repConfig, repState) => {
  5113. repState.clear();
  5114. };
  5115. var DatasetStore = [
  5116. option$3('initialValue'),
  5117. required$1('getFallbackEntry'),
  5118. required$1('getDataKey'),
  5119. required$1('setValue'),
  5120. output$1('manager', {
  5121. setValue: setValue$2,
  5122. getValue: getValue$2,
  5123. onLoad: onLoad$4,
  5124. onUnload: onUnload$1,
  5125. state: dataset
  5126. })
  5127. ];
  5128. const getValue$1 = (component, repConfig, _repState) => repConfig.store.getValue(component);
  5129. const setValue$1 = (component, repConfig, _repState, data) => {
  5130. repConfig.store.setValue(component, data);
  5131. repConfig.onSetValue(component, data);
  5132. };
  5133. const onLoad$3 = (component, repConfig, _repState) => {
  5134. repConfig.store.initialValue.each(data => {
  5135. repConfig.store.setValue(component, data);
  5136. });
  5137. };
  5138. var ManualStore = [
  5139. required$1('getValue'),
  5140. defaulted('setValue', noop),
  5141. option$3('initialValue'),
  5142. output$1('manager', {
  5143. setValue: setValue$1,
  5144. getValue: getValue$1,
  5145. onLoad: onLoad$3,
  5146. onUnload: noop,
  5147. state: NoState.init
  5148. })
  5149. ];
  5150. const setValue = (component, repConfig, repState, data) => {
  5151. repState.set(data);
  5152. repConfig.onSetValue(component, data);
  5153. };
  5154. const getValue = (component, repConfig, repState) => repState.get();
  5155. const onLoad$2 = (component, repConfig, repState) => {
  5156. repConfig.store.initialValue.each(initVal => {
  5157. if (repState.isNotSet()) {
  5158. repState.set(initVal);
  5159. }
  5160. });
  5161. };
  5162. const onUnload = (component, repConfig, repState) => {
  5163. repState.clear();
  5164. };
  5165. var MemoryStore = [
  5166. option$3('initialValue'),
  5167. output$1('manager', {
  5168. setValue,
  5169. getValue,
  5170. onLoad: onLoad$2,
  5171. onUnload,
  5172. state: memory$1
  5173. })
  5174. ];
  5175. var RepresentSchema = [
  5176. defaultedOf('store', { mode: 'memory' }, choose$1('mode', {
  5177. memory: MemoryStore,
  5178. manual: ManualStore,
  5179. dataset: DatasetStore
  5180. })),
  5181. onHandler('onSetValue'),
  5182. defaulted('resetOnDom', false)
  5183. ];
  5184. const Representing = create$4({
  5185. fields: RepresentSchema,
  5186. name: 'representing',
  5187. active: ActiveRepresenting,
  5188. apis: RepresentApis,
  5189. extra: {
  5190. setValueFrom: (component, source) => {
  5191. const value = Representing.getValue(source);
  5192. Representing.setValue(component, value);
  5193. }
  5194. },
  5195. state: RepresentState
  5196. });
  5197. const field = (name, forbidden) => defaultedObjOf(name, {}, map$2(forbidden, f => forbid(f.name(), 'Cannot configure ' + f.name() + ' for ' + name)).concat([customField('dump', identity)]));
  5198. const get$3 = data => data.dump;
  5199. const augment = (data, original) => ({
  5200. ...derive$1(original),
  5201. ...data.dump
  5202. });
  5203. const SketchBehaviours = {
  5204. field,
  5205. augment,
  5206. get: get$3
  5207. };
  5208. const _placeholder = 'placeholder';
  5209. const adt$3 = Adt.generate([
  5210. {
  5211. single: [
  5212. 'required',
  5213. 'valueThunk'
  5214. ]
  5215. },
  5216. {
  5217. multiple: [
  5218. 'required',
  5219. 'valueThunks'
  5220. ]
  5221. }
  5222. ]);
  5223. const isSubstituted = spec => has$2(spec, 'uiType');
  5224. const subPlaceholder = (owner, detail, compSpec, placeholders) => {
  5225. if (owner.exists(o => o !== compSpec.owner)) {
  5226. return adt$3.single(true, constant$1(compSpec));
  5227. }
  5228. return get$g(placeholders, compSpec.name).fold(() => {
  5229. throw new Error('Unknown placeholder component: ' + compSpec.name + '\nKnown: [' + keys(placeholders) + ']\nNamespace: ' + owner.getOr('none') + '\nSpec: ' + JSON.stringify(compSpec, null, 2));
  5230. }, newSpec => newSpec.replace());
  5231. };
  5232. const scan = (owner, detail, compSpec, placeholders) => {
  5233. if (isSubstituted(compSpec) && compSpec.uiType === _placeholder) {
  5234. return subPlaceholder(owner, detail, compSpec, placeholders);
  5235. } else {
  5236. return adt$3.single(false, constant$1(compSpec));
  5237. }
  5238. };
  5239. const substitute = (owner, detail, compSpec, placeholders) => {
  5240. const base = scan(owner, detail, compSpec, placeholders);
  5241. return base.fold((req, valueThunk) => {
  5242. const value = isSubstituted(compSpec) ? valueThunk(detail, compSpec.config, compSpec.validated) : valueThunk(detail);
  5243. const childSpecs = get$g(value, 'components').getOr([]);
  5244. const substituted = bind$3(childSpecs, c => substitute(owner, detail, c, placeholders));
  5245. return [{
  5246. ...value,
  5247. components: substituted
  5248. }];
  5249. }, (req, valuesThunk) => {
  5250. if (isSubstituted(compSpec)) {
  5251. const values = valuesThunk(detail, compSpec.config, compSpec.validated);
  5252. const preprocessor = compSpec.validated.preprocess.getOr(identity);
  5253. return preprocessor(values);
  5254. } else {
  5255. return valuesThunk(detail);
  5256. }
  5257. });
  5258. };
  5259. const substituteAll = (owner, detail, components, placeholders) => bind$3(components, c => substitute(owner, detail, c, placeholders));
  5260. const oneReplace = (label, replacements) => {
  5261. let called = false;
  5262. const used = () => called;
  5263. const replace = () => {
  5264. if (called) {
  5265. throw new Error('Trying to use the same placeholder more than once: ' + label);
  5266. }
  5267. called = true;
  5268. return replacements;
  5269. };
  5270. const required = () => replacements.fold((req, _) => req, (req, _) => req);
  5271. return {
  5272. name: constant$1(label),
  5273. required,
  5274. used,
  5275. replace
  5276. };
  5277. };
  5278. const substitutePlaces = (owner, detail, components, placeholders) => {
  5279. const ps = map$1(placeholders, (ph, name) => oneReplace(name, ph));
  5280. const outcome = substituteAll(owner, detail, components, ps);
  5281. each(ps, p => {
  5282. if (p.used() === false && p.required()) {
  5283. throw new Error('Placeholder: ' + p.name() + ' was not found in components list\nNamespace: ' + owner.getOr('none') + '\nComponents: ' + JSON.stringify(detail.components, null, 2));
  5284. }
  5285. });
  5286. return outcome;
  5287. };
  5288. const single$2 = adt$3.single;
  5289. const multiple = adt$3.multiple;
  5290. const placeholder = constant$1(_placeholder);
  5291. const adt$2 = Adt.generate([
  5292. { required: ['data'] },
  5293. { external: ['data'] },
  5294. { optional: ['data'] },
  5295. { group: ['data'] }
  5296. ]);
  5297. const fFactory = defaulted('factory', { sketch: identity });
  5298. const fSchema = defaulted('schema', []);
  5299. const fName = required$1('name');
  5300. const fPname = field$1('pname', 'pname', defaultedThunk(typeSpec => '<alloy.' + generate$6(typeSpec.name) + '>'), anyValue());
  5301. const fGroupSchema = customField('schema', () => [option$3('preprocess')]);
  5302. const fDefaults = defaulted('defaults', constant$1({}));
  5303. const fOverrides = defaulted('overrides', constant$1({}));
  5304. const requiredSpec = objOf([
  5305. fFactory,
  5306. fSchema,
  5307. fName,
  5308. fPname,
  5309. fDefaults,
  5310. fOverrides
  5311. ]);
  5312. const externalSpec = objOf([
  5313. fFactory,
  5314. fSchema,
  5315. fName,
  5316. fDefaults,
  5317. fOverrides
  5318. ]);
  5319. const optionalSpec = objOf([
  5320. fFactory,
  5321. fSchema,
  5322. fName,
  5323. fPname,
  5324. fDefaults,
  5325. fOverrides
  5326. ]);
  5327. const groupSpec = objOf([
  5328. fFactory,
  5329. fGroupSchema,
  5330. fName,
  5331. required$1('unit'),
  5332. fPname,
  5333. fDefaults,
  5334. fOverrides
  5335. ]);
  5336. const asNamedPart = part => {
  5337. return part.fold(Optional.some, Optional.none, Optional.some, Optional.some);
  5338. };
  5339. const name$2 = part => {
  5340. const get = data => data.name;
  5341. return part.fold(get, get, get, get);
  5342. };
  5343. const asCommon = part => {
  5344. return part.fold(identity, identity, identity, identity);
  5345. };
  5346. const convert = (adtConstructor, partSchema) => spec => {
  5347. const data = asRawOrDie$1('Converting part type', partSchema, spec);
  5348. return adtConstructor(data);
  5349. };
  5350. const required = convert(adt$2.required, requiredSpec);
  5351. const external = convert(adt$2.external, externalSpec);
  5352. const optional = convert(adt$2.optional, optionalSpec);
  5353. const group = convert(adt$2.group, groupSpec);
  5354. const original = constant$1('entirety');
  5355. var PartType = /*#__PURE__*/Object.freeze({
  5356. __proto__: null,
  5357. required: required,
  5358. external: external,
  5359. optional: optional,
  5360. group: group,
  5361. asNamedPart: asNamedPart,
  5362. name: name$2,
  5363. asCommon: asCommon,
  5364. original: original
  5365. });
  5366. const combine = (detail, data, partSpec, partValidated) => deepMerge(data.defaults(detail, partSpec, partValidated), partSpec, { uid: detail.partUids[data.name] }, data.overrides(detail, partSpec, partValidated));
  5367. const subs = (owner, detail, parts) => {
  5368. const internals = {};
  5369. const externals = {};
  5370. each$1(parts, part => {
  5371. part.fold(data => {
  5372. internals[data.pname] = single$2(true, (detail, partSpec, partValidated) => data.factory.sketch(combine(detail, data, partSpec, partValidated)));
  5373. }, data => {
  5374. const partSpec = detail.parts[data.name];
  5375. externals[data.name] = constant$1(data.factory.sketch(combine(detail, data, partSpec[original()]), partSpec));
  5376. }, data => {
  5377. internals[data.pname] = single$2(false, (detail, partSpec, partValidated) => data.factory.sketch(combine(detail, data, partSpec, partValidated)));
  5378. }, data => {
  5379. internals[data.pname] = multiple(true, (detail, _partSpec, _partValidated) => {
  5380. const units = detail[data.name];
  5381. return map$2(units, u => data.factory.sketch(deepMerge(data.defaults(detail, u, _partValidated), u, data.overrides(detail, u))));
  5382. });
  5383. });
  5384. });
  5385. return {
  5386. internals: constant$1(internals),
  5387. externals: constant$1(externals)
  5388. };
  5389. };
  5390. const generate$3 = (owner, parts) => {
  5391. const r = {};
  5392. each$1(parts, part => {
  5393. asNamedPart(part).each(np => {
  5394. const g = doGenerateOne(owner, np.pname);
  5395. r[np.name] = config => {
  5396. const validated = asRawOrDie$1('Part: ' + np.name + ' in ' + owner, objOf(np.schema), config);
  5397. return {
  5398. ...g,
  5399. config,
  5400. validated
  5401. };
  5402. };
  5403. });
  5404. });
  5405. return r;
  5406. };
  5407. const doGenerateOne = (owner, pname) => ({
  5408. uiType: placeholder(),
  5409. owner,
  5410. name: pname
  5411. });
  5412. const generateOne$1 = (owner, pname, config) => ({
  5413. uiType: placeholder(),
  5414. owner,
  5415. name: pname,
  5416. config,
  5417. validated: {}
  5418. });
  5419. 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());
  5420. const names = parts => map$2(parts, name$2);
  5421. const substitutes = (owner, detail, parts) => subs(owner, detail, parts);
  5422. const components$1 = (owner, detail, internals) => substitutePlaces(Optional.some(owner), detail, detail.components, internals);
  5423. const getPart = (component, detail, partKey) => {
  5424. const uid = detail.partUids[partKey];
  5425. return component.getSystem().getByUid(uid).toOptional();
  5426. };
  5427. const getPartOrDie = (component, detail, partKey) => getPart(component, detail, partKey).getOrDie('Could not find part: ' + partKey);
  5428. const getParts = (component, detail, partKeys) => {
  5429. const r = {};
  5430. const uids = detail.partUids;
  5431. const system = component.getSystem();
  5432. each$1(partKeys, pk => {
  5433. r[pk] = constant$1(system.getByUid(uids[pk]));
  5434. });
  5435. return r;
  5436. };
  5437. const getAllParts = (component, detail) => {
  5438. const system = component.getSystem();
  5439. return map$1(detail.partUids, (pUid, _k) => constant$1(system.getByUid(pUid)));
  5440. };
  5441. const getAllPartNames = detail => keys(detail.partUids);
  5442. const getPartsOrDie = (component, detail, partKeys) => {
  5443. const r = {};
  5444. const uids = detail.partUids;
  5445. const system = component.getSystem();
  5446. each$1(partKeys, pk => {
  5447. r[pk] = constant$1(system.getByUid(uids[pk]).getOrDie());
  5448. });
  5449. return r;
  5450. };
  5451. const defaultUids = (baseUid, partTypes) => {
  5452. const partNames = names(partTypes);
  5453. return wrapAll(map$2(partNames, pn => ({
  5454. key: pn,
  5455. value: baseUid + '-' + pn
  5456. })));
  5457. };
  5458. const defaultUidsSchema = partTypes => field$1('partUids', 'partUids', mergeWithThunk(spec => defaultUids(spec.uid, partTypes)), anyValue());
  5459. var AlloyParts = /*#__PURE__*/Object.freeze({
  5460. __proto__: null,
  5461. generate: generate$3,
  5462. generateOne: generateOne$1,
  5463. schemas: schemas,
  5464. names: names,
  5465. substitutes: substitutes,
  5466. components: components$1,
  5467. defaultUids: defaultUids,
  5468. defaultUidsSchema: defaultUidsSchema,
  5469. getAllParts: getAllParts,
  5470. getAllPartNames: getAllPartNames,
  5471. getPart: getPart,
  5472. getPartOrDie: getPartOrDie,
  5473. getParts: getParts,
  5474. getPartsOrDie: getPartsOrDie
  5475. });
  5476. const base = (partSchemas, partUidsSchemas) => {
  5477. const ps = partSchemas.length > 0 ? [requiredObjOf('parts', partSchemas)] : [];
  5478. return ps.concat([
  5479. required$1('uid'),
  5480. defaulted('dom', {}),
  5481. defaulted('components', []),
  5482. snapshot('originalSpec'),
  5483. defaulted('debug.sketcher', {})
  5484. ]).concat(partUidsSchemas);
  5485. };
  5486. const asRawOrDie = (label, schema, spec, partSchemas, partUidsSchemas) => {
  5487. const baseS = base(partSchemas, partUidsSchemas);
  5488. return asRawOrDie$1(label + ' [SpecSchema]', objOfOnly(baseS.concat(schema)), spec);
  5489. };
  5490. const single$1 = (owner, schema, factory, spec) => {
  5491. const specWithUid = supplyUid(spec);
  5492. const detail = asRawOrDie(owner, schema, specWithUid, [], []);
  5493. return factory(detail, specWithUid);
  5494. };
  5495. const composite$1 = (owner, schema, partTypes, factory, spec) => {
  5496. const specWithUid = supplyUid(spec);
  5497. const partSchemas = schemas(partTypes);
  5498. const partUidsSchema = defaultUidsSchema(partTypes);
  5499. const detail = asRawOrDie(owner, schema, specWithUid, partSchemas, [partUidsSchema]);
  5500. const subs = substitutes(owner, detail, partTypes);
  5501. const components = components$1(owner, detail, subs.internals());
  5502. return factory(detail, components, specWithUid, subs.externals());
  5503. };
  5504. const hasUid = spec => has$2(spec, 'uid');
  5505. const supplyUid = spec => {
  5506. return hasUid(spec) ? spec : {
  5507. ...spec,
  5508. uid: generate$5('uid')
  5509. };
  5510. };
  5511. const isSketchSpec = spec => {
  5512. return spec.uid !== undefined;
  5513. };
  5514. const singleSchema = objOfOnly([
  5515. required$1('name'),
  5516. required$1('factory'),
  5517. required$1('configFields'),
  5518. defaulted('apis', {}),
  5519. defaulted('extraApis', {})
  5520. ]);
  5521. const compositeSchema = objOfOnly([
  5522. required$1('name'),
  5523. required$1('factory'),
  5524. required$1('configFields'),
  5525. required$1('partFields'),
  5526. defaulted('apis', {}),
  5527. defaulted('extraApis', {})
  5528. ]);
  5529. const single = rawConfig => {
  5530. const config = asRawOrDie$1('Sketcher for ' + rawConfig.name, singleSchema, rawConfig);
  5531. const sketch = spec => single$1(config.name, config.configFields, config.factory, spec);
  5532. const apis = map$1(config.apis, makeApi);
  5533. const extraApis = map$1(config.extraApis, (f, k) => markAsExtraApi(f, k));
  5534. return {
  5535. name: config.name,
  5536. configFields: config.configFields,
  5537. sketch,
  5538. ...apis,
  5539. ...extraApis
  5540. };
  5541. };
  5542. const composite = rawConfig => {
  5543. const config = asRawOrDie$1('Sketcher for ' + rawConfig.name, compositeSchema, rawConfig);
  5544. const sketch = spec => composite$1(config.name, config.configFields, config.partFields, config.factory, spec);
  5545. const parts = generate$3(config.name, config.partFields);
  5546. const apis = map$1(config.apis, makeApi);
  5547. const extraApis = map$1(config.extraApis, (f, k) => markAsExtraApi(f, k));
  5548. return {
  5549. name: config.name,
  5550. partFields: config.partFields,
  5551. configFields: config.configFields,
  5552. sketch,
  5553. parts,
  5554. ...apis,
  5555. ...extraApis
  5556. };
  5557. };
  5558. const inside = target => isTag('input')(target) && get$f(target, 'type') !== 'radio' || isTag('textarea')(target);
  5559. const getCurrent = (component, composeConfig, _composeState) => composeConfig.find(component);
  5560. var ComposeApis = /*#__PURE__*/Object.freeze({
  5561. __proto__: null,
  5562. getCurrent: getCurrent
  5563. });
  5564. const ComposeSchema = [required$1('find')];
  5565. const Composing = create$4({
  5566. fields: ComposeSchema,
  5567. name: 'composing',
  5568. apis: ComposeApis
  5569. });
  5570. const nativeDisabled = [
  5571. 'input',
  5572. 'button',
  5573. 'textarea',
  5574. 'select'
  5575. ];
  5576. const onLoad$1 = (component, disableConfig, disableState) => {
  5577. const f = disableConfig.disabled() ? disable : enable;
  5578. f(component, disableConfig);
  5579. };
  5580. const hasNative = (component, config) => config.useNative === true && contains$2(nativeDisabled, name$3(component.element));
  5581. const nativeIsDisabled = component => has$1(component.element, 'disabled');
  5582. const nativeDisable = component => {
  5583. set$9(component.element, 'disabled', 'disabled');
  5584. };
  5585. const nativeEnable = component => {
  5586. remove$7(component.element, 'disabled');
  5587. };
  5588. const ariaIsDisabled = component => get$f(component.element, 'aria-disabled') === 'true';
  5589. const ariaDisable = component => {
  5590. set$9(component.element, 'aria-disabled', 'true');
  5591. };
  5592. const ariaEnable = component => {
  5593. set$9(component.element, 'aria-disabled', 'false');
  5594. };
  5595. const disable = (component, disableConfig, _disableState) => {
  5596. disableConfig.disableClass.each(disableClass => {
  5597. add$2(component.element, disableClass);
  5598. });
  5599. const f = hasNative(component, disableConfig) ? nativeDisable : ariaDisable;
  5600. f(component);
  5601. disableConfig.onDisabled(component);
  5602. };
  5603. const enable = (component, disableConfig, _disableState) => {
  5604. disableConfig.disableClass.each(disableClass => {
  5605. remove$2(component.element, disableClass);
  5606. });
  5607. const f = hasNative(component, disableConfig) ? nativeEnable : ariaEnable;
  5608. f(component);
  5609. disableConfig.onEnabled(component);
  5610. };
  5611. const isDisabled = (component, disableConfig) => hasNative(component, disableConfig) ? nativeIsDisabled(component) : ariaIsDisabled(component);
  5612. const set$4 = (component, disableConfig, disableState, disabled) => {
  5613. const f = disabled ? disable : enable;
  5614. f(component, disableConfig);
  5615. };
  5616. var DisableApis = /*#__PURE__*/Object.freeze({
  5617. __proto__: null,
  5618. enable: enable,
  5619. disable: disable,
  5620. isDisabled: isDisabled,
  5621. onLoad: onLoad$1,
  5622. set: set$4
  5623. });
  5624. const exhibit$5 = (base, disableConfig) => nu$7({ classes: disableConfig.disabled() ? disableConfig.disableClass.toArray() : [] });
  5625. const events$e = (disableConfig, disableState) => derive$2([
  5626. abort(execute$5(), (component, _simulatedEvent) => isDisabled(component, disableConfig)),
  5627. loadEvent(disableConfig, disableState, onLoad$1)
  5628. ]);
  5629. var ActiveDisable = /*#__PURE__*/Object.freeze({
  5630. __proto__: null,
  5631. exhibit: exhibit$5,
  5632. events: events$e
  5633. });
  5634. var DisableSchema = [
  5635. defaultedFunction('disabled', never),
  5636. defaulted('useNative', true),
  5637. option$3('disableClass'),
  5638. onHandler('onDisabled'),
  5639. onHandler('onEnabled')
  5640. ];
  5641. const Disabling = create$4({
  5642. fields: DisableSchema,
  5643. name: 'disabling',
  5644. active: ActiveDisable,
  5645. apis: DisableApis
  5646. });
  5647. const dehighlightAllExcept = (component, hConfig, hState, skip) => {
  5648. const highlighted = descendants(component.element, '.' + hConfig.highlightClass);
  5649. each$1(highlighted, h => {
  5650. const shouldSkip = exists(skip, skipComp => eq(skipComp.element, h));
  5651. if (!shouldSkip) {
  5652. remove$2(h, hConfig.highlightClass);
  5653. component.getSystem().getByDom(h).each(target => {
  5654. hConfig.onDehighlight(component, target);
  5655. emit(target, dehighlight$1());
  5656. });
  5657. }
  5658. });
  5659. };
  5660. const dehighlightAll = (component, hConfig, hState) => dehighlightAllExcept(component, hConfig, hState, []);
  5661. const dehighlight = (component, hConfig, hState, target) => {
  5662. if (isHighlighted(component, hConfig, hState, target)) {
  5663. remove$2(target.element, hConfig.highlightClass);
  5664. hConfig.onDehighlight(component, target);
  5665. emit(target, dehighlight$1());
  5666. }
  5667. };
  5668. const highlight = (component, hConfig, hState, target) => {
  5669. dehighlightAllExcept(component, hConfig, hState, [target]);
  5670. if (!isHighlighted(component, hConfig, hState, target)) {
  5671. add$2(target.element, hConfig.highlightClass);
  5672. hConfig.onHighlight(component, target);
  5673. emit(target, highlight$1());
  5674. }
  5675. };
  5676. const highlightFirst = (component, hConfig, hState) => {
  5677. getFirst(component, hConfig).each(firstComp => {
  5678. highlight(component, hConfig, hState, firstComp);
  5679. });
  5680. };
  5681. const highlightLast = (component, hConfig, hState) => {
  5682. getLast(component, hConfig).each(lastComp => {
  5683. highlight(component, hConfig, hState, lastComp);
  5684. });
  5685. };
  5686. const highlightAt = (component, hConfig, hState, index) => {
  5687. getByIndex(component, hConfig, hState, index).fold(err => {
  5688. throw err;
  5689. }, firstComp => {
  5690. highlight(component, hConfig, hState, firstComp);
  5691. });
  5692. };
  5693. const highlightBy = (component, hConfig, hState, predicate) => {
  5694. const candidates = getCandidates(component, hConfig);
  5695. const targetComp = find$5(candidates, predicate);
  5696. targetComp.each(c => {
  5697. highlight(component, hConfig, hState, c);
  5698. });
  5699. };
  5700. const isHighlighted = (component, hConfig, hState, queryTarget) => has(queryTarget.element, hConfig.highlightClass);
  5701. const getHighlighted = (component, hConfig, _hState) => descendant(component.element, '.' + hConfig.highlightClass).bind(e => component.getSystem().getByDom(e).toOptional());
  5702. const getByIndex = (component, hConfig, hState, index) => {
  5703. const items = descendants(component.element, '.' + hConfig.itemClass);
  5704. return Optional.from(items[index]).fold(() => Result.error(new Error('No element found with index ' + index)), component.getSystem().getByDom);
  5705. };
  5706. const getFirst = (component, hConfig, _hState) => descendant(component.element, '.' + hConfig.itemClass).bind(e => component.getSystem().getByDom(e).toOptional());
  5707. const getLast = (component, hConfig, _hState) => {
  5708. const items = descendants(component.element, '.' + hConfig.itemClass);
  5709. const last = items.length > 0 ? Optional.some(items[items.length - 1]) : Optional.none();
  5710. return last.bind(c => component.getSystem().getByDom(c).toOptional());
  5711. };
  5712. const getDelta$2 = (component, hConfig, hState, delta) => {
  5713. const items = descendants(component.element, '.' + hConfig.itemClass);
  5714. const current = findIndex$1(items, item => has(item, hConfig.highlightClass));
  5715. return current.bind(selected => {
  5716. const dest = cycleBy(selected, delta, 0, items.length - 1);
  5717. return component.getSystem().getByDom(items[dest]).toOptional();
  5718. });
  5719. };
  5720. const getPrevious = (component, hConfig, hState) => getDelta$2(component, hConfig, hState, -1);
  5721. const getNext = (component, hConfig, hState) => getDelta$2(component, hConfig, hState, +1);
  5722. const getCandidates = (component, hConfig, _hState) => {
  5723. const items = descendants(component.element, '.' + hConfig.itemClass);
  5724. return cat(map$2(items, i => component.getSystem().getByDom(i).toOptional()));
  5725. };
  5726. var HighlightApis = /*#__PURE__*/Object.freeze({
  5727. __proto__: null,
  5728. dehighlightAll: dehighlightAll,
  5729. dehighlight: dehighlight,
  5730. highlight: highlight,
  5731. highlightFirst: highlightFirst,
  5732. highlightLast: highlightLast,
  5733. highlightAt: highlightAt,
  5734. highlightBy: highlightBy,
  5735. isHighlighted: isHighlighted,
  5736. getHighlighted: getHighlighted,
  5737. getFirst: getFirst,
  5738. getLast: getLast,
  5739. getPrevious: getPrevious,
  5740. getNext: getNext,
  5741. getCandidates: getCandidates
  5742. });
  5743. var HighlightSchema = [
  5744. required$1('highlightClass'),
  5745. required$1('itemClass'),
  5746. onHandler('onHighlight'),
  5747. onHandler('onDehighlight')
  5748. ];
  5749. const Highlighting = create$4({
  5750. fields: HighlightSchema,
  5751. name: 'highlighting',
  5752. apis: HighlightApis
  5753. });
  5754. const BACKSPACE = [8];
  5755. const TAB = [9];
  5756. const ENTER = [13];
  5757. const ESCAPE = [27];
  5758. const SPACE = [32];
  5759. const LEFT = [37];
  5760. const UP = [38];
  5761. const RIGHT = [39];
  5762. const DOWN = [40];
  5763. const cyclePrev = (values, index, predicate) => {
  5764. const before = reverse(values.slice(0, index));
  5765. const after = reverse(values.slice(index + 1));
  5766. return find$5(before.concat(after), predicate);
  5767. };
  5768. const tryPrev = (values, index, predicate) => {
  5769. const before = reverse(values.slice(0, index));
  5770. return find$5(before, predicate);
  5771. };
  5772. const cycleNext = (values, index, predicate) => {
  5773. const before = values.slice(0, index);
  5774. const after = values.slice(index + 1);
  5775. return find$5(after.concat(before), predicate);
  5776. };
  5777. const tryNext = (values, index, predicate) => {
  5778. const after = values.slice(index + 1);
  5779. return find$5(after, predicate);
  5780. };
  5781. const inSet = keys => event => {
  5782. const raw = event.raw;
  5783. return contains$2(keys, raw.which);
  5784. };
  5785. const and = preds => event => forall(preds, pred => pred(event));
  5786. const isShift = event => {
  5787. const raw = event.raw;
  5788. return raw.shiftKey === true;
  5789. };
  5790. const isControl = event => {
  5791. const raw = event.raw;
  5792. return raw.ctrlKey === true;
  5793. };
  5794. const isNotShift = not(isShift);
  5795. const rule = (matches, action) => ({
  5796. matches,
  5797. classification: action
  5798. });
  5799. const choose = (transitions, event) => {
  5800. const transition = find$5(transitions, t => t.matches(event));
  5801. return transition.map(t => t.classification);
  5802. };
  5803. const reportFocusShifting = (component, prevFocus, newFocus) => {
  5804. const noChange = prevFocus.exists(p => newFocus.exists(n => eq(n, p)));
  5805. if (!noChange) {
  5806. emitWith(component, focusShifted(), {
  5807. prevFocus,
  5808. newFocus
  5809. });
  5810. }
  5811. };
  5812. const dom$2 = () => {
  5813. const get = component => search(component.element);
  5814. const set = (component, focusee) => {
  5815. const prevFocus = get(component);
  5816. component.getSystem().triggerFocus(focusee, component.element);
  5817. const newFocus = get(component);
  5818. reportFocusShifting(component, prevFocus, newFocus);
  5819. };
  5820. return {
  5821. get,
  5822. set
  5823. };
  5824. };
  5825. const highlights = () => {
  5826. const get = component => Highlighting.getHighlighted(component).map(item => item.element);
  5827. const set = (component, element) => {
  5828. const prevFocus = get(component);
  5829. component.getSystem().getByDom(element).fold(noop, item => {
  5830. Highlighting.highlight(component, item);
  5831. });
  5832. const newFocus = get(component);
  5833. reportFocusShifting(component, prevFocus, newFocus);
  5834. };
  5835. return {
  5836. get,
  5837. set
  5838. };
  5839. };
  5840. var FocusInsideModes;
  5841. (function (FocusInsideModes) {
  5842. FocusInsideModes['OnFocusMode'] = 'onFocus';
  5843. FocusInsideModes['OnEnterOrSpaceMode'] = 'onEnterOrSpace';
  5844. FocusInsideModes['OnApiMode'] = 'onApi';
  5845. }(FocusInsideModes || (FocusInsideModes = {})));
  5846. const typical = (infoSchema, stateInit, getKeydownRules, getKeyupRules, optFocusIn) => {
  5847. const schema = () => infoSchema.concat([
  5848. defaulted('focusManager', dom$2()),
  5849. defaultedOf('focusInside', 'onFocus', valueOf(val => contains$2([
  5850. 'onFocus',
  5851. 'onEnterOrSpace',
  5852. 'onApi'
  5853. ], val) ? Result.value(val) : Result.error('Invalid value for focusInside'))),
  5854. output$1('handler', me),
  5855. output$1('state', stateInit),
  5856. output$1('sendFocusIn', optFocusIn)
  5857. ]);
  5858. const processKey = (component, simulatedEvent, getRules, keyingConfig, keyingState) => {
  5859. const rules = getRules(component, simulatedEvent, keyingConfig, keyingState);
  5860. return choose(rules, simulatedEvent.event).bind(rule => rule(component, simulatedEvent, keyingConfig, keyingState));
  5861. };
  5862. const toEvents = (keyingConfig, keyingState) => {
  5863. const onFocusHandler = keyingConfig.focusInside !== FocusInsideModes.OnFocusMode ? Optional.none() : optFocusIn(keyingConfig).map(focusIn => run$1(focus$4(), (component, simulatedEvent) => {
  5864. focusIn(component, keyingConfig, keyingState);
  5865. simulatedEvent.stop();
  5866. }));
  5867. const tryGoInsideComponent = (component, simulatedEvent) => {
  5868. const isEnterOrSpace = inSet(SPACE.concat(ENTER))(simulatedEvent.event);
  5869. if (keyingConfig.focusInside === FocusInsideModes.OnEnterOrSpaceMode && isEnterOrSpace && isSource(component, simulatedEvent)) {
  5870. optFocusIn(keyingConfig).each(focusIn => {
  5871. focusIn(component, keyingConfig, keyingState);
  5872. simulatedEvent.stop();
  5873. });
  5874. }
  5875. };
  5876. const keyboardEvents = [
  5877. run$1(keydown(), (component, simulatedEvent) => {
  5878. processKey(component, simulatedEvent, getKeydownRules, keyingConfig, keyingState).fold(() => {
  5879. tryGoInsideComponent(component, simulatedEvent);
  5880. }, _ => {
  5881. simulatedEvent.stop();
  5882. });
  5883. }),
  5884. run$1(keyup(), (component, simulatedEvent) => {
  5885. processKey(component, simulatedEvent, getKeyupRules, keyingConfig, keyingState).each(_ => {
  5886. simulatedEvent.stop();
  5887. });
  5888. })
  5889. ];
  5890. return derive$2(onFocusHandler.toArray().concat(keyboardEvents));
  5891. };
  5892. const me = {
  5893. schema,
  5894. processKey,
  5895. toEvents
  5896. };
  5897. return me;
  5898. };
  5899. const create$2 = cyclicField => {
  5900. const schema = [
  5901. option$3('onEscape'),
  5902. option$3('onEnter'),
  5903. defaulted('selector', '[data-alloy-tabstop="true"]:not(:disabled)'),
  5904. defaulted('firstTabstop', 0),
  5905. defaulted('useTabstopAt', always),
  5906. option$3('visibilitySelector')
  5907. ].concat([cyclicField]);
  5908. const isVisible = (tabbingConfig, element) => {
  5909. const target = tabbingConfig.visibilitySelector.bind(sel => closest$1(element, sel)).getOr(element);
  5910. return get$d(target) > 0;
  5911. };
  5912. const findInitial = (component, tabbingConfig) => {
  5913. const tabstops = descendants(component.element, tabbingConfig.selector);
  5914. const visibles = filter$2(tabstops, elem => isVisible(tabbingConfig, elem));
  5915. return Optional.from(visibles[tabbingConfig.firstTabstop]);
  5916. };
  5917. const findCurrent = (component, tabbingConfig) => tabbingConfig.focusManager.get(component).bind(elem => closest$1(elem, tabbingConfig.selector));
  5918. const isTabstop = (tabbingConfig, element) => isVisible(tabbingConfig, element) && tabbingConfig.useTabstopAt(element);
  5919. const focusIn = (component, tabbingConfig, _tabbingState) => {
  5920. findInitial(component, tabbingConfig).each(target => {
  5921. tabbingConfig.focusManager.set(component, target);
  5922. });
  5923. };
  5924. const goFromTabstop = (component, tabstops, stopIndex, tabbingConfig, cycle) => cycle(tabstops, stopIndex, elem => isTabstop(tabbingConfig, elem)).fold(() => tabbingConfig.cyclic ? Optional.some(true) : Optional.none(), target => {
  5925. tabbingConfig.focusManager.set(component, target);
  5926. return Optional.some(true);
  5927. });
  5928. const go = (component, _simulatedEvent, tabbingConfig, cycle) => {
  5929. const tabstops = descendants(component.element, tabbingConfig.selector);
  5930. return findCurrent(component, tabbingConfig).bind(tabstop => {
  5931. const optStopIndex = findIndex$1(tabstops, curry(eq, tabstop));
  5932. return optStopIndex.bind(stopIndex => goFromTabstop(component, tabstops, stopIndex, tabbingConfig, cycle));
  5933. });
  5934. };
  5935. const goBackwards = (component, simulatedEvent, tabbingConfig) => {
  5936. const navigate = tabbingConfig.cyclic ? cyclePrev : tryPrev;
  5937. return go(component, simulatedEvent, tabbingConfig, navigate);
  5938. };
  5939. const goForwards = (component, simulatedEvent, tabbingConfig) => {
  5940. const navigate = tabbingConfig.cyclic ? cycleNext : tryNext;
  5941. return go(component, simulatedEvent, tabbingConfig, navigate);
  5942. };
  5943. const execute = (component, simulatedEvent, tabbingConfig) => tabbingConfig.onEnter.bind(f => f(component, simulatedEvent));
  5944. const exit = (component, simulatedEvent, tabbingConfig) => tabbingConfig.onEscape.bind(f => f(component, simulatedEvent));
  5945. const getKeydownRules = constant$1([
  5946. rule(and([
  5947. isShift,
  5948. inSet(TAB)
  5949. ]), goBackwards),
  5950. rule(inSet(TAB), goForwards),
  5951. rule(and([
  5952. isNotShift,
  5953. inSet(ENTER)
  5954. ]), execute)
  5955. ]);
  5956. const getKeyupRules = constant$1([rule(inSet(ESCAPE), exit)]);
  5957. return typical(schema, NoState.init, getKeydownRules, getKeyupRules, () => Optional.some(focusIn));
  5958. };
  5959. var AcyclicType = create$2(customField('cyclic', never));
  5960. var CyclicType = create$2(customField('cyclic', always));
  5961. const doDefaultExecute = (component, _simulatedEvent, focused) => {
  5962. dispatch(component, focused, execute$5());
  5963. return Optional.some(true);
  5964. };
  5965. const defaultExecute = (component, simulatedEvent, focused) => {
  5966. const isComplex = inside(focused) && inSet(SPACE)(simulatedEvent.event);
  5967. return isComplex ? Optional.none() : doDefaultExecute(component, simulatedEvent, focused);
  5968. };
  5969. const stopEventForFirefox = (_component, _simulatedEvent) => Optional.some(true);
  5970. const schema$v = [
  5971. defaulted('execute', defaultExecute),
  5972. defaulted('useSpace', false),
  5973. defaulted('useEnter', true),
  5974. defaulted('useControlEnter', false),
  5975. defaulted('useDown', false)
  5976. ];
  5977. const execute$4 = (component, simulatedEvent, executeConfig) => executeConfig.execute(component, simulatedEvent, component.element);
  5978. const getKeydownRules$5 = (component, _simulatedEvent, executeConfig, _executeState) => {
  5979. const spaceExec = executeConfig.useSpace && !inside(component.element) ? SPACE : [];
  5980. const enterExec = executeConfig.useEnter ? ENTER : [];
  5981. const downExec = executeConfig.useDown ? DOWN : [];
  5982. const execKeys = spaceExec.concat(enterExec).concat(downExec);
  5983. return [rule(inSet(execKeys), execute$4)].concat(executeConfig.useControlEnter ? [rule(and([
  5984. isControl,
  5985. inSet(ENTER)
  5986. ]), execute$4)] : []);
  5987. };
  5988. const getKeyupRules$5 = (component, _simulatedEvent, executeConfig, _executeState) => executeConfig.useSpace && !inside(component.element) ? [rule(inSet(SPACE), stopEventForFirefox)] : [];
  5989. var ExecutionType = typical(schema$v, NoState.init, getKeydownRules$5, getKeyupRules$5, () => Optional.none());
  5990. const flatgrid$1 = () => {
  5991. const dimensions = value$2();
  5992. const setGridSize = (numRows, numColumns) => {
  5993. dimensions.set({
  5994. numRows,
  5995. numColumns
  5996. });
  5997. };
  5998. const getNumRows = () => dimensions.get().map(d => d.numRows);
  5999. const getNumColumns = () => dimensions.get().map(d => d.numColumns);
  6000. return nu$8({
  6001. readState: () => dimensions.get().map(d => ({
  6002. numRows: String(d.numRows),
  6003. numColumns: String(d.numColumns)
  6004. })).getOr({
  6005. numRows: '?',
  6006. numColumns: '?'
  6007. }),
  6008. setGridSize,
  6009. getNumRows,
  6010. getNumColumns
  6011. });
  6012. };
  6013. const init$d = spec => spec.state(spec);
  6014. var KeyingState = /*#__PURE__*/Object.freeze({
  6015. __proto__: null,
  6016. flatgrid: flatgrid$1,
  6017. init: init$d
  6018. });
  6019. const useH = movement => (component, simulatedEvent, config, state) => {
  6020. const move = movement(component.element);
  6021. return use(move, component, simulatedEvent, config, state);
  6022. };
  6023. const west$1 = (moveLeft, moveRight) => {
  6024. const movement = onDirection(moveLeft, moveRight);
  6025. return useH(movement);
  6026. };
  6027. const east$1 = (moveLeft, moveRight) => {
  6028. const movement = onDirection(moveRight, moveLeft);
  6029. return useH(movement);
  6030. };
  6031. const useV = move => (component, simulatedEvent, config, state) => use(move, component, simulatedEvent, config, state);
  6032. const use = (move, component, simulatedEvent, config, state) => {
  6033. const outcome = config.focusManager.get(component).bind(focused => move(component.element, focused, config, state));
  6034. return outcome.map(newFocus => {
  6035. config.focusManager.set(component, newFocus);
  6036. return true;
  6037. });
  6038. };
  6039. const north$1 = useV;
  6040. const south$1 = useV;
  6041. const move$1 = useV;
  6042. const isHidden$1 = dom => dom.offsetWidth <= 0 && dom.offsetHeight <= 0;
  6043. const isVisible = element => !isHidden$1(element.dom);
  6044. const locate = (candidates, predicate) => findIndex$1(candidates, predicate).map(index => ({
  6045. index,
  6046. candidates
  6047. }));
  6048. const locateVisible = (container, current, selector) => {
  6049. const predicate = x => eq(x, current);
  6050. const candidates = descendants(container, selector);
  6051. const visible = filter$2(candidates, isVisible);
  6052. return locate(visible, predicate);
  6053. };
  6054. const findIndex = (elements, target) => findIndex$1(elements, elem => eq(target, elem));
  6055. const withGrid = (values, index, numCols, f) => {
  6056. const oldRow = Math.floor(index / numCols);
  6057. const oldColumn = index % numCols;
  6058. return f(oldRow, oldColumn).bind(address => {
  6059. const newIndex = address.row * numCols + address.column;
  6060. return newIndex >= 0 && newIndex < values.length ? Optional.some(values[newIndex]) : Optional.none();
  6061. });
  6062. };
  6063. const cycleHorizontal$1 = (values, index, numRows, numCols, delta) => withGrid(values, index, numCols, (oldRow, oldColumn) => {
  6064. const onLastRow = oldRow === numRows - 1;
  6065. const colsInRow = onLastRow ? values.length - oldRow * numCols : numCols;
  6066. const newColumn = cycleBy(oldColumn, delta, 0, colsInRow - 1);
  6067. return Optional.some({
  6068. row: oldRow,
  6069. column: newColumn
  6070. });
  6071. });
  6072. const cycleVertical$1 = (values, index, numRows, numCols, delta) => withGrid(values, index, numCols, (oldRow, oldColumn) => {
  6073. const newRow = cycleBy(oldRow, delta, 0, numRows - 1);
  6074. const onLastRow = newRow === numRows - 1;
  6075. const colsInRow = onLastRow ? values.length - newRow * numCols : numCols;
  6076. const newCol = clamp(oldColumn, 0, colsInRow - 1);
  6077. return Optional.some({
  6078. row: newRow,
  6079. column: newCol
  6080. });
  6081. });
  6082. const cycleRight$1 = (values, index, numRows, numCols) => cycleHorizontal$1(values, index, numRows, numCols, +1);
  6083. const cycleLeft$1 = (values, index, numRows, numCols) => cycleHorizontal$1(values, index, numRows, numCols, -1);
  6084. const cycleUp$1 = (values, index, numRows, numCols) => cycleVertical$1(values, index, numRows, numCols, -1);
  6085. const cycleDown$1 = (values, index, numRows, numCols) => cycleVertical$1(values, index, numRows, numCols, +1);
  6086. const schema$u = [
  6087. required$1('selector'),
  6088. defaulted('execute', defaultExecute),
  6089. onKeyboardHandler('onEscape'),
  6090. defaulted('captureTab', false),
  6091. initSize()
  6092. ];
  6093. const focusIn$3 = (component, gridConfig, _gridState) => {
  6094. descendant(component.element, gridConfig.selector).each(first => {
  6095. gridConfig.focusManager.set(component, first);
  6096. });
  6097. };
  6098. const findCurrent$1 = (component, gridConfig) => gridConfig.focusManager.get(component).bind(elem => closest$1(elem, gridConfig.selector));
  6099. const execute$3 = (component, simulatedEvent, gridConfig, _gridState) => findCurrent$1(component, gridConfig).bind(focused => gridConfig.execute(component, simulatedEvent, focused));
  6100. 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)));
  6101. const handleTab = (_component, _simulatedEvent, gridConfig) => gridConfig.captureTab ? Optional.some(true) : Optional.none();
  6102. const doEscape$1 = (component, simulatedEvent, gridConfig) => gridConfig.onEscape(component, simulatedEvent);
  6103. const moveLeft$3 = doMove$2(cycleLeft$1);
  6104. const moveRight$3 = doMove$2(cycleRight$1);
  6105. const moveNorth$1 = doMove$2(cycleUp$1);
  6106. const moveSouth$1 = doMove$2(cycleDown$1);
  6107. const getKeydownRules$4 = constant$1([
  6108. rule(inSet(LEFT), west$1(moveLeft$3, moveRight$3)),
  6109. rule(inSet(RIGHT), east$1(moveLeft$3, moveRight$3)),
  6110. rule(inSet(UP), north$1(moveNorth$1)),
  6111. rule(inSet(DOWN), south$1(moveSouth$1)),
  6112. rule(and([
  6113. isShift,
  6114. inSet(TAB)
  6115. ]), handleTab),
  6116. rule(and([
  6117. isNotShift,
  6118. inSet(TAB)
  6119. ]), handleTab),
  6120. rule(inSet(SPACE.concat(ENTER)), execute$3)
  6121. ]);
  6122. const getKeyupRules$4 = constant$1([
  6123. rule(inSet(ESCAPE), doEscape$1),
  6124. rule(inSet(SPACE), stopEventForFirefox)
  6125. ]);
  6126. var FlatgridType = typical(schema$u, flatgrid$1, getKeydownRules$4, getKeyupRules$4, () => Optional.some(focusIn$3));
  6127. const f = (container, selector, current, delta, getNewIndex) => {
  6128. const isDisabledButton = candidate => name$3(candidate) === 'button' && get$f(candidate, 'disabled') === 'disabled';
  6129. const tryNewIndex = (initial, index, candidates) => getNewIndex(initial, index, delta, 0, candidates.length - 1, candidates[index], newIndex => isDisabledButton(candidates[newIndex]) ? tryNewIndex(initial, newIndex, candidates) : Optional.from(candidates[newIndex]));
  6130. return locateVisible(container, current, selector).bind(identified => {
  6131. const index = identified.index;
  6132. const candidates = identified.candidates;
  6133. return tryNewIndex(index, index, candidates);
  6134. });
  6135. };
  6136. const horizontalWithoutCycles = (container, selector, current, delta) => f(container, selector, current, delta, (prevIndex, v, d, min, max, oldCandidate, onNewIndex) => {
  6137. const newIndex = clamp(v + d, min, max);
  6138. return newIndex === prevIndex ? Optional.from(oldCandidate) : onNewIndex(newIndex);
  6139. });
  6140. const horizontal = (container, selector, current, delta) => f(container, selector, current, delta, (prevIndex, v, d, min, max, _oldCandidate, onNewIndex) => {
  6141. const newIndex = cycleBy(v, d, min, max);
  6142. return newIndex === prevIndex ? Optional.none() : onNewIndex(newIndex);
  6143. });
  6144. const schema$t = [
  6145. required$1('selector'),
  6146. defaulted('getInitial', Optional.none),
  6147. defaulted('execute', defaultExecute),
  6148. onKeyboardHandler('onEscape'),
  6149. defaulted('executeOnMove', false),
  6150. defaulted('allowVertical', true),
  6151. defaulted('allowHorizontal', true),
  6152. defaulted('cycles', true)
  6153. ];
  6154. const findCurrent = (component, flowConfig) => flowConfig.focusManager.get(component).bind(elem => closest$1(elem, flowConfig.selector));
  6155. const execute$2 = (component, simulatedEvent, flowConfig) => findCurrent(component, flowConfig).bind(focused => flowConfig.execute(component, simulatedEvent, focused));
  6156. const focusIn$2 = (component, flowConfig, _state) => {
  6157. flowConfig.getInitial(component).orThunk(() => descendant(component.element, flowConfig.selector)).each(first => {
  6158. flowConfig.focusManager.set(component, first);
  6159. });
  6160. };
  6161. const moveLeft$2 = (element, focused, info) => (info.cycles ? horizontal : horizontalWithoutCycles)(element, info.selector, focused, -1);
  6162. const moveRight$2 = (element, focused, info) => (info.cycles ? horizontal : horizontalWithoutCycles)(element, info.selector, focused, +1);
  6163. const doMove$1 = movement => (component, simulatedEvent, flowConfig, flowState) => movement(component, simulatedEvent, flowConfig, flowState).bind(() => flowConfig.executeOnMove ? execute$2(component, simulatedEvent, flowConfig) : Optional.some(true));
  6164. const doEscape = (component, simulatedEvent, flowConfig) => flowConfig.onEscape(component, simulatedEvent);
  6165. const getKeydownRules$3 = (_component, _se, flowConfig, _flowState) => {
  6166. const westMovers = [...flowConfig.allowHorizontal ? LEFT : []].concat(flowConfig.allowVertical ? UP : []);
  6167. const eastMovers = [...flowConfig.allowHorizontal ? RIGHT : []].concat(flowConfig.allowVertical ? DOWN : []);
  6168. return [
  6169. rule(inSet(westMovers), doMove$1(west$1(moveLeft$2, moveRight$2))),
  6170. rule(inSet(eastMovers), doMove$1(east$1(moveLeft$2, moveRight$2))),
  6171. rule(inSet(ENTER), execute$2),
  6172. rule(inSet(SPACE), execute$2)
  6173. ];
  6174. };
  6175. const getKeyupRules$3 = constant$1([
  6176. rule(inSet(SPACE), stopEventForFirefox),
  6177. rule(inSet(ESCAPE), doEscape)
  6178. ]);
  6179. var FlowType = typical(schema$t, NoState.init, getKeydownRules$3, getKeyupRules$3, () => Optional.some(focusIn$2));
  6180. const toCell = (matrix, rowIndex, columnIndex) => Optional.from(matrix[rowIndex]).bind(row => Optional.from(row[columnIndex]).map(cell => ({
  6181. rowIndex,
  6182. columnIndex,
  6183. cell
  6184. })));
  6185. const cycleHorizontal = (matrix, rowIndex, startCol, deltaCol) => {
  6186. const row = matrix[rowIndex];
  6187. const colsInRow = row.length;
  6188. const newColIndex = cycleBy(startCol, deltaCol, 0, colsInRow - 1);
  6189. return toCell(matrix, rowIndex, newColIndex);
  6190. };
  6191. const cycleVertical = (matrix, colIndex, startRow, deltaRow) => {
  6192. const nextRowIndex = cycleBy(startRow, deltaRow, 0, matrix.length - 1);
  6193. const colsInNextRow = matrix[nextRowIndex].length;
  6194. const nextColIndex = clamp(colIndex, 0, colsInNextRow - 1);
  6195. return toCell(matrix, nextRowIndex, nextColIndex);
  6196. };
  6197. const moveHorizontal = (matrix, rowIndex, startCol, deltaCol) => {
  6198. const row = matrix[rowIndex];
  6199. const colsInRow = row.length;
  6200. const newColIndex = clamp(startCol + deltaCol, 0, colsInRow - 1);
  6201. return toCell(matrix, rowIndex, newColIndex);
  6202. };
  6203. const moveVertical = (matrix, colIndex, startRow, deltaRow) => {
  6204. const nextRowIndex = clamp(startRow + deltaRow, 0, matrix.length - 1);
  6205. const colsInNextRow = matrix[nextRowIndex].length;
  6206. const nextColIndex = clamp(colIndex, 0, colsInNextRow - 1);
  6207. return toCell(matrix, nextRowIndex, nextColIndex);
  6208. };
  6209. const cycleRight = (matrix, startRow, startCol) => cycleHorizontal(matrix, startRow, startCol, +1);
  6210. const cycleLeft = (matrix, startRow, startCol) => cycleHorizontal(matrix, startRow, startCol, -1);
  6211. const cycleUp = (matrix, startRow, startCol) => cycleVertical(matrix, startCol, startRow, -1);
  6212. const cycleDown = (matrix, startRow, startCol) => cycleVertical(matrix, startCol, startRow, +1);
  6213. const moveLeft$1 = (matrix, startRow, startCol) => moveHorizontal(matrix, startRow, startCol, -1);
  6214. const moveRight$1 = (matrix, startRow, startCol) => moveHorizontal(matrix, startRow, startCol, +1);
  6215. const moveUp$1 = (matrix, startRow, startCol) => moveVertical(matrix, startCol, startRow, -1);
  6216. const moveDown$1 = (matrix, startRow, startCol) => moveVertical(matrix, startCol, startRow, +1);
  6217. const schema$s = [
  6218. requiredObjOf('selectors', [
  6219. required$1('row'),
  6220. required$1('cell')
  6221. ]),
  6222. defaulted('cycles', true),
  6223. defaulted('previousSelector', Optional.none),
  6224. defaulted('execute', defaultExecute)
  6225. ];
  6226. const focusIn$1 = (component, matrixConfig, _state) => {
  6227. const focused = matrixConfig.previousSelector(component).orThunk(() => {
  6228. const selectors = matrixConfig.selectors;
  6229. return descendant(component.element, selectors.cell);
  6230. });
  6231. focused.each(cell => {
  6232. matrixConfig.focusManager.set(component, cell);
  6233. });
  6234. };
  6235. const execute$1 = (component, simulatedEvent, matrixConfig) => search(component.element).bind(focused => matrixConfig.execute(component, simulatedEvent, focused));
  6236. const toMatrix = (rows, matrixConfig) => map$2(rows, row => descendants(row, matrixConfig.selectors.cell));
  6237. const doMove = (ifCycle, ifMove) => (element, focused, matrixConfig) => {
  6238. const move = matrixConfig.cycles ? ifCycle : ifMove;
  6239. return closest$1(focused, matrixConfig.selectors.row).bind(inRow => {
  6240. const cellsInRow = descendants(inRow, matrixConfig.selectors.cell);
  6241. return findIndex(cellsInRow, focused).bind(colIndex => {
  6242. const allRows = descendants(element, matrixConfig.selectors.row);
  6243. return findIndex(allRows, inRow).bind(rowIndex => {
  6244. const matrix = toMatrix(allRows, matrixConfig);
  6245. return move(matrix, rowIndex, colIndex).map(next => next.cell);
  6246. });
  6247. });
  6248. });
  6249. };
  6250. const moveLeft = doMove(cycleLeft, moveLeft$1);
  6251. const moveRight = doMove(cycleRight, moveRight$1);
  6252. const moveNorth = doMove(cycleUp, moveUp$1);
  6253. const moveSouth = doMove(cycleDown, moveDown$1);
  6254. const getKeydownRules$2 = constant$1([
  6255. rule(inSet(LEFT), west$1(moveLeft, moveRight)),
  6256. rule(inSet(RIGHT), east$1(moveLeft, moveRight)),
  6257. rule(inSet(UP), north$1(moveNorth)),
  6258. rule(inSet(DOWN), south$1(moveSouth)),
  6259. rule(inSet(SPACE.concat(ENTER)), execute$1)
  6260. ]);
  6261. const getKeyupRules$2 = constant$1([rule(inSet(SPACE), stopEventForFirefox)]);
  6262. var MatrixType = typical(schema$s, NoState.init, getKeydownRules$2, getKeyupRules$2, () => Optional.some(focusIn$1));
  6263. const schema$r = [
  6264. required$1('selector'),
  6265. defaulted('execute', defaultExecute),
  6266. defaulted('moveOnTab', false)
  6267. ];
  6268. const execute = (component, simulatedEvent, menuConfig) => menuConfig.focusManager.get(component).bind(focused => menuConfig.execute(component, simulatedEvent, focused));
  6269. const focusIn = (component, menuConfig, _state) => {
  6270. descendant(component.element, menuConfig.selector).each(first => {
  6271. menuConfig.focusManager.set(component, first);
  6272. });
  6273. };
  6274. const moveUp = (element, focused, info) => horizontal(element, info.selector, focused, -1);
  6275. const moveDown = (element, focused, info) => horizontal(element, info.selector, focused, +1);
  6276. const fireShiftTab = (component, simulatedEvent, menuConfig, menuState) => menuConfig.moveOnTab ? move$1(moveUp)(component, simulatedEvent, menuConfig, menuState) : Optional.none();
  6277. const fireTab = (component, simulatedEvent, menuConfig, menuState) => menuConfig.moveOnTab ? move$1(moveDown)(component, simulatedEvent, menuConfig, menuState) : Optional.none();
  6278. const getKeydownRules$1 = constant$1([
  6279. rule(inSet(UP), move$1(moveUp)),
  6280. rule(inSet(DOWN), move$1(moveDown)),
  6281. rule(and([
  6282. isShift,
  6283. inSet(TAB)
  6284. ]), fireShiftTab),
  6285. rule(and([
  6286. isNotShift,
  6287. inSet(TAB)
  6288. ]), fireTab),
  6289. rule(inSet(ENTER), execute),
  6290. rule(inSet(SPACE), execute)
  6291. ]);
  6292. const getKeyupRules$1 = constant$1([rule(inSet(SPACE), stopEventForFirefox)]);
  6293. var MenuType = typical(schema$r, NoState.init, getKeydownRules$1, getKeyupRules$1, () => Optional.some(focusIn));
  6294. const schema$q = [
  6295. onKeyboardHandler('onSpace'),
  6296. onKeyboardHandler('onEnter'),
  6297. onKeyboardHandler('onShiftEnter'),
  6298. onKeyboardHandler('onLeft'),
  6299. onKeyboardHandler('onRight'),
  6300. onKeyboardHandler('onTab'),
  6301. onKeyboardHandler('onShiftTab'),
  6302. onKeyboardHandler('onUp'),
  6303. onKeyboardHandler('onDown'),
  6304. onKeyboardHandler('onEscape'),
  6305. defaulted('stopSpaceKeyup', false),
  6306. option$3('focusIn')
  6307. ];
  6308. const getKeydownRules = (component, simulatedEvent, specialInfo) => [
  6309. rule(inSet(SPACE), specialInfo.onSpace),
  6310. rule(and([
  6311. isNotShift,
  6312. inSet(ENTER)
  6313. ]), specialInfo.onEnter),
  6314. rule(and([
  6315. isShift,
  6316. inSet(ENTER)
  6317. ]), specialInfo.onShiftEnter),
  6318. rule(and([
  6319. isShift,
  6320. inSet(TAB)
  6321. ]), specialInfo.onShiftTab),
  6322. rule(and([
  6323. isNotShift,
  6324. inSet(TAB)
  6325. ]), specialInfo.onTab),
  6326. rule(inSet(UP), specialInfo.onUp),
  6327. rule(inSet(DOWN), specialInfo.onDown),
  6328. rule(inSet(LEFT), specialInfo.onLeft),
  6329. rule(inSet(RIGHT), specialInfo.onRight),
  6330. rule(inSet(SPACE), specialInfo.onSpace)
  6331. ];
  6332. const getKeyupRules = (component, simulatedEvent, specialInfo) => [
  6333. ...specialInfo.stopSpaceKeyup ? [rule(inSet(SPACE), stopEventForFirefox)] : [],
  6334. rule(inSet(ESCAPE), specialInfo.onEscape)
  6335. ];
  6336. var SpecialType = typical(schema$q, NoState.init, getKeydownRules, getKeyupRules, specialInfo => specialInfo.focusIn);
  6337. const acyclic = AcyclicType.schema();
  6338. const cyclic = CyclicType.schema();
  6339. const flow = FlowType.schema();
  6340. const flatgrid = FlatgridType.schema();
  6341. const matrix = MatrixType.schema();
  6342. const execution = ExecutionType.schema();
  6343. const menu = MenuType.schema();
  6344. const special = SpecialType.schema();
  6345. var KeyboardBranches = /*#__PURE__*/Object.freeze({
  6346. __proto__: null,
  6347. acyclic: acyclic,
  6348. cyclic: cyclic,
  6349. flow: flow,
  6350. flatgrid: flatgrid,
  6351. matrix: matrix,
  6352. execution: execution,
  6353. menu: menu,
  6354. special: special
  6355. });
  6356. const isFlatgridState = keyState => hasNonNullableKey(keyState, 'setGridSize');
  6357. const Keying = createModes({
  6358. branchKey: 'mode',
  6359. branches: KeyboardBranches,
  6360. name: 'keying',
  6361. active: {
  6362. events: (keyingConfig, keyingState) => {
  6363. const handler = keyingConfig.handler;
  6364. return handler.toEvents(keyingConfig, keyingState);
  6365. }
  6366. },
  6367. apis: {
  6368. focusIn: (component, keyConfig, keyState) => {
  6369. keyConfig.sendFocusIn(keyConfig).fold(() => {
  6370. component.getSystem().triggerFocus(component.element, component.element);
  6371. }, sendFocusIn => {
  6372. sendFocusIn(component, keyConfig, keyState);
  6373. });
  6374. },
  6375. setGridSize: (component, keyConfig, keyState, numRows, numColumns) => {
  6376. if (!isFlatgridState(keyState)) {
  6377. console.error('Layout does not support setGridSize');
  6378. } else {
  6379. keyState.setGridSize(numRows, numColumns);
  6380. }
  6381. }
  6382. },
  6383. state: KeyingState
  6384. });
  6385. const withoutReuse = (parent, data) => {
  6386. preserve$1(() => {
  6387. replaceChildren(parent, data, () => map$2(data, parent.getSystem().build));
  6388. }, parent.element);
  6389. };
  6390. const withReuse = (parent, data) => {
  6391. preserve$1(() => {
  6392. virtualReplaceChildren(parent, data, () => {
  6393. return patchSpecChildren(parent.element, data, parent.getSystem().buildOrPatch);
  6394. });
  6395. }, parent.element);
  6396. };
  6397. const virtualReplace = (component, replacee, replaceeIndex, childSpec) => {
  6398. virtualDetach(replacee);
  6399. const child = patchSpecChild(component.element, replaceeIndex, childSpec, component.getSystem().buildOrPatch);
  6400. virtualAttach(component, child);
  6401. component.syncComponents();
  6402. };
  6403. const insert = (component, insertion, childSpec) => {
  6404. const child = component.getSystem().build(childSpec);
  6405. attachWith(component, child, insertion);
  6406. };
  6407. const replace = (component, replacee, replaceeIndex, childSpec) => {
  6408. detach(replacee);
  6409. insert(component, (p, c) => appendAt(p, c, replaceeIndex), childSpec);
  6410. };
  6411. const set$3 = (component, replaceConfig, replaceState, data) => {
  6412. const replacer = replaceConfig.reuseDom ? withReuse : withoutReuse;
  6413. return replacer(component, data);
  6414. };
  6415. const append = (component, replaceConfig, replaceState, appendee) => {
  6416. insert(component, append$2, appendee);
  6417. };
  6418. const prepend = (component, replaceConfig, replaceState, prependee) => {
  6419. insert(component, prepend$1, prependee);
  6420. };
  6421. const remove = (component, replaceConfig, replaceState, removee) => {
  6422. const children = contents(component);
  6423. const foundChild = find$5(children, child => eq(removee.element, child.element));
  6424. foundChild.each(detach);
  6425. };
  6426. const contents = (component, _replaceConfig) => component.components();
  6427. const replaceAt = (component, replaceConfig, replaceState, replaceeIndex, replacer) => {
  6428. const children = contents(component);
  6429. return Optional.from(children[replaceeIndex]).map(replacee => {
  6430. replacer.fold(() => detach(replacee), r => {
  6431. const replacer = replaceConfig.reuseDom ? virtualReplace : replace;
  6432. replacer(component, replacee, replaceeIndex, r);
  6433. });
  6434. return replacee;
  6435. });
  6436. };
  6437. const replaceBy = (component, replaceConfig, replaceState, replaceePred, replacer) => {
  6438. const children = contents(component);
  6439. return findIndex$1(children, replaceePred).bind(replaceeIndex => replaceAt(component, replaceConfig, replaceState, replaceeIndex, replacer));
  6440. };
  6441. var ReplaceApis = /*#__PURE__*/Object.freeze({
  6442. __proto__: null,
  6443. append: append,
  6444. prepend: prepend,
  6445. remove: remove,
  6446. replaceAt: replaceAt,
  6447. replaceBy: replaceBy,
  6448. set: set$3,
  6449. contents: contents
  6450. });
  6451. const Replacing = create$4({
  6452. fields: [defaultedBoolean('reuseDom', true)],
  6453. name: 'replacing',
  6454. apis: ReplaceApis
  6455. });
  6456. const events$d = (name, eventHandlers) => {
  6457. const events = derive$2(eventHandlers);
  6458. return create$4({
  6459. fields: [required$1('enabled')],
  6460. name,
  6461. active: { events: constant$1(events) }
  6462. });
  6463. };
  6464. const config = (name, eventHandlers) => {
  6465. const me = events$d(name, eventHandlers);
  6466. return {
  6467. key: name,
  6468. value: {
  6469. config: {},
  6470. me,
  6471. configAsRaw: constant$1({}),
  6472. initialConfig: {},
  6473. state: NoState
  6474. }
  6475. };
  6476. };
  6477. const focus$2 = (component, focusConfig) => {
  6478. if (!focusConfig.ignore) {
  6479. focus$3(component.element);
  6480. focusConfig.onFocus(component);
  6481. }
  6482. };
  6483. const blur = (component, focusConfig) => {
  6484. if (!focusConfig.ignore) {
  6485. blur$1(component.element);
  6486. }
  6487. };
  6488. const isFocused = component => hasFocus(component.element);
  6489. var FocusApis = /*#__PURE__*/Object.freeze({
  6490. __proto__: null,
  6491. focus: focus$2,
  6492. blur: blur,
  6493. isFocused: isFocused
  6494. });
  6495. const exhibit$4 = (base, focusConfig) => {
  6496. const mod = focusConfig.ignore ? {} : { attributes: { tabindex: '-1' } };
  6497. return nu$7(mod);
  6498. };
  6499. const events$c = focusConfig => derive$2([run$1(focus$4(), (component, simulatedEvent) => {
  6500. focus$2(component, focusConfig);
  6501. simulatedEvent.stop();
  6502. })].concat(focusConfig.stopMousedown ? [run$1(mousedown(), (_, simulatedEvent) => {
  6503. simulatedEvent.event.prevent();
  6504. })] : []));
  6505. var ActiveFocus = /*#__PURE__*/Object.freeze({
  6506. __proto__: null,
  6507. exhibit: exhibit$4,
  6508. events: events$c
  6509. });
  6510. var FocusSchema = [
  6511. onHandler('onFocus'),
  6512. defaulted('stopMousedown', false),
  6513. defaulted('ignore', false)
  6514. ];
  6515. const Focusing = create$4({
  6516. fields: FocusSchema,
  6517. name: 'focusing',
  6518. active: ActiveFocus,
  6519. apis: FocusApis
  6520. });
  6521. const SetupBehaviourCellState = initialState => {
  6522. const init = () => {
  6523. const cell = Cell(initialState);
  6524. const get = () => cell.get();
  6525. const set = newState => cell.set(newState);
  6526. const clear = () => cell.set(initialState);
  6527. const readState = () => cell.get();
  6528. return {
  6529. get,
  6530. set,
  6531. clear,
  6532. readState
  6533. };
  6534. };
  6535. return { init };
  6536. };
  6537. const updateAriaState = (component, toggleConfig, toggleState) => {
  6538. const ariaInfo = toggleConfig.aria;
  6539. ariaInfo.update(component, ariaInfo, toggleState.get());
  6540. };
  6541. const updateClass = (component, toggleConfig, toggleState) => {
  6542. toggleConfig.toggleClass.each(toggleClass => {
  6543. if (toggleState.get()) {
  6544. add$2(component.element, toggleClass);
  6545. } else {
  6546. remove$2(component.element, toggleClass);
  6547. }
  6548. });
  6549. };
  6550. const set$2 = (component, toggleConfig, toggleState, state) => {
  6551. const initialState = toggleState.get();
  6552. toggleState.set(state);
  6553. updateClass(component, toggleConfig, toggleState);
  6554. updateAriaState(component, toggleConfig, toggleState);
  6555. if (initialState !== state) {
  6556. toggleConfig.onToggled(component, state);
  6557. }
  6558. };
  6559. const toggle$2 = (component, toggleConfig, toggleState) => {
  6560. set$2(component, toggleConfig, toggleState, !toggleState.get());
  6561. };
  6562. const on = (component, toggleConfig, toggleState) => {
  6563. set$2(component, toggleConfig, toggleState, true);
  6564. };
  6565. const off = (component, toggleConfig, toggleState) => {
  6566. set$2(component, toggleConfig, toggleState, false);
  6567. };
  6568. const isOn = (component, toggleConfig, toggleState) => toggleState.get();
  6569. const onLoad = (component, toggleConfig, toggleState) => {
  6570. set$2(component, toggleConfig, toggleState, toggleConfig.selected);
  6571. };
  6572. var ToggleApis = /*#__PURE__*/Object.freeze({
  6573. __proto__: null,
  6574. onLoad: onLoad,
  6575. toggle: toggle$2,
  6576. isOn: isOn,
  6577. on: on,
  6578. off: off,
  6579. set: set$2
  6580. });
  6581. const exhibit$3 = () => nu$7({});
  6582. const events$b = (toggleConfig, toggleState) => {
  6583. const execute = executeEvent(toggleConfig, toggleState, toggle$2);
  6584. const load = loadEvent(toggleConfig, toggleState, onLoad);
  6585. return derive$2(flatten([
  6586. toggleConfig.toggleOnExecute ? [execute] : [],
  6587. [load]
  6588. ]));
  6589. };
  6590. var ActiveToggle = /*#__PURE__*/Object.freeze({
  6591. __proto__: null,
  6592. exhibit: exhibit$3,
  6593. events: events$b
  6594. });
  6595. const updatePressed = (component, ariaInfo, status) => {
  6596. set$9(component.element, 'aria-pressed', status);
  6597. if (ariaInfo.syncWithExpanded) {
  6598. updateExpanded(component, ariaInfo, status);
  6599. }
  6600. };
  6601. const updateSelected = (component, ariaInfo, status) => {
  6602. set$9(component.element, 'aria-selected', status);
  6603. };
  6604. const updateChecked = (component, ariaInfo, status) => {
  6605. set$9(component.element, 'aria-checked', status);
  6606. };
  6607. const updateExpanded = (component, ariaInfo, status) => {
  6608. set$9(component.element, 'aria-expanded', status);
  6609. };
  6610. var ToggleSchema = [
  6611. defaulted('selected', false),
  6612. option$3('toggleClass'),
  6613. defaulted('toggleOnExecute', true),
  6614. onHandler('onToggled'),
  6615. defaultedOf('aria', { mode: 'none' }, choose$1('mode', {
  6616. pressed: [
  6617. defaulted('syncWithExpanded', false),
  6618. output$1('update', updatePressed)
  6619. ],
  6620. checked: [output$1('update', updateChecked)],
  6621. expanded: [output$1('update', updateExpanded)],
  6622. selected: [output$1('update', updateSelected)],
  6623. none: [output$1('update', noop)]
  6624. }))
  6625. ];
  6626. const Toggling = create$4({
  6627. fields: ToggleSchema,
  6628. name: 'toggling',
  6629. active: ActiveToggle,
  6630. apis: ToggleApis,
  6631. state: SetupBehaviourCellState(false)
  6632. });
  6633. const pointerEvents = () => {
  6634. const onClick = (component, simulatedEvent) => {
  6635. simulatedEvent.stop();
  6636. emitExecute(component);
  6637. };
  6638. return [
  6639. run$1(click(), onClick),
  6640. run$1(tap(), onClick),
  6641. cutter(touchstart()),
  6642. cutter(mousedown())
  6643. ];
  6644. };
  6645. const events$a = optAction => {
  6646. const executeHandler = action => runOnExecute$1((component, simulatedEvent) => {
  6647. action(component);
  6648. simulatedEvent.stop();
  6649. });
  6650. return derive$2(flatten([
  6651. optAction.map(executeHandler).toArray(),
  6652. pointerEvents()
  6653. ]));
  6654. };
  6655. const hoverEvent = 'alloy.item-hover';
  6656. const focusEvent = 'alloy.item-focus';
  6657. const toggledEvent = 'alloy.item-toggled';
  6658. const onHover = item => {
  6659. if (search(item.element).isNone() || Focusing.isFocused(item)) {
  6660. if (!Focusing.isFocused(item)) {
  6661. Focusing.focus(item);
  6662. }
  6663. emitWith(item, hoverEvent, { item });
  6664. }
  6665. };
  6666. const onFocus$1 = item => {
  6667. emitWith(item, focusEvent, { item });
  6668. };
  6669. const onToggled = (item, state) => {
  6670. emitWith(item, toggledEvent, {
  6671. item,
  6672. state
  6673. });
  6674. };
  6675. const hover = constant$1(hoverEvent);
  6676. const focus$1 = constant$1(focusEvent);
  6677. const toggled = constant$1(toggledEvent);
  6678. const getItemRole = detail => detail.toggling.map(toggling => toggling.exclusive ? 'menuitemradio' : 'menuitemcheckbox').getOr('menuitem');
  6679. const getTogglingSpec = tConfig => ({
  6680. aria: { mode: 'checked' },
  6681. ...filter$1(tConfig, (_value, name) => name !== 'exclusive'),
  6682. onToggled: (component, state) => {
  6683. if (isFunction(tConfig.onToggled)) {
  6684. tConfig.onToggled(component, state);
  6685. }
  6686. onToggled(component, state);
  6687. }
  6688. });
  6689. const builder$2 = detail => ({
  6690. dom: detail.dom,
  6691. domModification: {
  6692. ...detail.domModification,
  6693. attributes: {
  6694. 'role': getItemRole(detail),
  6695. ...detail.domModification.attributes,
  6696. 'aria-haspopup': detail.hasSubmenu,
  6697. ...detail.hasSubmenu ? { 'aria-expanded': false } : {}
  6698. }
  6699. },
  6700. behaviours: SketchBehaviours.augment(detail.itemBehaviours, [
  6701. detail.toggling.fold(Toggling.revoke, tConfig => Toggling.config(getTogglingSpec(tConfig))),
  6702. Focusing.config({
  6703. ignore: detail.ignoreFocus,
  6704. stopMousedown: detail.ignoreFocus,
  6705. onFocus: component => {
  6706. onFocus$1(component);
  6707. }
  6708. }),
  6709. Keying.config({ mode: 'execution' }),
  6710. Representing.config({
  6711. store: {
  6712. mode: 'memory',
  6713. initialValue: detail.data
  6714. }
  6715. }),
  6716. config('item-type-events', [
  6717. ...pointerEvents(),
  6718. run$1(mouseover(), onHover),
  6719. run$1(focusItem(), Focusing.focus)
  6720. ])
  6721. ]),
  6722. components: detail.components,
  6723. eventOrder: detail.eventOrder
  6724. });
  6725. const schema$p = [
  6726. required$1('data'),
  6727. required$1('components'),
  6728. required$1('dom'),
  6729. defaulted('hasSubmenu', false),
  6730. option$3('toggling'),
  6731. SketchBehaviours.field('itemBehaviours', [
  6732. Toggling,
  6733. Focusing,
  6734. Keying,
  6735. Representing
  6736. ]),
  6737. defaulted('ignoreFocus', false),
  6738. defaulted('domModification', {}),
  6739. output$1('builder', builder$2),
  6740. defaulted('eventOrder', {})
  6741. ];
  6742. const builder$1 = detail => ({
  6743. dom: detail.dom,
  6744. components: detail.components,
  6745. events: derive$2([stopper(focusItem())])
  6746. });
  6747. const schema$o = [
  6748. required$1('dom'),
  6749. required$1('components'),
  6750. output$1('builder', builder$1)
  6751. ];
  6752. const owner$2 = constant$1('item-widget');
  6753. const parts$h = constant$1([required({
  6754. name: 'widget',
  6755. overrides: detail => {
  6756. return {
  6757. behaviours: derive$1([Representing.config({
  6758. store: {
  6759. mode: 'manual',
  6760. getValue: _component => {
  6761. return detail.data;
  6762. },
  6763. setValue: noop
  6764. }
  6765. })])
  6766. };
  6767. }
  6768. })]);
  6769. const builder = detail => {
  6770. const subs = substitutes(owner$2(), detail, parts$h());
  6771. const components = components$1(owner$2(), detail, subs.internals());
  6772. const focusWidget = component => getPart(component, detail, 'widget').map(widget => {
  6773. Keying.focusIn(widget);
  6774. return widget;
  6775. });
  6776. const onHorizontalArrow = (component, simulatedEvent) => inside(simulatedEvent.event.target) ? Optional.none() : (() => {
  6777. if (detail.autofocus) {
  6778. simulatedEvent.setSource(component.element);
  6779. return Optional.none();
  6780. } else {
  6781. return Optional.none();
  6782. }
  6783. })();
  6784. return {
  6785. dom: detail.dom,
  6786. components,
  6787. domModification: detail.domModification,
  6788. events: derive$2([
  6789. runOnExecute$1((component, simulatedEvent) => {
  6790. focusWidget(component).each(_widget => {
  6791. simulatedEvent.stop();
  6792. });
  6793. }),
  6794. run$1(mouseover(), onHover),
  6795. run$1(focusItem(), (component, _simulatedEvent) => {
  6796. if (detail.autofocus) {
  6797. focusWidget(component);
  6798. } else {
  6799. Focusing.focus(component);
  6800. }
  6801. })
  6802. ]),
  6803. behaviours: SketchBehaviours.augment(detail.widgetBehaviours, [
  6804. Representing.config({
  6805. store: {
  6806. mode: 'memory',
  6807. initialValue: detail.data
  6808. }
  6809. }),
  6810. Focusing.config({
  6811. ignore: detail.ignoreFocus,
  6812. onFocus: component => {
  6813. onFocus$1(component);
  6814. }
  6815. }),
  6816. Keying.config({
  6817. mode: 'special',
  6818. focusIn: detail.autofocus ? component => {
  6819. focusWidget(component);
  6820. } : revoke(),
  6821. onLeft: onHorizontalArrow,
  6822. onRight: onHorizontalArrow,
  6823. onEscape: (component, simulatedEvent) => {
  6824. if (!Focusing.isFocused(component) && !detail.autofocus) {
  6825. Focusing.focus(component);
  6826. return Optional.some(true);
  6827. } else if (detail.autofocus) {
  6828. simulatedEvent.setSource(component.element);
  6829. return Optional.none();
  6830. } else {
  6831. return Optional.none();
  6832. }
  6833. }
  6834. })
  6835. ])
  6836. };
  6837. };
  6838. const schema$n = [
  6839. required$1('uid'),
  6840. required$1('data'),
  6841. required$1('components'),
  6842. required$1('dom'),
  6843. defaulted('autofocus', false),
  6844. defaulted('ignoreFocus', false),
  6845. SketchBehaviours.field('widgetBehaviours', [
  6846. Representing,
  6847. Focusing,
  6848. Keying
  6849. ]),
  6850. defaulted('domModification', {}),
  6851. defaultUidsSchema(parts$h()),
  6852. output$1('builder', builder)
  6853. ];
  6854. const itemSchema$2 = choose$1('type', {
  6855. widget: schema$n,
  6856. item: schema$p,
  6857. separator: schema$o
  6858. });
  6859. const configureGrid = (detail, movementInfo) => ({
  6860. mode: 'flatgrid',
  6861. selector: '.' + detail.markers.item,
  6862. initSize: {
  6863. numColumns: movementInfo.initSize.numColumns,
  6864. numRows: movementInfo.initSize.numRows
  6865. },
  6866. focusManager: detail.focusManager
  6867. });
  6868. const configureMatrix = (detail, movementInfo) => ({
  6869. mode: 'matrix',
  6870. selectors: {
  6871. row: movementInfo.rowSelector,
  6872. cell: '.' + detail.markers.item
  6873. },
  6874. previousSelector: movementInfo.previousSelector,
  6875. focusManager: detail.focusManager
  6876. });
  6877. const configureMenu = (detail, movementInfo) => ({
  6878. mode: 'menu',
  6879. selector: '.' + detail.markers.item,
  6880. moveOnTab: movementInfo.moveOnTab,
  6881. focusManager: detail.focusManager
  6882. });
  6883. const parts$g = constant$1([group({
  6884. factory: {
  6885. sketch: spec => {
  6886. const itemInfo = asRawOrDie$1('menu.spec item', itemSchema$2, spec);
  6887. return itemInfo.builder(itemInfo);
  6888. }
  6889. },
  6890. name: 'items',
  6891. unit: 'item',
  6892. defaults: (detail, u) => {
  6893. return has$2(u, 'uid') ? u : {
  6894. ...u,
  6895. uid: generate$5('item')
  6896. };
  6897. },
  6898. overrides: (detail, u) => {
  6899. return {
  6900. type: u.type,
  6901. ignoreFocus: detail.fakeFocus,
  6902. domModification: { classes: [detail.markers.item] }
  6903. };
  6904. }
  6905. })]);
  6906. const schema$m = constant$1([
  6907. required$1('value'),
  6908. required$1('items'),
  6909. required$1('dom'),
  6910. required$1('components'),
  6911. defaulted('eventOrder', {}),
  6912. field('menuBehaviours', [
  6913. Highlighting,
  6914. Representing,
  6915. Composing,
  6916. Keying
  6917. ]),
  6918. defaultedOf('movement', {
  6919. mode: 'menu',
  6920. moveOnTab: true
  6921. }, choose$1('mode', {
  6922. grid: [
  6923. initSize(),
  6924. output$1('config', configureGrid)
  6925. ],
  6926. matrix: [
  6927. output$1('config', configureMatrix),
  6928. required$1('rowSelector'),
  6929. defaulted('previousSelector', Optional.none)
  6930. ],
  6931. menu: [
  6932. defaulted('moveOnTab', true),
  6933. output$1('config', configureMenu)
  6934. ]
  6935. })),
  6936. itemMarkers(),
  6937. defaulted('fakeFocus', false),
  6938. defaulted('focusManager', dom$2()),
  6939. onHandler('onHighlight'),
  6940. onHandler('onDehighlight')
  6941. ]);
  6942. const focus = constant$1('alloy.menu-focus');
  6943. const deselectOtherRadioItems = (menu, item) => {
  6944. const checkedRadioItems = descendants(menu.element, '[role="menuitemradio"][aria-checked="true"]');
  6945. each$1(checkedRadioItems, ele => {
  6946. if (!eq(ele, item.element)) {
  6947. menu.getSystem().getByDom(ele).each(c => {
  6948. Toggling.off(c);
  6949. });
  6950. }
  6951. });
  6952. };
  6953. const make$7 = (detail, components, _spec, _externals) => ({
  6954. uid: detail.uid,
  6955. dom: detail.dom,
  6956. markers: detail.markers,
  6957. behaviours: augment(detail.menuBehaviours, [
  6958. Highlighting.config({
  6959. highlightClass: detail.markers.selectedItem,
  6960. itemClass: detail.markers.item,
  6961. onHighlight: detail.onHighlight,
  6962. onDehighlight: detail.onDehighlight
  6963. }),
  6964. Representing.config({
  6965. store: {
  6966. mode: 'memory',
  6967. initialValue: detail.value
  6968. }
  6969. }),
  6970. Composing.config({ find: Optional.some }),
  6971. Keying.config(detail.movement.config(detail, detail.movement))
  6972. ]),
  6973. events: derive$2([
  6974. run$1(focus$1(), (menu, simulatedEvent) => {
  6975. const event = simulatedEvent.event;
  6976. menu.getSystem().getByDom(event.target).each(item => {
  6977. Highlighting.highlight(menu, item);
  6978. simulatedEvent.stop();
  6979. emitWith(menu, focus(), {
  6980. menu,
  6981. item
  6982. });
  6983. });
  6984. }),
  6985. run$1(hover(), (menu, simulatedEvent) => {
  6986. const item = simulatedEvent.event.item;
  6987. Highlighting.highlight(menu, item);
  6988. }),
  6989. run$1(toggled(), (menu, simulatedEvent) => {
  6990. const {item, state} = simulatedEvent.event;
  6991. if (state && get$f(item.element, 'role') === 'menuitemradio') {
  6992. deselectOtherRadioItems(menu, item);
  6993. }
  6994. })
  6995. ]),
  6996. components,
  6997. eventOrder: detail.eventOrder,
  6998. domModification: { attributes: { role: 'menu' } }
  6999. });
  7000. const Menu = composite({
  7001. name: 'Menu',
  7002. configFields: schema$m(),
  7003. partFields: parts$g(),
  7004. factory: make$7
  7005. });
  7006. const transpose$1 = obj => tupleMap(obj, (v, k) => ({
  7007. k: v,
  7008. v: k
  7009. }));
  7010. const trace = (items, byItem, byMenu, finish) => get$g(byMenu, finish).bind(triggerItem => get$g(items, triggerItem).bind(triggerMenu => {
  7011. const rest = trace(items, byItem, byMenu, triggerMenu);
  7012. return Optional.some([triggerMenu].concat(rest));
  7013. })).getOr([]);
  7014. const generate$2 = (menus, expansions) => {
  7015. const items = {};
  7016. each(menus, (menuItems, menu) => {
  7017. each$1(menuItems, item => {
  7018. items[item] = menu;
  7019. });
  7020. });
  7021. const byItem = expansions;
  7022. const byMenu = transpose$1(expansions);
  7023. const menuPaths = map$1(byMenu, (_triggerItem, submenu) => [submenu].concat(trace(items, byItem, byMenu, submenu)));
  7024. return map$1(items, menu => get$g(menuPaths, menu).getOr([menu]));
  7025. };
  7026. const init$c = () => {
  7027. const expansions = Cell({});
  7028. const menus = Cell({});
  7029. const paths = Cell({});
  7030. const primary = value$2();
  7031. const directory = Cell({});
  7032. const clear = () => {
  7033. expansions.set({});
  7034. menus.set({});
  7035. paths.set({});
  7036. primary.clear();
  7037. };
  7038. const isClear = () => primary.get().isNone();
  7039. const setMenuBuilt = (menuName, built) => {
  7040. menus.set({
  7041. ...menus.get(),
  7042. [menuName]: {
  7043. type: 'prepared',
  7044. menu: built
  7045. }
  7046. });
  7047. };
  7048. const setContents = (sPrimary, sMenus, sExpansions, dir) => {
  7049. primary.set(sPrimary);
  7050. expansions.set(sExpansions);
  7051. menus.set(sMenus);
  7052. directory.set(dir);
  7053. const sPaths = generate$2(dir, sExpansions);
  7054. paths.set(sPaths);
  7055. };
  7056. const getTriggeringItem = menuValue => find$4(expansions.get(), (v, _k) => v === menuValue);
  7057. const getTriggerData = (menuValue, getItemByValue, path) => getPreparedMenu(menuValue).bind(menu => getTriggeringItem(menuValue).bind(triggeringItemValue => getItemByValue(triggeringItemValue).map(triggeredItem => ({
  7058. triggeredMenu: menu,
  7059. triggeringItem: triggeredItem,
  7060. triggeringPath: path
  7061. }))));
  7062. const getTriggeringPath = (itemValue, getItemByValue) => {
  7063. const extraPath = filter$2(lookupItem(itemValue).toArray(), menuValue => getPreparedMenu(menuValue).isSome());
  7064. return get$g(paths.get(), itemValue).bind(path => {
  7065. const revPath = reverse(extraPath.concat(path));
  7066. 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)]));
  7067. return sequence(triggers);
  7068. });
  7069. };
  7070. const expand = itemValue => get$g(expansions.get(), itemValue).map(menu => {
  7071. const current = get$g(paths.get(), itemValue).getOr([]);
  7072. return [menu].concat(current);
  7073. });
  7074. const collapse = itemValue => get$g(paths.get(), itemValue).bind(path => path.length > 1 ? Optional.some(path.slice(1)) : Optional.none());
  7075. const refresh = itemValue => get$g(paths.get(), itemValue);
  7076. const getPreparedMenu = menuValue => lookupMenu(menuValue).bind(extractPreparedMenu);
  7077. const lookupMenu = menuValue => get$g(menus.get(), menuValue);
  7078. const lookupItem = itemValue => get$g(expansions.get(), itemValue);
  7079. const otherMenus = path => {
  7080. const menuValues = directory.get();
  7081. return difference(keys(menuValues), path);
  7082. };
  7083. const getPrimary = () => primary.get().bind(getPreparedMenu);
  7084. const getMenus = () => menus.get();
  7085. return {
  7086. setMenuBuilt,
  7087. setContents,
  7088. expand,
  7089. refresh,
  7090. collapse,
  7091. lookupMenu,
  7092. lookupItem,
  7093. otherMenus,
  7094. getPrimary,
  7095. getMenus,
  7096. clear,
  7097. isClear,
  7098. getTriggeringPath
  7099. };
  7100. };
  7101. const extractPreparedMenu = prep => prep.type === 'prepared' ? Optional.some(prep.menu) : Optional.none();
  7102. const LayeredState = {
  7103. init: init$c,
  7104. extractPreparedMenu
  7105. };
  7106. const onMenuItemHighlightedEvent = generate$6('tiered-menu-item-highlight');
  7107. const onMenuItemDehighlightedEvent = generate$6('tiered-menu-item-dehighlight');
  7108. var HighlightOnOpen;
  7109. (function (HighlightOnOpen) {
  7110. HighlightOnOpen[HighlightOnOpen['HighlightMenuAndItem'] = 0] = 'HighlightMenuAndItem';
  7111. HighlightOnOpen[HighlightOnOpen['HighlightJustMenu'] = 1] = 'HighlightJustMenu';
  7112. HighlightOnOpen[HighlightOnOpen['HighlightNone'] = 2] = 'HighlightNone';
  7113. }(HighlightOnOpen || (HighlightOnOpen = {})));
  7114. const make$6 = (detail, _rawUiSpec) => {
  7115. const submenuParentItems = value$2();
  7116. const buildMenus = (container, primaryName, menus) => map$1(menus, (spec, name) => {
  7117. const makeSketch = () => Menu.sketch({
  7118. ...spec,
  7119. value: name,
  7120. markers: detail.markers,
  7121. fakeFocus: detail.fakeFocus,
  7122. onHighlight: (menuComp, itemComp) => {
  7123. const highlightData = {
  7124. menuComp,
  7125. itemComp
  7126. };
  7127. emitWith(menuComp, onMenuItemHighlightedEvent, highlightData);
  7128. },
  7129. onDehighlight: (menuComp, itemComp) => {
  7130. const dehighlightData = {
  7131. menuComp,
  7132. itemComp
  7133. };
  7134. emitWith(menuComp, onMenuItemDehighlightedEvent, dehighlightData);
  7135. },
  7136. focusManager: detail.fakeFocus ? highlights() : dom$2()
  7137. });
  7138. return name === primaryName ? {
  7139. type: 'prepared',
  7140. menu: container.getSystem().build(makeSketch())
  7141. } : {
  7142. type: 'notbuilt',
  7143. nbMenu: makeSketch
  7144. };
  7145. });
  7146. const layeredState = LayeredState.init();
  7147. const setup = container => {
  7148. const componentMap = buildMenus(container, detail.data.primary, detail.data.menus);
  7149. const directory = toDirectory();
  7150. layeredState.setContents(detail.data.primary, componentMap, detail.data.expansions, directory);
  7151. return layeredState.getPrimary();
  7152. };
  7153. const getItemValue = item => Representing.getValue(item).value;
  7154. const getItemByValue = (_container, menus, itemValue) => findMap(menus, menu => {
  7155. if (!menu.getSystem().isConnected()) {
  7156. return Optional.none();
  7157. }
  7158. const candidates = Highlighting.getCandidates(menu);
  7159. return find$5(candidates, c => getItemValue(c) === itemValue);
  7160. });
  7161. const toDirectory = _container => map$1(detail.data.menus, (data, _menuName) => bind$3(data.items, item => item.type === 'separator' ? [] : [item.data.value]));
  7162. const setActiveMenu = Highlighting.highlight;
  7163. const setActiveMenuAndItem = (container, menu) => {
  7164. setActiveMenu(container, menu);
  7165. Highlighting.getHighlighted(menu).orThunk(() => Highlighting.getFirst(menu)).each(item => {
  7166. if (detail.fakeFocus) {
  7167. Highlighting.highlight(menu, item);
  7168. } else {
  7169. dispatch(container, item.element, focusItem());
  7170. }
  7171. });
  7172. };
  7173. const getMenus = (state, menuValues) => cat(map$2(menuValues, mv => state.lookupMenu(mv).bind(prep => prep.type === 'prepared' ? Optional.some(prep.menu) : Optional.none())));
  7174. const closeOthers = (container, state, path) => {
  7175. const others = getMenus(state, state.otherMenus(path));
  7176. each$1(others, o => {
  7177. remove$1(o.element, [detail.markers.backgroundMenu]);
  7178. if (!detail.stayInDom) {
  7179. Replacing.remove(container, o);
  7180. }
  7181. });
  7182. };
  7183. const getSubmenuParents = container => submenuParentItems.get().getOrThunk(() => {
  7184. const r = {};
  7185. const items = descendants(container.element, `.${ detail.markers.item }`);
  7186. const parentItems = filter$2(items, i => get$f(i, 'aria-haspopup') === 'true');
  7187. each$1(parentItems, i => {
  7188. container.getSystem().getByDom(i).each(itemComp => {
  7189. const key = getItemValue(itemComp);
  7190. r[key] = itemComp;
  7191. });
  7192. });
  7193. submenuParentItems.set(r);
  7194. return r;
  7195. });
  7196. const updateAriaExpansions = (container, path) => {
  7197. const parentItems = getSubmenuParents(container);
  7198. each(parentItems, (v, k) => {
  7199. const expanded = contains$2(path, k);
  7200. set$9(v.element, 'aria-expanded', expanded);
  7201. });
  7202. };
  7203. const updateMenuPath = (container, state, path) => Optional.from(path[0]).bind(latestMenuName => state.lookupMenu(latestMenuName).bind(menuPrep => {
  7204. if (menuPrep.type === 'notbuilt') {
  7205. return Optional.none();
  7206. } else {
  7207. const activeMenu = menuPrep.menu;
  7208. const rest = getMenus(state, path.slice(1));
  7209. each$1(rest, r => {
  7210. add$2(r.element, detail.markers.backgroundMenu);
  7211. });
  7212. if (!inBody(activeMenu.element)) {
  7213. Replacing.append(container, premade(activeMenu));
  7214. }
  7215. remove$1(activeMenu.element, [detail.markers.backgroundMenu]);
  7216. setActiveMenuAndItem(container, activeMenu);
  7217. closeOthers(container, state, path);
  7218. return Optional.some(activeMenu);
  7219. }
  7220. }));
  7221. let ExpandHighlightDecision;
  7222. (function (ExpandHighlightDecision) {
  7223. ExpandHighlightDecision[ExpandHighlightDecision['HighlightSubmenu'] = 0] = 'HighlightSubmenu';
  7224. ExpandHighlightDecision[ExpandHighlightDecision['HighlightParent'] = 1] = 'HighlightParent';
  7225. }(ExpandHighlightDecision || (ExpandHighlightDecision = {})));
  7226. const buildIfRequired = (container, menuName, menuPrep) => {
  7227. if (menuPrep.type === 'notbuilt') {
  7228. const menu = container.getSystem().build(menuPrep.nbMenu());
  7229. layeredState.setMenuBuilt(menuName, menu);
  7230. return menu;
  7231. } else {
  7232. return menuPrep.menu;
  7233. }
  7234. };
  7235. const expandRight = (container, item, decision = ExpandHighlightDecision.HighlightSubmenu) => {
  7236. if (item.hasConfigured(Disabling) && Disabling.isDisabled(item)) {
  7237. return Optional.some(item);
  7238. } else {
  7239. const value = getItemValue(item);
  7240. return layeredState.expand(value).bind(path => {
  7241. updateAriaExpansions(container, path);
  7242. return Optional.from(path[0]).bind(menuName => layeredState.lookupMenu(menuName).bind(activeMenuPrep => {
  7243. const activeMenu = buildIfRequired(container, menuName, activeMenuPrep);
  7244. if (!inBody(activeMenu.element)) {
  7245. Replacing.append(container, premade(activeMenu));
  7246. }
  7247. detail.onOpenSubmenu(container, item, activeMenu, reverse(path));
  7248. if (decision === ExpandHighlightDecision.HighlightSubmenu) {
  7249. Highlighting.highlightFirst(activeMenu);
  7250. return updateMenuPath(container, layeredState, path);
  7251. } else {
  7252. Highlighting.dehighlightAll(activeMenu);
  7253. return Optional.some(item);
  7254. }
  7255. }));
  7256. });
  7257. }
  7258. };
  7259. const collapseLeft = (container, item) => {
  7260. const value = getItemValue(item);
  7261. return layeredState.collapse(value).bind(path => {
  7262. updateAriaExpansions(container, path);
  7263. return updateMenuPath(container, layeredState, path).map(activeMenu => {
  7264. detail.onCollapseMenu(container, item, activeMenu);
  7265. return activeMenu;
  7266. });
  7267. });
  7268. };
  7269. const updateView = (container, item) => {
  7270. const value = getItemValue(item);
  7271. return layeredState.refresh(value).bind(path => {
  7272. updateAriaExpansions(container, path);
  7273. return updateMenuPath(container, layeredState, path);
  7274. });
  7275. };
  7276. const onRight = (container, item) => inside(item.element) ? Optional.none() : expandRight(container, item, ExpandHighlightDecision.HighlightSubmenu);
  7277. const onLeft = (container, item) => inside(item.element) ? Optional.none() : collapseLeft(container, item);
  7278. const onEscape = (container, item) => collapseLeft(container, item).orThunk(() => detail.onEscape(container, item).map(() => container));
  7279. const keyOnItem = f => (container, simulatedEvent) => {
  7280. return closest$1(simulatedEvent.getSource(), `.${ detail.markers.item }`).bind(target => container.getSystem().getByDom(target).toOptional().bind(item => f(container, item).map(always)));
  7281. };
  7282. const events = derive$2([
  7283. run$1(focus(), (tmenu, simulatedEvent) => {
  7284. const item = simulatedEvent.event.item;
  7285. layeredState.lookupItem(getItemValue(item)).each(() => {
  7286. const menu = simulatedEvent.event.menu;
  7287. Highlighting.highlight(tmenu, menu);
  7288. const value = getItemValue(simulatedEvent.event.item);
  7289. layeredState.refresh(value).each(path => closeOthers(tmenu, layeredState, path));
  7290. });
  7291. }),
  7292. runOnExecute$1((component, simulatedEvent) => {
  7293. const target = simulatedEvent.event.target;
  7294. component.getSystem().getByDom(target).each(item => {
  7295. const itemValue = getItemValue(item);
  7296. if (itemValue.indexOf('collapse-item') === 0) {
  7297. collapseLeft(component, item);
  7298. }
  7299. expandRight(component, item, ExpandHighlightDecision.HighlightSubmenu).fold(() => {
  7300. detail.onExecute(component, item);
  7301. }, noop);
  7302. });
  7303. }),
  7304. runOnAttached((container, _simulatedEvent) => {
  7305. setup(container).each(primary => {
  7306. Replacing.append(container, premade(primary));
  7307. detail.onOpenMenu(container, primary);
  7308. if (detail.highlightOnOpen === HighlightOnOpen.HighlightMenuAndItem) {
  7309. setActiveMenuAndItem(container, primary);
  7310. } else if (detail.highlightOnOpen === HighlightOnOpen.HighlightJustMenu) {
  7311. setActiveMenu(container, primary);
  7312. }
  7313. });
  7314. }),
  7315. run$1(onMenuItemHighlightedEvent, (tmenuComp, se) => {
  7316. detail.onHighlightItem(tmenuComp, se.event.menuComp, se.event.itemComp);
  7317. }),
  7318. run$1(onMenuItemDehighlightedEvent, (tmenuComp, se) => {
  7319. detail.onDehighlightItem(tmenuComp, se.event.menuComp, se.event.itemComp);
  7320. }),
  7321. ...detail.navigateOnHover ? [run$1(hover(), (tmenu, simulatedEvent) => {
  7322. const item = simulatedEvent.event.item;
  7323. updateView(tmenu, item);
  7324. expandRight(tmenu, item, ExpandHighlightDecision.HighlightParent);
  7325. detail.onHover(tmenu, item);
  7326. })] : []
  7327. ]);
  7328. const getActiveItem = container => Highlighting.getHighlighted(container).bind(Highlighting.getHighlighted);
  7329. const collapseMenuApi = container => {
  7330. getActiveItem(container).each(currentItem => {
  7331. collapseLeft(container, currentItem);
  7332. });
  7333. };
  7334. const highlightPrimary = container => {
  7335. layeredState.getPrimary().each(primary => {
  7336. setActiveMenuAndItem(container, primary);
  7337. });
  7338. };
  7339. const extractMenuFromContainer = container => Optional.from(container.components()[0]).filter(comp => get$f(comp.element, 'role') === 'menu');
  7340. const repositionMenus = container => {
  7341. const maybeActivePrimary = layeredState.getPrimary().bind(primary => getActiveItem(container).bind(currentItem => {
  7342. const itemValue = getItemValue(currentItem);
  7343. const allMenus = values(layeredState.getMenus());
  7344. const preparedMenus = cat(map$2(allMenus, LayeredState.extractPreparedMenu));
  7345. return layeredState.getTriggeringPath(itemValue, v => getItemByValue(container, preparedMenus, v));
  7346. }).map(triggeringPath => ({
  7347. primary,
  7348. triggeringPath
  7349. })));
  7350. maybeActivePrimary.fold(() => {
  7351. extractMenuFromContainer(container).each(primaryMenu => {
  7352. detail.onRepositionMenu(container, primaryMenu, []);
  7353. });
  7354. }, ({primary, triggeringPath}) => {
  7355. detail.onRepositionMenu(container, primary, triggeringPath);
  7356. });
  7357. };
  7358. const apis = {
  7359. collapseMenu: collapseMenuApi,
  7360. highlightPrimary,
  7361. repositionMenus
  7362. };
  7363. return {
  7364. uid: detail.uid,
  7365. dom: detail.dom,
  7366. markers: detail.markers,
  7367. behaviours: augment(detail.tmenuBehaviours, [
  7368. Keying.config({
  7369. mode: 'special',
  7370. onRight: keyOnItem(onRight),
  7371. onLeft: keyOnItem(onLeft),
  7372. onEscape: keyOnItem(onEscape),
  7373. focusIn: (container, _keyInfo) => {
  7374. layeredState.getPrimary().each(primary => {
  7375. dispatch(container, primary.element, focusItem());
  7376. });
  7377. }
  7378. }),
  7379. Highlighting.config({
  7380. highlightClass: detail.markers.selectedMenu,
  7381. itemClass: detail.markers.menu
  7382. }),
  7383. Composing.config({
  7384. find: container => {
  7385. return Highlighting.getHighlighted(container);
  7386. }
  7387. }),
  7388. Replacing.config({})
  7389. ]),
  7390. eventOrder: detail.eventOrder,
  7391. apis,
  7392. events
  7393. };
  7394. };
  7395. const collapseItem$1 = constant$1('collapse-item');
  7396. const tieredData = (primary, menus, expansions) => ({
  7397. primary,
  7398. menus,
  7399. expansions
  7400. });
  7401. const singleData = (name, menu) => ({
  7402. primary: name,
  7403. menus: wrap$1(name, menu),
  7404. expansions: {}
  7405. });
  7406. const collapseItem = text => ({
  7407. value: generate$6(collapseItem$1()),
  7408. meta: { text }
  7409. });
  7410. const tieredMenu = single({
  7411. name: 'TieredMenu',
  7412. configFields: [
  7413. onStrictKeyboardHandler('onExecute'),
  7414. onStrictKeyboardHandler('onEscape'),
  7415. onStrictHandler('onOpenMenu'),
  7416. onStrictHandler('onOpenSubmenu'),
  7417. onHandler('onRepositionMenu'),
  7418. onHandler('onCollapseMenu'),
  7419. defaulted('highlightOnOpen', HighlightOnOpen.HighlightMenuAndItem),
  7420. requiredObjOf('data', [
  7421. required$1('primary'),
  7422. required$1('menus'),
  7423. required$1('expansions')
  7424. ]),
  7425. defaulted('fakeFocus', false),
  7426. onHandler('onHighlightItem'),
  7427. onHandler('onDehighlightItem'),
  7428. onHandler('onHover'),
  7429. tieredMenuMarkers(),
  7430. required$1('dom'),
  7431. defaulted('navigateOnHover', true),
  7432. defaulted('stayInDom', false),
  7433. field('tmenuBehaviours', [
  7434. Keying,
  7435. Highlighting,
  7436. Composing,
  7437. Replacing
  7438. ]),
  7439. defaulted('eventOrder', {})
  7440. ],
  7441. apis: {
  7442. collapseMenu: (apis, tmenu) => {
  7443. apis.collapseMenu(tmenu);
  7444. },
  7445. highlightPrimary: (apis, tmenu) => {
  7446. apis.highlightPrimary(tmenu);
  7447. },
  7448. repositionMenus: (apis, tmenu) => {
  7449. apis.repositionMenus(tmenu);
  7450. }
  7451. },
  7452. factory: make$6,
  7453. extraApis: {
  7454. tieredData,
  7455. singleData,
  7456. collapseItem
  7457. }
  7458. });
  7459. const makeMenu = (detail, menuSandbox, placementSpec, menuSpec, getBounds) => {
  7460. const lazySink = () => detail.lazySink(menuSandbox);
  7461. const layouts = menuSpec.type === 'horizontal' ? {
  7462. layouts: {
  7463. onLtr: () => belowOrAbove(),
  7464. onRtl: () => belowOrAboveRtl()
  7465. }
  7466. } : {};
  7467. const isFirstTierSubmenu = triggeringPaths => triggeringPaths.length === 2;
  7468. const getSubmenuLayouts = triggeringPaths => isFirstTierSubmenu(triggeringPaths) ? layouts : {};
  7469. return tieredMenu.sketch({
  7470. dom: { tag: 'div' },
  7471. data: menuSpec.data,
  7472. markers: menuSpec.menu.markers,
  7473. highlightOnOpen: menuSpec.menu.highlightOnOpen,
  7474. fakeFocus: menuSpec.menu.fakeFocus,
  7475. onEscape: () => {
  7476. Sandboxing.close(menuSandbox);
  7477. detail.onEscape.map(handler => handler(menuSandbox));
  7478. return Optional.some(true);
  7479. },
  7480. onExecute: () => {
  7481. return Optional.some(true);
  7482. },
  7483. onOpenMenu: (tmenu, menu) => {
  7484. Positioning.positionWithinBounds(lazySink().getOrDie(), menu, placementSpec, getBounds());
  7485. },
  7486. onOpenSubmenu: (tmenu, item, submenu, triggeringPaths) => {
  7487. const sink = lazySink().getOrDie();
  7488. Positioning.position(sink, submenu, {
  7489. anchor: {
  7490. type: 'submenu',
  7491. item,
  7492. ...getSubmenuLayouts(triggeringPaths)
  7493. }
  7494. });
  7495. },
  7496. onRepositionMenu: (tmenu, primaryMenu, submenuTriggers) => {
  7497. const sink = lazySink().getOrDie();
  7498. Positioning.positionWithinBounds(sink, primaryMenu, placementSpec, getBounds());
  7499. each$1(submenuTriggers, st => {
  7500. const submenuLayouts = getSubmenuLayouts(st.triggeringPath);
  7501. Positioning.position(sink, st.triggeredMenu, {
  7502. anchor: {
  7503. type: 'submenu',
  7504. item: st.triggeringItem,
  7505. ...submenuLayouts
  7506. }
  7507. });
  7508. });
  7509. }
  7510. });
  7511. };
  7512. const factory$o = (detail, spec) => {
  7513. const isPartOfRelated = (sandbox, queryElem) => {
  7514. const related = detail.getRelated(sandbox);
  7515. return related.exists(rel => isPartOf$1(rel, queryElem));
  7516. };
  7517. const setContent = (sandbox, thing) => {
  7518. Sandboxing.setContent(sandbox, thing);
  7519. };
  7520. const showAt = (sandbox, thing, placementSpec) => {
  7521. const getBounds = Optional.none;
  7522. showWithinBounds(sandbox, thing, placementSpec, getBounds);
  7523. };
  7524. const showWithinBounds = (sandbox, thing, placementSpec, getBounds) => {
  7525. const sink = detail.lazySink(sandbox).getOrDie();
  7526. Sandboxing.openWhileCloaked(sandbox, thing, () => Positioning.positionWithinBounds(sink, sandbox, placementSpec, getBounds()));
  7527. Representing.setValue(sandbox, Optional.some({
  7528. mode: 'position',
  7529. config: placementSpec,
  7530. getBounds
  7531. }));
  7532. };
  7533. const showMenuAt = (sandbox, placementSpec, menuSpec) => {
  7534. showMenuWithinBounds(sandbox, placementSpec, menuSpec, Optional.none);
  7535. };
  7536. const showMenuWithinBounds = (sandbox, placementSpec, menuSpec, getBounds) => {
  7537. const menu = makeMenu(detail, sandbox, placementSpec, menuSpec, getBounds);
  7538. Sandboxing.open(sandbox, menu);
  7539. Representing.setValue(sandbox, Optional.some({
  7540. mode: 'menu',
  7541. menu
  7542. }));
  7543. };
  7544. const hide = sandbox => {
  7545. if (Sandboxing.isOpen(sandbox)) {
  7546. Representing.setValue(sandbox, Optional.none());
  7547. Sandboxing.close(sandbox);
  7548. }
  7549. };
  7550. const getContent = sandbox => Sandboxing.getState(sandbox);
  7551. const reposition = sandbox => {
  7552. if (Sandboxing.isOpen(sandbox)) {
  7553. Representing.getValue(sandbox).each(state => {
  7554. switch (state.mode) {
  7555. case 'menu':
  7556. Sandboxing.getState(sandbox).each(tieredMenu.repositionMenus);
  7557. break;
  7558. case 'position':
  7559. const sink = detail.lazySink(sandbox).getOrDie();
  7560. Positioning.positionWithinBounds(sink, sandbox, state.config, state.getBounds());
  7561. break;
  7562. }
  7563. });
  7564. }
  7565. };
  7566. const apis = {
  7567. setContent,
  7568. showAt,
  7569. showWithinBounds,
  7570. showMenuAt,
  7571. showMenuWithinBounds,
  7572. hide,
  7573. getContent,
  7574. reposition,
  7575. isOpen: Sandboxing.isOpen
  7576. };
  7577. return {
  7578. uid: detail.uid,
  7579. dom: detail.dom,
  7580. behaviours: augment(detail.inlineBehaviours, [
  7581. Sandboxing.config({
  7582. isPartOf: (sandbox, data, queryElem) => {
  7583. return isPartOf$1(data, queryElem) || isPartOfRelated(sandbox, queryElem);
  7584. },
  7585. getAttachPoint: sandbox => {
  7586. return detail.lazySink(sandbox).getOrDie();
  7587. },
  7588. onOpen: sandbox => {
  7589. detail.onShow(sandbox);
  7590. },
  7591. onClose: sandbox => {
  7592. detail.onHide(sandbox);
  7593. }
  7594. }),
  7595. Representing.config({
  7596. store: {
  7597. mode: 'memory',
  7598. initialValue: Optional.none()
  7599. }
  7600. }),
  7601. Receiving.config({
  7602. channels: {
  7603. ...receivingChannel$1({
  7604. isExtraPart: spec.isExtraPart,
  7605. ...detail.fireDismissalEventInstead.map(fe => ({ fireEventInstead: { event: fe.event } })).getOr({})
  7606. }),
  7607. ...receivingChannel({
  7608. ...detail.fireRepositionEventInstead.map(fe => ({ fireEventInstead: { event: fe.event } })).getOr({}),
  7609. doReposition: reposition
  7610. })
  7611. }
  7612. })
  7613. ]),
  7614. eventOrder: detail.eventOrder,
  7615. apis
  7616. };
  7617. };
  7618. const InlineView = single({
  7619. name: 'InlineView',
  7620. configFields: [
  7621. required$1('lazySink'),
  7622. onHandler('onShow'),
  7623. onHandler('onHide'),
  7624. optionFunction('onEscape'),
  7625. field('inlineBehaviours', [
  7626. Sandboxing,
  7627. Representing,
  7628. Receiving
  7629. ]),
  7630. optionObjOf('fireDismissalEventInstead', [defaulted('event', dismissRequested())]),
  7631. optionObjOf('fireRepositionEventInstead', [defaulted('event', repositionRequested())]),
  7632. defaulted('getRelated', Optional.none),
  7633. defaulted('isExtraPart', never),
  7634. defaulted('eventOrder', Optional.none)
  7635. ],
  7636. factory: factory$o,
  7637. apis: {
  7638. showAt: (apis, component, anchor, thing) => {
  7639. apis.showAt(component, anchor, thing);
  7640. },
  7641. showWithinBounds: (apis, component, anchor, thing, bounds) => {
  7642. apis.showWithinBounds(component, anchor, thing, bounds);
  7643. },
  7644. showMenuAt: (apis, component, anchor, menuSpec) => {
  7645. apis.showMenuAt(component, anchor, menuSpec);
  7646. },
  7647. showMenuWithinBounds: (apis, component, anchor, menuSpec, bounds) => {
  7648. apis.showMenuWithinBounds(component, anchor, menuSpec, bounds);
  7649. },
  7650. hide: (apis, component) => {
  7651. apis.hide(component);
  7652. },
  7653. isOpen: (apis, component) => apis.isOpen(component),
  7654. getContent: (apis, component) => apis.getContent(component),
  7655. setContent: (apis, component, thing) => {
  7656. apis.setContent(component, thing);
  7657. },
  7658. reposition: (apis, component) => {
  7659. apis.reposition(component);
  7660. }
  7661. }
  7662. });
  7663. var global$9 = tinymce.util.Tools.resolve('tinymce.util.Delay');
  7664. const factory$n = detail => {
  7665. const events = events$a(detail.action);
  7666. const tag = detail.dom.tag;
  7667. const lookupAttr = attr => get$g(detail.dom, 'attributes').bind(attrs => get$g(attrs, attr));
  7668. const getModAttributes = () => {
  7669. if (tag === 'button') {
  7670. const type = lookupAttr('type').getOr('button');
  7671. const roleAttrs = lookupAttr('role').map(role => ({ role })).getOr({});
  7672. return {
  7673. type,
  7674. ...roleAttrs
  7675. };
  7676. } else {
  7677. const role = detail.role.getOr(lookupAttr('role').getOr('button'));
  7678. return { role };
  7679. }
  7680. };
  7681. return {
  7682. uid: detail.uid,
  7683. dom: detail.dom,
  7684. components: detail.components,
  7685. events,
  7686. behaviours: SketchBehaviours.augment(detail.buttonBehaviours, [
  7687. Focusing.config({}),
  7688. Keying.config({
  7689. mode: 'execution',
  7690. useSpace: true,
  7691. useEnter: true
  7692. })
  7693. ]),
  7694. domModification: { attributes: getModAttributes() },
  7695. eventOrder: detail.eventOrder
  7696. };
  7697. };
  7698. const Button = single({
  7699. name: 'Button',
  7700. factory: factory$n,
  7701. configFields: [
  7702. defaulted('uid', undefined),
  7703. required$1('dom'),
  7704. defaulted('components', []),
  7705. SketchBehaviours.field('buttonBehaviours', [
  7706. Focusing,
  7707. Keying
  7708. ]),
  7709. option$3('action'),
  7710. option$3('role'),
  7711. defaulted('eventOrder', {})
  7712. ]
  7713. });
  7714. const record = spec => {
  7715. const uid = isSketchSpec(spec) && hasNonNullableKey(spec, 'uid') ? spec.uid : generate$5('memento');
  7716. const get = anyInSystem => anyInSystem.getSystem().getByUid(uid).getOrDie();
  7717. const getOpt = anyInSystem => anyInSystem.getSystem().getByUid(uid).toOptional();
  7718. const asSpec = () => ({
  7719. ...spec,
  7720. uid
  7721. });
  7722. return {
  7723. get,
  7724. getOpt,
  7725. asSpec
  7726. };
  7727. };
  7728. var global$8 = tinymce.util.Tools.resolve('tinymce.util.I18n');
  7729. const rtlTransform = {
  7730. 'indent': true,
  7731. 'outdent': true,
  7732. 'table-insert-column-after': true,
  7733. 'table-insert-column-before': true,
  7734. 'paste-column-after': true,
  7735. 'paste-column-before': true,
  7736. 'unordered-list': true,
  7737. 'list-bull-circle': true,
  7738. 'list-bull-default': true,
  7739. 'list-bull-square': true
  7740. };
  7741. const defaultIconName = 'temporary-placeholder';
  7742. const defaultIcon = icons => () => get$g(icons, defaultIconName).getOr('!not found!');
  7743. const getIconName = (name, icons) => {
  7744. const lcName = name.toLowerCase();
  7745. if (global$8.isRtl()) {
  7746. const rtlName = ensureTrailing(lcName, '-rtl');
  7747. return has$2(icons, rtlName) ? rtlName : lcName;
  7748. } else {
  7749. return lcName;
  7750. }
  7751. };
  7752. const lookupIcon = (name, icons) => get$g(icons, getIconName(name, icons));
  7753. const get$2 = (name, iconProvider) => {
  7754. const icons = iconProvider();
  7755. return lookupIcon(name, icons).getOrThunk(defaultIcon(icons));
  7756. };
  7757. const getOr = (name, iconProvider, fallbackIcon) => {
  7758. const icons = iconProvider();
  7759. return lookupIcon(name, icons).or(fallbackIcon).getOrThunk(defaultIcon(icons));
  7760. };
  7761. const needsRtlTransform = iconName => global$8.isRtl() ? has$2(rtlTransform, iconName) : false;
  7762. const addFocusableBehaviour = () => config('add-focusable', [runOnAttached(comp => {
  7763. child(comp.element, 'svg').each(svg => set$9(svg, 'focusable', 'false'));
  7764. })]);
  7765. const renderIcon$3 = (spec, iconName, icons, fallbackIcon) => {
  7766. var _a, _b;
  7767. const rtlIconClasses = needsRtlTransform(iconName) ? ['tox-icon--flip'] : [];
  7768. const iconHtml = get$g(icons, getIconName(iconName, icons)).or(fallbackIcon).getOrThunk(defaultIcon(icons));
  7769. return {
  7770. dom: {
  7771. tag: spec.tag,
  7772. attributes: (_a = spec.attributes) !== null && _a !== void 0 ? _a : {},
  7773. classes: spec.classes.concat(rtlIconClasses),
  7774. innerHtml: iconHtml
  7775. },
  7776. behaviours: derive$1([
  7777. ...(_b = spec.behaviours) !== null && _b !== void 0 ? _b : [],
  7778. addFocusableBehaviour()
  7779. ])
  7780. };
  7781. };
  7782. const render$3 = (iconName, spec, iconProvider, fallbackIcon = Optional.none()) => renderIcon$3(spec, iconName, iconProvider(), fallbackIcon);
  7783. const renderFirst = (iconNames, spec, iconProvider) => {
  7784. const icons = iconProvider();
  7785. const iconName = find$5(iconNames, name => has$2(icons, getIconName(name, icons)));
  7786. return renderIcon$3(spec, iconName.getOr(defaultIconName), icons, Optional.none());
  7787. };
  7788. const notificationIconMap = {
  7789. success: 'checkmark',
  7790. error: 'warning',
  7791. err: 'error',
  7792. warning: 'warning',
  7793. warn: 'warning',
  7794. info: 'info'
  7795. };
  7796. const factory$m = detail => {
  7797. const memBannerText = record({
  7798. dom: {
  7799. tag: 'p',
  7800. innerHtml: detail.translationProvider(detail.text)
  7801. },
  7802. behaviours: derive$1([Replacing.config({})])
  7803. });
  7804. const renderPercentBar = percent => ({
  7805. dom: {
  7806. tag: 'div',
  7807. classes: ['tox-bar'],
  7808. styles: { width: `${ percent }%` }
  7809. }
  7810. });
  7811. const renderPercentText = percent => ({
  7812. dom: {
  7813. tag: 'div',
  7814. classes: ['tox-text'],
  7815. innerHtml: `${ percent }%`
  7816. }
  7817. });
  7818. const memBannerProgress = record({
  7819. dom: {
  7820. tag: 'div',
  7821. classes: detail.progress ? [
  7822. 'tox-progress-bar',
  7823. 'tox-progress-indicator'
  7824. ] : ['tox-progress-bar']
  7825. },
  7826. components: [
  7827. {
  7828. dom: {
  7829. tag: 'div',
  7830. classes: ['tox-bar-container']
  7831. },
  7832. components: [renderPercentBar(0)]
  7833. },
  7834. renderPercentText(0)
  7835. ],
  7836. behaviours: derive$1([Replacing.config({})])
  7837. });
  7838. const updateProgress = (comp, percent) => {
  7839. if (comp.getSystem().isConnected()) {
  7840. memBannerProgress.getOpt(comp).each(progress => {
  7841. Replacing.set(progress, [
  7842. {
  7843. dom: {
  7844. tag: 'div',
  7845. classes: ['tox-bar-container']
  7846. },
  7847. components: [renderPercentBar(percent)]
  7848. },
  7849. renderPercentText(percent)
  7850. ]);
  7851. });
  7852. }
  7853. };
  7854. const updateText = (comp, text) => {
  7855. if (comp.getSystem().isConnected()) {
  7856. const banner = memBannerText.get(comp);
  7857. Replacing.set(banner, [text$2(text)]);
  7858. }
  7859. };
  7860. const apis = {
  7861. updateProgress,
  7862. updateText
  7863. };
  7864. const iconChoices = flatten([
  7865. detail.icon.toArray(),
  7866. detail.level.toArray(),
  7867. detail.level.bind(level => Optional.from(notificationIconMap[level])).toArray()
  7868. ]);
  7869. const memButton = record(Button.sketch({
  7870. dom: {
  7871. tag: 'button',
  7872. classes: [
  7873. 'tox-notification__dismiss',
  7874. 'tox-button',
  7875. 'tox-button--naked',
  7876. 'tox-button--icon'
  7877. ]
  7878. },
  7879. components: [render$3('close', {
  7880. tag: 'div',
  7881. classes: ['tox-icon'],
  7882. attributes: { 'aria-label': detail.translationProvider('Close') }
  7883. }, detail.iconProvider)],
  7884. action: comp => {
  7885. detail.onAction(comp);
  7886. }
  7887. }));
  7888. const notificationIconSpec = renderFirst(iconChoices, {
  7889. tag: 'div',
  7890. classes: ['tox-notification__icon']
  7891. }, detail.iconProvider);
  7892. const notificationBodySpec = {
  7893. dom: {
  7894. tag: 'div',
  7895. classes: ['tox-notification__body']
  7896. },
  7897. components: [memBannerText.asSpec()],
  7898. behaviours: derive$1([Replacing.config({})])
  7899. };
  7900. const components = [
  7901. notificationIconSpec,
  7902. notificationBodySpec
  7903. ];
  7904. return {
  7905. uid: detail.uid,
  7906. dom: {
  7907. tag: 'div',
  7908. attributes: { role: 'alert' },
  7909. classes: detail.level.map(level => [
  7910. 'tox-notification',
  7911. 'tox-notification--in',
  7912. `tox-notification--${ level }`
  7913. ]).getOr([
  7914. 'tox-notification',
  7915. 'tox-notification--in'
  7916. ])
  7917. },
  7918. behaviours: derive$1([
  7919. Focusing.config({}),
  7920. config('notification-events', [run$1(focusin(), comp => {
  7921. memButton.getOpt(comp).each(Focusing.focus);
  7922. })])
  7923. ]),
  7924. components: components.concat(detail.progress ? [memBannerProgress.asSpec()] : []).concat(!detail.closeButton ? [] : [memButton.asSpec()]),
  7925. apis
  7926. };
  7927. };
  7928. const Notification = single({
  7929. name: 'Notification',
  7930. factory: factory$m,
  7931. configFields: [
  7932. option$3('level'),
  7933. required$1('progress'),
  7934. option$3('icon'),
  7935. required$1('onAction'),
  7936. required$1('text'),
  7937. required$1('iconProvider'),
  7938. required$1('translationProvider'),
  7939. defaultedBoolean('closeButton', true)
  7940. ],
  7941. apis: {
  7942. updateProgress: (apis, comp, percent) => {
  7943. apis.updateProgress(comp, percent);
  7944. },
  7945. updateText: (apis, comp, text) => {
  7946. apis.updateText(comp, text);
  7947. }
  7948. }
  7949. });
  7950. var NotificationManagerImpl = (editor, extras, uiMothership) => {
  7951. const sharedBackstage = extras.backstage.shared;
  7952. const getBounds = () => {
  7953. const contentArea = box$1(SugarElement.fromDom(editor.getContentAreaContainer()));
  7954. const win$1 = win();
  7955. const x = clamp(win$1.x, contentArea.x, contentArea.right);
  7956. const y = clamp(win$1.y, contentArea.y, contentArea.bottom);
  7957. const right = Math.max(contentArea.right, win$1.right);
  7958. const bottom = Math.max(contentArea.bottom, win$1.bottom);
  7959. return Optional.some(bounds(x, y, right - x, bottom - y));
  7960. };
  7961. const open = (settings, closeCallback) => {
  7962. const close = () => {
  7963. closeCallback();
  7964. InlineView.hide(notificationWrapper);
  7965. };
  7966. const notification = build$1(Notification.sketch({
  7967. text: settings.text,
  7968. level: contains$2([
  7969. 'success',
  7970. 'error',
  7971. 'warning',
  7972. 'warn',
  7973. 'info'
  7974. ], settings.type) ? settings.type : undefined,
  7975. progress: settings.progressBar === true,
  7976. icon: settings.icon,
  7977. closeButton: settings.closeButton,
  7978. onAction: close,
  7979. iconProvider: sharedBackstage.providers.icons,
  7980. translationProvider: sharedBackstage.providers.translate
  7981. }));
  7982. const notificationWrapper = build$1(InlineView.sketch({
  7983. dom: {
  7984. tag: 'div',
  7985. classes: ['tox-notifications-container']
  7986. },
  7987. lazySink: sharedBackstage.getSink,
  7988. fireDismissalEventInstead: {},
  7989. ...sharedBackstage.header.isPositionedAtTop() ? {} : { fireRepositionEventInstead: {} }
  7990. }));
  7991. uiMothership.add(notificationWrapper);
  7992. if (isNumber(settings.timeout) && settings.timeout > 0) {
  7993. global$9.setEditorTimeout(editor, () => {
  7994. close();
  7995. }, settings.timeout);
  7996. }
  7997. const reposition = () => {
  7998. const notificationSpec = premade(notification);
  7999. const anchorOverrides = { maxHeightFunction: expandable$1() };
  8000. const allNotifications = editor.notificationManager.getNotifications();
  8001. if (allNotifications[0] === thisNotification) {
  8002. const anchor = {
  8003. ...sharedBackstage.anchors.banner(),
  8004. overrides: anchorOverrides
  8005. };
  8006. InlineView.showWithinBounds(notificationWrapper, notificationSpec, { anchor }, getBounds);
  8007. } else {
  8008. indexOf(allNotifications, thisNotification).each(idx => {
  8009. const previousNotification = allNotifications[idx - 1].getEl();
  8010. const nodeAnchor = {
  8011. type: 'node',
  8012. root: body(),
  8013. node: Optional.some(SugarElement.fromDom(previousNotification)),
  8014. overrides: anchorOverrides,
  8015. layouts: {
  8016. onRtl: () => [south$2],
  8017. onLtr: () => [south$2]
  8018. }
  8019. };
  8020. InlineView.showWithinBounds(notificationWrapper, notificationSpec, { anchor: nodeAnchor }, getBounds);
  8021. });
  8022. }
  8023. };
  8024. const thisNotification = {
  8025. close,
  8026. reposition,
  8027. text: nuText => {
  8028. Notification.updateText(notification, nuText);
  8029. },
  8030. settings,
  8031. getEl: () => notification.element.dom,
  8032. progressBar: {
  8033. value: percent => {
  8034. Notification.updateProgress(notification, percent);
  8035. }
  8036. }
  8037. };
  8038. return thisNotification;
  8039. };
  8040. const close = notification => {
  8041. notification.close();
  8042. };
  8043. const getArgs = notification => {
  8044. return notification.settings;
  8045. };
  8046. return {
  8047. open,
  8048. close,
  8049. getArgs
  8050. };
  8051. };
  8052. var global$7 = tinymce.util.Tools.resolve('tinymce.dom.DOMUtils');
  8053. var global$6 = tinymce.util.Tools.resolve('tinymce.EditorManager');
  8054. var global$5 = tinymce.util.Tools.resolve('tinymce.Env');
  8055. var ToolbarMode$1;
  8056. (function (ToolbarMode) {
  8057. ToolbarMode['default'] = 'wrap';
  8058. ToolbarMode['floating'] = 'floating';
  8059. ToolbarMode['sliding'] = 'sliding';
  8060. ToolbarMode['scrolling'] = 'scrolling';
  8061. }(ToolbarMode$1 || (ToolbarMode$1 = {})));
  8062. var ToolbarLocation$1;
  8063. (function (ToolbarLocation) {
  8064. ToolbarLocation['auto'] = 'auto';
  8065. ToolbarLocation['top'] = 'top';
  8066. ToolbarLocation['bottom'] = 'bottom';
  8067. }(ToolbarLocation$1 || (ToolbarLocation$1 = {})));
  8068. const option$2 = name => editor => editor.options.get(name);
  8069. const wrapOptional = fn => editor => Optional.from(fn(editor));
  8070. const register$e = editor => {
  8071. const isPhone = global$5.deviceType.isPhone();
  8072. const isMobile = global$5.deviceType.isTablet() || isPhone;
  8073. const registerOption = editor.options.register;
  8074. const stringOrFalseProcessor = value => isString(value) || value === false;
  8075. const stringOrNumberProcessor = value => isString(value) || isNumber(value);
  8076. registerOption('skin', {
  8077. processor: value => isString(value) || value === false,
  8078. default: 'oxide'
  8079. });
  8080. registerOption('skin_url', { processor: 'string' });
  8081. registerOption('height', {
  8082. processor: stringOrNumberProcessor,
  8083. default: Math.max(editor.getElement().offsetHeight, 400)
  8084. });
  8085. registerOption('width', {
  8086. processor: stringOrNumberProcessor,
  8087. default: global$7.DOM.getStyle(editor.getElement(), 'width')
  8088. });
  8089. registerOption('min_height', {
  8090. processor: 'number',
  8091. default: 100
  8092. });
  8093. registerOption('min_width', { processor: 'number' });
  8094. registerOption('max_height', { processor: 'number' });
  8095. registerOption('max_width', { processor: 'number' });
  8096. registerOption('style_formats', { processor: 'object[]' });
  8097. registerOption('style_formats_merge', {
  8098. processor: 'boolean',
  8099. default: false
  8100. });
  8101. registerOption('style_formats_autohide', {
  8102. processor: 'boolean',
  8103. default: false
  8104. });
  8105. registerOption('line_height_formats', {
  8106. processor: 'string',
  8107. default: '1 1.1 1.2 1.3 1.4 1.5 2'
  8108. });
  8109. registerOption('font_family_formats', {
  8110. processor: 'string',
  8111. 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'
  8112. });
  8113. registerOption('font_size_formats', {
  8114. processor: 'string',
  8115. default: '8pt 10pt 12pt 14pt 18pt 24pt 36pt'
  8116. });
  8117. registerOption('font_size_input_default_unit', {
  8118. processor: 'string',
  8119. default: 'pt'
  8120. });
  8121. registerOption('block_formats', {
  8122. processor: 'string',
  8123. default: 'Paragraph=p;' + 'Heading 1=h1;' + 'Heading 2=h2;' + 'Heading 3=h3;' + 'Heading 4=h4;' + 'Heading 5=h5;' + 'Heading 6=h6;' + 'Preformatted=pre'
  8124. });
  8125. registerOption('content_langs', { processor: 'object[]' });
  8126. registerOption('removed_menuitems', {
  8127. processor: 'string',
  8128. default: ''
  8129. });
  8130. registerOption('menubar', {
  8131. processor: value => isString(value) || isBoolean(value),
  8132. default: !isPhone
  8133. });
  8134. registerOption('menu', {
  8135. processor: 'object',
  8136. default: {}
  8137. });
  8138. registerOption('toolbar', {
  8139. processor: value => {
  8140. if (isBoolean(value) || isString(value) || isArray(value)) {
  8141. return {
  8142. value,
  8143. valid: true
  8144. };
  8145. } else {
  8146. return {
  8147. valid: false,
  8148. message: 'Must be a boolean, string or array.'
  8149. };
  8150. }
  8151. },
  8152. default: true
  8153. });
  8154. range$2(9, num => {
  8155. registerOption('toolbar' + (num + 1), { processor: 'string' });
  8156. });
  8157. registerOption('toolbar_mode', {
  8158. processor: 'string',
  8159. default: isMobile ? 'scrolling' : 'floating'
  8160. });
  8161. registerOption('toolbar_groups', {
  8162. processor: 'object',
  8163. default: {}
  8164. });
  8165. registerOption('toolbar_location', {
  8166. processor: 'string',
  8167. default: ToolbarLocation$1.auto
  8168. });
  8169. registerOption('toolbar_persist', {
  8170. processor: 'boolean',
  8171. default: false
  8172. });
  8173. registerOption('toolbar_sticky', {
  8174. processor: 'boolean',
  8175. default: editor.inline
  8176. });
  8177. registerOption('toolbar_sticky_offset', {
  8178. processor: 'number',
  8179. default: 0
  8180. });
  8181. registerOption('fixed_toolbar_container', {
  8182. processor: 'string',
  8183. default: ''
  8184. });
  8185. registerOption('fixed_toolbar_container_target', { processor: 'object' });
  8186. registerOption('ui_mode', {
  8187. processor: 'string',
  8188. default: 'combined'
  8189. });
  8190. registerOption('file_picker_callback', { processor: 'function' });
  8191. registerOption('file_picker_validator_handler', { processor: 'function' });
  8192. registerOption('file_picker_types', { processor: 'string' });
  8193. registerOption('typeahead_urls', {
  8194. processor: 'boolean',
  8195. default: true
  8196. });
  8197. registerOption('anchor_top', {
  8198. processor: stringOrFalseProcessor,
  8199. default: '#top'
  8200. });
  8201. registerOption('anchor_bottom', {
  8202. processor: stringOrFalseProcessor,
  8203. default: '#bottom'
  8204. });
  8205. registerOption('draggable_modal', {
  8206. processor: 'boolean',
  8207. default: false
  8208. });
  8209. registerOption('statusbar', {
  8210. processor: 'boolean',
  8211. default: true
  8212. });
  8213. registerOption('elementpath', {
  8214. processor: 'boolean',
  8215. default: true
  8216. });
  8217. registerOption('branding', {
  8218. processor: 'boolean',
  8219. default: true
  8220. });
  8221. registerOption('promotion', {
  8222. processor: 'boolean',
  8223. default: true
  8224. });
  8225. registerOption('resize', {
  8226. processor: value => value === 'both' || isBoolean(value),
  8227. default: !global$5.deviceType.isTouch()
  8228. });
  8229. registerOption('sidebar_show', { processor: 'string' });
  8230. };
  8231. const isReadOnly = option$2('readonly');
  8232. const getHeightOption = option$2('height');
  8233. const getWidthOption = option$2('width');
  8234. const getMinWidthOption = wrapOptional(option$2('min_width'));
  8235. const getMinHeightOption = wrapOptional(option$2('min_height'));
  8236. const getMaxWidthOption = wrapOptional(option$2('max_width'));
  8237. const getMaxHeightOption = wrapOptional(option$2('max_height'));
  8238. const getUserStyleFormats = wrapOptional(option$2('style_formats'));
  8239. const shouldMergeStyleFormats = option$2('style_formats_merge');
  8240. const shouldAutoHideStyleFormats = option$2('style_formats_autohide');
  8241. const getContentLanguages = option$2('content_langs');
  8242. const getRemovedMenuItems = option$2('removed_menuitems');
  8243. const getToolbarMode = option$2('toolbar_mode');
  8244. const getToolbarGroups = option$2('toolbar_groups');
  8245. const getToolbarLocation = option$2('toolbar_location');
  8246. const fixedContainerSelector = option$2('fixed_toolbar_container');
  8247. const fixedToolbarContainerTarget = option$2('fixed_toolbar_container_target');
  8248. const isToolbarPersist = option$2('toolbar_persist');
  8249. const getStickyToolbarOffset = option$2('toolbar_sticky_offset');
  8250. const getMenubar = option$2('menubar');
  8251. const getToolbar = option$2('toolbar');
  8252. const getFilePickerCallback = option$2('file_picker_callback');
  8253. const getFilePickerValidatorHandler = option$2('file_picker_validator_handler');
  8254. const getFontSizeInputDefaultUnit = option$2('font_size_input_default_unit');
  8255. const getFilePickerTypes = option$2('file_picker_types');
  8256. const useTypeaheadUrls = option$2('typeahead_urls');
  8257. const getAnchorTop = option$2('anchor_top');
  8258. const getAnchorBottom = option$2('anchor_bottom');
  8259. const isDraggableModal$1 = option$2('draggable_modal');
  8260. const useStatusBar = option$2('statusbar');
  8261. const useElementPath = option$2('elementpath');
  8262. const useBranding = option$2('branding');
  8263. const getResize = option$2('resize');
  8264. const getPasteAsText = option$2('paste_as_text');
  8265. const getSidebarShow = option$2('sidebar_show');
  8266. const promotionEnabled = option$2('promotion');
  8267. const isSkinDisabled = editor => editor.options.get('skin') === false;
  8268. const isMenubarEnabled = editor => editor.options.get('menubar') !== false;
  8269. const getSkinUrl = editor => {
  8270. const skinUrl = editor.options.get('skin_url');
  8271. if (isSkinDisabled(editor)) {
  8272. return skinUrl;
  8273. } else {
  8274. if (skinUrl) {
  8275. return editor.documentBaseURI.toAbsolute(skinUrl);
  8276. } else {
  8277. const skin = editor.options.get('skin');
  8278. return global$6.baseURL + '/skins/ui/' + skin;
  8279. }
  8280. }
  8281. };
  8282. const getLineHeightFormats = editor => editor.options.get('line_height_formats').split(' ');
  8283. const isToolbarEnabled = editor => {
  8284. const toolbar = getToolbar(editor);
  8285. const isToolbarString = isString(toolbar);
  8286. const isToolbarObjectArray = isArray(toolbar) && toolbar.length > 0;
  8287. return !isMultipleToolbars(editor) && (isToolbarObjectArray || isToolbarString || toolbar === true);
  8288. };
  8289. const getMultipleToolbarsOption = editor => {
  8290. const toolbars = range$2(9, num => editor.options.get('toolbar' + (num + 1)));
  8291. const toolbarArray = filter$2(toolbars, isString);
  8292. return someIf(toolbarArray.length > 0, toolbarArray);
  8293. };
  8294. const isMultipleToolbars = editor => getMultipleToolbarsOption(editor).fold(() => {
  8295. const toolbar = getToolbar(editor);
  8296. return isArrayOf(toolbar, isString) && toolbar.length > 0;
  8297. }, always);
  8298. const isToolbarLocationBottom = editor => getToolbarLocation(editor) === ToolbarLocation$1.bottom;
  8299. const fixedContainerTarget = editor => {
  8300. var _a;
  8301. if (!editor.inline) {
  8302. return Optional.none();
  8303. }
  8304. const selector = (_a = fixedContainerSelector(editor)) !== null && _a !== void 0 ? _a : '';
  8305. if (selector.length > 0) {
  8306. return descendant(body(), selector);
  8307. }
  8308. const element = fixedToolbarContainerTarget(editor);
  8309. if (isNonNullable(element)) {
  8310. return Optional.some(SugarElement.fromDom(element));
  8311. }
  8312. return Optional.none();
  8313. };
  8314. const useFixedContainer = editor => editor.inline && fixedContainerTarget(editor).isSome();
  8315. const getUiContainer = editor => {
  8316. const fixedContainer = fixedContainerTarget(editor);
  8317. return fixedContainer.getOrThunk(() => getContentContainer(getRootNode(SugarElement.fromDom(editor.getElement()))));
  8318. };
  8319. const isDistractionFree = editor => editor.inline && !isMenubarEnabled(editor) && !isToolbarEnabled(editor) && !isMultipleToolbars(editor);
  8320. const isStickyToolbar = editor => {
  8321. const isStickyToolbar = editor.options.get('toolbar_sticky');
  8322. return (isStickyToolbar || editor.inline) && !useFixedContainer(editor) && !isDistractionFree(editor);
  8323. };
  8324. const isSplitUiMode = editor => !useFixedContainer(editor) && editor.options.get('ui_mode') === 'split';
  8325. const getMenus = editor => {
  8326. const menu = editor.options.get('menu');
  8327. return map$1(menu, menu => ({
  8328. ...menu,
  8329. items: menu.items
  8330. }));
  8331. };
  8332. var Options = /*#__PURE__*/Object.freeze({
  8333. __proto__: null,
  8334. get ToolbarMode () { return ToolbarMode$1; },
  8335. get ToolbarLocation () { return ToolbarLocation$1; },
  8336. register: register$e,
  8337. getSkinUrl: getSkinUrl,
  8338. isReadOnly: isReadOnly,
  8339. isSkinDisabled: isSkinDisabled,
  8340. getHeightOption: getHeightOption,
  8341. getWidthOption: getWidthOption,
  8342. getMinWidthOption: getMinWidthOption,
  8343. getMinHeightOption: getMinHeightOption,
  8344. getMaxWidthOption: getMaxWidthOption,
  8345. getMaxHeightOption: getMaxHeightOption,
  8346. getUserStyleFormats: getUserStyleFormats,
  8347. shouldMergeStyleFormats: shouldMergeStyleFormats,
  8348. shouldAutoHideStyleFormats: shouldAutoHideStyleFormats,
  8349. getLineHeightFormats: getLineHeightFormats,
  8350. getContentLanguages: getContentLanguages,
  8351. getRemovedMenuItems: getRemovedMenuItems,
  8352. isMenubarEnabled: isMenubarEnabled,
  8353. isMultipleToolbars: isMultipleToolbars,
  8354. isToolbarEnabled: isToolbarEnabled,
  8355. isToolbarPersist: isToolbarPersist,
  8356. getMultipleToolbarsOption: getMultipleToolbarsOption,
  8357. getUiContainer: getUiContainer,
  8358. useFixedContainer: useFixedContainer,
  8359. isSplitUiMode: isSplitUiMode,
  8360. getToolbarMode: getToolbarMode,
  8361. isDraggableModal: isDraggableModal$1,
  8362. isDistractionFree: isDistractionFree,
  8363. isStickyToolbar: isStickyToolbar,
  8364. getStickyToolbarOffset: getStickyToolbarOffset,
  8365. getToolbarLocation: getToolbarLocation,
  8366. isToolbarLocationBottom: isToolbarLocationBottom,
  8367. getToolbarGroups: getToolbarGroups,
  8368. getMenus: getMenus,
  8369. getMenubar: getMenubar,
  8370. getToolbar: getToolbar,
  8371. getFilePickerCallback: getFilePickerCallback,
  8372. getFilePickerTypes: getFilePickerTypes,
  8373. useTypeaheadUrls: useTypeaheadUrls,
  8374. getAnchorTop: getAnchorTop,
  8375. getAnchorBottom: getAnchorBottom,
  8376. getFilePickerValidatorHandler: getFilePickerValidatorHandler,
  8377. getFontSizeInputDefaultUnit: getFontSizeInputDefaultUnit,
  8378. useStatusBar: useStatusBar,
  8379. useElementPath: useElementPath,
  8380. promotionEnabled: promotionEnabled,
  8381. useBranding: useBranding,
  8382. getResize: getResize,
  8383. getPasteAsText: getPasteAsText,
  8384. getSidebarShow: getSidebarShow
  8385. });
  8386. const autocompleteSelector = '[data-mce-autocompleter]';
  8387. const detect$1 = elm => closest$1(elm, autocompleteSelector);
  8388. const findIn = elm => descendant(elm, autocompleteSelector);
  8389. const setup$e = (api, editor) => {
  8390. const redirectKeyToItem = (item, e) => {
  8391. emitWith(item, keydown(), { raw: e });
  8392. };
  8393. const getItem = () => api.getMenu().bind(Highlighting.getHighlighted);
  8394. editor.on('keydown', e => {
  8395. const keyCode = e.which;
  8396. if (!api.isActive()) {
  8397. return;
  8398. }
  8399. if (api.isMenuOpen()) {
  8400. if (keyCode === 13) {
  8401. getItem().each(emitExecute);
  8402. e.preventDefault();
  8403. } else if (keyCode === 40) {
  8404. getItem().fold(() => {
  8405. api.getMenu().each(Highlighting.highlightFirst);
  8406. }, item => {
  8407. redirectKeyToItem(item, e);
  8408. });
  8409. e.preventDefault();
  8410. e.stopImmediatePropagation();
  8411. } else if (keyCode === 37 || keyCode === 38 || keyCode === 39) {
  8412. getItem().each(item => {
  8413. redirectKeyToItem(item, e);
  8414. e.preventDefault();
  8415. e.stopImmediatePropagation();
  8416. });
  8417. }
  8418. } else {
  8419. if (keyCode === 13 || keyCode === 38 || keyCode === 40) {
  8420. api.cancelIfNecessary();
  8421. }
  8422. }
  8423. });
  8424. editor.on('NodeChange', e => {
  8425. if (api.isActive() && !api.isProcessingAction() && detect$1(SugarElement.fromDom(e.element)).isNone()) {
  8426. api.cancelIfNecessary();
  8427. }
  8428. });
  8429. };
  8430. const AutocompleterEditorEvents = { setup: setup$e };
  8431. var ItemResponse;
  8432. (function (ItemResponse) {
  8433. ItemResponse[ItemResponse['CLOSE_ON_EXECUTE'] = 0] = 'CLOSE_ON_EXECUTE';
  8434. ItemResponse[ItemResponse['BUBBLE_TO_SANDBOX'] = 1] = 'BUBBLE_TO_SANDBOX';
  8435. }(ItemResponse || (ItemResponse = {})));
  8436. var ItemResponse$1 = ItemResponse;
  8437. const navClass = 'tox-menu-nav__js';
  8438. const selectableClass = 'tox-collection__item';
  8439. const colorClass = 'tox-swatch';
  8440. const presetClasses = {
  8441. normal: navClass,
  8442. color: colorClass
  8443. };
  8444. const tickedClass = 'tox-collection__item--enabled';
  8445. const groupHeadingClass = 'tox-collection__group-heading';
  8446. const iconClass = 'tox-collection__item-icon';
  8447. const textClass = 'tox-collection__item-label';
  8448. const accessoryClass = 'tox-collection__item-accessory';
  8449. const caretClass = 'tox-collection__item-caret';
  8450. const checkmarkClass = 'tox-collection__item-checkmark';
  8451. const activeClass = 'tox-collection__item--active';
  8452. const containerClass = 'tox-collection__item-container';
  8453. const containerColumnClass = 'tox-collection__item-container--column';
  8454. const containerRowClass = 'tox-collection__item-container--row';
  8455. const containerAlignRightClass = 'tox-collection__item-container--align-right';
  8456. const containerAlignLeftClass = 'tox-collection__item-container--align-left';
  8457. const containerValignTopClass = 'tox-collection__item-container--valign-top';
  8458. const containerValignMiddleClass = 'tox-collection__item-container--valign-middle';
  8459. const containerValignBottomClass = 'tox-collection__item-container--valign-bottom';
  8460. const classForPreset = presets => get$g(presetClasses, presets).getOr(navClass);
  8461. const forMenu = presets => {
  8462. if (presets === 'color') {
  8463. return 'tox-swatches';
  8464. } else {
  8465. return 'tox-menu';
  8466. }
  8467. };
  8468. const classes = presets => ({
  8469. backgroundMenu: 'tox-background-menu',
  8470. selectedMenu: 'tox-selected-menu',
  8471. selectedItem: 'tox-collection__item--active',
  8472. hasIcons: 'tox-menu--has-icons',
  8473. menu: forMenu(presets),
  8474. tieredMenu: 'tox-tiered-menu'
  8475. });
  8476. const markers = presets => {
  8477. const menuClasses = classes(presets);
  8478. return {
  8479. backgroundMenu: menuClasses.backgroundMenu,
  8480. selectedMenu: menuClasses.selectedMenu,
  8481. menu: menuClasses.menu,
  8482. selectedItem: menuClasses.selectedItem,
  8483. item: classForPreset(presets)
  8484. };
  8485. };
  8486. const dom$1 = (hasIcons, columns, presets) => {
  8487. const menuClasses = classes(presets);
  8488. return {
  8489. tag: 'div',
  8490. classes: flatten([
  8491. [
  8492. menuClasses.menu,
  8493. `tox-menu-${ columns }-column`
  8494. ],
  8495. hasIcons ? [menuClasses.hasIcons] : []
  8496. ])
  8497. };
  8498. };
  8499. const components = [Menu.parts.items({})];
  8500. const part = (hasIcons, columns, presets) => {
  8501. const menuClasses = classes(presets);
  8502. const d = {
  8503. tag: 'div',
  8504. classes: flatten([[menuClasses.tieredMenu]])
  8505. };
  8506. return {
  8507. dom: d,
  8508. markers: markers(presets)
  8509. };
  8510. };
  8511. const schema$l = constant$1([
  8512. option$3('data'),
  8513. defaulted('inputAttributes', {}),
  8514. defaulted('inputStyles', {}),
  8515. defaulted('tag', 'input'),
  8516. defaulted('inputClasses', []),
  8517. onHandler('onSetValue'),
  8518. defaulted('styles', {}),
  8519. defaulted('eventOrder', {}),
  8520. field('inputBehaviours', [
  8521. Representing,
  8522. Focusing
  8523. ]),
  8524. defaulted('selectOnFocus', true)
  8525. ]);
  8526. const focusBehaviours = detail => derive$1([Focusing.config({
  8527. onFocus: !detail.selectOnFocus ? noop : component => {
  8528. const input = component.element;
  8529. const value = get$6(input);
  8530. input.dom.setSelectionRange(0, value.length);
  8531. }
  8532. })]);
  8533. const behaviours = detail => ({
  8534. ...focusBehaviours(detail),
  8535. ...augment(detail.inputBehaviours, [Representing.config({
  8536. store: {
  8537. mode: 'manual',
  8538. ...detail.data.map(data => ({ initialValue: data })).getOr({}),
  8539. getValue: input => {
  8540. return get$6(input.element);
  8541. },
  8542. setValue: (input, data) => {
  8543. const current = get$6(input.element);
  8544. if (current !== data) {
  8545. set$5(input.element, data);
  8546. }
  8547. }
  8548. },
  8549. onSetValue: detail.onSetValue
  8550. })])
  8551. });
  8552. const dom = detail => ({
  8553. tag: detail.tag,
  8554. attributes: {
  8555. type: 'text',
  8556. ...detail.inputAttributes
  8557. },
  8558. styles: detail.inputStyles,
  8559. classes: detail.inputClasses
  8560. });
  8561. const factory$l = (detail, _spec) => ({
  8562. uid: detail.uid,
  8563. dom: dom(detail),
  8564. components: [],
  8565. behaviours: behaviours(detail),
  8566. eventOrder: detail.eventOrder
  8567. });
  8568. const Input = single({
  8569. name: 'Input',
  8570. configFields: schema$l(),
  8571. factory: factory$l
  8572. });
  8573. const refetchTriggerEvent = generate$6('refetch-trigger-event');
  8574. const redirectMenuItemInteractionEvent = generate$6('redirect-menu-item-interaction');
  8575. const menuSearcherClass = 'tox-menu__searcher';
  8576. const findWithinSandbox = sandboxComp => {
  8577. return descendant(sandboxComp.element, `.${ menuSearcherClass }`).bind(inputElem => sandboxComp.getSystem().getByDom(inputElem).toOptional());
  8578. };
  8579. const findWithinMenu = findWithinSandbox;
  8580. const restoreState = (inputComp, searcherState) => {
  8581. Representing.setValue(inputComp, searcherState.fetchPattern);
  8582. inputComp.element.dom.selectionStart = searcherState.selectionStart;
  8583. inputComp.element.dom.selectionEnd = searcherState.selectionEnd;
  8584. };
  8585. const saveState = inputComp => {
  8586. const fetchPattern = Representing.getValue(inputComp);
  8587. const selectionStart = inputComp.element.dom.selectionStart;
  8588. const selectionEnd = inputComp.element.dom.selectionEnd;
  8589. return {
  8590. fetchPattern,
  8591. selectionStart,
  8592. selectionEnd
  8593. };
  8594. };
  8595. const setActiveDescendant = (inputComp, active) => {
  8596. getOpt(active.element, 'id').each(id => set$9(inputComp.element, 'aria-activedescendant', id));
  8597. };
  8598. const renderMenuSearcher = spec => {
  8599. const handleByBrowser = (comp, se) => {
  8600. se.cut();
  8601. return Optional.none();
  8602. };
  8603. const handleByHighlightedItem = (comp, se) => {
  8604. const eventData = {
  8605. interactionEvent: se.event,
  8606. eventType: se.event.raw.type
  8607. };
  8608. emitWith(comp, redirectMenuItemInteractionEvent, eventData);
  8609. return Optional.some(true);
  8610. };
  8611. const customSearcherEventsName = 'searcher-events';
  8612. return {
  8613. dom: {
  8614. tag: 'div',
  8615. classes: [selectableClass]
  8616. },
  8617. components: [Input.sketch({
  8618. inputClasses: [
  8619. menuSearcherClass,
  8620. 'tox-textfield'
  8621. ],
  8622. inputAttributes: {
  8623. ...spec.placeholder.map(placeholder => ({ placeholder: spec.i18n(placeholder) })).getOr({}),
  8624. 'type': 'search',
  8625. 'aria-autocomplete': 'list'
  8626. },
  8627. inputBehaviours: derive$1([
  8628. config(customSearcherEventsName, [
  8629. run$1(input(), inputComp => {
  8630. emit(inputComp, refetchTriggerEvent);
  8631. }),
  8632. run$1(keydown(), (inputComp, se) => {
  8633. if (se.event.raw.key === 'Escape') {
  8634. se.stop();
  8635. }
  8636. })
  8637. ]),
  8638. Keying.config({
  8639. mode: 'special',
  8640. onLeft: handleByBrowser,
  8641. onRight: handleByBrowser,
  8642. onSpace: handleByBrowser,
  8643. onEnter: handleByHighlightedItem,
  8644. onEscape: handleByHighlightedItem,
  8645. onUp: handleByHighlightedItem,
  8646. onDown: handleByHighlightedItem
  8647. })
  8648. ]),
  8649. eventOrder: {
  8650. keydown: [
  8651. customSearcherEventsName,
  8652. Keying.name()
  8653. ]
  8654. }
  8655. })]
  8656. };
  8657. };
  8658. const searchResultsClass = 'tox-collection--results__js';
  8659. const augmentWithAria = item => {
  8660. var _a;
  8661. if (item.dom) {
  8662. return {
  8663. ...item,
  8664. dom: {
  8665. ...item.dom,
  8666. attributes: {
  8667. ...(_a = item.dom.attributes) !== null && _a !== void 0 ? _a : {},
  8668. 'id': generate$6('aria-item-search-result-id'),
  8669. 'aria-selected': 'false'
  8670. }
  8671. }
  8672. };
  8673. } else {
  8674. return item;
  8675. }
  8676. };
  8677. const chunk = (rowDom, numColumns) => items => {
  8678. const chunks = chunk$1(items, numColumns);
  8679. return map$2(chunks, c => ({
  8680. dom: rowDom,
  8681. components: c
  8682. }));
  8683. };
  8684. const forSwatch = columns => ({
  8685. dom: {
  8686. tag: 'div',
  8687. classes: [
  8688. 'tox-menu',
  8689. 'tox-swatches-menu'
  8690. ]
  8691. },
  8692. components: [{
  8693. dom: {
  8694. tag: 'div',
  8695. classes: ['tox-swatches']
  8696. },
  8697. components: [Menu.parts.items({
  8698. preprocess: columns !== 'auto' ? chunk({
  8699. tag: 'div',
  8700. classes: ['tox-swatches__row']
  8701. }, columns) : identity
  8702. })]
  8703. }]
  8704. });
  8705. const forToolbar = columns => ({
  8706. dom: {
  8707. tag: 'div',
  8708. classes: [
  8709. 'tox-menu',
  8710. 'tox-collection',
  8711. 'tox-collection--toolbar',
  8712. 'tox-collection--toolbar-lg'
  8713. ]
  8714. },
  8715. components: [Menu.parts.items({
  8716. preprocess: chunk({
  8717. tag: 'div',
  8718. classes: ['tox-collection__group']
  8719. }, columns)
  8720. })]
  8721. });
  8722. const preprocessCollection = (items, isSeparator) => {
  8723. const allSplits = [];
  8724. let currentSplit = [];
  8725. each$1(items, (item, i) => {
  8726. if (isSeparator(item, i)) {
  8727. if (currentSplit.length > 0) {
  8728. allSplits.push(currentSplit);
  8729. }
  8730. currentSplit = [];
  8731. if (has$2(item.dom, 'innerHtml') || item.components && item.components.length > 0) {
  8732. currentSplit.push(item);
  8733. }
  8734. } else {
  8735. currentSplit.push(item);
  8736. }
  8737. });
  8738. if (currentSplit.length > 0) {
  8739. allSplits.push(currentSplit);
  8740. }
  8741. return map$2(allSplits, s => ({
  8742. dom: {
  8743. tag: 'div',
  8744. classes: ['tox-collection__group']
  8745. },
  8746. components: s
  8747. }));
  8748. };
  8749. const insertItemsPlaceholder = (columns, initItems, onItem) => {
  8750. return Menu.parts.items({
  8751. preprocess: rawItems => {
  8752. const enrichedItems = map$2(rawItems, onItem);
  8753. if (columns !== 'auto' && columns > 1) {
  8754. return chunk({
  8755. tag: 'div',
  8756. classes: ['tox-collection__group']
  8757. }, columns)(enrichedItems);
  8758. } else {
  8759. return preprocessCollection(enrichedItems, (_item, i) => initItems[i].type === 'separator');
  8760. }
  8761. }
  8762. });
  8763. };
  8764. const forCollection = (columns, initItems, _hasIcons = true) => ({
  8765. dom: {
  8766. tag: 'div',
  8767. classes: [
  8768. 'tox-menu',
  8769. 'tox-collection'
  8770. ].concat(columns === 1 ? ['tox-collection--list'] : ['tox-collection--grid'])
  8771. },
  8772. components: [insertItemsPlaceholder(columns, initItems, identity)]
  8773. });
  8774. const forCollectionWithSearchResults = (columns, initItems, _hasIcons = true) => {
  8775. const ariaControlsSearchResults = generate$6('aria-controls-search-results');
  8776. return {
  8777. dom: {
  8778. tag: 'div',
  8779. classes: [
  8780. 'tox-menu',
  8781. 'tox-collection',
  8782. searchResultsClass
  8783. ].concat(columns === 1 ? ['tox-collection--list'] : ['tox-collection--grid']),
  8784. attributes: { id: ariaControlsSearchResults }
  8785. },
  8786. components: [insertItemsPlaceholder(columns, initItems, augmentWithAria)]
  8787. };
  8788. };
  8789. const forCollectionWithSearchField = (columns, initItems, searchField) => {
  8790. const ariaControlsSearchResults = generate$6('aria-controls-search-results');
  8791. return {
  8792. dom: {
  8793. tag: 'div',
  8794. classes: [
  8795. 'tox-menu',
  8796. 'tox-collection'
  8797. ].concat(columns === 1 ? ['tox-collection--list'] : ['tox-collection--grid'])
  8798. },
  8799. components: [
  8800. renderMenuSearcher({
  8801. i18n: global$8.translate,
  8802. placeholder: searchField.placeholder
  8803. }),
  8804. {
  8805. dom: {
  8806. tag: 'div',
  8807. classes: [
  8808. ...columns === 1 ? ['tox-collection--list'] : ['tox-collection--grid'],
  8809. searchResultsClass
  8810. ],
  8811. attributes: { id: ariaControlsSearchResults }
  8812. },
  8813. components: [insertItemsPlaceholder(columns, initItems, augmentWithAria)]
  8814. }
  8815. ]
  8816. };
  8817. };
  8818. const forHorizontalCollection = (initItems, _hasIcons = true) => ({
  8819. dom: {
  8820. tag: 'div',
  8821. classes: [
  8822. 'tox-collection',
  8823. 'tox-collection--horizontal'
  8824. ]
  8825. },
  8826. components: [Menu.parts.items({ preprocess: items => preprocessCollection(items, (_item, i) => initItems[i].type === 'separator') })]
  8827. });
  8828. const menuHasIcons = xs => exists(xs, item => 'icon' in item && item.icon !== undefined);
  8829. const handleError = error => {
  8830. console.error(formatError(error));
  8831. console.log(error);
  8832. return Optional.none();
  8833. };
  8834. const createHorizontalPartialMenuWithAlloyItems = (value, _hasIcons, items, _columns, _menuLayout) => {
  8835. const structure = forHorizontalCollection(items);
  8836. return {
  8837. value,
  8838. dom: structure.dom,
  8839. components: structure.components,
  8840. items
  8841. };
  8842. };
  8843. const createPartialMenuWithAlloyItems = (value, hasIcons, items, columns, menuLayout) => {
  8844. const getNormalStructure = () => {
  8845. if (menuLayout.menuType !== 'searchable') {
  8846. return forCollection(columns, items);
  8847. } else {
  8848. return menuLayout.searchMode.searchMode === 'search-with-field' ? forCollectionWithSearchField(columns, items, menuLayout.searchMode) : forCollectionWithSearchResults(columns, items);
  8849. }
  8850. };
  8851. if (menuLayout.menuType === 'color') {
  8852. const structure = forSwatch(columns);
  8853. return {
  8854. value,
  8855. dom: structure.dom,
  8856. components: structure.components,
  8857. items
  8858. };
  8859. } else if (menuLayout.menuType === 'normal' && columns === 'auto') {
  8860. const structure = forCollection(columns, items);
  8861. return {
  8862. value,
  8863. dom: structure.dom,
  8864. components: structure.components,
  8865. items
  8866. };
  8867. } else if (menuLayout.menuType === 'normal' || menuLayout.menuType === 'searchable') {
  8868. const structure = getNormalStructure();
  8869. return {
  8870. value,
  8871. dom: structure.dom,
  8872. components: structure.components,
  8873. items
  8874. };
  8875. } else if (menuLayout.menuType === 'listpreview' && columns !== 'auto') {
  8876. const structure = forToolbar(columns);
  8877. return {
  8878. value,
  8879. dom: structure.dom,
  8880. components: structure.components,
  8881. items
  8882. };
  8883. } else {
  8884. return {
  8885. value,
  8886. dom: dom$1(hasIcons, columns, menuLayout.menuType),
  8887. components: components,
  8888. items
  8889. };
  8890. }
  8891. };
  8892. const type = requiredString('type');
  8893. const name$1 = requiredString('name');
  8894. const label = requiredString('label');
  8895. const text$1 = requiredString('text');
  8896. const title = requiredString('title');
  8897. const icon = requiredString('icon');
  8898. const value$1 = requiredString('value');
  8899. const fetch$1 = requiredFunction('fetch');
  8900. const getSubmenuItems = requiredFunction('getSubmenuItems');
  8901. const onAction = requiredFunction('onAction');
  8902. const onItemAction = requiredFunction('onItemAction');
  8903. const onSetup = defaultedFunction('onSetup', () => noop);
  8904. const optionalName = optionString('name');
  8905. const optionalText = optionString('text');
  8906. const optionalIcon = optionString('icon');
  8907. const optionalTooltip = optionString('tooltip');
  8908. const optionalLabel = optionString('label');
  8909. const optionalShortcut = optionString('shortcut');
  8910. const optionalSelect = optionFunction('select');
  8911. const active = defaultedBoolean('active', false);
  8912. const borderless = defaultedBoolean('borderless', false);
  8913. const enabled = defaultedBoolean('enabled', true);
  8914. const primary = defaultedBoolean('primary', false);
  8915. const defaultedColumns = num => defaulted('columns', num);
  8916. const defaultedMeta = defaulted('meta', {});
  8917. const defaultedOnAction = defaultedFunction('onAction', noop);
  8918. const defaultedType = type => defaultedString('type', type);
  8919. const generatedName = namePrefix => field$1('name', 'name', defaultedThunk(() => generate$6(`${ namePrefix }-name`)), string);
  8920. const generatedValue = valuePrefix => field$1('value', 'value', defaultedThunk(() => generate$6(`${ valuePrefix }-value`)), anyValue());
  8921. const separatorMenuItemSchema = objOf([
  8922. type,
  8923. optionalText
  8924. ]);
  8925. const createSeparatorMenuItem = spec => asRaw('separatormenuitem', separatorMenuItemSchema, spec);
  8926. const autocompleterItemSchema = objOf([
  8927. defaultedType('autocompleteitem'),
  8928. active,
  8929. enabled,
  8930. defaultedMeta,
  8931. value$1,
  8932. optionalText,
  8933. optionalIcon
  8934. ]);
  8935. const createSeparatorItem = spec => asRaw('Autocompleter.Separator', separatorMenuItemSchema, spec);
  8936. const createAutocompleterItem = spec => asRaw('Autocompleter.Item', autocompleterItemSchema, spec);
  8937. const baseToolbarButtonFields = [
  8938. enabled,
  8939. optionalTooltip,
  8940. optionalIcon,
  8941. optionalText,
  8942. onSetup
  8943. ];
  8944. const toolbarButtonSchema = objOf([
  8945. type,
  8946. onAction
  8947. ].concat(baseToolbarButtonFields));
  8948. const createToolbarButton = spec => asRaw('toolbarbutton', toolbarButtonSchema, spec);
  8949. const baseToolbarToggleButtonFields = [active].concat(baseToolbarButtonFields);
  8950. const toggleButtonSchema = objOf(baseToolbarToggleButtonFields.concat([
  8951. type,
  8952. onAction
  8953. ]));
  8954. const createToggleButton = spec => asRaw('ToggleButton', toggleButtonSchema, spec);
  8955. const contextBarFields = [
  8956. defaultedFunction('predicate', never),
  8957. defaultedStringEnum('scope', 'node', [
  8958. 'node',
  8959. 'editor'
  8960. ]),
  8961. defaultedStringEnum('position', 'selection', [
  8962. 'node',
  8963. 'selection',
  8964. 'line'
  8965. ])
  8966. ];
  8967. const contextButtonFields = baseToolbarButtonFields.concat([
  8968. defaultedType('contextformbutton'),
  8969. primary,
  8970. onAction,
  8971. customField('original', identity)
  8972. ]);
  8973. const contextToggleButtonFields = baseToolbarToggleButtonFields.concat([
  8974. defaultedType('contextformbutton'),
  8975. primary,
  8976. onAction,
  8977. customField('original', identity)
  8978. ]);
  8979. const launchButtonFields = baseToolbarButtonFields.concat([defaultedType('contextformbutton')]);
  8980. const launchToggleButtonFields = baseToolbarToggleButtonFields.concat([defaultedType('contextformtogglebutton')]);
  8981. const toggleOrNormal = choose$1('type', {
  8982. contextformbutton: contextButtonFields,
  8983. contextformtogglebutton: contextToggleButtonFields
  8984. });
  8985. const contextFormSchema = objOf([
  8986. defaultedType('contextform'),
  8987. defaultedFunction('initValue', constant$1('')),
  8988. optionalLabel,
  8989. requiredArrayOf('commands', toggleOrNormal),
  8990. optionOf('launch', choose$1('type', {
  8991. contextformbutton: launchButtonFields,
  8992. contextformtogglebutton: launchToggleButtonFields
  8993. }))
  8994. ].concat(contextBarFields));
  8995. const createContextForm = spec => asRaw('ContextForm', contextFormSchema, spec);
  8996. const contextToolbarSchema = objOf([
  8997. defaultedType('contexttoolbar'),
  8998. requiredString('items')
  8999. ].concat(contextBarFields));
  9000. const createContextToolbar = spec => asRaw('ContextToolbar', contextToolbarSchema, spec);
  9001. const cardImageFields = [
  9002. type,
  9003. requiredString('src'),
  9004. optionString('alt'),
  9005. defaultedArrayOf('classes', [], string)
  9006. ];
  9007. const cardImageSchema = objOf(cardImageFields);
  9008. const cardTextFields = [
  9009. type,
  9010. text$1,
  9011. optionalName,
  9012. defaultedArrayOf('classes', ['tox-collection__item-label'], string)
  9013. ];
  9014. const cardTextSchema = objOf(cardTextFields);
  9015. const itemSchema$1 = valueThunk(() => choose$2('type', {
  9016. cardimage: cardImageSchema,
  9017. cardtext: cardTextSchema,
  9018. cardcontainer: cardContainerSchema
  9019. }));
  9020. const cardContainerSchema = objOf([
  9021. type,
  9022. defaultedString('direction', 'horizontal'),
  9023. defaultedString('align', 'left'),
  9024. defaultedString('valign', 'middle'),
  9025. requiredArrayOf('items', itemSchema$1)
  9026. ]);
  9027. const commonMenuItemFields = [
  9028. enabled,
  9029. optionalText,
  9030. optionalShortcut,
  9031. generatedValue('menuitem'),
  9032. defaultedMeta
  9033. ];
  9034. const cardMenuItemSchema = objOf([
  9035. type,
  9036. optionalLabel,
  9037. requiredArrayOf('items', itemSchema$1),
  9038. onSetup,
  9039. defaultedOnAction
  9040. ].concat(commonMenuItemFields));
  9041. const createCardMenuItem = spec => asRaw('cardmenuitem', cardMenuItemSchema, spec);
  9042. const choiceMenuItemSchema = objOf([
  9043. type,
  9044. active,
  9045. optionalIcon
  9046. ].concat(commonMenuItemFields));
  9047. const createChoiceMenuItem = spec => asRaw('choicemenuitem', choiceMenuItemSchema, spec);
  9048. const baseFields = [
  9049. type,
  9050. requiredString('fancytype'),
  9051. defaultedOnAction
  9052. ];
  9053. const insertTableFields = [defaulted('initData', {})].concat(baseFields);
  9054. const colorSwatchFields = [
  9055. optionFunction('select'),
  9056. defaultedObjOf('initData', {}, [
  9057. defaultedBoolean('allowCustomColors', true),
  9058. defaultedString('storageKey', 'default'),
  9059. optionArrayOf('colors', anyValue())
  9060. ])
  9061. ].concat(baseFields);
  9062. const fancyMenuItemSchema = choose$1('fancytype', {
  9063. inserttable: insertTableFields,
  9064. colorswatch: colorSwatchFields
  9065. });
  9066. const createFancyMenuItem = spec => asRaw('fancymenuitem', fancyMenuItemSchema, spec);
  9067. const menuItemSchema = objOf([
  9068. type,
  9069. onSetup,
  9070. defaultedOnAction,
  9071. optionalIcon
  9072. ].concat(commonMenuItemFields));
  9073. const createMenuItem = spec => asRaw('menuitem', menuItemSchema, spec);
  9074. const nestedMenuItemSchema = objOf([
  9075. type,
  9076. getSubmenuItems,
  9077. onSetup,
  9078. optionalIcon
  9079. ].concat(commonMenuItemFields));
  9080. const createNestedMenuItem = spec => asRaw('nestedmenuitem', nestedMenuItemSchema, spec);
  9081. const toggleMenuItemSchema = objOf([
  9082. type,
  9083. optionalIcon,
  9084. active,
  9085. onSetup,
  9086. onAction
  9087. ].concat(commonMenuItemFields));
  9088. const createToggleMenuItem = spec => asRaw('togglemenuitem', toggleMenuItemSchema, spec);
  9089. const detectSize = (comp, margin, selectorClass) => {
  9090. const descendants$1 = descendants(comp.element, '.' + selectorClass);
  9091. if (descendants$1.length > 0) {
  9092. const columnLength = findIndex$1(descendants$1, c => {
  9093. const thisTop = c.dom.getBoundingClientRect().top;
  9094. const cTop = descendants$1[0].dom.getBoundingClientRect().top;
  9095. return Math.abs(thisTop - cTop) > margin;
  9096. }).getOr(descendants$1.length);
  9097. return Optional.some({
  9098. numColumns: columnLength,
  9099. numRows: Math.ceil(descendants$1.length / columnLength)
  9100. });
  9101. } else {
  9102. return Optional.none();
  9103. }
  9104. };
  9105. const namedEvents = (name, handlers) => derive$1([config(name, handlers)]);
  9106. const unnamedEvents = handlers => namedEvents(generate$6('unnamed-events'), handlers);
  9107. const SimpleBehaviours = {
  9108. namedEvents,
  9109. unnamedEvents
  9110. };
  9111. const ExclusivityChannel = generate$6('tooltip.exclusive');
  9112. const ShowTooltipEvent = generate$6('tooltip.show');
  9113. const HideTooltipEvent = generate$6('tooltip.hide');
  9114. const hideAllExclusive = (component, _tConfig, _tState) => {
  9115. component.getSystem().broadcastOn([ExclusivityChannel], {});
  9116. };
  9117. const setComponents = (component, tConfig, tState, specs) => {
  9118. tState.getTooltip().each(tooltip => {
  9119. if (tooltip.getSystem().isConnected()) {
  9120. Replacing.set(tooltip, specs);
  9121. }
  9122. });
  9123. };
  9124. var TooltippingApis = /*#__PURE__*/Object.freeze({
  9125. __proto__: null,
  9126. hideAllExclusive: hideAllExclusive,
  9127. setComponents: setComponents
  9128. });
  9129. const events$9 = (tooltipConfig, state) => {
  9130. const hide = comp => {
  9131. state.getTooltip().each(p => {
  9132. detach(p);
  9133. tooltipConfig.onHide(comp, p);
  9134. state.clearTooltip();
  9135. });
  9136. state.clearTimer();
  9137. };
  9138. const show = comp => {
  9139. if (!state.isShowing()) {
  9140. hideAllExclusive(comp);
  9141. const sink = tooltipConfig.lazySink(comp).getOrDie();
  9142. const popup = comp.getSystem().build({
  9143. dom: tooltipConfig.tooltipDom,
  9144. components: tooltipConfig.tooltipComponents,
  9145. events: derive$2(tooltipConfig.mode === 'normal' ? [
  9146. run$1(mouseover(), _ => {
  9147. emit(comp, ShowTooltipEvent);
  9148. }),
  9149. run$1(mouseout(), _ => {
  9150. emit(comp, HideTooltipEvent);
  9151. })
  9152. ] : []),
  9153. behaviours: derive$1([Replacing.config({})])
  9154. });
  9155. state.setTooltip(popup);
  9156. attach(sink, popup);
  9157. tooltipConfig.onShow(comp, popup);
  9158. Positioning.position(sink, popup, { anchor: tooltipConfig.anchor(comp) });
  9159. }
  9160. };
  9161. return derive$2(flatten([
  9162. [
  9163. run$1(ShowTooltipEvent, comp => {
  9164. state.resetTimer(() => {
  9165. show(comp);
  9166. }, tooltipConfig.delay);
  9167. }),
  9168. run$1(HideTooltipEvent, comp => {
  9169. state.resetTimer(() => {
  9170. hide(comp);
  9171. }, tooltipConfig.delay);
  9172. }),
  9173. run$1(receive(), (comp, message) => {
  9174. const receivingData = message;
  9175. if (!receivingData.universal) {
  9176. if (contains$2(receivingData.channels, ExclusivityChannel)) {
  9177. hide(comp);
  9178. }
  9179. }
  9180. }),
  9181. runOnDetached(comp => {
  9182. hide(comp);
  9183. })
  9184. ],
  9185. tooltipConfig.mode === 'normal' ? [
  9186. run$1(focusin(), comp => {
  9187. emit(comp, ShowTooltipEvent);
  9188. }),
  9189. run$1(postBlur(), comp => {
  9190. emit(comp, HideTooltipEvent);
  9191. }),
  9192. run$1(mouseover(), comp => {
  9193. emit(comp, ShowTooltipEvent);
  9194. }),
  9195. run$1(mouseout(), comp => {
  9196. emit(comp, HideTooltipEvent);
  9197. })
  9198. ] : [
  9199. run$1(highlight$1(), (comp, _se) => {
  9200. emit(comp, ShowTooltipEvent);
  9201. }),
  9202. run$1(dehighlight$1(), comp => {
  9203. emit(comp, HideTooltipEvent);
  9204. })
  9205. ]
  9206. ]));
  9207. };
  9208. var ActiveTooltipping = /*#__PURE__*/Object.freeze({
  9209. __proto__: null,
  9210. events: events$9
  9211. });
  9212. var TooltippingSchema = [
  9213. required$1('lazySink'),
  9214. required$1('tooltipDom'),
  9215. defaulted('exclusive', true),
  9216. defaulted('tooltipComponents', []),
  9217. defaulted('delay', 300),
  9218. defaultedStringEnum('mode', 'normal', [
  9219. 'normal',
  9220. 'follow-highlight'
  9221. ]),
  9222. defaulted('anchor', comp => ({
  9223. type: 'hotspot',
  9224. hotspot: comp,
  9225. layouts: {
  9226. onLtr: constant$1([
  9227. south$2,
  9228. north$2,
  9229. southeast$2,
  9230. northeast$2,
  9231. southwest$2,
  9232. northwest$2
  9233. ]),
  9234. onRtl: constant$1([
  9235. south$2,
  9236. north$2,
  9237. southeast$2,
  9238. northeast$2,
  9239. southwest$2,
  9240. northwest$2
  9241. ])
  9242. }
  9243. })),
  9244. onHandler('onHide'),
  9245. onHandler('onShow')
  9246. ];
  9247. const init$b = () => {
  9248. const timer = value$2();
  9249. const popup = value$2();
  9250. const clearTimer = () => {
  9251. timer.on(clearTimeout);
  9252. };
  9253. const resetTimer = (f, delay) => {
  9254. clearTimer();
  9255. timer.set(setTimeout(f, delay));
  9256. };
  9257. const readState = constant$1('not-implemented');
  9258. return nu$8({
  9259. getTooltip: popup.get,
  9260. isShowing: popup.isSet,
  9261. setTooltip: popup.set,
  9262. clearTooltip: popup.clear,
  9263. clearTimer,
  9264. resetTimer,
  9265. readState
  9266. });
  9267. };
  9268. var TooltippingState = /*#__PURE__*/Object.freeze({
  9269. __proto__: null,
  9270. init: init$b
  9271. });
  9272. const Tooltipping = create$4({
  9273. fields: TooltippingSchema,
  9274. name: 'tooltipping',
  9275. active: ActiveTooltipping,
  9276. state: TooltippingState,
  9277. apis: TooltippingApis
  9278. });
  9279. const escape = text => text.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
  9280. const ReadOnlyChannel = 'silver.readonly';
  9281. const ReadOnlyDataSchema = objOf([requiredBoolean('readonly')]);
  9282. const broadcastReadonly = (uiRefs, readonly) => {
  9283. const outerContainer = uiRefs.mainUi.outerContainer;
  9284. const target = outerContainer.element;
  9285. const motherships = [
  9286. uiRefs.mainUi.mothership,
  9287. ...uiRefs.uiMotherships
  9288. ];
  9289. if (readonly) {
  9290. each$1(motherships, m => {
  9291. m.broadcastOn([dismissPopups()], { target });
  9292. });
  9293. }
  9294. each$1(motherships, m => {
  9295. m.broadcastOn([ReadOnlyChannel], { readonly });
  9296. });
  9297. };
  9298. const setupReadonlyModeSwitch = (editor, uiRefs) => {
  9299. editor.on('init', () => {
  9300. if (editor.mode.isReadOnly()) {
  9301. broadcastReadonly(uiRefs, true);
  9302. }
  9303. });
  9304. editor.on('SwitchMode', () => broadcastReadonly(uiRefs, editor.mode.isReadOnly()));
  9305. if (isReadOnly(editor)) {
  9306. editor.mode.set('readonly');
  9307. }
  9308. };
  9309. const receivingConfig = () => Receiving.config({
  9310. channels: {
  9311. [ReadOnlyChannel]: {
  9312. schema: ReadOnlyDataSchema,
  9313. onReceive: (comp, data) => {
  9314. Disabling.set(comp, data.readonly);
  9315. }
  9316. }
  9317. }
  9318. });
  9319. const item = disabled => Disabling.config({
  9320. disabled,
  9321. disableClass: 'tox-collection__item--state-disabled'
  9322. });
  9323. const button = disabled => Disabling.config({ disabled });
  9324. const splitButton = disabled => Disabling.config({
  9325. disabled,
  9326. disableClass: 'tox-tbtn--disabled'
  9327. });
  9328. const toolbarButton = disabled => Disabling.config({
  9329. disabled,
  9330. disableClass: 'tox-tbtn--disabled',
  9331. useNative: false
  9332. });
  9333. const DisablingConfigs = {
  9334. item,
  9335. button,
  9336. splitButton,
  9337. toolbarButton
  9338. };
  9339. const runWithApi = (info, comp) => {
  9340. const api = info.getApi(comp);
  9341. return f => {
  9342. f(api);
  9343. };
  9344. };
  9345. const onControlAttached = (info, editorOffCell) => runOnAttached(comp => {
  9346. const run = runWithApi(info, comp);
  9347. run(api => {
  9348. const onDestroy = info.onSetup(api);
  9349. if (isFunction(onDestroy)) {
  9350. editorOffCell.set(onDestroy);
  9351. }
  9352. });
  9353. });
  9354. const onControlDetached = (getApi, editorOffCell) => runOnDetached(comp => runWithApi(getApi, comp)(editorOffCell.get()));
  9355. const onMenuItemExecute = (info, itemResponse) => runOnExecute$1((comp, simulatedEvent) => {
  9356. runWithApi(info, comp)(info.onAction);
  9357. if (!info.triggersSubmenu && itemResponse === ItemResponse$1.CLOSE_ON_EXECUTE) {
  9358. if (comp.getSystem().isConnected()) {
  9359. emit(comp, sandboxClose());
  9360. }
  9361. simulatedEvent.stop();
  9362. }
  9363. });
  9364. const menuItemEventOrder = {
  9365. [execute$5()]: [
  9366. 'disabling',
  9367. 'alloy.base.behaviour',
  9368. 'toggling',
  9369. 'item-events'
  9370. ]
  9371. };
  9372. const componentRenderPipeline = cat;
  9373. const renderCommonItem = (spec, structure, itemResponse, providersBackstage) => {
  9374. const editorOffCell = Cell(noop);
  9375. return {
  9376. type: 'item',
  9377. dom: structure.dom,
  9378. components: componentRenderPipeline(structure.optComponents),
  9379. data: spec.data,
  9380. eventOrder: menuItemEventOrder,
  9381. hasSubmenu: spec.triggersSubmenu,
  9382. itemBehaviours: derive$1([
  9383. config('item-events', [
  9384. onMenuItemExecute(spec, itemResponse),
  9385. onControlAttached(spec, editorOffCell),
  9386. onControlDetached(spec, editorOffCell)
  9387. ]),
  9388. DisablingConfigs.item(() => !spec.enabled || providersBackstage.isDisabled()),
  9389. receivingConfig(),
  9390. Replacing.config({})
  9391. ].concat(spec.itemBehaviours))
  9392. };
  9393. };
  9394. const buildData = source => ({
  9395. value: source.value,
  9396. meta: {
  9397. text: source.text.getOr(''),
  9398. ...source.meta
  9399. }
  9400. });
  9401. const convertText = source => {
  9402. const isMac = global$5.os.isMacOS() || global$5.os.isiOS();
  9403. const mac = {
  9404. alt: '\u2325',
  9405. ctrl: '\u2303',
  9406. shift: '\u21E7',
  9407. meta: '\u2318',
  9408. access: '\u2303\u2325'
  9409. };
  9410. const other = {
  9411. meta: 'Ctrl',
  9412. access: 'Shift+Alt'
  9413. };
  9414. const replace = isMac ? mac : other;
  9415. const shortcut = source.split('+');
  9416. const updated = map$2(shortcut, segment => {
  9417. const search = segment.toLowerCase().trim();
  9418. return has$2(replace, search) ? replace[search] : segment;
  9419. });
  9420. return isMac ? updated.join('') : updated.join('+');
  9421. };
  9422. const renderIcon$2 = (name, icons, classes = [iconClass]) => render$3(name, {
  9423. tag: 'div',
  9424. classes
  9425. }, icons);
  9426. const renderText = text => ({
  9427. dom: {
  9428. tag: 'div',
  9429. classes: [textClass]
  9430. },
  9431. components: [text$2(global$8.translate(text))]
  9432. });
  9433. const renderHtml = (html, classes) => ({
  9434. dom: {
  9435. tag: 'div',
  9436. classes,
  9437. innerHtml: html
  9438. }
  9439. });
  9440. const renderStyledText = (style, text) => ({
  9441. dom: {
  9442. tag: 'div',
  9443. classes: [textClass]
  9444. },
  9445. components: [{
  9446. dom: {
  9447. tag: style.tag,
  9448. styles: style.styles
  9449. },
  9450. components: [text$2(global$8.translate(text))]
  9451. }]
  9452. });
  9453. const renderShortcut = shortcut => ({
  9454. dom: {
  9455. tag: 'div',
  9456. classes: [accessoryClass]
  9457. },
  9458. components: [text$2(convertText(shortcut))]
  9459. });
  9460. const renderCheckmark = icons => renderIcon$2('checkmark', icons, [checkmarkClass]);
  9461. const renderSubmenuCaret = icons => renderIcon$2('chevron-right', icons, [caretClass]);
  9462. const renderDownwardsCaret = icons => renderIcon$2('chevron-down', icons, [caretClass]);
  9463. const renderContainer = (container, components) => {
  9464. const directionClass = container.direction === 'vertical' ? containerColumnClass : containerRowClass;
  9465. const alignClass = container.align === 'left' ? containerAlignLeftClass : containerAlignRightClass;
  9466. const getValignClass = () => {
  9467. switch (container.valign) {
  9468. case 'top':
  9469. return containerValignTopClass;
  9470. case 'middle':
  9471. return containerValignMiddleClass;
  9472. case 'bottom':
  9473. return containerValignBottomClass;
  9474. }
  9475. };
  9476. return {
  9477. dom: {
  9478. tag: 'div',
  9479. classes: [
  9480. containerClass,
  9481. directionClass,
  9482. alignClass,
  9483. getValignClass()
  9484. ]
  9485. },
  9486. components
  9487. };
  9488. };
  9489. const renderImage = (src, classes, alt) => ({
  9490. dom: {
  9491. tag: 'img',
  9492. classes,
  9493. attributes: {
  9494. src,
  9495. alt: alt.getOr('')
  9496. }
  9497. }
  9498. });
  9499. const renderColorStructure = (item, providerBackstage, fallbackIcon) => {
  9500. const colorPickerCommand = 'custom';
  9501. const removeColorCommand = 'remove';
  9502. const itemText = item.ariaLabel;
  9503. const itemValue = item.value;
  9504. const iconSvg = item.iconContent.map(name => getOr(name, providerBackstage.icons, fallbackIcon));
  9505. const getDom = () => {
  9506. const common = colorClass;
  9507. const icon = iconSvg.getOr('');
  9508. const attributes = itemText.map(text => ({ title: providerBackstage.translate(text) })).getOr({});
  9509. const baseDom = {
  9510. tag: 'div',
  9511. attributes,
  9512. classes: [common]
  9513. };
  9514. if (itemValue === colorPickerCommand) {
  9515. return {
  9516. ...baseDom,
  9517. tag: 'button',
  9518. classes: [
  9519. ...baseDom.classes,
  9520. 'tox-swatches__picker-btn'
  9521. ],
  9522. innerHtml: icon
  9523. };
  9524. } else if (itemValue === removeColorCommand) {
  9525. return {
  9526. ...baseDom,
  9527. classes: [
  9528. ...baseDom.classes,
  9529. 'tox-swatch--remove'
  9530. ],
  9531. innerHtml: icon
  9532. };
  9533. } else if (isNonNullable(itemValue)) {
  9534. return {
  9535. ...baseDom,
  9536. attributes: {
  9537. ...baseDom.attributes,
  9538. 'data-mce-color': itemValue
  9539. },
  9540. styles: { 'background-color': itemValue },
  9541. innerHtml: icon
  9542. };
  9543. } else {
  9544. return baseDom;
  9545. }
  9546. };
  9547. return {
  9548. dom: getDom(),
  9549. optComponents: []
  9550. };
  9551. };
  9552. const renderItemDomStructure = ariaLabel => {
  9553. const domTitle = ariaLabel.map(label => ({ attributes: { title: global$8.translate(label) } })).getOr({});
  9554. return {
  9555. tag: 'div',
  9556. classes: [
  9557. navClass,
  9558. selectableClass
  9559. ],
  9560. ...domTitle
  9561. };
  9562. };
  9563. const renderNormalItemStructure = (info, providersBackstage, renderIcons, fallbackIcon) => {
  9564. const iconSpec = {
  9565. tag: 'div',
  9566. classes: [iconClass]
  9567. };
  9568. const renderIcon = iconName => render$3(iconName, iconSpec, providersBackstage.icons, fallbackIcon);
  9569. const renderEmptyIcon = () => Optional.some({ dom: iconSpec });
  9570. const leftIcon = renderIcons ? info.iconContent.map(renderIcon).orThunk(renderEmptyIcon) : Optional.none();
  9571. const checkmark = info.checkMark;
  9572. const textRender = Optional.from(info.meta).fold(() => renderText, meta => has$2(meta, 'style') ? curry(renderStyledText, meta.style) : renderText);
  9573. const content = info.htmlContent.fold(() => info.textContent.map(textRender), html => Optional.some(renderHtml(html, [textClass])));
  9574. const menuItem = {
  9575. dom: renderItemDomStructure(info.ariaLabel),
  9576. optComponents: [
  9577. leftIcon,
  9578. content,
  9579. info.shortcutContent.map(renderShortcut),
  9580. checkmark,
  9581. info.caret
  9582. ]
  9583. };
  9584. return menuItem;
  9585. };
  9586. const renderItemStructure = (info, providersBackstage, renderIcons, fallbackIcon = Optional.none()) => {
  9587. if (info.presets === 'color') {
  9588. return renderColorStructure(info, providersBackstage, fallbackIcon);
  9589. } else {
  9590. return renderNormalItemStructure(info, providersBackstage, renderIcons, fallbackIcon);
  9591. }
  9592. };
  9593. const tooltipBehaviour = (meta, sharedBackstage) => get$g(meta, 'tooltipWorker').map(tooltipWorker => [Tooltipping.config({
  9594. lazySink: sharedBackstage.getSink,
  9595. tooltipDom: {
  9596. tag: 'div',
  9597. classes: ['tox-tooltip-worker-container']
  9598. },
  9599. tooltipComponents: [],
  9600. anchor: comp => ({
  9601. type: 'submenu',
  9602. item: comp,
  9603. overrides: { maxHeightFunction: expandable$1 }
  9604. }),
  9605. mode: 'follow-highlight',
  9606. onShow: (component, _tooltip) => {
  9607. tooltipWorker(elm => {
  9608. Tooltipping.setComponents(component, [external$1({ element: SugarElement.fromDom(elm) })]);
  9609. });
  9610. }
  9611. })]).getOr([]);
  9612. const encodeText = text => global$7.DOM.encode(text);
  9613. const replaceText = (text, matchText) => {
  9614. const translated = global$8.translate(text);
  9615. const encoded = encodeText(translated);
  9616. if (matchText.length > 0) {
  9617. const escapedMatchRegex = new RegExp(escape(matchText), 'gi');
  9618. return encoded.replace(escapedMatchRegex, match => `<span class="tox-autocompleter-highlight">${ match }</span>`);
  9619. } else {
  9620. return encoded;
  9621. }
  9622. };
  9623. const renderAutocompleteItem = (spec, matchText, useText, presets, onItemValueHandler, itemResponse, sharedBackstage, renderIcons = true) => {
  9624. const structure = renderItemStructure({
  9625. presets,
  9626. textContent: Optional.none(),
  9627. htmlContent: useText ? spec.text.map(text => replaceText(text, matchText)) : Optional.none(),
  9628. ariaLabel: spec.text,
  9629. iconContent: spec.icon,
  9630. shortcutContent: Optional.none(),
  9631. checkMark: Optional.none(),
  9632. caret: Optional.none(),
  9633. value: spec.value
  9634. }, sharedBackstage.providers, renderIcons, spec.icon);
  9635. return renderCommonItem({
  9636. data: buildData(spec),
  9637. enabled: spec.enabled,
  9638. getApi: constant$1({}),
  9639. onAction: _api => onItemValueHandler(spec.value, spec.meta),
  9640. onSetup: constant$1(noop),
  9641. triggersSubmenu: false,
  9642. itemBehaviours: tooltipBehaviour(spec.meta, sharedBackstage)
  9643. }, structure, itemResponse, sharedBackstage.providers);
  9644. };
  9645. const render$2 = (items, extras) => map$2(items, item => {
  9646. switch (item.type) {
  9647. case 'cardcontainer':
  9648. return renderContainer(item, render$2(item.items, extras));
  9649. case 'cardimage':
  9650. return renderImage(item.src, item.classes, item.alt);
  9651. case 'cardtext':
  9652. const shouldHighlight = item.name.exists(name => contains$2(extras.cardText.highlightOn, name));
  9653. const matchText = shouldHighlight ? Optional.from(extras.cardText.matchText).getOr('') : '';
  9654. return renderHtml(replaceText(item.text, matchText), item.classes);
  9655. }
  9656. });
  9657. const renderCardMenuItem = (spec, itemResponse, sharedBackstage, extras) => {
  9658. const getApi = component => ({
  9659. isEnabled: () => !Disabling.isDisabled(component),
  9660. setEnabled: state => {
  9661. Disabling.set(component, !state);
  9662. each$1(descendants(component.element, '*'), elm => {
  9663. component.getSystem().getByDom(elm).each(comp => {
  9664. if (comp.hasConfigured(Disabling)) {
  9665. Disabling.set(comp, !state);
  9666. }
  9667. });
  9668. });
  9669. }
  9670. });
  9671. const structure = {
  9672. dom: renderItemDomStructure(spec.label),
  9673. optComponents: [Optional.some({
  9674. dom: {
  9675. tag: 'div',
  9676. classes: [
  9677. containerClass,
  9678. containerRowClass
  9679. ]
  9680. },
  9681. components: render$2(spec.items, extras)
  9682. })]
  9683. };
  9684. return renderCommonItem({
  9685. data: buildData({
  9686. text: Optional.none(),
  9687. ...spec
  9688. }),
  9689. enabled: spec.enabled,
  9690. getApi,
  9691. onAction: spec.onAction,
  9692. onSetup: spec.onSetup,
  9693. triggersSubmenu: false,
  9694. itemBehaviours: Optional.from(extras.itemBehaviours).getOr([])
  9695. }, structure, itemResponse, sharedBackstage.providers);
  9696. };
  9697. const renderChoiceItem = (spec, useText, presets, onItemValueHandler, isSelected, itemResponse, providersBackstage, renderIcons = true) => {
  9698. const getApi = component => ({
  9699. setActive: state => {
  9700. Toggling.set(component, state);
  9701. },
  9702. isActive: () => Toggling.isOn(component),
  9703. isEnabled: () => !Disabling.isDisabled(component),
  9704. setEnabled: state => Disabling.set(component, !state)
  9705. });
  9706. const structure = renderItemStructure({
  9707. presets,
  9708. textContent: useText ? spec.text : Optional.none(),
  9709. htmlContent: Optional.none(),
  9710. ariaLabel: spec.text,
  9711. iconContent: spec.icon,
  9712. shortcutContent: useText ? spec.shortcut : Optional.none(),
  9713. checkMark: useText ? Optional.some(renderCheckmark(providersBackstage.icons)) : Optional.none(),
  9714. caret: Optional.none(),
  9715. value: spec.value
  9716. }, providersBackstage, renderIcons);
  9717. return deepMerge(renderCommonItem({
  9718. data: buildData(spec),
  9719. enabled: spec.enabled,
  9720. getApi,
  9721. onAction: _api => onItemValueHandler(spec.value),
  9722. onSetup: api => {
  9723. api.setActive(isSelected);
  9724. return noop;
  9725. },
  9726. triggersSubmenu: false,
  9727. itemBehaviours: []
  9728. }, structure, itemResponse, providersBackstage), {
  9729. toggling: {
  9730. toggleClass: tickedClass,
  9731. toggleOnExecute: false,
  9732. selected: spec.active,
  9733. exclusive: true
  9734. }
  9735. });
  9736. };
  9737. const parts$f = generate$3(owner$2(), parts$h());
  9738. const hexColour = value => ({ value: normalizeHex(value) });
  9739. const shorthandRegex = /^#?([a-f\d])([a-f\d])([a-f\d])$/i;
  9740. const longformRegex = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i;
  9741. const isHexString = hex => shorthandRegex.test(hex) || longformRegex.test(hex);
  9742. const normalizeHex = hex => removeLeading(hex, '#').toUpperCase();
  9743. const fromString$1 = hex => isHexString(hex) ? Optional.some({ value: normalizeHex(hex) }) : Optional.none();
  9744. const getLongForm = hex => {
  9745. const hexString = hex.value.replace(shorthandRegex, (m, r, g, b) => r + r + g + g + b + b);
  9746. return { value: hexString };
  9747. };
  9748. const extractValues = hex => {
  9749. const longForm = getLongForm(hex);
  9750. const splitForm = longformRegex.exec(longForm.value);
  9751. return splitForm === null ? [
  9752. 'FFFFFF',
  9753. 'FF',
  9754. 'FF',
  9755. 'FF'
  9756. ] : splitForm;
  9757. };
  9758. const toHex = component => {
  9759. const hex = component.toString(16);
  9760. return (hex.length === 1 ? '0' + hex : hex).toUpperCase();
  9761. };
  9762. const fromRgba = rgbaColour => {
  9763. const value = toHex(rgbaColour.red) + toHex(rgbaColour.green) + toHex(rgbaColour.blue);
  9764. return hexColour(value);
  9765. };
  9766. const min = Math.min;
  9767. const max = Math.max;
  9768. const round$1 = Math.round;
  9769. const rgbRegex = /^\s*rgb\s*\(\s*(\d+)\s*,\s*(\d+)\s*,\s*(\d+)\s*\)\s*$/i;
  9770. const rgbaRegex = /^\s*rgba\s*\(\s*(\d+)\s*,\s*(\d+)\s*,\s*(\d+)\s*,\s*(\d?(?:\.\d+)?)\s*\)\s*$/i;
  9771. const rgbaColour = (red, green, blue, alpha) => ({
  9772. red,
  9773. green,
  9774. blue,
  9775. alpha
  9776. });
  9777. const isRgbaComponent = value => {
  9778. const num = parseInt(value, 10);
  9779. return num.toString() === value && num >= 0 && num <= 255;
  9780. };
  9781. const fromHsv = hsv => {
  9782. let r;
  9783. let g;
  9784. let b;
  9785. const hue = (hsv.hue || 0) % 360;
  9786. let saturation = hsv.saturation / 100;
  9787. let brightness = hsv.value / 100;
  9788. saturation = max(0, min(saturation, 1));
  9789. brightness = max(0, min(brightness, 1));
  9790. if (saturation === 0) {
  9791. r = g = b = round$1(255 * brightness);
  9792. return rgbaColour(r, g, b, 1);
  9793. }
  9794. const side = hue / 60;
  9795. const chroma = brightness * saturation;
  9796. const x = chroma * (1 - Math.abs(side % 2 - 1));
  9797. const match = brightness - chroma;
  9798. switch (Math.floor(side)) {
  9799. case 0:
  9800. r = chroma;
  9801. g = x;
  9802. b = 0;
  9803. break;
  9804. case 1:
  9805. r = x;
  9806. g = chroma;
  9807. b = 0;
  9808. break;
  9809. case 2:
  9810. r = 0;
  9811. g = chroma;
  9812. b = x;
  9813. break;
  9814. case 3:
  9815. r = 0;
  9816. g = x;
  9817. b = chroma;
  9818. break;
  9819. case 4:
  9820. r = x;
  9821. g = 0;
  9822. b = chroma;
  9823. break;
  9824. case 5:
  9825. r = chroma;
  9826. g = 0;
  9827. b = x;
  9828. break;
  9829. default:
  9830. r = g = b = 0;
  9831. }
  9832. r = round$1(255 * (r + match));
  9833. g = round$1(255 * (g + match));
  9834. b = round$1(255 * (b + match));
  9835. return rgbaColour(r, g, b, 1);
  9836. };
  9837. const fromHex = hexColour => {
  9838. const result = extractValues(hexColour);
  9839. const red = parseInt(result[1], 16);
  9840. const green = parseInt(result[2], 16);
  9841. const blue = parseInt(result[3], 16);
  9842. return rgbaColour(red, green, blue, 1);
  9843. };
  9844. const fromStringValues = (red, green, blue, alpha) => {
  9845. const r = parseInt(red, 10);
  9846. const g = parseInt(green, 10);
  9847. const b = parseInt(blue, 10);
  9848. const a = parseFloat(alpha);
  9849. return rgbaColour(r, g, b, a);
  9850. };
  9851. const fromString = rgbaString => {
  9852. if (rgbaString === 'transparent') {
  9853. return Optional.some(rgbaColour(0, 0, 0, 0));
  9854. }
  9855. const rgbMatch = rgbRegex.exec(rgbaString);
  9856. if (rgbMatch !== null) {
  9857. return Optional.some(fromStringValues(rgbMatch[1], rgbMatch[2], rgbMatch[3], '1'));
  9858. }
  9859. const rgbaMatch = rgbaRegex.exec(rgbaString);
  9860. if (rgbaMatch !== null) {
  9861. return Optional.some(fromStringValues(rgbaMatch[1], rgbaMatch[2], rgbaMatch[3], rgbaMatch[4]));
  9862. }
  9863. return Optional.none();
  9864. };
  9865. const toString = rgba => `rgba(${ rgba.red },${ rgba.green },${ rgba.blue },${ rgba.alpha })`;
  9866. const red = rgbaColour(255, 0, 0, 1);
  9867. const fireSkinLoaded$1 = editor => {
  9868. editor.dispatch('SkinLoaded');
  9869. };
  9870. const fireSkinLoadError$1 = (editor, error) => {
  9871. editor.dispatch('SkinLoadError', error);
  9872. };
  9873. const fireResizeEditor = editor => {
  9874. editor.dispatch('ResizeEditor');
  9875. };
  9876. const fireResizeContent = (editor, e) => {
  9877. editor.dispatch('ResizeContent', e);
  9878. };
  9879. const fireScrollContent = (editor, e) => {
  9880. editor.dispatch('ScrollContent', e);
  9881. };
  9882. const fireTextColorChange = (editor, data) => {
  9883. editor.dispatch('TextColorChange', data);
  9884. };
  9885. const fireAfterProgressState = (editor, state) => {
  9886. editor.dispatch('AfterProgressState', { state });
  9887. };
  9888. const fireResolveName = (editor, node) => editor.dispatch('ResolveName', {
  9889. name: node.nodeName.toLowerCase(),
  9890. target: node
  9891. });
  9892. const fireToggleToolbarDrawer = (editor, state) => {
  9893. editor.dispatch('ToggleToolbarDrawer', { state });
  9894. };
  9895. var global$4 = tinymce.util.Tools.resolve('tinymce.util.LocalStorage');
  9896. const cacheStorage = {};
  9897. const ColorCache = (storageId, max = 10) => {
  9898. const storageString = global$4.getItem(storageId);
  9899. const localstorage = isString(storageString) ? JSON.parse(storageString) : [];
  9900. const prune = list => {
  9901. const diff = max - list.length;
  9902. return diff < 0 ? list.slice(0, max) : list;
  9903. };
  9904. const cache = prune(localstorage);
  9905. const add = key => {
  9906. indexOf(cache, key).each(remove);
  9907. cache.unshift(key);
  9908. if (cache.length > max) {
  9909. cache.pop();
  9910. }
  9911. global$4.setItem(storageId, JSON.stringify(cache));
  9912. };
  9913. const remove = idx => {
  9914. cache.splice(idx, 1);
  9915. };
  9916. const state = () => cache.slice(0);
  9917. return {
  9918. add,
  9919. state
  9920. };
  9921. };
  9922. const getCacheForId = id => get$g(cacheStorage, id).getOrThunk(() => {
  9923. const storageId = `tinymce-custom-colors-${ id }`;
  9924. const currentData = global$4.getItem(storageId);
  9925. if (isNullable(currentData)) {
  9926. const legacyDefault = global$4.getItem('tinymce-custom-colors');
  9927. global$4.setItem(storageId, isNonNullable(legacyDefault) ? legacyDefault : '[]');
  9928. }
  9929. const storage = ColorCache(storageId, 10);
  9930. cacheStorage[id] = storage;
  9931. return storage;
  9932. });
  9933. const getCurrentColors = id => map$2(getCacheForId(id).state(), color => ({
  9934. type: 'choiceitem',
  9935. text: color,
  9936. icon: 'checkmark',
  9937. value: color
  9938. }));
  9939. const addColor = (id, color) => {
  9940. getCacheForId(id).add(color);
  9941. };
  9942. const hsvColour = (hue, saturation, value) => ({
  9943. hue,
  9944. saturation,
  9945. value
  9946. });
  9947. const fromRgb = rgbaColour => {
  9948. let h = 0;
  9949. let s = 0;
  9950. let v = 0;
  9951. const r = rgbaColour.red / 255;
  9952. const g = rgbaColour.green / 255;
  9953. const b = rgbaColour.blue / 255;
  9954. const minRGB = Math.min(r, Math.min(g, b));
  9955. const maxRGB = Math.max(r, Math.max(g, b));
  9956. if (minRGB === maxRGB) {
  9957. v = minRGB;
  9958. return hsvColour(0, 0, v * 100);
  9959. }
  9960. const d = r === minRGB ? g - b : b === minRGB ? r - g : b - r;
  9961. h = r === minRGB ? 3 : b === minRGB ? 1 : 5;
  9962. h = 60 * (h - d / (maxRGB - minRGB));
  9963. s = (maxRGB - minRGB) / maxRGB;
  9964. v = maxRGB;
  9965. return hsvColour(Math.round(h), Math.round(s * 100), Math.round(v * 100));
  9966. };
  9967. const hexToHsv = hex => fromRgb(fromHex(hex));
  9968. const hsvToHex = hsv => fromRgba(fromHsv(hsv));
  9969. const anyToHex = color => fromString$1(color).orThunk(() => fromString(color).map(fromRgba)).getOrThunk(() => {
  9970. const canvas = document.createElement('canvas');
  9971. canvas.height = 1;
  9972. canvas.width = 1;
  9973. const canvasContext = canvas.getContext('2d');
  9974. canvasContext.clearRect(0, 0, canvas.width, canvas.height);
  9975. canvasContext.fillStyle = '#FFFFFF';
  9976. canvasContext.fillStyle = color;
  9977. canvasContext.fillRect(0, 0, 1, 1);
  9978. const rgba = canvasContext.getImageData(0, 0, 1, 1).data;
  9979. const r = rgba[0];
  9980. const g = rgba[1];
  9981. const b = rgba[2];
  9982. const a = rgba[3];
  9983. return fromRgba(rgbaColour(r, g, b, a));
  9984. });
  9985. const foregroundId = 'forecolor';
  9986. const backgroundId = 'hilitecolor';
  9987. const defaultCols = 5;
  9988. const calcCols = colors => Math.max(defaultCols, Math.ceil(Math.sqrt(colors)));
  9989. const calcColsOption = (editor, numColors) => {
  9990. const calculatedCols = calcCols(numColors);
  9991. const fallbackCols = option$1('color_cols')(editor);
  9992. return defaultCols === calculatedCols ? fallbackCols : calculatedCols;
  9993. };
  9994. const mapColors = colorMap => {
  9995. const colors = [];
  9996. for (let i = 0; i < colorMap.length; i += 2) {
  9997. colors.push({
  9998. text: colorMap[i + 1],
  9999. value: '#' + anyToHex(colorMap[i]).value,
  10000. icon: 'checkmark',
  10001. type: 'choiceitem'
  10002. });
  10003. }
  10004. return colors;
  10005. };
  10006. const option$1 = name => editor => editor.options.get(name);
  10007. const fallbackColor = '#000000';
  10008. const register$d = editor => {
  10009. const registerOption = editor.options.register;
  10010. const colorProcessor = value => {
  10011. if (isArrayOf(value, isString)) {
  10012. return {
  10013. value: mapColors(value),
  10014. valid: true
  10015. };
  10016. } else {
  10017. return {
  10018. valid: false,
  10019. message: 'Must be an array of strings.'
  10020. };
  10021. }
  10022. };
  10023. registerOption('color_map', {
  10024. processor: colorProcessor,
  10025. default: [
  10026. '#BFEDD2',
  10027. 'Light Green',
  10028. '#FBEEB8',
  10029. 'Light Yellow',
  10030. '#F8CAC6',
  10031. 'Light Red',
  10032. '#ECCAFA',
  10033. 'Light Purple',
  10034. '#C2E0F4',
  10035. 'Light Blue',
  10036. '#2DC26B',
  10037. 'Green',
  10038. '#F1C40F',
  10039. 'Yellow',
  10040. '#E03E2D',
  10041. 'Red',
  10042. '#B96AD9',
  10043. 'Purple',
  10044. '#3598DB',
  10045. 'Blue',
  10046. '#169179',
  10047. 'Dark Turquoise',
  10048. '#E67E23',
  10049. 'Orange',
  10050. '#BA372A',
  10051. 'Dark Red',
  10052. '#843FA1',
  10053. 'Dark Purple',
  10054. '#236FA1',
  10055. 'Dark Blue',
  10056. '#ECF0F1',
  10057. 'Light Gray',
  10058. '#CED4D9',
  10059. 'Medium Gray',
  10060. '#95A5A6',
  10061. 'Gray',
  10062. '#7E8C8D',
  10063. 'Dark Gray',
  10064. '#34495E',
  10065. 'Navy Blue',
  10066. '#000000',
  10067. 'Black',
  10068. '#ffffff',
  10069. 'White'
  10070. ]
  10071. });
  10072. registerOption('color_map_background', { processor: colorProcessor });
  10073. registerOption('color_map_foreground', { processor: colorProcessor });
  10074. registerOption('color_cols', {
  10075. processor: 'number',
  10076. default: calcCols(getColors$2(editor, 'default').length)
  10077. });
  10078. registerOption('color_cols_foreground', {
  10079. processor: 'number',
  10080. default: calcColsOption(editor, getColors$2(editor, foregroundId).length)
  10081. });
  10082. registerOption('color_cols_background', {
  10083. processor: 'number',
  10084. default: calcColsOption(editor, getColors$2(editor, backgroundId).length)
  10085. });
  10086. registerOption('custom_colors', {
  10087. processor: 'boolean',
  10088. default: true
  10089. });
  10090. registerOption('color_default_foreground', {
  10091. processor: 'string',
  10092. default: fallbackColor
  10093. });
  10094. registerOption('color_default_background', {
  10095. processor: 'string',
  10096. default: fallbackColor
  10097. });
  10098. };
  10099. const colorColsOption = (editor, id) => {
  10100. if (id === foregroundId) {
  10101. return option$1('color_cols_foreground')(editor);
  10102. } else if (id === backgroundId) {
  10103. return option$1('color_cols_background')(editor);
  10104. } else {
  10105. return option$1('color_cols')(editor);
  10106. }
  10107. };
  10108. const getColorCols$1 = (editor, id) => {
  10109. const colorCols = colorColsOption(editor, id);
  10110. return colorCols > 0 ? colorCols : defaultCols;
  10111. };
  10112. const hasCustomColors$1 = option$1('custom_colors');
  10113. const getColors$2 = (editor, id) => {
  10114. if (id === foregroundId && editor.options.isSet('color_map_foreground')) {
  10115. return option$1('color_map_foreground')(editor);
  10116. } else if (id === backgroundId && editor.options.isSet('color_map_background')) {
  10117. return option$1('color_map_background')(editor);
  10118. } else {
  10119. return option$1('color_map')(editor);
  10120. }
  10121. };
  10122. const getDefaultForegroundColor = option$1('color_default_foreground');
  10123. const getDefaultBackgroundColor = option$1('color_default_background');
  10124. const defaultBackgroundColor = 'rgba(0, 0, 0, 0)';
  10125. const isValidBackgroundColor = value => fromString(value).exists(c => c.alpha !== 0);
  10126. const getClosestCssBackgroundColorValue = scope => {
  10127. return closest$4(scope, node => {
  10128. if (isElement$1(node)) {
  10129. const color = get$e(node, 'background-color');
  10130. return someIf(isValidBackgroundColor(color), color);
  10131. } else {
  10132. return Optional.none();
  10133. }
  10134. }).getOr(defaultBackgroundColor);
  10135. };
  10136. const getCurrentColor = (editor, format) => {
  10137. const node = SugarElement.fromDom(editor.selection.getStart());
  10138. const cssRgbValue = format === 'hilitecolor' ? getClosestCssBackgroundColorValue(node) : get$e(node, 'color');
  10139. return fromString(cssRgbValue).map(rgba => '#' + fromRgba(rgba).value);
  10140. };
  10141. const applyFormat = (editor, format, value) => {
  10142. editor.undoManager.transact(() => {
  10143. editor.focus();
  10144. editor.formatter.apply(format, { value });
  10145. editor.nodeChanged();
  10146. });
  10147. };
  10148. const removeFormat = (editor, format) => {
  10149. editor.undoManager.transact(() => {
  10150. editor.focus();
  10151. editor.formatter.remove(format, { value: null }, undefined, true);
  10152. editor.nodeChanged();
  10153. });
  10154. };
  10155. const registerCommands = editor => {
  10156. editor.addCommand('mceApplyTextcolor', (format, value) => {
  10157. applyFormat(editor, format, value);
  10158. });
  10159. editor.addCommand('mceRemoveTextcolor', format => {
  10160. removeFormat(editor, format);
  10161. });
  10162. };
  10163. const getAdditionalColors = hasCustom => {
  10164. const type = 'choiceitem';
  10165. const remove = {
  10166. type,
  10167. text: 'Remove color',
  10168. icon: 'color-swatch-remove-color',
  10169. value: 'remove'
  10170. };
  10171. const custom = {
  10172. type,
  10173. text: 'Custom color',
  10174. icon: 'color-picker',
  10175. value: 'custom'
  10176. };
  10177. return hasCustom ? [
  10178. remove,
  10179. custom
  10180. ] : [remove];
  10181. };
  10182. const applyColor = (editor, format, value, onChoice) => {
  10183. if (value === 'custom') {
  10184. const dialog = colorPickerDialog(editor);
  10185. dialog(colorOpt => {
  10186. colorOpt.each(color => {
  10187. addColor(format, color);
  10188. editor.execCommand('mceApplyTextcolor', format, color);
  10189. onChoice(color);
  10190. });
  10191. }, getCurrentColor(editor, format).getOr(fallbackColor));
  10192. } else if (value === 'remove') {
  10193. onChoice('');
  10194. editor.execCommand('mceRemoveTextcolor', format);
  10195. } else {
  10196. onChoice(value);
  10197. editor.execCommand('mceApplyTextcolor', format, value);
  10198. }
  10199. };
  10200. const getColors$1 = (colors, id, hasCustom) => colors.concat(getCurrentColors(id).concat(getAdditionalColors(hasCustom)));
  10201. const getFetch$1 = (colors, id, hasCustom) => callback => {
  10202. callback(getColors$1(colors, id, hasCustom));
  10203. };
  10204. const setIconColor = (splitButtonApi, name, newColor) => {
  10205. const id = name === 'forecolor' ? 'tox-icon-text-color__color' : 'tox-icon-highlight-bg-color__color';
  10206. splitButtonApi.setIconFill(id, newColor);
  10207. };
  10208. const select$1 = (editor, format) => value => {
  10209. const optCurrentHex = getCurrentColor(editor, format);
  10210. return is$1(optCurrentHex, value.toUpperCase());
  10211. };
  10212. const registerTextColorButton = (editor, name, format, tooltip, lastColor) => {
  10213. editor.ui.registry.addSplitButton(name, {
  10214. tooltip,
  10215. presets: 'color',
  10216. icon: name === 'forecolor' ? 'text-color' : 'highlight-bg-color',
  10217. select: select$1(editor, format),
  10218. columns: getColorCols$1(editor, format),
  10219. fetch: getFetch$1(getColors$2(editor, format), format, hasCustomColors$1(editor)),
  10220. onAction: _splitButtonApi => {
  10221. applyColor(editor, format, lastColor.get(), noop);
  10222. },
  10223. onItemAction: (_splitButtonApi, value) => {
  10224. applyColor(editor, format, value, newColor => {
  10225. lastColor.set(newColor);
  10226. fireTextColorChange(editor, {
  10227. name,
  10228. color: newColor
  10229. });
  10230. });
  10231. },
  10232. onSetup: splitButtonApi => {
  10233. setIconColor(splitButtonApi, name, lastColor.get());
  10234. const handler = e => {
  10235. if (e.name === name) {
  10236. setIconColor(splitButtonApi, e.name, e.color);
  10237. }
  10238. };
  10239. editor.on('TextColorChange', handler);
  10240. return () => {
  10241. editor.off('TextColorChange', handler);
  10242. };
  10243. }
  10244. });
  10245. };
  10246. const registerTextColorMenuItem = (editor, name, format, text, lastColor) => {
  10247. editor.ui.registry.addNestedMenuItem(name, {
  10248. text,
  10249. icon: name === 'forecolor' ? 'text-color' : 'highlight-bg-color',
  10250. onSetup: api => {
  10251. setIconColor(api, name, lastColor.get());
  10252. return noop;
  10253. },
  10254. getSubmenuItems: () => [{
  10255. type: 'fancymenuitem',
  10256. fancytype: 'colorswatch',
  10257. select: select$1(editor, format),
  10258. initData: { storageKey: format },
  10259. onAction: data => {
  10260. applyColor(editor, format, data.value, newColor => {
  10261. lastColor.set(newColor);
  10262. fireTextColorChange(editor, {
  10263. name,
  10264. color: newColor
  10265. });
  10266. });
  10267. }
  10268. }]
  10269. });
  10270. };
  10271. const colorPickerDialog = editor => (callback, value) => {
  10272. let isValid = false;
  10273. const onSubmit = api => {
  10274. const data = api.getData();
  10275. const hex = data.colorpicker;
  10276. if (isValid) {
  10277. callback(Optional.from(hex));
  10278. api.close();
  10279. } else {
  10280. editor.windowManager.alert(editor.translate([
  10281. 'Invalid hex color code: {0}',
  10282. hex
  10283. ]));
  10284. }
  10285. };
  10286. const onAction = (_api, details) => {
  10287. if (details.name === 'hex-valid') {
  10288. isValid = details.value;
  10289. }
  10290. };
  10291. const initialData = { colorpicker: value };
  10292. editor.windowManager.open({
  10293. title: 'Color Picker',
  10294. size: 'normal',
  10295. body: {
  10296. type: 'panel',
  10297. items: [{
  10298. type: 'colorpicker',
  10299. name: 'colorpicker',
  10300. label: 'Color'
  10301. }]
  10302. },
  10303. buttons: [
  10304. {
  10305. type: 'cancel',
  10306. name: 'cancel',
  10307. text: 'Cancel'
  10308. },
  10309. {
  10310. type: 'submit',
  10311. name: 'save',
  10312. text: 'Save',
  10313. primary: true
  10314. }
  10315. ],
  10316. initialData,
  10317. onAction,
  10318. onSubmit,
  10319. onClose: noop,
  10320. onCancel: () => {
  10321. callback(Optional.none());
  10322. }
  10323. });
  10324. };
  10325. const register$c = editor => {
  10326. registerCommands(editor);
  10327. const fallbackColorForeground = getDefaultForegroundColor(editor);
  10328. const fallbackColorBackground = getDefaultBackgroundColor(editor);
  10329. const lastForeColor = Cell(fallbackColorForeground);
  10330. const lastBackColor = Cell(fallbackColorBackground);
  10331. registerTextColorButton(editor, 'forecolor', 'forecolor', 'Text color', lastForeColor);
  10332. registerTextColorButton(editor, 'backcolor', 'hilitecolor', 'Background color', lastBackColor);
  10333. registerTextColorMenuItem(editor, 'forecolor', 'forecolor', 'Text color', lastForeColor);
  10334. registerTextColorMenuItem(editor, 'backcolor', 'hilitecolor', 'Background color', lastBackColor);
  10335. };
  10336. const createPartialChoiceMenu = (value, items, onItemValueHandler, columns, presets, itemResponse, select, providersBackstage) => {
  10337. const hasIcons = menuHasIcons(items);
  10338. const presetItemTypes = presets !== 'color' ? 'normal' : 'color';
  10339. const alloyItems = createChoiceItems(items, onItemValueHandler, columns, presetItemTypes, itemResponse, select, providersBackstage);
  10340. const menuLayout = { menuType: presets };
  10341. return createPartialMenuWithAlloyItems(value, hasIcons, alloyItems, columns, menuLayout);
  10342. };
  10343. const createChoiceItems = (items, onItemValueHandler, columns, itemPresets, itemResponse, select, providersBackstage) => cat(map$2(items, item => {
  10344. if (item.type === 'choiceitem') {
  10345. return createChoiceMenuItem(item).fold(handleError, d => Optional.some(renderChoiceItem(d, columns === 1, itemPresets, onItemValueHandler, select(d.value), itemResponse, providersBackstage, menuHasIcons(items))));
  10346. } else {
  10347. return Optional.none();
  10348. }
  10349. }));
  10350. const deriveMenuMovement = (columns, presets) => {
  10351. const menuMarkers = markers(presets);
  10352. if (columns === 1) {
  10353. return {
  10354. mode: 'menu',
  10355. moveOnTab: true
  10356. };
  10357. } else if (columns === 'auto') {
  10358. return {
  10359. mode: 'grid',
  10360. selector: '.' + menuMarkers.item,
  10361. initSize: {
  10362. numColumns: 1,
  10363. numRows: 1
  10364. }
  10365. };
  10366. } else {
  10367. const rowClass = presets === 'color' ? 'tox-swatches__row' : 'tox-collection__group';
  10368. return {
  10369. mode: 'matrix',
  10370. rowSelector: '.' + rowClass,
  10371. previousSelector: menu => {
  10372. return presets === 'color' ? descendant(menu.element, '[aria-checked=true]') : Optional.none();
  10373. }
  10374. };
  10375. }
  10376. };
  10377. const deriveCollectionMovement = (columns, presets) => {
  10378. if (columns === 1) {
  10379. return {
  10380. mode: 'menu',
  10381. moveOnTab: false,
  10382. selector: '.tox-collection__item'
  10383. };
  10384. } else if (columns === 'auto') {
  10385. return {
  10386. mode: 'flatgrid',
  10387. selector: '.' + 'tox-collection__item',
  10388. initSize: {
  10389. numColumns: 1,
  10390. numRows: 1
  10391. }
  10392. };
  10393. } else {
  10394. return {
  10395. mode: 'matrix',
  10396. selectors: {
  10397. row: presets === 'color' ? '.tox-swatches__row' : '.tox-collection__group',
  10398. cell: presets === 'color' ? `.${ colorClass }` : `.${ selectableClass }`
  10399. }
  10400. };
  10401. }
  10402. };
  10403. const renderColorSwatchItem = (spec, backstage) => {
  10404. const items = getColorItems(spec, backstage);
  10405. const columns = backstage.colorinput.getColorCols(spec.initData.storageKey);
  10406. const presets = 'color';
  10407. const menuSpec = createPartialChoiceMenu(generate$6('menu-value'), items, value => {
  10408. spec.onAction({ value });
  10409. }, columns, presets, ItemResponse$1.CLOSE_ON_EXECUTE, spec.select.getOr(never), backstage.shared.providers);
  10410. const widgetSpec = {
  10411. ...menuSpec,
  10412. markers: markers(presets),
  10413. movement: deriveMenuMovement(columns, presets)
  10414. };
  10415. return {
  10416. type: 'widget',
  10417. data: { value: generate$6('widget-id') },
  10418. dom: {
  10419. tag: 'div',
  10420. classes: ['tox-fancymenuitem']
  10421. },
  10422. autofocus: true,
  10423. components: [parts$f.widget(Menu.sketch(widgetSpec))]
  10424. };
  10425. };
  10426. const getColorItems = (spec, backstage) => {
  10427. const useCustomColors = spec.initData.allowCustomColors && backstage.colorinput.hasCustomColors();
  10428. return spec.initData.colors.fold(() => getColors$1(backstage.colorinput.getColors(spec.initData.storageKey), spec.initData.storageKey, useCustomColors), colors => colors.concat(getAdditionalColors(useCustomColors)));
  10429. };
  10430. const cellOverEvent = generate$6('cell-over');
  10431. const cellExecuteEvent = generate$6('cell-execute');
  10432. const makeCell = (row, col, labelId) => {
  10433. const emitCellOver = c => emitWith(c, cellOverEvent, {
  10434. row,
  10435. col
  10436. });
  10437. const emitExecute = c => emitWith(c, cellExecuteEvent, {
  10438. row,
  10439. col
  10440. });
  10441. const onClick = (c, se) => {
  10442. se.stop();
  10443. emitExecute(c);
  10444. };
  10445. return build$1({
  10446. dom: {
  10447. tag: 'div',
  10448. attributes: {
  10449. role: 'button',
  10450. ['aria-labelledby']: labelId
  10451. }
  10452. },
  10453. behaviours: derive$1([
  10454. config('insert-table-picker-cell', [
  10455. run$1(mouseover(), Focusing.focus),
  10456. run$1(execute$5(), emitExecute),
  10457. run$1(click(), onClick),
  10458. run$1(tap(), onClick)
  10459. ]),
  10460. Toggling.config({
  10461. toggleClass: 'tox-insert-table-picker__selected',
  10462. toggleOnExecute: false
  10463. }),
  10464. Focusing.config({ onFocus: emitCellOver })
  10465. ])
  10466. });
  10467. };
  10468. const makeCells = (labelId, numRows, numCols) => {
  10469. const cells = [];
  10470. for (let i = 0; i < numRows; i++) {
  10471. const row = [];
  10472. for (let j = 0; j < numCols; j++) {
  10473. row.push(makeCell(i, j, labelId));
  10474. }
  10475. cells.push(row);
  10476. }
  10477. return cells;
  10478. };
  10479. const selectCells = (cells, selectedRow, selectedColumn, numRows, numColumns) => {
  10480. for (let i = 0; i < numRows; i++) {
  10481. for (let j = 0; j < numColumns; j++) {
  10482. Toggling.set(cells[i][j], i <= selectedRow && j <= selectedColumn);
  10483. }
  10484. }
  10485. };
  10486. const makeComponents = cells => bind$3(cells, cellRow => map$2(cellRow, premade));
  10487. const makeLabelText = (row, col) => text$2(`${ col }x${ row }`);
  10488. const renderInsertTableMenuItem = spec => {
  10489. const numRows = 10;
  10490. const numColumns = 10;
  10491. const sizeLabelId = generate$6('size-label');
  10492. const cells = makeCells(sizeLabelId, numRows, numColumns);
  10493. const emptyLabelText = makeLabelText(0, 0);
  10494. const memLabel = record({
  10495. dom: {
  10496. tag: 'span',
  10497. classes: ['tox-insert-table-picker__label'],
  10498. attributes: { id: sizeLabelId }
  10499. },
  10500. components: [emptyLabelText],
  10501. behaviours: derive$1([Replacing.config({})])
  10502. });
  10503. return {
  10504. type: 'widget',
  10505. data: { value: generate$6('widget-id') },
  10506. dom: {
  10507. tag: 'div',
  10508. classes: ['tox-fancymenuitem']
  10509. },
  10510. autofocus: true,
  10511. components: [parts$f.widget({
  10512. dom: {
  10513. tag: 'div',
  10514. classes: ['tox-insert-table-picker']
  10515. },
  10516. components: makeComponents(cells).concat(memLabel.asSpec()),
  10517. behaviours: derive$1([
  10518. config('insert-table-picker', [
  10519. runOnAttached(c => {
  10520. Replacing.set(memLabel.get(c), [emptyLabelText]);
  10521. }),
  10522. runWithTarget(cellOverEvent, (c, t, e) => {
  10523. const {row, col} = e.event;
  10524. selectCells(cells, row, col, numRows, numColumns);
  10525. Replacing.set(memLabel.get(c), [makeLabelText(row + 1, col + 1)]);
  10526. }),
  10527. runWithTarget(cellExecuteEvent, (c, _, e) => {
  10528. const {row, col} = e.event;
  10529. spec.onAction({
  10530. numRows: row + 1,
  10531. numColumns: col + 1
  10532. });
  10533. emit(c, sandboxClose());
  10534. })
  10535. ]),
  10536. Keying.config({
  10537. initSize: {
  10538. numRows,
  10539. numColumns
  10540. },
  10541. mode: 'flatgrid',
  10542. selector: '[role="button"]'
  10543. })
  10544. ])
  10545. })]
  10546. };
  10547. };
  10548. const fancyMenuItems = {
  10549. inserttable: renderInsertTableMenuItem,
  10550. colorswatch: renderColorSwatchItem
  10551. };
  10552. const renderFancyMenuItem = (spec, backstage) => get$g(fancyMenuItems, spec.fancytype).map(render => render(spec, backstage));
  10553. const renderNestedItem = (spec, itemResponse, providersBackstage, renderIcons = true, downwardsCaret = false) => {
  10554. const caret = downwardsCaret ? renderDownwardsCaret(providersBackstage.icons) : renderSubmenuCaret(providersBackstage.icons);
  10555. const getApi = component => ({
  10556. isEnabled: () => !Disabling.isDisabled(component),
  10557. setEnabled: state => Disabling.set(component, !state),
  10558. setIconFill: (id, value) => {
  10559. descendant(component.element, `svg path[id="${ id }"], rect[id="${ id }"]`).each(underlinePath => {
  10560. set$9(underlinePath, 'fill', value);
  10561. });
  10562. }
  10563. });
  10564. const structure = renderItemStructure({
  10565. presets: 'normal',
  10566. iconContent: spec.icon,
  10567. textContent: spec.text,
  10568. htmlContent: Optional.none(),
  10569. ariaLabel: spec.text,
  10570. caret: Optional.some(caret),
  10571. checkMark: Optional.none(),
  10572. shortcutContent: spec.shortcut
  10573. }, providersBackstage, renderIcons);
  10574. return renderCommonItem({
  10575. data: buildData(spec),
  10576. getApi,
  10577. enabled: spec.enabled,
  10578. onAction: noop,
  10579. onSetup: spec.onSetup,
  10580. triggersSubmenu: true,
  10581. itemBehaviours: []
  10582. }, structure, itemResponse, providersBackstage);
  10583. };
  10584. const renderNormalItem = (spec, itemResponse, providersBackstage, renderIcons = true) => {
  10585. const getApi = component => ({
  10586. isEnabled: () => !Disabling.isDisabled(component),
  10587. setEnabled: state => Disabling.set(component, !state)
  10588. });
  10589. const structure = renderItemStructure({
  10590. presets: 'normal',
  10591. iconContent: spec.icon,
  10592. textContent: spec.text,
  10593. htmlContent: Optional.none(),
  10594. ariaLabel: spec.text,
  10595. caret: Optional.none(),
  10596. checkMark: Optional.none(),
  10597. shortcutContent: spec.shortcut
  10598. }, providersBackstage, renderIcons);
  10599. return renderCommonItem({
  10600. data: buildData(spec),
  10601. getApi,
  10602. enabled: spec.enabled,
  10603. onAction: spec.onAction,
  10604. onSetup: spec.onSetup,
  10605. triggersSubmenu: false,
  10606. itemBehaviours: []
  10607. }, structure, itemResponse, providersBackstage);
  10608. };
  10609. const renderSeparatorItem = spec => ({
  10610. type: 'separator',
  10611. dom: {
  10612. tag: 'div',
  10613. classes: [
  10614. selectableClass,
  10615. groupHeadingClass
  10616. ]
  10617. },
  10618. components: spec.text.map(text$2).toArray()
  10619. });
  10620. const renderToggleMenuItem = (spec, itemResponse, providersBackstage, renderIcons = true) => {
  10621. const getApi = component => ({
  10622. setActive: state => {
  10623. Toggling.set(component, state);
  10624. },
  10625. isActive: () => Toggling.isOn(component),
  10626. isEnabled: () => !Disabling.isDisabled(component),
  10627. setEnabled: state => Disabling.set(component, !state)
  10628. });
  10629. const structure = renderItemStructure({
  10630. iconContent: spec.icon,
  10631. textContent: spec.text,
  10632. htmlContent: Optional.none(),
  10633. ariaLabel: spec.text,
  10634. checkMark: Optional.some(renderCheckmark(providersBackstage.icons)),
  10635. caret: Optional.none(),
  10636. shortcutContent: spec.shortcut,
  10637. presets: 'normal',
  10638. meta: spec.meta
  10639. }, providersBackstage, renderIcons);
  10640. return deepMerge(renderCommonItem({
  10641. data: buildData(spec),
  10642. enabled: spec.enabled,
  10643. getApi,
  10644. onAction: spec.onAction,
  10645. onSetup: spec.onSetup,
  10646. triggersSubmenu: false,
  10647. itemBehaviours: []
  10648. }, structure, itemResponse, providersBackstage), {
  10649. toggling: {
  10650. toggleClass: tickedClass,
  10651. toggleOnExecute: false,
  10652. selected: spec.active
  10653. }
  10654. });
  10655. };
  10656. const autocomplete = renderAutocompleteItem;
  10657. const separator$3 = renderSeparatorItem;
  10658. const normal = renderNormalItem;
  10659. const nested = renderNestedItem;
  10660. const toggle$1 = renderToggleMenuItem;
  10661. const fancy = renderFancyMenuItem;
  10662. const card = renderCardMenuItem;
  10663. const getCoupled = (component, coupleConfig, coupleState, name) => coupleState.getOrCreate(component, coupleConfig, name);
  10664. const getExistingCoupled = (component, coupleConfig, coupleState, name) => coupleState.getExisting(component, coupleConfig, name);
  10665. var CouplingApis = /*#__PURE__*/Object.freeze({
  10666. __proto__: null,
  10667. getCoupled: getCoupled,
  10668. getExistingCoupled: getExistingCoupled
  10669. });
  10670. var CouplingSchema = [requiredOf('others', setOf(Result.value, anyValue()))];
  10671. const init$a = () => {
  10672. const coupled = {};
  10673. const lookupCoupled = (coupleConfig, coupledName) => {
  10674. const available = keys(coupleConfig.others);
  10675. if (available.length === 0) {
  10676. throw new Error('Cannot find any known coupled components');
  10677. } else {
  10678. return get$g(coupled, coupledName);
  10679. }
  10680. };
  10681. const getOrCreate = (component, coupleConfig, name) => {
  10682. return lookupCoupled(coupleConfig, name).getOrThunk(() => {
  10683. const builder = get$g(coupleConfig.others, name).getOrDie('No information found for coupled component: ' + name);
  10684. const spec = builder(component);
  10685. const built = component.getSystem().build(spec);
  10686. coupled[name] = built;
  10687. return built;
  10688. });
  10689. };
  10690. const getExisting = (component, coupleConfig, name) => {
  10691. return lookupCoupled(coupleConfig, name).orThunk(() => {
  10692. get$g(coupleConfig.others, name).getOrDie('No information found for coupled component: ' + name);
  10693. return Optional.none();
  10694. });
  10695. };
  10696. const readState = constant$1({});
  10697. return nu$8({
  10698. readState,
  10699. getExisting,
  10700. getOrCreate
  10701. });
  10702. };
  10703. var CouplingState = /*#__PURE__*/Object.freeze({
  10704. __proto__: null,
  10705. init: init$a
  10706. });
  10707. const Coupling = create$4({
  10708. fields: CouplingSchema,
  10709. name: 'coupling',
  10710. apis: CouplingApis,
  10711. state: CouplingState
  10712. });
  10713. const nu$3 = baseFn => {
  10714. let data = Optional.none();
  10715. let callbacks = [];
  10716. const map = f => nu$3(nCallback => {
  10717. get(data => {
  10718. nCallback(f(data));
  10719. });
  10720. });
  10721. const get = nCallback => {
  10722. if (isReady()) {
  10723. call(nCallback);
  10724. } else {
  10725. callbacks.push(nCallback);
  10726. }
  10727. };
  10728. const set = x => {
  10729. if (!isReady()) {
  10730. data = Optional.some(x);
  10731. run(callbacks);
  10732. callbacks = [];
  10733. }
  10734. };
  10735. const isReady = () => data.isSome();
  10736. const run = cbs => {
  10737. each$1(cbs, call);
  10738. };
  10739. const call = cb => {
  10740. data.each(x => {
  10741. setTimeout(() => {
  10742. cb(x);
  10743. }, 0);
  10744. });
  10745. };
  10746. baseFn(set);
  10747. return {
  10748. get,
  10749. map,
  10750. isReady
  10751. };
  10752. };
  10753. const pure$1 = a => nu$3(callback => {
  10754. callback(a);
  10755. });
  10756. const LazyValue = {
  10757. nu: nu$3,
  10758. pure: pure$1
  10759. };
  10760. const errorReporter = err => {
  10761. setTimeout(() => {
  10762. throw err;
  10763. }, 0);
  10764. };
  10765. const make$5 = run => {
  10766. const get = callback => {
  10767. run().then(callback, errorReporter);
  10768. };
  10769. const map = fab => {
  10770. return make$5(() => run().then(fab));
  10771. };
  10772. const bind = aFutureB => {
  10773. return make$5(() => run().then(v => aFutureB(v).toPromise()));
  10774. };
  10775. const anonBind = futureB => {
  10776. return make$5(() => run().then(() => futureB.toPromise()));
  10777. };
  10778. const toLazy = () => {
  10779. return LazyValue.nu(get);
  10780. };
  10781. const toCached = () => {
  10782. let cache = null;
  10783. return make$5(() => {
  10784. if (cache === null) {
  10785. cache = run();
  10786. }
  10787. return cache;
  10788. });
  10789. };
  10790. const toPromise = run;
  10791. return {
  10792. map,
  10793. bind,
  10794. anonBind,
  10795. toLazy,
  10796. toCached,
  10797. toPromise,
  10798. get
  10799. };
  10800. };
  10801. const nu$2 = baseFn => {
  10802. return make$5(() => new Promise(baseFn));
  10803. };
  10804. const pure = a => {
  10805. return make$5(() => Promise.resolve(a));
  10806. };
  10807. const Future = {
  10808. nu: nu$2,
  10809. pure
  10810. };
  10811. const suffix = constant$1('sink');
  10812. const partType$1 = constant$1(optional({
  10813. name: suffix(),
  10814. overrides: constant$1({
  10815. dom: { tag: 'div' },
  10816. behaviours: derive$1([Positioning.config({ useFixed: always })]),
  10817. events: derive$2([
  10818. cutter(keydown()),
  10819. cutter(mousedown()),
  10820. cutter(click())
  10821. ])
  10822. })
  10823. }));
  10824. const getAnchor = (detail, component) => {
  10825. const hotspot = detail.getHotspot(component).getOr(component);
  10826. const type = 'hotspot';
  10827. const overrides = detail.getAnchorOverrides();
  10828. return detail.layouts.fold(() => ({
  10829. type,
  10830. hotspot,
  10831. overrides
  10832. }), layouts => ({
  10833. type,
  10834. hotspot,
  10835. overrides,
  10836. layouts
  10837. }));
  10838. };
  10839. const fetch = (detail, mapFetch, component) => {
  10840. const fetcher = detail.fetch;
  10841. return fetcher(component).map(mapFetch);
  10842. };
  10843. const openF = (detail, mapFetch, anchor, component, sandbox, externals, highlightOnOpen) => {
  10844. const futureData = fetch(detail, mapFetch, component);
  10845. const getLazySink = getSink(component, detail);
  10846. return futureData.map(tdata => tdata.bind(data => Optional.from(tieredMenu.sketch({
  10847. ...externals.menu(),
  10848. uid: generate$5(''),
  10849. data,
  10850. highlightOnOpen,
  10851. onOpenMenu: (tmenu, menu) => {
  10852. const sink = getLazySink().getOrDie();
  10853. Positioning.position(sink, menu, { anchor });
  10854. Sandboxing.decloak(sandbox);
  10855. },
  10856. onOpenSubmenu: (tmenu, item, submenu) => {
  10857. const sink = getLazySink().getOrDie();
  10858. Positioning.position(sink, submenu, {
  10859. anchor: {
  10860. type: 'submenu',
  10861. item
  10862. }
  10863. });
  10864. Sandboxing.decloak(sandbox);
  10865. },
  10866. onRepositionMenu: (tmenu, primaryMenu, submenuTriggers) => {
  10867. const sink = getLazySink().getOrDie();
  10868. Positioning.position(sink, primaryMenu, { anchor });
  10869. each$1(submenuTriggers, st => {
  10870. Positioning.position(sink, st.triggeredMenu, {
  10871. anchor: {
  10872. type: 'submenu',
  10873. item: st.triggeringItem
  10874. }
  10875. });
  10876. });
  10877. },
  10878. onEscape: () => {
  10879. Focusing.focus(component);
  10880. Sandboxing.close(sandbox);
  10881. return Optional.some(true);
  10882. }
  10883. }))));
  10884. };
  10885. const open = (detail, mapFetch, hotspot, sandbox, externals, onOpenSync, highlightOnOpen) => {
  10886. const anchor = getAnchor(detail, hotspot);
  10887. const processed = openF(detail, mapFetch, anchor, hotspot, sandbox, externals, highlightOnOpen);
  10888. return processed.map(tdata => {
  10889. tdata.fold(() => {
  10890. if (Sandboxing.isOpen(sandbox)) {
  10891. Sandboxing.close(sandbox);
  10892. }
  10893. }, data => {
  10894. Sandboxing.cloak(sandbox);
  10895. Sandboxing.open(sandbox, data);
  10896. onOpenSync(sandbox);
  10897. });
  10898. return sandbox;
  10899. });
  10900. };
  10901. const close = (detail, mapFetch, component, sandbox, _externals, _onOpenSync, _highlightOnOpen) => {
  10902. Sandboxing.close(sandbox);
  10903. return Future.pure(sandbox);
  10904. };
  10905. const togglePopup = (detail, mapFetch, hotspot, externals, onOpenSync, highlightOnOpen) => {
  10906. const sandbox = Coupling.getCoupled(hotspot, 'sandbox');
  10907. const showing = Sandboxing.isOpen(sandbox);
  10908. const action = showing ? close : open;
  10909. return action(detail, mapFetch, hotspot, sandbox, externals, onOpenSync, highlightOnOpen);
  10910. };
  10911. const matchWidth = (hotspot, container, useMinWidth) => {
  10912. const menu = Composing.getCurrent(container).getOr(container);
  10913. const buttonWidth = get$c(hotspot.element);
  10914. if (useMinWidth) {
  10915. set$8(menu.element, 'min-width', buttonWidth + 'px');
  10916. } else {
  10917. set$7(menu.element, buttonWidth);
  10918. }
  10919. };
  10920. 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)));
  10921. const doRepositionMenus = sandbox => {
  10922. Sandboxing.getState(sandbox).each(tmenu => {
  10923. tieredMenu.repositionMenus(tmenu);
  10924. });
  10925. };
  10926. const makeSandbox$1 = (detail, hotspot, extras) => {
  10927. const ariaControls = manager();
  10928. const onOpen = (component, menu) => {
  10929. const anchor = getAnchor(detail, hotspot);
  10930. ariaControls.link(hotspot.element);
  10931. if (detail.matchWidth) {
  10932. matchWidth(anchor.hotspot, menu, detail.useMinWidth);
  10933. }
  10934. detail.onOpen(anchor, component, menu);
  10935. if (extras !== undefined && extras.onOpen !== undefined) {
  10936. extras.onOpen(component, menu);
  10937. }
  10938. };
  10939. const onClose = (component, menu) => {
  10940. ariaControls.unlink(hotspot.element);
  10941. if (extras !== undefined && extras.onClose !== undefined) {
  10942. extras.onClose(component, menu);
  10943. }
  10944. };
  10945. const lazySink = getSink(hotspot, detail);
  10946. return {
  10947. dom: {
  10948. tag: 'div',
  10949. classes: detail.sandboxClasses,
  10950. attributes: {
  10951. id: ariaControls.id,
  10952. role: 'listbox'
  10953. }
  10954. },
  10955. behaviours: SketchBehaviours.augment(detail.sandboxBehaviours, [
  10956. Representing.config({
  10957. store: {
  10958. mode: 'memory',
  10959. initialValue: hotspot
  10960. }
  10961. }),
  10962. Sandboxing.config({
  10963. onOpen,
  10964. onClose,
  10965. isPartOf: (container, data, queryElem) => {
  10966. return isPartOf$1(data, queryElem) || isPartOf$1(hotspot, queryElem);
  10967. },
  10968. getAttachPoint: () => {
  10969. return lazySink().getOrDie();
  10970. }
  10971. }),
  10972. Composing.config({
  10973. find: sandbox => {
  10974. return Sandboxing.getState(sandbox).bind(menu => Composing.getCurrent(menu));
  10975. }
  10976. }),
  10977. Receiving.config({
  10978. channels: {
  10979. ...receivingChannel$1({ isExtraPart: never }),
  10980. ...receivingChannel({ doReposition: doRepositionMenus })
  10981. }
  10982. })
  10983. ])
  10984. };
  10985. };
  10986. const repositionMenus = comp => {
  10987. const sandbox = Coupling.getCoupled(comp, 'sandbox');
  10988. doRepositionMenus(sandbox);
  10989. };
  10990. const sandboxFields = () => [
  10991. defaulted('sandboxClasses', []),
  10992. SketchBehaviours.field('sandboxBehaviours', [
  10993. Composing,
  10994. Receiving,
  10995. Sandboxing,
  10996. Representing
  10997. ])
  10998. ];
  10999. const schema$k = constant$1([
  11000. required$1('dom'),
  11001. required$1('fetch'),
  11002. onHandler('onOpen'),
  11003. onKeyboardHandler('onExecute'),
  11004. defaulted('getHotspot', Optional.some),
  11005. defaulted('getAnchorOverrides', constant$1({})),
  11006. schema$y(),
  11007. field('dropdownBehaviours', [
  11008. Toggling,
  11009. Coupling,
  11010. Keying,
  11011. Focusing
  11012. ]),
  11013. required$1('toggleClass'),
  11014. defaulted('eventOrder', {}),
  11015. option$3('lazySink'),
  11016. defaulted('matchWidth', false),
  11017. defaulted('useMinWidth', false),
  11018. option$3('role')
  11019. ].concat(sandboxFields()));
  11020. const parts$e = constant$1([
  11021. external({
  11022. schema: [
  11023. tieredMenuMarkers(),
  11024. defaulted('fakeFocus', false)
  11025. ],
  11026. name: 'menu',
  11027. defaults: detail => {
  11028. return { onExecute: detail.onExecute };
  11029. }
  11030. }),
  11031. partType$1()
  11032. ]);
  11033. const factory$k = (detail, components, _spec, externals) => {
  11034. const lookupAttr = attr => get$g(detail.dom, 'attributes').bind(attrs => get$g(attrs, attr));
  11035. const switchToMenu = sandbox => {
  11036. Sandboxing.getState(sandbox).each(tmenu => {
  11037. tieredMenu.highlightPrimary(tmenu);
  11038. });
  11039. };
  11040. const togglePopup$1 = (dropdownComp, onOpenSync, highlightOnOpen) => {
  11041. return togglePopup(detail, identity, dropdownComp, externals, onOpenSync, highlightOnOpen);
  11042. };
  11043. const action = component => {
  11044. const onOpenSync = switchToMenu;
  11045. togglePopup$1(component, onOpenSync, HighlightOnOpen.HighlightMenuAndItem).get(noop);
  11046. };
  11047. const apis = {
  11048. expand: comp => {
  11049. if (!Toggling.isOn(comp)) {
  11050. togglePopup$1(comp, noop, HighlightOnOpen.HighlightNone).get(noop);
  11051. }
  11052. },
  11053. open: comp => {
  11054. if (!Toggling.isOn(comp)) {
  11055. togglePopup$1(comp, noop, HighlightOnOpen.HighlightMenuAndItem).get(noop);
  11056. }
  11057. },
  11058. refetch: comp => {
  11059. const optSandbox = Coupling.getExistingCoupled(comp, 'sandbox');
  11060. return optSandbox.fold(() => {
  11061. return togglePopup$1(comp, noop, HighlightOnOpen.HighlightMenuAndItem).map(noop);
  11062. }, sandboxComp => {
  11063. return open(detail, identity, comp, sandboxComp, externals, noop, HighlightOnOpen.HighlightMenuAndItem).map(noop);
  11064. });
  11065. },
  11066. isOpen: Toggling.isOn,
  11067. close: comp => {
  11068. if (Toggling.isOn(comp)) {
  11069. togglePopup$1(comp, noop, HighlightOnOpen.HighlightMenuAndItem).get(noop);
  11070. }
  11071. },
  11072. repositionMenus: comp => {
  11073. if (Toggling.isOn(comp)) {
  11074. repositionMenus(comp);
  11075. }
  11076. }
  11077. };
  11078. const triggerExecute = (comp, _se) => {
  11079. emitExecute(comp);
  11080. return Optional.some(true);
  11081. };
  11082. return {
  11083. uid: detail.uid,
  11084. dom: detail.dom,
  11085. components,
  11086. behaviours: augment(detail.dropdownBehaviours, [
  11087. Toggling.config({
  11088. toggleClass: detail.toggleClass,
  11089. aria: { mode: 'expanded' }
  11090. }),
  11091. Coupling.config({
  11092. others: {
  11093. sandbox: hotspot => {
  11094. return makeSandbox$1(detail, hotspot, {
  11095. onOpen: () => Toggling.on(hotspot),
  11096. onClose: () => Toggling.off(hotspot)
  11097. });
  11098. }
  11099. }
  11100. }),
  11101. Keying.config({
  11102. mode: 'special',
  11103. onSpace: triggerExecute,
  11104. onEnter: triggerExecute,
  11105. onDown: (comp, _se) => {
  11106. if (Dropdown.isOpen(comp)) {
  11107. const sandbox = Coupling.getCoupled(comp, 'sandbox');
  11108. switchToMenu(sandbox);
  11109. } else {
  11110. Dropdown.open(comp);
  11111. }
  11112. return Optional.some(true);
  11113. },
  11114. onEscape: (comp, _se) => {
  11115. if (Dropdown.isOpen(comp)) {
  11116. Dropdown.close(comp);
  11117. return Optional.some(true);
  11118. } else {
  11119. return Optional.none();
  11120. }
  11121. }
  11122. }),
  11123. Focusing.config({})
  11124. ]),
  11125. events: events$a(Optional.some(action)),
  11126. eventOrder: {
  11127. ...detail.eventOrder,
  11128. [execute$5()]: [
  11129. 'disabling',
  11130. 'toggling',
  11131. 'alloy.base.behaviour'
  11132. ]
  11133. },
  11134. apis,
  11135. domModification: {
  11136. attributes: {
  11137. 'aria-haspopup': 'true',
  11138. ...detail.role.fold(() => ({}), role => ({ role })),
  11139. ...detail.dom.tag === 'button' ? { type: lookupAttr('type').getOr('button') } : {}
  11140. }
  11141. }
  11142. };
  11143. };
  11144. const Dropdown = composite({
  11145. name: 'Dropdown',
  11146. configFields: schema$k(),
  11147. partFields: parts$e(),
  11148. factory: factory$k,
  11149. apis: {
  11150. open: (apis, comp) => apis.open(comp),
  11151. refetch: (apis, comp) => apis.refetch(comp),
  11152. expand: (apis, comp) => apis.expand(comp),
  11153. close: (apis, comp) => apis.close(comp),
  11154. isOpen: (apis, comp) => apis.isOpen(comp),
  11155. repositionMenus: (apis, comp) => apis.repositionMenus(comp)
  11156. }
  11157. });
  11158. const identifyMenuLayout = searchMode => {
  11159. switch (searchMode.searchMode) {
  11160. case 'no-search': {
  11161. return { menuType: 'normal' };
  11162. }
  11163. default: {
  11164. return {
  11165. menuType: 'searchable',
  11166. searchMode
  11167. };
  11168. }
  11169. }
  11170. };
  11171. const handleRefetchTrigger = originalSandboxComp => {
  11172. const dropdown = Representing.getValue(originalSandboxComp);
  11173. const optSearcherState = findWithinSandbox(originalSandboxComp).map(saveState);
  11174. Dropdown.refetch(dropdown).get(() => {
  11175. const newSandboxComp = Coupling.getCoupled(dropdown, 'sandbox');
  11176. optSearcherState.each(searcherState => findWithinSandbox(newSandboxComp).each(inputComp => restoreState(inputComp, searcherState)));
  11177. });
  11178. };
  11179. const handleRedirectToMenuItem = (sandboxComp, se) => {
  11180. getActiveMenuItemFrom(sandboxComp).each(activeItem => {
  11181. retargetAndDispatchWith(sandboxComp, activeItem.element, se.event.eventType, se.event.interactionEvent);
  11182. });
  11183. };
  11184. const getActiveMenuItemFrom = sandboxComp => {
  11185. return Sandboxing.getState(sandboxComp).bind(Highlighting.getHighlighted).bind(Highlighting.getHighlighted);
  11186. };
  11187. const getSearchResults = activeMenuComp => {
  11188. return has(activeMenuComp.element, searchResultsClass) ? Optional.some(activeMenuComp.element) : descendant(activeMenuComp.element, '.' + searchResultsClass);
  11189. };
  11190. const updateAriaOnHighlight = (tmenuComp, menuComp, itemComp) => {
  11191. findWithinMenu(tmenuComp).each(inputComp => {
  11192. setActiveDescendant(inputComp, itemComp);
  11193. const optActiveResults = getSearchResults(menuComp);
  11194. optActiveResults.each(resultsElem => {
  11195. getOpt(resultsElem, 'id').each(controlledId => set$9(inputComp.element, 'aria-controls', controlledId));
  11196. });
  11197. });
  11198. set$9(itemComp.element, 'aria-selected', 'true');
  11199. };
  11200. const updateAriaOnDehighlight = (tmenuComp, menuComp, itemComp) => {
  11201. set$9(itemComp.element, 'aria-selected', 'false');
  11202. };
  11203. const focusSearchField = tmenuComp => {
  11204. findWithinMenu(tmenuComp).each(searcherComp => Focusing.focus(searcherComp));
  11205. };
  11206. const getSearchPattern = dropdownComp => {
  11207. const optSandboxComp = Coupling.getExistingCoupled(dropdownComp, 'sandbox');
  11208. return optSandboxComp.bind(findWithinSandbox).map(saveState).map(state => state.fetchPattern).getOr('');
  11209. };
  11210. var FocusMode;
  11211. (function (FocusMode) {
  11212. FocusMode[FocusMode['ContentFocus'] = 0] = 'ContentFocus';
  11213. FocusMode[FocusMode['UiFocus'] = 1] = 'UiFocus';
  11214. }(FocusMode || (FocusMode = {})));
  11215. const createMenuItemFromBridge = (item, itemResponse, backstage, menuHasIcons, isHorizontalMenu) => {
  11216. const providersBackstage = backstage.shared.providers;
  11217. const parseForHorizontalMenu = menuitem => !isHorizontalMenu ? menuitem : {
  11218. ...menuitem,
  11219. shortcut: Optional.none(),
  11220. icon: menuitem.text.isSome() ? Optional.none() : menuitem.icon
  11221. };
  11222. switch (item.type) {
  11223. case 'menuitem':
  11224. return createMenuItem(item).fold(handleError, d => Optional.some(normal(parseForHorizontalMenu(d), itemResponse, providersBackstage, menuHasIcons)));
  11225. case 'nestedmenuitem':
  11226. return createNestedMenuItem(item).fold(handleError, d => Optional.some(nested(parseForHorizontalMenu(d), itemResponse, providersBackstage, menuHasIcons, isHorizontalMenu)));
  11227. case 'togglemenuitem':
  11228. return createToggleMenuItem(item).fold(handleError, d => Optional.some(toggle$1(parseForHorizontalMenu(d), itemResponse, providersBackstage, menuHasIcons)));
  11229. case 'separator':
  11230. return createSeparatorMenuItem(item).fold(handleError, d => Optional.some(separator$3(d)));
  11231. case 'fancymenuitem':
  11232. return createFancyMenuItem(item).fold(handleError, d => fancy(d, backstage));
  11233. default: {
  11234. console.error('Unknown item in general menu', item);
  11235. return Optional.none();
  11236. }
  11237. }
  11238. };
  11239. const createAutocompleteItems = (items, matchText, onItemValueHandler, columns, itemResponse, sharedBackstage, highlightOn) => {
  11240. const renderText = columns === 1;
  11241. const renderIcons = !renderText || menuHasIcons(items);
  11242. return cat(map$2(items, item => {
  11243. switch (item.type) {
  11244. case 'separator':
  11245. return createSeparatorItem(item).fold(handleError, d => Optional.some(separator$3(d)));
  11246. case 'cardmenuitem':
  11247. return createCardMenuItem(item).fold(handleError, d => Optional.some(card({
  11248. ...d,
  11249. onAction: api => {
  11250. d.onAction(api);
  11251. onItemValueHandler(d.value, d.meta);
  11252. }
  11253. }, itemResponse, sharedBackstage, {
  11254. itemBehaviours: tooltipBehaviour(d.meta, sharedBackstage),
  11255. cardText: {
  11256. matchText,
  11257. highlightOn
  11258. }
  11259. })));
  11260. case 'autocompleteitem':
  11261. default:
  11262. return createAutocompleterItem(item).fold(handleError, d => Optional.some(autocomplete(d, matchText, renderText, 'normal', onItemValueHandler, itemResponse, sharedBackstage, renderIcons)));
  11263. }
  11264. }));
  11265. };
  11266. const createPartialMenu = (value, items, itemResponse, backstage, isHorizontalMenu, searchMode) => {
  11267. const hasIcons = menuHasIcons(items);
  11268. const alloyItems = cat(map$2(items, item => {
  11269. const itemHasIcon = i => isHorizontalMenu ? !has$2(i, 'text') : hasIcons;
  11270. const createItem = i => createMenuItemFromBridge(i, itemResponse, backstage, itemHasIcon(i), isHorizontalMenu);
  11271. if (item.type === 'nestedmenuitem' && item.getSubmenuItems().length <= 0) {
  11272. return createItem({
  11273. ...item,
  11274. enabled: false
  11275. });
  11276. } else {
  11277. return createItem(item);
  11278. }
  11279. }));
  11280. const menuLayout = identifyMenuLayout(searchMode);
  11281. const createPartial = isHorizontalMenu ? createHorizontalPartialMenuWithAlloyItems : createPartialMenuWithAlloyItems;
  11282. return createPartial(value, hasIcons, alloyItems, 1, menuLayout);
  11283. };
  11284. const createTieredDataFrom = partialMenu => tieredMenu.singleData(partialMenu.value, partialMenu);
  11285. const createInlineMenuFrom = (partialMenu, columns, focusMode, presets) => {
  11286. const movement = deriveMenuMovement(columns, presets);
  11287. const menuMarkers = markers(presets);
  11288. return {
  11289. data: createTieredDataFrom({
  11290. ...partialMenu,
  11291. movement,
  11292. menuBehaviours: SimpleBehaviours.unnamedEvents(columns !== 'auto' ? [] : [runOnAttached((comp, _se) => {
  11293. detectSize(comp, 4, menuMarkers.item).each(({numColumns, numRows}) => {
  11294. Keying.setGridSize(comp, numRows, numColumns);
  11295. });
  11296. })])
  11297. }),
  11298. menu: {
  11299. markers: markers(presets),
  11300. fakeFocus: focusMode === FocusMode.ContentFocus
  11301. }
  11302. };
  11303. };
  11304. const getAutocompleterRange = (dom, initRange) => {
  11305. return detect$1(SugarElement.fromDom(initRange.startContainer)).map(elm => {
  11306. const range = dom.createRng();
  11307. range.selectNode(elm.dom);
  11308. return range;
  11309. });
  11310. };
  11311. const register$b = (editor, sharedBackstage) => {
  11312. const processingAction = Cell(false);
  11313. const activeState = Cell(false);
  11314. const autocompleter = build$1(InlineView.sketch({
  11315. dom: {
  11316. tag: 'div',
  11317. classes: ['tox-autocompleter']
  11318. },
  11319. components: [],
  11320. fireDismissalEventInstead: {},
  11321. inlineBehaviours: derive$1([config('dismissAutocompleter', [run$1(dismissRequested(), () => cancelIfNecessary())])]),
  11322. lazySink: sharedBackstage.getSink
  11323. }));
  11324. const isMenuOpen = () => InlineView.isOpen(autocompleter);
  11325. const isActive = activeState.get;
  11326. const hideIfNecessary = () => {
  11327. if (isMenuOpen()) {
  11328. InlineView.hide(autocompleter);
  11329. }
  11330. };
  11331. const getMenu = () => InlineView.getContent(autocompleter).bind(tmenu => {
  11332. return get$h(tmenu.components(), 0);
  11333. });
  11334. const cancelIfNecessary = () => editor.execCommand('mceAutocompleterClose');
  11335. const getCombinedItems = matches => {
  11336. const columns = findMap(matches, m => Optional.from(m.columns)).getOr(1);
  11337. return bind$3(matches, match => {
  11338. const choices = match.items;
  11339. return createAutocompleteItems(choices, match.matchText, (itemValue, itemMeta) => {
  11340. const nr = editor.selection.getRng();
  11341. getAutocompleterRange(editor.dom, nr).each(range => {
  11342. const autocompleterApi = {
  11343. hide: () => cancelIfNecessary(),
  11344. reload: fetchOptions => {
  11345. hideIfNecessary();
  11346. editor.execCommand('mceAutocompleterReload', false, { fetchOptions });
  11347. }
  11348. };
  11349. processingAction.set(true);
  11350. match.onAction(autocompleterApi, range, itemValue, itemMeta);
  11351. processingAction.set(false);
  11352. });
  11353. }, columns, ItemResponse$1.BUBBLE_TO_SANDBOX, sharedBackstage, match.highlightOn);
  11354. });
  11355. };
  11356. const display = (lookupData, items) => {
  11357. findIn(SugarElement.fromDom(editor.getBody())).each(element => {
  11358. const columns = findMap(lookupData, ld => Optional.from(ld.columns)).getOr(1);
  11359. InlineView.showMenuAt(autocompleter, {
  11360. anchor: {
  11361. type: 'node',
  11362. root: SugarElement.fromDom(editor.getBody()),
  11363. node: Optional.from(element)
  11364. }
  11365. }, createInlineMenuFrom(createPartialMenuWithAlloyItems('autocompleter-value', true, items, columns, { menuType: 'normal' }), columns, FocusMode.ContentFocus, 'normal'));
  11366. });
  11367. getMenu().each(Highlighting.highlightFirst);
  11368. };
  11369. const updateDisplay = lookupData => {
  11370. const combinedItems = getCombinedItems(lookupData);
  11371. if (combinedItems.length > 0) {
  11372. display(lookupData, combinedItems);
  11373. } else {
  11374. hideIfNecessary();
  11375. }
  11376. };
  11377. editor.on('AutocompleterStart', ({lookupData}) => {
  11378. activeState.set(true);
  11379. processingAction.set(false);
  11380. updateDisplay(lookupData);
  11381. });
  11382. editor.on('AutocompleterUpdate', ({lookupData}) => updateDisplay(lookupData));
  11383. editor.on('AutocompleterEnd', () => {
  11384. hideIfNecessary();
  11385. activeState.set(false);
  11386. processingAction.set(false);
  11387. });
  11388. const autocompleterUiApi = {
  11389. cancelIfNecessary,
  11390. isMenuOpen,
  11391. isActive,
  11392. isProcessingAction: processingAction.get,
  11393. getMenu
  11394. };
  11395. AutocompleterEditorEvents.setup(autocompleterUiApi, editor);
  11396. };
  11397. const Autocompleter = { register: register$b };
  11398. const nonScrollingOverflows = [
  11399. 'visible',
  11400. 'hidden'
  11401. ];
  11402. const isScroller = elem => {
  11403. if (isHTMLElement(elem)) {
  11404. const overflow = get$e(elem, 'overflow');
  11405. return trim$1(overflow).length > 0 && !contains$2(nonScrollingOverflows, overflow);
  11406. } else {
  11407. return false;
  11408. }
  11409. };
  11410. const detect = poupSinkElem => {
  11411. const scrollers = ancestors(poupSinkElem, isScroller);
  11412. return head(scrollers).map(element => ({
  11413. element,
  11414. others: scrollers.slice(1)
  11415. }));
  11416. };
  11417. const detectWhenSplitUiMode = (editor, popupSinkElem) => isSplitUiMode(editor) ? detect(popupSinkElem) : Optional.none();
  11418. const getBoundsFrom = sc => {
  11419. const scrollableBoxes = [
  11420. ...map$2(sc.others, box$1),
  11421. win()
  11422. ];
  11423. return constrainByMany(box$1(sc.element), scrollableBoxes);
  11424. };
  11425. const closest = (scope, selector, isRoot) => closest$1(scope, selector, isRoot).isSome();
  11426. const DelayedFunction = (fun, delay) => {
  11427. let ref = null;
  11428. const schedule = (...args) => {
  11429. ref = setTimeout(() => {
  11430. fun.apply(null, args);
  11431. ref = null;
  11432. }, delay);
  11433. };
  11434. const cancel = () => {
  11435. if (ref !== null) {
  11436. clearTimeout(ref);
  11437. ref = null;
  11438. }
  11439. };
  11440. return {
  11441. cancel,
  11442. schedule
  11443. };
  11444. };
  11445. const SIGNIFICANT_MOVE = 5;
  11446. const LONGPRESS_DELAY = 400;
  11447. const getTouch = event => {
  11448. const raw = event.raw;
  11449. if (raw.touches === undefined || raw.touches.length !== 1) {
  11450. return Optional.none();
  11451. }
  11452. return Optional.some(raw.touches[0]);
  11453. };
  11454. const isFarEnough = (touch, data) => {
  11455. const distX = Math.abs(touch.clientX - data.x);
  11456. const distY = Math.abs(touch.clientY - data.y);
  11457. return distX > SIGNIFICANT_MOVE || distY > SIGNIFICANT_MOVE;
  11458. };
  11459. const monitor = settings => {
  11460. const startData = value$2();
  11461. const longpressFired = Cell(false);
  11462. const longpress$1 = DelayedFunction(event => {
  11463. settings.triggerEvent(longpress(), event);
  11464. longpressFired.set(true);
  11465. }, LONGPRESS_DELAY);
  11466. const handleTouchstart = event => {
  11467. getTouch(event).each(touch => {
  11468. longpress$1.cancel();
  11469. const data = {
  11470. x: touch.clientX,
  11471. y: touch.clientY,
  11472. target: event.target
  11473. };
  11474. longpress$1.schedule(event);
  11475. longpressFired.set(false);
  11476. startData.set(data);
  11477. });
  11478. return Optional.none();
  11479. };
  11480. const handleTouchmove = event => {
  11481. longpress$1.cancel();
  11482. getTouch(event).each(touch => {
  11483. startData.on(data => {
  11484. if (isFarEnough(touch, data)) {
  11485. startData.clear();
  11486. }
  11487. });
  11488. });
  11489. return Optional.none();
  11490. };
  11491. const handleTouchend = event => {
  11492. longpress$1.cancel();
  11493. const isSame = data => eq(data.target, event.target);
  11494. return startData.get().filter(isSame).map(_data => {
  11495. if (longpressFired.get()) {
  11496. event.prevent();
  11497. return false;
  11498. } else {
  11499. return settings.triggerEvent(tap(), event);
  11500. }
  11501. });
  11502. };
  11503. const handlers = wrapAll([
  11504. {
  11505. key: touchstart(),
  11506. value: handleTouchstart
  11507. },
  11508. {
  11509. key: touchmove(),
  11510. value: handleTouchmove
  11511. },
  11512. {
  11513. key: touchend(),
  11514. value: handleTouchend
  11515. }
  11516. ]);
  11517. const fireIfReady = (event, type) => get$g(handlers, type).bind(handler => handler(event));
  11518. return { fireIfReady };
  11519. };
  11520. const isDangerous = event => {
  11521. const keyEv = event.raw;
  11522. return keyEv.which === BACKSPACE[0] && !contains$2([
  11523. 'input',
  11524. 'textarea'
  11525. ], name$3(event.target)) && !closest(event.target, '[contenteditable="true"]');
  11526. };
  11527. const setup$d = (container, rawSettings) => {
  11528. const settings = {
  11529. stopBackspace: true,
  11530. ...rawSettings
  11531. };
  11532. const pointerEvents = [
  11533. 'touchstart',
  11534. 'touchmove',
  11535. 'touchend',
  11536. 'touchcancel',
  11537. 'gesturestart',
  11538. 'mousedown',
  11539. 'mouseup',
  11540. 'mouseover',
  11541. 'mousemove',
  11542. 'mouseout',
  11543. 'click'
  11544. ];
  11545. const tapEvent = monitor(settings);
  11546. const simpleEvents = map$2(pointerEvents.concat([
  11547. 'selectstart',
  11548. 'input',
  11549. 'contextmenu',
  11550. 'change',
  11551. 'transitionend',
  11552. 'transitioncancel',
  11553. 'drag',
  11554. 'dragstart',
  11555. 'dragend',
  11556. 'dragenter',
  11557. 'dragleave',
  11558. 'dragover',
  11559. 'drop',
  11560. 'keyup'
  11561. ]), type => bind(container, type, event => {
  11562. tapEvent.fireIfReady(event, type).each(tapStopped => {
  11563. if (tapStopped) {
  11564. event.kill();
  11565. }
  11566. });
  11567. const stopped = settings.triggerEvent(type, event);
  11568. if (stopped) {
  11569. event.kill();
  11570. }
  11571. }));
  11572. const pasteTimeout = value$2();
  11573. const onPaste = bind(container, 'paste', event => {
  11574. tapEvent.fireIfReady(event, 'paste').each(tapStopped => {
  11575. if (tapStopped) {
  11576. event.kill();
  11577. }
  11578. });
  11579. const stopped = settings.triggerEvent('paste', event);
  11580. if (stopped) {
  11581. event.kill();
  11582. }
  11583. pasteTimeout.set(setTimeout(() => {
  11584. settings.triggerEvent(postPaste(), event);
  11585. }, 0));
  11586. });
  11587. const onKeydown = bind(container, 'keydown', event => {
  11588. const stopped = settings.triggerEvent('keydown', event);
  11589. if (stopped) {
  11590. event.kill();
  11591. } else if (settings.stopBackspace && isDangerous(event)) {
  11592. event.prevent();
  11593. }
  11594. });
  11595. const onFocusIn = bind(container, 'focusin', event => {
  11596. const stopped = settings.triggerEvent('focusin', event);
  11597. if (stopped) {
  11598. event.kill();
  11599. }
  11600. });
  11601. const focusoutTimeout = value$2();
  11602. const onFocusOut = bind(container, 'focusout', event => {
  11603. const stopped = settings.triggerEvent('focusout', event);
  11604. if (stopped) {
  11605. event.kill();
  11606. }
  11607. focusoutTimeout.set(setTimeout(() => {
  11608. settings.triggerEvent(postBlur(), event);
  11609. }, 0));
  11610. });
  11611. const unbind = () => {
  11612. each$1(simpleEvents, e => {
  11613. e.unbind();
  11614. });
  11615. onKeydown.unbind();
  11616. onFocusIn.unbind();
  11617. onFocusOut.unbind();
  11618. onPaste.unbind();
  11619. pasteTimeout.on(clearTimeout);
  11620. focusoutTimeout.on(clearTimeout);
  11621. };
  11622. return { unbind };
  11623. };
  11624. const derive = (rawEvent, rawTarget) => {
  11625. const source = get$g(rawEvent, 'target').getOr(rawTarget);
  11626. return Cell(source);
  11627. };
  11628. const fromSource = (event, source) => {
  11629. const stopper = Cell(false);
  11630. const cutter = Cell(false);
  11631. const stop = () => {
  11632. stopper.set(true);
  11633. };
  11634. const cut = () => {
  11635. cutter.set(true);
  11636. };
  11637. return {
  11638. stop,
  11639. cut,
  11640. isStopped: stopper.get,
  11641. isCut: cutter.get,
  11642. event,
  11643. setSource: source.set,
  11644. getSource: source.get
  11645. };
  11646. };
  11647. const fromExternal = event => {
  11648. const stopper = Cell(false);
  11649. const stop = () => {
  11650. stopper.set(true);
  11651. };
  11652. return {
  11653. stop,
  11654. cut: noop,
  11655. isStopped: stopper.get,
  11656. isCut: never,
  11657. event,
  11658. setSource: die('Cannot set source of a broadcasted event'),
  11659. getSource: die('Cannot get source of a broadcasted event')
  11660. };
  11661. };
  11662. const adt$1 = Adt.generate([
  11663. { stopped: [] },
  11664. { resume: ['element'] },
  11665. { complete: [] }
  11666. ]);
  11667. const doTriggerHandler = (lookup, eventType, rawEvent, target, source, logger) => {
  11668. const handler = lookup(eventType, target);
  11669. const simulatedEvent = fromSource(rawEvent, source);
  11670. return handler.fold(() => {
  11671. logger.logEventNoHandlers(eventType, target);
  11672. return adt$1.complete();
  11673. }, handlerInfo => {
  11674. const descHandler = handlerInfo.descHandler;
  11675. const eventHandler = getCurried(descHandler);
  11676. eventHandler(simulatedEvent);
  11677. if (simulatedEvent.isStopped()) {
  11678. logger.logEventStopped(eventType, handlerInfo.element, descHandler.purpose);
  11679. return adt$1.stopped();
  11680. } else if (simulatedEvent.isCut()) {
  11681. logger.logEventCut(eventType, handlerInfo.element, descHandler.purpose);
  11682. return adt$1.complete();
  11683. } else {
  11684. return parent(handlerInfo.element).fold(() => {
  11685. logger.logNoParent(eventType, handlerInfo.element, descHandler.purpose);
  11686. return adt$1.complete();
  11687. }, parent => {
  11688. logger.logEventResponse(eventType, handlerInfo.element, descHandler.purpose);
  11689. return adt$1.resume(parent);
  11690. });
  11691. }
  11692. });
  11693. };
  11694. 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);
  11695. const triggerHandler = (lookup, eventType, rawEvent, target, logger) => {
  11696. const source = derive(rawEvent, target);
  11697. return doTriggerHandler(lookup, eventType, rawEvent, target, source, logger);
  11698. };
  11699. const broadcast = (listeners, rawEvent, _logger) => {
  11700. const simulatedEvent = fromExternal(rawEvent);
  11701. each$1(listeners, listener => {
  11702. const descHandler = listener.descHandler;
  11703. const handler = getCurried(descHandler);
  11704. handler(simulatedEvent);
  11705. });
  11706. return simulatedEvent.isStopped();
  11707. };
  11708. const triggerUntilStopped = (lookup, eventType, rawEvent, logger) => triggerOnUntilStopped(lookup, eventType, rawEvent, rawEvent.target, logger);
  11709. const triggerOnUntilStopped = (lookup, eventType, rawEvent, rawTarget, logger) => {
  11710. const source = derive(rawEvent, rawTarget);
  11711. return doTriggerOnUntilStopped(lookup, eventType, rawEvent, rawTarget, source, logger);
  11712. };
  11713. const eventHandler = (element, descHandler) => ({
  11714. element,
  11715. descHandler
  11716. });
  11717. const broadcastHandler = (id, handler) => ({
  11718. id,
  11719. descHandler: handler
  11720. });
  11721. const EventRegistry = () => {
  11722. const registry = {};
  11723. const registerId = (extraArgs, id, events) => {
  11724. each(events, (v, k) => {
  11725. const handlers = registry[k] !== undefined ? registry[k] : {};
  11726. handlers[id] = curryArgs(v, extraArgs);
  11727. registry[k] = handlers;
  11728. });
  11729. };
  11730. const findHandler = (handlers, elem) => read$1(elem).bind(id => get$g(handlers, id)).map(descHandler => eventHandler(elem, descHandler));
  11731. const filterByType = type => get$g(registry, type).map(handlers => mapToArray(handlers, (f, id) => broadcastHandler(id, f))).getOr([]);
  11732. const find = (isAboveRoot, type, target) => get$g(registry, type).bind(handlers => closest$4(target, elem => findHandler(handlers, elem), isAboveRoot));
  11733. const unregisterId = id => {
  11734. each(registry, (handlersById, _eventName) => {
  11735. if (has$2(handlersById, id)) {
  11736. delete handlersById[id];
  11737. }
  11738. });
  11739. };
  11740. return {
  11741. registerId,
  11742. unregisterId,
  11743. filterByType,
  11744. find
  11745. };
  11746. };
  11747. const Registry = () => {
  11748. const events = EventRegistry();
  11749. const components = {};
  11750. const readOrTag = component => {
  11751. const elem = component.element;
  11752. return read$1(elem).getOrThunk(() => write('uid-', component.element));
  11753. };
  11754. const failOnDuplicate = (component, tagId) => {
  11755. const conflict = components[tagId];
  11756. if (conflict === component) {
  11757. unregister(component);
  11758. } else {
  11759. 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');
  11760. }
  11761. };
  11762. const register = component => {
  11763. const tagId = readOrTag(component);
  11764. if (hasNonNullableKey(components, tagId)) {
  11765. failOnDuplicate(component, tagId);
  11766. }
  11767. const extraArgs = [component];
  11768. events.registerId(extraArgs, tagId, component.events);
  11769. components[tagId] = component;
  11770. };
  11771. const unregister = component => {
  11772. read$1(component.element).each(tagId => {
  11773. delete components[tagId];
  11774. events.unregisterId(tagId);
  11775. });
  11776. };
  11777. const filter = type => events.filterByType(type);
  11778. const find = (isAboveRoot, type, target) => events.find(isAboveRoot, type, target);
  11779. const getById = id => get$g(components, id);
  11780. return {
  11781. find,
  11782. filter,
  11783. register,
  11784. unregister,
  11785. getById
  11786. };
  11787. };
  11788. const factory$j = detail => {
  11789. const {attributes, ...domWithoutAttributes} = detail.dom;
  11790. return {
  11791. uid: detail.uid,
  11792. dom: {
  11793. tag: 'div',
  11794. attributes: {
  11795. role: 'presentation',
  11796. ...attributes
  11797. },
  11798. ...domWithoutAttributes
  11799. },
  11800. components: detail.components,
  11801. behaviours: get$3(detail.containerBehaviours),
  11802. events: detail.events,
  11803. domModification: detail.domModification,
  11804. eventOrder: detail.eventOrder
  11805. };
  11806. };
  11807. const Container = single({
  11808. name: 'Container',
  11809. factory: factory$j,
  11810. configFields: [
  11811. defaulted('components', []),
  11812. field('containerBehaviours', []),
  11813. defaulted('events', {}),
  11814. defaulted('domModification', {}),
  11815. defaulted('eventOrder', {})
  11816. ]
  11817. });
  11818. const takeover = root => {
  11819. const isAboveRoot = el => parent(root.element).fold(always, parent => eq(el, parent));
  11820. const registry = Registry();
  11821. const lookup = (eventName, target) => registry.find(isAboveRoot, eventName, target);
  11822. const domEvents = setup$d(root.element, {
  11823. triggerEvent: (eventName, event) => {
  11824. return monitorEvent(eventName, event.target, logger => triggerUntilStopped(lookup, eventName, event, logger));
  11825. }
  11826. });
  11827. const systemApi = {
  11828. debugInfo: constant$1('real'),
  11829. triggerEvent: (eventName, target, data) => {
  11830. monitorEvent(eventName, target, logger => triggerOnUntilStopped(lookup, eventName, data, target, logger));
  11831. },
  11832. triggerFocus: (target, originator) => {
  11833. read$1(target).fold(() => {
  11834. focus$3(target);
  11835. }, _alloyId => {
  11836. monitorEvent(focus$4(), target, logger => {
  11837. triggerHandler(lookup, focus$4(), {
  11838. originator,
  11839. kill: noop,
  11840. prevent: noop,
  11841. target
  11842. }, target, logger);
  11843. return false;
  11844. });
  11845. });
  11846. },
  11847. triggerEscape: (comp, simulatedEvent) => {
  11848. systemApi.triggerEvent('keydown', comp.element, simulatedEvent.event);
  11849. },
  11850. getByUid: uid => {
  11851. return getByUid(uid);
  11852. },
  11853. getByDom: elem => {
  11854. return getByDom(elem);
  11855. },
  11856. build: build$1,
  11857. buildOrPatch: buildOrPatch,
  11858. addToGui: c => {
  11859. add(c);
  11860. },
  11861. removeFromGui: c => {
  11862. remove(c);
  11863. },
  11864. addToWorld: c => {
  11865. addToWorld(c);
  11866. },
  11867. removeFromWorld: c => {
  11868. removeFromWorld(c);
  11869. },
  11870. broadcast: message => {
  11871. broadcast$1(message);
  11872. },
  11873. broadcastOn: (channels, message) => {
  11874. broadcastOn(channels, message);
  11875. },
  11876. broadcastEvent: (eventName, event) => {
  11877. broadcastEvent(eventName, event);
  11878. },
  11879. isConnected: always
  11880. };
  11881. const addToWorld = component => {
  11882. component.connect(systemApi);
  11883. if (!isText(component.element)) {
  11884. registry.register(component);
  11885. each$1(component.components(), addToWorld);
  11886. systemApi.triggerEvent(systemInit(), component.element, { target: component.element });
  11887. }
  11888. };
  11889. const removeFromWorld = component => {
  11890. if (!isText(component.element)) {
  11891. each$1(component.components(), removeFromWorld);
  11892. registry.unregister(component);
  11893. }
  11894. component.disconnect();
  11895. };
  11896. const add = component => {
  11897. attach(root, component);
  11898. };
  11899. const remove = component => {
  11900. detach(component);
  11901. };
  11902. const destroy = () => {
  11903. domEvents.unbind();
  11904. remove$5(root.element);
  11905. };
  11906. const broadcastData = data => {
  11907. const receivers = registry.filter(receive());
  11908. each$1(receivers, receiver => {
  11909. const descHandler = receiver.descHandler;
  11910. const handler = getCurried(descHandler);
  11911. handler(data);
  11912. });
  11913. };
  11914. const broadcast$1 = message => {
  11915. broadcastData({
  11916. universal: true,
  11917. data: message
  11918. });
  11919. };
  11920. const broadcastOn = (channels, message) => {
  11921. broadcastData({
  11922. universal: false,
  11923. channels,
  11924. data: message
  11925. });
  11926. };
  11927. const broadcastEvent = (eventName, event) => {
  11928. const listeners = registry.filter(eventName);
  11929. return broadcast(listeners, event);
  11930. };
  11931. const getByUid = uid => registry.getById(uid).fold(() => Result.error(new Error('Could not find component with uid: "' + uid + '" in system.')), Result.value);
  11932. const getByDom = elem => {
  11933. const uid = read$1(elem).getOr('not found');
  11934. return getByUid(uid);
  11935. };
  11936. addToWorld(root);
  11937. return {
  11938. root,
  11939. element: root.element,
  11940. destroy,
  11941. add,
  11942. remove,
  11943. getByUid,
  11944. getByDom,
  11945. addToWorld,
  11946. removeFromWorld,
  11947. broadcast: broadcast$1,
  11948. broadcastOn,
  11949. broadcastEvent
  11950. };
  11951. };
  11952. const renderBar = (spec, backstage) => ({
  11953. dom: {
  11954. tag: 'div',
  11955. classes: [
  11956. 'tox-bar',
  11957. 'tox-form__controls-h-stack'
  11958. ]
  11959. },
  11960. components: map$2(spec.items, backstage.interpreter)
  11961. });
  11962. const schema$j = constant$1([
  11963. defaulted('prefix', 'form-field'),
  11964. field('fieldBehaviours', [
  11965. Composing,
  11966. Representing
  11967. ])
  11968. ]);
  11969. const parts$d = constant$1([
  11970. optional({
  11971. schema: [required$1('dom')],
  11972. name: 'label'
  11973. }),
  11974. optional({
  11975. factory: {
  11976. sketch: spec => {
  11977. return {
  11978. uid: spec.uid,
  11979. dom: {
  11980. tag: 'span',
  11981. styles: { display: 'none' },
  11982. attributes: { 'aria-hidden': 'true' },
  11983. innerHtml: spec.text
  11984. }
  11985. };
  11986. }
  11987. },
  11988. schema: [required$1('text')],
  11989. name: 'aria-descriptor'
  11990. }),
  11991. required({
  11992. factory: {
  11993. sketch: spec => {
  11994. const excludeFactory = exclude(spec, ['factory']);
  11995. return spec.factory.sketch(excludeFactory);
  11996. }
  11997. },
  11998. schema: [required$1('factory')],
  11999. name: 'field'
  12000. })
  12001. ]);
  12002. const factory$i = (detail, components, _spec, _externals) => {
  12003. const behaviours = augment(detail.fieldBehaviours, [
  12004. Composing.config({
  12005. find: container => {
  12006. return getPart(container, detail, 'field');
  12007. }
  12008. }),
  12009. Representing.config({
  12010. store: {
  12011. mode: 'manual',
  12012. getValue: field => {
  12013. return Composing.getCurrent(field).bind(Representing.getValue);
  12014. },
  12015. setValue: (field, value) => {
  12016. Composing.getCurrent(field).each(current => {
  12017. Representing.setValue(current, value);
  12018. });
  12019. }
  12020. }
  12021. })
  12022. ]);
  12023. const events = derive$2([runOnAttached((component, _simulatedEvent) => {
  12024. const ps = getParts(component, detail, [
  12025. 'label',
  12026. 'field',
  12027. 'aria-descriptor'
  12028. ]);
  12029. ps.field().each(field => {
  12030. const id = generate$6(detail.prefix);
  12031. ps.label().each(label => {
  12032. set$9(label.element, 'for', id);
  12033. set$9(field.element, 'id', id);
  12034. });
  12035. ps['aria-descriptor']().each(descriptor => {
  12036. const descriptorId = generate$6(detail.prefix);
  12037. set$9(descriptor.element, 'id', descriptorId);
  12038. set$9(field.element, 'aria-describedby', descriptorId);
  12039. });
  12040. });
  12041. })]);
  12042. const apis = {
  12043. getField: container => getPart(container, detail, 'field'),
  12044. getLabel: container => getPart(container, detail, 'label')
  12045. };
  12046. return {
  12047. uid: detail.uid,
  12048. dom: detail.dom,
  12049. components,
  12050. behaviours,
  12051. events,
  12052. apis
  12053. };
  12054. };
  12055. const FormField = composite({
  12056. name: 'FormField',
  12057. configFields: schema$j(),
  12058. partFields: parts$d(),
  12059. factory: factory$i,
  12060. apis: {
  12061. getField: (apis, comp) => apis.getField(comp),
  12062. getLabel: (apis, comp) => apis.getLabel(comp)
  12063. }
  12064. });
  12065. const exhibit$2 = (base, tabConfig) => nu$7({
  12066. attributes: wrapAll([{
  12067. key: tabConfig.tabAttr,
  12068. value: 'true'
  12069. }])
  12070. });
  12071. var ActiveTabstopping = /*#__PURE__*/Object.freeze({
  12072. __proto__: null,
  12073. exhibit: exhibit$2
  12074. });
  12075. var TabstopSchema = [defaulted('tabAttr', 'data-alloy-tabstop')];
  12076. const Tabstopping = create$4({
  12077. fields: TabstopSchema,
  12078. name: 'tabstopping',
  12079. active: ActiveTabstopping
  12080. });
  12081. var global$3 = tinymce.util.Tools.resolve('tinymce.html.Entities');
  12082. const renderFormFieldWith = (pLabel, pField, extraClasses, extraBehaviours) => {
  12083. const spec = renderFormFieldSpecWith(pLabel, pField, extraClasses, extraBehaviours);
  12084. return FormField.sketch(spec);
  12085. };
  12086. const renderFormField = (pLabel, pField) => renderFormFieldWith(pLabel, pField, [], []);
  12087. const renderFormFieldSpecWith = (pLabel, pField, extraClasses, extraBehaviours) => ({
  12088. dom: renderFormFieldDomWith(extraClasses),
  12089. components: pLabel.toArray().concat([pField]),
  12090. fieldBehaviours: derive$1(extraBehaviours)
  12091. });
  12092. const renderFormFieldDom = () => renderFormFieldDomWith([]);
  12093. const renderFormFieldDomWith = extraClasses => ({
  12094. tag: 'div',
  12095. classes: ['tox-form__group'].concat(extraClasses)
  12096. });
  12097. const renderLabel$3 = (label, providersBackstage) => FormField.parts.label({
  12098. dom: {
  12099. tag: 'label',
  12100. classes: ['tox-label']
  12101. },
  12102. components: [text$2(providersBackstage.translate(label))]
  12103. });
  12104. const formChangeEvent = generate$6('form-component-change');
  12105. const formCloseEvent = generate$6('form-close');
  12106. const formCancelEvent = generate$6('form-cancel');
  12107. const formActionEvent = generate$6('form-action');
  12108. const formSubmitEvent = generate$6('form-submit');
  12109. const formBlockEvent = generate$6('form-block');
  12110. const formUnblockEvent = generate$6('form-unblock');
  12111. const formTabChangeEvent = generate$6('form-tabchange');
  12112. const formResizeEvent = generate$6('form-resize');
  12113. const renderCollection = (spec, providersBackstage, initialData) => {
  12114. const pLabel = spec.label.map(label => renderLabel$3(label, providersBackstage));
  12115. const runOnItem = f => (comp, se) => {
  12116. closest$1(se.event.target, '[data-collection-item-value]').each(target => {
  12117. f(comp, se, target, get$f(target, 'data-collection-item-value'));
  12118. });
  12119. };
  12120. const setContents = (comp, items) => {
  12121. const htmlLines = map$2(items, item => {
  12122. const itemText = global$8.translate(item.text);
  12123. const textContent = spec.columns === 1 ? `<div class="tox-collection__item-label">${ itemText }</div>` : '';
  12124. const iconContent = `<div class="tox-collection__item-icon">${ item.icon }</div>`;
  12125. const mapItemName = {
  12126. '_': ' ',
  12127. ' - ': ' ',
  12128. '-': ' '
  12129. };
  12130. const ariaLabel = itemText.replace(/\_| \- |\-/g, match => mapItemName[match]);
  12131. const disabledClass = providersBackstage.isDisabled() ? ' tox-collection__item--state-disabled' : '';
  12132. 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>`;
  12133. });
  12134. const chunks = spec.columns !== 'auto' && spec.columns > 1 ? chunk$1(htmlLines, spec.columns) : [htmlLines];
  12135. const html = map$2(chunks, ch => `<div class="tox-collection__group">${ ch.join('') }</div>`);
  12136. set$6(comp.element, html.join(''));
  12137. };
  12138. const onClick = runOnItem((comp, se, tgt, itemValue) => {
  12139. se.stop();
  12140. if (!providersBackstage.isDisabled()) {
  12141. emitWith(comp, formActionEvent, {
  12142. name: spec.name,
  12143. value: itemValue
  12144. });
  12145. }
  12146. });
  12147. const collectionEvents = [
  12148. run$1(mouseover(), runOnItem((comp, se, tgt) => {
  12149. focus$3(tgt);
  12150. })),
  12151. run$1(click(), onClick),
  12152. run$1(tap(), onClick),
  12153. run$1(focusin(), runOnItem((comp, se, tgt) => {
  12154. descendant(comp.element, '.' + activeClass).each(currentActive => {
  12155. remove$2(currentActive, activeClass);
  12156. });
  12157. add$2(tgt, activeClass);
  12158. })),
  12159. run$1(focusout(), runOnItem(comp => {
  12160. descendant(comp.element, '.' + activeClass).each(currentActive => {
  12161. remove$2(currentActive, activeClass);
  12162. });
  12163. })),
  12164. runOnExecute$1(runOnItem((comp, se, tgt, itemValue) => {
  12165. emitWith(comp, formActionEvent, {
  12166. name: spec.name,
  12167. value: itemValue
  12168. });
  12169. }))
  12170. ];
  12171. const iterCollectionItems = (comp, applyAttributes) => map$2(descendants(comp.element, '.tox-collection__item'), applyAttributes);
  12172. const pField = FormField.parts.field({
  12173. dom: {
  12174. tag: 'div',
  12175. classes: ['tox-collection'].concat(spec.columns !== 1 ? ['tox-collection--grid'] : ['tox-collection--list'])
  12176. },
  12177. components: [],
  12178. factory: { sketch: identity },
  12179. behaviours: derive$1([
  12180. Disabling.config({
  12181. disabled: providersBackstage.isDisabled,
  12182. onDisabled: comp => {
  12183. iterCollectionItems(comp, childElm => {
  12184. add$2(childElm, 'tox-collection__item--state-disabled');
  12185. set$9(childElm, 'aria-disabled', true);
  12186. });
  12187. },
  12188. onEnabled: comp => {
  12189. iterCollectionItems(comp, childElm => {
  12190. remove$2(childElm, 'tox-collection__item--state-disabled');
  12191. remove$7(childElm, 'aria-disabled');
  12192. });
  12193. }
  12194. }),
  12195. receivingConfig(),
  12196. Replacing.config({}),
  12197. Representing.config({
  12198. store: {
  12199. mode: 'memory',
  12200. initialValue: initialData.getOr([])
  12201. },
  12202. onSetValue: (comp, items) => {
  12203. setContents(comp, items);
  12204. if (spec.columns === 'auto') {
  12205. detectSize(comp, 5, 'tox-collection__item').each(({numRows, numColumns}) => {
  12206. Keying.setGridSize(comp, numRows, numColumns);
  12207. });
  12208. }
  12209. emit(comp, formResizeEvent);
  12210. }
  12211. }),
  12212. Tabstopping.config({}),
  12213. Keying.config(deriveCollectionMovement(spec.columns, 'normal')),
  12214. config('collection-events', collectionEvents)
  12215. ]),
  12216. eventOrder: {
  12217. [execute$5()]: [
  12218. 'disabling',
  12219. 'alloy.base.behaviour',
  12220. 'collection-events'
  12221. ]
  12222. }
  12223. });
  12224. const extraClasses = ['tox-form__group--collection'];
  12225. return renderFormFieldWith(pLabel, pField, extraClasses, []);
  12226. };
  12227. const ariaElements = [
  12228. 'input',
  12229. 'textarea'
  12230. ];
  12231. const isAriaElement = elem => {
  12232. const name = name$3(elem);
  12233. return contains$2(ariaElements, name);
  12234. };
  12235. const markValid = (component, invalidConfig) => {
  12236. const elem = invalidConfig.getRoot(component).getOr(component.element);
  12237. remove$2(elem, invalidConfig.invalidClass);
  12238. invalidConfig.notify.each(notifyInfo => {
  12239. if (isAriaElement(component.element)) {
  12240. set$9(component.element, 'aria-invalid', false);
  12241. }
  12242. notifyInfo.getContainer(component).each(container => {
  12243. set$6(container, notifyInfo.validHtml);
  12244. });
  12245. notifyInfo.onValid(component);
  12246. });
  12247. };
  12248. const markInvalid = (component, invalidConfig, invalidState, text) => {
  12249. const elem = invalidConfig.getRoot(component).getOr(component.element);
  12250. add$2(elem, invalidConfig.invalidClass);
  12251. invalidConfig.notify.each(notifyInfo => {
  12252. if (isAriaElement(component.element)) {
  12253. set$9(component.element, 'aria-invalid', true);
  12254. }
  12255. notifyInfo.getContainer(component).each(container => {
  12256. set$6(container, text);
  12257. });
  12258. notifyInfo.onInvalid(component, text);
  12259. });
  12260. };
  12261. const query = (component, invalidConfig, _invalidState) => invalidConfig.validator.fold(() => Future.pure(Result.value(true)), validatorInfo => validatorInfo.validate(component));
  12262. const run = (component, invalidConfig, invalidState) => {
  12263. invalidConfig.notify.each(notifyInfo => {
  12264. notifyInfo.onValidate(component);
  12265. });
  12266. return query(component, invalidConfig).map(valid => {
  12267. if (component.getSystem().isConnected()) {
  12268. return valid.fold(err => {
  12269. markInvalid(component, invalidConfig, invalidState, err);
  12270. return Result.error(err);
  12271. }, v => {
  12272. markValid(component, invalidConfig);
  12273. return Result.value(v);
  12274. });
  12275. } else {
  12276. return Result.error('No longer in system');
  12277. }
  12278. });
  12279. };
  12280. const isInvalid = (component, invalidConfig) => {
  12281. const elem = invalidConfig.getRoot(component).getOr(component.element);
  12282. return has(elem, invalidConfig.invalidClass);
  12283. };
  12284. var InvalidateApis = /*#__PURE__*/Object.freeze({
  12285. __proto__: null,
  12286. markValid: markValid,
  12287. markInvalid: markInvalid,
  12288. query: query,
  12289. run: run,
  12290. isInvalid: isInvalid
  12291. });
  12292. const events$8 = (invalidConfig, invalidState) => invalidConfig.validator.map(validatorInfo => derive$2([run$1(validatorInfo.onEvent, component => {
  12293. run(component, invalidConfig, invalidState).get(identity);
  12294. })].concat(validatorInfo.validateOnLoad ? [runOnAttached(component => {
  12295. run(component, invalidConfig, invalidState).get(noop);
  12296. })] : []))).getOr({});
  12297. var ActiveInvalidate = /*#__PURE__*/Object.freeze({
  12298. __proto__: null,
  12299. events: events$8
  12300. });
  12301. var InvalidateSchema = [
  12302. required$1('invalidClass'),
  12303. defaulted('getRoot', Optional.none),
  12304. optionObjOf('notify', [
  12305. defaulted('aria', 'alert'),
  12306. defaulted('getContainer', Optional.none),
  12307. defaulted('validHtml', ''),
  12308. onHandler('onValid'),
  12309. onHandler('onInvalid'),
  12310. onHandler('onValidate')
  12311. ]),
  12312. optionObjOf('validator', [
  12313. required$1('validate'),
  12314. defaulted('onEvent', 'input'),
  12315. defaulted('validateOnLoad', true)
  12316. ])
  12317. ];
  12318. const Invalidating = create$4({
  12319. fields: InvalidateSchema,
  12320. name: 'invalidating',
  12321. active: ActiveInvalidate,
  12322. apis: InvalidateApis,
  12323. extra: {
  12324. validation: validator => {
  12325. return component => {
  12326. const v = Representing.getValue(component);
  12327. return Future.pure(validator(v));
  12328. };
  12329. }
  12330. }
  12331. });
  12332. const exhibit$1 = () => nu$7({
  12333. styles: {
  12334. '-webkit-user-select': 'none',
  12335. 'user-select': 'none',
  12336. '-ms-user-select': 'none',
  12337. '-moz-user-select': '-moz-none'
  12338. },
  12339. attributes: { unselectable: 'on' }
  12340. });
  12341. const events$7 = () => derive$2([abort(selectstart(), always)]);
  12342. var ActiveUnselecting = /*#__PURE__*/Object.freeze({
  12343. __proto__: null,
  12344. events: events$7,
  12345. exhibit: exhibit$1
  12346. });
  12347. const Unselecting = create$4({
  12348. fields: [],
  12349. name: 'unselecting',
  12350. active: ActiveUnselecting
  12351. });
  12352. const renderPanelButton = (spec, sharedBackstage) => Dropdown.sketch({
  12353. dom: spec.dom,
  12354. components: spec.components,
  12355. toggleClass: 'mce-active',
  12356. dropdownBehaviours: derive$1([
  12357. DisablingConfigs.button(sharedBackstage.providers.isDisabled),
  12358. receivingConfig(),
  12359. Unselecting.config({}),
  12360. Tabstopping.config({})
  12361. ]),
  12362. layouts: spec.layouts,
  12363. sandboxClasses: ['tox-dialog__popups'],
  12364. lazySink: sharedBackstage.getSink,
  12365. fetch: comp => Future.nu(callback => spec.fetch(callback)).map(items => Optional.from(createTieredDataFrom(deepMerge(createPartialChoiceMenu(generate$6('menu-value'), items, value => {
  12366. spec.onItemAction(comp, value);
  12367. }, spec.columns, spec.presets, ItemResponse$1.CLOSE_ON_EXECUTE, never, sharedBackstage.providers), { movement: deriveMenuMovement(spec.columns, spec.presets) })))),
  12368. parts: { menu: part(false, 1, spec.presets) }
  12369. });
  12370. const colorInputChangeEvent = generate$6('color-input-change');
  12371. const colorSwatchChangeEvent = generate$6('color-swatch-change');
  12372. const colorPickerCancelEvent = generate$6('color-picker-cancel');
  12373. const renderColorInput = (spec, sharedBackstage, colorInputBackstage, initialData) => {
  12374. const pField = FormField.parts.field({
  12375. factory: Input,
  12376. inputClasses: ['tox-textfield'],
  12377. data: initialData,
  12378. onSetValue: c => Invalidating.run(c).get(noop),
  12379. inputBehaviours: derive$1([
  12380. Disabling.config({ disabled: sharedBackstage.providers.isDisabled }),
  12381. receivingConfig(),
  12382. Tabstopping.config({}),
  12383. Invalidating.config({
  12384. invalidClass: 'tox-textbox-field-invalid',
  12385. getRoot: comp => parentElement(comp.element),
  12386. notify: {
  12387. onValid: comp => {
  12388. const val = Representing.getValue(comp);
  12389. emitWith(comp, colorInputChangeEvent, { color: val });
  12390. }
  12391. },
  12392. validator: {
  12393. validateOnLoad: false,
  12394. validate: input => {
  12395. const inputValue = Representing.getValue(input);
  12396. if (inputValue.length === 0) {
  12397. return Future.pure(Result.value(true));
  12398. } else {
  12399. const span = SugarElement.fromTag('span');
  12400. set$8(span, 'background-color', inputValue);
  12401. const res = getRaw(span, 'background-color').fold(() => Result.error('blah'), _ => Result.value(inputValue));
  12402. return Future.pure(res);
  12403. }
  12404. }
  12405. }
  12406. })
  12407. ]),
  12408. selectOnFocus: false
  12409. });
  12410. const pLabel = spec.label.map(label => renderLabel$3(label, sharedBackstage.providers));
  12411. const emitSwatchChange = (colorBit, value) => {
  12412. emitWith(colorBit, colorSwatchChangeEvent, { value });
  12413. };
  12414. const onItemAction = (comp, value) => {
  12415. memColorButton.getOpt(comp).each(colorBit => {
  12416. if (value === 'custom') {
  12417. colorInputBackstage.colorPicker(valueOpt => {
  12418. valueOpt.fold(() => emit(colorBit, colorPickerCancelEvent), value => {
  12419. emitSwatchChange(colorBit, value);
  12420. addColor(spec.storageKey, value);
  12421. });
  12422. }, '#ffffff');
  12423. } else if (value === 'remove') {
  12424. emitSwatchChange(colorBit, '');
  12425. } else {
  12426. emitSwatchChange(colorBit, value);
  12427. }
  12428. });
  12429. };
  12430. const memColorButton = record(renderPanelButton({
  12431. dom: {
  12432. tag: 'span',
  12433. attributes: { 'aria-label': sharedBackstage.providers.translate('Color swatch') }
  12434. },
  12435. layouts: {
  12436. onRtl: () => [
  12437. southwest$2,
  12438. southeast$2,
  12439. south$2
  12440. ],
  12441. onLtr: () => [
  12442. southeast$2,
  12443. southwest$2,
  12444. south$2
  12445. ]
  12446. },
  12447. components: [],
  12448. fetch: getFetch$1(colorInputBackstage.getColors(spec.storageKey), spec.storageKey, colorInputBackstage.hasCustomColors()),
  12449. columns: colorInputBackstage.getColorCols(spec.storageKey),
  12450. presets: 'color',
  12451. onItemAction
  12452. }, sharedBackstage));
  12453. return FormField.sketch({
  12454. dom: {
  12455. tag: 'div',
  12456. classes: ['tox-form__group']
  12457. },
  12458. components: pLabel.toArray().concat([{
  12459. dom: {
  12460. tag: 'div',
  12461. classes: ['tox-color-input']
  12462. },
  12463. components: [
  12464. pField,
  12465. memColorButton.asSpec()
  12466. ]
  12467. }]),
  12468. fieldBehaviours: derive$1([config('form-field-events', [
  12469. run$1(colorInputChangeEvent, (comp, se) => {
  12470. memColorButton.getOpt(comp).each(colorButton => {
  12471. set$8(colorButton.element, 'background-color', se.event.color);
  12472. });
  12473. emitWith(comp, formChangeEvent, { name: spec.name });
  12474. }),
  12475. run$1(colorSwatchChangeEvent, (comp, se) => {
  12476. FormField.getField(comp).each(field => {
  12477. Representing.setValue(field, se.event.value);
  12478. Composing.getCurrent(comp).each(Focusing.focus);
  12479. });
  12480. }),
  12481. run$1(colorPickerCancelEvent, (comp, _se) => {
  12482. FormField.getField(comp).each(_field => {
  12483. Composing.getCurrent(comp).each(Focusing.focus);
  12484. });
  12485. })
  12486. ])])
  12487. });
  12488. };
  12489. const labelPart = optional({
  12490. schema: [required$1('dom')],
  12491. name: 'label'
  12492. });
  12493. const edgePart = name => optional({
  12494. name: '' + name + '-edge',
  12495. overrides: detail => {
  12496. const action = detail.model.manager.edgeActions[name];
  12497. return action.fold(() => ({}), a => ({
  12498. events: derive$2([
  12499. runActionExtra(touchstart(), (comp, se, d) => a(comp, d), [detail]),
  12500. runActionExtra(mousedown(), (comp, se, d) => a(comp, d), [detail]),
  12501. runActionExtra(mousemove(), (comp, se, det) => {
  12502. if (det.mouseIsDown.get()) {
  12503. a(comp, det);
  12504. }
  12505. }, [detail])
  12506. ])
  12507. }));
  12508. }
  12509. });
  12510. const tlEdgePart = edgePart('top-left');
  12511. const tedgePart = edgePart('top');
  12512. const trEdgePart = edgePart('top-right');
  12513. const redgePart = edgePart('right');
  12514. const brEdgePart = edgePart('bottom-right');
  12515. const bedgePart = edgePart('bottom');
  12516. const blEdgePart = edgePart('bottom-left');
  12517. const ledgePart = edgePart('left');
  12518. const thumbPart = required({
  12519. name: 'thumb',
  12520. defaults: constant$1({ dom: { styles: { position: 'absolute' } } }),
  12521. overrides: detail => {
  12522. return {
  12523. events: derive$2([
  12524. redirectToPart(touchstart(), detail, 'spectrum'),
  12525. redirectToPart(touchmove(), detail, 'spectrum'),
  12526. redirectToPart(touchend(), detail, 'spectrum'),
  12527. redirectToPart(mousedown(), detail, 'spectrum'),
  12528. redirectToPart(mousemove(), detail, 'spectrum'),
  12529. redirectToPart(mouseup(), detail, 'spectrum')
  12530. ])
  12531. };
  12532. }
  12533. });
  12534. const spectrumPart = required({
  12535. schema: [customField('mouseIsDown', () => Cell(false))],
  12536. name: 'spectrum',
  12537. overrides: detail => {
  12538. const modelDetail = detail.model;
  12539. const model = modelDetail.manager;
  12540. const setValueFrom = (component, simulatedEvent) => model.getValueFromEvent(simulatedEvent).map(value => model.setValueFrom(component, detail, value));
  12541. return {
  12542. behaviours: derive$1([
  12543. Keying.config({
  12544. mode: 'special',
  12545. onLeft: spectrum => model.onLeft(spectrum, detail),
  12546. onRight: spectrum => model.onRight(spectrum, detail),
  12547. onUp: spectrum => model.onUp(spectrum, detail),
  12548. onDown: spectrum => model.onDown(spectrum, detail)
  12549. }),
  12550. Focusing.config({})
  12551. ]),
  12552. events: derive$2([
  12553. run$1(touchstart(), setValueFrom),
  12554. run$1(touchmove(), setValueFrom),
  12555. run$1(mousedown(), setValueFrom),
  12556. run$1(mousemove(), (spectrum, se) => {
  12557. if (detail.mouseIsDown.get()) {
  12558. setValueFrom(spectrum, se);
  12559. }
  12560. })
  12561. ])
  12562. };
  12563. }
  12564. });
  12565. var SliderParts = [
  12566. labelPart,
  12567. ledgePart,
  12568. redgePart,
  12569. tedgePart,
  12570. bedgePart,
  12571. tlEdgePart,
  12572. trEdgePart,
  12573. blEdgePart,
  12574. brEdgePart,
  12575. thumbPart,
  12576. spectrumPart
  12577. ];
  12578. const _sliderChangeEvent = 'slider.change.value';
  12579. const sliderChangeEvent = constant$1(_sliderChangeEvent);
  12580. const isTouchEvent$2 = evt => evt.type.indexOf('touch') !== -1;
  12581. const getEventSource = simulatedEvent => {
  12582. const evt = simulatedEvent.event.raw;
  12583. if (isTouchEvent$2(evt)) {
  12584. const touchEvent = evt;
  12585. return touchEvent.touches !== undefined && touchEvent.touches.length === 1 ? Optional.some(touchEvent.touches[0]).map(t => SugarPosition(t.clientX, t.clientY)) : Optional.none();
  12586. } else {
  12587. const mouseEvent = evt;
  12588. return mouseEvent.clientX !== undefined ? Optional.some(mouseEvent).map(me => SugarPosition(me.clientX, me.clientY)) : Optional.none();
  12589. }
  12590. };
  12591. const t = 'top', r = 'right', b = 'bottom', l = 'left';
  12592. const minX = detail => detail.model.minX;
  12593. const minY = detail => detail.model.minY;
  12594. const min1X = detail => detail.model.minX - 1;
  12595. const min1Y = detail => detail.model.minY - 1;
  12596. const maxX = detail => detail.model.maxX;
  12597. const maxY = detail => detail.model.maxY;
  12598. const max1X = detail => detail.model.maxX + 1;
  12599. const max1Y = detail => detail.model.maxY + 1;
  12600. const range = (detail, max, min) => max(detail) - min(detail);
  12601. const xRange = detail => range(detail, maxX, minX);
  12602. const yRange = detail => range(detail, maxY, minY);
  12603. const halfX = detail => xRange(detail) / 2;
  12604. const halfY = detail => yRange(detail) / 2;
  12605. const step = detail => detail.stepSize;
  12606. const snap = detail => detail.snapToGrid;
  12607. const snapStart = detail => detail.snapStart;
  12608. const rounded = detail => detail.rounded;
  12609. const hasEdge = (detail, edgeName) => detail[edgeName + '-edge'] !== undefined;
  12610. const hasLEdge = detail => hasEdge(detail, l);
  12611. const hasREdge = detail => hasEdge(detail, r);
  12612. const hasTEdge = detail => hasEdge(detail, t);
  12613. const hasBEdge = detail => hasEdge(detail, b);
  12614. const currentValue = detail => detail.model.value.get();
  12615. const xyValue = (x, y) => ({
  12616. x,
  12617. y
  12618. });
  12619. const fireSliderChange$3 = (component, value) => {
  12620. emitWith(component, sliderChangeEvent(), { value });
  12621. };
  12622. const setToTLEdgeXY = (edge, detail) => {
  12623. fireSliderChange$3(edge, xyValue(min1X(detail), min1Y(detail)));
  12624. };
  12625. const setToTEdge = (edge, detail) => {
  12626. fireSliderChange$3(edge, min1Y(detail));
  12627. };
  12628. const setToTEdgeXY = (edge, detail) => {
  12629. fireSliderChange$3(edge, xyValue(halfX(detail), min1Y(detail)));
  12630. };
  12631. const setToTREdgeXY = (edge, detail) => {
  12632. fireSliderChange$3(edge, xyValue(max1X(detail), min1Y(detail)));
  12633. };
  12634. const setToREdge = (edge, detail) => {
  12635. fireSliderChange$3(edge, max1X(detail));
  12636. };
  12637. const setToREdgeXY = (edge, detail) => {
  12638. fireSliderChange$3(edge, xyValue(max1X(detail), halfY(detail)));
  12639. };
  12640. const setToBREdgeXY = (edge, detail) => {
  12641. fireSliderChange$3(edge, xyValue(max1X(detail), max1Y(detail)));
  12642. };
  12643. const setToBEdge = (edge, detail) => {
  12644. fireSliderChange$3(edge, max1Y(detail));
  12645. };
  12646. const setToBEdgeXY = (edge, detail) => {
  12647. fireSliderChange$3(edge, xyValue(halfX(detail), max1Y(detail)));
  12648. };
  12649. const setToBLEdgeXY = (edge, detail) => {
  12650. fireSliderChange$3(edge, xyValue(min1X(detail), max1Y(detail)));
  12651. };
  12652. const setToLEdge = (edge, detail) => {
  12653. fireSliderChange$3(edge, min1X(detail));
  12654. };
  12655. const setToLEdgeXY = (edge, detail) => {
  12656. fireSliderChange$3(edge, xyValue(min1X(detail), halfY(detail)));
  12657. };
  12658. const reduceBy = (value, min, max, step) => {
  12659. if (value < min) {
  12660. return value;
  12661. } else if (value > max) {
  12662. return max;
  12663. } else if (value === min) {
  12664. return min - 1;
  12665. } else {
  12666. return Math.max(min, value - step);
  12667. }
  12668. };
  12669. const increaseBy = (value, min, max, step) => {
  12670. if (value > max) {
  12671. return value;
  12672. } else if (value < min) {
  12673. return min;
  12674. } else if (value === max) {
  12675. return max + 1;
  12676. } else {
  12677. return Math.min(max, value + step);
  12678. }
  12679. };
  12680. const capValue = (value, min, max) => Math.max(min, Math.min(max, value));
  12681. const snapValueOf = (value, min, max, step, snapStart) => snapStart.fold(() => {
  12682. const initValue = value - min;
  12683. const extraValue = Math.round(initValue / step) * step;
  12684. return capValue(min + extraValue, min - 1, max + 1);
  12685. }, start => {
  12686. const remainder = (value - start) % step;
  12687. const adjustment = Math.round(remainder / step);
  12688. const rawSteps = Math.floor((value - start) / step);
  12689. const maxSteps = Math.floor((max - start) / step);
  12690. const numSteps = Math.min(maxSteps, rawSteps + adjustment);
  12691. const r = start + numSteps * step;
  12692. return Math.max(start, r);
  12693. });
  12694. const findOffsetOf = (value, min, max) => Math.min(max, Math.max(value, min)) - min;
  12695. const findValueOf = args => {
  12696. const {min, max, range, value, step, snap, snapStart, rounded, hasMinEdge, hasMaxEdge, minBound, maxBound, screenRange} = args;
  12697. const capMin = hasMinEdge ? min - 1 : min;
  12698. const capMax = hasMaxEdge ? max + 1 : max;
  12699. if (value < minBound) {
  12700. return capMin;
  12701. } else if (value > maxBound) {
  12702. return capMax;
  12703. } else {
  12704. const offset = findOffsetOf(value, minBound, maxBound);
  12705. const newValue = capValue(offset / screenRange * range + min, capMin, capMax);
  12706. if (snap && newValue >= min && newValue <= max) {
  12707. return snapValueOf(newValue, min, max, step, snapStart);
  12708. } else if (rounded) {
  12709. return Math.round(newValue);
  12710. } else {
  12711. return newValue;
  12712. }
  12713. }
  12714. };
  12715. const findOffsetOfValue$2 = args => {
  12716. const {min, max, range, value, hasMinEdge, hasMaxEdge, maxBound, maxOffset, centerMinEdge, centerMaxEdge} = args;
  12717. if (value < min) {
  12718. return hasMinEdge ? 0 : centerMinEdge;
  12719. } else if (value > max) {
  12720. return hasMaxEdge ? maxBound : centerMaxEdge;
  12721. } else {
  12722. return (value - min) / range * maxOffset;
  12723. }
  12724. };
  12725. const top = 'top', right = 'right', bottom = 'bottom', left = 'left', width = 'width', height = 'height';
  12726. const getBounds = component => component.element.dom.getBoundingClientRect();
  12727. const getBoundsProperty = (bounds, property) => bounds[property];
  12728. const getMinXBounds = component => {
  12729. const bounds = getBounds(component);
  12730. return getBoundsProperty(bounds, left);
  12731. };
  12732. const getMaxXBounds = component => {
  12733. const bounds = getBounds(component);
  12734. return getBoundsProperty(bounds, right);
  12735. };
  12736. const getMinYBounds = component => {
  12737. const bounds = getBounds(component);
  12738. return getBoundsProperty(bounds, top);
  12739. };
  12740. const getMaxYBounds = component => {
  12741. const bounds = getBounds(component);
  12742. return getBoundsProperty(bounds, bottom);
  12743. };
  12744. const getXScreenRange = component => {
  12745. const bounds = getBounds(component);
  12746. return getBoundsProperty(bounds, width);
  12747. };
  12748. const getYScreenRange = component => {
  12749. const bounds = getBounds(component);
  12750. return getBoundsProperty(bounds, height);
  12751. };
  12752. const getCenterOffsetOf = (componentMinEdge, componentMaxEdge, spectrumMinEdge) => (componentMinEdge + componentMaxEdge) / 2 - spectrumMinEdge;
  12753. const getXCenterOffSetOf = (component, spectrum) => {
  12754. const componentBounds = getBounds(component);
  12755. const spectrumBounds = getBounds(spectrum);
  12756. const componentMinEdge = getBoundsProperty(componentBounds, left);
  12757. const componentMaxEdge = getBoundsProperty(componentBounds, right);
  12758. const spectrumMinEdge = getBoundsProperty(spectrumBounds, left);
  12759. return getCenterOffsetOf(componentMinEdge, componentMaxEdge, spectrumMinEdge);
  12760. };
  12761. const getYCenterOffSetOf = (component, spectrum) => {
  12762. const componentBounds = getBounds(component);
  12763. const spectrumBounds = getBounds(spectrum);
  12764. const componentMinEdge = getBoundsProperty(componentBounds, top);
  12765. const componentMaxEdge = getBoundsProperty(componentBounds, bottom);
  12766. const spectrumMinEdge = getBoundsProperty(spectrumBounds, top);
  12767. return getCenterOffsetOf(componentMinEdge, componentMaxEdge, spectrumMinEdge);
  12768. };
  12769. const fireSliderChange$2 = (spectrum, value) => {
  12770. emitWith(spectrum, sliderChangeEvent(), { value });
  12771. };
  12772. const findValueOfOffset$1 = (spectrum, detail, left) => {
  12773. const args = {
  12774. min: minX(detail),
  12775. max: maxX(detail),
  12776. range: xRange(detail),
  12777. value: left,
  12778. step: step(detail),
  12779. snap: snap(detail),
  12780. snapStart: snapStart(detail),
  12781. rounded: rounded(detail),
  12782. hasMinEdge: hasLEdge(detail),
  12783. hasMaxEdge: hasREdge(detail),
  12784. minBound: getMinXBounds(spectrum),
  12785. maxBound: getMaxXBounds(spectrum),
  12786. screenRange: getXScreenRange(spectrum)
  12787. };
  12788. return findValueOf(args);
  12789. };
  12790. const setValueFrom$2 = (spectrum, detail, value) => {
  12791. const xValue = findValueOfOffset$1(spectrum, detail, value);
  12792. const sliderVal = xValue;
  12793. fireSliderChange$2(spectrum, sliderVal);
  12794. return xValue;
  12795. };
  12796. const setToMin$2 = (spectrum, detail) => {
  12797. const min = minX(detail);
  12798. fireSliderChange$2(spectrum, min);
  12799. };
  12800. const setToMax$2 = (spectrum, detail) => {
  12801. const max = maxX(detail);
  12802. fireSliderChange$2(spectrum, max);
  12803. };
  12804. const moveBy$2 = (direction, spectrum, detail) => {
  12805. const f = direction > 0 ? increaseBy : reduceBy;
  12806. const xValue = f(currentValue(detail), minX(detail), maxX(detail), step(detail));
  12807. fireSliderChange$2(spectrum, xValue);
  12808. return Optional.some(xValue);
  12809. };
  12810. const handleMovement$2 = direction => (spectrum, detail) => moveBy$2(direction, spectrum, detail).map(always);
  12811. const getValueFromEvent$2 = simulatedEvent => {
  12812. const pos = getEventSource(simulatedEvent);
  12813. return pos.map(p => p.left);
  12814. };
  12815. const findOffsetOfValue$1 = (spectrum, detail, value, minEdge, maxEdge) => {
  12816. const minOffset = 0;
  12817. const maxOffset = getXScreenRange(spectrum);
  12818. const centerMinEdge = minEdge.bind(edge => Optional.some(getXCenterOffSetOf(edge, spectrum))).getOr(minOffset);
  12819. const centerMaxEdge = maxEdge.bind(edge => Optional.some(getXCenterOffSetOf(edge, spectrum))).getOr(maxOffset);
  12820. const args = {
  12821. min: minX(detail),
  12822. max: maxX(detail),
  12823. range: xRange(detail),
  12824. value,
  12825. hasMinEdge: hasLEdge(detail),
  12826. hasMaxEdge: hasREdge(detail),
  12827. minBound: getMinXBounds(spectrum),
  12828. minOffset,
  12829. maxBound: getMaxXBounds(spectrum),
  12830. maxOffset,
  12831. centerMinEdge,
  12832. centerMaxEdge
  12833. };
  12834. return findOffsetOfValue$2(args);
  12835. };
  12836. const findPositionOfValue$1 = (slider, spectrum, value, minEdge, maxEdge, detail) => {
  12837. const offset = findOffsetOfValue$1(spectrum, detail, value, minEdge, maxEdge);
  12838. return getMinXBounds(spectrum) - getMinXBounds(slider) + offset;
  12839. };
  12840. const setPositionFromValue$2 = (slider, thumb, detail, edges) => {
  12841. const value = currentValue(detail);
  12842. const pos = findPositionOfValue$1(slider, edges.getSpectrum(slider), value, edges.getLeftEdge(slider), edges.getRightEdge(slider), detail);
  12843. const thumbRadius = get$c(thumb.element) / 2;
  12844. set$8(thumb.element, 'left', pos - thumbRadius + 'px');
  12845. };
  12846. const onLeft$2 = handleMovement$2(-1);
  12847. const onRight$2 = handleMovement$2(1);
  12848. const onUp$2 = Optional.none;
  12849. const onDown$2 = Optional.none;
  12850. const edgeActions$2 = {
  12851. 'top-left': Optional.none(),
  12852. 'top': Optional.none(),
  12853. 'top-right': Optional.none(),
  12854. 'right': Optional.some(setToREdge),
  12855. 'bottom-right': Optional.none(),
  12856. 'bottom': Optional.none(),
  12857. 'bottom-left': Optional.none(),
  12858. 'left': Optional.some(setToLEdge)
  12859. };
  12860. var HorizontalModel = /*#__PURE__*/Object.freeze({
  12861. __proto__: null,
  12862. setValueFrom: setValueFrom$2,
  12863. setToMin: setToMin$2,
  12864. setToMax: setToMax$2,
  12865. findValueOfOffset: findValueOfOffset$1,
  12866. getValueFromEvent: getValueFromEvent$2,
  12867. findPositionOfValue: findPositionOfValue$1,
  12868. setPositionFromValue: setPositionFromValue$2,
  12869. onLeft: onLeft$2,
  12870. onRight: onRight$2,
  12871. onUp: onUp$2,
  12872. onDown: onDown$2,
  12873. edgeActions: edgeActions$2
  12874. });
  12875. const fireSliderChange$1 = (spectrum, value) => {
  12876. emitWith(spectrum, sliderChangeEvent(), { value });
  12877. };
  12878. const findValueOfOffset = (spectrum, detail, top) => {
  12879. const args = {
  12880. min: minY(detail),
  12881. max: maxY(detail),
  12882. range: yRange(detail),
  12883. value: top,
  12884. step: step(detail),
  12885. snap: snap(detail),
  12886. snapStart: snapStart(detail),
  12887. rounded: rounded(detail),
  12888. hasMinEdge: hasTEdge(detail),
  12889. hasMaxEdge: hasBEdge(detail),
  12890. minBound: getMinYBounds(spectrum),
  12891. maxBound: getMaxYBounds(spectrum),
  12892. screenRange: getYScreenRange(spectrum)
  12893. };
  12894. return findValueOf(args);
  12895. };
  12896. const setValueFrom$1 = (spectrum, detail, value) => {
  12897. const yValue = findValueOfOffset(spectrum, detail, value);
  12898. const sliderVal = yValue;
  12899. fireSliderChange$1(spectrum, sliderVal);
  12900. return yValue;
  12901. };
  12902. const setToMin$1 = (spectrum, detail) => {
  12903. const min = minY(detail);
  12904. fireSliderChange$1(spectrum, min);
  12905. };
  12906. const setToMax$1 = (spectrum, detail) => {
  12907. const max = maxY(detail);
  12908. fireSliderChange$1(spectrum, max);
  12909. };
  12910. const moveBy$1 = (direction, spectrum, detail) => {
  12911. const f = direction > 0 ? increaseBy : reduceBy;
  12912. const yValue = f(currentValue(detail), minY(detail), maxY(detail), step(detail));
  12913. fireSliderChange$1(spectrum, yValue);
  12914. return Optional.some(yValue);
  12915. };
  12916. const handleMovement$1 = direction => (spectrum, detail) => moveBy$1(direction, spectrum, detail).map(always);
  12917. const getValueFromEvent$1 = simulatedEvent => {
  12918. const pos = getEventSource(simulatedEvent);
  12919. return pos.map(p => {
  12920. return p.top;
  12921. });
  12922. };
  12923. const findOffsetOfValue = (spectrum, detail, value, minEdge, maxEdge) => {
  12924. const minOffset = 0;
  12925. const maxOffset = getYScreenRange(spectrum);
  12926. const centerMinEdge = minEdge.bind(edge => Optional.some(getYCenterOffSetOf(edge, spectrum))).getOr(minOffset);
  12927. const centerMaxEdge = maxEdge.bind(edge => Optional.some(getYCenterOffSetOf(edge, spectrum))).getOr(maxOffset);
  12928. const args = {
  12929. min: minY(detail),
  12930. max: maxY(detail),
  12931. range: yRange(detail),
  12932. value,
  12933. hasMinEdge: hasTEdge(detail),
  12934. hasMaxEdge: hasBEdge(detail),
  12935. minBound: getMinYBounds(spectrum),
  12936. minOffset,
  12937. maxBound: getMaxYBounds(spectrum),
  12938. maxOffset,
  12939. centerMinEdge,
  12940. centerMaxEdge
  12941. };
  12942. return findOffsetOfValue$2(args);
  12943. };
  12944. const findPositionOfValue = (slider, spectrum, value, minEdge, maxEdge, detail) => {
  12945. const offset = findOffsetOfValue(spectrum, detail, value, minEdge, maxEdge);
  12946. return getMinYBounds(spectrum) - getMinYBounds(slider) + offset;
  12947. };
  12948. const setPositionFromValue$1 = (slider, thumb, detail, edges) => {
  12949. const value = currentValue(detail);
  12950. const pos = findPositionOfValue(slider, edges.getSpectrum(slider), value, edges.getTopEdge(slider), edges.getBottomEdge(slider), detail);
  12951. const thumbRadius = get$d(thumb.element) / 2;
  12952. set$8(thumb.element, 'top', pos - thumbRadius + 'px');
  12953. };
  12954. const onLeft$1 = Optional.none;
  12955. const onRight$1 = Optional.none;
  12956. const onUp$1 = handleMovement$1(-1);
  12957. const onDown$1 = handleMovement$1(1);
  12958. const edgeActions$1 = {
  12959. 'top-left': Optional.none(),
  12960. 'top': Optional.some(setToTEdge),
  12961. 'top-right': Optional.none(),
  12962. 'right': Optional.none(),
  12963. 'bottom-right': Optional.none(),
  12964. 'bottom': Optional.some(setToBEdge),
  12965. 'bottom-left': Optional.none(),
  12966. 'left': Optional.none()
  12967. };
  12968. var VerticalModel = /*#__PURE__*/Object.freeze({
  12969. __proto__: null,
  12970. setValueFrom: setValueFrom$1,
  12971. setToMin: setToMin$1,
  12972. setToMax: setToMax$1,
  12973. findValueOfOffset: findValueOfOffset,
  12974. getValueFromEvent: getValueFromEvent$1,
  12975. findPositionOfValue: findPositionOfValue,
  12976. setPositionFromValue: setPositionFromValue$1,
  12977. onLeft: onLeft$1,
  12978. onRight: onRight$1,
  12979. onUp: onUp$1,
  12980. onDown: onDown$1,
  12981. edgeActions: edgeActions$1
  12982. });
  12983. const fireSliderChange = (spectrum, value) => {
  12984. emitWith(spectrum, sliderChangeEvent(), { value });
  12985. };
  12986. const sliderValue = (x, y) => ({
  12987. x,
  12988. y
  12989. });
  12990. const setValueFrom = (spectrum, detail, value) => {
  12991. const xValue = findValueOfOffset$1(spectrum, detail, value.left);
  12992. const yValue = findValueOfOffset(spectrum, detail, value.top);
  12993. const val = sliderValue(xValue, yValue);
  12994. fireSliderChange(spectrum, val);
  12995. return val;
  12996. };
  12997. const moveBy = (direction, isVerticalMovement, spectrum, detail) => {
  12998. const f = direction > 0 ? increaseBy : reduceBy;
  12999. const xValue = isVerticalMovement ? currentValue(detail).x : f(currentValue(detail).x, minX(detail), maxX(detail), step(detail));
  13000. const yValue = !isVerticalMovement ? currentValue(detail).y : f(currentValue(detail).y, minY(detail), maxY(detail), step(detail));
  13001. fireSliderChange(spectrum, sliderValue(xValue, yValue));
  13002. return Optional.some(xValue);
  13003. };
  13004. const handleMovement = (direction, isVerticalMovement) => (spectrum, detail) => moveBy(direction, isVerticalMovement, spectrum, detail).map(always);
  13005. const setToMin = (spectrum, detail) => {
  13006. const mX = minX(detail);
  13007. const mY = minY(detail);
  13008. fireSliderChange(spectrum, sliderValue(mX, mY));
  13009. };
  13010. const setToMax = (spectrum, detail) => {
  13011. const mX = maxX(detail);
  13012. const mY = maxY(detail);
  13013. fireSliderChange(spectrum, sliderValue(mX, mY));
  13014. };
  13015. const getValueFromEvent = simulatedEvent => getEventSource(simulatedEvent);
  13016. const setPositionFromValue = (slider, thumb, detail, edges) => {
  13017. const value = currentValue(detail);
  13018. const xPos = findPositionOfValue$1(slider, edges.getSpectrum(slider), value.x, edges.getLeftEdge(slider), edges.getRightEdge(slider), detail);
  13019. const yPos = findPositionOfValue(slider, edges.getSpectrum(slider), value.y, edges.getTopEdge(slider), edges.getBottomEdge(slider), detail);
  13020. const thumbXRadius = get$c(thumb.element) / 2;
  13021. const thumbYRadius = get$d(thumb.element) / 2;
  13022. set$8(thumb.element, 'left', xPos - thumbXRadius + 'px');
  13023. set$8(thumb.element, 'top', yPos - thumbYRadius + 'px');
  13024. };
  13025. const onLeft = handleMovement(-1, false);
  13026. const onRight = handleMovement(1, false);
  13027. const onUp = handleMovement(-1, true);
  13028. const onDown = handleMovement(1, true);
  13029. const edgeActions = {
  13030. 'top-left': Optional.some(setToTLEdgeXY),
  13031. 'top': Optional.some(setToTEdgeXY),
  13032. 'top-right': Optional.some(setToTREdgeXY),
  13033. 'right': Optional.some(setToREdgeXY),
  13034. 'bottom-right': Optional.some(setToBREdgeXY),
  13035. 'bottom': Optional.some(setToBEdgeXY),
  13036. 'bottom-left': Optional.some(setToBLEdgeXY),
  13037. 'left': Optional.some(setToLEdgeXY)
  13038. };
  13039. var TwoDModel = /*#__PURE__*/Object.freeze({
  13040. __proto__: null,
  13041. setValueFrom: setValueFrom,
  13042. setToMin: setToMin,
  13043. setToMax: setToMax,
  13044. getValueFromEvent: getValueFromEvent,
  13045. setPositionFromValue: setPositionFromValue,
  13046. onLeft: onLeft,
  13047. onRight: onRight,
  13048. onUp: onUp,
  13049. onDown: onDown,
  13050. edgeActions: edgeActions
  13051. });
  13052. const SliderSchema = [
  13053. defaulted('stepSize', 1),
  13054. defaulted('onChange', noop),
  13055. defaulted('onChoose', noop),
  13056. defaulted('onInit', noop),
  13057. defaulted('onDragStart', noop),
  13058. defaulted('onDragEnd', noop),
  13059. defaulted('snapToGrid', false),
  13060. defaulted('rounded', true),
  13061. option$3('snapStart'),
  13062. requiredOf('model', choose$1('mode', {
  13063. x: [
  13064. defaulted('minX', 0),
  13065. defaulted('maxX', 100),
  13066. customField('value', spec => Cell(spec.mode.minX)),
  13067. required$1('getInitialValue'),
  13068. output$1('manager', HorizontalModel)
  13069. ],
  13070. y: [
  13071. defaulted('minY', 0),
  13072. defaulted('maxY', 100),
  13073. customField('value', spec => Cell(spec.mode.minY)),
  13074. required$1('getInitialValue'),
  13075. output$1('manager', VerticalModel)
  13076. ],
  13077. xy: [
  13078. defaulted('minX', 0),
  13079. defaulted('maxX', 100),
  13080. defaulted('minY', 0),
  13081. defaulted('maxY', 100),
  13082. customField('value', spec => Cell({
  13083. x: spec.mode.minX,
  13084. y: spec.mode.minY
  13085. })),
  13086. required$1('getInitialValue'),
  13087. output$1('manager', TwoDModel)
  13088. ]
  13089. })),
  13090. field('sliderBehaviours', [
  13091. Keying,
  13092. Representing
  13093. ]),
  13094. customField('mouseIsDown', () => Cell(false))
  13095. ];
  13096. const sketch$2 = (detail, components, _spec, _externals) => {
  13097. const getThumb = component => getPartOrDie(component, detail, 'thumb');
  13098. const getSpectrum = component => getPartOrDie(component, detail, 'spectrum');
  13099. const getLeftEdge = component => getPart(component, detail, 'left-edge');
  13100. const getRightEdge = component => getPart(component, detail, 'right-edge');
  13101. const getTopEdge = component => getPart(component, detail, 'top-edge');
  13102. const getBottomEdge = component => getPart(component, detail, 'bottom-edge');
  13103. const modelDetail = detail.model;
  13104. const model = modelDetail.manager;
  13105. const refresh = (slider, thumb) => {
  13106. model.setPositionFromValue(slider, thumb, detail, {
  13107. getLeftEdge,
  13108. getRightEdge,
  13109. getTopEdge,
  13110. getBottomEdge,
  13111. getSpectrum
  13112. });
  13113. };
  13114. const setValue = (slider, newValue) => {
  13115. modelDetail.value.set(newValue);
  13116. const thumb = getThumb(slider);
  13117. refresh(slider, thumb);
  13118. };
  13119. const changeValue = (slider, newValue) => {
  13120. setValue(slider, newValue);
  13121. const thumb = getThumb(slider);
  13122. detail.onChange(slider, thumb, newValue);
  13123. return Optional.some(true);
  13124. };
  13125. const resetToMin = slider => {
  13126. model.setToMin(slider, detail);
  13127. };
  13128. const resetToMax = slider => {
  13129. model.setToMax(slider, detail);
  13130. };
  13131. const choose = slider => {
  13132. const fireOnChoose = () => {
  13133. getPart(slider, detail, 'thumb').each(thumb => {
  13134. const value = modelDetail.value.get();
  13135. detail.onChoose(slider, thumb, value);
  13136. });
  13137. };
  13138. const wasDown = detail.mouseIsDown.get();
  13139. detail.mouseIsDown.set(false);
  13140. if (wasDown) {
  13141. fireOnChoose();
  13142. }
  13143. };
  13144. const onDragStart = (slider, simulatedEvent) => {
  13145. simulatedEvent.stop();
  13146. detail.mouseIsDown.set(true);
  13147. detail.onDragStart(slider, getThumb(slider));
  13148. };
  13149. const onDragEnd = (slider, simulatedEvent) => {
  13150. simulatedEvent.stop();
  13151. detail.onDragEnd(slider, getThumb(slider));
  13152. choose(slider);
  13153. };
  13154. return {
  13155. uid: detail.uid,
  13156. dom: detail.dom,
  13157. components,
  13158. behaviours: augment(detail.sliderBehaviours, [
  13159. Keying.config({
  13160. mode: 'special',
  13161. focusIn: slider => {
  13162. return getPart(slider, detail, 'spectrum').map(Keying.focusIn).map(always);
  13163. }
  13164. }),
  13165. Representing.config({
  13166. store: {
  13167. mode: 'manual',
  13168. getValue: _ => {
  13169. return modelDetail.value.get();
  13170. },
  13171. setValue
  13172. }
  13173. }),
  13174. Receiving.config({ channels: { [mouseReleased()]: { onReceive: choose } } })
  13175. ]),
  13176. events: derive$2([
  13177. run$1(sliderChangeEvent(), (slider, simulatedEvent) => {
  13178. changeValue(slider, simulatedEvent.event.value);
  13179. }),
  13180. runOnAttached((slider, _simulatedEvent) => {
  13181. const getInitial = modelDetail.getInitialValue();
  13182. modelDetail.value.set(getInitial);
  13183. const thumb = getThumb(slider);
  13184. refresh(slider, thumb);
  13185. const spectrum = getSpectrum(slider);
  13186. detail.onInit(slider, thumb, spectrum, modelDetail.value.get());
  13187. }),
  13188. run$1(touchstart(), onDragStart),
  13189. run$1(touchend(), onDragEnd),
  13190. run$1(mousedown(), onDragStart),
  13191. run$1(mouseup(), onDragEnd)
  13192. ]),
  13193. apis: {
  13194. resetToMin,
  13195. resetToMax,
  13196. setValue,
  13197. refresh
  13198. },
  13199. domModification: { styles: { position: 'relative' } }
  13200. };
  13201. };
  13202. const Slider = composite({
  13203. name: 'Slider',
  13204. configFields: SliderSchema,
  13205. partFields: SliderParts,
  13206. factory: sketch$2,
  13207. apis: {
  13208. setValue: (apis, slider, value) => {
  13209. apis.setValue(slider, value);
  13210. },
  13211. resetToMin: (apis, slider) => {
  13212. apis.resetToMin(slider);
  13213. },
  13214. resetToMax: (apis, slider) => {
  13215. apis.resetToMax(slider);
  13216. },
  13217. refresh: (apis, slider) => {
  13218. apis.refresh(slider);
  13219. }
  13220. }
  13221. });
  13222. const fieldsUpdate = generate$6('rgb-hex-update');
  13223. const sliderUpdate = generate$6('slider-update');
  13224. const paletteUpdate = generate$6('palette-update');
  13225. const sliderFactory = (translate, getClass) => {
  13226. const spectrum = Slider.parts.spectrum({
  13227. dom: {
  13228. tag: 'div',
  13229. classes: [getClass('hue-slider-spectrum')],
  13230. attributes: { role: 'presentation' }
  13231. }
  13232. });
  13233. const thumb = Slider.parts.thumb({
  13234. dom: {
  13235. tag: 'div',
  13236. classes: [getClass('hue-slider-thumb')],
  13237. attributes: { role: 'presentation' }
  13238. }
  13239. });
  13240. return Slider.sketch({
  13241. dom: {
  13242. tag: 'div',
  13243. classes: [getClass('hue-slider')],
  13244. attributes: { role: 'presentation' }
  13245. },
  13246. rounded: false,
  13247. model: {
  13248. mode: 'y',
  13249. getInitialValue: constant$1(0)
  13250. },
  13251. components: [
  13252. spectrum,
  13253. thumb
  13254. ],
  13255. sliderBehaviours: derive$1([Focusing.config({})]),
  13256. onChange: (slider, _thumb, value) => {
  13257. emitWith(slider, sliderUpdate, { value });
  13258. }
  13259. });
  13260. };
  13261. const owner$1 = 'form';
  13262. const schema$i = [field('formBehaviours', [Representing])];
  13263. const getPartName$1 = name => '<alloy.field.' + name + '>';
  13264. const sketch$1 = fSpec => {
  13265. const parts = (() => {
  13266. const record = [];
  13267. const field = (name, config) => {
  13268. record.push(name);
  13269. return generateOne$1(owner$1, getPartName$1(name), config);
  13270. };
  13271. return {
  13272. field,
  13273. record: constant$1(record)
  13274. };
  13275. })();
  13276. const spec = fSpec(parts);
  13277. const partNames = parts.record();
  13278. const fieldParts = map$2(partNames, n => required({
  13279. name: n,
  13280. pname: getPartName$1(n)
  13281. }));
  13282. return composite$1(owner$1, schema$i, fieldParts, make$4, spec);
  13283. };
  13284. const toResult = (o, e) => o.fold(() => Result.error(e), Result.value);
  13285. const make$4 = (detail, components) => ({
  13286. uid: detail.uid,
  13287. dom: detail.dom,
  13288. components,
  13289. behaviours: augment(detail.formBehaviours, [Representing.config({
  13290. store: {
  13291. mode: 'manual',
  13292. getValue: form => {
  13293. const resPs = getAllParts(form, detail);
  13294. return map$1(resPs, (resPThunk, pName) => resPThunk().bind(v => {
  13295. const opt = Composing.getCurrent(v);
  13296. return toResult(opt, new Error(`Cannot find a current component to extract the value from for form part '${ pName }': ` + element(v.element)));
  13297. }).map(Representing.getValue));
  13298. },
  13299. setValue: (form, values) => {
  13300. each(values, (newValue, key) => {
  13301. getPart(form, detail, key).each(wrapper => {
  13302. Composing.getCurrent(wrapper).each(field => {
  13303. Representing.setValue(field, newValue);
  13304. });
  13305. });
  13306. });
  13307. }
  13308. }
  13309. })]),
  13310. apis: {
  13311. getField: (form, key) => {
  13312. return getPart(form, detail, key).bind(Composing.getCurrent);
  13313. }
  13314. }
  13315. });
  13316. const Form = {
  13317. getField: makeApi((apis, component, key) => apis.getField(component, key)),
  13318. sketch: sketch$1
  13319. };
  13320. const validInput = generate$6('valid-input');
  13321. const invalidInput = generate$6('invalid-input');
  13322. const validatingInput = generate$6('validating-input');
  13323. const translatePrefix = 'colorcustom.rgb.';
  13324. const rgbFormFactory = (translate, getClass, onValidHexx, onInvalidHexx) => {
  13325. const invalidation = (label, isValid) => Invalidating.config({
  13326. invalidClass: getClass('invalid'),
  13327. notify: {
  13328. onValidate: comp => {
  13329. emitWith(comp, validatingInput, { type: label });
  13330. },
  13331. onValid: comp => {
  13332. emitWith(comp, validInput, {
  13333. type: label,
  13334. value: Representing.getValue(comp)
  13335. });
  13336. },
  13337. onInvalid: comp => {
  13338. emitWith(comp, invalidInput, {
  13339. type: label,
  13340. value: Representing.getValue(comp)
  13341. });
  13342. }
  13343. },
  13344. validator: {
  13345. validate: comp => {
  13346. const value = Representing.getValue(comp);
  13347. const res = isValid(value) ? Result.value(true) : Result.error(translate('aria.input.invalid'));
  13348. return Future.pure(res);
  13349. },
  13350. validateOnLoad: false
  13351. }
  13352. });
  13353. const renderTextField = (isValid, name, label, description, data) => {
  13354. const helptext = translate(translatePrefix + 'range');
  13355. const pLabel = FormField.parts.label({
  13356. dom: {
  13357. tag: 'label',
  13358. attributes: { 'aria-label': description }
  13359. },
  13360. components: [text$2(label)]
  13361. });
  13362. const pField = FormField.parts.field({
  13363. data,
  13364. factory: Input,
  13365. inputAttributes: {
  13366. type: 'text',
  13367. ...name === 'hex' ? { 'aria-live': 'polite' } : {}
  13368. },
  13369. inputClasses: [getClass('textfield')],
  13370. inputBehaviours: derive$1([
  13371. invalidation(name, isValid),
  13372. Tabstopping.config({})
  13373. ]),
  13374. onSetValue: input => {
  13375. if (Invalidating.isInvalid(input)) {
  13376. const run = Invalidating.run(input);
  13377. run.get(noop);
  13378. }
  13379. }
  13380. });
  13381. const comps = [
  13382. pLabel,
  13383. pField
  13384. ];
  13385. const concats = name !== 'hex' ? [FormField.parts['aria-descriptor']({ text: helptext })] : [];
  13386. const components = comps.concat(concats);
  13387. return {
  13388. dom: {
  13389. tag: 'div',
  13390. attributes: { role: 'presentation' }
  13391. },
  13392. components
  13393. };
  13394. };
  13395. const copyRgbToHex = (form, rgba) => {
  13396. const hex = fromRgba(rgba);
  13397. Form.getField(form, 'hex').each(hexField => {
  13398. if (!Focusing.isFocused(hexField)) {
  13399. Representing.setValue(form, { hex: hex.value });
  13400. }
  13401. });
  13402. return hex;
  13403. };
  13404. const copyRgbToForm = (form, rgb) => {
  13405. const red = rgb.red;
  13406. const green = rgb.green;
  13407. const blue = rgb.blue;
  13408. Representing.setValue(form, {
  13409. red,
  13410. green,
  13411. blue
  13412. });
  13413. };
  13414. const memPreview = record({
  13415. dom: {
  13416. tag: 'div',
  13417. classes: [getClass('rgba-preview')],
  13418. styles: { 'background-color': 'white' },
  13419. attributes: { role: 'presentation' }
  13420. }
  13421. });
  13422. const updatePreview = (anyInSystem, hex) => {
  13423. memPreview.getOpt(anyInSystem).each(preview => {
  13424. set$8(preview.element, 'background-color', '#' + hex.value);
  13425. });
  13426. };
  13427. const factory = () => {
  13428. const state = {
  13429. red: Cell(Optional.some(255)),
  13430. green: Cell(Optional.some(255)),
  13431. blue: Cell(Optional.some(255)),
  13432. hex: Cell(Optional.some('ffffff'))
  13433. };
  13434. const copyHexToRgb = (form, hex) => {
  13435. const rgb = fromHex(hex);
  13436. copyRgbToForm(form, rgb);
  13437. setValueRgb(rgb);
  13438. };
  13439. const get = prop => state[prop].get();
  13440. const set = (prop, value) => {
  13441. state[prop].set(value);
  13442. };
  13443. const getValueRgb = () => get('red').bind(red => get('green').bind(green => get('blue').map(blue => rgbaColour(red, green, blue, 1))));
  13444. const setValueRgb = rgb => {
  13445. const red = rgb.red;
  13446. const green = rgb.green;
  13447. const blue = rgb.blue;
  13448. set('red', Optional.some(red));
  13449. set('green', Optional.some(green));
  13450. set('blue', Optional.some(blue));
  13451. };
  13452. const onInvalidInput = (form, simulatedEvent) => {
  13453. const data = simulatedEvent.event;
  13454. if (data.type !== 'hex') {
  13455. set(data.type, Optional.none());
  13456. } else {
  13457. onInvalidHexx(form);
  13458. }
  13459. };
  13460. const onValidHex = (form, value) => {
  13461. onValidHexx(form);
  13462. const hex = hexColour(value);
  13463. set('hex', Optional.some(hex.value));
  13464. const rgb = fromHex(hex);
  13465. copyRgbToForm(form, rgb);
  13466. setValueRgb(rgb);
  13467. emitWith(form, fieldsUpdate, { hex });
  13468. updatePreview(form, hex);
  13469. };
  13470. const onValidRgb = (form, prop, value) => {
  13471. const val = parseInt(value, 10);
  13472. set(prop, Optional.some(val));
  13473. getValueRgb().each(rgb => {
  13474. const hex = copyRgbToHex(form, rgb);
  13475. emitWith(form, fieldsUpdate, { hex });
  13476. updatePreview(form, hex);
  13477. });
  13478. };
  13479. const isHexInputEvent = data => data.type === 'hex';
  13480. const onValidInput = (form, simulatedEvent) => {
  13481. const data = simulatedEvent.event;
  13482. if (isHexInputEvent(data)) {
  13483. onValidHex(form, data.value);
  13484. } else {
  13485. onValidRgb(form, data.type, data.value);
  13486. }
  13487. };
  13488. const formPartStrings = key => ({
  13489. label: translate(translatePrefix + key + '.label'),
  13490. description: translate(translatePrefix + key + '.description')
  13491. });
  13492. const redStrings = formPartStrings('red');
  13493. const greenStrings = formPartStrings('green');
  13494. const blueStrings = formPartStrings('blue');
  13495. const hexStrings = formPartStrings('hex');
  13496. return deepMerge(Form.sketch(parts => ({
  13497. dom: {
  13498. tag: 'form',
  13499. classes: [getClass('rgb-form')],
  13500. attributes: { 'aria-label': translate('aria.color.picker') }
  13501. },
  13502. components: [
  13503. parts.field('red', FormField.sketch(renderTextField(isRgbaComponent, 'red', redStrings.label, redStrings.description, 255))),
  13504. parts.field('green', FormField.sketch(renderTextField(isRgbaComponent, 'green', greenStrings.label, greenStrings.description, 255))),
  13505. parts.field('blue', FormField.sketch(renderTextField(isRgbaComponent, 'blue', blueStrings.label, blueStrings.description, 255))),
  13506. parts.field('hex', FormField.sketch(renderTextField(isHexString, 'hex', hexStrings.label, hexStrings.description, 'ffffff'))),
  13507. memPreview.asSpec()
  13508. ],
  13509. formBehaviours: derive$1([
  13510. Invalidating.config({ invalidClass: getClass('form-invalid') }),
  13511. config('rgb-form-events', [
  13512. run$1(validInput, onValidInput),
  13513. run$1(invalidInput, onInvalidInput),
  13514. run$1(validatingInput, onInvalidInput)
  13515. ])
  13516. ])
  13517. })), {
  13518. apis: {
  13519. updateHex: (form, hex) => {
  13520. Representing.setValue(form, { hex: hex.value });
  13521. copyHexToRgb(form, hex);
  13522. updatePreview(form, hex);
  13523. }
  13524. }
  13525. });
  13526. };
  13527. const rgbFormSketcher = single({
  13528. factory,
  13529. name: 'RgbForm',
  13530. configFields: [],
  13531. apis: {
  13532. updateHex: (apis, form, hex) => {
  13533. apis.updateHex(form, hex);
  13534. }
  13535. },
  13536. extraApis: {}
  13537. });
  13538. return rgbFormSketcher;
  13539. };
  13540. const paletteFactory = (_translate, getClass) => {
  13541. const spectrumPart = Slider.parts.spectrum({
  13542. dom: {
  13543. tag: 'canvas',
  13544. attributes: { role: 'presentation' },
  13545. classes: [getClass('sv-palette-spectrum')]
  13546. }
  13547. });
  13548. const thumbPart = Slider.parts.thumb({
  13549. dom: {
  13550. tag: 'div',
  13551. attributes: { role: 'presentation' },
  13552. classes: [getClass('sv-palette-thumb')],
  13553. innerHtml: `<div class=${ getClass('sv-palette-inner-thumb') } role="presentation"></div>`
  13554. }
  13555. });
  13556. const setColour = (canvas, rgba) => {
  13557. const {width, height} = canvas;
  13558. const ctx = canvas.getContext('2d');
  13559. if (ctx === null) {
  13560. return;
  13561. }
  13562. ctx.fillStyle = rgba;
  13563. ctx.fillRect(0, 0, width, height);
  13564. const grdWhite = ctx.createLinearGradient(0, 0, width, 0);
  13565. grdWhite.addColorStop(0, 'rgba(255,255,255,1)');
  13566. grdWhite.addColorStop(1, 'rgba(255,255,255,0)');
  13567. ctx.fillStyle = grdWhite;
  13568. ctx.fillRect(0, 0, width, height);
  13569. const grdBlack = ctx.createLinearGradient(0, 0, 0, height);
  13570. grdBlack.addColorStop(0, 'rgba(0,0,0,0)');
  13571. grdBlack.addColorStop(1, 'rgba(0,0,0,1)');
  13572. ctx.fillStyle = grdBlack;
  13573. ctx.fillRect(0, 0, width, height);
  13574. };
  13575. const setPaletteHue = (slider, hue) => {
  13576. const canvas = slider.components()[0].element.dom;
  13577. const hsv = hsvColour(hue, 100, 100);
  13578. const rgba = fromHsv(hsv);
  13579. setColour(canvas, toString(rgba));
  13580. };
  13581. const setPaletteThumb = (slider, hex) => {
  13582. const hsv = fromRgb(fromHex(hex));
  13583. Slider.setValue(slider, {
  13584. x: hsv.saturation,
  13585. y: 100 - hsv.value
  13586. });
  13587. };
  13588. const factory = _detail => {
  13589. const getInitialValue = constant$1({
  13590. x: 0,
  13591. y: 0
  13592. });
  13593. const onChange = (slider, _thumb, value) => {
  13594. emitWith(slider, paletteUpdate, { value });
  13595. };
  13596. const onInit = (_slider, _thumb, spectrum, _value) => {
  13597. setColour(spectrum.element.dom, toString(red));
  13598. };
  13599. const sliderBehaviours = derive$1([
  13600. Composing.config({ find: Optional.some }),
  13601. Focusing.config({})
  13602. ]);
  13603. return Slider.sketch({
  13604. dom: {
  13605. tag: 'div',
  13606. attributes: { role: 'presentation' },
  13607. classes: [getClass('sv-palette')]
  13608. },
  13609. model: {
  13610. mode: 'xy',
  13611. getInitialValue
  13612. },
  13613. rounded: false,
  13614. components: [
  13615. spectrumPart,
  13616. thumbPart
  13617. ],
  13618. onChange,
  13619. onInit,
  13620. sliderBehaviours
  13621. });
  13622. };
  13623. const saturationBrightnessPaletteSketcher = single({
  13624. factory,
  13625. name: 'SaturationBrightnessPalette',
  13626. configFields: [],
  13627. apis: {
  13628. setHue: (_apis, slider, hue) => {
  13629. setPaletteHue(slider, hue);
  13630. },
  13631. setThumb: (_apis, slider, hex) => {
  13632. setPaletteThumb(slider, hex);
  13633. }
  13634. },
  13635. extraApis: {}
  13636. });
  13637. return saturationBrightnessPaletteSketcher;
  13638. };
  13639. const makeFactory = (translate, getClass) => {
  13640. const factory = detail => {
  13641. const rgbForm = rgbFormFactory(translate, getClass, detail.onValidHex, detail.onInvalidHex);
  13642. const sbPalette = paletteFactory(translate, getClass);
  13643. const hueSliderToDegrees = hue => (100 - hue) / 100 * 360;
  13644. const hueDegreesToSlider = hue => 100 - hue / 360 * 100;
  13645. const state = {
  13646. paletteRgba: Cell(red),
  13647. paletteHue: Cell(0)
  13648. };
  13649. const memSlider = record(sliderFactory(translate, getClass));
  13650. const memPalette = record(sbPalette.sketch({}));
  13651. const memRgb = record(rgbForm.sketch({}));
  13652. const updatePalette = (anyInSystem, _hex, hue) => {
  13653. memPalette.getOpt(anyInSystem).each(palette => {
  13654. sbPalette.setHue(palette, hue);
  13655. });
  13656. };
  13657. const updateFields = (anyInSystem, hex) => {
  13658. memRgb.getOpt(anyInSystem).each(form => {
  13659. rgbForm.updateHex(form, hex);
  13660. });
  13661. };
  13662. const updateSlider = (anyInSystem, _hex, hue) => {
  13663. memSlider.getOpt(anyInSystem).each(slider => {
  13664. Slider.setValue(slider, hueDegreesToSlider(hue));
  13665. });
  13666. };
  13667. const updatePaletteThumb = (anyInSystem, hex) => {
  13668. memPalette.getOpt(anyInSystem).each(palette => {
  13669. sbPalette.setThumb(palette, hex);
  13670. });
  13671. };
  13672. const updateState = (hex, hue) => {
  13673. const rgba = fromHex(hex);
  13674. state.paletteRgba.set(rgba);
  13675. state.paletteHue.set(hue);
  13676. };
  13677. const runUpdates = (anyInSystem, hex, hue, updates) => {
  13678. updateState(hex, hue);
  13679. each$1(updates, update => {
  13680. update(anyInSystem, hex, hue);
  13681. });
  13682. };
  13683. const onPaletteUpdate = () => {
  13684. const updates = [updateFields];
  13685. return (form, simulatedEvent) => {
  13686. const value = simulatedEvent.event.value;
  13687. const oldHue = state.paletteHue.get();
  13688. const newHsv = hsvColour(oldHue, value.x, 100 - value.y);
  13689. const newHex = hsvToHex(newHsv);
  13690. runUpdates(form, newHex, oldHue, updates);
  13691. };
  13692. };
  13693. const onSliderUpdate = () => {
  13694. const updates = [
  13695. updatePalette,
  13696. updateFields
  13697. ];
  13698. return (form, simulatedEvent) => {
  13699. const hue = hueSliderToDegrees(simulatedEvent.event.value);
  13700. const oldRgb = state.paletteRgba.get();
  13701. const oldHsv = fromRgb(oldRgb);
  13702. const newHsv = hsvColour(hue, oldHsv.saturation, oldHsv.value);
  13703. const newHex = hsvToHex(newHsv);
  13704. runUpdates(form, newHex, hue, updates);
  13705. };
  13706. };
  13707. const onFieldsUpdate = () => {
  13708. const updates = [
  13709. updatePalette,
  13710. updateSlider,
  13711. updatePaletteThumb
  13712. ];
  13713. return (form, simulatedEvent) => {
  13714. const hex = simulatedEvent.event.hex;
  13715. const hsv = hexToHsv(hex);
  13716. runUpdates(form, hex, hsv.hue, updates);
  13717. };
  13718. };
  13719. return {
  13720. uid: detail.uid,
  13721. dom: detail.dom,
  13722. components: [
  13723. memPalette.asSpec(),
  13724. memSlider.asSpec(),
  13725. memRgb.asSpec()
  13726. ],
  13727. behaviours: derive$1([
  13728. config('colour-picker-events', [
  13729. run$1(fieldsUpdate, onFieldsUpdate()),
  13730. run$1(paletteUpdate, onPaletteUpdate()),
  13731. run$1(sliderUpdate, onSliderUpdate())
  13732. ]),
  13733. Composing.config({ find: comp => memRgb.getOpt(comp) }),
  13734. Keying.config({ mode: 'acyclic' })
  13735. ])
  13736. };
  13737. };
  13738. const colourPickerSketcher = single({
  13739. name: 'ColourPicker',
  13740. configFields: [
  13741. required$1('dom'),
  13742. defaulted('onValidHex', noop),
  13743. defaulted('onInvalidHex', noop)
  13744. ],
  13745. factory
  13746. });
  13747. return colourPickerSketcher;
  13748. };
  13749. const self = () => Composing.config({ find: Optional.some });
  13750. const memento$1 = mem => Composing.config({ find: mem.getOpt });
  13751. const childAt = index => Composing.config({ find: comp => child$2(comp.element, index).bind(element => comp.getSystem().getByDom(element).toOptional()) });
  13752. const ComposingConfigs = {
  13753. self,
  13754. memento: memento$1,
  13755. childAt
  13756. };
  13757. const processors = objOf([
  13758. defaulted('preprocess', identity),
  13759. defaulted('postprocess', identity)
  13760. ]);
  13761. const memento = (mem, rawProcessors) => {
  13762. const ps = asRawOrDie$1('RepresentingConfigs.memento processors', processors, rawProcessors);
  13763. return Representing.config({
  13764. store: {
  13765. mode: 'manual',
  13766. getValue: comp => {
  13767. const other = mem.get(comp);
  13768. const rawValue = Representing.getValue(other);
  13769. return ps.postprocess(rawValue);
  13770. },
  13771. setValue: (comp, rawValue) => {
  13772. const newValue = ps.preprocess(rawValue);
  13773. const other = mem.get(comp);
  13774. Representing.setValue(other, newValue);
  13775. }
  13776. }
  13777. });
  13778. };
  13779. const withComp = (optInitialValue, getter, setter) => Representing.config({
  13780. store: {
  13781. mode: 'manual',
  13782. ...optInitialValue.map(initialValue => ({ initialValue })).getOr({}),
  13783. getValue: getter,
  13784. setValue: setter
  13785. }
  13786. });
  13787. const withElement = (initialValue, getter, setter) => withComp(initialValue, c => getter(c.element), (c, v) => setter(c.element, v));
  13788. const domValue = optInitialValue => withElement(optInitialValue, get$6, set$5);
  13789. const domHtml = optInitialValue => withElement(optInitialValue, get$9, set$6);
  13790. const memory = initialValue => Representing.config({
  13791. store: {
  13792. mode: 'memory',
  13793. initialValue
  13794. }
  13795. });
  13796. const RepresentingConfigs = {
  13797. memento,
  13798. withElement,
  13799. withComp,
  13800. domValue,
  13801. domHtml,
  13802. memory
  13803. };
  13804. const english = {
  13805. 'colorcustom.rgb.red.label': 'R',
  13806. 'colorcustom.rgb.red.description': 'Red component',
  13807. 'colorcustom.rgb.green.label': 'G',
  13808. 'colorcustom.rgb.green.description': 'Green component',
  13809. 'colorcustom.rgb.blue.label': 'B',
  13810. 'colorcustom.rgb.blue.description': 'Blue component',
  13811. 'colorcustom.rgb.hex.label': '#',
  13812. 'colorcustom.rgb.hex.description': 'Hex color code',
  13813. 'colorcustom.rgb.range': 'Range 0 to 255',
  13814. 'aria.color.picker': 'Color Picker',
  13815. 'aria.input.invalid': 'Invalid input'
  13816. };
  13817. const translate$1 = providerBackstage => key => {
  13818. return providerBackstage.translate(english[key]);
  13819. };
  13820. const renderColorPicker = (_spec, providerBackstage, initialData) => {
  13821. const getClass = key => 'tox-' + key;
  13822. const colourPickerFactory = makeFactory(translate$1(providerBackstage), getClass);
  13823. const onValidHex = form => {
  13824. emitWith(form, formActionEvent, {
  13825. name: 'hex-valid',
  13826. value: true
  13827. });
  13828. };
  13829. const onInvalidHex = form => {
  13830. emitWith(form, formActionEvent, {
  13831. name: 'hex-valid',
  13832. value: false
  13833. });
  13834. };
  13835. const memPicker = record(colourPickerFactory.sketch({
  13836. dom: {
  13837. tag: 'div',
  13838. classes: [getClass('color-picker-container')],
  13839. attributes: { role: 'presentation' }
  13840. },
  13841. onValidHex,
  13842. onInvalidHex
  13843. }));
  13844. return {
  13845. dom: { tag: 'div' },
  13846. components: [memPicker.asSpec()],
  13847. behaviours: derive$1([
  13848. RepresentingConfigs.withComp(initialData, comp => {
  13849. const picker = memPicker.get(comp);
  13850. const optRgbForm = Composing.getCurrent(picker);
  13851. const optHex = optRgbForm.bind(rgbForm => {
  13852. const formValues = Representing.getValue(rgbForm);
  13853. return formValues.hex;
  13854. });
  13855. return optHex.map(hex => '#' + removeLeading(hex, '#')).getOr('');
  13856. }, (comp, newValue) => {
  13857. const pattern = /^#([a-fA-F0-9]{3}(?:[a-fA-F0-9]{3})?)/;
  13858. const valOpt = Optional.from(pattern.exec(newValue)).bind(matches => get$h(matches, 1));
  13859. const picker = memPicker.get(comp);
  13860. const optRgbForm = Composing.getCurrent(picker);
  13861. optRgbForm.fold(() => {
  13862. console.log('Can not find form');
  13863. }, rgbForm => {
  13864. Representing.setValue(rgbForm, { hex: valOpt.getOr('') });
  13865. Form.getField(rgbForm, 'hex').each(hexField => {
  13866. emit(hexField, input());
  13867. });
  13868. });
  13869. }),
  13870. ComposingConfigs.self()
  13871. ])
  13872. };
  13873. };
  13874. var global$2 = tinymce.util.Tools.resolve('tinymce.Resource');
  13875. const isOldCustomEditor = spec => has$2(spec, 'init');
  13876. const renderCustomEditor = spec => {
  13877. const editorApi = value$2();
  13878. const memReplaced = record({ dom: { tag: spec.tag } });
  13879. const initialValue = value$2();
  13880. return {
  13881. dom: {
  13882. tag: 'div',
  13883. classes: ['tox-custom-editor']
  13884. },
  13885. behaviours: derive$1([
  13886. config('custom-editor-events', [runOnAttached(component => {
  13887. memReplaced.getOpt(component).each(ta => {
  13888. (isOldCustomEditor(spec) ? spec.init(ta.element.dom) : global$2.load(spec.scriptId, spec.scriptUrl).then(init => init(ta.element.dom, spec.settings))).then(ea => {
  13889. initialValue.on(cvalue => {
  13890. ea.setValue(cvalue);
  13891. });
  13892. initialValue.clear();
  13893. editorApi.set(ea);
  13894. });
  13895. });
  13896. })]),
  13897. RepresentingConfigs.withComp(Optional.none(), () => editorApi.get().fold(() => initialValue.get().getOr(''), ed => ed.getValue()), (component, value) => {
  13898. editorApi.get().fold(() => initialValue.set(value), ed => ed.setValue(value));
  13899. }),
  13900. ComposingConfigs.self()
  13901. ]),
  13902. components: [memReplaced.asSpec()]
  13903. };
  13904. };
  13905. var global$1 = tinymce.util.Tools.resolve('tinymce.util.Tools');
  13906. const filterByExtension = (files, providersBackstage) => {
  13907. const allowedImageFileTypes = global$1.explode(providersBackstage.getOption('images_file_types'));
  13908. const isFileInAllowedTypes = file => exists(allowedImageFileTypes, type => endsWith(file.name.toLowerCase(), `.${ type.toLowerCase() }`));
  13909. return filter$2(from(files), isFileInAllowedTypes);
  13910. };
  13911. const renderDropZone = (spec, providersBackstage, initialData) => {
  13912. const stopper = (_, se) => {
  13913. se.stop();
  13914. };
  13915. const sequence = actions => (comp, se) => {
  13916. each$1(actions, a => {
  13917. a(comp, se);
  13918. });
  13919. };
  13920. const onDrop = (comp, se) => {
  13921. var _a;
  13922. if (!Disabling.isDisabled(comp)) {
  13923. const transferEvent = se.event.raw;
  13924. handleFiles(comp, (_a = transferEvent.dataTransfer) === null || _a === void 0 ? void 0 : _a.files);
  13925. }
  13926. };
  13927. const onSelect = (component, simulatedEvent) => {
  13928. const input = simulatedEvent.event.raw.target;
  13929. handleFiles(component, input.files);
  13930. };
  13931. const handleFiles = (component, files) => {
  13932. if (files) {
  13933. Representing.setValue(component, filterByExtension(files, providersBackstage));
  13934. emitWith(component, formChangeEvent, { name: spec.name });
  13935. }
  13936. };
  13937. const memInput = record({
  13938. dom: {
  13939. tag: 'input',
  13940. attributes: {
  13941. type: 'file',
  13942. accept: 'image/*'
  13943. },
  13944. styles: { display: 'none' }
  13945. },
  13946. behaviours: derive$1([config('input-file-events', [
  13947. cutter(click()),
  13948. cutter(tap())
  13949. ])])
  13950. });
  13951. const renderField = s => ({
  13952. uid: s.uid,
  13953. dom: {
  13954. tag: 'div',
  13955. classes: ['tox-dropzone-container']
  13956. },
  13957. behaviours: derive$1([
  13958. RepresentingConfigs.memory(initialData.getOr([])),
  13959. ComposingConfigs.self(),
  13960. Disabling.config({}),
  13961. Toggling.config({
  13962. toggleClass: 'dragenter',
  13963. toggleOnExecute: false
  13964. }),
  13965. config('dropzone-events', [
  13966. run$1('dragenter', sequence([
  13967. stopper,
  13968. Toggling.toggle
  13969. ])),
  13970. run$1('dragleave', sequence([
  13971. stopper,
  13972. Toggling.toggle
  13973. ])),
  13974. run$1('dragover', stopper),
  13975. run$1('drop', sequence([
  13976. stopper,
  13977. onDrop
  13978. ])),
  13979. run$1(change(), onSelect)
  13980. ])
  13981. ]),
  13982. components: [{
  13983. dom: {
  13984. tag: 'div',
  13985. classes: ['tox-dropzone'],
  13986. styles: {}
  13987. },
  13988. components: [
  13989. {
  13990. dom: { tag: 'p' },
  13991. components: [text$2(providersBackstage.translate('Drop an image here'))]
  13992. },
  13993. Button.sketch({
  13994. dom: {
  13995. tag: 'button',
  13996. styles: { position: 'relative' },
  13997. classes: [
  13998. 'tox-button',
  13999. 'tox-button--secondary'
  14000. ]
  14001. },
  14002. components: [
  14003. text$2(providersBackstage.translate('Browse for an image')),
  14004. memInput.asSpec()
  14005. ],
  14006. action: comp => {
  14007. const inputComp = memInput.get(comp);
  14008. inputComp.element.dom.click();
  14009. },
  14010. buttonBehaviours: derive$1([
  14011. Tabstopping.config({}),
  14012. DisablingConfigs.button(providersBackstage.isDisabled),
  14013. receivingConfig()
  14014. ])
  14015. })
  14016. ]
  14017. }]
  14018. });
  14019. const pLabel = spec.label.map(label => renderLabel$3(label, providersBackstage));
  14020. const pField = FormField.parts.field({ factory: { sketch: renderField } });
  14021. return renderFormFieldWith(pLabel, pField, ['tox-form__group--stretched'], []);
  14022. };
  14023. const renderGrid = (spec, backstage) => ({
  14024. dom: {
  14025. tag: 'div',
  14026. classes: [
  14027. 'tox-form__grid',
  14028. `tox-form__grid--${ spec.columns }col`
  14029. ]
  14030. },
  14031. components: map$2(spec.items, backstage.interpreter)
  14032. });
  14033. const beforeObject = generate$6('alloy-fake-before-tabstop');
  14034. const afterObject = generate$6('alloy-fake-after-tabstop');
  14035. const craftWithClasses = classes => {
  14036. return {
  14037. dom: {
  14038. tag: 'div',
  14039. styles: {
  14040. width: '1px',
  14041. height: '1px',
  14042. outline: 'none'
  14043. },
  14044. attributes: { tabindex: '0' },
  14045. classes
  14046. },
  14047. behaviours: derive$1([
  14048. Focusing.config({ ignore: true }),
  14049. Tabstopping.config({})
  14050. ])
  14051. };
  14052. };
  14053. const craft = spec => {
  14054. return {
  14055. dom: {
  14056. tag: 'div',
  14057. classes: ['tox-navobj']
  14058. },
  14059. components: [
  14060. craftWithClasses([beforeObject]),
  14061. spec,
  14062. craftWithClasses([afterObject])
  14063. ],
  14064. behaviours: derive$1([ComposingConfigs.childAt(1)])
  14065. };
  14066. };
  14067. const triggerTab = (placeholder, shiftKey) => {
  14068. emitWith(placeholder, keydown(), {
  14069. raw: {
  14070. which: 9,
  14071. shiftKey
  14072. }
  14073. });
  14074. };
  14075. const onFocus = (container, targetComp) => {
  14076. const target = targetComp.element;
  14077. if (has(target, beforeObject)) {
  14078. triggerTab(container, true);
  14079. } else if (has(target, afterObject)) {
  14080. triggerTab(container, false);
  14081. }
  14082. };
  14083. const isPseudoStop = element => {
  14084. return closest(element, [
  14085. '.' + beforeObject,
  14086. '.' + afterObject
  14087. ].join(','), never);
  14088. };
  14089. const getDynamicSource = initialData => {
  14090. const cachedValue = Cell(initialData.getOr(''));
  14091. return {
  14092. getValue: _frameComponent => cachedValue.get(),
  14093. setValue: (frameComponent, html) => {
  14094. if (cachedValue.get() !== html) {
  14095. set$9(frameComponent.element, 'srcdoc', html);
  14096. }
  14097. cachedValue.set(html);
  14098. }
  14099. };
  14100. };
  14101. const renderIFrame = (spec, providersBackstage, initialData) => {
  14102. const isSandbox = spec.sandboxed;
  14103. const isTransparent = spec.transparent;
  14104. const baseClass = 'tox-dialog__iframe';
  14105. const attributes = {
  14106. ...spec.label.map(title => ({ title })).getOr({}),
  14107. ...initialData.map(html => ({ srcdoc: html })).getOr({}),
  14108. ...isSandbox ? { sandbox: 'allow-scripts allow-same-origin' } : {}
  14109. };
  14110. const sourcing = getDynamicSource(initialData);
  14111. const pLabel = spec.label.map(label => renderLabel$3(label, providersBackstage));
  14112. const factory = newSpec => craft({
  14113. uid: newSpec.uid,
  14114. dom: {
  14115. tag: 'iframe',
  14116. attributes,
  14117. classes: isTransparent ? [baseClass] : [
  14118. baseClass,
  14119. `${ baseClass }--opaque`
  14120. ]
  14121. },
  14122. behaviours: derive$1([
  14123. Tabstopping.config({}),
  14124. Focusing.config({}),
  14125. RepresentingConfigs.withComp(initialData, sourcing.getValue, sourcing.setValue)
  14126. ])
  14127. });
  14128. const pField = FormField.parts.field({ factory: { sketch: factory } });
  14129. return renderFormFieldWith(pLabel, pField, ['tox-form__group--stretched'], []);
  14130. };
  14131. const image = image => new Promise((resolve, reject) => {
  14132. const loaded = () => {
  14133. destroy();
  14134. resolve(image);
  14135. };
  14136. const listeners = [
  14137. bind(image, 'load', loaded),
  14138. bind(image, 'error', () => {
  14139. destroy();
  14140. reject('Unable to load data from image: ' + image.dom.src);
  14141. })
  14142. ];
  14143. const destroy = () => each$1(listeners, l => l.unbind());
  14144. if (image.dom.complete) {
  14145. loaded();
  14146. }
  14147. });
  14148. const calculateImagePosition = (panelWidth, panelHeight, imageWidth, imageHeight, zoom) => {
  14149. const width = imageWidth * zoom;
  14150. const height = imageHeight * zoom;
  14151. const left = Math.max(0, panelWidth / 2 - width / 2);
  14152. const top = Math.max(0, panelHeight / 2 - height / 2);
  14153. return {
  14154. left: left.toString() + 'px',
  14155. top: top.toString() + 'px',
  14156. width: width.toString() + 'px',
  14157. height: height.toString() + 'px'
  14158. };
  14159. };
  14160. const zoomToFit = (panel, width, height) => {
  14161. const panelW = get$c(panel);
  14162. const panelH = get$d(panel);
  14163. return Math.min(panelW / width, panelH / height, 1);
  14164. };
  14165. const renderImagePreview = (spec, initialData) => {
  14166. const cachedData = Cell(initialData.getOr({ url: '' }));
  14167. const memImage = record({
  14168. dom: {
  14169. tag: 'img',
  14170. classes: ['tox-imagepreview__image'],
  14171. attributes: initialData.map(data => ({ src: data.url })).getOr({})
  14172. }
  14173. });
  14174. const memContainer = record({
  14175. dom: {
  14176. tag: 'div',
  14177. classes: ['tox-imagepreview__container'],
  14178. attributes: { role: 'presentation' }
  14179. },
  14180. components: [memImage.asSpec()]
  14181. });
  14182. const setValue = (frameComponent, data) => {
  14183. const translatedData = { url: data.url };
  14184. data.zoom.each(z => translatedData.zoom = z);
  14185. data.cachedWidth.each(z => translatedData.cachedWidth = z);
  14186. data.cachedHeight.each(z => translatedData.cachedHeight = z);
  14187. cachedData.set(translatedData);
  14188. const applyFramePositioning = () => {
  14189. const {cachedWidth, cachedHeight, zoom} = translatedData;
  14190. if (!isUndefined(cachedWidth) && !isUndefined(cachedHeight)) {
  14191. if (isUndefined(zoom)) {
  14192. const z = zoomToFit(frameComponent.element, cachedWidth, cachedHeight);
  14193. translatedData.zoom = z;
  14194. }
  14195. const position = calculateImagePosition(get$c(frameComponent.element), get$d(frameComponent.element), cachedWidth, cachedHeight, translatedData.zoom);
  14196. memContainer.getOpt(frameComponent).each(container => {
  14197. setAll(container.element, position);
  14198. });
  14199. }
  14200. };
  14201. memImage.getOpt(frameComponent).each(imageComponent => {
  14202. const img = imageComponent.element;
  14203. if (data.url !== get$f(img, 'src')) {
  14204. set$9(img, 'src', data.url);
  14205. remove$2(frameComponent.element, 'tox-imagepreview__loaded');
  14206. }
  14207. applyFramePositioning();
  14208. image(img).then(img => {
  14209. if (frameComponent.getSystem().isConnected()) {
  14210. add$2(frameComponent.element, 'tox-imagepreview__loaded');
  14211. translatedData.cachedWidth = img.dom.naturalWidth;
  14212. translatedData.cachedHeight = img.dom.naturalHeight;
  14213. applyFramePositioning();
  14214. }
  14215. });
  14216. });
  14217. };
  14218. const styles = {};
  14219. spec.height.each(h => styles.height = h);
  14220. const fakeValidatedData = initialData.map(d => ({
  14221. url: d.url,
  14222. zoom: Optional.from(d.zoom),
  14223. cachedWidth: Optional.from(d.cachedWidth),
  14224. cachedHeight: Optional.from(d.cachedHeight)
  14225. }));
  14226. return {
  14227. dom: {
  14228. tag: 'div',
  14229. classes: ['tox-imagepreview'],
  14230. styles,
  14231. attributes: { role: 'presentation' }
  14232. },
  14233. components: [memContainer.asSpec()],
  14234. behaviours: derive$1([
  14235. ComposingConfigs.self(),
  14236. RepresentingConfigs.withComp(fakeValidatedData, () => cachedData.get(), setValue)
  14237. ])
  14238. };
  14239. };
  14240. const renderLabel$2 = (spec, backstageShared) => {
  14241. const label = {
  14242. dom: {
  14243. tag: 'label',
  14244. classes: ['tox-label']
  14245. },
  14246. components: [text$2(backstageShared.providers.translate(spec.label))]
  14247. };
  14248. const comps = map$2(spec.items, backstageShared.interpreter);
  14249. return {
  14250. dom: {
  14251. tag: 'div',
  14252. classes: ['tox-form__group']
  14253. },
  14254. components: [
  14255. label,
  14256. ...comps
  14257. ],
  14258. behaviours: derive$1([
  14259. ComposingConfigs.self(),
  14260. Replacing.config({}),
  14261. RepresentingConfigs.domHtml(Optional.none()),
  14262. Keying.config({ mode: 'acyclic' })
  14263. ])
  14264. };
  14265. };
  14266. const internalToolbarButtonExecute = generate$6('toolbar.button.execute');
  14267. const onToolbarButtonExecute = info => runOnExecute$1((comp, _simulatedEvent) => {
  14268. runWithApi(info, comp)(itemApi => {
  14269. emitWith(comp, internalToolbarButtonExecute, { buttonApi: itemApi });
  14270. info.onAction(itemApi);
  14271. });
  14272. });
  14273. const commonButtonDisplayEvent = generate$6('common-button-display-events');
  14274. const toolbarButtonEventOrder = {
  14275. [execute$5()]: [
  14276. 'disabling',
  14277. 'alloy.base.behaviour',
  14278. 'toggling',
  14279. 'toolbar-button-events'
  14280. ],
  14281. [attachedToDom()]: [
  14282. 'toolbar-button-events',
  14283. commonButtonDisplayEvent
  14284. ],
  14285. [mousedown()]: [
  14286. 'focusing',
  14287. 'alloy.base.behaviour',
  14288. commonButtonDisplayEvent
  14289. ]
  14290. };
  14291. const forceInitialSize = comp => set$8(comp.element, 'width', get$e(comp.element, 'width'));
  14292. const renderIcon$1 = (iconName, iconsProvider, behaviours) => render$3(iconName, {
  14293. tag: 'span',
  14294. classes: [
  14295. 'tox-icon',
  14296. 'tox-tbtn__icon-wrap'
  14297. ],
  14298. behaviours
  14299. }, iconsProvider);
  14300. const renderIconFromPack$1 = (iconName, iconsProvider) => renderIcon$1(iconName, iconsProvider, []);
  14301. const renderReplaceableIconFromPack = (iconName, iconsProvider) => renderIcon$1(iconName, iconsProvider, [Replacing.config({})]);
  14302. const renderLabel$1 = (text, prefix, providersBackstage) => ({
  14303. dom: {
  14304. tag: 'span',
  14305. classes: [`${ prefix }__select-label`]
  14306. },
  14307. components: [text$2(providersBackstage.translate(text))],
  14308. behaviours: derive$1([Replacing.config({})])
  14309. });
  14310. const updateMenuText = generate$6('update-menu-text');
  14311. const updateMenuIcon = generate$6('update-menu-icon');
  14312. const renderCommonDropdown = (spec, prefix, sharedBackstage) => {
  14313. const editorOffCell = Cell(noop);
  14314. const optMemDisplayText = spec.text.map(text => record(renderLabel$1(text, prefix, sharedBackstage.providers)));
  14315. const optMemDisplayIcon = spec.icon.map(iconName => record(renderReplaceableIconFromPack(iconName, sharedBackstage.providers.icons)));
  14316. const onLeftOrRightInMenu = (comp, se) => {
  14317. const dropdown = Representing.getValue(comp);
  14318. Focusing.focus(dropdown);
  14319. emitWith(dropdown, 'keydown', { raw: se.event.raw });
  14320. Dropdown.close(dropdown);
  14321. return Optional.some(true);
  14322. };
  14323. const role = spec.role.fold(() => ({}), role => ({ role }));
  14324. const tooltipAttributes = spec.tooltip.fold(() => ({}), tooltip => {
  14325. const translatedTooltip = sharedBackstage.providers.translate(tooltip);
  14326. return {
  14327. 'title': translatedTooltip,
  14328. 'aria-label': translatedTooltip
  14329. };
  14330. });
  14331. const iconSpec = render$3('chevron-down', {
  14332. tag: 'div',
  14333. classes: [`${ prefix }__select-chevron`]
  14334. }, sharedBackstage.providers.icons);
  14335. const fixWidthBehaviourName = generate$6('common-button-display-events');
  14336. const memDropdown = record(Dropdown.sketch({
  14337. ...spec.uid ? { uid: spec.uid } : {},
  14338. ...role,
  14339. dom: {
  14340. tag: 'button',
  14341. classes: [
  14342. prefix,
  14343. `${ prefix }--select`
  14344. ].concat(map$2(spec.classes, c => `${ prefix }--${ c }`)),
  14345. attributes: { ...tooltipAttributes }
  14346. },
  14347. components: componentRenderPipeline([
  14348. optMemDisplayIcon.map(mem => mem.asSpec()),
  14349. optMemDisplayText.map(mem => mem.asSpec()),
  14350. Optional.some(iconSpec)
  14351. ]),
  14352. matchWidth: true,
  14353. useMinWidth: true,
  14354. onOpen: (anchor, dropdownComp, tmenuComp) => {
  14355. if (spec.searchable) {
  14356. focusSearchField(tmenuComp);
  14357. }
  14358. },
  14359. dropdownBehaviours: derive$1([
  14360. ...spec.dropdownBehaviours,
  14361. DisablingConfigs.button(() => spec.disabled || sharedBackstage.providers.isDisabled()),
  14362. receivingConfig(),
  14363. Unselecting.config({}),
  14364. Replacing.config({}),
  14365. config('dropdown-events', [
  14366. onControlAttached(spec, editorOffCell),
  14367. onControlDetached(spec, editorOffCell)
  14368. ]),
  14369. config(fixWidthBehaviourName, [runOnAttached((comp, _se) => forceInitialSize(comp))]),
  14370. config('menubutton-update-display-text', [
  14371. run$1(updateMenuText, (comp, se) => {
  14372. optMemDisplayText.bind(mem => mem.getOpt(comp)).each(displayText => {
  14373. Replacing.set(displayText, [text$2(sharedBackstage.providers.translate(se.event.text))]);
  14374. });
  14375. }),
  14376. run$1(updateMenuIcon, (comp, se) => {
  14377. optMemDisplayIcon.bind(mem => mem.getOpt(comp)).each(displayIcon => {
  14378. Replacing.set(displayIcon, [renderReplaceableIconFromPack(se.event.icon, sharedBackstage.providers.icons)]);
  14379. });
  14380. })
  14381. ])
  14382. ]),
  14383. eventOrder: deepMerge(toolbarButtonEventOrder, {
  14384. mousedown: [
  14385. 'focusing',
  14386. 'alloy.base.behaviour',
  14387. 'item-type-events',
  14388. 'normal-dropdown-events'
  14389. ],
  14390. [attachedToDom()]: [
  14391. 'toolbar-button-events',
  14392. 'dropdown-events',
  14393. fixWidthBehaviourName
  14394. ]
  14395. }),
  14396. sandboxBehaviours: derive$1([
  14397. Keying.config({
  14398. mode: 'special',
  14399. onLeft: onLeftOrRightInMenu,
  14400. onRight: onLeftOrRightInMenu
  14401. }),
  14402. config('dropdown-sandbox-events', [
  14403. run$1(refetchTriggerEvent, (originalSandboxComp, se) => {
  14404. handleRefetchTrigger(originalSandboxComp);
  14405. se.stop();
  14406. }),
  14407. run$1(redirectMenuItemInteractionEvent, (sandboxComp, se) => {
  14408. handleRedirectToMenuItem(sandboxComp, se);
  14409. se.stop();
  14410. })
  14411. ])
  14412. ]),
  14413. lazySink: sharedBackstage.getSink,
  14414. toggleClass: `${ prefix }--active`,
  14415. parts: {
  14416. menu: {
  14417. ...part(false, spec.columns, spec.presets),
  14418. fakeFocus: spec.searchable,
  14419. onHighlightItem: updateAriaOnHighlight,
  14420. onCollapseMenu: (tmenuComp, itemCompCausingCollapse, nowActiveMenuComp) => {
  14421. Highlighting.getHighlighted(nowActiveMenuComp).each(itemComp => {
  14422. updateAriaOnHighlight(tmenuComp, nowActiveMenuComp, itemComp);
  14423. });
  14424. },
  14425. onDehighlightItem: updateAriaOnDehighlight
  14426. }
  14427. },
  14428. fetch: comp => Future.nu(curry(spec.fetch, comp))
  14429. }));
  14430. return memDropdown.asSpec();
  14431. };
  14432. const isMenuItemReference = item => isString(item);
  14433. const isSeparator$2 = item => item.type === 'separator';
  14434. const isExpandingMenuItem = item => has$2(item, 'getSubmenuItems');
  14435. const separator$2 = { type: 'separator' };
  14436. const unwrapReferences = (items, menuItems) => {
  14437. const realItems = foldl(items, (acc, item) => {
  14438. if (isMenuItemReference(item)) {
  14439. if (item === '') {
  14440. return acc;
  14441. } else if (item === '|') {
  14442. return acc.length > 0 && !isSeparator$2(acc[acc.length - 1]) ? acc.concat([separator$2]) : acc;
  14443. } else if (has$2(menuItems, item.toLowerCase())) {
  14444. return acc.concat([menuItems[item.toLowerCase()]]);
  14445. } else {
  14446. return acc;
  14447. }
  14448. } else {
  14449. return acc.concat([item]);
  14450. }
  14451. }, []);
  14452. if (realItems.length > 0 && isSeparator$2(realItems[realItems.length - 1])) {
  14453. realItems.pop();
  14454. }
  14455. return realItems;
  14456. };
  14457. const getFromExpandingItem = (item, menuItems) => {
  14458. const submenuItems = item.getSubmenuItems();
  14459. const rest = expand(submenuItems, menuItems);
  14460. const newMenus = deepMerge(rest.menus, { [item.value]: rest.items });
  14461. const newExpansions = deepMerge(rest.expansions, { [item.value]: item.value });
  14462. return {
  14463. item,
  14464. menus: newMenus,
  14465. expansions: newExpansions
  14466. };
  14467. };
  14468. const generateValueIfRequired = item => {
  14469. const itemValue = get$g(item, 'value').getOrThunk(() => generate$6('generated-menu-item'));
  14470. return deepMerge({ value: itemValue }, item);
  14471. };
  14472. const expand = (items, menuItems) => {
  14473. const realItems = unwrapReferences(isString(items) ? items.split(' ') : items, menuItems);
  14474. return foldr(realItems, (acc, item) => {
  14475. if (isExpandingMenuItem(item)) {
  14476. const itemWithValue = generateValueIfRequired(item);
  14477. const newData = getFromExpandingItem(itemWithValue, menuItems);
  14478. return {
  14479. menus: deepMerge(acc.menus, newData.menus),
  14480. items: [
  14481. newData.item,
  14482. ...acc.items
  14483. ],
  14484. expansions: deepMerge(acc.expansions, newData.expansions)
  14485. };
  14486. } else {
  14487. return {
  14488. ...acc,
  14489. items: [
  14490. item,
  14491. ...acc.items
  14492. ]
  14493. };
  14494. }
  14495. }, {
  14496. menus: {},
  14497. expansions: {},
  14498. items: []
  14499. });
  14500. };
  14501. const getSearchModeForField = settings => {
  14502. return settings.search.fold(() => ({ searchMode: 'no-search' }), searchSettings => ({
  14503. searchMode: 'search-with-field',
  14504. placeholder: searchSettings.placeholder
  14505. }));
  14506. };
  14507. const getSearchModeForResults = settings => {
  14508. return settings.search.fold(() => ({ searchMode: 'no-search' }), _ => ({ searchMode: 'search-with-results' }));
  14509. };
  14510. const build = (items, itemResponse, backstage, settings) => {
  14511. const primary = generate$6('primary-menu');
  14512. const data = expand(items, backstage.shared.providers.menuItems());
  14513. if (data.items.length === 0) {
  14514. return Optional.none();
  14515. }
  14516. const mainMenuSearchMode = getSearchModeForField(settings);
  14517. const mainMenu = createPartialMenu(primary, data.items, itemResponse, backstage, settings.isHorizontalMenu, mainMenuSearchMode);
  14518. const submenuSearchMode = getSearchModeForResults(settings);
  14519. const submenus = map$1(data.menus, (menuItems, menuName) => createPartialMenu(menuName, menuItems, itemResponse, backstage, false, submenuSearchMode));
  14520. const menus = deepMerge(submenus, wrap$1(primary, mainMenu));
  14521. return Optional.from(tieredMenu.tieredData(primary, menus, data.expansions));
  14522. };
  14523. const isSingleListItem = item => !has$2(item, 'items');
  14524. const dataAttribute = 'data-value';
  14525. const fetchItems = (dropdownComp, name, items, selectedValue) => map$2(items, item => {
  14526. if (!isSingleListItem(item)) {
  14527. return {
  14528. type: 'nestedmenuitem',
  14529. text: item.text,
  14530. getSubmenuItems: () => fetchItems(dropdownComp, name, item.items, selectedValue)
  14531. };
  14532. } else {
  14533. return {
  14534. type: 'togglemenuitem',
  14535. text: item.text,
  14536. value: item.value,
  14537. active: item.value === selectedValue,
  14538. onAction: () => {
  14539. Representing.setValue(dropdownComp, item.value);
  14540. emitWith(dropdownComp, formChangeEvent, { name });
  14541. Focusing.focus(dropdownComp);
  14542. }
  14543. };
  14544. }
  14545. });
  14546. const findItemByValue = (items, value) => findMap(items, item => {
  14547. if (!isSingleListItem(item)) {
  14548. return findItemByValue(item.items, value);
  14549. } else {
  14550. return someIf(item.value === value, item);
  14551. }
  14552. });
  14553. const renderListBox = (spec, backstage, initialData) => {
  14554. const providersBackstage = backstage.shared.providers;
  14555. const initialItem = initialData.bind(value => findItemByValue(spec.items, value)).orThunk(() => head(spec.items).filter(isSingleListItem));
  14556. const pLabel = spec.label.map(label => renderLabel$3(label, providersBackstage));
  14557. const pField = FormField.parts.field({
  14558. dom: {},
  14559. factory: {
  14560. sketch: sketchSpec => renderCommonDropdown({
  14561. uid: sketchSpec.uid,
  14562. text: initialItem.map(item => item.text),
  14563. icon: Optional.none(),
  14564. tooltip: spec.label,
  14565. role: Optional.none(),
  14566. fetch: (comp, callback) => {
  14567. const items = fetchItems(comp, spec.name, spec.items, Representing.getValue(comp));
  14568. callback(build(items, ItemResponse$1.CLOSE_ON_EXECUTE, backstage, {
  14569. isHorizontalMenu: false,
  14570. search: Optional.none()
  14571. }));
  14572. },
  14573. onSetup: constant$1(noop),
  14574. getApi: constant$1({}),
  14575. columns: 1,
  14576. presets: 'normal',
  14577. classes: [],
  14578. dropdownBehaviours: [
  14579. Tabstopping.config({}),
  14580. RepresentingConfigs.withComp(initialItem.map(item => item.value), comp => get$f(comp.element, dataAttribute), (comp, data) => {
  14581. findItemByValue(spec.items, data).each(item => {
  14582. set$9(comp.element, dataAttribute, item.value);
  14583. emitWith(comp, updateMenuText, { text: item.text });
  14584. });
  14585. })
  14586. ]
  14587. }, 'tox-listbox', backstage.shared)
  14588. }
  14589. });
  14590. const listBoxWrap = {
  14591. dom: {
  14592. tag: 'div',
  14593. classes: ['tox-listboxfield']
  14594. },
  14595. components: [pField]
  14596. };
  14597. return FormField.sketch({
  14598. dom: {
  14599. tag: 'div',
  14600. classes: ['tox-form__group']
  14601. },
  14602. components: flatten([
  14603. pLabel.toArray(),
  14604. [listBoxWrap]
  14605. ]),
  14606. fieldBehaviours: derive$1([Disabling.config({
  14607. disabled: constant$1(!spec.enabled),
  14608. onDisabled: comp => {
  14609. FormField.getField(comp).each(Disabling.disable);
  14610. },
  14611. onEnabled: comp => {
  14612. FormField.getField(comp).each(Disabling.enable);
  14613. }
  14614. })])
  14615. });
  14616. };
  14617. const renderPanel = (spec, backstage) => ({
  14618. dom: {
  14619. tag: 'div',
  14620. classes: spec.classes
  14621. },
  14622. components: map$2(spec.items, backstage.shared.interpreter)
  14623. });
  14624. const factory$h = (detail, _spec) => {
  14625. const options = map$2(detail.options, option => ({
  14626. dom: {
  14627. tag: 'option',
  14628. value: option.value,
  14629. innerHtml: option.text
  14630. }
  14631. }));
  14632. const initialValues = detail.data.map(v => wrap$1('initialValue', v)).getOr({});
  14633. return {
  14634. uid: detail.uid,
  14635. dom: {
  14636. tag: 'select',
  14637. classes: detail.selectClasses,
  14638. attributes: detail.selectAttributes
  14639. },
  14640. components: options,
  14641. behaviours: augment(detail.selectBehaviours, [
  14642. Focusing.config({}),
  14643. Representing.config({
  14644. store: {
  14645. mode: 'manual',
  14646. getValue: select => {
  14647. return get$6(select.element);
  14648. },
  14649. setValue: (select, newValue) => {
  14650. const firstOption = head(detail.options);
  14651. const found = find$5(detail.options, opt => opt.value === newValue);
  14652. if (found.isSome()) {
  14653. set$5(select.element, newValue);
  14654. } else if (select.element.dom.selectedIndex === -1 && newValue === '') {
  14655. firstOption.each(value => set$5(select.element, value.value));
  14656. }
  14657. },
  14658. ...initialValues
  14659. }
  14660. })
  14661. ])
  14662. };
  14663. };
  14664. const HtmlSelect = single({
  14665. name: 'HtmlSelect',
  14666. configFields: [
  14667. required$1('options'),
  14668. field('selectBehaviours', [
  14669. Focusing,
  14670. Representing
  14671. ]),
  14672. defaulted('selectClasses', []),
  14673. defaulted('selectAttributes', {}),
  14674. option$3('data')
  14675. ],
  14676. factory: factory$h
  14677. });
  14678. const renderSelectBox = (spec, providersBackstage, initialData) => {
  14679. const translatedOptions = map$2(spec.items, item => ({
  14680. text: providersBackstage.translate(item.text),
  14681. value: item.value
  14682. }));
  14683. const pLabel = spec.label.map(label => renderLabel$3(label, providersBackstage));
  14684. const pField = FormField.parts.field({
  14685. dom: {},
  14686. ...initialData.map(data => ({ data })).getOr({}),
  14687. selectAttributes: { size: spec.size },
  14688. options: translatedOptions,
  14689. factory: HtmlSelect,
  14690. selectBehaviours: derive$1([
  14691. Disabling.config({ disabled: () => !spec.enabled || providersBackstage.isDisabled() }),
  14692. Tabstopping.config({}),
  14693. config('selectbox-change', [run$1(change(), (component, _) => {
  14694. emitWith(component, formChangeEvent, { name: spec.name });
  14695. })])
  14696. ])
  14697. });
  14698. const chevron = spec.size > 1 ? Optional.none() : Optional.some(render$3('chevron-down', {
  14699. tag: 'div',
  14700. classes: ['tox-selectfield__icon-js']
  14701. }, providersBackstage.icons));
  14702. const selectWrap = {
  14703. dom: {
  14704. tag: 'div',
  14705. classes: ['tox-selectfield']
  14706. },
  14707. components: flatten([
  14708. [pField],
  14709. chevron.toArray()
  14710. ])
  14711. };
  14712. return FormField.sketch({
  14713. dom: {
  14714. tag: 'div',
  14715. classes: ['tox-form__group']
  14716. },
  14717. components: flatten([
  14718. pLabel.toArray(),
  14719. [selectWrap]
  14720. ]),
  14721. fieldBehaviours: derive$1([
  14722. Disabling.config({
  14723. disabled: () => !spec.enabled || providersBackstage.isDisabled(),
  14724. onDisabled: comp => {
  14725. FormField.getField(comp).each(Disabling.disable);
  14726. },
  14727. onEnabled: comp => {
  14728. FormField.getField(comp).each(Disabling.enable);
  14729. }
  14730. }),
  14731. receivingConfig()
  14732. ])
  14733. });
  14734. };
  14735. const schema$h = constant$1([
  14736. defaulted('field1Name', 'field1'),
  14737. defaulted('field2Name', 'field2'),
  14738. onStrictHandler('onLockedChange'),
  14739. markers$1(['lockClass']),
  14740. defaulted('locked', false),
  14741. SketchBehaviours.field('coupledFieldBehaviours', [
  14742. Composing,
  14743. Representing
  14744. ])
  14745. ]);
  14746. const getField = (comp, detail, partName) => getPart(comp, detail, partName).bind(Composing.getCurrent);
  14747. const coupledPart = (selfName, otherName) => required({
  14748. factory: FormField,
  14749. name: selfName,
  14750. overrides: detail => {
  14751. return {
  14752. fieldBehaviours: derive$1([config('coupled-input-behaviour', [run$1(input(), me => {
  14753. getField(me, detail, otherName).each(other => {
  14754. getPart(me, detail, 'lock').each(lock => {
  14755. if (Toggling.isOn(lock)) {
  14756. detail.onLockedChange(me, other, lock);
  14757. }
  14758. });
  14759. });
  14760. })])])
  14761. };
  14762. }
  14763. });
  14764. const parts$c = constant$1([
  14765. coupledPart('field1', 'field2'),
  14766. coupledPart('field2', 'field1'),
  14767. required({
  14768. factory: Button,
  14769. schema: [required$1('dom')],
  14770. name: 'lock',
  14771. overrides: detail => {
  14772. return {
  14773. buttonBehaviours: derive$1([Toggling.config({
  14774. selected: detail.locked,
  14775. toggleClass: detail.markers.lockClass,
  14776. aria: { mode: 'pressed' }
  14777. })])
  14778. };
  14779. }
  14780. })
  14781. ]);
  14782. const factory$g = (detail, components, _spec, _externals) => ({
  14783. uid: detail.uid,
  14784. dom: detail.dom,
  14785. components,
  14786. behaviours: SketchBehaviours.augment(detail.coupledFieldBehaviours, [
  14787. Composing.config({ find: Optional.some }),
  14788. Representing.config({
  14789. store: {
  14790. mode: 'manual',
  14791. getValue: comp => {
  14792. const parts = getPartsOrDie(comp, detail, [
  14793. 'field1',
  14794. 'field2'
  14795. ]);
  14796. return {
  14797. [detail.field1Name]: Representing.getValue(parts.field1()),
  14798. [detail.field2Name]: Representing.getValue(parts.field2())
  14799. };
  14800. },
  14801. setValue: (comp, value) => {
  14802. const parts = getPartsOrDie(comp, detail, [
  14803. 'field1',
  14804. 'field2'
  14805. ]);
  14806. if (hasNonNullableKey(value, detail.field1Name)) {
  14807. Representing.setValue(parts.field1(), value[detail.field1Name]);
  14808. }
  14809. if (hasNonNullableKey(value, detail.field2Name)) {
  14810. Representing.setValue(parts.field2(), value[detail.field2Name]);
  14811. }
  14812. }
  14813. }
  14814. })
  14815. ]),
  14816. apis: {
  14817. getField1: component => getPart(component, detail, 'field1'),
  14818. getField2: component => getPart(component, detail, 'field2'),
  14819. getLock: component => getPart(component, detail, 'lock')
  14820. }
  14821. });
  14822. const FormCoupledInputs = composite({
  14823. name: 'FormCoupledInputs',
  14824. configFields: schema$h(),
  14825. partFields: parts$c(),
  14826. factory: factory$g,
  14827. apis: {
  14828. getField1: (apis, component) => apis.getField1(component),
  14829. getField2: (apis, component) => apis.getField2(component),
  14830. getLock: (apis, component) => apis.getLock(component)
  14831. }
  14832. });
  14833. const formatSize = size => {
  14834. const unitDec = {
  14835. '': 0,
  14836. 'px': 0,
  14837. 'pt': 1,
  14838. 'mm': 1,
  14839. 'pc': 2,
  14840. 'ex': 2,
  14841. 'em': 2,
  14842. 'ch': 2,
  14843. 'rem': 2,
  14844. 'cm': 3,
  14845. 'in': 4,
  14846. '%': 4
  14847. };
  14848. const maxDecimal = unit => unit in unitDec ? unitDec[unit] : 1;
  14849. let numText = size.value.toFixed(maxDecimal(size.unit));
  14850. if (numText.indexOf('.') !== -1) {
  14851. numText = numText.replace(/\.?0*$/, '');
  14852. }
  14853. return numText + size.unit;
  14854. };
  14855. const parseSize = sizeText => {
  14856. const numPattern = /^\s*(\d+(?:\.\d+)?)\s*(|cm|mm|in|px|pt|pc|em|ex|ch|rem|vw|vh|vmin|vmax|%)\s*$/;
  14857. const match = numPattern.exec(sizeText);
  14858. if (match !== null) {
  14859. const value = parseFloat(match[1]);
  14860. const unit = match[2];
  14861. return Result.value({
  14862. value,
  14863. unit
  14864. });
  14865. } else {
  14866. return Result.error(sizeText);
  14867. }
  14868. };
  14869. const convertUnit = (size, unit) => {
  14870. const inInch = {
  14871. '': 96,
  14872. 'px': 96,
  14873. 'pt': 72,
  14874. 'cm': 2.54,
  14875. 'pc': 12,
  14876. 'mm': 25.4,
  14877. 'in': 1
  14878. };
  14879. const supported = u => has$2(inInch, u);
  14880. if (size.unit === unit) {
  14881. return Optional.some(size.value);
  14882. } else if (supported(size.unit) && supported(unit)) {
  14883. if (inInch[size.unit] === inInch[unit]) {
  14884. return Optional.some(size.value);
  14885. } else {
  14886. return Optional.some(size.value / inInch[size.unit] * inInch[unit]);
  14887. }
  14888. } else {
  14889. return Optional.none();
  14890. }
  14891. };
  14892. const noSizeConversion = _input => Optional.none();
  14893. const ratioSizeConversion = (scale, unit) => size => convertUnit(size, unit).map(value => ({
  14894. value: value * scale,
  14895. unit
  14896. }));
  14897. const makeRatioConverter = (currentFieldText, otherFieldText) => {
  14898. const cValue = parseSize(currentFieldText).toOptional();
  14899. const oValue = parseSize(otherFieldText).toOptional();
  14900. 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);
  14901. };
  14902. const renderSizeInput = (spec, providersBackstage) => {
  14903. let converter = noSizeConversion;
  14904. const ratioEvent = generate$6('ratio-event');
  14905. const makeIcon = iconName => render$3(iconName, {
  14906. tag: 'span',
  14907. classes: [
  14908. 'tox-icon',
  14909. 'tox-lock-icon__' + iconName
  14910. ]
  14911. }, providersBackstage.icons);
  14912. const pLock = FormCoupledInputs.parts.lock({
  14913. dom: {
  14914. tag: 'button',
  14915. classes: [
  14916. 'tox-lock',
  14917. 'tox-button',
  14918. 'tox-button--naked',
  14919. 'tox-button--icon'
  14920. ],
  14921. attributes: { title: providersBackstage.translate(spec.label.getOr('Constrain proportions')) }
  14922. },
  14923. components: [
  14924. makeIcon('lock'),
  14925. makeIcon('unlock')
  14926. ],
  14927. buttonBehaviours: derive$1([
  14928. Disabling.config({ disabled: () => !spec.enabled || providersBackstage.isDisabled() }),
  14929. receivingConfig(),
  14930. Tabstopping.config({})
  14931. ])
  14932. });
  14933. const formGroup = components => ({
  14934. dom: {
  14935. tag: 'div',
  14936. classes: ['tox-form__group']
  14937. },
  14938. components
  14939. });
  14940. const getFieldPart = isField1 => FormField.parts.field({
  14941. factory: Input,
  14942. inputClasses: ['tox-textfield'],
  14943. inputBehaviours: derive$1([
  14944. Disabling.config({ disabled: () => !spec.enabled || providersBackstage.isDisabled() }),
  14945. receivingConfig(),
  14946. Tabstopping.config({}),
  14947. config('size-input-events', [
  14948. run$1(focusin(), (component, _simulatedEvent) => {
  14949. emitWith(component, ratioEvent, { isField1 });
  14950. }),
  14951. run$1(change(), (component, _simulatedEvent) => {
  14952. emitWith(component, formChangeEvent, { name: spec.name });
  14953. })
  14954. ])
  14955. ]),
  14956. selectOnFocus: false
  14957. });
  14958. const getLabel = label => ({
  14959. dom: {
  14960. tag: 'label',
  14961. classes: ['tox-label']
  14962. },
  14963. components: [text$2(providersBackstage.translate(label))]
  14964. });
  14965. const widthField = FormCoupledInputs.parts.field1(formGroup([
  14966. FormField.parts.label(getLabel('Width')),
  14967. getFieldPart(true)
  14968. ]));
  14969. const heightField = FormCoupledInputs.parts.field2(formGroup([
  14970. FormField.parts.label(getLabel('Height')),
  14971. getFieldPart(false)
  14972. ]));
  14973. return FormCoupledInputs.sketch({
  14974. dom: {
  14975. tag: 'div',
  14976. classes: ['tox-form__group']
  14977. },
  14978. components: [{
  14979. dom: {
  14980. tag: 'div',
  14981. classes: ['tox-form__controls-h-stack']
  14982. },
  14983. components: [
  14984. widthField,
  14985. heightField,
  14986. formGroup([
  14987. getLabel(nbsp),
  14988. pLock
  14989. ])
  14990. ]
  14991. }],
  14992. field1Name: 'width',
  14993. field2Name: 'height',
  14994. locked: true,
  14995. markers: { lockClass: 'tox-locked' },
  14996. onLockedChange: (current, other, _lock) => {
  14997. parseSize(Representing.getValue(current)).each(size => {
  14998. converter(size).each(newSize => {
  14999. Representing.setValue(other, formatSize(newSize));
  15000. });
  15001. });
  15002. },
  15003. coupledFieldBehaviours: derive$1([
  15004. Disabling.config({
  15005. disabled: () => !spec.enabled || providersBackstage.isDisabled(),
  15006. onDisabled: comp => {
  15007. FormCoupledInputs.getField1(comp).bind(FormField.getField).each(Disabling.disable);
  15008. FormCoupledInputs.getField2(comp).bind(FormField.getField).each(Disabling.disable);
  15009. FormCoupledInputs.getLock(comp).each(Disabling.disable);
  15010. },
  15011. onEnabled: comp => {
  15012. FormCoupledInputs.getField1(comp).bind(FormField.getField).each(Disabling.enable);
  15013. FormCoupledInputs.getField2(comp).bind(FormField.getField).each(Disabling.enable);
  15014. FormCoupledInputs.getLock(comp).each(Disabling.enable);
  15015. }
  15016. }),
  15017. receivingConfig(),
  15018. config('size-input-events2', [run$1(ratioEvent, (component, simulatedEvent) => {
  15019. const isField1 = simulatedEvent.event.isField1;
  15020. const optCurrent = isField1 ? FormCoupledInputs.getField1(component) : FormCoupledInputs.getField2(component);
  15021. const optOther = isField1 ? FormCoupledInputs.getField2(component) : FormCoupledInputs.getField1(component);
  15022. const value1 = optCurrent.map(Representing.getValue).getOr('');
  15023. const value2 = optOther.map(Representing.getValue).getOr('');
  15024. converter = makeRatioConverter(value1, value2);
  15025. })])
  15026. ])
  15027. });
  15028. };
  15029. const renderSlider = (spec, providerBackstage, initialData) => {
  15030. const labelPart = Slider.parts.label({
  15031. dom: {
  15032. tag: 'label',
  15033. classes: ['tox-label']
  15034. },
  15035. components: [text$2(providerBackstage.translate(spec.label))]
  15036. });
  15037. const spectrum = Slider.parts.spectrum({
  15038. dom: {
  15039. tag: 'div',
  15040. classes: ['tox-slider__rail'],
  15041. attributes: { role: 'presentation' }
  15042. }
  15043. });
  15044. const thumb = Slider.parts.thumb({
  15045. dom: {
  15046. tag: 'div',
  15047. classes: ['tox-slider__handle'],
  15048. attributes: { role: 'presentation' }
  15049. }
  15050. });
  15051. return Slider.sketch({
  15052. dom: {
  15053. tag: 'div',
  15054. classes: ['tox-slider'],
  15055. attributes: { role: 'presentation' }
  15056. },
  15057. model: {
  15058. mode: 'x',
  15059. minX: spec.min,
  15060. maxX: spec.max,
  15061. getInitialValue: constant$1(initialData.getOrThunk(() => (Math.abs(spec.max) - Math.abs(spec.min)) / 2))
  15062. },
  15063. components: [
  15064. labelPart,
  15065. spectrum,
  15066. thumb
  15067. ],
  15068. sliderBehaviours: derive$1([
  15069. ComposingConfigs.self(),
  15070. Focusing.config({})
  15071. ]),
  15072. onChoose: (component, thumb, value) => {
  15073. emitWith(component, formChangeEvent, {
  15074. name: spec.name,
  15075. value
  15076. });
  15077. }
  15078. });
  15079. };
  15080. const renderTable = (spec, providersBackstage) => {
  15081. const renderTh = text => ({
  15082. dom: {
  15083. tag: 'th',
  15084. innerHtml: providersBackstage.translate(text)
  15085. }
  15086. });
  15087. const renderHeader = header => ({
  15088. dom: { tag: 'thead' },
  15089. components: [{
  15090. dom: { tag: 'tr' },
  15091. components: map$2(header, renderTh)
  15092. }]
  15093. });
  15094. const renderTd = text => ({
  15095. dom: {
  15096. tag: 'td',
  15097. innerHtml: providersBackstage.translate(text)
  15098. }
  15099. });
  15100. const renderTr = row => ({
  15101. dom: { tag: 'tr' },
  15102. components: map$2(row, renderTd)
  15103. });
  15104. const renderRows = rows => ({
  15105. dom: { tag: 'tbody' },
  15106. components: map$2(rows, renderTr)
  15107. });
  15108. return {
  15109. dom: {
  15110. tag: 'table',
  15111. classes: ['tox-dialog__table']
  15112. },
  15113. components: [
  15114. renderHeader(spec.header),
  15115. renderRows(spec.cells)
  15116. ],
  15117. behaviours: derive$1([
  15118. Tabstopping.config({}),
  15119. Focusing.config({})
  15120. ])
  15121. };
  15122. };
  15123. const renderTextField = (spec, providersBackstage) => {
  15124. const pLabel = spec.label.map(label => renderLabel$3(label, providersBackstage));
  15125. const baseInputBehaviours = [
  15126. Disabling.config({ disabled: () => spec.disabled || providersBackstage.isDisabled() }),
  15127. receivingConfig(),
  15128. Keying.config({
  15129. mode: 'execution',
  15130. useEnter: spec.multiline !== true,
  15131. useControlEnter: spec.multiline === true,
  15132. execute: comp => {
  15133. emit(comp, formSubmitEvent);
  15134. return Optional.some(true);
  15135. }
  15136. }),
  15137. config('textfield-change', [
  15138. run$1(input(), (component, _) => {
  15139. emitWith(component, formChangeEvent, { name: spec.name });
  15140. }),
  15141. run$1(postPaste(), (component, _) => {
  15142. emitWith(component, formChangeEvent, { name: spec.name });
  15143. })
  15144. ]),
  15145. Tabstopping.config({})
  15146. ];
  15147. const validatingBehaviours = spec.validation.map(vl => Invalidating.config({
  15148. getRoot: input => {
  15149. return parentElement(input.element);
  15150. },
  15151. invalidClass: 'tox-invalid',
  15152. validator: {
  15153. validate: input => {
  15154. const v = Representing.getValue(input);
  15155. const result = vl.validator(v);
  15156. return Future.pure(result === true ? Result.value(v) : Result.error(result));
  15157. },
  15158. validateOnLoad: vl.validateOnLoad
  15159. }
  15160. })).toArray();
  15161. const placeholder = spec.placeholder.fold(constant$1({}), p => ({ placeholder: providersBackstage.translate(p) }));
  15162. const inputMode = spec.inputMode.fold(constant$1({}), mode => ({ inputmode: mode }));
  15163. const inputAttributes = {
  15164. ...placeholder,
  15165. ...inputMode
  15166. };
  15167. const pField = FormField.parts.field({
  15168. tag: spec.multiline === true ? 'textarea' : 'input',
  15169. ...spec.data.map(data => ({ data })).getOr({}),
  15170. inputAttributes,
  15171. inputClasses: [spec.classname],
  15172. inputBehaviours: derive$1(flatten([
  15173. baseInputBehaviours,
  15174. validatingBehaviours
  15175. ])),
  15176. selectOnFocus: false,
  15177. factory: Input
  15178. });
  15179. const pTextField = spec.multiline ? {
  15180. dom: {
  15181. tag: 'div',
  15182. classes: ['tox-textarea-wrap']
  15183. },
  15184. components: [pField]
  15185. } : pField;
  15186. const extraClasses = spec.flex ? ['tox-form__group--stretched'] : [];
  15187. const extraClasses2 = extraClasses.concat(spec.maximized ? ['tox-form-group--maximize'] : []);
  15188. const extraBehaviours = [
  15189. Disabling.config({
  15190. disabled: () => spec.disabled || providersBackstage.isDisabled(),
  15191. onDisabled: comp => {
  15192. FormField.getField(comp).each(Disabling.disable);
  15193. },
  15194. onEnabled: comp => {
  15195. FormField.getField(comp).each(Disabling.enable);
  15196. }
  15197. }),
  15198. receivingConfig()
  15199. ];
  15200. return renderFormFieldWith(pLabel, pTextField, extraClasses2, extraBehaviours);
  15201. };
  15202. const renderInput = (spec, providersBackstage, initialData) => renderTextField({
  15203. name: spec.name,
  15204. multiline: false,
  15205. label: spec.label,
  15206. inputMode: spec.inputMode,
  15207. placeholder: spec.placeholder,
  15208. flex: false,
  15209. disabled: !spec.enabled,
  15210. classname: 'tox-textfield',
  15211. validation: Optional.none(),
  15212. maximized: spec.maximized,
  15213. data: initialData
  15214. }, providersBackstage);
  15215. const renderTextarea = (spec, providersBackstage, initialData) => renderTextField({
  15216. name: spec.name,
  15217. multiline: true,
  15218. label: spec.label,
  15219. inputMode: Optional.none(),
  15220. placeholder: spec.placeholder,
  15221. flex: true,
  15222. disabled: !spec.enabled,
  15223. classname: 'tox-textarea',
  15224. validation: Optional.none(),
  15225. maximized: spec.maximized,
  15226. data: initialData
  15227. }, providersBackstage);
  15228. const getAnimationRoot = (component, slideConfig) => slideConfig.getAnimationRoot.fold(() => component.element, get => get(component));
  15229. const getDimensionProperty = slideConfig => slideConfig.dimension.property;
  15230. const getDimension = (slideConfig, elem) => slideConfig.dimension.getDimension(elem);
  15231. const disableTransitions = (component, slideConfig) => {
  15232. const root = getAnimationRoot(component, slideConfig);
  15233. remove$1(root, [
  15234. slideConfig.shrinkingClass,
  15235. slideConfig.growingClass
  15236. ]);
  15237. };
  15238. const setShrunk = (component, slideConfig) => {
  15239. remove$2(component.element, slideConfig.openClass);
  15240. add$2(component.element, slideConfig.closedClass);
  15241. set$8(component.element, getDimensionProperty(slideConfig), '0px');
  15242. reflow(component.element);
  15243. };
  15244. const setGrown = (component, slideConfig) => {
  15245. remove$2(component.element, slideConfig.closedClass);
  15246. add$2(component.element, slideConfig.openClass);
  15247. remove$6(component.element, getDimensionProperty(slideConfig));
  15248. };
  15249. const doImmediateShrink = (component, slideConfig, slideState, _calculatedSize) => {
  15250. slideState.setCollapsed();
  15251. set$8(component.element, getDimensionProperty(slideConfig), getDimension(slideConfig, component.element));
  15252. disableTransitions(component, slideConfig);
  15253. setShrunk(component, slideConfig);
  15254. slideConfig.onStartShrink(component);
  15255. slideConfig.onShrunk(component);
  15256. };
  15257. const doStartShrink = (component, slideConfig, slideState, calculatedSize) => {
  15258. const size = calculatedSize.getOrThunk(() => getDimension(slideConfig, component.element));
  15259. slideState.setCollapsed();
  15260. set$8(component.element, getDimensionProperty(slideConfig), size);
  15261. reflow(component.element);
  15262. const root = getAnimationRoot(component, slideConfig);
  15263. remove$2(root, slideConfig.growingClass);
  15264. add$2(root, slideConfig.shrinkingClass);
  15265. setShrunk(component, slideConfig);
  15266. slideConfig.onStartShrink(component);
  15267. };
  15268. const doStartSmartShrink = (component, slideConfig, slideState) => {
  15269. const size = getDimension(slideConfig, component.element);
  15270. const shrinker = size === '0px' ? doImmediateShrink : doStartShrink;
  15271. shrinker(component, slideConfig, slideState, Optional.some(size));
  15272. };
  15273. const doStartGrow = (component, slideConfig, slideState) => {
  15274. const root = getAnimationRoot(component, slideConfig);
  15275. const wasShrinking = has(root, slideConfig.shrinkingClass);
  15276. const beforeSize = getDimension(slideConfig, component.element);
  15277. setGrown(component, slideConfig);
  15278. const fullSize = getDimension(slideConfig, component.element);
  15279. const startPartialGrow = () => {
  15280. set$8(component.element, getDimensionProperty(slideConfig), beforeSize);
  15281. reflow(component.element);
  15282. };
  15283. const startCompleteGrow = () => {
  15284. setShrunk(component, slideConfig);
  15285. };
  15286. const setStartSize = wasShrinking ? startPartialGrow : startCompleteGrow;
  15287. setStartSize();
  15288. remove$2(root, slideConfig.shrinkingClass);
  15289. add$2(root, slideConfig.growingClass);
  15290. setGrown(component, slideConfig);
  15291. set$8(component.element, getDimensionProperty(slideConfig), fullSize);
  15292. slideState.setExpanded();
  15293. slideConfig.onStartGrow(component);
  15294. };
  15295. const refresh$4 = (component, slideConfig, slideState) => {
  15296. if (slideState.isExpanded()) {
  15297. remove$6(component.element, getDimensionProperty(slideConfig));
  15298. const fullSize = getDimension(slideConfig, component.element);
  15299. set$8(component.element, getDimensionProperty(slideConfig), fullSize);
  15300. }
  15301. };
  15302. const grow = (component, slideConfig, slideState) => {
  15303. if (!slideState.isExpanded()) {
  15304. doStartGrow(component, slideConfig, slideState);
  15305. }
  15306. };
  15307. const shrink = (component, slideConfig, slideState) => {
  15308. if (slideState.isExpanded()) {
  15309. doStartSmartShrink(component, slideConfig, slideState);
  15310. }
  15311. };
  15312. const immediateShrink = (component, slideConfig, slideState) => {
  15313. if (slideState.isExpanded()) {
  15314. doImmediateShrink(component, slideConfig, slideState);
  15315. }
  15316. };
  15317. const hasGrown = (component, slideConfig, slideState) => slideState.isExpanded();
  15318. const hasShrunk = (component, slideConfig, slideState) => slideState.isCollapsed();
  15319. const isGrowing = (component, slideConfig, _slideState) => {
  15320. const root = getAnimationRoot(component, slideConfig);
  15321. return has(root, slideConfig.growingClass) === true;
  15322. };
  15323. const isShrinking = (component, slideConfig, _slideState) => {
  15324. const root = getAnimationRoot(component, slideConfig);
  15325. return has(root, slideConfig.shrinkingClass) === true;
  15326. };
  15327. const isTransitioning = (component, slideConfig, slideState) => isGrowing(component, slideConfig) || isShrinking(component, slideConfig);
  15328. const toggleGrow = (component, slideConfig, slideState) => {
  15329. const f = slideState.isExpanded() ? doStartSmartShrink : doStartGrow;
  15330. f(component, slideConfig, slideState);
  15331. };
  15332. const immediateGrow = (component, slideConfig, slideState) => {
  15333. if (!slideState.isExpanded()) {
  15334. setGrown(component, slideConfig);
  15335. set$8(component.element, getDimensionProperty(slideConfig), getDimension(slideConfig, component.element));
  15336. disableTransitions(component, slideConfig);
  15337. slideState.setExpanded();
  15338. slideConfig.onStartGrow(component);
  15339. slideConfig.onGrown(component);
  15340. }
  15341. };
  15342. var SlidingApis = /*#__PURE__*/Object.freeze({
  15343. __proto__: null,
  15344. refresh: refresh$4,
  15345. grow: grow,
  15346. shrink: shrink,
  15347. immediateShrink: immediateShrink,
  15348. hasGrown: hasGrown,
  15349. hasShrunk: hasShrunk,
  15350. isGrowing: isGrowing,
  15351. isShrinking: isShrinking,
  15352. isTransitioning: isTransitioning,
  15353. toggleGrow: toggleGrow,
  15354. disableTransitions: disableTransitions,
  15355. immediateGrow: immediateGrow
  15356. });
  15357. const exhibit = (base, slideConfig, _slideState) => {
  15358. const expanded = slideConfig.expanded;
  15359. return expanded ? nu$7({
  15360. classes: [slideConfig.openClass],
  15361. styles: {}
  15362. }) : nu$7({
  15363. classes: [slideConfig.closedClass],
  15364. styles: wrap$1(slideConfig.dimension.property, '0px')
  15365. });
  15366. };
  15367. const events$6 = (slideConfig, slideState) => derive$2([runOnSource(transitionend(), (component, simulatedEvent) => {
  15368. const raw = simulatedEvent.event.raw;
  15369. if (raw.propertyName === slideConfig.dimension.property) {
  15370. disableTransitions(component, slideConfig);
  15371. if (slideState.isExpanded()) {
  15372. remove$6(component.element, slideConfig.dimension.property);
  15373. }
  15374. const notify = slideState.isExpanded() ? slideConfig.onGrown : slideConfig.onShrunk;
  15375. notify(component);
  15376. }
  15377. })]);
  15378. var ActiveSliding = /*#__PURE__*/Object.freeze({
  15379. __proto__: null,
  15380. exhibit: exhibit,
  15381. events: events$6
  15382. });
  15383. var SlidingSchema = [
  15384. required$1('closedClass'),
  15385. required$1('openClass'),
  15386. required$1('shrinkingClass'),
  15387. required$1('growingClass'),
  15388. option$3('getAnimationRoot'),
  15389. onHandler('onShrunk'),
  15390. onHandler('onStartShrink'),
  15391. onHandler('onGrown'),
  15392. onHandler('onStartGrow'),
  15393. defaulted('expanded', false),
  15394. requiredOf('dimension', choose$1('property', {
  15395. width: [
  15396. output$1('property', 'width'),
  15397. output$1('getDimension', elem => get$c(elem) + 'px')
  15398. ],
  15399. height: [
  15400. output$1('property', 'height'),
  15401. output$1('getDimension', elem => get$d(elem) + 'px')
  15402. ]
  15403. }))
  15404. ];
  15405. const init$9 = spec => {
  15406. const state = Cell(spec.expanded);
  15407. const readState = () => 'expanded: ' + state.get();
  15408. return nu$8({
  15409. isExpanded: () => state.get() === true,
  15410. isCollapsed: () => state.get() === false,
  15411. setCollapsed: curry(state.set, false),
  15412. setExpanded: curry(state.set, true),
  15413. readState
  15414. });
  15415. };
  15416. var SlidingState = /*#__PURE__*/Object.freeze({
  15417. __proto__: null,
  15418. init: init$9
  15419. });
  15420. const Sliding = create$4({
  15421. fields: SlidingSchema,
  15422. name: 'sliding',
  15423. active: ActiveSliding,
  15424. apis: SlidingApis,
  15425. state: SlidingState
  15426. });
  15427. const getMenuButtonApi = component => ({
  15428. isEnabled: () => !Disabling.isDisabled(component),
  15429. setEnabled: state => Disabling.set(component, !state),
  15430. setActive: state => {
  15431. const elm = component.element;
  15432. if (state) {
  15433. add$2(elm, 'tox-tbtn--enabled');
  15434. set$9(elm, 'aria-pressed', true);
  15435. } else {
  15436. remove$2(elm, 'tox-tbtn--enabled');
  15437. remove$7(elm, 'aria-pressed');
  15438. }
  15439. },
  15440. isActive: () => has(component.element, 'tox-tbtn--enabled'),
  15441. setText: text => {
  15442. emitWith(component, updateMenuText, { text });
  15443. },
  15444. setIcon: icon => emitWith(component, updateMenuIcon, { icon })
  15445. });
  15446. const renderMenuButton = (spec, prefix, backstage, role, tabstopping = true) => {
  15447. return renderCommonDropdown({
  15448. text: spec.text,
  15449. icon: spec.icon,
  15450. tooltip: spec.tooltip,
  15451. searchable: spec.search.isSome(),
  15452. role,
  15453. fetch: (dropdownComp, callback) => {
  15454. const fetchContext = { pattern: spec.search.isSome() ? getSearchPattern(dropdownComp) : '' };
  15455. spec.fetch(items => {
  15456. callback(build(items, ItemResponse$1.CLOSE_ON_EXECUTE, backstage, {
  15457. isHorizontalMenu: false,
  15458. search: spec.search
  15459. }));
  15460. }, fetchContext, getMenuButtonApi(dropdownComp));
  15461. },
  15462. onSetup: spec.onSetup,
  15463. getApi: getMenuButtonApi,
  15464. columns: 1,
  15465. presets: 'normal',
  15466. classes: [],
  15467. dropdownBehaviours: [...tabstopping ? [Tabstopping.config({})] : []]
  15468. }, prefix, backstage.shared);
  15469. };
  15470. const getFetch = (items, getButton, backstage) => {
  15471. const getMenuItemAction = item => api => {
  15472. const newValue = !api.isActive();
  15473. api.setActive(newValue);
  15474. item.storage.set(newValue);
  15475. backstage.shared.getSink().each(sink => {
  15476. getButton().getOpt(sink).each(orig => {
  15477. focus$3(orig.element);
  15478. emitWith(orig, formActionEvent, {
  15479. name: item.name,
  15480. value: item.storage.get()
  15481. });
  15482. });
  15483. });
  15484. };
  15485. const getMenuItemSetup = item => api => {
  15486. api.setActive(item.storage.get());
  15487. };
  15488. return success => {
  15489. success(map$2(items, item => {
  15490. const text = item.text.fold(() => ({}), text => ({ text }));
  15491. return {
  15492. type: item.type,
  15493. active: false,
  15494. ...text,
  15495. onAction: getMenuItemAction(item),
  15496. onSetup: getMenuItemSetup(item)
  15497. };
  15498. }));
  15499. };
  15500. };
  15501. const renderLabel = text => ({
  15502. dom: {
  15503. tag: 'span',
  15504. classes: ['tox-tree__label'],
  15505. attributes: {
  15506. 'title': text,
  15507. 'aria-label': text
  15508. }
  15509. },
  15510. components: [text$2(text)]
  15511. });
  15512. const leafLabelEventsId = generate$6('leaf-label-event-id');
  15513. const renderLeafLabel = ({leaf, onLeafAction, visible, treeId, backstage}) => {
  15514. const internalMenuButton = leaf.menu.map(btn => renderMenuButton(btn, 'tox-mbtn', backstage, Optional.none(), visible));
  15515. const components = [renderLabel(leaf.title)];
  15516. internalMenuButton.each(btn => components.push(btn));
  15517. return Button.sketch({
  15518. dom: {
  15519. tag: 'div',
  15520. classes: [
  15521. 'tox-tree--leaf__label',
  15522. 'tox-trbtn'
  15523. ].concat(visible ? ['tox-tree--leaf__label--visible'] : [])
  15524. },
  15525. components,
  15526. role: 'treeitem',
  15527. action: button => {
  15528. onLeafAction(leaf.id);
  15529. button.getSystem().broadcastOn([`update-active-item-${ treeId }`], { value: leaf.id });
  15530. },
  15531. eventOrder: {
  15532. [keydown()]: [
  15533. leafLabelEventsId,
  15534. 'keying'
  15535. ]
  15536. },
  15537. buttonBehaviours: derive$1([
  15538. ...visible ? [Tabstopping.config({})] : [],
  15539. Toggling.config({
  15540. toggleClass: 'tox-trbtn--enabled',
  15541. toggleOnExecute: false,
  15542. aria: { mode: 'selected' }
  15543. }),
  15544. Receiving.config({
  15545. channels: {
  15546. [`update-active-item-${ treeId }`]: {
  15547. onReceive: (comp, message) => {
  15548. (message.value === leaf.id ? Toggling.on : Toggling.off)(comp);
  15549. }
  15550. }
  15551. }
  15552. }),
  15553. config(leafLabelEventsId, [run$1(keydown(), (comp, se) => {
  15554. const isLeftArrowKey = se.event.raw.code === 'ArrowLeft';
  15555. const isRightArrowKey = se.event.raw.code === 'ArrowRight';
  15556. if (isLeftArrowKey) {
  15557. ancestor(comp.element, '.tox-tree--directory').each(dirElement => {
  15558. comp.getSystem().getByDom(dirElement).each(dirComp => {
  15559. child(dirElement, '.tox-tree--directory__label').each(dirLabelElement => {
  15560. dirComp.getSystem().getByDom(dirLabelElement).each(Focusing.focus);
  15561. });
  15562. });
  15563. });
  15564. se.stop();
  15565. } else if (isRightArrowKey) {
  15566. se.stop();
  15567. }
  15568. })])
  15569. ])
  15570. });
  15571. };
  15572. const renderIcon = (iconName, iconsProvider, behaviours) => render$3(iconName, {
  15573. tag: 'span',
  15574. classes: [
  15575. 'tox-tree__icon-wrap',
  15576. 'tox-icon'
  15577. ],
  15578. behaviours
  15579. }, iconsProvider);
  15580. const renderIconFromPack = (iconName, iconsProvider) => renderIcon(iconName, iconsProvider, []);
  15581. const directoryLabelEventsId = generate$6('directory-label-event-id');
  15582. const renderDirectoryLabel = ({directory, visible, noChildren, backstage}) => {
  15583. const internalMenuButton = directory.menu.map(btn => renderMenuButton(btn, 'tox-mbtn', backstage, Optional.none()));
  15584. const components = [
  15585. {
  15586. dom: {
  15587. tag: 'div',
  15588. classes: ['tox-chevron']
  15589. },
  15590. components: [renderIconFromPack('chevron-right', backstage.shared.providers.icons)]
  15591. },
  15592. renderLabel(directory.title)
  15593. ];
  15594. internalMenuButton.each(btn => {
  15595. components.push(btn);
  15596. });
  15597. const expandChildren = button => {
  15598. ancestor(button.element, '.tox-tree--directory').each(directoryEle => {
  15599. button.getSystem().getByDom(directoryEle).each(directoryComp => Toggling.toggle(directoryComp));
  15600. });
  15601. };
  15602. return Button.sketch({
  15603. dom: {
  15604. tag: 'div',
  15605. classes: [
  15606. 'tox-tree--directory__label',
  15607. 'tox-trbtn'
  15608. ].concat(visible ? ['tox-tree--directory__label--visible'] : [])
  15609. },
  15610. components,
  15611. action: expandChildren,
  15612. eventOrder: {
  15613. [keydown()]: [
  15614. directoryLabelEventsId,
  15615. 'keying'
  15616. ]
  15617. },
  15618. buttonBehaviours: derive$1([
  15619. ...visible ? [Tabstopping.config({})] : [],
  15620. config(directoryLabelEventsId, [run$1(keydown(), (comp, se) => {
  15621. const isRightArrowKey = se.event.raw.code === 'ArrowRight';
  15622. const isLeftArrowKey = se.event.raw.code === 'ArrowLeft';
  15623. if (isRightArrowKey && noChildren) {
  15624. se.stop();
  15625. }
  15626. if (isRightArrowKey || isLeftArrowKey) {
  15627. ancestor(comp.element, '.tox-tree--directory').each(directoryEle => {
  15628. comp.getSystem().getByDom(directoryEle).each(directoryComp => {
  15629. if (!Toggling.isOn(directoryComp) && isRightArrowKey || Toggling.isOn(directoryComp) && isLeftArrowKey) {
  15630. expandChildren(comp);
  15631. se.stop();
  15632. } else if (isLeftArrowKey && !Toggling.isOn(directoryComp)) {
  15633. ancestor(directoryComp.element, '.tox-tree--directory').each(parentDirElement => {
  15634. child(parentDirElement, '.tox-tree--directory__label').each(parentDirLabelElement => {
  15635. directoryComp.getSystem().getByDom(parentDirLabelElement).each(Focusing.focus);
  15636. });
  15637. });
  15638. se.stop();
  15639. }
  15640. });
  15641. });
  15642. }
  15643. })])
  15644. ])
  15645. });
  15646. };
  15647. const renderDirectoryChildren = ({children, onLeafAction, visible, treeId, backstage}) => {
  15648. return {
  15649. dom: {
  15650. tag: 'div',
  15651. classes: ['tox-tree--directory__children']
  15652. },
  15653. components: children.map(item => {
  15654. return item.type === 'leaf' ? renderLeafLabel({
  15655. leaf: item,
  15656. onLeafAction,
  15657. visible,
  15658. treeId,
  15659. backstage
  15660. }) : renderDirectory({
  15661. directory: item,
  15662. onLeafAction,
  15663. labelTabstopping: visible,
  15664. treeId,
  15665. backstage
  15666. });
  15667. }),
  15668. behaviours: derive$1([
  15669. Sliding.config({
  15670. dimension: { property: 'height' },
  15671. closedClass: 'tox-tree--directory__children--closed',
  15672. openClass: 'tox-tree--directory__children--open',
  15673. growingClass: 'tox-tree--directory__children--growing',
  15674. shrinkingClass: 'tox-tree--directory__children--shrinking'
  15675. }),
  15676. Replacing.config({})
  15677. ])
  15678. };
  15679. };
  15680. const renderDirectory = ({directory, onLeafAction, labelTabstopping, treeId, backstage}) => {
  15681. const {children} = directory;
  15682. const computedChildrenComponents = visible => children.map(item => {
  15683. return item.type === 'leaf' ? renderLeafLabel({
  15684. leaf: item,
  15685. onLeafAction,
  15686. visible,
  15687. treeId,
  15688. backstage
  15689. }) : renderDirectory({
  15690. directory: item,
  15691. onLeafAction,
  15692. labelTabstopping: visible,
  15693. treeId,
  15694. backstage
  15695. });
  15696. });
  15697. return {
  15698. dom: {
  15699. tag: 'div',
  15700. classes: ['tox-tree--directory'],
  15701. attributes: { role: 'treeitem' }
  15702. },
  15703. components: [
  15704. renderDirectoryLabel({
  15705. directory,
  15706. visible: labelTabstopping,
  15707. noChildren: directory.children.length === 0,
  15708. backstage
  15709. }),
  15710. renderDirectoryChildren({
  15711. children,
  15712. onLeafAction,
  15713. visible: false,
  15714. treeId,
  15715. backstage
  15716. })
  15717. ],
  15718. behaviours: derive$1([Toggling.config({
  15719. ...directory.children.length > 0 ? { aria: { mode: 'expanded' } } : {},
  15720. toggleClass: 'tox-tree--directory--expanded',
  15721. onToggled: (comp, childrenVisible) => {
  15722. const childrenComp = comp.components()[1];
  15723. const newChildren = computedChildrenComponents(childrenVisible);
  15724. if (childrenVisible) {
  15725. Sliding.grow(childrenComp);
  15726. } else {
  15727. Sliding.shrink(childrenComp);
  15728. }
  15729. Replacing.set(childrenComp, newChildren);
  15730. }
  15731. })])
  15732. };
  15733. };
  15734. const renderTree = (spec, backstage) => {
  15735. const onLeafAction = spec.onLeafAction.getOr(noop);
  15736. const treeId = generate$6('tree-id');
  15737. const children = spec.items.map(item => {
  15738. return item.type === 'leaf' ? renderLeafLabel({
  15739. leaf: item,
  15740. onLeafAction,
  15741. visible: true,
  15742. treeId,
  15743. backstage
  15744. }) : renderDirectory({
  15745. directory: item,
  15746. onLeafAction,
  15747. labelTabstopping: true,
  15748. treeId,
  15749. backstage
  15750. });
  15751. });
  15752. return {
  15753. dom: {
  15754. tag: 'div',
  15755. classes: ['tox-tree'],
  15756. attributes: { role: 'tree' }
  15757. },
  15758. components: children,
  15759. behaviours: derive$1([Keying.config({
  15760. mode: 'flow',
  15761. selector: '.tox-tree--leaf__label--visible, .tox-tree--directory__label--visible',
  15762. cycles: false
  15763. })])
  15764. };
  15765. };
  15766. const events$5 = (streamConfig, streamState) => {
  15767. const streams = streamConfig.stream.streams;
  15768. const processor = streams.setup(streamConfig, streamState);
  15769. return derive$2([
  15770. run$1(streamConfig.event, processor),
  15771. runOnDetached(() => streamState.cancel())
  15772. ].concat(streamConfig.cancelEvent.map(e => [run$1(e, () => streamState.cancel())]).getOr([])));
  15773. };
  15774. var ActiveStreaming = /*#__PURE__*/Object.freeze({
  15775. __proto__: null,
  15776. events: events$5
  15777. });
  15778. const first = (fn, rate) => {
  15779. let timer = null;
  15780. const cancel = () => {
  15781. if (!isNull(timer)) {
  15782. clearTimeout(timer);
  15783. timer = null;
  15784. }
  15785. };
  15786. const throttle = (...args) => {
  15787. if (isNull(timer)) {
  15788. timer = setTimeout(() => {
  15789. timer = null;
  15790. fn.apply(null, args);
  15791. }, rate);
  15792. }
  15793. };
  15794. return {
  15795. cancel,
  15796. throttle
  15797. };
  15798. };
  15799. const last = (fn, rate) => {
  15800. let timer = null;
  15801. const cancel = () => {
  15802. if (!isNull(timer)) {
  15803. clearTimeout(timer);
  15804. timer = null;
  15805. }
  15806. };
  15807. const throttle = (...args) => {
  15808. cancel();
  15809. timer = setTimeout(() => {
  15810. timer = null;
  15811. fn.apply(null, args);
  15812. }, rate);
  15813. };
  15814. return {
  15815. cancel,
  15816. throttle
  15817. };
  15818. };
  15819. const throttle = _config => {
  15820. const state = Cell(null);
  15821. const readState = () => ({ timer: state.get() !== null ? 'set' : 'unset' });
  15822. const setTimer = t => {
  15823. state.set(t);
  15824. };
  15825. const cancel = () => {
  15826. const t = state.get();
  15827. if (t !== null) {
  15828. t.cancel();
  15829. }
  15830. };
  15831. return nu$8({
  15832. readState,
  15833. setTimer,
  15834. cancel
  15835. });
  15836. };
  15837. const init$8 = spec => spec.stream.streams.state(spec);
  15838. var StreamingState = /*#__PURE__*/Object.freeze({
  15839. __proto__: null,
  15840. throttle: throttle,
  15841. init: init$8
  15842. });
  15843. const setup$c = (streamInfo, streamState) => {
  15844. const sInfo = streamInfo.stream;
  15845. const throttler = last(streamInfo.onStream, sInfo.delay);
  15846. streamState.setTimer(throttler);
  15847. return (component, simulatedEvent) => {
  15848. throttler.throttle(component, simulatedEvent);
  15849. if (sInfo.stopEvent) {
  15850. simulatedEvent.stop();
  15851. }
  15852. };
  15853. };
  15854. var StreamingSchema = [
  15855. requiredOf('stream', choose$1('mode', {
  15856. throttle: [
  15857. required$1('delay'),
  15858. defaulted('stopEvent', true),
  15859. output$1('streams', {
  15860. setup: setup$c,
  15861. state: throttle
  15862. })
  15863. ]
  15864. })),
  15865. defaulted('event', 'input'),
  15866. option$3('cancelEvent'),
  15867. onStrictHandler('onStream')
  15868. ];
  15869. const Streaming = create$4({
  15870. fields: StreamingSchema,
  15871. name: 'streaming',
  15872. active: ActiveStreaming,
  15873. state: StreamingState
  15874. });
  15875. const setValueFromItem = (model, input, item) => {
  15876. const itemData = Representing.getValue(item);
  15877. Representing.setValue(input, itemData);
  15878. setCursorAtEnd(input);
  15879. };
  15880. const setSelectionOn = (input, f) => {
  15881. const el = input.element;
  15882. const value = get$6(el);
  15883. const node = el.dom;
  15884. if (get$f(el, 'type') !== 'number') {
  15885. f(node, value);
  15886. }
  15887. };
  15888. const setCursorAtEnd = input => {
  15889. setSelectionOn(input, (node, value) => node.setSelectionRange(value.length, value.length));
  15890. };
  15891. const setSelectionToEnd = (input, startOffset) => {
  15892. setSelectionOn(input, (node, value) => node.setSelectionRange(startOffset, value.length));
  15893. };
  15894. const attemptSelectOver = (model, input, item) => {
  15895. if (!model.selectsOver) {
  15896. return Optional.none();
  15897. } else {
  15898. const currentValue = Representing.getValue(input);
  15899. const inputDisplay = model.getDisplayText(currentValue);
  15900. const itemValue = Representing.getValue(item);
  15901. const itemDisplay = model.getDisplayText(itemValue);
  15902. return itemDisplay.indexOf(inputDisplay) === 0 ? Optional.some(() => {
  15903. setValueFromItem(model, input, item);
  15904. setSelectionToEnd(input, inputDisplay.length);
  15905. }) : Optional.none();
  15906. }
  15907. };
  15908. const itemExecute = constant$1('alloy.typeahead.itemexecute');
  15909. const make$3 = (detail, components, spec, externals) => {
  15910. const navigateList = (comp, simulatedEvent, highlighter) => {
  15911. detail.previewing.set(false);
  15912. const sandbox = Coupling.getCoupled(comp, 'sandbox');
  15913. if (Sandboxing.isOpen(sandbox)) {
  15914. Composing.getCurrent(sandbox).each(menu => {
  15915. Highlighting.getHighlighted(menu).fold(() => {
  15916. highlighter(menu);
  15917. }, () => {
  15918. dispatchEvent(sandbox, menu.element, 'keydown', simulatedEvent);
  15919. });
  15920. });
  15921. } else {
  15922. const onOpenSync = sandbox => {
  15923. Composing.getCurrent(sandbox).each(highlighter);
  15924. };
  15925. open(detail, mapFetch(comp), comp, sandbox, externals, onOpenSync, HighlightOnOpen.HighlightMenuAndItem).get(noop);
  15926. }
  15927. };
  15928. const focusBehaviours$1 = focusBehaviours(detail);
  15929. const mapFetch = comp => tdata => tdata.map(data => {
  15930. const menus = values(data.menus);
  15931. const items = bind$3(menus, menu => filter$2(menu.items, item => item.type === 'item'));
  15932. const repState = Representing.getState(comp);
  15933. repState.update(map$2(items, item => item.data));
  15934. return data;
  15935. });
  15936. const getActiveMenu = sandboxComp => Composing.getCurrent(sandboxComp);
  15937. const typeaheadCustomEvents = 'typeaheadevents';
  15938. const behaviours = [
  15939. Focusing.config({}),
  15940. Representing.config({
  15941. onSetValue: detail.onSetValue,
  15942. store: {
  15943. mode: 'dataset',
  15944. getDataKey: comp => get$6(comp.element),
  15945. getFallbackEntry: itemString => ({
  15946. value: itemString,
  15947. meta: {}
  15948. }),
  15949. setValue: (comp, data) => {
  15950. set$5(comp.element, detail.model.getDisplayText(data));
  15951. },
  15952. ...detail.initialData.map(d => wrap$1('initialValue', d)).getOr({})
  15953. }
  15954. }),
  15955. Streaming.config({
  15956. stream: {
  15957. mode: 'throttle',
  15958. delay: detail.responseTime,
  15959. stopEvent: false
  15960. },
  15961. onStream: (component, _simulatedEvent) => {
  15962. const sandbox = Coupling.getCoupled(component, 'sandbox');
  15963. const focusInInput = Focusing.isFocused(component);
  15964. if (focusInInput) {
  15965. if (get$6(component.element).length >= detail.minChars) {
  15966. const previousValue = getActiveMenu(sandbox).bind(activeMenu => Highlighting.getHighlighted(activeMenu).map(Representing.getValue));
  15967. detail.previewing.set(true);
  15968. const onOpenSync = _sandbox => {
  15969. getActiveMenu(sandbox).each(activeMenu => {
  15970. previousValue.fold(() => {
  15971. if (detail.model.selectsOver) {
  15972. Highlighting.highlightFirst(activeMenu);
  15973. }
  15974. }, pv => {
  15975. Highlighting.highlightBy(activeMenu, item => {
  15976. const itemData = Representing.getValue(item);
  15977. return itemData.value === pv.value;
  15978. });
  15979. Highlighting.getHighlighted(activeMenu).orThunk(() => {
  15980. Highlighting.highlightFirst(activeMenu);
  15981. return Optional.none();
  15982. });
  15983. });
  15984. });
  15985. };
  15986. open(detail, mapFetch(component), component, sandbox, externals, onOpenSync, HighlightOnOpen.HighlightJustMenu).get(noop);
  15987. }
  15988. }
  15989. },
  15990. cancelEvent: typeaheadCancel()
  15991. }),
  15992. Keying.config({
  15993. mode: 'special',
  15994. onDown: (comp, simulatedEvent) => {
  15995. navigateList(comp, simulatedEvent, Highlighting.highlightFirst);
  15996. return Optional.some(true);
  15997. },
  15998. onEscape: comp => {
  15999. const sandbox = Coupling.getCoupled(comp, 'sandbox');
  16000. if (Sandboxing.isOpen(sandbox)) {
  16001. Sandboxing.close(sandbox);
  16002. return Optional.some(true);
  16003. }
  16004. return Optional.none();
  16005. },
  16006. onUp: (comp, simulatedEvent) => {
  16007. navigateList(comp, simulatedEvent, Highlighting.highlightLast);
  16008. return Optional.some(true);
  16009. },
  16010. onEnter: comp => {
  16011. const sandbox = Coupling.getCoupled(comp, 'sandbox');
  16012. const sandboxIsOpen = Sandboxing.isOpen(sandbox);
  16013. if (sandboxIsOpen && !detail.previewing.get()) {
  16014. return getActiveMenu(sandbox).bind(activeMenu => Highlighting.getHighlighted(activeMenu)).map(item => {
  16015. emitWith(comp, itemExecute(), { item });
  16016. return true;
  16017. });
  16018. } else {
  16019. const currentValue = Representing.getValue(comp);
  16020. emit(comp, typeaheadCancel());
  16021. detail.onExecute(sandbox, comp, currentValue);
  16022. if (sandboxIsOpen) {
  16023. Sandboxing.close(sandbox);
  16024. }
  16025. return Optional.some(true);
  16026. }
  16027. }
  16028. }),
  16029. Toggling.config({
  16030. toggleClass: detail.markers.openClass,
  16031. aria: { mode: 'expanded' }
  16032. }),
  16033. Coupling.config({
  16034. others: {
  16035. sandbox: hotspot => {
  16036. return makeSandbox$1(detail, hotspot, {
  16037. onOpen: () => Toggling.on(hotspot),
  16038. onClose: () => Toggling.off(hotspot)
  16039. });
  16040. }
  16041. }
  16042. }),
  16043. config(typeaheadCustomEvents, [
  16044. runOnAttached(typeaheadComp => {
  16045. detail.lazyTypeaheadComp.set(Optional.some(typeaheadComp));
  16046. }),
  16047. runOnDetached(_typeaheadComp => {
  16048. detail.lazyTypeaheadComp.set(Optional.none());
  16049. }),
  16050. runOnExecute$1(comp => {
  16051. const onOpenSync = noop;
  16052. togglePopup(detail, mapFetch(comp), comp, externals, onOpenSync, HighlightOnOpen.HighlightMenuAndItem).get(noop);
  16053. }),
  16054. run$1(itemExecute(), (comp, se) => {
  16055. const sandbox = Coupling.getCoupled(comp, 'sandbox');
  16056. setValueFromItem(detail.model, comp, se.event.item);
  16057. emit(comp, typeaheadCancel());
  16058. detail.onItemExecute(comp, sandbox, se.event.item, Representing.getValue(comp));
  16059. Sandboxing.close(sandbox);
  16060. setCursorAtEnd(comp);
  16061. })
  16062. ].concat(detail.dismissOnBlur ? [run$1(postBlur(), typeahead => {
  16063. const sandbox = Coupling.getCoupled(typeahead, 'sandbox');
  16064. if (search(sandbox.element).isNone()) {
  16065. Sandboxing.close(sandbox);
  16066. }
  16067. })] : []))
  16068. ];
  16069. const eventOrder = {
  16070. [detachedFromDom()]: [
  16071. Representing.name(),
  16072. Streaming.name(),
  16073. typeaheadCustomEvents
  16074. ],
  16075. ...detail.eventOrder
  16076. };
  16077. return {
  16078. uid: detail.uid,
  16079. dom: dom(deepMerge(detail, {
  16080. inputAttributes: {
  16081. 'role': 'combobox',
  16082. 'aria-autocomplete': 'list',
  16083. 'aria-haspopup': 'true'
  16084. }
  16085. })),
  16086. behaviours: {
  16087. ...focusBehaviours$1,
  16088. ...augment(detail.typeaheadBehaviours, behaviours)
  16089. },
  16090. eventOrder
  16091. };
  16092. };
  16093. const schema$g = constant$1([
  16094. option$3('lazySink'),
  16095. required$1('fetch'),
  16096. defaulted('minChars', 5),
  16097. defaulted('responseTime', 1000),
  16098. onHandler('onOpen'),
  16099. defaulted('getHotspot', Optional.some),
  16100. defaulted('getAnchorOverrides', constant$1({})),
  16101. defaulted('layouts', Optional.none()),
  16102. defaulted('eventOrder', {}),
  16103. defaultedObjOf('model', {}, [
  16104. defaulted('getDisplayText', itemData => itemData.meta !== undefined && itemData.meta.text !== undefined ? itemData.meta.text : itemData.value),
  16105. defaulted('selectsOver', true),
  16106. defaulted('populateFromBrowse', true)
  16107. ]),
  16108. onHandler('onSetValue'),
  16109. onKeyboardHandler('onExecute'),
  16110. onHandler('onItemExecute'),
  16111. defaulted('inputClasses', []),
  16112. defaulted('inputAttributes', {}),
  16113. defaulted('inputStyles', {}),
  16114. defaulted('matchWidth', true),
  16115. defaulted('useMinWidth', false),
  16116. defaulted('dismissOnBlur', true),
  16117. markers$1(['openClass']),
  16118. option$3('initialData'),
  16119. field('typeaheadBehaviours', [
  16120. Focusing,
  16121. Representing,
  16122. Streaming,
  16123. Keying,
  16124. Toggling,
  16125. Coupling
  16126. ]),
  16127. customField('lazyTypeaheadComp', () => Cell(Optional.none)),
  16128. customField('previewing', () => Cell(true))
  16129. ].concat(schema$l()).concat(sandboxFields()));
  16130. const parts$b = constant$1([external({
  16131. schema: [tieredMenuMarkers()],
  16132. name: 'menu',
  16133. overrides: detail => {
  16134. return {
  16135. fakeFocus: true,
  16136. onHighlightItem: (_tmenu, menu, item) => {
  16137. if (!detail.previewing.get()) {
  16138. detail.lazyTypeaheadComp.get().each(input => {
  16139. if (detail.model.populateFromBrowse) {
  16140. setValueFromItem(detail.model, input, item);
  16141. }
  16142. });
  16143. } else {
  16144. detail.lazyTypeaheadComp.get().each(input => {
  16145. attemptSelectOver(detail.model, input, item).fold(() => {
  16146. if (detail.model.selectsOver) {
  16147. Highlighting.dehighlight(menu, item);
  16148. detail.previewing.set(true);
  16149. } else {
  16150. detail.previewing.set(false);
  16151. }
  16152. }, selectOverTextInInput => {
  16153. selectOverTextInInput();
  16154. detail.previewing.set(false);
  16155. });
  16156. });
  16157. }
  16158. },
  16159. onExecute: (_menu, item) => {
  16160. return detail.lazyTypeaheadComp.get().map(typeahead => {
  16161. emitWith(typeahead, itemExecute(), { item });
  16162. return true;
  16163. });
  16164. },
  16165. onHover: (menu, item) => {
  16166. detail.previewing.set(false);
  16167. detail.lazyTypeaheadComp.get().each(input => {
  16168. if (detail.model.populateFromBrowse) {
  16169. setValueFromItem(detail.model, input, item);
  16170. }
  16171. });
  16172. }
  16173. };
  16174. }
  16175. })]);
  16176. const Typeahead = composite({
  16177. name: 'Typeahead',
  16178. configFields: schema$g(),
  16179. partFields: parts$b(),
  16180. factory: make$3
  16181. });
  16182. const wrap = delegate => {
  16183. const toCached = () => {
  16184. return wrap(delegate.toCached());
  16185. };
  16186. const bindFuture = f => {
  16187. return wrap(delegate.bind(resA => resA.fold(err => Future.pure(Result.error(err)), a => f(a))));
  16188. };
  16189. const bindResult = f => {
  16190. return wrap(delegate.map(resA => resA.bind(f)));
  16191. };
  16192. const mapResult = f => {
  16193. return wrap(delegate.map(resA => resA.map(f)));
  16194. };
  16195. const mapError = f => {
  16196. return wrap(delegate.map(resA => resA.mapError(f)));
  16197. };
  16198. const foldResult = (whenError, whenValue) => {
  16199. return delegate.map(res => res.fold(whenError, whenValue));
  16200. };
  16201. const withTimeout = (timeout, errorThunk) => {
  16202. return wrap(Future.nu(callback => {
  16203. let timedOut = false;
  16204. const timer = setTimeout(() => {
  16205. timedOut = true;
  16206. callback(Result.error(errorThunk()));
  16207. }, timeout);
  16208. delegate.get(result => {
  16209. if (!timedOut) {
  16210. clearTimeout(timer);
  16211. callback(result);
  16212. }
  16213. });
  16214. }));
  16215. };
  16216. return {
  16217. ...delegate,
  16218. toCached,
  16219. bindFuture,
  16220. bindResult,
  16221. mapResult,
  16222. mapError,
  16223. foldResult,
  16224. withTimeout
  16225. };
  16226. };
  16227. const nu$1 = worker => {
  16228. return wrap(Future.nu(worker));
  16229. };
  16230. const value = value => {
  16231. return wrap(Future.pure(Result.value(value)));
  16232. };
  16233. const error = error => {
  16234. return wrap(Future.pure(Result.error(error)));
  16235. };
  16236. const fromResult = result => {
  16237. return wrap(Future.pure(result));
  16238. };
  16239. const fromFuture = future => {
  16240. return wrap(future.map(Result.value));
  16241. };
  16242. const fromPromise = promise => {
  16243. return nu$1(completer => {
  16244. promise.then(value => {
  16245. completer(Result.value(value));
  16246. }, error => {
  16247. completer(Result.error(error));
  16248. });
  16249. });
  16250. };
  16251. const FutureResult = {
  16252. nu: nu$1,
  16253. wrap,
  16254. pure: value,
  16255. value,
  16256. error,
  16257. fromResult,
  16258. fromFuture,
  16259. fromPromise
  16260. };
  16261. const renderCommonSpec = (spec, actionOpt, extraBehaviours = [], dom, components, providersBackstage) => {
  16262. const action = actionOpt.fold(() => ({}), action => ({ action }));
  16263. const common = {
  16264. buttonBehaviours: derive$1([
  16265. DisablingConfigs.button(() => !spec.enabled || providersBackstage.isDisabled()),
  16266. receivingConfig(),
  16267. Tabstopping.config({}),
  16268. config('button press', [
  16269. preventDefault('click'),
  16270. preventDefault('mousedown')
  16271. ])
  16272. ].concat(extraBehaviours)),
  16273. eventOrder: {
  16274. click: [
  16275. 'button press',
  16276. 'alloy.base.behaviour'
  16277. ],
  16278. mousedown: [
  16279. 'button press',
  16280. 'alloy.base.behaviour'
  16281. ]
  16282. },
  16283. ...action
  16284. };
  16285. const domFinal = deepMerge(common, { dom });
  16286. return deepMerge(domFinal, { components });
  16287. };
  16288. const renderIconButtonSpec = (spec, action, providersBackstage, extraBehaviours = []) => {
  16289. const tooltipAttributes = spec.tooltip.map(tooltip => ({
  16290. 'aria-label': providersBackstage.translate(tooltip),
  16291. 'title': providersBackstage.translate(tooltip)
  16292. })).getOr({});
  16293. const dom = {
  16294. tag: 'button',
  16295. classes: ['tox-tbtn'],
  16296. attributes: tooltipAttributes
  16297. };
  16298. const icon = spec.icon.map(iconName => renderIconFromPack$1(iconName, providersBackstage.icons));
  16299. const components = componentRenderPipeline([icon]);
  16300. return renderCommonSpec(spec, action, extraBehaviours, dom, components, providersBackstage);
  16301. };
  16302. const calculateClassesFromButtonType = buttonType => {
  16303. switch (buttonType) {
  16304. case 'primary':
  16305. return ['tox-button'];
  16306. case 'toolbar':
  16307. return ['tox-tbtn'];
  16308. case 'secondary':
  16309. default:
  16310. return [
  16311. 'tox-button',
  16312. 'tox-button--secondary'
  16313. ];
  16314. }
  16315. };
  16316. const renderButtonSpec = (spec, action, providersBackstage, extraBehaviours = [], extraClasses = []) => {
  16317. const translatedText = providersBackstage.translate(spec.text);
  16318. const icon = spec.icon.map(iconName => renderIconFromPack$1(iconName, providersBackstage.icons));
  16319. const components = [icon.getOrThunk(() => text$2(translatedText))];
  16320. const buttonType = spec.buttonType.getOr(!spec.primary && !spec.borderless ? 'secondary' : 'primary');
  16321. const baseClasses = calculateClassesFromButtonType(buttonType);
  16322. const classes = [
  16323. ...baseClasses,
  16324. ...icon.isSome() ? ['tox-button--icon'] : [],
  16325. ...spec.borderless ? ['tox-button--naked'] : [],
  16326. ...extraClasses
  16327. ];
  16328. const dom = {
  16329. tag: 'button',
  16330. classes,
  16331. attributes: { title: translatedText }
  16332. };
  16333. return renderCommonSpec(spec, action, extraBehaviours, dom, components, providersBackstage);
  16334. };
  16335. const renderButton$1 = (spec, action, providersBackstage, extraBehaviours = [], extraClasses = []) => {
  16336. const buttonSpec = renderButtonSpec(spec, Optional.some(action), providersBackstage, extraBehaviours, extraClasses);
  16337. return Button.sketch(buttonSpec);
  16338. };
  16339. const getAction = (name, buttonType) => comp => {
  16340. if (buttonType === 'custom') {
  16341. emitWith(comp, formActionEvent, {
  16342. name,
  16343. value: {}
  16344. });
  16345. } else if (buttonType === 'submit') {
  16346. emit(comp, formSubmitEvent);
  16347. } else if (buttonType === 'cancel') {
  16348. emit(comp, formCancelEvent);
  16349. } else {
  16350. console.error('Unknown button type: ', buttonType);
  16351. }
  16352. };
  16353. const isMenuFooterButtonSpec = (spec, buttonType) => buttonType === 'menu';
  16354. const isNormalFooterButtonSpec = (spec, buttonType) => buttonType === 'custom' || buttonType === 'cancel' || buttonType === 'submit';
  16355. const isToggleButtonSpec = (spec, buttonType) => buttonType === 'togglebutton';
  16356. const renderToggleButton = (spec, providers) => {
  16357. var _a, _b, _c;
  16358. const optMemIcon = Optional.from(spec.icon).map(memIcon => renderReplaceableIconFromPack(memIcon, providers.icons)).map(record);
  16359. const action = comp => {
  16360. emitWith(comp, formActionEvent, {
  16361. name: spec.name,
  16362. value: {
  16363. setIcon: newIcon => {
  16364. optMemIcon.map(memIcon => memIcon.getOpt(comp).each(displayIcon => {
  16365. Replacing.set(displayIcon, [renderReplaceableIconFromPack(newIcon, providers.icons)]);
  16366. }));
  16367. }
  16368. }
  16369. });
  16370. };
  16371. const buttonSpec = {
  16372. ...spec,
  16373. name: (_a = spec.name) !== null && _a !== void 0 ? _a : '',
  16374. primary: spec.buttonType === 'primary',
  16375. buttonType: Optional.from(spec.buttonType),
  16376. tooltip: Optional.from(spec.tooltip),
  16377. icon: Optional.from(spec.name),
  16378. enabled: (_b = spec.enabled) !== null && _b !== void 0 ? _b : false,
  16379. borderless: false
  16380. };
  16381. const tooltipAttributes = buttonSpec.tooltip.map(tooltip => ({
  16382. 'aria-label': providers.translate(tooltip),
  16383. 'title': providers.translate(tooltip)
  16384. })).getOr({});
  16385. const buttonTypeClasses = calculateClassesFromButtonType((_c = spec.buttonType) !== null && _c !== void 0 ? _c : 'secondary');
  16386. const showIconAndText = !!spec.icon && !!spec.text;
  16387. const dom = {
  16388. tag: 'button',
  16389. classes: [
  16390. ...buttonTypeClasses.concat(['tox-button--icon']),
  16391. ...spec.active ? ['tox-button--enabled'] : [],
  16392. ...showIconAndText ? ['tox-button--icon-and-text'] : []
  16393. ],
  16394. attributes: tooltipAttributes
  16395. };
  16396. const extraBehaviours = [];
  16397. const translatedText = providers.translate(spec.text);
  16398. const translatedTextComponed = text$2(translatedText);
  16399. const iconComp = componentRenderPipeline([optMemIcon.map(memIcon => memIcon.asSpec())]);
  16400. const components = [
  16401. ...iconComp,
  16402. ...showIconAndText ? [translatedTextComponed] : []
  16403. ];
  16404. const iconButtonSpec = renderCommonSpec(buttonSpec, Optional.some(action), extraBehaviours, dom, components, providers);
  16405. return Button.sketch(iconButtonSpec);
  16406. };
  16407. const renderFooterButton = (spec, buttonType, backstage) => {
  16408. if (isMenuFooterButtonSpec(spec, buttonType)) {
  16409. const getButton = () => memButton;
  16410. const menuButtonSpec = spec;
  16411. const fixedSpec = {
  16412. ...spec,
  16413. type: 'menubutton',
  16414. search: Optional.none(),
  16415. onSetup: api => {
  16416. api.setEnabled(spec.enabled);
  16417. return noop;
  16418. },
  16419. fetch: getFetch(menuButtonSpec.items, getButton, backstage)
  16420. };
  16421. const memButton = record(renderMenuButton(fixedSpec, 'tox-tbtn', backstage, Optional.none()));
  16422. return memButton.asSpec();
  16423. } else if (isNormalFooterButtonSpec(spec, buttonType)) {
  16424. const action = getAction(spec.name, buttonType);
  16425. const buttonSpec = {
  16426. ...spec,
  16427. borderless: false
  16428. };
  16429. return renderButton$1(buttonSpec, action, backstage.shared.providers, []);
  16430. } else if (isToggleButtonSpec(spec, buttonType)) {
  16431. const buttonSpec = {
  16432. ...spec,
  16433. tooltip: spec.tooltip,
  16434. text: spec.text.getOrUndefined(),
  16435. buttonType: spec.buttonType.getOrUndefined()
  16436. };
  16437. return renderToggleButton(buttonSpec, backstage.shared.providers);
  16438. } else {
  16439. console.error('Unknown footer button type: ', buttonType);
  16440. throw new Error('Unknown footer button type');
  16441. }
  16442. };
  16443. const renderDialogButton = (spec, providersBackstage) => {
  16444. const action = getAction(spec.name, 'custom');
  16445. return renderFormField(Optional.none(), FormField.parts.field({
  16446. factory: Button,
  16447. ...renderButtonSpec(spec, Optional.some(action), providersBackstage, [
  16448. RepresentingConfigs.memory(''),
  16449. ComposingConfigs.self()
  16450. ])
  16451. }));
  16452. };
  16453. const separator$1 = { type: 'separator' };
  16454. const toMenuItem = target => ({
  16455. type: 'menuitem',
  16456. value: target.url,
  16457. text: target.title,
  16458. meta: { attach: target.attach },
  16459. onAction: noop
  16460. });
  16461. const staticMenuItem = (title, url) => ({
  16462. type: 'menuitem',
  16463. value: url,
  16464. text: title,
  16465. meta: { attach: undefined },
  16466. onAction: noop
  16467. });
  16468. const toMenuItems = targets => map$2(targets, toMenuItem);
  16469. const filterLinkTargets = (type, targets) => filter$2(targets, target => target.type === type);
  16470. const filteredTargets = (type, targets) => toMenuItems(filterLinkTargets(type, targets));
  16471. const headerTargets = linkInfo => filteredTargets('header', linkInfo.targets);
  16472. const anchorTargets = linkInfo => filteredTargets('anchor', linkInfo.targets);
  16473. const anchorTargetTop = linkInfo => Optional.from(linkInfo.anchorTop).map(url => staticMenuItem('<top>', url)).toArray();
  16474. const anchorTargetBottom = linkInfo => Optional.from(linkInfo.anchorBottom).map(url => staticMenuItem('<bottom>', url)).toArray();
  16475. const historyTargets = history => map$2(history, url => staticMenuItem(url, url));
  16476. const joinMenuLists = items => {
  16477. return foldl(items, (a, b) => {
  16478. const bothEmpty = a.length === 0 || b.length === 0;
  16479. return bothEmpty ? a.concat(b) : a.concat(separator$1, b);
  16480. }, []);
  16481. };
  16482. const filterByQuery = (term, menuItems) => {
  16483. const lowerCaseTerm = term.toLowerCase();
  16484. return filter$2(menuItems, item => {
  16485. var _a;
  16486. const text = item.meta !== undefined && item.meta.text !== undefined ? item.meta.text : item.text;
  16487. const value = (_a = item.value) !== null && _a !== void 0 ? _a : '';
  16488. return contains$1(text.toLowerCase(), lowerCaseTerm) || contains$1(value.toLowerCase(), lowerCaseTerm);
  16489. });
  16490. };
  16491. const getItems = (fileType, input, urlBackstage) => {
  16492. var _a, _b;
  16493. const urlInputValue = Representing.getValue(input);
  16494. const term = (_b = (_a = urlInputValue === null || urlInputValue === void 0 ? void 0 : urlInputValue.meta) === null || _a === void 0 ? void 0 : _a.text) !== null && _b !== void 0 ? _b : urlInputValue.value;
  16495. const info = urlBackstage.getLinkInformation();
  16496. return info.fold(() => [], linkInfo => {
  16497. const history = filterByQuery(term, historyTargets(urlBackstage.getHistory(fileType)));
  16498. return fileType === 'file' ? joinMenuLists([
  16499. history,
  16500. filterByQuery(term, headerTargets(linkInfo)),
  16501. filterByQuery(term, flatten([
  16502. anchorTargetTop(linkInfo),
  16503. anchorTargets(linkInfo),
  16504. anchorTargetBottom(linkInfo)
  16505. ]))
  16506. ]) : history;
  16507. });
  16508. };
  16509. const errorId = generate$6('aria-invalid');
  16510. const renderUrlInput = (spec, backstage, urlBackstage, initialData) => {
  16511. const providersBackstage = backstage.shared.providers;
  16512. const updateHistory = component => {
  16513. const urlEntry = Representing.getValue(component);
  16514. urlBackstage.addToHistory(urlEntry.value, spec.filetype);
  16515. };
  16516. const typeaheadSpec = {
  16517. ...initialData.map(initialData => ({ initialData })).getOr({}),
  16518. dismissOnBlur: true,
  16519. inputClasses: ['tox-textfield'],
  16520. sandboxClasses: ['tox-dialog__popups'],
  16521. inputAttributes: {
  16522. 'aria-errormessage': errorId,
  16523. 'type': 'url'
  16524. },
  16525. minChars: 0,
  16526. responseTime: 0,
  16527. fetch: input => {
  16528. const items = getItems(spec.filetype, input, urlBackstage);
  16529. const tdata = build(items, ItemResponse$1.BUBBLE_TO_SANDBOX, backstage, {
  16530. isHorizontalMenu: false,
  16531. search: Optional.none()
  16532. });
  16533. return Future.pure(tdata);
  16534. },
  16535. getHotspot: comp => memUrlBox.getOpt(comp),
  16536. onSetValue: (comp, _newValue) => {
  16537. if (comp.hasConfigured(Invalidating)) {
  16538. Invalidating.run(comp).get(noop);
  16539. }
  16540. },
  16541. typeaheadBehaviours: derive$1([
  16542. ...urlBackstage.getValidationHandler().map(handler => Invalidating.config({
  16543. getRoot: comp => parentElement(comp.element),
  16544. invalidClass: 'tox-control-wrap--status-invalid',
  16545. notify: {
  16546. onInvalid: (comp, err) => {
  16547. memInvalidIcon.getOpt(comp).each(invalidComp => {
  16548. set$9(invalidComp.element, 'title', providersBackstage.translate(err));
  16549. });
  16550. }
  16551. },
  16552. validator: {
  16553. validate: input => {
  16554. const urlEntry = Representing.getValue(input);
  16555. return FutureResult.nu(completer => {
  16556. handler({
  16557. type: spec.filetype,
  16558. url: urlEntry.value
  16559. }, validation => {
  16560. if (validation.status === 'invalid') {
  16561. const err = Result.error(validation.message);
  16562. completer(err);
  16563. } else {
  16564. const val = Result.value(validation.message);
  16565. completer(val);
  16566. }
  16567. });
  16568. });
  16569. },
  16570. validateOnLoad: false
  16571. }
  16572. })).toArray(),
  16573. Disabling.config({ disabled: () => !spec.enabled || providersBackstage.isDisabled() }),
  16574. Tabstopping.config({}),
  16575. config('urlinput-events', [
  16576. run$1(input(), comp => {
  16577. const currentValue = get$6(comp.element);
  16578. const trimmedValue = currentValue.trim();
  16579. if (trimmedValue !== currentValue) {
  16580. set$5(comp.element, trimmedValue);
  16581. }
  16582. if (spec.filetype === 'file') {
  16583. emitWith(comp, formChangeEvent, { name: spec.name });
  16584. }
  16585. }),
  16586. run$1(change(), comp => {
  16587. emitWith(comp, formChangeEvent, { name: spec.name });
  16588. updateHistory(comp);
  16589. }),
  16590. run$1(postPaste(), comp => {
  16591. emitWith(comp, formChangeEvent, { name: spec.name });
  16592. updateHistory(comp);
  16593. })
  16594. ])
  16595. ]),
  16596. eventOrder: {
  16597. [input()]: [
  16598. 'streaming',
  16599. 'urlinput-events',
  16600. 'invalidating'
  16601. ]
  16602. },
  16603. model: {
  16604. getDisplayText: itemData => itemData.value,
  16605. selectsOver: false,
  16606. populateFromBrowse: false
  16607. },
  16608. markers: { openClass: 'tox-textfield--popup-open' },
  16609. lazySink: backstage.shared.getSink,
  16610. parts: { menu: part(false, 1, 'normal') },
  16611. onExecute: (_menu, component, _entry) => {
  16612. emitWith(component, formSubmitEvent, {});
  16613. },
  16614. onItemExecute: (typeahead, _sandbox, _item, _value) => {
  16615. updateHistory(typeahead);
  16616. emitWith(typeahead, formChangeEvent, { name: spec.name });
  16617. }
  16618. };
  16619. const pField = FormField.parts.field({
  16620. ...typeaheadSpec,
  16621. factory: Typeahead
  16622. });
  16623. const pLabel = spec.label.map(label => renderLabel$3(label, providersBackstage));
  16624. const makeIcon = (name, errId, icon = name, label = name) => render$3(icon, {
  16625. tag: 'div',
  16626. classes: [
  16627. 'tox-icon',
  16628. 'tox-control-wrap__status-icon-' + name
  16629. ],
  16630. attributes: {
  16631. 'title': providersBackstage.translate(label),
  16632. 'aria-live': 'polite',
  16633. ...errId.fold(() => ({}), id => ({ id }))
  16634. }
  16635. }, providersBackstage.icons);
  16636. const memInvalidIcon = record(makeIcon('invalid', Optional.some(errorId), 'warning'));
  16637. const memStatus = record({
  16638. dom: {
  16639. tag: 'div',
  16640. classes: ['tox-control-wrap__status-icon-wrap']
  16641. },
  16642. components: [memInvalidIcon.asSpec()]
  16643. });
  16644. const optUrlPicker = urlBackstage.getUrlPicker(spec.filetype);
  16645. const browseUrlEvent = generate$6('browser.url.event');
  16646. const memUrlBox = record({
  16647. dom: {
  16648. tag: 'div',
  16649. classes: ['tox-control-wrap']
  16650. },
  16651. components: [
  16652. pField,
  16653. memStatus.asSpec()
  16654. ],
  16655. behaviours: derive$1([Disabling.config({ disabled: () => !spec.enabled || providersBackstage.isDisabled() })])
  16656. });
  16657. const memUrlPickerButton = record(renderButton$1({
  16658. name: spec.name,
  16659. icon: Optional.some('browse'),
  16660. text: spec.label.getOr(''),
  16661. enabled: spec.enabled,
  16662. primary: false,
  16663. buttonType: Optional.none(),
  16664. borderless: true
  16665. }, component => emit(component, browseUrlEvent), providersBackstage, [], ['tox-browse-url']));
  16666. const controlHWrapper = () => ({
  16667. dom: {
  16668. tag: 'div',
  16669. classes: ['tox-form__controls-h-stack']
  16670. },
  16671. components: flatten([
  16672. [memUrlBox.asSpec()],
  16673. optUrlPicker.map(() => memUrlPickerButton.asSpec()).toArray()
  16674. ])
  16675. });
  16676. const openUrlPicker = comp => {
  16677. Composing.getCurrent(comp).each(field => {
  16678. const componentData = Representing.getValue(field);
  16679. const urlData = {
  16680. fieldname: spec.name,
  16681. ...componentData
  16682. };
  16683. optUrlPicker.each(picker => {
  16684. picker(urlData).get(chosenData => {
  16685. Representing.setValue(field, chosenData);
  16686. emitWith(comp, formChangeEvent, { name: spec.name });
  16687. });
  16688. });
  16689. });
  16690. };
  16691. return FormField.sketch({
  16692. dom: renderFormFieldDom(),
  16693. components: pLabel.toArray().concat([controlHWrapper()]),
  16694. fieldBehaviours: derive$1([
  16695. Disabling.config({
  16696. disabled: () => !spec.enabled || providersBackstage.isDisabled(),
  16697. onDisabled: comp => {
  16698. FormField.getField(comp).each(Disabling.disable);
  16699. memUrlPickerButton.getOpt(comp).each(Disabling.disable);
  16700. },
  16701. onEnabled: comp => {
  16702. FormField.getField(comp).each(Disabling.enable);
  16703. memUrlPickerButton.getOpt(comp).each(Disabling.enable);
  16704. }
  16705. }),
  16706. receivingConfig(),
  16707. config('url-input-events', [run$1(browseUrlEvent, openUrlPicker)])
  16708. ])
  16709. });
  16710. };
  16711. const renderAlertBanner = (spec, providersBackstage) => Container.sketch({
  16712. dom: {
  16713. tag: 'div',
  16714. attributes: { role: 'alert' },
  16715. classes: [
  16716. 'tox-notification',
  16717. 'tox-notification--in',
  16718. `tox-notification--${ spec.level }`
  16719. ]
  16720. },
  16721. components: [
  16722. {
  16723. dom: {
  16724. tag: 'div',
  16725. classes: ['tox-notification__icon']
  16726. },
  16727. components: [Button.sketch({
  16728. dom: {
  16729. tag: 'button',
  16730. classes: [
  16731. 'tox-button',
  16732. 'tox-button--naked',
  16733. 'tox-button--icon'
  16734. ],
  16735. innerHtml: get$2(spec.icon, providersBackstage.icons),
  16736. attributes: { title: providersBackstage.translate(spec.iconTooltip) }
  16737. },
  16738. action: comp => {
  16739. emitWith(comp, formActionEvent, {
  16740. name: 'alert-banner',
  16741. value: spec.url
  16742. });
  16743. },
  16744. buttonBehaviours: derive$1([addFocusableBehaviour()])
  16745. })]
  16746. },
  16747. {
  16748. dom: {
  16749. tag: 'div',
  16750. classes: ['tox-notification__body'],
  16751. innerHtml: providersBackstage.translate(spec.text)
  16752. }
  16753. }
  16754. ]
  16755. });
  16756. const set$1 = (element, status) => {
  16757. element.dom.checked = status;
  16758. };
  16759. const get$1 = element => element.dom.checked;
  16760. const renderCheckbox = (spec, providerBackstage, initialData) => {
  16761. const toggleCheckboxHandler = comp => {
  16762. comp.element.dom.click();
  16763. return Optional.some(true);
  16764. };
  16765. const pField = FormField.parts.field({
  16766. factory: { sketch: identity },
  16767. dom: {
  16768. tag: 'input',
  16769. classes: ['tox-checkbox__input'],
  16770. attributes: { type: 'checkbox' }
  16771. },
  16772. behaviours: derive$1([
  16773. ComposingConfigs.self(),
  16774. Disabling.config({ disabled: () => !spec.enabled || providerBackstage.isDisabled() }),
  16775. Tabstopping.config({}),
  16776. Focusing.config({}),
  16777. RepresentingConfigs.withElement(initialData, get$1, set$1),
  16778. Keying.config({
  16779. mode: 'special',
  16780. onEnter: toggleCheckboxHandler,
  16781. onSpace: toggleCheckboxHandler,
  16782. stopSpaceKeyup: true
  16783. }),
  16784. config('checkbox-events', [run$1(change(), (component, _) => {
  16785. emitWith(component, formChangeEvent, { name: spec.name });
  16786. })])
  16787. ])
  16788. });
  16789. const pLabel = FormField.parts.label({
  16790. dom: {
  16791. tag: 'span',
  16792. classes: ['tox-checkbox__label']
  16793. },
  16794. components: [text$2(providerBackstage.translate(spec.label))],
  16795. behaviours: derive$1([Unselecting.config({})])
  16796. });
  16797. const makeIcon = className => {
  16798. const iconName = className === 'checked' ? 'selected' : 'unselected';
  16799. return render$3(iconName, {
  16800. tag: 'span',
  16801. classes: [
  16802. 'tox-icon',
  16803. 'tox-checkbox-icon__' + className
  16804. ]
  16805. }, providerBackstage.icons);
  16806. };
  16807. const memIcons = record({
  16808. dom: {
  16809. tag: 'div',
  16810. classes: ['tox-checkbox__icons']
  16811. },
  16812. components: [
  16813. makeIcon('checked'),
  16814. makeIcon('unchecked')
  16815. ]
  16816. });
  16817. return FormField.sketch({
  16818. dom: {
  16819. tag: 'label',
  16820. classes: ['tox-checkbox']
  16821. },
  16822. components: [
  16823. pField,
  16824. memIcons.asSpec(),
  16825. pLabel
  16826. ],
  16827. fieldBehaviours: derive$1([
  16828. Disabling.config({
  16829. disabled: () => !spec.enabled || providerBackstage.isDisabled(),
  16830. disableClass: 'tox-checkbox--disabled',
  16831. onDisabled: comp => {
  16832. FormField.getField(comp).each(Disabling.disable);
  16833. },
  16834. onEnabled: comp => {
  16835. FormField.getField(comp).each(Disabling.enable);
  16836. }
  16837. }),
  16838. receivingConfig()
  16839. ])
  16840. });
  16841. };
  16842. const renderHtmlPanel = spec => {
  16843. if (spec.presets === 'presentation') {
  16844. return Container.sketch({
  16845. dom: {
  16846. tag: 'div',
  16847. classes: ['tox-form__group'],
  16848. innerHtml: spec.html
  16849. }
  16850. });
  16851. } else {
  16852. return Container.sketch({
  16853. dom: {
  16854. tag: 'div',
  16855. classes: ['tox-form__group'],
  16856. innerHtml: spec.html,
  16857. attributes: { role: 'document' }
  16858. },
  16859. containerBehaviours: derive$1([
  16860. Tabstopping.config({}),
  16861. Focusing.config({})
  16862. ])
  16863. });
  16864. }
  16865. };
  16866. const make$2 = render => {
  16867. 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))));
  16868. };
  16869. const makeIframe = render => (parts, spec, dialogData, backstage) => {
  16870. const iframeSpec = deepMerge(spec, { source: 'dynamic' });
  16871. return make$2(render)(parts, iframeSpec, dialogData, backstage);
  16872. };
  16873. const factories = {
  16874. bar: make$2((spec, backstage) => renderBar(spec, backstage.shared)),
  16875. collection: make$2((spec, backstage, data) => renderCollection(spec, backstage.shared.providers, data)),
  16876. alertbanner: make$2((spec, backstage) => renderAlertBanner(spec, backstage.shared.providers)),
  16877. input: make$2((spec, backstage, data) => renderInput(spec, backstage.shared.providers, data)),
  16878. textarea: make$2((spec, backstage, data) => renderTextarea(spec, backstage.shared.providers, data)),
  16879. label: make$2((spec, backstage) => renderLabel$2(spec, backstage.shared)),
  16880. iframe: makeIframe((spec, backstage, data) => renderIFrame(spec, backstage.shared.providers, data)),
  16881. button: make$2((spec, backstage) => renderDialogButton(spec, backstage.shared.providers)),
  16882. checkbox: make$2((spec, backstage, data) => renderCheckbox(spec, backstage.shared.providers, data)),
  16883. colorinput: make$2((spec, backstage, data) => renderColorInput(spec, backstage.shared, backstage.colorinput, data)),
  16884. colorpicker: make$2((spec, backstage, data) => renderColorPicker(spec, backstage.shared.providers, data)),
  16885. dropzone: make$2((spec, backstage, data) => renderDropZone(spec, backstage.shared.providers, data)),
  16886. grid: make$2((spec, backstage) => renderGrid(spec, backstage.shared)),
  16887. listbox: make$2((spec, backstage, data) => renderListBox(spec, backstage, data)),
  16888. selectbox: make$2((spec, backstage, data) => renderSelectBox(spec, backstage.shared.providers, data)),
  16889. sizeinput: make$2((spec, backstage) => renderSizeInput(spec, backstage.shared.providers)),
  16890. slider: make$2((spec, backstage, data) => renderSlider(spec, backstage.shared.providers, data)),
  16891. urlinput: make$2((spec, backstage, data) => renderUrlInput(spec, backstage, backstage.urlinput, data)),
  16892. customeditor: make$2(renderCustomEditor),
  16893. htmlpanel: make$2(renderHtmlPanel),
  16894. imagepreview: make$2((spec, _, data) => renderImagePreview(spec, data)),
  16895. table: make$2((spec, backstage) => renderTable(spec, backstage.shared.providers)),
  16896. tree: make$2((spec, backstage) => renderTree(spec, backstage)),
  16897. panel: make$2((spec, backstage) => renderPanel(spec, backstage))
  16898. };
  16899. const noFormParts = {
  16900. field: (_name, spec) => spec,
  16901. record: constant$1([])
  16902. };
  16903. const interpretInForm = (parts, spec, dialogData, oldBackstage) => {
  16904. const newBackstage = deepMerge(oldBackstage, { shared: { interpreter: childSpec => interpretParts(parts, childSpec, dialogData, newBackstage) } });
  16905. return interpretParts(parts, spec, dialogData, newBackstage);
  16906. };
  16907. const interpretParts = (parts, spec, dialogData, backstage) => get$g(factories, spec.type).fold(() => {
  16908. console.error(`Unknown factory type "${ spec.type }", defaulting to container: `, spec);
  16909. return spec;
  16910. }, factory => factory(parts, spec, dialogData, backstage));
  16911. const interpretWithoutForm = (spec, dialogData, backstage) => interpretParts(noFormParts, spec, dialogData, backstage);
  16912. const labelPrefix = 'layout-inset';
  16913. const westEdgeX = anchor => anchor.x;
  16914. const middleX = (anchor, element) => anchor.x + anchor.width / 2 - element.width / 2;
  16915. const eastEdgeX = (anchor, element) => anchor.x + anchor.width - element.width;
  16916. const northY = anchor => anchor.y;
  16917. const southY = (anchor, element) => anchor.y + anchor.height - element.height;
  16918. const centreY = (anchor, element) => anchor.y + anchor.height / 2 - element.height / 2;
  16919. const southwest = (anchor, element, bubbles) => nu$6(eastEdgeX(anchor, element), southY(anchor, element), bubbles.insetSouthwest(), northwest$3(), 'southwest', boundsRestriction(anchor, {
  16920. right: 0,
  16921. bottom: 3
  16922. }), labelPrefix);
  16923. const southeast = (anchor, element, bubbles) => nu$6(westEdgeX(anchor), southY(anchor, element), bubbles.insetSoutheast(), northeast$3(), 'southeast', boundsRestriction(anchor, {
  16924. left: 1,
  16925. bottom: 3
  16926. }), labelPrefix);
  16927. const northwest = (anchor, element, bubbles) => nu$6(eastEdgeX(anchor, element), northY(anchor), bubbles.insetNorthwest(), southwest$3(), 'northwest', boundsRestriction(anchor, {
  16928. right: 0,
  16929. top: 2
  16930. }), labelPrefix);
  16931. const northeast = (anchor, element, bubbles) => nu$6(westEdgeX(anchor), northY(anchor), bubbles.insetNortheast(), southeast$3(), 'northeast', boundsRestriction(anchor, {
  16932. left: 1,
  16933. top: 2
  16934. }), labelPrefix);
  16935. const north = (anchor, element, bubbles) => nu$6(middleX(anchor, element), northY(anchor), bubbles.insetNorth(), south$3(), 'north', boundsRestriction(anchor, { top: 2 }), labelPrefix);
  16936. const south = (anchor, element, bubbles) => nu$6(middleX(anchor, element), southY(anchor, element), bubbles.insetSouth(), north$3(), 'south', boundsRestriction(anchor, { bottom: 3 }), labelPrefix);
  16937. const east = (anchor, element, bubbles) => nu$6(eastEdgeX(anchor, element), centreY(anchor, element), bubbles.insetEast(), west$3(), 'east', boundsRestriction(anchor, { right: 0 }), labelPrefix);
  16938. const west = (anchor, element, bubbles) => nu$6(westEdgeX(anchor), centreY(anchor, element), bubbles.insetWest(), east$3(), 'west', boundsRestriction(anchor, { left: 1 }), labelPrefix);
  16939. const lookupPreserveLayout = lastPlacement => {
  16940. switch (lastPlacement) {
  16941. case 'north':
  16942. return north;
  16943. case 'northeast':
  16944. return northeast;
  16945. case 'northwest':
  16946. return northwest;
  16947. case 'south':
  16948. return south;
  16949. case 'southeast':
  16950. return southeast;
  16951. case 'southwest':
  16952. return southwest;
  16953. case 'east':
  16954. return east;
  16955. case 'west':
  16956. return west;
  16957. }
  16958. };
  16959. const preserve = (anchor, element, bubbles, placee, bounds) => {
  16960. const layout = getPlacement(placee).map(lookupPreserveLayout).getOr(north);
  16961. return layout(anchor, element, bubbles, placee, bounds);
  16962. };
  16963. const lookupFlippedLayout = lastPlacement => {
  16964. switch (lastPlacement) {
  16965. case 'north':
  16966. return south;
  16967. case 'northeast':
  16968. return southeast;
  16969. case 'northwest':
  16970. return southwest;
  16971. case 'south':
  16972. return north;
  16973. case 'southeast':
  16974. return northeast;
  16975. case 'southwest':
  16976. return northwest;
  16977. case 'east':
  16978. return west;
  16979. case 'west':
  16980. return east;
  16981. }
  16982. };
  16983. const flip = (anchor, element, bubbles, placee, bounds) => {
  16984. const layout = getPlacement(placee).map(lookupFlippedLayout).getOr(north);
  16985. return layout(anchor, element, bubbles, placee, bounds);
  16986. };
  16987. const bubbleAlignments$2 = {
  16988. valignCentre: [],
  16989. alignCentre: [],
  16990. alignLeft: [],
  16991. alignRight: [],
  16992. right: [],
  16993. left: [],
  16994. bottom: [],
  16995. top: []
  16996. };
  16997. const getInlineDialogAnchor = (contentAreaElement, lazyAnchorbar, lazyUseEditableAreaAnchor) => {
  16998. const bubbleSize = 12;
  16999. const overrides = { maxHeightFunction: expandable$1() };
  17000. const editableAreaAnchor = () => ({
  17001. type: 'node',
  17002. root: getContentContainer(getRootNode(contentAreaElement())),
  17003. node: Optional.from(contentAreaElement()),
  17004. bubble: nu$5(bubbleSize, bubbleSize, bubbleAlignments$2),
  17005. layouts: {
  17006. onRtl: () => [northeast],
  17007. onLtr: () => [northwest]
  17008. },
  17009. overrides
  17010. });
  17011. const standardAnchor = () => ({
  17012. type: 'hotspot',
  17013. hotspot: lazyAnchorbar(),
  17014. bubble: nu$5(-bubbleSize, bubbleSize, bubbleAlignments$2),
  17015. layouts: {
  17016. onRtl: () => [
  17017. southeast$2,
  17018. southwest$2,
  17019. south$2
  17020. ],
  17021. onLtr: () => [
  17022. southwest$2,
  17023. southeast$2,
  17024. south$2
  17025. ]
  17026. },
  17027. overrides
  17028. });
  17029. return () => lazyUseEditableAreaAnchor() ? editableAreaAnchor() : standardAnchor();
  17030. };
  17031. const getBannerAnchor = (contentAreaElement, lazyAnchorbar, lazyUseEditableAreaAnchor) => {
  17032. const editableAreaAnchor = () => ({
  17033. type: 'node',
  17034. root: getContentContainer(getRootNode(contentAreaElement())),
  17035. node: Optional.from(contentAreaElement()),
  17036. layouts: {
  17037. onRtl: () => [north],
  17038. onLtr: () => [north]
  17039. }
  17040. });
  17041. const standardAnchor = () => ({
  17042. type: 'hotspot',
  17043. hotspot: lazyAnchorbar(),
  17044. layouts: {
  17045. onRtl: () => [south$2],
  17046. onLtr: () => [south$2]
  17047. }
  17048. });
  17049. return () => lazyUseEditableAreaAnchor() ? editableAreaAnchor() : standardAnchor();
  17050. };
  17051. const getCursorAnchor = (editor, bodyElement) => () => ({
  17052. type: 'selection',
  17053. root: bodyElement(),
  17054. getSelection: () => {
  17055. const rng = editor.selection.getRng();
  17056. return Optional.some(SimSelection.range(SugarElement.fromDom(rng.startContainer), rng.startOffset, SugarElement.fromDom(rng.endContainer), rng.endOffset));
  17057. }
  17058. });
  17059. const getNodeAnchor$1 = bodyElement => element => ({
  17060. type: 'node',
  17061. root: bodyElement(),
  17062. node: element
  17063. });
  17064. const getAnchors = (editor, lazyAnchorbar, isToolbarTop) => {
  17065. const useFixedToolbarContainer = useFixedContainer(editor);
  17066. const bodyElement = () => SugarElement.fromDom(editor.getBody());
  17067. const contentAreaElement = () => SugarElement.fromDom(editor.getContentAreaContainer());
  17068. const lazyUseEditableAreaAnchor = () => useFixedToolbarContainer || !isToolbarTop();
  17069. return {
  17070. inlineDialog: getInlineDialogAnchor(contentAreaElement, lazyAnchorbar, lazyUseEditableAreaAnchor),
  17071. banner: getBannerAnchor(contentAreaElement, lazyAnchorbar, lazyUseEditableAreaAnchor),
  17072. cursor: getCursorAnchor(editor, bodyElement),
  17073. node: getNodeAnchor$1(bodyElement)
  17074. };
  17075. };
  17076. const colorPicker = editor => (callback, value) => {
  17077. const dialog = colorPickerDialog(editor);
  17078. dialog(callback, value);
  17079. };
  17080. const hasCustomColors = editor => () => hasCustomColors$1(editor);
  17081. const getColors = editor => id => getColors$2(editor, id);
  17082. const getColorCols = editor => id => getColorCols$1(editor, id);
  17083. const ColorInputBackstage = editor => ({
  17084. colorPicker: colorPicker(editor),
  17085. hasCustomColors: hasCustomColors(editor),
  17086. getColors: getColors(editor),
  17087. getColorCols: getColorCols(editor)
  17088. });
  17089. const isDraggableModal = editor => () => isDraggableModal$1(editor);
  17090. const DialogBackstage = editor => ({ isDraggableModal: isDraggableModal(editor) });
  17091. const HeaderBackstage = editor => {
  17092. const mode = Cell(isToolbarLocationBottom(editor) ? 'bottom' : 'top');
  17093. return {
  17094. isPositionedAtTop: () => mode.get() === 'top',
  17095. getDockingMode: mode.get,
  17096. setDockingMode: mode.set
  17097. };
  17098. };
  17099. const isNestedFormat = format => hasNonNullableKey(format, 'items');
  17100. const isFormatReference = format => hasNonNullableKey(format, 'format');
  17101. const defaultStyleFormats = [
  17102. {
  17103. title: 'Headings',
  17104. items: [
  17105. {
  17106. title: 'Heading 1',
  17107. format: 'h1'
  17108. },
  17109. {
  17110. title: 'Heading 2',
  17111. format: 'h2'
  17112. },
  17113. {
  17114. title: 'Heading 3',
  17115. format: 'h3'
  17116. },
  17117. {
  17118. title: 'Heading 4',
  17119. format: 'h4'
  17120. },
  17121. {
  17122. title: 'Heading 5',
  17123. format: 'h5'
  17124. },
  17125. {
  17126. title: 'Heading 6',
  17127. format: 'h6'
  17128. }
  17129. ]
  17130. },
  17131. {
  17132. title: 'Inline',
  17133. items: [
  17134. {
  17135. title: 'Bold',
  17136. format: 'bold'
  17137. },
  17138. {
  17139. title: 'Italic',
  17140. format: 'italic'
  17141. },
  17142. {
  17143. title: 'Underline',
  17144. format: 'underline'
  17145. },
  17146. {
  17147. title: 'Strikethrough',
  17148. format: 'strikethrough'
  17149. },
  17150. {
  17151. title: 'Superscript',
  17152. format: 'superscript'
  17153. },
  17154. {
  17155. title: 'Subscript',
  17156. format: 'subscript'
  17157. },
  17158. {
  17159. title: 'Code',
  17160. format: 'code'
  17161. }
  17162. ]
  17163. },
  17164. {
  17165. title: 'Blocks',
  17166. items: [
  17167. {
  17168. title: 'Paragraph',
  17169. format: 'p'
  17170. },
  17171. {
  17172. title: 'Blockquote',
  17173. format: 'blockquote'
  17174. },
  17175. {
  17176. title: 'Div',
  17177. format: 'div'
  17178. },
  17179. {
  17180. title: 'Pre',
  17181. format: 'pre'
  17182. }
  17183. ]
  17184. },
  17185. {
  17186. title: 'Align',
  17187. items: [
  17188. {
  17189. title: 'Left',
  17190. format: 'alignleft'
  17191. },
  17192. {
  17193. title: 'Center',
  17194. format: 'aligncenter'
  17195. },
  17196. {
  17197. title: 'Right',
  17198. format: 'alignright'
  17199. },
  17200. {
  17201. title: 'Justify',
  17202. format: 'alignjustify'
  17203. }
  17204. ]
  17205. }
  17206. ];
  17207. const isNestedFormats = format => has$2(format, 'items');
  17208. const isBlockFormat = format => has$2(format, 'block');
  17209. const isInlineFormat = format => has$2(format, 'inline');
  17210. const isSelectorFormat = format => has$2(format, 'selector');
  17211. const mapFormats = userFormats => foldl(userFormats, (acc, fmt) => {
  17212. if (isNestedFormats(fmt)) {
  17213. const result = mapFormats(fmt.items);
  17214. return {
  17215. customFormats: acc.customFormats.concat(result.customFormats),
  17216. formats: acc.formats.concat([{
  17217. title: fmt.title,
  17218. items: result.formats
  17219. }])
  17220. };
  17221. } else if (isInlineFormat(fmt) || isBlockFormat(fmt) || isSelectorFormat(fmt)) {
  17222. const formatName = isString(fmt.name) ? fmt.name : fmt.title.toLowerCase();
  17223. const formatNameWithPrefix = `custom-${ formatName }`;
  17224. return {
  17225. customFormats: acc.customFormats.concat([{
  17226. name: formatNameWithPrefix,
  17227. format: fmt
  17228. }]),
  17229. formats: acc.formats.concat([{
  17230. title: fmt.title,
  17231. format: formatNameWithPrefix,
  17232. icon: fmt.icon
  17233. }])
  17234. };
  17235. } else {
  17236. return {
  17237. ...acc,
  17238. formats: acc.formats.concat(fmt)
  17239. };
  17240. }
  17241. }, {
  17242. customFormats: [],
  17243. formats: []
  17244. });
  17245. const registerCustomFormats = (editor, userFormats) => {
  17246. const result = mapFormats(userFormats);
  17247. const registerFormats = customFormats => {
  17248. each$1(customFormats, fmt => {
  17249. if (!editor.formatter.has(fmt.name)) {
  17250. editor.formatter.register(fmt.name, fmt.format);
  17251. }
  17252. });
  17253. };
  17254. if (editor.formatter) {
  17255. registerFormats(result.customFormats);
  17256. } else {
  17257. editor.on('init', () => {
  17258. registerFormats(result.customFormats);
  17259. });
  17260. }
  17261. return result.formats;
  17262. };
  17263. const getStyleFormats = editor => getUserStyleFormats(editor).map(userFormats => {
  17264. const registeredUserFormats = registerCustomFormats(editor, userFormats);
  17265. return shouldMergeStyleFormats(editor) ? defaultStyleFormats.concat(registeredUserFormats) : registeredUserFormats;
  17266. }).getOr(defaultStyleFormats);
  17267. const isSeparator$1 = format => {
  17268. const keys$1 = keys(format);
  17269. return keys$1.length === 1 && contains$2(keys$1, 'title');
  17270. };
  17271. const processBasic = (item, isSelectedFor, getPreviewFor) => ({
  17272. ...item,
  17273. type: 'formatter',
  17274. isSelected: isSelectedFor(item.format),
  17275. getStylePreview: getPreviewFor(item.format)
  17276. });
  17277. const register$a = (editor, formats, isSelectedFor, getPreviewFor) => {
  17278. const enrichSupported = item => processBasic(item, isSelectedFor, getPreviewFor);
  17279. const enrichMenu = item => {
  17280. const newItems = doEnrich(item.items);
  17281. return {
  17282. ...item,
  17283. type: 'submenu',
  17284. getStyleItems: constant$1(newItems)
  17285. };
  17286. };
  17287. const enrichCustom = item => {
  17288. const formatName = isString(item.name) ? item.name : generate$6(item.title);
  17289. const formatNameWithPrefix = `custom-${ formatName }`;
  17290. const newItem = {
  17291. ...item,
  17292. type: 'formatter',
  17293. format: formatNameWithPrefix,
  17294. isSelected: isSelectedFor(formatNameWithPrefix),
  17295. getStylePreview: getPreviewFor(formatNameWithPrefix)
  17296. };
  17297. editor.formatter.register(formatName, newItem);
  17298. return newItem;
  17299. };
  17300. const doEnrich = items => map$2(items, item => {
  17301. if (isNestedFormat(item)) {
  17302. return enrichMenu(item);
  17303. } else if (isFormatReference(item)) {
  17304. return enrichSupported(item);
  17305. } else if (isSeparator$1(item)) {
  17306. return {
  17307. ...item,
  17308. type: 'separator'
  17309. };
  17310. } else {
  17311. return enrichCustom(item);
  17312. }
  17313. });
  17314. return doEnrich(formats);
  17315. };
  17316. const init$7 = editor => {
  17317. const isSelectedFor = format => () => editor.formatter.match(format);
  17318. const getPreviewFor = format => () => {
  17319. const fmt = editor.formatter.get(format);
  17320. return fmt !== undefined ? Optional.some({
  17321. tag: fmt.length > 0 ? fmt[0].inline || fmt[0].block || 'div' : 'div',
  17322. styles: editor.dom.parseStyle(editor.formatter.getCssText(format))
  17323. }) : Optional.none();
  17324. };
  17325. const settingsFormats = Cell([]);
  17326. const eventsFormats = Cell([]);
  17327. const replaceSettings = Cell(false);
  17328. editor.on('PreInit', _e => {
  17329. const formats = getStyleFormats(editor);
  17330. const enriched = register$a(editor, formats, isSelectedFor, getPreviewFor);
  17331. settingsFormats.set(enriched);
  17332. });
  17333. editor.on('addStyleModifications', e => {
  17334. const modifications = register$a(editor, e.items, isSelectedFor, getPreviewFor);
  17335. eventsFormats.set(modifications);
  17336. replaceSettings.set(e.replace);
  17337. });
  17338. const getData = () => {
  17339. const fromSettings = replaceSettings.get() ? [] : settingsFormats.get();
  17340. const fromEvents = eventsFormats.get();
  17341. return fromSettings.concat(fromEvents);
  17342. };
  17343. return { getData };
  17344. };
  17345. const isElement = node => isNonNullable(node) && node.nodeType === 1;
  17346. const trim = global$1.trim;
  17347. const hasContentEditableState = value => {
  17348. return node => {
  17349. if (isElement(node)) {
  17350. if (node.contentEditable === value) {
  17351. return true;
  17352. }
  17353. if (node.getAttribute('data-mce-contenteditable') === value) {
  17354. return true;
  17355. }
  17356. }
  17357. return false;
  17358. };
  17359. };
  17360. const isContentEditableTrue = hasContentEditableState('true');
  17361. const isContentEditableFalse = hasContentEditableState('false');
  17362. const create$1 = (type, title, url, level, attach) => ({
  17363. type,
  17364. title,
  17365. url,
  17366. level,
  17367. attach
  17368. });
  17369. const isChildOfContentEditableTrue = node => {
  17370. let tempNode = node;
  17371. while (tempNode = tempNode.parentNode) {
  17372. const value = tempNode.contentEditable;
  17373. if (value && value !== 'inherit') {
  17374. return isContentEditableTrue(tempNode);
  17375. }
  17376. }
  17377. return false;
  17378. };
  17379. const select = (selector, root) => {
  17380. return map$2(descendants(SugarElement.fromDom(root), selector), element => {
  17381. return element.dom;
  17382. });
  17383. };
  17384. const getElementText = elm => {
  17385. return elm.innerText || elm.textContent;
  17386. };
  17387. const getOrGenerateId = elm => {
  17388. return elm.id ? elm.id : generate$6('h');
  17389. };
  17390. const isAnchor = elm => {
  17391. return elm && elm.nodeName === 'A' && (elm.id || elm.name) !== undefined;
  17392. };
  17393. const isValidAnchor = elm => {
  17394. return isAnchor(elm) && isEditable(elm);
  17395. };
  17396. const isHeader = elm => {
  17397. return elm && /^(H[1-6])$/.test(elm.nodeName);
  17398. };
  17399. const isEditable = elm => {
  17400. return isChildOfContentEditableTrue(elm) && !isContentEditableFalse(elm);
  17401. };
  17402. const isValidHeader = elm => {
  17403. return isHeader(elm) && isEditable(elm);
  17404. };
  17405. const getLevel = elm => {
  17406. return isHeader(elm) ? parseInt(elm.nodeName.substr(1), 10) : 0;
  17407. };
  17408. const headerTarget = elm => {
  17409. var _a;
  17410. const headerId = getOrGenerateId(elm);
  17411. const attach = () => {
  17412. elm.id = headerId;
  17413. };
  17414. return create$1('header', (_a = getElementText(elm)) !== null && _a !== void 0 ? _a : '', '#' + headerId, getLevel(elm), attach);
  17415. };
  17416. const anchorTarget = elm => {
  17417. const anchorId = elm.id || elm.name;
  17418. const anchorText = getElementText(elm);
  17419. return create$1('anchor', anchorText ? anchorText : '#' + anchorId, '#' + anchorId, 0, noop);
  17420. };
  17421. const getHeaderTargets = elms => {
  17422. return map$2(filter$2(elms, isValidHeader), headerTarget);
  17423. };
  17424. const getAnchorTargets = elms => {
  17425. return map$2(filter$2(elms, isValidAnchor), anchorTarget);
  17426. };
  17427. const getTargetElements = elm => {
  17428. const elms = select('h1,h2,h3,h4,h5,h6,a:not([href])', elm);
  17429. return elms;
  17430. };
  17431. const hasTitle = target => {
  17432. return trim(target.title).length > 0;
  17433. };
  17434. const find = elm => {
  17435. const elms = getTargetElements(elm);
  17436. return filter$2(getHeaderTargets(elms).concat(getAnchorTargets(elms)), hasTitle);
  17437. };
  17438. const LinkTargets = { find };
  17439. const STORAGE_KEY = 'tinymce-url-history';
  17440. const HISTORY_LENGTH = 5;
  17441. const isHttpUrl = url => isString(url) && /^https?/.test(url);
  17442. const isArrayOfUrl = a => isArray(a) && a.length <= HISTORY_LENGTH && forall(a, isHttpUrl);
  17443. const isRecordOfUrlArray = r => isObject(r) && find$4(r, value => !isArrayOfUrl(value)).isNone();
  17444. const getAllHistory = () => {
  17445. const unparsedHistory = global$4.getItem(STORAGE_KEY);
  17446. if (unparsedHistory === null) {
  17447. return {};
  17448. }
  17449. let history;
  17450. try {
  17451. history = JSON.parse(unparsedHistory);
  17452. } catch (e) {
  17453. if (e instanceof SyntaxError) {
  17454. console.log('Local storage ' + STORAGE_KEY + ' was not valid JSON', e);
  17455. return {};
  17456. }
  17457. throw e;
  17458. }
  17459. if (!isRecordOfUrlArray(history)) {
  17460. console.log('Local storage ' + STORAGE_KEY + ' was not valid format', history);
  17461. return {};
  17462. }
  17463. return history;
  17464. };
  17465. const setAllHistory = history => {
  17466. if (!isRecordOfUrlArray(history)) {
  17467. throw new Error('Bad format for history:\n' + JSON.stringify(history));
  17468. }
  17469. global$4.setItem(STORAGE_KEY, JSON.stringify(history));
  17470. };
  17471. const getHistory = fileType => {
  17472. const history = getAllHistory();
  17473. return get$g(history, fileType).getOr([]);
  17474. };
  17475. const addToHistory = (url, fileType) => {
  17476. if (!isHttpUrl(url)) {
  17477. return;
  17478. }
  17479. const history = getAllHistory();
  17480. const items = get$g(history, fileType).getOr([]);
  17481. const itemsWithoutUrl = filter$2(items, item => item !== url);
  17482. history[fileType] = [url].concat(itemsWithoutUrl).slice(0, HISTORY_LENGTH);
  17483. setAllHistory(history);
  17484. };
  17485. const isTruthy = value => !!value;
  17486. const makeMap = value => map$1(global$1.makeMap(value, /[, ]/), isTruthy);
  17487. const getPicker = editor => Optional.from(getFilePickerCallback(editor));
  17488. const getPickerTypes = editor => {
  17489. const optFileTypes = Optional.from(getFilePickerTypes(editor)).filter(isTruthy).map(makeMap);
  17490. return getPicker(editor).fold(never, _picker => optFileTypes.fold(always, types => keys(types).length > 0 ? types : false));
  17491. };
  17492. const getPickerSetting = (editor, filetype) => {
  17493. const pickerTypes = getPickerTypes(editor);
  17494. if (isBoolean(pickerTypes)) {
  17495. return pickerTypes ? getPicker(editor) : Optional.none();
  17496. } else {
  17497. return pickerTypes[filetype] ? getPicker(editor) : Optional.none();
  17498. }
  17499. };
  17500. const getUrlPicker = (editor, filetype) => getPickerSetting(editor, filetype).map(picker => entry => Future.nu(completer => {
  17501. const handler = (value, meta) => {
  17502. if (!isString(value)) {
  17503. throw new Error('Expected value to be string');
  17504. }
  17505. if (meta !== undefined && !isObject(meta)) {
  17506. throw new Error('Expected meta to be a object');
  17507. }
  17508. const r = {
  17509. value,
  17510. meta
  17511. };
  17512. completer(r);
  17513. };
  17514. const meta = {
  17515. filetype,
  17516. fieldname: entry.fieldname,
  17517. ...Optional.from(entry.meta).getOr({})
  17518. };
  17519. picker.call(editor, handler, entry.value, meta);
  17520. }));
  17521. const getTextSetting = value => Optional.from(value).filter(isString).getOrUndefined();
  17522. const getLinkInformation = editor => {
  17523. if (!useTypeaheadUrls(editor)) {
  17524. return Optional.none();
  17525. }
  17526. return Optional.some({
  17527. targets: LinkTargets.find(editor.getBody()),
  17528. anchorTop: getTextSetting(getAnchorTop(editor)),
  17529. anchorBottom: getTextSetting(getAnchorBottom(editor))
  17530. });
  17531. };
  17532. const getValidationHandler = editor => Optional.from(getFilePickerValidatorHandler(editor));
  17533. const UrlInputBackstage = editor => ({
  17534. getHistory,
  17535. addToHistory,
  17536. getLinkInformation: () => getLinkInformation(editor),
  17537. getValidationHandler: () => getValidationHandler(editor),
  17538. getUrlPicker: filetype => getUrlPicker(editor, filetype)
  17539. });
  17540. const init$6 = (lazySinks, editor, lazyAnchorbar) => {
  17541. const contextMenuState = Cell(false);
  17542. const toolbar = HeaderBackstage(editor);
  17543. const providers = {
  17544. icons: () => editor.ui.registry.getAll().icons,
  17545. menuItems: () => editor.ui.registry.getAll().menuItems,
  17546. translate: global$8.translate,
  17547. isDisabled: () => editor.mode.isReadOnly() || !editor.ui.isEnabled(),
  17548. getOption: editor.options.get
  17549. };
  17550. const urlinput = UrlInputBackstage(editor);
  17551. const styles = init$7(editor);
  17552. const colorinput = ColorInputBackstage(editor);
  17553. const dialogSettings = DialogBackstage(editor);
  17554. const isContextMenuOpen = () => contextMenuState.get();
  17555. const setContextMenuState = state => contextMenuState.set(state);
  17556. const commonBackstage = {
  17557. shared: {
  17558. providers,
  17559. anchors: getAnchors(editor, lazyAnchorbar, toolbar.isPositionedAtTop),
  17560. header: toolbar
  17561. },
  17562. urlinput,
  17563. styles,
  17564. colorinput,
  17565. dialog: dialogSettings,
  17566. isContextMenuOpen,
  17567. setContextMenuState
  17568. };
  17569. const popupBackstage = {
  17570. ...commonBackstage,
  17571. shared: {
  17572. ...commonBackstage.shared,
  17573. interpreter: s => interpretWithoutForm(s, {}, popupBackstage),
  17574. getSink: lazySinks.popup
  17575. }
  17576. };
  17577. const dialogBackstage = {
  17578. ...commonBackstage,
  17579. shared: {
  17580. ...commonBackstage.shared,
  17581. interpreter: s => interpretWithoutForm(s, {}, dialogBackstage),
  17582. getSink: lazySinks.dialog
  17583. }
  17584. };
  17585. return {
  17586. popup: popupBackstage,
  17587. dialog: dialogBackstage
  17588. };
  17589. };
  17590. const setup$b = (editor, mothership, uiMotherships) => {
  17591. const broadcastEvent = (name, evt) => {
  17592. each$1([
  17593. mothership,
  17594. ...uiMotherships
  17595. ], m => {
  17596. m.broadcastEvent(name, evt);
  17597. });
  17598. };
  17599. const broadcastOn = (channel, message) => {
  17600. each$1([
  17601. mothership,
  17602. ...uiMotherships
  17603. ], m => {
  17604. m.broadcastOn([channel], message);
  17605. });
  17606. };
  17607. const fireDismissPopups = evt => broadcastOn(dismissPopups(), { target: evt.target });
  17608. const doc = getDocument();
  17609. const onTouchstart = bind(doc, 'touchstart', fireDismissPopups);
  17610. const onTouchmove = bind(doc, 'touchmove', evt => broadcastEvent(documentTouchmove(), evt));
  17611. const onTouchend = bind(doc, 'touchend', evt => broadcastEvent(documentTouchend(), evt));
  17612. const onMousedown = bind(doc, 'mousedown', fireDismissPopups);
  17613. const onMouseup = bind(doc, 'mouseup', evt => {
  17614. if (evt.raw.button === 0) {
  17615. broadcastOn(mouseReleased(), { target: evt.target });
  17616. }
  17617. });
  17618. const onContentClick = raw => broadcastOn(dismissPopups(), { target: SugarElement.fromDom(raw.target) });
  17619. const onContentMouseup = raw => {
  17620. if (raw.button === 0) {
  17621. broadcastOn(mouseReleased(), { target: SugarElement.fromDom(raw.target) });
  17622. }
  17623. };
  17624. const onContentMousedown = () => {
  17625. each$1(editor.editorManager.get(), loopEditor => {
  17626. if (editor !== loopEditor) {
  17627. loopEditor.dispatch('DismissPopups', { relatedTarget: editor });
  17628. }
  17629. });
  17630. };
  17631. const onWindowScroll = evt => broadcastEvent(windowScroll(), fromRawEvent(evt));
  17632. const onWindowResize = evt => {
  17633. broadcastOn(repositionPopups(), {});
  17634. broadcastEvent(windowResize(), fromRawEvent(evt));
  17635. };
  17636. const dos = getRootNode(SugarElement.fromDom(editor.getElement()));
  17637. const onElementScroll = capture(dos, 'scroll', evt => {
  17638. requestAnimationFrame(() => {
  17639. const c = editor.getContainer();
  17640. if (c !== undefined && c !== null) {
  17641. const optScrollingContext = detectWhenSplitUiMode(editor, mothership.element);
  17642. const scrollers = optScrollingContext.map(sc => [
  17643. sc.element,
  17644. ...sc.others
  17645. ]).getOr([]);
  17646. if (exists(scrollers, s => eq(s, evt.target))) {
  17647. editor.dispatch('ElementScroll', { target: evt.target.dom });
  17648. broadcastEvent(externalElementScroll(), evt);
  17649. }
  17650. }
  17651. });
  17652. });
  17653. const onEditorResize = () => broadcastOn(repositionPopups(), {});
  17654. const onEditorProgress = evt => {
  17655. if (evt.state) {
  17656. broadcastOn(dismissPopups(), { target: SugarElement.fromDom(editor.getContainer()) });
  17657. }
  17658. };
  17659. const onDismissPopups = event => {
  17660. broadcastOn(dismissPopups(), { target: SugarElement.fromDom(event.relatedTarget.getContainer()) });
  17661. };
  17662. editor.on('PostRender', () => {
  17663. editor.on('click', onContentClick);
  17664. editor.on('tap', onContentClick);
  17665. editor.on('mouseup', onContentMouseup);
  17666. editor.on('mousedown', onContentMousedown);
  17667. editor.on('ScrollWindow', onWindowScroll);
  17668. editor.on('ResizeWindow', onWindowResize);
  17669. editor.on('ResizeEditor', onEditorResize);
  17670. editor.on('AfterProgressState', onEditorProgress);
  17671. editor.on('DismissPopups', onDismissPopups);
  17672. });
  17673. editor.on('remove', () => {
  17674. editor.off('click', onContentClick);
  17675. editor.off('tap', onContentClick);
  17676. editor.off('mouseup', onContentMouseup);
  17677. editor.off('mousedown', onContentMousedown);
  17678. editor.off('ScrollWindow', onWindowScroll);
  17679. editor.off('ResizeWindow', onWindowResize);
  17680. editor.off('ResizeEditor', onEditorResize);
  17681. editor.off('AfterProgressState', onEditorProgress);
  17682. editor.off('DismissPopups', onDismissPopups);
  17683. onMousedown.unbind();
  17684. onTouchstart.unbind();
  17685. onTouchmove.unbind();
  17686. onTouchend.unbind();
  17687. onMouseup.unbind();
  17688. onElementScroll.unbind();
  17689. });
  17690. editor.on('detach', () => {
  17691. each$1([
  17692. mothership,
  17693. ...uiMotherships
  17694. ], detachSystem);
  17695. each$1([
  17696. mothership,
  17697. ...uiMotherships
  17698. ], m => m.destroy());
  17699. });
  17700. };
  17701. const parts$a = AlloyParts;
  17702. const partType = PartType;
  17703. const schema$f = constant$1([
  17704. defaulted('shell', false),
  17705. required$1('makeItem'),
  17706. defaulted('setupItem', noop),
  17707. SketchBehaviours.field('listBehaviours', [Replacing])
  17708. ]);
  17709. const customListDetail = () => ({ behaviours: derive$1([Replacing.config({})]) });
  17710. const itemsPart = optional({
  17711. name: 'items',
  17712. overrides: customListDetail
  17713. });
  17714. const parts$9 = constant$1([itemsPart]);
  17715. const name = constant$1('CustomList');
  17716. const factory$f = (detail, components, _spec, _external) => {
  17717. const setItems = (list, items) => {
  17718. getListContainer(list).fold(() => {
  17719. console.error('Custom List was defined to not be a shell, but no item container was specified in components');
  17720. throw new Error('Custom List was defined to not be a shell, but no item container was specified in components');
  17721. }, container => {
  17722. const itemComps = Replacing.contents(container);
  17723. const numListsRequired = items.length;
  17724. const numListsToAdd = numListsRequired - itemComps.length;
  17725. const itemsToAdd = numListsToAdd > 0 ? range$2(numListsToAdd, () => detail.makeItem()) : [];
  17726. const itemsToRemove = itemComps.slice(numListsRequired);
  17727. each$1(itemsToRemove, item => Replacing.remove(container, item));
  17728. each$1(itemsToAdd, item => Replacing.append(container, item));
  17729. const builtLists = Replacing.contents(container);
  17730. each$1(builtLists, (item, i) => {
  17731. detail.setupItem(list, item, items[i], i);
  17732. });
  17733. });
  17734. };
  17735. const extra = detail.shell ? {
  17736. behaviours: [Replacing.config({})],
  17737. components: []
  17738. } : {
  17739. behaviours: [],
  17740. components
  17741. };
  17742. const getListContainer = component => detail.shell ? Optional.some(component) : getPart(component, detail, 'items');
  17743. return {
  17744. uid: detail.uid,
  17745. dom: detail.dom,
  17746. components: extra.components,
  17747. behaviours: augment(detail.listBehaviours, extra.behaviours),
  17748. apis: { setItems }
  17749. };
  17750. };
  17751. const CustomList = composite({
  17752. name: name(),
  17753. configFields: schema$f(),
  17754. partFields: parts$9(),
  17755. factory: factory$f,
  17756. apis: {
  17757. setItems: (apis, list, items) => {
  17758. apis.setItems(list, items);
  17759. }
  17760. }
  17761. });
  17762. const schema$e = constant$1([
  17763. required$1('dom'),
  17764. defaulted('shell', true),
  17765. field('toolbarBehaviours', [Replacing])
  17766. ]);
  17767. const enhanceGroups = () => ({ behaviours: derive$1([Replacing.config({})]) });
  17768. const parts$8 = constant$1([optional({
  17769. name: 'groups',
  17770. overrides: enhanceGroups
  17771. })]);
  17772. const factory$e = (detail, components, _spec, _externals) => {
  17773. const setGroups = (toolbar, groups) => {
  17774. getGroupContainer(toolbar).fold(() => {
  17775. console.error('Toolbar was defined to not be a shell, but no groups container was specified in components');
  17776. throw new Error('Toolbar was defined to not be a shell, but no groups container was specified in components');
  17777. }, container => {
  17778. Replacing.set(container, groups);
  17779. });
  17780. };
  17781. const getGroupContainer = component => detail.shell ? Optional.some(component) : getPart(component, detail, 'groups');
  17782. const extra = detail.shell ? {
  17783. behaviours: [Replacing.config({})],
  17784. components: []
  17785. } : {
  17786. behaviours: [],
  17787. components
  17788. };
  17789. return {
  17790. uid: detail.uid,
  17791. dom: detail.dom,
  17792. components: extra.components,
  17793. behaviours: augment(detail.toolbarBehaviours, extra.behaviours),
  17794. apis: { setGroups },
  17795. domModification: { attributes: { role: 'group' } }
  17796. };
  17797. };
  17798. const Toolbar = composite({
  17799. name: 'Toolbar',
  17800. configFields: schema$e(),
  17801. partFields: parts$8(),
  17802. factory: factory$e,
  17803. apis: {
  17804. setGroups: (apis, toolbar, groups) => {
  17805. apis.setGroups(toolbar, groups);
  17806. }
  17807. }
  17808. });
  17809. const setup$a = noop;
  17810. const isDocked$2 = never;
  17811. const getBehaviours$1 = constant$1([]);
  17812. var StaticHeader = /*#__PURE__*/Object.freeze({
  17813. __proto__: null,
  17814. setup: setup$a,
  17815. isDocked: isDocked$2,
  17816. getBehaviours: getBehaviours$1
  17817. });
  17818. const getOffsetParent = element => {
  17819. const isFixed = is$1(getRaw(element, 'position'), 'fixed');
  17820. const offsetParent$1 = isFixed ? Optional.none() : offsetParent(element);
  17821. return offsetParent$1.orThunk(() => {
  17822. const marker = SugarElement.fromTag('span');
  17823. return parent(element).bind(parent => {
  17824. append$2(parent, marker);
  17825. const offsetParent$1 = offsetParent(marker);
  17826. remove$5(marker);
  17827. return offsetParent$1;
  17828. });
  17829. });
  17830. };
  17831. const getOrigin = element => getOffsetParent(element).map(absolute$3).getOrThunk(() => SugarPosition(0, 0));
  17832. const appear = (component, contextualInfo) => {
  17833. const elem = component.element;
  17834. add$2(elem, contextualInfo.transitionClass);
  17835. remove$2(elem, contextualInfo.fadeOutClass);
  17836. add$2(elem, contextualInfo.fadeInClass);
  17837. contextualInfo.onShow(component);
  17838. };
  17839. const disappear = (component, contextualInfo) => {
  17840. const elem = component.element;
  17841. add$2(elem, contextualInfo.transitionClass);
  17842. remove$2(elem, contextualInfo.fadeInClass);
  17843. add$2(elem, contextualInfo.fadeOutClass);
  17844. contextualInfo.onHide(component);
  17845. };
  17846. const isPartiallyVisible = (box, bounds) => box.y < bounds.bottom && box.bottom > bounds.y;
  17847. const isTopCompletelyVisible = (box, bounds) => box.y >= bounds.y;
  17848. const isBottomCompletelyVisible = (box, bounds) => box.bottom <= bounds.bottom;
  17849. const forceTopPosition = (winBox, leftX, viewport) => ({
  17850. location: 'top',
  17851. leftX,
  17852. topY: viewport.bounds.y - winBox.y
  17853. });
  17854. const forceBottomPosition = (winBox, leftX, viewport) => ({
  17855. location: 'bottom',
  17856. leftX,
  17857. bottomY: winBox.bottom - viewport.bounds.bottom
  17858. });
  17859. const getDockedLeftPosition = bounds => {
  17860. return bounds.box.x - bounds.win.x;
  17861. };
  17862. const tryDockingPosition = (modes, bounds, viewport) => {
  17863. const winBox = bounds.win;
  17864. const box = bounds.box;
  17865. const leftX = getDockedLeftPosition(bounds);
  17866. return findMap(modes, mode => {
  17867. switch (mode) {
  17868. case 'bottom':
  17869. return !isBottomCompletelyVisible(box, viewport.bounds) ? Optional.some(forceBottomPosition(winBox, leftX, viewport)) : Optional.none();
  17870. case 'top':
  17871. return !isTopCompletelyVisible(box, viewport.bounds) ? Optional.some(forceTopPosition(winBox, leftX, viewport)) : Optional.none();
  17872. default:
  17873. return Optional.none();
  17874. }
  17875. }).getOr({ location: 'no-dock' });
  17876. };
  17877. const isVisibleForModes = (modes, box, viewport) => forall(modes, mode => {
  17878. switch (mode) {
  17879. case 'bottom':
  17880. return isBottomCompletelyVisible(box, viewport.bounds);
  17881. case 'top':
  17882. return isTopCompletelyVisible(box, viewport.bounds);
  17883. }
  17884. });
  17885. const getXYForRestoring = (pos, viewport) => {
  17886. const priorY = viewport.optScrollEnv.fold(constant$1(pos.bounds.y), scrollEnv => scrollEnv.scrollElmTop + (pos.bounds.y - scrollEnv.currentScrollTop));
  17887. return SugarPosition(pos.bounds.x, priorY);
  17888. };
  17889. const getXYForSaving = (box, viewport) => {
  17890. const priorY = viewport.optScrollEnv.fold(constant$1(box.y), scrollEnv => box.y + scrollEnv.currentScrollTop - scrollEnv.scrollElmTop);
  17891. return SugarPosition(box.x, priorY);
  17892. };
  17893. const getPrior = (elem, viewport, state) => state.getInitialPos().map(pos => {
  17894. const xy = getXYForRestoring(pos, viewport);
  17895. return {
  17896. box: bounds(xy.left, xy.top, get$c(elem), get$d(elem)),
  17897. location: pos.location
  17898. };
  17899. });
  17900. const storePrior = (elem, box, viewport, state, decision) => {
  17901. const xy = getXYForSaving(box, viewport);
  17902. const bounds$1 = bounds(xy.left, xy.top, box.width, box.height);
  17903. state.setInitialPos({
  17904. style: getAllRaw(elem),
  17905. position: get$e(elem, 'position') || 'static',
  17906. bounds: bounds$1,
  17907. location: decision.location
  17908. });
  17909. };
  17910. const storePriorIfNone = (elem, box, viewport, state, decision) => {
  17911. state.getInitialPos().fold(() => storePrior(elem, box, viewport, state, decision), () => noop);
  17912. };
  17913. const revertToOriginal = (elem, box, state) => state.getInitialPos().bind(position => {
  17914. var _a;
  17915. state.clearInitialPos();
  17916. switch (position.position) {
  17917. case 'static':
  17918. return Optional.some({ morph: 'static' });
  17919. case 'absolute':
  17920. const offsetParent = getOffsetParent(elem).getOr(body());
  17921. const offsetBox = box$1(offsetParent);
  17922. const scrollDelta = (_a = offsetParent.dom.scrollTop) !== null && _a !== void 0 ? _a : 0;
  17923. return Optional.some({
  17924. morph: 'absolute',
  17925. positionCss: NuPositionCss('absolute', get$g(position.style, 'left').map(_left => box.x - offsetBox.x), get$g(position.style, 'top').map(_top => box.y - offsetBox.y + scrollDelta), get$g(position.style, 'right').map(_right => offsetBox.right - box.right), get$g(position.style, 'bottom').map(_bottom => offsetBox.bottom - box.bottom))
  17926. });
  17927. default:
  17928. return Optional.none();
  17929. }
  17930. });
  17931. const tryMorphToOriginal = (elem, viewport, state) => getPrior(elem, viewport, state).filter(({box}) => isVisibleForModes(state.getModes(), box, viewport)).bind(({box}) => revertToOriginal(elem, box, state));
  17932. const tryDecisionToFixedMorph = decision => {
  17933. switch (decision.location) {
  17934. case 'top': {
  17935. return Optional.some({
  17936. morph: 'fixed',
  17937. positionCss: NuPositionCss('fixed', Optional.some(decision.leftX), Optional.some(decision.topY), Optional.none(), Optional.none())
  17938. });
  17939. }
  17940. case 'bottom': {
  17941. return Optional.some({
  17942. morph: 'fixed',
  17943. positionCss: NuPositionCss('fixed', Optional.some(decision.leftX), Optional.none(), Optional.none(), Optional.some(decision.bottomY))
  17944. });
  17945. }
  17946. default:
  17947. return Optional.none();
  17948. }
  17949. };
  17950. const tryMorphToFixed = (elem, viewport, state) => {
  17951. const box = box$1(elem);
  17952. const winBox = win();
  17953. const decision = tryDockingPosition(state.getModes(), {
  17954. win: winBox,
  17955. box
  17956. }, viewport);
  17957. if (decision.location === 'top' || decision.location === 'bottom') {
  17958. storePrior(elem, box, viewport, state, decision);
  17959. return tryDecisionToFixedMorph(decision);
  17960. } else {
  17961. return Optional.none();
  17962. }
  17963. };
  17964. const tryMorphToOriginalOrUpdateFixed = (elem, viewport, state) => {
  17965. return tryMorphToOriginal(elem, viewport, state).orThunk(() => {
  17966. return viewport.optScrollEnv.bind(_ => getPrior(elem, viewport, state)).bind(({box, location}) => {
  17967. const winBox = win();
  17968. const leftX = getDockedLeftPosition({
  17969. win: winBox,
  17970. box
  17971. });
  17972. const decision = location === 'top' ? forceTopPosition(winBox, leftX, viewport) : forceBottomPosition(winBox, leftX, viewport);
  17973. return tryDecisionToFixedMorph(decision);
  17974. });
  17975. });
  17976. };
  17977. const tryMorph = (component, viewport, state) => {
  17978. const elem = component.element;
  17979. const isDocked = is$1(getRaw(elem, 'position'), 'fixed');
  17980. return isDocked ? tryMorphToOriginalOrUpdateFixed(elem, viewport, state) : tryMorphToFixed(elem, viewport, state);
  17981. };
  17982. const calculateMorphToOriginal = (component, viewport, state) => {
  17983. const elem = component.element;
  17984. return getPrior(elem, viewport, state).bind(({box}) => revertToOriginal(elem, box, state));
  17985. };
  17986. const forceDockWith = (elem, viewport, state, getDecision) => {
  17987. const box = box$1(elem);
  17988. const winBox = win();
  17989. const leftX = getDockedLeftPosition({
  17990. win: winBox,
  17991. box
  17992. });
  17993. const decision = getDecision(winBox, leftX, viewport);
  17994. if (decision.location === 'bottom' || decision.location === 'top') {
  17995. storePriorIfNone(elem, box, viewport, state, decision);
  17996. return tryDecisionToFixedMorph(decision);
  17997. } else {
  17998. return Optional.none();
  17999. }
  18000. };
  18001. const morphToStatic = (component, config, state) => {
  18002. state.setDocked(false);
  18003. each$1([
  18004. 'left',
  18005. 'right',
  18006. 'top',
  18007. 'bottom',
  18008. 'position'
  18009. ], prop => remove$6(component.element, prop));
  18010. config.onUndocked(component);
  18011. };
  18012. const morphToCoord = (component, config, state, position) => {
  18013. const isDocked = position.position === 'fixed';
  18014. state.setDocked(isDocked);
  18015. applyPositionCss(component.element, position);
  18016. const method = isDocked ? config.onDocked : config.onUndocked;
  18017. method(component);
  18018. };
  18019. const updateVisibility = (component, config, state, viewport, morphToDocked = false) => {
  18020. config.contextual.each(contextInfo => {
  18021. contextInfo.lazyContext(component).each(box => {
  18022. const isVisible = isPartiallyVisible(box, viewport.bounds);
  18023. if (isVisible !== state.isVisible()) {
  18024. state.setVisible(isVisible);
  18025. if (morphToDocked && !isVisible) {
  18026. add$1(component.element, [contextInfo.fadeOutClass]);
  18027. contextInfo.onHide(component);
  18028. } else {
  18029. const method = isVisible ? appear : disappear;
  18030. method(component, contextInfo);
  18031. }
  18032. }
  18033. });
  18034. });
  18035. };
  18036. const applyFixedMorph = (component, config, state, viewport, morph) => {
  18037. updateVisibility(component, config, state, viewport, true);
  18038. morphToCoord(component, config, state, morph.positionCss);
  18039. };
  18040. const applyMorph = (component, config, state, viewport, morph) => {
  18041. switch (morph.morph) {
  18042. case 'static': {
  18043. return morphToStatic(component, config, state);
  18044. }
  18045. case 'absolute': {
  18046. return morphToCoord(component, config, state, morph.positionCss);
  18047. }
  18048. case 'fixed': {
  18049. return applyFixedMorph(component, config, state, viewport, morph);
  18050. }
  18051. }
  18052. };
  18053. const refreshInternal = (component, config, state) => {
  18054. const viewport = config.lazyViewport(component);
  18055. updateVisibility(component, config, state, viewport);
  18056. tryMorph(component, viewport, state).each(morph => {
  18057. applyMorph(component, config, state, viewport, morph);
  18058. });
  18059. };
  18060. const resetInternal = (component, config, state) => {
  18061. const elem = component.element;
  18062. state.setDocked(false);
  18063. const viewport = config.lazyViewport(component);
  18064. calculateMorphToOriginal(component, viewport, state).each(staticOrAbsoluteMorph => {
  18065. switch (staticOrAbsoluteMorph.morph) {
  18066. case 'static': {
  18067. morphToStatic(component, config, state);
  18068. break;
  18069. }
  18070. case 'absolute': {
  18071. morphToCoord(component, config, state, staticOrAbsoluteMorph.positionCss);
  18072. break;
  18073. }
  18074. }
  18075. });
  18076. state.setVisible(true);
  18077. config.contextual.each(contextInfo => {
  18078. remove$1(elem, [
  18079. contextInfo.fadeInClass,
  18080. contextInfo.fadeOutClass,
  18081. contextInfo.transitionClass
  18082. ]);
  18083. contextInfo.onShow(component);
  18084. });
  18085. refresh$3(component, config, state);
  18086. };
  18087. const refresh$3 = (component, config, state) => {
  18088. if (component.getSystem().isConnected()) {
  18089. refreshInternal(component, config, state);
  18090. }
  18091. };
  18092. const reset = (component, config, state) => {
  18093. if (state.isDocked()) {
  18094. resetInternal(component, config, state);
  18095. }
  18096. };
  18097. const forceDockWithDecision = getDecision => (component, config, state) => {
  18098. const viewport = config.lazyViewport(component);
  18099. const optMorph = forceDockWith(component.element, viewport, state, getDecision);
  18100. optMorph.each(morph => {
  18101. applyFixedMorph(component, config, state, viewport, morph);
  18102. });
  18103. };
  18104. const forceDockToTop = forceDockWithDecision(forceTopPosition);
  18105. const forceDockToBottom = forceDockWithDecision(forceBottomPosition);
  18106. const isDocked$1 = (component, config, state) => state.isDocked();
  18107. const setModes = (component, config, state, modes) => state.setModes(modes);
  18108. const getModes = (component, config, state) => state.getModes();
  18109. var DockingApis = /*#__PURE__*/Object.freeze({
  18110. __proto__: null,
  18111. refresh: refresh$3,
  18112. reset: reset,
  18113. isDocked: isDocked$1,
  18114. getModes: getModes,
  18115. setModes: setModes,
  18116. forceDockToTop: forceDockToTop,
  18117. forceDockToBottom: forceDockToBottom
  18118. });
  18119. const events$4 = (dockInfo, dockState) => derive$2([
  18120. runOnSource(transitionend(), (component, simulatedEvent) => {
  18121. dockInfo.contextual.each(contextInfo => {
  18122. if (has(component.element, contextInfo.transitionClass)) {
  18123. remove$1(component.element, [
  18124. contextInfo.transitionClass,
  18125. contextInfo.fadeInClass
  18126. ]);
  18127. const notify = dockState.isVisible() ? contextInfo.onShown : contextInfo.onHidden;
  18128. notify(component);
  18129. }
  18130. simulatedEvent.stop();
  18131. });
  18132. }),
  18133. run$1(windowScroll(), (component, _) => {
  18134. refresh$3(component, dockInfo, dockState);
  18135. }),
  18136. run$1(externalElementScroll(), (component, _) => {
  18137. refresh$3(component, dockInfo, dockState);
  18138. }),
  18139. run$1(windowResize(), (component, _) => {
  18140. reset(component, dockInfo, dockState);
  18141. })
  18142. ]);
  18143. var ActiveDocking = /*#__PURE__*/Object.freeze({
  18144. __proto__: null,
  18145. events: events$4
  18146. });
  18147. var DockingSchema = [
  18148. optionObjOf('contextual', [
  18149. requiredString('fadeInClass'),
  18150. requiredString('fadeOutClass'),
  18151. requiredString('transitionClass'),
  18152. requiredFunction('lazyContext'),
  18153. onHandler('onShow'),
  18154. onHandler('onShown'),
  18155. onHandler('onHide'),
  18156. onHandler('onHidden')
  18157. ]),
  18158. defaultedFunction('lazyViewport', () => ({
  18159. bounds: win(),
  18160. optScrollEnv: Optional.none()
  18161. })),
  18162. defaultedArrayOf('modes', [
  18163. 'top',
  18164. 'bottom'
  18165. ], string),
  18166. onHandler('onDocked'),
  18167. onHandler('onUndocked')
  18168. ];
  18169. const init$5 = spec => {
  18170. const docked = Cell(false);
  18171. const visible = Cell(true);
  18172. const initialBounds = value$2();
  18173. const modes = Cell(spec.modes);
  18174. const readState = () => `docked: ${ docked.get() }, visible: ${ visible.get() }, modes: ${ modes.get().join(',') }`;
  18175. return nu$8({
  18176. isDocked: docked.get,
  18177. setDocked: docked.set,
  18178. getInitialPos: initialBounds.get,
  18179. setInitialPos: initialBounds.set,
  18180. clearInitialPos: initialBounds.clear,
  18181. isVisible: visible.get,
  18182. setVisible: visible.set,
  18183. getModes: modes.get,
  18184. setModes: modes.set,
  18185. readState
  18186. });
  18187. };
  18188. var DockingState = /*#__PURE__*/Object.freeze({
  18189. __proto__: null,
  18190. init: init$5
  18191. });
  18192. const Docking = create$4({
  18193. fields: DockingSchema,
  18194. name: 'docking',
  18195. active: ActiveDocking,
  18196. apis: DockingApis,
  18197. state: DockingState
  18198. });
  18199. const toolbarHeightChange = constant$1(generate$6('toolbar-height-change'));
  18200. const visibility = {
  18201. fadeInClass: 'tox-editor-dock-fadein',
  18202. fadeOutClass: 'tox-editor-dock-fadeout',
  18203. transitionClass: 'tox-editor-dock-transition'
  18204. };
  18205. const editorStickyOnClass = 'tox-tinymce--toolbar-sticky-on';
  18206. const editorStickyOffClass = 'tox-tinymce--toolbar-sticky-off';
  18207. const scrollFromBehindHeader = (e, containerHeader) => {
  18208. const doc = owner$4(containerHeader);
  18209. const win = defaultView(containerHeader);
  18210. const viewHeight = win.dom.innerHeight;
  18211. const scrollPos = get$b(doc);
  18212. const markerElement = SugarElement.fromDom(e.elm);
  18213. const markerPos = absolute$2(markerElement);
  18214. const markerHeight = get$d(markerElement);
  18215. const markerTop = markerPos.y;
  18216. const markerBottom = markerTop + markerHeight;
  18217. const editorHeaderPos = absolute$3(containerHeader);
  18218. const editorHeaderHeight = get$d(containerHeader);
  18219. const editorHeaderTop = editorHeaderPos.top;
  18220. const editorHeaderBottom = editorHeaderTop + editorHeaderHeight;
  18221. const editorHeaderDockedAtTop = Math.abs(editorHeaderTop - scrollPos.top) < 2;
  18222. const editorHeaderDockedAtBottom = Math.abs(editorHeaderBottom - (scrollPos.top + viewHeight)) < 2;
  18223. if (editorHeaderDockedAtTop && markerTop < editorHeaderBottom) {
  18224. to(scrollPos.left, markerTop - editorHeaderHeight, doc);
  18225. } else if (editorHeaderDockedAtBottom && markerBottom > editorHeaderTop) {
  18226. const y = markerTop - viewHeight + markerHeight + editorHeaderHeight;
  18227. to(scrollPos.left, y, doc);
  18228. }
  18229. };
  18230. const isDockedMode = (header, mode) => contains$2(Docking.getModes(header), mode);
  18231. const updateIframeContentFlow = header => {
  18232. const getOccupiedHeight = elm => getOuter$2(elm) + (parseInt(get$e(elm, 'margin-top'), 10) || 0) + (parseInt(get$e(elm, 'margin-bottom'), 10) || 0);
  18233. const elm = header.element;
  18234. parentElement(elm).each(parentElem => {
  18235. const padding = 'padding-' + Docking.getModes(header)[0];
  18236. if (Docking.isDocked(header)) {
  18237. const parentWidth = get$c(parentElem);
  18238. set$8(elm, 'width', parentWidth + 'px');
  18239. set$8(parentElem, padding, getOccupiedHeight(elm) + 'px');
  18240. } else {
  18241. remove$6(elm, 'width');
  18242. remove$6(parentElem, padding);
  18243. }
  18244. });
  18245. };
  18246. const updateSinkVisibility = (sinkElem, visible) => {
  18247. if (visible) {
  18248. remove$2(sinkElem, visibility.fadeOutClass);
  18249. add$1(sinkElem, [
  18250. visibility.transitionClass,
  18251. visibility.fadeInClass
  18252. ]);
  18253. } else {
  18254. remove$2(sinkElem, visibility.fadeInClass);
  18255. add$1(sinkElem, [
  18256. visibility.fadeOutClass,
  18257. visibility.transitionClass
  18258. ]);
  18259. }
  18260. };
  18261. const updateEditorClasses = (editor, docked) => {
  18262. const editorContainer = SugarElement.fromDom(editor.getContainer());
  18263. if (docked) {
  18264. add$2(editorContainer, editorStickyOnClass);
  18265. remove$2(editorContainer, editorStickyOffClass);
  18266. } else {
  18267. add$2(editorContainer, editorStickyOffClass);
  18268. remove$2(editorContainer, editorStickyOnClass);
  18269. }
  18270. };
  18271. const restoreFocus = (headerElem, focusedElem) => {
  18272. const ownerDoc = owner$4(focusedElem);
  18273. active$1(ownerDoc).filter(activeElm => !eq(focusedElem, activeElm)).filter(activeElm => eq(activeElm, SugarElement.fromDom(ownerDoc.dom.body)) || contains(headerElem, activeElm)).each(() => focus$3(focusedElem));
  18274. };
  18275. const findFocusedElem = (rootElm, lazySink) => search(rootElm).orThunk(() => lazySink().toOptional().bind(sink => search(sink.element)));
  18276. const setup$9 = (editor, sharedBackstage, lazyHeader) => {
  18277. if (!editor.inline) {
  18278. if (!sharedBackstage.header.isPositionedAtTop()) {
  18279. editor.on('ResizeEditor', () => {
  18280. lazyHeader().each(Docking.reset);
  18281. });
  18282. }
  18283. editor.on('ResizeWindow ResizeEditor', () => {
  18284. lazyHeader().each(updateIframeContentFlow);
  18285. });
  18286. editor.on('SkinLoaded', () => {
  18287. lazyHeader().each(comp => {
  18288. Docking.isDocked(comp) ? Docking.reset(comp) : Docking.refresh(comp);
  18289. });
  18290. });
  18291. editor.on('FullscreenStateChanged', () => {
  18292. lazyHeader().each(Docking.reset);
  18293. });
  18294. }
  18295. editor.on('AfterScrollIntoView', e => {
  18296. lazyHeader().each(header => {
  18297. Docking.refresh(header);
  18298. const headerElem = header.element;
  18299. if (isVisible(headerElem)) {
  18300. scrollFromBehindHeader(e, headerElem);
  18301. }
  18302. });
  18303. });
  18304. editor.on('PostRender', () => {
  18305. updateEditorClasses(editor, false);
  18306. });
  18307. };
  18308. const isDocked = lazyHeader => lazyHeader().map(Docking.isDocked).getOr(false);
  18309. const getIframeBehaviours = () => [Receiving.config({ channels: { [toolbarHeightChange()]: { onReceive: updateIframeContentFlow } } })];
  18310. const getBehaviours = (editor, sharedBackstage) => {
  18311. const focusedElm = value$2();
  18312. const lazySink = sharedBackstage.getSink;
  18313. const runOnSinkElement = f => {
  18314. lazySink().each(sink => f(sink.element));
  18315. };
  18316. const onDockingSwitch = comp => {
  18317. if (!editor.inline) {
  18318. updateIframeContentFlow(comp);
  18319. }
  18320. updateEditorClasses(editor, Docking.isDocked(comp));
  18321. comp.getSystem().broadcastOn([repositionPopups()], {});
  18322. lazySink().each(sink => sink.getSystem().broadcastOn([repositionPopups()], {}));
  18323. };
  18324. const additionalBehaviours = editor.inline ? [] : getIframeBehaviours();
  18325. return [
  18326. Focusing.config({}),
  18327. Docking.config({
  18328. contextual: {
  18329. lazyContext: comp => {
  18330. const headerHeight = getOuter$2(comp.element);
  18331. const container = editor.inline ? editor.getContentAreaContainer() : editor.getContainer();
  18332. return Optional.from(container).map(c => {
  18333. const box = box$1(SugarElement.fromDom(c));
  18334. const optScrollingContext = detectWhenSplitUiMode(editor, comp.element);
  18335. return optScrollingContext.fold(() => {
  18336. const boxHeight = box.height - headerHeight;
  18337. const topBound = box.y + (isDockedMode(comp, 'top') ? 0 : headerHeight);
  18338. return bounds(box.x, topBound, box.width, boxHeight);
  18339. }, scrollEnv => {
  18340. const constrainedBounds = constrain(box, getBoundsFrom(scrollEnv));
  18341. return bounds(constrainedBounds.x, constrainedBounds.y, constrainedBounds.width, constrainedBounds.height - headerHeight);
  18342. });
  18343. });
  18344. },
  18345. onShow: () => {
  18346. runOnSinkElement(elem => updateSinkVisibility(elem, true));
  18347. },
  18348. onShown: comp => {
  18349. runOnSinkElement(elem => remove$1(elem, [
  18350. visibility.transitionClass,
  18351. visibility.fadeInClass
  18352. ]));
  18353. focusedElm.get().each(elem => {
  18354. restoreFocus(comp.element, elem);
  18355. focusedElm.clear();
  18356. });
  18357. },
  18358. onHide: comp => {
  18359. findFocusedElem(comp.element, lazySink).fold(focusedElm.clear, focusedElm.set);
  18360. runOnSinkElement(elem => updateSinkVisibility(elem, false));
  18361. },
  18362. onHidden: () => {
  18363. runOnSinkElement(elem => remove$1(elem, [visibility.transitionClass]));
  18364. },
  18365. ...visibility
  18366. },
  18367. lazyViewport: comp => {
  18368. const optScrollingContext = detectWhenSplitUiMode(editor, comp.element);
  18369. return optScrollingContext.fold(() => {
  18370. const boundsWithoutOffset = win();
  18371. const offset = getStickyToolbarOffset(editor);
  18372. const top = boundsWithoutOffset.y + (isDockedMode(comp, 'top') ? offset : 0);
  18373. const height = boundsWithoutOffset.height - (isDockedMode(comp, 'bottom') ? offset : 0);
  18374. return {
  18375. bounds: bounds(boundsWithoutOffset.x, top, boundsWithoutOffset.width, height),
  18376. optScrollEnv: Optional.none()
  18377. };
  18378. }, sc => {
  18379. const combinedBounds = getBoundsFrom(sc);
  18380. return {
  18381. bounds: combinedBounds,
  18382. optScrollEnv: Optional.some({
  18383. currentScrollTop: sc.element.dom.scrollTop,
  18384. scrollElmTop: absolute$3(sc.element).top
  18385. })
  18386. };
  18387. });
  18388. },
  18389. modes: [sharedBackstage.header.getDockingMode()],
  18390. onDocked: onDockingSwitch,
  18391. onUndocked: onDockingSwitch
  18392. }),
  18393. ...additionalBehaviours
  18394. ];
  18395. };
  18396. var StickyHeader = /*#__PURE__*/Object.freeze({
  18397. __proto__: null,
  18398. setup: setup$9,
  18399. isDocked: isDocked,
  18400. getBehaviours: getBehaviours
  18401. });
  18402. const renderHeader = spec => {
  18403. const editor = spec.editor;
  18404. const getBehaviours$2 = spec.sticky ? getBehaviours : getBehaviours$1;
  18405. return {
  18406. uid: spec.uid,
  18407. dom: spec.dom,
  18408. components: spec.components,
  18409. behaviours: derive$1(getBehaviours$2(editor, spec.sharedBackstage))
  18410. };
  18411. };
  18412. const groupToolbarButtonSchema = objOf([
  18413. type,
  18414. requiredOf('items', oneOf([
  18415. arrOfObj([
  18416. name$1,
  18417. requiredArrayOf('items', string)
  18418. ]),
  18419. string
  18420. ]))
  18421. ].concat(baseToolbarButtonFields));
  18422. const createGroupToolbarButton = spec => asRaw('GroupToolbarButton', groupToolbarButtonSchema, spec);
  18423. const baseMenuButtonFields = [
  18424. optionString('text'),
  18425. optionString('tooltip'),
  18426. optionString('icon'),
  18427. defaultedOf('search', false, oneOf([
  18428. boolean,
  18429. objOf([optionString('placeholder')])
  18430. ], x => {
  18431. if (isBoolean(x)) {
  18432. return x ? Optional.some({ placeholder: Optional.none() }) : Optional.none();
  18433. } else {
  18434. return Optional.some(x);
  18435. }
  18436. })),
  18437. requiredFunction('fetch'),
  18438. defaultedFunction('onSetup', () => noop)
  18439. ];
  18440. const MenuButtonSchema = objOf([
  18441. type,
  18442. ...baseMenuButtonFields
  18443. ]);
  18444. const createMenuButton = spec => asRaw('menubutton', MenuButtonSchema, spec);
  18445. const splitButtonSchema = objOf([
  18446. type,
  18447. optionalTooltip,
  18448. optionalIcon,
  18449. optionalText,
  18450. optionalSelect,
  18451. fetch$1,
  18452. onSetup,
  18453. defaultedStringEnum('presets', 'normal', [
  18454. 'normal',
  18455. 'color',
  18456. 'listpreview'
  18457. ]),
  18458. defaultedColumns(1),
  18459. onAction,
  18460. onItemAction
  18461. ]);
  18462. const createSplitButton = spec => asRaw('SplitButton', splitButtonSchema, spec);
  18463. const factory$d = (detail, spec) => {
  18464. const setMenus = (comp, menus) => {
  18465. const newMenus = map$2(menus, m => {
  18466. const buttonSpec = {
  18467. type: 'menubutton',
  18468. text: m.text,
  18469. fetch: callback => {
  18470. callback(m.getItems());
  18471. }
  18472. };
  18473. const internal = createMenuButton(buttonSpec).mapError(errInfo => formatError(errInfo)).getOrDie();
  18474. return renderMenuButton(internal, 'tox-mbtn', spec.backstage, Optional.some('menuitem'));
  18475. });
  18476. Replacing.set(comp, newMenus);
  18477. };
  18478. const apis = {
  18479. focus: Keying.focusIn,
  18480. setMenus
  18481. };
  18482. return {
  18483. uid: detail.uid,
  18484. dom: detail.dom,
  18485. components: [],
  18486. behaviours: derive$1([
  18487. Replacing.config({}),
  18488. config('menubar-events', [
  18489. runOnAttached(component => {
  18490. detail.onSetup(component);
  18491. }),
  18492. run$1(mouseover(), (comp, se) => {
  18493. descendant(comp.element, '.' + 'tox-mbtn--active').each(activeButton => {
  18494. closest$1(se.event.target, '.' + 'tox-mbtn').each(hoveredButton => {
  18495. if (!eq(activeButton, hoveredButton)) {
  18496. comp.getSystem().getByDom(activeButton).each(activeComp => {
  18497. comp.getSystem().getByDom(hoveredButton).each(hoveredComp => {
  18498. Dropdown.expand(hoveredComp);
  18499. Dropdown.close(activeComp);
  18500. Focusing.focus(hoveredComp);
  18501. });
  18502. });
  18503. }
  18504. });
  18505. });
  18506. }),
  18507. run$1(focusShifted(), (comp, se) => {
  18508. se.event.prevFocus.bind(prev => comp.getSystem().getByDom(prev).toOptional()).each(prev => {
  18509. se.event.newFocus.bind(nu => comp.getSystem().getByDom(nu).toOptional()).each(nu => {
  18510. if (Dropdown.isOpen(prev)) {
  18511. Dropdown.expand(nu);
  18512. Dropdown.close(prev);
  18513. }
  18514. });
  18515. });
  18516. })
  18517. ]),
  18518. Keying.config({
  18519. mode: 'flow',
  18520. selector: '.' + 'tox-mbtn',
  18521. onEscape: comp => {
  18522. detail.onEscape(comp);
  18523. return Optional.some(true);
  18524. }
  18525. }),
  18526. Tabstopping.config({})
  18527. ]),
  18528. apis,
  18529. domModification: { attributes: { role: 'menubar' } }
  18530. };
  18531. };
  18532. var SilverMenubar = single({
  18533. factory: factory$d,
  18534. name: 'silver.Menubar',
  18535. configFields: [
  18536. required$1('dom'),
  18537. required$1('uid'),
  18538. required$1('onEscape'),
  18539. required$1('backstage'),
  18540. defaulted('onSetup', noop)
  18541. ],
  18542. apis: {
  18543. focus: (apis, comp) => {
  18544. apis.focus(comp);
  18545. },
  18546. setMenus: (apis, comp, menus) => {
  18547. apis.setMenus(comp, menus);
  18548. }
  18549. }
  18550. });
  18551. const promotionMessage = '\u26A1\ufe0fUpgrade';
  18552. const promotionLink = 'https://www.tiny.cloud/tinymce-self-hosted-premium-features/?utm_source=TinyMCE&utm_medium=SPAP&utm_campaign=SPAP&utm_id=editorreferral';
  18553. const renderPromotion = spec => {
  18554. return {
  18555. uid: spec.uid,
  18556. dom: spec.dom,
  18557. components: [{
  18558. dom: {
  18559. tag: 'a',
  18560. attributes: {
  18561. 'href': promotionLink,
  18562. 'rel': 'noopener',
  18563. 'target': '_blank',
  18564. 'aria-hidden': 'true'
  18565. },
  18566. classes: ['tox-promotion-link'],
  18567. innerHtml: promotionMessage
  18568. }
  18569. }]
  18570. };
  18571. };
  18572. const owner = 'container';
  18573. const schema$d = [field('slotBehaviours', [])];
  18574. const getPartName = name => '<alloy.field.' + name + '>';
  18575. const sketch = sSpec => {
  18576. const parts = (() => {
  18577. const record = [];
  18578. const slot = (name, config) => {
  18579. record.push(name);
  18580. return generateOne$1(owner, getPartName(name), config);
  18581. };
  18582. return {
  18583. slot,
  18584. record: constant$1(record)
  18585. };
  18586. })();
  18587. const spec = sSpec(parts);
  18588. const partNames = parts.record();
  18589. const fieldParts = map$2(partNames, n => required({
  18590. name: n,
  18591. pname: getPartName(n)
  18592. }));
  18593. return composite$1(owner, schema$d, fieldParts, make$1, spec);
  18594. };
  18595. const make$1 = (detail, components) => {
  18596. const getSlotNames = _ => getAllPartNames(detail);
  18597. const getSlot = (container, key) => getPart(container, detail, key);
  18598. const onSlot = (f, def) => (container, key) => getPart(container, detail, key).map(slot => f(slot, key)).getOr(def);
  18599. const onSlots = f => (container, keys) => {
  18600. each$1(keys, key => f(container, key));
  18601. };
  18602. const doShowing = (comp, _key) => get$f(comp.element, 'aria-hidden') !== 'true';
  18603. const doShow = (comp, key) => {
  18604. if (!doShowing(comp)) {
  18605. const element = comp.element;
  18606. remove$6(element, 'display');
  18607. remove$7(element, 'aria-hidden');
  18608. emitWith(comp, slotVisibility(), {
  18609. name: key,
  18610. visible: true
  18611. });
  18612. }
  18613. };
  18614. const doHide = (comp, key) => {
  18615. if (doShowing(comp)) {
  18616. const element = comp.element;
  18617. set$8(element, 'display', 'none');
  18618. set$9(element, 'aria-hidden', 'true');
  18619. emitWith(comp, slotVisibility(), {
  18620. name: key,
  18621. visible: false
  18622. });
  18623. }
  18624. };
  18625. const isShowing = onSlot(doShowing, false);
  18626. const hideSlot = onSlot(doHide);
  18627. const hideSlots = onSlots(hideSlot);
  18628. const hideAllSlots = container => hideSlots(container, getSlotNames());
  18629. const showSlot = onSlot(doShow);
  18630. const apis = {
  18631. getSlotNames,
  18632. getSlot,
  18633. isShowing,
  18634. hideSlot,
  18635. hideAllSlots,
  18636. showSlot
  18637. };
  18638. return {
  18639. uid: detail.uid,
  18640. dom: detail.dom,
  18641. components,
  18642. behaviours: get$3(detail.slotBehaviours),
  18643. apis
  18644. };
  18645. };
  18646. const slotApis = map$1({
  18647. getSlotNames: (apis, c) => apis.getSlotNames(c),
  18648. getSlot: (apis, c, key) => apis.getSlot(c, key),
  18649. isShowing: (apis, c, key) => apis.isShowing(c, key),
  18650. hideSlot: (apis, c, key) => apis.hideSlot(c, key),
  18651. hideAllSlots: (apis, c) => apis.hideAllSlots(c),
  18652. showSlot: (apis, c, key) => apis.showSlot(c, key)
  18653. }, value => makeApi(value));
  18654. const SlotContainer = {
  18655. ...slotApis,
  18656. ...{ sketch }
  18657. };
  18658. const sidebarSchema = objOf([
  18659. optionalIcon,
  18660. optionalTooltip,
  18661. defaultedFunction('onShow', noop),
  18662. defaultedFunction('onHide', noop),
  18663. onSetup
  18664. ]);
  18665. const createSidebar = spec => asRaw('sidebar', sidebarSchema, spec);
  18666. const setup$8 = editor => {
  18667. const {sidebars} = editor.ui.registry.getAll();
  18668. each$1(keys(sidebars), name => {
  18669. const spec = sidebars[name];
  18670. const isActive = () => is$1(Optional.from(editor.queryCommandValue('ToggleSidebar')), name);
  18671. editor.ui.registry.addToggleButton(name, {
  18672. icon: spec.icon,
  18673. tooltip: spec.tooltip,
  18674. onAction: buttonApi => {
  18675. editor.execCommand('ToggleSidebar', false, name);
  18676. buttonApi.setActive(isActive());
  18677. },
  18678. onSetup: buttonApi => {
  18679. buttonApi.setActive(isActive());
  18680. const handleToggle = () => buttonApi.setActive(isActive());
  18681. editor.on('ToggleSidebar', handleToggle);
  18682. return () => {
  18683. editor.off('ToggleSidebar', handleToggle);
  18684. };
  18685. }
  18686. });
  18687. });
  18688. };
  18689. const getApi = comp => ({ element: () => comp.element.dom });
  18690. const makePanels = (parts, panelConfigs) => {
  18691. const specs = map$2(keys(panelConfigs), name => {
  18692. const spec = panelConfigs[name];
  18693. const bridged = getOrDie(createSidebar(spec));
  18694. return {
  18695. name,
  18696. getApi,
  18697. onSetup: bridged.onSetup,
  18698. onShow: bridged.onShow,
  18699. onHide: bridged.onHide
  18700. };
  18701. });
  18702. return map$2(specs, spec => {
  18703. const editorOffCell = Cell(noop);
  18704. return parts.slot(spec.name, {
  18705. dom: {
  18706. tag: 'div',
  18707. classes: ['tox-sidebar__pane']
  18708. },
  18709. behaviours: SimpleBehaviours.unnamedEvents([
  18710. onControlAttached(spec, editorOffCell),
  18711. onControlDetached(spec, editorOffCell),
  18712. run$1(slotVisibility(), (sidepanel, se) => {
  18713. const data = se.event;
  18714. const optSidePanelSpec = find$5(specs, config => config.name === data.name);
  18715. optSidePanelSpec.each(sidePanelSpec => {
  18716. const handler = data.visible ? sidePanelSpec.onShow : sidePanelSpec.onHide;
  18717. handler(sidePanelSpec.getApi(sidepanel));
  18718. });
  18719. })
  18720. ])
  18721. });
  18722. });
  18723. };
  18724. const makeSidebar = panelConfigs => SlotContainer.sketch(parts => ({
  18725. dom: {
  18726. tag: 'div',
  18727. classes: ['tox-sidebar__pane-container']
  18728. },
  18729. components: makePanels(parts, panelConfigs),
  18730. slotBehaviours: SimpleBehaviours.unnamedEvents([runOnAttached(slotContainer => SlotContainer.hideAllSlots(slotContainer))])
  18731. }));
  18732. const setSidebar = (sidebar, panelConfigs, showSidebar) => {
  18733. const optSlider = Composing.getCurrent(sidebar);
  18734. optSlider.each(slider => {
  18735. Replacing.set(slider, [makeSidebar(panelConfigs)]);
  18736. const configKey = showSidebar === null || showSidebar === void 0 ? void 0 : showSidebar.toLowerCase();
  18737. if (isString(configKey) && has$2(panelConfigs, configKey)) {
  18738. Composing.getCurrent(slider).each(slotContainer => {
  18739. SlotContainer.showSlot(slotContainer, configKey);
  18740. Sliding.immediateGrow(slider);
  18741. remove$6(slider.element, 'width');
  18742. updateSidebarRoleOnToggle(sidebar.element, 'region');
  18743. });
  18744. }
  18745. });
  18746. };
  18747. const updateSidebarRoleOnToggle = (sidebar, sidebarState) => {
  18748. set$9(sidebar, 'role', sidebarState);
  18749. };
  18750. const toggleSidebar = (sidebar, name) => {
  18751. const optSlider = Composing.getCurrent(sidebar);
  18752. optSlider.each(slider => {
  18753. const optSlotContainer = Composing.getCurrent(slider);
  18754. optSlotContainer.each(slotContainer => {
  18755. if (Sliding.hasGrown(slider)) {
  18756. if (SlotContainer.isShowing(slotContainer, name)) {
  18757. Sliding.shrink(slider);
  18758. updateSidebarRoleOnToggle(sidebar.element, 'presentation');
  18759. } else {
  18760. SlotContainer.hideAllSlots(slotContainer);
  18761. SlotContainer.showSlot(slotContainer, name);
  18762. updateSidebarRoleOnToggle(sidebar.element, 'region');
  18763. }
  18764. } else {
  18765. SlotContainer.hideAllSlots(slotContainer);
  18766. SlotContainer.showSlot(slotContainer, name);
  18767. Sliding.grow(slider);
  18768. updateSidebarRoleOnToggle(sidebar.element, 'region');
  18769. }
  18770. });
  18771. });
  18772. };
  18773. const whichSidebar = sidebar => {
  18774. const optSlider = Composing.getCurrent(sidebar);
  18775. return optSlider.bind(slider => {
  18776. const sidebarOpen = Sliding.isGrowing(slider) || Sliding.hasGrown(slider);
  18777. if (sidebarOpen) {
  18778. const optSlotContainer = Composing.getCurrent(slider);
  18779. return optSlotContainer.bind(slotContainer => find$5(SlotContainer.getSlotNames(slotContainer), name => SlotContainer.isShowing(slotContainer, name)));
  18780. } else {
  18781. return Optional.none();
  18782. }
  18783. });
  18784. };
  18785. const fixSize = generate$6('FixSizeEvent');
  18786. const autoSize = generate$6('AutoSizeEvent');
  18787. const renderSidebar = spec => ({
  18788. uid: spec.uid,
  18789. dom: {
  18790. tag: 'div',
  18791. classes: ['tox-sidebar'],
  18792. attributes: { role: 'presentation' }
  18793. },
  18794. components: [{
  18795. dom: {
  18796. tag: 'div',
  18797. classes: ['tox-sidebar__slider']
  18798. },
  18799. components: [],
  18800. behaviours: derive$1([
  18801. Tabstopping.config({}),
  18802. Focusing.config({}),
  18803. Sliding.config({
  18804. dimension: { property: 'width' },
  18805. closedClass: 'tox-sidebar--sliding-closed',
  18806. openClass: 'tox-sidebar--sliding-open',
  18807. shrinkingClass: 'tox-sidebar--sliding-shrinking',
  18808. growingClass: 'tox-sidebar--sliding-growing',
  18809. onShrunk: slider => {
  18810. const optSlotContainer = Composing.getCurrent(slider);
  18811. optSlotContainer.each(SlotContainer.hideAllSlots);
  18812. emit(slider, autoSize);
  18813. },
  18814. onGrown: slider => {
  18815. emit(slider, autoSize);
  18816. },
  18817. onStartGrow: slider => {
  18818. emitWith(slider, fixSize, { width: getRaw(slider.element, 'width').getOr('') });
  18819. },
  18820. onStartShrink: slider => {
  18821. emitWith(slider, fixSize, { width: get$c(slider.element) + 'px' });
  18822. }
  18823. }),
  18824. Replacing.config({}),
  18825. Composing.config({
  18826. find: comp => {
  18827. const children = Replacing.contents(comp);
  18828. return head(children);
  18829. }
  18830. })
  18831. ])
  18832. }],
  18833. behaviours: derive$1([
  18834. ComposingConfigs.childAt(0),
  18835. config('sidebar-sliding-events', [
  18836. run$1(fixSize, (comp, se) => {
  18837. set$8(comp.element, 'width', se.event.width);
  18838. }),
  18839. run$1(autoSize, (comp, _se) => {
  18840. remove$6(comp.element, 'width');
  18841. })
  18842. ])
  18843. ])
  18844. });
  18845. const block = (component, config, state, getBusySpec) => {
  18846. set$9(component.element, 'aria-busy', true);
  18847. const root = config.getRoot(component).getOr(component);
  18848. const blockerBehaviours = derive$1([
  18849. Keying.config({
  18850. mode: 'special',
  18851. onTab: () => Optional.some(true),
  18852. onShiftTab: () => Optional.some(true)
  18853. }),
  18854. Focusing.config({})
  18855. ]);
  18856. const blockSpec = getBusySpec(root, blockerBehaviours);
  18857. const blocker = root.getSystem().build(blockSpec);
  18858. Replacing.append(root, premade(blocker));
  18859. if (blocker.hasConfigured(Keying) && config.focus) {
  18860. Keying.focusIn(blocker);
  18861. }
  18862. if (!state.isBlocked()) {
  18863. config.onBlock(component);
  18864. }
  18865. state.blockWith(() => Replacing.remove(root, blocker));
  18866. };
  18867. const unblock = (component, config, state) => {
  18868. remove$7(component.element, 'aria-busy');
  18869. if (state.isBlocked()) {
  18870. config.onUnblock(component);
  18871. }
  18872. state.clear();
  18873. };
  18874. var BlockingApis = /*#__PURE__*/Object.freeze({
  18875. __proto__: null,
  18876. block: block,
  18877. unblock: unblock
  18878. });
  18879. var BlockingSchema = [
  18880. defaultedFunction('getRoot', Optional.none),
  18881. defaultedBoolean('focus', true),
  18882. onHandler('onBlock'),
  18883. onHandler('onUnblock')
  18884. ];
  18885. const init$4 = () => {
  18886. const blocker = destroyable();
  18887. const blockWith = destroy => {
  18888. blocker.set({ destroy });
  18889. };
  18890. return nu$8({
  18891. readState: blocker.isSet,
  18892. blockWith,
  18893. clear: blocker.clear,
  18894. isBlocked: blocker.isSet
  18895. });
  18896. };
  18897. var BlockingState = /*#__PURE__*/Object.freeze({
  18898. __proto__: null,
  18899. init: init$4
  18900. });
  18901. const Blocking = create$4({
  18902. fields: BlockingSchema,
  18903. name: 'blocking',
  18904. apis: BlockingApis,
  18905. state: BlockingState
  18906. });
  18907. const getAttrs = elem => {
  18908. const attributes = elem.dom.attributes !== undefined ? elem.dom.attributes : [];
  18909. return foldl(attributes, (b, attr) => {
  18910. if (attr.name === 'class') {
  18911. return b;
  18912. } else {
  18913. return {
  18914. ...b,
  18915. [attr.name]: attr.value
  18916. };
  18917. }
  18918. }, {});
  18919. };
  18920. const getClasses = elem => Array.prototype.slice.call(elem.dom.classList, 0);
  18921. const fromHtml = html => {
  18922. const elem = SugarElement.fromHtml(html);
  18923. const children$1 = children(elem);
  18924. const attrs = getAttrs(elem);
  18925. const classes = getClasses(elem);
  18926. const contents = children$1.length === 0 ? {} : { innerHtml: get$9(elem) };
  18927. return {
  18928. tag: name$3(elem),
  18929. classes,
  18930. attributes: attrs,
  18931. ...contents
  18932. };
  18933. };
  18934. const getBusySpec$1 = providerBackstage => (_root, _behaviours) => ({
  18935. dom: {
  18936. tag: 'div',
  18937. attributes: {
  18938. 'aria-label': providerBackstage.translate('Loading...'),
  18939. 'tabindex': '0'
  18940. },
  18941. classes: ['tox-throbber__busy-spinner']
  18942. },
  18943. components: [{ dom: fromHtml('<div class="tox-spinner"><div></div><div></div><div></div></div>') }]
  18944. });
  18945. const focusBusyComponent = throbber => Composing.getCurrent(throbber).each(comp => focus$3(comp.element));
  18946. const toggleEditorTabIndex = (editor, state) => {
  18947. const tabIndexAttr = 'tabindex';
  18948. const dataTabIndexAttr = `data-mce-${ tabIndexAttr }`;
  18949. Optional.from(editor.iframeElement).map(SugarElement.fromDom).each(iframe => {
  18950. if (state) {
  18951. getOpt(iframe, tabIndexAttr).each(tabIndex => set$9(iframe, dataTabIndexAttr, tabIndex));
  18952. set$9(iframe, tabIndexAttr, -1);
  18953. } else {
  18954. remove$7(iframe, tabIndexAttr);
  18955. getOpt(iframe, dataTabIndexAttr).each(tabIndex => {
  18956. set$9(iframe, tabIndexAttr, tabIndex);
  18957. remove$7(iframe, dataTabIndexAttr);
  18958. });
  18959. }
  18960. });
  18961. };
  18962. const toggleThrobber = (editor, comp, state, providerBackstage) => {
  18963. const element = comp.element;
  18964. toggleEditorTabIndex(editor, state);
  18965. if (state) {
  18966. Blocking.block(comp, getBusySpec$1(providerBackstage));
  18967. remove$6(element, 'display');
  18968. remove$7(element, 'aria-hidden');
  18969. if (editor.hasFocus()) {
  18970. focusBusyComponent(comp);
  18971. }
  18972. } else {
  18973. const throbberFocus = Composing.getCurrent(comp).exists(busyComp => hasFocus(busyComp.element));
  18974. Blocking.unblock(comp);
  18975. set$8(element, 'display', 'none');
  18976. set$9(element, 'aria-hidden', 'true');
  18977. if (throbberFocus) {
  18978. editor.focus();
  18979. }
  18980. }
  18981. };
  18982. const renderThrobber = spec => ({
  18983. uid: spec.uid,
  18984. dom: {
  18985. tag: 'div',
  18986. attributes: { 'aria-hidden': 'true' },
  18987. classes: ['tox-throbber'],
  18988. styles: { display: 'none' }
  18989. },
  18990. behaviours: derive$1([
  18991. Replacing.config({}),
  18992. Blocking.config({ focus: false }),
  18993. Composing.config({ find: comp => head(comp.components()) })
  18994. ]),
  18995. components: []
  18996. });
  18997. const isFocusEvent = event => event.type === 'focusin';
  18998. const isPasteBinTarget = event => {
  18999. if (isFocusEvent(event)) {
  19000. const node = event.composed ? head(event.composedPath()) : Optional.from(event.target);
  19001. return node.map(SugarElement.fromDom).filter(isElement$1).exists(targetElm => has(targetElm, 'mce-pastebin'));
  19002. } else {
  19003. return false;
  19004. }
  19005. };
  19006. const setup$7 = (editor, lazyThrobber, sharedBackstage) => {
  19007. const throbberState = Cell(false);
  19008. const timer = value$2();
  19009. const stealFocus = e => {
  19010. if (throbberState.get() && !isPasteBinTarget(e)) {
  19011. e.preventDefault();
  19012. focusBusyComponent(lazyThrobber());
  19013. editor.editorManager.setActive(editor);
  19014. }
  19015. };
  19016. if (!editor.inline) {
  19017. editor.on('PreInit', () => {
  19018. editor.dom.bind(editor.getWin(), 'focusin', stealFocus);
  19019. editor.on('BeforeExecCommand', e => {
  19020. if (e.command.toLowerCase() === 'mcefocus' && e.value !== true) {
  19021. stealFocus(e);
  19022. }
  19023. });
  19024. });
  19025. }
  19026. const toggle = state => {
  19027. if (state !== throbberState.get()) {
  19028. throbberState.set(state);
  19029. toggleThrobber(editor, lazyThrobber(), state, sharedBackstage.providers);
  19030. fireAfterProgressState(editor, state);
  19031. }
  19032. };
  19033. editor.on('ProgressState', e => {
  19034. timer.on(clearTimeout);
  19035. if (isNumber(e.time)) {
  19036. const timerId = global$9.setEditorTimeout(editor, () => toggle(e.state), e.time);
  19037. timer.set(timerId);
  19038. } else {
  19039. toggle(e.state);
  19040. timer.clear();
  19041. }
  19042. });
  19043. };
  19044. const generate$1 = (xs, f) => {
  19045. const init = {
  19046. len: 0,
  19047. list: []
  19048. };
  19049. const r = foldl(xs, (b, a) => {
  19050. const value = f(a, b.len);
  19051. return value.fold(constant$1(b), v => ({
  19052. len: v.finish,
  19053. list: b.list.concat([v])
  19054. }));
  19055. }, init);
  19056. return r.list;
  19057. };
  19058. const output = (within, extra, withinWidth) => ({
  19059. within,
  19060. extra,
  19061. withinWidth
  19062. });
  19063. const apportion = (units, total, len) => {
  19064. const parray = generate$1(units, (unit, current) => {
  19065. const width = len(unit);
  19066. return Optional.some({
  19067. element: unit,
  19068. start: current,
  19069. finish: current + width,
  19070. width
  19071. });
  19072. });
  19073. const within = filter$2(parray, unit => unit.finish <= total);
  19074. const withinWidth = foldr(within, (acc, el) => acc + el.width, 0);
  19075. const extra = parray.slice(within.length);
  19076. return {
  19077. within,
  19078. extra,
  19079. withinWidth
  19080. };
  19081. };
  19082. const toUnit = parray => map$2(parray, unit => unit.element);
  19083. const fitLast = (within, extra, withinWidth) => {
  19084. const fits = toUnit(within.concat(extra));
  19085. return output(fits, [], withinWidth);
  19086. };
  19087. const overflow = (within, extra, overflower, withinWidth) => {
  19088. const fits = toUnit(within).concat([overflower]);
  19089. return output(fits, toUnit(extra), withinWidth);
  19090. };
  19091. const fitAll = (within, extra, withinWidth) => output(toUnit(within), [], withinWidth);
  19092. const tryFit = (total, units, len) => {
  19093. const divide = apportion(units, total, len);
  19094. return divide.extra.length === 0 ? Optional.some(divide) : Optional.none();
  19095. };
  19096. const partition = (total, units, len, overflower) => {
  19097. const divide = tryFit(total, units, len).getOrThunk(() => apportion(units, total - len(overflower), len));
  19098. const within = divide.within;
  19099. const extra = divide.extra;
  19100. const withinWidth = divide.withinWidth;
  19101. if (extra.length === 1 && extra[0].width <= len(overflower)) {
  19102. return fitLast(within, extra, withinWidth);
  19103. } else if (extra.length >= 1) {
  19104. return overflow(within, extra, overflower, withinWidth);
  19105. } else {
  19106. return fitAll(within, extra, withinWidth);
  19107. }
  19108. };
  19109. const setGroups$1 = (toolbar, storedGroups) => {
  19110. const bGroups = map$2(storedGroups, g => premade(g));
  19111. Toolbar.setGroups(toolbar, bGroups);
  19112. };
  19113. const findFocusedComp = comps => findMap(comps, comp => search(comp.element).bind(focusedElm => comp.getSystem().getByDom(focusedElm).toOptional()));
  19114. const refresh$2 = (toolbar, detail, setOverflow) => {
  19115. const builtGroups = detail.builtGroups.get();
  19116. if (builtGroups.length === 0) {
  19117. return;
  19118. }
  19119. const primary = getPartOrDie(toolbar, detail, 'primary');
  19120. const overflowGroup = Coupling.getCoupled(toolbar, 'overflowGroup');
  19121. set$8(primary.element, 'visibility', 'hidden');
  19122. const groups = builtGroups.concat([overflowGroup]);
  19123. const focusedComp = findFocusedComp(groups);
  19124. setOverflow([]);
  19125. setGroups$1(primary, groups);
  19126. const availableWidth = get$c(primary.element);
  19127. const overflows = partition(availableWidth, detail.builtGroups.get(), comp => get$c(comp.element), overflowGroup);
  19128. if (overflows.extra.length === 0) {
  19129. Replacing.remove(primary, overflowGroup);
  19130. setOverflow([]);
  19131. } else {
  19132. setGroups$1(primary, overflows.within);
  19133. setOverflow(overflows.extra);
  19134. }
  19135. remove$6(primary.element, 'visibility');
  19136. reflow(primary.element);
  19137. focusedComp.each(Focusing.focus);
  19138. };
  19139. const schema$c = constant$1([
  19140. field('splitToolbarBehaviours', [Coupling]),
  19141. customField('builtGroups', () => Cell([]))
  19142. ]);
  19143. const schema$b = constant$1([
  19144. markers$1(['overflowToggledClass']),
  19145. optionFunction('getOverflowBounds'),
  19146. required$1('lazySink'),
  19147. customField('overflowGroups', () => Cell([])),
  19148. onHandler('onOpened'),
  19149. onHandler('onClosed')
  19150. ].concat(schema$c()));
  19151. const parts$7 = constant$1([
  19152. required({
  19153. factory: Toolbar,
  19154. schema: schema$e(),
  19155. name: 'primary'
  19156. }),
  19157. external({
  19158. schema: schema$e(),
  19159. name: 'overflow'
  19160. }),
  19161. external({ name: 'overflow-button' }),
  19162. external({ name: 'overflow-group' })
  19163. ]);
  19164. const expandable = constant$1((element, available) => {
  19165. setMax(element, Math.floor(available));
  19166. });
  19167. const schema$a = constant$1([
  19168. markers$1(['toggledClass']),
  19169. required$1('lazySink'),
  19170. requiredFunction('fetch'),
  19171. optionFunction('getBounds'),
  19172. optionObjOf('fireDismissalEventInstead', [defaulted('event', dismissRequested())]),
  19173. schema$y(),
  19174. onHandler('onToggled')
  19175. ]);
  19176. const parts$6 = constant$1([
  19177. external({
  19178. name: 'button',
  19179. overrides: detail => ({
  19180. dom: { attributes: { 'aria-haspopup': 'true' } },
  19181. buttonBehaviours: derive$1([Toggling.config({
  19182. toggleClass: detail.markers.toggledClass,
  19183. aria: { mode: 'expanded' },
  19184. toggleOnExecute: false,
  19185. onToggled: detail.onToggled
  19186. })])
  19187. })
  19188. }),
  19189. external({
  19190. factory: Toolbar,
  19191. schema: schema$e(),
  19192. name: 'toolbar',
  19193. overrides: detail => {
  19194. return {
  19195. toolbarBehaviours: derive$1([Keying.config({
  19196. mode: 'cyclic',
  19197. onEscape: comp => {
  19198. getPart(comp, detail, 'button').each(Focusing.focus);
  19199. return Optional.none();
  19200. }
  19201. })])
  19202. };
  19203. }
  19204. })
  19205. ]);
  19206. const shouldSkipFocus = value$2();
  19207. const toggleWithoutFocusing = (button, externals) => {
  19208. shouldSkipFocus.set(true);
  19209. toggle(button, externals);
  19210. shouldSkipFocus.clear();
  19211. };
  19212. const toggle = (button, externals) => {
  19213. const toolbarSandbox = Coupling.getCoupled(button, 'toolbarSandbox');
  19214. if (Sandboxing.isOpen(toolbarSandbox)) {
  19215. Sandboxing.close(toolbarSandbox);
  19216. } else {
  19217. Sandboxing.open(toolbarSandbox, externals.toolbar());
  19218. }
  19219. };
  19220. const position = (button, toolbar, detail, layouts) => {
  19221. const bounds = detail.getBounds.map(bounder => bounder());
  19222. const sink = detail.lazySink(button).getOrDie();
  19223. Positioning.positionWithinBounds(sink, toolbar, {
  19224. anchor: {
  19225. type: 'hotspot',
  19226. hotspot: button,
  19227. layouts,
  19228. overrides: { maxWidthFunction: expandable() }
  19229. }
  19230. }, bounds);
  19231. };
  19232. const setGroups = (button, toolbar, detail, layouts, groups) => {
  19233. Toolbar.setGroups(toolbar, groups);
  19234. position(button, toolbar, detail, layouts);
  19235. Toggling.on(button);
  19236. };
  19237. const makeSandbox = (button, spec, detail) => {
  19238. const ariaControls = manager();
  19239. const onOpen = (sandbox, toolbar) => {
  19240. const skipFocus = shouldSkipFocus.get().getOr(false);
  19241. detail.fetch().get(groups => {
  19242. setGroups(button, toolbar, detail, spec.layouts, groups);
  19243. ariaControls.link(button.element);
  19244. if (!skipFocus) {
  19245. Keying.focusIn(toolbar);
  19246. }
  19247. });
  19248. };
  19249. const onClose = () => {
  19250. Toggling.off(button);
  19251. if (!shouldSkipFocus.get().getOr(false)) {
  19252. Focusing.focus(button);
  19253. }
  19254. ariaControls.unlink(button.element);
  19255. };
  19256. return {
  19257. dom: {
  19258. tag: 'div',
  19259. attributes: { id: ariaControls.id }
  19260. },
  19261. behaviours: derive$1([
  19262. Keying.config({
  19263. mode: 'special',
  19264. onEscape: comp => {
  19265. Sandboxing.close(comp);
  19266. return Optional.some(true);
  19267. }
  19268. }),
  19269. Sandboxing.config({
  19270. onOpen,
  19271. onClose,
  19272. isPartOf: (container, data, queryElem) => {
  19273. return isPartOf$1(data, queryElem) || isPartOf$1(button, queryElem);
  19274. },
  19275. getAttachPoint: () => {
  19276. return detail.lazySink(button).getOrDie();
  19277. }
  19278. }),
  19279. Receiving.config({
  19280. channels: {
  19281. ...receivingChannel$1({
  19282. isExtraPart: never,
  19283. ...detail.fireDismissalEventInstead.map(fe => ({ fireEventInstead: { event: fe.event } })).getOr({})
  19284. }),
  19285. ...receivingChannel({
  19286. doReposition: () => {
  19287. Sandboxing.getState(Coupling.getCoupled(button, 'toolbarSandbox')).each(toolbar => {
  19288. position(button, toolbar, detail, spec.layouts);
  19289. });
  19290. }
  19291. })
  19292. }
  19293. })
  19294. ])
  19295. };
  19296. };
  19297. const factory$c = (detail, components, spec, externals) => ({
  19298. ...Button.sketch({
  19299. ...externals.button(),
  19300. action: button => {
  19301. toggle(button, externals);
  19302. },
  19303. buttonBehaviours: SketchBehaviours.augment({ dump: externals.button().buttonBehaviours }, [Coupling.config({
  19304. others: {
  19305. toolbarSandbox: button => {
  19306. return makeSandbox(button, spec, detail);
  19307. }
  19308. }
  19309. })])
  19310. }),
  19311. apis: {
  19312. setGroups: (button, groups) => {
  19313. Sandboxing.getState(Coupling.getCoupled(button, 'toolbarSandbox')).each(toolbar => {
  19314. setGroups(button, toolbar, detail, spec.layouts, groups);
  19315. });
  19316. },
  19317. reposition: button => {
  19318. Sandboxing.getState(Coupling.getCoupled(button, 'toolbarSandbox')).each(toolbar => {
  19319. position(button, toolbar, detail, spec.layouts);
  19320. });
  19321. },
  19322. toggle: button => {
  19323. toggle(button, externals);
  19324. },
  19325. toggleWithoutFocusing: button => {
  19326. toggleWithoutFocusing(button, externals);
  19327. },
  19328. getToolbar: button => {
  19329. return Sandboxing.getState(Coupling.getCoupled(button, 'toolbarSandbox'));
  19330. },
  19331. isOpen: button => {
  19332. return Sandboxing.isOpen(Coupling.getCoupled(button, 'toolbarSandbox'));
  19333. }
  19334. }
  19335. });
  19336. const FloatingToolbarButton = composite({
  19337. name: 'FloatingToolbarButton',
  19338. factory: factory$c,
  19339. configFields: schema$a(),
  19340. partFields: parts$6(),
  19341. apis: {
  19342. setGroups: (apis, button, groups) => {
  19343. apis.setGroups(button, groups);
  19344. },
  19345. reposition: (apis, button) => {
  19346. apis.reposition(button);
  19347. },
  19348. toggle: (apis, button) => {
  19349. apis.toggle(button);
  19350. },
  19351. toggleWithoutFocusing: (apis, button) => {
  19352. apis.toggleWithoutFocusing(button);
  19353. },
  19354. getToolbar: (apis, button) => apis.getToolbar(button),
  19355. isOpen: (apis, button) => apis.isOpen(button)
  19356. }
  19357. });
  19358. const schema$9 = constant$1([
  19359. required$1('items'),
  19360. markers$1(['itemSelector']),
  19361. field('tgroupBehaviours', [Keying])
  19362. ]);
  19363. const parts$5 = constant$1([group({
  19364. name: 'items',
  19365. unit: 'item'
  19366. })]);
  19367. const factory$b = (detail, components, _spec, _externals) => ({
  19368. uid: detail.uid,
  19369. dom: detail.dom,
  19370. components,
  19371. behaviours: augment(detail.tgroupBehaviours, [Keying.config({
  19372. mode: 'flow',
  19373. selector: detail.markers.itemSelector
  19374. })]),
  19375. domModification: { attributes: { role: 'toolbar' } }
  19376. });
  19377. const ToolbarGroup = composite({
  19378. name: 'ToolbarGroup',
  19379. configFields: schema$9(),
  19380. partFields: parts$5(),
  19381. factory: factory$b
  19382. });
  19383. const buildGroups = comps => map$2(comps, g => premade(g));
  19384. const refresh$1 = (toolbar, memFloatingToolbarButton, detail) => {
  19385. refresh$2(toolbar, detail, overflowGroups => {
  19386. detail.overflowGroups.set(overflowGroups);
  19387. memFloatingToolbarButton.getOpt(toolbar).each(floatingToolbarButton => {
  19388. FloatingToolbarButton.setGroups(floatingToolbarButton, buildGroups(overflowGroups));
  19389. });
  19390. });
  19391. };
  19392. const factory$a = (detail, components, spec, externals) => {
  19393. const memFloatingToolbarButton = record(FloatingToolbarButton.sketch({
  19394. fetch: () => Future.nu(resolve => {
  19395. resolve(buildGroups(detail.overflowGroups.get()));
  19396. }),
  19397. layouts: {
  19398. onLtr: () => [
  19399. southwest$2,
  19400. southeast$2
  19401. ],
  19402. onRtl: () => [
  19403. southeast$2,
  19404. southwest$2
  19405. ],
  19406. onBottomLtr: () => [
  19407. northwest$2,
  19408. northeast$2
  19409. ],
  19410. onBottomRtl: () => [
  19411. northeast$2,
  19412. northwest$2
  19413. ]
  19414. },
  19415. getBounds: spec.getOverflowBounds,
  19416. lazySink: detail.lazySink,
  19417. fireDismissalEventInstead: {},
  19418. markers: { toggledClass: detail.markers.overflowToggledClass },
  19419. parts: {
  19420. button: externals['overflow-button'](),
  19421. toolbar: externals.overflow()
  19422. },
  19423. onToggled: (comp, state) => detail[state ? 'onOpened' : 'onClosed'](comp)
  19424. }));
  19425. return {
  19426. uid: detail.uid,
  19427. dom: detail.dom,
  19428. components,
  19429. behaviours: augment(detail.splitToolbarBehaviours, [Coupling.config({
  19430. others: {
  19431. overflowGroup: () => {
  19432. return ToolbarGroup.sketch({
  19433. ...externals['overflow-group'](),
  19434. items: [memFloatingToolbarButton.asSpec()]
  19435. });
  19436. }
  19437. }
  19438. })]),
  19439. apis: {
  19440. setGroups: (toolbar, groups) => {
  19441. detail.builtGroups.set(map$2(groups, toolbar.getSystem().build));
  19442. refresh$1(toolbar, memFloatingToolbarButton, detail);
  19443. },
  19444. refresh: toolbar => refresh$1(toolbar, memFloatingToolbarButton, detail),
  19445. toggle: toolbar => {
  19446. memFloatingToolbarButton.getOpt(toolbar).each(floatingToolbarButton => {
  19447. FloatingToolbarButton.toggle(floatingToolbarButton);
  19448. });
  19449. },
  19450. toggleWithoutFocusing: toolbar => {
  19451. memFloatingToolbarButton.getOpt(toolbar).each(FloatingToolbarButton.toggleWithoutFocusing);
  19452. },
  19453. isOpen: toolbar => memFloatingToolbarButton.getOpt(toolbar).map(FloatingToolbarButton.isOpen).getOr(false),
  19454. reposition: toolbar => {
  19455. memFloatingToolbarButton.getOpt(toolbar).each(floatingToolbarButton => {
  19456. FloatingToolbarButton.reposition(floatingToolbarButton);
  19457. });
  19458. },
  19459. getOverflow: toolbar => memFloatingToolbarButton.getOpt(toolbar).bind(FloatingToolbarButton.getToolbar)
  19460. },
  19461. domModification: { attributes: { role: 'group' } }
  19462. };
  19463. };
  19464. const SplitFloatingToolbar = composite({
  19465. name: 'SplitFloatingToolbar',
  19466. configFields: schema$b(),
  19467. partFields: parts$7(),
  19468. factory: factory$a,
  19469. apis: {
  19470. setGroups: (apis, toolbar, groups) => {
  19471. apis.setGroups(toolbar, groups);
  19472. },
  19473. refresh: (apis, toolbar) => {
  19474. apis.refresh(toolbar);
  19475. },
  19476. reposition: (apis, toolbar) => {
  19477. apis.reposition(toolbar);
  19478. },
  19479. toggle: (apis, toolbar) => {
  19480. apis.toggle(toolbar);
  19481. },
  19482. toggleWithoutFocusing: (apis, toolbar) => {
  19483. apis.toggle(toolbar);
  19484. },
  19485. isOpen: (apis, toolbar) => apis.isOpen(toolbar),
  19486. getOverflow: (apis, toolbar) => apis.getOverflow(toolbar)
  19487. }
  19488. });
  19489. const schema$8 = constant$1([
  19490. markers$1([
  19491. 'closedClass',
  19492. 'openClass',
  19493. 'shrinkingClass',
  19494. 'growingClass',
  19495. 'overflowToggledClass'
  19496. ]),
  19497. onHandler('onOpened'),
  19498. onHandler('onClosed')
  19499. ].concat(schema$c()));
  19500. const parts$4 = constant$1([
  19501. required({
  19502. factory: Toolbar,
  19503. schema: schema$e(),
  19504. name: 'primary'
  19505. }),
  19506. required({
  19507. factory: Toolbar,
  19508. schema: schema$e(),
  19509. name: 'overflow',
  19510. overrides: detail => {
  19511. return {
  19512. toolbarBehaviours: derive$1([
  19513. Sliding.config({
  19514. dimension: { property: 'height' },
  19515. closedClass: detail.markers.closedClass,
  19516. openClass: detail.markers.openClass,
  19517. shrinkingClass: detail.markers.shrinkingClass,
  19518. growingClass: detail.markers.growingClass,
  19519. onShrunk: comp => {
  19520. getPart(comp, detail, 'overflow-button').each(button => {
  19521. Toggling.off(button);
  19522. Focusing.focus(button);
  19523. });
  19524. detail.onClosed(comp);
  19525. },
  19526. onGrown: comp => {
  19527. Keying.focusIn(comp);
  19528. detail.onOpened(comp);
  19529. },
  19530. onStartGrow: comp => {
  19531. getPart(comp, detail, 'overflow-button').each(Toggling.on);
  19532. }
  19533. }),
  19534. Keying.config({
  19535. mode: 'acyclic',
  19536. onEscape: comp => {
  19537. getPart(comp, detail, 'overflow-button').each(Focusing.focus);
  19538. return Optional.some(true);
  19539. }
  19540. })
  19541. ])
  19542. };
  19543. }
  19544. }),
  19545. external({
  19546. name: 'overflow-button',
  19547. overrides: detail => ({
  19548. buttonBehaviours: derive$1([Toggling.config({
  19549. toggleClass: detail.markers.overflowToggledClass,
  19550. aria: { mode: 'pressed' },
  19551. toggleOnExecute: false
  19552. })])
  19553. })
  19554. }),
  19555. external({ name: 'overflow-group' })
  19556. ]);
  19557. const isOpen = (toolbar, detail) => getPart(toolbar, detail, 'overflow').map(Sliding.hasGrown).getOr(false);
  19558. const toggleToolbar = (toolbar, detail) => {
  19559. getPart(toolbar, detail, 'overflow-button').bind(() => getPart(toolbar, detail, 'overflow')).each(overf => {
  19560. refresh(toolbar, detail);
  19561. Sliding.toggleGrow(overf);
  19562. });
  19563. };
  19564. const refresh = (toolbar, detail) => {
  19565. getPart(toolbar, detail, 'overflow').each(overflow => {
  19566. refresh$2(toolbar, detail, groups => {
  19567. const builtGroups = map$2(groups, g => premade(g));
  19568. Toolbar.setGroups(overflow, builtGroups);
  19569. });
  19570. getPart(toolbar, detail, 'overflow-button').each(button => {
  19571. if (Sliding.hasGrown(overflow)) {
  19572. Toggling.on(button);
  19573. }
  19574. });
  19575. Sliding.refresh(overflow);
  19576. });
  19577. };
  19578. const factory$9 = (detail, components, spec, externals) => {
  19579. const toolbarToggleEvent = 'alloy.toolbar.toggle';
  19580. const doSetGroups = (toolbar, groups) => {
  19581. const built = map$2(groups, toolbar.getSystem().build);
  19582. detail.builtGroups.set(built);
  19583. };
  19584. return {
  19585. uid: detail.uid,
  19586. dom: detail.dom,
  19587. components,
  19588. behaviours: augment(detail.splitToolbarBehaviours, [
  19589. Coupling.config({
  19590. others: {
  19591. overflowGroup: toolbar => {
  19592. return ToolbarGroup.sketch({
  19593. ...externals['overflow-group'](),
  19594. items: [Button.sketch({
  19595. ...externals['overflow-button'](),
  19596. action: _button => {
  19597. emit(toolbar, toolbarToggleEvent);
  19598. }
  19599. })]
  19600. });
  19601. }
  19602. }
  19603. }),
  19604. config('toolbar-toggle-events', [run$1(toolbarToggleEvent, toolbar => {
  19605. toggleToolbar(toolbar, detail);
  19606. })])
  19607. ]),
  19608. apis: {
  19609. setGroups: (toolbar, groups) => {
  19610. doSetGroups(toolbar, groups);
  19611. refresh(toolbar, detail);
  19612. },
  19613. refresh: toolbar => refresh(toolbar, detail),
  19614. toggle: toolbar => toggleToolbar(toolbar, detail),
  19615. isOpen: toolbar => isOpen(toolbar, detail)
  19616. },
  19617. domModification: { attributes: { role: 'group' } }
  19618. };
  19619. };
  19620. const SplitSlidingToolbar = composite({
  19621. name: 'SplitSlidingToolbar',
  19622. configFields: schema$8(),
  19623. partFields: parts$4(),
  19624. factory: factory$9,
  19625. apis: {
  19626. setGroups: (apis, toolbar, groups) => {
  19627. apis.setGroups(toolbar, groups);
  19628. },
  19629. refresh: (apis, toolbar) => {
  19630. apis.refresh(toolbar);
  19631. },
  19632. toggle: (apis, toolbar) => {
  19633. apis.toggle(toolbar);
  19634. },
  19635. isOpen: (apis, toolbar) => apis.isOpen(toolbar)
  19636. }
  19637. });
  19638. const renderToolbarGroupCommon = toolbarGroup => {
  19639. const attributes = toolbarGroup.title.fold(() => ({}), title => ({ attributes: { title } }));
  19640. return {
  19641. dom: {
  19642. tag: 'div',
  19643. classes: ['tox-toolbar__group'],
  19644. ...attributes
  19645. },
  19646. components: [ToolbarGroup.parts.items({})],
  19647. items: toolbarGroup.items,
  19648. markers: { itemSelector: '*:not(.tox-split-button) > .tox-tbtn:not([disabled]), ' + '.tox-split-button:not([disabled]), ' + '.tox-toolbar-nav-js:not([disabled]), ' + '.tox-number-input:not([disabled])' },
  19649. tgroupBehaviours: derive$1([
  19650. Tabstopping.config({}),
  19651. Focusing.config({})
  19652. ])
  19653. };
  19654. };
  19655. const renderToolbarGroup = toolbarGroup => ToolbarGroup.sketch(renderToolbarGroupCommon(toolbarGroup));
  19656. const getToolbarBehaviours = (toolbarSpec, modeName) => {
  19657. const onAttached = runOnAttached(component => {
  19658. const groups = map$2(toolbarSpec.initGroups, renderToolbarGroup);
  19659. Toolbar.setGroups(component, groups);
  19660. });
  19661. return derive$1([
  19662. DisablingConfigs.toolbarButton(toolbarSpec.providers.isDisabled),
  19663. receivingConfig(),
  19664. Keying.config({
  19665. mode: modeName,
  19666. onEscape: toolbarSpec.onEscape,
  19667. selector: '.tox-toolbar__group'
  19668. }),
  19669. config('toolbar-events', [onAttached])
  19670. ]);
  19671. };
  19672. const renderMoreToolbarCommon = toolbarSpec => {
  19673. const modeName = toolbarSpec.cyclicKeying ? 'cyclic' : 'acyclic';
  19674. return {
  19675. uid: toolbarSpec.uid,
  19676. dom: {
  19677. tag: 'div',
  19678. classes: ['tox-toolbar-overlord']
  19679. },
  19680. parts: {
  19681. 'overflow-group': renderToolbarGroupCommon({
  19682. title: Optional.none(),
  19683. items: []
  19684. }),
  19685. 'overflow-button': renderIconButtonSpec({
  19686. name: 'more',
  19687. icon: Optional.some('more-drawer'),
  19688. enabled: true,
  19689. tooltip: Optional.some('More...'),
  19690. primary: false,
  19691. buttonType: Optional.none(),
  19692. borderless: false
  19693. }, Optional.none(), toolbarSpec.providers)
  19694. },
  19695. splitToolbarBehaviours: getToolbarBehaviours(toolbarSpec, modeName)
  19696. };
  19697. };
  19698. const renderFloatingMoreToolbar = toolbarSpec => {
  19699. const baseSpec = renderMoreToolbarCommon(toolbarSpec);
  19700. const overflowXOffset = 4;
  19701. const primary = SplitFloatingToolbar.parts.primary({
  19702. dom: {
  19703. tag: 'div',
  19704. classes: ['tox-toolbar__primary']
  19705. }
  19706. });
  19707. return SplitFloatingToolbar.sketch({
  19708. ...baseSpec,
  19709. lazySink: toolbarSpec.getSink,
  19710. getOverflowBounds: () => {
  19711. const headerElem = toolbarSpec.moreDrawerData.lazyHeader().element;
  19712. const headerBounds = absolute$2(headerElem);
  19713. const docElem = documentElement(headerElem);
  19714. const docBounds = absolute$2(docElem);
  19715. const height = Math.max(docElem.dom.scrollHeight, docBounds.height);
  19716. return bounds(headerBounds.x + overflowXOffset, docBounds.y, headerBounds.width - overflowXOffset * 2, height);
  19717. },
  19718. parts: {
  19719. ...baseSpec.parts,
  19720. overflow: {
  19721. dom: {
  19722. tag: 'div',
  19723. classes: ['tox-toolbar__overflow'],
  19724. attributes: toolbarSpec.attributes
  19725. }
  19726. }
  19727. },
  19728. components: [primary],
  19729. markers: { overflowToggledClass: 'tox-tbtn--enabled' },
  19730. onOpened: comp => toolbarSpec.onToggled(comp, true),
  19731. onClosed: comp => toolbarSpec.onToggled(comp, false)
  19732. });
  19733. };
  19734. const renderSlidingMoreToolbar = toolbarSpec => {
  19735. const primary = SplitSlidingToolbar.parts.primary({
  19736. dom: {
  19737. tag: 'div',
  19738. classes: ['tox-toolbar__primary']
  19739. }
  19740. });
  19741. const overflow = SplitSlidingToolbar.parts.overflow({
  19742. dom: {
  19743. tag: 'div',
  19744. classes: ['tox-toolbar__overflow']
  19745. }
  19746. });
  19747. const baseSpec = renderMoreToolbarCommon(toolbarSpec);
  19748. return SplitSlidingToolbar.sketch({
  19749. ...baseSpec,
  19750. components: [
  19751. primary,
  19752. overflow
  19753. ],
  19754. markers: {
  19755. openClass: 'tox-toolbar__overflow--open',
  19756. closedClass: 'tox-toolbar__overflow--closed',
  19757. growingClass: 'tox-toolbar__overflow--growing',
  19758. shrinkingClass: 'tox-toolbar__overflow--shrinking',
  19759. overflowToggledClass: 'tox-tbtn--enabled'
  19760. },
  19761. onOpened: comp => {
  19762. comp.getSystem().broadcastOn([toolbarHeightChange()], { type: 'opened' });
  19763. toolbarSpec.onToggled(comp, true);
  19764. },
  19765. onClosed: comp => {
  19766. comp.getSystem().broadcastOn([toolbarHeightChange()], { type: 'closed' });
  19767. toolbarSpec.onToggled(comp, false);
  19768. }
  19769. });
  19770. };
  19771. const renderToolbar = toolbarSpec => {
  19772. const modeName = toolbarSpec.cyclicKeying ? 'cyclic' : 'acyclic';
  19773. return Toolbar.sketch({
  19774. uid: toolbarSpec.uid,
  19775. dom: {
  19776. tag: 'div',
  19777. classes: ['tox-toolbar'].concat(toolbarSpec.type === ToolbarMode$1.scrolling ? ['tox-toolbar--scrolling'] : [])
  19778. },
  19779. components: [Toolbar.parts.groups({})],
  19780. toolbarBehaviours: getToolbarBehaviours(toolbarSpec, modeName)
  19781. });
  19782. };
  19783. const baseButtonFields = [
  19784. optionalText,
  19785. optionalIcon,
  19786. optionString('tooltip'),
  19787. defaultedStringEnum('buttonType', 'secondary', [
  19788. 'primary',
  19789. 'secondary'
  19790. ]),
  19791. defaultedBoolean('borderless', false),
  19792. requiredFunction('onAction')
  19793. ];
  19794. const normalButtonFields = [
  19795. ...baseButtonFields,
  19796. text$1,
  19797. requiredStringEnum('type', ['button'])
  19798. ];
  19799. const toggleButtonFields = [
  19800. ...baseButtonFields,
  19801. defaultedBoolean('active', false),
  19802. requiredStringEnum('type', ['togglebutton'])
  19803. ];
  19804. const schemaWithoutGroupButton = {
  19805. button: normalButtonFields,
  19806. togglebutton: toggleButtonFields
  19807. };
  19808. const groupFields = [
  19809. requiredStringEnum('type', ['group']),
  19810. defaultedArrayOf('buttons', [], choose$1('type', schemaWithoutGroupButton))
  19811. ];
  19812. const viewButtonSchema = choose$1('type', {
  19813. ...schemaWithoutGroupButton,
  19814. group: groupFields
  19815. });
  19816. const viewSchema = objOf([
  19817. defaultedArrayOf('buttons', [], viewButtonSchema),
  19818. requiredFunction('onShow'),
  19819. requiredFunction('onHide')
  19820. ]);
  19821. const createView = spec => asRaw('view', viewSchema, spec);
  19822. const renderButton = (spec, providers) => {
  19823. var _a, _b;
  19824. const isToggleButton = spec.type === 'togglebutton';
  19825. const optMemIcon = spec.icon.map(memIcon => renderReplaceableIconFromPack(memIcon, providers.icons)).map(record);
  19826. const getAction = () => comp => {
  19827. const setIcon = newIcon => {
  19828. optMemIcon.map(memIcon => memIcon.getOpt(comp).each(displayIcon => {
  19829. Replacing.set(displayIcon, [renderReplaceableIconFromPack(newIcon, providers.icons)]);
  19830. }));
  19831. };
  19832. const setActive = state => {
  19833. const elm = comp.element;
  19834. if (state) {
  19835. add$2(elm, 'tox-button--enabled');
  19836. set$9(elm, 'aria-pressed', true);
  19837. } else {
  19838. remove$2(elm, 'tox-button--enabled');
  19839. remove$7(elm, 'aria-pressed');
  19840. }
  19841. };
  19842. const isActive = () => has(comp.element, 'tox-button--enabled');
  19843. if (isToggleButton) {
  19844. return spec.onAction({
  19845. setIcon,
  19846. setActive,
  19847. isActive
  19848. });
  19849. }
  19850. if (spec.type === 'button') {
  19851. return spec.onAction({ setIcon });
  19852. }
  19853. };
  19854. const action = getAction();
  19855. const buttonSpec = {
  19856. ...spec,
  19857. name: isToggleButton ? spec.text.getOr(spec.icon.getOr('')) : (_a = spec.text) !== null && _a !== void 0 ? _a : spec.icon.getOr(''),
  19858. primary: spec.buttonType === 'primary',
  19859. buttonType: Optional.from(spec.buttonType),
  19860. tooltip: spec.tooltip,
  19861. icon: spec.icon,
  19862. enabled: true,
  19863. borderless: spec.borderless
  19864. };
  19865. const buttonTypeClasses = calculateClassesFromButtonType((_b = spec.buttonType) !== null && _b !== void 0 ? _b : 'secondary');
  19866. const optTranslatedText = isToggleButton ? spec.text.map(providers.translate) : Optional.some(providers.translate(spec.text));
  19867. const optTranslatedTextComponed = optTranslatedText.map(text$2);
  19868. const tooltipAttributes = buttonSpec.tooltip.or(optTranslatedText).map(tooltip => ({
  19869. 'aria-label': providers.translate(tooltip),
  19870. 'title': providers.translate(tooltip)
  19871. })).getOr({});
  19872. const optIconSpec = optMemIcon.map(memIcon => memIcon.asSpec());
  19873. const components = componentRenderPipeline([
  19874. optIconSpec,
  19875. optTranslatedTextComponed
  19876. ]);
  19877. const hasIconAndText = spec.icon.isSome() && optTranslatedTextComponed.isSome();
  19878. const dom = {
  19879. tag: 'button',
  19880. classes: buttonTypeClasses.concat(...spec.icon.isSome() && !hasIconAndText ? ['tox-button--icon'] : []).concat(...hasIconAndText ? ['tox-button--icon-and-text'] : []).concat(...spec.borderless ? ['tox-button--naked'] : []).concat(...spec.type === 'togglebutton' && spec.active ? ['tox-button--enabled'] : []),
  19881. attributes: tooltipAttributes
  19882. };
  19883. const extraBehaviours = [];
  19884. const iconButtonSpec = renderCommonSpec(buttonSpec, Optional.some(action), extraBehaviours, dom, components, providers);
  19885. return Button.sketch(iconButtonSpec);
  19886. };
  19887. const renderViewButton = (spec, providers) => renderButton(spec, providers);
  19888. const renderButtonsGroup = (spec, providers) => {
  19889. return {
  19890. dom: {
  19891. tag: 'div',
  19892. classes: ['tox-view__toolbar__group']
  19893. },
  19894. components: map$2(spec.buttons, button => renderViewButton(button, providers))
  19895. };
  19896. };
  19897. const deviceDetection = detect$2().deviceType;
  19898. const isPhone = deviceDetection.isPhone();
  19899. const isTablet = deviceDetection.isTablet();
  19900. const renderViewHeader = spec => {
  19901. let hasGroups = false;
  19902. const endButtons = map$2(spec.buttons, btnspec => {
  19903. if (btnspec.type === 'group') {
  19904. hasGroups = true;
  19905. return renderButtonsGroup(btnspec, spec.providers);
  19906. } else {
  19907. return renderViewButton(btnspec, spec.providers);
  19908. }
  19909. });
  19910. return {
  19911. uid: spec.uid,
  19912. dom: {
  19913. tag: 'div',
  19914. classes: [
  19915. !hasGroups ? 'tox-view__header' : 'tox-view__toolbar',
  19916. ...isPhone || isTablet ? [
  19917. 'tox-view--mobile',
  19918. 'tox-view--scrolling'
  19919. ] : []
  19920. ]
  19921. },
  19922. behaviours: derive$1([
  19923. Focusing.config({}),
  19924. Keying.config({
  19925. mode: 'flow',
  19926. selector: 'button, .tox-button',
  19927. focusInside: FocusInsideModes.OnEnterOrSpaceMode
  19928. })
  19929. ]),
  19930. components: hasGroups ? endButtons : [
  19931. Container.sketch({
  19932. dom: {
  19933. tag: 'div',
  19934. classes: ['tox-view__header-start']
  19935. },
  19936. components: []
  19937. }),
  19938. Container.sketch({
  19939. dom: {
  19940. tag: 'div',
  19941. classes: ['tox-view__header-end']
  19942. },
  19943. components: endButtons
  19944. })
  19945. ]
  19946. };
  19947. };
  19948. const renderViewPane = spec => {
  19949. return {
  19950. uid: spec.uid,
  19951. dom: {
  19952. tag: 'div',
  19953. classes: ['tox-view__pane']
  19954. }
  19955. };
  19956. };
  19957. const factory$8 = (detail, components, _spec, _externals) => {
  19958. const apis = {
  19959. getPane: comp => parts$a.getPart(comp, detail, 'pane'),
  19960. getOnShow: _comp => detail.viewConfig.onShow,
  19961. getOnHide: _comp => detail.viewConfig.onHide
  19962. };
  19963. return {
  19964. uid: detail.uid,
  19965. dom: detail.dom,
  19966. components,
  19967. apis
  19968. };
  19969. };
  19970. var View = composite({
  19971. name: 'silver.View',
  19972. configFields: [required$1('viewConfig')],
  19973. partFields: [
  19974. optional({
  19975. factory: { sketch: renderViewHeader },
  19976. schema: [
  19977. required$1('buttons'),
  19978. required$1('providers')
  19979. ],
  19980. name: 'header'
  19981. }),
  19982. optional({
  19983. factory: { sketch: renderViewPane },
  19984. schema: [],
  19985. name: 'pane'
  19986. })
  19987. ],
  19988. factory: factory$8,
  19989. apis: {
  19990. getPane: (apis, comp) => apis.getPane(comp),
  19991. getOnShow: (apis, comp) => apis.getOnShow(comp),
  19992. getOnHide: (apis, comp) => apis.getOnHide(comp)
  19993. }
  19994. });
  19995. const makeViews = (parts, viewConfigs, providers) => {
  19996. return mapToArray(viewConfigs, (config, name) => {
  19997. const internalViewConfig = getOrDie(createView(config));
  19998. return parts.slot(name, View.sketch({
  19999. dom: {
  20000. tag: 'div',
  20001. classes: ['tox-view']
  20002. },
  20003. viewConfig: internalViewConfig,
  20004. components: [
  20005. ...internalViewConfig.buttons.length > 0 ? [View.parts.header({
  20006. buttons: internalViewConfig.buttons,
  20007. providers
  20008. })] : [],
  20009. View.parts.pane({})
  20010. ]
  20011. }));
  20012. });
  20013. };
  20014. const makeSlotContainer = (viewConfigs, providers) => SlotContainer.sketch(parts => ({
  20015. dom: {
  20016. tag: 'div',
  20017. classes: ['tox-view-wrap__slot-container']
  20018. },
  20019. components: makeViews(parts, viewConfigs, providers),
  20020. slotBehaviours: SimpleBehaviours.unnamedEvents([runOnAttached(slotContainer => SlotContainer.hideAllSlots(slotContainer))])
  20021. }));
  20022. const getCurrentName = slotContainer => {
  20023. return find$5(SlotContainer.getSlotNames(slotContainer), name => SlotContainer.isShowing(slotContainer, name));
  20024. };
  20025. const hideContainer = comp => {
  20026. const element = comp.element;
  20027. set$8(element, 'display', 'none');
  20028. set$9(element, 'aria-hidden', 'true');
  20029. };
  20030. const showContainer = comp => {
  20031. const element = comp.element;
  20032. remove$6(element, 'display');
  20033. remove$7(element, 'aria-hidden');
  20034. };
  20035. const makeViewInstanceApi = slot => ({ getContainer: constant$1(slot) });
  20036. const runOnPaneWithInstanceApi = (slotContainer, name, get) => {
  20037. SlotContainer.getSlot(slotContainer, name).each(view => {
  20038. View.getPane(view).each(pane => {
  20039. const onCallback = get(view);
  20040. onCallback(makeViewInstanceApi(pane.element.dom));
  20041. });
  20042. });
  20043. };
  20044. const runOnShow = (slotContainer, name) => runOnPaneWithInstanceApi(slotContainer, name, View.getOnShow);
  20045. const runOnHide = (slotContainer, name) => runOnPaneWithInstanceApi(slotContainer, name, View.getOnHide);
  20046. const factory$7 = (detail, spec) => {
  20047. const setViews = (comp, viewConfigs) => {
  20048. Replacing.set(comp, [makeSlotContainer(viewConfigs, spec.backstage.shared.providers)]);
  20049. };
  20050. const whichView = comp => {
  20051. return Composing.getCurrent(comp).bind(getCurrentName);
  20052. };
  20053. const toggleView = (comp, showMainView, hideMainView, name) => {
  20054. return Composing.getCurrent(comp).exists(slotContainer => {
  20055. const optCurrentSlotName = getCurrentName(slotContainer);
  20056. const isTogglingCurrentView = optCurrentSlotName.exists(current => name === current);
  20057. const exists = SlotContainer.getSlot(slotContainer, name).isSome();
  20058. if (exists) {
  20059. SlotContainer.hideAllSlots(slotContainer);
  20060. if (!isTogglingCurrentView) {
  20061. hideMainView();
  20062. showContainer(comp);
  20063. SlotContainer.showSlot(slotContainer, name);
  20064. runOnShow(slotContainer, name);
  20065. } else {
  20066. hideContainer(comp);
  20067. showMainView();
  20068. }
  20069. optCurrentSlotName.each(prevName => runOnHide(slotContainer, prevName));
  20070. }
  20071. return exists;
  20072. });
  20073. };
  20074. const apis = {
  20075. setViews,
  20076. whichView,
  20077. toggleView
  20078. };
  20079. return {
  20080. uid: detail.uid,
  20081. dom: {
  20082. tag: 'div',
  20083. classes: ['tox-view-wrap'],
  20084. attributes: { 'aria-hidden': 'true' },
  20085. styles: { display: 'none' }
  20086. },
  20087. components: [],
  20088. behaviours: derive$1([
  20089. Replacing.config({}),
  20090. Composing.config({
  20091. find: comp => {
  20092. const children = Replacing.contents(comp);
  20093. return head(children);
  20094. }
  20095. })
  20096. ]),
  20097. apis
  20098. };
  20099. };
  20100. var ViewWrapper = single({
  20101. factory: factory$7,
  20102. name: 'silver.ViewWrapper',
  20103. configFields: [required$1('backstage')],
  20104. apis: {
  20105. setViews: (apis, comp, views) => apis.setViews(comp, views),
  20106. toggleView: (apis, comp, outerContainer, editorCont, name) => apis.toggleView(comp, outerContainer, editorCont, name),
  20107. whichView: (apis, comp) => apis.whichView(comp)
  20108. }
  20109. });
  20110. const factory$6 = (detail, components, _spec) => {
  20111. let toolbarDrawerOpenState = false;
  20112. const apis = {
  20113. getSocket: comp => {
  20114. return parts$a.getPart(comp, detail, 'socket');
  20115. },
  20116. setSidebar: (comp, panelConfigs, showSidebar) => {
  20117. parts$a.getPart(comp, detail, 'sidebar').each(sidebar => setSidebar(sidebar, panelConfigs, showSidebar));
  20118. },
  20119. toggleSidebar: (comp, name) => {
  20120. parts$a.getPart(comp, detail, 'sidebar').each(sidebar => toggleSidebar(sidebar, name));
  20121. },
  20122. whichSidebar: comp => {
  20123. return parts$a.getPart(comp, detail, 'sidebar').bind(whichSidebar).getOrNull();
  20124. },
  20125. getHeader: comp => {
  20126. return parts$a.getPart(comp, detail, 'header');
  20127. },
  20128. getToolbar: comp => {
  20129. return parts$a.getPart(comp, detail, 'toolbar');
  20130. },
  20131. setToolbar: (comp, groups) => {
  20132. parts$a.getPart(comp, detail, 'toolbar').each(toolbar => {
  20133. const renderedGroups = map$2(groups, renderToolbarGroup);
  20134. toolbar.getApis().setGroups(toolbar, renderedGroups);
  20135. });
  20136. },
  20137. setToolbars: (comp, toolbars) => {
  20138. parts$a.getPart(comp, detail, 'multiple-toolbar').each(mToolbar => {
  20139. const renderedToolbars = map$2(toolbars, g => map$2(g, renderToolbarGroup));
  20140. CustomList.setItems(mToolbar, renderedToolbars);
  20141. });
  20142. },
  20143. refreshToolbar: comp => {
  20144. const toolbar = parts$a.getPart(comp, detail, 'toolbar');
  20145. toolbar.each(toolbar => toolbar.getApis().refresh(toolbar));
  20146. },
  20147. toggleToolbarDrawer: comp => {
  20148. parts$a.getPart(comp, detail, 'toolbar').each(toolbar => {
  20149. mapFrom(toolbar.getApis().toggle, toggle => toggle(toolbar));
  20150. });
  20151. },
  20152. toggleToolbarDrawerWithoutFocusing: comp => {
  20153. parts$a.getPart(comp, detail, 'toolbar').each(toolbar => {
  20154. mapFrom(toolbar.getApis().toggleWithoutFocusing, toggleWithoutFocusing => toggleWithoutFocusing(toolbar));
  20155. });
  20156. },
  20157. isToolbarDrawerToggled: comp => {
  20158. return parts$a.getPart(comp, detail, 'toolbar').bind(toolbar => Optional.from(toolbar.getApis().isOpen).map(isOpen => isOpen(toolbar))).getOr(false);
  20159. },
  20160. getThrobber: comp => {
  20161. return parts$a.getPart(comp, detail, 'throbber');
  20162. },
  20163. focusToolbar: comp => {
  20164. const optToolbar = parts$a.getPart(comp, detail, 'toolbar').orThunk(() => parts$a.getPart(comp, detail, 'multiple-toolbar'));
  20165. optToolbar.each(toolbar => {
  20166. Keying.focusIn(toolbar);
  20167. });
  20168. },
  20169. setMenubar: (comp, menus) => {
  20170. parts$a.getPart(comp, detail, 'menubar').each(menubar => {
  20171. SilverMenubar.setMenus(menubar, menus);
  20172. });
  20173. },
  20174. focusMenubar: comp => {
  20175. parts$a.getPart(comp, detail, 'menubar').each(menubar => {
  20176. SilverMenubar.focus(menubar);
  20177. });
  20178. },
  20179. setViews: (comp, viewConfigs) => {
  20180. parts$a.getPart(comp, detail, 'viewWrapper').each(wrapper => {
  20181. ViewWrapper.setViews(wrapper, viewConfigs);
  20182. });
  20183. },
  20184. toggleView: (comp, name) => {
  20185. return parts$a.getPart(comp, detail, 'viewWrapper').exists(wrapper => ViewWrapper.toggleView(wrapper, () => apis.showMainView(comp), () => apis.hideMainView(comp), name));
  20186. },
  20187. whichView: comp => {
  20188. return parts$a.getPart(comp, detail, 'viewWrapper').bind(ViewWrapper.whichView).getOrNull();
  20189. },
  20190. hideMainView: comp => {
  20191. toolbarDrawerOpenState = apis.isToolbarDrawerToggled(comp);
  20192. if (toolbarDrawerOpenState) {
  20193. apis.toggleToolbarDrawer(comp);
  20194. }
  20195. parts$a.getPart(comp, detail, 'editorContainer').each(editorContainer => {
  20196. const element = editorContainer.element;
  20197. set$8(element, 'display', 'none');
  20198. set$9(element, 'aria-hidden', 'true');
  20199. });
  20200. },
  20201. showMainView: comp => {
  20202. if (toolbarDrawerOpenState) {
  20203. apis.toggleToolbarDrawer(comp);
  20204. }
  20205. parts$a.getPart(comp, detail, 'editorContainer').each(editorContainer => {
  20206. const element = editorContainer.element;
  20207. remove$6(element, 'display');
  20208. remove$7(element, 'aria-hidden');
  20209. });
  20210. apis.refreshToolbar(comp);
  20211. }
  20212. };
  20213. return {
  20214. uid: detail.uid,
  20215. dom: detail.dom,
  20216. components,
  20217. apis,
  20218. behaviours: detail.behaviours
  20219. };
  20220. };
  20221. const partMenubar = partType.optional({
  20222. factory: SilverMenubar,
  20223. name: 'menubar',
  20224. schema: [required$1('backstage')]
  20225. });
  20226. const toolbarFactory = spec => {
  20227. if (spec.type === ToolbarMode$1.sliding) {
  20228. return renderSlidingMoreToolbar;
  20229. } else if (spec.type === ToolbarMode$1.floating) {
  20230. return renderFloatingMoreToolbar;
  20231. } else {
  20232. return renderToolbar;
  20233. }
  20234. };
  20235. const partMultipleToolbar = partType.optional({
  20236. factory: {
  20237. sketch: spec => CustomList.sketch({
  20238. uid: spec.uid,
  20239. dom: spec.dom,
  20240. listBehaviours: derive$1([Keying.config({
  20241. mode: 'acyclic',
  20242. selector: '.tox-toolbar'
  20243. })]),
  20244. makeItem: () => renderToolbar({
  20245. type: spec.type,
  20246. uid: generate$6('multiple-toolbar-item'),
  20247. cyclicKeying: false,
  20248. initGroups: [],
  20249. providers: spec.providers,
  20250. onEscape: () => {
  20251. spec.onEscape();
  20252. return Optional.some(true);
  20253. }
  20254. }),
  20255. setupItem: (_mToolbar, tc, data, _index) => {
  20256. Toolbar.setGroups(tc, data);
  20257. },
  20258. shell: true
  20259. })
  20260. },
  20261. name: 'multiple-toolbar',
  20262. schema: [
  20263. required$1('dom'),
  20264. required$1('onEscape')
  20265. ]
  20266. });
  20267. const partToolbar = partType.optional({
  20268. factory: {
  20269. sketch: spec => {
  20270. const renderer = toolbarFactory(spec);
  20271. const toolbarSpec = {
  20272. type: spec.type,
  20273. uid: spec.uid,
  20274. onEscape: () => {
  20275. spec.onEscape();
  20276. return Optional.some(true);
  20277. },
  20278. onToggled: (_comp, state) => spec.onToolbarToggled(state),
  20279. cyclicKeying: false,
  20280. initGroups: [],
  20281. getSink: spec.getSink,
  20282. providers: spec.providers,
  20283. moreDrawerData: {
  20284. lazyToolbar: spec.lazyToolbar,
  20285. lazyMoreButton: spec.lazyMoreButton,
  20286. lazyHeader: spec.lazyHeader
  20287. },
  20288. attributes: spec.attributes
  20289. };
  20290. return renderer(toolbarSpec);
  20291. }
  20292. },
  20293. name: 'toolbar',
  20294. schema: [
  20295. required$1('dom'),
  20296. required$1('onEscape'),
  20297. required$1('getSink')
  20298. ]
  20299. });
  20300. const partHeader = partType.optional({
  20301. factory: { sketch: renderHeader },
  20302. name: 'header',
  20303. schema: [required$1('dom')]
  20304. });
  20305. const partPromotion = partType.optional({
  20306. factory: { sketch: renderPromotion },
  20307. name: 'promotion',
  20308. schema: [required$1('dom')]
  20309. });
  20310. const partSocket = partType.optional({
  20311. name: 'socket',
  20312. schema: [required$1('dom')]
  20313. });
  20314. const partSidebar = partType.optional({
  20315. factory: { sketch: renderSidebar },
  20316. name: 'sidebar',
  20317. schema: [required$1('dom')]
  20318. });
  20319. const partThrobber = partType.optional({
  20320. factory: { sketch: renderThrobber },
  20321. name: 'throbber',
  20322. schema: [required$1('dom')]
  20323. });
  20324. const partViewWrapper = partType.optional({
  20325. factory: ViewWrapper,
  20326. name: 'viewWrapper',
  20327. schema: [required$1('backstage')]
  20328. });
  20329. const renderEditorContainer = spec => ({
  20330. uid: spec.uid,
  20331. dom: {
  20332. tag: 'div',
  20333. classes: ['tox-editor-container']
  20334. },
  20335. components: spec.components
  20336. });
  20337. const partEditorContainer = partType.optional({
  20338. factory: { sketch: renderEditorContainer },
  20339. name: 'editorContainer',
  20340. schema: []
  20341. });
  20342. var OuterContainer = composite({
  20343. name: 'OuterContainer',
  20344. factory: factory$6,
  20345. configFields: [
  20346. required$1('dom'),
  20347. required$1('behaviours')
  20348. ],
  20349. partFields: [
  20350. partHeader,
  20351. partMenubar,
  20352. partToolbar,
  20353. partMultipleToolbar,
  20354. partSocket,
  20355. partSidebar,
  20356. partPromotion,
  20357. partThrobber,
  20358. partViewWrapper,
  20359. partEditorContainer
  20360. ],
  20361. apis: {
  20362. getSocket: (apis, comp) => {
  20363. return apis.getSocket(comp);
  20364. },
  20365. setSidebar: (apis, comp, panelConfigs, showSidebar) => {
  20366. apis.setSidebar(comp, panelConfigs, showSidebar);
  20367. },
  20368. toggleSidebar: (apis, comp, name) => {
  20369. apis.toggleSidebar(comp, name);
  20370. },
  20371. whichSidebar: (apis, comp) => {
  20372. return apis.whichSidebar(comp);
  20373. },
  20374. getHeader: (apis, comp) => {
  20375. return apis.getHeader(comp);
  20376. },
  20377. getToolbar: (apis, comp) => {
  20378. return apis.getToolbar(comp);
  20379. },
  20380. setToolbar: (apis, comp, groups) => {
  20381. apis.setToolbar(comp, groups);
  20382. },
  20383. setToolbars: (apis, comp, toolbars) => {
  20384. apis.setToolbars(comp, toolbars);
  20385. },
  20386. refreshToolbar: (apis, comp) => {
  20387. return apis.refreshToolbar(comp);
  20388. },
  20389. toggleToolbarDrawer: (apis, comp) => {
  20390. apis.toggleToolbarDrawer(comp);
  20391. },
  20392. toggleToolbarDrawerWithoutFocusing: (apis, comp) => {
  20393. apis.toggleToolbarDrawerWithoutFocusing(comp);
  20394. },
  20395. isToolbarDrawerToggled: (apis, comp) => {
  20396. return apis.isToolbarDrawerToggled(comp);
  20397. },
  20398. getThrobber: (apis, comp) => {
  20399. return apis.getThrobber(comp);
  20400. },
  20401. setMenubar: (apis, comp, menus) => {
  20402. apis.setMenubar(comp, menus);
  20403. },
  20404. focusMenubar: (apis, comp) => {
  20405. apis.focusMenubar(comp);
  20406. },
  20407. focusToolbar: (apis, comp) => {
  20408. apis.focusToolbar(comp);
  20409. },
  20410. setViews: (apis, comp, views) => {
  20411. apis.setViews(comp, views);
  20412. },
  20413. toggleView: (apis, comp, name) => {
  20414. return apis.toggleView(comp, name);
  20415. },
  20416. whichView: (apis, comp) => {
  20417. return apis.whichView(comp);
  20418. }
  20419. }
  20420. });
  20421. const defaultMenubar = 'file edit view insert format tools table help';
  20422. const defaultMenus = {
  20423. file: {
  20424. title: 'File',
  20425. items: 'newdocument restoredraft | preview | export print | deleteallconversations'
  20426. },
  20427. edit: {
  20428. title: 'Edit',
  20429. items: 'undo redo | cut copy paste pastetext | selectall | searchreplace'
  20430. },
  20431. view: {
  20432. title: 'View',
  20433. items: 'code | visualaid visualchars visualblocks | spellchecker | preview fullscreen | showcomments'
  20434. },
  20435. insert: {
  20436. title: 'Insert',
  20437. items: 'image link media addcomment pageembed template inserttemplate codesample inserttable | charmap emoticons hr | pagebreak nonbreaking anchor tableofcontents footnotes | mergetags | insertdatetime'
  20438. },
  20439. format: {
  20440. title: 'Format',
  20441. items: 'bold italic underline strikethrough superscript subscript codeformat | styles blocks fontfamily fontsize align lineheight | forecolor backcolor | language | removeformat'
  20442. },
  20443. tools: {
  20444. title: 'Tools',
  20445. items: 'spellchecker spellcheckerlanguage | autocorrect capitalization | a11ycheck code typography wordcount addtemplate'
  20446. },
  20447. table: {
  20448. title: 'Table',
  20449. items: 'inserttable | cell row column | advtablesort | tableprops deletetable'
  20450. },
  20451. help: {
  20452. title: 'Help',
  20453. items: 'help'
  20454. }
  20455. };
  20456. const make = (menu, registry, editor) => {
  20457. const removedMenuItems = getRemovedMenuItems(editor).split(/[ ,]/);
  20458. return {
  20459. text: menu.title,
  20460. getItems: () => bind$3(menu.items, i => {
  20461. const itemName = i.toLowerCase();
  20462. if (itemName.trim().length === 0) {
  20463. return [];
  20464. } else if (exists(removedMenuItems, removedMenuItem => removedMenuItem === itemName)) {
  20465. return [];
  20466. } else if (itemName === 'separator' || itemName === '|') {
  20467. return [{ type: 'separator' }];
  20468. } else if (registry.menuItems[itemName]) {
  20469. return [registry.menuItems[itemName]];
  20470. } else {
  20471. return [];
  20472. }
  20473. })
  20474. };
  20475. };
  20476. const parseItemsString = items => {
  20477. return items.split(' ');
  20478. };
  20479. const identifyMenus = (editor, registry) => {
  20480. const rawMenuData = {
  20481. ...defaultMenus,
  20482. ...registry.menus
  20483. };
  20484. const userDefinedMenus = keys(registry.menus).length > 0;
  20485. const menubar = registry.menubar === undefined || registry.menubar === true ? parseItemsString(defaultMenubar) : parseItemsString(registry.menubar === false ? '' : registry.menubar);
  20486. const validMenus = filter$2(menubar, menuName => {
  20487. const isDefaultMenu = has$2(defaultMenus, menuName);
  20488. if (userDefinedMenus) {
  20489. return isDefaultMenu || get$g(registry.menus, menuName).exists(menu => has$2(menu, 'items'));
  20490. } else {
  20491. return isDefaultMenu;
  20492. }
  20493. });
  20494. const menus = map$2(validMenus, menuName => {
  20495. const menuData = rawMenuData[menuName];
  20496. return make({
  20497. title: menuData.title,
  20498. items: parseItemsString(menuData.items)
  20499. }, registry, editor);
  20500. });
  20501. return filter$2(menus, menu => {
  20502. const isNotSeparator = item => isString(item) || item.type !== 'separator';
  20503. return menu.getItems().length > 0 && exists(menu.getItems(), isNotSeparator);
  20504. });
  20505. };
  20506. const fireSkinLoaded = editor => {
  20507. const done = () => {
  20508. editor._skinLoaded = true;
  20509. fireSkinLoaded$1(editor);
  20510. };
  20511. return () => {
  20512. if (editor.initialized) {
  20513. done();
  20514. } else {
  20515. editor.on('init', done);
  20516. }
  20517. };
  20518. };
  20519. const fireSkinLoadError = (editor, err) => () => fireSkinLoadError$1(editor, { message: err });
  20520. const loadStylesheet = (editor, stylesheetUrl, styleSheetLoader) => {
  20521. editor.on('remove', () => styleSheetLoader.unload(stylesheetUrl));
  20522. return styleSheetLoader.load(stylesheetUrl);
  20523. };
  20524. const loadUiSkins = (editor, skinUrl) => {
  20525. const skinUiCss = skinUrl + '/skin.min.css';
  20526. return loadStylesheet(editor, skinUiCss, editor.ui.styleSheetLoader);
  20527. };
  20528. const loadShadowDomUiSkins = (editor, skinUrl) => {
  20529. const isInShadowRoot$1 = isInShadowRoot(SugarElement.fromDom(editor.getElement()));
  20530. if (isInShadowRoot$1) {
  20531. const shadowDomSkinCss = skinUrl + '/skin.shadowdom.min.css';
  20532. return loadStylesheet(editor, shadowDomSkinCss, global$7.DOM.styleSheetLoader);
  20533. } else {
  20534. return Promise.resolve();
  20535. }
  20536. };
  20537. const loadSkin = (isInline, editor) => {
  20538. const skinUrl = getSkinUrl(editor);
  20539. if (skinUrl) {
  20540. editor.contentCSS.push(skinUrl + (isInline ? '/content.inline' : '/content') + '.min.css');
  20541. }
  20542. if (!isSkinDisabled(editor) && isString(skinUrl)) {
  20543. return Promise.all([
  20544. loadUiSkins(editor, skinUrl),
  20545. loadShadowDomUiSkins(editor, skinUrl)
  20546. ]).then(fireSkinLoaded(editor), fireSkinLoadError(editor, 'Skin could not be loaded'));
  20547. } else {
  20548. return Promise.resolve(fireSkinLoaded(editor)());
  20549. }
  20550. };
  20551. const iframe = curry(loadSkin, false);
  20552. const inline = curry(loadSkin, true);
  20553. const onSetupFormatToggle = (editor, name) => api => {
  20554. const boundCallback = unbindable();
  20555. const init = () => {
  20556. api.setActive(editor.formatter.match(name));
  20557. const binding = editor.formatter.formatChanged(name, api.setActive);
  20558. boundCallback.set(binding);
  20559. };
  20560. editor.initialized ? init() : editor.once('init', init);
  20561. return () => {
  20562. editor.off('init', init);
  20563. boundCallback.clear();
  20564. };
  20565. };
  20566. const onSetupEvent = (editor, event, f) => api => {
  20567. const handleEvent = () => f(api);
  20568. const init = () => {
  20569. f(api);
  20570. editor.on(event, handleEvent);
  20571. };
  20572. editor.initialized ? init() : editor.once('init', init);
  20573. return () => {
  20574. editor.off('init', init);
  20575. editor.off(event, handleEvent);
  20576. };
  20577. };
  20578. const onActionToggleFormat$1 = editor => rawItem => () => {
  20579. editor.undoManager.transact(() => {
  20580. editor.focus();
  20581. editor.execCommand('mceToggleFormat', false, rawItem.format);
  20582. });
  20583. };
  20584. const onActionExecCommand = (editor, command) => () => editor.execCommand(command);
  20585. const generateSelectItems = (_editor, backstage, spec) => {
  20586. const generateItem = (rawItem, response, invalid, value) => {
  20587. const translatedText = backstage.shared.providers.translate(rawItem.title);
  20588. if (rawItem.type === 'separator') {
  20589. return Optional.some({
  20590. type: 'separator',
  20591. text: translatedText
  20592. });
  20593. } else if (rawItem.type === 'submenu') {
  20594. const items = bind$3(rawItem.getStyleItems(), si => validate(si, response, value));
  20595. if (response === 0 && items.length <= 0) {
  20596. return Optional.none();
  20597. } else {
  20598. return Optional.some({
  20599. type: 'nestedmenuitem',
  20600. text: translatedText,
  20601. enabled: items.length > 0,
  20602. getSubmenuItems: () => bind$3(rawItem.getStyleItems(), si => validate(si, response, value))
  20603. });
  20604. }
  20605. } else {
  20606. return Optional.some({
  20607. type: 'togglemenuitem',
  20608. text: translatedText,
  20609. icon: rawItem.icon,
  20610. active: rawItem.isSelected(value),
  20611. enabled: !invalid,
  20612. onAction: spec.onAction(rawItem),
  20613. ...rawItem.getStylePreview().fold(() => ({}), preview => ({ meta: { style: preview } }))
  20614. });
  20615. }
  20616. };
  20617. const validate = (item, response, value) => {
  20618. const invalid = item.type === 'formatter' && spec.isInvalid(item);
  20619. if (response === 0) {
  20620. return invalid ? [] : generateItem(item, response, false, value).toArray();
  20621. } else {
  20622. return generateItem(item, response, invalid, value).toArray();
  20623. }
  20624. };
  20625. const validateItems = preItems => {
  20626. const value = spec.getCurrentValue();
  20627. const response = spec.shouldHide ? 0 : 1;
  20628. return bind$3(preItems, item => validate(item, response, value));
  20629. };
  20630. const getFetch = (backstage, getStyleItems) => (comp, callback) => {
  20631. const preItems = getStyleItems();
  20632. const items = validateItems(preItems);
  20633. const menu = build(items, ItemResponse$1.CLOSE_ON_EXECUTE, backstage, {
  20634. isHorizontalMenu: false,
  20635. search: Optional.none()
  20636. });
  20637. callback(menu);
  20638. };
  20639. return {
  20640. validateItems,
  20641. getFetch
  20642. };
  20643. };
  20644. const createMenuItems = (editor, backstage, spec) => {
  20645. const dataset = spec.dataset;
  20646. const getStyleItems = dataset.type === 'basic' ? () => map$2(dataset.data, d => processBasic(d, spec.isSelectedFor, spec.getPreviewFor)) : dataset.getData;
  20647. return {
  20648. items: generateSelectItems(editor, backstage, spec),
  20649. getStyleItems
  20650. };
  20651. };
  20652. const createSelectButton = (editor, backstage, spec) => {
  20653. const {items, getStyleItems} = createMenuItems(editor, backstage, spec);
  20654. const getApi = comp => ({ getComponent: constant$1(comp) });
  20655. const onSetup = onSetupEvent(editor, 'NodeChange', api => {
  20656. const comp = api.getComponent();
  20657. spec.updateText(comp);
  20658. });
  20659. return renderCommonDropdown({
  20660. text: spec.icon.isSome() ? Optional.none() : spec.text,
  20661. icon: spec.icon,
  20662. tooltip: Optional.from(spec.tooltip),
  20663. role: Optional.none(),
  20664. fetch: items.getFetch(backstage, getStyleItems),
  20665. onSetup,
  20666. getApi,
  20667. columns: 1,
  20668. presets: 'normal',
  20669. classes: spec.icon.isSome() ? [] : ['bespoke'],
  20670. dropdownBehaviours: []
  20671. }, 'tox-tbtn', backstage.shared);
  20672. };
  20673. const process = rawFormats => map$2(rawFormats, item => {
  20674. let title = item, format = item;
  20675. const values = item.split('=');
  20676. if (values.length > 1) {
  20677. title = values[0];
  20678. format = values[1];
  20679. }
  20680. return {
  20681. title,
  20682. format
  20683. };
  20684. });
  20685. const buildBasicStaticDataset = data => ({
  20686. type: 'basic',
  20687. data
  20688. });
  20689. var Delimiter;
  20690. (function (Delimiter) {
  20691. Delimiter[Delimiter['SemiColon'] = 0] = 'SemiColon';
  20692. Delimiter[Delimiter['Space'] = 1] = 'Space';
  20693. }(Delimiter || (Delimiter = {})));
  20694. const split = (rawFormats, delimiter) => {
  20695. if (delimiter === Delimiter.SemiColon) {
  20696. return rawFormats.replace(/;$/, '').split(';');
  20697. } else {
  20698. return rawFormats.split(' ');
  20699. }
  20700. };
  20701. const buildBasicSettingsDataset = (editor, settingName, delimiter) => {
  20702. const rawFormats = editor.options.get(settingName);
  20703. const data = process(split(rawFormats, delimiter));
  20704. return {
  20705. type: 'basic',
  20706. data
  20707. };
  20708. };
  20709. const alignMenuItems = [
  20710. {
  20711. title: 'Left',
  20712. icon: 'align-left',
  20713. format: 'alignleft',
  20714. command: 'JustifyLeft'
  20715. },
  20716. {
  20717. title: 'Center',
  20718. icon: 'align-center',
  20719. format: 'aligncenter',
  20720. command: 'JustifyCenter'
  20721. },
  20722. {
  20723. title: 'Right',
  20724. icon: 'align-right',
  20725. format: 'alignright',
  20726. command: 'JustifyRight'
  20727. },
  20728. {
  20729. title: 'Justify',
  20730. icon: 'align-justify',
  20731. format: 'alignjustify',
  20732. command: 'JustifyFull'
  20733. }
  20734. ];
  20735. const getSpec$4 = editor => {
  20736. const getMatchingValue = () => find$5(alignMenuItems, item => editor.formatter.match(item.format));
  20737. const isSelectedFor = format => () => editor.formatter.match(format);
  20738. const getPreviewFor = _format => Optional.none;
  20739. const updateSelectMenuIcon = comp => {
  20740. const match = getMatchingValue();
  20741. const alignment = match.fold(constant$1('left'), item => item.title.toLowerCase());
  20742. emitWith(comp, updateMenuIcon, { icon: `align-${ alignment }` });
  20743. };
  20744. const dataset = buildBasicStaticDataset(alignMenuItems);
  20745. const onAction = rawItem => () => find$5(alignMenuItems, item => item.format === rawItem.format).each(item => editor.execCommand(item.command));
  20746. return {
  20747. tooltip: 'Align',
  20748. text: Optional.none(),
  20749. icon: Optional.some('align-left'),
  20750. isSelectedFor,
  20751. getCurrentValue: Optional.none,
  20752. getPreviewFor,
  20753. onAction,
  20754. updateText: updateSelectMenuIcon,
  20755. dataset,
  20756. shouldHide: false,
  20757. isInvalid: item => !editor.formatter.canApply(item.format)
  20758. };
  20759. };
  20760. const createAlignButton = (editor, backstage) => createSelectButton(editor, backstage, getSpec$4(editor));
  20761. const createAlignMenu = (editor, backstage) => {
  20762. const menuItems = createMenuItems(editor, backstage, getSpec$4(editor));
  20763. editor.ui.registry.addNestedMenuItem('align', {
  20764. text: backstage.shared.providers.translate('Align'),
  20765. getSubmenuItems: () => menuItems.items.validateItems(menuItems.getStyleItems())
  20766. });
  20767. };
  20768. const findNearest = (editor, getStyles) => {
  20769. const styles = getStyles();
  20770. const formats = map$2(styles, style => style.format);
  20771. return Optional.from(editor.formatter.closest(formats)).bind(fmt => find$5(styles, data => data.format === fmt)).orThunk(() => someIf(editor.formatter.match('p'), {
  20772. title: 'Paragraph',
  20773. format: 'p'
  20774. }));
  20775. };
  20776. const getSpec$3 = editor => {
  20777. const fallbackFormat = 'Paragraph';
  20778. const isSelectedFor = format => () => editor.formatter.match(format);
  20779. const getPreviewFor = format => () => {
  20780. const fmt = editor.formatter.get(format);
  20781. if (fmt) {
  20782. return Optional.some({
  20783. tag: fmt.length > 0 ? fmt[0].inline || fmt[0].block || 'div' : 'div',
  20784. styles: editor.dom.parseStyle(editor.formatter.getCssText(format))
  20785. });
  20786. } else {
  20787. return Optional.none();
  20788. }
  20789. };
  20790. const updateSelectMenuText = comp => {
  20791. const detectedFormat = findNearest(editor, () => dataset.data);
  20792. const text = detectedFormat.fold(constant$1(fallbackFormat), fmt => fmt.title);
  20793. emitWith(comp, updateMenuText, { text });
  20794. };
  20795. const dataset = buildBasicSettingsDataset(editor, 'block_formats', Delimiter.SemiColon);
  20796. return {
  20797. tooltip: 'Blocks',
  20798. text: Optional.some(fallbackFormat),
  20799. icon: Optional.none(),
  20800. isSelectedFor,
  20801. getCurrentValue: Optional.none,
  20802. getPreviewFor,
  20803. onAction: onActionToggleFormat$1(editor),
  20804. updateText: updateSelectMenuText,
  20805. dataset,
  20806. shouldHide: false,
  20807. isInvalid: item => !editor.formatter.canApply(item.format)
  20808. };
  20809. };
  20810. const createBlocksButton = (editor, backstage) => createSelectButton(editor, backstage, getSpec$3(editor));
  20811. const createBlocksMenu = (editor, backstage) => {
  20812. const menuItems = createMenuItems(editor, backstage, getSpec$3(editor));
  20813. editor.ui.registry.addNestedMenuItem('blocks', {
  20814. text: 'Blocks',
  20815. getSubmenuItems: () => menuItems.items.validateItems(menuItems.getStyleItems())
  20816. });
  20817. };
  20818. const systemStackFonts = [
  20819. '-apple-system',
  20820. 'Segoe UI',
  20821. 'Roboto',
  20822. 'Helvetica Neue',
  20823. 'sans-serif'
  20824. ];
  20825. const splitFonts = fontFamily => {
  20826. const fonts = fontFamily.split(/\s*,\s*/);
  20827. return map$2(fonts, font => font.replace(/^['"]+|['"]+$/g, ''));
  20828. };
  20829. const isSystemFontStack = fontFamily => {
  20830. const matchesSystemStack = () => {
  20831. const fonts = splitFonts(fontFamily.toLowerCase());
  20832. return forall(systemStackFonts, font => fonts.indexOf(font.toLowerCase()) > -1);
  20833. };
  20834. return fontFamily.indexOf('-apple-system') === 0 && matchesSystemStack();
  20835. };
  20836. const getSpec$2 = editor => {
  20837. const systemFont = 'System Font';
  20838. const getMatchingValue = () => {
  20839. const getFirstFont = fontFamily => fontFamily ? splitFonts(fontFamily)[0] : '';
  20840. const fontFamily = editor.queryCommandValue('FontName');
  20841. const items = dataset.data;
  20842. const font = fontFamily ? fontFamily.toLowerCase() : '';
  20843. const matchOpt = find$5(items, item => {
  20844. const format = item.format;
  20845. return format.toLowerCase() === font || getFirstFont(format).toLowerCase() === getFirstFont(font).toLowerCase();
  20846. }).orThunk(() => {
  20847. return someIf(isSystemFontStack(font), {
  20848. title: systemFont,
  20849. format: font
  20850. });
  20851. });
  20852. return {
  20853. matchOpt,
  20854. font: fontFamily
  20855. };
  20856. };
  20857. const isSelectedFor = item => valueOpt => valueOpt.exists(value => value.format === item);
  20858. const getCurrentValue = () => {
  20859. const {matchOpt} = getMatchingValue();
  20860. return matchOpt;
  20861. };
  20862. const getPreviewFor = item => () => Optional.some({
  20863. tag: 'div',
  20864. styles: item.indexOf('dings') === -1 ? { 'font-family': item } : {}
  20865. });
  20866. const onAction = rawItem => () => {
  20867. editor.undoManager.transact(() => {
  20868. editor.focus();
  20869. editor.execCommand('FontName', false, rawItem.format);
  20870. });
  20871. };
  20872. const updateSelectMenuText = comp => {
  20873. const {matchOpt, font} = getMatchingValue();
  20874. const text = matchOpt.fold(constant$1(font), item => item.title);
  20875. emitWith(comp, updateMenuText, { text });
  20876. };
  20877. const dataset = buildBasicSettingsDataset(editor, 'font_family_formats', Delimiter.SemiColon);
  20878. return {
  20879. tooltip: 'Fonts',
  20880. text: Optional.some(systemFont),
  20881. icon: Optional.none(),
  20882. isSelectedFor,
  20883. getCurrentValue,
  20884. getPreviewFor,
  20885. onAction,
  20886. updateText: updateSelectMenuText,
  20887. dataset,
  20888. shouldHide: false,
  20889. isInvalid: never
  20890. };
  20891. };
  20892. const createFontFamilyButton = (editor, backstage) => createSelectButton(editor, backstage, getSpec$2(editor));
  20893. const createFontFamilyMenu = (editor, backstage) => {
  20894. const menuItems = createMenuItems(editor, backstage, getSpec$2(editor));
  20895. editor.ui.registry.addNestedMenuItem('fontfamily', {
  20896. text: backstage.shared.providers.translate('Fonts'),
  20897. getSubmenuItems: () => menuItems.items.validateItems(menuItems.getStyleItems())
  20898. });
  20899. };
  20900. const units = {
  20901. unsupportedLength: [
  20902. 'em',
  20903. 'ex',
  20904. 'cap',
  20905. 'ch',
  20906. 'ic',
  20907. 'rem',
  20908. 'lh',
  20909. 'rlh',
  20910. 'vw',
  20911. 'vh',
  20912. 'vi',
  20913. 'vb',
  20914. 'vmin',
  20915. 'vmax',
  20916. 'cm',
  20917. 'mm',
  20918. 'Q',
  20919. 'in',
  20920. 'pc',
  20921. 'pt',
  20922. 'px'
  20923. ],
  20924. fixed: [
  20925. 'px',
  20926. 'pt'
  20927. ],
  20928. relative: ['%'],
  20929. empty: ['']
  20930. };
  20931. const pattern = (() => {
  20932. const decimalDigits = '[0-9]+';
  20933. const signedInteger = '[+-]?' + decimalDigits;
  20934. const exponentPart = '[eE]' + signedInteger;
  20935. const dot = '\\.';
  20936. const opt = input => `(?:${ input })?`;
  20937. const unsignedDecimalLiteral = [
  20938. 'Infinity',
  20939. decimalDigits + dot + opt(decimalDigits) + opt(exponentPart),
  20940. dot + decimalDigits + opt(exponentPart),
  20941. decimalDigits + opt(exponentPart)
  20942. ].join('|');
  20943. const float = `[+-]?(?:${ unsignedDecimalLiteral })`;
  20944. return new RegExp(`^(${ float })(.*)$`);
  20945. })();
  20946. const isUnit = (unit, accepted) => exists(accepted, acc => exists(units[acc], check => unit === check));
  20947. const parse = (input, accepted) => {
  20948. const match = Optional.from(pattern.exec(input));
  20949. return match.bind(array => {
  20950. const value = Number(array[1]);
  20951. const unitRaw = array[2];
  20952. if (isUnit(unitRaw, accepted)) {
  20953. return Optional.some({
  20954. value,
  20955. unit: unitRaw
  20956. });
  20957. } else {
  20958. return Optional.none();
  20959. }
  20960. });
  20961. };
  20962. const normalise = (input, accepted) => parse(input, accepted).map(({value, unit}) => value + unit);
  20963. const Keys = {
  20964. tab: constant$1(9),
  20965. escape: constant$1(27),
  20966. enter: constant$1(13),
  20967. backspace: constant$1(8),
  20968. delete: constant$1(46),
  20969. left: constant$1(37),
  20970. up: constant$1(38),
  20971. right: constant$1(39),
  20972. down: constant$1(40),
  20973. space: constant$1(32),
  20974. home: constant$1(36),
  20975. end: constant$1(35),
  20976. pageUp: constant$1(33),
  20977. pageDown: constant$1(34)
  20978. };
  20979. const createBespokeNumberInput = (editor, backstage, spec) => {
  20980. let currentComp = Optional.none();
  20981. const getValueFromCurrentComp = comp => comp.map(alloyComp => Representing.getValue(alloyComp)).getOr('');
  20982. const onSetup = onSetupEvent(editor, 'NodeChange', api => {
  20983. const comp = api.getComponent();
  20984. currentComp = Optional.some(comp);
  20985. spec.updateInputValue(comp);
  20986. });
  20987. const getApi = comp => ({ getComponent: constant$1(comp) });
  20988. const editorOffCell = Cell(noop);
  20989. const customEvents = generate$6('custom-number-input-events');
  20990. const changeValue = (f, fromInput, focusBack) => {
  20991. const text = getValueFromCurrentComp(currentComp);
  20992. const newValue = spec.getNewValue(text, f);
  20993. const lenghtDelta = text.length - `${ newValue }`.length;
  20994. const oldStart = currentComp.map(comp => comp.element.dom.selectionStart - lenghtDelta);
  20995. const oldEnd = currentComp.map(comp => comp.element.dom.selectionEnd - lenghtDelta);
  20996. spec.onAction(newValue, focusBack);
  20997. currentComp.each(comp => {
  20998. Representing.setValue(comp, newValue);
  20999. if (fromInput) {
  21000. oldStart.each(oldStart => comp.element.dom.selectionStart = oldStart);
  21001. oldEnd.each(oldEnd => comp.element.dom.selectionEnd = oldEnd);
  21002. }
  21003. });
  21004. };
  21005. const decrease = (fromInput, focusBack) => changeValue((n, s) => n - s, fromInput, focusBack);
  21006. const increase = (fromInput, focusBack) => changeValue((n, s) => n + s, fromInput, focusBack);
  21007. const goToParent = comp => parentElement(comp.element).fold(Optional.none, parent => {
  21008. focus$3(parent);
  21009. return Optional.some(true);
  21010. });
  21011. const focusInput = comp => {
  21012. if (hasFocus(comp.element)) {
  21013. firstChild(comp.element).each(input => focus$3(input));
  21014. return Optional.some(true);
  21015. } else {
  21016. return Optional.none();
  21017. }
  21018. };
  21019. const makeStepperButton = (action, title, tooltip, classes) => {
  21020. const translatedTooltip = backstage.shared.providers.translate(tooltip);
  21021. const altExecuting = generate$6('altExecuting');
  21022. const onClick = () => action(true);
  21023. return Button.sketch({
  21024. dom: {
  21025. tag: 'button',
  21026. attributes: {
  21027. 'title': translatedTooltip,
  21028. 'aria-label': translatedTooltip
  21029. },
  21030. classes: classes.concat(title)
  21031. },
  21032. components: [renderIconFromPack$1(title, backstage.shared.providers.icons)],
  21033. buttonBehaviours: derive$1([config(altExecuting, [
  21034. run$1(keydown(), (_comp, se) => {
  21035. if (se.event.raw.keyCode === Keys.space() || se.event.raw.keyCode === Keys.enter()) {
  21036. action(false);
  21037. }
  21038. }),
  21039. run$1(click(), onClick),
  21040. run$1(touchend(), onClick)
  21041. ])]),
  21042. eventOrder: {
  21043. [keydown()]: [
  21044. altExecuting,
  21045. 'keying'
  21046. ],
  21047. [click()]: [
  21048. altExecuting,
  21049. 'alloy.base.behaviour'
  21050. ],
  21051. [touchend()]: [
  21052. altExecuting,
  21053. 'alloy.base.behaviour'
  21054. ]
  21055. }
  21056. });
  21057. };
  21058. const memMinus = record(makeStepperButton(focusBack => decrease(false, focusBack), 'minus', 'Decrease font size', ['highlight-on-focus']));
  21059. const memPlus = record(makeStepperButton(focusBack => increase(false, focusBack), 'plus', 'Increase font size', ['highlight-on-focus']));
  21060. const memInput = record({
  21061. dom: {
  21062. tag: 'div',
  21063. classes: [
  21064. 'tox-input-wrapper',
  21065. 'highlight-on-focus'
  21066. ]
  21067. },
  21068. components: [Input.sketch({
  21069. inputBehaviours: derive$1([
  21070. config(customEvents, [
  21071. onControlAttached({
  21072. onSetup,
  21073. getApi
  21074. }, editorOffCell),
  21075. onControlDetached({ getApi }, editorOffCell)
  21076. ]),
  21077. config('input-update-display-text', [
  21078. run$1(updateMenuText, (comp, se) => {
  21079. Representing.setValue(comp, se.event.text);
  21080. }),
  21081. run$1(focusout(), comp => {
  21082. spec.onAction(Representing.getValue(comp));
  21083. }),
  21084. run$1(change(), comp => {
  21085. spec.onAction(Representing.getValue(comp));
  21086. })
  21087. ]),
  21088. Keying.config({
  21089. mode: 'special',
  21090. onEnter: _comp => {
  21091. changeValue(identity, true, true);
  21092. return Optional.some(true);
  21093. },
  21094. onEscape: goToParent,
  21095. onUp: _comp => {
  21096. increase(true, false);
  21097. return Optional.some(true);
  21098. },
  21099. onDown: _comp => {
  21100. decrease(true, false);
  21101. return Optional.some(true);
  21102. },
  21103. onLeft: (_comp, se) => {
  21104. se.cut();
  21105. return Optional.none();
  21106. },
  21107. onRight: (_comp, se) => {
  21108. se.cut();
  21109. return Optional.none();
  21110. }
  21111. })
  21112. ])
  21113. })],
  21114. behaviours: derive$1([
  21115. Focusing.config({}),
  21116. Keying.config({
  21117. mode: 'special',
  21118. onEnter: focusInput,
  21119. onSpace: focusInput,
  21120. onEscape: goToParent
  21121. }),
  21122. config('input-wrapper-events', [run$1(mouseover(), comp => {
  21123. each$1([
  21124. memMinus,
  21125. memPlus
  21126. ], button => {
  21127. const buttonNode = SugarElement.fromDom(button.get(comp).element.dom);
  21128. if (hasFocus(buttonNode)) {
  21129. blur$1(buttonNode);
  21130. }
  21131. });
  21132. })])
  21133. ])
  21134. });
  21135. return {
  21136. dom: {
  21137. tag: 'div',
  21138. classes: ['tox-number-input']
  21139. },
  21140. components: [
  21141. memMinus.asSpec(),
  21142. memInput.asSpec(),
  21143. memPlus.asSpec()
  21144. ],
  21145. behaviours: derive$1([
  21146. Focusing.config({}),
  21147. Keying.config({
  21148. mode: 'flow',
  21149. focusInside: FocusInsideModes.OnEnterOrSpaceMode,
  21150. cycles: false,
  21151. selector: 'button, .tox-input-wrapper',
  21152. onEscape: wrapperComp => {
  21153. if (hasFocus(wrapperComp.element)) {
  21154. return Optional.none();
  21155. } else {
  21156. focus$3(wrapperComp.element);
  21157. return Optional.some(true);
  21158. }
  21159. }
  21160. })
  21161. ])
  21162. };
  21163. };
  21164. const legacyFontSizes = {
  21165. '8pt': '1',
  21166. '10pt': '2',
  21167. '12pt': '3',
  21168. '14pt': '4',
  21169. '18pt': '5',
  21170. '24pt': '6',
  21171. '36pt': '7'
  21172. };
  21173. const keywordFontSizes = {
  21174. 'xx-small': '7pt',
  21175. 'x-small': '8pt',
  21176. 'small': '10pt',
  21177. 'medium': '12pt',
  21178. 'large': '14pt',
  21179. 'x-large': '18pt',
  21180. 'xx-large': '24pt'
  21181. };
  21182. const round = (number, precision) => {
  21183. const factor = Math.pow(10, precision);
  21184. return Math.round(number * factor) / factor;
  21185. };
  21186. const toPt = (fontSize, precision) => {
  21187. if (/[0-9.]+px$/.test(fontSize)) {
  21188. return round(parseInt(fontSize, 10) * 72 / 96, precision || 0) + 'pt';
  21189. } else {
  21190. return get$g(keywordFontSizes, fontSize).getOr(fontSize);
  21191. }
  21192. };
  21193. const toLegacy = fontSize => get$g(legacyFontSizes, fontSize).getOr('');
  21194. const getSpec$1 = editor => {
  21195. const getMatchingValue = () => {
  21196. let matchOpt = Optional.none();
  21197. const items = dataset.data;
  21198. const fontSize = editor.queryCommandValue('FontSize');
  21199. if (fontSize) {
  21200. for (let precision = 3; matchOpt.isNone() && precision >= 0; precision--) {
  21201. const pt = toPt(fontSize, precision);
  21202. const legacy = toLegacy(pt);
  21203. matchOpt = find$5(items, item => item.format === fontSize || item.format === pt || item.format === legacy);
  21204. }
  21205. }
  21206. return {
  21207. matchOpt,
  21208. size: fontSize
  21209. };
  21210. };
  21211. const isSelectedFor = item => valueOpt => valueOpt.exists(value => value.format === item);
  21212. const getCurrentValue = () => {
  21213. const {matchOpt} = getMatchingValue();
  21214. return matchOpt;
  21215. };
  21216. const getPreviewFor = constant$1(Optional.none);
  21217. const onAction = rawItem => () => {
  21218. editor.undoManager.transact(() => {
  21219. editor.focus();
  21220. editor.execCommand('FontSize', false, rawItem.format);
  21221. });
  21222. };
  21223. const updateSelectMenuText = comp => {
  21224. const {matchOpt, size} = getMatchingValue();
  21225. const text = matchOpt.fold(constant$1(size), match => match.title);
  21226. emitWith(comp, updateMenuText, { text });
  21227. };
  21228. const dataset = buildBasicSettingsDataset(editor, 'font_size_formats', Delimiter.Space);
  21229. return {
  21230. tooltip: 'Font sizes',
  21231. text: Optional.some('12pt'),
  21232. icon: Optional.none(),
  21233. isSelectedFor,
  21234. getPreviewFor,
  21235. getCurrentValue,
  21236. onAction,
  21237. updateText: updateSelectMenuText,
  21238. dataset,
  21239. shouldHide: false,
  21240. isInvalid: never
  21241. };
  21242. };
  21243. const createFontSizeButton = (editor, backstage) => createSelectButton(editor, backstage, getSpec$1(editor));
  21244. const getConfigFromUnit = unit => {
  21245. var _a;
  21246. const baseConfig = { step: 1 };
  21247. const configs = {
  21248. em: { step: 0.1 },
  21249. cm: { step: 0.1 },
  21250. in: { step: 0.1 },
  21251. pc: { step: 0.1 },
  21252. ch: { step: 0.1 },
  21253. rem: { step: 0.1 }
  21254. };
  21255. return (_a = configs[unit]) !== null && _a !== void 0 ? _a : baseConfig;
  21256. };
  21257. const defaultValue = 16;
  21258. const isValidValue = value => value >= 0;
  21259. const getNumberInputSpec = editor => {
  21260. const getCurrentValue = () => editor.queryCommandValue('FontSize');
  21261. const updateInputValue = comp => emitWith(comp, updateMenuText, { text: getCurrentValue() });
  21262. return {
  21263. updateInputValue,
  21264. onAction: (format, focusBack) => editor.execCommand('FontSize', false, format, { skip_focus: !focusBack }),
  21265. getNewValue: (text, updateFunction) => {
  21266. parse(text, [
  21267. 'unsupportedLength',
  21268. 'empty'
  21269. ]);
  21270. const parsedText = parse(text, [
  21271. 'unsupportedLength',
  21272. 'empty'
  21273. ]).or(parse(getCurrentValue(), [
  21274. 'unsupportedLength',
  21275. 'empty'
  21276. ]));
  21277. const value = parsedText.map(res => res.value).getOr(defaultValue);
  21278. const defaultUnit = getFontSizeInputDefaultUnit(editor);
  21279. const unit = parsedText.map(res => res.unit).filter(u => u !== '').getOr(defaultUnit);
  21280. const newValue = updateFunction(value, getConfigFromUnit(unit).step);
  21281. return `${ isValidValue(newValue) ? newValue : value }${ unit }`;
  21282. }
  21283. };
  21284. };
  21285. const createFontSizeInputButton = (editor, backstage) => createBespokeNumberInput(editor, backstage, getNumberInputSpec(editor));
  21286. const createFontSizeMenu = (editor, backstage) => {
  21287. const menuItems = createMenuItems(editor, backstage, getSpec$1(editor));
  21288. editor.ui.registry.addNestedMenuItem('fontsize', {
  21289. text: 'Font sizes',
  21290. getSubmenuItems: () => menuItems.items.validateItems(menuItems.getStyleItems())
  21291. });
  21292. };
  21293. const getSpec = (editor, dataset) => {
  21294. const fallbackFormat = 'Paragraph';
  21295. const isSelectedFor = format => () => editor.formatter.match(format);
  21296. const getPreviewFor = format => () => {
  21297. const fmt = editor.formatter.get(format);
  21298. return fmt !== undefined ? Optional.some({
  21299. tag: fmt.length > 0 ? fmt[0].inline || fmt[0].block || 'div' : 'div',
  21300. styles: editor.dom.parseStyle(editor.formatter.getCssText(format))
  21301. }) : Optional.none();
  21302. };
  21303. const updateSelectMenuText = comp => {
  21304. const getFormatItems = fmt => {
  21305. if (isNestedFormat(fmt)) {
  21306. return bind$3(fmt.items, getFormatItems);
  21307. } else if (isFormatReference(fmt)) {
  21308. return [{
  21309. title: fmt.title,
  21310. format: fmt.format
  21311. }];
  21312. } else {
  21313. return [];
  21314. }
  21315. };
  21316. const flattenedItems = bind$3(getStyleFormats(editor), getFormatItems);
  21317. const detectedFormat = findNearest(editor, constant$1(flattenedItems));
  21318. const text = detectedFormat.fold(constant$1(fallbackFormat), fmt => fmt.title);
  21319. emitWith(comp, updateMenuText, { text });
  21320. };
  21321. return {
  21322. tooltip: 'Formats',
  21323. text: Optional.some(fallbackFormat),
  21324. icon: Optional.none(),
  21325. isSelectedFor,
  21326. getCurrentValue: Optional.none,
  21327. getPreviewFor,
  21328. onAction: onActionToggleFormat$1(editor),
  21329. updateText: updateSelectMenuText,
  21330. shouldHide: shouldAutoHideStyleFormats(editor),
  21331. isInvalid: item => !editor.formatter.canApply(item.format),
  21332. dataset
  21333. };
  21334. };
  21335. const createStylesButton = (editor, backstage) => {
  21336. const dataset = {
  21337. type: 'advanced',
  21338. ...backstage.styles
  21339. };
  21340. return createSelectButton(editor, backstage, getSpec(editor, dataset));
  21341. };
  21342. const createStylesMenu = (editor, backstage) => {
  21343. const dataset = {
  21344. type: 'advanced',
  21345. ...backstage.styles
  21346. };
  21347. const menuItems = createMenuItems(editor, backstage, getSpec(editor, dataset));
  21348. editor.ui.registry.addNestedMenuItem('styles', {
  21349. text: 'Formats',
  21350. getSubmenuItems: () => menuItems.items.validateItems(menuItems.getStyleItems())
  21351. });
  21352. };
  21353. const schema$7 = constant$1([
  21354. required$1('toggleClass'),
  21355. required$1('fetch'),
  21356. onStrictHandler('onExecute'),
  21357. defaulted('getHotspot', Optional.some),
  21358. defaulted('getAnchorOverrides', constant$1({})),
  21359. schema$y(),
  21360. onStrictHandler('onItemExecute'),
  21361. option$3('lazySink'),
  21362. required$1('dom'),
  21363. onHandler('onOpen'),
  21364. field('splitDropdownBehaviours', [
  21365. Coupling,
  21366. Keying,
  21367. Focusing
  21368. ]),
  21369. defaulted('matchWidth', false),
  21370. defaulted('useMinWidth', false),
  21371. defaulted('eventOrder', {}),
  21372. option$3('role')
  21373. ].concat(sandboxFields()));
  21374. const arrowPart = required({
  21375. factory: Button,
  21376. schema: [required$1('dom')],
  21377. name: 'arrow',
  21378. defaults: () => {
  21379. return { buttonBehaviours: derive$1([Focusing.revoke()]) };
  21380. },
  21381. overrides: detail => {
  21382. return {
  21383. dom: {
  21384. tag: 'span',
  21385. attributes: { role: 'presentation' }
  21386. },
  21387. action: arrow => {
  21388. arrow.getSystem().getByUid(detail.uid).each(emitExecute);
  21389. },
  21390. buttonBehaviours: derive$1([Toggling.config({
  21391. toggleOnExecute: false,
  21392. toggleClass: detail.toggleClass
  21393. })])
  21394. };
  21395. }
  21396. });
  21397. const buttonPart = required({
  21398. factory: Button,
  21399. schema: [required$1('dom')],
  21400. name: 'button',
  21401. defaults: () => {
  21402. return { buttonBehaviours: derive$1([Focusing.revoke()]) };
  21403. },
  21404. overrides: detail => {
  21405. return {
  21406. dom: {
  21407. tag: 'span',
  21408. attributes: { role: 'presentation' }
  21409. },
  21410. action: btn => {
  21411. btn.getSystem().getByUid(detail.uid).each(splitDropdown => {
  21412. detail.onExecute(splitDropdown, btn);
  21413. });
  21414. }
  21415. };
  21416. }
  21417. });
  21418. const parts$3 = constant$1([
  21419. arrowPart,
  21420. buttonPart,
  21421. optional({
  21422. factory: {
  21423. sketch: spec => {
  21424. return {
  21425. uid: spec.uid,
  21426. dom: {
  21427. tag: 'span',
  21428. styles: { display: 'none' },
  21429. attributes: { 'aria-hidden': 'true' },
  21430. innerHtml: spec.text
  21431. }
  21432. };
  21433. }
  21434. },
  21435. schema: [required$1('text')],
  21436. name: 'aria-descriptor'
  21437. }),
  21438. external({
  21439. schema: [tieredMenuMarkers()],
  21440. name: 'menu',
  21441. defaults: detail => {
  21442. return {
  21443. onExecute: (tmenu, item) => {
  21444. tmenu.getSystem().getByUid(detail.uid).each(splitDropdown => {
  21445. detail.onItemExecute(splitDropdown, tmenu, item);
  21446. });
  21447. }
  21448. };
  21449. }
  21450. }),
  21451. partType$1()
  21452. ]);
  21453. const factory$5 = (detail, components, spec, externals) => {
  21454. const switchToMenu = sandbox => {
  21455. Composing.getCurrent(sandbox).each(current => {
  21456. Highlighting.highlightFirst(current);
  21457. Keying.focusIn(current);
  21458. });
  21459. };
  21460. const action = component => {
  21461. const onOpenSync = switchToMenu;
  21462. togglePopup(detail, identity, component, externals, onOpenSync, HighlightOnOpen.HighlightMenuAndItem).get(noop);
  21463. };
  21464. const openMenu = comp => {
  21465. action(comp);
  21466. return Optional.some(true);
  21467. };
  21468. const executeOnButton = comp => {
  21469. const button = getPartOrDie(comp, detail, 'button');
  21470. emitExecute(button);
  21471. return Optional.some(true);
  21472. };
  21473. const buttonEvents = {
  21474. ...derive$2([runOnAttached((component, _simulatedEvent) => {
  21475. const ariaDescriptor = getPart(component, detail, 'aria-descriptor');
  21476. ariaDescriptor.each(descriptor => {
  21477. const descriptorId = generate$6('aria');
  21478. set$9(descriptor.element, 'id', descriptorId);
  21479. set$9(component.element, 'aria-describedby', descriptorId);
  21480. });
  21481. })]),
  21482. ...events$a(Optional.some(action))
  21483. };
  21484. const apis = {
  21485. repositionMenus: comp => {
  21486. if (Toggling.isOn(comp)) {
  21487. repositionMenus(comp);
  21488. }
  21489. }
  21490. };
  21491. return {
  21492. uid: detail.uid,
  21493. dom: detail.dom,
  21494. components,
  21495. apis,
  21496. eventOrder: {
  21497. ...detail.eventOrder,
  21498. [execute$5()]: [
  21499. 'disabling',
  21500. 'toggling',
  21501. 'alloy.base.behaviour'
  21502. ]
  21503. },
  21504. events: buttonEvents,
  21505. behaviours: augment(detail.splitDropdownBehaviours, [
  21506. Coupling.config({
  21507. others: {
  21508. sandbox: hotspot => {
  21509. const arrow = getPartOrDie(hotspot, detail, 'arrow');
  21510. const extras = {
  21511. onOpen: () => {
  21512. Toggling.on(arrow);
  21513. Toggling.on(hotspot);
  21514. },
  21515. onClose: () => {
  21516. Toggling.off(arrow);
  21517. Toggling.off(hotspot);
  21518. }
  21519. };
  21520. return makeSandbox$1(detail, hotspot, extras);
  21521. }
  21522. }
  21523. }),
  21524. Keying.config({
  21525. mode: 'special',
  21526. onSpace: executeOnButton,
  21527. onEnter: executeOnButton,
  21528. onDown: openMenu
  21529. }),
  21530. Focusing.config({}),
  21531. Toggling.config({
  21532. toggleOnExecute: false,
  21533. aria: { mode: 'expanded' }
  21534. })
  21535. ]),
  21536. domModification: {
  21537. attributes: {
  21538. 'role': detail.role.getOr('button'),
  21539. 'aria-haspopup': true
  21540. }
  21541. }
  21542. };
  21543. };
  21544. const SplitDropdown = composite({
  21545. name: 'SplitDropdown',
  21546. configFields: schema$7(),
  21547. partFields: parts$3(),
  21548. factory: factory$5,
  21549. apis: { repositionMenus: (apis, comp) => apis.repositionMenus(comp) }
  21550. });
  21551. const getButtonApi = component => ({
  21552. isEnabled: () => !Disabling.isDisabled(component),
  21553. setEnabled: state => Disabling.set(component, !state),
  21554. setText: text => emitWith(component, updateMenuText, { text }),
  21555. setIcon: icon => emitWith(component, updateMenuIcon, { icon })
  21556. });
  21557. const getToggleApi = component => ({
  21558. setActive: state => {
  21559. Toggling.set(component, state);
  21560. },
  21561. isActive: () => Toggling.isOn(component),
  21562. isEnabled: () => !Disabling.isDisabled(component),
  21563. setEnabled: state => Disabling.set(component, !state),
  21564. setText: text => emitWith(component, updateMenuText, { text }),
  21565. setIcon: icon => emitWith(component, updateMenuIcon, { icon })
  21566. });
  21567. const getTooltipAttributes = (tooltip, providersBackstage) => tooltip.map(tooltip => ({
  21568. 'aria-label': providersBackstage.translate(tooltip),
  21569. 'title': providersBackstage.translate(tooltip)
  21570. })).getOr({});
  21571. const focusButtonEvent = generate$6('focus-button');
  21572. const renderCommonStructure = (optIcon, optText, tooltip, behaviours, providersBackstage) => {
  21573. const optMemDisplayText = optText.map(text => record(renderLabel$1(text, 'tox-tbtn', providersBackstage)));
  21574. const optMemDisplayIcon = optIcon.map(icon => record(renderReplaceableIconFromPack(icon, providersBackstage.icons)));
  21575. return {
  21576. dom: {
  21577. tag: 'button',
  21578. classes: ['tox-tbtn'].concat(optText.isSome() ? ['tox-tbtn--select'] : []),
  21579. attributes: getTooltipAttributes(tooltip, providersBackstage)
  21580. },
  21581. components: componentRenderPipeline([
  21582. optMemDisplayIcon.map(mem => mem.asSpec()),
  21583. optMemDisplayText.map(mem => mem.asSpec())
  21584. ]),
  21585. eventOrder: {
  21586. [mousedown()]: [
  21587. 'focusing',
  21588. 'alloy.base.behaviour',
  21589. commonButtonDisplayEvent
  21590. ],
  21591. [attachedToDom()]: [
  21592. commonButtonDisplayEvent,
  21593. 'toolbar-group-button-events'
  21594. ]
  21595. },
  21596. buttonBehaviours: derive$1([
  21597. DisablingConfigs.toolbarButton(providersBackstage.isDisabled),
  21598. receivingConfig(),
  21599. config(commonButtonDisplayEvent, [
  21600. runOnAttached((comp, _se) => forceInitialSize(comp)),
  21601. run$1(updateMenuText, (comp, se) => {
  21602. optMemDisplayText.bind(mem => mem.getOpt(comp)).each(displayText => {
  21603. Replacing.set(displayText, [text$2(providersBackstage.translate(se.event.text))]);
  21604. });
  21605. }),
  21606. run$1(updateMenuIcon, (comp, se) => {
  21607. optMemDisplayIcon.bind(mem => mem.getOpt(comp)).each(displayIcon => {
  21608. Replacing.set(displayIcon, [renderReplaceableIconFromPack(se.event.icon, providersBackstage.icons)]);
  21609. });
  21610. }),
  21611. run$1(mousedown(), (button, se) => {
  21612. se.event.prevent();
  21613. emit(button, focusButtonEvent);
  21614. })
  21615. ])
  21616. ].concat(behaviours.getOr([])))
  21617. };
  21618. };
  21619. const renderFloatingToolbarButton = (spec, backstage, identifyButtons, attributes) => {
  21620. const sharedBackstage = backstage.shared;
  21621. const editorOffCell = Cell(noop);
  21622. const specialisation = {
  21623. toolbarButtonBehaviours: [],
  21624. getApi: getButtonApi,
  21625. onSetup: spec.onSetup
  21626. };
  21627. const behaviours = [config('toolbar-group-button-events', [
  21628. onControlAttached(specialisation, editorOffCell),
  21629. onControlDetached(specialisation, editorOffCell)
  21630. ])];
  21631. return FloatingToolbarButton.sketch({
  21632. lazySink: sharedBackstage.getSink,
  21633. fetch: () => Future.nu(resolve => {
  21634. resolve(map$2(identifyButtons(spec.items), renderToolbarGroup));
  21635. }),
  21636. markers: { toggledClass: 'tox-tbtn--enabled' },
  21637. parts: {
  21638. button: renderCommonStructure(spec.icon, spec.text, spec.tooltip, Optional.some(behaviours), sharedBackstage.providers),
  21639. toolbar: {
  21640. dom: {
  21641. tag: 'div',
  21642. classes: ['tox-toolbar__overflow'],
  21643. attributes
  21644. }
  21645. }
  21646. }
  21647. });
  21648. };
  21649. const renderCommonToolbarButton = (spec, specialisation, providersBackstage) => {
  21650. var _d;
  21651. const editorOffCell = Cell(noop);
  21652. const structure = renderCommonStructure(spec.icon, spec.text, spec.tooltip, Optional.none(), providersBackstage);
  21653. return Button.sketch({
  21654. dom: structure.dom,
  21655. components: structure.components,
  21656. eventOrder: toolbarButtonEventOrder,
  21657. buttonBehaviours: {
  21658. ...derive$1([
  21659. config('toolbar-button-events', [
  21660. onToolbarButtonExecute({
  21661. onAction: spec.onAction,
  21662. getApi: specialisation.getApi
  21663. }),
  21664. onControlAttached(specialisation, editorOffCell),
  21665. onControlDetached(specialisation, editorOffCell)
  21666. ]),
  21667. DisablingConfigs.toolbarButton(() => !spec.enabled || providersBackstage.isDisabled()),
  21668. receivingConfig()
  21669. ].concat(specialisation.toolbarButtonBehaviours)),
  21670. [commonButtonDisplayEvent]: (_d = structure.buttonBehaviours) === null || _d === void 0 ? void 0 : _d[commonButtonDisplayEvent]
  21671. }
  21672. });
  21673. };
  21674. const renderToolbarButton = (spec, providersBackstage) => renderToolbarButtonWith(spec, providersBackstage, []);
  21675. const renderToolbarButtonWith = (spec, providersBackstage, bonusEvents) => renderCommonToolbarButton(spec, {
  21676. toolbarButtonBehaviours: bonusEvents.length > 0 ? [config('toolbarButtonWith', bonusEvents)] : [],
  21677. getApi: getButtonApi,
  21678. onSetup: spec.onSetup
  21679. }, providersBackstage);
  21680. const renderToolbarToggleButton = (spec, providersBackstage) => renderToolbarToggleButtonWith(spec, providersBackstage, []);
  21681. const renderToolbarToggleButtonWith = (spec, providersBackstage, bonusEvents) => renderCommonToolbarButton(spec, {
  21682. toolbarButtonBehaviours: [
  21683. Replacing.config({}),
  21684. Toggling.config({
  21685. toggleClass: 'tox-tbtn--enabled',
  21686. aria: { mode: 'pressed' },
  21687. toggleOnExecute: false
  21688. })
  21689. ].concat(bonusEvents.length > 0 ? [config('toolbarToggleButtonWith', bonusEvents)] : []),
  21690. getApi: getToggleApi,
  21691. onSetup: spec.onSetup
  21692. }, providersBackstage);
  21693. 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 => {
  21694. spec.onItemAction(getApi(comp), value);
  21695. }, spec.columns, spec.presets, ItemResponse$1.CLOSE_ON_EXECUTE, spec.select.getOr(never), providersBackstage), {
  21696. movement: deriveMenuMovement(spec.columns, spec.presets),
  21697. menuBehaviours: SimpleBehaviours.unnamedEvents(spec.columns !== 'auto' ? [] : [runOnAttached((comp, _se) => {
  21698. detectSize(comp, 4, classForPreset(spec.presets)).each(({numRows, numColumns}) => {
  21699. Keying.setGridSize(comp, numRows, numColumns);
  21700. });
  21701. })])
  21702. }))));
  21703. const renderSplitButton = (spec, sharedBackstage) => {
  21704. const getApi = comp => ({
  21705. isEnabled: () => !Disabling.isDisabled(comp),
  21706. setEnabled: state => Disabling.set(comp, !state),
  21707. setIconFill: (id, value) => {
  21708. descendant(comp.element, `svg path[id="${ id }"], rect[id="${ id }"]`).each(underlinePath => {
  21709. set$9(underlinePath, 'fill', value);
  21710. });
  21711. },
  21712. setActive: state => {
  21713. set$9(comp.element, 'aria-pressed', state);
  21714. descendant(comp.element, 'span').each(button => {
  21715. comp.getSystem().getByDom(button).each(buttonComp => Toggling.set(buttonComp, state));
  21716. });
  21717. },
  21718. isActive: () => descendant(comp.element, 'span').exists(button => comp.getSystem().getByDom(button).exists(Toggling.isOn)),
  21719. setText: text => descendant(comp.element, 'span').each(button => comp.getSystem().getByDom(button).each(buttonComp => emitWith(buttonComp, updateMenuText, { text }))),
  21720. setIcon: icon => descendant(comp.element, 'span').each(button => comp.getSystem().getByDom(button).each(buttonComp => emitWith(buttonComp, updateMenuIcon, { icon })))
  21721. });
  21722. const editorOffCell = Cell(noop);
  21723. const specialisation = {
  21724. getApi,
  21725. onSetup: spec.onSetup
  21726. };
  21727. return SplitDropdown.sketch({
  21728. dom: {
  21729. tag: 'div',
  21730. classes: ['tox-split-button'],
  21731. attributes: {
  21732. 'aria-pressed': false,
  21733. ...getTooltipAttributes(spec.tooltip, sharedBackstage.providers)
  21734. }
  21735. },
  21736. onExecute: button => {
  21737. const api = getApi(button);
  21738. if (api.isEnabled()) {
  21739. spec.onAction(api);
  21740. }
  21741. },
  21742. onItemExecute: (_a, _b, _c) => {
  21743. },
  21744. splitDropdownBehaviours: derive$1([
  21745. DisablingConfigs.splitButton(sharedBackstage.providers.isDisabled),
  21746. receivingConfig(),
  21747. config('split-dropdown-events', [
  21748. runOnAttached((comp, _se) => forceInitialSize(comp)),
  21749. run$1(focusButtonEvent, Focusing.focus),
  21750. onControlAttached(specialisation, editorOffCell),
  21751. onControlDetached(specialisation, editorOffCell)
  21752. ]),
  21753. Unselecting.config({})
  21754. ]),
  21755. eventOrder: {
  21756. [attachedToDom()]: [
  21757. 'alloy.base.behaviour',
  21758. 'split-dropdown-events'
  21759. ]
  21760. },
  21761. toggleClass: 'tox-tbtn--enabled',
  21762. lazySink: sharedBackstage.getSink,
  21763. fetch: fetchChoices(getApi, spec, sharedBackstage.providers),
  21764. parts: { menu: part(false, spec.columns, spec.presets) },
  21765. components: [
  21766. SplitDropdown.parts.button(renderCommonStructure(spec.icon, spec.text, Optional.none(), Optional.some([Toggling.config({
  21767. toggleClass: 'tox-tbtn--enabled',
  21768. toggleOnExecute: false
  21769. })]), sharedBackstage.providers)),
  21770. SplitDropdown.parts.arrow({
  21771. dom: {
  21772. tag: 'button',
  21773. classes: [
  21774. 'tox-tbtn',
  21775. 'tox-split-button__chevron'
  21776. ],
  21777. innerHtml: get$2('chevron-down', sharedBackstage.providers.icons)
  21778. },
  21779. buttonBehaviours: derive$1([
  21780. DisablingConfigs.splitButton(sharedBackstage.providers.isDisabled),
  21781. receivingConfig(),
  21782. addFocusableBehaviour()
  21783. ])
  21784. }),
  21785. SplitDropdown.parts['aria-descriptor']({ text: sharedBackstage.providers.translate('To open the popup, press Shift+Enter') })
  21786. ]
  21787. });
  21788. };
  21789. const defaultToolbar = [
  21790. {
  21791. name: 'history',
  21792. items: [
  21793. 'undo',
  21794. 'redo'
  21795. ]
  21796. },
  21797. {
  21798. name: 'styles',
  21799. items: ['styles']
  21800. },
  21801. {
  21802. name: 'formatting',
  21803. items: [
  21804. 'bold',
  21805. 'italic'
  21806. ]
  21807. },
  21808. {
  21809. name: 'alignment',
  21810. items: [
  21811. 'alignleft',
  21812. 'aligncenter',
  21813. 'alignright',
  21814. 'alignjustify'
  21815. ]
  21816. },
  21817. {
  21818. name: 'indentation',
  21819. items: [
  21820. 'outdent',
  21821. 'indent'
  21822. ]
  21823. },
  21824. {
  21825. name: 'permanent pen',
  21826. items: ['permanentpen']
  21827. },
  21828. {
  21829. name: 'comments',
  21830. items: ['addcomment']
  21831. }
  21832. ];
  21833. const renderFromBridge = (bridgeBuilder, render) => (spec, backstage, editor) => {
  21834. const internal = bridgeBuilder(spec).mapError(errInfo => formatError(errInfo)).getOrDie();
  21835. return render(internal, backstage, editor);
  21836. };
  21837. const types = {
  21838. button: renderFromBridge(createToolbarButton, (s, backstage) => renderToolbarButton(s, backstage.shared.providers)),
  21839. togglebutton: renderFromBridge(createToggleButton, (s, backstage) => renderToolbarToggleButton(s, backstage.shared.providers)),
  21840. menubutton: renderFromBridge(createMenuButton, (s, backstage) => renderMenuButton(s, 'tox-tbtn', backstage, Optional.none(), false)),
  21841. splitbutton: renderFromBridge(createSplitButton, (s, backstage) => renderSplitButton(s, backstage.shared)),
  21842. grouptoolbarbutton: renderFromBridge(createGroupToolbarButton, (s, backstage, editor) => {
  21843. const buttons = editor.ui.registry.getAll().buttons;
  21844. const identify = toolbar => identifyButtons(editor, {
  21845. buttons,
  21846. toolbar,
  21847. allowToolbarGroups: false
  21848. }, backstage, Optional.none());
  21849. const attributes = { [Attribute]: backstage.shared.header.isPositionedAtTop() ? AttributeValue.TopToBottom : AttributeValue.BottomToTop };
  21850. switch (getToolbarMode(editor)) {
  21851. case ToolbarMode$1.floating:
  21852. return renderFloatingToolbarButton(s, backstage, identify, attributes);
  21853. default:
  21854. throw new Error('Toolbar groups are only supported when using floating toolbar mode');
  21855. }
  21856. })
  21857. };
  21858. const extractFrom = (spec, backstage, editor) => get$g(types, spec.type).fold(() => {
  21859. console.error('skipping button defined by', spec);
  21860. return Optional.none();
  21861. }, render => Optional.some(render(spec, backstage, editor)));
  21862. const bespokeButtons = {
  21863. styles: createStylesButton,
  21864. fontsize: createFontSizeButton,
  21865. fontsizeinput: createFontSizeInputButton,
  21866. fontfamily: createFontFamilyButton,
  21867. blocks: createBlocksButton,
  21868. align: createAlignButton
  21869. };
  21870. const removeUnusedDefaults = buttons => {
  21871. const filteredItemGroups = map$2(defaultToolbar, group => {
  21872. const items = filter$2(group.items, subItem => has$2(buttons, subItem) || has$2(bespokeButtons, subItem));
  21873. return {
  21874. name: group.name,
  21875. items
  21876. };
  21877. });
  21878. return filter$2(filteredItemGroups, group => group.items.length > 0);
  21879. };
  21880. const convertStringToolbar = strToolbar => {
  21881. const groupsStrings = strToolbar.split('|');
  21882. return map$2(groupsStrings, g => ({ items: g.trim().split(' ') }));
  21883. };
  21884. const isToolbarGroupSettingArray = toolbar => isArrayOf(toolbar, t => has$2(t, 'name') && has$2(t, 'items'));
  21885. const createToolbar = toolbarConfig => {
  21886. const toolbar = toolbarConfig.toolbar;
  21887. const buttons = toolbarConfig.buttons;
  21888. if (toolbar === false) {
  21889. return [];
  21890. } else if (toolbar === undefined || toolbar === true) {
  21891. return removeUnusedDefaults(buttons);
  21892. } else if (isString(toolbar)) {
  21893. return convertStringToolbar(toolbar);
  21894. } else if (isToolbarGroupSettingArray(toolbar)) {
  21895. return toolbar;
  21896. } else {
  21897. console.error('Toolbar type should be string, string[], boolean or ToolbarGroup[]');
  21898. return [];
  21899. }
  21900. };
  21901. 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 => {
  21902. if (spec.type === 'grouptoolbarbutton' && !allowToolbarGroups) {
  21903. console.warn(`Ignoring the '${ toolbarItem }' toolbar button. Group toolbar buttons are only supported when using floating toolbar mode and cannot be nested.`);
  21904. return Optional.none();
  21905. } else {
  21906. return extractFrom(spec, backstage, editor);
  21907. }
  21908. });
  21909. const identifyButtons = (editor, toolbarConfig, backstage, prefixes) => {
  21910. const toolbarGroups = createToolbar(toolbarConfig);
  21911. const groups = map$2(toolbarGroups, group => {
  21912. const items = bind$3(group.items, toolbarItem => {
  21913. return toolbarItem.trim().length === 0 ? [] : lookupButton(editor, toolbarConfig.buttons, toolbarItem, toolbarConfig.allowToolbarGroups, backstage, prefixes).toArray();
  21914. });
  21915. return {
  21916. title: Optional.from(editor.translate(group.name)),
  21917. items
  21918. };
  21919. });
  21920. return filter$2(groups, group => group.items.length > 0);
  21921. };
  21922. const setToolbar = (editor, uiRefs, rawUiConfig, backstage) => {
  21923. const outerContainer = uiRefs.mainUi.outerContainer;
  21924. const toolbarConfig = rawUiConfig.toolbar;
  21925. const toolbarButtonsConfig = rawUiConfig.buttons;
  21926. if (isArrayOf(toolbarConfig, isString)) {
  21927. const toolbars = toolbarConfig.map(t => {
  21928. const config = {
  21929. toolbar: t,
  21930. buttons: toolbarButtonsConfig,
  21931. allowToolbarGroups: rawUiConfig.allowToolbarGroups
  21932. };
  21933. return identifyButtons(editor, config, backstage, Optional.none());
  21934. });
  21935. OuterContainer.setToolbars(outerContainer, toolbars);
  21936. } else {
  21937. OuterContainer.setToolbar(outerContainer, identifyButtons(editor, rawUiConfig, backstage, Optional.none()));
  21938. }
  21939. };
  21940. const detection = detect$2();
  21941. const isiOS12 = detection.os.isiOS() && detection.os.version.major <= 12;
  21942. const setupEvents$1 = (editor, uiRefs) => {
  21943. const {uiMotherships} = uiRefs;
  21944. const dom = editor.dom;
  21945. let contentWindow = editor.getWin();
  21946. const initialDocEle = editor.getDoc().documentElement;
  21947. const lastWindowDimensions = Cell(SugarPosition(contentWindow.innerWidth, contentWindow.innerHeight));
  21948. const lastDocumentDimensions = Cell(SugarPosition(initialDocEle.offsetWidth, initialDocEle.offsetHeight));
  21949. const resizeWindow = () => {
  21950. const outer = lastWindowDimensions.get();
  21951. if (outer.left !== contentWindow.innerWidth || outer.top !== contentWindow.innerHeight) {
  21952. lastWindowDimensions.set(SugarPosition(contentWindow.innerWidth, contentWindow.innerHeight));
  21953. fireResizeContent(editor);
  21954. }
  21955. };
  21956. const resizeDocument = () => {
  21957. const docEle = editor.getDoc().documentElement;
  21958. const inner = lastDocumentDimensions.get();
  21959. if (inner.left !== docEle.offsetWidth || inner.top !== docEle.offsetHeight) {
  21960. lastDocumentDimensions.set(SugarPosition(docEle.offsetWidth, docEle.offsetHeight));
  21961. fireResizeContent(editor);
  21962. }
  21963. };
  21964. const scroll = e => {
  21965. fireScrollContent(editor, e);
  21966. };
  21967. dom.bind(contentWindow, 'resize', resizeWindow);
  21968. dom.bind(contentWindow, 'scroll', scroll);
  21969. const elementLoad = capture(SugarElement.fromDom(editor.getBody()), 'load', resizeDocument);
  21970. editor.on('hide', () => {
  21971. each$1(uiMotherships, m => {
  21972. set$8(m.element, 'display', 'none');
  21973. });
  21974. });
  21975. editor.on('show', () => {
  21976. each$1(uiMotherships, m => {
  21977. remove$6(m.element, 'display');
  21978. });
  21979. });
  21980. editor.on('NodeChange', resizeDocument);
  21981. editor.on('remove', () => {
  21982. elementLoad.unbind();
  21983. dom.unbind(contentWindow, 'resize', resizeWindow);
  21984. dom.unbind(contentWindow, 'scroll', scroll);
  21985. contentWindow = null;
  21986. });
  21987. };
  21988. const attachUiMotherships = (editor, uiRoot, uiRefs) => {
  21989. if (isSplitUiMode(editor)) {
  21990. attachSystemAfter(uiRefs.mainUi.mothership.element, uiRefs.popupUi.mothership);
  21991. }
  21992. attachSystem(uiRoot, uiRefs.dialogUi.mothership);
  21993. };
  21994. const render$1 = async (editor, uiRefs, rawUiConfig, backstage, args) => {
  21995. const {mainUi, uiMotherships} = uiRefs;
  21996. const lastToolbarWidth = Cell(0);
  21997. const outerContainer = mainUi.outerContainer;
  21998. await iframe(editor);
  21999. const eTargetNode = SugarElement.fromDom(args.targetNode);
  22000. const uiRoot = getContentContainer(getRootNode(eTargetNode));
  22001. attachSystemAfter(eTargetNode, mainUi.mothership);
  22002. attachUiMotherships(editor, uiRoot, uiRefs);
  22003. editor.on('PostRender', () => {
  22004. OuterContainer.setSidebar(outerContainer, rawUiConfig.sidebar, getSidebarShow(editor));
  22005. setToolbar(editor, uiRefs, rawUiConfig, backstage);
  22006. lastToolbarWidth.set(editor.getWin().innerWidth);
  22007. OuterContainer.setMenubar(outerContainer, identifyMenus(editor, rawUiConfig));
  22008. OuterContainer.setViews(outerContainer, rawUiConfig.views);
  22009. setupEvents$1(editor, uiRefs);
  22010. });
  22011. const socket = OuterContainer.getSocket(outerContainer).getOrDie('Could not find expected socket element');
  22012. if (isiOS12) {
  22013. setAll(socket.element, {
  22014. 'overflow': 'scroll',
  22015. '-webkit-overflow-scrolling': 'touch'
  22016. });
  22017. const limit = first(() => {
  22018. editor.dispatch('ScrollContent');
  22019. }, 20);
  22020. const unbinder = bind(socket.element, 'scroll', limit.throttle);
  22021. editor.on('remove', unbinder.unbind);
  22022. }
  22023. setupReadonlyModeSwitch(editor, uiRefs);
  22024. editor.addCommand('ToggleSidebar', (_ui, value) => {
  22025. OuterContainer.toggleSidebar(outerContainer, value);
  22026. editor.dispatch('ToggleSidebar');
  22027. });
  22028. editor.addQueryValueHandler('ToggleSidebar', () => {
  22029. var _a;
  22030. return (_a = OuterContainer.whichSidebar(outerContainer)) !== null && _a !== void 0 ? _a : '';
  22031. });
  22032. editor.addCommand('ToggleView', (_ui, value) => {
  22033. if (OuterContainer.toggleView(outerContainer, value)) {
  22034. const target = outerContainer.element;
  22035. mainUi.mothership.broadcastOn([dismissPopups()], { target });
  22036. each$1(uiMotherships, m => {
  22037. m.broadcastOn([dismissPopups()], { target });
  22038. });
  22039. if (isNull(OuterContainer.whichView(outerContainer))) {
  22040. editor.focus();
  22041. editor.nodeChanged();
  22042. }
  22043. }
  22044. });
  22045. editor.addQueryValueHandler('ToggleView', () => {
  22046. var _a;
  22047. return (_a = OuterContainer.whichView(outerContainer)) !== null && _a !== void 0 ? _a : '';
  22048. });
  22049. const toolbarMode = getToolbarMode(editor);
  22050. const refreshDrawer = () => {
  22051. OuterContainer.refreshToolbar(uiRefs.mainUi.outerContainer);
  22052. };
  22053. if (toolbarMode === ToolbarMode$1.sliding || toolbarMode === ToolbarMode$1.floating) {
  22054. editor.on('ResizeWindow ResizeEditor ResizeContent', () => {
  22055. const width = editor.getWin().innerWidth;
  22056. if (width !== lastToolbarWidth.get()) {
  22057. refreshDrawer();
  22058. lastToolbarWidth.set(width);
  22059. }
  22060. });
  22061. }
  22062. const api = {
  22063. setEnabled: state => {
  22064. broadcastReadonly(uiRefs, !state);
  22065. },
  22066. isEnabled: () => !Disabling.isDisabled(outerContainer)
  22067. };
  22068. return {
  22069. iframeContainer: socket.element.dom,
  22070. editorContainer: outerContainer.element.dom,
  22071. api
  22072. };
  22073. };
  22074. var Iframe = /*#__PURE__*/Object.freeze({
  22075. __proto__: null,
  22076. render: render$1
  22077. });
  22078. const parseToInt = val => {
  22079. const re = /^[0-9\.]+(|px)$/i;
  22080. if (re.test('' + val)) {
  22081. return Optional.some(parseInt('' + val, 10));
  22082. }
  22083. return Optional.none();
  22084. };
  22085. const numToPx = val => isNumber(val) ? val + 'px' : val;
  22086. const calcCappedSize = (size, minSize, maxSize) => {
  22087. const minOverride = minSize.filter(min => size < min);
  22088. const maxOverride = maxSize.filter(max => size > max);
  22089. return minOverride.or(maxOverride).getOr(size);
  22090. };
  22091. const getHeight = editor => {
  22092. const baseHeight = getHeightOption(editor);
  22093. const minHeight = getMinHeightOption(editor);
  22094. const maxHeight = getMaxHeightOption(editor);
  22095. return parseToInt(baseHeight).map(height => calcCappedSize(height, minHeight, maxHeight));
  22096. };
  22097. const getHeightWithFallback = editor => {
  22098. const height = getHeight(editor);
  22099. return height.getOr(getHeightOption(editor));
  22100. };
  22101. const getWidth = editor => {
  22102. const baseWidth = getWidthOption(editor);
  22103. const minWidth = getMinWidthOption(editor);
  22104. const maxWidth = getMaxWidthOption(editor);
  22105. return parseToInt(baseWidth).map(width => calcCappedSize(width, minWidth, maxWidth));
  22106. };
  22107. const getWidthWithFallback = editor => {
  22108. const width = getWidth(editor);
  22109. return width.getOr(getWidthOption(editor));
  22110. };
  22111. const {ToolbarLocation, ToolbarMode} = Options;
  22112. const maximumDistanceToEdge = 40;
  22113. const InlineHeader = (editor, targetElm, uiRefs, backstage, floatContainer) => {
  22114. const {mainUi, uiMotherships} = uiRefs;
  22115. const DOM = global$7.DOM;
  22116. const useFixedToolbarContainer = useFixedContainer(editor);
  22117. const isSticky = isStickyToolbar(editor);
  22118. const editorMaxWidthOpt = getMaxWidthOption(editor).or(getWidth(editor));
  22119. const headerBackstage = backstage.shared.header;
  22120. const isPositionedAtTop = headerBackstage.isPositionedAtTop;
  22121. const toolbarMode = getToolbarMode(editor);
  22122. const isSplitToolbar = toolbarMode === ToolbarMode.sliding || toolbarMode === ToolbarMode.floating;
  22123. const visible = Cell(false);
  22124. const isVisible = () => visible.get() && !editor.removed;
  22125. const calcToolbarOffset = toolbar => isSplitToolbar ? toolbar.fold(constant$1(0), tbar => tbar.components().length > 1 ? get$d(tbar.components()[1].element) : 0) : 0;
  22126. const calcMode = container => {
  22127. switch (getToolbarLocation(editor)) {
  22128. case ToolbarLocation.auto:
  22129. const toolbar = OuterContainer.getToolbar(mainUi.outerContainer);
  22130. const offset = calcToolbarOffset(toolbar);
  22131. const toolbarHeight = get$d(container.element) - offset;
  22132. const targetBounds = box$1(targetElm);
  22133. const roomAtTop = targetBounds.y > toolbarHeight;
  22134. if (roomAtTop) {
  22135. return 'top';
  22136. } else {
  22137. const doc = documentElement(targetElm);
  22138. const docHeight = Math.max(doc.dom.scrollHeight, get$d(doc));
  22139. const roomAtBottom = targetBounds.bottom < docHeight - toolbarHeight;
  22140. if (roomAtBottom) {
  22141. return 'bottom';
  22142. } else {
  22143. const winBounds = win();
  22144. const isRoomAtBottomViewport = winBounds.bottom < targetBounds.bottom - toolbarHeight;
  22145. return isRoomAtBottomViewport ? 'bottom' : 'top';
  22146. }
  22147. }
  22148. case ToolbarLocation.bottom:
  22149. return 'bottom';
  22150. case ToolbarLocation.top:
  22151. default:
  22152. return 'top';
  22153. }
  22154. };
  22155. const setupMode = mode => {
  22156. floatContainer.on(container => {
  22157. Docking.setModes(container, [mode]);
  22158. headerBackstage.setDockingMode(mode);
  22159. const verticalDir = isPositionedAtTop() ? AttributeValue.TopToBottom : AttributeValue.BottomToTop;
  22160. set$9(container.element, Attribute, verticalDir);
  22161. });
  22162. };
  22163. const updateChromeWidth = () => {
  22164. floatContainer.on(container => {
  22165. const maxWidth = editorMaxWidthOpt.getOrThunk(() => {
  22166. const bodyMargin = parseToInt(get$e(body(), 'margin-left')).getOr(0);
  22167. return get$c(body()) - absolute$3(targetElm).left + bodyMargin;
  22168. });
  22169. set$8(container.element, 'max-width', maxWidth + 'px');
  22170. });
  22171. };
  22172. const updateChromePosition = optToolbarWidth => {
  22173. floatContainer.on(container => {
  22174. const toolbar = OuterContainer.getToolbar(mainUi.outerContainer);
  22175. const offset = calcToolbarOffset(toolbar);
  22176. const targetBounds = box$1(targetElm);
  22177. const {top, left} = getOffsetParent$1(editor, mainUi.outerContainer.element).fold(() => {
  22178. return {
  22179. top: isPositionedAtTop() ? Math.max(targetBounds.y - get$d(container.element) + offset, 0) : targetBounds.bottom,
  22180. left: targetBounds.x
  22181. };
  22182. }, offsetParent => {
  22183. var _a;
  22184. const offsetBox = box$1(offsetParent);
  22185. const scrollDelta = (_a = offsetParent.dom.scrollTop) !== null && _a !== void 0 ? _a : 0;
  22186. const isOffsetParentBody = eq(offsetParent, body());
  22187. const topValue = isOffsetParentBody ? Math.max(targetBounds.y - get$d(container.element) + offset, 0) : targetBounds.y - offsetBox.y + scrollDelta - get$d(container.element) + offset;
  22188. return {
  22189. top: isPositionedAtTop() ? topValue : targetBounds.bottom,
  22190. left: isOffsetParentBody ? targetBounds.x : targetBounds.x - offsetBox.x
  22191. };
  22192. });
  22193. const baseProperties = {
  22194. position: 'absolute',
  22195. left: Math.round(left) + 'px',
  22196. top: Math.round(top) + 'px'
  22197. };
  22198. const widthProperties = optToolbarWidth.map(toolbarWidth => {
  22199. const scroll = get$b();
  22200. const minimumToolbarWidth = 150;
  22201. const availableWidth = window.innerWidth - (left - scroll.left);
  22202. const width = Math.max(Math.min(toolbarWidth, availableWidth), minimumToolbarWidth);
  22203. return { width: width + 'px' };
  22204. }).getOr({});
  22205. setAll(mainUi.outerContainer.element, {
  22206. ...baseProperties,
  22207. ...widthProperties
  22208. });
  22209. });
  22210. };
  22211. const getOffsetParent$1 = (editor, element) => isSplitUiMode(editor) ? getOffsetParent(element) : Optional.none();
  22212. const repositionPopups$1 = () => {
  22213. each$1(uiMotherships, m => {
  22214. m.broadcastOn([repositionPopups()], {});
  22215. });
  22216. };
  22217. const restoreAndGetCompleteOuterContainerWidth = () => {
  22218. if (!useFixedToolbarContainer) {
  22219. const toolbarCurrentRightsidePosition = absolute$3(mainUi.outerContainer.element).left + getOuter$1(mainUi.outerContainer.element);
  22220. if (toolbarCurrentRightsidePosition >= window.innerWidth - maximumDistanceToEdge || getRaw(mainUi.outerContainer.element, 'width').isSome()) {
  22221. set$8(mainUi.outerContainer.element, 'position', 'absolute');
  22222. set$8(mainUi.outerContainer.element, 'left', '0px');
  22223. remove$6(mainUi.outerContainer.element, 'width');
  22224. const w = getOuter$1(mainUi.outerContainer.element);
  22225. return Optional.some(w);
  22226. } else {
  22227. return Optional.none();
  22228. }
  22229. } else {
  22230. return Optional.none();
  22231. }
  22232. };
  22233. const update = stickyAction => {
  22234. if (!isVisible()) {
  22235. return;
  22236. }
  22237. if (!useFixedToolbarContainer) {
  22238. updateChromeWidth();
  22239. }
  22240. const optToolbarWidth = useFixedToolbarContainer ? Optional.none() : restoreAndGetCompleteOuterContainerWidth();
  22241. if (isSplitToolbar) {
  22242. OuterContainer.refreshToolbar(mainUi.outerContainer);
  22243. }
  22244. if (!useFixedToolbarContainer) {
  22245. updateChromePosition(optToolbarWidth);
  22246. }
  22247. if (isSticky) {
  22248. floatContainer.on(stickyAction);
  22249. }
  22250. repositionPopups$1();
  22251. };
  22252. const doUpdateMode = () => {
  22253. if (useFixedToolbarContainer || !isSticky || !isVisible()) {
  22254. return false;
  22255. }
  22256. return floatContainer.get().exists(fc => {
  22257. const currentMode = headerBackstage.getDockingMode();
  22258. const newMode = calcMode(fc);
  22259. if (newMode !== currentMode) {
  22260. setupMode(newMode);
  22261. return true;
  22262. } else {
  22263. return false;
  22264. }
  22265. });
  22266. };
  22267. const show = () => {
  22268. visible.set(true);
  22269. set$8(mainUi.outerContainer.element, 'display', 'flex');
  22270. DOM.addClass(editor.getBody(), 'mce-edit-focus');
  22271. each$1(uiMotherships, m => {
  22272. remove$6(m.element, 'display');
  22273. });
  22274. doUpdateMode();
  22275. if (isSplitUiMode(editor)) {
  22276. update(elem => Docking.isDocked(elem) ? Docking.reset(elem) : Docking.refresh(elem));
  22277. } else {
  22278. update(Docking.refresh);
  22279. }
  22280. };
  22281. const hide = () => {
  22282. visible.set(false);
  22283. set$8(mainUi.outerContainer.element, 'display', 'none');
  22284. DOM.removeClass(editor.getBody(), 'mce-edit-focus');
  22285. each$1(uiMotherships, m => {
  22286. set$8(m.element, 'display', 'none');
  22287. });
  22288. };
  22289. const updateMode = () => {
  22290. const changedMode = doUpdateMode();
  22291. if (changedMode) {
  22292. update(Docking.reset);
  22293. }
  22294. };
  22295. return {
  22296. isVisible,
  22297. isPositionedAtTop,
  22298. show,
  22299. hide,
  22300. update,
  22301. updateMode,
  22302. repositionPopups: repositionPopups$1
  22303. };
  22304. };
  22305. const getTargetPosAndBounds = (targetElm, isToolbarTop) => {
  22306. const bounds = box$1(targetElm);
  22307. return {
  22308. pos: isToolbarTop ? bounds.y : bounds.bottom,
  22309. bounds
  22310. };
  22311. };
  22312. const setupEvents = (editor, targetElm, ui, toolbarPersist) => {
  22313. const prevPosAndBounds = Cell(getTargetPosAndBounds(targetElm, ui.isPositionedAtTop()));
  22314. const resizeContent = e => {
  22315. const {pos, bounds} = getTargetPosAndBounds(targetElm, ui.isPositionedAtTop());
  22316. const {
  22317. pos: prevPos,
  22318. bounds: prevBounds
  22319. } = prevPosAndBounds.get();
  22320. const hasResized = bounds.height !== prevBounds.height || bounds.width !== prevBounds.width;
  22321. prevPosAndBounds.set({
  22322. pos,
  22323. bounds
  22324. });
  22325. if (hasResized) {
  22326. fireResizeContent(editor, e);
  22327. }
  22328. if (ui.isVisible()) {
  22329. if (prevPos !== pos) {
  22330. ui.update(Docking.reset);
  22331. } else if (hasResized) {
  22332. ui.updateMode();
  22333. ui.repositionPopups();
  22334. }
  22335. }
  22336. };
  22337. if (!toolbarPersist) {
  22338. editor.on('activate', ui.show);
  22339. editor.on('deactivate', ui.hide);
  22340. }
  22341. editor.on('SkinLoaded ResizeWindow', () => ui.update(Docking.reset));
  22342. editor.on('NodeChange keydown', e => {
  22343. requestAnimationFrame(() => resizeContent(e));
  22344. });
  22345. let lastScrollX = 0;
  22346. const updateUi = last(() => ui.update(Docking.refresh), 33);
  22347. editor.on('ScrollWindow', () => {
  22348. const newScrollX = get$b().left;
  22349. if (newScrollX !== lastScrollX) {
  22350. lastScrollX = newScrollX;
  22351. updateUi.throttle();
  22352. }
  22353. ui.updateMode();
  22354. });
  22355. if (isSplitUiMode(editor)) {
  22356. editor.on('ElementScroll', _args => {
  22357. ui.update(Docking.refresh);
  22358. });
  22359. }
  22360. const elementLoad = unbindable();
  22361. elementLoad.set(capture(SugarElement.fromDom(editor.getBody()), 'load', e => resizeContent(e.raw)));
  22362. editor.on('remove', () => {
  22363. elementLoad.clear();
  22364. });
  22365. };
  22366. const render = async (editor, uiRefs, rawUiConfig, backstage, args) => {
  22367. const {mainUi} = uiRefs;
  22368. const floatContainer = value$2();
  22369. const targetElm = SugarElement.fromDom(args.targetNode);
  22370. const ui = InlineHeader(editor, targetElm, uiRefs, backstage, floatContainer);
  22371. const toolbarPersist = isToolbarPersist(editor);
  22372. await inline(editor);
  22373. const render = () => {
  22374. if (floatContainer.isSet()) {
  22375. ui.show();
  22376. return;
  22377. }
  22378. floatContainer.set(OuterContainer.getHeader(mainUi.outerContainer).getOrDie());
  22379. const uiContainer = getUiContainer(editor);
  22380. if (isSplitUiMode(editor)) {
  22381. attachSystemAfter(targetElm, mainUi.mothership);
  22382. attachSystemAfter(targetElm, uiRefs.popupUi.mothership);
  22383. } else {
  22384. attachSystem(uiContainer, mainUi.mothership);
  22385. }
  22386. attachSystem(uiContainer, uiRefs.dialogUi.mothership);
  22387. setToolbar(editor, uiRefs, rawUiConfig, backstage);
  22388. OuterContainer.setMenubar(mainUi.outerContainer, identifyMenus(editor, rawUiConfig));
  22389. ui.show();
  22390. setupEvents(editor, targetElm, ui, toolbarPersist);
  22391. editor.nodeChanged();
  22392. };
  22393. editor.on('show', render);
  22394. editor.on('hide', ui.hide);
  22395. if (!toolbarPersist) {
  22396. editor.on('focus', render);
  22397. editor.on('blur', ui.hide);
  22398. }
  22399. editor.on('init', () => {
  22400. if (editor.hasFocus() || toolbarPersist) {
  22401. render();
  22402. }
  22403. });
  22404. setupReadonlyModeSwitch(editor, uiRefs);
  22405. const api = {
  22406. show: render,
  22407. hide: ui.hide,
  22408. setEnabled: state => {
  22409. broadcastReadonly(uiRefs, !state);
  22410. },
  22411. isEnabled: () => !Disabling.isDisabled(mainUi.outerContainer)
  22412. };
  22413. return {
  22414. editorContainer: mainUi.outerContainer.element.dom,
  22415. api
  22416. };
  22417. };
  22418. var Inline = /*#__PURE__*/Object.freeze({
  22419. __proto__: null,
  22420. render: render
  22421. });
  22422. const LazyUiReferences = () => {
  22423. const dialogUi = value$2();
  22424. const popupUi = value$2();
  22425. const mainUi = value$2();
  22426. const lazyGetInOuterOrDie = (label, f) => () => mainUi.get().bind(oc => f(oc.outerContainer)).getOrDie(`Could not find ${ label } element in OuterContainer`);
  22427. const getUiMotherships = () => {
  22428. const optDialogMothership = dialogUi.get().map(ui => ui.mothership);
  22429. const optPopupMothership = popupUi.get().map(ui => ui.mothership);
  22430. return optDialogMothership.fold(() => optPopupMothership.toArray(), dm => optPopupMothership.fold(() => [dm], pm => eq(dm.element, pm.element) ? [dm] : [
  22431. dm,
  22432. pm
  22433. ]));
  22434. };
  22435. return {
  22436. dialogUi,
  22437. popupUi,
  22438. mainUi,
  22439. getUiMotherships,
  22440. lazyGetInOuterOrDie
  22441. };
  22442. };
  22443. const showContextToolbarEvent = 'contexttoolbar-show';
  22444. const hideContextToolbarEvent = 'contexttoolbar-hide';
  22445. const getFormApi = input => ({
  22446. hide: () => emit(input, sandboxClose()),
  22447. getValue: () => Representing.getValue(input)
  22448. });
  22449. const runOnExecute = (memInput, original) => run$1(internalToolbarButtonExecute, (comp, se) => {
  22450. const input = memInput.get(comp);
  22451. const formApi = getFormApi(input);
  22452. original.onAction(formApi, se.event.buttonApi);
  22453. });
  22454. const renderContextButton = (memInput, button, providers) => {
  22455. const {primary, ...rest} = button.original;
  22456. const bridged = getOrDie(createToolbarButton({
  22457. ...rest,
  22458. type: 'button',
  22459. onAction: noop
  22460. }));
  22461. return renderToolbarButtonWith(bridged, providers, [runOnExecute(memInput, button)]);
  22462. };
  22463. const renderContextToggleButton = (memInput, button, providers) => {
  22464. const {primary, ...rest} = button.original;
  22465. const bridged = getOrDie(createToggleButton({
  22466. ...rest,
  22467. type: 'togglebutton',
  22468. onAction: noop
  22469. }));
  22470. return renderToolbarToggleButtonWith(bridged, providers, [runOnExecute(memInput, button)]);
  22471. };
  22472. const isToggleButton = button => button.type === 'contextformtogglebutton';
  22473. const generateOne = (memInput, button, providersBackstage) => {
  22474. if (isToggleButton(button)) {
  22475. return renderContextToggleButton(memInput, button, providersBackstage);
  22476. } else {
  22477. return renderContextButton(memInput, button, providersBackstage);
  22478. }
  22479. };
  22480. const generate = (memInput, buttons, providersBackstage) => {
  22481. const mementos = map$2(buttons, button => record(generateOne(memInput, button, providersBackstage)));
  22482. const asSpecs = () => map$2(mementos, mem => mem.asSpec());
  22483. const findPrimary = compInSystem => findMap(buttons, (button, i) => {
  22484. if (button.primary) {
  22485. return Optional.from(mementos[i]).bind(mem => mem.getOpt(compInSystem)).filter(not(Disabling.isDisabled));
  22486. } else {
  22487. return Optional.none();
  22488. }
  22489. });
  22490. return {
  22491. asSpecs,
  22492. findPrimary
  22493. };
  22494. };
  22495. const buildInitGroups = (ctx, providers) => {
  22496. const inputAttributes = ctx.label.fold(() => ({}), label => ({ 'aria-label': label }));
  22497. const memInput = record(Input.sketch({
  22498. inputClasses: [
  22499. 'tox-toolbar-textfield',
  22500. 'tox-toolbar-nav-js'
  22501. ],
  22502. data: ctx.initValue(),
  22503. inputAttributes,
  22504. selectOnFocus: true,
  22505. inputBehaviours: derive$1([Keying.config({
  22506. mode: 'special',
  22507. onEnter: input => commands.findPrimary(input).map(primary => {
  22508. emitExecute(primary);
  22509. return true;
  22510. }),
  22511. onLeft: (comp, se) => {
  22512. se.cut();
  22513. return Optional.none();
  22514. },
  22515. onRight: (comp, se) => {
  22516. se.cut();
  22517. return Optional.none();
  22518. }
  22519. })])
  22520. }));
  22521. const commands = generate(memInput, ctx.commands, providers);
  22522. return [
  22523. {
  22524. title: Optional.none(),
  22525. items: [memInput.asSpec()]
  22526. },
  22527. {
  22528. title: Optional.none(),
  22529. items: commands.asSpecs()
  22530. }
  22531. ];
  22532. };
  22533. const renderContextForm = (toolbarType, ctx, providers) => renderToolbar({
  22534. type: toolbarType,
  22535. uid: generate$6('context-toolbar'),
  22536. initGroups: buildInitGroups(ctx, providers),
  22537. onEscape: Optional.none,
  22538. cyclicKeying: true,
  22539. providers
  22540. });
  22541. const ContextForm = {
  22542. renderContextForm,
  22543. buildInitGroups
  22544. };
  22545. const isVerticalOverlap = (a, b, threshold) => b.bottom - a.y >= threshold && a.bottom - b.y >= threshold;
  22546. const getRangeRect = rng => {
  22547. const rect = rng.getBoundingClientRect();
  22548. if (rect.height <= 0 && rect.width <= 0) {
  22549. const leaf$1 = leaf(SugarElement.fromDom(rng.startContainer), rng.startOffset).element;
  22550. const elm = isText(leaf$1) ? parent(leaf$1) : Optional.some(leaf$1);
  22551. return elm.filter(isElement$1).map(e => e.dom.getBoundingClientRect()).getOr(rect);
  22552. } else {
  22553. return rect;
  22554. }
  22555. };
  22556. const getSelectionBounds = editor => {
  22557. const rng = editor.selection.getRng();
  22558. const rect = getRangeRect(rng);
  22559. if (editor.inline) {
  22560. const scroll = get$b();
  22561. return bounds(scroll.left + rect.left, scroll.top + rect.top, rect.width, rect.height);
  22562. } else {
  22563. const bodyPos = absolute$2(SugarElement.fromDom(editor.getBody()));
  22564. return bounds(bodyPos.x + rect.left, bodyPos.y + rect.top, rect.width, rect.height);
  22565. }
  22566. };
  22567. const getAnchorElementBounds = (editor, lastElement) => lastElement.filter(elem => inBody(elem) && isHTMLElement(elem)).map(absolute$2).getOrThunk(() => getSelectionBounds(editor));
  22568. const getHorizontalBounds = (contentAreaBox, viewportBounds, margin) => {
  22569. const x = Math.max(contentAreaBox.x + margin, viewportBounds.x);
  22570. const right = Math.min(contentAreaBox.right - margin, viewportBounds.right);
  22571. return {
  22572. x,
  22573. width: right - x
  22574. };
  22575. };
  22576. const getVerticalBounds = (editor, contentAreaBox, viewportBounds, isToolbarLocationTop, toolbarType, margin) => {
  22577. const container = SugarElement.fromDom(editor.getContainer());
  22578. const header = descendant(container, '.tox-editor-header').getOr(container);
  22579. const headerBox = box$1(header);
  22580. const isToolbarBelowContentArea = headerBox.y >= contentAreaBox.bottom;
  22581. const isToolbarAbove = isToolbarLocationTop && !isToolbarBelowContentArea;
  22582. if (editor.inline && isToolbarAbove) {
  22583. return {
  22584. y: Math.max(headerBox.bottom + margin, viewportBounds.y),
  22585. bottom: viewportBounds.bottom
  22586. };
  22587. }
  22588. if (editor.inline && !isToolbarAbove) {
  22589. return {
  22590. y: viewportBounds.y,
  22591. bottom: Math.min(headerBox.y - margin, viewportBounds.bottom)
  22592. };
  22593. }
  22594. const containerBounds = toolbarType === 'line' ? box$1(container) : contentAreaBox;
  22595. if (isToolbarAbove) {
  22596. return {
  22597. y: Math.max(headerBox.bottom + margin, viewportBounds.y),
  22598. bottom: Math.min(containerBounds.bottom - margin, viewportBounds.bottom)
  22599. };
  22600. }
  22601. return {
  22602. y: Math.max(containerBounds.y + margin, viewportBounds.y),
  22603. bottom: Math.min(headerBox.y - margin, viewportBounds.bottom)
  22604. };
  22605. };
  22606. const getContextToolbarBounds = (editor, sharedBackstage, toolbarType, margin = 0) => {
  22607. const viewportBounds = getBounds$3(window);
  22608. const contentAreaBox = box$1(SugarElement.fromDom(editor.getContentAreaContainer()));
  22609. const toolbarOrMenubarEnabled = isMenubarEnabled(editor) || isToolbarEnabled(editor) || isMultipleToolbars(editor);
  22610. const {x, width} = getHorizontalBounds(contentAreaBox, viewportBounds, margin);
  22611. if (editor.inline && !toolbarOrMenubarEnabled) {
  22612. return bounds(x, viewportBounds.y, width, viewportBounds.height);
  22613. } else {
  22614. const isToolbarTop = sharedBackstage.header.isPositionedAtTop();
  22615. const {y, bottom} = getVerticalBounds(editor, contentAreaBox, viewportBounds, isToolbarTop, toolbarType, margin);
  22616. return bounds(x, y, width, bottom - y);
  22617. }
  22618. };
  22619. const bubbleSize$1 = 12;
  22620. const bubbleAlignments$1 = {
  22621. valignCentre: [],
  22622. alignCentre: [],
  22623. alignLeft: ['tox-pop--align-left'],
  22624. alignRight: ['tox-pop--align-right'],
  22625. right: ['tox-pop--right'],
  22626. left: ['tox-pop--left'],
  22627. bottom: ['tox-pop--bottom'],
  22628. top: ['tox-pop--top'],
  22629. inset: ['tox-pop--inset']
  22630. };
  22631. const anchorOverrides = {
  22632. maxHeightFunction: expandable$1(),
  22633. maxWidthFunction: expandable()
  22634. };
  22635. const isEntireElementSelected = (editor, elem) => {
  22636. const rng = editor.selection.getRng();
  22637. const leaf$1 = leaf(SugarElement.fromDom(rng.startContainer), rng.startOffset);
  22638. return rng.startContainer === rng.endContainer && rng.startOffset === rng.endOffset - 1 && eq(leaf$1.element, elem);
  22639. };
  22640. const preservePosition = (elem, position, f) => {
  22641. const currentPosition = getRaw(elem, 'position');
  22642. set$8(elem, 'position', position);
  22643. const result = f(elem);
  22644. currentPosition.each(pos => set$8(elem, 'position', pos));
  22645. return result;
  22646. };
  22647. const shouldUseInsetLayouts = position => position === 'node';
  22648. const determineInsetLayout = (editor, contextbar, elem, data, bounds) => {
  22649. const selectionBounds = getSelectionBounds(editor);
  22650. const isSameAnchorElement = data.lastElement().exists(prev => eq(elem, prev));
  22651. if (isEntireElementSelected(editor, elem)) {
  22652. return isSameAnchorElement ? preserve : north;
  22653. } else if (isSameAnchorElement) {
  22654. return preservePosition(contextbar, data.getMode(), () => {
  22655. const isOverlapping = isVerticalOverlap(selectionBounds, box$1(contextbar), -20);
  22656. return isOverlapping && !data.isReposition() ? flip : preserve;
  22657. });
  22658. } else {
  22659. const yBounds = data.getMode() === 'fixed' ? bounds.y + get$b().top : bounds.y;
  22660. const contextbarHeight = get$d(contextbar) + bubbleSize$1;
  22661. return yBounds + contextbarHeight <= selectionBounds.y ? north : south;
  22662. }
  22663. };
  22664. const getAnchorSpec$2 = (editor, mobile, data, position) => {
  22665. const smartInsetLayout = elem => (anchor, element, bubbles, placee, bounds) => {
  22666. const layout = determineInsetLayout(editor, placee, elem, data, bounds);
  22667. const newAnchor = {
  22668. ...anchor,
  22669. y: bounds.y,
  22670. height: bounds.height
  22671. };
  22672. return {
  22673. ...layout(newAnchor, element, bubbles, placee, bounds),
  22674. alwaysFit: true
  22675. };
  22676. };
  22677. const getInsetLayouts = elem => shouldUseInsetLayouts(position) ? [smartInsetLayout(elem)] : [];
  22678. const desktopAnchorSpecLayouts = {
  22679. onLtr: elem => [
  22680. north$2,
  22681. south$2,
  22682. northeast$2,
  22683. southeast$2,
  22684. northwest$2,
  22685. southwest$2
  22686. ].concat(getInsetLayouts(elem)),
  22687. onRtl: elem => [
  22688. north$2,
  22689. south$2,
  22690. northwest$2,
  22691. southwest$2,
  22692. northeast$2,
  22693. southeast$2
  22694. ].concat(getInsetLayouts(elem))
  22695. };
  22696. const mobileAnchorSpecLayouts = {
  22697. onLtr: elem => [
  22698. south$2,
  22699. southeast$2,
  22700. southwest$2,
  22701. northeast$2,
  22702. northwest$2,
  22703. north$2
  22704. ].concat(getInsetLayouts(elem)),
  22705. onRtl: elem => [
  22706. south$2,
  22707. southwest$2,
  22708. southeast$2,
  22709. northwest$2,
  22710. northeast$2,
  22711. north$2
  22712. ].concat(getInsetLayouts(elem))
  22713. };
  22714. return mobile ? mobileAnchorSpecLayouts : desktopAnchorSpecLayouts;
  22715. };
  22716. const getAnchorLayout = (editor, position, isTouch, data) => {
  22717. if (position === 'line') {
  22718. return {
  22719. bubble: nu$5(bubbleSize$1, 0, bubbleAlignments$1),
  22720. layouts: {
  22721. onLtr: () => [east$2],
  22722. onRtl: () => [west$2]
  22723. },
  22724. overrides: anchorOverrides
  22725. };
  22726. } else {
  22727. return {
  22728. bubble: nu$5(0, bubbleSize$1, bubbleAlignments$1, 1 / bubbleSize$1),
  22729. layouts: getAnchorSpec$2(editor, isTouch, data, position),
  22730. overrides: anchorOverrides
  22731. };
  22732. }
  22733. };
  22734. const matchTargetWith = (elem, candidates) => {
  22735. const ctxs = filter$2(candidates, toolbarApi => toolbarApi.predicate(elem.dom));
  22736. const {pass, fail} = partition$3(ctxs, t => t.type === 'contexttoolbar');
  22737. return {
  22738. contextToolbars: pass,
  22739. contextForms: fail
  22740. };
  22741. };
  22742. const filterByPositionForStartNode = toolbars => {
  22743. if (toolbars.length <= 1) {
  22744. return toolbars;
  22745. } else {
  22746. const doesPositionExist = value => exists(toolbars, t => t.position === value);
  22747. const filterToolbarsByPosition = value => filter$2(toolbars, t => t.position === value);
  22748. const hasSelectionToolbars = doesPositionExist('selection');
  22749. const hasNodeToolbars = doesPositionExist('node');
  22750. if (hasSelectionToolbars || hasNodeToolbars) {
  22751. if (hasNodeToolbars && hasSelectionToolbars) {
  22752. const nodeToolbars = filterToolbarsByPosition('node');
  22753. const selectionToolbars = map$2(filterToolbarsByPosition('selection'), t => ({
  22754. ...t,
  22755. position: 'node'
  22756. }));
  22757. return nodeToolbars.concat(selectionToolbars);
  22758. } else {
  22759. return hasSelectionToolbars ? filterToolbarsByPosition('selection') : filterToolbarsByPosition('node');
  22760. }
  22761. } else {
  22762. return filterToolbarsByPosition('line');
  22763. }
  22764. }
  22765. };
  22766. const filterByPositionForAncestorNode = toolbars => {
  22767. if (toolbars.length <= 1) {
  22768. return toolbars;
  22769. } else {
  22770. const findPosition = value => find$5(toolbars, t => t.position === value);
  22771. const basePosition = findPosition('selection').orThunk(() => findPosition('node')).orThunk(() => findPosition('line')).map(t => t.position);
  22772. return basePosition.fold(() => [], pos => filter$2(toolbars, t => t.position === pos));
  22773. }
  22774. };
  22775. const matchStartNode = (elem, nodeCandidates, editorCandidates) => {
  22776. const nodeMatches = matchTargetWith(elem, nodeCandidates);
  22777. if (nodeMatches.contextForms.length > 0) {
  22778. return Optional.some({
  22779. elem,
  22780. toolbars: [nodeMatches.contextForms[0]]
  22781. });
  22782. } else {
  22783. const editorMatches = matchTargetWith(elem, editorCandidates);
  22784. if (editorMatches.contextForms.length > 0) {
  22785. return Optional.some({
  22786. elem,
  22787. toolbars: [editorMatches.contextForms[0]]
  22788. });
  22789. } else if (nodeMatches.contextToolbars.length > 0 || editorMatches.contextToolbars.length > 0) {
  22790. const toolbars = filterByPositionForStartNode(nodeMatches.contextToolbars.concat(editorMatches.contextToolbars));
  22791. return Optional.some({
  22792. elem,
  22793. toolbars
  22794. });
  22795. } else {
  22796. return Optional.none();
  22797. }
  22798. }
  22799. };
  22800. const matchAncestor = (isRoot, startNode, scopes) => {
  22801. if (isRoot(startNode)) {
  22802. return Optional.none();
  22803. } else {
  22804. return ancestor$2(startNode, ancestorElem => {
  22805. if (isElement$1(ancestorElem)) {
  22806. const {contextToolbars, contextForms} = matchTargetWith(ancestorElem, scopes.inNodeScope);
  22807. const toolbars = contextForms.length > 0 ? contextForms : filterByPositionForAncestorNode(contextToolbars);
  22808. return toolbars.length > 0 ? Optional.some({
  22809. elem: ancestorElem,
  22810. toolbars
  22811. }) : Optional.none();
  22812. } else {
  22813. return Optional.none();
  22814. }
  22815. }, isRoot);
  22816. }
  22817. };
  22818. const lookup$1 = (scopes, editor) => {
  22819. const rootElem = SugarElement.fromDom(editor.getBody());
  22820. const isRoot = elem => eq(elem, rootElem);
  22821. const isOutsideRoot = startNode => !isRoot(startNode) && !contains(rootElem, startNode);
  22822. const startNode = SugarElement.fromDom(editor.selection.getNode());
  22823. if (isOutsideRoot(startNode)) {
  22824. return Optional.none();
  22825. }
  22826. return matchStartNode(startNode, scopes.inNodeScope, scopes.inEditorScope).orThunk(() => matchAncestor(isRoot, startNode, scopes));
  22827. };
  22828. const categorise = (contextToolbars, navigate) => {
  22829. const forms = {};
  22830. const inNodeScope = [];
  22831. const inEditorScope = [];
  22832. const formNavigators = {};
  22833. const lookupTable = {};
  22834. const registerForm = (key, toolbarSpec) => {
  22835. const contextForm = getOrDie(createContextForm(toolbarSpec));
  22836. forms[key] = contextForm;
  22837. contextForm.launch.map(launch => {
  22838. formNavigators['form:' + key + ''] = {
  22839. ...toolbarSpec.launch,
  22840. type: launch.type === 'contextformtogglebutton' ? 'togglebutton' : 'button',
  22841. onAction: () => {
  22842. navigate(contextForm);
  22843. }
  22844. };
  22845. });
  22846. if (contextForm.scope === 'editor') {
  22847. inEditorScope.push(contextForm);
  22848. } else {
  22849. inNodeScope.push(contextForm);
  22850. }
  22851. lookupTable[key] = contextForm;
  22852. };
  22853. const registerToolbar = (key, toolbarSpec) => {
  22854. createContextToolbar(toolbarSpec).each(contextToolbar => {
  22855. if (toolbarSpec.scope === 'editor') {
  22856. inEditorScope.push(contextToolbar);
  22857. } else {
  22858. inNodeScope.push(contextToolbar);
  22859. }
  22860. lookupTable[key] = contextToolbar;
  22861. });
  22862. };
  22863. const keys$1 = keys(contextToolbars);
  22864. each$1(keys$1, key => {
  22865. const toolbarApi = contextToolbars[key];
  22866. if (toolbarApi.type === 'contextform') {
  22867. registerForm(key, toolbarApi);
  22868. } else if (toolbarApi.type === 'contexttoolbar') {
  22869. registerToolbar(key, toolbarApi);
  22870. }
  22871. });
  22872. return {
  22873. forms,
  22874. inNodeScope,
  22875. inEditorScope,
  22876. lookupTable,
  22877. formNavigators
  22878. };
  22879. };
  22880. const forwardSlideEvent = generate$6('forward-slide');
  22881. const backSlideEvent = generate$6('backward-slide');
  22882. const changeSlideEvent = generate$6('change-slide-event');
  22883. const resizingClass = 'tox-pop--resizing';
  22884. const renderContextToolbar = spec => {
  22885. const stack = Cell([]);
  22886. return InlineView.sketch({
  22887. dom: {
  22888. tag: 'div',
  22889. classes: ['tox-pop']
  22890. },
  22891. fireDismissalEventInstead: { event: 'doNotDismissYet' },
  22892. onShow: comp => {
  22893. stack.set([]);
  22894. InlineView.getContent(comp).each(c => {
  22895. remove$6(c.element, 'visibility');
  22896. });
  22897. remove$2(comp.element, resizingClass);
  22898. remove$6(comp.element, 'width');
  22899. },
  22900. inlineBehaviours: derive$1([
  22901. config('context-toolbar-events', [
  22902. runOnSource(transitionend(), (comp, se) => {
  22903. if (se.event.raw.propertyName === 'width') {
  22904. remove$2(comp.element, resizingClass);
  22905. remove$6(comp.element, 'width');
  22906. }
  22907. }),
  22908. run$1(changeSlideEvent, (comp, se) => {
  22909. const elem = comp.element;
  22910. remove$6(elem, 'width');
  22911. const currentWidth = get$c(elem);
  22912. InlineView.setContent(comp, se.event.contents);
  22913. add$2(elem, resizingClass);
  22914. const newWidth = get$c(elem);
  22915. set$8(elem, 'width', currentWidth + 'px');
  22916. InlineView.getContent(comp).each(newContents => {
  22917. se.event.focus.bind(f => {
  22918. focus$3(f);
  22919. return search(elem);
  22920. }).orThunk(() => {
  22921. Keying.focusIn(newContents);
  22922. return active$1(getRootNode(elem));
  22923. });
  22924. });
  22925. setTimeout(() => {
  22926. set$8(comp.element, 'width', newWidth + 'px');
  22927. }, 0);
  22928. }),
  22929. run$1(forwardSlideEvent, (comp, se) => {
  22930. InlineView.getContent(comp).each(oldContents => {
  22931. stack.set(stack.get().concat([{
  22932. bar: oldContents,
  22933. focus: active$1(getRootNode(comp.element))
  22934. }]));
  22935. });
  22936. emitWith(comp, changeSlideEvent, {
  22937. contents: se.event.forwardContents,
  22938. focus: Optional.none()
  22939. });
  22940. }),
  22941. run$1(backSlideEvent, (comp, _se) => {
  22942. last$1(stack.get()).each(last => {
  22943. stack.set(stack.get().slice(0, stack.get().length - 1));
  22944. emitWith(comp, changeSlideEvent, {
  22945. contents: premade(last.bar),
  22946. focus: last.focus
  22947. });
  22948. });
  22949. })
  22950. ]),
  22951. Keying.config({
  22952. mode: 'special',
  22953. onEscape: comp => last$1(stack.get()).fold(() => spec.onEscape(), _ => {
  22954. emit(comp, backSlideEvent);
  22955. return Optional.some(true);
  22956. })
  22957. })
  22958. ]),
  22959. lazySink: () => Result.value(spec.sink)
  22960. });
  22961. };
  22962. const transitionClass = 'tox-pop--transition';
  22963. const register$9 = (editor, registryContextToolbars, sink, extras) => {
  22964. const backstage = extras.backstage;
  22965. const sharedBackstage = backstage.shared;
  22966. const isTouch = detect$2().deviceType.isTouch;
  22967. const lastElement = value$2();
  22968. const lastTrigger = value$2();
  22969. const lastContextPosition = value$2();
  22970. const contextbar = build$1(renderContextToolbar({
  22971. sink,
  22972. onEscape: () => {
  22973. editor.focus();
  22974. return Optional.some(true);
  22975. }
  22976. }));
  22977. const getBounds = () => {
  22978. const position = lastContextPosition.get().getOr('node');
  22979. const margin = shouldUseInsetLayouts(position) ? 1 : 0;
  22980. return getContextToolbarBounds(editor, sharedBackstage, position, margin);
  22981. };
  22982. const canLaunchToolbar = () => {
  22983. return !editor.removed && !(isTouch() && backstage.isContextMenuOpen());
  22984. };
  22985. const isSameLaunchElement = elem => is$1(lift2(elem, lastElement.get(), eq), true);
  22986. const shouldContextToolbarHide = () => {
  22987. if (!canLaunchToolbar()) {
  22988. return true;
  22989. } else {
  22990. const contextToolbarBounds = getBounds();
  22991. const anchorBounds = is$1(lastContextPosition.get(), 'node') ? getAnchorElementBounds(editor, lastElement.get()) : getSelectionBounds(editor);
  22992. return contextToolbarBounds.height <= 0 || !isVerticalOverlap(anchorBounds, contextToolbarBounds, 0.01);
  22993. }
  22994. };
  22995. const close = () => {
  22996. lastElement.clear();
  22997. lastTrigger.clear();
  22998. lastContextPosition.clear();
  22999. InlineView.hide(contextbar);
  23000. };
  23001. const hideOrRepositionIfNecessary = () => {
  23002. if (InlineView.isOpen(contextbar)) {
  23003. const contextBarEle = contextbar.element;
  23004. remove$6(contextBarEle, 'display');
  23005. if (shouldContextToolbarHide()) {
  23006. set$8(contextBarEle, 'display', 'none');
  23007. } else {
  23008. lastTrigger.set(0);
  23009. InlineView.reposition(contextbar);
  23010. }
  23011. }
  23012. };
  23013. const wrapInPopDialog = toolbarSpec => ({
  23014. dom: {
  23015. tag: 'div',
  23016. classes: ['tox-pop__dialog']
  23017. },
  23018. components: [toolbarSpec],
  23019. behaviours: derive$1([
  23020. Keying.config({ mode: 'acyclic' }),
  23021. config('pop-dialog-wrap-events', [
  23022. runOnAttached(comp => {
  23023. editor.shortcuts.add('ctrl+F9', 'focus statusbar', () => Keying.focusIn(comp));
  23024. }),
  23025. runOnDetached(_comp => {
  23026. editor.shortcuts.remove('ctrl+F9');
  23027. })
  23028. ])
  23029. ])
  23030. });
  23031. const getScopes = cached(() => categorise(registryContextToolbars, toolbarApi => {
  23032. const alloySpec = buildToolbar([toolbarApi]);
  23033. emitWith(contextbar, forwardSlideEvent, { forwardContents: wrapInPopDialog(alloySpec) });
  23034. }));
  23035. const buildContextToolbarGroups = (allButtons, ctx) => identifyButtons(editor, {
  23036. buttons: allButtons,
  23037. toolbar: ctx.items,
  23038. allowToolbarGroups: false
  23039. }, extras.backstage, Optional.some(['form:']));
  23040. const buildContextFormGroups = (ctx, providers) => ContextForm.buildInitGroups(ctx, providers);
  23041. const buildToolbar = toolbars => {
  23042. const {buttons} = editor.ui.registry.getAll();
  23043. const scopes = getScopes();
  23044. const allButtons = {
  23045. ...buttons,
  23046. ...scopes.formNavigators
  23047. };
  23048. const toolbarType = getToolbarMode(editor) === ToolbarMode$1.scrolling ? ToolbarMode$1.scrolling : ToolbarMode$1.default;
  23049. const initGroups = flatten(map$2(toolbars, ctx => ctx.type === 'contexttoolbar' ? buildContextToolbarGroups(allButtons, ctx) : buildContextFormGroups(ctx, sharedBackstage.providers)));
  23050. return renderToolbar({
  23051. type: toolbarType,
  23052. uid: generate$6('context-toolbar'),
  23053. initGroups,
  23054. onEscape: Optional.none,
  23055. cyclicKeying: true,
  23056. providers: sharedBackstage.providers
  23057. });
  23058. };
  23059. const getAnchor = (position, element) => {
  23060. const anchorage = position === 'node' ? sharedBackstage.anchors.node(element) : sharedBackstage.anchors.cursor();
  23061. const anchorLayout = getAnchorLayout(editor, position, isTouch(), {
  23062. lastElement: lastElement.get,
  23063. isReposition: () => is$1(lastTrigger.get(), 0),
  23064. getMode: () => Positioning.getMode(sink)
  23065. });
  23066. return deepMerge(anchorage, anchorLayout);
  23067. };
  23068. const launchContext = (toolbarApi, elem) => {
  23069. launchContextToolbar.cancel();
  23070. if (!canLaunchToolbar()) {
  23071. return;
  23072. }
  23073. const toolbarSpec = buildToolbar(toolbarApi);
  23074. const position = toolbarApi[0].position;
  23075. const anchor = getAnchor(position, elem);
  23076. lastContextPosition.set(position);
  23077. lastTrigger.set(1);
  23078. const contextBarEle = contextbar.element;
  23079. remove$6(contextBarEle, 'display');
  23080. if (!isSameLaunchElement(elem)) {
  23081. remove$2(contextBarEle, transitionClass);
  23082. Positioning.reset(sink, contextbar);
  23083. }
  23084. InlineView.showWithinBounds(contextbar, wrapInPopDialog(toolbarSpec), {
  23085. anchor,
  23086. transition: {
  23087. classes: [transitionClass],
  23088. mode: 'placement'
  23089. }
  23090. }, () => Optional.some(getBounds()));
  23091. elem.fold(lastElement.clear, lastElement.set);
  23092. if (shouldContextToolbarHide()) {
  23093. set$8(contextBarEle, 'display', 'none');
  23094. }
  23095. };
  23096. let isDragging = false;
  23097. const launchContextToolbar = last(() => {
  23098. if (!editor.hasFocus() || editor.removed || isDragging) {
  23099. return;
  23100. }
  23101. if (has(contextbar.element, transitionClass)) {
  23102. launchContextToolbar.throttle();
  23103. } else {
  23104. const scopes = getScopes();
  23105. lookup$1(scopes, editor).fold(close, info => {
  23106. launchContext(info.toolbars, Optional.some(info.elem));
  23107. });
  23108. }
  23109. }, 17);
  23110. editor.on('init', () => {
  23111. editor.on('remove', close);
  23112. editor.on('ScrollContent ScrollWindow ObjectResized ResizeEditor longpress', hideOrRepositionIfNecessary);
  23113. editor.on('click keyup focus SetContent', launchContextToolbar.throttle);
  23114. editor.on(hideContextToolbarEvent, close);
  23115. editor.on(showContextToolbarEvent, e => {
  23116. const scopes = getScopes();
  23117. get$g(scopes.lookupTable, e.toolbarKey).each(ctx => {
  23118. launchContext([ctx], someIf(e.target !== editor, e.target));
  23119. InlineView.getContent(contextbar).each(Keying.focusIn);
  23120. });
  23121. });
  23122. editor.on('focusout', _e => {
  23123. global$9.setEditorTimeout(editor, () => {
  23124. if (search(sink.element).isNone() && search(contextbar.element).isNone()) {
  23125. close();
  23126. }
  23127. }, 0);
  23128. });
  23129. editor.on('SwitchMode', () => {
  23130. if (editor.mode.isReadOnly()) {
  23131. close();
  23132. }
  23133. });
  23134. editor.on('AfterProgressState', event => {
  23135. if (event.state) {
  23136. close();
  23137. } else if (editor.hasFocus()) {
  23138. launchContextToolbar.throttle();
  23139. }
  23140. });
  23141. editor.on('dragstart', () => {
  23142. isDragging = true;
  23143. });
  23144. editor.on('dragend drop', () => {
  23145. isDragging = false;
  23146. });
  23147. editor.on('NodeChange', _e => {
  23148. search(contextbar.element).fold(launchContextToolbar.throttle, noop);
  23149. });
  23150. });
  23151. };
  23152. const register$8 = editor => {
  23153. const alignToolbarButtons = [
  23154. {
  23155. name: 'alignleft',
  23156. text: 'Align left',
  23157. cmd: 'JustifyLeft',
  23158. icon: 'align-left'
  23159. },
  23160. {
  23161. name: 'aligncenter',
  23162. text: 'Align center',
  23163. cmd: 'JustifyCenter',
  23164. icon: 'align-center'
  23165. },
  23166. {
  23167. name: 'alignright',
  23168. text: 'Align right',
  23169. cmd: 'JustifyRight',
  23170. icon: 'align-right'
  23171. },
  23172. {
  23173. name: 'alignjustify',
  23174. text: 'Justify',
  23175. cmd: 'JustifyFull',
  23176. icon: 'align-justify'
  23177. }
  23178. ];
  23179. each$1(alignToolbarButtons, item => {
  23180. editor.ui.registry.addToggleButton(item.name, {
  23181. tooltip: item.text,
  23182. icon: item.icon,
  23183. onAction: onActionExecCommand(editor, item.cmd),
  23184. onSetup: onSetupFormatToggle(editor, item.name)
  23185. });
  23186. });
  23187. editor.ui.registry.addButton('alignnone', {
  23188. tooltip: 'No alignment',
  23189. icon: 'align-none',
  23190. onAction: onActionExecCommand(editor, 'JustifyNone')
  23191. });
  23192. };
  23193. const registerController = (editor, spec) => {
  23194. const getMenuItems = () => {
  23195. const options = spec.getOptions(editor);
  23196. const initial = spec.getCurrent(editor).map(spec.hash);
  23197. const current = value$2();
  23198. return map$2(options, value => ({
  23199. type: 'togglemenuitem',
  23200. text: spec.display(value),
  23201. onSetup: api => {
  23202. const setActive = active => {
  23203. if (active) {
  23204. current.on(oldApi => oldApi.setActive(false));
  23205. current.set(api);
  23206. }
  23207. api.setActive(active);
  23208. };
  23209. setActive(is$1(initial, spec.hash(value)));
  23210. const unbindWatcher = spec.watcher(editor, value, setActive);
  23211. return () => {
  23212. current.clear();
  23213. unbindWatcher();
  23214. };
  23215. },
  23216. onAction: () => spec.setCurrent(editor, value)
  23217. }));
  23218. };
  23219. editor.ui.registry.addMenuButton(spec.name, {
  23220. tooltip: spec.text,
  23221. icon: spec.icon,
  23222. fetch: callback => callback(getMenuItems()),
  23223. onSetup: spec.onToolbarSetup
  23224. });
  23225. editor.ui.registry.addNestedMenuItem(spec.name, {
  23226. type: 'nestedmenuitem',
  23227. text: spec.text,
  23228. getSubmenuItems: getMenuItems,
  23229. onSetup: spec.onMenuSetup
  23230. });
  23231. };
  23232. const lineHeightSpec = {
  23233. name: 'lineheight',
  23234. text: 'Line height',
  23235. icon: 'line-height',
  23236. getOptions: getLineHeightFormats,
  23237. hash: input => normalise(input, [
  23238. 'fixed',
  23239. 'relative',
  23240. 'empty'
  23241. ]).getOr(input),
  23242. display: identity,
  23243. watcher: (editor, value, callback) => editor.formatter.formatChanged('lineheight', callback, false, { value }).unbind,
  23244. getCurrent: editor => Optional.from(editor.queryCommandValue('LineHeight')),
  23245. setCurrent: (editor, value) => editor.execCommand('LineHeight', false, value)
  23246. };
  23247. const languageSpec = editor => {
  23248. const settingsOpt = Optional.from(getContentLanguages(editor));
  23249. return settingsOpt.map(settings => ({
  23250. name: 'language',
  23251. text: 'Language',
  23252. icon: 'language',
  23253. getOptions: constant$1(settings),
  23254. hash: input => isUndefined(input.customCode) ? input.code : `${ input.code }/${ input.customCode }`,
  23255. display: input => input.title,
  23256. watcher: (editor, value, callback) => {
  23257. var _a;
  23258. return editor.formatter.formatChanged('lang', callback, false, {
  23259. value: value.code,
  23260. customValue: (_a = value.customCode) !== null && _a !== void 0 ? _a : null
  23261. }).unbind;
  23262. },
  23263. getCurrent: editor => {
  23264. const node = SugarElement.fromDom(editor.selection.getNode());
  23265. return closest$4(node, n => Optional.some(n).filter(isElement$1).bind(ele => {
  23266. const codeOpt = getOpt(ele, 'lang');
  23267. return codeOpt.map(code => {
  23268. const customCode = getOpt(ele, 'data-mce-lang').getOrUndefined();
  23269. return {
  23270. code,
  23271. customCode,
  23272. title: ''
  23273. };
  23274. });
  23275. }));
  23276. },
  23277. setCurrent: (editor, lang) => editor.execCommand('Lang', false, lang),
  23278. onToolbarSetup: api => {
  23279. const unbinder = unbindable();
  23280. api.setActive(editor.formatter.match('lang', {}, undefined, true));
  23281. unbinder.set(editor.formatter.formatChanged('lang', api.setActive, true));
  23282. return unbinder.clear;
  23283. }
  23284. }));
  23285. };
  23286. const register$7 = editor => {
  23287. registerController(editor, lineHeightSpec);
  23288. languageSpec(editor).each(spec => registerController(editor, spec));
  23289. };
  23290. const register$6 = (editor, backstage) => {
  23291. createAlignMenu(editor, backstage);
  23292. createFontFamilyMenu(editor, backstage);
  23293. createStylesMenu(editor, backstage);
  23294. createBlocksMenu(editor, backstage);
  23295. createFontSizeMenu(editor, backstage);
  23296. };
  23297. const onSetupOutdentState = editor => onSetupEvent(editor, 'NodeChange', api => {
  23298. api.setEnabled(editor.queryCommandState('outdent'));
  23299. });
  23300. const registerButtons$2 = editor => {
  23301. editor.ui.registry.addButton('outdent', {
  23302. tooltip: 'Decrease indent',
  23303. icon: 'outdent',
  23304. onSetup: onSetupOutdentState(editor),
  23305. onAction: onActionExecCommand(editor, 'outdent')
  23306. });
  23307. editor.ui.registry.addButton('indent', {
  23308. tooltip: 'Increase indent',
  23309. icon: 'indent',
  23310. onAction: onActionExecCommand(editor, 'indent')
  23311. });
  23312. };
  23313. const register$5 = editor => {
  23314. registerButtons$2(editor);
  23315. };
  23316. const makeSetupHandler = (editor, pasteAsText) => api => {
  23317. api.setActive(pasteAsText.get());
  23318. const pastePlainTextToggleHandler = e => {
  23319. pasteAsText.set(e.state);
  23320. api.setActive(e.state);
  23321. };
  23322. editor.on('PastePlainTextToggle', pastePlainTextToggleHandler);
  23323. return () => editor.off('PastePlainTextToggle', pastePlainTextToggleHandler);
  23324. };
  23325. const register$4 = editor => {
  23326. const pasteAsText = Cell(getPasteAsText(editor));
  23327. const onAction = () => editor.execCommand('mceTogglePlainTextPaste');
  23328. editor.ui.registry.addToggleButton('pastetext', {
  23329. active: false,
  23330. icon: 'paste-text',
  23331. tooltip: 'Paste as text',
  23332. onAction,
  23333. onSetup: makeSetupHandler(editor, pasteAsText)
  23334. });
  23335. editor.ui.registry.addToggleMenuItem('pastetext', {
  23336. text: 'Paste as text',
  23337. icon: 'paste-text',
  23338. onAction,
  23339. onSetup: makeSetupHandler(editor, pasteAsText)
  23340. });
  23341. };
  23342. const onActionToggleFormat = (editor, fmt) => () => {
  23343. editor.execCommand('mceToggleFormat', false, fmt);
  23344. };
  23345. const registerFormatButtons = editor => {
  23346. global$1.each([
  23347. {
  23348. name: 'bold',
  23349. text: 'Bold',
  23350. icon: 'bold'
  23351. },
  23352. {
  23353. name: 'italic',
  23354. text: 'Italic',
  23355. icon: 'italic'
  23356. },
  23357. {
  23358. name: 'underline',
  23359. text: 'Underline',
  23360. icon: 'underline'
  23361. },
  23362. {
  23363. name: 'strikethrough',
  23364. text: 'Strikethrough',
  23365. icon: 'strike-through'
  23366. },
  23367. {
  23368. name: 'subscript',
  23369. text: 'Subscript',
  23370. icon: 'subscript'
  23371. },
  23372. {
  23373. name: 'superscript',
  23374. text: 'Superscript',
  23375. icon: 'superscript'
  23376. }
  23377. ], (btn, _idx) => {
  23378. editor.ui.registry.addToggleButton(btn.name, {
  23379. tooltip: btn.text,
  23380. icon: btn.icon,
  23381. onSetup: onSetupFormatToggle(editor, btn.name),
  23382. onAction: onActionToggleFormat(editor, btn.name)
  23383. });
  23384. });
  23385. for (let i = 1; i <= 6; i++) {
  23386. const name = 'h' + i;
  23387. editor.ui.registry.addToggleButton(name, {
  23388. text: name.toUpperCase(),
  23389. tooltip: 'Heading ' + i,
  23390. onSetup: onSetupFormatToggle(editor, name),
  23391. onAction: onActionToggleFormat(editor, name)
  23392. });
  23393. }
  23394. };
  23395. const registerCommandButtons = editor => {
  23396. global$1.each([
  23397. {
  23398. name: 'cut',
  23399. text: 'Cut',
  23400. action: 'Cut',
  23401. icon: 'cut'
  23402. },
  23403. {
  23404. name: 'copy',
  23405. text: 'Copy',
  23406. action: 'Copy',
  23407. icon: 'copy'
  23408. },
  23409. {
  23410. name: 'paste',
  23411. text: 'Paste',
  23412. action: 'Paste',
  23413. icon: 'paste'
  23414. },
  23415. {
  23416. name: 'help',
  23417. text: 'Help',
  23418. action: 'mceHelp',
  23419. icon: 'help'
  23420. },
  23421. {
  23422. name: 'selectall',
  23423. text: 'Select all',
  23424. action: 'SelectAll',
  23425. icon: 'select-all'
  23426. },
  23427. {
  23428. name: 'newdocument',
  23429. text: 'New document',
  23430. action: 'mceNewDocument',
  23431. icon: 'new-document'
  23432. },
  23433. {
  23434. name: 'removeformat',
  23435. text: 'Clear formatting',
  23436. action: 'RemoveFormat',
  23437. icon: 'remove-formatting'
  23438. },
  23439. {
  23440. name: 'remove',
  23441. text: 'Remove',
  23442. action: 'Delete',
  23443. icon: 'remove'
  23444. },
  23445. {
  23446. name: 'print',
  23447. text: 'Print',
  23448. action: 'mcePrint',
  23449. icon: 'print'
  23450. },
  23451. {
  23452. name: 'hr',
  23453. text: 'Horizontal line',
  23454. action: 'InsertHorizontalRule',
  23455. icon: 'horizontal-rule'
  23456. }
  23457. ], btn => {
  23458. editor.ui.registry.addButton(btn.name, {
  23459. tooltip: btn.text,
  23460. icon: btn.icon,
  23461. onAction: onActionExecCommand(editor, btn.action)
  23462. });
  23463. });
  23464. };
  23465. const registerCommandToggleButtons = editor => {
  23466. global$1.each([{
  23467. name: 'blockquote',
  23468. text: 'Blockquote',
  23469. action: 'mceBlockQuote',
  23470. icon: 'quote'
  23471. }], btn => {
  23472. editor.ui.registry.addToggleButton(btn.name, {
  23473. tooltip: btn.text,
  23474. icon: btn.icon,
  23475. onAction: onActionExecCommand(editor, btn.action),
  23476. onSetup: onSetupFormatToggle(editor, btn.name)
  23477. });
  23478. });
  23479. };
  23480. const registerButtons$1 = editor => {
  23481. registerFormatButtons(editor);
  23482. registerCommandButtons(editor);
  23483. registerCommandToggleButtons(editor);
  23484. };
  23485. const registerMenuItems$2 = editor => {
  23486. global$1.each([
  23487. {
  23488. name: 'bold',
  23489. text: 'Bold',
  23490. action: 'Bold',
  23491. icon: 'bold',
  23492. shortcut: 'Meta+B'
  23493. },
  23494. {
  23495. name: 'italic',
  23496. text: 'Italic',
  23497. action: 'Italic',
  23498. icon: 'italic',
  23499. shortcut: 'Meta+I'
  23500. },
  23501. {
  23502. name: 'underline',
  23503. text: 'Underline',
  23504. action: 'Underline',
  23505. icon: 'underline',
  23506. shortcut: 'Meta+U'
  23507. },
  23508. {
  23509. name: 'strikethrough',
  23510. text: 'Strikethrough',
  23511. action: 'Strikethrough',
  23512. icon: 'strike-through'
  23513. },
  23514. {
  23515. name: 'subscript',
  23516. text: 'Subscript',
  23517. action: 'Subscript',
  23518. icon: 'subscript'
  23519. },
  23520. {
  23521. name: 'superscript',
  23522. text: 'Superscript',
  23523. action: 'Superscript',
  23524. icon: 'superscript'
  23525. },
  23526. {
  23527. name: 'removeformat',
  23528. text: 'Clear formatting',
  23529. action: 'RemoveFormat',
  23530. icon: 'remove-formatting'
  23531. },
  23532. {
  23533. name: 'newdocument',
  23534. text: 'New document',
  23535. action: 'mceNewDocument',
  23536. icon: 'new-document'
  23537. },
  23538. {
  23539. name: 'cut',
  23540. text: 'Cut',
  23541. action: 'Cut',
  23542. icon: 'cut',
  23543. shortcut: 'Meta+X'
  23544. },
  23545. {
  23546. name: 'copy',
  23547. text: 'Copy',
  23548. action: 'Copy',
  23549. icon: 'copy',
  23550. shortcut: 'Meta+C'
  23551. },
  23552. {
  23553. name: 'paste',
  23554. text: 'Paste',
  23555. action: 'Paste',
  23556. icon: 'paste',
  23557. shortcut: 'Meta+V'
  23558. },
  23559. {
  23560. name: 'selectall',
  23561. text: 'Select all',
  23562. action: 'SelectAll',
  23563. icon: 'select-all',
  23564. shortcut: 'Meta+A'
  23565. },
  23566. {
  23567. name: 'print',
  23568. text: 'Print...',
  23569. action: 'mcePrint',
  23570. icon: 'print',
  23571. shortcut: 'Meta+P'
  23572. },
  23573. {
  23574. name: 'hr',
  23575. text: 'Horizontal line',
  23576. action: 'InsertHorizontalRule',
  23577. icon: 'horizontal-rule'
  23578. }
  23579. ], menuitem => {
  23580. editor.ui.registry.addMenuItem(menuitem.name, {
  23581. text: menuitem.text,
  23582. icon: menuitem.icon,
  23583. shortcut: menuitem.shortcut,
  23584. onAction: onActionExecCommand(editor, menuitem.action)
  23585. });
  23586. });
  23587. editor.ui.registry.addMenuItem('codeformat', {
  23588. text: 'Code',
  23589. icon: 'sourcecode',
  23590. onAction: onActionToggleFormat(editor, 'code')
  23591. });
  23592. };
  23593. const register$3 = editor => {
  23594. registerButtons$1(editor);
  23595. registerMenuItems$2(editor);
  23596. };
  23597. const onSetupUndoRedoState = (editor, type) => onSetupEvent(editor, 'Undo Redo AddUndo TypingUndo ClearUndos SwitchMode', api => {
  23598. api.setEnabled(!editor.mode.isReadOnly() && editor.undoManager[type]());
  23599. });
  23600. const registerMenuItems$1 = editor => {
  23601. editor.ui.registry.addMenuItem('undo', {
  23602. text: 'Undo',
  23603. icon: 'undo',
  23604. shortcut: 'Meta+Z',
  23605. onSetup: onSetupUndoRedoState(editor, 'hasUndo'),
  23606. onAction: onActionExecCommand(editor, 'undo')
  23607. });
  23608. editor.ui.registry.addMenuItem('redo', {
  23609. text: 'Redo',
  23610. icon: 'redo',
  23611. shortcut: 'Meta+Y',
  23612. onSetup: onSetupUndoRedoState(editor, 'hasRedo'),
  23613. onAction: onActionExecCommand(editor, 'redo')
  23614. });
  23615. };
  23616. const registerButtons = editor => {
  23617. editor.ui.registry.addButton('undo', {
  23618. tooltip: 'Undo',
  23619. icon: 'undo',
  23620. enabled: false,
  23621. onSetup: onSetupUndoRedoState(editor, 'hasUndo'),
  23622. onAction: onActionExecCommand(editor, 'undo')
  23623. });
  23624. editor.ui.registry.addButton('redo', {
  23625. tooltip: 'Redo',
  23626. icon: 'redo',
  23627. enabled: false,
  23628. onSetup: onSetupUndoRedoState(editor, 'hasRedo'),
  23629. onAction: onActionExecCommand(editor, 'redo')
  23630. });
  23631. };
  23632. const register$2 = editor => {
  23633. registerMenuItems$1(editor);
  23634. registerButtons(editor);
  23635. };
  23636. const onSetupVisualAidState = editor => onSetupEvent(editor, 'VisualAid', api => {
  23637. api.setActive(editor.hasVisual);
  23638. });
  23639. const registerMenuItems = editor => {
  23640. editor.ui.registry.addToggleMenuItem('visualaid', {
  23641. text: 'Visual aids',
  23642. onSetup: onSetupVisualAidState(editor),
  23643. onAction: onActionExecCommand(editor, 'mceToggleVisualAid')
  23644. });
  23645. };
  23646. const registerToolbarButton = editor => {
  23647. editor.ui.registry.addButton('visualaid', {
  23648. tooltip: 'Visual aids',
  23649. text: 'Visual aids',
  23650. onAction: onActionExecCommand(editor, 'mceToggleVisualAid')
  23651. });
  23652. };
  23653. const register$1 = editor => {
  23654. registerToolbarButton(editor);
  23655. registerMenuItems(editor);
  23656. };
  23657. const setup$6 = (editor, backstage) => {
  23658. register$8(editor);
  23659. register$3(editor);
  23660. register$6(editor, backstage);
  23661. register$2(editor);
  23662. register$c(editor);
  23663. register$1(editor);
  23664. register$5(editor);
  23665. register$7(editor);
  23666. register$4(editor);
  23667. };
  23668. const patchPipeConfig = config => isString(config) ? config.split(/[ ,]/) : config;
  23669. const option = name => editor => editor.options.get(name);
  23670. const register = editor => {
  23671. const registerOption = editor.options.register;
  23672. registerOption('contextmenu_avoid_overlap', {
  23673. processor: 'string',
  23674. default: ''
  23675. });
  23676. registerOption('contextmenu_never_use_native', {
  23677. processor: 'boolean',
  23678. default: false
  23679. });
  23680. registerOption('contextmenu', {
  23681. processor: value => {
  23682. if (value === false) {
  23683. return {
  23684. value: [],
  23685. valid: true
  23686. };
  23687. } else if (isString(value) || isArrayOf(value, isString)) {
  23688. return {
  23689. value: patchPipeConfig(value),
  23690. valid: true
  23691. };
  23692. } else {
  23693. return {
  23694. valid: false,
  23695. message: 'Must be false or a string.'
  23696. };
  23697. }
  23698. },
  23699. default: 'link linkchecker image editimage table spellchecker configurepermanentpen'
  23700. });
  23701. };
  23702. const shouldNeverUseNative = option('contextmenu_never_use_native');
  23703. const getAvoidOverlapSelector = option('contextmenu_avoid_overlap');
  23704. const isContextMenuDisabled = editor => getContextMenu(editor).length === 0;
  23705. const getContextMenu = editor => {
  23706. const contextMenus = editor.ui.registry.getAll().contextMenus;
  23707. const contextMenu = editor.options.get('contextmenu');
  23708. if (editor.options.isSet('contextmenu')) {
  23709. return contextMenu;
  23710. } else {
  23711. return filter$2(contextMenu, item => has$2(contextMenus, item));
  23712. }
  23713. };
  23714. const nu = (x, y) => ({
  23715. type: 'makeshift',
  23716. x,
  23717. y
  23718. });
  23719. const transpose = (pos, dx, dy) => {
  23720. return nu(pos.x + dx, pos.y + dy);
  23721. };
  23722. const isTouchEvent$1 = e => e.type === 'longpress' || e.type.indexOf('touch') === 0;
  23723. const fromPageXY = e => {
  23724. if (isTouchEvent$1(e)) {
  23725. const touch = e.touches[0];
  23726. return nu(touch.pageX, touch.pageY);
  23727. } else {
  23728. return nu(e.pageX, e.pageY);
  23729. }
  23730. };
  23731. const fromClientXY = e => {
  23732. if (isTouchEvent$1(e)) {
  23733. const touch = e.touches[0];
  23734. return nu(touch.clientX, touch.clientY);
  23735. } else {
  23736. return nu(e.clientX, e.clientY);
  23737. }
  23738. };
  23739. const transposeContentAreaContainer = (element, pos) => {
  23740. const containerPos = global$7.DOM.getPos(element);
  23741. return transpose(pos, containerPos.x, containerPos.y);
  23742. };
  23743. const getPointAnchor = (editor, e) => {
  23744. if (e.type === 'contextmenu' || e.type === 'longpress') {
  23745. if (editor.inline) {
  23746. return fromPageXY(e);
  23747. } else {
  23748. return transposeContentAreaContainer(editor.getContentAreaContainer(), fromClientXY(e));
  23749. }
  23750. } else {
  23751. return getSelectionAnchor(editor);
  23752. }
  23753. };
  23754. const getSelectionAnchor = editor => {
  23755. return {
  23756. type: 'selection',
  23757. root: SugarElement.fromDom(editor.selection.getNode())
  23758. };
  23759. };
  23760. const getNodeAnchor = editor => ({
  23761. type: 'node',
  23762. node: Optional.some(SugarElement.fromDom(editor.selection.getNode())),
  23763. root: SugarElement.fromDom(editor.getBody())
  23764. });
  23765. const getAnchorSpec$1 = (editor, e, anchorType) => {
  23766. switch (anchorType) {
  23767. case 'node':
  23768. return getNodeAnchor(editor);
  23769. case 'point':
  23770. return getPointAnchor(editor, e);
  23771. case 'selection':
  23772. return getSelectionAnchor(editor);
  23773. }
  23774. };
  23775. const initAndShow$1 = (editor, e, buildMenu, backstage, contextmenu, anchorType) => {
  23776. const items = buildMenu();
  23777. const anchorSpec = getAnchorSpec$1(editor, e, anchorType);
  23778. build(items, ItemResponse$1.CLOSE_ON_EXECUTE, backstage, {
  23779. isHorizontalMenu: false,
  23780. search: Optional.none()
  23781. }).map(menuData => {
  23782. e.preventDefault();
  23783. InlineView.showMenuAt(contextmenu, { anchor: anchorSpec }, {
  23784. menu: { markers: markers('normal') },
  23785. data: menuData
  23786. });
  23787. });
  23788. };
  23789. const layouts = {
  23790. onLtr: () => [
  23791. south$2,
  23792. southeast$2,
  23793. southwest$2,
  23794. northeast$2,
  23795. northwest$2,
  23796. north$2,
  23797. north,
  23798. south,
  23799. northeast,
  23800. southeast,
  23801. northwest,
  23802. southwest
  23803. ],
  23804. onRtl: () => [
  23805. south$2,
  23806. southwest$2,
  23807. southeast$2,
  23808. northwest$2,
  23809. northeast$2,
  23810. north$2,
  23811. north,
  23812. south,
  23813. northwest,
  23814. southwest,
  23815. northeast,
  23816. southeast
  23817. ]
  23818. };
  23819. const bubbleSize = 12;
  23820. const bubbleAlignments = {
  23821. valignCentre: [],
  23822. alignCentre: [],
  23823. alignLeft: ['tox-pop--align-left'],
  23824. alignRight: ['tox-pop--align-right'],
  23825. right: ['tox-pop--right'],
  23826. left: ['tox-pop--left'],
  23827. bottom: ['tox-pop--bottom'],
  23828. top: ['tox-pop--top']
  23829. };
  23830. const isTouchWithinSelection = (editor, e) => {
  23831. const selection = editor.selection;
  23832. if (selection.isCollapsed() || e.touches.length < 1) {
  23833. return false;
  23834. } else {
  23835. const touch = e.touches[0];
  23836. const rng = selection.getRng();
  23837. const rngRectOpt = getFirstRect(editor.getWin(), SimSelection.domRange(rng));
  23838. return rngRectOpt.exists(rngRect => rngRect.left <= touch.clientX && rngRect.right >= touch.clientX && rngRect.top <= touch.clientY && rngRect.bottom >= touch.clientY);
  23839. }
  23840. };
  23841. const setupiOSOverrides = editor => {
  23842. const originalSelection = editor.selection.getRng();
  23843. const selectionReset = () => {
  23844. global$9.setEditorTimeout(editor, () => {
  23845. editor.selection.setRng(originalSelection);
  23846. }, 10);
  23847. unbindEventListeners();
  23848. };
  23849. editor.once('touchend', selectionReset);
  23850. const preventMousedown = e => {
  23851. e.preventDefault();
  23852. e.stopImmediatePropagation();
  23853. };
  23854. editor.on('mousedown', preventMousedown, true);
  23855. const clearSelectionReset = () => unbindEventListeners();
  23856. editor.once('longpresscancel', clearSelectionReset);
  23857. const unbindEventListeners = () => {
  23858. editor.off('touchend', selectionReset);
  23859. editor.off('longpresscancel', clearSelectionReset);
  23860. editor.off('mousedown', preventMousedown);
  23861. };
  23862. };
  23863. const getAnchorSpec = (editor, e, anchorType) => {
  23864. const anchorSpec = getAnchorSpec$1(editor, e, anchorType);
  23865. const bubbleYOffset = anchorType === 'point' ? bubbleSize : 0;
  23866. return {
  23867. bubble: nu$5(0, bubbleYOffset, bubbleAlignments),
  23868. layouts,
  23869. overrides: {
  23870. maxWidthFunction: expandable(),
  23871. maxHeightFunction: expandable$1()
  23872. },
  23873. ...anchorSpec
  23874. };
  23875. };
  23876. const show = (editor, e, items, backstage, contextmenu, anchorType, highlightImmediately) => {
  23877. const anchorSpec = getAnchorSpec(editor, e, anchorType);
  23878. build(items, ItemResponse$1.CLOSE_ON_EXECUTE, backstage, {
  23879. isHorizontalMenu: true,
  23880. search: Optional.none()
  23881. }).map(menuData => {
  23882. e.preventDefault();
  23883. const highlightOnOpen = highlightImmediately ? HighlightOnOpen.HighlightMenuAndItem : HighlightOnOpen.HighlightNone;
  23884. InlineView.showMenuWithinBounds(contextmenu, { anchor: anchorSpec }, {
  23885. menu: {
  23886. markers: markers('normal'),
  23887. highlightOnOpen
  23888. },
  23889. data: menuData,
  23890. type: 'horizontal'
  23891. }, () => Optional.some(getContextToolbarBounds(editor, backstage.shared, anchorType === 'node' ? 'node' : 'selection')));
  23892. editor.dispatch(hideContextToolbarEvent);
  23893. });
  23894. };
  23895. const initAndShow = (editor, e, buildMenu, backstage, contextmenu, anchorType) => {
  23896. const detection = detect$2();
  23897. const isiOS = detection.os.isiOS();
  23898. const isMacOS = detection.os.isMacOS();
  23899. const isAndroid = detection.os.isAndroid();
  23900. const isTouch = detection.deviceType.isTouch();
  23901. const shouldHighlightImmediately = () => !(isAndroid || isiOS || isMacOS && isTouch);
  23902. const open = () => {
  23903. const items = buildMenu();
  23904. show(editor, e, items, backstage, contextmenu, anchorType, shouldHighlightImmediately());
  23905. };
  23906. if ((isMacOS || isiOS) && anchorType !== 'node') {
  23907. const openiOS = () => {
  23908. setupiOSOverrides(editor);
  23909. open();
  23910. };
  23911. if (isTouchWithinSelection(editor, e)) {
  23912. openiOS();
  23913. } else {
  23914. editor.once('selectionchange', openiOS);
  23915. editor.once('touchend', () => editor.off('selectionchange', openiOS));
  23916. }
  23917. } else {
  23918. open();
  23919. }
  23920. };
  23921. const isSeparator = item => isString(item) ? item === '|' : item.type === 'separator';
  23922. const separator = { type: 'separator' };
  23923. const makeContextItem = item => {
  23924. const commonMenuItem = item => ({
  23925. text: item.text,
  23926. icon: item.icon,
  23927. enabled: item.enabled,
  23928. shortcut: item.shortcut
  23929. });
  23930. if (isString(item)) {
  23931. return item;
  23932. } else {
  23933. switch (item.type) {
  23934. case 'separator':
  23935. return separator;
  23936. case 'submenu':
  23937. return {
  23938. type: 'nestedmenuitem',
  23939. ...commonMenuItem(item),
  23940. getSubmenuItems: () => {
  23941. const items = item.getSubmenuItems();
  23942. if (isString(items)) {
  23943. return items;
  23944. } else {
  23945. return map$2(items, makeContextItem);
  23946. }
  23947. }
  23948. };
  23949. default:
  23950. const commonItem = item;
  23951. return {
  23952. type: 'menuitem',
  23953. ...commonMenuItem(commonItem),
  23954. onAction: noarg(commonItem.onAction)
  23955. };
  23956. }
  23957. }
  23958. };
  23959. const addContextMenuGroup = (xs, groupItems) => {
  23960. if (groupItems.length === 0) {
  23961. return xs;
  23962. }
  23963. const lastMenuItem = last$1(xs).filter(item => !isSeparator(item));
  23964. const before = lastMenuItem.fold(() => [], _ => [separator]);
  23965. return xs.concat(before).concat(groupItems).concat([separator]);
  23966. };
  23967. const generateContextMenu = (contextMenus, menuConfig, selectedElement) => {
  23968. const sections = foldl(menuConfig, (acc, name) => {
  23969. return get$g(contextMenus, name.toLowerCase()).map(menu => {
  23970. const items = menu.update(selectedElement);
  23971. if (isString(items)) {
  23972. return addContextMenuGroup(acc, items.split(' '));
  23973. } else if (items.length > 0) {
  23974. const allItems = map$2(items, makeContextItem);
  23975. return addContextMenuGroup(acc, allItems);
  23976. } else {
  23977. return acc;
  23978. }
  23979. }).getOrThunk(() => acc.concat([name]));
  23980. }, []);
  23981. if (sections.length > 0 && isSeparator(sections[sections.length - 1])) {
  23982. sections.pop();
  23983. }
  23984. return sections;
  23985. };
  23986. const isNativeOverrideKeyEvent = (editor, e) => e.ctrlKey && !shouldNeverUseNative(editor);
  23987. const isTouchEvent = e => e.type === 'longpress' || has$2(e, 'touches');
  23988. const isTriggeredByKeyboard = (editor, e) => !isTouchEvent(e) && (e.button !== 2 || e.target === editor.getBody() && e.pointerType === '');
  23989. const getSelectedElement = (editor, e) => isTriggeredByKeyboard(editor, e) ? editor.selection.getStart(true) : e.target;
  23990. const getAnchorType = (editor, e) => {
  23991. const selector = getAvoidOverlapSelector(editor);
  23992. const anchorType = isTriggeredByKeyboard(editor, e) ? 'selection' : 'point';
  23993. if (isNotEmpty(selector)) {
  23994. const target = getSelectedElement(editor, e);
  23995. const selectorExists = closest(SugarElement.fromDom(target), selector);
  23996. return selectorExists ? 'node' : anchorType;
  23997. } else {
  23998. return anchorType;
  23999. }
  24000. };
  24001. const setup$5 = (editor, lazySink, backstage) => {
  24002. const detection = detect$2();
  24003. const isTouch = detection.deviceType.isTouch;
  24004. const contextmenu = build$1(InlineView.sketch({
  24005. dom: { tag: 'div' },
  24006. lazySink,
  24007. onEscape: () => editor.focus(),
  24008. onShow: () => backstage.setContextMenuState(true),
  24009. onHide: () => backstage.setContextMenuState(false),
  24010. fireDismissalEventInstead: {},
  24011. inlineBehaviours: derive$1([config('dismissContextMenu', [run$1(dismissRequested(), (comp, _se) => {
  24012. Sandboxing.close(comp);
  24013. editor.focus();
  24014. })])])
  24015. }));
  24016. const hideContextMenu = () => InlineView.hide(contextmenu);
  24017. const showContextMenu = e => {
  24018. if (shouldNeverUseNative(editor)) {
  24019. e.preventDefault();
  24020. }
  24021. if (isNativeOverrideKeyEvent(editor, e) || isContextMenuDisabled(editor)) {
  24022. return;
  24023. }
  24024. const anchorType = getAnchorType(editor, e);
  24025. const buildMenu = () => {
  24026. const selectedElement = getSelectedElement(editor, e);
  24027. const registry = editor.ui.registry.getAll();
  24028. const menuConfig = getContextMenu(editor);
  24029. return generateContextMenu(registry.contextMenus, menuConfig, selectedElement);
  24030. };
  24031. const initAndShow$2 = isTouch() ? initAndShow : initAndShow$1;
  24032. initAndShow$2(editor, e, buildMenu, backstage, contextmenu, anchorType);
  24033. };
  24034. editor.on('init', () => {
  24035. const hideEvents = 'ResizeEditor ScrollContent ScrollWindow longpresscancel' + (isTouch() ? '' : ' ResizeWindow');
  24036. editor.on(hideEvents, hideContextMenu);
  24037. editor.on('longpress contextmenu', showContextMenu);
  24038. });
  24039. };
  24040. const adt = Adt.generate([
  24041. {
  24042. offset: [
  24043. 'x',
  24044. 'y'
  24045. ]
  24046. },
  24047. {
  24048. absolute: [
  24049. 'x',
  24050. 'y'
  24051. ]
  24052. },
  24053. {
  24054. fixed: [
  24055. 'x',
  24056. 'y'
  24057. ]
  24058. }
  24059. ]);
  24060. const subtract = change => point => point.translate(-change.left, -change.top);
  24061. const add = change => point => point.translate(change.left, change.top);
  24062. const transform = changes => (x, y) => foldl(changes, (rest, f) => f(rest), SugarPosition(x, y));
  24063. const asFixed = (coord, scroll, origin) => coord.fold(transform([
  24064. add(origin),
  24065. subtract(scroll)
  24066. ]), transform([subtract(scroll)]), transform([]));
  24067. const asAbsolute = (coord, scroll, origin) => coord.fold(transform([add(origin)]), transform([]), transform([add(scroll)]));
  24068. const asOffset = (coord, scroll, origin) => coord.fold(transform([]), transform([subtract(origin)]), transform([
  24069. add(scroll),
  24070. subtract(origin)
  24071. ]));
  24072. const withinRange = (coord1, coord2, xRange, yRange, scroll, origin) => {
  24073. const a1 = asAbsolute(coord1, scroll, origin);
  24074. const a2 = asAbsolute(coord2, scroll, origin);
  24075. return Math.abs(a1.left - a2.left) <= xRange && Math.abs(a1.top - a2.top) <= yRange;
  24076. };
  24077. const getDeltas = (coord1, coord2, xRange, yRange, scroll, origin) => {
  24078. const a1 = asAbsolute(coord1, scroll, origin);
  24079. const a2 = asAbsolute(coord2, scroll, origin);
  24080. const left = Math.abs(a1.left - a2.left);
  24081. const top = Math.abs(a1.top - a2.top);
  24082. return SugarPosition(left, top);
  24083. };
  24084. const toStyles = (coord, scroll, origin) => {
  24085. const stylesOpt = coord.fold((x, y) => ({
  24086. position: Optional.some('absolute'),
  24087. left: Optional.some(x + 'px'),
  24088. top: Optional.some(y + 'px')
  24089. }), (x, y) => ({
  24090. position: Optional.some('absolute'),
  24091. left: Optional.some(x - origin.left + 'px'),
  24092. top: Optional.some(y - origin.top + 'px')
  24093. }), (x, y) => ({
  24094. position: Optional.some('fixed'),
  24095. left: Optional.some(x + 'px'),
  24096. top: Optional.some(y + 'px')
  24097. }));
  24098. return {
  24099. right: Optional.none(),
  24100. bottom: Optional.none(),
  24101. ...stylesOpt
  24102. };
  24103. };
  24104. 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));
  24105. const absorb = (partialCoord, originalCoord, scroll, origin) => {
  24106. const absorbOne = (stencil, nu) => (optX, optY) => {
  24107. const original = stencil(originalCoord, scroll, origin);
  24108. return nu(optX.getOr(original.left), optY.getOr(original.top));
  24109. };
  24110. return partialCoord.fold(absorbOne(asOffset, offset), absorbOne(asAbsolute, absolute), absorbOne(asFixed, fixed));
  24111. };
  24112. const offset = adt.offset;
  24113. const absolute = adt.absolute;
  24114. const fixed = adt.fixed;
  24115. const parseAttrToInt = (element, name) => {
  24116. const value = get$f(element, name);
  24117. return isUndefined(value) ? NaN : parseInt(value, 10);
  24118. };
  24119. const get = (component, snapsInfo) => {
  24120. const element = component.element;
  24121. const x = parseAttrToInt(element, snapsInfo.leftAttr);
  24122. const y = parseAttrToInt(element, snapsInfo.topAttr);
  24123. return isNaN(x) || isNaN(y) ? Optional.none() : Optional.some(SugarPosition(x, y));
  24124. };
  24125. const set = (component, snapsInfo, pt) => {
  24126. const element = component.element;
  24127. set$9(element, snapsInfo.leftAttr, pt.left + 'px');
  24128. set$9(element, snapsInfo.topAttr, pt.top + 'px');
  24129. };
  24130. const clear = (component, snapsInfo) => {
  24131. const element = component.element;
  24132. remove$7(element, snapsInfo.leftAttr);
  24133. remove$7(element, snapsInfo.topAttr);
  24134. };
  24135. const getCoords = (component, snapInfo, coord, delta) => get(component, snapInfo).fold(() => coord, fixed$1 => fixed(fixed$1.left + delta.left, fixed$1.top + delta.top));
  24136. const moveOrSnap = (component, snapInfo, coord, delta, scroll, origin) => {
  24137. const newCoord = getCoords(component, snapInfo, coord, delta);
  24138. const snap = snapInfo.mustSnap ? findClosestSnap(component, snapInfo, newCoord, scroll, origin) : findSnap(component, snapInfo, newCoord, scroll, origin);
  24139. const fixedCoord = asFixed(newCoord, scroll, origin);
  24140. set(component, snapInfo, fixedCoord);
  24141. return snap.fold(() => ({
  24142. coord: fixed(fixedCoord.left, fixedCoord.top),
  24143. extra: Optional.none()
  24144. }), spanned => ({
  24145. coord: spanned.output,
  24146. extra: spanned.extra
  24147. }));
  24148. };
  24149. const stopDrag = (component, snapInfo) => {
  24150. clear(component, snapInfo);
  24151. };
  24152. const findMatchingSnap = (snaps, newCoord, scroll, origin) => findMap(snaps, snap => {
  24153. const sensor = snap.sensor;
  24154. const inRange = withinRange(newCoord, sensor, snap.range.left, snap.range.top, scroll, origin);
  24155. return inRange ? Optional.some({
  24156. output: absorb(snap.output, newCoord, scroll, origin),
  24157. extra: snap.extra
  24158. }) : Optional.none();
  24159. });
  24160. const findClosestSnap = (component, snapInfo, newCoord, scroll, origin) => {
  24161. const snaps = snapInfo.getSnapPoints(component);
  24162. const matchSnap = findMatchingSnap(snaps, newCoord, scroll, origin);
  24163. return matchSnap.orThunk(() => {
  24164. const bestSnap = foldl(snaps, (acc, snap) => {
  24165. const sensor = snap.sensor;
  24166. const deltas = getDeltas(newCoord, sensor, snap.range.left, snap.range.top, scroll, origin);
  24167. return acc.deltas.fold(() => ({
  24168. deltas: Optional.some(deltas),
  24169. snap: Optional.some(snap)
  24170. }), bestDeltas => {
  24171. const currAvg = (deltas.left + deltas.top) / 2;
  24172. const bestAvg = (bestDeltas.left + bestDeltas.top) / 2;
  24173. if (currAvg <= bestAvg) {
  24174. return {
  24175. deltas: Optional.some(deltas),
  24176. snap: Optional.some(snap)
  24177. };
  24178. } else {
  24179. return acc;
  24180. }
  24181. });
  24182. }, {
  24183. deltas: Optional.none(),
  24184. snap: Optional.none()
  24185. });
  24186. return bestSnap.snap.map(snap => ({
  24187. output: absorb(snap.output, newCoord, scroll, origin),
  24188. extra: snap.extra
  24189. }));
  24190. });
  24191. };
  24192. const findSnap = (component, snapInfo, newCoord, scroll, origin) => {
  24193. const snaps = snapInfo.getSnapPoints(component);
  24194. return findMatchingSnap(snaps, newCoord, scroll, origin);
  24195. };
  24196. const snapTo$1 = (snap, scroll, origin) => ({
  24197. coord: absorb(snap.output, snap.output, scroll, origin),
  24198. extra: snap.extra
  24199. });
  24200. const snapTo = (component, dragConfig, _state, snap) => {
  24201. const target = dragConfig.getTarget(component.element);
  24202. if (dragConfig.repositionTarget) {
  24203. const doc = owner$4(component.element);
  24204. const scroll = get$b(doc);
  24205. const origin = getOrigin(target);
  24206. const snapPin = snapTo$1(snap, scroll, origin);
  24207. const styles = toStyles(snapPin.coord, scroll, origin);
  24208. setOptions(target, styles);
  24209. }
  24210. };
  24211. var DraggingApis = /*#__PURE__*/Object.freeze({
  24212. __proto__: null,
  24213. snapTo: snapTo
  24214. });
  24215. const initialAttribute = 'data-initial-z-index';
  24216. const resetZIndex = blocker => {
  24217. parent(blocker.element).filter(isElement$1).each(root => {
  24218. getOpt(root, initialAttribute).fold(() => remove$6(root, 'z-index'), zIndex => set$8(root, 'z-index', zIndex));
  24219. remove$7(root, initialAttribute);
  24220. });
  24221. };
  24222. const changeZIndex = blocker => {
  24223. parent(blocker.element).filter(isElement$1).each(root => {
  24224. getRaw(root, 'z-index').each(zindex => {
  24225. set$9(root, initialAttribute, zindex);
  24226. });
  24227. set$8(root, 'z-index', get$e(blocker.element, 'z-index'));
  24228. });
  24229. };
  24230. const instigate = (anyComponent, blocker) => {
  24231. anyComponent.getSystem().addToGui(blocker);
  24232. changeZIndex(blocker);
  24233. };
  24234. const discard = blocker => {
  24235. resetZIndex(blocker);
  24236. blocker.getSystem().removeFromGui(blocker);
  24237. };
  24238. const createComponent = (component, blockerClass, blockerEvents) => component.getSystem().build(Container.sketch({
  24239. dom: {
  24240. styles: {
  24241. 'left': '0px',
  24242. 'top': '0px',
  24243. 'width': '100%',
  24244. 'height': '100%',
  24245. 'position': 'fixed',
  24246. 'z-index': '1000000000000000'
  24247. },
  24248. classes: [blockerClass]
  24249. },
  24250. events: blockerEvents
  24251. }));
  24252. var SnapSchema = optionObjOf('snaps', [
  24253. required$1('getSnapPoints'),
  24254. onHandler('onSensor'),
  24255. required$1('leftAttr'),
  24256. required$1('topAttr'),
  24257. defaulted('lazyViewport', win),
  24258. defaulted('mustSnap', false)
  24259. ]);
  24260. const schema$6 = [
  24261. defaulted('useFixed', never),
  24262. required$1('blockerClass'),
  24263. defaulted('getTarget', identity),
  24264. defaulted('onDrag', noop),
  24265. defaulted('repositionTarget', true),
  24266. defaulted('onDrop', noop),
  24267. defaultedFunction('getBounds', win),
  24268. SnapSchema
  24269. ];
  24270. const getCurrentCoord = target => lift3(getRaw(target, 'left'), getRaw(target, 'top'), getRaw(target, 'position'), (left, top, position) => {
  24271. const nu = position === 'fixed' ? fixed : offset;
  24272. return nu(parseInt(left, 10), parseInt(top, 10));
  24273. }).getOrThunk(() => {
  24274. const location = absolute$3(target);
  24275. return absolute(location.left, location.top);
  24276. });
  24277. const clampCoords = (component, coords, scroll, origin, startData) => {
  24278. const bounds = startData.bounds;
  24279. const absoluteCoord = asAbsolute(coords, scroll, origin);
  24280. const newX = clamp(absoluteCoord.left, bounds.x, bounds.x + bounds.width - startData.width);
  24281. const newY = clamp(absoluteCoord.top, bounds.y, bounds.y + bounds.height - startData.height);
  24282. const newCoords = absolute(newX, newY);
  24283. return coords.fold(() => {
  24284. const offset$1 = asOffset(newCoords, scroll, origin);
  24285. return offset(offset$1.left, offset$1.top);
  24286. }, constant$1(newCoords), () => {
  24287. const fixed$1 = asFixed(newCoords, scroll, origin);
  24288. return fixed(fixed$1.left, fixed$1.top);
  24289. });
  24290. };
  24291. const calcNewCoord = (component, optSnaps, currentCoord, scroll, origin, delta, startData) => {
  24292. const newCoord = optSnaps.fold(() => {
  24293. const translated = translate(currentCoord, delta.left, delta.top);
  24294. const fixedCoord = asFixed(translated, scroll, origin);
  24295. return fixed(fixedCoord.left, fixedCoord.top);
  24296. }, snapInfo => {
  24297. const snapping = moveOrSnap(component, snapInfo, currentCoord, delta, scroll, origin);
  24298. snapping.extra.each(extra => {
  24299. snapInfo.onSensor(component, extra);
  24300. });
  24301. return snapping.coord;
  24302. });
  24303. return clampCoords(component, newCoord, scroll, origin, startData);
  24304. };
  24305. const dragBy = (component, dragConfig, startData, delta) => {
  24306. const target = dragConfig.getTarget(component.element);
  24307. if (dragConfig.repositionTarget) {
  24308. const doc = owner$4(component.element);
  24309. const scroll = get$b(doc);
  24310. const origin = getOrigin(target);
  24311. const currentCoord = getCurrentCoord(target);
  24312. const newCoord = calcNewCoord(component, dragConfig.snaps, currentCoord, scroll, origin, delta, startData);
  24313. const styles = toStyles(newCoord, scroll, origin);
  24314. setOptions(target, styles);
  24315. }
  24316. dragConfig.onDrag(component, target, delta);
  24317. };
  24318. const calcStartData = (dragConfig, comp) => ({
  24319. bounds: dragConfig.getBounds(),
  24320. height: getOuter$2(comp.element),
  24321. width: getOuter$1(comp.element)
  24322. });
  24323. const move = (component, dragConfig, dragState, dragMode, event) => {
  24324. const delta = dragState.update(dragMode, event);
  24325. const dragStartData = dragState.getStartData().getOrThunk(() => calcStartData(dragConfig, component));
  24326. delta.each(dlt => {
  24327. dragBy(component, dragConfig, dragStartData, dlt);
  24328. });
  24329. };
  24330. const stop = (component, blocker, dragConfig, dragState) => {
  24331. blocker.each(discard);
  24332. dragConfig.snaps.each(snapInfo => {
  24333. stopDrag(component, snapInfo);
  24334. });
  24335. const target = dragConfig.getTarget(component.element);
  24336. dragState.reset();
  24337. dragConfig.onDrop(component, target);
  24338. };
  24339. const handlers = events => (dragConfig, dragState) => {
  24340. const updateStartState = comp => {
  24341. dragState.setStartData(calcStartData(dragConfig, comp));
  24342. };
  24343. return derive$2([
  24344. run$1(windowScroll(), comp => {
  24345. dragState.getStartData().each(() => updateStartState(comp));
  24346. }),
  24347. ...events(dragConfig, dragState, updateStartState)
  24348. ]);
  24349. };
  24350. const init$3 = dragApi => derive$2([
  24351. run$1(mousedown(), dragApi.forceDrop),
  24352. run$1(mouseup(), dragApi.drop),
  24353. run$1(mousemove(), (comp, simulatedEvent) => {
  24354. dragApi.move(simulatedEvent.event);
  24355. }),
  24356. run$1(mouseout(), dragApi.delayDrop)
  24357. ]);
  24358. const getData$1 = event => Optional.from(SugarPosition(event.x, event.y));
  24359. const getDelta$1 = (old, nu) => SugarPosition(nu.left - old.left, nu.top - old.top);
  24360. var MouseData = /*#__PURE__*/Object.freeze({
  24361. __proto__: null,
  24362. getData: getData$1,
  24363. getDelta: getDelta$1
  24364. });
  24365. const events$3 = (dragConfig, dragState, updateStartState) => [run$1(mousedown(), (component, simulatedEvent) => {
  24366. const raw = simulatedEvent.event.raw;
  24367. if (raw.button !== 0) {
  24368. return;
  24369. }
  24370. simulatedEvent.stop();
  24371. const stop$1 = () => stop(component, Optional.some(blocker), dragConfig, dragState);
  24372. const delayDrop = DelayedFunction(stop$1, 200);
  24373. const dragApi = {
  24374. drop: stop$1,
  24375. delayDrop: delayDrop.schedule,
  24376. forceDrop: stop$1,
  24377. move: event => {
  24378. delayDrop.cancel();
  24379. move(component, dragConfig, dragState, MouseData, event);
  24380. }
  24381. };
  24382. const blocker = createComponent(component, dragConfig.blockerClass, init$3(dragApi));
  24383. const start = () => {
  24384. updateStartState(component);
  24385. instigate(component, blocker);
  24386. };
  24387. start();
  24388. })];
  24389. const schema$5 = [
  24390. ...schema$6,
  24391. output$1('dragger', { handlers: handlers(events$3) })
  24392. ];
  24393. const init$2 = dragApi => derive$2([
  24394. run$1(touchstart(), dragApi.forceDrop),
  24395. run$1(touchend(), dragApi.drop),
  24396. run$1(touchcancel(), dragApi.drop),
  24397. run$1(touchmove(), (comp, simulatedEvent) => {
  24398. dragApi.move(simulatedEvent.event);
  24399. })
  24400. ]);
  24401. const getDataFrom = touches => {
  24402. const touch = touches[0];
  24403. return Optional.some(SugarPosition(touch.clientX, touch.clientY));
  24404. };
  24405. const getData = event => {
  24406. const raw = event.raw;
  24407. const touches = raw.touches;
  24408. return touches.length === 1 ? getDataFrom(touches) : Optional.none();
  24409. };
  24410. const getDelta = (old, nu) => SugarPosition(nu.left - old.left, nu.top - old.top);
  24411. var TouchData = /*#__PURE__*/Object.freeze({
  24412. __proto__: null,
  24413. getData: getData,
  24414. getDelta: getDelta
  24415. });
  24416. const events$2 = (dragConfig, dragState, updateStartState) => {
  24417. const blockerSingleton = value$2();
  24418. const stopBlocking = component => {
  24419. stop(component, blockerSingleton.get(), dragConfig, dragState);
  24420. blockerSingleton.clear();
  24421. };
  24422. return [
  24423. run$1(touchstart(), (component, simulatedEvent) => {
  24424. simulatedEvent.stop();
  24425. const stop = () => stopBlocking(component);
  24426. const dragApi = {
  24427. drop: stop,
  24428. delayDrop: noop,
  24429. forceDrop: stop,
  24430. move: event => {
  24431. move(component, dragConfig, dragState, TouchData, event);
  24432. }
  24433. };
  24434. const blocker = createComponent(component, dragConfig.blockerClass, init$2(dragApi));
  24435. blockerSingleton.set(blocker);
  24436. const start = () => {
  24437. updateStartState(component);
  24438. instigate(component, blocker);
  24439. };
  24440. start();
  24441. }),
  24442. run$1(touchmove(), (component, simulatedEvent) => {
  24443. simulatedEvent.stop();
  24444. move(component, dragConfig, dragState, TouchData, simulatedEvent.event);
  24445. }),
  24446. run$1(touchend(), (component, simulatedEvent) => {
  24447. simulatedEvent.stop();
  24448. stopBlocking(component);
  24449. }),
  24450. run$1(touchcancel(), stopBlocking)
  24451. ];
  24452. };
  24453. const schema$4 = [
  24454. ...schema$6,
  24455. output$1('dragger', { handlers: handlers(events$2) })
  24456. ];
  24457. const events$1 = (dragConfig, dragState, updateStartState) => [
  24458. ...events$3(dragConfig, dragState, updateStartState),
  24459. ...events$2(dragConfig, dragState, updateStartState)
  24460. ];
  24461. const schema$3 = [
  24462. ...schema$6,
  24463. output$1('dragger', { handlers: handlers(events$1) })
  24464. ];
  24465. const mouse = schema$5;
  24466. const touch = schema$4;
  24467. const mouseOrTouch = schema$3;
  24468. var DraggingBranches = /*#__PURE__*/Object.freeze({
  24469. __proto__: null,
  24470. mouse: mouse,
  24471. touch: touch,
  24472. mouseOrTouch: mouseOrTouch
  24473. });
  24474. const init$1 = () => {
  24475. let previous = Optional.none();
  24476. let startData = Optional.none();
  24477. const reset = () => {
  24478. previous = Optional.none();
  24479. startData = Optional.none();
  24480. };
  24481. const calculateDelta = (mode, nu) => {
  24482. const result = previous.map(old => mode.getDelta(old, nu));
  24483. previous = Optional.some(nu);
  24484. return result;
  24485. };
  24486. const update = (mode, dragEvent) => mode.getData(dragEvent).bind(nuData => calculateDelta(mode, nuData));
  24487. const setStartData = data => {
  24488. startData = Optional.some(data);
  24489. };
  24490. const getStartData = () => startData;
  24491. const readState = constant$1({});
  24492. return nu$8({
  24493. readState,
  24494. reset,
  24495. update,
  24496. getStartData,
  24497. setStartData
  24498. });
  24499. };
  24500. var DragState = /*#__PURE__*/Object.freeze({
  24501. __proto__: null,
  24502. init: init$1
  24503. });
  24504. const Dragging = createModes({
  24505. branchKey: 'mode',
  24506. branches: DraggingBranches,
  24507. name: 'dragging',
  24508. active: {
  24509. events: (dragConfig, dragState) => {
  24510. const dragger = dragConfig.dragger;
  24511. return dragger.handlers(dragConfig, dragState);
  24512. }
  24513. },
  24514. extra: {
  24515. snap: sConfig => ({
  24516. sensor: sConfig.sensor,
  24517. range: sConfig.range,
  24518. output: sConfig.output,
  24519. extra: Optional.from(sConfig.extra)
  24520. })
  24521. },
  24522. state: DragState,
  24523. apis: DraggingApis
  24524. });
  24525. const snapWidth = 40;
  24526. const snapOffset = snapWidth / 2;
  24527. const calcSnap = (selectorOpt, td, x, y, width, height) => selectorOpt.fold(() => Dragging.snap({
  24528. sensor: absolute(x - snapOffset, y - snapOffset),
  24529. range: SugarPosition(width, height),
  24530. output: absolute(Optional.some(x), Optional.some(y)),
  24531. extra: { td }
  24532. }), selectorHandle => {
  24533. const sensorLeft = x - snapOffset;
  24534. const sensorTop = y - snapOffset;
  24535. const sensorWidth = snapWidth;
  24536. const sensorHeight = snapWidth;
  24537. const rect = selectorHandle.element.dom.getBoundingClientRect();
  24538. return Dragging.snap({
  24539. sensor: absolute(sensorLeft, sensorTop),
  24540. range: SugarPosition(sensorWidth, sensorHeight),
  24541. output: absolute(Optional.some(x - rect.width / 2), Optional.some(y - rect.height / 2)),
  24542. extra: { td }
  24543. });
  24544. });
  24545. const getSnapsConfig = (getSnapPoints, cell, onChange) => {
  24546. const isSameCell = (cellOpt, td) => cellOpt.exists(currentTd => eq(currentTd, td));
  24547. return {
  24548. getSnapPoints,
  24549. leftAttr: 'data-drag-left',
  24550. topAttr: 'data-drag-top',
  24551. onSensor: (component, extra) => {
  24552. const td = extra.td;
  24553. if (!isSameCell(cell.get(), td)) {
  24554. cell.set(td);
  24555. onChange(td);
  24556. }
  24557. },
  24558. mustSnap: true
  24559. };
  24560. };
  24561. const createSelector = snaps => record(Button.sketch({
  24562. dom: {
  24563. tag: 'div',
  24564. classes: ['tox-selector']
  24565. },
  24566. buttonBehaviours: derive$1([
  24567. Dragging.config({
  24568. mode: 'mouseOrTouch',
  24569. blockerClass: 'blocker',
  24570. snaps
  24571. }),
  24572. Unselecting.config({})
  24573. ]),
  24574. eventOrder: {
  24575. mousedown: [
  24576. 'dragging',
  24577. 'alloy.base.behaviour'
  24578. ],
  24579. touchstart: [
  24580. 'dragging',
  24581. 'alloy.base.behaviour'
  24582. ]
  24583. }
  24584. }));
  24585. const setup$4 = (editor, sink) => {
  24586. const tlTds = Cell([]);
  24587. const brTds = Cell([]);
  24588. const isVisible = Cell(false);
  24589. const startCell = value$2();
  24590. const finishCell = value$2();
  24591. const getTopLeftSnap = td => {
  24592. const box = absolute$2(td);
  24593. return calcSnap(memTopLeft.getOpt(sink), td, box.x, box.y, box.width, box.height);
  24594. };
  24595. const getTopLeftSnaps = () => map$2(tlTds.get(), td => getTopLeftSnap(td));
  24596. const getBottomRightSnap = td => {
  24597. const box = absolute$2(td);
  24598. return calcSnap(memBottomRight.getOpt(sink), td, box.right, box.bottom, box.width, box.height);
  24599. };
  24600. const getBottomRightSnaps = () => map$2(brTds.get(), td => getBottomRightSnap(td));
  24601. const topLeftSnaps = getSnapsConfig(getTopLeftSnaps, startCell, start => {
  24602. finishCell.get().each(finish => {
  24603. editor.dispatch('TableSelectorChange', {
  24604. start,
  24605. finish
  24606. });
  24607. });
  24608. });
  24609. const bottomRightSnaps = getSnapsConfig(getBottomRightSnaps, finishCell, finish => {
  24610. startCell.get().each(start => {
  24611. editor.dispatch('TableSelectorChange', {
  24612. start,
  24613. finish
  24614. });
  24615. });
  24616. });
  24617. const memTopLeft = createSelector(topLeftSnaps);
  24618. const memBottomRight = createSelector(bottomRightSnaps);
  24619. const topLeft = build$1(memTopLeft.asSpec());
  24620. const bottomRight = build$1(memBottomRight.asSpec());
  24621. const showOrHideHandle = (selector, cell, isAbove, isBelow) => {
  24622. const cellRect = cell.dom.getBoundingClientRect();
  24623. remove$6(selector.element, 'display');
  24624. const viewportHeight = defaultView(SugarElement.fromDom(editor.getBody())).dom.innerHeight;
  24625. const aboveViewport = isAbove(cellRect);
  24626. const belowViewport = isBelow(cellRect, viewportHeight);
  24627. if (aboveViewport || belowViewport) {
  24628. set$8(selector.element, 'display', 'none');
  24629. }
  24630. };
  24631. const snapTo = (selector, cell, getSnapConfig, pos) => {
  24632. const snap = getSnapConfig(cell);
  24633. Dragging.snapTo(selector, snap);
  24634. const isAbove = rect => rect[pos] < 0;
  24635. const isBelow = (rect, viewportHeight) => rect[pos] > viewportHeight;
  24636. showOrHideHandle(selector, cell, isAbove, isBelow);
  24637. };
  24638. const snapTopLeft = cell => snapTo(topLeft, cell, getTopLeftSnap, 'top');
  24639. const snapLastTopLeft = () => startCell.get().each(snapTopLeft);
  24640. const snapBottomRight = cell => snapTo(bottomRight, cell, getBottomRightSnap, 'bottom');
  24641. const snapLastBottomRight = () => finishCell.get().each(snapBottomRight);
  24642. if (detect$2().deviceType.isTouch()) {
  24643. editor.on('TableSelectionChange', e => {
  24644. if (!isVisible.get()) {
  24645. attach(sink, topLeft);
  24646. attach(sink, bottomRight);
  24647. isVisible.set(true);
  24648. }
  24649. startCell.set(e.start);
  24650. finishCell.set(e.finish);
  24651. e.otherCells.each(otherCells => {
  24652. tlTds.set(otherCells.upOrLeftCells);
  24653. brTds.set(otherCells.downOrRightCells);
  24654. snapTopLeft(e.start);
  24655. snapBottomRight(e.finish);
  24656. });
  24657. });
  24658. editor.on('ResizeEditor ResizeWindow ScrollContent', () => {
  24659. snapLastTopLeft();
  24660. snapLastBottomRight();
  24661. });
  24662. editor.on('TableSelectionClear', () => {
  24663. if (isVisible.get()) {
  24664. detach(topLeft);
  24665. detach(bottomRight);
  24666. isVisible.set(false);
  24667. }
  24668. startCell.clear();
  24669. finishCell.clear();
  24670. });
  24671. }
  24672. };
  24673. 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";
  24674. const isHidden = elm => elm.nodeName === 'BR' || !!elm.getAttribute('data-mce-bogus') || elm.getAttribute('data-mce-type') === 'bookmark';
  24675. const renderElementPath = (editor, settings, providersBackstage) => {
  24676. var _a;
  24677. const delimiter = (_a = settings.delimiter) !== null && _a !== void 0 ? _a : '\u203A';
  24678. const renderElement = (name, element, index) => Button.sketch({
  24679. dom: {
  24680. tag: 'div',
  24681. classes: ['tox-statusbar__path-item'],
  24682. attributes: {
  24683. 'data-index': index,
  24684. 'aria-level': index + 1
  24685. }
  24686. },
  24687. components: [text$2(name)],
  24688. action: _btn => {
  24689. editor.focus();
  24690. editor.selection.select(element);
  24691. editor.nodeChanged();
  24692. },
  24693. buttonBehaviours: derive$1([
  24694. DisablingConfigs.button(providersBackstage.isDisabled),
  24695. receivingConfig()
  24696. ])
  24697. });
  24698. const renderDivider = () => ({
  24699. dom: {
  24700. tag: 'div',
  24701. classes: ['tox-statusbar__path-divider'],
  24702. attributes: { 'aria-hidden': true }
  24703. },
  24704. components: [text$2(` ${ delimiter } `)]
  24705. });
  24706. const renderPathData = data => foldl(data, (acc, path, index) => {
  24707. const element = renderElement(path.name, path.element, index);
  24708. if (index === 0) {
  24709. return acc.concat([element]);
  24710. } else {
  24711. return acc.concat([
  24712. renderDivider(),
  24713. element
  24714. ]);
  24715. }
  24716. }, []);
  24717. const updatePath = parents => {
  24718. const newPath = [];
  24719. let i = parents.length;
  24720. while (i-- > 0) {
  24721. const parent = parents[i];
  24722. if (parent.nodeType === 1 && !isHidden(parent)) {
  24723. const args = fireResolveName(editor, parent);
  24724. if (!args.isDefaultPrevented()) {
  24725. newPath.push({
  24726. name: args.name,
  24727. element: parent
  24728. });
  24729. }
  24730. if (args.isPropagationStopped()) {
  24731. break;
  24732. }
  24733. }
  24734. }
  24735. return newPath;
  24736. };
  24737. return {
  24738. dom: {
  24739. tag: 'div',
  24740. classes: ['tox-statusbar__path'],
  24741. attributes: { role: 'navigation' }
  24742. },
  24743. behaviours: derive$1([
  24744. Keying.config({
  24745. mode: 'flow',
  24746. selector: 'div[role=button]'
  24747. }),
  24748. Disabling.config({ disabled: providersBackstage.isDisabled }),
  24749. receivingConfig(),
  24750. Tabstopping.config({}),
  24751. Replacing.config({}),
  24752. config('elementPathEvents', [runOnAttached((comp, _e) => {
  24753. editor.shortcuts.add('alt+F11', 'focus statusbar elementpath', () => Keying.focusIn(comp));
  24754. editor.on('NodeChange', e => {
  24755. const newPath = updatePath(e.parents);
  24756. const newChildren = newPath.length > 0 ? renderPathData(newPath) : [];
  24757. Replacing.set(comp, newChildren);
  24758. });
  24759. })])
  24760. ]),
  24761. components: []
  24762. };
  24763. };
  24764. var ResizeTypes;
  24765. (function (ResizeTypes) {
  24766. ResizeTypes[ResizeTypes['None'] = 0] = 'None';
  24767. ResizeTypes[ResizeTypes['Both'] = 1] = 'Both';
  24768. ResizeTypes[ResizeTypes['Vertical'] = 2] = 'Vertical';
  24769. }(ResizeTypes || (ResizeTypes = {})));
  24770. const getDimensions = (editor, deltas, resizeType, originalHeight, originalWidth) => {
  24771. const dimensions = { height: calcCappedSize(originalHeight + deltas.top, getMinHeightOption(editor), getMaxHeightOption(editor)) };
  24772. if (resizeType === ResizeTypes.Both) {
  24773. dimensions.width = calcCappedSize(originalWidth + deltas.left, getMinWidthOption(editor), getMaxWidthOption(editor));
  24774. }
  24775. return dimensions;
  24776. };
  24777. const resize = (editor, deltas, resizeType) => {
  24778. const container = SugarElement.fromDom(editor.getContainer());
  24779. const dimensions = getDimensions(editor, deltas, resizeType, get$d(container), get$c(container));
  24780. each(dimensions, (val, dim) => {
  24781. if (isNumber(val)) {
  24782. set$8(container, dim, numToPx(val));
  24783. }
  24784. });
  24785. fireResizeEditor(editor);
  24786. };
  24787. const getResizeType = editor => {
  24788. const resize = getResize(editor);
  24789. if (resize === false) {
  24790. return ResizeTypes.None;
  24791. } else if (resize === 'both') {
  24792. return ResizeTypes.Both;
  24793. } else {
  24794. return ResizeTypes.Vertical;
  24795. }
  24796. };
  24797. const keyboardHandler = (editor, resizeType, x, y) => {
  24798. const scale = 20;
  24799. const delta = SugarPosition(x * scale, y * scale);
  24800. resize(editor, delta, resizeType);
  24801. return Optional.some(true);
  24802. };
  24803. const renderResizeHandler = (editor, providersBackstage) => {
  24804. const resizeType = getResizeType(editor);
  24805. if (resizeType === ResizeTypes.None) {
  24806. return Optional.none();
  24807. }
  24808. return Optional.some(render$3('resize-handle', {
  24809. tag: 'div',
  24810. classes: ['tox-statusbar__resize-handle'],
  24811. attributes: { title: providersBackstage.translate('Resize') },
  24812. behaviours: [
  24813. Dragging.config({
  24814. mode: 'mouse',
  24815. repositionTarget: false,
  24816. onDrag: (_comp, _target, delta) => resize(editor, delta, resizeType),
  24817. blockerClass: 'tox-blocker'
  24818. }),
  24819. Keying.config({
  24820. mode: 'special',
  24821. onLeft: () => keyboardHandler(editor, resizeType, -1, 0),
  24822. onRight: () => keyboardHandler(editor, resizeType, 1, 0),
  24823. onUp: () => keyboardHandler(editor, resizeType, 0, -1),
  24824. onDown: () => keyboardHandler(editor, resizeType, 0, 1)
  24825. }),
  24826. Tabstopping.config({}),
  24827. Focusing.config({})
  24828. ]
  24829. }, providersBackstage.icons));
  24830. };
  24831. const renderWordCount = (editor, providersBackstage) => {
  24832. const replaceCountText = (comp, count, mode) => Replacing.set(comp, [text$2(providersBackstage.translate([
  24833. '{0} ' + mode,
  24834. count[mode]
  24835. ]))]);
  24836. return Button.sketch({
  24837. dom: {
  24838. tag: 'button',
  24839. classes: ['tox-statusbar__wordcount']
  24840. },
  24841. components: [],
  24842. buttonBehaviours: derive$1([
  24843. DisablingConfigs.button(providersBackstage.isDisabled),
  24844. receivingConfig(),
  24845. Tabstopping.config({}),
  24846. Replacing.config({}),
  24847. Representing.config({
  24848. store: {
  24849. mode: 'memory',
  24850. initialValue: {
  24851. mode: 'words',
  24852. count: {
  24853. words: 0,
  24854. characters: 0
  24855. }
  24856. }
  24857. }
  24858. }),
  24859. config('wordcount-events', [
  24860. runOnExecute$1(comp => {
  24861. const currentVal = Representing.getValue(comp);
  24862. const newMode = currentVal.mode === 'words' ? 'characters' : 'words';
  24863. Representing.setValue(comp, {
  24864. mode: newMode,
  24865. count: currentVal.count
  24866. });
  24867. replaceCountText(comp, currentVal.count, newMode);
  24868. }),
  24869. runOnAttached(comp => {
  24870. editor.on('wordCountUpdate', e => {
  24871. const {mode} = Representing.getValue(comp);
  24872. Representing.setValue(comp, {
  24873. mode,
  24874. count: e.wordCount
  24875. });
  24876. replaceCountText(comp, e.wordCount, mode);
  24877. });
  24878. })
  24879. ])
  24880. ]),
  24881. eventOrder: {
  24882. [execute$5()]: [
  24883. 'disabling',
  24884. 'alloy.base.behaviour',
  24885. 'wordcount-events'
  24886. ]
  24887. }
  24888. });
  24889. };
  24890. const renderStatusbar = (editor, providersBackstage) => {
  24891. const renderBranding = () => {
  24892. return {
  24893. dom: {
  24894. tag: 'span',
  24895. classes: ['tox-statusbar__branding']
  24896. },
  24897. components: [{
  24898. dom: {
  24899. tag: 'a',
  24900. attributes: {
  24901. 'href': 'https://www.tiny.cloud/powered-by-tiny?utm_campaign=editor_referral&utm_medium=poweredby&utm_source=tinymce&utm_content=v6',
  24902. 'rel': 'noopener',
  24903. 'target': '_blank',
  24904. 'aria-label': global$8.translate([
  24905. 'Powered by {0}',
  24906. 'Tiny'
  24907. ])
  24908. },
  24909. innerHtml: Logo.trim()
  24910. },
  24911. behaviours: derive$1([Focusing.config({})])
  24912. }]
  24913. };
  24914. };
  24915. const getTextComponents = () => {
  24916. const components = [];
  24917. if (useElementPath(editor)) {
  24918. components.push(renderElementPath(editor, {}, providersBackstage));
  24919. }
  24920. if (editor.hasPlugin('wordcount')) {
  24921. components.push(renderWordCount(editor, providersBackstage));
  24922. }
  24923. if (useBranding(editor)) {
  24924. components.push(renderBranding());
  24925. }
  24926. if (components.length > 0) {
  24927. return [{
  24928. dom: {
  24929. tag: 'div',
  24930. classes: ['tox-statusbar__text-container']
  24931. },
  24932. components
  24933. }];
  24934. }
  24935. return [];
  24936. };
  24937. const getComponents = () => {
  24938. const components = getTextComponents();
  24939. const resizeHandler = renderResizeHandler(editor, providersBackstage);
  24940. return components.concat(resizeHandler.toArray());
  24941. };
  24942. return {
  24943. dom: {
  24944. tag: 'div',
  24945. classes: ['tox-statusbar']
  24946. },
  24947. components: getComponents()
  24948. };
  24949. };
  24950. const getLazyMothership = (label, singleton) => singleton.get().getOrDie(`UI for ${ label } has not been rendered`);
  24951. const setup$3 = (editor, setupForTheme) => {
  24952. const isInline = editor.inline;
  24953. const mode = isInline ? Inline : Iframe;
  24954. const header = isStickyToolbar(editor) ? StickyHeader : StaticHeader;
  24955. const lazyUiRefs = LazyUiReferences();
  24956. const lazyMothership = value$2();
  24957. const lazyDialogMothership = value$2();
  24958. const lazyPopupMothership = value$2();
  24959. const platform = detect$2();
  24960. const isTouch = platform.deviceType.isTouch();
  24961. const touchPlatformClass = 'tox-platform-touch';
  24962. const deviceClasses = isTouch ? [touchPlatformClass] : [];
  24963. const isToolbarBottom = isToolbarLocationBottom(editor);
  24964. const toolbarMode = getToolbarMode(editor);
  24965. const memAnchorBar = record({
  24966. dom: {
  24967. tag: 'div',
  24968. classes: ['tox-anchorbar']
  24969. }
  24970. });
  24971. const lazyHeader = () => lazyUiRefs.mainUi.get().map(ui => ui.outerContainer).bind(OuterContainer.getHeader);
  24972. const lazyDialogSinkResult = () => Result.fromOption(lazyUiRefs.dialogUi.get().map(ui => ui.sink), 'UI has not been rendered');
  24973. const lazyPopupSinkResult = () => Result.fromOption(lazyUiRefs.popupUi.get().map(ui => ui.sink), '(popup) UI has not been rendered');
  24974. const lazyAnchorBar = lazyUiRefs.lazyGetInOuterOrDie('anchor bar', memAnchorBar.getOpt);
  24975. const lazyToolbar = lazyUiRefs.lazyGetInOuterOrDie('toolbar', OuterContainer.getToolbar);
  24976. const lazyThrobber = lazyUiRefs.lazyGetInOuterOrDie('throbber', OuterContainer.getThrobber);
  24977. const backstages = init$6({
  24978. popup: lazyPopupSinkResult,
  24979. dialog: lazyDialogSinkResult
  24980. }, editor, lazyAnchorBar);
  24981. const makeHeaderPart = () => {
  24982. const verticalDirAttributes = { attributes: { [Attribute]: isToolbarBottom ? AttributeValue.BottomToTop : AttributeValue.TopToBottom } };
  24983. const partMenubar = OuterContainer.parts.menubar({
  24984. dom: {
  24985. tag: 'div',
  24986. classes: ['tox-menubar']
  24987. },
  24988. backstage: backstages.popup,
  24989. onEscape: () => {
  24990. editor.focus();
  24991. }
  24992. });
  24993. const partToolbar = OuterContainer.parts.toolbar({
  24994. dom: {
  24995. tag: 'div',
  24996. classes: ['tox-toolbar']
  24997. },
  24998. getSink: backstages.popup.shared.getSink,
  24999. providers: backstages.popup.shared.providers,
  25000. onEscape: () => {
  25001. editor.focus();
  25002. },
  25003. onToolbarToggled: state => {
  25004. fireToggleToolbarDrawer(editor, state);
  25005. },
  25006. type: toolbarMode,
  25007. lazyToolbar,
  25008. lazyHeader: () => lazyHeader().getOrDie('Could not find header element'),
  25009. ...verticalDirAttributes
  25010. });
  25011. const partMultipleToolbar = OuterContainer.parts['multiple-toolbar']({
  25012. dom: {
  25013. tag: 'div',
  25014. classes: ['tox-toolbar-overlord']
  25015. },
  25016. providers: backstages.popup.shared.providers,
  25017. onEscape: () => {
  25018. editor.focus();
  25019. },
  25020. type: toolbarMode
  25021. });
  25022. const hasMultipleToolbar = isMultipleToolbars(editor);
  25023. const hasToolbar = isToolbarEnabled(editor);
  25024. const hasMenubar = isMenubarEnabled(editor);
  25025. const shouldHavePromotion = promotionEnabled(editor);
  25026. const partPromotion = makePromotion();
  25027. const hasAnyContents = hasMultipleToolbar || hasToolbar || hasMenubar;
  25028. const getPartToolbar = () => {
  25029. if (hasMultipleToolbar) {
  25030. return [partMultipleToolbar];
  25031. } else if (hasToolbar) {
  25032. return [partToolbar];
  25033. } else {
  25034. return [];
  25035. }
  25036. };
  25037. const menubarCollection = shouldHavePromotion ? [
  25038. partPromotion,
  25039. partMenubar
  25040. ] : [partMenubar];
  25041. return OuterContainer.parts.header({
  25042. dom: {
  25043. tag: 'div',
  25044. classes: ['tox-editor-header'].concat(hasAnyContents ? [] : ['tox-editor-header--empty']),
  25045. ...verticalDirAttributes
  25046. },
  25047. components: flatten([
  25048. hasMenubar ? menubarCollection : [],
  25049. getPartToolbar(),
  25050. useFixedContainer(editor) ? [] : [memAnchorBar.asSpec()]
  25051. ]),
  25052. sticky: isStickyToolbar(editor),
  25053. editor,
  25054. sharedBackstage: backstages.popup.shared
  25055. });
  25056. };
  25057. const makePromotion = () => {
  25058. return OuterContainer.parts.promotion({
  25059. dom: {
  25060. tag: 'div',
  25061. classes: ['tox-promotion']
  25062. }
  25063. });
  25064. };
  25065. const makeSidebarDefinition = () => {
  25066. const partSocket = OuterContainer.parts.socket({
  25067. dom: {
  25068. tag: 'div',
  25069. classes: ['tox-edit-area']
  25070. }
  25071. });
  25072. const partSidebar = OuterContainer.parts.sidebar({
  25073. dom: {
  25074. tag: 'div',
  25075. classes: ['tox-sidebar']
  25076. }
  25077. });
  25078. return {
  25079. dom: {
  25080. tag: 'div',
  25081. classes: ['tox-sidebar-wrap']
  25082. },
  25083. components: [
  25084. partSocket,
  25085. partSidebar
  25086. ]
  25087. };
  25088. };
  25089. const renderDialogUi = () => {
  25090. const uiContainer = getUiContainer(editor);
  25091. const isGridUiContainer = eq(body(), uiContainer) && get$e(uiContainer, 'display') === 'grid';
  25092. const sinkSpec = {
  25093. dom: {
  25094. tag: 'div',
  25095. classes: [
  25096. 'tox',
  25097. 'tox-silver-sink',
  25098. 'tox-tinymce-aux'
  25099. ].concat(deviceClasses),
  25100. attributes: { ...global$8.isRtl() ? { dir: 'rtl' } : {} }
  25101. },
  25102. behaviours: derive$1([Positioning.config({ useFixed: () => header.isDocked(lazyHeader) })])
  25103. };
  25104. const reactiveWidthSpec = {
  25105. dom: { styles: { width: document.body.clientWidth + 'px' } },
  25106. events: derive$2([run$1(windowResize(), comp => {
  25107. set$8(comp.element, 'width', document.body.clientWidth + 'px');
  25108. })])
  25109. };
  25110. const sink = build$1(deepMerge(sinkSpec, isGridUiContainer ? reactiveWidthSpec : {}));
  25111. const uiMothership = takeover(sink);
  25112. lazyDialogMothership.set(uiMothership);
  25113. return {
  25114. sink,
  25115. mothership: uiMothership
  25116. };
  25117. };
  25118. const renderPopupUi = () => {
  25119. const sinkSpec = {
  25120. dom: {
  25121. tag: 'div',
  25122. classes: [
  25123. 'tox',
  25124. 'tox-silver-sink',
  25125. 'tox-silver-popup-sink',
  25126. 'tox-tinymce-aux'
  25127. ].concat(deviceClasses),
  25128. attributes: { ...global$8.isRtl() ? { dir: 'rtl' } : {} }
  25129. },
  25130. behaviours: derive$1([Positioning.config({
  25131. useFixed: () => header.isDocked(lazyHeader),
  25132. getBounds: () => setupForTheme.getPopupSinkBounds()
  25133. })])
  25134. };
  25135. const sink = build$1(sinkSpec);
  25136. const uiMothership = takeover(sink);
  25137. lazyPopupMothership.set(uiMothership);
  25138. return {
  25139. sink,
  25140. mothership: uiMothership
  25141. };
  25142. };
  25143. const renderMainUi = () => {
  25144. const partHeader = makeHeaderPart();
  25145. const sidebarContainer = makeSidebarDefinition();
  25146. const partThrobber = OuterContainer.parts.throbber({
  25147. dom: {
  25148. tag: 'div',
  25149. classes: ['tox-throbber']
  25150. },
  25151. backstage: backstages.popup
  25152. });
  25153. const partViewWrapper = OuterContainer.parts.viewWrapper({ backstage: backstages.popup });
  25154. const statusbar = useStatusBar(editor) && !isInline ? Optional.some(renderStatusbar(editor, backstages.popup.shared.providers)) : Optional.none();
  25155. const editorComponents = flatten([
  25156. isToolbarBottom ? [] : [partHeader],
  25157. isInline ? [] : [sidebarContainer],
  25158. isToolbarBottom ? [partHeader] : []
  25159. ]);
  25160. const editorContainer = OuterContainer.parts.editorContainer({
  25161. components: flatten([
  25162. editorComponents,
  25163. isInline ? [] : statusbar.toArray()
  25164. ])
  25165. });
  25166. const isHidden = isDistractionFree(editor);
  25167. const attributes = {
  25168. role: 'application',
  25169. ...global$8.isRtl() ? { dir: 'rtl' } : {},
  25170. ...isHidden ? { 'aria-hidden': 'true' } : {}
  25171. };
  25172. const outerContainer = build$1(OuterContainer.sketch({
  25173. dom: {
  25174. tag: 'div',
  25175. classes: [
  25176. 'tox',
  25177. 'tox-tinymce'
  25178. ].concat(isInline ? ['tox-tinymce-inline'] : []).concat(isToolbarBottom ? ['tox-tinymce--toolbar-bottom'] : []).concat(deviceClasses),
  25179. styles: {
  25180. visibility: 'hidden',
  25181. ...isHidden ? {
  25182. opacity: '0',
  25183. border: '0'
  25184. } : {}
  25185. },
  25186. attributes
  25187. },
  25188. components: [
  25189. editorContainer,
  25190. ...isInline ? [] : [partViewWrapper],
  25191. partThrobber
  25192. ],
  25193. behaviours: derive$1([
  25194. receivingConfig(),
  25195. Disabling.config({ disableClass: 'tox-tinymce--disabled' }),
  25196. Keying.config({
  25197. mode: 'cyclic',
  25198. 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'
  25199. })
  25200. ])
  25201. }));
  25202. const mothership = takeover(outerContainer);
  25203. lazyMothership.set(mothership);
  25204. return {
  25205. mothership,
  25206. outerContainer
  25207. };
  25208. };
  25209. const setEditorSize = outerContainer => {
  25210. const parsedHeight = numToPx(getHeightWithFallback(editor));
  25211. const parsedWidth = numToPx(getWidthWithFallback(editor));
  25212. if (!editor.inline) {
  25213. if (isValidValue$1('div', 'width', parsedWidth)) {
  25214. set$8(outerContainer.element, 'width', parsedWidth);
  25215. }
  25216. if (isValidValue$1('div', 'height', parsedHeight)) {
  25217. set$8(outerContainer.element, 'height', parsedHeight);
  25218. } else {
  25219. set$8(outerContainer.element, 'height', '400px');
  25220. }
  25221. }
  25222. return parsedHeight;
  25223. };
  25224. const setupShortcutsAndCommands = outerContainer => {
  25225. editor.addShortcut('alt+F9', 'focus menubar', () => {
  25226. OuterContainer.focusMenubar(outerContainer);
  25227. });
  25228. editor.addShortcut('alt+F10', 'focus toolbar', () => {
  25229. OuterContainer.focusToolbar(outerContainer);
  25230. });
  25231. editor.addCommand('ToggleToolbarDrawer', (_ui, options) => {
  25232. if (options === null || options === void 0 ? void 0 : options.skipFocus) {
  25233. OuterContainer.toggleToolbarDrawerWithoutFocusing(outerContainer);
  25234. } else {
  25235. OuterContainer.toggleToolbarDrawer(outerContainer);
  25236. }
  25237. });
  25238. editor.addQueryStateHandler('ToggleToolbarDrawer', () => OuterContainer.isToolbarDrawerToggled(outerContainer));
  25239. };
  25240. const renderUIWithRefs = uiRefs => {
  25241. const {mainUi, popupUi, uiMotherships} = uiRefs;
  25242. map$1(getToolbarGroups(editor), (toolbarGroupButtonConfig, name) => {
  25243. editor.ui.registry.addGroupToolbarButton(name, toolbarGroupButtonConfig);
  25244. });
  25245. const {buttons, menuItems, contextToolbars, sidebars, views} = editor.ui.registry.getAll();
  25246. const toolbarOpt = getMultipleToolbarsOption(editor);
  25247. const rawUiConfig = {
  25248. menuItems,
  25249. menus: getMenus(editor),
  25250. menubar: getMenubar(editor),
  25251. toolbar: toolbarOpt.getOrThunk(() => getToolbar(editor)),
  25252. allowToolbarGroups: toolbarMode === ToolbarMode$1.floating,
  25253. buttons,
  25254. sidebar: sidebars,
  25255. views
  25256. };
  25257. setupShortcutsAndCommands(mainUi.outerContainer);
  25258. setup$b(editor, mainUi.mothership, uiMotherships);
  25259. header.setup(editor, backstages.popup.shared, lazyHeader);
  25260. setup$6(editor, backstages.popup);
  25261. setup$5(editor, backstages.popup.shared.getSink, backstages.popup);
  25262. setup$8(editor);
  25263. setup$7(editor, lazyThrobber, backstages.popup.shared);
  25264. register$9(editor, contextToolbars, popupUi.sink, { backstage: backstages.popup });
  25265. setup$4(editor, popupUi.sink);
  25266. const elm = editor.getElement();
  25267. const height = setEditorSize(mainUi.outerContainer);
  25268. const args = {
  25269. targetNode: elm,
  25270. height
  25271. };
  25272. return mode.render(editor, uiRefs, rawUiConfig, backstages.popup, args);
  25273. };
  25274. const reuseDialogUiForPopuUi = dialogUi => {
  25275. lazyPopupMothership.set(dialogUi.mothership);
  25276. return dialogUi;
  25277. };
  25278. const renderUI = () => {
  25279. const mainUi = renderMainUi();
  25280. const dialogUi = renderDialogUi();
  25281. const popupUi = isSplitUiMode(editor) ? renderPopupUi() : reuseDialogUiForPopuUi(dialogUi);
  25282. lazyUiRefs.dialogUi.set(dialogUi);
  25283. lazyUiRefs.popupUi.set(popupUi);
  25284. lazyUiRefs.mainUi.set(mainUi);
  25285. const uiRefs = {
  25286. popupUi,
  25287. dialogUi,
  25288. mainUi,
  25289. uiMotherships: lazyUiRefs.getUiMotherships()
  25290. };
  25291. return renderUIWithRefs(uiRefs);
  25292. };
  25293. return {
  25294. popups: {
  25295. backstage: backstages.popup,
  25296. getMothership: () => getLazyMothership('popups', lazyPopupMothership)
  25297. },
  25298. dialogs: {
  25299. backstage: backstages.dialog,
  25300. getMothership: () => getLazyMothership('dialogs', lazyDialogMothership)
  25301. },
  25302. renderUI
  25303. };
  25304. };
  25305. const describedBy = (describedElement, describeElement) => {
  25306. const describeId = Optional.from(get$f(describedElement, 'id')).fold(() => {
  25307. const id = generate$6('dialog-describe');
  25308. set$9(describeElement, 'id', id);
  25309. return id;
  25310. }, identity);
  25311. set$9(describedElement, 'aria-describedby', describeId);
  25312. };
  25313. const labelledBy = (labelledElement, labelElement) => {
  25314. const labelId = getOpt(labelledElement, 'id').fold(() => {
  25315. const id = generate$6('dialog-label');
  25316. set$9(labelElement, 'id', id);
  25317. return id;
  25318. }, identity);
  25319. set$9(labelledElement, 'aria-labelledby', labelId);
  25320. };
  25321. const schema$2 = constant$1([
  25322. required$1('lazySink'),
  25323. option$3('dragBlockClass'),
  25324. defaultedFunction('getBounds', win),
  25325. defaulted('useTabstopAt', always),
  25326. defaulted('firstTabstop', 0),
  25327. defaulted('eventOrder', {}),
  25328. field('modalBehaviours', [Keying]),
  25329. onKeyboardHandler('onExecute'),
  25330. onStrictKeyboardHandler('onEscape')
  25331. ]);
  25332. const basic = { sketch: identity };
  25333. const parts$2 = constant$1([
  25334. optional({
  25335. name: 'draghandle',
  25336. overrides: (detail, spec) => {
  25337. return {
  25338. behaviours: derive$1([Dragging.config({
  25339. mode: 'mouse',
  25340. getTarget: handle => {
  25341. return ancestor(handle, '[role="dialog"]').getOr(handle);
  25342. },
  25343. 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),
  25344. getBounds: detail.getDragBounds
  25345. })])
  25346. };
  25347. }
  25348. }),
  25349. required({
  25350. schema: [required$1('dom')],
  25351. name: 'title'
  25352. }),
  25353. required({
  25354. factory: basic,
  25355. schema: [required$1('dom')],
  25356. name: 'close'
  25357. }),
  25358. required({
  25359. factory: basic,
  25360. schema: [required$1('dom')],
  25361. name: 'body'
  25362. }),
  25363. optional({
  25364. factory: basic,
  25365. schema: [required$1('dom')],
  25366. name: 'footer'
  25367. }),
  25368. external({
  25369. factory: {
  25370. sketch: (spec, detail) => ({
  25371. ...spec,
  25372. dom: detail.dom,
  25373. components: detail.components
  25374. })
  25375. },
  25376. schema: [
  25377. defaulted('dom', {
  25378. tag: 'div',
  25379. styles: {
  25380. position: 'fixed',
  25381. left: '0px',
  25382. top: '0px',
  25383. right: '0px',
  25384. bottom: '0px'
  25385. }
  25386. }),
  25387. defaulted('components', [])
  25388. ],
  25389. name: 'blocker'
  25390. })
  25391. ]);
  25392. const factory$4 = (detail, components, spec, externals) => {
  25393. const dialogComp = value$2();
  25394. const showDialog = dialog => {
  25395. dialogComp.set(dialog);
  25396. const sink = detail.lazySink(dialog).getOrDie();
  25397. const externalBlocker = externals.blocker();
  25398. const blocker = sink.getSystem().build({
  25399. ...externalBlocker,
  25400. components: externalBlocker.components.concat([premade(dialog)]),
  25401. behaviours: derive$1([
  25402. Focusing.config({}),
  25403. config('dialog-blocker-events', [runOnSource(focusin(), () => {
  25404. Keying.focusIn(dialog);
  25405. })])
  25406. ])
  25407. });
  25408. attach(sink, blocker);
  25409. Keying.focusIn(dialog);
  25410. };
  25411. const hideDialog = dialog => {
  25412. dialogComp.clear();
  25413. parent(dialog.element).each(blockerDom => {
  25414. dialog.getSystem().getByDom(blockerDom).each(blocker => {
  25415. detach(blocker);
  25416. });
  25417. });
  25418. };
  25419. const getDialogBody = dialog => getPartOrDie(dialog, detail, 'body');
  25420. const getDialogFooter = dialog => getPartOrDie(dialog, detail, 'footer');
  25421. const setBusy = (dialog, getBusySpec) => {
  25422. Blocking.block(dialog, getBusySpec);
  25423. };
  25424. const setIdle = dialog => {
  25425. Blocking.unblock(dialog);
  25426. };
  25427. const modalEventsId = generate$6('modal-events');
  25428. const eventOrder = {
  25429. ...detail.eventOrder,
  25430. [attachedToDom()]: [modalEventsId].concat(detail.eventOrder['alloy.system.attached'] || [])
  25431. };
  25432. return {
  25433. uid: detail.uid,
  25434. dom: detail.dom,
  25435. components,
  25436. apis: {
  25437. show: showDialog,
  25438. hide: hideDialog,
  25439. getBody: getDialogBody,
  25440. getFooter: getDialogFooter,
  25441. setIdle,
  25442. setBusy
  25443. },
  25444. eventOrder,
  25445. domModification: {
  25446. attributes: {
  25447. 'role': 'dialog',
  25448. 'aria-modal': 'true'
  25449. }
  25450. },
  25451. behaviours: augment(detail.modalBehaviours, [
  25452. Replacing.config({}),
  25453. Keying.config({
  25454. mode: 'cyclic',
  25455. onEnter: detail.onExecute,
  25456. onEscape: detail.onEscape,
  25457. useTabstopAt: detail.useTabstopAt,
  25458. firstTabstop: detail.firstTabstop
  25459. }),
  25460. Blocking.config({ getRoot: dialogComp.get }),
  25461. config(modalEventsId, [runOnAttached(c => {
  25462. labelledBy(c.element, getPartOrDie(c, detail, 'title').element);
  25463. describedBy(c.element, getPartOrDie(c, detail, 'body').element);
  25464. })])
  25465. ])
  25466. };
  25467. };
  25468. const ModalDialog = composite({
  25469. name: 'ModalDialog',
  25470. configFields: schema$2(),
  25471. partFields: parts$2(),
  25472. factory: factory$4,
  25473. apis: {
  25474. show: (apis, dialog) => {
  25475. apis.show(dialog);
  25476. },
  25477. hide: (apis, dialog) => {
  25478. apis.hide(dialog);
  25479. },
  25480. getBody: (apis, dialog) => apis.getBody(dialog),
  25481. getFooter: (apis, dialog) => apis.getFooter(dialog),
  25482. setBusy: (apis, dialog, getBusySpec) => {
  25483. apis.setBusy(dialog, getBusySpec);
  25484. },
  25485. setIdle: (apis, dialog) => {
  25486. apis.setIdle(dialog);
  25487. }
  25488. }
  25489. });
  25490. const dialogToggleMenuItemSchema = objOf([
  25491. type,
  25492. name$1
  25493. ].concat(commonMenuItemFields));
  25494. const dialogToggleMenuItemDataProcessor = boolean;
  25495. const baseFooterButtonFields = [
  25496. generatedName('button'),
  25497. optionalIcon,
  25498. defaultedStringEnum('align', 'end', [
  25499. 'start',
  25500. 'end'
  25501. ]),
  25502. primary,
  25503. enabled,
  25504. optionStringEnum('buttonType', [
  25505. 'primary',
  25506. 'secondary'
  25507. ])
  25508. ];
  25509. const dialogFooterButtonFields = [
  25510. ...baseFooterButtonFields,
  25511. text$1
  25512. ];
  25513. const normalFooterButtonFields = [
  25514. requiredStringEnum('type', [
  25515. 'submit',
  25516. 'cancel',
  25517. 'custom'
  25518. ]),
  25519. ...dialogFooterButtonFields
  25520. ];
  25521. const menuFooterButtonFields = [
  25522. requiredStringEnum('type', ['menu']),
  25523. optionalText,
  25524. optionalTooltip,
  25525. optionalIcon,
  25526. requiredArrayOf('items', dialogToggleMenuItemSchema),
  25527. ...baseFooterButtonFields
  25528. ];
  25529. const toggleButtonSpecFields = [
  25530. ...baseFooterButtonFields,
  25531. requiredStringEnum('type', ['togglebutton']),
  25532. requiredString('tooltip'),
  25533. icon,
  25534. optionalText,
  25535. defaultedBoolean('active', false)
  25536. ];
  25537. const dialogFooterButtonSchema = choose$1('type', {
  25538. submit: normalFooterButtonFields,
  25539. cancel: normalFooterButtonFields,
  25540. custom: normalFooterButtonFields,
  25541. menu: menuFooterButtonFields,
  25542. togglebutton: toggleButtonSpecFields
  25543. });
  25544. const alertBannerFields = [
  25545. type,
  25546. text$1,
  25547. requiredStringEnum('level', [
  25548. 'info',
  25549. 'warn',
  25550. 'error',
  25551. 'success'
  25552. ]),
  25553. icon,
  25554. defaulted('url', '')
  25555. ];
  25556. const alertBannerSchema = objOf(alertBannerFields);
  25557. const createBarFields = itemsField => [
  25558. type,
  25559. itemsField
  25560. ];
  25561. const buttonFields = [
  25562. type,
  25563. text$1,
  25564. enabled,
  25565. generatedName('button'),
  25566. optionalIcon,
  25567. borderless,
  25568. optionStringEnum('buttonType', [
  25569. 'primary',
  25570. 'secondary',
  25571. 'toolbar'
  25572. ]),
  25573. primary
  25574. ];
  25575. const buttonSchema = objOf(buttonFields);
  25576. const formComponentFields = [
  25577. type,
  25578. name$1
  25579. ];
  25580. const formComponentWithLabelFields = formComponentFields.concat([optionalLabel]);
  25581. const checkboxFields = formComponentFields.concat([
  25582. label,
  25583. enabled
  25584. ]);
  25585. const checkboxSchema = objOf(checkboxFields);
  25586. const checkboxDataProcessor = boolean;
  25587. const collectionFields = formComponentWithLabelFields.concat([defaultedColumns('auto')]);
  25588. const collectionSchema = objOf(collectionFields);
  25589. const collectionDataProcessor = arrOfObj([
  25590. value$1,
  25591. text$1,
  25592. icon
  25593. ]);
  25594. const colorInputFields = formComponentWithLabelFields.concat([defaultedString('storageKey', 'default')]);
  25595. const colorInputSchema = objOf(colorInputFields);
  25596. const colorInputDataProcessor = string;
  25597. const colorPickerFields = formComponentWithLabelFields;
  25598. const colorPickerSchema = objOf(colorPickerFields);
  25599. const colorPickerDataProcessor = string;
  25600. const customEditorFields = formComponentFields.concat([
  25601. defaultedString('tag', 'textarea'),
  25602. requiredString('scriptId'),
  25603. requiredString('scriptUrl'),
  25604. defaultedPostMsg('settings', undefined)
  25605. ]);
  25606. const customEditorFieldsOld = formComponentFields.concat([
  25607. defaultedString('tag', 'textarea'),
  25608. requiredFunction('init')
  25609. ]);
  25610. const customEditorSchema = valueOf(v => asRaw('customeditor.old', objOfOnly(customEditorFieldsOld), v).orThunk(() => asRaw('customeditor.new', objOfOnly(customEditorFields), v)));
  25611. const customEditorDataProcessor = string;
  25612. const dropZoneFields = formComponentWithLabelFields;
  25613. const dropZoneSchema = objOf(dropZoneFields);
  25614. const dropZoneDataProcessor = arrOfVal();
  25615. const createGridFields = itemsField => [
  25616. type,
  25617. requiredNumber('columns'),
  25618. itemsField
  25619. ];
  25620. const htmlPanelFields = [
  25621. type,
  25622. requiredString('html'),
  25623. defaultedStringEnum('presets', 'presentation', [
  25624. 'presentation',
  25625. 'document'
  25626. ])
  25627. ];
  25628. const htmlPanelSchema = objOf(htmlPanelFields);
  25629. const iframeFields = formComponentWithLabelFields.concat([
  25630. defaultedBoolean('sandboxed', true),
  25631. defaultedBoolean('transparent', true)
  25632. ]);
  25633. const iframeSchema = objOf(iframeFields);
  25634. const iframeDataProcessor = string;
  25635. const imagePreviewSchema = objOf(formComponentFields.concat([optionString('height')]));
  25636. const imagePreviewDataProcessor = objOf([
  25637. requiredString('url'),
  25638. optionNumber('zoom'),
  25639. optionNumber('cachedWidth'),
  25640. optionNumber('cachedHeight')
  25641. ]);
  25642. const inputFields = formComponentWithLabelFields.concat([
  25643. optionString('inputMode'),
  25644. optionString('placeholder'),
  25645. defaultedBoolean('maximized', false),
  25646. enabled
  25647. ]);
  25648. const inputSchema = objOf(inputFields);
  25649. const inputDataProcessor = string;
  25650. const createLabelFields = itemsField => [
  25651. type,
  25652. label,
  25653. itemsField
  25654. ];
  25655. const listBoxSingleItemFields = [
  25656. text$1,
  25657. value$1
  25658. ];
  25659. const listBoxNestedItemFields = [
  25660. text$1,
  25661. requiredArrayOf('items', thunkOf('items', () => listBoxItemSchema))
  25662. ];
  25663. const listBoxItemSchema = oneOf([
  25664. objOf(listBoxSingleItemFields),
  25665. objOf(listBoxNestedItemFields)
  25666. ]);
  25667. const listBoxFields = formComponentWithLabelFields.concat([
  25668. requiredArrayOf('items', listBoxItemSchema),
  25669. enabled
  25670. ]);
  25671. const listBoxSchema = objOf(listBoxFields);
  25672. const listBoxDataProcessor = string;
  25673. const selectBoxFields = formComponentWithLabelFields.concat([
  25674. requiredArrayOfObj('items', [
  25675. text$1,
  25676. value$1
  25677. ]),
  25678. defaultedNumber('size', 1),
  25679. enabled
  25680. ]);
  25681. const selectBoxSchema = objOf(selectBoxFields);
  25682. const selectBoxDataProcessor = string;
  25683. const sizeInputFields = formComponentWithLabelFields.concat([
  25684. defaultedBoolean('constrain', true),
  25685. enabled
  25686. ]);
  25687. const sizeInputSchema = objOf(sizeInputFields);
  25688. const sizeInputDataProcessor = objOf([
  25689. requiredString('width'),
  25690. requiredString('height')
  25691. ]);
  25692. const sliderFields = formComponentFields.concat([
  25693. label,
  25694. defaultedNumber('min', 0),
  25695. defaultedNumber('max', 0)
  25696. ]);
  25697. const sliderSchema = objOf(sliderFields);
  25698. const sliderInputDataProcessor = number;
  25699. const tableFields = [
  25700. type,
  25701. requiredArrayOf('header', string),
  25702. requiredArrayOf('cells', arrOf(string))
  25703. ];
  25704. const tableSchema = objOf(tableFields);
  25705. const textAreaFields = formComponentWithLabelFields.concat([
  25706. optionString('placeholder'),
  25707. defaultedBoolean('maximized', false),
  25708. enabled
  25709. ]);
  25710. const textAreaSchema = objOf(textAreaFields);
  25711. const textAreaDataProcessor = string;
  25712. const baseTreeItemFields = [
  25713. requiredStringEnum('type', [
  25714. 'directory',
  25715. 'leaf'
  25716. ]),
  25717. title,
  25718. requiredString('id'),
  25719. optionOf('menu', MenuButtonSchema)
  25720. ];
  25721. const treeItemLeafFields = baseTreeItemFields;
  25722. const treeItemLeafSchema = objOf(treeItemLeafFields);
  25723. const treeItemDirectoryFields = baseTreeItemFields.concat([requiredArrayOf('children', thunkOf('children', () => {
  25724. return choose$2('type', {
  25725. directory: treeItemDirectorySchema,
  25726. leaf: treeItemLeafSchema
  25727. });
  25728. }))]);
  25729. const treeItemDirectorySchema = objOf(treeItemDirectoryFields);
  25730. const treeItemSchema = choose$2('type', {
  25731. directory: treeItemDirectorySchema,
  25732. leaf: treeItemLeafSchema
  25733. });
  25734. const treeFields = [
  25735. type,
  25736. requiredArrayOf('items', treeItemSchema),
  25737. optionFunction('onLeafAction')
  25738. ];
  25739. const treeSchema = objOf(treeFields);
  25740. const urlInputFields = formComponentWithLabelFields.concat([
  25741. defaultedStringEnum('filetype', 'file', [
  25742. 'image',
  25743. 'media',
  25744. 'file'
  25745. ]),
  25746. enabled
  25747. ]);
  25748. const urlInputSchema = objOf(urlInputFields);
  25749. const urlInputDataProcessor = objOf([
  25750. value$1,
  25751. defaultedMeta
  25752. ]);
  25753. 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)))));
  25754. const itemSchema = valueThunk(() => choose$2('type', {
  25755. alertbanner: alertBannerSchema,
  25756. bar: objOf(createBarFields(createItemsField('bar'))),
  25757. button: buttonSchema,
  25758. checkbox: checkboxSchema,
  25759. colorinput: colorInputSchema,
  25760. colorpicker: colorPickerSchema,
  25761. dropzone: dropZoneSchema,
  25762. grid: objOf(createGridFields(createItemsField('grid'))),
  25763. iframe: iframeSchema,
  25764. input: inputSchema,
  25765. listbox: listBoxSchema,
  25766. selectbox: selectBoxSchema,
  25767. sizeinput: sizeInputSchema,
  25768. slider: sliderSchema,
  25769. textarea: textAreaSchema,
  25770. urlinput: urlInputSchema,
  25771. customeditor: customEditorSchema,
  25772. htmlpanel: htmlPanelSchema,
  25773. imagepreview: imagePreviewSchema,
  25774. collection: collectionSchema,
  25775. label: objOf(createLabelFields(createItemsField('label'))),
  25776. table: tableSchema,
  25777. tree: treeSchema,
  25778. panel: panelSchema
  25779. }));
  25780. const panelFields = [
  25781. type,
  25782. defaulted('classes', []),
  25783. requiredArrayOf('items', itemSchema)
  25784. ];
  25785. const panelSchema = objOf(panelFields);
  25786. const tabFields = [
  25787. generatedName('tab'),
  25788. title,
  25789. requiredArrayOf('items', itemSchema)
  25790. ];
  25791. const tabPanelFields = [
  25792. type,
  25793. requiredArrayOfObj('tabs', tabFields)
  25794. ];
  25795. const tabPanelSchema = objOf(tabPanelFields);
  25796. const dialogButtonFields = dialogFooterButtonFields;
  25797. const dialogButtonSchema = dialogFooterButtonSchema;
  25798. const dialogSchema = objOf([
  25799. requiredString('title'),
  25800. requiredOf('body', choose$2('type', {
  25801. panel: panelSchema,
  25802. tabpanel: tabPanelSchema
  25803. })),
  25804. defaultedString('size', 'normal'),
  25805. requiredArrayOf('buttons', dialogButtonSchema),
  25806. defaulted('initialData', {}),
  25807. defaultedFunction('onAction', noop),
  25808. defaultedFunction('onChange', noop),
  25809. defaultedFunction('onSubmit', noop),
  25810. defaultedFunction('onClose', noop),
  25811. defaultedFunction('onCancel', noop),
  25812. defaultedFunction('onTabChange', noop)
  25813. ]);
  25814. const createDialog = spec => asRaw('dialog', dialogSchema, spec);
  25815. const urlDialogButtonSchema = objOf([
  25816. requiredStringEnum('type', [
  25817. 'cancel',
  25818. 'custom'
  25819. ]),
  25820. ...dialogButtonFields
  25821. ]);
  25822. const urlDialogSchema = objOf([
  25823. requiredString('title'),
  25824. requiredString('url'),
  25825. optionNumber('height'),
  25826. optionNumber('width'),
  25827. optionArrayOf('buttons', urlDialogButtonSchema),
  25828. defaultedFunction('onAction', noop),
  25829. defaultedFunction('onCancel', noop),
  25830. defaultedFunction('onClose', noop),
  25831. defaultedFunction('onMessage', noop)
  25832. ]);
  25833. const createUrlDialog = spec => asRaw('dialog', urlDialogSchema, spec);
  25834. const getAllObjects = obj => {
  25835. if (isObject(obj)) {
  25836. return [obj].concat(bind$3(values(obj), getAllObjects));
  25837. } else if (isArray(obj)) {
  25838. return bind$3(obj, getAllObjects);
  25839. } else {
  25840. return [];
  25841. }
  25842. };
  25843. const isNamedItem = obj => isString(obj.type) && isString(obj.name);
  25844. const dataProcessors = {
  25845. checkbox: checkboxDataProcessor,
  25846. colorinput: colorInputDataProcessor,
  25847. colorpicker: colorPickerDataProcessor,
  25848. dropzone: dropZoneDataProcessor,
  25849. input: inputDataProcessor,
  25850. iframe: iframeDataProcessor,
  25851. imagepreview: imagePreviewDataProcessor,
  25852. selectbox: selectBoxDataProcessor,
  25853. sizeinput: sizeInputDataProcessor,
  25854. slider: sliderInputDataProcessor,
  25855. listbox: listBoxDataProcessor,
  25856. size: sizeInputDataProcessor,
  25857. textarea: textAreaDataProcessor,
  25858. urlinput: urlInputDataProcessor,
  25859. customeditor: customEditorDataProcessor,
  25860. collection: collectionDataProcessor,
  25861. togglemenuitem: dialogToggleMenuItemDataProcessor
  25862. };
  25863. const getDataProcessor = item => Optional.from(dataProcessors[item.type]);
  25864. const getNamedItems = structure => filter$2(getAllObjects(structure), isNamedItem);
  25865. const createDataValidator = structure => {
  25866. const namedItems = getNamedItems(structure);
  25867. const fields = bind$3(namedItems, item => getDataProcessor(item).fold(() => [], schema => [requiredOf(item.name, schema)]));
  25868. return objOf(fields);
  25869. };
  25870. const extract = structure => {
  25871. var _a;
  25872. const internalDialog = getOrDie(createDialog(structure));
  25873. const dataValidator = createDataValidator(structure);
  25874. const initialData = (_a = structure.initialData) !== null && _a !== void 0 ? _a : {};
  25875. return {
  25876. internalDialog,
  25877. dataValidator,
  25878. initialData
  25879. };
  25880. };
  25881. const DialogManager = {
  25882. open: (factory, structure) => {
  25883. const extraction = extract(structure);
  25884. return factory(extraction.internalDialog, extraction.initialData, extraction.dataValidator);
  25885. },
  25886. openUrl: (factory, structure) => {
  25887. const internalDialog = getOrDie(createUrlDialog(structure));
  25888. return factory(internalDialog);
  25889. },
  25890. redial: structure => extract(structure)
  25891. };
  25892. const events = (reflectingConfig, reflectingState) => {
  25893. const update = (component, data) => {
  25894. reflectingConfig.updateState.each(updateState => {
  25895. const newState = updateState(component, data);
  25896. reflectingState.set(newState);
  25897. });
  25898. reflectingConfig.renderComponents.each(renderComponents => {
  25899. const newComponents = renderComponents(data, reflectingState.get());
  25900. const replacer = reflectingConfig.reuseDom ? withReuse : withoutReuse;
  25901. replacer(component, newComponents);
  25902. });
  25903. };
  25904. return derive$2([
  25905. run$1(receive(), (component, message) => {
  25906. const receivingData = message;
  25907. if (!receivingData.universal) {
  25908. const channel = reflectingConfig.channel;
  25909. if (contains$2(receivingData.channels, channel)) {
  25910. update(component, receivingData.data);
  25911. }
  25912. }
  25913. }),
  25914. runOnAttached((comp, _se) => {
  25915. reflectingConfig.initialData.each(rawData => {
  25916. update(comp, rawData);
  25917. });
  25918. })
  25919. ]);
  25920. };
  25921. var ActiveReflecting = /*#__PURE__*/Object.freeze({
  25922. __proto__: null,
  25923. events: events
  25924. });
  25925. const getState = (component, replaceConfig, reflectState) => reflectState;
  25926. var ReflectingApis = /*#__PURE__*/Object.freeze({
  25927. __proto__: null,
  25928. getState: getState
  25929. });
  25930. var ReflectingSchema = [
  25931. required$1('channel'),
  25932. option$3('renderComponents'),
  25933. option$3('updateState'),
  25934. option$3('initialData'),
  25935. defaultedBoolean('reuseDom', true)
  25936. ];
  25937. const init = () => {
  25938. const cell = Cell(Optional.none());
  25939. const clear = () => cell.set(Optional.none());
  25940. const readState = () => cell.get().getOr('none');
  25941. return {
  25942. readState,
  25943. get: cell.get,
  25944. set: cell.set,
  25945. clear
  25946. };
  25947. };
  25948. var ReflectingState = /*#__PURE__*/Object.freeze({
  25949. __proto__: null,
  25950. init: init
  25951. });
  25952. const Reflecting = create$4({
  25953. fields: ReflectingSchema,
  25954. name: 'reflecting',
  25955. active: ActiveReflecting,
  25956. apis: ReflectingApis,
  25957. state: ReflectingState
  25958. });
  25959. const toValidValues = values => {
  25960. const errors = [];
  25961. const result = {};
  25962. each(values, (value, name) => {
  25963. value.fold(() => {
  25964. errors.push(name);
  25965. }, v => {
  25966. result[name] = v;
  25967. });
  25968. });
  25969. return errors.length > 0 ? Result.error(errors) : Result.value(result);
  25970. };
  25971. const renderBodyPanel = (spec, dialogData, backstage) => {
  25972. const memForm = record(Form.sketch(parts => ({
  25973. dom: {
  25974. tag: 'div',
  25975. classes: ['tox-form'].concat(spec.classes)
  25976. },
  25977. components: map$2(spec.items, item => interpretInForm(parts, item, dialogData, backstage))
  25978. })));
  25979. return {
  25980. dom: {
  25981. tag: 'div',
  25982. classes: ['tox-dialog__body']
  25983. },
  25984. components: [{
  25985. dom: {
  25986. tag: 'div',
  25987. classes: ['tox-dialog__body-content']
  25988. },
  25989. components: [memForm.asSpec()]
  25990. }],
  25991. behaviours: derive$1([
  25992. Keying.config({
  25993. mode: 'acyclic',
  25994. useTabstopAt: not(isPseudoStop)
  25995. }),
  25996. ComposingConfigs.memento(memForm),
  25997. RepresentingConfigs.memento(memForm, {
  25998. postprocess: formValue => toValidValues(formValue).fold(err => {
  25999. console.error(err);
  26000. return {};
  26001. }, identity)
  26002. })
  26003. ])
  26004. };
  26005. };
  26006. const factory$3 = (detail, _spec) => ({
  26007. uid: detail.uid,
  26008. dom: detail.dom,
  26009. components: detail.components,
  26010. events: events$a(detail.action),
  26011. behaviours: augment(detail.tabButtonBehaviours, [
  26012. Focusing.config({}),
  26013. Keying.config({
  26014. mode: 'execution',
  26015. useSpace: true,
  26016. useEnter: true
  26017. }),
  26018. Representing.config({
  26019. store: {
  26020. mode: 'memory',
  26021. initialValue: detail.value
  26022. }
  26023. })
  26024. ]),
  26025. domModification: detail.domModification
  26026. });
  26027. const TabButton = single({
  26028. name: 'TabButton',
  26029. configFields: [
  26030. defaulted('uid', undefined),
  26031. required$1('value'),
  26032. field$1('dom', 'dom', mergeWithThunk(() => ({
  26033. attributes: {
  26034. 'role': 'tab',
  26035. 'id': generate$6('aria'),
  26036. 'aria-selected': 'false'
  26037. }
  26038. })), anyValue()),
  26039. option$3('action'),
  26040. defaulted('domModification', {}),
  26041. field('tabButtonBehaviours', [
  26042. Focusing,
  26043. Keying,
  26044. Representing
  26045. ]),
  26046. required$1('view')
  26047. ],
  26048. factory: factory$3
  26049. });
  26050. const schema$1 = constant$1([
  26051. required$1('tabs'),
  26052. required$1('dom'),
  26053. defaulted('clickToDismiss', false),
  26054. field('tabbarBehaviours', [
  26055. Highlighting,
  26056. Keying
  26057. ]),
  26058. markers$1([
  26059. 'tabClass',
  26060. 'selectedClass'
  26061. ])
  26062. ]);
  26063. const tabsPart = group({
  26064. factory: TabButton,
  26065. name: 'tabs',
  26066. unit: 'tab',
  26067. overrides: barDetail => {
  26068. const dismissTab$1 = (tabbar, button) => {
  26069. Highlighting.dehighlight(tabbar, button);
  26070. emitWith(tabbar, dismissTab(), {
  26071. tabbar,
  26072. button
  26073. });
  26074. };
  26075. const changeTab$1 = (tabbar, button) => {
  26076. Highlighting.highlight(tabbar, button);
  26077. emitWith(tabbar, changeTab(), {
  26078. tabbar,
  26079. button
  26080. });
  26081. };
  26082. return {
  26083. action: button => {
  26084. const tabbar = button.getSystem().getByUid(barDetail.uid).getOrDie();
  26085. const activeButton = Highlighting.isHighlighted(tabbar, button);
  26086. const response = (() => {
  26087. if (activeButton && barDetail.clickToDismiss) {
  26088. return dismissTab$1;
  26089. } else if (!activeButton) {
  26090. return changeTab$1;
  26091. } else {
  26092. return noop;
  26093. }
  26094. })();
  26095. response(tabbar, button);
  26096. },
  26097. domModification: { classes: [barDetail.markers.tabClass] }
  26098. };
  26099. }
  26100. });
  26101. const parts$1 = constant$1([tabsPart]);
  26102. const factory$2 = (detail, components, _spec, _externals) => ({
  26103. 'uid': detail.uid,
  26104. 'dom': detail.dom,
  26105. components,
  26106. 'debug.sketcher': 'Tabbar',
  26107. 'domModification': { attributes: { role: 'tablist' } },
  26108. 'behaviours': augment(detail.tabbarBehaviours, [
  26109. Highlighting.config({
  26110. highlightClass: detail.markers.selectedClass,
  26111. itemClass: detail.markers.tabClass,
  26112. onHighlight: (tabbar, tab) => {
  26113. set$9(tab.element, 'aria-selected', 'true');
  26114. },
  26115. onDehighlight: (tabbar, tab) => {
  26116. set$9(tab.element, 'aria-selected', 'false');
  26117. }
  26118. }),
  26119. Keying.config({
  26120. mode: 'flow',
  26121. getInitial: tabbar => {
  26122. return Highlighting.getHighlighted(tabbar).map(tab => tab.element);
  26123. },
  26124. selector: '.' + detail.markers.tabClass,
  26125. executeOnMove: true
  26126. })
  26127. ])
  26128. });
  26129. const Tabbar = composite({
  26130. name: 'Tabbar',
  26131. configFields: schema$1(),
  26132. partFields: parts$1(),
  26133. factory: factory$2
  26134. });
  26135. const factory$1 = (detail, _spec) => ({
  26136. uid: detail.uid,
  26137. dom: detail.dom,
  26138. behaviours: augment(detail.tabviewBehaviours, [Replacing.config({})]),
  26139. domModification: { attributes: { role: 'tabpanel' } }
  26140. });
  26141. const Tabview = single({
  26142. name: 'Tabview',
  26143. configFields: [field('tabviewBehaviours', [Replacing])],
  26144. factory: factory$1
  26145. });
  26146. const schema = constant$1([
  26147. defaulted('selectFirst', true),
  26148. onHandler('onChangeTab'),
  26149. onHandler('onDismissTab'),
  26150. defaulted('tabs', []),
  26151. field('tabSectionBehaviours', [])
  26152. ]);
  26153. const barPart = required({
  26154. factory: Tabbar,
  26155. schema: [
  26156. required$1('dom'),
  26157. requiredObjOf('markers', [
  26158. required$1('tabClass'),
  26159. required$1('selectedClass')
  26160. ])
  26161. ],
  26162. name: 'tabbar',
  26163. defaults: detail => {
  26164. return { tabs: detail.tabs };
  26165. }
  26166. });
  26167. const viewPart = required({
  26168. factory: Tabview,
  26169. name: 'tabview'
  26170. });
  26171. const parts = constant$1([
  26172. barPart,
  26173. viewPart
  26174. ]);
  26175. const factory = (detail, components, _spec, _externals) => {
  26176. const changeTab$1 = button => {
  26177. const tabValue = Representing.getValue(button);
  26178. getPart(button, detail, 'tabview').each(tabview => {
  26179. const tabWithValue = find$5(detail.tabs, t => t.value === tabValue);
  26180. tabWithValue.each(tabData => {
  26181. const panel = tabData.view();
  26182. getOpt(button.element, 'id').each(id => {
  26183. set$9(tabview.element, 'aria-labelledby', id);
  26184. });
  26185. Replacing.set(tabview, panel);
  26186. detail.onChangeTab(tabview, button, panel);
  26187. });
  26188. });
  26189. };
  26190. const changeTabBy = (section, byPred) => {
  26191. getPart(section, detail, 'tabbar').each(tabbar => {
  26192. byPred(tabbar).each(emitExecute);
  26193. });
  26194. };
  26195. return {
  26196. uid: detail.uid,
  26197. dom: detail.dom,
  26198. components,
  26199. behaviours: get$3(detail.tabSectionBehaviours),
  26200. events: derive$2(flatten([
  26201. detail.selectFirst ? [runOnAttached((section, _simulatedEvent) => {
  26202. changeTabBy(section, Highlighting.getFirst);
  26203. })] : [],
  26204. [
  26205. run$1(changeTab(), (section, simulatedEvent) => {
  26206. const button = simulatedEvent.event.button;
  26207. changeTab$1(button);
  26208. }),
  26209. run$1(dismissTab(), (section, simulatedEvent) => {
  26210. const button = simulatedEvent.event.button;
  26211. detail.onDismissTab(section, button);
  26212. })
  26213. ]
  26214. ])),
  26215. apis: {
  26216. getViewItems: section => {
  26217. return getPart(section, detail, 'tabview').map(tabview => Replacing.contents(tabview)).getOr([]);
  26218. },
  26219. showTab: (section, tabKey) => {
  26220. const getTabIfNotActive = tabbar => {
  26221. const candidates = Highlighting.getCandidates(tabbar);
  26222. const optTab = find$5(candidates, c => Representing.getValue(c) === tabKey);
  26223. return optTab.filter(tab => !Highlighting.isHighlighted(tabbar, tab));
  26224. };
  26225. changeTabBy(section, getTabIfNotActive);
  26226. }
  26227. }
  26228. };
  26229. };
  26230. const TabSection = composite({
  26231. name: 'TabSection',
  26232. configFields: schema(),
  26233. partFields: parts(),
  26234. factory,
  26235. apis: {
  26236. getViewItems: (apis, component) => apis.getViewItems(component),
  26237. showTab: (apis, component, tabKey) => {
  26238. apis.showTab(component, tabKey);
  26239. }
  26240. }
  26241. });
  26242. const measureHeights = (allTabs, tabview, tabviewComp) => map$2(allTabs, (_tab, i) => {
  26243. Replacing.set(tabviewComp, allTabs[i].view());
  26244. const rect = tabview.dom.getBoundingClientRect();
  26245. Replacing.set(tabviewComp, []);
  26246. return rect.height;
  26247. });
  26248. const getMaxHeight = heights => head(sort(heights, (a, b) => {
  26249. if (a > b) {
  26250. return -1;
  26251. } else if (a < b) {
  26252. return +1;
  26253. } else {
  26254. return 0;
  26255. }
  26256. }));
  26257. const getMaxTabviewHeight = (dialog, tabview, tablist) => {
  26258. const documentElement$1 = documentElement(dialog).dom;
  26259. const rootElm = ancestor(dialog, '.tox-dialog-wrap').getOr(dialog);
  26260. const isFixed = get$e(rootElm, 'position') === 'fixed';
  26261. let maxHeight;
  26262. if (isFixed) {
  26263. maxHeight = Math.max(documentElement$1.clientHeight, window.innerHeight);
  26264. } else {
  26265. maxHeight = Math.max(documentElement$1.offsetHeight, documentElement$1.scrollHeight);
  26266. }
  26267. const tabviewHeight = get$d(tabview);
  26268. const isTabListBeside = tabview.dom.offsetLeft >= tablist.dom.offsetLeft + get$c(tablist);
  26269. const currentTabHeight = isTabListBeside ? Math.max(get$d(tablist), tabviewHeight) : tabviewHeight;
  26270. const dialogTopMargin = parseInt(get$e(dialog, 'margin-top'), 10) || 0;
  26271. const dialogBottomMargin = parseInt(get$e(dialog, 'margin-bottom'), 10) || 0;
  26272. const dialogHeight = get$d(dialog) + dialogTopMargin + dialogBottomMargin;
  26273. const chromeHeight = dialogHeight - currentTabHeight;
  26274. return maxHeight - chromeHeight;
  26275. };
  26276. const showTab = (allTabs, comp) => {
  26277. head(allTabs).each(tab => TabSection.showTab(comp, tab.value));
  26278. };
  26279. const setTabviewHeight = (tabview, height) => {
  26280. set$8(tabview, 'height', height + 'px');
  26281. set$8(tabview, 'flex-basis', height + 'px');
  26282. };
  26283. const updateTabviewHeight = (dialogBody, tabview, maxTabHeight) => {
  26284. ancestor(dialogBody, '[role="dialog"]').each(dialog => {
  26285. descendant(dialog, '[role="tablist"]').each(tablist => {
  26286. maxTabHeight.get().map(height => {
  26287. set$8(tabview, 'height', '0');
  26288. set$8(tabview, 'flex-basis', '0');
  26289. return Math.min(height, getMaxTabviewHeight(dialog, tabview, tablist));
  26290. }).each(height => {
  26291. setTabviewHeight(tabview, height);
  26292. });
  26293. });
  26294. });
  26295. };
  26296. const getTabview = dialog => descendant(dialog, '[role="tabpanel"]');
  26297. const smartMode = allTabs => {
  26298. const maxTabHeight = value$2();
  26299. const extraEvents = [
  26300. runOnAttached(comp => {
  26301. const dialog = comp.element;
  26302. getTabview(dialog).each(tabview => {
  26303. set$8(tabview, 'visibility', 'hidden');
  26304. comp.getSystem().getByDom(tabview).toOptional().each(tabviewComp => {
  26305. const heights = measureHeights(allTabs, tabview, tabviewComp);
  26306. const maxTabHeightOpt = getMaxHeight(heights);
  26307. maxTabHeightOpt.fold(maxTabHeight.clear, maxTabHeight.set);
  26308. });
  26309. updateTabviewHeight(dialog, tabview, maxTabHeight);
  26310. remove$6(tabview, 'visibility');
  26311. showTab(allTabs, comp);
  26312. requestAnimationFrame(() => {
  26313. updateTabviewHeight(dialog, tabview, maxTabHeight);
  26314. });
  26315. });
  26316. }),
  26317. run$1(windowResize(), comp => {
  26318. const dialog = comp.element;
  26319. getTabview(dialog).each(tabview => {
  26320. updateTabviewHeight(dialog, tabview, maxTabHeight);
  26321. });
  26322. }),
  26323. run$1(formResizeEvent, (comp, _se) => {
  26324. const dialog = comp.element;
  26325. getTabview(dialog).each(tabview => {
  26326. const oldFocus = active$1(getRootNode(tabview));
  26327. set$8(tabview, 'visibility', 'hidden');
  26328. const oldHeight = getRaw(tabview, 'height').map(h => parseInt(h, 10));
  26329. remove$6(tabview, 'height');
  26330. remove$6(tabview, 'flex-basis');
  26331. const newHeight = tabview.dom.getBoundingClientRect().height;
  26332. const hasGrown = oldHeight.forall(h => newHeight > h);
  26333. if (hasGrown) {
  26334. maxTabHeight.set(newHeight);
  26335. updateTabviewHeight(dialog, tabview, maxTabHeight);
  26336. } else {
  26337. oldHeight.each(h => {
  26338. setTabviewHeight(tabview, h);
  26339. });
  26340. }
  26341. remove$6(tabview, 'visibility');
  26342. oldFocus.each(focus$3);
  26343. });
  26344. })
  26345. ];
  26346. const selectFirst = false;
  26347. return {
  26348. extraEvents,
  26349. selectFirst
  26350. };
  26351. };
  26352. const SendDataToSectionChannel = 'send-data-to-section';
  26353. const SendDataToViewChannel = 'send-data-to-view';
  26354. const renderTabPanel = (spec, dialogData, backstage) => {
  26355. const storedValue = Cell({});
  26356. const updateDataWithForm = form => {
  26357. const formData = Representing.getValue(form);
  26358. const validData = toValidValues(formData).getOr({});
  26359. const currentData = storedValue.get();
  26360. const newData = deepMerge(currentData, validData);
  26361. storedValue.set(newData);
  26362. };
  26363. const setDataOnForm = form => {
  26364. const tabData = storedValue.get();
  26365. Representing.setValue(form, tabData);
  26366. };
  26367. const oldTab = Cell(null);
  26368. const allTabs = map$2(spec.tabs, tab => {
  26369. return {
  26370. value: tab.name,
  26371. dom: {
  26372. tag: 'div',
  26373. classes: ['tox-dialog__body-nav-item']
  26374. },
  26375. components: [text$2(backstage.shared.providers.translate(tab.title))],
  26376. view: () => {
  26377. return [Form.sketch(parts => ({
  26378. dom: {
  26379. tag: 'div',
  26380. classes: ['tox-form']
  26381. },
  26382. components: map$2(tab.items, item => interpretInForm(parts, item, dialogData, backstage)),
  26383. formBehaviours: derive$1([
  26384. Keying.config({
  26385. mode: 'acyclic',
  26386. useTabstopAt: not(isPseudoStop)
  26387. }),
  26388. config('TabView.form.events', [
  26389. runOnAttached(setDataOnForm),
  26390. runOnDetached(updateDataWithForm)
  26391. ]),
  26392. Receiving.config({
  26393. channels: wrapAll([
  26394. {
  26395. key: SendDataToSectionChannel,
  26396. value: { onReceive: updateDataWithForm }
  26397. },
  26398. {
  26399. key: SendDataToViewChannel,
  26400. value: { onReceive: setDataOnForm }
  26401. }
  26402. ])
  26403. })
  26404. ])
  26405. }))];
  26406. }
  26407. };
  26408. });
  26409. const tabMode = smartMode(allTabs);
  26410. return TabSection.sketch({
  26411. dom: {
  26412. tag: 'div',
  26413. classes: ['tox-dialog__body']
  26414. },
  26415. onChangeTab: (section, button, _viewItems) => {
  26416. const name = Representing.getValue(button);
  26417. emitWith(section, formTabChangeEvent, {
  26418. name,
  26419. oldName: oldTab.get()
  26420. });
  26421. oldTab.set(name);
  26422. },
  26423. tabs: allTabs,
  26424. components: [
  26425. TabSection.parts.tabbar({
  26426. dom: {
  26427. tag: 'div',
  26428. classes: ['tox-dialog__body-nav']
  26429. },
  26430. components: [Tabbar.parts.tabs({})],
  26431. markers: {
  26432. tabClass: 'tox-tab',
  26433. selectedClass: 'tox-dialog__body-nav-item--active'
  26434. },
  26435. tabbarBehaviours: derive$1([Tabstopping.config({})])
  26436. }),
  26437. TabSection.parts.tabview({
  26438. dom: {
  26439. tag: 'div',
  26440. classes: ['tox-dialog__body-content']
  26441. }
  26442. })
  26443. ],
  26444. selectFirst: tabMode.selectFirst,
  26445. tabSectionBehaviours: derive$1([
  26446. config('tabpanel', tabMode.extraEvents),
  26447. Keying.config({ mode: 'acyclic' }),
  26448. Composing.config({ find: comp => head(TabSection.getViewItems(comp)) }),
  26449. RepresentingConfigs.withComp(Optional.none(), tsection => {
  26450. tsection.getSystem().broadcastOn([SendDataToSectionChannel], {});
  26451. return storedValue.get();
  26452. }, (tsection, value) => {
  26453. storedValue.set(value);
  26454. tsection.getSystem().broadcastOn([SendDataToViewChannel], {});
  26455. })
  26456. ])
  26457. });
  26458. };
  26459. const dialogChannel = generate$6('update-dialog');
  26460. const titleChannel = generate$6('update-title');
  26461. const bodyChannel = generate$6('update-body');
  26462. const footerChannel = generate$6('update-footer');
  26463. const bodySendMessageChannel = generate$6('body-send-message');
  26464. const renderBody = (spec, dialogId, contentId, backstage, ariaAttrs) => {
  26465. const renderComponents = incoming => {
  26466. const body = incoming.body;
  26467. switch (body.type) {
  26468. case 'tabpanel': {
  26469. return [renderTabPanel(body, incoming.initialData, backstage)];
  26470. }
  26471. default: {
  26472. return [renderBodyPanel(body, incoming.initialData, backstage)];
  26473. }
  26474. }
  26475. };
  26476. const updateState = (_comp, incoming) => Optional.some({ isTabPanel: () => incoming.body.type === 'tabpanel' });
  26477. const ariaAttributes = { 'aria-live': 'polite' };
  26478. return {
  26479. dom: {
  26480. tag: 'div',
  26481. classes: ['tox-dialog__content-js'],
  26482. attributes: {
  26483. ...contentId.map(x => ({ id: x })).getOr({}),
  26484. ...ariaAttrs ? ariaAttributes : {}
  26485. }
  26486. },
  26487. components: [],
  26488. behaviours: derive$1([
  26489. ComposingConfigs.childAt(0),
  26490. Reflecting.config({
  26491. channel: `${ bodyChannel }-${ dialogId }`,
  26492. updateState,
  26493. renderComponents,
  26494. initialData: spec
  26495. })
  26496. ])
  26497. };
  26498. };
  26499. const renderInlineBody = (spec, dialogId, contentId, backstage, ariaAttrs) => renderBody(spec, dialogId, Optional.some(contentId), backstage, ariaAttrs);
  26500. const renderModalBody = (spec, dialogId, backstage) => {
  26501. const bodySpec = renderBody(spec, dialogId, Optional.none(), backstage, false);
  26502. return ModalDialog.parts.body(bodySpec);
  26503. };
  26504. const renderIframeBody = spec => {
  26505. const bodySpec = {
  26506. dom: {
  26507. tag: 'div',
  26508. classes: ['tox-dialog__content-js']
  26509. },
  26510. components: [{
  26511. dom: {
  26512. tag: 'div',
  26513. classes: ['tox-dialog__body-iframe']
  26514. },
  26515. components: [craft({
  26516. dom: {
  26517. tag: 'iframe',
  26518. attributes: { src: spec.url }
  26519. },
  26520. behaviours: derive$1([
  26521. Tabstopping.config({}),
  26522. Focusing.config({})
  26523. ])
  26524. })]
  26525. }],
  26526. behaviours: derive$1([Keying.config({
  26527. mode: 'acyclic',
  26528. useTabstopAt: not(isPseudoStop)
  26529. })])
  26530. };
  26531. return ModalDialog.parts.body(bodySpec);
  26532. };
  26533. function _typeof(obj) {
  26534. '@babel/helpers - typeof';
  26535. return _typeof = 'function' == typeof Symbol && 'symbol' == typeof Symbol.iterator ? function (obj) {
  26536. return typeof obj;
  26537. } : function (obj) {
  26538. return obj && 'function' == typeof Symbol && obj.constructor === Symbol && obj !== Symbol.prototype ? 'symbol' : typeof obj;
  26539. }, _typeof(obj);
  26540. }
  26541. function _setPrototypeOf(o, p) {
  26542. _setPrototypeOf = Object.setPrototypeOf || function _setPrototypeOf(o, p) {
  26543. o.__proto__ = p;
  26544. return o;
  26545. };
  26546. return _setPrototypeOf(o, p);
  26547. }
  26548. function _isNativeReflectConstruct() {
  26549. if (typeof Reflect === 'undefined' || !Reflect.construct)
  26550. return false;
  26551. if (Reflect.construct.sham)
  26552. return false;
  26553. if (typeof Proxy === 'function')
  26554. return true;
  26555. try {
  26556. Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {
  26557. }));
  26558. return true;
  26559. } catch (e) {
  26560. return false;
  26561. }
  26562. }
  26563. function _construct(Parent, args, Class) {
  26564. if (_isNativeReflectConstruct()) {
  26565. _construct = Reflect.construct;
  26566. } else {
  26567. _construct = function _construct(Parent, args, Class) {
  26568. var a = [null];
  26569. a.push.apply(a, args);
  26570. var Constructor = Function.bind.apply(Parent, a);
  26571. var instance = new Constructor();
  26572. if (Class)
  26573. _setPrototypeOf(instance, Class.prototype);
  26574. return instance;
  26575. };
  26576. }
  26577. return _construct.apply(null, arguments);
  26578. }
  26579. function _toConsumableArray(arr) {
  26580. return _arrayWithoutHoles(arr) || _iterableToArray(arr) || _unsupportedIterableToArray(arr) || _nonIterableSpread();
  26581. }
  26582. function _arrayWithoutHoles(arr) {
  26583. if (Array.isArray(arr))
  26584. return _arrayLikeToArray(arr);
  26585. }
  26586. function _iterableToArray(iter) {
  26587. if (typeof Symbol !== 'undefined' && iter[Symbol.iterator] != null || iter['@@iterator'] != null)
  26588. return Array.from(iter);
  26589. }
  26590. function _unsupportedIterableToArray(o, minLen) {
  26591. if (!o)
  26592. return;
  26593. if (typeof o === 'string')
  26594. return _arrayLikeToArray(o, minLen);
  26595. var n = Object.prototype.toString.call(o).slice(8, -1);
  26596. if (n === 'Object' && o.constructor)
  26597. n = o.constructor.name;
  26598. if (n === 'Map' || n === 'Set')
  26599. return Array.from(o);
  26600. if (n === 'Arguments' || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n))
  26601. return _arrayLikeToArray(o, minLen);
  26602. }
  26603. function _arrayLikeToArray(arr, len) {
  26604. if (len == null || len > arr.length)
  26605. len = arr.length;
  26606. for (var i = 0, arr2 = new Array(len); i < len; i++)
  26607. arr2[i] = arr[i];
  26608. return arr2;
  26609. }
  26610. function _nonIterableSpread() {
  26611. throw new TypeError('Invalid attempt to spread non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.');
  26612. }
  26613. var hasOwnProperty = Object.hasOwnProperty, setPrototypeOf = Object.setPrototypeOf, isFrozen = Object.isFrozen, getPrototypeOf = Object.getPrototypeOf, getOwnPropertyDescriptor = Object.getOwnPropertyDescriptor;
  26614. var freeze = Object.freeze, seal = Object.seal, create = Object.create;
  26615. var _ref = typeof Reflect !== 'undefined' && Reflect, apply = _ref.apply, construct = _ref.construct;
  26616. if (!apply) {
  26617. apply = function apply(fun, thisValue, args) {
  26618. return fun.apply(thisValue, args);
  26619. };
  26620. }
  26621. if (!freeze) {
  26622. freeze = function freeze(x) {
  26623. return x;
  26624. };
  26625. }
  26626. if (!seal) {
  26627. seal = function seal(x) {
  26628. return x;
  26629. };
  26630. }
  26631. if (!construct) {
  26632. construct = function construct(Func, args) {
  26633. return _construct(Func, _toConsumableArray(args));
  26634. };
  26635. }
  26636. var arrayForEach = unapply(Array.prototype.forEach);
  26637. var arrayPop = unapply(Array.prototype.pop);
  26638. var arrayPush = unapply(Array.prototype.push);
  26639. var stringToLowerCase = unapply(String.prototype.toLowerCase);
  26640. var stringMatch = unapply(String.prototype.match);
  26641. var stringReplace = unapply(String.prototype.replace);
  26642. var stringIndexOf = unapply(String.prototype.indexOf);
  26643. var stringTrim = unapply(String.prototype.trim);
  26644. var regExpTest = unapply(RegExp.prototype.test);
  26645. var typeErrorCreate = unconstruct(TypeError);
  26646. function unapply(func) {
  26647. return function (thisArg) {
  26648. for (var _len = arguments.length, args = new Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) {
  26649. args[_key - 1] = arguments[_key];
  26650. }
  26651. return apply(func, thisArg, args);
  26652. };
  26653. }
  26654. function unconstruct(func) {
  26655. return function () {
  26656. for (var _len2 = arguments.length, args = new Array(_len2), _key2 = 0; _key2 < _len2; _key2++) {
  26657. args[_key2] = arguments[_key2];
  26658. }
  26659. return construct(func, args);
  26660. };
  26661. }
  26662. function addToSet(set, array) {
  26663. if (setPrototypeOf) {
  26664. setPrototypeOf(set, null);
  26665. }
  26666. var l = array.length;
  26667. while (l--) {
  26668. var element = array[l];
  26669. if (typeof element === 'string') {
  26670. var lcElement = stringToLowerCase(element);
  26671. if (lcElement !== element) {
  26672. if (!isFrozen(array)) {
  26673. array[l] = lcElement;
  26674. }
  26675. element = lcElement;
  26676. }
  26677. }
  26678. set[element] = true;
  26679. }
  26680. return set;
  26681. }
  26682. function clone(object) {
  26683. var newObject = create(null);
  26684. var property;
  26685. for (property in object) {
  26686. if (apply(hasOwnProperty, object, [property])) {
  26687. newObject[property] = object[property];
  26688. }
  26689. }
  26690. return newObject;
  26691. }
  26692. function lookupGetter(object, prop) {
  26693. while (object !== null) {
  26694. var desc = getOwnPropertyDescriptor(object, prop);
  26695. if (desc) {
  26696. if (desc.get) {
  26697. return unapply(desc.get);
  26698. }
  26699. if (typeof desc.value === 'function') {
  26700. return unapply(desc.value);
  26701. }
  26702. }
  26703. object = getPrototypeOf(object);
  26704. }
  26705. function fallbackValue(element) {
  26706. console.warn('fallback value for', element);
  26707. return null;
  26708. }
  26709. return fallbackValue;
  26710. }
  26711. var html$1 = freeze([
  26712. 'a',
  26713. 'abbr',
  26714. 'acronym',
  26715. 'address',
  26716. 'area',
  26717. 'article',
  26718. 'aside',
  26719. 'audio',
  26720. 'b',
  26721. 'bdi',
  26722. 'bdo',
  26723. 'big',
  26724. 'blink',
  26725. 'blockquote',
  26726. 'body',
  26727. 'br',
  26728. 'button',
  26729. 'canvas',
  26730. 'caption',
  26731. 'center',
  26732. 'cite',
  26733. 'code',
  26734. 'col',
  26735. 'colgroup',
  26736. 'content',
  26737. 'data',
  26738. 'datalist',
  26739. 'dd',
  26740. 'decorator',
  26741. 'del',
  26742. 'details',
  26743. 'dfn',
  26744. 'dialog',
  26745. 'dir',
  26746. 'div',
  26747. 'dl',
  26748. 'dt',
  26749. 'element',
  26750. 'em',
  26751. 'fieldset',
  26752. 'figcaption',
  26753. 'figure',
  26754. 'font',
  26755. 'footer',
  26756. 'form',
  26757. 'h1',
  26758. 'h2',
  26759. 'h3',
  26760. 'h4',
  26761. 'h5',
  26762. 'h6',
  26763. 'head',
  26764. 'header',
  26765. 'hgroup',
  26766. 'hr',
  26767. 'html',
  26768. 'i',
  26769. 'img',
  26770. 'input',
  26771. 'ins',
  26772. 'kbd',
  26773. 'label',
  26774. 'legend',
  26775. 'li',
  26776. 'main',
  26777. 'map',
  26778. 'mark',
  26779. 'marquee',
  26780. 'menu',
  26781. 'menuitem',
  26782. 'meter',
  26783. 'nav',
  26784. 'nobr',
  26785. 'ol',
  26786. 'optgroup',
  26787. 'option',
  26788. 'output',
  26789. 'p',
  26790. 'picture',
  26791. 'pre',
  26792. 'progress',
  26793. 'q',
  26794. 'rp',
  26795. 'rt',
  26796. 'ruby',
  26797. 's',
  26798. 'samp',
  26799. 'section',
  26800. 'select',
  26801. 'shadow',
  26802. 'small',
  26803. 'source',
  26804. 'spacer',
  26805. 'span',
  26806. 'strike',
  26807. 'strong',
  26808. 'style',
  26809. 'sub',
  26810. 'summary',
  26811. 'sup',
  26812. 'table',
  26813. 'tbody',
  26814. 'td',
  26815. 'template',
  26816. 'textarea',
  26817. 'tfoot',
  26818. 'th',
  26819. 'thead',
  26820. 'time',
  26821. 'tr',
  26822. 'track',
  26823. 'tt',
  26824. 'u',
  26825. 'ul',
  26826. 'var',
  26827. 'video',
  26828. 'wbr'
  26829. ]);
  26830. var svg$1 = freeze([
  26831. 'svg',
  26832. 'a',
  26833. 'altglyph',
  26834. 'altglyphdef',
  26835. 'altglyphitem',
  26836. 'animatecolor',
  26837. 'animatemotion',
  26838. 'animatetransform',
  26839. 'circle',
  26840. 'clippath',
  26841. 'defs',
  26842. 'desc',
  26843. 'ellipse',
  26844. 'filter',
  26845. 'font',
  26846. 'g',
  26847. 'glyph',
  26848. 'glyphref',
  26849. 'hkern',
  26850. 'image',
  26851. 'line',
  26852. 'lineargradient',
  26853. 'marker',
  26854. 'mask',
  26855. 'metadata',
  26856. 'mpath',
  26857. 'path',
  26858. 'pattern',
  26859. 'polygon',
  26860. 'polyline',
  26861. 'radialgradient',
  26862. 'rect',
  26863. 'stop',
  26864. 'style',
  26865. 'switch',
  26866. 'symbol',
  26867. 'text',
  26868. 'textpath',
  26869. 'title',
  26870. 'tref',
  26871. 'tspan',
  26872. 'view',
  26873. 'vkern'
  26874. ]);
  26875. var svgFilters = freeze([
  26876. 'feBlend',
  26877. 'feColorMatrix',
  26878. 'feComponentTransfer',
  26879. 'feComposite',
  26880. 'feConvolveMatrix',
  26881. 'feDiffuseLighting',
  26882. 'feDisplacementMap',
  26883. 'feDistantLight',
  26884. 'feFlood',
  26885. 'feFuncA',
  26886. 'feFuncB',
  26887. 'feFuncG',
  26888. 'feFuncR',
  26889. 'feGaussianBlur',
  26890. 'feImage',
  26891. 'feMerge',
  26892. 'feMergeNode',
  26893. 'feMorphology',
  26894. 'feOffset',
  26895. 'fePointLight',
  26896. 'feSpecularLighting',
  26897. 'feSpotLight',
  26898. 'feTile',
  26899. 'feTurbulence'
  26900. ]);
  26901. var svgDisallowed = freeze([
  26902. 'animate',
  26903. 'color-profile',
  26904. 'cursor',
  26905. 'discard',
  26906. 'fedropshadow',
  26907. 'font-face',
  26908. 'font-face-format',
  26909. 'font-face-name',
  26910. 'font-face-src',
  26911. 'font-face-uri',
  26912. 'foreignobject',
  26913. 'hatch',
  26914. 'hatchpath',
  26915. 'mesh',
  26916. 'meshgradient',
  26917. 'meshpatch',
  26918. 'meshrow',
  26919. 'missing-glyph',
  26920. 'script',
  26921. 'set',
  26922. 'solidcolor',
  26923. 'unknown',
  26924. 'use'
  26925. ]);
  26926. var mathMl$1 = freeze([
  26927. 'math',
  26928. 'menclose',
  26929. 'merror',
  26930. 'mfenced',
  26931. 'mfrac',
  26932. 'mglyph',
  26933. 'mi',
  26934. 'mlabeledtr',
  26935. 'mmultiscripts',
  26936. 'mn',
  26937. 'mo',
  26938. 'mover',
  26939. 'mpadded',
  26940. 'mphantom',
  26941. 'mroot',
  26942. 'mrow',
  26943. 'ms',
  26944. 'mspace',
  26945. 'msqrt',
  26946. 'mstyle',
  26947. 'msub',
  26948. 'msup',
  26949. 'msubsup',
  26950. 'mtable',
  26951. 'mtd',
  26952. 'mtext',
  26953. 'mtr',
  26954. 'munder',
  26955. 'munderover'
  26956. ]);
  26957. var mathMlDisallowed = freeze([
  26958. 'maction',
  26959. 'maligngroup',
  26960. 'malignmark',
  26961. 'mlongdiv',
  26962. 'mscarries',
  26963. 'mscarry',
  26964. 'msgroup',
  26965. 'mstack',
  26966. 'msline',
  26967. 'msrow',
  26968. 'semantics',
  26969. 'annotation',
  26970. 'annotation-xml',
  26971. 'mprescripts',
  26972. 'none'
  26973. ]);
  26974. var text = freeze(['#text']);
  26975. var html = freeze([
  26976. 'accept',
  26977. 'action',
  26978. 'align',
  26979. 'alt',
  26980. 'autocapitalize',
  26981. 'autocomplete',
  26982. 'autopictureinpicture',
  26983. 'autoplay',
  26984. 'background',
  26985. 'bgcolor',
  26986. 'border',
  26987. 'capture',
  26988. 'cellpadding',
  26989. 'cellspacing',
  26990. 'checked',
  26991. 'cite',
  26992. 'class',
  26993. 'clear',
  26994. 'color',
  26995. 'cols',
  26996. 'colspan',
  26997. 'controls',
  26998. 'controlslist',
  26999. 'coords',
  27000. 'crossorigin',
  27001. 'datetime',
  27002. 'decoding',
  27003. 'default',
  27004. 'dir',
  27005. 'disabled',
  27006. 'disablepictureinpicture',
  27007. 'disableremoteplayback',
  27008. 'download',
  27009. 'draggable',
  27010. 'enctype',
  27011. 'enterkeyhint',
  27012. 'face',
  27013. 'for',
  27014. 'headers',
  27015. 'height',
  27016. 'hidden',
  27017. 'high',
  27018. 'href',
  27019. 'hreflang',
  27020. 'id',
  27021. 'inputmode',
  27022. 'integrity',
  27023. 'ismap',
  27024. 'kind',
  27025. 'label',
  27026. 'lang',
  27027. 'list',
  27028. 'loading',
  27029. 'loop',
  27030. 'low',
  27031. 'max',
  27032. 'maxlength',
  27033. 'media',
  27034. 'method',
  27035. 'min',
  27036. 'minlength',
  27037. 'multiple',
  27038. 'muted',
  27039. 'name',
  27040. 'nonce',
  27041. 'noshade',
  27042. 'novalidate',
  27043. 'nowrap',
  27044. 'open',
  27045. 'optimum',
  27046. 'pattern',
  27047. 'placeholder',
  27048. 'playsinline',
  27049. 'poster',
  27050. 'preload',
  27051. 'pubdate',
  27052. 'radiogroup',
  27053. 'readonly',
  27054. 'rel',
  27055. 'required',
  27056. 'rev',
  27057. 'reversed',
  27058. 'role',
  27059. 'rows',
  27060. 'rowspan',
  27061. 'spellcheck',
  27062. 'scope',
  27063. 'selected',
  27064. 'shape',
  27065. 'size',
  27066. 'sizes',
  27067. 'span',
  27068. 'srclang',
  27069. 'start',
  27070. 'src',
  27071. 'srcset',
  27072. 'step',
  27073. 'style',
  27074. 'summary',
  27075. 'tabindex',
  27076. 'title',
  27077. 'translate',
  27078. 'type',
  27079. 'usemap',
  27080. 'valign',
  27081. 'value',
  27082. 'width',
  27083. 'xmlns',
  27084. 'slot'
  27085. ]);
  27086. var svg = freeze([
  27087. 'accent-height',
  27088. 'accumulate',
  27089. 'additive',
  27090. 'alignment-baseline',
  27091. 'ascent',
  27092. 'attributename',
  27093. 'attributetype',
  27094. 'azimuth',
  27095. 'basefrequency',
  27096. 'baseline-shift',
  27097. 'begin',
  27098. 'bias',
  27099. 'by',
  27100. 'class',
  27101. 'clip',
  27102. 'clippathunits',
  27103. 'clip-path',
  27104. 'clip-rule',
  27105. 'color',
  27106. 'color-interpolation',
  27107. 'color-interpolation-filters',
  27108. 'color-profile',
  27109. 'color-rendering',
  27110. 'cx',
  27111. 'cy',
  27112. 'd',
  27113. 'dx',
  27114. 'dy',
  27115. 'diffuseconstant',
  27116. 'direction',
  27117. 'display',
  27118. 'divisor',
  27119. 'dur',
  27120. 'edgemode',
  27121. 'elevation',
  27122. 'end',
  27123. 'fill',
  27124. 'fill-opacity',
  27125. 'fill-rule',
  27126. 'filter',
  27127. 'filterunits',
  27128. 'flood-color',
  27129. 'flood-opacity',
  27130. 'font-family',
  27131. 'font-size',
  27132. 'font-size-adjust',
  27133. 'font-stretch',
  27134. 'font-style',
  27135. 'font-variant',
  27136. 'font-weight',
  27137. 'fx',
  27138. 'fy',
  27139. 'g1',
  27140. 'g2',
  27141. 'glyph-name',
  27142. 'glyphref',
  27143. 'gradientunits',
  27144. 'gradienttransform',
  27145. 'height',
  27146. 'href',
  27147. 'id',
  27148. 'image-rendering',
  27149. 'in',
  27150. 'in2',
  27151. 'k',
  27152. 'k1',
  27153. 'k2',
  27154. 'k3',
  27155. 'k4',
  27156. 'kerning',
  27157. 'keypoints',
  27158. 'keysplines',
  27159. 'keytimes',
  27160. 'lang',
  27161. 'lengthadjust',
  27162. 'letter-spacing',
  27163. 'kernelmatrix',
  27164. 'kernelunitlength',
  27165. 'lighting-color',
  27166. 'local',
  27167. 'marker-end',
  27168. 'marker-mid',
  27169. 'marker-start',
  27170. 'markerheight',
  27171. 'markerunits',
  27172. 'markerwidth',
  27173. 'maskcontentunits',
  27174. 'maskunits',
  27175. 'max',
  27176. 'mask',
  27177. 'media',
  27178. 'method',
  27179. 'mode',
  27180. 'min',
  27181. 'name',
  27182. 'numoctaves',
  27183. 'offset',
  27184. 'operator',
  27185. 'opacity',
  27186. 'order',
  27187. 'orient',
  27188. 'orientation',
  27189. 'origin',
  27190. 'overflow',
  27191. 'paint-order',
  27192. 'path',
  27193. 'pathlength',
  27194. 'patterncontentunits',
  27195. 'patterntransform',
  27196. 'patternunits',
  27197. 'points',
  27198. 'preservealpha',
  27199. 'preserveaspectratio',
  27200. 'primitiveunits',
  27201. 'r',
  27202. 'rx',
  27203. 'ry',
  27204. 'radius',
  27205. 'refx',
  27206. 'refy',
  27207. 'repeatcount',
  27208. 'repeatdur',
  27209. 'restart',
  27210. 'result',
  27211. 'rotate',
  27212. 'scale',
  27213. 'seed',
  27214. 'shape-rendering',
  27215. 'specularconstant',
  27216. 'specularexponent',
  27217. 'spreadmethod',
  27218. 'startoffset',
  27219. 'stddeviation',
  27220. 'stitchtiles',
  27221. 'stop-color',
  27222. 'stop-opacity',
  27223. 'stroke-dasharray',
  27224. 'stroke-dashoffset',
  27225. 'stroke-linecap',
  27226. 'stroke-linejoin',
  27227. 'stroke-miterlimit',
  27228. 'stroke-opacity',
  27229. 'stroke',
  27230. 'stroke-width',
  27231. 'style',
  27232. 'surfacescale',
  27233. 'systemlanguage',
  27234. 'tabindex',
  27235. 'targetx',
  27236. 'targety',
  27237. 'transform',
  27238. 'transform-origin',
  27239. 'text-anchor',
  27240. 'text-decoration',
  27241. 'text-rendering',
  27242. 'textlength',
  27243. 'type',
  27244. 'u1',
  27245. 'u2',
  27246. 'unicode',
  27247. 'values',
  27248. 'viewbox',
  27249. 'visibility',
  27250. 'version',
  27251. 'vert-adv-y',
  27252. 'vert-origin-x',
  27253. 'vert-origin-y',
  27254. 'width',
  27255. 'word-spacing',
  27256. 'wrap',
  27257. 'writing-mode',
  27258. 'xchannelselector',
  27259. 'ychannelselector',
  27260. 'x',
  27261. 'x1',
  27262. 'x2',
  27263. 'xmlns',
  27264. 'y',
  27265. 'y1',
  27266. 'y2',
  27267. 'z',
  27268. 'zoomandpan'
  27269. ]);
  27270. var mathMl = freeze([
  27271. 'accent',
  27272. 'accentunder',
  27273. 'align',
  27274. 'bevelled',
  27275. 'close',
  27276. 'columnsalign',
  27277. 'columnlines',
  27278. 'columnspan',
  27279. 'denomalign',
  27280. 'depth',
  27281. 'dir',
  27282. 'display',
  27283. 'displaystyle',
  27284. 'encoding',
  27285. 'fence',
  27286. 'frame',
  27287. 'height',
  27288. 'href',
  27289. 'id',
  27290. 'largeop',
  27291. 'length',
  27292. 'linethickness',
  27293. 'lspace',
  27294. 'lquote',
  27295. 'mathbackground',
  27296. 'mathcolor',
  27297. 'mathsize',
  27298. 'mathvariant',
  27299. 'maxsize',
  27300. 'minsize',
  27301. 'movablelimits',
  27302. 'notation',
  27303. 'numalign',
  27304. 'open',
  27305. 'rowalign',
  27306. 'rowlines',
  27307. 'rowspacing',
  27308. 'rowspan',
  27309. 'rspace',
  27310. 'rquote',
  27311. 'scriptlevel',
  27312. 'scriptminsize',
  27313. 'scriptsizemultiplier',
  27314. 'selection',
  27315. 'separator',
  27316. 'separators',
  27317. 'stretchy',
  27318. 'subscriptshift',
  27319. 'supscriptshift',
  27320. 'symmetric',
  27321. 'voffset',
  27322. 'width',
  27323. 'xmlns'
  27324. ]);
  27325. var xml = freeze([
  27326. 'xlink:href',
  27327. 'xml:id',
  27328. 'xlink:title',
  27329. 'xml:space',
  27330. 'xmlns:xlink'
  27331. ]);
  27332. var MUSTACHE_EXPR = seal(/\{\{[\w\W]*|[\w\W]*\}\}/gm);
  27333. var ERB_EXPR = seal(/<%[\w\W]*|[\w\W]*%>/gm);
  27334. var DATA_ATTR = seal(/^data-[\-\w.\u00B7-\uFFFF]/);
  27335. var ARIA_ATTR = seal(/^aria-[\-\w]+$/);
  27336. var IS_ALLOWED_URI = seal(/^(?:(?:(?:f|ht)tps?|mailto|tel|callto|cid|xmpp):|[^a-z]|[a-z+.\-]+(?:[^a-z+.\-:]|$))/i);
  27337. var IS_SCRIPT_OR_DATA = seal(/^(?:\w+script|data):/i);
  27338. var ATTR_WHITESPACE = seal(/[\u0000-\u0020\u00A0\u1680\u180E\u2000-\u2029\u205F\u3000]/g);
  27339. var DOCTYPE_NAME = seal(/^html$/i);
  27340. var getGlobal = function getGlobal() {
  27341. return typeof window === 'undefined' ? null : window;
  27342. };
  27343. var _createTrustedTypesPolicy = function _createTrustedTypesPolicy(trustedTypes, document) {
  27344. if (_typeof(trustedTypes) !== 'object' || typeof trustedTypes.createPolicy !== 'function') {
  27345. return null;
  27346. }
  27347. var suffix = null;
  27348. var ATTR_NAME = 'data-tt-policy-suffix';
  27349. if (document.currentScript && document.currentScript.hasAttribute(ATTR_NAME)) {
  27350. suffix = document.currentScript.getAttribute(ATTR_NAME);
  27351. }
  27352. var policyName = 'dompurify' + (suffix ? '#' + suffix : '');
  27353. try {
  27354. return trustedTypes.createPolicy(policyName, {
  27355. createHTML: function createHTML(html) {
  27356. return html;
  27357. }
  27358. });
  27359. } catch (_) {
  27360. console.warn('TrustedTypes policy ' + policyName + ' could not be created.');
  27361. return null;
  27362. }
  27363. };
  27364. function createDOMPurify() {
  27365. var window = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : getGlobal();
  27366. var DOMPurify = function DOMPurify(root) {
  27367. return createDOMPurify(root);
  27368. };
  27369. DOMPurify.version = '2.3.8';
  27370. DOMPurify.removed = [];
  27371. if (!window || !window.document || window.document.nodeType !== 9) {
  27372. DOMPurify.isSupported = false;
  27373. return DOMPurify;
  27374. }
  27375. var originalDocument = window.document;
  27376. var document = window.document;
  27377. 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;
  27378. var ElementPrototype = Element.prototype;
  27379. var cloneNode = lookupGetter(ElementPrototype, 'cloneNode');
  27380. var getNextSibling = lookupGetter(ElementPrototype, 'nextSibling');
  27381. var getChildNodes = lookupGetter(ElementPrototype, 'childNodes');
  27382. var getParentNode = lookupGetter(ElementPrototype, 'parentNode');
  27383. if (typeof HTMLTemplateElement === 'function') {
  27384. var template = document.createElement('template');
  27385. if (template.content && template.content.ownerDocument) {
  27386. document = template.content.ownerDocument;
  27387. }
  27388. }
  27389. var trustedTypesPolicy = _createTrustedTypesPolicy(trustedTypes, originalDocument);
  27390. var emptyHTML = trustedTypesPolicy ? trustedTypesPolicy.createHTML('') : '';
  27391. var _document = document, implementation = _document.implementation, createNodeIterator = _document.createNodeIterator, createDocumentFragment = _document.createDocumentFragment, getElementsByTagName = _document.getElementsByTagName;
  27392. var importNode = originalDocument.importNode;
  27393. var documentMode = {};
  27394. try {
  27395. documentMode = clone(document).documentMode ? document.documentMode : {};
  27396. } catch (_) {
  27397. }
  27398. var hooks = {};
  27399. DOMPurify.isSupported = typeof getParentNode === 'function' && implementation && typeof implementation.createHTMLDocument !== 'undefined' && documentMode !== 9;
  27400. 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;
  27401. var IS_ALLOWED_URI$1 = IS_ALLOWED_URI;
  27402. var ALLOWED_TAGS = null;
  27403. var DEFAULT_ALLOWED_TAGS = addToSet({}, [].concat(_toConsumableArray(html$1), _toConsumableArray(svg$1), _toConsumableArray(svgFilters), _toConsumableArray(mathMl$1), _toConsumableArray(text)));
  27404. var ALLOWED_ATTR = null;
  27405. var DEFAULT_ALLOWED_ATTR = addToSet({}, [].concat(_toConsumableArray(html), _toConsumableArray(svg), _toConsumableArray(mathMl), _toConsumableArray(xml)));
  27406. var CUSTOM_ELEMENT_HANDLING = Object.seal(Object.create(null, {
  27407. tagNameCheck: {
  27408. writable: true,
  27409. configurable: false,
  27410. enumerable: true,
  27411. value: null
  27412. },
  27413. attributeNameCheck: {
  27414. writable: true,
  27415. configurable: false,
  27416. enumerable: true,
  27417. value: null
  27418. },
  27419. allowCustomizedBuiltInElements: {
  27420. writable: true,
  27421. configurable: false,
  27422. enumerable: true,
  27423. value: false
  27424. }
  27425. }));
  27426. var FORBID_TAGS = null;
  27427. var FORBID_ATTR = null;
  27428. var ALLOW_ARIA_ATTR = true;
  27429. var ALLOW_DATA_ATTR = true;
  27430. var ALLOW_UNKNOWN_PROTOCOLS = false;
  27431. var SAFE_FOR_TEMPLATES = false;
  27432. var WHOLE_DOCUMENT = false;
  27433. var SET_CONFIG = false;
  27434. var FORCE_BODY = false;
  27435. var RETURN_DOM = false;
  27436. var RETURN_DOM_FRAGMENT = false;
  27437. var RETURN_TRUSTED_TYPE = false;
  27438. var SANITIZE_DOM = true;
  27439. var KEEP_CONTENT = true;
  27440. var IN_PLACE = false;
  27441. var USE_PROFILES = {};
  27442. var FORBID_CONTENTS = null;
  27443. var DEFAULT_FORBID_CONTENTS = addToSet({}, [
  27444. 'annotation-xml',
  27445. 'audio',
  27446. 'colgroup',
  27447. 'desc',
  27448. 'foreignobject',
  27449. 'head',
  27450. 'iframe',
  27451. 'math',
  27452. 'mi',
  27453. 'mn',
  27454. 'mo',
  27455. 'ms',
  27456. 'mtext',
  27457. 'noembed',
  27458. 'noframes',
  27459. 'noscript',
  27460. 'plaintext',
  27461. 'script',
  27462. 'style',
  27463. 'svg',
  27464. 'template',
  27465. 'thead',
  27466. 'title',
  27467. 'video',
  27468. 'xmp'
  27469. ]);
  27470. var DATA_URI_TAGS = null;
  27471. var DEFAULT_DATA_URI_TAGS = addToSet({}, [
  27472. 'audio',
  27473. 'video',
  27474. 'img',
  27475. 'source',
  27476. 'image',
  27477. 'track'
  27478. ]);
  27479. var URI_SAFE_ATTRIBUTES = null;
  27480. var DEFAULT_URI_SAFE_ATTRIBUTES = addToSet({}, [
  27481. 'alt',
  27482. 'class',
  27483. 'for',
  27484. 'id',
  27485. 'label',
  27486. 'name',
  27487. 'pattern',
  27488. 'placeholder',
  27489. 'role',
  27490. 'summary',
  27491. 'title',
  27492. 'value',
  27493. 'style',
  27494. 'xmlns'
  27495. ]);
  27496. var MATHML_NAMESPACE = 'http://www.w3.org/1998/Math/MathML';
  27497. var SVG_NAMESPACE = 'http://www.w3.org/2000/svg';
  27498. var HTML_NAMESPACE = 'http://www.w3.org/1999/xhtml';
  27499. var NAMESPACE = HTML_NAMESPACE;
  27500. var IS_EMPTY_INPUT = false;
  27501. var PARSER_MEDIA_TYPE;
  27502. var SUPPORTED_PARSER_MEDIA_TYPES = [
  27503. 'application/xhtml+xml',
  27504. 'text/html'
  27505. ];
  27506. var DEFAULT_PARSER_MEDIA_TYPE = 'text/html';
  27507. var transformCaseFunc;
  27508. var CONFIG = null;
  27509. var formElement = document.createElement('form');
  27510. var isRegexOrFunction = function isRegexOrFunction(testValue) {
  27511. return testValue instanceof RegExp || testValue instanceof Function;
  27512. };
  27513. var _parseConfig = function _parseConfig(cfg) {
  27514. if (CONFIG && CONFIG === cfg) {
  27515. return;
  27516. }
  27517. if (!cfg || _typeof(cfg) !== 'object') {
  27518. cfg = {};
  27519. }
  27520. cfg = clone(cfg);
  27521. ALLOWED_TAGS = 'ALLOWED_TAGS' in cfg ? addToSet({}, cfg.ALLOWED_TAGS) : DEFAULT_ALLOWED_TAGS;
  27522. ALLOWED_ATTR = 'ALLOWED_ATTR' in cfg ? addToSet({}, cfg.ALLOWED_ATTR) : DEFAULT_ALLOWED_ATTR;
  27523. URI_SAFE_ATTRIBUTES = 'ADD_URI_SAFE_ATTR' in cfg ? addToSet(clone(DEFAULT_URI_SAFE_ATTRIBUTES), cfg.ADD_URI_SAFE_ATTR) : DEFAULT_URI_SAFE_ATTRIBUTES;
  27524. DATA_URI_TAGS = 'ADD_DATA_URI_TAGS' in cfg ? addToSet(clone(DEFAULT_DATA_URI_TAGS), cfg.ADD_DATA_URI_TAGS) : DEFAULT_DATA_URI_TAGS;
  27525. FORBID_CONTENTS = 'FORBID_CONTENTS' in cfg ? addToSet({}, cfg.FORBID_CONTENTS) : DEFAULT_FORBID_CONTENTS;
  27526. FORBID_TAGS = 'FORBID_TAGS' in cfg ? addToSet({}, cfg.FORBID_TAGS) : {};
  27527. FORBID_ATTR = 'FORBID_ATTR' in cfg ? addToSet({}, cfg.FORBID_ATTR) : {};
  27528. USE_PROFILES = 'USE_PROFILES' in cfg ? cfg.USE_PROFILES : false;
  27529. ALLOW_ARIA_ATTR = cfg.ALLOW_ARIA_ATTR !== false;
  27530. ALLOW_DATA_ATTR = cfg.ALLOW_DATA_ATTR !== false;
  27531. ALLOW_UNKNOWN_PROTOCOLS = cfg.ALLOW_UNKNOWN_PROTOCOLS || false;
  27532. SAFE_FOR_TEMPLATES = cfg.SAFE_FOR_TEMPLATES || false;
  27533. WHOLE_DOCUMENT = cfg.WHOLE_DOCUMENT || false;
  27534. RETURN_DOM = cfg.RETURN_DOM || false;
  27535. RETURN_DOM_FRAGMENT = cfg.RETURN_DOM_FRAGMENT || false;
  27536. RETURN_TRUSTED_TYPE = cfg.RETURN_TRUSTED_TYPE || false;
  27537. FORCE_BODY = cfg.FORCE_BODY || false;
  27538. SANITIZE_DOM = cfg.SANITIZE_DOM !== false;
  27539. KEEP_CONTENT = cfg.KEEP_CONTENT !== false;
  27540. IN_PLACE = cfg.IN_PLACE || false;
  27541. IS_ALLOWED_URI$1 = cfg.ALLOWED_URI_REGEXP || IS_ALLOWED_URI$1;
  27542. NAMESPACE = cfg.NAMESPACE || HTML_NAMESPACE;
  27543. if (cfg.CUSTOM_ELEMENT_HANDLING && isRegexOrFunction(cfg.CUSTOM_ELEMENT_HANDLING.tagNameCheck)) {
  27544. CUSTOM_ELEMENT_HANDLING.tagNameCheck = cfg.CUSTOM_ELEMENT_HANDLING.tagNameCheck;
  27545. }
  27546. if (cfg.CUSTOM_ELEMENT_HANDLING && isRegexOrFunction(cfg.CUSTOM_ELEMENT_HANDLING.attributeNameCheck)) {
  27547. CUSTOM_ELEMENT_HANDLING.attributeNameCheck = cfg.CUSTOM_ELEMENT_HANDLING.attributeNameCheck;
  27548. }
  27549. if (cfg.CUSTOM_ELEMENT_HANDLING && typeof cfg.CUSTOM_ELEMENT_HANDLING.allowCustomizedBuiltInElements === 'boolean') {
  27550. CUSTOM_ELEMENT_HANDLING.allowCustomizedBuiltInElements = cfg.CUSTOM_ELEMENT_HANDLING.allowCustomizedBuiltInElements;
  27551. }
  27552. 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;
  27553. transformCaseFunc = PARSER_MEDIA_TYPE === 'application/xhtml+xml' ? function (x) {
  27554. return x;
  27555. } : stringToLowerCase;
  27556. if (SAFE_FOR_TEMPLATES) {
  27557. ALLOW_DATA_ATTR = false;
  27558. }
  27559. if (RETURN_DOM_FRAGMENT) {
  27560. RETURN_DOM = true;
  27561. }
  27562. if (USE_PROFILES) {
  27563. ALLOWED_TAGS = addToSet({}, _toConsumableArray(text));
  27564. ALLOWED_ATTR = [];
  27565. if (USE_PROFILES.html === true) {
  27566. addToSet(ALLOWED_TAGS, html$1);
  27567. addToSet(ALLOWED_ATTR, html);
  27568. }
  27569. if (USE_PROFILES.svg === true) {
  27570. addToSet(ALLOWED_TAGS, svg$1);
  27571. addToSet(ALLOWED_ATTR, svg);
  27572. addToSet(ALLOWED_ATTR, xml);
  27573. }
  27574. if (USE_PROFILES.svgFilters === true) {
  27575. addToSet(ALLOWED_TAGS, svgFilters);
  27576. addToSet(ALLOWED_ATTR, svg);
  27577. addToSet(ALLOWED_ATTR, xml);
  27578. }
  27579. if (USE_PROFILES.mathMl === true) {
  27580. addToSet(ALLOWED_TAGS, mathMl$1);
  27581. addToSet(ALLOWED_ATTR, mathMl);
  27582. addToSet(ALLOWED_ATTR, xml);
  27583. }
  27584. }
  27585. if (cfg.ADD_TAGS) {
  27586. if (ALLOWED_TAGS === DEFAULT_ALLOWED_TAGS) {
  27587. ALLOWED_TAGS = clone(ALLOWED_TAGS);
  27588. }
  27589. addToSet(ALLOWED_TAGS, cfg.ADD_TAGS);
  27590. }
  27591. if (cfg.ADD_ATTR) {
  27592. if (ALLOWED_ATTR === DEFAULT_ALLOWED_ATTR) {
  27593. ALLOWED_ATTR = clone(ALLOWED_ATTR);
  27594. }
  27595. addToSet(ALLOWED_ATTR, cfg.ADD_ATTR);
  27596. }
  27597. if (cfg.ADD_URI_SAFE_ATTR) {
  27598. addToSet(URI_SAFE_ATTRIBUTES, cfg.ADD_URI_SAFE_ATTR);
  27599. }
  27600. if (cfg.FORBID_CONTENTS) {
  27601. if (FORBID_CONTENTS === DEFAULT_FORBID_CONTENTS) {
  27602. FORBID_CONTENTS = clone(FORBID_CONTENTS);
  27603. }
  27604. addToSet(FORBID_CONTENTS, cfg.FORBID_CONTENTS);
  27605. }
  27606. if (KEEP_CONTENT) {
  27607. ALLOWED_TAGS['#text'] = true;
  27608. }
  27609. if (WHOLE_DOCUMENT) {
  27610. addToSet(ALLOWED_TAGS, [
  27611. 'html',
  27612. 'head',
  27613. 'body'
  27614. ]);
  27615. }
  27616. if (ALLOWED_TAGS.table) {
  27617. addToSet(ALLOWED_TAGS, ['tbody']);
  27618. delete FORBID_TAGS.tbody;
  27619. }
  27620. if (freeze) {
  27621. freeze(cfg);
  27622. }
  27623. CONFIG = cfg;
  27624. };
  27625. var MATHML_TEXT_INTEGRATION_POINTS = addToSet({}, [
  27626. 'mi',
  27627. 'mo',
  27628. 'mn',
  27629. 'ms',
  27630. 'mtext'
  27631. ]);
  27632. var HTML_INTEGRATION_POINTS = addToSet({}, [
  27633. 'foreignobject',
  27634. 'desc',
  27635. 'title',
  27636. 'annotation-xml'
  27637. ]);
  27638. var COMMON_SVG_AND_HTML_ELEMENTS = addToSet({}, [
  27639. 'title',
  27640. 'style',
  27641. 'font',
  27642. 'a',
  27643. 'script'
  27644. ]);
  27645. var ALL_SVG_TAGS = addToSet({}, svg$1);
  27646. addToSet(ALL_SVG_TAGS, svgFilters);
  27647. addToSet(ALL_SVG_TAGS, svgDisallowed);
  27648. var ALL_MATHML_TAGS = addToSet({}, mathMl$1);
  27649. addToSet(ALL_MATHML_TAGS, mathMlDisallowed);
  27650. var _checkValidNamespace = function _checkValidNamespace(element) {
  27651. var parent = getParentNode(element);
  27652. if (!parent || !parent.tagName) {
  27653. parent = {
  27654. namespaceURI: HTML_NAMESPACE,
  27655. tagName: 'template'
  27656. };
  27657. }
  27658. var tagName = stringToLowerCase(element.tagName);
  27659. var parentTagName = stringToLowerCase(parent.tagName);
  27660. if (element.namespaceURI === SVG_NAMESPACE) {
  27661. if (parent.namespaceURI === HTML_NAMESPACE) {
  27662. return tagName === 'svg';
  27663. }
  27664. if (parent.namespaceURI === MATHML_NAMESPACE) {
  27665. return tagName === 'svg' && (parentTagName === 'annotation-xml' || MATHML_TEXT_INTEGRATION_POINTS[parentTagName]);
  27666. }
  27667. return Boolean(ALL_SVG_TAGS[tagName]);
  27668. }
  27669. if (element.namespaceURI === MATHML_NAMESPACE) {
  27670. if (parent.namespaceURI === HTML_NAMESPACE) {
  27671. return tagName === 'math';
  27672. }
  27673. if (parent.namespaceURI === SVG_NAMESPACE) {
  27674. return tagName === 'math' && HTML_INTEGRATION_POINTS[parentTagName];
  27675. }
  27676. return Boolean(ALL_MATHML_TAGS[tagName]);
  27677. }
  27678. if (element.namespaceURI === HTML_NAMESPACE) {
  27679. if (parent.namespaceURI === SVG_NAMESPACE && !HTML_INTEGRATION_POINTS[parentTagName]) {
  27680. return false;
  27681. }
  27682. if (parent.namespaceURI === MATHML_NAMESPACE && !MATHML_TEXT_INTEGRATION_POINTS[parentTagName]) {
  27683. return false;
  27684. }
  27685. return !ALL_MATHML_TAGS[tagName] && (COMMON_SVG_AND_HTML_ELEMENTS[tagName] || !ALL_SVG_TAGS[tagName]);
  27686. }
  27687. return false;
  27688. };
  27689. var _forceRemove = function _forceRemove(node) {
  27690. arrayPush(DOMPurify.removed, { element: node });
  27691. try {
  27692. node.parentNode.removeChild(node);
  27693. } catch (_) {
  27694. try {
  27695. node.outerHTML = emptyHTML;
  27696. } catch (_) {
  27697. node.remove();
  27698. }
  27699. }
  27700. };
  27701. var _removeAttribute = function _removeAttribute(name, node) {
  27702. try {
  27703. arrayPush(DOMPurify.removed, {
  27704. attribute: node.getAttributeNode(name),
  27705. from: node
  27706. });
  27707. } catch (_) {
  27708. arrayPush(DOMPurify.removed, {
  27709. attribute: null,
  27710. from: node
  27711. });
  27712. }
  27713. node.removeAttribute(name);
  27714. if (name === 'is' && !ALLOWED_ATTR[name]) {
  27715. if (RETURN_DOM || RETURN_DOM_FRAGMENT) {
  27716. try {
  27717. _forceRemove(node);
  27718. } catch (_) {
  27719. }
  27720. } else {
  27721. try {
  27722. node.setAttribute(name, '');
  27723. } catch (_) {
  27724. }
  27725. }
  27726. }
  27727. };
  27728. var _initDocument = function _initDocument(dirty) {
  27729. var doc;
  27730. var leadingWhitespace;
  27731. if (FORCE_BODY) {
  27732. dirty = '<remove></remove>' + dirty;
  27733. } else {
  27734. var matches = stringMatch(dirty, /^[\r\n\t ]+/);
  27735. leadingWhitespace = matches && matches[0];
  27736. }
  27737. if (PARSER_MEDIA_TYPE === 'application/xhtml+xml') {
  27738. dirty = '<html xmlns="http://www.w3.org/1999/xhtml"><head></head><body>' + dirty + '</body></html>';
  27739. }
  27740. var dirtyPayload = trustedTypesPolicy ? trustedTypesPolicy.createHTML(dirty) : dirty;
  27741. if (NAMESPACE === HTML_NAMESPACE) {
  27742. try {
  27743. doc = new DOMParser().parseFromString(dirtyPayload, PARSER_MEDIA_TYPE);
  27744. } catch (_) {
  27745. }
  27746. }
  27747. if (!doc || !doc.documentElement) {
  27748. doc = implementation.createDocument(NAMESPACE, 'template', null);
  27749. try {
  27750. doc.documentElement.innerHTML = IS_EMPTY_INPUT ? '' : dirtyPayload;
  27751. } catch (_) {
  27752. }
  27753. }
  27754. var body = doc.body || doc.documentElement;
  27755. if (dirty && leadingWhitespace) {
  27756. body.insertBefore(document.createTextNode(leadingWhitespace), body.childNodes[0] || null);
  27757. }
  27758. if (NAMESPACE === HTML_NAMESPACE) {
  27759. return getElementsByTagName.call(doc, WHOLE_DOCUMENT ? 'html' : 'body')[0];
  27760. }
  27761. return WHOLE_DOCUMENT ? doc.documentElement : body;
  27762. };
  27763. var _createIterator = function _createIterator(root) {
  27764. return createNodeIterator.call(root.ownerDocument || root, root, NodeFilter.SHOW_ELEMENT | NodeFilter.SHOW_COMMENT | NodeFilter.SHOW_TEXT, null, false);
  27765. };
  27766. var _isClobbered = function _isClobbered(elm) {
  27767. 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');
  27768. };
  27769. var _isNode = function _isNode(object) {
  27770. return _typeof(Node) === 'object' ? object instanceof Node : object && _typeof(object) === 'object' && typeof object.nodeType === 'number' && typeof object.nodeName === 'string';
  27771. };
  27772. var _executeHook = function _executeHook(entryPoint, currentNode, data) {
  27773. if (!hooks[entryPoint]) {
  27774. return;
  27775. }
  27776. arrayForEach(hooks[entryPoint], function (hook) {
  27777. hook.call(DOMPurify, currentNode, data, CONFIG);
  27778. });
  27779. };
  27780. var _sanitizeElements = function _sanitizeElements(currentNode) {
  27781. var content;
  27782. _executeHook('beforeSanitizeElements', currentNode, null);
  27783. if (_isClobbered(currentNode)) {
  27784. _forceRemove(currentNode);
  27785. return true;
  27786. }
  27787. if (regExpTest(/[\u0080-\uFFFF]/, currentNode.nodeName)) {
  27788. _forceRemove(currentNode);
  27789. return true;
  27790. }
  27791. var tagName = transformCaseFunc(currentNode.nodeName);
  27792. _executeHook('uponSanitizeElement', currentNode, {
  27793. tagName: tagName,
  27794. allowedTags: ALLOWED_TAGS
  27795. });
  27796. if (currentNode.hasChildNodes() && !_isNode(currentNode.firstElementChild) && (!_isNode(currentNode.content) || !_isNode(currentNode.content.firstElementChild)) && regExpTest(/<[/\w]/g, currentNode.innerHTML) && regExpTest(/<[/\w]/g, currentNode.textContent)) {
  27797. _forceRemove(currentNode);
  27798. return true;
  27799. }
  27800. if (tagName === 'select' && regExpTest(/<template/i, currentNode.innerHTML)) {
  27801. _forceRemove(currentNode);
  27802. return true;
  27803. }
  27804. if (!ALLOWED_TAGS[tagName] || FORBID_TAGS[tagName]) {
  27805. if (!FORBID_TAGS[tagName] && _basicCustomElementTest(tagName)) {
  27806. if (CUSTOM_ELEMENT_HANDLING.tagNameCheck instanceof RegExp && regExpTest(CUSTOM_ELEMENT_HANDLING.tagNameCheck, tagName))
  27807. return false;
  27808. if (CUSTOM_ELEMENT_HANDLING.tagNameCheck instanceof Function && CUSTOM_ELEMENT_HANDLING.tagNameCheck(tagName))
  27809. return false;
  27810. }
  27811. if (KEEP_CONTENT && !FORBID_CONTENTS[tagName]) {
  27812. var parentNode = getParentNode(currentNode) || currentNode.parentNode;
  27813. var childNodes = getChildNodes(currentNode) || currentNode.childNodes;
  27814. if (childNodes && parentNode) {
  27815. var childCount = childNodes.length;
  27816. for (var i = childCount - 1; i >= 0; --i) {
  27817. parentNode.insertBefore(cloneNode(childNodes[i], true), getNextSibling(currentNode));
  27818. }
  27819. }
  27820. }
  27821. _forceRemove(currentNode);
  27822. return true;
  27823. }
  27824. if (currentNode instanceof Element && !_checkValidNamespace(currentNode)) {
  27825. _forceRemove(currentNode);
  27826. return true;
  27827. }
  27828. if ((tagName === 'noscript' || tagName === 'noembed') && regExpTest(/<\/no(script|embed)/i, currentNode.innerHTML)) {
  27829. _forceRemove(currentNode);
  27830. return true;
  27831. }
  27832. if (SAFE_FOR_TEMPLATES && currentNode.nodeType === 3) {
  27833. content = currentNode.textContent;
  27834. content = stringReplace(content, MUSTACHE_EXPR$1, ' ');
  27835. content = stringReplace(content, ERB_EXPR$1, ' ');
  27836. if (currentNode.textContent !== content) {
  27837. arrayPush(DOMPurify.removed, { element: currentNode.cloneNode() });
  27838. currentNode.textContent = content;
  27839. }
  27840. }
  27841. _executeHook('afterSanitizeElements', currentNode, null);
  27842. return false;
  27843. };
  27844. var _isValidAttribute = function _isValidAttribute(lcTag, lcName, value) {
  27845. if (SANITIZE_DOM && (lcName === 'id' || lcName === 'name') && (value in document || value in formElement)) {
  27846. return false;
  27847. }
  27848. if (ALLOW_DATA_ATTR && !FORBID_ATTR[lcName] && regExpTest(DATA_ATTR$1, lcName));
  27849. else if (ALLOW_ARIA_ATTR && regExpTest(ARIA_ATTR$1, lcName));
  27850. else if (!ALLOWED_ATTR[lcName] || FORBID_ATTR[lcName]) {
  27851. 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)));
  27852. else {
  27853. return false;
  27854. }
  27855. } else if (URI_SAFE_ATTRIBUTES[lcName]);
  27856. else if (regExpTest(IS_ALLOWED_URI$1, stringReplace(value, ATTR_WHITESPACE$1, '')));
  27857. else if ((lcName === 'src' || lcName === 'xlink:href' || lcName === 'href') && lcTag !== 'script' && stringIndexOf(value, 'data:') === 0 && DATA_URI_TAGS[lcTag]);
  27858. else if (ALLOW_UNKNOWN_PROTOCOLS && !regExpTest(IS_SCRIPT_OR_DATA$1, stringReplace(value, ATTR_WHITESPACE$1, '')));
  27859. else if (!value);
  27860. else {
  27861. return false;
  27862. }
  27863. return true;
  27864. };
  27865. var _basicCustomElementTest = function _basicCustomElementTest(tagName) {
  27866. return tagName.indexOf('-') > 0;
  27867. };
  27868. var _sanitizeAttributes = function _sanitizeAttributes(currentNode) {
  27869. var attr;
  27870. var value;
  27871. var lcName;
  27872. var l;
  27873. _executeHook('beforeSanitizeAttributes', currentNode, null);
  27874. var attributes = currentNode.attributes;
  27875. if (!attributes) {
  27876. return;
  27877. }
  27878. var hookEvent = {
  27879. attrName: '',
  27880. attrValue: '',
  27881. keepAttr: true,
  27882. allowedAttributes: ALLOWED_ATTR
  27883. };
  27884. l = attributes.length;
  27885. while (l--) {
  27886. attr = attributes[l];
  27887. var _attr = attr, name = _attr.name, namespaceURI = _attr.namespaceURI;
  27888. value = name === 'value' ? attr.value : stringTrim(attr.value);
  27889. lcName = transformCaseFunc(name);
  27890. var initValue = value;
  27891. hookEvent.attrName = lcName;
  27892. hookEvent.attrValue = value;
  27893. hookEvent.keepAttr = true;
  27894. hookEvent.forceKeepAttr = undefined;
  27895. _executeHook('uponSanitizeAttribute', currentNode, hookEvent);
  27896. value = hookEvent.attrValue;
  27897. if (hookEvent.forceKeepAttr) {
  27898. continue;
  27899. }
  27900. if (!hookEvent.keepAttr) {
  27901. _removeAttribute(name, currentNode);
  27902. continue;
  27903. }
  27904. if (regExpTest(/\/>/i, value)) {
  27905. _removeAttribute(name, currentNode);
  27906. continue;
  27907. }
  27908. if (SAFE_FOR_TEMPLATES) {
  27909. value = stringReplace(value, MUSTACHE_EXPR$1, ' ');
  27910. value = stringReplace(value, ERB_EXPR$1, ' ');
  27911. }
  27912. var lcTag = transformCaseFunc(currentNode.nodeName);
  27913. if (!_isValidAttribute(lcTag, lcName, value)) {
  27914. _removeAttribute(name, currentNode);
  27915. continue;
  27916. }
  27917. if (value !== initValue) {
  27918. try {
  27919. if (namespaceURI) {
  27920. currentNode.setAttributeNS(namespaceURI, name, value);
  27921. } else {
  27922. currentNode.setAttribute(name, value);
  27923. }
  27924. } catch (_) {
  27925. _removeAttribute(name, currentNode);
  27926. }
  27927. }
  27928. }
  27929. _executeHook('afterSanitizeAttributes', currentNode, null);
  27930. };
  27931. var _sanitizeShadowDOM = function _sanitizeShadowDOM(fragment) {
  27932. var shadowNode;
  27933. var shadowIterator = _createIterator(fragment);
  27934. _executeHook('beforeSanitizeShadowDOM', fragment, null);
  27935. while (shadowNode = shadowIterator.nextNode()) {
  27936. _executeHook('uponSanitizeShadowNode', shadowNode, null);
  27937. if (_sanitizeElements(shadowNode)) {
  27938. continue;
  27939. }
  27940. if (shadowNode.content instanceof DocumentFragment) {
  27941. _sanitizeShadowDOM(shadowNode.content);
  27942. }
  27943. _sanitizeAttributes(shadowNode);
  27944. }
  27945. _executeHook('afterSanitizeShadowDOM', fragment, null);
  27946. };
  27947. DOMPurify.sanitize = function (dirty, cfg) {
  27948. var body;
  27949. var importedNode;
  27950. var currentNode;
  27951. var oldNode;
  27952. var returnNode;
  27953. IS_EMPTY_INPUT = !dirty;
  27954. if (IS_EMPTY_INPUT) {
  27955. dirty = '<!-->';
  27956. }
  27957. if (typeof dirty !== 'string' && !_isNode(dirty)) {
  27958. if (typeof dirty.toString !== 'function') {
  27959. throw typeErrorCreate('toString is not a function');
  27960. } else {
  27961. dirty = dirty.toString();
  27962. if (typeof dirty !== 'string') {
  27963. throw typeErrorCreate('dirty is not a string, aborting');
  27964. }
  27965. }
  27966. }
  27967. if (!DOMPurify.isSupported) {
  27968. if (_typeof(window.toStaticHTML) === 'object' || typeof window.toStaticHTML === 'function') {
  27969. if (typeof dirty === 'string') {
  27970. return window.toStaticHTML(dirty);
  27971. }
  27972. if (_isNode(dirty)) {
  27973. return window.toStaticHTML(dirty.outerHTML);
  27974. }
  27975. }
  27976. return dirty;
  27977. }
  27978. if (!SET_CONFIG) {
  27979. _parseConfig(cfg);
  27980. }
  27981. DOMPurify.removed = [];
  27982. if (typeof dirty === 'string') {
  27983. IN_PLACE = false;
  27984. }
  27985. if (IN_PLACE) {
  27986. if (dirty.nodeName) {
  27987. var tagName = transformCaseFunc(dirty.nodeName);
  27988. if (!ALLOWED_TAGS[tagName] || FORBID_TAGS[tagName]) {
  27989. throw typeErrorCreate('root node is forbidden and cannot be sanitized in-place');
  27990. }
  27991. }
  27992. } else if (dirty instanceof Node) {
  27993. body = _initDocument('<!---->');
  27994. importedNode = body.ownerDocument.importNode(dirty, true);
  27995. if (importedNode.nodeType === 1 && importedNode.nodeName === 'BODY') {
  27996. body = importedNode;
  27997. } else if (importedNode.nodeName === 'HTML') {
  27998. body = importedNode;
  27999. } else {
  28000. body.appendChild(importedNode);
  28001. }
  28002. } else {
  28003. if (!RETURN_DOM && !SAFE_FOR_TEMPLATES && !WHOLE_DOCUMENT && dirty.indexOf('<') === -1) {
  28004. return trustedTypesPolicy && RETURN_TRUSTED_TYPE ? trustedTypesPolicy.createHTML(dirty) : dirty;
  28005. }
  28006. body = _initDocument(dirty);
  28007. if (!body) {
  28008. return RETURN_DOM ? null : RETURN_TRUSTED_TYPE ? emptyHTML : '';
  28009. }
  28010. }
  28011. if (body && FORCE_BODY) {
  28012. _forceRemove(body.firstChild);
  28013. }
  28014. var nodeIterator = _createIterator(IN_PLACE ? dirty : body);
  28015. while (currentNode = nodeIterator.nextNode()) {
  28016. if (currentNode.nodeType === 3 && currentNode === oldNode) {
  28017. continue;
  28018. }
  28019. if (_sanitizeElements(currentNode)) {
  28020. continue;
  28021. }
  28022. if (currentNode.content instanceof DocumentFragment) {
  28023. _sanitizeShadowDOM(currentNode.content);
  28024. }
  28025. _sanitizeAttributes(currentNode);
  28026. oldNode = currentNode;
  28027. }
  28028. oldNode = null;
  28029. if (IN_PLACE) {
  28030. return dirty;
  28031. }
  28032. if (RETURN_DOM) {
  28033. if (RETURN_DOM_FRAGMENT) {
  28034. returnNode = createDocumentFragment.call(body.ownerDocument);
  28035. while (body.firstChild) {
  28036. returnNode.appendChild(body.firstChild);
  28037. }
  28038. } else {
  28039. returnNode = body;
  28040. }
  28041. if (ALLOWED_ATTR.shadowroot) {
  28042. returnNode = importNode.call(originalDocument, returnNode, true);
  28043. }
  28044. return returnNode;
  28045. }
  28046. var serializedHTML = WHOLE_DOCUMENT ? body.outerHTML : body.innerHTML;
  28047. if (WHOLE_DOCUMENT && ALLOWED_TAGS['!doctype'] && body.ownerDocument && body.ownerDocument.doctype && body.ownerDocument.doctype.name && regExpTest(DOCTYPE_NAME, body.ownerDocument.doctype.name)) {
  28048. serializedHTML = '<!DOCTYPE ' + body.ownerDocument.doctype.name + '>\n' + serializedHTML;
  28049. }
  28050. if (SAFE_FOR_TEMPLATES) {
  28051. serializedHTML = stringReplace(serializedHTML, MUSTACHE_EXPR$1, ' ');
  28052. serializedHTML = stringReplace(serializedHTML, ERB_EXPR$1, ' ');
  28053. }
  28054. return trustedTypesPolicy && RETURN_TRUSTED_TYPE ? trustedTypesPolicy.createHTML(serializedHTML) : serializedHTML;
  28055. };
  28056. DOMPurify.setConfig = function (cfg) {
  28057. _parseConfig(cfg);
  28058. SET_CONFIG = true;
  28059. };
  28060. DOMPurify.clearConfig = function () {
  28061. CONFIG = null;
  28062. SET_CONFIG = false;
  28063. };
  28064. DOMPurify.isValidAttribute = function (tag, attr, value) {
  28065. if (!CONFIG) {
  28066. _parseConfig({});
  28067. }
  28068. var lcTag = transformCaseFunc(tag);
  28069. var lcName = transformCaseFunc(attr);
  28070. return _isValidAttribute(lcTag, lcName, value);
  28071. };
  28072. DOMPurify.addHook = function (entryPoint, hookFunction) {
  28073. if (typeof hookFunction !== 'function') {
  28074. return;
  28075. }
  28076. hooks[entryPoint] = hooks[entryPoint] || [];
  28077. arrayPush(hooks[entryPoint], hookFunction);
  28078. };
  28079. DOMPurify.removeHook = function (entryPoint) {
  28080. if (hooks[entryPoint]) {
  28081. return arrayPop(hooks[entryPoint]);
  28082. }
  28083. };
  28084. DOMPurify.removeHooks = function (entryPoint) {
  28085. if (hooks[entryPoint]) {
  28086. hooks[entryPoint] = [];
  28087. }
  28088. };
  28089. DOMPurify.removeAllHooks = function () {
  28090. hooks = {};
  28091. };
  28092. return DOMPurify;
  28093. }
  28094. var purify = createDOMPurify();
  28095. const sanitizeHtmlString = html => purify().sanitize(html);
  28096. const isTouch = global$5.deviceType.isTouch();
  28097. const hiddenHeader = (title, close) => ({
  28098. dom: {
  28099. tag: 'div',
  28100. styles: { display: 'none' },
  28101. classes: ['tox-dialog__header']
  28102. },
  28103. components: [
  28104. title,
  28105. close
  28106. ]
  28107. });
  28108. const pClose = (onClose, providersBackstage) => ModalDialog.parts.close(Button.sketch({
  28109. dom: {
  28110. tag: 'button',
  28111. classes: [
  28112. 'tox-button',
  28113. 'tox-button--icon',
  28114. 'tox-button--naked'
  28115. ],
  28116. attributes: {
  28117. 'type': 'button',
  28118. 'aria-label': providersBackstage.translate('Close')
  28119. }
  28120. },
  28121. action: onClose,
  28122. buttonBehaviours: derive$1([Tabstopping.config({})])
  28123. }));
  28124. const pUntitled = () => ModalDialog.parts.title({
  28125. dom: {
  28126. tag: 'div',
  28127. classes: ['tox-dialog__title'],
  28128. innerHtml: '',
  28129. styles: { display: 'none' }
  28130. }
  28131. });
  28132. const pBodyMessage = (message, providersBackstage) => ModalDialog.parts.body({
  28133. dom: {
  28134. tag: 'div',
  28135. classes: ['tox-dialog__body']
  28136. },
  28137. components: [{
  28138. dom: {
  28139. tag: 'div',
  28140. classes: ['tox-dialog__body-content']
  28141. },
  28142. components: [{ dom: fromHtml(`<p>${ sanitizeHtmlString(providersBackstage.translate(message)) }</p>`) }]
  28143. }]
  28144. });
  28145. const pFooter = buttons => ModalDialog.parts.footer({
  28146. dom: {
  28147. tag: 'div',
  28148. classes: ['tox-dialog__footer']
  28149. },
  28150. components: buttons
  28151. });
  28152. const pFooterGroup = (startButtons, endButtons) => [
  28153. Container.sketch({
  28154. dom: {
  28155. tag: 'div',
  28156. classes: ['tox-dialog__footer-start']
  28157. },
  28158. components: startButtons
  28159. }),
  28160. Container.sketch({
  28161. dom: {
  28162. tag: 'div',
  28163. classes: ['tox-dialog__footer-end']
  28164. },
  28165. components: endButtons
  28166. })
  28167. ];
  28168. const renderDialog$1 = spec => {
  28169. const dialogClass = 'tox-dialog';
  28170. const blockerClass = dialogClass + '-wrap';
  28171. const blockerBackdropClass = blockerClass + '__backdrop';
  28172. const scrollLockClass = dialogClass + '__disable-scroll';
  28173. return ModalDialog.sketch({
  28174. lazySink: spec.lazySink,
  28175. onEscape: comp => {
  28176. spec.onEscape(comp);
  28177. return Optional.some(true);
  28178. },
  28179. useTabstopAt: elem => !isPseudoStop(elem),
  28180. firstTabstop: spec.firstTabstop,
  28181. dom: {
  28182. tag: 'div',
  28183. classes: [dialogClass].concat(spec.extraClasses),
  28184. styles: {
  28185. position: 'relative',
  28186. ...spec.extraStyles
  28187. }
  28188. },
  28189. components: [
  28190. spec.header,
  28191. spec.body,
  28192. ...spec.footer.toArray()
  28193. ],
  28194. parts: {
  28195. blocker: {
  28196. dom: fromHtml(`<div class="${ blockerClass }"></div>`),
  28197. components: [{
  28198. dom: {
  28199. tag: 'div',
  28200. classes: isTouch ? [
  28201. blockerBackdropClass,
  28202. blockerBackdropClass + '--opaque'
  28203. ] : [blockerBackdropClass]
  28204. }
  28205. }]
  28206. }
  28207. },
  28208. dragBlockClass: blockerClass,
  28209. modalBehaviours: derive$1([
  28210. Focusing.config({}),
  28211. config('dialog-events', spec.dialogEvents.concat([runOnSource(focusin(), (comp, _se) => {
  28212. Keying.focusIn(comp);
  28213. })])),
  28214. config('scroll-lock', [
  28215. runOnAttached(() => {
  28216. add$2(body(), scrollLockClass);
  28217. }),
  28218. runOnDetached(() => {
  28219. remove$2(body(), scrollLockClass);
  28220. })
  28221. ]),
  28222. ...spec.extraBehaviours
  28223. ]),
  28224. eventOrder: {
  28225. [execute$5()]: ['dialog-events'],
  28226. [attachedToDom()]: [
  28227. 'scroll-lock',
  28228. 'dialog-events',
  28229. 'alloy.base.behaviour'
  28230. ],
  28231. [detachedFromDom()]: [
  28232. 'alloy.base.behaviour',
  28233. 'dialog-events',
  28234. 'scroll-lock'
  28235. ],
  28236. ...spec.eventOrder
  28237. }
  28238. });
  28239. };
  28240. const renderClose = providersBackstage => Button.sketch({
  28241. dom: {
  28242. tag: 'button',
  28243. classes: [
  28244. 'tox-button',
  28245. 'tox-button--icon',
  28246. 'tox-button--naked'
  28247. ],
  28248. attributes: {
  28249. 'type': 'button',
  28250. 'aria-label': providersBackstage.translate('Close'),
  28251. 'title': providersBackstage.translate('Close')
  28252. }
  28253. },
  28254. buttonBehaviours: derive$1([Tabstopping.config({})]),
  28255. components: [render$3('close', {
  28256. tag: 'div',
  28257. classes: ['tox-icon']
  28258. }, providersBackstage.icons)],
  28259. action: comp => {
  28260. emit(comp, formCancelEvent);
  28261. }
  28262. });
  28263. const renderTitle = (spec, dialogId, titleId, providersBackstage) => {
  28264. const renderComponents = data => [text$2(providersBackstage.translate(data.title))];
  28265. return {
  28266. dom: {
  28267. tag: 'div',
  28268. classes: ['tox-dialog__title'],
  28269. attributes: { ...titleId.map(x => ({ id: x })).getOr({}) }
  28270. },
  28271. components: [],
  28272. behaviours: derive$1([Reflecting.config({
  28273. channel: `${ titleChannel }-${ dialogId }`,
  28274. initialData: spec,
  28275. renderComponents
  28276. })])
  28277. };
  28278. };
  28279. const renderDragHandle = () => ({ dom: fromHtml('<div class="tox-dialog__draghandle"></div>') });
  28280. const renderInlineHeader = (spec, dialogId, titleId, providersBackstage) => Container.sketch({
  28281. dom: fromHtml('<div class="tox-dialog__header"></div>'),
  28282. components: [
  28283. renderTitle(spec, dialogId, Optional.some(titleId), providersBackstage),
  28284. renderDragHandle(),
  28285. renderClose(providersBackstage)
  28286. ],
  28287. containerBehaviours: derive$1([Dragging.config({
  28288. mode: 'mouse',
  28289. blockerClass: 'blocker',
  28290. getTarget: handle => {
  28291. return closest$1(handle, '[role="dialog"]').getOrDie();
  28292. },
  28293. snaps: {
  28294. getSnapPoints: () => [],
  28295. leftAttr: 'data-drag-left',
  28296. topAttr: 'data-drag-top'
  28297. }
  28298. })])
  28299. });
  28300. const renderModalHeader = (spec, dialogId, providersBackstage) => {
  28301. const pTitle = ModalDialog.parts.title(renderTitle(spec, dialogId, Optional.none(), providersBackstage));
  28302. const pHandle = ModalDialog.parts.draghandle(renderDragHandle());
  28303. const pClose = ModalDialog.parts.close(renderClose(providersBackstage));
  28304. const components = [pTitle].concat(spec.draggable ? [pHandle] : []).concat([pClose]);
  28305. return Container.sketch({
  28306. dom: fromHtml('<div class="tox-dialog__header"></div>'),
  28307. components
  28308. });
  28309. };
  28310. const getHeader = (title, dialogId, backstage) => renderModalHeader({
  28311. title: backstage.shared.providers.translate(title),
  28312. draggable: backstage.dialog.isDraggableModal()
  28313. }, dialogId, backstage.shared.providers);
  28314. const getBusySpec = (message, bs, providers) => ({
  28315. dom: {
  28316. tag: 'div',
  28317. classes: ['tox-dialog__busy-spinner'],
  28318. attributes: { 'aria-label': providers.translate(message) },
  28319. styles: {
  28320. left: '0px',
  28321. right: '0px',
  28322. bottom: '0px',
  28323. top: '0px',
  28324. position: 'absolute'
  28325. }
  28326. },
  28327. behaviours: bs,
  28328. components: [{ dom: fromHtml('<div class="tox-spinner"><div></div><div></div><div></div></div>') }]
  28329. });
  28330. const getEventExtras = (lazyDialog, providers, extra) => ({
  28331. onClose: () => extra.closeWindow(),
  28332. onBlock: blockEvent => {
  28333. ModalDialog.setBusy(lazyDialog(), (_comp, bs) => getBusySpec(blockEvent.message, bs, providers));
  28334. },
  28335. onUnblock: () => {
  28336. ModalDialog.setIdle(lazyDialog());
  28337. }
  28338. });
  28339. const renderModalDialog = (spec, initialData, dialogEvents, backstage) => {
  28340. const updateState = (_comp, incoming) => Optional.some(incoming);
  28341. return build$1(renderDialog$1({
  28342. ...spec,
  28343. firstTabstop: 1,
  28344. lazySink: backstage.shared.getSink,
  28345. extraBehaviours: [
  28346. Reflecting.config({
  28347. channel: `${ dialogChannel }-${ spec.id }`,
  28348. updateState,
  28349. initialData
  28350. }),
  28351. RepresentingConfigs.memory({}),
  28352. ...spec.extraBehaviours
  28353. ],
  28354. onEscape: comp => {
  28355. emit(comp, formCancelEvent);
  28356. },
  28357. dialogEvents,
  28358. eventOrder: {
  28359. [receive()]: [
  28360. Reflecting.name(),
  28361. Receiving.name()
  28362. ],
  28363. [attachedToDom()]: [
  28364. 'scroll-lock',
  28365. Reflecting.name(),
  28366. 'messages',
  28367. 'dialog-events',
  28368. 'alloy.base.behaviour'
  28369. ],
  28370. [detachedFromDom()]: [
  28371. 'alloy.base.behaviour',
  28372. 'dialog-events',
  28373. 'messages',
  28374. Reflecting.name(),
  28375. 'scroll-lock'
  28376. ]
  28377. }
  28378. }));
  28379. };
  28380. const mapMenuButtons = (buttons, menuItemStates = {}) => {
  28381. const mapItems = button => {
  28382. const items = map$2(button.items, item => {
  28383. const cell = get$g(menuItemStates, item.name).getOr(Cell(false));
  28384. return {
  28385. ...item,
  28386. storage: cell
  28387. };
  28388. });
  28389. return {
  28390. ...button,
  28391. items
  28392. };
  28393. };
  28394. return map$2(buttons, button => {
  28395. return button.type === 'menu' ? mapItems(button) : button;
  28396. });
  28397. };
  28398. const extractCellsToObject = buttons => foldl(buttons, (acc, button) => {
  28399. if (button.type === 'menu') {
  28400. const menuButton = button;
  28401. return foldl(menuButton.items, (innerAcc, item) => {
  28402. innerAcc[item.name] = item.storage;
  28403. return innerAcc;
  28404. }, acc);
  28405. }
  28406. return acc;
  28407. }, {});
  28408. const initCommonEvents = (fireApiEvent, extras) => [
  28409. runWithTarget(focusin(), onFocus),
  28410. fireApiEvent(formCloseEvent, (_api, spec, _event, self) => {
  28411. active$1(getRootNode(self.element)).fold(noop, blur$1);
  28412. extras.onClose();
  28413. spec.onClose();
  28414. }),
  28415. fireApiEvent(formCancelEvent, (api, spec, _event, self) => {
  28416. spec.onCancel(api);
  28417. emit(self, formCloseEvent);
  28418. }),
  28419. run$1(formUnblockEvent, (_c, _se) => extras.onUnblock()),
  28420. run$1(formBlockEvent, (_c, se) => extras.onBlock(se.event))
  28421. ];
  28422. const initUrlDialog = (getInstanceApi, extras) => {
  28423. const fireApiEvent = (eventName, f) => run$1(eventName, (c, se) => {
  28424. withSpec(c, (spec, _c) => {
  28425. f(getInstanceApi(), spec, se.event, c);
  28426. });
  28427. });
  28428. const withSpec = (c, f) => {
  28429. Reflecting.getState(c).get().each(currentDialog => {
  28430. f(currentDialog, c);
  28431. });
  28432. };
  28433. return [
  28434. ...initCommonEvents(fireApiEvent, extras),
  28435. fireApiEvent(formActionEvent, (api, spec, event) => {
  28436. spec.onAction(api, { name: event.name });
  28437. })
  28438. ];
  28439. };
  28440. const initDialog = (getInstanceApi, extras, getSink) => {
  28441. const fireApiEvent = (eventName, f) => run$1(eventName, (c, se) => {
  28442. withSpec(c, (spec, _c) => {
  28443. f(getInstanceApi(), spec, se.event, c);
  28444. });
  28445. });
  28446. const withSpec = (c, f) => {
  28447. Reflecting.getState(c).get().each(currentDialogInit => {
  28448. f(currentDialogInit.internalDialog, c);
  28449. });
  28450. };
  28451. return [
  28452. ...initCommonEvents(fireApiEvent, extras),
  28453. fireApiEvent(formSubmitEvent, (api, spec) => spec.onSubmit(api)),
  28454. fireApiEvent(formChangeEvent, (api, spec, event) => {
  28455. spec.onChange(api, { name: event.name });
  28456. }),
  28457. fireApiEvent(formActionEvent, (api, spec, event, component) => {
  28458. const focusIn = () => Keying.focusIn(component);
  28459. const isDisabled = focused => has$1(focused, 'disabled') || getOpt(focused, 'aria-disabled').exists(val => val === 'true');
  28460. const rootNode = getRootNode(component.element);
  28461. const current = active$1(rootNode);
  28462. spec.onAction(api, {
  28463. name: event.name,
  28464. value: event.value
  28465. });
  28466. active$1(rootNode).fold(focusIn, focused => {
  28467. if (isDisabled(focused)) {
  28468. focusIn();
  28469. } else if (current.exists(cur => contains(focused, cur) && isDisabled(cur))) {
  28470. focusIn();
  28471. } else {
  28472. getSink().toOptional().filter(sink => !contains(sink.element, focused)).each(focusIn);
  28473. }
  28474. });
  28475. }),
  28476. fireApiEvent(formTabChangeEvent, (api, spec, event) => {
  28477. spec.onTabChange(api, {
  28478. newTabName: event.name,
  28479. oldTabName: event.oldName
  28480. });
  28481. }),
  28482. runOnDetached(component => {
  28483. const api = getInstanceApi();
  28484. Representing.setValue(component, api.getData());
  28485. })
  28486. ];
  28487. };
  28488. const SilverDialogEvents = {
  28489. initUrlDialog,
  28490. initDialog
  28491. };
  28492. const makeButton = (button, backstage) => renderFooterButton(button, button.type, backstage);
  28493. const lookup = (compInSystem, footerButtons, buttonName) => find$5(footerButtons, button => button.name === buttonName).bind(memButton => memButton.memento.getOpt(compInSystem));
  28494. const renderComponents = (_data, state) => {
  28495. const footerButtons = state.map(s => s.footerButtons).getOr([]);
  28496. const buttonGroups = partition$3(footerButtons, button => button.align === 'start');
  28497. const makeGroup = (edge, buttons) => Container.sketch({
  28498. dom: {
  28499. tag: 'div',
  28500. classes: [`tox-dialog__footer-${ edge }`]
  28501. },
  28502. components: map$2(buttons, button => button.memento.asSpec())
  28503. });
  28504. const startButtons = makeGroup('start', buttonGroups.pass);
  28505. const endButtons = makeGroup('end', buttonGroups.fail);
  28506. return [
  28507. startButtons,
  28508. endButtons
  28509. ];
  28510. };
  28511. const renderFooter = (initSpec, dialogId, backstage) => {
  28512. const updateState = (comp, data) => {
  28513. const footerButtons = map$2(data.buttons, button => {
  28514. const memButton = record(makeButton(button, backstage));
  28515. return {
  28516. name: button.name,
  28517. align: button.align,
  28518. memento: memButton
  28519. };
  28520. });
  28521. const lookupByName = buttonName => lookup(comp, footerButtons, buttonName);
  28522. return Optional.some({
  28523. lookupByName,
  28524. footerButtons
  28525. });
  28526. };
  28527. return {
  28528. dom: fromHtml('<div class="tox-dialog__footer"></div>'),
  28529. components: [],
  28530. behaviours: derive$1([Reflecting.config({
  28531. channel: `${ footerChannel }-${ dialogId }`,
  28532. initialData: initSpec,
  28533. updateState,
  28534. renderComponents
  28535. })])
  28536. };
  28537. };
  28538. const renderInlineFooter = (initSpec, dialogId, backstage) => renderFooter(initSpec, dialogId, backstage);
  28539. const renderModalFooter = (initSpec, dialogId, backstage) => ModalDialog.parts.footer(renderFooter(initSpec, dialogId, backstage));
  28540. const getCompByName = (access, name) => {
  28541. const root = access.getRoot();
  28542. if (root.getSystem().isConnected()) {
  28543. const form = Composing.getCurrent(access.getFormWrapper()).getOr(access.getFormWrapper());
  28544. return Form.getField(form, name).orThunk(() => {
  28545. const footer = access.getFooter();
  28546. const footerState = Reflecting.getState(footer).get();
  28547. return footerState.bind(f => f.lookupByName(name));
  28548. });
  28549. } else {
  28550. return Optional.none();
  28551. }
  28552. };
  28553. const validateData$1 = (access, data) => {
  28554. const root = access.getRoot();
  28555. return Reflecting.getState(root).get().map(dialogState => getOrDie(asRaw('data', dialogState.dataValidator, data))).getOr(data);
  28556. };
  28557. const getDialogApi = (access, doRedial, menuItemStates) => {
  28558. const withRoot = f => {
  28559. const root = access.getRoot();
  28560. if (root.getSystem().isConnected()) {
  28561. f(root);
  28562. }
  28563. };
  28564. const getData = () => {
  28565. const root = access.getRoot();
  28566. const valueComp = root.getSystem().isConnected() ? access.getFormWrapper() : root;
  28567. const representedValues = Representing.getValue(valueComp);
  28568. const menuItemCurrentState = map$1(menuItemStates, cell => cell.get());
  28569. return {
  28570. ...representedValues,
  28571. ...menuItemCurrentState
  28572. };
  28573. };
  28574. const setData = newData => {
  28575. withRoot(_ => {
  28576. const prevData = instanceApi.getData();
  28577. const mergedData = deepMerge(prevData, newData);
  28578. const newInternalData = validateData$1(access, mergedData);
  28579. const form = access.getFormWrapper();
  28580. Representing.setValue(form, newInternalData);
  28581. each(menuItemStates, (v, k) => {
  28582. if (has$2(mergedData, k)) {
  28583. v.set(mergedData[k]);
  28584. }
  28585. });
  28586. });
  28587. };
  28588. const setEnabled = (name, state) => {
  28589. getCompByName(access, name).each(state ? Disabling.enable : Disabling.disable);
  28590. };
  28591. const focus = name => {
  28592. getCompByName(access, name).each(Focusing.focus);
  28593. };
  28594. const block = message => {
  28595. if (!isString(message)) {
  28596. throw new Error('The dialogInstanceAPI.block function should be passed a blocking message of type string as an argument');
  28597. }
  28598. withRoot(root => {
  28599. emitWith(root, formBlockEvent, { message });
  28600. });
  28601. };
  28602. const unblock = () => {
  28603. withRoot(root => {
  28604. emit(root, formUnblockEvent);
  28605. });
  28606. };
  28607. const showTab = name => {
  28608. withRoot(_ => {
  28609. const body = access.getBody();
  28610. const bodyState = Reflecting.getState(body);
  28611. if (bodyState.get().exists(b => b.isTabPanel())) {
  28612. Composing.getCurrent(body).each(tabSection => {
  28613. TabSection.showTab(tabSection, name);
  28614. });
  28615. }
  28616. });
  28617. };
  28618. const redial = d => {
  28619. withRoot(root => {
  28620. const id = access.getId();
  28621. const dialogInit = doRedial(d);
  28622. const storedMenuButtons = mapMenuButtons(dialogInit.internalDialog.buttons, menuItemStates);
  28623. root.getSystem().broadcastOn([`${ dialogChannel }-${ id }`], dialogInit);
  28624. root.getSystem().broadcastOn([`${ titleChannel }-${ id }`], dialogInit.internalDialog);
  28625. root.getSystem().broadcastOn([`${ bodyChannel }-${ id }`], dialogInit.internalDialog);
  28626. root.getSystem().broadcastOn([`${ footerChannel }-${ id }`], {
  28627. ...dialogInit.internalDialog,
  28628. buttons: storedMenuButtons
  28629. });
  28630. instanceApi.setData(dialogInit.initialData);
  28631. });
  28632. };
  28633. const close = () => {
  28634. withRoot(root => {
  28635. emit(root, formCloseEvent);
  28636. });
  28637. };
  28638. const instanceApi = {
  28639. getData,
  28640. setData,
  28641. setEnabled,
  28642. focus,
  28643. block,
  28644. unblock,
  28645. showTab,
  28646. redial,
  28647. close,
  28648. toggleFullscreen: access.toggleFullscreen
  28649. };
  28650. return instanceApi;
  28651. };
  28652. const getDialogSizeClasses = size => {
  28653. switch (size) {
  28654. case 'large':
  28655. return ['tox-dialog--width-lg'];
  28656. case 'medium':
  28657. return ['tox-dialog--width-md'];
  28658. default:
  28659. return [];
  28660. }
  28661. };
  28662. const renderDialog = (dialogInit, extra, backstage) => {
  28663. const dialogId = generate$6('dialog');
  28664. const internalDialog = dialogInit.internalDialog;
  28665. const header = getHeader(internalDialog.title, dialogId, backstage);
  28666. const body = renderModalBody({
  28667. body: internalDialog.body,
  28668. initialData: internalDialog.initialData
  28669. }, dialogId, backstage);
  28670. const storedMenuButtons = mapMenuButtons(internalDialog.buttons);
  28671. const objOfCells = extractCellsToObject(storedMenuButtons);
  28672. const footer = renderModalFooter({ buttons: storedMenuButtons }, dialogId, backstage);
  28673. const dialogEvents = SilverDialogEvents.initDialog(() => instanceApi, getEventExtras(() => dialog, backstage.shared.providers, extra), backstage.shared.getSink);
  28674. const dialogSize = getDialogSizeClasses(internalDialog.size);
  28675. const spec = {
  28676. id: dialogId,
  28677. header,
  28678. body,
  28679. footer: Optional.some(footer),
  28680. extraClasses: dialogSize,
  28681. extraBehaviours: [],
  28682. extraStyles: {}
  28683. };
  28684. const dialog = renderModalDialog(spec, dialogInit, dialogEvents, backstage);
  28685. const modalAccess = (() => {
  28686. const getForm = () => {
  28687. const outerForm = ModalDialog.getBody(dialog);
  28688. return Composing.getCurrent(outerForm).getOr(outerForm);
  28689. };
  28690. const toggleFullscreen = () => {
  28691. const fullscreenClass = 'tox-dialog--fullscreen';
  28692. const sugarBody = SugarElement.fromDom(dialog.element.dom);
  28693. if (!has(sugarBody, fullscreenClass)) {
  28694. remove$1(sugarBody, dialogSize);
  28695. add$2(sugarBody, fullscreenClass);
  28696. } else {
  28697. remove$2(sugarBody, fullscreenClass);
  28698. add$1(sugarBody, dialogSize);
  28699. }
  28700. };
  28701. return {
  28702. getId: constant$1(dialogId),
  28703. getRoot: constant$1(dialog),
  28704. getBody: () => ModalDialog.getBody(dialog),
  28705. getFooter: () => ModalDialog.getFooter(dialog),
  28706. getFormWrapper: getForm,
  28707. toggleFullscreen
  28708. };
  28709. })();
  28710. const instanceApi = getDialogApi(modalAccess, extra.redial, objOfCells);
  28711. return {
  28712. dialog,
  28713. instanceApi
  28714. };
  28715. };
  28716. const renderInlineDialog = (dialogInit, extra, backstage, ariaAttrs) => {
  28717. const dialogId = generate$6('dialog');
  28718. const dialogLabelId = generate$6('dialog-label');
  28719. const dialogContentId = generate$6('dialog-content');
  28720. const internalDialog = dialogInit.internalDialog;
  28721. const updateState = (_comp, incoming) => Optional.some(incoming);
  28722. const memHeader = record(renderInlineHeader({
  28723. title: internalDialog.title,
  28724. draggable: true
  28725. }, dialogId, dialogLabelId, backstage.shared.providers));
  28726. const memBody = record(renderInlineBody({
  28727. body: internalDialog.body,
  28728. initialData: internalDialog.initialData
  28729. }, dialogId, dialogContentId, backstage, ariaAttrs));
  28730. const storagedMenuButtons = mapMenuButtons(internalDialog.buttons);
  28731. const objOfCells = extractCellsToObject(storagedMenuButtons);
  28732. const memFooter = record(renderInlineFooter({ buttons: storagedMenuButtons }, dialogId, backstage));
  28733. const dialogEvents = SilverDialogEvents.initDialog(() => instanceApi, {
  28734. onBlock: event => {
  28735. Blocking.block(dialog, (_comp, bs) => getBusySpec(event.message, bs, backstage.shared.providers));
  28736. },
  28737. onUnblock: () => {
  28738. Blocking.unblock(dialog);
  28739. },
  28740. onClose: () => extra.closeWindow()
  28741. }, backstage.shared.getSink);
  28742. const inlineClass = 'tox-dialog-inline';
  28743. const dialog = build$1({
  28744. dom: {
  28745. tag: 'div',
  28746. classes: [
  28747. 'tox-dialog',
  28748. inlineClass
  28749. ],
  28750. attributes: {
  28751. role: 'dialog',
  28752. ['aria-labelledby']: dialogLabelId,
  28753. ['aria-describedby']: dialogContentId
  28754. }
  28755. },
  28756. eventOrder: {
  28757. [receive()]: [
  28758. Reflecting.name(),
  28759. Receiving.name()
  28760. ],
  28761. [execute$5()]: ['execute-on-form'],
  28762. [attachedToDom()]: [
  28763. 'reflecting',
  28764. 'execute-on-form'
  28765. ]
  28766. },
  28767. behaviours: derive$1([
  28768. Keying.config({
  28769. mode: 'cyclic',
  28770. onEscape: c => {
  28771. emit(c, formCloseEvent);
  28772. return Optional.some(true);
  28773. },
  28774. useTabstopAt: elem => !isPseudoStop(elem) && (name$3(elem) !== 'button' || get$f(elem, 'disabled') !== 'disabled'),
  28775. firstTabstop: 1
  28776. }),
  28777. Reflecting.config({
  28778. channel: `${ dialogChannel }-${ dialogId }`,
  28779. updateState,
  28780. initialData: dialogInit
  28781. }),
  28782. Focusing.config({}),
  28783. config('execute-on-form', dialogEvents.concat([runOnSource(focusin(), (comp, _se) => {
  28784. Keying.focusIn(comp);
  28785. })])),
  28786. Blocking.config({ getRoot: () => Optional.some(dialog) }),
  28787. Replacing.config({}),
  28788. RepresentingConfigs.memory({})
  28789. ]),
  28790. components: [
  28791. memHeader.asSpec(),
  28792. memBody.asSpec(),
  28793. memFooter.asSpec()
  28794. ]
  28795. });
  28796. const toggleFullscreen = () => {
  28797. const fullscreenClass = 'tox-dialog--fullscreen';
  28798. const sugarBody = SugarElement.fromDom(dialog.element.dom);
  28799. if (!hasAll(sugarBody, [fullscreenClass])) {
  28800. remove$1(sugarBody, [inlineClass]);
  28801. add$1(sugarBody, [fullscreenClass]);
  28802. } else {
  28803. remove$1(sugarBody, [fullscreenClass]);
  28804. add$1(sugarBody, [inlineClass]);
  28805. }
  28806. };
  28807. const instanceApi = getDialogApi({
  28808. getId: constant$1(dialogId),
  28809. getRoot: constant$1(dialog),
  28810. getFooter: () => memFooter.get(dialog),
  28811. getBody: () => memBody.get(dialog),
  28812. getFormWrapper: () => {
  28813. const body = memBody.get(dialog);
  28814. return Composing.getCurrent(body).getOr(body);
  28815. },
  28816. toggleFullscreen
  28817. }, extra.redial, objOfCells);
  28818. return {
  28819. dialog,
  28820. instanceApi
  28821. };
  28822. };
  28823. var global = tinymce.util.Tools.resolve('tinymce.util.URI');
  28824. const getUrlDialogApi = root => {
  28825. const withRoot = f => {
  28826. if (root.getSystem().isConnected()) {
  28827. f(root);
  28828. }
  28829. };
  28830. const block = message => {
  28831. if (!isString(message)) {
  28832. throw new Error('The urlDialogInstanceAPI.block function should be passed a blocking message of type string as an argument');
  28833. }
  28834. withRoot(root => {
  28835. emitWith(root, formBlockEvent, { message });
  28836. });
  28837. };
  28838. const unblock = () => {
  28839. withRoot(root => {
  28840. emit(root, formUnblockEvent);
  28841. });
  28842. };
  28843. const close = () => {
  28844. withRoot(root => {
  28845. emit(root, formCloseEvent);
  28846. });
  28847. };
  28848. const sendMessage = data => {
  28849. withRoot(root => {
  28850. root.getSystem().broadcastOn([bodySendMessageChannel], data);
  28851. });
  28852. };
  28853. return {
  28854. block,
  28855. unblock,
  28856. close,
  28857. sendMessage
  28858. };
  28859. };
  28860. const SUPPORTED_MESSAGE_ACTIONS = [
  28861. 'insertContent',
  28862. 'setContent',
  28863. 'execCommand',
  28864. 'close',
  28865. 'block',
  28866. 'unblock'
  28867. ];
  28868. const isSupportedMessage = data => isObject(data) && SUPPORTED_MESSAGE_ACTIONS.indexOf(data.mceAction) !== -1;
  28869. const isCustomMessage = data => !isSupportedMessage(data) && isObject(data) && has$2(data, 'mceAction');
  28870. const handleMessage = (editor, api, data) => {
  28871. switch (data.mceAction) {
  28872. case 'insertContent':
  28873. editor.insertContent(data.content);
  28874. break;
  28875. case 'setContent':
  28876. editor.setContent(data.content);
  28877. break;
  28878. case 'execCommand':
  28879. const ui = isBoolean(data.ui) ? data.ui : false;
  28880. editor.execCommand(data.cmd, ui, data.value);
  28881. break;
  28882. case 'close':
  28883. api.close();
  28884. break;
  28885. case 'block':
  28886. api.block(data.message);
  28887. break;
  28888. case 'unblock':
  28889. api.unblock();
  28890. break;
  28891. }
  28892. };
  28893. const renderUrlDialog = (internalDialog, extra, editor, backstage) => {
  28894. const dialogId = generate$6('dialog');
  28895. const header = getHeader(internalDialog.title, dialogId, backstage);
  28896. const body = renderIframeBody(internalDialog);
  28897. const footer = internalDialog.buttons.bind(buttons => {
  28898. if (buttons.length === 0) {
  28899. return Optional.none();
  28900. } else {
  28901. return Optional.some(renderModalFooter({ buttons }, dialogId, backstage));
  28902. }
  28903. });
  28904. const dialogEvents = SilverDialogEvents.initUrlDialog(() => instanceApi, getEventExtras(() => dialog, backstage.shared.providers, extra));
  28905. const styles = {
  28906. ...internalDialog.height.fold(() => ({}), height => ({
  28907. 'height': height + 'px',
  28908. 'max-height': height + 'px'
  28909. })),
  28910. ...internalDialog.width.fold(() => ({}), width => ({
  28911. 'width': width + 'px',
  28912. 'max-width': width + 'px'
  28913. }))
  28914. };
  28915. const classes = internalDialog.width.isNone() && internalDialog.height.isNone() ? ['tox-dialog--width-lg'] : [];
  28916. const iframeUri = new global(internalDialog.url, { base_uri: new global(window.location.href) });
  28917. const iframeDomain = `${ iframeUri.protocol }://${ iframeUri.host }${ iframeUri.port ? ':' + iframeUri.port : '' }`;
  28918. const messageHandlerUnbinder = unbindable();
  28919. const extraBehaviours = [
  28920. config('messages', [
  28921. runOnAttached(() => {
  28922. const unbind = bind(SugarElement.fromDom(window), 'message', e => {
  28923. if (iframeUri.isSameOrigin(new global(e.raw.origin))) {
  28924. const data = e.raw.data;
  28925. if (isSupportedMessage(data)) {
  28926. handleMessage(editor, instanceApi, data);
  28927. } else if (isCustomMessage(data)) {
  28928. internalDialog.onMessage(instanceApi, data);
  28929. }
  28930. }
  28931. });
  28932. messageHandlerUnbinder.set(unbind);
  28933. }),
  28934. runOnDetached(messageHandlerUnbinder.clear)
  28935. ]),
  28936. Receiving.config({
  28937. channels: {
  28938. [bodySendMessageChannel]: {
  28939. onReceive: (comp, data) => {
  28940. descendant(comp.element, 'iframe').each(iframeEle => {
  28941. const iframeWin = iframeEle.dom.contentWindow;
  28942. if (isNonNullable(iframeWin)) {
  28943. iframeWin.postMessage(data, iframeDomain);
  28944. }
  28945. });
  28946. }
  28947. }
  28948. }
  28949. })
  28950. ];
  28951. const spec = {
  28952. id: dialogId,
  28953. header,
  28954. body,
  28955. footer,
  28956. extraClasses: classes,
  28957. extraBehaviours,
  28958. extraStyles: styles
  28959. };
  28960. const dialog = renderModalDialog(spec, internalDialog, dialogEvents, backstage);
  28961. const instanceApi = getUrlDialogApi(dialog);
  28962. return {
  28963. dialog,
  28964. instanceApi
  28965. };
  28966. };
  28967. const setup$2 = backstage => {
  28968. const sharedBackstage = backstage.shared;
  28969. const open = (message, callback) => {
  28970. const closeDialog = () => {
  28971. ModalDialog.hide(alertDialog);
  28972. callback();
  28973. };
  28974. const memFooterClose = record(renderFooterButton({
  28975. name: 'close-alert',
  28976. text: 'OK',
  28977. primary: true,
  28978. buttonType: Optional.some('primary'),
  28979. align: 'end',
  28980. enabled: true,
  28981. icon: Optional.none()
  28982. }, 'cancel', backstage));
  28983. const titleSpec = pUntitled();
  28984. const closeSpec = pClose(closeDialog, sharedBackstage.providers);
  28985. const alertDialog = build$1(renderDialog$1({
  28986. lazySink: () => sharedBackstage.getSink(),
  28987. header: hiddenHeader(titleSpec, closeSpec),
  28988. body: pBodyMessage(message, sharedBackstage.providers),
  28989. footer: Optional.some(pFooter(pFooterGroup([], [memFooterClose.asSpec()]))),
  28990. onEscape: closeDialog,
  28991. extraClasses: ['tox-alert-dialog'],
  28992. extraBehaviours: [],
  28993. extraStyles: {},
  28994. dialogEvents: [run$1(formCancelEvent, closeDialog)],
  28995. eventOrder: {}
  28996. }));
  28997. ModalDialog.show(alertDialog);
  28998. const footerCloseButton = memFooterClose.get(alertDialog);
  28999. Focusing.focus(footerCloseButton);
  29000. };
  29001. return { open };
  29002. };
  29003. const setup$1 = backstage => {
  29004. const sharedBackstage = backstage.shared;
  29005. const open = (message, callback) => {
  29006. const closeDialog = state => {
  29007. ModalDialog.hide(confirmDialog);
  29008. callback(state);
  29009. };
  29010. const memFooterYes = record(renderFooterButton({
  29011. name: 'yes',
  29012. text: 'Yes',
  29013. primary: true,
  29014. buttonType: Optional.some('primary'),
  29015. align: 'end',
  29016. enabled: true,
  29017. icon: Optional.none()
  29018. }, 'submit', backstage));
  29019. const footerNo = renderFooterButton({
  29020. name: 'no',
  29021. text: 'No',
  29022. primary: false,
  29023. buttonType: Optional.some('secondary'),
  29024. align: 'end',
  29025. enabled: true,
  29026. icon: Optional.none()
  29027. }, 'cancel', backstage);
  29028. const titleSpec = pUntitled();
  29029. const closeSpec = pClose(() => closeDialog(false), sharedBackstage.providers);
  29030. const confirmDialog = build$1(renderDialog$1({
  29031. lazySink: () => sharedBackstage.getSink(),
  29032. header: hiddenHeader(titleSpec, closeSpec),
  29033. body: pBodyMessage(message, sharedBackstage.providers),
  29034. footer: Optional.some(pFooter(pFooterGroup([], [
  29035. footerNo,
  29036. memFooterYes.asSpec()
  29037. ]))),
  29038. onEscape: () => closeDialog(false),
  29039. extraClasses: ['tox-confirm-dialog'],
  29040. extraBehaviours: [],
  29041. extraStyles: {},
  29042. dialogEvents: [
  29043. run$1(formCancelEvent, () => closeDialog(false)),
  29044. run$1(formSubmitEvent, () => closeDialog(true))
  29045. ],
  29046. eventOrder: {}
  29047. }));
  29048. ModalDialog.show(confirmDialog);
  29049. const footerYesButton = memFooterYes.get(confirmDialog);
  29050. Focusing.focus(footerYesButton);
  29051. };
  29052. return { open };
  29053. };
  29054. const validateData = (data, validator) => getOrDie(asRaw('data', validator, data));
  29055. const isAlertOrConfirmDialog = target => closest(target, '.tox-alert-dialog') || closest(target, '.tox-confirm-dialog');
  29056. const inlineAdditionalBehaviours = (editor, isStickyToolbar, isToolbarLocationTop) => {
  29057. if (isStickyToolbar && isToolbarLocationTop) {
  29058. return [];
  29059. } else {
  29060. return [Docking.config({
  29061. contextual: {
  29062. lazyContext: () => Optional.some(box$1(SugarElement.fromDom(editor.getContentAreaContainer()))),
  29063. fadeInClass: 'tox-dialog-dock-fadein',
  29064. fadeOutClass: 'tox-dialog-dock-fadeout',
  29065. transitionClass: 'tox-dialog-dock-transition'
  29066. },
  29067. modes: ['top'],
  29068. lazyViewport: comp => {
  29069. const optScrollingContext = detectWhenSplitUiMode(editor, comp.element);
  29070. return optScrollingContext.map(sc => {
  29071. const combinedBounds = getBoundsFrom(sc);
  29072. return {
  29073. bounds: combinedBounds,
  29074. optScrollEnv: Optional.some({
  29075. currentScrollTop: sc.element.dom.scrollTop,
  29076. scrollElmTop: absolute$3(sc.element).top
  29077. })
  29078. };
  29079. }).getOrThunk(() => ({
  29080. bounds: win(),
  29081. optScrollEnv: Optional.none()
  29082. }));
  29083. }
  29084. })];
  29085. }
  29086. };
  29087. const setup = extras => {
  29088. const editor = extras.editor;
  29089. const isStickyToolbar$1 = isStickyToolbar(editor);
  29090. const alertDialog = setup$2(extras.backstages.dialog);
  29091. const confirmDialog = setup$1(extras.backstages.dialog);
  29092. const open = (config, params, closeWindow) => {
  29093. if (params !== undefined && params.inline === 'toolbar') {
  29094. return openInlineDialog(config, extras.backstages.popup.shared.anchors.inlineDialog(), closeWindow, params.ariaAttrs);
  29095. } else if (params !== undefined && params.inline === 'cursor') {
  29096. return openInlineDialog(config, extras.backstages.popup.shared.anchors.cursor(), closeWindow, params.ariaAttrs);
  29097. } else {
  29098. return openModalDialog(config, closeWindow);
  29099. }
  29100. };
  29101. const openUrl = (config, closeWindow) => openModalUrlDialog(config, closeWindow);
  29102. const openModalUrlDialog = (config, closeWindow) => {
  29103. const factory = contents => {
  29104. const dialog = renderUrlDialog(contents, {
  29105. closeWindow: () => {
  29106. ModalDialog.hide(dialog.dialog);
  29107. closeWindow(dialog.instanceApi);
  29108. }
  29109. }, editor, extras.backstages.dialog);
  29110. ModalDialog.show(dialog.dialog);
  29111. return dialog.instanceApi;
  29112. };
  29113. return DialogManager.openUrl(factory, config);
  29114. };
  29115. const openModalDialog = (config, closeWindow) => {
  29116. const factory = (contents, internalInitialData, dataValidator) => {
  29117. const initialData = internalInitialData;
  29118. const dialogInit = {
  29119. dataValidator,
  29120. initialData,
  29121. internalDialog: contents
  29122. };
  29123. const dialog = renderDialog(dialogInit, {
  29124. redial: DialogManager.redial,
  29125. closeWindow: () => {
  29126. ModalDialog.hide(dialog.dialog);
  29127. closeWindow(dialog.instanceApi);
  29128. }
  29129. }, extras.backstages.dialog);
  29130. ModalDialog.show(dialog.dialog);
  29131. dialog.instanceApi.setData(initialData);
  29132. return dialog.instanceApi;
  29133. };
  29134. return DialogManager.open(factory, config);
  29135. };
  29136. const openInlineDialog = (config$1, anchor, closeWindow, ariaAttrs = false) => {
  29137. const factory = (contents, internalInitialData, dataValidator) => {
  29138. const initialData = validateData(internalInitialData, dataValidator);
  29139. const inlineDialog = value$2();
  29140. const isToolbarLocationTop = extras.backstages.popup.shared.header.isPositionedAtTop();
  29141. const dialogInit = {
  29142. dataValidator,
  29143. initialData,
  29144. internalDialog: contents
  29145. };
  29146. const refreshDocking = () => inlineDialog.on(dialog => {
  29147. InlineView.reposition(dialog);
  29148. Docking.refresh(dialog);
  29149. });
  29150. const dialogUi = renderInlineDialog(dialogInit, {
  29151. redial: DialogManager.redial,
  29152. closeWindow: () => {
  29153. inlineDialog.on(InlineView.hide);
  29154. editor.off('ResizeEditor', refreshDocking);
  29155. inlineDialog.clear();
  29156. closeWindow(dialogUi.instanceApi);
  29157. }
  29158. }, extras.backstages.popup, ariaAttrs);
  29159. const inlineDialogComp = build$1(InlineView.sketch({
  29160. lazySink: extras.backstages.popup.shared.getSink,
  29161. dom: {
  29162. tag: 'div',
  29163. classes: []
  29164. },
  29165. fireDismissalEventInstead: {},
  29166. ...isToolbarLocationTop ? {} : { fireRepositionEventInstead: {} },
  29167. inlineBehaviours: derive$1([
  29168. config('window-manager-inline-events', [run$1(dismissRequested(), (_comp, _se) => {
  29169. emit(dialogUi.dialog, formCancelEvent);
  29170. })]),
  29171. ...inlineAdditionalBehaviours(editor, isStickyToolbar$1, isToolbarLocationTop)
  29172. ]),
  29173. isExtraPart: (_comp, target) => isAlertOrConfirmDialog(target)
  29174. }));
  29175. inlineDialog.set(inlineDialogComp);
  29176. const getInlineDialogBounds = () => {
  29177. const elem = editor.inline ? body() : SugarElement.fromDom(editor.getContainer());
  29178. const bounds = box$1(elem);
  29179. return Optional.some(bounds);
  29180. };
  29181. InlineView.showWithinBounds(inlineDialogComp, premade(dialogUi.dialog), { anchor }, getInlineDialogBounds);
  29182. if (!isStickyToolbar$1 || !isToolbarLocationTop) {
  29183. Docking.refresh(inlineDialogComp);
  29184. editor.on('ResizeEditor', refreshDocking);
  29185. }
  29186. dialogUi.instanceApi.setData(initialData);
  29187. Keying.focusIn(dialogUi.dialog);
  29188. return dialogUi.instanceApi;
  29189. };
  29190. return DialogManager.open(factory, config$1);
  29191. };
  29192. const confirm = (message, callback) => {
  29193. confirmDialog.open(message, callback);
  29194. };
  29195. const alert = (message, callback) => {
  29196. alertDialog.open(message, callback);
  29197. };
  29198. const close = instanceApi => {
  29199. instanceApi.close();
  29200. };
  29201. return {
  29202. open,
  29203. openUrl,
  29204. alert,
  29205. close,
  29206. confirm
  29207. };
  29208. };
  29209. const registerOptions = editor => {
  29210. register$e(editor);
  29211. register$d(editor);
  29212. register(editor);
  29213. };
  29214. var Theme = () => {
  29215. global$a.add('silver', editor => {
  29216. registerOptions(editor);
  29217. let popupSinkBounds = () => win();
  29218. const {
  29219. dialogs,
  29220. popups,
  29221. renderUI: renderModeUI
  29222. } = setup$3(editor, { getPopupSinkBounds: () => popupSinkBounds() });
  29223. const renderUI = async () => {
  29224. const renderResult = await renderModeUI();
  29225. const optScrollingContext = detectWhenSplitUiMode(editor, popups.getMothership().element);
  29226. optScrollingContext.each(sc => {
  29227. popupSinkBounds = () => {
  29228. return getBoundsFrom(sc);
  29229. };
  29230. });
  29231. return renderResult;
  29232. };
  29233. Autocompleter.register(editor, popups.backstage.shared);
  29234. const windowMgr = setup({
  29235. editor,
  29236. backstages: {
  29237. popup: popups.backstage,
  29238. dialog: dialogs.backstage
  29239. }
  29240. });
  29241. const getNotificationManagerImpl = () => NotificationManagerImpl(editor, { backstage: popups.backstage }, popups.getMothership());
  29242. return {
  29243. renderUI,
  29244. getWindowManagerImpl: constant$1(windowMgr),
  29245. getNotificationManagerImpl
  29246. };
  29247. });
  29248. };
  29249. Theme();
  29250. })();