model.js 287 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353235423552356235723582359236023612362236323642365236623672368236923702371237223732374237523762377237823792380238123822383238423852386238723882389239023912392239323942395239623972398239924002401240224032404240524062407240824092410241124122413241424152416241724182419242024212422242324242425242624272428242924302431243224332434243524362437243824392440244124422443244424452446244724482449245024512452245324542455245624572458245924602461246224632464246524662467246824692470247124722473247424752476247724782479248024812482248324842485248624872488248924902491249224932494249524962497249824992500250125022503250425052506250725082509251025112512251325142515251625172518251925202521252225232524252525262527252825292530253125322533253425352536253725382539254025412542254325442545254625472548254925502551255225532554255525562557255825592560256125622563256425652566256725682569257025712572257325742575257625772578257925802581258225832584258525862587258825892590259125922593259425952596259725982599260026012602260326042605260626072608260926102611261226132614261526162617261826192620262126222623262426252626262726282629263026312632263326342635263626372638263926402641264226432644264526462647264826492650265126522653265426552656265726582659266026612662266326642665266626672668266926702671267226732674267526762677267826792680268126822683268426852686268726882689269026912692269326942695269626972698269927002701270227032704270527062707270827092710271127122713271427152716271727182719272027212722272327242725272627272728272927302731273227332734273527362737273827392740274127422743274427452746274727482749275027512752275327542755275627572758275927602761276227632764276527662767276827692770277127722773277427752776277727782779278027812782278327842785278627872788278927902791279227932794279527962797279827992800280128022803280428052806280728082809281028112812281328142815281628172818281928202821282228232824282528262827282828292830283128322833283428352836283728382839284028412842284328442845284628472848284928502851285228532854285528562857285828592860286128622863286428652866286728682869287028712872287328742875287628772878287928802881288228832884288528862887288828892890289128922893289428952896289728982899290029012902290329042905290629072908290929102911291229132914291529162917291829192920292129222923292429252926292729282929293029312932293329342935293629372938293929402941294229432944294529462947294829492950295129522953295429552956295729582959296029612962296329642965296629672968296929702971297229732974297529762977297829792980298129822983298429852986298729882989299029912992299329942995299629972998299930003001300230033004300530063007300830093010301130123013301430153016301730183019302030213022302330243025302630273028302930303031303230333034303530363037303830393040304130423043304430453046304730483049305030513052305330543055305630573058305930603061306230633064306530663067306830693070307130723073307430753076307730783079308030813082308330843085308630873088308930903091309230933094309530963097309830993100310131023103310431053106310731083109311031113112311331143115311631173118311931203121312231233124312531263127312831293130313131323133313431353136313731383139314031413142314331443145314631473148314931503151315231533154315531563157315831593160316131623163316431653166316731683169317031713172317331743175317631773178317931803181318231833184318531863187318831893190319131923193319431953196319731983199320032013202320332043205320632073208320932103211321232133214321532163217321832193220322132223223322432253226322732283229323032313232323332343235323632373238323932403241324232433244324532463247324832493250325132523253325432553256325732583259326032613262326332643265326632673268326932703271327232733274327532763277327832793280328132823283328432853286328732883289329032913292329332943295329632973298329933003301330233033304330533063307330833093310331133123313331433153316331733183319332033213322332333243325332633273328332933303331333233333334333533363337333833393340334133423343334433453346334733483349335033513352335333543355335633573358335933603361336233633364336533663367336833693370337133723373337433753376337733783379338033813382338333843385338633873388338933903391339233933394339533963397339833993400340134023403340434053406340734083409341034113412341334143415341634173418341934203421342234233424342534263427342834293430343134323433343434353436343734383439344034413442344334443445344634473448344934503451345234533454345534563457345834593460346134623463346434653466346734683469347034713472347334743475347634773478347934803481348234833484348534863487348834893490349134923493349434953496349734983499350035013502350335043505350635073508350935103511351235133514351535163517351835193520352135223523352435253526352735283529353035313532353335343535353635373538353935403541354235433544354535463547354835493550355135523553355435553556355735583559356035613562356335643565356635673568356935703571357235733574357535763577357835793580358135823583358435853586358735883589359035913592359335943595359635973598359936003601360236033604360536063607360836093610361136123613361436153616361736183619362036213622362336243625362636273628362936303631363236333634363536363637363836393640364136423643364436453646364736483649365036513652365336543655365636573658365936603661366236633664366536663667366836693670367136723673367436753676367736783679368036813682368336843685368636873688368936903691369236933694369536963697369836993700370137023703370437053706370737083709371037113712371337143715371637173718371937203721372237233724372537263727372837293730373137323733373437353736373737383739374037413742374337443745374637473748374937503751375237533754375537563757375837593760376137623763376437653766376737683769377037713772377337743775377637773778377937803781378237833784378537863787378837893790379137923793379437953796379737983799380038013802380338043805380638073808380938103811381238133814381538163817381838193820382138223823382438253826382738283829383038313832383338343835383638373838383938403841384238433844384538463847384838493850385138523853385438553856385738583859386038613862386338643865386638673868386938703871387238733874387538763877387838793880388138823883388438853886388738883889389038913892389338943895389638973898389939003901390239033904390539063907390839093910391139123913391439153916391739183919392039213922392339243925392639273928392939303931393239333934393539363937393839393940394139423943394439453946394739483949395039513952395339543955395639573958395939603961396239633964396539663967396839693970397139723973397439753976397739783979398039813982398339843985398639873988398939903991399239933994399539963997399839994000400140024003400440054006400740084009401040114012401340144015401640174018401940204021402240234024402540264027402840294030403140324033403440354036403740384039404040414042404340444045404640474048404940504051405240534054405540564057405840594060406140624063406440654066406740684069407040714072407340744075407640774078407940804081408240834084408540864087408840894090409140924093409440954096409740984099410041014102410341044105410641074108410941104111411241134114411541164117411841194120412141224123412441254126412741284129413041314132413341344135413641374138413941404141414241434144414541464147414841494150415141524153415441554156415741584159416041614162416341644165416641674168416941704171417241734174417541764177417841794180418141824183418441854186418741884189419041914192419341944195419641974198419942004201420242034204420542064207420842094210421142124213421442154216421742184219422042214222422342244225422642274228422942304231423242334234423542364237423842394240424142424243424442454246424742484249425042514252425342544255425642574258425942604261426242634264426542664267426842694270427142724273427442754276427742784279428042814282428342844285428642874288428942904291429242934294429542964297429842994300430143024303430443054306430743084309431043114312431343144315431643174318431943204321432243234324432543264327432843294330433143324333433443354336433743384339434043414342434343444345434643474348434943504351435243534354435543564357435843594360436143624363436443654366436743684369437043714372437343744375437643774378437943804381438243834384438543864387438843894390439143924393439443954396439743984399440044014402440344044405440644074408440944104411441244134414441544164417441844194420442144224423442444254426442744284429443044314432443344344435443644374438443944404441444244434444444544464447444844494450445144524453445444554456445744584459446044614462446344644465446644674468446944704471447244734474447544764477447844794480448144824483448444854486448744884489449044914492449344944495449644974498449945004501450245034504450545064507450845094510451145124513451445154516451745184519452045214522452345244525452645274528452945304531453245334534453545364537453845394540454145424543454445454546454745484549455045514552455345544555455645574558455945604561456245634564456545664567456845694570457145724573457445754576457745784579458045814582458345844585458645874588458945904591459245934594459545964597459845994600460146024603460446054606460746084609461046114612461346144615461646174618461946204621462246234624462546264627462846294630463146324633463446354636463746384639464046414642464346444645464646474648464946504651465246534654465546564657465846594660466146624663466446654666466746684669467046714672467346744675467646774678467946804681468246834684468546864687468846894690469146924693469446954696469746984699470047014702470347044705470647074708470947104711471247134714471547164717471847194720472147224723472447254726472747284729473047314732473347344735473647374738473947404741474247434744474547464747474847494750475147524753475447554756475747584759476047614762476347644765476647674768476947704771477247734774477547764777477847794780478147824783478447854786478747884789479047914792479347944795479647974798479948004801480248034804480548064807480848094810481148124813481448154816481748184819482048214822482348244825482648274828482948304831483248334834483548364837483848394840484148424843484448454846484748484849485048514852485348544855485648574858485948604861486248634864486548664867486848694870487148724873487448754876487748784879488048814882488348844885488648874888488948904891489248934894489548964897489848994900490149024903490449054906490749084909491049114912491349144915491649174918491949204921492249234924492549264927492849294930493149324933493449354936493749384939494049414942494349444945494649474948494949504951495249534954495549564957495849594960496149624963496449654966496749684969497049714972497349744975497649774978497949804981498249834984498549864987498849894990499149924993499449954996499749984999500050015002500350045005500650075008500950105011501250135014501550165017501850195020502150225023502450255026502750285029503050315032503350345035503650375038503950405041504250435044504550465047504850495050505150525053505450555056505750585059506050615062506350645065506650675068506950705071507250735074507550765077507850795080508150825083508450855086508750885089509050915092509350945095509650975098509951005101510251035104510551065107510851095110511151125113511451155116511751185119512051215122512351245125512651275128512951305131513251335134513551365137513851395140514151425143514451455146514751485149515051515152515351545155515651575158515951605161516251635164516551665167516851695170517151725173517451755176517751785179518051815182518351845185518651875188518951905191519251935194519551965197519851995200520152025203520452055206520752085209521052115212521352145215521652175218521952205221522252235224522552265227522852295230523152325233523452355236523752385239524052415242524352445245524652475248524952505251525252535254525552565257525852595260526152625263526452655266526752685269527052715272527352745275527652775278527952805281528252835284528552865287528852895290529152925293529452955296529752985299530053015302530353045305530653075308530953105311531253135314531553165317531853195320532153225323532453255326532753285329533053315332533353345335533653375338533953405341534253435344534553465347534853495350535153525353535453555356535753585359536053615362536353645365536653675368536953705371537253735374537553765377537853795380538153825383538453855386538753885389539053915392539353945395539653975398539954005401540254035404540554065407540854095410541154125413541454155416541754185419542054215422542354245425542654275428542954305431543254335434543554365437543854395440544154425443544454455446544754485449545054515452545354545455545654575458545954605461546254635464546554665467546854695470547154725473547454755476547754785479548054815482548354845485548654875488548954905491549254935494549554965497549854995500550155025503550455055506550755085509551055115512551355145515551655175518551955205521552255235524552555265527552855295530553155325533553455355536553755385539554055415542554355445545554655475548554955505551555255535554555555565557555855595560556155625563556455655566556755685569557055715572557355745575557655775578557955805581558255835584558555865587558855895590559155925593559455955596559755985599560056015602560356045605560656075608560956105611561256135614561556165617561856195620562156225623562456255626562756285629563056315632563356345635563656375638563956405641564256435644564556465647564856495650565156525653565456555656565756585659566056615662566356645665566656675668566956705671567256735674567556765677567856795680568156825683568456855686568756885689569056915692569356945695569656975698569957005701570257035704570557065707570857095710571157125713571457155716571757185719572057215722572357245725572657275728572957305731573257335734573557365737573857395740574157425743574457455746574757485749575057515752575357545755575657575758575957605761576257635764576557665767576857695770577157725773577457755776577757785779578057815782578357845785578657875788578957905791579257935794579557965797579857995800580158025803580458055806580758085809581058115812581358145815581658175818581958205821582258235824582558265827582858295830583158325833583458355836583758385839584058415842584358445845584658475848584958505851585258535854585558565857585858595860586158625863586458655866586758685869587058715872587358745875587658775878587958805881588258835884588558865887588858895890589158925893589458955896589758985899590059015902590359045905590659075908590959105911591259135914591559165917591859195920592159225923592459255926592759285929593059315932593359345935593659375938593959405941594259435944594559465947594859495950595159525953595459555956595759585959596059615962596359645965596659675968596959705971597259735974597559765977597859795980598159825983598459855986598759885989599059915992599359945995599659975998599960006001600260036004600560066007600860096010601160126013601460156016601760186019602060216022602360246025602660276028602960306031603260336034603560366037603860396040604160426043604460456046604760486049605060516052605360546055605660576058605960606061606260636064606560666067606860696070607160726073607460756076607760786079608060816082608360846085608660876088608960906091609260936094609560966097609860996100610161026103610461056106610761086109611061116112611361146115611661176118611961206121612261236124612561266127612861296130613161326133613461356136613761386139614061416142614361446145614661476148614961506151615261536154615561566157615861596160616161626163616461656166616761686169617061716172617361746175617661776178617961806181618261836184618561866187618861896190619161926193619461956196619761986199620062016202620362046205620662076208620962106211621262136214621562166217621862196220622162226223622462256226622762286229623062316232623362346235623662376238623962406241624262436244624562466247624862496250625162526253625462556256625762586259626062616262626362646265626662676268626962706271627262736274627562766277627862796280628162826283628462856286628762886289629062916292629362946295629662976298629963006301630263036304630563066307630863096310631163126313631463156316631763186319632063216322632363246325632663276328632963306331633263336334633563366337633863396340634163426343634463456346634763486349635063516352635363546355635663576358635963606361636263636364636563666367636863696370637163726373637463756376637763786379638063816382638363846385638663876388638963906391639263936394639563966397639863996400640164026403640464056406640764086409641064116412641364146415641664176418641964206421642264236424642564266427642864296430643164326433643464356436643764386439644064416442644364446445644664476448644964506451645264536454645564566457645864596460646164626463646464656466646764686469647064716472647364746475647664776478647964806481648264836484648564866487648864896490649164926493649464956496649764986499650065016502650365046505650665076508650965106511651265136514651565166517651865196520652165226523652465256526652765286529653065316532653365346535653665376538653965406541654265436544654565466547654865496550655165526553655465556556655765586559656065616562656365646565656665676568656965706571657265736574657565766577657865796580658165826583658465856586658765886589659065916592659365946595659665976598659966006601660266036604660566066607660866096610661166126613661466156616661766186619662066216622662366246625662666276628662966306631663266336634663566366637663866396640664166426643664466456646664766486649665066516652665366546655665666576658665966606661666266636664666566666667666866696670667166726673667466756676667766786679668066816682668366846685668666876688668966906691669266936694669566966697669866996700670167026703670467056706670767086709671067116712671367146715671667176718671967206721672267236724672567266727672867296730673167326733673467356736673767386739674067416742674367446745674667476748674967506751675267536754675567566757675867596760676167626763676467656766676767686769677067716772677367746775677667776778677967806781678267836784678567866787678867896790679167926793679467956796679767986799680068016802680368046805680668076808680968106811681268136814681568166817681868196820682168226823682468256826682768286829683068316832683368346835683668376838683968406841684268436844684568466847684868496850685168526853685468556856685768586859686068616862686368646865686668676868686968706871687268736874687568766877687868796880688168826883688468856886688768886889689068916892689368946895689668976898689969006901690269036904690569066907690869096910691169126913691469156916691769186919692069216922692369246925692669276928692969306931693269336934693569366937693869396940694169426943694469456946694769486949695069516952695369546955695669576958695969606961696269636964696569666967696869696970697169726973697469756976697769786979698069816982698369846985698669876988698969906991699269936994699569966997699869997000700170027003700470057006700770087009701070117012701370147015701670177018701970207021702270237024702570267027702870297030703170327033703470357036703770387039704070417042704370447045704670477048704970507051705270537054705570567057705870597060706170627063706470657066706770687069707070717072707370747075707670777078707970807081708270837084708570867087708870897090709170927093709470957096709770987099710071017102710371047105710671077108710971107111711271137114711571167117711871197120712171227123712471257126712771287129713071317132713371347135713671377138713971407141714271437144714571467147714871497150715171527153715471557156715771587159716071617162716371647165716671677168716971707171717271737174717571767177717871797180718171827183718471857186718771887189719071917192719371947195719671977198719972007201720272037204720572067207720872097210721172127213721472157216721772187219722072217222722372247225722672277228722972307231723272337234723572367237723872397240724172427243724472457246724772487249725072517252725372547255725672577258725972607261726272637264726572667267726872697270727172727273727472757276727772787279728072817282728372847285728672877288728972907291729272937294729572967297729872997300730173027303730473057306730773087309731073117312731373147315731673177318731973207321732273237324732573267327732873297330733173327333733473357336733773387339734073417342734373447345734673477348734973507351735273537354735573567357735873597360736173627363736473657366736773687369737073717372737373747375737673777378737973807381738273837384738573867387738873897390739173927393739473957396739773987399740074017402740374047405740674077408740974107411741274137414741574167417741874197420742174227423742474257426742774287429743074317432743374347435743674377438743974407441744274437444744574467447744874497450745174527453745474557456745774587459746074617462746374647465746674677468746974707471747274737474747574767477747874797480748174827483748474857486748774887489749074917492749374947495749674977498749975007501750275037504750575067507750875097510751175127513751475157516751775187519752075217522752375247525752675277528752975307531753275337534753575367537753875397540754175427543754475457546754775487549755075517552755375547555755675577558755975607561756275637564756575667567756875697570757175727573757475757576757775787579758075817582758375847585758675877588758975907591759275937594759575967597759875997600760176027603760476057606760776087609761076117612761376147615761676177618761976207621762276237624762576267627762876297630763176327633763476357636763776387639764076417642764376447645764676477648764976507651765276537654765576567657765876597660766176627663766476657666766776687669767076717672767376747675767676777678767976807681768276837684768576867687768876897690769176927693769476957696769776987699770077017702770377047705770677077708770977107711771277137714771577167717771877197720772177227723772477257726772777287729773077317732773377347735773677377738773977407741774277437744774577467747774877497750775177527753775477557756775777587759776077617762776377647765776677677768776977707771777277737774777577767777777877797780778177827783778477857786778777887789779077917792779377947795779677977798779978007801780278037804780578067807780878097810781178127813781478157816781778187819782078217822782378247825782678277828782978307831783278337834783578367837783878397840784178427843784478457846784778487849785078517852785378547855785678577858785978607861786278637864786578667867786878697870787178727873787478757876787778787879788078817882788378847885788678877888788978907891789278937894789578967897789878997900790179027903790479057906790779087909791079117912791379147915791679177918791979207921792279237924792579267927792879297930793179327933793479357936793779387939794079417942794379447945794679477948794979507951795279537954795579567957795879597960796179627963796479657966796779687969797079717972797379747975797679777978797979807981798279837984798579867987798879897990799179927993799479957996799779987999800080018002800380048005800680078008800980108011801280138014801580168017801880198020802180228023802480258026802780288029803080318032803380348035
  1. /**
  2. * TinyMCE version 6.4.2 (2023-04-26)
  3. */
  4. (function () {
  5. 'use strict';
  6. var global$1 = tinymce.util.Tools.resolve('tinymce.ModelManager');
  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$2 = t => a => t === a;
  30. const isString = isType$1('string');
  31. const isObject = isType$1('object');
  32. const isArray = isType$1('array');
  33. const isNull = eq$2(null);
  34. const isBoolean = isSimpleType('boolean');
  35. const isUndefined = eq$2(undefined);
  36. const isNullable = a => a === null || a === undefined;
  37. const isNonNullable = a => !isNullable(a);
  38. const isFunction = isSimpleType('function');
  39. const isNumber = isSimpleType('number');
  40. const noop = () => {
  41. };
  42. const compose = (fa, fb) => {
  43. return (...args) => {
  44. return fa(fb.apply(null, args));
  45. };
  46. };
  47. const compose1 = (fbc, fab) => a => fbc(fab(a));
  48. const constant = value => {
  49. return () => {
  50. return value;
  51. };
  52. };
  53. const identity = x => {
  54. return x;
  55. };
  56. const tripleEquals = (a, b) => {
  57. return a === b;
  58. };
  59. function curry(fn, ...initialArgs) {
  60. return (...restArgs) => {
  61. const all = initialArgs.concat(restArgs);
  62. return fn.apply(null, all);
  63. };
  64. }
  65. const not = f => t => !f(t);
  66. const die = msg => {
  67. return () => {
  68. throw new Error(msg);
  69. };
  70. };
  71. const apply = f => {
  72. return f();
  73. };
  74. const never = constant(false);
  75. const always = constant(true);
  76. class Optional {
  77. constructor(tag, value) {
  78. this.tag = tag;
  79. this.value = value;
  80. }
  81. static some(value) {
  82. return new Optional(true, value);
  83. }
  84. static none() {
  85. return Optional.singletonNone;
  86. }
  87. fold(onNone, onSome) {
  88. if (this.tag) {
  89. return onSome(this.value);
  90. } else {
  91. return onNone();
  92. }
  93. }
  94. isSome() {
  95. return this.tag;
  96. }
  97. isNone() {
  98. return !this.tag;
  99. }
  100. map(mapper) {
  101. if (this.tag) {
  102. return Optional.some(mapper(this.value));
  103. } else {
  104. return Optional.none();
  105. }
  106. }
  107. bind(binder) {
  108. if (this.tag) {
  109. return binder(this.value);
  110. } else {
  111. return Optional.none();
  112. }
  113. }
  114. exists(predicate) {
  115. return this.tag && predicate(this.value);
  116. }
  117. forall(predicate) {
  118. return !this.tag || predicate(this.value);
  119. }
  120. filter(predicate) {
  121. if (!this.tag || predicate(this.value)) {
  122. return this;
  123. } else {
  124. return Optional.none();
  125. }
  126. }
  127. getOr(replacement) {
  128. return this.tag ? this.value : replacement;
  129. }
  130. or(replacement) {
  131. return this.tag ? this : replacement;
  132. }
  133. getOrThunk(thunk) {
  134. return this.tag ? this.value : thunk();
  135. }
  136. orThunk(thunk) {
  137. return this.tag ? this : thunk();
  138. }
  139. getOrDie(message) {
  140. if (!this.tag) {
  141. throw new Error(message !== null && message !== void 0 ? message : 'Called getOrDie on None');
  142. } else {
  143. return this.value;
  144. }
  145. }
  146. static from(value) {
  147. return isNonNullable(value) ? Optional.some(value) : Optional.none();
  148. }
  149. getOrNull() {
  150. return this.tag ? this.value : null;
  151. }
  152. getOrUndefined() {
  153. return this.value;
  154. }
  155. each(worker) {
  156. if (this.tag) {
  157. worker(this.value);
  158. }
  159. }
  160. toArray() {
  161. return this.tag ? [this.value] : [];
  162. }
  163. toString() {
  164. return this.tag ? `some(${ this.value })` : 'none()';
  165. }
  166. }
  167. Optional.singletonNone = new Optional(false);
  168. const nativeSlice = Array.prototype.slice;
  169. const nativeIndexOf = Array.prototype.indexOf;
  170. const nativePush = Array.prototype.push;
  171. const rawIndexOf = (ts, t) => nativeIndexOf.call(ts, t);
  172. const contains$2 = (xs, x) => rawIndexOf(xs, x) > -1;
  173. const exists = (xs, pred) => {
  174. for (let i = 0, len = xs.length; i < len; i++) {
  175. const x = xs[i];
  176. if (pred(x, i)) {
  177. return true;
  178. }
  179. }
  180. return false;
  181. };
  182. const range$1 = (num, f) => {
  183. const r = [];
  184. for (let i = 0; i < num; i++) {
  185. r.push(f(i));
  186. }
  187. return r;
  188. };
  189. const map$1 = (xs, f) => {
  190. const len = xs.length;
  191. const r = new Array(len);
  192. for (let i = 0; i < len; i++) {
  193. const x = xs[i];
  194. r[i] = f(x, i);
  195. }
  196. return r;
  197. };
  198. const each$2 = (xs, f) => {
  199. for (let i = 0, len = xs.length; i < len; i++) {
  200. const x = xs[i];
  201. f(x, i);
  202. }
  203. };
  204. const eachr = (xs, f) => {
  205. for (let i = xs.length - 1; i >= 0; i--) {
  206. const x = xs[i];
  207. f(x, i);
  208. }
  209. };
  210. const partition = (xs, pred) => {
  211. const pass = [];
  212. const fail = [];
  213. for (let i = 0, len = xs.length; i < len; i++) {
  214. const x = xs[i];
  215. const arr = pred(x, i) ? pass : fail;
  216. arr.push(x);
  217. }
  218. return {
  219. pass,
  220. fail
  221. };
  222. };
  223. const filter$2 = (xs, pred) => {
  224. const r = [];
  225. for (let i = 0, len = xs.length; i < len; i++) {
  226. const x = xs[i];
  227. if (pred(x, i)) {
  228. r.push(x);
  229. }
  230. }
  231. return r;
  232. };
  233. const foldr = (xs, f, acc) => {
  234. eachr(xs, (x, i) => {
  235. acc = f(acc, x, i);
  236. });
  237. return acc;
  238. };
  239. const foldl = (xs, f, acc) => {
  240. each$2(xs, (x, i) => {
  241. acc = f(acc, x, i);
  242. });
  243. return acc;
  244. };
  245. const findUntil = (xs, pred, until) => {
  246. for (let i = 0, len = xs.length; i < len; i++) {
  247. const x = xs[i];
  248. if (pred(x, i)) {
  249. return Optional.some(x);
  250. } else if (until(x, i)) {
  251. break;
  252. }
  253. }
  254. return Optional.none();
  255. };
  256. const find$1 = (xs, pred) => {
  257. return findUntil(xs, pred, never);
  258. };
  259. const findIndex = (xs, pred) => {
  260. for (let i = 0, len = xs.length; i < len; i++) {
  261. const x = xs[i];
  262. if (pred(x, i)) {
  263. return Optional.some(i);
  264. }
  265. }
  266. return Optional.none();
  267. };
  268. const flatten = xs => {
  269. const r = [];
  270. for (let i = 0, len = xs.length; i < len; ++i) {
  271. if (!isArray(xs[i])) {
  272. throw new Error('Arr.flatten item ' + i + ' was not an array, input: ' + xs);
  273. }
  274. nativePush.apply(r, xs[i]);
  275. }
  276. return r;
  277. };
  278. const bind$2 = (xs, f) => flatten(map$1(xs, f));
  279. const forall = (xs, pred) => {
  280. for (let i = 0, len = xs.length; i < len; ++i) {
  281. const x = xs[i];
  282. if (pred(x, i) !== true) {
  283. return false;
  284. }
  285. }
  286. return true;
  287. };
  288. const reverse = xs => {
  289. const r = nativeSlice.call(xs, 0);
  290. r.reverse();
  291. return r;
  292. };
  293. const mapToObject = (xs, f) => {
  294. const r = {};
  295. for (let i = 0, len = xs.length; i < len; i++) {
  296. const x = xs[i];
  297. r[String(x)] = f(x, i);
  298. }
  299. return r;
  300. };
  301. const sort$1 = (xs, comparator) => {
  302. const copy = nativeSlice.call(xs, 0);
  303. copy.sort(comparator);
  304. return copy;
  305. };
  306. const get$d = (xs, i) => i >= 0 && i < xs.length ? Optional.some(xs[i]) : Optional.none();
  307. const head = xs => get$d(xs, 0);
  308. const last$2 = xs => get$d(xs, xs.length - 1);
  309. const findMap = (arr, f) => {
  310. for (let i = 0; i < arr.length; i++) {
  311. const r = f(arr[i], i);
  312. if (r.isSome()) {
  313. return r;
  314. }
  315. }
  316. return Optional.none();
  317. };
  318. const keys = Object.keys;
  319. const hasOwnProperty = Object.hasOwnProperty;
  320. const each$1 = (obj, f) => {
  321. const props = keys(obj);
  322. for (let k = 0, len = props.length; k < len; k++) {
  323. const i = props[k];
  324. const x = obj[i];
  325. f(x, i);
  326. }
  327. };
  328. const map = (obj, f) => {
  329. return tupleMap(obj, (x, i) => ({
  330. k: i,
  331. v: f(x, i)
  332. }));
  333. };
  334. const tupleMap = (obj, f) => {
  335. const r = {};
  336. each$1(obj, (x, i) => {
  337. const tuple = f(x, i);
  338. r[tuple.k] = tuple.v;
  339. });
  340. return r;
  341. };
  342. const objAcc = r => (x, i) => {
  343. r[i] = x;
  344. };
  345. const internalFilter = (obj, pred, onTrue, onFalse) => {
  346. each$1(obj, (x, i) => {
  347. (pred(x, i) ? onTrue : onFalse)(x, i);
  348. });
  349. };
  350. const filter$1 = (obj, pred) => {
  351. const t = {};
  352. internalFilter(obj, pred, objAcc(t), noop);
  353. return t;
  354. };
  355. const mapToArray = (obj, f) => {
  356. const r = [];
  357. each$1(obj, (value, name) => {
  358. r.push(f(value, name));
  359. });
  360. return r;
  361. };
  362. const values = obj => {
  363. return mapToArray(obj, identity);
  364. };
  365. const get$c = (obj, key) => {
  366. return has$1(obj, key) ? Optional.from(obj[key]) : Optional.none();
  367. };
  368. const has$1 = (obj, key) => hasOwnProperty.call(obj, key);
  369. const hasNonNullableKey = (obj, key) => has$1(obj, key) && obj[key] !== undefined && obj[key] !== null;
  370. const isEmpty = r => {
  371. for (const x in r) {
  372. if (hasOwnProperty.call(r, x)) {
  373. return false;
  374. }
  375. }
  376. return true;
  377. };
  378. const Global = typeof window !== 'undefined' ? window : Function('return this;')();
  379. const path = (parts, scope) => {
  380. let o = scope !== undefined && scope !== null ? scope : Global;
  381. for (let i = 0; i < parts.length && o !== undefined && o !== null; ++i) {
  382. o = o[parts[i]];
  383. }
  384. return o;
  385. };
  386. const resolve$2 = (p, scope) => {
  387. const parts = p.split('.');
  388. return path(parts, scope);
  389. };
  390. const unsafe = (name, scope) => {
  391. return resolve$2(name, scope);
  392. };
  393. const getOrDie = (name, scope) => {
  394. const actual = unsafe(name, scope);
  395. if (actual === undefined || actual === null) {
  396. throw new Error(name + ' not available on this browser');
  397. }
  398. return actual;
  399. };
  400. const getPrototypeOf = Object.getPrototypeOf;
  401. const sandHTMLElement = scope => {
  402. return getOrDie('HTMLElement', scope);
  403. };
  404. const isPrototypeOf = x => {
  405. const scope = resolve$2('ownerDocument.defaultView', x);
  406. return isObject(x) && (sandHTMLElement(scope).prototype.isPrototypeOf(x) || /^HTML\w*Element$/.test(getPrototypeOf(x).constructor.name));
  407. };
  408. const COMMENT = 8;
  409. const DOCUMENT = 9;
  410. const DOCUMENT_FRAGMENT = 11;
  411. const ELEMENT = 1;
  412. const TEXT = 3;
  413. const name = element => {
  414. const r = element.dom.nodeName;
  415. return r.toLowerCase();
  416. };
  417. const type = element => element.dom.nodeType;
  418. const isType = t => element => type(element) === t;
  419. const isComment = element => type(element) === COMMENT || name(element) === '#comment';
  420. const isHTMLElement = element => isElement(element) && isPrototypeOf(element.dom);
  421. const isElement = isType(ELEMENT);
  422. const isText = isType(TEXT);
  423. const isDocument = isType(DOCUMENT);
  424. const isDocumentFragment = isType(DOCUMENT_FRAGMENT);
  425. const isTag = tag => e => isElement(e) && name(e) === tag;
  426. const rawSet = (dom, key, value) => {
  427. if (isString(value) || isBoolean(value) || isNumber(value)) {
  428. dom.setAttribute(key, value + '');
  429. } else {
  430. console.error('Invalid call to Attribute.set. Key ', key, ':: Value ', value, ':: Element ', dom);
  431. throw new Error('Attribute value was not simple');
  432. }
  433. };
  434. const set$2 = (element, key, value) => {
  435. rawSet(element.dom, key, value);
  436. };
  437. const setAll$1 = (element, attrs) => {
  438. const dom = element.dom;
  439. each$1(attrs, (v, k) => {
  440. rawSet(dom, k, v);
  441. });
  442. };
  443. const setOptions = (element, attrs) => {
  444. each$1(attrs, (v, k) => {
  445. v.fold(() => {
  446. remove$7(element, k);
  447. }, value => {
  448. rawSet(element.dom, k, value);
  449. });
  450. });
  451. };
  452. const get$b = (element, key) => {
  453. const v = element.dom.getAttribute(key);
  454. return v === null ? undefined : v;
  455. };
  456. const getOpt = (element, key) => Optional.from(get$b(element, key));
  457. const remove$7 = (element, key) => {
  458. element.dom.removeAttribute(key);
  459. };
  460. const clone$2 = element => foldl(element.dom.attributes, (acc, attr) => {
  461. acc[attr.name] = attr.value;
  462. return acc;
  463. }, {});
  464. const fromHtml$1 = (html, scope) => {
  465. const doc = scope || document;
  466. const div = doc.createElement('div');
  467. div.innerHTML = html;
  468. if (!div.hasChildNodes() || div.childNodes.length > 1) {
  469. const message = 'HTML does not have a single root node';
  470. console.error(message, html);
  471. throw new Error(message);
  472. }
  473. return fromDom$1(div.childNodes[0]);
  474. };
  475. const fromTag = (tag, scope) => {
  476. const doc = scope || document;
  477. const node = doc.createElement(tag);
  478. return fromDom$1(node);
  479. };
  480. const fromText = (text, scope) => {
  481. const doc = scope || document;
  482. const node = doc.createTextNode(text);
  483. return fromDom$1(node);
  484. };
  485. const fromDom$1 = node => {
  486. if (node === null || node === undefined) {
  487. throw new Error('Node cannot be null or undefined');
  488. }
  489. return { dom: node };
  490. };
  491. const fromPoint$1 = (docElm, x, y) => Optional.from(docElm.dom.elementFromPoint(x, y)).map(fromDom$1);
  492. const SugarElement = {
  493. fromHtml: fromHtml$1,
  494. fromTag,
  495. fromText,
  496. fromDom: fromDom$1,
  497. fromPoint: fromPoint$1
  498. };
  499. const is$2 = (element, selector) => {
  500. const dom = element.dom;
  501. if (dom.nodeType !== ELEMENT) {
  502. return false;
  503. } else {
  504. const elem = dom;
  505. if (elem.matches !== undefined) {
  506. return elem.matches(selector);
  507. } else if (elem.msMatchesSelector !== undefined) {
  508. return elem.msMatchesSelector(selector);
  509. } else if (elem.webkitMatchesSelector !== undefined) {
  510. return elem.webkitMatchesSelector(selector);
  511. } else if (elem.mozMatchesSelector !== undefined) {
  512. return elem.mozMatchesSelector(selector);
  513. } else {
  514. throw new Error('Browser lacks native selectors');
  515. }
  516. }
  517. };
  518. const bypassSelector = dom => dom.nodeType !== ELEMENT && dom.nodeType !== DOCUMENT && dom.nodeType !== DOCUMENT_FRAGMENT || dom.childElementCount === 0;
  519. const all$1 = (selector, scope) => {
  520. const base = scope === undefined ? document : scope.dom;
  521. return bypassSelector(base) ? [] : map$1(base.querySelectorAll(selector), SugarElement.fromDom);
  522. };
  523. const one = (selector, scope) => {
  524. const base = scope === undefined ? document : scope.dom;
  525. return bypassSelector(base) ? Optional.none() : Optional.from(base.querySelector(selector)).map(SugarElement.fromDom);
  526. };
  527. const eq$1 = (e1, e2) => e1.dom === e2.dom;
  528. const contains$1 = (e1, e2) => {
  529. const d1 = e1.dom;
  530. const d2 = e2.dom;
  531. return d1 === d2 ? false : d1.contains(d2);
  532. };
  533. const is$1 = is$2;
  534. const owner = element => SugarElement.fromDom(element.dom.ownerDocument);
  535. const documentOrOwner = dos => isDocument(dos) ? dos : owner(dos);
  536. const documentElement = element => SugarElement.fromDom(documentOrOwner(element).dom.documentElement);
  537. const defaultView = element => SugarElement.fromDom(documentOrOwner(element).dom.defaultView);
  538. const parent = element => Optional.from(element.dom.parentNode).map(SugarElement.fromDom);
  539. const parentElement = element => Optional.from(element.dom.parentElement).map(SugarElement.fromDom);
  540. const parents = (element, isRoot) => {
  541. const stop = isFunction(isRoot) ? isRoot : never;
  542. let dom = element.dom;
  543. const ret = [];
  544. while (dom.parentNode !== null && dom.parentNode !== undefined) {
  545. const rawParent = dom.parentNode;
  546. const p = SugarElement.fromDom(rawParent);
  547. ret.push(p);
  548. if (stop(p) === true) {
  549. break;
  550. } else {
  551. dom = rawParent;
  552. }
  553. }
  554. return ret;
  555. };
  556. const prevSibling = element => Optional.from(element.dom.previousSibling).map(SugarElement.fromDom);
  557. const nextSibling = element => Optional.from(element.dom.nextSibling).map(SugarElement.fromDom);
  558. const children$2 = element => map$1(element.dom.childNodes, SugarElement.fromDom);
  559. const child$2 = (element, index) => {
  560. const cs = element.dom.childNodes;
  561. return Optional.from(cs[index]).map(SugarElement.fromDom);
  562. };
  563. const firstChild = element => child$2(element, 0);
  564. const before$3 = (marker, element) => {
  565. const parent$1 = parent(marker);
  566. parent$1.each(v => {
  567. v.dom.insertBefore(element.dom, marker.dom);
  568. });
  569. };
  570. const after$5 = (marker, element) => {
  571. const sibling = nextSibling(marker);
  572. sibling.fold(() => {
  573. const parent$1 = parent(marker);
  574. parent$1.each(v => {
  575. append$1(v, element);
  576. });
  577. }, v => {
  578. before$3(v, element);
  579. });
  580. };
  581. const prepend = (parent, element) => {
  582. const firstChild$1 = firstChild(parent);
  583. firstChild$1.fold(() => {
  584. append$1(parent, element);
  585. }, v => {
  586. parent.dom.insertBefore(element.dom, v.dom);
  587. });
  588. };
  589. const append$1 = (parent, element) => {
  590. parent.dom.appendChild(element.dom);
  591. };
  592. const appendAt = (parent, element, index) => {
  593. child$2(parent, index).fold(() => {
  594. append$1(parent, element);
  595. }, v => {
  596. before$3(v, element);
  597. });
  598. };
  599. const wrap = (element, wrapper) => {
  600. before$3(element, wrapper);
  601. append$1(wrapper, element);
  602. };
  603. const after$4 = (marker, elements) => {
  604. each$2(elements, (x, i) => {
  605. const e = i === 0 ? marker : elements[i - 1];
  606. after$5(e, x);
  607. });
  608. };
  609. const append = (parent, elements) => {
  610. each$2(elements, x => {
  611. append$1(parent, x);
  612. });
  613. };
  614. const empty = element => {
  615. element.dom.textContent = '';
  616. each$2(children$2(element), rogue => {
  617. remove$6(rogue);
  618. });
  619. };
  620. const remove$6 = element => {
  621. const dom = element.dom;
  622. if (dom.parentNode !== null) {
  623. dom.parentNode.removeChild(dom);
  624. }
  625. };
  626. const unwrap = wrapper => {
  627. const children = children$2(wrapper);
  628. if (children.length > 0) {
  629. after$4(wrapper, children);
  630. }
  631. remove$6(wrapper);
  632. };
  633. const clone$1 = (original, isDeep) => SugarElement.fromDom(original.dom.cloneNode(isDeep));
  634. const shallow = original => clone$1(original, false);
  635. const deep = original => clone$1(original, true);
  636. const shallowAs = (original, tag) => {
  637. const nu = SugarElement.fromTag(tag);
  638. const attributes = clone$2(original);
  639. setAll$1(nu, attributes);
  640. return nu;
  641. };
  642. const copy$2 = (original, tag) => {
  643. const nu = shallowAs(original, tag);
  644. const cloneChildren = children$2(deep(original));
  645. append(nu, cloneChildren);
  646. return nu;
  647. };
  648. const mutate$1 = (original, tag) => {
  649. const nu = shallowAs(original, tag);
  650. after$5(original, nu);
  651. const children = children$2(original);
  652. append(nu, children);
  653. remove$6(original);
  654. return nu;
  655. };
  656. const validSectionList = [
  657. 'tfoot',
  658. 'thead',
  659. 'tbody',
  660. 'colgroup'
  661. ];
  662. const isValidSection = parentName => contains$2(validSectionList, parentName);
  663. const grid = (rows, columns) => ({
  664. rows,
  665. columns
  666. });
  667. const address = (row, column) => ({
  668. row,
  669. column
  670. });
  671. const detail = (element, rowspan, colspan) => ({
  672. element,
  673. rowspan,
  674. colspan
  675. });
  676. const detailnew = (element, rowspan, colspan, isNew) => ({
  677. element,
  678. rowspan,
  679. colspan,
  680. isNew
  681. });
  682. const extended = (element, rowspan, colspan, row, column, isLocked) => ({
  683. element,
  684. rowspan,
  685. colspan,
  686. row,
  687. column,
  688. isLocked
  689. });
  690. const rowdetail = (element, cells, section) => ({
  691. element,
  692. cells,
  693. section
  694. });
  695. const rowdetailnew = (element, cells, section, isNew) => ({
  696. element,
  697. cells,
  698. section,
  699. isNew
  700. });
  701. const elementnew = (element, isNew, isLocked) => ({
  702. element,
  703. isNew,
  704. isLocked
  705. });
  706. const rowcells = (element, cells, section, isNew) => ({
  707. element,
  708. cells,
  709. section,
  710. isNew
  711. });
  712. const bounds = (startRow, startCol, finishRow, finishCol) => ({
  713. startRow,
  714. startCol,
  715. finishRow,
  716. finishCol
  717. });
  718. const columnext = (element, colspan, column) => ({
  719. element,
  720. colspan,
  721. column
  722. });
  723. const colgroup = (element, columns) => ({
  724. element,
  725. columns
  726. });
  727. const isShadowRoot = dos => isDocumentFragment(dos) && isNonNullable(dos.dom.host);
  728. const supported = isFunction(Element.prototype.attachShadow) && isFunction(Node.prototype.getRootNode);
  729. const isSupported$1 = constant(supported);
  730. const getRootNode = supported ? e => SugarElement.fromDom(e.dom.getRootNode()) : documentOrOwner;
  731. const getShadowRoot = e => {
  732. const r = getRootNode(e);
  733. return isShadowRoot(r) ? Optional.some(r) : Optional.none();
  734. };
  735. const getShadowHost = e => SugarElement.fromDom(e.dom.host);
  736. const getOriginalEventTarget = event => {
  737. if (isSupported$1() && isNonNullable(event.target)) {
  738. const el = SugarElement.fromDom(event.target);
  739. if (isElement(el) && isOpenShadowHost(el)) {
  740. if (event.composed && event.composedPath) {
  741. const composedPath = event.composedPath();
  742. if (composedPath) {
  743. return head(composedPath);
  744. }
  745. }
  746. }
  747. }
  748. return Optional.from(event.target);
  749. };
  750. const isOpenShadowHost = element => isNonNullable(element.dom.shadowRoot);
  751. const inBody = element => {
  752. const dom = isText(element) ? element.dom.parentNode : element.dom;
  753. if (dom === undefined || dom === null || dom.ownerDocument === null) {
  754. return false;
  755. }
  756. const doc = dom.ownerDocument;
  757. return getShadowRoot(SugarElement.fromDom(dom)).fold(() => doc.body.contains(dom), compose1(inBody, getShadowHost));
  758. };
  759. const body$1 = () => getBody$1(SugarElement.fromDom(document));
  760. const getBody$1 = doc => {
  761. const b = doc.dom.body;
  762. if (b === null || b === undefined) {
  763. throw new Error('Body is not available yet');
  764. }
  765. return SugarElement.fromDom(b);
  766. };
  767. const ancestors$4 = (scope, predicate, isRoot) => filter$2(parents(scope, isRoot), predicate);
  768. const children$1 = (scope, predicate) => filter$2(children$2(scope), predicate);
  769. const descendants$1 = (scope, predicate) => {
  770. let result = [];
  771. each$2(children$2(scope), x => {
  772. if (predicate(x)) {
  773. result = result.concat([x]);
  774. }
  775. result = result.concat(descendants$1(x, predicate));
  776. });
  777. return result;
  778. };
  779. const ancestors$3 = (scope, selector, isRoot) => ancestors$4(scope, e => is$2(e, selector), isRoot);
  780. const children = (scope, selector) => children$1(scope, e => is$2(e, selector));
  781. const descendants = (scope, selector) => all$1(selector, scope);
  782. var ClosestOrAncestor = (is, ancestor, scope, a, isRoot) => {
  783. if (is(scope, a)) {
  784. return Optional.some(scope);
  785. } else if (isFunction(isRoot) && isRoot(scope)) {
  786. return Optional.none();
  787. } else {
  788. return ancestor(scope, a, isRoot);
  789. }
  790. };
  791. const ancestor$2 = (scope, predicate, isRoot) => {
  792. let element = scope.dom;
  793. const stop = isFunction(isRoot) ? isRoot : never;
  794. while (element.parentNode) {
  795. element = element.parentNode;
  796. const el = SugarElement.fromDom(element);
  797. if (predicate(el)) {
  798. return Optional.some(el);
  799. } else if (stop(el)) {
  800. break;
  801. }
  802. }
  803. return Optional.none();
  804. };
  805. const closest$2 = (scope, predicate, isRoot) => {
  806. const is = (s, test) => test(s);
  807. return ClosestOrAncestor(is, ancestor$2, scope, predicate, isRoot);
  808. };
  809. const child$1 = (scope, predicate) => {
  810. const pred = node => predicate(SugarElement.fromDom(node));
  811. const result = find$1(scope.dom.childNodes, pred);
  812. return result.map(SugarElement.fromDom);
  813. };
  814. const descendant$1 = (scope, predicate) => {
  815. const descend = node => {
  816. for (let i = 0; i < node.childNodes.length; i++) {
  817. const child = SugarElement.fromDom(node.childNodes[i]);
  818. if (predicate(child)) {
  819. return Optional.some(child);
  820. }
  821. const res = descend(node.childNodes[i]);
  822. if (res.isSome()) {
  823. return res;
  824. }
  825. }
  826. return Optional.none();
  827. };
  828. return descend(scope.dom);
  829. };
  830. const ancestor$1 = (scope, selector, isRoot) => ancestor$2(scope, e => is$2(e, selector), isRoot);
  831. const child = (scope, selector) => child$1(scope, e => is$2(e, selector));
  832. const descendant = (scope, selector) => one(selector, scope);
  833. const closest$1 = (scope, selector, isRoot) => {
  834. const is = (element, selector) => is$2(element, selector);
  835. return ClosestOrAncestor(is, ancestor$1, scope, selector, isRoot);
  836. };
  837. const is = (lhs, rhs, comparator = tripleEquals) => lhs.exists(left => comparator(left, rhs));
  838. const cat = arr => {
  839. const r = [];
  840. const push = x => {
  841. r.push(x);
  842. };
  843. for (let i = 0; i < arr.length; i++) {
  844. arr[i].each(push);
  845. }
  846. return r;
  847. };
  848. const bindFrom = (a, f) => a !== undefined && a !== null ? f(a) : Optional.none();
  849. const someIf = (b, a) => b ? Optional.some(a) : Optional.none();
  850. const checkRange = (str, substr, start) => substr === '' || str.length >= substr.length && str.substr(start, start + substr.length) === substr;
  851. const contains = (str, substr, start = 0, end) => {
  852. const idx = str.indexOf(substr, start);
  853. if (idx !== -1) {
  854. return isUndefined(end) ? true : idx + substr.length <= end;
  855. } else {
  856. return false;
  857. }
  858. };
  859. const startsWith = (str, prefix) => {
  860. return checkRange(str, prefix, 0);
  861. };
  862. const endsWith = (str, suffix) => {
  863. return checkRange(str, suffix, str.length - suffix.length);
  864. };
  865. const blank = r => s => s.replace(r, '');
  866. const trim = blank(/^\s+|\s+$/g);
  867. const isNotEmpty = s => s.length > 0;
  868. const toFloat = value => {
  869. const num = parseFloat(value);
  870. return isNaN(num) ? Optional.none() : Optional.some(num);
  871. };
  872. const isSupported = dom => dom.style !== undefined && isFunction(dom.style.getPropertyValue);
  873. const internalSet = (dom, property, value) => {
  874. if (!isString(value)) {
  875. console.error('Invalid call to CSS.set. Property ', property, ':: Value ', value, ':: Element ', dom);
  876. throw new Error('CSS value must be a string: ' + value);
  877. }
  878. if (isSupported(dom)) {
  879. dom.style.setProperty(property, value);
  880. }
  881. };
  882. const internalRemove = (dom, property) => {
  883. if (isSupported(dom)) {
  884. dom.style.removeProperty(property);
  885. }
  886. };
  887. const set$1 = (element, property, value) => {
  888. const dom = element.dom;
  889. internalSet(dom, property, value);
  890. };
  891. const setAll = (element, css) => {
  892. const dom = element.dom;
  893. each$1(css, (v, k) => {
  894. internalSet(dom, k, v);
  895. });
  896. };
  897. const get$a = (element, property) => {
  898. const dom = element.dom;
  899. const styles = window.getComputedStyle(dom);
  900. const r = styles.getPropertyValue(property);
  901. return r === '' && !inBody(element) ? getUnsafeProperty(dom, property) : r;
  902. };
  903. const getUnsafeProperty = (dom, property) => isSupported(dom) ? dom.style.getPropertyValue(property) : '';
  904. const getRaw$2 = (element, property) => {
  905. const dom = element.dom;
  906. const raw = getUnsafeProperty(dom, property);
  907. return Optional.from(raw).filter(r => r.length > 0);
  908. };
  909. const remove$5 = (element, property) => {
  910. const dom = element.dom;
  911. internalRemove(dom, property);
  912. if (is(getOpt(element, 'style').map(trim), '')) {
  913. remove$7(element, 'style');
  914. }
  915. };
  916. const copy$1 = (source, target) => {
  917. const sourceDom = source.dom;
  918. const targetDom = target.dom;
  919. if (isSupported(sourceDom) && isSupported(targetDom)) {
  920. targetDom.style.cssText = sourceDom.style.cssText;
  921. }
  922. };
  923. const getAttrValue = (cell, name, fallback = 0) => getOpt(cell, name).map(value => parseInt(value, 10)).getOr(fallback);
  924. const getSpan = (cell, type) => getAttrValue(cell, type, 1);
  925. const hasColspan = cellOrCol => {
  926. if (isTag('col')(cellOrCol)) {
  927. return getAttrValue(cellOrCol, 'span', 1) > 1;
  928. } else {
  929. return getSpan(cellOrCol, 'colspan') > 1;
  930. }
  931. };
  932. const hasRowspan = cell => getSpan(cell, 'rowspan') > 1;
  933. const getCssValue = (element, property) => parseInt(get$a(element, property), 10);
  934. const minWidth = constant(10);
  935. const minHeight = constant(10);
  936. const firstLayer = (scope, selector) => {
  937. return filterFirstLayer(scope, selector, always);
  938. };
  939. const filterFirstLayer = (scope, selector, predicate) => {
  940. return bind$2(children$2(scope), x => {
  941. if (is$2(x, selector)) {
  942. return predicate(x) ? [x] : [];
  943. } else {
  944. return filterFirstLayer(x, selector, predicate);
  945. }
  946. });
  947. };
  948. const lookup = (tags, element, isRoot = never) => {
  949. if (isRoot(element)) {
  950. return Optional.none();
  951. }
  952. if (contains$2(tags, name(element))) {
  953. return Optional.some(element);
  954. }
  955. const isRootOrUpperTable = elm => is$2(elm, 'table') || isRoot(elm);
  956. return ancestor$1(element, tags.join(','), isRootOrUpperTable);
  957. };
  958. const cell = (element, isRoot) => lookup([
  959. 'td',
  960. 'th'
  961. ], element, isRoot);
  962. const cells$1 = ancestor => firstLayer(ancestor, 'th,td');
  963. const columns$1 = ancestor => {
  964. if (is$2(ancestor, 'colgroup')) {
  965. return children(ancestor, 'col');
  966. } else {
  967. return bind$2(columnGroups(ancestor), columnGroup => children(columnGroup, 'col'));
  968. }
  969. };
  970. const table = (element, isRoot) => closest$1(element, 'table', isRoot);
  971. const rows$1 = ancestor => firstLayer(ancestor, 'tr');
  972. const columnGroups = ancestor => table(ancestor).fold(constant([]), table => children(table, 'colgroup'));
  973. const fromRowsOrColGroups = (elems, getSection) => map$1(elems, row => {
  974. if (name(row) === 'colgroup') {
  975. const cells = map$1(columns$1(row), column => {
  976. const colspan = getAttrValue(column, 'span', 1);
  977. return detail(column, 1, colspan);
  978. });
  979. return rowdetail(row, cells, 'colgroup');
  980. } else {
  981. const cells = map$1(cells$1(row), cell => {
  982. const rowspan = getAttrValue(cell, 'rowspan', 1);
  983. const colspan = getAttrValue(cell, 'colspan', 1);
  984. return detail(cell, rowspan, colspan);
  985. });
  986. return rowdetail(row, cells, getSection(row));
  987. }
  988. });
  989. const getParentSection = group => parent(group).map(parent => {
  990. const parentName = name(parent);
  991. return isValidSection(parentName) ? parentName : 'tbody';
  992. }).getOr('tbody');
  993. const fromTable$1 = table => {
  994. const rows = rows$1(table);
  995. const columnGroups$1 = columnGroups(table);
  996. const elems = [
  997. ...columnGroups$1,
  998. ...rows
  999. ];
  1000. return fromRowsOrColGroups(elems, getParentSection);
  1001. };
  1002. const fromPastedRows = (elems, section) => fromRowsOrColGroups(elems, () => section);
  1003. const cached = f => {
  1004. let called = false;
  1005. let r;
  1006. return (...args) => {
  1007. if (!called) {
  1008. called = true;
  1009. r = f.apply(null, args);
  1010. }
  1011. return r;
  1012. };
  1013. };
  1014. const DeviceType = (os, browser, userAgent, mediaMatch) => {
  1015. const isiPad = os.isiOS() && /ipad/i.test(userAgent) === true;
  1016. const isiPhone = os.isiOS() && !isiPad;
  1017. const isMobile = os.isiOS() || os.isAndroid();
  1018. const isTouch = isMobile || mediaMatch('(pointer:coarse)');
  1019. const isTablet = isiPad || !isiPhone && isMobile && mediaMatch('(min-device-width:768px)');
  1020. const isPhone = isiPhone || isMobile && !isTablet;
  1021. const iOSwebview = browser.isSafari() && os.isiOS() && /safari/i.test(userAgent) === false;
  1022. const isDesktop = !isPhone && !isTablet && !iOSwebview;
  1023. return {
  1024. isiPad: constant(isiPad),
  1025. isiPhone: constant(isiPhone),
  1026. isTablet: constant(isTablet),
  1027. isPhone: constant(isPhone),
  1028. isTouch: constant(isTouch),
  1029. isAndroid: os.isAndroid,
  1030. isiOS: os.isiOS,
  1031. isWebView: constant(iOSwebview),
  1032. isDesktop: constant(isDesktop)
  1033. };
  1034. };
  1035. const firstMatch = (regexes, s) => {
  1036. for (let i = 0; i < regexes.length; i++) {
  1037. const x = regexes[i];
  1038. if (x.test(s)) {
  1039. return x;
  1040. }
  1041. }
  1042. return undefined;
  1043. };
  1044. const find = (regexes, agent) => {
  1045. const r = firstMatch(regexes, agent);
  1046. if (!r) {
  1047. return {
  1048. major: 0,
  1049. minor: 0
  1050. };
  1051. }
  1052. const group = i => {
  1053. return Number(agent.replace(r, '$' + i));
  1054. };
  1055. return nu$2(group(1), group(2));
  1056. };
  1057. const detect$5 = (versionRegexes, agent) => {
  1058. const cleanedAgent = String(agent).toLowerCase();
  1059. if (versionRegexes.length === 0) {
  1060. return unknown$2();
  1061. }
  1062. return find(versionRegexes, cleanedAgent);
  1063. };
  1064. const unknown$2 = () => {
  1065. return nu$2(0, 0);
  1066. };
  1067. const nu$2 = (major, minor) => {
  1068. return {
  1069. major,
  1070. minor
  1071. };
  1072. };
  1073. const Version = {
  1074. nu: nu$2,
  1075. detect: detect$5,
  1076. unknown: unknown$2
  1077. };
  1078. const detectBrowser$1 = (browsers, userAgentData) => {
  1079. return findMap(userAgentData.brands, uaBrand => {
  1080. const lcBrand = uaBrand.brand.toLowerCase();
  1081. return find$1(browsers, browser => {
  1082. var _a;
  1083. return lcBrand === ((_a = browser.brand) === null || _a === void 0 ? void 0 : _a.toLowerCase());
  1084. }).map(info => ({
  1085. current: info.name,
  1086. version: Version.nu(parseInt(uaBrand.version, 10), 0)
  1087. }));
  1088. });
  1089. };
  1090. const detect$4 = (candidates, userAgent) => {
  1091. const agent = String(userAgent).toLowerCase();
  1092. return find$1(candidates, candidate => {
  1093. return candidate.search(agent);
  1094. });
  1095. };
  1096. const detectBrowser = (browsers, userAgent) => {
  1097. return detect$4(browsers, userAgent).map(browser => {
  1098. const version = Version.detect(browser.versionRegexes, userAgent);
  1099. return {
  1100. current: browser.name,
  1101. version
  1102. };
  1103. });
  1104. };
  1105. const detectOs = (oses, userAgent) => {
  1106. return detect$4(oses, userAgent).map(os => {
  1107. const version = Version.detect(os.versionRegexes, userAgent);
  1108. return {
  1109. current: os.name,
  1110. version
  1111. };
  1112. });
  1113. };
  1114. const normalVersionRegex = /.*?version\/\ ?([0-9]+)\.([0-9]+).*/;
  1115. const checkContains = target => {
  1116. return uastring => {
  1117. return contains(uastring, target);
  1118. };
  1119. };
  1120. const browsers = [
  1121. {
  1122. name: 'Edge',
  1123. versionRegexes: [/.*?edge\/ ?([0-9]+)\.([0-9]+)$/],
  1124. search: uastring => {
  1125. return contains(uastring, 'edge/') && contains(uastring, 'chrome') && contains(uastring, 'safari') && contains(uastring, 'applewebkit');
  1126. }
  1127. },
  1128. {
  1129. name: 'Chromium',
  1130. brand: 'Chromium',
  1131. versionRegexes: [
  1132. /.*?chrome\/([0-9]+)\.([0-9]+).*/,
  1133. normalVersionRegex
  1134. ],
  1135. search: uastring => {
  1136. return contains(uastring, 'chrome') && !contains(uastring, 'chromeframe');
  1137. }
  1138. },
  1139. {
  1140. name: 'IE',
  1141. versionRegexes: [
  1142. /.*?msie\ ?([0-9]+)\.([0-9]+).*/,
  1143. /.*?rv:([0-9]+)\.([0-9]+).*/
  1144. ],
  1145. search: uastring => {
  1146. return contains(uastring, 'msie') || contains(uastring, 'trident');
  1147. }
  1148. },
  1149. {
  1150. name: 'Opera',
  1151. versionRegexes: [
  1152. normalVersionRegex,
  1153. /.*?opera\/([0-9]+)\.([0-9]+).*/
  1154. ],
  1155. search: checkContains('opera')
  1156. },
  1157. {
  1158. name: 'Firefox',
  1159. versionRegexes: [/.*?firefox\/\ ?([0-9]+)\.([0-9]+).*/],
  1160. search: checkContains('firefox')
  1161. },
  1162. {
  1163. name: 'Safari',
  1164. versionRegexes: [
  1165. normalVersionRegex,
  1166. /.*?cpu os ([0-9]+)_([0-9]+).*/
  1167. ],
  1168. search: uastring => {
  1169. return (contains(uastring, 'safari') || contains(uastring, 'mobile/')) && contains(uastring, 'applewebkit');
  1170. }
  1171. }
  1172. ];
  1173. const oses = [
  1174. {
  1175. name: 'Windows',
  1176. search: checkContains('win'),
  1177. versionRegexes: [/.*?windows\ nt\ ?([0-9]+)\.([0-9]+).*/]
  1178. },
  1179. {
  1180. name: 'iOS',
  1181. search: uastring => {
  1182. return contains(uastring, 'iphone') || contains(uastring, 'ipad');
  1183. },
  1184. versionRegexes: [
  1185. /.*?version\/\ ?([0-9]+)\.([0-9]+).*/,
  1186. /.*cpu os ([0-9]+)_([0-9]+).*/,
  1187. /.*cpu iphone os ([0-9]+)_([0-9]+).*/
  1188. ]
  1189. },
  1190. {
  1191. name: 'Android',
  1192. search: checkContains('android'),
  1193. versionRegexes: [/.*?android\ ?([0-9]+)\.([0-9]+).*/]
  1194. },
  1195. {
  1196. name: 'macOS',
  1197. search: checkContains('mac os x'),
  1198. versionRegexes: [/.*?mac\ os\ x\ ?([0-9]+)_([0-9]+).*/]
  1199. },
  1200. {
  1201. name: 'Linux',
  1202. search: checkContains('linux'),
  1203. versionRegexes: []
  1204. },
  1205. {
  1206. name: 'Solaris',
  1207. search: checkContains('sunos'),
  1208. versionRegexes: []
  1209. },
  1210. {
  1211. name: 'FreeBSD',
  1212. search: checkContains('freebsd'),
  1213. versionRegexes: []
  1214. },
  1215. {
  1216. name: 'ChromeOS',
  1217. search: checkContains('cros'),
  1218. versionRegexes: [/.*?chrome\/([0-9]+)\.([0-9]+).*/]
  1219. }
  1220. ];
  1221. const PlatformInfo = {
  1222. browsers: constant(browsers),
  1223. oses: constant(oses)
  1224. };
  1225. const edge = 'Edge';
  1226. const chromium = 'Chromium';
  1227. const ie = 'IE';
  1228. const opera = 'Opera';
  1229. const firefox = 'Firefox';
  1230. const safari = 'Safari';
  1231. const unknown$1 = () => {
  1232. return nu$1({
  1233. current: undefined,
  1234. version: Version.unknown()
  1235. });
  1236. };
  1237. const nu$1 = info => {
  1238. const current = info.current;
  1239. const version = info.version;
  1240. const isBrowser = name => () => current === name;
  1241. return {
  1242. current,
  1243. version,
  1244. isEdge: isBrowser(edge),
  1245. isChromium: isBrowser(chromium),
  1246. isIE: isBrowser(ie),
  1247. isOpera: isBrowser(opera),
  1248. isFirefox: isBrowser(firefox),
  1249. isSafari: isBrowser(safari)
  1250. };
  1251. };
  1252. const Browser = {
  1253. unknown: unknown$1,
  1254. nu: nu$1,
  1255. edge: constant(edge),
  1256. chromium: constant(chromium),
  1257. ie: constant(ie),
  1258. opera: constant(opera),
  1259. firefox: constant(firefox),
  1260. safari: constant(safari)
  1261. };
  1262. const windows = 'Windows';
  1263. const ios = 'iOS';
  1264. const android = 'Android';
  1265. const linux = 'Linux';
  1266. const macos = 'macOS';
  1267. const solaris = 'Solaris';
  1268. const freebsd = 'FreeBSD';
  1269. const chromeos = 'ChromeOS';
  1270. const unknown = () => {
  1271. return nu({
  1272. current: undefined,
  1273. version: Version.unknown()
  1274. });
  1275. };
  1276. const nu = info => {
  1277. const current = info.current;
  1278. const version = info.version;
  1279. const isOS = name => () => current === name;
  1280. return {
  1281. current,
  1282. version,
  1283. isWindows: isOS(windows),
  1284. isiOS: isOS(ios),
  1285. isAndroid: isOS(android),
  1286. isMacOS: isOS(macos),
  1287. isLinux: isOS(linux),
  1288. isSolaris: isOS(solaris),
  1289. isFreeBSD: isOS(freebsd),
  1290. isChromeOS: isOS(chromeos)
  1291. };
  1292. };
  1293. const OperatingSystem = {
  1294. unknown,
  1295. nu,
  1296. windows: constant(windows),
  1297. ios: constant(ios),
  1298. android: constant(android),
  1299. linux: constant(linux),
  1300. macos: constant(macos),
  1301. solaris: constant(solaris),
  1302. freebsd: constant(freebsd),
  1303. chromeos: constant(chromeos)
  1304. };
  1305. const detect$3 = (userAgent, userAgentDataOpt, mediaMatch) => {
  1306. const browsers = PlatformInfo.browsers();
  1307. const oses = PlatformInfo.oses();
  1308. const browser = userAgentDataOpt.bind(userAgentData => detectBrowser$1(browsers, userAgentData)).orThunk(() => detectBrowser(browsers, userAgent)).fold(Browser.unknown, Browser.nu);
  1309. const os = detectOs(oses, userAgent).fold(OperatingSystem.unknown, OperatingSystem.nu);
  1310. const deviceType = DeviceType(os, browser, userAgent, mediaMatch);
  1311. return {
  1312. browser,
  1313. os,
  1314. deviceType
  1315. };
  1316. };
  1317. const PlatformDetection = { detect: detect$3 };
  1318. const mediaMatch = query => window.matchMedia(query).matches;
  1319. let platform = cached(() => PlatformDetection.detect(navigator.userAgent, Optional.from(navigator.userAgentData), mediaMatch));
  1320. const detect$2 = () => platform();
  1321. const Dimension = (name, getOffset) => {
  1322. const set = (element, h) => {
  1323. if (!isNumber(h) && !h.match(/^[0-9]+$/)) {
  1324. throw new Error(name + '.set accepts only positive integer values. Value was ' + h);
  1325. }
  1326. const dom = element.dom;
  1327. if (isSupported(dom)) {
  1328. dom.style[name] = h + 'px';
  1329. }
  1330. };
  1331. const get = element => {
  1332. const r = getOffset(element);
  1333. if (r <= 0 || r === null) {
  1334. const css = get$a(element, name);
  1335. return parseFloat(css) || 0;
  1336. }
  1337. return r;
  1338. };
  1339. const getOuter = get;
  1340. const aggregate = (element, properties) => foldl(properties, (acc, property) => {
  1341. const val = get$a(element, property);
  1342. const value = val === undefined ? 0 : parseInt(val, 10);
  1343. return isNaN(value) ? acc : acc + value;
  1344. }, 0);
  1345. const max = (element, value, properties) => {
  1346. const cumulativeInclusions = aggregate(element, properties);
  1347. const absoluteMax = value > cumulativeInclusions ? value - cumulativeInclusions : 0;
  1348. return absoluteMax;
  1349. };
  1350. return {
  1351. set,
  1352. get,
  1353. getOuter,
  1354. aggregate,
  1355. max
  1356. };
  1357. };
  1358. const toNumber = (px, fallback) => toFloat(px).getOr(fallback);
  1359. const getProp = (element, name, fallback) => toNumber(get$a(element, name), fallback);
  1360. const calcContentBoxSize = (element, size, upper, lower) => {
  1361. const paddingUpper = getProp(element, `padding-${ upper }`, 0);
  1362. const paddingLower = getProp(element, `padding-${ lower }`, 0);
  1363. const borderUpper = getProp(element, `border-${ upper }-width`, 0);
  1364. const borderLower = getProp(element, `border-${ lower }-width`, 0);
  1365. return size - paddingUpper - paddingLower - borderUpper - borderLower;
  1366. };
  1367. const getCalculatedWidth = (element, boxSizing) => {
  1368. const dom = element.dom;
  1369. const width = dom.getBoundingClientRect().width || dom.offsetWidth;
  1370. return boxSizing === 'border-box' ? width : calcContentBoxSize(element, width, 'left', 'right');
  1371. };
  1372. const getHeight$1 = element => getProp(element, 'height', element.dom.offsetHeight);
  1373. const getWidth = element => getProp(element, 'width', element.dom.offsetWidth);
  1374. const getInnerWidth = element => getCalculatedWidth(element, 'content-box');
  1375. const api$2 = Dimension('width', element => element.dom.offsetWidth);
  1376. const get$9 = element => api$2.get(element);
  1377. const getOuter$2 = element => api$2.getOuter(element);
  1378. const getInner = getInnerWidth;
  1379. const getRuntime$1 = getWidth;
  1380. const addCells = (gridRow, index, cells) => {
  1381. const existingCells = gridRow.cells;
  1382. const before = existingCells.slice(0, index);
  1383. const after = existingCells.slice(index);
  1384. const newCells = before.concat(cells).concat(after);
  1385. return setCells(gridRow, newCells);
  1386. };
  1387. const addCell = (gridRow, index, cell) => addCells(gridRow, index, [cell]);
  1388. const mutateCell = (gridRow, index, cell) => {
  1389. const cells = gridRow.cells;
  1390. cells[index] = cell;
  1391. };
  1392. const setCells = (gridRow, cells) => rowcells(gridRow.element, cells, gridRow.section, gridRow.isNew);
  1393. const mapCells = (gridRow, f) => {
  1394. const cells = gridRow.cells;
  1395. const r = map$1(cells, f);
  1396. return rowcells(gridRow.element, r, gridRow.section, gridRow.isNew);
  1397. };
  1398. const getCell = (gridRow, index) => gridRow.cells[index];
  1399. const getCellElement = (gridRow, index) => getCell(gridRow, index).element;
  1400. const cellLength = gridRow => gridRow.cells.length;
  1401. const extractGridDetails = grid => {
  1402. const result = partition(grid, row => row.section === 'colgroup');
  1403. return {
  1404. rows: result.fail,
  1405. cols: result.pass
  1406. };
  1407. };
  1408. const clone = (gridRow, cloneRow, cloneCell) => {
  1409. const newCells = map$1(gridRow.cells, cloneCell);
  1410. return rowcells(cloneRow(gridRow.element), newCells, gridRow.section, true);
  1411. };
  1412. const LOCKED_COL_ATTR = 'data-snooker-locked-cols';
  1413. const getLockedColumnsFromTable = table => getOpt(table, LOCKED_COL_ATTR).bind(lockedColStr => Optional.from(lockedColStr.match(/\d+/g))).map(lockedCols => mapToObject(lockedCols, always));
  1414. const getLockedColumnsFromGrid = grid => {
  1415. const locked = foldl(extractGridDetails(grid).rows, (acc, row) => {
  1416. each$2(row.cells, (cell, idx) => {
  1417. if (cell.isLocked) {
  1418. acc[idx] = true;
  1419. }
  1420. });
  1421. return acc;
  1422. }, {});
  1423. const lockedArr = mapToArray(locked, (_val, key) => parseInt(key, 10));
  1424. return sort$1(lockedArr);
  1425. };
  1426. const key = (row, column) => {
  1427. return row + ',' + column;
  1428. };
  1429. const getAt = (warehouse, row, column) => Optional.from(warehouse.access[key(row, column)]);
  1430. const findItem = (warehouse, item, comparator) => {
  1431. const filtered = filterItems(warehouse, detail => {
  1432. return comparator(item, detail.element);
  1433. });
  1434. return filtered.length > 0 ? Optional.some(filtered[0]) : Optional.none();
  1435. };
  1436. const filterItems = (warehouse, predicate) => {
  1437. const all = bind$2(warehouse.all, r => {
  1438. return r.cells;
  1439. });
  1440. return filter$2(all, predicate);
  1441. };
  1442. const generateColumns = rowData => {
  1443. const columnsGroup = {};
  1444. let index = 0;
  1445. each$2(rowData.cells, column => {
  1446. const colspan = column.colspan;
  1447. range$1(colspan, columnIndex => {
  1448. const colIndex = index + columnIndex;
  1449. columnsGroup[colIndex] = columnext(column.element, colspan, colIndex);
  1450. });
  1451. index += colspan;
  1452. });
  1453. return columnsGroup;
  1454. };
  1455. const generate$1 = list => {
  1456. const access = {};
  1457. const cells = [];
  1458. const tableOpt = head(list).map(rowData => rowData.element).bind(table);
  1459. const lockedColumns = tableOpt.bind(getLockedColumnsFromTable).getOr({});
  1460. let maxRows = 0;
  1461. let maxColumns = 0;
  1462. let rowCount = 0;
  1463. const {
  1464. pass: colgroupRows,
  1465. fail: rows
  1466. } = partition(list, rowData => rowData.section === 'colgroup');
  1467. each$2(rows, rowData => {
  1468. const currentRow = [];
  1469. each$2(rowData.cells, rowCell => {
  1470. let start = 0;
  1471. while (access[key(rowCount, start)] !== undefined) {
  1472. start++;
  1473. }
  1474. const isLocked = hasNonNullableKey(lockedColumns, start.toString());
  1475. const current = extended(rowCell.element, rowCell.rowspan, rowCell.colspan, rowCount, start, isLocked);
  1476. for (let occupiedColumnPosition = 0; occupiedColumnPosition < rowCell.colspan; occupiedColumnPosition++) {
  1477. for (let occupiedRowPosition = 0; occupiedRowPosition < rowCell.rowspan; occupiedRowPosition++) {
  1478. const rowPosition = rowCount + occupiedRowPosition;
  1479. const columnPosition = start + occupiedColumnPosition;
  1480. const newpos = key(rowPosition, columnPosition);
  1481. access[newpos] = current;
  1482. maxColumns = Math.max(maxColumns, columnPosition + 1);
  1483. }
  1484. }
  1485. currentRow.push(current);
  1486. });
  1487. maxRows++;
  1488. cells.push(rowdetail(rowData.element, currentRow, rowData.section));
  1489. rowCount++;
  1490. });
  1491. const {columns, colgroups} = last$2(colgroupRows).map(rowData => {
  1492. const columns = generateColumns(rowData);
  1493. const colgroup$1 = colgroup(rowData.element, values(columns));
  1494. return {
  1495. colgroups: [colgroup$1],
  1496. columns
  1497. };
  1498. }).getOrThunk(() => ({
  1499. colgroups: [],
  1500. columns: {}
  1501. }));
  1502. const grid$1 = grid(maxRows, maxColumns);
  1503. return {
  1504. grid: grid$1,
  1505. access,
  1506. all: cells,
  1507. columns,
  1508. colgroups
  1509. };
  1510. };
  1511. const fromTable = table => {
  1512. const list = fromTable$1(table);
  1513. return generate$1(list);
  1514. };
  1515. const justCells = warehouse => bind$2(warehouse.all, w => w.cells);
  1516. const justColumns = warehouse => values(warehouse.columns);
  1517. const hasColumns = warehouse => keys(warehouse.columns).length > 0;
  1518. const getColumnAt = (warehouse, columnIndex) => Optional.from(warehouse.columns[columnIndex]);
  1519. const Warehouse = {
  1520. fromTable,
  1521. generate: generate$1,
  1522. getAt,
  1523. findItem,
  1524. filterItems,
  1525. justCells,
  1526. justColumns,
  1527. hasColumns,
  1528. getColumnAt
  1529. };
  1530. const columns = (warehouse, isValidCell = always) => {
  1531. const grid = warehouse.grid;
  1532. const cols = range$1(grid.columns, identity);
  1533. const rowsArr = range$1(grid.rows, identity);
  1534. return map$1(cols, col => {
  1535. const getBlock = () => bind$2(rowsArr, r => Warehouse.getAt(warehouse, r, col).filter(detail => detail.column === col).toArray());
  1536. const isValid = detail => detail.colspan === 1 && isValidCell(detail.element);
  1537. const getFallback = () => Warehouse.getAt(warehouse, 0, col);
  1538. return decide(getBlock, isValid, getFallback);
  1539. });
  1540. };
  1541. const decide = (getBlock, isValid, getFallback) => {
  1542. const inBlock = getBlock();
  1543. const validInBlock = find$1(inBlock, isValid);
  1544. const detailOption = validInBlock.orThunk(() => Optional.from(inBlock[0]).orThunk(getFallback));
  1545. return detailOption.map(detail => detail.element);
  1546. };
  1547. const rows = warehouse => {
  1548. const grid = warehouse.grid;
  1549. const rowsArr = range$1(grid.rows, identity);
  1550. const cols = range$1(grid.columns, identity);
  1551. return map$1(rowsArr, row => {
  1552. const getBlock = () => bind$2(cols, c => Warehouse.getAt(warehouse, row, c).filter(detail => detail.row === row).fold(constant([]), detail => [detail]));
  1553. const isSingle = detail => detail.rowspan === 1;
  1554. const getFallback = () => Warehouse.getAt(warehouse, row, 0);
  1555. return decide(getBlock, isSingle, getFallback);
  1556. });
  1557. };
  1558. const deduce = (xs, index) => {
  1559. if (index < 0 || index >= xs.length - 1) {
  1560. return Optional.none();
  1561. }
  1562. const current = xs[index].fold(() => {
  1563. const rest = reverse(xs.slice(0, index));
  1564. return findMap(rest, (a, i) => a.map(aa => ({
  1565. value: aa,
  1566. delta: i + 1
  1567. })));
  1568. }, c => Optional.some({
  1569. value: c,
  1570. delta: 0
  1571. }));
  1572. const next = xs[index + 1].fold(() => {
  1573. const rest = xs.slice(index + 1);
  1574. return findMap(rest, (a, i) => a.map(aa => ({
  1575. value: aa,
  1576. delta: i + 1
  1577. })));
  1578. }, n => Optional.some({
  1579. value: n,
  1580. delta: 1
  1581. }));
  1582. return current.bind(c => next.map(n => {
  1583. const extras = n.delta + c.delta;
  1584. return Math.abs(n.value - c.value) / extras;
  1585. }));
  1586. };
  1587. const onDirection = (isLtr, isRtl) => element => getDirection(element) === 'rtl' ? isRtl : isLtr;
  1588. const getDirection = element => get$a(element, 'direction') === 'rtl' ? 'rtl' : 'ltr';
  1589. const api$1 = Dimension('height', element => {
  1590. const dom = element.dom;
  1591. return inBody(element) ? dom.getBoundingClientRect().height : dom.offsetHeight;
  1592. });
  1593. const get$8 = element => api$1.get(element);
  1594. const getOuter$1 = element => api$1.getOuter(element);
  1595. const getRuntime = getHeight$1;
  1596. const r = (left, top) => {
  1597. const translate = (x, y) => r(left + x, top + y);
  1598. return {
  1599. left,
  1600. top,
  1601. translate
  1602. };
  1603. };
  1604. const SugarPosition = r;
  1605. const boxPosition = dom => {
  1606. const box = dom.getBoundingClientRect();
  1607. return SugarPosition(box.left, box.top);
  1608. };
  1609. const firstDefinedOrZero = (a, b) => {
  1610. if (a !== undefined) {
  1611. return a;
  1612. } else {
  1613. return b !== undefined ? b : 0;
  1614. }
  1615. };
  1616. const absolute = element => {
  1617. const doc = element.dom.ownerDocument;
  1618. const body = doc.body;
  1619. const win = doc.defaultView;
  1620. const html = doc.documentElement;
  1621. if (body === element.dom) {
  1622. return SugarPosition(body.offsetLeft, body.offsetTop);
  1623. }
  1624. const scrollTop = firstDefinedOrZero(win === null || win === void 0 ? void 0 : win.pageYOffset, html.scrollTop);
  1625. const scrollLeft = firstDefinedOrZero(win === null || win === void 0 ? void 0 : win.pageXOffset, html.scrollLeft);
  1626. const clientTop = firstDefinedOrZero(html.clientTop, body.clientTop);
  1627. const clientLeft = firstDefinedOrZero(html.clientLeft, body.clientLeft);
  1628. return viewport(element).translate(scrollLeft - clientLeft, scrollTop - clientTop);
  1629. };
  1630. const viewport = element => {
  1631. const dom = element.dom;
  1632. const doc = dom.ownerDocument;
  1633. const body = doc.body;
  1634. if (body === dom) {
  1635. return SugarPosition(body.offsetLeft, body.offsetTop);
  1636. }
  1637. if (!inBody(element)) {
  1638. return SugarPosition(0, 0);
  1639. }
  1640. return boxPosition(dom);
  1641. };
  1642. const rowInfo = (row, y) => ({
  1643. row,
  1644. y
  1645. });
  1646. const colInfo = (col, x) => ({
  1647. col,
  1648. x
  1649. });
  1650. const rtlEdge = cell => {
  1651. const pos = absolute(cell);
  1652. return pos.left + getOuter$2(cell);
  1653. };
  1654. const ltrEdge = cell => {
  1655. return absolute(cell).left;
  1656. };
  1657. const getLeftEdge = (index, cell) => {
  1658. return colInfo(index, ltrEdge(cell));
  1659. };
  1660. const getRightEdge = (index, cell) => {
  1661. return colInfo(index, rtlEdge(cell));
  1662. };
  1663. const getTop$1 = cell => {
  1664. return absolute(cell).top;
  1665. };
  1666. const getTopEdge = (index, cell) => {
  1667. return rowInfo(index, getTop$1(cell));
  1668. };
  1669. const getBottomEdge = (index, cell) => {
  1670. return rowInfo(index, getTop$1(cell) + getOuter$1(cell));
  1671. };
  1672. const findPositions = (getInnerEdge, getOuterEdge, array) => {
  1673. if (array.length === 0) {
  1674. return [];
  1675. }
  1676. const lines = map$1(array.slice(1), (cellOption, index) => {
  1677. return cellOption.map(cell => {
  1678. return getInnerEdge(index, cell);
  1679. });
  1680. });
  1681. const lastLine = array[array.length - 1].map(cell => {
  1682. return getOuterEdge(array.length - 1, cell);
  1683. });
  1684. return lines.concat([lastLine]);
  1685. };
  1686. const negate = step => {
  1687. return -step;
  1688. };
  1689. const height = {
  1690. delta: identity,
  1691. positions: optElements => findPositions(getTopEdge, getBottomEdge, optElements),
  1692. edge: getTop$1
  1693. };
  1694. const ltr$1 = {
  1695. delta: identity,
  1696. edge: ltrEdge,
  1697. positions: optElements => findPositions(getLeftEdge, getRightEdge, optElements)
  1698. };
  1699. const rtl$1 = {
  1700. delta: negate,
  1701. edge: rtlEdge,
  1702. positions: optElements => findPositions(getRightEdge, getLeftEdge, optElements)
  1703. };
  1704. const detect$1 = onDirection(ltr$1, rtl$1);
  1705. const width = {
  1706. delta: (amount, table) => detect$1(table).delta(amount, table),
  1707. positions: (cols, table) => detect$1(table).positions(cols, table),
  1708. edge: cell => detect$1(cell).edge(cell)
  1709. };
  1710. const units = {
  1711. unsupportedLength: [
  1712. 'em',
  1713. 'ex',
  1714. 'cap',
  1715. 'ch',
  1716. 'ic',
  1717. 'rem',
  1718. 'lh',
  1719. 'rlh',
  1720. 'vw',
  1721. 'vh',
  1722. 'vi',
  1723. 'vb',
  1724. 'vmin',
  1725. 'vmax',
  1726. 'cm',
  1727. 'mm',
  1728. 'Q',
  1729. 'in',
  1730. 'pc',
  1731. 'pt',
  1732. 'px'
  1733. ],
  1734. fixed: [
  1735. 'px',
  1736. 'pt'
  1737. ],
  1738. relative: ['%'],
  1739. empty: ['']
  1740. };
  1741. const pattern = (() => {
  1742. const decimalDigits = '[0-9]+';
  1743. const signedInteger = '[+-]?' + decimalDigits;
  1744. const exponentPart = '[eE]' + signedInteger;
  1745. const dot = '\\.';
  1746. const opt = input => `(?:${ input })?`;
  1747. const unsignedDecimalLiteral = [
  1748. 'Infinity',
  1749. decimalDigits + dot + opt(decimalDigits) + opt(exponentPart),
  1750. dot + decimalDigits + opt(exponentPart),
  1751. decimalDigits + opt(exponentPart)
  1752. ].join('|');
  1753. const float = `[+-]?(?:${ unsignedDecimalLiteral })`;
  1754. return new RegExp(`^(${ float })(.*)$`);
  1755. })();
  1756. const isUnit = (unit, accepted) => exists(accepted, acc => exists(units[acc], check => unit === check));
  1757. const parse = (input, accepted) => {
  1758. const match = Optional.from(pattern.exec(input));
  1759. return match.bind(array => {
  1760. const value = Number(array[1]);
  1761. const unitRaw = array[2];
  1762. if (isUnit(unitRaw, accepted)) {
  1763. return Optional.some({
  1764. value,
  1765. unit: unitRaw
  1766. });
  1767. } else {
  1768. return Optional.none();
  1769. }
  1770. });
  1771. };
  1772. const rPercentageBasedSizeRegex = /(\d+(\.\d+)?)%/;
  1773. const rPixelBasedSizeRegex = /(\d+(\.\d+)?)px|em/;
  1774. const isCol$2 = isTag('col');
  1775. const getPercentSize = (elm, outerGetter, innerGetter) => {
  1776. const relativeParent = parentElement(elm).getOrThunk(() => getBody$1(owner(elm)));
  1777. return outerGetter(elm) / innerGetter(relativeParent) * 100;
  1778. };
  1779. const setPixelWidth = (cell, amount) => {
  1780. set$1(cell, 'width', amount + 'px');
  1781. };
  1782. const setPercentageWidth = (cell, amount) => {
  1783. set$1(cell, 'width', amount + '%');
  1784. };
  1785. const setHeight = (cell, amount) => {
  1786. set$1(cell, 'height', amount + 'px');
  1787. };
  1788. const getHeightValue = cell => getRuntime(cell) + 'px';
  1789. const convert = (cell, number, getter, setter) => {
  1790. const newSize = table(cell).map(table => {
  1791. const total = getter(table);
  1792. return Math.floor(number / 100 * total);
  1793. }).getOr(number);
  1794. setter(cell, newSize);
  1795. return newSize;
  1796. };
  1797. const normalizePixelSize = (value, cell, getter, setter) => {
  1798. const number = parseFloat(value);
  1799. return endsWith(value, '%') && name(cell) !== 'table' ? convert(cell, number, getter, setter) : number;
  1800. };
  1801. const getTotalHeight = cell => {
  1802. const value = getHeightValue(cell);
  1803. if (!value) {
  1804. return get$8(cell);
  1805. }
  1806. return normalizePixelSize(value, cell, get$8, setHeight);
  1807. };
  1808. const get$7 = (cell, type, f) => {
  1809. const v = f(cell);
  1810. const span = getSpan(cell, type);
  1811. return v / span;
  1812. };
  1813. const getRaw$1 = (element, prop) => {
  1814. return getRaw$2(element, prop).orThunk(() => {
  1815. return getOpt(element, prop).map(val => val + 'px');
  1816. });
  1817. };
  1818. const getRawWidth$1 = element => getRaw$1(element, 'width');
  1819. const getRawHeight = element => getRaw$1(element, 'height');
  1820. const getPercentageWidth = cell => getPercentSize(cell, get$9, getInner);
  1821. const getPixelWidth$1 = cell => isCol$2(cell) ? get$9(cell) : getRuntime$1(cell);
  1822. const getHeight = cell => {
  1823. return get$7(cell, 'rowspan', getTotalHeight);
  1824. };
  1825. const getGenericWidth = cell => {
  1826. const width = getRawWidth$1(cell);
  1827. return width.bind(w => parse(w, [
  1828. 'fixed',
  1829. 'relative',
  1830. 'empty'
  1831. ]));
  1832. };
  1833. const setGenericWidth = (cell, amount, unit) => {
  1834. set$1(cell, 'width', amount + unit);
  1835. };
  1836. const getPixelTableWidth = table => get$9(table) + 'px';
  1837. const getPercentTableWidth = table => getPercentSize(table, get$9, getInner) + '%';
  1838. const isPercentSizing$1 = table => getRawWidth$1(table).exists(size => rPercentageBasedSizeRegex.test(size));
  1839. const isPixelSizing$1 = table => getRawWidth$1(table).exists(size => rPixelBasedSizeRegex.test(size));
  1840. const isNoneSizing$1 = table => getRawWidth$1(table).isNone();
  1841. const percentageBasedSizeRegex = constant(rPercentageBasedSizeRegex);
  1842. const isCol$1 = isTag('col');
  1843. const getRawW = cell => {
  1844. return getRawWidth$1(cell).getOrThunk(() => getPixelWidth$1(cell) + 'px');
  1845. };
  1846. const getRawH = cell => {
  1847. return getRawHeight(cell).getOrThunk(() => getHeight(cell) + 'px');
  1848. };
  1849. const justCols = warehouse => map$1(Warehouse.justColumns(warehouse), column => Optional.from(column.element));
  1850. const isValidColumn = cell => {
  1851. const browser = detect$2().browser;
  1852. const supportsColWidths = browser.isChromium() || browser.isFirefox();
  1853. return isCol$1(cell) ? supportsColWidths : true;
  1854. };
  1855. const getDimension = (cellOpt, index, backups, filter, getter, fallback) => cellOpt.filter(filter).fold(() => fallback(deduce(backups, index)), cell => getter(cell));
  1856. const getWidthFrom = (warehouse, table, getWidth, fallback) => {
  1857. const columnCells = columns(warehouse);
  1858. const columns$1 = Warehouse.hasColumns(warehouse) ? justCols(warehouse) : columnCells;
  1859. const backups = [Optional.some(width.edge(table))].concat(map$1(width.positions(columnCells, table), pos => pos.map(p => p.x)));
  1860. const colFilter = not(hasColspan);
  1861. return map$1(columns$1, (cellOption, c) => {
  1862. return getDimension(cellOption, c, backups, colFilter, column => {
  1863. if (isValidColumn(column)) {
  1864. return getWidth(column);
  1865. } else {
  1866. const cell = bindFrom(columnCells[c], identity);
  1867. return getDimension(cell, c, backups, colFilter, cell => fallback(Optional.some(get$9(cell))), fallback);
  1868. }
  1869. }, fallback);
  1870. });
  1871. };
  1872. const getDeduced = deduced => {
  1873. return deduced.map(d => {
  1874. return d + 'px';
  1875. }).getOr('');
  1876. };
  1877. const getRawWidths = (warehouse, table) => {
  1878. return getWidthFrom(warehouse, table, getRawW, getDeduced);
  1879. };
  1880. const getPercentageWidths = (warehouse, table, tableSize) => {
  1881. return getWidthFrom(warehouse, table, getPercentageWidth, deduced => {
  1882. return deduced.fold(() => {
  1883. return tableSize.minCellWidth();
  1884. }, cellWidth => {
  1885. return cellWidth / tableSize.pixelWidth() * 100;
  1886. });
  1887. });
  1888. };
  1889. const getPixelWidths = (warehouse, table, tableSize) => {
  1890. return getWidthFrom(warehouse, table, getPixelWidth$1, deduced => {
  1891. return deduced.getOrThunk(tableSize.minCellWidth);
  1892. });
  1893. };
  1894. const getHeightFrom = (warehouse, table, direction, getHeight, fallback) => {
  1895. const rows$1 = rows(warehouse);
  1896. const backups = [Optional.some(direction.edge(table))].concat(map$1(direction.positions(rows$1, table), pos => pos.map(p => p.y)));
  1897. return map$1(rows$1, (cellOption, c) => {
  1898. return getDimension(cellOption, c, backups, not(hasRowspan), getHeight, fallback);
  1899. });
  1900. };
  1901. const getPixelHeights = (warehouse, table, direction) => {
  1902. return getHeightFrom(warehouse, table, direction, getHeight, deduced => {
  1903. return deduced.getOrThunk(minHeight);
  1904. });
  1905. };
  1906. const getRawHeights = (warehouse, table, direction) => {
  1907. return getHeightFrom(warehouse, table, direction, getRawH, getDeduced);
  1908. };
  1909. const widthLookup = (table, getter) => () => {
  1910. if (inBody(table)) {
  1911. return getter(table);
  1912. } else {
  1913. return parseFloat(getRaw$2(table, 'width').getOr('0'));
  1914. }
  1915. };
  1916. const noneSize = table => {
  1917. const getWidth = widthLookup(table, get$9);
  1918. const zero = constant(0);
  1919. const getWidths = (warehouse, tableSize) => getPixelWidths(warehouse, table, tableSize);
  1920. return {
  1921. width: getWidth,
  1922. pixelWidth: getWidth,
  1923. getWidths,
  1924. getCellDelta: zero,
  1925. singleColumnWidth: constant([0]),
  1926. minCellWidth: zero,
  1927. setElementWidth: noop,
  1928. adjustTableWidth: noop,
  1929. isRelative: true,
  1930. label: 'none'
  1931. };
  1932. };
  1933. const percentageSize = table => {
  1934. const getFloatWidth = widthLookup(table, elem => parseFloat(getPercentTableWidth(elem)));
  1935. const getWidth = widthLookup(table, get$9);
  1936. const getCellDelta = delta => delta / getWidth() * 100;
  1937. const singleColumnWidth = (w, _delta) => [100 - w];
  1938. const minCellWidth = () => minWidth() / getWidth() * 100;
  1939. const adjustTableWidth = delta => {
  1940. const currentWidth = getFloatWidth();
  1941. const change = delta / 100 * currentWidth;
  1942. const newWidth = currentWidth + change;
  1943. setPercentageWidth(table, newWidth);
  1944. };
  1945. const getWidths = (warehouse, tableSize) => getPercentageWidths(warehouse, table, tableSize);
  1946. return {
  1947. width: getFloatWidth,
  1948. pixelWidth: getWidth,
  1949. getWidths,
  1950. getCellDelta,
  1951. singleColumnWidth,
  1952. minCellWidth,
  1953. setElementWidth: setPercentageWidth,
  1954. adjustTableWidth,
  1955. isRelative: true,
  1956. label: 'percent'
  1957. };
  1958. };
  1959. const pixelSize = table => {
  1960. const getWidth = widthLookup(table, get$9);
  1961. const getCellDelta = identity;
  1962. const singleColumnWidth = (w, delta) => {
  1963. const newNext = Math.max(minWidth(), w + delta);
  1964. return [newNext - w];
  1965. };
  1966. const adjustTableWidth = delta => {
  1967. const newWidth = getWidth() + delta;
  1968. setPixelWidth(table, newWidth);
  1969. };
  1970. const getWidths = (warehouse, tableSize) => getPixelWidths(warehouse, table, tableSize);
  1971. return {
  1972. width: getWidth,
  1973. pixelWidth: getWidth,
  1974. getWidths,
  1975. getCellDelta,
  1976. singleColumnWidth,
  1977. minCellWidth: minWidth,
  1978. setElementWidth: setPixelWidth,
  1979. adjustTableWidth,
  1980. isRelative: false,
  1981. label: 'pixel'
  1982. };
  1983. };
  1984. const chooseSize = (element, width) => {
  1985. const percentMatch = percentageBasedSizeRegex().exec(width);
  1986. if (percentMatch !== null) {
  1987. return percentageSize(element);
  1988. } else {
  1989. return pixelSize(element);
  1990. }
  1991. };
  1992. const getTableSize = table => {
  1993. const width = getRawWidth$1(table);
  1994. return width.fold(() => noneSize(table), w => chooseSize(table, w));
  1995. };
  1996. const TableSize = {
  1997. getTableSize,
  1998. pixelSize,
  1999. percentageSize,
  2000. noneSize
  2001. };
  2002. const statsStruct = (minRow, minCol, maxRow, maxCol, allCells, selectedCells) => ({
  2003. minRow,
  2004. minCol,
  2005. maxRow,
  2006. maxCol,
  2007. allCells,
  2008. selectedCells
  2009. });
  2010. const findSelectedStats = (house, isSelected) => {
  2011. const totalColumns = house.grid.columns;
  2012. const totalRows = house.grid.rows;
  2013. let minRow = totalRows;
  2014. let minCol = totalColumns;
  2015. let maxRow = 0;
  2016. let maxCol = 0;
  2017. const allCells = [];
  2018. const selectedCells = [];
  2019. each$1(house.access, detail => {
  2020. allCells.push(detail);
  2021. if (isSelected(detail)) {
  2022. selectedCells.push(detail);
  2023. const startRow = detail.row;
  2024. const endRow = startRow + detail.rowspan - 1;
  2025. const startCol = detail.column;
  2026. const endCol = startCol + detail.colspan - 1;
  2027. if (startRow < minRow) {
  2028. minRow = startRow;
  2029. } else if (endRow > maxRow) {
  2030. maxRow = endRow;
  2031. }
  2032. if (startCol < minCol) {
  2033. minCol = startCol;
  2034. } else if (endCol > maxCol) {
  2035. maxCol = endCol;
  2036. }
  2037. }
  2038. });
  2039. return statsStruct(minRow, minCol, maxRow, maxCol, allCells, selectedCells);
  2040. };
  2041. const makeCell = (list, seenSelected, rowIndex) => {
  2042. const row = list[rowIndex].element;
  2043. const td = SugarElement.fromTag('td');
  2044. append$1(td, SugarElement.fromTag('br'));
  2045. const f = seenSelected ? append$1 : prepend;
  2046. f(row, td);
  2047. };
  2048. const fillInGaps = (list, house, stats, isSelected) => {
  2049. const rows = filter$2(list, row => row.section !== 'colgroup');
  2050. const totalColumns = house.grid.columns;
  2051. const totalRows = house.grid.rows;
  2052. for (let i = 0; i < totalRows; i++) {
  2053. let seenSelected = false;
  2054. for (let j = 0; j < totalColumns; j++) {
  2055. if (!(i < stats.minRow || i > stats.maxRow || j < stats.minCol || j > stats.maxCol)) {
  2056. const needCell = Warehouse.getAt(house, i, j).filter(isSelected).isNone();
  2057. if (needCell) {
  2058. makeCell(rows, seenSelected, i);
  2059. } else {
  2060. seenSelected = true;
  2061. }
  2062. }
  2063. }
  2064. }
  2065. };
  2066. const clean = (replica, stats, house, widthDelta) => {
  2067. each$1(house.columns, col => {
  2068. if (col.column < stats.minCol || col.column > stats.maxCol) {
  2069. remove$6(col.element);
  2070. }
  2071. });
  2072. const emptyRows = filter$2(firstLayer(replica, 'tr'), row => row.dom.childElementCount === 0);
  2073. each$2(emptyRows, remove$6);
  2074. if (stats.minCol === stats.maxCol || stats.minRow === stats.maxRow) {
  2075. each$2(firstLayer(replica, 'th,td'), cell => {
  2076. remove$7(cell, 'rowspan');
  2077. remove$7(cell, 'colspan');
  2078. });
  2079. }
  2080. remove$7(replica, LOCKED_COL_ATTR);
  2081. remove$7(replica, 'data-snooker-col-series');
  2082. const tableSize = TableSize.getTableSize(replica);
  2083. tableSize.adjustTableWidth(widthDelta);
  2084. };
  2085. const getTableWidthDelta = (table, warehouse, tableSize, stats) => {
  2086. if (stats.minCol === 0 && warehouse.grid.columns === stats.maxCol + 1) {
  2087. return 0;
  2088. }
  2089. const colWidths = getPixelWidths(warehouse, table, tableSize);
  2090. const allColsWidth = foldl(colWidths, (acc, width) => acc + width, 0);
  2091. const selectedColsWidth = foldl(colWidths.slice(stats.minCol, stats.maxCol + 1), (acc, width) => acc + width, 0);
  2092. const newWidth = selectedColsWidth / allColsWidth * tableSize.pixelWidth();
  2093. const delta = newWidth - tableSize.pixelWidth();
  2094. return tableSize.getCellDelta(delta);
  2095. };
  2096. const extract$1 = (table, selectedSelector) => {
  2097. const isSelected = detail => is$2(detail.element, selectedSelector);
  2098. const replica = deep(table);
  2099. const list = fromTable$1(replica);
  2100. const tableSize = TableSize.getTableSize(table);
  2101. const replicaHouse = Warehouse.generate(list);
  2102. const replicaStats = findSelectedStats(replicaHouse, isSelected);
  2103. const selector = 'th:not(' + selectedSelector + ')' + ',td:not(' + selectedSelector + ')';
  2104. const unselectedCells = filterFirstLayer(replica, 'th,td', cell => is$2(cell, selector));
  2105. each$2(unselectedCells, remove$6);
  2106. fillInGaps(list, replicaHouse, replicaStats, isSelected);
  2107. const house = Warehouse.fromTable(table);
  2108. const widthDelta = getTableWidthDelta(table, house, tableSize, replicaStats);
  2109. clean(replica, replicaStats, replicaHouse, widthDelta);
  2110. return replica;
  2111. };
  2112. const nbsp = '\xA0';
  2113. const NodeValue = (is, name) => {
  2114. const get = element => {
  2115. if (!is(element)) {
  2116. throw new Error('Can only get ' + name + ' value of a ' + name + ' node');
  2117. }
  2118. return getOption(element).getOr('');
  2119. };
  2120. const getOption = element => is(element) ? Optional.from(element.dom.nodeValue) : Optional.none();
  2121. const set = (element, value) => {
  2122. if (!is(element)) {
  2123. throw new Error('Can only set raw ' + name + ' value of a ' + name + ' node');
  2124. }
  2125. element.dom.nodeValue = value;
  2126. };
  2127. return {
  2128. get,
  2129. getOption,
  2130. set
  2131. };
  2132. };
  2133. const api = NodeValue(isText, 'text');
  2134. const get$6 = element => api.get(element);
  2135. const getOption = element => api.getOption(element);
  2136. const set = (element, value) => api.set(element, value);
  2137. const getEnd = element => name(element) === 'img' ? 1 : getOption(element).fold(() => children$2(element).length, v => v.length);
  2138. const isTextNodeWithCursorPosition = el => getOption(el).filter(text => text.trim().length !== 0 || text.indexOf(nbsp) > -1).isSome();
  2139. const isContentEditableFalse = elem => isHTMLElement(elem) && get$b(elem, 'contenteditable') === 'false';
  2140. const elementsWithCursorPosition = [
  2141. 'img',
  2142. 'br'
  2143. ];
  2144. const isCursorPosition = elem => {
  2145. const hasCursorPosition = isTextNodeWithCursorPosition(elem);
  2146. return hasCursorPosition || contains$2(elementsWithCursorPosition, name(elem)) || isContentEditableFalse(elem);
  2147. };
  2148. const first = element => descendant$1(element, isCursorPosition);
  2149. const last$1 = element => descendantRtl(element, isCursorPosition);
  2150. const descendantRtl = (scope, predicate) => {
  2151. const descend = element => {
  2152. const children = children$2(element);
  2153. for (let i = children.length - 1; i >= 0; i--) {
  2154. const child = children[i];
  2155. if (predicate(child)) {
  2156. return Optional.some(child);
  2157. }
  2158. const res = descend(child);
  2159. if (res.isSome()) {
  2160. return res;
  2161. }
  2162. }
  2163. return Optional.none();
  2164. };
  2165. return descend(scope);
  2166. };
  2167. const transferableAttributes = {
  2168. scope: [
  2169. 'row',
  2170. 'col'
  2171. ]
  2172. };
  2173. const createCell = doc => () => {
  2174. const td = SugarElement.fromTag('td', doc.dom);
  2175. append$1(td, SugarElement.fromTag('br', doc.dom));
  2176. return td;
  2177. };
  2178. const createCol = doc => () => {
  2179. return SugarElement.fromTag('col', doc.dom);
  2180. };
  2181. const createColgroup = doc => () => {
  2182. return SugarElement.fromTag('colgroup', doc.dom);
  2183. };
  2184. const createRow$1 = doc => () => {
  2185. return SugarElement.fromTag('tr', doc.dom);
  2186. };
  2187. const replace$1 = (cell, tag, attrs) => {
  2188. const replica = copy$2(cell, tag);
  2189. each$1(attrs, (v, k) => {
  2190. if (v === null) {
  2191. remove$7(replica, k);
  2192. } else {
  2193. set$2(replica, k, v);
  2194. }
  2195. });
  2196. return replica;
  2197. };
  2198. const pasteReplace = cell => {
  2199. return cell;
  2200. };
  2201. const cloneFormats = (oldCell, newCell, formats) => {
  2202. const first$1 = first(oldCell);
  2203. return first$1.map(firstText => {
  2204. const formatSelector = formats.join(',');
  2205. const parents = ancestors$3(firstText, formatSelector, element => {
  2206. return eq$1(element, oldCell);
  2207. });
  2208. return foldr(parents, (last, parent) => {
  2209. const clonedFormat = shallow(parent);
  2210. append$1(last, clonedFormat);
  2211. return clonedFormat;
  2212. }, newCell);
  2213. }).getOr(newCell);
  2214. };
  2215. const cloneAppropriateAttributes = (original, clone) => {
  2216. each$1(transferableAttributes, (validAttributes, attributeName) => getOpt(original, attributeName).filter(attribute => contains$2(validAttributes, attribute)).each(attribute => set$2(clone, attributeName, attribute)));
  2217. };
  2218. const cellOperations = (mutate, doc, formatsToClone) => {
  2219. const cloneCss = (prev, clone) => {
  2220. copy$1(prev.element, clone);
  2221. remove$5(clone, 'height');
  2222. if (prev.colspan !== 1) {
  2223. remove$5(clone, 'width');
  2224. }
  2225. };
  2226. const newCell = prev => {
  2227. const td = SugarElement.fromTag(name(prev.element), doc.dom);
  2228. const formats = formatsToClone.getOr([
  2229. 'strong',
  2230. 'em',
  2231. 'b',
  2232. 'i',
  2233. 'span',
  2234. 'font',
  2235. 'h1',
  2236. 'h2',
  2237. 'h3',
  2238. 'h4',
  2239. 'h5',
  2240. 'h6',
  2241. 'p',
  2242. 'div'
  2243. ]);
  2244. const lastNode = formats.length > 0 ? cloneFormats(prev.element, td, formats) : td;
  2245. append$1(lastNode, SugarElement.fromTag('br'));
  2246. cloneCss(prev, td);
  2247. cloneAppropriateAttributes(prev.element, td);
  2248. mutate(prev.element, td);
  2249. return td;
  2250. };
  2251. const newCol = prev => {
  2252. const col = SugarElement.fromTag(name(prev.element), doc.dom);
  2253. cloneCss(prev, col);
  2254. mutate(prev.element, col);
  2255. return col;
  2256. };
  2257. return {
  2258. col: newCol,
  2259. colgroup: createColgroup(doc),
  2260. row: createRow$1(doc),
  2261. cell: newCell,
  2262. replace: replace$1,
  2263. colGap: createCol(doc),
  2264. gap: createCell(doc)
  2265. };
  2266. };
  2267. const paste$1 = doc => {
  2268. return {
  2269. col: createCol(doc),
  2270. colgroup: createColgroup(doc),
  2271. row: createRow$1(doc),
  2272. cell: createCell(doc),
  2273. replace: pasteReplace,
  2274. colGap: createCol(doc),
  2275. gap: createCell(doc)
  2276. };
  2277. };
  2278. const fromHtml = (html, scope) => {
  2279. const doc = scope || document;
  2280. const div = doc.createElement('div');
  2281. div.innerHTML = html;
  2282. return children$2(SugarElement.fromDom(div));
  2283. };
  2284. const fromDom = nodes => map$1(nodes, SugarElement.fromDom);
  2285. const closest = target => closest$1(target, '[contenteditable]');
  2286. const isEditable$1 = (element, assumeEditable = false) => {
  2287. if (inBody(element)) {
  2288. return element.dom.isContentEditable;
  2289. } else {
  2290. return closest(element).fold(constant(assumeEditable), editable => getRaw(editable) === 'true');
  2291. }
  2292. };
  2293. const getRaw = element => element.dom.contentEditable;
  2294. const getBody = editor => SugarElement.fromDom(editor.getBody());
  2295. const getIsRoot = editor => element => eq$1(element, getBody(editor));
  2296. const removeDataStyle = table => {
  2297. remove$7(table, 'data-mce-style');
  2298. const removeStyleAttribute = element => remove$7(element, 'data-mce-style');
  2299. each$2(cells$1(table), removeStyleAttribute);
  2300. each$2(columns$1(table), removeStyleAttribute);
  2301. each$2(rows$1(table), removeStyleAttribute);
  2302. };
  2303. const getSelectionStart = editor => SugarElement.fromDom(editor.selection.getStart());
  2304. const getPixelWidth = elm => elm.getBoundingClientRect().width;
  2305. const getPixelHeight = elm => elm.getBoundingClientRect().height;
  2306. const getRawWidth = (editor, elm) => {
  2307. const raw = editor.dom.getStyle(elm, 'width') || editor.dom.getAttrib(elm, 'width');
  2308. return Optional.from(raw).filter(isNotEmpty);
  2309. };
  2310. const isPercentage$1 = value => /^(\d+(\.\d+)?)%$/.test(value);
  2311. const isPixel = value => /^(\d+(\.\d+)?)px$/.test(value);
  2312. const isInEditableContext$1 = cell => closest$2(cell, isTag('table')).exists(isEditable$1);
  2313. const inSelection = (bounds, detail) => {
  2314. const leftEdge = detail.column;
  2315. const rightEdge = detail.column + detail.colspan - 1;
  2316. const topEdge = detail.row;
  2317. const bottomEdge = detail.row + detail.rowspan - 1;
  2318. return leftEdge <= bounds.finishCol && rightEdge >= bounds.startCol && (topEdge <= bounds.finishRow && bottomEdge >= bounds.startRow);
  2319. };
  2320. const isWithin = (bounds, detail) => {
  2321. return detail.column >= bounds.startCol && detail.column + detail.colspan - 1 <= bounds.finishCol && detail.row >= bounds.startRow && detail.row + detail.rowspan - 1 <= bounds.finishRow;
  2322. };
  2323. const isRectangular = (warehouse, bounds) => {
  2324. let isRect = true;
  2325. const detailIsWithin = curry(isWithin, bounds);
  2326. for (let i = bounds.startRow; i <= bounds.finishRow; i++) {
  2327. for (let j = bounds.startCol; j <= bounds.finishCol; j++) {
  2328. isRect = isRect && Warehouse.getAt(warehouse, i, j).exists(detailIsWithin);
  2329. }
  2330. }
  2331. return isRect ? Optional.some(bounds) : Optional.none();
  2332. };
  2333. const getBounds = (detailA, detailB) => {
  2334. return bounds(Math.min(detailA.row, detailB.row), Math.min(detailA.column, detailB.column), Math.max(detailA.row + detailA.rowspan - 1, detailB.row + detailB.rowspan - 1), Math.max(detailA.column + detailA.colspan - 1, detailB.column + detailB.colspan - 1));
  2335. };
  2336. const getAnyBox = (warehouse, startCell, finishCell) => {
  2337. const startCoords = Warehouse.findItem(warehouse, startCell, eq$1);
  2338. const finishCoords = Warehouse.findItem(warehouse, finishCell, eq$1);
  2339. return startCoords.bind(sc => {
  2340. return finishCoords.map(fc => {
  2341. return getBounds(sc, fc);
  2342. });
  2343. });
  2344. };
  2345. const getBox$1 = (warehouse, startCell, finishCell) => {
  2346. return getAnyBox(warehouse, startCell, finishCell).bind(bounds => {
  2347. return isRectangular(warehouse, bounds);
  2348. });
  2349. };
  2350. const moveBy$1 = (warehouse, cell, row, column) => {
  2351. return Warehouse.findItem(warehouse, cell, eq$1).bind(detail => {
  2352. const startRow = row > 0 ? detail.row + detail.rowspan - 1 : detail.row;
  2353. const startCol = column > 0 ? detail.column + detail.colspan - 1 : detail.column;
  2354. const dest = Warehouse.getAt(warehouse, startRow + row, startCol + column);
  2355. return dest.map(d => {
  2356. return d.element;
  2357. });
  2358. });
  2359. };
  2360. const intercepts$1 = (warehouse, start, finish) => {
  2361. return getAnyBox(warehouse, start, finish).map(bounds => {
  2362. const inside = Warehouse.filterItems(warehouse, curry(inSelection, bounds));
  2363. return map$1(inside, detail => {
  2364. return detail.element;
  2365. });
  2366. });
  2367. };
  2368. const parentCell = (warehouse, innerCell) => {
  2369. const isContainedBy = (c1, c2) => {
  2370. return contains$1(c2, c1);
  2371. };
  2372. return Warehouse.findItem(warehouse, innerCell, isContainedBy).map(detail => {
  2373. return detail.element;
  2374. });
  2375. };
  2376. const moveBy = (cell, deltaRow, deltaColumn) => {
  2377. return table(cell).bind(table => {
  2378. const warehouse = getWarehouse(table);
  2379. return moveBy$1(warehouse, cell, deltaRow, deltaColumn);
  2380. });
  2381. };
  2382. const intercepts = (table, first, last) => {
  2383. const warehouse = getWarehouse(table);
  2384. return intercepts$1(warehouse, first, last);
  2385. };
  2386. const nestedIntercepts = (table, first, firstTable, last, lastTable) => {
  2387. const warehouse = getWarehouse(table);
  2388. const optStartCell = eq$1(table, firstTable) ? Optional.some(first) : parentCell(warehouse, first);
  2389. const optLastCell = eq$1(table, lastTable) ? Optional.some(last) : parentCell(warehouse, last);
  2390. return optStartCell.bind(startCell => optLastCell.bind(lastCell => intercepts$1(warehouse, startCell, lastCell)));
  2391. };
  2392. const getBox = (table, first, last) => {
  2393. const warehouse = getWarehouse(table);
  2394. return getBox$1(warehouse, first, last);
  2395. };
  2396. const getWarehouse = Warehouse.fromTable;
  2397. var TagBoundaries = [
  2398. 'body',
  2399. 'p',
  2400. 'div',
  2401. 'article',
  2402. 'aside',
  2403. 'figcaption',
  2404. 'figure',
  2405. 'footer',
  2406. 'header',
  2407. 'nav',
  2408. 'section',
  2409. 'ol',
  2410. 'ul',
  2411. 'li',
  2412. 'table',
  2413. 'thead',
  2414. 'tbody',
  2415. 'tfoot',
  2416. 'caption',
  2417. 'tr',
  2418. 'td',
  2419. 'th',
  2420. 'h1',
  2421. 'h2',
  2422. 'h3',
  2423. 'h4',
  2424. 'h5',
  2425. 'h6',
  2426. 'blockquote',
  2427. 'pre',
  2428. 'address'
  2429. ];
  2430. var DomUniverse = () => {
  2431. const clone = element => {
  2432. return SugarElement.fromDom(element.dom.cloneNode(false));
  2433. };
  2434. const document = element => documentOrOwner(element).dom;
  2435. const isBoundary = element => {
  2436. if (!isElement(element)) {
  2437. return false;
  2438. }
  2439. if (name(element) === 'body') {
  2440. return true;
  2441. }
  2442. return contains$2(TagBoundaries, name(element));
  2443. };
  2444. const isEmptyTag = element => {
  2445. if (!isElement(element)) {
  2446. return false;
  2447. }
  2448. return contains$2([
  2449. 'br',
  2450. 'img',
  2451. 'hr',
  2452. 'input'
  2453. ], name(element));
  2454. };
  2455. const isNonEditable = element => isElement(element) && get$b(element, 'contenteditable') === 'false';
  2456. const comparePosition = (element, other) => {
  2457. return element.dom.compareDocumentPosition(other.dom);
  2458. };
  2459. const copyAttributesTo = (source, destination) => {
  2460. const as = clone$2(source);
  2461. setAll$1(destination, as);
  2462. };
  2463. const isSpecial = element => {
  2464. const tag = name(element);
  2465. return contains$2([
  2466. 'script',
  2467. 'noscript',
  2468. 'iframe',
  2469. 'noframes',
  2470. 'noembed',
  2471. 'title',
  2472. 'style',
  2473. 'textarea',
  2474. 'xmp'
  2475. ], tag);
  2476. };
  2477. const getLanguage = element => isElement(element) ? getOpt(element, 'lang') : Optional.none();
  2478. return {
  2479. up: constant({
  2480. selector: ancestor$1,
  2481. closest: closest$1,
  2482. predicate: ancestor$2,
  2483. all: parents
  2484. }),
  2485. down: constant({
  2486. selector: descendants,
  2487. predicate: descendants$1
  2488. }),
  2489. styles: constant({
  2490. get: get$a,
  2491. getRaw: getRaw$2,
  2492. set: set$1,
  2493. remove: remove$5
  2494. }),
  2495. attrs: constant({
  2496. get: get$b,
  2497. set: set$2,
  2498. remove: remove$7,
  2499. copyTo: copyAttributesTo
  2500. }),
  2501. insert: constant({
  2502. before: before$3,
  2503. after: after$5,
  2504. afterAll: after$4,
  2505. append: append$1,
  2506. appendAll: append,
  2507. prepend: prepend,
  2508. wrap: wrap
  2509. }),
  2510. remove: constant({
  2511. unwrap: unwrap,
  2512. remove: remove$6
  2513. }),
  2514. create: constant({
  2515. nu: SugarElement.fromTag,
  2516. clone,
  2517. text: SugarElement.fromText
  2518. }),
  2519. query: constant({
  2520. comparePosition,
  2521. prevSibling: prevSibling,
  2522. nextSibling: nextSibling
  2523. }),
  2524. property: constant({
  2525. children: children$2,
  2526. name: name,
  2527. parent: parent,
  2528. document,
  2529. isText: isText,
  2530. isComment: isComment,
  2531. isElement: isElement,
  2532. isSpecial,
  2533. getLanguage,
  2534. getText: get$6,
  2535. setText: set,
  2536. isBoundary,
  2537. isEmptyTag,
  2538. isNonEditable
  2539. }),
  2540. eq: eq$1,
  2541. is: is$1
  2542. };
  2543. };
  2544. const all = (universe, look, elements, f) => {
  2545. const head = elements[0];
  2546. const tail = elements.slice(1);
  2547. return f(universe, look, head, tail);
  2548. };
  2549. const oneAll = (universe, look, elements) => {
  2550. return elements.length > 0 ? all(universe, look, elements, unsafeOne) : Optional.none();
  2551. };
  2552. const unsafeOne = (universe, look, head, tail) => {
  2553. const start = look(universe, head);
  2554. return foldr(tail, (b, a) => {
  2555. const current = look(universe, a);
  2556. return commonElement(universe, b, current);
  2557. }, start);
  2558. };
  2559. const commonElement = (universe, start, end) => {
  2560. return start.bind(s => {
  2561. return end.filter(curry(universe.eq, s));
  2562. });
  2563. };
  2564. const eq = (universe, item) => {
  2565. return curry(universe.eq, item);
  2566. };
  2567. const ancestors$2 = (universe, start, end, isRoot = never) => {
  2568. const ps1 = [start].concat(universe.up().all(start));
  2569. const ps2 = [end].concat(universe.up().all(end));
  2570. const prune = path => {
  2571. const index = findIndex(path, isRoot);
  2572. return index.fold(() => {
  2573. return path;
  2574. }, ind => {
  2575. return path.slice(0, ind + 1);
  2576. });
  2577. };
  2578. const pruned1 = prune(ps1);
  2579. const pruned2 = prune(ps2);
  2580. const shared = find$1(pruned1, x => {
  2581. return exists(pruned2, eq(universe, x));
  2582. });
  2583. return {
  2584. firstpath: pruned1,
  2585. secondpath: pruned2,
  2586. shared
  2587. };
  2588. };
  2589. const sharedOne$1 = oneAll;
  2590. const ancestors$1 = ancestors$2;
  2591. const universe$3 = DomUniverse();
  2592. const sharedOne = (look, elements) => {
  2593. return sharedOne$1(universe$3, (_universe, element) => {
  2594. return look(element);
  2595. }, elements);
  2596. };
  2597. const ancestors = (start, finish, isRoot) => {
  2598. return ancestors$1(universe$3, start, finish, isRoot);
  2599. };
  2600. const lookupTable = container => {
  2601. return ancestor$1(container, 'table');
  2602. };
  2603. const identify = (start, finish, isRoot) => {
  2604. const getIsRoot = rootTable => {
  2605. return element => {
  2606. return isRoot !== undefined && isRoot(element) || eq$1(element, rootTable);
  2607. };
  2608. };
  2609. if (eq$1(start, finish)) {
  2610. return Optional.some({
  2611. boxes: Optional.some([start]),
  2612. start,
  2613. finish
  2614. });
  2615. } else {
  2616. return lookupTable(start).bind(startTable => {
  2617. return lookupTable(finish).bind(finishTable => {
  2618. if (eq$1(startTable, finishTable)) {
  2619. return Optional.some({
  2620. boxes: intercepts(startTable, start, finish),
  2621. start,
  2622. finish
  2623. });
  2624. } else if (contains$1(startTable, finishTable)) {
  2625. const ancestorCells = ancestors$3(finish, 'td,th', getIsRoot(startTable));
  2626. const finishCell = ancestorCells.length > 0 ? ancestorCells[ancestorCells.length - 1] : finish;
  2627. return Optional.some({
  2628. boxes: nestedIntercepts(startTable, start, startTable, finish, finishTable),
  2629. start,
  2630. finish: finishCell
  2631. });
  2632. } else if (contains$1(finishTable, startTable)) {
  2633. const ancestorCells = ancestors$3(start, 'td,th', getIsRoot(finishTable));
  2634. const startCell = ancestorCells.length > 0 ? ancestorCells[ancestorCells.length - 1] : start;
  2635. return Optional.some({
  2636. boxes: nestedIntercepts(finishTable, start, startTable, finish, finishTable),
  2637. start,
  2638. finish: startCell
  2639. });
  2640. } else {
  2641. return ancestors(start, finish).shared.bind(lca => {
  2642. return closest$1(lca, 'table', isRoot).bind(lcaTable => {
  2643. const finishAncestorCells = ancestors$3(finish, 'td,th', getIsRoot(lcaTable));
  2644. const finishCell = finishAncestorCells.length > 0 ? finishAncestorCells[finishAncestorCells.length - 1] : finish;
  2645. const startAncestorCells = ancestors$3(start, 'td,th', getIsRoot(lcaTable));
  2646. const startCell = startAncestorCells.length > 0 ? startAncestorCells[startAncestorCells.length - 1] : start;
  2647. return Optional.some({
  2648. boxes: nestedIntercepts(lcaTable, start, startTable, finish, finishTable),
  2649. start: startCell,
  2650. finish: finishCell
  2651. });
  2652. });
  2653. });
  2654. }
  2655. });
  2656. });
  2657. }
  2658. };
  2659. const retrieve$1 = (container, selector) => {
  2660. const sels = descendants(container, selector);
  2661. return sels.length > 0 ? Optional.some(sels) : Optional.none();
  2662. };
  2663. const getLast = (boxes, lastSelectedSelector) => {
  2664. return find$1(boxes, box => {
  2665. return is$2(box, lastSelectedSelector);
  2666. });
  2667. };
  2668. const getEdges = (container, firstSelectedSelector, lastSelectedSelector) => {
  2669. return descendant(container, firstSelectedSelector).bind(first => {
  2670. return descendant(container, lastSelectedSelector).bind(last => {
  2671. return sharedOne(lookupTable, [
  2672. first,
  2673. last
  2674. ]).map(table => {
  2675. return {
  2676. first,
  2677. last,
  2678. table
  2679. };
  2680. });
  2681. });
  2682. });
  2683. };
  2684. const expandTo = (finish, firstSelectedSelector) => {
  2685. return ancestor$1(finish, 'table').bind(table => {
  2686. return descendant(table, firstSelectedSelector).bind(start => {
  2687. return identify(start, finish).bind(identified => {
  2688. return identified.boxes.map(boxes => {
  2689. return {
  2690. boxes,
  2691. start: identified.start,
  2692. finish: identified.finish
  2693. };
  2694. });
  2695. });
  2696. });
  2697. });
  2698. };
  2699. const shiftSelection = (boxes, deltaRow, deltaColumn, firstSelectedSelector, lastSelectedSelector) => {
  2700. return getLast(boxes, lastSelectedSelector).bind(last => {
  2701. return moveBy(last, deltaRow, deltaColumn).bind(finish => {
  2702. return expandTo(finish, firstSelectedSelector);
  2703. });
  2704. });
  2705. };
  2706. const retrieve = (container, selector) => {
  2707. return retrieve$1(container, selector);
  2708. };
  2709. const retrieveBox = (container, firstSelectedSelector, lastSelectedSelector) => {
  2710. return getEdges(container, firstSelectedSelector, lastSelectedSelector).bind(edges => {
  2711. const isRoot = ancestor => {
  2712. return eq$1(container, ancestor);
  2713. };
  2714. const sectionSelector = 'thead,tfoot,tbody,table';
  2715. const firstAncestor = ancestor$1(edges.first, sectionSelector, isRoot);
  2716. const lastAncestor = ancestor$1(edges.last, sectionSelector, isRoot);
  2717. return firstAncestor.bind(fA => {
  2718. return lastAncestor.bind(lA => {
  2719. return eq$1(fA, lA) ? getBox(edges.table, edges.first, edges.last) : Optional.none();
  2720. });
  2721. });
  2722. });
  2723. };
  2724. const selection = identity;
  2725. const unmergable = selectedCells => {
  2726. const hasSpan = (elem, type) => getOpt(elem, type).exists(span => parseInt(span, 10) > 1);
  2727. const hasRowOrColSpan = elem => hasSpan(elem, 'rowspan') || hasSpan(elem, 'colspan');
  2728. return selectedCells.length > 0 && forall(selectedCells, hasRowOrColSpan) ? Optional.some(selectedCells) : Optional.none();
  2729. };
  2730. const mergable = (table, selectedCells, ephemera) => {
  2731. if (selectedCells.length <= 1) {
  2732. return Optional.none();
  2733. } else {
  2734. return retrieveBox(table, ephemera.firstSelectedSelector, ephemera.lastSelectedSelector).map(bounds => ({
  2735. bounds,
  2736. cells: selectedCells
  2737. }));
  2738. }
  2739. };
  2740. const strSelected = 'data-mce-selected';
  2741. const strSelectedSelector = 'td[' + strSelected + '],th[' + strSelected + ']';
  2742. const strAttributeSelector = '[' + strSelected + ']';
  2743. const strFirstSelected = 'data-mce-first-selected';
  2744. const strFirstSelectedSelector = 'td[' + strFirstSelected + '],th[' + strFirstSelected + ']';
  2745. const strLastSelected = 'data-mce-last-selected';
  2746. const strLastSelectedSelector = 'td[' + strLastSelected + '],th[' + strLastSelected + ']';
  2747. const attributeSelector = strAttributeSelector;
  2748. const ephemera = {
  2749. selected: strSelected,
  2750. selectedSelector: strSelectedSelector,
  2751. firstSelected: strFirstSelected,
  2752. firstSelectedSelector: strFirstSelectedSelector,
  2753. lastSelected: strLastSelected,
  2754. lastSelectedSelector: strLastSelectedSelector
  2755. };
  2756. const forMenu = (selectedCells, table, cell) => ({
  2757. element: cell,
  2758. mergable: mergable(table, selectedCells, ephemera),
  2759. unmergable: unmergable(selectedCells),
  2760. selection: selection(selectedCells)
  2761. });
  2762. const paste = (element, clipboard, generators) => ({
  2763. element,
  2764. clipboard,
  2765. generators
  2766. });
  2767. const pasteRows = (selectedCells, _cell, clipboard, generators) => ({
  2768. selection: selection(selectedCells),
  2769. clipboard,
  2770. generators
  2771. });
  2772. const getSelectionCellFallback = element => table(element).bind(table => retrieve(table, ephemera.firstSelectedSelector)).fold(constant(element), cells => cells[0]);
  2773. const getSelectionFromSelector = selector => (initCell, isRoot) => {
  2774. const cellName = name(initCell);
  2775. const cell = cellName === 'col' || cellName === 'colgroup' ? getSelectionCellFallback(initCell) : initCell;
  2776. return closest$1(cell, selector, isRoot);
  2777. };
  2778. const getSelectionCellOrCaption = getSelectionFromSelector('th,td,caption');
  2779. const getSelectionCell = getSelectionFromSelector('th,td');
  2780. const getCellsFromSelection = editor => fromDom(editor.model.table.getSelectedCells());
  2781. const getCellsFromFakeSelection = editor => filter$2(getCellsFromSelection(editor), cell => is$2(cell, ephemera.selectedSelector));
  2782. const extractSelected = cells => {
  2783. return table(cells[0]).map(table => {
  2784. const replica = extract$1(table, attributeSelector);
  2785. removeDataStyle(replica);
  2786. return [replica];
  2787. });
  2788. };
  2789. const serializeElements = (editor, elements) => map$1(elements, elm => editor.selection.serializer.serialize(elm.dom, {})).join('');
  2790. const getTextContent = elements => map$1(elements, element => element.dom.innerText).join('');
  2791. const registerEvents = (editor, actions) => {
  2792. editor.on('BeforeGetContent', e => {
  2793. const multiCellContext = cells => {
  2794. e.preventDefault();
  2795. extractSelected(cells).each(elements => {
  2796. e.content = e.format === 'text' ? getTextContent(elements) : serializeElements(editor, elements);
  2797. });
  2798. };
  2799. if (e.selection === true) {
  2800. const cells = getCellsFromFakeSelection(editor);
  2801. if (cells.length >= 1) {
  2802. multiCellContext(cells);
  2803. }
  2804. }
  2805. });
  2806. editor.on('BeforeSetContent', e => {
  2807. if (e.selection === true && e.paste === true) {
  2808. const selectedCells = getCellsFromSelection(editor);
  2809. head(selectedCells).each(cell => {
  2810. table(cell).each(table => {
  2811. const elements = filter$2(fromHtml(e.content), content => {
  2812. return name(content) !== 'meta';
  2813. });
  2814. const isTable = isTag('table');
  2815. if (elements.length === 1 && isTable(elements[0])) {
  2816. e.preventDefault();
  2817. const doc = SugarElement.fromDom(editor.getDoc());
  2818. const generators = paste$1(doc);
  2819. const targets = paste(cell, elements[0], generators);
  2820. actions.pasteCells(table, targets).each(() => {
  2821. editor.focus();
  2822. });
  2823. }
  2824. });
  2825. });
  2826. }
  2827. });
  2828. };
  2829. const point = (element, offset) => ({
  2830. element,
  2831. offset
  2832. });
  2833. const scan$1 = (universe, element, direction) => {
  2834. if (universe.property().isText(element) && universe.property().getText(element).trim().length === 0 || universe.property().isComment(element)) {
  2835. return direction(element).bind(elem => {
  2836. return scan$1(universe, elem, direction).orThunk(() => {
  2837. return Optional.some(elem);
  2838. });
  2839. });
  2840. } else {
  2841. return Optional.none();
  2842. }
  2843. };
  2844. const toEnd = (universe, element) => {
  2845. if (universe.property().isText(element)) {
  2846. return universe.property().getText(element).length;
  2847. }
  2848. const children = universe.property().children(element);
  2849. return children.length;
  2850. };
  2851. const freefallRtl$2 = (universe, element) => {
  2852. const candidate = scan$1(universe, element, universe.query().prevSibling).getOr(element);
  2853. if (universe.property().isText(candidate)) {
  2854. return point(candidate, toEnd(universe, candidate));
  2855. }
  2856. const children = universe.property().children(candidate);
  2857. return children.length > 0 ? freefallRtl$2(universe, children[children.length - 1]) : point(candidate, toEnd(universe, candidate));
  2858. };
  2859. const freefallRtl$1 = freefallRtl$2;
  2860. const universe$2 = DomUniverse();
  2861. const freefallRtl = element => {
  2862. return freefallRtl$1(universe$2, element);
  2863. };
  2864. const halve = (main, other) => {
  2865. if (!hasColspan(main)) {
  2866. const width = getGenericWidth(main);
  2867. width.each(w => {
  2868. const newWidth = w.value / 2;
  2869. setGenericWidth(main, newWidth, w.unit);
  2870. setGenericWidth(other, newWidth, w.unit);
  2871. });
  2872. }
  2873. };
  2874. const zero = array => map$1(array, constant(0));
  2875. const surround = (sizes, startIndex, endIndex, results, f) => f(sizes.slice(0, startIndex)).concat(results).concat(f(sizes.slice(endIndex)));
  2876. const clampDeltaHelper = predicate => (sizes, index, delta, minCellSize) => {
  2877. if (!predicate(delta)) {
  2878. return delta;
  2879. } else {
  2880. const newSize = Math.max(minCellSize, sizes[index] - Math.abs(delta));
  2881. const diff = Math.abs(newSize - sizes[index]);
  2882. return delta >= 0 ? diff : -diff;
  2883. }
  2884. };
  2885. const clampNegativeDelta = clampDeltaHelper(delta => delta < 0);
  2886. const clampDelta = clampDeltaHelper(always);
  2887. const resizeTable = () => {
  2888. const calcFixedDeltas = (sizes, index, next, delta, minCellSize) => {
  2889. const clampedDelta = clampNegativeDelta(sizes, index, delta, minCellSize);
  2890. return surround(sizes, index, next + 1, [
  2891. clampedDelta,
  2892. 0
  2893. ], zero);
  2894. };
  2895. const calcRelativeDeltas = (sizes, index, delta, minCellSize) => {
  2896. const ratio = (100 + delta) / 100;
  2897. const newThis = Math.max(minCellSize, (sizes[index] + delta) / ratio);
  2898. return map$1(sizes, (size, idx) => {
  2899. const newSize = idx === index ? newThis : size / ratio;
  2900. return newSize - size;
  2901. });
  2902. };
  2903. const calcLeftEdgeDeltas = (sizes, index, next, delta, minCellSize, isRelative) => {
  2904. if (isRelative) {
  2905. return calcRelativeDeltas(sizes, index, delta, minCellSize);
  2906. } else {
  2907. return calcFixedDeltas(sizes, index, next, delta, minCellSize);
  2908. }
  2909. };
  2910. const calcMiddleDeltas = (sizes, _prev, index, next, delta, minCellSize, isRelative) => calcLeftEdgeDeltas(sizes, index, next, delta, minCellSize, isRelative);
  2911. const resizeTable = (resizer, delta) => resizer(delta);
  2912. const calcRightEdgeDeltas = (sizes, _prev, index, delta, minCellSize, isRelative) => {
  2913. if (isRelative) {
  2914. return calcRelativeDeltas(sizes, index, delta, minCellSize);
  2915. } else {
  2916. const clampedDelta = clampNegativeDelta(sizes, index, delta, minCellSize);
  2917. return zero(sizes.slice(0, index)).concat([clampedDelta]);
  2918. }
  2919. };
  2920. const calcRedestributedWidths = (sizes, totalWidth, pixelDelta, isRelative) => {
  2921. if (isRelative) {
  2922. const tableWidth = totalWidth + pixelDelta;
  2923. const ratio = tableWidth / totalWidth;
  2924. const newSizes = map$1(sizes, size => size / ratio);
  2925. return {
  2926. delta: ratio * 100 - 100,
  2927. newSizes
  2928. };
  2929. } else {
  2930. return {
  2931. delta: pixelDelta,
  2932. newSizes: sizes
  2933. };
  2934. }
  2935. };
  2936. return {
  2937. resizeTable,
  2938. clampTableDelta: clampNegativeDelta,
  2939. calcLeftEdgeDeltas,
  2940. calcMiddleDeltas,
  2941. calcRightEdgeDeltas,
  2942. calcRedestributedWidths
  2943. };
  2944. };
  2945. const preserveTable = () => {
  2946. const calcLeftEdgeDeltas = (sizes, index, next, delta, minCellSize) => {
  2947. const idx = delta >= 0 ? next : index;
  2948. const clampedDelta = clampDelta(sizes, idx, delta, minCellSize);
  2949. return surround(sizes, index, next + 1, [
  2950. clampedDelta,
  2951. -clampedDelta
  2952. ], zero);
  2953. };
  2954. const calcMiddleDeltas = (sizes, _prev, index, next, delta, minCellSize) => calcLeftEdgeDeltas(sizes, index, next, delta, minCellSize);
  2955. const resizeTable = (resizer, delta, isLastColumn) => {
  2956. if (isLastColumn) {
  2957. resizer(delta);
  2958. }
  2959. };
  2960. const calcRightEdgeDeltas = (sizes, _prev, _index, delta, _minCellSize, isRelative) => {
  2961. if (isRelative) {
  2962. return zero(sizes);
  2963. } else {
  2964. const diff = delta / sizes.length;
  2965. return map$1(sizes, constant(diff));
  2966. }
  2967. };
  2968. const clampTableDelta = (sizes, index, delta, minCellSize, isLastColumn) => {
  2969. if (isLastColumn) {
  2970. if (delta >= 0) {
  2971. return delta;
  2972. } else {
  2973. const maxDelta = foldl(sizes, (a, b) => a + b - minCellSize, 0);
  2974. return Math.max(-maxDelta, delta);
  2975. }
  2976. } else {
  2977. return clampNegativeDelta(sizes, index, delta, minCellSize);
  2978. }
  2979. };
  2980. const calcRedestributedWidths = (sizes, _totalWidth, _pixelDelta, _isRelative) => ({
  2981. delta: 0,
  2982. newSizes: sizes
  2983. });
  2984. return {
  2985. resizeTable,
  2986. clampTableDelta,
  2987. calcLeftEdgeDeltas,
  2988. calcMiddleDeltas,
  2989. calcRightEdgeDeltas,
  2990. calcRedestributedWidths
  2991. };
  2992. };
  2993. const getGridSize = table => {
  2994. const warehouse = Warehouse.fromTable(table);
  2995. return warehouse.grid;
  2996. };
  2997. const isHeaderCell = isTag('th');
  2998. const isHeaderCells = cells => forall(cells, cell => isHeaderCell(cell.element));
  2999. const getRowHeaderType = (isHeaderRow, isHeaderCells) => {
  3000. if (isHeaderRow && isHeaderCells) {
  3001. return 'sectionCells';
  3002. } else if (isHeaderRow) {
  3003. return 'section';
  3004. } else {
  3005. return 'cells';
  3006. }
  3007. };
  3008. const getRowType = row => {
  3009. const isHeaderRow = row.section === 'thead';
  3010. const isHeaderCells = is(findCommonCellType(row.cells), 'th');
  3011. if (row.section === 'tfoot') {
  3012. return { type: 'footer' };
  3013. } else if (isHeaderRow || isHeaderCells) {
  3014. return {
  3015. type: 'header',
  3016. subType: getRowHeaderType(isHeaderRow, isHeaderCells)
  3017. };
  3018. } else {
  3019. return { type: 'body' };
  3020. }
  3021. };
  3022. const findCommonCellType = cells => {
  3023. const headerCells = filter$2(cells, cell => isHeaderCell(cell.element));
  3024. if (headerCells.length === 0) {
  3025. return Optional.some('td');
  3026. } else if (headerCells.length === cells.length) {
  3027. return Optional.some('th');
  3028. } else {
  3029. return Optional.none();
  3030. }
  3031. };
  3032. const findCommonRowType = rows => {
  3033. const rowTypes = map$1(rows, row => getRowType(row).type);
  3034. const hasHeader = contains$2(rowTypes, 'header');
  3035. const hasFooter = contains$2(rowTypes, 'footer');
  3036. if (!hasHeader && !hasFooter) {
  3037. return Optional.some('body');
  3038. } else {
  3039. const hasBody = contains$2(rowTypes, 'body');
  3040. if (hasHeader && !hasBody && !hasFooter) {
  3041. return Optional.some('header');
  3042. } else if (!hasHeader && !hasBody && hasFooter) {
  3043. return Optional.some('footer');
  3044. } else {
  3045. return Optional.none();
  3046. }
  3047. }
  3048. };
  3049. const findTableRowHeaderType = warehouse => findMap(warehouse.all, row => {
  3050. const rowType = getRowType(row);
  3051. return rowType.type === 'header' ? Optional.from(rowType.subType) : Optional.none();
  3052. });
  3053. const transformCell = (cell, comparator, substitution) => elementnew(substitution(cell.element, comparator), true, cell.isLocked);
  3054. const transformRow = (row, section) => row.section !== section ? rowcells(row.element, row.cells, section, row.isNew) : row;
  3055. const section = () => ({
  3056. transformRow,
  3057. transformCell: (cell, comparator, substitution) => {
  3058. const newCell = substitution(cell.element, comparator);
  3059. const fixedCell = name(newCell) !== 'td' ? mutate$1(newCell, 'td') : newCell;
  3060. return elementnew(fixedCell, cell.isNew, cell.isLocked);
  3061. }
  3062. });
  3063. const sectionCells = () => ({
  3064. transformRow,
  3065. transformCell
  3066. });
  3067. const cells = () => ({
  3068. transformRow: (row, section) => {
  3069. const newSection = section === 'thead' ? 'tbody' : section;
  3070. return transformRow(row, newSection);
  3071. },
  3072. transformCell
  3073. });
  3074. const fallback = () => ({
  3075. transformRow: identity,
  3076. transformCell
  3077. });
  3078. const getTableSectionType = (table, fallback) => {
  3079. const warehouse = Warehouse.fromTable(table);
  3080. const type = findTableRowHeaderType(warehouse).getOr(fallback);
  3081. switch (type) {
  3082. case 'section':
  3083. return section();
  3084. case 'sectionCells':
  3085. return sectionCells();
  3086. case 'cells':
  3087. return cells();
  3088. }
  3089. };
  3090. const TableSection = {
  3091. getTableSectionType,
  3092. section,
  3093. sectionCells,
  3094. cells,
  3095. fallback
  3096. };
  3097. const setIfNot = (element, property, value, ignore) => {
  3098. if (value === ignore) {
  3099. remove$7(element, property);
  3100. } else {
  3101. set$2(element, property, value);
  3102. }
  3103. };
  3104. const insert$1 = (table, selector, element) => {
  3105. last$2(children(table, selector)).fold(() => prepend(table, element), child => after$5(child, element));
  3106. };
  3107. const generateSection = (table, sectionName) => {
  3108. const section = child(table, sectionName).getOrThunk(() => {
  3109. const newSection = SugarElement.fromTag(sectionName, owner(table).dom);
  3110. if (sectionName === 'thead') {
  3111. insert$1(table, 'caption,colgroup', newSection);
  3112. } else if (sectionName === 'colgroup') {
  3113. insert$1(table, 'caption', newSection);
  3114. } else {
  3115. append$1(table, newSection);
  3116. }
  3117. return newSection;
  3118. });
  3119. empty(section);
  3120. return section;
  3121. };
  3122. const render$1 = (table, grid) => {
  3123. const newRows = [];
  3124. const newCells = [];
  3125. const syncRows = gridSection => map$1(gridSection, row => {
  3126. if (row.isNew) {
  3127. newRows.push(row.element);
  3128. }
  3129. const tr = row.element;
  3130. empty(tr);
  3131. each$2(row.cells, cell => {
  3132. if (cell.isNew) {
  3133. newCells.push(cell.element);
  3134. }
  3135. setIfNot(cell.element, 'colspan', cell.colspan, 1);
  3136. setIfNot(cell.element, 'rowspan', cell.rowspan, 1);
  3137. append$1(tr, cell.element);
  3138. });
  3139. return tr;
  3140. });
  3141. const syncColGroup = gridSection => bind$2(gridSection, colGroup => map$1(colGroup.cells, col => {
  3142. setIfNot(col.element, 'span', col.colspan, 1);
  3143. return col.element;
  3144. }));
  3145. const renderSection = (gridSection, sectionName) => {
  3146. const section = generateSection(table, sectionName);
  3147. const sync = sectionName === 'colgroup' ? syncColGroup : syncRows;
  3148. const sectionElems = sync(gridSection);
  3149. append(section, sectionElems);
  3150. };
  3151. const removeSection = sectionName => {
  3152. child(table, sectionName).each(remove$6);
  3153. };
  3154. const renderOrRemoveSection = (gridSection, sectionName) => {
  3155. if (gridSection.length > 0) {
  3156. renderSection(gridSection, sectionName);
  3157. } else {
  3158. removeSection(sectionName);
  3159. }
  3160. };
  3161. const headSection = [];
  3162. const bodySection = [];
  3163. const footSection = [];
  3164. const columnGroupsSection = [];
  3165. each$2(grid, row => {
  3166. switch (row.section) {
  3167. case 'thead':
  3168. headSection.push(row);
  3169. break;
  3170. case 'tbody':
  3171. bodySection.push(row);
  3172. break;
  3173. case 'tfoot':
  3174. footSection.push(row);
  3175. break;
  3176. case 'colgroup':
  3177. columnGroupsSection.push(row);
  3178. break;
  3179. }
  3180. });
  3181. renderOrRemoveSection(columnGroupsSection, 'colgroup');
  3182. renderOrRemoveSection(headSection, 'thead');
  3183. renderOrRemoveSection(bodySection, 'tbody');
  3184. renderOrRemoveSection(footSection, 'tfoot');
  3185. return {
  3186. newRows,
  3187. newCells
  3188. };
  3189. };
  3190. const copy = grid => map$1(grid, row => {
  3191. const tr = shallow(row.element);
  3192. each$2(row.cells, cell => {
  3193. const clonedCell = deep(cell.element);
  3194. setIfNot(clonedCell, 'colspan', cell.colspan, 1);
  3195. setIfNot(clonedCell, 'rowspan', cell.rowspan, 1);
  3196. append$1(tr, clonedCell);
  3197. });
  3198. return tr;
  3199. });
  3200. const getColumn = (grid, index) => {
  3201. return map$1(grid, row => {
  3202. return getCell(row, index);
  3203. });
  3204. };
  3205. const getRow = (grid, index) => {
  3206. return grid[index];
  3207. };
  3208. const findDiff = (xs, comp) => {
  3209. if (xs.length === 0) {
  3210. return 0;
  3211. }
  3212. const first = xs[0];
  3213. const index = findIndex(xs, x => {
  3214. return !comp(first.element, x.element);
  3215. });
  3216. return index.getOr(xs.length);
  3217. };
  3218. const subgrid = (grid, row, column, comparator) => {
  3219. const gridRow = getRow(grid, row);
  3220. const isColRow = gridRow.section === 'colgroup';
  3221. const colspan = findDiff(gridRow.cells.slice(column), comparator);
  3222. const rowspan = isColRow ? 1 : findDiff(getColumn(grid.slice(row), column), comparator);
  3223. return {
  3224. colspan,
  3225. rowspan
  3226. };
  3227. };
  3228. const toDetails = (grid, comparator) => {
  3229. const seen = map$1(grid, row => map$1(row.cells, never));
  3230. const updateSeen = (rowIndex, columnIndex, rowspan, colspan) => {
  3231. for (let row = rowIndex; row < rowIndex + rowspan; row++) {
  3232. for (let column = columnIndex; column < columnIndex + colspan; column++) {
  3233. seen[row][column] = true;
  3234. }
  3235. }
  3236. };
  3237. return map$1(grid, (row, rowIndex) => {
  3238. const details = bind$2(row.cells, (cell, columnIndex) => {
  3239. if (seen[rowIndex][columnIndex] === false) {
  3240. const result = subgrid(grid, rowIndex, columnIndex, comparator);
  3241. updateSeen(rowIndex, columnIndex, result.rowspan, result.colspan);
  3242. return [detailnew(cell.element, result.rowspan, result.colspan, cell.isNew)];
  3243. } else {
  3244. return [];
  3245. }
  3246. });
  3247. return rowdetailnew(row.element, details, row.section, row.isNew);
  3248. });
  3249. };
  3250. const toGrid = (warehouse, generators, isNew) => {
  3251. const grid = [];
  3252. each$2(warehouse.colgroups, colgroup => {
  3253. const colgroupCols = [];
  3254. for (let columnIndex = 0; columnIndex < warehouse.grid.columns; columnIndex++) {
  3255. const element = Warehouse.getColumnAt(warehouse, columnIndex).map(column => elementnew(column.element, isNew, false)).getOrThunk(() => elementnew(generators.colGap(), true, false));
  3256. colgroupCols.push(element);
  3257. }
  3258. grid.push(rowcells(colgroup.element, colgroupCols, 'colgroup', isNew));
  3259. });
  3260. for (let rowIndex = 0; rowIndex < warehouse.grid.rows; rowIndex++) {
  3261. const rowCells = [];
  3262. for (let columnIndex = 0; columnIndex < warehouse.grid.columns; columnIndex++) {
  3263. const element = Warehouse.getAt(warehouse, rowIndex, columnIndex).map(item => elementnew(item.element, isNew, item.isLocked)).getOrThunk(() => elementnew(generators.gap(), true, false));
  3264. rowCells.push(element);
  3265. }
  3266. const rowDetail = warehouse.all[rowIndex];
  3267. const row = rowcells(rowDetail.element, rowCells, rowDetail.section, isNew);
  3268. grid.push(row);
  3269. }
  3270. return grid;
  3271. };
  3272. const fromWarehouse = (warehouse, generators) => toGrid(warehouse, generators, false);
  3273. const toDetailList = grid => toDetails(grid, eq$1);
  3274. const findInWarehouse = (warehouse, element) => findMap(warehouse.all, r => find$1(r.cells, e => eq$1(element, e.element)));
  3275. const extractCells = (warehouse, target, predicate) => {
  3276. const details = map$1(target.selection, cell$1 => {
  3277. return cell(cell$1).bind(lc => findInWarehouse(warehouse, lc)).filter(predicate);
  3278. });
  3279. const cells = cat(details);
  3280. return someIf(cells.length > 0, cells);
  3281. };
  3282. const run = (operation, extract, adjustment, postAction, genWrappers) => (table, target, generators, behaviours) => {
  3283. const warehouse = Warehouse.fromTable(table);
  3284. const tableSection = Optional.from(behaviours === null || behaviours === void 0 ? void 0 : behaviours.section).getOrThunk(TableSection.fallback);
  3285. const output = extract(warehouse, target).map(info => {
  3286. const model = fromWarehouse(warehouse, generators);
  3287. const result = operation(model, info, eq$1, genWrappers(generators), tableSection);
  3288. const lockedColumns = getLockedColumnsFromGrid(result.grid);
  3289. const grid = toDetailList(result.grid);
  3290. return {
  3291. info,
  3292. grid,
  3293. cursor: result.cursor,
  3294. lockedColumns
  3295. };
  3296. });
  3297. return output.bind(out => {
  3298. const newElements = render$1(table, out.grid);
  3299. const tableSizing = Optional.from(behaviours === null || behaviours === void 0 ? void 0 : behaviours.sizing).getOrThunk(() => TableSize.getTableSize(table));
  3300. const resizing = Optional.from(behaviours === null || behaviours === void 0 ? void 0 : behaviours.resize).getOrThunk(preserveTable);
  3301. adjustment(table, out.grid, out.info, {
  3302. sizing: tableSizing,
  3303. resize: resizing,
  3304. section: tableSection
  3305. });
  3306. postAction(table);
  3307. remove$7(table, LOCKED_COL_ATTR);
  3308. if (out.lockedColumns.length > 0) {
  3309. set$2(table, LOCKED_COL_ATTR, out.lockedColumns.join(','));
  3310. }
  3311. return Optional.some({
  3312. cursor: out.cursor,
  3313. newRows: newElements.newRows,
  3314. newCells: newElements.newCells
  3315. });
  3316. });
  3317. };
  3318. const onPaste = (warehouse, target) => cell(target.element).bind(cell => findInWarehouse(warehouse, cell).map(details => {
  3319. const value = {
  3320. ...details,
  3321. generators: target.generators,
  3322. clipboard: target.clipboard
  3323. };
  3324. return value;
  3325. }));
  3326. const onPasteByEditor = (warehouse, target) => extractCells(warehouse, target, always).map(cells => ({
  3327. cells,
  3328. generators: target.generators,
  3329. clipboard: target.clipboard
  3330. }));
  3331. const onMergable = (_warehouse, target) => target.mergable;
  3332. const onUnmergable = (_warehouse, target) => target.unmergable;
  3333. const onCells = (warehouse, target) => extractCells(warehouse, target, always);
  3334. const onUnlockedCells = (warehouse, target) => extractCells(warehouse, target, detail => !detail.isLocked);
  3335. const isUnlockedTableCell = (warehouse, cell) => findInWarehouse(warehouse, cell).exists(detail => !detail.isLocked);
  3336. const allUnlocked = (warehouse, cells) => forall(cells, cell => isUnlockedTableCell(warehouse, cell));
  3337. const onUnlockedMergable = (warehouse, target) => onMergable(warehouse, target).filter(mergeable => allUnlocked(warehouse, mergeable.cells));
  3338. const onUnlockedUnmergable = (warehouse, target) => onUnmergable(warehouse, target).filter(cells => allUnlocked(warehouse, cells));
  3339. const merge$2 = (grid, bounds, comparator, substitution) => {
  3340. const rows = extractGridDetails(grid).rows;
  3341. if (rows.length === 0) {
  3342. return grid;
  3343. }
  3344. for (let i = bounds.startRow; i <= bounds.finishRow; i++) {
  3345. for (let j = bounds.startCol; j <= bounds.finishCol; j++) {
  3346. const row = rows[i];
  3347. const isLocked = getCell(row, j).isLocked;
  3348. mutateCell(row, j, elementnew(substitution(), false, isLocked));
  3349. }
  3350. }
  3351. return grid;
  3352. };
  3353. const unmerge = (grid, target, comparator, substitution) => {
  3354. const rows = extractGridDetails(grid).rows;
  3355. let first = true;
  3356. for (let i = 0; i < rows.length; i++) {
  3357. for (let j = 0; j < cellLength(rows[0]); j++) {
  3358. const row = rows[i];
  3359. const currentCell = getCell(row, j);
  3360. const currentCellElm = currentCell.element;
  3361. const isToReplace = comparator(currentCellElm, target);
  3362. if (isToReplace && !first) {
  3363. mutateCell(row, j, elementnew(substitution(), true, currentCell.isLocked));
  3364. } else if (isToReplace) {
  3365. first = false;
  3366. }
  3367. }
  3368. }
  3369. return grid;
  3370. };
  3371. const uniqueCells = (row, comparator) => {
  3372. return foldl(row, (rest, cell) => {
  3373. return exists(rest, currentCell => {
  3374. return comparator(currentCell.element, cell.element);
  3375. }) ? rest : rest.concat([cell]);
  3376. }, []);
  3377. };
  3378. const splitCols = (grid, index, comparator, substitution) => {
  3379. if (index > 0 && index < grid[0].cells.length) {
  3380. each$2(grid, row => {
  3381. const prevCell = row.cells[index - 1];
  3382. let offset = 0;
  3383. const substitute = substitution();
  3384. while (row.cells.length > index + offset && comparator(prevCell.element, row.cells[index + offset].element)) {
  3385. mutateCell(row, index + offset, elementnew(substitute, true, row.cells[index + offset].isLocked));
  3386. offset++;
  3387. }
  3388. });
  3389. }
  3390. return grid;
  3391. };
  3392. const splitRows = (grid, index, comparator, substitution) => {
  3393. const rows = extractGridDetails(grid).rows;
  3394. if (index > 0 && index < rows.length) {
  3395. const rowPrevCells = rows[index - 1].cells;
  3396. const cells = uniqueCells(rowPrevCells, comparator);
  3397. each$2(cells, cell => {
  3398. let replacement = Optional.none();
  3399. for (let i = index; i < rows.length; i++) {
  3400. for (let j = 0; j < cellLength(rows[0]); j++) {
  3401. const row = rows[i];
  3402. const current = getCell(row, j);
  3403. const isToReplace = comparator(current.element, cell.element);
  3404. if (isToReplace) {
  3405. if (replacement.isNone()) {
  3406. replacement = Optional.some(substitution());
  3407. }
  3408. replacement.each(sub => {
  3409. mutateCell(row, j, elementnew(sub, true, current.isLocked));
  3410. });
  3411. }
  3412. }
  3413. }
  3414. });
  3415. }
  3416. return grid;
  3417. };
  3418. const value$1 = value => {
  3419. const applyHelper = fn => fn(value);
  3420. const constHelper = constant(value);
  3421. const outputHelper = () => output;
  3422. const output = {
  3423. tag: true,
  3424. inner: value,
  3425. fold: (_onError, onValue) => onValue(value),
  3426. isValue: always,
  3427. isError: never,
  3428. map: mapper => Result.value(mapper(value)),
  3429. mapError: outputHelper,
  3430. bind: applyHelper,
  3431. exists: applyHelper,
  3432. forall: applyHelper,
  3433. getOr: constHelper,
  3434. or: outputHelper,
  3435. getOrThunk: constHelper,
  3436. orThunk: outputHelper,
  3437. getOrDie: constHelper,
  3438. each: fn => {
  3439. fn(value);
  3440. },
  3441. toOptional: () => Optional.some(value)
  3442. };
  3443. return output;
  3444. };
  3445. const error = error => {
  3446. const outputHelper = () => output;
  3447. const output = {
  3448. tag: false,
  3449. inner: error,
  3450. fold: (onError, _onValue) => onError(error),
  3451. isValue: never,
  3452. isError: always,
  3453. map: outputHelper,
  3454. mapError: mapper => Result.error(mapper(error)),
  3455. bind: outputHelper,
  3456. exists: never,
  3457. forall: always,
  3458. getOr: identity,
  3459. or: identity,
  3460. getOrThunk: apply,
  3461. orThunk: apply,
  3462. getOrDie: die(String(error)),
  3463. each: noop,
  3464. toOptional: Optional.none
  3465. };
  3466. return output;
  3467. };
  3468. const fromOption = (optional, err) => optional.fold(() => error(err), value$1);
  3469. const Result = {
  3470. value: value$1,
  3471. error,
  3472. fromOption
  3473. };
  3474. const measure = (startAddress, gridA, gridB) => {
  3475. if (startAddress.row >= gridA.length || startAddress.column > cellLength(gridA[0])) {
  3476. return Result.error('invalid start address out of table bounds, row: ' + startAddress.row + ', column: ' + startAddress.column);
  3477. }
  3478. const rowRemainder = gridA.slice(startAddress.row);
  3479. const colRemainder = rowRemainder[0].cells.slice(startAddress.column);
  3480. const colRequired = cellLength(gridB[0]);
  3481. const rowRequired = gridB.length;
  3482. return Result.value({
  3483. rowDelta: rowRemainder.length - rowRequired,
  3484. colDelta: colRemainder.length - colRequired
  3485. });
  3486. };
  3487. const measureWidth = (gridA, gridB) => {
  3488. const colLengthA = cellLength(gridA[0]);
  3489. const colLengthB = cellLength(gridB[0]);
  3490. return {
  3491. rowDelta: 0,
  3492. colDelta: colLengthA - colLengthB
  3493. };
  3494. };
  3495. const measureHeight = (gridA, gridB) => {
  3496. const rowLengthA = gridA.length;
  3497. const rowLengthB = gridB.length;
  3498. return {
  3499. rowDelta: rowLengthA - rowLengthB,
  3500. colDelta: 0
  3501. };
  3502. };
  3503. const generateElements = (amount, row, generators, isLocked) => {
  3504. const generator = row.section === 'colgroup' ? generators.col : generators.cell;
  3505. return range$1(amount, idx => elementnew(generator(), true, isLocked(idx)));
  3506. };
  3507. const rowFill = (grid, amount, generators, lockedColumns) => {
  3508. const exampleRow = grid[grid.length - 1];
  3509. return grid.concat(range$1(amount, () => {
  3510. const generator = exampleRow.section === 'colgroup' ? generators.colgroup : generators.row;
  3511. const row = clone(exampleRow, generator, identity);
  3512. const elements = generateElements(row.cells.length, row, generators, idx => has$1(lockedColumns, idx.toString()));
  3513. return setCells(row, elements);
  3514. }));
  3515. };
  3516. const colFill = (grid, amount, generators, startIndex) => map$1(grid, row => {
  3517. const newChildren = generateElements(amount, row, generators, never);
  3518. return addCells(row, startIndex, newChildren);
  3519. });
  3520. const lockedColFill = (grid, generators, lockedColumns) => map$1(grid, row => {
  3521. return foldl(lockedColumns, (acc, colNum) => {
  3522. const newChild = generateElements(1, row, generators, always)[0];
  3523. return addCell(acc, colNum, newChild);
  3524. }, row);
  3525. });
  3526. const tailor = (gridA, delta, generators) => {
  3527. const fillCols = delta.colDelta < 0 ? colFill : identity;
  3528. const fillRows = delta.rowDelta < 0 ? rowFill : identity;
  3529. const lockedColumns = getLockedColumnsFromGrid(gridA);
  3530. const gridWidth = cellLength(gridA[0]);
  3531. const isLastColLocked = exists(lockedColumns, locked => locked === gridWidth - 1);
  3532. const modifiedCols = fillCols(gridA, Math.abs(delta.colDelta), generators, isLastColLocked ? gridWidth - 1 : gridWidth);
  3533. const newLockedColumns = getLockedColumnsFromGrid(modifiedCols);
  3534. return fillRows(modifiedCols, Math.abs(delta.rowDelta), generators, mapToObject(newLockedColumns, always));
  3535. };
  3536. const isSpanning = (grid, row, col, comparator) => {
  3537. const candidate = getCell(grid[row], col);
  3538. const matching = curry(comparator, candidate.element);
  3539. const currentRow = grid[row];
  3540. return grid.length > 1 && cellLength(currentRow) > 1 && (col > 0 && matching(getCellElement(currentRow, col - 1)) || col < currentRow.cells.length - 1 && matching(getCellElement(currentRow, col + 1)) || row > 0 && matching(getCellElement(grid[row - 1], col)) || row < grid.length - 1 && matching(getCellElement(grid[row + 1], col)));
  3541. };
  3542. const mergeTables = (startAddress, gridA, gridBRows, generator, comparator, lockedColumns) => {
  3543. const startRow = startAddress.row;
  3544. const startCol = startAddress.column;
  3545. const mergeHeight = gridBRows.length;
  3546. const mergeWidth = cellLength(gridBRows[0]);
  3547. const endRow = startRow + mergeHeight;
  3548. const endCol = startCol + mergeWidth + lockedColumns.length;
  3549. const lockedColumnObj = mapToObject(lockedColumns, always);
  3550. for (let r = startRow; r < endRow; r++) {
  3551. let skippedCol = 0;
  3552. for (let c = startCol; c < endCol; c++) {
  3553. if (lockedColumnObj[c]) {
  3554. skippedCol++;
  3555. continue;
  3556. }
  3557. if (isSpanning(gridA, r, c, comparator)) {
  3558. unmerge(gridA, getCellElement(gridA[r], c), comparator, generator.cell);
  3559. }
  3560. const gridBColIndex = c - startCol - skippedCol;
  3561. const newCell = getCell(gridBRows[r - startRow], gridBColIndex);
  3562. const newCellElm = newCell.element;
  3563. const replacement = generator.replace(newCellElm);
  3564. mutateCell(gridA[r], c, elementnew(replacement, true, newCell.isLocked));
  3565. }
  3566. }
  3567. return gridA;
  3568. };
  3569. const getValidStartAddress = (currentStartAddress, grid, lockedColumns) => {
  3570. const gridColLength = cellLength(grid[0]);
  3571. const adjustedRowAddress = extractGridDetails(grid).cols.length + currentStartAddress.row;
  3572. const possibleColAddresses = range$1(gridColLength - currentStartAddress.column, num => num + currentStartAddress.column);
  3573. const validColAddress = find$1(possibleColAddresses, num => forall(lockedColumns, col => col !== num)).getOr(gridColLength - 1);
  3574. return {
  3575. row: adjustedRowAddress,
  3576. column: validColAddress
  3577. };
  3578. };
  3579. const getLockedColumnsWithinBounds = (startAddress, rows, lockedColumns) => filter$2(lockedColumns, colNum => colNum >= startAddress.column && colNum <= cellLength(rows[0]) + startAddress.column);
  3580. const merge$1 = (startAddress, gridA, gridB, generator, comparator) => {
  3581. const lockedColumns = getLockedColumnsFromGrid(gridA);
  3582. const validStartAddress = getValidStartAddress(startAddress, gridA, lockedColumns);
  3583. const gridBRows = extractGridDetails(gridB).rows;
  3584. const lockedColumnsWithinBounds = getLockedColumnsWithinBounds(validStartAddress, gridBRows, lockedColumns);
  3585. const result = measure(validStartAddress, gridA, gridBRows);
  3586. return result.map(diff => {
  3587. const delta = {
  3588. ...diff,
  3589. colDelta: diff.colDelta - lockedColumnsWithinBounds.length
  3590. };
  3591. const fittedGrid = tailor(gridA, delta, generator);
  3592. const newLockedColumns = getLockedColumnsFromGrid(fittedGrid);
  3593. const newLockedColumnsWithinBounds = getLockedColumnsWithinBounds(validStartAddress, gridBRows, newLockedColumns);
  3594. return mergeTables(validStartAddress, fittedGrid, gridBRows, generator, comparator, newLockedColumnsWithinBounds);
  3595. });
  3596. };
  3597. const insertCols = (index, gridA, gridB, generator, comparator) => {
  3598. splitCols(gridA, index, comparator, generator.cell);
  3599. const delta = measureHeight(gridB, gridA);
  3600. const fittedNewGrid = tailor(gridB, delta, generator);
  3601. const secondDelta = measureHeight(gridA, fittedNewGrid);
  3602. const fittedOldGrid = tailor(gridA, secondDelta, generator);
  3603. return map$1(fittedOldGrid, (gridRow, i) => {
  3604. return addCells(gridRow, index, fittedNewGrid[i].cells);
  3605. });
  3606. };
  3607. const insertRows = (index, gridA, gridB, generator, comparator) => {
  3608. splitRows(gridA, index, comparator, generator.cell);
  3609. const locked = getLockedColumnsFromGrid(gridA);
  3610. const diff = measureWidth(gridA, gridB);
  3611. const delta = {
  3612. ...diff,
  3613. colDelta: diff.colDelta - locked.length
  3614. };
  3615. const fittedOldGrid = tailor(gridA, delta, generator);
  3616. const {
  3617. cols: oldCols,
  3618. rows: oldRows
  3619. } = extractGridDetails(fittedOldGrid);
  3620. const newLocked = getLockedColumnsFromGrid(fittedOldGrid);
  3621. const secondDiff = measureWidth(gridB, gridA);
  3622. const secondDelta = {
  3623. ...secondDiff,
  3624. colDelta: secondDiff.colDelta + newLocked.length
  3625. };
  3626. const fittedGridB = lockedColFill(gridB, generator, newLocked);
  3627. const fittedNewGrid = tailor(fittedGridB, secondDelta, generator);
  3628. return [
  3629. ...oldCols,
  3630. ...oldRows.slice(0, index),
  3631. ...fittedNewGrid,
  3632. ...oldRows.slice(index, oldRows.length)
  3633. ];
  3634. };
  3635. const cloneRow = (row, cloneCell, comparator, substitution) => clone(row, elem => substitution(elem, comparator), cloneCell);
  3636. const insertRowAt = (grid, index, example, comparator, substitution) => {
  3637. const {rows, cols} = extractGridDetails(grid);
  3638. const before = rows.slice(0, index);
  3639. const after = rows.slice(index);
  3640. const newRow = cloneRow(rows[example], (ex, c) => {
  3641. const withinSpan = index > 0 && index < rows.length && comparator(getCellElement(rows[index - 1], c), getCellElement(rows[index], c));
  3642. const ret = withinSpan ? getCell(rows[index], c) : elementnew(substitution(ex.element, comparator), true, ex.isLocked);
  3643. return ret;
  3644. }, comparator, substitution);
  3645. return [
  3646. ...cols,
  3647. ...before,
  3648. newRow,
  3649. ...after
  3650. ];
  3651. };
  3652. const getElementFor = (row, column, section, withinSpan, example, comparator, substitution) => {
  3653. if (section === 'colgroup' || !withinSpan) {
  3654. const cell = getCell(row, example);
  3655. return elementnew(substitution(cell.element, comparator), true, false);
  3656. } else {
  3657. return getCell(row, column);
  3658. }
  3659. };
  3660. const insertColumnAt = (grid, index, example, comparator, substitution) => map$1(grid, row => {
  3661. const withinSpan = index > 0 && index < cellLength(row) && comparator(getCellElement(row, index - 1), getCellElement(row, index));
  3662. const sub = getElementFor(row, index, row.section, withinSpan, example, comparator, substitution);
  3663. return addCell(row, index, sub);
  3664. });
  3665. const deleteColumnsAt = (grid, columns) => bind$2(grid, row => {
  3666. const existingCells = row.cells;
  3667. const cells = foldr(columns, (acc, column) => column >= 0 && column < acc.length ? acc.slice(0, column).concat(acc.slice(column + 1)) : acc, existingCells);
  3668. return cells.length > 0 ? [rowcells(row.element, cells, row.section, row.isNew)] : [];
  3669. });
  3670. const deleteRowsAt = (grid, start, finish) => {
  3671. const {rows, cols} = extractGridDetails(grid);
  3672. return [
  3673. ...cols,
  3674. ...rows.slice(0, start),
  3675. ...rows.slice(finish + 1)
  3676. ];
  3677. };
  3678. const notInStartRow = (grid, rowIndex, colIndex, comparator) => getCellElement(grid[rowIndex], colIndex) !== undefined && (rowIndex > 0 && comparator(getCellElement(grid[rowIndex - 1], colIndex), getCellElement(grid[rowIndex], colIndex)));
  3679. const notInStartColumn = (row, index, comparator) => index > 0 && comparator(getCellElement(row, index - 1), getCellElement(row, index));
  3680. const isDuplicatedCell = (grid, rowIndex, colIndex, comparator) => notInStartRow(grid, rowIndex, colIndex, comparator) || notInStartColumn(grid[rowIndex], colIndex, comparator);
  3681. const rowReplacerPredicate = (targetRow, columnHeaders) => {
  3682. const entireTableIsHeader = forall(columnHeaders, identity) && isHeaderCells(targetRow.cells);
  3683. return entireTableIsHeader ? always : (cell, _rowIndex, colIndex) => {
  3684. const type = name(cell.element);
  3685. return !(type === 'th' && columnHeaders[colIndex]);
  3686. };
  3687. };
  3688. const columnReplacePredicate = (targetColumn, rowHeaders) => {
  3689. const entireTableIsHeader = forall(rowHeaders, identity) && isHeaderCells(targetColumn);
  3690. return entireTableIsHeader ? always : (cell, rowIndex, _colIndex) => {
  3691. const type = name(cell.element);
  3692. return !(type === 'th' && rowHeaders[rowIndex]);
  3693. };
  3694. };
  3695. const determineScope = (applyScope, cell, newScope, isInHeader) => {
  3696. const hasSpan = scope => scope === 'row' ? hasRowspan(cell) : hasColspan(cell);
  3697. const getScope = scope => hasSpan(scope) ? `${ scope }group` : scope;
  3698. if (applyScope) {
  3699. return isHeaderCell(cell) ? getScope(newScope) : null;
  3700. } else if (isInHeader && isHeaderCell(cell)) {
  3701. const oppositeScope = newScope === 'row' ? 'col' : 'row';
  3702. return getScope(oppositeScope);
  3703. } else {
  3704. return null;
  3705. }
  3706. };
  3707. const rowScopeGenerator = (applyScope, columnHeaders) => (cell, rowIndex, columnIndex) => Optional.some(determineScope(applyScope, cell.element, 'col', columnHeaders[columnIndex]));
  3708. const columnScopeGenerator = (applyScope, rowHeaders) => (cell, rowIndex) => Optional.some(determineScope(applyScope, cell.element, 'row', rowHeaders[rowIndex]));
  3709. const replace = (cell, comparator, substitute) => elementnew(substitute(cell.element, comparator), true, cell.isLocked);
  3710. const replaceIn = (grid, targets, comparator, substitute, replacer, genScope, shouldReplace) => {
  3711. const isTarget = cell => {
  3712. return exists(targets, target => {
  3713. return comparator(cell.element, target.element);
  3714. });
  3715. };
  3716. return map$1(grid, (row, rowIndex) => {
  3717. return mapCells(row, (cell, colIndex) => {
  3718. if (isTarget(cell)) {
  3719. const newCell = shouldReplace(cell, rowIndex, colIndex) ? replacer(cell, comparator, substitute) : cell;
  3720. genScope(newCell, rowIndex, colIndex).each(scope => {
  3721. setOptions(newCell.element, { scope: Optional.from(scope) });
  3722. });
  3723. return newCell;
  3724. } else {
  3725. return cell;
  3726. }
  3727. });
  3728. });
  3729. };
  3730. const getColumnCells = (rows, columnIndex, comparator) => bind$2(rows, (row, i) => {
  3731. return isDuplicatedCell(rows, i, columnIndex, comparator) ? [] : [getCell(row, columnIndex)];
  3732. });
  3733. const getRowCells = (rows, rowIndex, comparator) => {
  3734. const targetRow = rows[rowIndex];
  3735. return bind$2(targetRow.cells, (item, i) => {
  3736. return isDuplicatedCell(rows, rowIndex, i, comparator) ? [] : [item];
  3737. });
  3738. };
  3739. const replaceColumns = (grid, indexes, applyScope, comparator, substitution) => {
  3740. const rows = extractGridDetails(grid).rows;
  3741. const targets = bind$2(indexes, index => getColumnCells(rows, index, comparator));
  3742. const rowHeaders = map$1(rows, row => isHeaderCells(row.cells));
  3743. const shouldReplaceCell = columnReplacePredicate(targets, rowHeaders);
  3744. const scopeGenerator = columnScopeGenerator(applyScope, rowHeaders);
  3745. return replaceIn(grid, targets, comparator, substitution, replace, scopeGenerator, shouldReplaceCell);
  3746. };
  3747. const replaceRows = (grid, indexes, section, applyScope, comparator, substitution, tableSection) => {
  3748. const {cols, rows} = extractGridDetails(grid);
  3749. const targetRow = rows[indexes[0]];
  3750. const targets = bind$2(indexes, index => getRowCells(rows, index, comparator));
  3751. const columnHeaders = map$1(targetRow.cells, (_cell, index) => isHeaderCells(getColumnCells(rows, index, comparator)));
  3752. const newRows = [...rows];
  3753. each$2(indexes, index => {
  3754. newRows[index] = tableSection.transformRow(rows[index], section);
  3755. });
  3756. const newGrid = [
  3757. ...cols,
  3758. ...newRows
  3759. ];
  3760. const shouldReplaceCell = rowReplacerPredicate(targetRow, columnHeaders);
  3761. const scopeGenerator = rowScopeGenerator(applyScope, columnHeaders);
  3762. return replaceIn(newGrid, targets, comparator, substitution, tableSection.transformCell, scopeGenerator, shouldReplaceCell);
  3763. };
  3764. const replaceCells = (grid, details, comparator, substitution) => {
  3765. const rows = extractGridDetails(grid).rows;
  3766. const targetCells = map$1(details, detail => getCell(rows[detail.row], detail.column));
  3767. return replaceIn(grid, targetCells, comparator, substitution, replace, Optional.none, always);
  3768. };
  3769. const generate = cases => {
  3770. if (!isArray(cases)) {
  3771. throw new Error('cases must be an array');
  3772. }
  3773. if (cases.length === 0) {
  3774. throw new Error('there must be at least one case');
  3775. }
  3776. const constructors = [];
  3777. const adt = {};
  3778. each$2(cases, (acase, count) => {
  3779. const keys$1 = keys(acase);
  3780. if (keys$1.length !== 1) {
  3781. throw new Error('one and only one name per case');
  3782. }
  3783. const key = keys$1[0];
  3784. const value = acase[key];
  3785. if (adt[key] !== undefined) {
  3786. throw new Error('duplicate key detected:' + key);
  3787. } else if (key === 'cata') {
  3788. throw new Error('cannot have a case named cata (sorry)');
  3789. } else if (!isArray(value)) {
  3790. throw new Error('case arguments must be an array');
  3791. }
  3792. constructors.push(key);
  3793. adt[key] = (...args) => {
  3794. const argLength = args.length;
  3795. if (argLength !== value.length) {
  3796. throw new Error('Wrong number of arguments to case ' + key + '. Expected ' + value.length + ' (' + value + '), got ' + argLength);
  3797. }
  3798. const match = branches => {
  3799. const branchKeys = keys(branches);
  3800. if (constructors.length !== branchKeys.length) {
  3801. throw new Error('Wrong number of arguments to match. Expected: ' + constructors.join(',') + '\nActual: ' + branchKeys.join(','));
  3802. }
  3803. const allReqd = forall(constructors, reqKey => {
  3804. return contains$2(branchKeys, reqKey);
  3805. });
  3806. if (!allReqd) {
  3807. throw new Error('Not all branches were specified when using match. Specified: ' + branchKeys.join(', ') + '\nRequired: ' + constructors.join(', '));
  3808. }
  3809. return branches[key].apply(null, args);
  3810. };
  3811. return {
  3812. fold: (...foldArgs) => {
  3813. if (foldArgs.length !== cases.length) {
  3814. throw new Error('Wrong number of arguments to fold. Expected ' + cases.length + ', got ' + foldArgs.length);
  3815. }
  3816. const target = foldArgs[count];
  3817. return target.apply(null, args);
  3818. },
  3819. match,
  3820. log: label => {
  3821. console.log(label, {
  3822. constructors,
  3823. constructor: key,
  3824. params: args
  3825. });
  3826. }
  3827. };
  3828. };
  3829. });
  3830. return adt;
  3831. };
  3832. const Adt = { generate };
  3833. const adt$6 = Adt.generate([
  3834. { none: [] },
  3835. { only: ['index'] },
  3836. {
  3837. left: [
  3838. 'index',
  3839. 'next'
  3840. ]
  3841. },
  3842. {
  3843. middle: [
  3844. 'prev',
  3845. 'index',
  3846. 'next'
  3847. ]
  3848. },
  3849. {
  3850. right: [
  3851. 'prev',
  3852. 'index'
  3853. ]
  3854. }
  3855. ]);
  3856. const ColumnContext = { ...adt$6 };
  3857. const neighbours = (input, index) => {
  3858. if (input.length === 0) {
  3859. return ColumnContext.none();
  3860. }
  3861. if (input.length === 1) {
  3862. return ColumnContext.only(0);
  3863. }
  3864. if (index === 0) {
  3865. return ColumnContext.left(0, 1);
  3866. }
  3867. if (index === input.length - 1) {
  3868. return ColumnContext.right(index - 1, index);
  3869. }
  3870. if (index > 0 && index < input.length - 1) {
  3871. return ColumnContext.middle(index - 1, index, index + 1);
  3872. }
  3873. return ColumnContext.none();
  3874. };
  3875. const determine = (input, column, step, tableSize, resize) => {
  3876. const result = input.slice(0);
  3877. const context = neighbours(input, column);
  3878. const onNone = constant(map$1(result, constant(0)));
  3879. const onOnly = index => tableSize.singleColumnWidth(result[index], step);
  3880. const onLeft = (index, next) => resize.calcLeftEdgeDeltas(result, index, next, step, tableSize.minCellWidth(), tableSize.isRelative);
  3881. const onMiddle = (prev, index, next) => resize.calcMiddleDeltas(result, prev, index, next, step, tableSize.minCellWidth(), tableSize.isRelative);
  3882. const onRight = (prev, index) => resize.calcRightEdgeDeltas(result, prev, index, step, tableSize.minCellWidth(), tableSize.isRelative);
  3883. return context.fold(onNone, onOnly, onLeft, onMiddle, onRight);
  3884. };
  3885. const total = (start, end, measures) => {
  3886. let r = 0;
  3887. for (let i = start; i < end; i++) {
  3888. r += measures[i] !== undefined ? measures[i] : 0;
  3889. }
  3890. return r;
  3891. };
  3892. const recalculateWidthForCells = (warehouse, widths) => {
  3893. const all = Warehouse.justCells(warehouse);
  3894. return map$1(all, cell => {
  3895. const width = total(cell.column, cell.column + cell.colspan, widths);
  3896. return {
  3897. element: cell.element,
  3898. width,
  3899. colspan: cell.colspan
  3900. };
  3901. });
  3902. };
  3903. const recalculateWidthForColumns = (warehouse, widths) => {
  3904. const groups = Warehouse.justColumns(warehouse);
  3905. return map$1(groups, (column, index) => ({
  3906. element: column.element,
  3907. width: widths[index],
  3908. colspan: column.colspan
  3909. }));
  3910. };
  3911. const recalculateHeightForCells = (warehouse, heights) => {
  3912. const all = Warehouse.justCells(warehouse);
  3913. return map$1(all, cell => {
  3914. const height = total(cell.row, cell.row + cell.rowspan, heights);
  3915. return {
  3916. element: cell.element,
  3917. height,
  3918. rowspan: cell.rowspan
  3919. };
  3920. });
  3921. };
  3922. const matchRowHeight = (warehouse, heights) => {
  3923. return map$1(warehouse.all, (row, i) => {
  3924. return {
  3925. element: row.element,
  3926. height: heights[i]
  3927. };
  3928. });
  3929. };
  3930. const sumUp = newSize => foldr(newSize, (b, a) => b + a, 0);
  3931. const recalculate = (warehouse, widths) => {
  3932. if (Warehouse.hasColumns(warehouse)) {
  3933. return recalculateWidthForColumns(warehouse, widths);
  3934. } else {
  3935. return recalculateWidthForCells(warehouse, widths);
  3936. }
  3937. };
  3938. const recalculateAndApply = (warehouse, widths, tableSize) => {
  3939. const newSizes = recalculate(warehouse, widths);
  3940. each$2(newSizes, cell => {
  3941. tableSize.setElementWidth(cell.element, cell.width);
  3942. });
  3943. };
  3944. const adjustWidth = (table, delta, index, resizing, tableSize) => {
  3945. const warehouse = Warehouse.fromTable(table);
  3946. const step = tableSize.getCellDelta(delta);
  3947. const widths = tableSize.getWidths(warehouse, tableSize);
  3948. const isLastColumn = index === warehouse.grid.columns - 1;
  3949. const clampedStep = resizing.clampTableDelta(widths, index, step, tableSize.minCellWidth(), isLastColumn);
  3950. const deltas = determine(widths, index, clampedStep, tableSize, resizing);
  3951. const newWidths = map$1(deltas, (dx, i) => dx + widths[i]);
  3952. recalculateAndApply(warehouse, newWidths, tableSize);
  3953. resizing.resizeTable(tableSize.adjustTableWidth, clampedStep, isLastColumn);
  3954. };
  3955. const adjustHeight = (table, delta, index, direction) => {
  3956. const warehouse = Warehouse.fromTable(table);
  3957. const heights = getPixelHeights(warehouse, table, direction);
  3958. const newHeights = map$1(heights, (dy, i) => index === i ? Math.max(delta + dy, minHeight()) : dy);
  3959. const newCellSizes = recalculateHeightForCells(warehouse, newHeights);
  3960. const newRowSizes = matchRowHeight(warehouse, newHeights);
  3961. each$2(newRowSizes, row => {
  3962. setHeight(row.element, row.height);
  3963. });
  3964. each$2(newCellSizes, cell => {
  3965. setHeight(cell.element, cell.height);
  3966. });
  3967. const total = sumUp(newHeights);
  3968. setHeight(table, total);
  3969. };
  3970. const adjustAndRedistributeWidths$1 = (_table, list, details, tableSize, resizeBehaviour) => {
  3971. const warehouse = Warehouse.generate(list);
  3972. const sizes = tableSize.getWidths(warehouse, tableSize);
  3973. const tablePixelWidth = tableSize.pixelWidth();
  3974. const {newSizes, delta} = resizeBehaviour.calcRedestributedWidths(sizes, tablePixelWidth, details.pixelDelta, tableSize.isRelative);
  3975. recalculateAndApply(warehouse, newSizes, tableSize);
  3976. tableSize.adjustTableWidth(delta);
  3977. };
  3978. const adjustWidthTo = (_table, list, _info, tableSize) => {
  3979. const warehouse = Warehouse.generate(list);
  3980. const widths = tableSize.getWidths(warehouse, tableSize);
  3981. recalculateAndApply(warehouse, widths, tableSize);
  3982. };
  3983. const uniqueColumns = details => {
  3984. const uniqueCheck = (rest, detail) => {
  3985. const columnExists = exists(rest, currentDetail => currentDetail.column === detail.column);
  3986. return columnExists ? rest : rest.concat([detail]);
  3987. };
  3988. return foldl(details, uniqueCheck, []).sort((detailA, detailB) => detailA.column - detailB.column);
  3989. };
  3990. const isCol = isTag('col');
  3991. const isColgroup = isTag('colgroup');
  3992. const isRow$1 = element => name(element) === 'tr' || isColgroup(element);
  3993. const elementToData = element => {
  3994. const colspan = getAttrValue(element, 'colspan', 1);
  3995. const rowspan = getAttrValue(element, 'rowspan', 1);
  3996. return {
  3997. element,
  3998. colspan,
  3999. rowspan
  4000. };
  4001. };
  4002. const modification = (generators, toData = elementToData) => {
  4003. const nuCell = data => isCol(data.element) ? generators.col(data) : generators.cell(data);
  4004. const nuRow = data => isColgroup(data.element) ? generators.colgroup(data) : generators.row(data);
  4005. const add = element => {
  4006. if (isRow$1(element)) {
  4007. return nuRow({ element });
  4008. } else {
  4009. const cell = element;
  4010. const replacement = nuCell(toData(cell));
  4011. recent = Optional.some({
  4012. item: cell,
  4013. replacement
  4014. });
  4015. return replacement;
  4016. }
  4017. };
  4018. let recent = Optional.none();
  4019. const getOrInit = (element, comparator) => {
  4020. return recent.fold(() => {
  4021. return add(element);
  4022. }, p => {
  4023. return comparator(element, p.item) ? p.replacement : add(element);
  4024. });
  4025. };
  4026. return { getOrInit };
  4027. };
  4028. const transform$1 = tag => {
  4029. return generators => {
  4030. const list = [];
  4031. const find = (element, comparator) => {
  4032. return find$1(list, x => {
  4033. return comparator(x.item, element);
  4034. });
  4035. };
  4036. const makeNew = element => {
  4037. const attrs = tag === 'td' ? { scope: null } : {};
  4038. const cell = generators.replace(element, tag, attrs);
  4039. list.push({
  4040. item: element,
  4041. sub: cell
  4042. });
  4043. return cell;
  4044. };
  4045. const replaceOrInit = (element, comparator) => {
  4046. if (isRow$1(element) || isCol(element)) {
  4047. return element;
  4048. } else {
  4049. const cell = element;
  4050. return find(cell, comparator).fold(() => {
  4051. return makeNew(cell);
  4052. }, p => {
  4053. return comparator(element, p.item) ? p.sub : makeNew(cell);
  4054. });
  4055. }
  4056. };
  4057. return { replaceOrInit };
  4058. };
  4059. };
  4060. const getScopeAttribute = cell => getOpt(cell, 'scope').map(attribute => attribute.substr(0, 3));
  4061. const merging = generators => {
  4062. const unmerge = cell => {
  4063. const scope = getScopeAttribute(cell);
  4064. scope.each(attribute => set$2(cell, 'scope', attribute));
  4065. return () => {
  4066. const raw = generators.cell({
  4067. element: cell,
  4068. colspan: 1,
  4069. rowspan: 1
  4070. });
  4071. remove$5(raw, 'width');
  4072. remove$5(cell, 'width');
  4073. scope.each(attribute => set$2(raw, 'scope', attribute));
  4074. return raw;
  4075. };
  4076. };
  4077. const merge = cells => {
  4078. const getScopeProperty = () => {
  4079. const stringAttributes = cat(map$1(cells, getScopeAttribute));
  4080. if (stringAttributes.length === 0) {
  4081. return Optional.none();
  4082. } else {
  4083. const baseScope = stringAttributes[0];
  4084. const scopes = [
  4085. 'row',
  4086. 'col'
  4087. ];
  4088. const isMixed = exists(stringAttributes, attribute => {
  4089. return attribute !== baseScope && contains$2(scopes, attribute);
  4090. });
  4091. return isMixed ? Optional.none() : Optional.from(baseScope);
  4092. }
  4093. };
  4094. remove$5(cells[0], 'width');
  4095. getScopeProperty().fold(() => remove$7(cells[0], 'scope'), attribute => set$2(cells[0], 'scope', attribute + 'group'));
  4096. return constant(cells[0]);
  4097. };
  4098. return {
  4099. unmerge,
  4100. merge
  4101. };
  4102. };
  4103. const Generators = {
  4104. modification,
  4105. transform: transform$1,
  4106. merging
  4107. };
  4108. const blockList = [
  4109. 'body',
  4110. 'p',
  4111. 'div',
  4112. 'article',
  4113. 'aside',
  4114. 'figcaption',
  4115. 'figure',
  4116. 'footer',
  4117. 'header',
  4118. 'nav',
  4119. 'section',
  4120. 'ol',
  4121. 'ul',
  4122. 'table',
  4123. 'thead',
  4124. 'tfoot',
  4125. 'tbody',
  4126. 'caption',
  4127. 'tr',
  4128. 'td',
  4129. 'th',
  4130. 'h1',
  4131. 'h2',
  4132. 'h3',
  4133. 'h4',
  4134. 'h5',
  4135. 'h6',
  4136. 'blockquote',
  4137. 'pre',
  4138. 'address'
  4139. ];
  4140. const isList$1 = (universe, item) => {
  4141. const tagName = universe.property().name(item);
  4142. return contains$2([
  4143. 'ol',
  4144. 'ul'
  4145. ], tagName);
  4146. };
  4147. const isBlock$1 = (universe, item) => {
  4148. const tagName = universe.property().name(item);
  4149. return contains$2(blockList, tagName);
  4150. };
  4151. const isEmptyTag$1 = (universe, item) => {
  4152. return contains$2([
  4153. 'br',
  4154. 'img',
  4155. 'hr',
  4156. 'input'
  4157. ], universe.property().name(item));
  4158. };
  4159. const universe$1 = DomUniverse();
  4160. const isBlock = element => {
  4161. return isBlock$1(universe$1, element);
  4162. };
  4163. const isList = element => {
  4164. return isList$1(universe$1, element);
  4165. };
  4166. const isEmptyTag = element => {
  4167. return isEmptyTag$1(universe$1, element);
  4168. };
  4169. const merge = cells => {
  4170. const isBr = isTag('br');
  4171. const advancedBr = children => {
  4172. return forall(children, c => {
  4173. return isBr(c) || isText(c) && get$6(c).trim().length === 0;
  4174. });
  4175. };
  4176. const isListItem = el => {
  4177. return name(el) === 'li' || ancestor$2(el, isList).isSome();
  4178. };
  4179. const siblingIsBlock = el => {
  4180. return nextSibling(el).map(rightSibling => {
  4181. if (isBlock(rightSibling)) {
  4182. return true;
  4183. }
  4184. if (isEmptyTag(rightSibling)) {
  4185. return name(rightSibling) === 'img' ? false : true;
  4186. }
  4187. return false;
  4188. }).getOr(false);
  4189. };
  4190. const markCell = cell => {
  4191. return last$1(cell).bind(rightEdge => {
  4192. const rightSiblingIsBlock = siblingIsBlock(rightEdge);
  4193. return parent(rightEdge).map(parent => {
  4194. return rightSiblingIsBlock === true || isListItem(parent) || isBr(rightEdge) || isBlock(parent) && !eq$1(cell, parent) ? [] : [SugarElement.fromTag('br')];
  4195. });
  4196. }).getOr([]);
  4197. };
  4198. const markContent = () => {
  4199. const content = bind$2(cells, cell => {
  4200. const children = children$2(cell);
  4201. return advancedBr(children) ? [] : children.concat(markCell(cell));
  4202. });
  4203. return content.length === 0 ? [SugarElement.fromTag('br')] : content;
  4204. };
  4205. const contents = markContent();
  4206. empty(cells[0]);
  4207. append(cells[0], contents);
  4208. };
  4209. const isEditable = elem => isEditable$1(elem, true);
  4210. const prune = table => {
  4211. const cells = cells$1(table);
  4212. if (cells.length === 0) {
  4213. remove$6(table);
  4214. }
  4215. };
  4216. const outcome = (grid, cursor) => ({
  4217. grid,
  4218. cursor
  4219. });
  4220. const findEditableCursorPosition = rows => findMap(rows, row => findMap(row.cells, cell => {
  4221. const elem = cell.element;
  4222. return someIf(isEditable(elem), elem);
  4223. }));
  4224. const elementFromGrid = (grid, row, column) => {
  4225. var _a, _b;
  4226. const rows = extractGridDetails(grid).rows;
  4227. return Optional.from((_b = (_a = rows[row]) === null || _a === void 0 ? void 0 : _a.cells[column]) === null || _b === void 0 ? void 0 : _b.element).filter(isEditable).orThunk(() => findEditableCursorPosition(rows));
  4228. };
  4229. const bundle = (grid, row, column) => {
  4230. const cursorElement = elementFromGrid(grid, row, column);
  4231. return outcome(grid, cursorElement);
  4232. };
  4233. const uniqueRows = details => {
  4234. const rowCompilation = (rest, detail) => {
  4235. const rowExists = exists(rest, currentDetail => currentDetail.row === detail.row);
  4236. return rowExists ? rest : rest.concat([detail]);
  4237. };
  4238. return foldl(details, rowCompilation, []).sort((detailA, detailB) => detailA.row - detailB.row);
  4239. };
  4240. const opInsertRowsBefore = (grid, details, comparator, genWrappers) => {
  4241. const targetIndex = details[0].row;
  4242. const rows = uniqueRows(details);
  4243. const newGrid = foldr(rows, (acc, row) => {
  4244. const newG = insertRowAt(acc.grid, targetIndex, row.row + acc.delta, comparator, genWrappers.getOrInit);
  4245. return {
  4246. grid: newG,
  4247. delta: acc.delta + 1
  4248. };
  4249. }, {
  4250. grid,
  4251. delta: 0
  4252. }).grid;
  4253. return bundle(newGrid, targetIndex, details[0].column);
  4254. };
  4255. const opInsertRowsAfter = (grid, details, comparator, genWrappers) => {
  4256. const rows = uniqueRows(details);
  4257. const target = rows[rows.length - 1];
  4258. const targetIndex = target.row + target.rowspan;
  4259. const newGrid = foldr(rows, (newG, row) => {
  4260. return insertRowAt(newG, targetIndex, row.row, comparator, genWrappers.getOrInit);
  4261. }, grid);
  4262. return bundle(newGrid, targetIndex, details[0].column);
  4263. };
  4264. const opInsertColumnsBefore = (grid, extractDetail, comparator, genWrappers) => {
  4265. const details = extractDetail.details;
  4266. const columns = uniqueColumns(details);
  4267. const targetIndex = columns[0].column;
  4268. const newGrid = foldr(columns, (acc, col) => {
  4269. const newG = insertColumnAt(acc.grid, targetIndex, col.column + acc.delta, comparator, genWrappers.getOrInit);
  4270. return {
  4271. grid: newG,
  4272. delta: acc.delta + 1
  4273. };
  4274. }, {
  4275. grid,
  4276. delta: 0
  4277. }).grid;
  4278. return bundle(newGrid, details[0].row, targetIndex);
  4279. };
  4280. const opInsertColumnsAfter = (grid, extractDetail, comparator, genWrappers) => {
  4281. const details = extractDetail.details;
  4282. const target = details[details.length - 1];
  4283. const targetIndex = target.column + target.colspan;
  4284. const columns = uniqueColumns(details);
  4285. const newGrid = foldr(columns, (newG, col) => {
  4286. return insertColumnAt(newG, targetIndex, col.column, comparator, genWrappers.getOrInit);
  4287. }, grid);
  4288. return bundle(newGrid, details[0].row, targetIndex);
  4289. };
  4290. const opMakeColumnsHeader = (initialGrid, details, comparator, genWrappers) => {
  4291. const columns = uniqueColumns(details);
  4292. const columnIndexes = map$1(columns, detail => detail.column);
  4293. const newGrid = replaceColumns(initialGrid, columnIndexes, true, comparator, genWrappers.replaceOrInit);
  4294. return bundle(newGrid, details[0].row, details[0].column);
  4295. };
  4296. const opMakeCellsHeader = (initialGrid, details, comparator, genWrappers) => {
  4297. const newGrid = replaceCells(initialGrid, details, comparator, genWrappers.replaceOrInit);
  4298. return bundle(newGrid, details[0].row, details[0].column);
  4299. };
  4300. const opUnmakeColumnsHeader = (initialGrid, details, comparator, genWrappers) => {
  4301. const columns = uniqueColumns(details);
  4302. const columnIndexes = map$1(columns, detail => detail.column);
  4303. const newGrid = replaceColumns(initialGrid, columnIndexes, false, comparator, genWrappers.replaceOrInit);
  4304. return bundle(newGrid, details[0].row, details[0].column);
  4305. };
  4306. const opUnmakeCellsHeader = (initialGrid, details, comparator, genWrappers) => {
  4307. const newGrid = replaceCells(initialGrid, details, comparator, genWrappers.replaceOrInit);
  4308. return bundle(newGrid, details[0].row, details[0].column);
  4309. };
  4310. const makeRowsSection = (section, applyScope) => (initialGrid, details, comparator, genWrappers, tableSection) => {
  4311. const rows = uniqueRows(details);
  4312. const rowIndexes = map$1(rows, detail => detail.row);
  4313. const newGrid = replaceRows(initialGrid, rowIndexes, section, applyScope, comparator, genWrappers.replaceOrInit, tableSection);
  4314. return bundle(newGrid, details[0].row, details[0].column);
  4315. };
  4316. const opMakeRowsHeader = makeRowsSection('thead', true);
  4317. const opMakeRowsBody = makeRowsSection('tbody', false);
  4318. const opMakeRowsFooter = makeRowsSection('tfoot', false);
  4319. const opEraseColumns = (grid, extractDetail, _comparator, _genWrappers) => {
  4320. const columns = uniqueColumns(extractDetail.details);
  4321. const newGrid = deleteColumnsAt(grid, map$1(columns, column => column.column));
  4322. const maxColIndex = newGrid.length > 0 ? newGrid[0].cells.length - 1 : 0;
  4323. return bundle(newGrid, columns[0].row, Math.min(columns[0].column, maxColIndex));
  4324. };
  4325. const opEraseRows = (grid, details, _comparator, _genWrappers) => {
  4326. const rows = uniqueRows(details);
  4327. const newGrid = deleteRowsAt(grid, rows[0].row, rows[rows.length - 1].row);
  4328. const maxRowIndex = newGrid.length > 0 ? newGrid.length - 1 : 0;
  4329. return bundle(newGrid, Math.min(details[0].row, maxRowIndex), details[0].column);
  4330. };
  4331. const opMergeCells = (grid, mergable, comparator, genWrappers) => {
  4332. const cells = mergable.cells;
  4333. merge(cells);
  4334. const newGrid = merge$2(grid, mergable.bounds, comparator, genWrappers.merge(cells));
  4335. return outcome(newGrid, Optional.from(cells[0]));
  4336. };
  4337. const opUnmergeCells = (grid, unmergable, comparator, genWrappers) => {
  4338. const unmerge$1 = (b, cell) => unmerge(b, cell, comparator, genWrappers.unmerge(cell));
  4339. const newGrid = foldr(unmergable, unmerge$1, grid);
  4340. return outcome(newGrid, Optional.from(unmergable[0]));
  4341. };
  4342. const opPasteCells = (grid, pasteDetails, comparator, _genWrappers) => {
  4343. const gridify = (table, generators) => {
  4344. const wh = Warehouse.fromTable(table);
  4345. return toGrid(wh, generators, true);
  4346. };
  4347. const gridB = gridify(pasteDetails.clipboard, pasteDetails.generators);
  4348. const startAddress = address(pasteDetails.row, pasteDetails.column);
  4349. const mergedGrid = merge$1(startAddress, grid, gridB, pasteDetails.generators, comparator);
  4350. return mergedGrid.fold(() => outcome(grid, Optional.some(pasteDetails.element)), newGrid => {
  4351. return bundle(newGrid, pasteDetails.row, pasteDetails.column);
  4352. });
  4353. };
  4354. const gridifyRows = (rows, generators, context) => {
  4355. const pasteDetails = fromPastedRows(rows, context.section);
  4356. const wh = Warehouse.generate(pasteDetails);
  4357. return toGrid(wh, generators, true);
  4358. };
  4359. const opPasteColsBefore = (grid, pasteDetails, comparator, _genWrappers) => {
  4360. const rows = extractGridDetails(grid).rows;
  4361. const index = pasteDetails.cells[0].column;
  4362. const context = rows[pasteDetails.cells[0].row];
  4363. const gridB = gridifyRows(pasteDetails.clipboard, pasteDetails.generators, context);
  4364. const mergedGrid = insertCols(index, grid, gridB, pasteDetails.generators, comparator);
  4365. return bundle(mergedGrid, pasteDetails.cells[0].row, pasteDetails.cells[0].column);
  4366. };
  4367. const opPasteColsAfter = (grid, pasteDetails, comparator, _genWrappers) => {
  4368. const rows = extractGridDetails(grid).rows;
  4369. const index = pasteDetails.cells[pasteDetails.cells.length - 1].column + pasteDetails.cells[pasteDetails.cells.length - 1].colspan;
  4370. const context = rows[pasteDetails.cells[0].row];
  4371. const gridB = gridifyRows(pasteDetails.clipboard, pasteDetails.generators, context);
  4372. const mergedGrid = insertCols(index, grid, gridB, pasteDetails.generators, comparator);
  4373. return bundle(mergedGrid, pasteDetails.cells[0].row, pasteDetails.cells[0].column);
  4374. };
  4375. const opPasteRowsBefore = (grid, pasteDetails, comparator, _genWrappers) => {
  4376. const rows = extractGridDetails(grid).rows;
  4377. const index = pasteDetails.cells[0].row;
  4378. const context = rows[index];
  4379. const gridB = gridifyRows(pasteDetails.clipboard, pasteDetails.generators, context);
  4380. const mergedGrid = insertRows(index, grid, gridB, pasteDetails.generators, comparator);
  4381. return bundle(mergedGrid, pasteDetails.cells[0].row, pasteDetails.cells[0].column);
  4382. };
  4383. const opPasteRowsAfter = (grid, pasteDetails, comparator, _genWrappers) => {
  4384. const rows = extractGridDetails(grid).rows;
  4385. const index = pasteDetails.cells[pasteDetails.cells.length - 1].row + pasteDetails.cells[pasteDetails.cells.length - 1].rowspan;
  4386. const context = rows[pasteDetails.cells[0].row];
  4387. const gridB = gridifyRows(pasteDetails.clipboard, pasteDetails.generators, context);
  4388. const mergedGrid = insertRows(index, grid, gridB, pasteDetails.generators, comparator);
  4389. return bundle(mergedGrid, pasteDetails.cells[0].row, pasteDetails.cells[0].column);
  4390. };
  4391. const opGetColumnsType = (table, target) => {
  4392. const house = Warehouse.fromTable(table);
  4393. const details = onCells(house, target);
  4394. return details.bind(selectedCells => {
  4395. const lastSelectedCell = selectedCells[selectedCells.length - 1];
  4396. const minColRange = selectedCells[0].column;
  4397. const maxColRange = lastSelectedCell.column + lastSelectedCell.colspan;
  4398. const selectedColumnCells = flatten(map$1(house.all, row => filter$2(row.cells, cell => cell.column >= minColRange && cell.column < maxColRange)));
  4399. return findCommonCellType(selectedColumnCells);
  4400. }).getOr('');
  4401. };
  4402. const opGetCellsType = (table, target) => {
  4403. const house = Warehouse.fromTable(table);
  4404. const details = onCells(house, target);
  4405. return details.bind(findCommonCellType).getOr('');
  4406. };
  4407. const opGetRowsType = (table, target) => {
  4408. const house = Warehouse.fromTable(table);
  4409. const details = onCells(house, target);
  4410. return details.bind(selectedCells => {
  4411. const lastSelectedCell = selectedCells[selectedCells.length - 1];
  4412. const minRowRange = selectedCells[0].row;
  4413. const maxRowRange = lastSelectedCell.row + lastSelectedCell.rowspan;
  4414. const selectedRows = house.all.slice(minRowRange, maxRowRange);
  4415. return findCommonRowType(selectedRows);
  4416. }).getOr('');
  4417. };
  4418. const resize = (table, list, details, behaviours) => adjustWidthTo(table, list, details, behaviours.sizing);
  4419. const adjustAndRedistributeWidths = (table, list, details, behaviours) => adjustAndRedistributeWidths$1(table, list, details, behaviours.sizing, behaviours.resize);
  4420. const firstColumnIsLocked = (_warehouse, details) => exists(details, detail => detail.column === 0 && detail.isLocked);
  4421. const lastColumnIsLocked = (warehouse, details) => exists(details, detail => detail.column + detail.colspan >= warehouse.grid.columns && detail.isLocked);
  4422. const getColumnsWidth = (warehouse, details) => {
  4423. const columns$1 = columns(warehouse);
  4424. const uniqueCols = uniqueColumns(details);
  4425. return foldl(uniqueCols, (acc, detail) => {
  4426. const column = columns$1[detail.column];
  4427. const colWidth = column.map(getOuter$2).getOr(0);
  4428. return acc + colWidth;
  4429. }, 0);
  4430. };
  4431. const insertColumnsExtractor = before => (warehouse, target) => onCells(warehouse, target).filter(details => {
  4432. const checkLocked = before ? firstColumnIsLocked : lastColumnIsLocked;
  4433. return !checkLocked(warehouse, details);
  4434. }).map(details => ({
  4435. details,
  4436. pixelDelta: getColumnsWidth(warehouse, details)
  4437. }));
  4438. const eraseColumnsExtractor = (warehouse, target) => onUnlockedCells(warehouse, target).map(details => ({
  4439. details,
  4440. pixelDelta: -getColumnsWidth(warehouse, details)
  4441. }));
  4442. const pasteColumnsExtractor = before => (warehouse, target) => onPasteByEditor(warehouse, target).filter(details => {
  4443. const checkLocked = before ? firstColumnIsLocked : lastColumnIsLocked;
  4444. return !checkLocked(warehouse, details.cells);
  4445. });
  4446. const headerCellGenerator = Generators.transform('th');
  4447. const bodyCellGenerator = Generators.transform('td');
  4448. const insertRowsBefore = run(opInsertRowsBefore, onCells, noop, noop, Generators.modification);
  4449. const insertRowsAfter = run(opInsertRowsAfter, onCells, noop, noop, Generators.modification);
  4450. const insertColumnsBefore = run(opInsertColumnsBefore, insertColumnsExtractor(true), adjustAndRedistributeWidths, noop, Generators.modification);
  4451. const insertColumnsAfter = run(opInsertColumnsAfter, insertColumnsExtractor(false), adjustAndRedistributeWidths, noop, Generators.modification);
  4452. const eraseColumns = run(opEraseColumns, eraseColumnsExtractor, adjustAndRedistributeWidths, prune, Generators.modification);
  4453. const eraseRows = run(opEraseRows, onCells, noop, prune, Generators.modification);
  4454. const makeColumnsHeader = run(opMakeColumnsHeader, onUnlockedCells, noop, noop, headerCellGenerator);
  4455. const unmakeColumnsHeader = run(opUnmakeColumnsHeader, onUnlockedCells, noop, noop, bodyCellGenerator);
  4456. const makeRowsHeader = run(opMakeRowsHeader, onUnlockedCells, noop, noop, headerCellGenerator);
  4457. const makeRowsBody = run(opMakeRowsBody, onUnlockedCells, noop, noop, bodyCellGenerator);
  4458. const makeRowsFooter = run(opMakeRowsFooter, onUnlockedCells, noop, noop, bodyCellGenerator);
  4459. const makeCellsHeader = run(opMakeCellsHeader, onUnlockedCells, noop, noop, headerCellGenerator);
  4460. const unmakeCellsHeader = run(opUnmakeCellsHeader, onUnlockedCells, noop, noop, bodyCellGenerator);
  4461. const mergeCells = run(opMergeCells, onUnlockedMergable, resize, noop, Generators.merging);
  4462. const unmergeCells = run(opUnmergeCells, onUnlockedUnmergable, resize, noop, Generators.merging);
  4463. const pasteCells = run(opPasteCells, onPaste, resize, noop, Generators.modification);
  4464. const pasteColsBefore = run(opPasteColsBefore, pasteColumnsExtractor(true), noop, noop, Generators.modification);
  4465. const pasteColsAfter = run(opPasteColsAfter, pasteColumnsExtractor(false), noop, noop, Generators.modification);
  4466. const pasteRowsBefore = run(opPasteRowsBefore, onPasteByEditor, noop, noop, Generators.modification);
  4467. const pasteRowsAfter = run(opPasteRowsAfter, onPasteByEditor, noop, noop, Generators.modification);
  4468. const getColumnsType = opGetColumnsType;
  4469. const getCellsType = opGetCellsType;
  4470. const getRowsType = opGetRowsType;
  4471. const fireNewRow = (editor, row) => editor.dispatch('NewRow', { node: row });
  4472. const fireNewCell = (editor, cell) => editor.dispatch('NewCell', { node: cell });
  4473. const fireTableModified = (editor, table, data) => {
  4474. editor.dispatch('TableModified', {
  4475. ...data,
  4476. table
  4477. });
  4478. };
  4479. const fireTableSelectionChange = (editor, cells, start, finish, otherCells) => {
  4480. editor.dispatch('TableSelectionChange', {
  4481. cells,
  4482. start,
  4483. finish,
  4484. otherCells
  4485. });
  4486. };
  4487. const fireTableSelectionClear = editor => {
  4488. editor.dispatch('TableSelectionClear');
  4489. };
  4490. const fireObjectResizeStart = (editor, target, width, height, origin) => {
  4491. editor.dispatch('ObjectResizeStart', {
  4492. target,
  4493. width,
  4494. height,
  4495. origin
  4496. });
  4497. };
  4498. const fireObjectResized = (editor, target, width, height, origin) => {
  4499. editor.dispatch('ObjectResized', {
  4500. target,
  4501. width,
  4502. height,
  4503. origin
  4504. });
  4505. };
  4506. const styleModified = {
  4507. structure: false,
  4508. style: true
  4509. };
  4510. const structureModified = {
  4511. structure: true,
  4512. style: false
  4513. };
  4514. const styleAndStructureModified = {
  4515. structure: true,
  4516. style: true
  4517. };
  4518. const option = name => editor => editor.options.get(name);
  4519. const defaultWidth = '100%';
  4520. const getPixelForcedWidth = editor => {
  4521. var _a;
  4522. const dom = editor.dom;
  4523. const parentBlock = (_a = dom.getParent(editor.selection.getStart(), dom.isBlock)) !== null && _a !== void 0 ? _a : editor.getBody();
  4524. return getInner(SugarElement.fromDom(parentBlock)) + 'px';
  4525. };
  4526. const determineDefaultTableStyles = (editor, defaultStyles) => {
  4527. if (isTableResponsiveForced(editor) || !shouldStyleWithCss(editor)) {
  4528. return defaultStyles;
  4529. } else if (isTablePixelsForced(editor)) {
  4530. return {
  4531. ...defaultStyles,
  4532. width: getPixelForcedWidth(editor)
  4533. };
  4534. } else {
  4535. return {
  4536. ...defaultStyles,
  4537. width: defaultWidth
  4538. };
  4539. }
  4540. };
  4541. const determineDefaultTableAttributes = (editor, defaultAttributes) => {
  4542. if (isTableResponsiveForced(editor) || shouldStyleWithCss(editor)) {
  4543. return defaultAttributes;
  4544. } else if (isTablePixelsForced(editor)) {
  4545. return {
  4546. ...defaultAttributes,
  4547. width: getPixelForcedWidth(editor)
  4548. };
  4549. } else {
  4550. return {
  4551. ...defaultAttributes,
  4552. width: defaultWidth
  4553. };
  4554. }
  4555. };
  4556. const register = editor => {
  4557. const registerOption = editor.options.register;
  4558. registerOption('table_clone_elements', { processor: 'string[]' });
  4559. registerOption('table_use_colgroups', {
  4560. processor: 'boolean',
  4561. default: true
  4562. });
  4563. registerOption('table_header_type', {
  4564. processor: value => {
  4565. const valid = contains$2([
  4566. 'section',
  4567. 'cells',
  4568. 'sectionCells',
  4569. 'auto'
  4570. ], value);
  4571. return valid ? {
  4572. value,
  4573. valid
  4574. } : {
  4575. valid: false,
  4576. message: 'Must be one of: section, cells, sectionCells or auto.'
  4577. };
  4578. },
  4579. default: 'section'
  4580. });
  4581. registerOption('table_sizing_mode', {
  4582. processor: 'string',
  4583. default: 'auto'
  4584. });
  4585. registerOption('table_default_attributes', {
  4586. processor: 'object',
  4587. default: { border: '1' }
  4588. });
  4589. registerOption('table_default_styles', {
  4590. processor: 'object',
  4591. default: { 'border-collapse': 'collapse' }
  4592. });
  4593. registerOption('table_column_resizing', {
  4594. processor: value => {
  4595. const valid = contains$2([
  4596. 'preservetable',
  4597. 'resizetable'
  4598. ], value);
  4599. return valid ? {
  4600. value,
  4601. valid
  4602. } : {
  4603. valid: false,
  4604. message: 'Must be preservetable, or resizetable.'
  4605. };
  4606. },
  4607. default: 'preservetable'
  4608. });
  4609. registerOption('table_resize_bars', {
  4610. processor: 'boolean',
  4611. default: true
  4612. });
  4613. registerOption('table_style_by_css', {
  4614. processor: 'boolean',
  4615. default: true
  4616. });
  4617. };
  4618. const getTableCloneElements = editor => {
  4619. return Optional.from(editor.options.get('table_clone_elements'));
  4620. };
  4621. const hasTableObjectResizing = editor => {
  4622. const objectResizing = editor.options.get('object_resizing');
  4623. return contains$2(objectResizing.split(','), 'table');
  4624. };
  4625. const getTableHeaderType = option('table_header_type');
  4626. const getTableColumnResizingBehaviour = option('table_column_resizing');
  4627. const isPreserveTableColumnResizing = editor => getTableColumnResizingBehaviour(editor) === 'preservetable';
  4628. const isResizeTableColumnResizing = editor => getTableColumnResizingBehaviour(editor) === 'resizetable';
  4629. const getTableSizingMode = option('table_sizing_mode');
  4630. const isTablePercentagesForced = editor => getTableSizingMode(editor) === 'relative';
  4631. const isTablePixelsForced = editor => getTableSizingMode(editor) === 'fixed';
  4632. const isTableResponsiveForced = editor => getTableSizingMode(editor) === 'responsive';
  4633. const hasTableResizeBars = option('table_resize_bars');
  4634. const shouldStyleWithCss = option('table_style_by_css');
  4635. const getTableDefaultAttributes = editor => {
  4636. const options = editor.options;
  4637. const defaultAttributes = options.get('table_default_attributes');
  4638. return options.isSet('table_default_attributes') ? defaultAttributes : determineDefaultTableAttributes(editor, defaultAttributes);
  4639. };
  4640. const getTableDefaultStyles = editor => {
  4641. const options = editor.options;
  4642. const defaultStyles = options.get('table_default_styles');
  4643. return options.isSet('table_default_styles') ? defaultStyles : determineDefaultTableStyles(editor, defaultStyles);
  4644. };
  4645. const tableUseColumnGroup = option('table_use_colgroups');
  4646. const get$5 = (editor, table) => {
  4647. if (isTablePercentagesForced(editor)) {
  4648. return TableSize.percentageSize(table);
  4649. } else if (isTablePixelsForced(editor)) {
  4650. return TableSize.pixelSize(table);
  4651. } else {
  4652. return TableSize.getTableSize(table);
  4653. }
  4654. };
  4655. const TableActions = (editor, resizeHandler, cellSelectionHandler) => {
  4656. const isTableBody = editor => name(getBody(editor)) === 'table';
  4657. const lastRowGuard = table => !isTableBody(editor) || getGridSize(table).rows > 1;
  4658. const lastColumnGuard = table => !isTableBody(editor) || getGridSize(table).columns > 1;
  4659. const cloneFormats = getTableCloneElements(editor);
  4660. const colMutationOp = isResizeTableColumnResizing(editor) ? noop : halve;
  4661. const getTableSectionType = table => {
  4662. switch (getTableHeaderType(editor)) {
  4663. case 'section':
  4664. return TableSection.section();
  4665. case 'sectionCells':
  4666. return TableSection.sectionCells();
  4667. case 'cells':
  4668. return TableSection.cells();
  4669. default:
  4670. return TableSection.getTableSectionType(table, 'section');
  4671. }
  4672. };
  4673. const setSelectionFromAction = (table, result) => result.cursor.fold(() => {
  4674. const cells = cells$1(table);
  4675. return head(cells).filter(inBody).map(firstCell => {
  4676. cellSelectionHandler.clearSelectedCells(table.dom);
  4677. const rng = editor.dom.createRng();
  4678. rng.selectNode(firstCell.dom);
  4679. editor.selection.setRng(rng);
  4680. set$2(firstCell, 'data-mce-selected', '1');
  4681. return rng;
  4682. });
  4683. }, cell => {
  4684. const des = freefallRtl(cell);
  4685. const rng = editor.dom.createRng();
  4686. rng.setStart(des.element.dom, des.offset);
  4687. rng.setEnd(des.element.dom, des.offset);
  4688. editor.selection.setRng(rng);
  4689. cellSelectionHandler.clearSelectedCells(table.dom);
  4690. return Optional.some(rng);
  4691. });
  4692. const execute = (operation, guard, mutate, effect) => (table, target, noEvents = false) => {
  4693. removeDataStyle(table);
  4694. const doc = SugarElement.fromDom(editor.getDoc());
  4695. const generators = cellOperations(mutate, doc, cloneFormats);
  4696. const behaviours = {
  4697. sizing: get$5(editor, table),
  4698. resize: isResizeTableColumnResizing(editor) ? resizeTable() : preserveTable(),
  4699. section: getTableSectionType(table)
  4700. };
  4701. return guard(table) ? operation(table, target, generators, behaviours).bind(result => {
  4702. resizeHandler.refresh(table.dom);
  4703. each$2(result.newRows, row => {
  4704. fireNewRow(editor, row.dom);
  4705. });
  4706. each$2(result.newCells, cell => {
  4707. fireNewCell(editor, cell.dom);
  4708. });
  4709. const range = setSelectionFromAction(table, result);
  4710. if (inBody(table)) {
  4711. removeDataStyle(table);
  4712. if (!noEvents) {
  4713. fireTableModified(editor, table.dom, effect);
  4714. }
  4715. }
  4716. return range.map(rng => ({
  4717. rng,
  4718. effect
  4719. }));
  4720. }) : Optional.none();
  4721. };
  4722. const deleteRow = execute(eraseRows, lastRowGuard, noop, structureModified);
  4723. const deleteColumn = execute(eraseColumns, lastColumnGuard, noop, structureModified);
  4724. const insertRowsBefore$1 = execute(insertRowsBefore, always, noop, structureModified);
  4725. const insertRowsAfter$1 = execute(insertRowsAfter, always, noop, structureModified);
  4726. const insertColumnsBefore$1 = execute(insertColumnsBefore, always, colMutationOp, structureModified);
  4727. const insertColumnsAfter$1 = execute(insertColumnsAfter, always, colMutationOp, structureModified);
  4728. const mergeCells$1 = execute(mergeCells, always, noop, structureModified);
  4729. const unmergeCells$1 = execute(unmergeCells, always, noop, structureModified);
  4730. const pasteColsBefore$1 = execute(pasteColsBefore, always, noop, structureModified);
  4731. const pasteColsAfter$1 = execute(pasteColsAfter, always, noop, structureModified);
  4732. const pasteRowsBefore$1 = execute(pasteRowsBefore, always, noop, structureModified);
  4733. const pasteRowsAfter$1 = execute(pasteRowsAfter, always, noop, structureModified);
  4734. const pasteCells$1 = execute(pasteCells, always, noop, styleAndStructureModified);
  4735. const makeCellsHeader$1 = execute(makeCellsHeader, always, noop, structureModified);
  4736. const unmakeCellsHeader$1 = execute(unmakeCellsHeader, always, noop, structureModified);
  4737. const makeColumnsHeader$1 = execute(makeColumnsHeader, always, noop, structureModified);
  4738. const unmakeColumnsHeader$1 = execute(unmakeColumnsHeader, always, noop, structureModified);
  4739. const makeRowsHeader$1 = execute(makeRowsHeader, always, noop, structureModified);
  4740. const makeRowsBody$1 = execute(makeRowsBody, always, noop, structureModified);
  4741. const makeRowsFooter$1 = execute(makeRowsFooter, always, noop, structureModified);
  4742. const getTableCellType = getCellsType;
  4743. const getTableColType = getColumnsType;
  4744. const getTableRowType = getRowsType;
  4745. return {
  4746. deleteRow,
  4747. deleteColumn,
  4748. insertRowsBefore: insertRowsBefore$1,
  4749. insertRowsAfter: insertRowsAfter$1,
  4750. insertColumnsBefore: insertColumnsBefore$1,
  4751. insertColumnsAfter: insertColumnsAfter$1,
  4752. mergeCells: mergeCells$1,
  4753. unmergeCells: unmergeCells$1,
  4754. pasteColsBefore: pasteColsBefore$1,
  4755. pasteColsAfter: pasteColsAfter$1,
  4756. pasteRowsBefore: pasteRowsBefore$1,
  4757. pasteRowsAfter: pasteRowsAfter$1,
  4758. pasteCells: pasteCells$1,
  4759. makeCellsHeader: makeCellsHeader$1,
  4760. unmakeCellsHeader: unmakeCellsHeader$1,
  4761. makeColumnsHeader: makeColumnsHeader$1,
  4762. unmakeColumnsHeader: unmakeColumnsHeader$1,
  4763. makeRowsHeader: makeRowsHeader$1,
  4764. makeRowsBody: makeRowsBody$1,
  4765. makeRowsFooter: makeRowsFooter$1,
  4766. getTableRowType,
  4767. getTableCellType,
  4768. getTableColType
  4769. };
  4770. };
  4771. const constrainSpan = (element, property, value) => {
  4772. const currentColspan = getAttrValue(element, property, 1);
  4773. if (value === 1 || currentColspan <= 1) {
  4774. remove$7(element, property);
  4775. } else {
  4776. set$2(element, property, Math.min(value, currentColspan));
  4777. }
  4778. };
  4779. const isColInRange = (minColRange, maxColRange) => cell => {
  4780. const endCol = cell.column + cell.colspan - 1;
  4781. const startCol = cell.column;
  4782. return endCol >= minColRange && startCol < maxColRange;
  4783. };
  4784. const generateColGroup = (house, minColRange, maxColRange) => {
  4785. if (Warehouse.hasColumns(house)) {
  4786. const colsToCopy = filter$2(Warehouse.justColumns(house), isColInRange(minColRange, maxColRange));
  4787. const copiedCols = map$1(colsToCopy, c => {
  4788. const clonedCol = deep(c.element);
  4789. constrainSpan(clonedCol, 'span', maxColRange - minColRange);
  4790. return clonedCol;
  4791. });
  4792. const fakeColgroup = SugarElement.fromTag('colgroup');
  4793. append(fakeColgroup, copiedCols);
  4794. return [fakeColgroup];
  4795. } else {
  4796. return [];
  4797. }
  4798. };
  4799. const generateRows = (house, minColRange, maxColRange) => map$1(house.all, row => {
  4800. const cellsToCopy = filter$2(row.cells, isColInRange(minColRange, maxColRange));
  4801. const copiedCells = map$1(cellsToCopy, cell => {
  4802. const clonedCell = deep(cell.element);
  4803. constrainSpan(clonedCell, 'colspan', maxColRange - minColRange);
  4804. return clonedCell;
  4805. });
  4806. const fakeTR = SugarElement.fromTag('tr');
  4807. append(fakeTR, copiedCells);
  4808. return fakeTR;
  4809. });
  4810. const copyCols = (table, target) => {
  4811. const house = Warehouse.fromTable(table);
  4812. const details = onUnlockedCells(house, target);
  4813. return details.map(selectedCells => {
  4814. const lastSelectedCell = selectedCells[selectedCells.length - 1];
  4815. const minColRange = selectedCells[0].column;
  4816. const maxColRange = lastSelectedCell.column + lastSelectedCell.colspan;
  4817. const fakeColGroups = generateColGroup(house, minColRange, maxColRange);
  4818. const fakeRows = generateRows(house, minColRange, maxColRange);
  4819. return [
  4820. ...fakeColGroups,
  4821. ...fakeRows
  4822. ];
  4823. });
  4824. };
  4825. const copyRows = (table, target, generators) => {
  4826. const warehouse = Warehouse.fromTable(table);
  4827. const details = onCells(warehouse, target);
  4828. return details.bind(selectedCells => {
  4829. const grid = toGrid(warehouse, generators, false);
  4830. const rows = extractGridDetails(grid).rows;
  4831. const slicedGrid = rows.slice(selectedCells[0].row, selectedCells[selectedCells.length - 1].row + selectedCells[selectedCells.length - 1].rowspan);
  4832. const filteredGrid = bind$2(slicedGrid, row => {
  4833. const newCells = filter$2(row.cells, cell => !cell.isLocked);
  4834. return newCells.length > 0 ? [{
  4835. ...row,
  4836. cells: newCells
  4837. }] : [];
  4838. });
  4839. const slicedDetails = toDetailList(filteredGrid);
  4840. return someIf(slicedDetails.length > 0, slicedDetails);
  4841. }).map(slicedDetails => copy(slicedDetails));
  4842. };
  4843. const adt$5 = Adt.generate([
  4844. { invalid: ['raw'] },
  4845. { pixels: ['value'] },
  4846. { percent: ['value'] }
  4847. ]);
  4848. const validateFor = (suffix, type, value) => {
  4849. const rawAmount = value.substring(0, value.length - suffix.length);
  4850. const amount = parseFloat(rawAmount);
  4851. return rawAmount === amount.toString() ? type(amount) : adt$5.invalid(value);
  4852. };
  4853. const from = value => {
  4854. if (endsWith(value, '%')) {
  4855. return validateFor('%', adt$5.percent, value);
  4856. }
  4857. if (endsWith(value, 'px')) {
  4858. return validateFor('px', adt$5.pixels, value);
  4859. }
  4860. return adt$5.invalid(value);
  4861. };
  4862. const Size = {
  4863. ...adt$5,
  4864. from
  4865. };
  4866. const redistributeToPercent = (widths, totalWidth) => {
  4867. return map$1(widths, w => {
  4868. const colType = Size.from(w);
  4869. return colType.fold(() => {
  4870. return w;
  4871. }, px => {
  4872. const ratio = px / totalWidth * 100;
  4873. return ratio + '%';
  4874. }, pc => {
  4875. return pc + '%';
  4876. });
  4877. });
  4878. };
  4879. const redistributeToPx = (widths, totalWidth, newTotalWidth) => {
  4880. const scale = newTotalWidth / totalWidth;
  4881. return map$1(widths, w => {
  4882. const colType = Size.from(w);
  4883. return colType.fold(() => {
  4884. return w;
  4885. }, px => {
  4886. return px * scale + 'px';
  4887. }, pc => {
  4888. return pc / 100 * newTotalWidth + 'px';
  4889. });
  4890. });
  4891. };
  4892. const redistributeEmpty = (newWidthType, columns) => {
  4893. const f = newWidthType.fold(() => constant(''), pixels => {
  4894. const num = pixels / columns;
  4895. return constant(num + 'px');
  4896. }, () => {
  4897. const num = 100 / columns;
  4898. return constant(num + '%');
  4899. });
  4900. return range$1(columns, f);
  4901. };
  4902. const redistributeValues = (newWidthType, widths, totalWidth) => {
  4903. return newWidthType.fold(() => {
  4904. return widths;
  4905. }, px => {
  4906. return redistributeToPx(widths, totalWidth, px);
  4907. }, _pc => {
  4908. return redistributeToPercent(widths, totalWidth);
  4909. });
  4910. };
  4911. const redistribute$1 = (widths, totalWidth, newWidth) => {
  4912. const newType = Size.from(newWidth);
  4913. const floats = forall(widths, s => {
  4914. return s === '0px';
  4915. }) ? redistributeEmpty(newType, widths.length) : redistributeValues(newType, widths, totalWidth);
  4916. return normalize(floats);
  4917. };
  4918. const sum = (values, fallback) => {
  4919. if (values.length === 0) {
  4920. return fallback;
  4921. }
  4922. return foldr(values, (rest, v) => {
  4923. return Size.from(v).fold(constant(0), identity, identity) + rest;
  4924. }, 0);
  4925. };
  4926. const roundDown = (num, unit) => {
  4927. const floored = Math.floor(num);
  4928. return {
  4929. value: floored + unit,
  4930. remainder: num - floored
  4931. };
  4932. };
  4933. const add$3 = (value, amount) => {
  4934. return Size.from(value).fold(constant(value), px => {
  4935. return px + amount + 'px';
  4936. }, pc => {
  4937. return pc + amount + '%';
  4938. });
  4939. };
  4940. const normalize = values => {
  4941. if (values.length === 0) {
  4942. return values;
  4943. }
  4944. const scan = foldr(values, (rest, value) => {
  4945. const info = Size.from(value).fold(() => ({
  4946. value,
  4947. remainder: 0
  4948. }), num => roundDown(num, 'px'), num => ({
  4949. value: num + '%',
  4950. remainder: 0
  4951. }));
  4952. return {
  4953. output: [info.value].concat(rest.output),
  4954. remainder: rest.remainder + info.remainder
  4955. };
  4956. }, {
  4957. output: [],
  4958. remainder: 0
  4959. });
  4960. const r = scan.output;
  4961. return r.slice(0, r.length - 1).concat([add$3(r[r.length - 1], Math.round(scan.remainder))]);
  4962. };
  4963. const validate = Size.from;
  4964. const redistributeToW = (newWidths, cells, unit) => {
  4965. each$2(cells, cell => {
  4966. const widths = newWidths.slice(cell.column, cell.colspan + cell.column);
  4967. const w = sum(widths, minWidth());
  4968. set$1(cell.element, 'width', w + unit);
  4969. });
  4970. };
  4971. const redistributeToColumns = (newWidths, columns, unit) => {
  4972. each$2(columns, (column, index) => {
  4973. const width = sum([newWidths[index]], minWidth());
  4974. set$1(column.element, 'width', width + unit);
  4975. });
  4976. };
  4977. const redistributeToH = (newHeights, rows, cells, unit) => {
  4978. each$2(cells, cell => {
  4979. const heights = newHeights.slice(cell.row, cell.rowspan + cell.row);
  4980. const h = sum(heights, minHeight());
  4981. set$1(cell.element, 'height', h + unit);
  4982. });
  4983. each$2(rows, (row, i) => {
  4984. set$1(row.element, 'height', newHeights[i]);
  4985. });
  4986. };
  4987. const getUnit = newSize => {
  4988. return validate(newSize).fold(constant('px'), constant('px'), constant('%'));
  4989. };
  4990. const redistribute = (table, optWidth, optHeight) => {
  4991. const warehouse = Warehouse.fromTable(table);
  4992. const rows = warehouse.all;
  4993. const cells = Warehouse.justCells(warehouse);
  4994. const columns = Warehouse.justColumns(warehouse);
  4995. optWidth.each(newWidth => {
  4996. const widthUnit = getUnit(newWidth);
  4997. const totalWidth = get$9(table);
  4998. const oldWidths = getRawWidths(warehouse, table);
  4999. const nuWidths = redistribute$1(oldWidths, totalWidth, newWidth);
  5000. if (Warehouse.hasColumns(warehouse)) {
  5001. redistributeToColumns(nuWidths, columns, widthUnit);
  5002. } else {
  5003. redistributeToW(nuWidths, cells, widthUnit);
  5004. }
  5005. set$1(table, 'width', newWidth);
  5006. });
  5007. optHeight.each(newHeight => {
  5008. const hUnit = getUnit(newHeight);
  5009. const totalHeight = get$8(table);
  5010. const oldHeights = getRawHeights(warehouse, table, height);
  5011. const nuHeights = redistribute$1(oldHeights, totalHeight, newHeight);
  5012. redistributeToH(nuHeights, rows, cells, hUnit);
  5013. set$1(table, 'height', newHeight);
  5014. });
  5015. };
  5016. const isPercentSizing = isPercentSizing$1;
  5017. const isPixelSizing = isPixelSizing$1;
  5018. const isNoneSizing = isNoneSizing$1;
  5019. const cleanupLegacyAttributes = element => {
  5020. remove$7(element, 'width');
  5021. };
  5022. const convertToPercentSize = table => {
  5023. const newWidth = getPercentTableWidth(table);
  5024. redistribute(table, Optional.some(newWidth), Optional.none());
  5025. cleanupLegacyAttributes(table);
  5026. };
  5027. const convertToPixelSize = table => {
  5028. const newWidth = getPixelTableWidth(table);
  5029. redistribute(table, Optional.some(newWidth), Optional.none());
  5030. cleanupLegacyAttributes(table);
  5031. };
  5032. const convertToNoneSize = table => {
  5033. remove$5(table, 'width');
  5034. const columns = columns$1(table);
  5035. const rowElements = columns.length > 0 ? columns : cells$1(table);
  5036. each$2(rowElements, cell => {
  5037. remove$5(cell, 'width');
  5038. cleanupLegacyAttributes(cell);
  5039. });
  5040. cleanupLegacyAttributes(table);
  5041. };
  5042. const DefaultRenderOptions = {
  5043. styles: {
  5044. 'border-collapse': 'collapse',
  5045. 'width': '100%'
  5046. },
  5047. attributes: { border: '1' },
  5048. colGroups: false
  5049. };
  5050. const tableHeaderCell = () => SugarElement.fromTag('th');
  5051. const tableCell = () => SugarElement.fromTag('td');
  5052. const tableColumn = () => SugarElement.fromTag('col');
  5053. const createRow = (columns, rowHeaders, columnHeaders, rowIndex) => {
  5054. const tr = SugarElement.fromTag('tr');
  5055. for (let j = 0; j < columns; j++) {
  5056. const td = rowIndex < rowHeaders || j < columnHeaders ? tableHeaderCell() : tableCell();
  5057. if (j < columnHeaders) {
  5058. set$2(td, 'scope', 'row');
  5059. }
  5060. if (rowIndex < rowHeaders) {
  5061. set$2(td, 'scope', 'col');
  5062. }
  5063. append$1(td, SugarElement.fromTag('br'));
  5064. append$1(tr, td);
  5065. }
  5066. return tr;
  5067. };
  5068. const createGroupRow = columns => {
  5069. const columnGroup = SugarElement.fromTag('colgroup');
  5070. range$1(columns, () => append$1(columnGroup, tableColumn()));
  5071. return columnGroup;
  5072. };
  5073. const createRows = (rows, columns, rowHeaders, columnHeaders) => range$1(rows, r => createRow(columns, rowHeaders, columnHeaders, r));
  5074. const render = (rows, columns, rowHeaders, columnHeaders, headerType, renderOpts = DefaultRenderOptions) => {
  5075. const table = SugarElement.fromTag('table');
  5076. const rowHeadersGoInThead = headerType !== 'cells';
  5077. setAll(table, renderOpts.styles);
  5078. setAll$1(table, renderOpts.attributes);
  5079. if (renderOpts.colGroups) {
  5080. append$1(table, createGroupRow(columns));
  5081. }
  5082. const actualRowHeaders = Math.min(rows, rowHeaders);
  5083. if (rowHeadersGoInThead && rowHeaders > 0) {
  5084. const thead = SugarElement.fromTag('thead');
  5085. append$1(table, thead);
  5086. const theadRowHeaders = headerType === 'sectionCells' ? actualRowHeaders : 0;
  5087. const theadRows = createRows(rowHeaders, columns, theadRowHeaders, columnHeaders);
  5088. append(thead, theadRows);
  5089. }
  5090. const tbody = SugarElement.fromTag('tbody');
  5091. append$1(table, tbody);
  5092. const numRows = rowHeadersGoInThead ? rows - actualRowHeaders : rows;
  5093. const numRowHeaders = rowHeadersGoInThead ? 0 : rowHeaders;
  5094. const tbodyRows = createRows(numRows, columns, numRowHeaders, columnHeaders);
  5095. append(tbody, tbodyRows);
  5096. return table;
  5097. };
  5098. const get$4 = element => element.dom.innerHTML;
  5099. const getOuter = element => {
  5100. const container = SugarElement.fromTag('div');
  5101. const clone = SugarElement.fromDom(element.dom.cloneNode(true));
  5102. append$1(container, clone);
  5103. return get$4(container);
  5104. };
  5105. const placeCaretInCell = (editor, cell) => {
  5106. editor.selection.select(cell.dom, true);
  5107. editor.selection.collapse(true);
  5108. };
  5109. const selectFirstCellInTable = (editor, tableElm) => {
  5110. descendant(tableElm, 'td,th').each(curry(placeCaretInCell, editor));
  5111. };
  5112. const fireEvents = (editor, table) => {
  5113. each$2(descendants(table, 'tr'), row => {
  5114. fireNewRow(editor, row.dom);
  5115. each$2(descendants(row, 'th,td'), cell => {
  5116. fireNewCell(editor, cell.dom);
  5117. });
  5118. });
  5119. };
  5120. const isPercentage = width => isString(width) && width.indexOf('%') !== -1;
  5121. const insert = (editor, columns, rows, colHeaders, rowHeaders) => {
  5122. const defaultStyles = getTableDefaultStyles(editor);
  5123. const options = {
  5124. styles: defaultStyles,
  5125. attributes: getTableDefaultAttributes(editor),
  5126. colGroups: tableUseColumnGroup(editor)
  5127. };
  5128. editor.undoManager.ignore(() => {
  5129. const table = render(rows, columns, rowHeaders, colHeaders, getTableHeaderType(editor), options);
  5130. set$2(table, 'data-mce-id', '__mce');
  5131. const html = getOuter(table);
  5132. editor.insertContent(html);
  5133. editor.addVisual();
  5134. });
  5135. return descendant(getBody(editor), 'table[data-mce-id="__mce"]').map(table => {
  5136. if (isTablePixelsForced(editor)) {
  5137. convertToPixelSize(table);
  5138. } else if (isTableResponsiveForced(editor)) {
  5139. convertToNoneSize(table);
  5140. } else if (isTablePercentagesForced(editor) || isPercentage(defaultStyles.width)) {
  5141. convertToPercentSize(table);
  5142. }
  5143. removeDataStyle(table);
  5144. remove$7(table, 'data-mce-id');
  5145. fireEvents(editor, table);
  5146. selectFirstCellInTable(editor, table);
  5147. return table.dom;
  5148. }).getOrNull();
  5149. };
  5150. const insertTable = (editor, rows, columns, options = {}) => {
  5151. const checkInput = val => isNumber(val) && val > 0;
  5152. if (checkInput(rows) && checkInput(columns)) {
  5153. const headerRows = options.headerRows || 0;
  5154. const headerColumns = options.headerColumns || 0;
  5155. return insert(editor, columns, rows, headerColumns, headerRows);
  5156. } else {
  5157. console.error('Invalid values for mceInsertTable - rows and columns values are required to insert a table.');
  5158. return null;
  5159. }
  5160. };
  5161. var global = tinymce.util.Tools.resolve('tinymce.FakeClipboard');
  5162. const tableTypeBase = 'x-tinymce/dom-table-';
  5163. const tableTypeRow = tableTypeBase + 'rows';
  5164. const tableTypeColumn = tableTypeBase + 'columns';
  5165. const setData = items => {
  5166. const fakeClipboardItem = global.FakeClipboardItem(items);
  5167. global.write([fakeClipboardItem]);
  5168. };
  5169. const getData = type => {
  5170. var _a;
  5171. const items = (_a = global.read()) !== null && _a !== void 0 ? _a : [];
  5172. return findMap(items, item => Optional.from(item.getType(type)));
  5173. };
  5174. const clearData = type => {
  5175. if (getData(type).isSome()) {
  5176. global.clear();
  5177. }
  5178. };
  5179. const setRows = rowsOpt => {
  5180. rowsOpt.fold(clearRows, rows => setData({ [tableTypeRow]: rows }));
  5181. };
  5182. const getRows = () => getData(tableTypeRow);
  5183. const clearRows = () => clearData(tableTypeRow);
  5184. const setColumns = columnsOpt => {
  5185. columnsOpt.fold(clearColumns, columns => setData({ [tableTypeColumn]: columns }));
  5186. };
  5187. const getColumns = () => getData(tableTypeColumn);
  5188. const clearColumns = () => clearData(tableTypeColumn);
  5189. const getSelectionStartCellOrCaption = editor => getSelectionCellOrCaption(getSelectionStart(editor), getIsRoot(editor)).filter(isInEditableContext$1);
  5190. const getSelectionStartCell = editor => getSelectionCell(getSelectionStart(editor), getIsRoot(editor)).filter(isInEditableContext$1);
  5191. const registerCommands = (editor, actions) => {
  5192. const isRoot = getIsRoot(editor);
  5193. const eraseTable = () => getSelectionStartCellOrCaption(editor).each(cellOrCaption => {
  5194. table(cellOrCaption, isRoot).filter(not(isRoot)).each(table => {
  5195. const cursor = SugarElement.fromText('');
  5196. after$5(table, cursor);
  5197. remove$6(table);
  5198. if (editor.dom.isEmpty(editor.getBody())) {
  5199. editor.setContent('');
  5200. editor.selection.setCursorLocation();
  5201. } else {
  5202. const rng = editor.dom.createRng();
  5203. rng.setStart(cursor.dom, 0);
  5204. rng.setEnd(cursor.dom, 0);
  5205. editor.selection.setRng(rng);
  5206. editor.nodeChanged();
  5207. }
  5208. });
  5209. });
  5210. const setSizingMode = sizing => getSelectionStartCellOrCaption(editor).each(cellOrCaption => {
  5211. const isForcedSizing = isTableResponsiveForced(editor) || isTablePixelsForced(editor) || isTablePercentagesForced(editor);
  5212. if (!isForcedSizing) {
  5213. table(cellOrCaption, isRoot).each(table => {
  5214. if (sizing === 'relative' && !isPercentSizing(table)) {
  5215. convertToPercentSize(table);
  5216. } else if (sizing === 'fixed' && !isPixelSizing(table)) {
  5217. convertToPixelSize(table);
  5218. } else if (sizing === 'responsive' && !isNoneSizing(table)) {
  5219. convertToNoneSize(table);
  5220. }
  5221. removeDataStyle(table);
  5222. fireTableModified(editor, table.dom, structureModified);
  5223. });
  5224. }
  5225. });
  5226. const getTableFromCell = cell => table(cell, isRoot);
  5227. const performActionOnSelection = action => getSelectionStartCell(editor).bind(cell => getTableFromCell(cell).map(table => action(table, cell)));
  5228. const toggleTableClass = (_ui, clazz) => {
  5229. performActionOnSelection(table => {
  5230. editor.formatter.toggle('tableclass', { value: clazz }, table.dom);
  5231. fireTableModified(editor, table.dom, styleModified);
  5232. });
  5233. };
  5234. const toggleTableCellClass = (_ui, clazz) => {
  5235. performActionOnSelection(table => {
  5236. const selectedCells = getCellsFromSelection(editor);
  5237. const allHaveClass = forall(selectedCells, cell => editor.formatter.match('tablecellclass', { value: clazz }, cell.dom));
  5238. const formatterAction = allHaveClass ? editor.formatter.remove : editor.formatter.apply;
  5239. each$2(selectedCells, cell => formatterAction('tablecellclass', { value: clazz }, cell.dom));
  5240. fireTableModified(editor, table.dom, styleModified);
  5241. });
  5242. };
  5243. const toggleCaption = () => {
  5244. getSelectionStartCellOrCaption(editor).each(cellOrCaption => {
  5245. table(cellOrCaption, isRoot).each(table => {
  5246. child(table, 'caption').fold(() => {
  5247. const caption = SugarElement.fromTag('caption');
  5248. append$1(caption, SugarElement.fromText('Caption'));
  5249. appendAt(table, caption, 0);
  5250. editor.selection.setCursorLocation(caption.dom, 0);
  5251. }, caption => {
  5252. if (isTag('caption')(cellOrCaption)) {
  5253. one('td', table).each(td => editor.selection.setCursorLocation(td.dom, 0));
  5254. }
  5255. remove$6(caption);
  5256. });
  5257. fireTableModified(editor, table.dom, structureModified);
  5258. });
  5259. });
  5260. };
  5261. const postExecute = _data => {
  5262. editor.focus();
  5263. };
  5264. const actOnSelection = (execute, noEvents = false) => performActionOnSelection((table, startCell) => {
  5265. const targets = forMenu(getCellsFromSelection(editor), table, startCell);
  5266. execute(table, targets, noEvents).each(postExecute);
  5267. });
  5268. const copyRowSelection = () => performActionOnSelection((table, startCell) => {
  5269. const targets = forMenu(getCellsFromSelection(editor), table, startCell);
  5270. const generators = cellOperations(noop, SugarElement.fromDom(editor.getDoc()), Optional.none());
  5271. return copyRows(table, targets, generators);
  5272. });
  5273. const copyColSelection = () => performActionOnSelection((table, startCell) => {
  5274. const targets = forMenu(getCellsFromSelection(editor), table, startCell);
  5275. return copyCols(table, targets);
  5276. });
  5277. const pasteOnSelection = (execute, getRows) => getRows().each(rows => {
  5278. const clonedRows = map$1(rows, row => deep(row));
  5279. performActionOnSelection((table, startCell) => {
  5280. const generators = paste$1(SugarElement.fromDom(editor.getDoc()));
  5281. const targets = pasteRows(getCellsFromSelection(editor), startCell, clonedRows, generators);
  5282. execute(table, targets).each(postExecute);
  5283. });
  5284. });
  5285. const actOnType = getAction => (_ui, args) => get$c(args, 'type').each(type => {
  5286. actOnSelection(getAction(type), args.no_events);
  5287. });
  5288. each$1({
  5289. mceTableSplitCells: () => actOnSelection(actions.unmergeCells),
  5290. mceTableMergeCells: () => actOnSelection(actions.mergeCells),
  5291. mceTableInsertRowBefore: () => actOnSelection(actions.insertRowsBefore),
  5292. mceTableInsertRowAfter: () => actOnSelection(actions.insertRowsAfter),
  5293. mceTableInsertColBefore: () => actOnSelection(actions.insertColumnsBefore),
  5294. mceTableInsertColAfter: () => actOnSelection(actions.insertColumnsAfter),
  5295. mceTableDeleteCol: () => actOnSelection(actions.deleteColumn),
  5296. mceTableDeleteRow: () => actOnSelection(actions.deleteRow),
  5297. mceTableCutCol: () => copyColSelection().each(selection => {
  5298. setColumns(selection);
  5299. actOnSelection(actions.deleteColumn);
  5300. }),
  5301. mceTableCutRow: () => copyRowSelection().each(selection => {
  5302. setRows(selection);
  5303. actOnSelection(actions.deleteRow);
  5304. }),
  5305. mceTableCopyCol: () => copyColSelection().each(selection => setColumns(selection)),
  5306. mceTableCopyRow: () => copyRowSelection().each(selection => setRows(selection)),
  5307. mceTablePasteColBefore: () => pasteOnSelection(actions.pasteColsBefore, getColumns),
  5308. mceTablePasteColAfter: () => pasteOnSelection(actions.pasteColsAfter, getColumns),
  5309. mceTablePasteRowBefore: () => pasteOnSelection(actions.pasteRowsBefore, getRows),
  5310. mceTablePasteRowAfter: () => pasteOnSelection(actions.pasteRowsAfter, getRows),
  5311. mceTableDelete: eraseTable,
  5312. mceTableCellToggleClass: toggleTableCellClass,
  5313. mceTableToggleClass: toggleTableClass,
  5314. mceTableToggleCaption: toggleCaption,
  5315. mceTableSizingMode: (_ui, sizing) => setSizingMode(sizing),
  5316. mceTableCellType: actOnType(type => type === 'th' ? actions.makeCellsHeader : actions.unmakeCellsHeader),
  5317. mceTableColType: actOnType(type => type === 'th' ? actions.makeColumnsHeader : actions.unmakeColumnsHeader),
  5318. mceTableRowType: actOnType(type => {
  5319. switch (type) {
  5320. case 'header':
  5321. return actions.makeRowsHeader;
  5322. case 'footer':
  5323. return actions.makeRowsFooter;
  5324. default:
  5325. return actions.makeRowsBody;
  5326. }
  5327. })
  5328. }, (func, name) => editor.addCommand(name, func));
  5329. editor.addCommand('mceInsertTable', (_ui, args) => {
  5330. insertTable(editor, args.rows, args.columns, args.options);
  5331. });
  5332. editor.addCommand('mceTableApplyCellStyle', (_ui, args) => {
  5333. const getFormatName = style => 'tablecell' + style.toLowerCase().replace('-', '');
  5334. if (!isObject(args)) {
  5335. return;
  5336. }
  5337. const cells = filter$2(getCellsFromSelection(editor), isInEditableContext$1);
  5338. if (cells.length === 0) {
  5339. return;
  5340. }
  5341. const validArgs = filter$1(args, (value, style) => editor.formatter.has(getFormatName(style)) && isString(value));
  5342. if (isEmpty(validArgs)) {
  5343. return;
  5344. }
  5345. each$1(validArgs, (value, style) => {
  5346. const formatName = getFormatName(style);
  5347. each$2(cells, cell => {
  5348. if (value === '') {
  5349. editor.formatter.remove(formatName, { value: null }, cell.dom, true);
  5350. } else {
  5351. editor.formatter.apply(formatName, { value }, cell.dom);
  5352. }
  5353. });
  5354. });
  5355. getTableFromCell(cells[0]).each(table => fireTableModified(editor, table.dom, styleModified));
  5356. });
  5357. };
  5358. const registerQueryCommands = (editor, actions) => {
  5359. const isRoot = getIsRoot(editor);
  5360. const lookupOnSelection = action => getSelectionCell(getSelectionStart(editor)).bind(cell => table(cell, isRoot).map(table => {
  5361. const targets = forMenu(getCellsFromSelection(editor), table, cell);
  5362. return action(table, targets);
  5363. })).getOr('');
  5364. each$1({
  5365. mceTableRowType: () => lookupOnSelection(actions.getTableRowType),
  5366. mceTableCellType: () => lookupOnSelection(actions.getTableCellType),
  5367. mceTableColType: () => lookupOnSelection(actions.getTableColType)
  5368. }, (func, name) => editor.addQueryValueHandler(name, func));
  5369. };
  5370. const adt$4 = Adt.generate([
  5371. { before: ['element'] },
  5372. {
  5373. on: [
  5374. 'element',
  5375. 'offset'
  5376. ]
  5377. },
  5378. { after: ['element'] }
  5379. ]);
  5380. const cata$1 = (subject, onBefore, onOn, onAfter) => subject.fold(onBefore, onOn, onAfter);
  5381. const getStart$1 = situ => situ.fold(identity, identity, identity);
  5382. const before$2 = adt$4.before;
  5383. const on = adt$4.on;
  5384. const after$3 = adt$4.after;
  5385. const Situ = {
  5386. before: before$2,
  5387. on,
  5388. after: after$3,
  5389. cata: cata$1,
  5390. getStart: getStart$1
  5391. };
  5392. const create$4 = (selection, kill) => ({
  5393. selection,
  5394. kill
  5395. });
  5396. const Response = { create: create$4 };
  5397. const selectNode = (win, element) => {
  5398. const rng = win.document.createRange();
  5399. rng.selectNode(element.dom);
  5400. return rng;
  5401. };
  5402. const selectNodeContents = (win, element) => {
  5403. const rng = win.document.createRange();
  5404. selectNodeContentsUsing(rng, element);
  5405. return rng;
  5406. };
  5407. const selectNodeContentsUsing = (rng, element) => rng.selectNodeContents(element.dom);
  5408. const setStart = (rng, situ) => {
  5409. situ.fold(e => {
  5410. rng.setStartBefore(e.dom);
  5411. }, (e, o) => {
  5412. rng.setStart(e.dom, o);
  5413. }, e => {
  5414. rng.setStartAfter(e.dom);
  5415. });
  5416. };
  5417. const setFinish = (rng, situ) => {
  5418. situ.fold(e => {
  5419. rng.setEndBefore(e.dom);
  5420. }, (e, o) => {
  5421. rng.setEnd(e.dom, o);
  5422. }, e => {
  5423. rng.setEndAfter(e.dom);
  5424. });
  5425. };
  5426. const relativeToNative = (win, startSitu, finishSitu) => {
  5427. const range = win.document.createRange();
  5428. setStart(range, startSitu);
  5429. setFinish(range, finishSitu);
  5430. return range;
  5431. };
  5432. const exactToNative = (win, start, soffset, finish, foffset) => {
  5433. const rng = win.document.createRange();
  5434. rng.setStart(start.dom, soffset);
  5435. rng.setEnd(finish.dom, foffset);
  5436. return rng;
  5437. };
  5438. const toRect = rect => ({
  5439. left: rect.left,
  5440. top: rect.top,
  5441. right: rect.right,
  5442. bottom: rect.bottom,
  5443. width: rect.width,
  5444. height: rect.height
  5445. });
  5446. const getFirstRect$1 = rng => {
  5447. const rects = rng.getClientRects();
  5448. const rect = rects.length > 0 ? rects[0] : rng.getBoundingClientRect();
  5449. return rect.width > 0 || rect.height > 0 ? Optional.some(rect).map(toRect) : Optional.none();
  5450. };
  5451. const adt$3 = Adt.generate([
  5452. {
  5453. ltr: [
  5454. 'start',
  5455. 'soffset',
  5456. 'finish',
  5457. 'foffset'
  5458. ]
  5459. },
  5460. {
  5461. rtl: [
  5462. 'start',
  5463. 'soffset',
  5464. 'finish',
  5465. 'foffset'
  5466. ]
  5467. }
  5468. ]);
  5469. const fromRange = (win, type, range) => type(SugarElement.fromDom(range.startContainer), range.startOffset, SugarElement.fromDom(range.endContainer), range.endOffset);
  5470. const getRanges = (win, selection) => selection.match({
  5471. domRange: rng => {
  5472. return {
  5473. ltr: constant(rng),
  5474. rtl: Optional.none
  5475. };
  5476. },
  5477. relative: (startSitu, finishSitu) => {
  5478. return {
  5479. ltr: cached(() => relativeToNative(win, startSitu, finishSitu)),
  5480. rtl: cached(() => Optional.some(relativeToNative(win, finishSitu, startSitu)))
  5481. };
  5482. },
  5483. exact: (start, soffset, finish, foffset) => {
  5484. return {
  5485. ltr: cached(() => exactToNative(win, start, soffset, finish, foffset)),
  5486. rtl: cached(() => Optional.some(exactToNative(win, finish, foffset, start, soffset)))
  5487. };
  5488. }
  5489. });
  5490. const doDiagnose = (win, ranges) => {
  5491. const rng = ranges.ltr();
  5492. if (rng.collapsed) {
  5493. const reversed = ranges.rtl().filter(rev => rev.collapsed === false);
  5494. return reversed.map(rev => adt$3.rtl(SugarElement.fromDom(rev.endContainer), rev.endOffset, SugarElement.fromDom(rev.startContainer), rev.startOffset)).getOrThunk(() => fromRange(win, adt$3.ltr, rng));
  5495. } else {
  5496. return fromRange(win, adt$3.ltr, rng);
  5497. }
  5498. };
  5499. const diagnose = (win, selection) => {
  5500. const ranges = getRanges(win, selection);
  5501. return doDiagnose(win, ranges);
  5502. };
  5503. const asLtrRange = (win, selection) => {
  5504. const diagnosis = diagnose(win, selection);
  5505. return diagnosis.match({
  5506. ltr: (start, soffset, finish, foffset) => {
  5507. const rng = win.document.createRange();
  5508. rng.setStart(start.dom, soffset);
  5509. rng.setEnd(finish.dom, foffset);
  5510. return rng;
  5511. },
  5512. rtl: (start, soffset, finish, foffset) => {
  5513. const rng = win.document.createRange();
  5514. rng.setStart(finish.dom, foffset);
  5515. rng.setEnd(start.dom, soffset);
  5516. return rng;
  5517. }
  5518. });
  5519. };
  5520. adt$3.ltr;
  5521. adt$3.rtl;
  5522. const create$3 = (start, soffset, finish, foffset) => ({
  5523. start,
  5524. soffset,
  5525. finish,
  5526. foffset
  5527. });
  5528. const SimRange = { create: create$3 };
  5529. const create$2 = (start, soffset, finish, foffset) => {
  5530. return {
  5531. start: Situ.on(start, soffset),
  5532. finish: Situ.on(finish, foffset)
  5533. };
  5534. };
  5535. const Situs = { create: create$2 };
  5536. const convertToRange = (win, selection) => {
  5537. const rng = asLtrRange(win, selection);
  5538. return SimRange.create(SugarElement.fromDom(rng.startContainer), rng.startOffset, SugarElement.fromDom(rng.endContainer), rng.endOffset);
  5539. };
  5540. const makeSitus = Situs.create;
  5541. const sync = (container, isRoot, start, soffset, finish, foffset, selectRange) => {
  5542. if (!(eq$1(start, finish) && soffset === foffset)) {
  5543. return closest$1(start, 'td,th', isRoot).bind(s => {
  5544. return closest$1(finish, 'td,th', isRoot).bind(f => {
  5545. return detect(container, isRoot, s, f, selectRange);
  5546. });
  5547. });
  5548. } else {
  5549. return Optional.none();
  5550. }
  5551. };
  5552. const detect = (container, isRoot, start, finish, selectRange) => {
  5553. if (!eq$1(start, finish)) {
  5554. return identify(start, finish, isRoot).bind(cellSel => {
  5555. const boxes = cellSel.boxes.getOr([]);
  5556. if (boxes.length > 1) {
  5557. selectRange(container, boxes, cellSel.start, cellSel.finish);
  5558. return Optional.some(Response.create(Optional.some(makeSitus(start, 0, start, getEnd(start))), true));
  5559. } else {
  5560. return Optional.none();
  5561. }
  5562. });
  5563. } else {
  5564. return Optional.none();
  5565. }
  5566. };
  5567. const update = (rows, columns, container, selected, annotations) => {
  5568. const updateSelection = newSels => {
  5569. annotations.clearBeforeUpdate(container);
  5570. annotations.selectRange(container, newSels.boxes, newSels.start, newSels.finish);
  5571. return newSels.boxes;
  5572. };
  5573. return shiftSelection(selected, rows, columns, annotations.firstSelectedSelector, annotations.lastSelectedSelector).map(updateSelection);
  5574. };
  5575. const traverse = (item, mode) => ({
  5576. item,
  5577. mode
  5578. });
  5579. const backtrack = (universe, item, _direction, transition = sidestep) => {
  5580. return universe.property().parent(item).map(p => {
  5581. return traverse(p, transition);
  5582. });
  5583. };
  5584. const sidestep = (universe, item, direction, transition = advance) => {
  5585. return direction.sibling(universe, item).map(p => {
  5586. return traverse(p, transition);
  5587. });
  5588. };
  5589. const advance = (universe, item, direction, transition = advance) => {
  5590. const children = universe.property().children(item);
  5591. const result = direction.first(children);
  5592. return result.map(r => {
  5593. return traverse(r, transition);
  5594. });
  5595. };
  5596. const successors = [
  5597. {
  5598. current: backtrack,
  5599. next: sidestep,
  5600. fallback: Optional.none()
  5601. },
  5602. {
  5603. current: sidestep,
  5604. next: advance,
  5605. fallback: Optional.some(backtrack)
  5606. },
  5607. {
  5608. current: advance,
  5609. next: advance,
  5610. fallback: Optional.some(sidestep)
  5611. }
  5612. ];
  5613. const go = (universe, item, mode, direction, rules = successors) => {
  5614. const ruleOpt = find$1(rules, succ => {
  5615. return succ.current === mode;
  5616. });
  5617. return ruleOpt.bind(rule => {
  5618. return rule.current(universe, item, direction, rule.next).orThunk(() => {
  5619. return rule.fallback.bind(fb => {
  5620. return go(universe, item, fb, direction);
  5621. });
  5622. });
  5623. });
  5624. };
  5625. const left$1 = () => {
  5626. const sibling = (universe, item) => {
  5627. return universe.query().prevSibling(item);
  5628. };
  5629. const first = children => {
  5630. return children.length > 0 ? Optional.some(children[children.length - 1]) : Optional.none();
  5631. };
  5632. return {
  5633. sibling,
  5634. first
  5635. };
  5636. };
  5637. const right$1 = () => {
  5638. const sibling = (universe, item) => {
  5639. return universe.query().nextSibling(item);
  5640. };
  5641. const first = children => {
  5642. return children.length > 0 ? Optional.some(children[0]) : Optional.none();
  5643. };
  5644. return {
  5645. sibling,
  5646. first
  5647. };
  5648. };
  5649. const Walkers = {
  5650. left: left$1,
  5651. right: right$1
  5652. };
  5653. const hone = (universe, item, predicate, mode, direction, isRoot) => {
  5654. const next = go(universe, item, mode, direction);
  5655. return next.bind(n => {
  5656. if (isRoot(n.item)) {
  5657. return Optional.none();
  5658. } else {
  5659. return predicate(n.item) ? Optional.some(n.item) : hone(universe, n.item, predicate, n.mode, direction, isRoot);
  5660. }
  5661. });
  5662. };
  5663. const left = (universe, item, predicate, isRoot) => {
  5664. return hone(universe, item, predicate, sidestep, Walkers.left(), isRoot);
  5665. };
  5666. const right = (universe, item, predicate, isRoot) => {
  5667. return hone(universe, item, predicate, sidestep, Walkers.right(), isRoot);
  5668. };
  5669. const isLeaf = universe => element => universe.property().children(element).length === 0;
  5670. const before$1 = (universe, item, isRoot) => {
  5671. return seekLeft$1(universe, item, isLeaf(universe), isRoot);
  5672. };
  5673. const after$2 = (universe, item, isRoot) => {
  5674. return seekRight$1(universe, item, isLeaf(universe), isRoot);
  5675. };
  5676. const seekLeft$1 = left;
  5677. const seekRight$1 = right;
  5678. const universe = DomUniverse();
  5679. const before = (element, isRoot) => {
  5680. return before$1(universe, element, isRoot);
  5681. };
  5682. const after$1 = (element, isRoot) => {
  5683. return after$2(universe, element, isRoot);
  5684. };
  5685. const seekLeft = (element, predicate, isRoot) => {
  5686. return seekLeft$1(universe, element, predicate, isRoot);
  5687. };
  5688. const seekRight = (element, predicate, isRoot) => {
  5689. return seekRight$1(universe, element, predicate, isRoot);
  5690. };
  5691. const ancestor = (scope, predicate, isRoot) => ancestor$2(scope, predicate, isRoot).isSome();
  5692. const adt$2 = Adt.generate([
  5693. { none: ['message'] },
  5694. { success: [] },
  5695. { failedUp: ['cell'] },
  5696. { failedDown: ['cell'] }
  5697. ]);
  5698. const isOverlapping = (bridge, before, after) => {
  5699. const beforeBounds = bridge.getRect(before);
  5700. const afterBounds = bridge.getRect(after);
  5701. return afterBounds.right > beforeBounds.left && afterBounds.left < beforeBounds.right;
  5702. };
  5703. const isRow = elem => {
  5704. return closest$1(elem, 'tr');
  5705. };
  5706. const verify = (bridge, before, beforeOffset, after, afterOffset, failure, isRoot) => {
  5707. return closest$1(after, 'td,th', isRoot).bind(afterCell => {
  5708. return closest$1(before, 'td,th', isRoot).map(beforeCell => {
  5709. if (!eq$1(afterCell, beforeCell)) {
  5710. return sharedOne(isRow, [
  5711. afterCell,
  5712. beforeCell
  5713. ]).fold(() => {
  5714. return isOverlapping(bridge, beforeCell, afterCell) ? adt$2.success() : failure(beforeCell);
  5715. }, _sharedRow => {
  5716. return failure(beforeCell);
  5717. });
  5718. } else {
  5719. return eq$1(after, afterCell) && getEnd(afterCell) === afterOffset ? failure(beforeCell) : adt$2.none('in same cell');
  5720. }
  5721. });
  5722. }).getOr(adt$2.none('default'));
  5723. };
  5724. const cata = (subject, onNone, onSuccess, onFailedUp, onFailedDown) => {
  5725. return subject.fold(onNone, onSuccess, onFailedUp, onFailedDown);
  5726. };
  5727. const BeforeAfter = {
  5728. ...adt$2,
  5729. verify,
  5730. cata
  5731. };
  5732. const inParent = (parent, children, element, index) => ({
  5733. parent,
  5734. children,
  5735. element,
  5736. index
  5737. });
  5738. const indexInParent = element => parent(element).bind(parent => {
  5739. const children = children$2(parent);
  5740. return indexOf(children, element).map(index => inParent(parent, children, element, index));
  5741. });
  5742. const indexOf = (elements, element) => findIndex(elements, curry(eq$1, element));
  5743. const isBr = isTag('br');
  5744. const gatherer = (cand, gather, isRoot) => {
  5745. return gather(cand, isRoot).bind(target => {
  5746. return isText(target) && get$6(target).trim().length === 0 ? gatherer(target, gather, isRoot) : Optional.some(target);
  5747. });
  5748. };
  5749. const handleBr = (isRoot, element, direction) => {
  5750. return direction.traverse(element).orThunk(() => {
  5751. return gatherer(element, direction.gather, isRoot);
  5752. }).map(direction.relative);
  5753. };
  5754. const findBr = (element, offset) => {
  5755. return child$2(element, offset).filter(isBr).orThunk(() => {
  5756. return child$2(element, offset - 1).filter(isBr);
  5757. });
  5758. };
  5759. const handleParent = (isRoot, element, offset, direction) => {
  5760. return findBr(element, offset).bind(br => {
  5761. return direction.traverse(br).fold(() => {
  5762. return gatherer(br, direction.gather, isRoot).map(direction.relative);
  5763. }, adjacent => {
  5764. return indexInParent(adjacent).map(info => {
  5765. return Situ.on(info.parent, info.index);
  5766. });
  5767. });
  5768. });
  5769. };
  5770. const tryBr = (isRoot, element, offset, direction) => {
  5771. const target = isBr(element) ? handleBr(isRoot, element, direction) : handleParent(isRoot, element, offset, direction);
  5772. return target.map(tgt => {
  5773. return {
  5774. start: tgt,
  5775. finish: tgt
  5776. };
  5777. });
  5778. };
  5779. const process = analysis => {
  5780. return BeforeAfter.cata(analysis, _message => {
  5781. return Optional.none();
  5782. }, () => {
  5783. return Optional.none();
  5784. }, cell => {
  5785. return Optional.some(point(cell, 0));
  5786. }, cell => {
  5787. return Optional.some(point(cell, getEnd(cell)));
  5788. });
  5789. };
  5790. const moveDown = (caret, amount) => {
  5791. return {
  5792. left: caret.left,
  5793. top: caret.top + amount,
  5794. right: caret.right,
  5795. bottom: caret.bottom + amount
  5796. };
  5797. };
  5798. const moveUp = (caret, amount) => {
  5799. return {
  5800. left: caret.left,
  5801. top: caret.top - amount,
  5802. right: caret.right,
  5803. bottom: caret.bottom - amount
  5804. };
  5805. };
  5806. const translate = (caret, xDelta, yDelta) => {
  5807. return {
  5808. left: caret.left + xDelta,
  5809. top: caret.top + yDelta,
  5810. right: caret.right + xDelta,
  5811. bottom: caret.bottom + yDelta
  5812. };
  5813. };
  5814. const getTop = caret => {
  5815. return caret.top;
  5816. };
  5817. const getBottom = caret => {
  5818. return caret.bottom;
  5819. };
  5820. const getPartialBox = (bridge, element, offset) => {
  5821. if (offset >= 0 && offset < getEnd(element)) {
  5822. return bridge.getRangedRect(element, offset, element, offset + 1);
  5823. } else if (offset > 0) {
  5824. return bridge.getRangedRect(element, offset - 1, element, offset);
  5825. }
  5826. return Optional.none();
  5827. };
  5828. const toCaret = rect => ({
  5829. left: rect.left,
  5830. top: rect.top,
  5831. right: rect.right,
  5832. bottom: rect.bottom
  5833. });
  5834. const getElemBox = (bridge, element) => {
  5835. return Optional.some(bridge.getRect(element));
  5836. };
  5837. const getBoxAt = (bridge, element, offset) => {
  5838. if (isElement(element)) {
  5839. return getElemBox(bridge, element).map(toCaret);
  5840. } else if (isText(element)) {
  5841. return getPartialBox(bridge, element, offset).map(toCaret);
  5842. } else {
  5843. return Optional.none();
  5844. }
  5845. };
  5846. const getEntireBox = (bridge, element) => {
  5847. if (isElement(element)) {
  5848. return getElemBox(bridge, element).map(toCaret);
  5849. } else if (isText(element)) {
  5850. return bridge.getRangedRect(element, 0, element, getEnd(element)).map(toCaret);
  5851. } else {
  5852. return Optional.none();
  5853. }
  5854. };
  5855. const JUMP_SIZE = 5;
  5856. const NUM_RETRIES = 100;
  5857. const adt$1 = Adt.generate([
  5858. { none: [] },
  5859. { retry: ['caret'] }
  5860. ]);
  5861. const isOutside = (caret, box) => {
  5862. return caret.left < box.left || Math.abs(box.right - caret.left) < 1 || caret.left > box.right;
  5863. };
  5864. const inOutsideBlock = (bridge, element, caret) => {
  5865. return closest$2(element, isBlock).fold(never, cell => {
  5866. return getEntireBox(bridge, cell).exists(box => {
  5867. return isOutside(caret, box);
  5868. });
  5869. });
  5870. };
  5871. const adjustDown = (bridge, element, guessBox, original, caret) => {
  5872. const lowerCaret = moveDown(caret, JUMP_SIZE);
  5873. if (Math.abs(guessBox.bottom - original.bottom) < 1) {
  5874. return adt$1.retry(lowerCaret);
  5875. } else if (guessBox.top > caret.bottom) {
  5876. return adt$1.retry(lowerCaret);
  5877. } else if (guessBox.top === caret.bottom) {
  5878. return adt$1.retry(moveDown(caret, 1));
  5879. } else {
  5880. return inOutsideBlock(bridge, element, caret) ? adt$1.retry(translate(lowerCaret, JUMP_SIZE, 0)) : adt$1.none();
  5881. }
  5882. };
  5883. const adjustUp = (bridge, element, guessBox, original, caret) => {
  5884. const higherCaret = moveUp(caret, JUMP_SIZE);
  5885. if (Math.abs(guessBox.top - original.top) < 1) {
  5886. return adt$1.retry(higherCaret);
  5887. } else if (guessBox.bottom < caret.top) {
  5888. return adt$1.retry(higherCaret);
  5889. } else if (guessBox.bottom === caret.top) {
  5890. return adt$1.retry(moveUp(caret, 1));
  5891. } else {
  5892. return inOutsideBlock(bridge, element, caret) ? adt$1.retry(translate(higherCaret, JUMP_SIZE, 0)) : adt$1.none();
  5893. }
  5894. };
  5895. const upMovement = {
  5896. point: getTop,
  5897. adjuster: adjustUp,
  5898. move: moveUp,
  5899. gather: before
  5900. };
  5901. const downMovement = {
  5902. point: getBottom,
  5903. adjuster: adjustDown,
  5904. move: moveDown,
  5905. gather: after$1
  5906. };
  5907. const isAtTable = (bridge, x, y) => {
  5908. return bridge.elementFromPoint(x, y).filter(elm => {
  5909. return name(elm) === 'table';
  5910. }).isSome();
  5911. };
  5912. const adjustForTable = (bridge, movement, original, caret, numRetries) => {
  5913. return adjustTil(bridge, movement, original, movement.move(caret, JUMP_SIZE), numRetries);
  5914. };
  5915. const adjustTil = (bridge, movement, original, caret, numRetries) => {
  5916. if (numRetries === 0) {
  5917. return Optional.some(caret);
  5918. }
  5919. if (isAtTable(bridge, caret.left, movement.point(caret))) {
  5920. return adjustForTable(bridge, movement, original, caret, numRetries - 1);
  5921. }
  5922. return bridge.situsFromPoint(caret.left, movement.point(caret)).bind(guess => {
  5923. return guess.start.fold(Optional.none, element => {
  5924. return getEntireBox(bridge, element).bind(guessBox => {
  5925. return movement.adjuster(bridge, element, guessBox, original, caret).fold(Optional.none, newCaret => {
  5926. return adjustTil(bridge, movement, original, newCaret, numRetries - 1);
  5927. });
  5928. }).orThunk(() => {
  5929. return Optional.some(caret);
  5930. });
  5931. }, Optional.none);
  5932. });
  5933. };
  5934. const checkScroll = (movement, adjusted, bridge) => {
  5935. if (movement.point(adjusted) > bridge.getInnerHeight()) {
  5936. return Optional.some(movement.point(adjusted) - bridge.getInnerHeight());
  5937. } else if (movement.point(adjusted) < 0) {
  5938. return Optional.some(-movement.point(adjusted));
  5939. } else {
  5940. return Optional.none();
  5941. }
  5942. };
  5943. const retry = (movement, bridge, caret) => {
  5944. const moved = movement.move(caret, JUMP_SIZE);
  5945. const adjusted = adjustTil(bridge, movement, caret, moved, NUM_RETRIES).getOr(moved);
  5946. return checkScroll(movement, adjusted, bridge).fold(() => {
  5947. return bridge.situsFromPoint(adjusted.left, movement.point(adjusted));
  5948. }, delta => {
  5949. bridge.scrollBy(0, delta);
  5950. return bridge.situsFromPoint(adjusted.left, movement.point(adjusted) - delta);
  5951. });
  5952. };
  5953. const Retries = {
  5954. tryUp: curry(retry, upMovement),
  5955. tryDown: curry(retry, downMovement),
  5956. getJumpSize: constant(JUMP_SIZE)
  5957. };
  5958. const MAX_RETRIES = 20;
  5959. const findSpot = (bridge, isRoot, direction) => {
  5960. return bridge.getSelection().bind(sel => {
  5961. return tryBr(isRoot, sel.finish, sel.foffset, direction).fold(() => {
  5962. return Optional.some(point(sel.finish, sel.foffset));
  5963. }, brNeighbour => {
  5964. const range = bridge.fromSitus(brNeighbour);
  5965. const analysis = BeforeAfter.verify(bridge, sel.finish, sel.foffset, range.finish, range.foffset, direction.failure, isRoot);
  5966. return process(analysis);
  5967. });
  5968. });
  5969. };
  5970. const scan = (bridge, isRoot, element, offset, direction, numRetries) => {
  5971. if (numRetries === 0) {
  5972. return Optional.none();
  5973. }
  5974. return tryCursor(bridge, isRoot, element, offset, direction).bind(situs => {
  5975. const range = bridge.fromSitus(situs);
  5976. const analysis = BeforeAfter.verify(bridge, element, offset, range.finish, range.foffset, direction.failure, isRoot);
  5977. return BeforeAfter.cata(analysis, () => {
  5978. return Optional.none();
  5979. }, () => {
  5980. return Optional.some(situs);
  5981. }, cell => {
  5982. if (eq$1(element, cell) && offset === 0) {
  5983. return tryAgain(bridge, element, offset, moveUp, direction);
  5984. } else {
  5985. return scan(bridge, isRoot, cell, 0, direction, numRetries - 1);
  5986. }
  5987. }, cell => {
  5988. if (eq$1(element, cell) && offset === getEnd(cell)) {
  5989. return tryAgain(bridge, element, offset, moveDown, direction);
  5990. } else {
  5991. return scan(bridge, isRoot, cell, getEnd(cell), direction, numRetries - 1);
  5992. }
  5993. });
  5994. });
  5995. };
  5996. const tryAgain = (bridge, element, offset, move, direction) => {
  5997. return getBoxAt(bridge, element, offset).bind(box => {
  5998. return tryAt(bridge, direction, move(box, Retries.getJumpSize()));
  5999. });
  6000. };
  6001. const tryAt = (bridge, direction, box) => {
  6002. const browser = detect$2().browser;
  6003. if (browser.isChromium() || browser.isSafari() || browser.isFirefox()) {
  6004. return direction.retry(bridge, box);
  6005. } else {
  6006. return Optional.none();
  6007. }
  6008. };
  6009. const tryCursor = (bridge, isRoot, element, offset, direction) => {
  6010. return getBoxAt(bridge, element, offset).bind(box => {
  6011. return tryAt(bridge, direction, box);
  6012. });
  6013. };
  6014. const handle$1 = (bridge, isRoot, direction) => {
  6015. return findSpot(bridge, isRoot, direction).bind(spot => {
  6016. return scan(bridge, isRoot, spot.element, spot.offset, direction, MAX_RETRIES).map(bridge.fromSitus);
  6017. });
  6018. };
  6019. const inSameTable = (elem, table) => {
  6020. return ancestor(elem, e => {
  6021. return parent(e).exists(p => {
  6022. return eq$1(p, table);
  6023. });
  6024. });
  6025. };
  6026. const simulate = (bridge, isRoot, direction, initial, anchor) => {
  6027. return closest$1(initial, 'td,th', isRoot).bind(start => {
  6028. return closest$1(start, 'table', isRoot).bind(table => {
  6029. if (!inSameTable(anchor, table)) {
  6030. return Optional.none();
  6031. }
  6032. return handle$1(bridge, isRoot, direction).bind(range => {
  6033. return closest$1(range.finish, 'td,th', isRoot).map(finish => {
  6034. return {
  6035. start,
  6036. finish,
  6037. range
  6038. };
  6039. });
  6040. });
  6041. });
  6042. });
  6043. };
  6044. const navigate = (bridge, isRoot, direction, initial, anchor, precheck) => {
  6045. return precheck(initial, isRoot).orThunk(() => {
  6046. return simulate(bridge, isRoot, direction, initial, anchor).map(info => {
  6047. const range = info.range;
  6048. return Response.create(Optional.some(makeSitus(range.start, range.soffset, range.finish, range.foffset)), true);
  6049. });
  6050. });
  6051. };
  6052. const firstUpCheck = (initial, isRoot) => {
  6053. return closest$1(initial, 'tr', isRoot).bind(startRow => {
  6054. return closest$1(startRow, 'table', isRoot).bind(table => {
  6055. const rows = descendants(table, 'tr');
  6056. if (eq$1(startRow, rows[0])) {
  6057. return seekLeft(table, element => {
  6058. return last$1(element).isSome();
  6059. }, isRoot).map(last => {
  6060. const lastOffset = getEnd(last);
  6061. return Response.create(Optional.some(makeSitus(last, lastOffset, last, lastOffset)), true);
  6062. });
  6063. } else {
  6064. return Optional.none();
  6065. }
  6066. });
  6067. });
  6068. };
  6069. const lastDownCheck = (initial, isRoot) => {
  6070. return closest$1(initial, 'tr', isRoot).bind(startRow => {
  6071. return closest$1(startRow, 'table', isRoot).bind(table => {
  6072. const rows = descendants(table, 'tr');
  6073. if (eq$1(startRow, rows[rows.length - 1])) {
  6074. return seekRight(table, element => {
  6075. return first(element).isSome();
  6076. }, isRoot).map(first => {
  6077. return Response.create(Optional.some(makeSitus(first, 0, first, 0)), true);
  6078. });
  6079. } else {
  6080. return Optional.none();
  6081. }
  6082. });
  6083. });
  6084. };
  6085. const select = (bridge, container, isRoot, direction, initial, anchor, selectRange) => {
  6086. return simulate(bridge, isRoot, direction, initial, anchor).bind(info => {
  6087. return detect(container, isRoot, info.start, info.finish, selectRange);
  6088. });
  6089. };
  6090. const Cell = initial => {
  6091. let value = initial;
  6092. const get = () => {
  6093. return value;
  6094. };
  6095. const set = v => {
  6096. value = v;
  6097. };
  6098. return {
  6099. get,
  6100. set
  6101. };
  6102. };
  6103. const singleton = doRevoke => {
  6104. const subject = Cell(Optional.none());
  6105. const revoke = () => subject.get().each(doRevoke);
  6106. const clear = () => {
  6107. revoke();
  6108. subject.set(Optional.none());
  6109. };
  6110. const isSet = () => subject.get().isSome();
  6111. const get = () => subject.get();
  6112. const set = s => {
  6113. revoke();
  6114. subject.set(Optional.some(s));
  6115. };
  6116. return {
  6117. clear,
  6118. isSet,
  6119. get,
  6120. set
  6121. };
  6122. };
  6123. const value = () => {
  6124. const subject = singleton(noop);
  6125. const on = f => subject.get().each(f);
  6126. return {
  6127. ...subject,
  6128. on
  6129. };
  6130. };
  6131. const findCell = (target, isRoot) => closest$1(target, 'td,th', isRoot);
  6132. const isInEditableContext = cell => parentElement(cell).exists(isEditable$1);
  6133. const MouseSelection = (bridge, container, isRoot, annotations) => {
  6134. const cursor = value();
  6135. const clearstate = cursor.clear;
  6136. const applySelection = event => {
  6137. cursor.on(start => {
  6138. annotations.clearBeforeUpdate(container);
  6139. findCell(event.target, isRoot).each(finish => {
  6140. identify(start, finish, isRoot).each(cellSel => {
  6141. const boxes = cellSel.boxes.getOr([]);
  6142. if (boxes.length === 1) {
  6143. const singleCell = boxes[0];
  6144. const isNonEditableCell = getRaw(singleCell) === 'false';
  6145. const isCellClosestContentEditable = is(closest(event.target), singleCell, eq$1);
  6146. if (isNonEditableCell && isCellClosestContentEditable) {
  6147. annotations.selectRange(container, boxes, singleCell, singleCell);
  6148. bridge.selectContents(singleCell);
  6149. }
  6150. } else if (boxes.length > 1) {
  6151. annotations.selectRange(container, boxes, cellSel.start, cellSel.finish);
  6152. bridge.selectContents(finish);
  6153. }
  6154. });
  6155. });
  6156. });
  6157. };
  6158. const mousedown = event => {
  6159. annotations.clear(container);
  6160. findCell(event.target, isRoot).filter(isInEditableContext).each(cursor.set);
  6161. };
  6162. const mouseover = event => {
  6163. applySelection(event);
  6164. };
  6165. const mouseup = event => {
  6166. applySelection(event);
  6167. clearstate();
  6168. };
  6169. return {
  6170. clearstate,
  6171. mousedown,
  6172. mouseover,
  6173. mouseup
  6174. };
  6175. };
  6176. const down = {
  6177. traverse: nextSibling,
  6178. gather: after$1,
  6179. relative: Situ.before,
  6180. retry: Retries.tryDown,
  6181. failure: BeforeAfter.failedDown
  6182. };
  6183. const up = {
  6184. traverse: prevSibling,
  6185. gather: before,
  6186. relative: Situ.before,
  6187. retry: Retries.tryUp,
  6188. failure: BeforeAfter.failedUp
  6189. };
  6190. const isKey = key => {
  6191. return keycode => {
  6192. return keycode === key;
  6193. };
  6194. };
  6195. const isUp = isKey(38);
  6196. const isDown = isKey(40);
  6197. const isNavigation = keycode => {
  6198. return keycode >= 37 && keycode <= 40;
  6199. };
  6200. const ltr = {
  6201. isBackward: isKey(37),
  6202. isForward: isKey(39)
  6203. };
  6204. const rtl = {
  6205. isBackward: isKey(39),
  6206. isForward: isKey(37)
  6207. };
  6208. const get$3 = _DOC => {
  6209. const doc = _DOC !== undefined ? _DOC.dom : document;
  6210. const x = doc.body.scrollLeft || doc.documentElement.scrollLeft;
  6211. const y = doc.body.scrollTop || doc.documentElement.scrollTop;
  6212. return SugarPosition(x, y);
  6213. };
  6214. const by = (x, y, _DOC) => {
  6215. const doc = _DOC !== undefined ? _DOC.dom : document;
  6216. const win = doc.defaultView;
  6217. if (win) {
  6218. win.scrollBy(x, y);
  6219. }
  6220. };
  6221. const adt = Adt.generate([
  6222. { domRange: ['rng'] },
  6223. {
  6224. relative: [
  6225. 'startSitu',
  6226. 'finishSitu'
  6227. ]
  6228. },
  6229. {
  6230. exact: [
  6231. 'start',
  6232. 'soffset',
  6233. 'finish',
  6234. 'foffset'
  6235. ]
  6236. }
  6237. ]);
  6238. const exactFromRange = simRange => adt.exact(simRange.start, simRange.soffset, simRange.finish, simRange.foffset);
  6239. const getStart = selection => selection.match({
  6240. domRange: rng => SugarElement.fromDom(rng.startContainer),
  6241. relative: (startSitu, _finishSitu) => Situ.getStart(startSitu),
  6242. exact: (start, _soffset, _finish, _foffset) => start
  6243. });
  6244. const domRange = adt.domRange;
  6245. const relative = adt.relative;
  6246. const exact = adt.exact;
  6247. const getWin = selection => {
  6248. const start = getStart(selection);
  6249. return defaultView(start);
  6250. };
  6251. const range = SimRange.create;
  6252. const SimSelection = {
  6253. domRange,
  6254. relative,
  6255. exact,
  6256. exactFromRange,
  6257. getWin,
  6258. range
  6259. };
  6260. const caretPositionFromPoint = (doc, x, y) => {
  6261. var _a, _b;
  6262. return Optional.from((_b = (_a = doc.dom).caretPositionFromPoint) === null || _b === void 0 ? void 0 : _b.call(_a, x, y)).bind(pos => {
  6263. if (pos.offsetNode === null) {
  6264. return Optional.none();
  6265. }
  6266. const r = doc.dom.createRange();
  6267. r.setStart(pos.offsetNode, pos.offset);
  6268. r.collapse();
  6269. return Optional.some(r);
  6270. });
  6271. };
  6272. const caretRangeFromPoint = (doc, x, y) => {
  6273. var _a, _b;
  6274. return Optional.from((_b = (_a = doc.dom).caretRangeFromPoint) === null || _b === void 0 ? void 0 : _b.call(_a, x, y));
  6275. };
  6276. const availableSearch = (() => {
  6277. if (document.caretPositionFromPoint) {
  6278. return caretPositionFromPoint;
  6279. } else if (document.caretRangeFromPoint) {
  6280. return caretRangeFromPoint;
  6281. } else {
  6282. return Optional.none;
  6283. }
  6284. })();
  6285. const fromPoint = (win, x, y) => {
  6286. const doc = SugarElement.fromDom(win.document);
  6287. return availableSearch(doc, x, y).map(rng => SimRange.create(SugarElement.fromDom(rng.startContainer), rng.startOffset, SugarElement.fromDom(rng.endContainer), rng.endOffset));
  6288. };
  6289. const beforeSpecial = (element, offset) => {
  6290. const name$1 = name(element);
  6291. if ('input' === name$1) {
  6292. return Situ.after(element);
  6293. } else if (!contains$2([
  6294. 'br',
  6295. 'img'
  6296. ], name$1)) {
  6297. return Situ.on(element, offset);
  6298. } else {
  6299. return offset === 0 ? Situ.before(element) : Situ.after(element);
  6300. }
  6301. };
  6302. const preprocessRelative = (startSitu, finishSitu) => {
  6303. const start = startSitu.fold(Situ.before, beforeSpecial, Situ.after);
  6304. const finish = finishSitu.fold(Situ.before, beforeSpecial, Situ.after);
  6305. return SimSelection.relative(start, finish);
  6306. };
  6307. const preprocessExact = (start, soffset, finish, foffset) => {
  6308. const startSitu = beforeSpecial(start, soffset);
  6309. const finishSitu = beforeSpecial(finish, foffset);
  6310. return SimSelection.relative(startSitu, finishSitu);
  6311. };
  6312. const makeRange = (start, soffset, finish, foffset) => {
  6313. const doc = owner(start);
  6314. const rng = doc.dom.createRange();
  6315. rng.setStart(start.dom, soffset);
  6316. rng.setEnd(finish.dom, foffset);
  6317. return rng;
  6318. };
  6319. const after = (start, soffset, finish, foffset) => {
  6320. const r = makeRange(start, soffset, finish, foffset);
  6321. const same = eq$1(start, finish) && soffset === foffset;
  6322. return r.collapsed && !same;
  6323. };
  6324. const getNativeSelection = win => Optional.from(win.getSelection());
  6325. const doSetNativeRange = (win, rng) => {
  6326. getNativeSelection(win).each(selection => {
  6327. selection.removeAllRanges();
  6328. selection.addRange(rng);
  6329. });
  6330. };
  6331. const doSetRange = (win, start, soffset, finish, foffset) => {
  6332. const rng = exactToNative(win, start, soffset, finish, foffset);
  6333. doSetNativeRange(win, rng);
  6334. };
  6335. const setLegacyRtlRange = (win, selection, start, soffset, finish, foffset) => {
  6336. selection.collapse(start.dom, soffset);
  6337. selection.extend(finish.dom, foffset);
  6338. };
  6339. const setRangeFromRelative = (win, relative) => diagnose(win, relative).match({
  6340. ltr: (start, soffset, finish, foffset) => {
  6341. doSetRange(win, start, soffset, finish, foffset);
  6342. },
  6343. rtl: (start, soffset, finish, foffset) => {
  6344. getNativeSelection(win).each(selection => {
  6345. if (selection.setBaseAndExtent) {
  6346. selection.setBaseAndExtent(start.dom, soffset, finish.dom, foffset);
  6347. } else if (selection.extend) {
  6348. try {
  6349. setLegacyRtlRange(win, selection, start, soffset, finish, foffset);
  6350. } catch (e) {
  6351. doSetRange(win, finish, foffset, start, soffset);
  6352. }
  6353. } else {
  6354. doSetRange(win, finish, foffset, start, soffset);
  6355. }
  6356. });
  6357. }
  6358. });
  6359. const setExact = (win, start, soffset, finish, foffset) => {
  6360. const relative = preprocessExact(start, soffset, finish, foffset);
  6361. setRangeFromRelative(win, relative);
  6362. };
  6363. const setRelative = (win, startSitu, finishSitu) => {
  6364. const relative = preprocessRelative(startSitu, finishSitu);
  6365. setRangeFromRelative(win, relative);
  6366. };
  6367. const readRange = selection => {
  6368. if (selection.rangeCount > 0) {
  6369. const firstRng = selection.getRangeAt(0);
  6370. const lastRng = selection.getRangeAt(selection.rangeCount - 1);
  6371. return Optional.some(SimRange.create(SugarElement.fromDom(firstRng.startContainer), firstRng.startOffset, SugarElement.fromDom(lastRng.endContainer), lastRng.endOffset));
  6372. } else {
  6373. return Optional.none();
  6374. }
  6375. };
  6376. const doGetExact = selection => {
  6377. if (selection.anchorNode === null || selection.focusNode === null) {
  6378. return readRange(selection);
  6379. } else {
  6380. const anchor = SugarElement.fromDom(selection.anchorNode);
  6381. const focus = SugarElement.fromDom(selection.focusNode);
  6382. return after(anchor, selection.anchorOffset, focus, selection.focusOffset) ? Optional.some(SimRange.create(anchor, selection.anchorOffset, focus, selection.focusOffset)) : readRange(selection);
  6383. }
  6384. };
  6385. const setToElement = (win, element, selectNodeContents$1 = true) => {
  6386. const rngGetter = selectNodeContents$1 ? selectNodeContents : selectNode;
  6387. const rng = rngGetter(win, element);
  6388. doSetNativeRange(win, rng);
  6389. };
  6390. const getExact = win => getNativeSelection(win).filter(sel => sel.rangeCount > 0).bind(doGetExact);
  6391. const get$2 = win => getExact(win).map(range => SimSelection.exact(range.start, range.soffset, range.finish, range.foffset));
  6392. const getFirstRect = (win, selection) => {
  6393. const rng = asLtrRange(win, selection);
  6394. return getFirstRect$1(rng);
  6395. };
  6396. const getAtPoint = (win, x, y) => fromPoint(win, x, y);
  6397. const clear = win => {
  6398. getNativeSelection(win).each(selection => selection.removeAllRanges());
  6399. };
  6400. const WindowBridge = win => {
  6401. const elementFromPoint = (x, y) => {
  6402. return SugarElement.fromPoint(SugarElement.fromDom(win.document), x, y);
  6403. };
  6404. const getRect = element => {
  6405. return element.dom.getBoundingClientRect();
  6406. };
  6407. const getRangedRect = (start, soffset, finish, foffset) => {
  6408. const sel = SimSelection.exact(start, soffset, finish, foffset);
  6409. return getFirstRect(win, sel);
  6410. };
  6411. const getSelection = () => {
  6412. return get$2(win).map(exactAdt => {
  6413. return convertToRange(win, exactAdt);
  6414. });
  6415. };
  6416. const fromSitus = situs => {
  6417. const relative = SimSelection.relative(situs.start, situs.finish);
  6418. return convertToRange(win, relative);
  6419. };
  6420. const situsFromPoint = (x, y) => {
  6421. return getAtPoint(win, x, y).map(exact => {
  6422. return Situs.create(exact.start, exact.soffset, exact.finish, exact.foffset);
  6423. });
  6424. };
  6425. const clearSelection = () => {
  6426. clear(win);
  6427. };
  6428. const collapseSelection = (toStart = false) => {
  6429. get$2(win).each(sel => sel.fold(rng => rng.collapse(toStart), (startSitu, finishSitu) => {
  6430. const situ = toStart ? startSitu : finishSitu;
  6431. setRelative(win, situ, situ);
  6432. }, (start, soffset, finish, foffset) => {
  6433. const node = toStart ? start : finish;
  6434. const offset = toStart ? soffset : foffset;
  6435. setExact(win, node, offset, node, offset);
  6436. }));
  6437. };
  6438. const selectNode = element => {
  6439. setToElement(win, element, false);
  6440. };
  6441. const selectContents = element => {
  6442. setToElement(win, element);
  6443. };
  6444. const setSelection = sel => {
  6445. setExact(win, sel.start, sel.soffset, sel.finish, sel.foffset);
  6446. };
  6447. const setRelativeSelection = (start, finish) => {
  6448. setRelative(win, start, finish);
  6449. };
  6450. const getInnerHeight = () => {
  6451. return win.innerHeight;
  6452. };
  6453. const getScrollY = () => {
  6454. const pos = get$3(SugarElement.fromDom(win.document));
  6455. return pos.top;
  6456. };
  6457. const scrollBy = (x, y) => {
  6458. by(x, y, SugarElement.fromDom(win.document));
  6459. };
  6460. return {
  6461. elementFromPoint,
  6462. getRect,
  6463. getRangedRect,
  6464. getSelection,
  6465. fromSitus,
  6466. situsFromPoint,
  6467. clearSelection,
  6468. collapseSelection,
  6469. setSelection,
  6470. setRelativeSelection,
  6471. selectNode,
  6472. selectContents,
  6473. getInnerHeight,
  6474. getScrollY,
  6475. scrollBy
  6476. };
  6477. };
  6478. const rc = (rows, cols) => ({
  6479. rows,
  6480. cols
  6481. });
  6482. const mouse = (win, container, isRoot, annotations) => {
  6483. const bridge = WindowBridge(win);
  6484. const handlers = MouseSelection(bridge, container, isRoot, annotations);
  6485. return {
  6486. clearstate: handlers.clearstate,
  6487. mousedown: handlers.mousedown,
  6488. mouseover: handlers.mouseover,
  6489. mouseup: handlers.mouseup
  6490. };
  6491. };
  6492. const isEditableNode = node => closest$2(node, isHTMLElement).exists(isEditable$1);
  6493. const isEditableSelection = (start, finish) => isEditableNode(start) || isEditableNode(finish);
  6494. const keyboard = (win, container, isRoot, annotations) => {
  6495. const bridge = WindowBridge(win);
  6496. const clearToNavigate = () => {
  6497. annotations.clear(container);
  6498. return Optional.none();
  6499. };
  6500. const keydown = (event, start, soffset, finish, foffset, direction) => {
  6501. const realEvent = event.raw;
  6502. const keycode = realEvent.which;
  6503. const shiftKey = realEvent.shiftKey === true;
  6504. const handler = retrieve$1(container, annotations.selectedSelector).fold(() => {
  6505. if (isNavigation(keycode) && !shiftKey) {
  6506. annotations.clearBeforeUpdate(container);
  6507. }
  6508. if (isNavigation(keycode) && shiftKey && !isEditableSelection(start, finish)) {
  6509. return Optional.none;
  6510. } else if (isDown(keycode) && shiftKey) {
  6511. return curry(select, bridge, container, isRoot, down, finish, start, annotations.selectRange);
  6512. } else if (isUp(keycode) && shiftKey) {
  6513. return curry(select, bridge, container, isRoot, up, finish, start, annotations.selectRange);
  6514. } else if (isDown(keycode)) {
  6515. return curry(navigate, bridge, isRoot, down, finish, start, lastDownCheck);
  6516. } else if (isUp(keycode)) {
  6517. return curry(navigate, bridge, isRoot, up, finish, start, firstUpCheck);
  6518. } else {
  6519. return Optional.none;
  6520. }
  6521. }, selected => {
  6522. const update$1 = attempts => {
  6523. return () => {
  6524. const navigation = findMap(attempts, delta => {
  6525. return update(delta.rows, delta.cols, container, selected, annotations);
  6526. });
  6527. return navigation.fold(() => {
  6528. return getEdges(container, annotations.firstSelectedSelector, annotations.lastSelectedSelector).map(edges => {
  6529. const relative = isDown(keycode) || direction.isForward(keycode) ? Situ.after : Situ.before;
  6530. bridge.setRelativeSelection(Situ.on(edges.first, 0), relative(edges.table));
  6531. annotations.clear(container);
  6532. return Response.create(Optional.none(), true);
  6533. });
  6534. }, _ => {
  6535. return Optional.some(Response.create(Optional.none(), true));
  6536. });
  6537. };
  6538. };
  6539. if (isNavigation(keycode) && shiftKey && !isEditableSelection(start, finish)) {
  6540. return Optional.none;
  6541. } else if (isDown(keycode) && shiftKey) {
  6542. return update$1([rc(+1, 0)]);
  6543. } else if (isUp(keycode) && shiftKey) {
  6544. return update$1([rc(-1, 0)]);
  6545. } else if (direction.isBackward(keycode) && shiftKey) {
  6546. return update$1([
  6547. rc(0, -1),
  6548. rc(-1, 0)
  6549. ]);
  6550. } else if (direction.isForward(keycode) && shiftKey) {
  6551. return update$1([
  6552. rc(0, +1),
  6553. rc(+1, 0)
  6554. ]);
  6555. } else if (isNavigation(keycode) && !shiftKey) {
  6556. return clearToNavigate;
  6557. } else {
  6558. return Optional.none;
  6559. }
  6560. });
  6561. return handler();
  6562. };
  6563. const keyup = (event, start, soffset, finish, foffset) => {
  6564. return retrieve$1(container, annotations.selectedSelector).fold(() => {
  6565. const realEvent = event.raw;
  6566. const keycode = realEvent.which;
  6567. const shiftKey = realEvent.shiftKey === true;
  6568. if (!shiftKey) {
  6569. return Optional.none();
  6570. }
  6571. if (isNavigation(keycode) && isEditableSelection(start, finish)) {
  6572. return sync(container, isRoot, start, soffset, finish, foffset, annotations.selectRange);
  6573. } else {
  6574. return Optional.none();
  6575. }
  6576. }, Optional.none);
  6577. };
  6578. return {
  6579. keydown,
  6580. keyup
  6581. };
  6582. };
  6583. const external = (win, container, isRoot, annotations) => {
  6584. const bridge = WindowBridge(win);
  6585. return (start, finish) => {
  6586. annotations.clearBeforeUpdate(container);
  6587. identify(start, finish, isRoot).each(cellSel => {
  6588. const boxes = cellSel.boxes.getOr([]);
  6589. annotations.selectRange(container, boxes, cellSel.start, cellSel.finish);
  6590. bridge.selectContents(finish);
  6591. bridge.collapseSelection();
  6592. });
  6593. };
  6594. };
  6595. const read = (element, attr) => {
  6596. const value = get$b(element, attr);
  6597. return value === undefined || value === '' ? [] : value.split(' ');
  6598. };
  6599. const add$2 = (element, attr, id) => {
  6600. const old = read(element, attr);
  6601. const nu = old.concat([id]);
  6602. set$2(element, attr, nu.join(' '));
  6603. return true;
  6604. };
  6605. const remove$4 = (element, attr, id) => {
  6606. const nu = filter$2(read(element, attr), v => v !== id);
  6607. if (nu.length > 0) {
  6608. set$2(element, attr, nu.join(' '));
  6609. } else {
  6610. remove$7(element, attr);
  6611. }
  6612. return false;
  6613. };
  6614. const supports = element => element.dom.classList !== undefined;
  6615. const get$1 = element => read(element, 'class');
  6616. const add$1 = (element, clazz) => add$2(element, 'class', clazz);
  6617. const remove$3 = (element, clazz) => remove$4(element, 'class', clazz);
  6618. const add = (element, clazz) => {
  6619. if (supports(element)) {
  6620. element.dom.classList.add(clazz);
  6621. } else {
  6622. add$1(element, clazz);
  6623. }
  6624. };
  6625. const cleanClass = element => {
  6626. const classList = supports(element) ? element.dom.classList : get$1(element);
  6627. if (classList.length === 0) {
  6628. remove$7(element, 'class');
  6629. }
  6630. };
  6631. const remove$2 = (element, clazz) => {
  6632. if (supports(element)) {
  6633. const classList = element.dom.classList;
  6634. classList.remove(clazz);
  6635. } else {
  6636. remove$3(element, clazz);
  6637. }
  6638. cleanClass(element);
  6639. };
  6640. const has = (element, clazz) => supports(element) && element.dom.classList.contains(clazz);
  6641. const remove$1 = (element, classes) => {
  6642. each$2(classes, x => {
  6643. remove$2(element, x);
  6644. });
  6645. };
  6646. const addClass = clazz => element => {
  6647. add(element, clazz);
  6648. };
  6649. const removeClasses = classes => element => {
  6650. remove$1(element, classes);
  6651. };
  6652. const byClass = ephemera => {
  6653. const addSelectionClass = addClass(ephemera.selected);
  6654. const removeSelectionClasses = removeClasses([
  6655. ephemera.selected,
  6656. ephemera.lastSelected,
  6657. ephemera.firstSelected
  6658. ]);
  6659. const clear = container => {
  6660. const sels = descendants(container, ephemera.selectedSelector);
  6661. each$2(sels, removeSelectionClasses);
  6662. };
  6663. const selectRange = (container, cells, start, finish) => {
  6664. clear(container);
  6665. each$2(cells, addSelectionClass);
  6666. add(start, ephemera.firstSelected);
  6667. add(finish, ephemera.lastSelected);
  6668. };
  6669. return {
  6670. clearBeforeUpdate: clear,
  6671. clear,
  6672. selectRange,
  6673. selectedSelector: ephemera.selectedSelector,
  6674. firstSelectedSelector: ephemera.firstSelectedSelector,
  6675. lastSelectedSelector: ephemera.lastSelectedSelector
  6676. };
  6677. };
  6678. const byAttr = (ephemera, onSelection, onClear) => {
  6679. const removeSelectionAttributes = element => {
  6680. remove$7(element, ephemera.selected);
  6681. remove$7(element, ephemera.firstSelected);
  6682. remove$7(element, ephemera.lastSelected);
  6683. };
  6684. const addSelectionAttribute = element => {
  6685. set$2(element, ephemera.selected, '1');
  6686. };
  6687. const clear = container => {
  6688. clearBeforeUpdate(container);
  6689. onClear();
  6690. };
  6691. const clearBeforeUpdate = container => {
  6692. const sels = descendants(container, `${ ephemera.selectedSelector },${ ephemera.firstSelectedSelector },${ ephemera.lastSelectedSelector }`);
  6693. each$2(sels, removeSelectionAttributes);
  6694. };
  6695. const selectRange = (container, cells, start, finish) => {
  6696. clear(container);
  6697. each$2(cells, addSelectionAttribute);
  6698. set$2(start, ephemera.firstSelected, '1');
  6699. set$2(finish, ephemera.lastSelected, '1');
  6700. onSelection(cells, start, finish);
  6701. };
  6702. return {
  6703. clearBeforeUpdate,
  6704. clear,
  6705. selectRange,
  6706. selectedSelector: ephemera.selectedSelector,
  6707. firstSelectedSelector: ephemera.firstSelectedSelector,
  6708. lastSelectedSelector: ephemera.lastSelectedSelector
  6709. };
  6710. };
  6711. const SelectionAnnotation = {
  6712. byClass,
  6713. byAttr
  6714. };
  6715. const fold = (subject, onNone, onMultiple, onSingle) => {
  6716. switch (subject.tag) {
  6717. case 'none':
  6718. return onNone();
  6719. case 'single':
  6720. return onSingle(subject.element);
  6721. case 'multiple':
  6722. return onMultiple(subject.elements);
  6723. }
  6724. };
  6725. const none = () => ({ tag: 'none' });
  6726. const multiple = elements => ({
  6727. tag: 'multiple',
  6728. elements
  6729. });
  6730. const single = element => ({
  6731. tag: 'single',
  6732. element
  6733. });
  6734. const Selections = (lazyRoot, getStart, selectedSelector) => {
  6735. const get = () => retrieve(lazyRoot(), selectedSelector).fold(() => getStart().fold(none, single), multiple);
  6736. return { get };
  6737. };
  6738. const getUpOrLeftCells = (grid, selectedCells) => {
  6739. const upGrid = grid.slice(0, selectedCells[selectedCells.length - 1].row + 1);
  6740. const upDetails = toDetailList(upGrid);
  6741. return bind$2(upDetails, detail => {
  6742. const slicedCells = detail.cells.slice(0, selectedCells[selectedCells.length - 1].column + 1);
  6743. return map$1(slicedCells, cell => cell.element);
  6744. });
  6745. };
  6746. const getDownOrRightCells = (grid, selectedCells) => {
  6747. const downGrid = grid.slice(selectedCells[0].row + selectedCells[0].rowspan - 1, grid.length);
  6748. const downDetails = toDetailList(downGrid);
  6749. return bind$2(downDetails, detail => {
  6750. const slicedCells = detail.cells.slice(selectedCells[0].column + selectedCells[0].colspan - 1, detail.cells.length);
  6751. return map$1(slicedCells, cell => cell.element);
  6752. });
  6753. };
  6754. const getOtherCells = (table, target, generators) => {
  6755. const warehouse = Warehouse.fromTable(table);
  6756. const details = onCells(warehouse, target);
  6757. return details.map(selectedCells => {
  6758. const grid = toGrid(warehouse, generators, false);
  6759. const {rows} = extractGridDetails(grid);
  6760. const upOrLeftCells = getUpOrLeftCells(rows, selectedCells);
  6761. const downOrRightCells = getDownOrRightCells(rows, selectedCells);
  6762. return {
  6763. upOrLeftCells,
  6764. downOrRightCells
  6765. };
  6766. });
  6767. };
  6768. const mkEvent = (target, x, y, stop, prevent, kill, raw) => ({
  6769. target,
  6770. x,
  6771. y,
  6772. stop,
  6773. prevent,
  6774. kill,
  6775. raw
  6776. });
  6777. const fromRawEvent$1 = rawEvent => {
  6778. const target = SugarElement.fromDom(getOriginalEventTarget(rawEvent).getOr(rawEvent.target));
  6779. const stop = () => rawEvent.stopPropagation();
  6780. const prevent = () => rawEvent.preventDefault();
  6781. const kill = compose(prevent, stop);
  6782. return mkEvent(target, rawEvent.clientX, rawEvent.clientY, stop, prevent, kill, rawEvent);
  6783. };
  6784. const handle = (filter, handler) => rawEvent => {
  6785. if (filter(rawEvent)) {
  6786. handler(fromRawEvent$1(rawEvent));
  6787. }
  6788. };
  6789. const binder = (element, event, filter, handler, useCapture) => {
  6790. const wrapped = handle(filter, handler);
  6791. element.dom.addEventListener(event, wrapped, useCapture);
  6792. return { unbind: curry(unbind, element, event, wrapped, useCapture) };
  6793. };
  6794. const bind$1 = (element, event, filter, handler) => binder(element, event, filter, handler, false);
  6795. const unbind = (element, event, handler, useCapture) => {
  6796. element.dom.removeEventListener(event, handler, useCapture);
  6797. };
  6798. const filter = always;
  6799. const bind = (element, event, handler) => bind$1(element, event, filter, handler);
  6800. const fromRawEvent = fromRawEvent$1;
  6801. const hasInternalTarget = e => !has(SugarElement.fromDom(e.target), 'ephox-snooker-resizer-bar');
  6802. const TableCellSelectionHandler = (editor, resizeHandler) => {
  6803. const cellSelection = Selections(() => SugarElement.fromDom(editor.getBody()), () => getSelectionCell(getSelectionStart(editor), getIsRoot(editor)), ephemera.selectedSelector);
  6804. const onSelection = (cells, start, finish) => {
  6805. const tableOpt = table(start);
  6806. tableOpt.each(table => {
  6807. const cloneFormats = getTableCloneElements(editor);
  6808. const generators = cellOperations(noop, SugarElement.fromDom(editor.getDoc()), cloneFormats);
  6809. const selectedCells = getCellsFromSelection(editor);
  6810. const otherCells = getOtherCells(table, { selection: selectedCells }, generators);
  6811. fireTableSelectionChange(editor, cells, start, finish, otherCells);
  6812. });
  6813. };
  6814. const onClear = () => fireTableSelectionClear(editor);
  6815. const annotations = SelectionAnnotation.byAttr(ephemera, onSelection, onClear);
  6816. editor.on('init', _e => {
  6817. const win = editor.getWin();
  6818. const body = getBody(editor);
  6819. const isRoot = getIsRoot(editor);
  6820. const syncSelection = () => {
  6821. const sel = editor.selection;
  6822. const start = SugarElement.fromDom(sel.getStart());
  6823. const end = SugarElement.fromDom(sel.getEnd());
  6824. const shared = sharedOne(table, [
  6825. start,
  6826. end
  6827. ]);
  6828. shared.fold(() => annotations.clear(body), noop);
  6829. };
  6830. const mouseHandlers = mouse(win, body, isRoot, annotations);
  6831. const keyHandlers = keyboard(win, body, isRoot, annotations);
  6832. const external$1 = external(win, body, isRoot, annotations);
  6833. const hasShiftKey = event => event.raw.shiftKey === true;
  6834. editor.on('TableSelectorChange', e => external$1(e.start, e.finish));
  6835. const handleResponse = (event, response) => {
  6836. if (!hasShiftKey(event)) {
  6837. return;
  6838. }
  6839. if (response.kill) {
  6840. event.kill();
  6841. }
  6842. response.selection.each(ns => {
  6843. const relative = SimSelection.relative(ns.start, ns.finish);
  6844. const rng = asLtrRange(win, relative);
  6845. editor.selection.setRng(rng);
  6846. });
  6847. };
  6848. const keyup = event => {
  6849. const wrappedEvent = fromRawEvent(event);
  6850. if (wrappedEvent.raw.shiftKey && isNavigation(wrappedEvent.raw.which)) {
  6851. const rng = editor.selection.getRng();
  6852. const start = SugarElement.fromDom(rng.startContainer);
  6853. const end = SugarElement.fromDom(rng.endContainer);
  6854. keyHandlers.keyup(wrappedEvent, start, rng.startOffset, end, rng.endOffset).each(response => {
  6855. handleResponse(wrappedEvent, response);
  6856. });
  6857. }
  6858. };
  6859. const keydown = event => {
  6860. const wrappedEvent = fromRawEvent(event);
  6861. resizeHandler.hide();
  6862. const rng = editor.selection.getRng();
  6863. const start = SugarElement.fromDom(rng.startContainer);
  6864. const end = SugarElement.fromDom(rng.endContainer);
  6865. const direction = onDirection(ltr, rtl)(SugarElement.fromDom(editor.selection.getStart()));
  6866. keyHandlers.keydown(wrappedEvent, start, rng.startOffset, end, rng.endOffset, direction).each(response => {
  6867. handleResponse(wrappedEvent, response);
  6868. });
  6869. resizeHandler.show();
  6870. };
  6871. const isLeftMouse = raw => raw.button === 0;
  6872. const isLeftButtonPressed = raw => {
  6873. if (raw.buttons === undefined) {
  6874. return true;
  6875. }
  6876. return (raw.buttons & 1) !== 0;
  6877. };
  6878. const dragStart = _e => {
  6879. mouseHandlers.clearstate();
  6880. };
  6881. const mouseDown = e => {
  6882. if (isLeftMouse(e) && hasInternalTarget(e)) {
  6883. mouseHandlers.mousedown(fromRawEvent(e));
  6884. }
  6885. };
  6886. const mouseOver = e => {
  6887. if (isLeftButtonPressed(e) && hasInternalTarget(e)) {
  6888. mouseHandlers.mouseover(fromRawEvent(e));
  6889. }
  6890. };
  6891. const mouseUp = e => {
  6892. if (isLeftMouse(e) && hasInternalTarget(e)) {
  6893. mouseHandlers.mouseup(fromRawEvent(e));
  6894. }
  6895. };
  6896. const getDoubleTap = () => {
  6897. const lastTarget = Cell(SugarElement.fromDom(body));
  6898. const lastTimeStamp = Cell(0);
  6899. const touchEnd = t => {
  6900. const target = SugarElement.fromDom(t.target);
  6901. if (isTag('td')(target) || isTag('th')(target)) {
  6902. const lT = lastTarget.get();
  6903. const lTS = lastTimeStamp.get();
  6904. if (eq$1(lT, target) && t.timeStamp - lTS < 300) {
  6905. t.preventDefault();
  6906. external$1(target, target);
  6907. }
  6908. }
  6909. lastTarget.set(target);
  6910. lastTimeStamp.set(t.timeStamp);
  6911. };
  6912. return { touchEnd };
  6913. };
  6914. const doubleTap = getDoubleTap();
  6915. editor.on('dragstart', dragStart);
  6916. editor.on('mousedown', mouseDown);
  6917. editor.on('mouseover', mouseOver);
  6918. editor.on('mouseup', mouseUp);
  6919. editor.on('touchend', doubleTap.touchEnd);
  6920. editor.on('keyup', keyup);
  6921. editor.on('keydown', keydown);
  6922. editor.on('NodeChange', syncSelection);
  6923. });
  6924. editor.on('PreInit', () => {
  6925. editor.serializer.addTempAttr(ephemera.firstSelected);
  6926. editor.serializer.addTempAttr(ephemera.lastSelected);
  6927. });
  6928. const clearSelectedCells = container => annotations.clear(SugarElement.fromDom(container));
  6929. const getSelectedCells = () => fold(cellSelection.get(), constant([]), cells => {
  6930. return map$1(cells, cell => cell.dom);
  6931. }, cell => [cell.dom]);
  6932. return {
  6933. getSelectedCells,
  6934. clearSelectedCells
  6935. };
  6936. };
  6937. const Event = fields => {
  6938. let handlers = [];
  6939. const bind = handler => {
  6940. if (handler === undefined) {
  6941. throw new Error('Event bind error: undefined handler');
  6942. }
  6943. handlers.push(handler);
  6944. };
  6945. const unbind = handler => {
  6946. handlers = filter$2(handlers, h => {
  6947. return h !== handler;
  6948. });
  6949. };
  6950. const trigger = (...args) => {
  6951. const event = {};
  6952. each$2(fields, (name, i) => {
  6953. event[name] = args[i];
  6954. });
  6955. each$2(handlers, handler => {
  6956. handler(event);
  6957. });
  6958. };
  6959. return {
  6960. bind,
  6961. unbind,
  6962. trigger
  6963. };
  6964. };
  6965. const create$1 = typeDefs => {
  6966. const registry = map(typeDefs, event => {
  6967. return {
  6968. bind: event.bind,
  6969. unbind: event.unbind
  6970. };
  6971. });
  6972. const trigger = map(typeDefs, event => {
  6973. return event.trigger;
  6974. });
  6975. return {
  6976. registry,
  6977. trigger
  6978. };
  6979. };
  6980. const last = (fn, rate) => {
  6981. let timer = null;
  6982. const cancel = () => {
  6983. if (!isNull(timer)) {
  6984. clearTimeout(timer);
  6985. timer = null;
  6986. }
  6987. };
  6988. const throttle = (...args) => {
  6989. cancel();
  6990. timer = setTimeout(() => {
  6991. timer = null;
  6992. fn.apply(null, args);
  6993. }, rate);
  6994. };
  6995. return {
  6996. cancel,
  6997. throttle
  6998. };
  6999. };
  7000. const sort = arr => {
  7001. return arr.slice(0).sort();
  7002. };
  7003. const reqMessage = (required, keys) => {
  7004. throw new Error('All required keys (' + sort(required).join(', ') + ') were not specified. Specified keys were: ' + sort(keys).join(', ') + '.');
  7005. };
  7006. const unsuppMessage = unsupported => {
  7007. throw new Error('Unsupported keys for object: ' + sort(unsupported).join(', '));
  7008. };
  7009. const validateStrArr = (label, array) => {
  7010. if (!isArray(array)) {
  7011. throw new Error('The ' + label + ' fields must be an array. Was: ' + array + '.');
  7012. }
  7013. each$2(array, a => {
  7014. if (!isString(a)) {
  7015. throw new Error('The value ' + a + ' in the ' + label + ' fields was not a string.');
  7016. }
  7017. });
  7018. };
  7019. const invalidTypeMessage = (incorrect, type) => {
  7020. throw new Error('All values need to be of type: ' + type + '. Keys (' + sort(incorrect).join(', ') + ') were not.');
  7021. };
  7022. const checkDupes = everything => {
  7023. const sorted = sort(everything);
  7024. const dupe = find$1(sorted, (s, i) => {
  7025. return i < sorted.length - 1 && s === sorted[i + 1];
  7026. });
  7027. dupe.each(d => {
  7028. throw new Error('The field: ' + d + ' occurs more than once in the combined fields: [' + sorted.join(', ') + '].');
  7029. });
  7030. };
  7031. const base = (handleUnsupported, required) => {
  7032. return baseWith(handleUnsupported, required, {
  7033. validate: isFunction,
  7034. label: 'function'
  7035. });
  7036. };
  7037. const baseWith = (handleUnsupported, required, pred) => {
  7038. if (required.length === 0) {
  7039. throw new Error('You must specify at least one required field.');
  7040. }
  7041. validateStrArr('required', required);
  7042. checkDupes(required);
  7043. return obj => {
  7044. const keys$1 = keys(obj);
  7045. const allReqd = forall(required, req => {
  7046. return contains$2(keys$1, req);
  7047. });
  7048. if (!allReqd) {
  7049. reqMessage(required, keys$1);
  7050. }
  7051. handleUnsupported(required, keys$1);
  7052. const invalidKeys = filter$2(required, key => {
  7053. return !pred.validate(obj[key], key);
  7054. });
  7055. if (invalidKeys.length > 0) {
  7056. invalidTypeMessage(invalidKeys, pred.label);
  7057. }
  7058. return obj;
  7059. };
  7060. };
  7061. const handleExact = (required, keys) => {
  7062. const unsupported = filter$2(keys, key => {
  7063. return !contains$2(required, key);
  7064. });
  7065. if (unsupported.length > 0) {
  7066. unsuppMessage(unsupported);
  7067. }
  7068. };
  7069. const exactly = required => base(handleExact, required);
  7070. const DragMode = exactly([
  7071. 'compare',
  7072. 'extract',
  7073. 'mutate',
  7074. 'sink'
  7075. ]);
  7076. const DragSink = exactly([
  7077. 'element',
  7078. 'start',
  7079. 'stop',
  7080. 'destroy'
  7081. ]);
  7082. const DragApi = exactly([
  7083. 'forceDrop',
  7084. 'drop',
  7085. 'move',
  7086. 'delayDrop'
  7087. ]);
  7088. const InDrag = () => {
  7089. let previous = Optional.none();
  7090. const reset = () => {
  7091. previous = Optional.none();
  7092. };
  7093. const update = (mode, nu) => {
  7094. const result = previous.map(old => {
  7095. return mode.compare(old, nu);
  7096. });
  7097. previous = Optional.some(nu);
  7098. return result;
  7099. };
  7100. const onEvent = (event, mode) => {
  7101. const dataOption = mode.extract(event);
  7102. dataOption.each(data => {
  7103. const offset = update(mode, data);
  7104. offset.each(d => {
  7105. events.trigger.move(d);
  7106. });
  7107. });
  7108. };
  7109. const events = create$1({ move: Event(['info']) });
  7110. return {
  7111. onEvent,
  7112. reset,
  7113. events: events.registry
  7114. };
  7115. };
  7116. const NoDrag = () => {
  7117. const events = create$1({ move: Event(['info']) });
  7118. return {
  7119. onEvent: noop,
  7120. reset: noop,
  7121. events: events.registry
  7122. };
  7123. };
  7124. const Movement = () => {
  7125. const noDragState = NoDrag();
  7126. const inDragState = InDrag();
  7127. let dragState = noDragState;
  7128. const on = () => {
  7129. dragState.reset();
  7130. dragState = inDragState;
  7131. };
  7132. const off = () => {
  7133. dragState.reset();
  7134. dragState = noDragState;
  7135. };
  7136. const onEvent = (event, mode) => {
  7137. dragState.onEvent(event, mode);
  7138. };
  7139. const isOn = () => {
  7140. return dragState === inDragState;
  7141. };
  7142. return {
  7143. on,
  7144. off,
  7145. isOn,
  7146. onEvent,
  7147. events: inDragState.events
  7148. };
  7149. };
  7150. const setup = (mutation, mode, settings) => {
  7151. let active = false;
  7152. const events = create$1({
  7153. start: Event([]),
  7154. stop: Event([])
  7155. });
  7156. const movement = Movement();
  7157. const drop = () => {
  7158. sink.stop();
  7159. if (movement.isOn()) {
  7160. movement.off();
  7161. events.trigger.stop();
  7162. }
  7163. };
  7164. const throttledDrop = last(drop, 200);
  7165. const go = parent => {
  7166. sink.start(parent);
  7167. movement.on();
  7168. events.trigger.start();
  7169. };
  7170. const mousemove = event => {
  7171. throttledDrop.cancel();
  7172. movement.onEvent(event, mode);
  7173. };
  7174. movement.events.move.bind(event => {
  7175. mode.mutate(mutation, event.info);
  7176. });
  7177. const on = () => {
  7178. active = true;
  7179. };
  7180. const off = () => {
  7181. active = false;
  7182. };
  7183. const isActive = () => active;
  7184. const runIfActive = f => {
  7185. return (...args) => {
  7186. if (active) {
  7187. f.apply(null, args);
  7188. }
  7189. };
  7190. };
  7191. const sink = mode.sink(DragApi({
  7192. forceDrop: drop,
  7193. drop: runIfActive(drop),
  7194. move: runIfActive(mousemove),
  7195. delayDrop: runIfActive(throttledDrop.throttle)
  7196. }), settings);
  7197. const destroy = () => {
  7198. sink.destroy();
  7199. };
  7200. return {
  7201. element: sink.element,
  7202. go,
  7203. on,
  7204. off,
  7205. isActive,
  7206. destroy,
  7207. events: events.registry
  7208. };
  7209. };
  7210. const css = namespace => {
  7211. const dashNamespace = namespace.replace(/\./g, '-');
  7212. const resolve = str => {
  7213. return dashNamespace + '-' + str;
  7214. };
  7215. return { resolve };
  7216. };
  7217. const styles$1 = css('ephox-dragster');
  7218. const resolve$1 = styles$1.resolve;
  7219. const Blocker = options => {
  7220. const settings = {
  7221. layerClass: resolve$1('blocker'),
  7222. ...options
  7223. };
  7224. const div = SugarElement.fromTag('div');
  7225. set$2(div, 'role', 'presentation');
  7226. setAll(div, {
  7227. position: 'fixed',
  7228. left: '0px',
  7229. top: '0px',
  7230. width: '100%',
  7231. height: '100%'
  7232. });
  7233. add(div, resolve$1('blocker'));
  7234. add(div, settings.layerClass);
  7235. const element = constant(div);
  7236. const destroy = () => {
  7237. remove$6(div);
  7238. };
  7239. return {
  7240. element,
  7241. destroy
  7242. };
  7243. };
  7244. const compare = (old, nu) => {
  7245. return SugarPosition(nu.left - old.left, nu.top - old.top);
  7246. };
  7247. const extract = event => {
  7248. return Optional.some(SugarPosition(event.x, event.y));
  7249. };
  7250. const mutate = (mutation, info) => {
  7251. mutation.mutate(info.left, info.top);
  7252. };
  7253. const sink = (dragApi, settings) => {
  7254. const blocker = Blocker(settings);
  7255. const mdown = bind(blocker.element(), 'mousedown', dragApi.forceDrop);
  7256. const mup = bind(blocker.element(), 'mouseup', dragApi.drop);
  7257. const mmove = bind(blocker.element(), 'mousemove', dragApi.move);
  7258. const mout = bind(blocker.element(), 'mouseout', dragApi.delayDrop);
  7259. const destroy = () => {
  7260. blocker.destroy();
  7261. mup.unbind();
  7262. mmove.unbind();
  7263. mout.unbind();
  7264. mdown.unbind();
  7265. };
  7266. const start = parent => {
  7267. append$1(parent, blocker.element());
  7268. };
  7269. const stop = () => {
  7270. remove$6(blocker.element());
  7271. };
  7272. return DragSink({
  7273. element: blocker.element,
  7274. start,
  7275. stop,
  7276. destroy
  7277. });
  7278. };
  7279. var MouseDrag = DragMode({
  7280. compare,
  7281. extract,
  7282. sink,
  7283. mutate
  7284. });
  7285. const transform = (mutation, settings = {}) => {
  7286. var _a;
  7287. const mode = (_a = settings.mode) !== null && _a !== void 0 ? _a : MouseDrag;
  7288. return setup(mutation, mode, settings);
  7289. };
  7290. const styles = css('ephox-snooker');
  7291. const resolve = styles.resolve;
  7292. const Mutation = () => {
  7293. const events = create$1({
  7294. drag: Event([
  7295. 'xDelta',
  7296. 'yDelta'
  7297. ])
  7298. });
  7299. const mutate = (x, y) => {
  7300. events.trigger.drag(x, y);
  7301. };
  7302. return {
  7303. mutate,
  7304. events: events.registry
  7305. };
  7306. };
  7307. const BarMutation = () => {
  7308. const events = create$1({
  7309. drag: Event([
  7310. 'xDelta',
  7311. 'yDelta',
  7312. 'target'
  7313. ])
  7314. });
  7315. let target = Optional.none();
  7316. const delegate = Mutation();
  7317. delegate.events.drag.bind(event => {
  7318. target.each(t => {
  7319. events.trigger.drag(event.xDelta, event.yDelta, t);
  7320. });
  7321. });
  7322. const assign = t => {
  7323. target = Optional.some(t);
  7324. };
  7325. const get = () => {
  7326. return target;
  7327. };
  7328. return {
  7329. assign,
  7330. get,
  7331. mutate: delegate.mutate,
  7332. events: events.registry
  7333. };
  7334. };
  7335. const col = (column, x, y, w, h) => {
  7336. const bar = SugarElement.fromTag('div');
  7337. setAll(bar, {
  7338. position: 'absolute',
  7339. left: x - w / 2 + 'px',
  7340. top: y + 'px',
  7341. height: h + 'px',
  7342. width: w + 'px'
  7343. });
  7344. setAll$1(bar, {
  7345. 'data-column': column,
  7346. 'role': 'presentation'
  7347. });
  7348. return bar;
  7349. };
  7350. const row = (r, x, y, w, h) => {
  7351. const bar = SugarElement.fromTag('div');
  7352. setAll(bar, {
  7353. position: 'absolute',
  7354. left: x + 'px',
  7355. top: y - h / 2 + 'px',
  7356. height: h + 'px',
  7357. width: w + 'px'
  7358. });
  7359. setAll$1(bar, {
  7360. 'data-row': r,
  7361. 'role': 'presentation'
  7362. });
  7363. return bar;
  7364. };
  7365. const resizeBar = resolve('resizer-bar');
  7366. const resizeRowBar = resolve('resizer-rows');
  7367. const resizeColBar = resolve('resizer-cols');
  7368. const BAR_THICKNESS = 7;
  7369. const resizableRows = (warehouse, isResizable) => bind$2(warehouse.all, (row, i) => isResizable(row.element) ? [i] : []);
  7370. const resizableColumns = (warehouse, isResizable) => {
  7371. const resizableCols = [];
  7372. range$1(warehouse.grid.columns, index => {
  7373. const colElmOpt = Warehouse.getColumnAt(warehouse, index).map(col => col.element);
  7374. if (colElmOpt.forall(isResizable)) {
  7375. resizableCols.push(index);
  7376. }
  7377. });
  7378. return filter$2(resizableCols, colIndex => {
  7379. const columnCells = Warehouse.filterItems(warehouse, cell => cell.column === colIndex);
  7380. return forall(columnCells, cell => isResizable(cell.element));
  7381. });
  7382. };
  7383. const destroy = wire => {
  7384. const previous = descendants(wire.parent(), '.' + resizeBar);
  7385. each$2(previous, remove$6);
  7386. };
  7387. const drawBar = (wire, positions, create) => {
  7388. const origin = wire.origin();
  7389. each$2(positions, cpOption => {
  7390. cpOption.each(cp => {
  7391. const bar = create(origin, cp);
  7392. add(bar, resizeBar);
  7393. append$1(wire.parent(), bar);
  7394. });
  7395. });
  7396. };
  7397. const refreshCol = (wire, colPositions, position, tableHeight) => {
  7398. drawBar(wire, colPositions, (origin, cp) => {
  7399. const colBar = col(cp.col, cp.x - origin.left, position.top - origin.top, BAR_THICKNESS, tableHeight);
  7400. add(colBar, resizeColBar);
  7401. return colBar;
  7402. });
  7403. };
  7404. const refreshRow = (wire, rowPositions, position, tableWidth) => {
  7405. drawBar(wire, rowPositions, (origin, cp) => {
  7406. const rowBar = row(cp.row, position.left - origin.left, cp.y - origin.top, tableWidth, BAR_THICKNESS);
  7407. add(rowBar, resizeRowBar);
  7408. return rowBar;
  7409. });
  7410. };
  7411. const refreshGrid = (warhouse, wire, table, rows, cols) => {
  7412. const position = absolute(table);
  7413. const isResizable = wire.isResizable;
  7414. const rowPositions = rows.length > 0 ? height.positions(rows, table) : [];
  7415. const resizableRowBars = rowPositions.length > 0 ? resizableRows(warhouse, isResizable) : [];
  7416. const resizableRowPositions = filter$2(rowPositions, (_pos, i) => exists(resizableRowBars, barIndex => i === barIndex));
  7417. refreshRow(wire, resizableRowPositions, position, getOuter$2(table));
  7418. const colPositions = cols.length > 0 ? width.positions(cols, table) : [];
  7419. const resizableColBars = colPositions.length > 0 ? resizableColumns(warhouse, isResizable) : [];
  7420. const resizableColPositions = filter$2(colPositions, (_pos, i) => exists(resizableColBars, barIndex => i === barIndex));
  7421. refreshCol(wire, resizableColPositions, position, getOuter$1(table));
  7422. };
  7423. const refresh = (wire, table) => {
  7424. destroy(wire);
  7425. if (wire.isResizable(table)) {
  7426. const warehouse = Warehouse.fromTable(table);
  7427. const rows$1 = rows(warehouse);
  7428. const cols = columns(warehouse);
  7429. refreshGrid(warehouse, wire, table, rows$1, cols);
  7430. }
  7431. };
  7432. const each = (wire, f) => {
  7433. const bars = descendants(wire.parent(), '.' + resizeBar);
  7434. each$2(bars, f);
  7435. };
  7436. const hide = wire => {
  7437. each(wire, bar => {
  7438. set$1(bar, 'display', 'none');
  7439. });
  7440. };
  7441. const show = wire => {
  7442. each(wire, bar => {
  7443. set$1(bar, 'display', 'block');
  7444. });
  7445. };
  7446. const isRowBar = element => {
  7447. return has(element, resizeRowBar);
  7448. };
  7449. const isColBar = element => {
  7450. return has(element, resizeColBar);
  7451. };
  7452. const resizeBarDragging = resolve('resizer-bar-dragging');
  7453. const BarManager = wire => {
  7454. const mutation = BarMutation();
  7455. const resizing = transform(mutation, {});
  7456. let hoverTable = Optional.none();
  7457. const getResizer = (element, type) => {
  7458. return Optional.from(get$b(element, type));
  7459. };
  7460. mutation.events.drag.bind(event => {
  7461. getResizer(event.target, 'data-row').each(_dataRow => {
  7462. const currentRow = getCssValue(event.target, 'top');
  7463. set$1(event.target, 'top', currentRow + event.yDelta + 'px');
  7464. });
  7465. getResizer(event.target, 'data-column').each(_dataCol => {
  7466. const currentCol = getCssValue(event.target, 'left');
  7467. set$1(event.target, 'left', currentCol + event.xDelta + 'px');
  7468. });
  7469. });
  7470. const getDelta = (target, dir) => {
  7471. const newX = getCssValue(target, dir);
  7472. const oldX = getAttrValue(target, 'data-initial-' + dir, 0);
  7473. return newX - oldX;
  7474. };
  7475. resizing.events.stop.bind(() => {
  7476. mutation.get().each(target => {
  7477. hoverTable.each(table => {
  7478. getResizer(target, 'data-row').each(row => {
  7479. const delta = getDelta(target, 'top');
  7480. remove$7(target, 'data-initial-top');
  7481. events.trigger.adjustHeight(table, delta, parseInt(row, 10));
  7482. });
  7483. getResizer(target, 'data-column').each(column => {
  7484. const delta = getDelta(target, 'left');
  7485. remove$7(target, 'data-initial-left');
  7486. events.trigger.adjustWidth(table, delta, parseInt(column, 10));
  7487. });
  7488. refresh(wire, table);
  7489. });
  7490. });
  7491. });
  7492. const handler = (target, dir) => {
  7493. events.trigger.startAdjust();
  7494. mutation.assign(target);
  7495. set$2(target, 'data-initial-' + dir, getCssValue(target, dir));
  7496. add(target, resizeBarDragging);
  7497. set$1(target, 'opacity', '0.2');
  7498. resizing.go(wire.parent());
  7499. };
  7500. const mousedown = bind(wire.parent(), 'mousedown', event => {
  7501. if (isRowBar(event.target)) {
  7502. handler(event.target, 'top');
  7503. }
  7504. if (isColBar(event.target)) {
  7505. handler(event.target, 'left');
  7506. }
  7507. });
  7508. const isRoot = e => {
  7509. return eq$1(e, wire.view());
  7510. };
  7511. const findClosestEditableTable = target => closest$1(target, 'table', isRoot).filter(isEditable$1);
  7512. const mouseover = bind(wire.view(), 'mouseover', event => {
  7513. findClosestEditableTable(event.target).fold(() => {
  7514. if (inBody(event.target)) {
  7515. destroy(wire);
  7516. }
  7517. }, table => {
  7518. if (resizing.isActive()) {
  7519. hoverTable = Optional.some(table);
  7520. refresh(wire, table);
  7521. }
  7522. });
  7523. });
  7524. const destroy$1 = () => {
  7525. mousedown.unbind();
  7526. mouseover.unbind();
  7527. resizing.destroy();
  7528. destroy(wire);
  7529. };
  7530. const refresh$1 = tbl => {
  7531. refresh(wire, tbl);
  7532. };
  7533. const events = create$1({
  7534. adjustHeight: Event([
  7535. 'table',
  7536. 'delta',
  7537. 'row'
  7538. ]),
  7539. adjustWidth: Event([
  7540. 'table',
  7541. 'delta',
  7542. 'column'
  7543. ]),
  7544. startAdjust: Event([])
  7545. });
  7546. return {
  7547. destroy: destroy$1,
  7548. refresh: refresh$1,
  7549. on: resizing.on,
  7550. off: resizing.off,
  7551. hideBars: curry(hide, wire),
  7552. showBars: curry(show, wire),
  7553. events: events.registry
  7554. };
  7555. };
  7556. const create = (wire, resizing, lazySizing) => {
  7557. const hdirection = height;
  7558. const vdirection = width;
  7559. const manager = BarManager(wire);
  7560. const events = create$1({
  7561. beforeResize: Event([
  7562. 'table',
  7563. 'type'
  7564. ]),
  7565. afterResize: Event([
  7566. 'table',
  7567. 'type'
  7568. ]),
  7569. startDrag: Event([])
  7570. });
  7571. manager.events.adjustHeight.bind(event => {
  7572. const table = event.table;
  7573. events.trigger.beforeResize(table, 'row');
  7574. const delta = hdirection.delta(event.delta, table);
  7575. adjustHeight(table, delta, event.row, hdirection);
  7576. events.trigger.afterResize(table, 'row');
  7577. });
  7578. manager.events.startAdjust.bind(_event => {
  7579. events.trigger.startDrag();
  7580. });
  7581. manager.events.adjustWidth.bind(event => {
  7582. const table = event.table;
  7583. events.trigger.beforeResize(table, 'col');
  7584. const delta = vdirection.delta(event.delta, table);
  7585. const tableSize = lazySizing(table);
  7586. adjustWidth(table, delta, event.column, resizing, tableSize);
  7587. events.trigger.afterResize(table, 'col');
  7588. });
  7589. return {
  7590. on: manager.on,
  7591. off: manager.off,
  7592. refreshBars: manager.refresh,
  7593. hideBars: manager.hideBars,
  7594. showBars: manager.showBars,
  7595. destroy: manager.destroy,
  7596. events: events.registry
  7597. };
  7598. };
  7599. const TableResize = { create };
  7600. const only = (element, isResizable) => {
  7601. const parent = isDocument(element) ? documentElement(element) : element;
  7602. return {
  7603. parent: constant(parent),
  7604. view: constant(element),
  7605. origin: constant(SugarPosition(0, 0)),
  7606. isResizable
  7607. };
  7608. };
  7609. const detached = (editable, chrome, isResizable) => {
  7610. const origin = () => absolute(chrome);
  7611. return {
  7612. parent: constant(chrome),
  7613. view: constant(editable),
  7614. origin,
  7615. isResizable
  7616. };
  7617. };
  7618. const body = (editable, chrome, isResizable) => {
  7619. return {
  7620. parent: constant(chrome),
  7621. view: constant(editable),
  7622. origin: constant(SugarPosition(0, 0)),
  7623. isResizable
  7624. };
  7625. };
  7626. const ResizeWire = {
  7627. only,
  7628. detached,
  7629. body
  7630. };
  7631. const createContainer = () => {
  7632. const container = SugarElement.fromTag('div');
  7633. setAll(container, {
  7634. position: 'static',
  7635. height: '0',
  7636. width: '0',
  7637. padding: '0',
  7638. margin: '0',
  7639. border: '0'
  7640. });
  7641. append$1(body$1(), container);
  7642. return container;
  7643. };
  7644. const get = (editor, isResizable) => {
  7645. return editor.inline ? ResizeWire.body(SugarElement.fromDom(editor.getBody()), createContainer(), isResizable) : ResizeWire.only(SugarElement.fromDom(editor.getDoc()), isResizable);
  7646. };
  7647. const remove = (editor, wire) => {
  7648. if (editor.inline) {
  7649. remove$6(wire.parent());
  7650. }
  7651. };
  7652. const isTable = node => isNonNullable(node) && node.nodeName === 'TABLE';
  7653. const barResizerPrefix = 'bar-';
  7654. const isResizable = elm => get$b(elm, 'data-mce-resize') !== 'false';
  7655. const syncPixels = table => {
  7656. const warehouse = Warehouse.fromTable(table);
  7657. if (!Warehouse.hasColumns(warehouse)) {
  7658. each$2(cells$1(table), cell => {
  7659. const computedWidth = get$a(cell, 'width');
  7660. set$1(cell, 'width', computedWidth);
  7661. remove$7(cell, 'width');
  7662. });
  7663. }
  7664. };
  7665. const TableResizeHandler = editor => {
  7666. const selectionRng = value();
  7667. const tableResize = value();
  7668. const resizeWire = value();
  7669. let startW;
  7670. let startRawW;
  7671. const lazySizing = table => get$5(editor, table);
  7672. const lazyResizingBehaviour = () => isPreserveTableColumnResizing(editor) ? preserveTable() : resizeTable();
  7673. const getNumColumns = table => getGridSize(table).columns;
  7674. const afterCornerResize = (table, origin, width) => {
  7675. const isRightEdgeResize = endsWith(origin, 'e');
  7676. if (startRawW === '') {
  7677. convertToPercentSize(table);
  7678. }
  7679. if (width !== startW && startRawW !== '') {
  7680. set$1(table, 'width', startRawW);
  7681. const resizing = lazyResizingBehaviour();
  7682. const tableSize = lazySizing(table);
  7683. const col = isPreserveTableColumnResizing(editor) || isRightEdgeResize ? getNumColumns(table) - 1 : 0;
  7684. adjustWidth(table, width - startW, col, resizing, tableSize);
  7685. } else if (isPercentage$1(startRawW)) {
  7686. const percentW = parseFloat(startRawW.replace('%', ''));
  7687. const targetPercentW = width * percentW / startW;
  7688. set$1(table, 'width', targetPercentW + '%');
  7689. }
  7690. if (isPixel(startRawW)) {
  7691. syncPixels(table);
  7692. }
  7693. };
  7694. const destroy = () => {
  7695. tableResize.on(sz => {
  7696. sz.destroy();
  7697. });
  7698. resizeWire.on(w => {
  7699. remove(editor, w);
  7700. });
  7701. };
  7702. editor.on('init', () => {
  7703. const rawWire = get(editor, isResizable);
  7704. resizeWire.set(rawWire);
  7705. if (hasTableObjectResizing(editor) && hasTableResizeBars(editor)) {
  7706. const resizing = lazyResizingBehaviour();
  7707. const sz = TableResize.create(rawWire, resizing, lazySizing);
  7708. sz.on();
  7709. sz.events.startDrag.bind(_event => {
  7710. selectionRng.set(editor.selection.getRng());
  7711. });
  7712. sz.events.beforeResize.bind(event => {
  7713. const rawTable = event.table.dom;
  7714. fireObjectResizeStart(editor, rawTable, getPixelWidth(rawTable), getPixelHeight(rawTable), barResizerPrefix + event.type);
  7715. });
  7716. sz.events.afterResize.bind(event => {
  7717. const table = event.table;
  7718. const rawTable = table.dom;
  7719. removeDataStyle(table);
  7720. selectionRng.on(rng => {
  7721. editor.selection.setRng(rng);
  7722. editor.focus();
  7723. });
  7724. fireObjectResized(editor, rawTable, getPixelWidth(rawTable), getPixelHeight(rawTable), barResizerPrefix + event.type);
  7725. editor.undoManager.add();
  7726. });
  7727. tableResize.set(sz);
  7728. }
  7729. });
  7730. editor.on('ObjectResizeStart', e => {
  7731. const targetElm = e.target;
  7732. if (isTable(targetElm)) {
  7733. const table = SugarElement.fromDom(targetElm);
  7734. each$2(editor.dom.select('.mce-clonedresizable'), clone => {
  7735. editor.dom.addClass(clone, 'mce-' + getTableColumnResizingBehaviour(editor) + '-columns');
  7736. });
  7737. if (!isPixelSizing(table) && isTablePixelsForced(editor)) {
  7738. convertToPixelSize(table);
  7739. } else if (!isPercentSizing(table) && isTablePercentagesForced(editor)) {
  7740. convertToPercentSize(table);
  7741. }
  7742. if (isNoneSizing(table) && startsWith(e.origin, barResizerPrefix)) {
  7743. convertToPercentSize(table);
  7744. }
  7745. startW = e.width;
  7746. startRawW = isTableResponsiveForced(editor) ? '' : getRawWidth(editor, targetElm).getOr('');
  7747. }
  7748. });
  7749. editor.on('ObjectResized', e => {
  7750. const targetElm = e.target;
  7751. if (isTable(targetElm)) {
  7752. const table = SugarElement.fromDom(targetElm);
  7753. const origin = e.origin;
  7754. if (startsWith(origin, 'corner-')) {
  7755. afterCornerResize(table, origin, e.width);
  7756. }
  7757. removeDataStyle(table);
  7758. fireTableModified(editor, table.dom, styleModified);
  7759. }
  7760. });
  7761. editor.on('SwitchMode', () => {
  7762. tableResize.on(resize => {
  7763. if (editor.mode.isReadOnly()) {
  7764. resize.hideBars();
  7765. } else {
  7766. resize.showBars();
  7767. }
  7768. });
  7769. });
  7770. editor.on('dragstart dragend', e => {
  7771. tableResize.on(resize => {
  7772. if (e.type === 'dragstart') {
  7773. resize.hideBars();
  7774. resize.off();
  7775. } else {
  7776. resize.on();
  7777. resize.showBars();
  7778. }
  7779. });
  7780. });
  7781. editor.on('remove', () => {
  7782. destroy();
  7783. });
  7784. const refresh = table => {
  7785. tableResize.on(resize => resize.refreshBars(SugarElement.fromDom(table)));
  7786. };
  7787. const hide = () => {
  7788. tableResize.on(resize => resize.hideBars());
  7789. };
  7790. const show = () => {
  7791. tableResize.on(resize => resize.showBars());
  7792. };
  7793. return {
  7794. refresh,
  7795. hide,
  7796. show
  7797. };
  7798. };
  7799. const setupTable = editor => {
  7800. register(editor);
  7801. const resizeHandler = TableResizeHandler(editor);
  7802. const cellSelectionHandler = TableCellSelectionHandler(editor, resizeHandler);
  7803. const actions = TableActions(editor, resizeHandler, cellSelectionHandler);
  7804. registerCommands(editor, actions);
  7805. registerQueryCommands(editor, actions);
  7806. registerEvents(editor, actions);
  7807. return {
  7808. getSelectedCells: cellSelectionHandler.getSelectedCells,
  7809. clearSelectedCells: cellSelectionHandler.clearSelectedCells
  7810. };
  7811. };
  7812. const DomModel = editor => {
  7813. const table = setupTable(editor);
  7814. return { table };
  7815. };
  7816. var Model = () => {
  7817. global$1.add('dom', DomModel);
  7818. };
  7819. Model();
  7820. })();