1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353235423552356235723582359236023612362236323642365236623672368236923702371237223732374237523762377237823792380238123822383238423852386238723882389239023912392239323942395239623972398239924002401240224032404240524062407240824092410241124122413241424152416241724182419242024212422242324242425242624272428242924302431243224332434243524362437243824392440244124422443244424452446244724482449245024512452245324542455245624572458245924602461246224632464246524662467246824692470247124722473247424752476247724782479248024812482248324842485248624872488248924902491249224932494249524962497249824992500250125022503250425052506250725082509251025112512251325142515251625172518251925202521252225232524252525262527252825292530253125322533253425352536253725382539254025412542254325442545254625472548254925502551255225532554255525562557255825592560256125622563256425652566256725682569257025712572257325742575257625772578257925802581258225832584258525862587258825892590259125922593259425952596259725982599260026012602260326042605260626072608260926102611261226132614261526162617261826192620262126222623262426252626262726282629263026312632263326342635263626372638263926402641264226432644264526462647264826492650265126522653265426552656265726582659266026612662266326642665266626672668266926702671267226732674267526762677267826792680268126822683268426852686268726882689269026912692269326942695269626972698269927002701270227032704270527062707270827092710271127122713271427152716271727182719272027212722272327242725272627272728272927302731273227332734273527362737273827392740274127422743274427452746274727482749275027512752275327542755275627572758275927602761276227632764276527662767276827692770277127722773277427752776277727782779278027812782278327842785278627872788278927902791279227932794279527962797279827992800280128022803280428052806280728082809281028112812281328142815281628172818281928202821282228232824282528262827282828292830283128322833283428352836283728382839284028412842284328442845284628472848284928502851285228532854285528562857285828592860286128622863286428652866286728682869287028712872287328742875287628772878287928802881288228832884288528862887288828892890289128922893289428952896289728982899290029012902290329042905290629072908290929102911291229132914291529162917291829192920292129222923292429252926292729282929293029312932293329342935293629372938293929402941294229432944294529462947294829492950295129522953295429552956295729582959296029612962296329642965296629672968296929702971297229732974297529762977297829792980298129822983298429852986298729882989299029912992299329942995299629972998299930003001300230033004300530063007300830093010301130123013301430153016301730183019302030213022302330243025302630273028302930303031303230333034303530363037303830393040304130423043304430453046304730483049305030513052305330543055305630573058305930603061306230633064306530663067306830693070307130723073307430753076307730783079308030813082308330843085308630873088308930903091309230933094309530963097309830993100310131023103310431053106310731083109311031113112311331143115311631173118311931203121312231233124312531263127312831293130313131323133313431353136313731383139314031413142314331443145314631473148314931503151315231533154315531563157315831593160316131623163316431653166316731683169317031713172317331743175317631773178317931803181318231833184318531863187318831893190319131923193319431953196319731983199320032013202320332043205320632073208320932103211321232133214321532163217321832193220322132223223322432253226322732283229323032313232323332343235323632373238323932403241324232433244324532463247324832493250325132523253325432553256325732583259326032613262326332643265326632673268326932703271327232733274327532763277327832793280328132823283328432853286328732883289329032913292329332943295329632973298329933003301330233033304330533063307330833093310331133123313331433153316331733183319332033213322332333243325332633273328332933303331333233333334333533363337333833393340334133423343334433453346334733483349335033513352335333543355335633573358335933603361336233633364336533663367336833693370337133723373337433753376337733783379338033813382338333843385338633873388338933903391339233933394339533963397339833993400340134023403340434053406340734083409341034113412341334143415341634173418341934203421342234233424342534263427342834293430343134323433343434353436343734383439344034413442344334443445344634473448344934503451345234533454345534563457345834593460346134623463346434653466346734683469347034713472347334743475347634773478347934803481348234833484348534863487348834893490349134923493349434953496349734983499350035013502350335043505350635073508350935103511351235133514351535163517351835193520352135223523352435253526352735283529353035313532353335343535353635373538353935403541354235433544354535463547354835493550355135523553355435553556355735583559356035613562356335643565356635673568356935703571357235733574357535763577357835793580358135823583358435853586358735883589359035913592359335943595359635973598359936003601360236033604360536063607360836093610361136123613361436153616361736183619362036213622362336243625362636273628362936303631363236333634363536363637363836393640364136423643364436453646364736483649365036513652365336543655365636573658365936603661366236633664366536663667366836693670367136723673367436753676367736783679368036813682368336843685368636873688368936903691369236933694369536963697369836993700370137023703370437053706370737083709371037113712371337143715371637173718371937203721372237233724372537263727372837293730373137323733373437353736373737383739374037413742374337443745374637473748374937503751375237533754375537563757375837593760376137623763376437653766376737683769377037713772377337743775377637773778377937803781378237833784378537863787378837893790379137923793379437953796379737983799380038013802380338043805380638073808380938103811381238133814381538163817381838193820382138223823382438253826382738283829383038313832383338343835383638373838383938403841384238433844384538463847384838493850385138523853385438553856385738583859386038613862386338643865386638673868386938703871387238733874387538763877387838793880388138823883388438853886388738883889389038913892389338943895389638973898389939003901390239033904390539063907390839093910391139123913391439153916391739183919392039213922392339243925392639273928392939303931393239333934393539363937393839393940394139423943394439453946394739483949395039513952395339543955395639573958395939603961396239633964396539663967396839693970397139723973397439753976397739783979398039813982398339843985398639873988398939903991399239933994399539963997399839994000400140024003400440054006400740084009401040114012401340144015401640174018401940204021402240234024402540264027402840294030403140324033403440354036403740384039404040414042404340444045404640474048404940504051405240534054405540564057405840594060406140624063406440654066406740684069407040714072407340744075407640774078407940804081408240834084408540864087408840894090409140924093409440954096409740984099410041014102410341044105410641074108410941104111411241134114411541164117411841194120412141224123412441254126412741284129413041314132413341344135413641374138413941404141414241434144414541464147414841494150415141524153415441554156415741584159416041614162416341644165416641674168416941704171417241734174417541764177417841794180418141824183418441854186418741884189419041914192419341944195419641974198419942004201420242034204420542064207420842094210421142124213421442154216421742184219422042214222422342244225422642274228422942304231423242334234423542364237423842394240424142424243424442454246424742484249425042514252425342544255425642574258425942604261426242634264426542664267426842694270427142724273427442754276427742784279428042814282428342844285428642874288428942904291429242934294429542964297429842994300430143024303430443054306430743084309431043114312431343144315431643174318431943204321432243234324432543264327432843294330433143324333433443354336433743384339434043414342434343444345434643474348434943504351435243534354435543564357435843594360436143624363436443654366436743684369437043714372437343744375437643774378437943804381438243834384438543864387438843894390439143924393439443954396439743984399440044014402440344044405440644074408440944104411441244134414441544164417441844194420442144224423442444254426442744284429443044314432443344344435443644374438443944404441444244434444444544464447444844494450445144524453445444554456445744584459446044614462446344644465446644674468446944704471447244734474447544764477447844794480448144824483448444854486448744884489449044914492449344944495449644974498449945004501450245034504450545064507450845094510451145124513451445154516451745184519452045214522452345244525452645274528452945304531453245334534453545364537453845394540454145424543454445454546454745484549455045514552455345544555455645574558455945604561456245634564456545664567456845694570457145724573457445754576457745784579458045814582458345844585458645874588458945904591459245934594459545964597459845994600460146024603460446054606460746084609461046114612461346144615461646174618461946204621462246234624462546264627462846294630463146324633463446354636463746384639464046414642464346444645464646474648464946504651465246534654465546564657465846594660466146624663466446654666466746684669467046714672467346744675467646774678467946804681468246834684468546864687468846894690469146924693469446954696469746984699470047014702470347044705470647074708470947104711471247134714471547164717471847194720472147224723472447254726472747284729473047314732473347344735473647374738473947404741474247434744474547464747474847494750475147524753475447554756475747584759476047614762476347644765476647674768476947704771477247734774477547764777477847794780478147824783478447854786478747884789479047914792479347944795479647974798479948004801480248034804480548064807480848094810481148124813481448154816481748184819482048214822482348244825482648274828482948304831483248334834483548364837483848394840484148424843484448454846484748484849485048514852485348544855485648574858485948604861486248634864486548664867486848694870487148724873487448754876487748784879488048814882488348844885488648874888488948904891489248934894489548964897489848994900490149024903490449054906490749084909491049114912491349144915491649174918491949204921492249234924492549264927492849294930493149324933493449354936493749384939494049414942494349444945494649474948494949504951495249534954495549564957495849594960496149624963496449654966496749684969497049714972497349744975497649774978497949804981498249834984498549864987498849894990499149924993499449954996499749984999500050015002500350045005500650075008500950105011501250135014501550165017501850195020502150225023502450255026502750285029503050315032503350345035503650375038503950405041504250435044504550465047504850495050505150525053505450555056505750585059506050615062506350645065506650675068506950705071507250735074507550765077507850795080508150825083508450855086508750885089509050915092509350945095509650975098509951005101510251035104510551065107510851095110511151125113511451155116511751185119512051215122512351245125512651275128512951305131513251335134513551365137513851395140514151425143514451455146514751485149515051515152515351545155515651575158515951605161516251635164516551665167516851695170517151725173517451755176517751785179518051815182518351845185518651875188518951905191519251935194519551965197519851995200520152025203520452055206520752085209521052115212521352145215521652175218521952205221522252235224522552265227522852295230523152325233523452355236523752385239524052415242524352445245524652475248524952505251525252535254525552565257525852595260526152625263526452655266526752685269527052715272527352745275527652775278527952805281528252835284528552865287528852895290529152925293529452955296529752985299530053015302530353045305530653075308530953105311531253135314531553165317531853195320532153225323532453255326532753285329533053315332533353345335533653375338533953405341534253435344534553465347534853495350535153525353535453555356535753585359536053615362536353645365536653675368536953705371537253735374537553765377537853795380538153825383538453855386538753885389539053915392539353945395539653975398539954005401540254035404540554065407540854095410541154125413541454155416541754185419542054215422542354245425542654275428542954305431543254335434543554365437543854395440544154425443544454455446544754485449545054515452545354545455545654575458545954605461546254635464546554665467546854695470547154725473547454755476547754785479548054815482548354845485548654875488548954905491549254935494549554965497549854995500550155025503550455055506550755085509551055115512551355145515551655175518551955205521552255235524552555265527552855295530553155325533553455355536553755385539554055415542554355445545554655475548554955505551555255535554555555565557555855595560556155625563556455655566556755685569557055715572557355745575557655775578557955805581558255835584558555865587558855895590559155925593559455955596559755985599560056015602560356045605560656075608560956105611561256135614561556165617561856195620562156225623562456255626562756285629563056315632563356345635563656375638563956405641564256435644564556465647564856495650565156525653565456555656565756585659566056615662566356645665566656675668566956705671567256735674567556765677567856795680568156825683568456855686568756885689569056915692569356945695569656975698569957005701570257035704570557065707570857095710571157125713571457155716571757185719572057215722572357245725572657275728572957305731573257335734573557365737573857395740574157425743574457455746574757485749575057515752575357545755575657575758575957605761576257635764576557665767576857695770577157725773577457755776577757785779578057815782578357845785578657875788578957905791579257935794579557965797579857995800580158025803580458055806580758085809581058115812581358145815581658175818581958205821582258235824582558265827582858295830583158325833583458355836583758385839584058415842584358445845584658475848584958505851585258535854585558565857585858595860586158625863586458655866586758685869587058715872587358745875587658775878587958805881588258835884588558865887588858895890589158925893589458955896589758985899590059015902590359045905590659075908590959105911591259135914591559165917591859195920592159225923592459255926592759285929593059315932593359345935593659375938593959405941594259435944594559465947594859495950595159525953595459555956595759585959596059615962596359645965596659675968596959705971597259735974597559765977597859795980598159825983598459855986598759885989599059915992599359945995599659975998599960006001600260036004600560066007600860096010601160126013601460156016601760186019602060216022602360246025602660276028602960306031603260336034603560366037603860396040604160426043604460456046604760486049605060516052605360546055605660576058605960606061606260636064606560666067606860696070607160726073607460756076607760786079608060816082608360846085608660876088608960906091609260936094609560966097609860996100610161026103610461056106610761086109611061116112611361146115611661176118611961206121612261236124612561266127612861296130613161326133613461356136613761386139614061416142614361446145614661476148614961506151615261536154615561566157615861596160616161626163616461656166616761686169617061716172617361746175617661776178617961806181618261836184618561866187618861896190619161926193619461956196619761986199620062016202620362046205620662076208620962106211621262136214621562166217621862196220622162226223622462256226622762286229623062316232623362346235623662376238623962406241624262436244624562466247624862496250625162526253625462556256625762586259626062616262626362646265626662676268626962706271627262736274627562766277627862796280628162826283628462856286628762886289629062916292629362946295629662976298629963006301630263036304630563066307630863096310631163126313631463156316631763186319632063216322632363246325632663276328632963306331633263336334633563366337633863396340634163426343634463456346634763486349635063516352635363546355635663576358635963606361636263636364636563666367636863696370637163726373637463756376637763786379638063816382638363846385638663876388638963906391639263936394639563966397639863996400640164026403640464056406640764086409641064116412641364146415641664176418641964206421642264236424642564266427642864296430643164326433643464356436643764386439644064416442644364446445644664476448644964506451645264536454645564566457645864596460646164626463646464656466646764686469647064716472647364746475647664776478647964806481648264836484648564866487648864896490649164926493649464956496649764986499650065016502650365046505650665076508650965106511651265136514651565166517651865196520652165226523652465256526652765286529653065316532653365346535653665376538653965406541654265436544654565466547654865496550655165526553655465556556655765586559656065616562656365646565656665676568656965706571657265736574657565766577657865796580658165826583658465856586658765886589659065916592659365946595659665976598659966006601660266036604660566066607660866096610661166126613661466156616661766186619662066216622662366246625662666276628662966306631663266336634663566366637663866396640664166426643664466456646664766486649665066516652665366546655665666576658665966606661666266636664666566666667666866696670667166726673667466756676667766786679668066816682668366846685668666876688668966906691669266936694669566966697669866996700670167026703670467056706670767086709671067116712671367146715671667176718671967206721672267236724672567266727672867296730673167326733673467356736673767386739674067416742674367446745674667476748674967506751675267536754675567566757675867596760676167626763676467656766676767686769677067716772677367746775677667776778677967806781678267836784678567866787678867896790679167926793679467956796679767986799680068016802680368046805680668076808680968106811681268136814681568166817681868196820682168226823682468256826682768286829683068316832683368346835683668376838683968406841684268436844684568466847684868496850685168526853685468556856685768586859686068616862686368646865686668676868686968706871687268736874687568766877687868796880688168826883688468856886688768886889689068916892689368946895689668976898689969006901690269036904690569066907690869096910691169126913691469156916691769186919692069216922692369246925692669276928692969306931693269336934693569366937693869396940694169426943694469456946694769486949695069516952695369546955695669576958695969606961696269636964696569666967696869696970697169726973697469756976697769786979698069816982698369846985698669876988698969906991699269936994699569966997699869997000700170027003700470057006700770087009701070117012701370147015701670177018701970207021702270237024702570267027702870297030703170327033703470357036703770387039704070417042704370447045704670477048704970507051705270537054705570567057705870597060706170627063706470657066706770687069707070717072707370747075707670777078707970807081708270837084708570867087708870897090709170927093709470957096709770987099710071017102710371047105710671077108710971107111711271137114711571167117711871197120712171227123712471257126712771287129713071317132713371347135713671377138713971407141714271437144714571467147714871497150715171527153715471557156715771587159716071617162716371647165716671677168716971707171717271737174717571767177717871797180718171827183718471857186718771887189719071917192719371947195719671977198719972007201720272037204720572067207720872097210721172127213721472157216721772187219722072217222722372247225722672277228722972307231723272337234723572367237723872397240724172427243724472457246724772487249725072517252725372547255725672577258725972607261726272637264726572667267726872697270727172727273727472757276727772787279728072817282728372847285728672877288728972907291729272937294729572967297729872997300730173027303730473057306730773087309731073117312731373147315731673177318731973207321732273237324732573267327732873297330733173327333733473357336733773387339734073417342734373447345734673477348734973507351735273537354735573567357735873597360736173627363736473657366736773687369737073717372737373747375737673777378737973807381738273837384738573867387738873897390739173927393739473957396739773987399740074017402740374047405740674077408740974107411741274137414741574167417741874197420742174227423742474257426742774287429743074317432743374347435743674377438743974407441744274437444744574467447744874497450745174527453745474557456745774587459746074617462746374647465746674677468746974707471747274737474747574767477747874797480748174827483748474857486748774887489749074917492749374947495749674977498749975007501750275037504750575067507750875097510751175127513751475157516751775187519752075217522752375247525752675277528752975307531753275337534753575367537753875397540754175427543754475457546754775487549755075517552755375547555755675577558755975607561756275637564756575667567756875697570757175727573757475757576757775787579758075817582758375847585758675877588758975907591759275937594759575967597759875997600760176027603760476057606760776087609761076117612761376147615761676177618761976207621762276237624762576267627762876297630763176327633763476357636763776387639764076417642764376447645764676477648764976507651765276537654765576567657765876597660766176627663766476657666766776687669767076717672767376747675767676777678767976807681768276837684768576867687768876897690769176927693769476957696769776987699770077017702770377047705770677077708770977107711771277137714771577167717771877197720772177227723772477257726772777287729773077317732773377347735773677377738773977407741774277437744774577467747774877497750775177527753775477557756775777587759776077617762776377647765776677677768776977707771777277737774777577767777777877797780778177827783778477857786778777887789779077917792779377947795779677977798779978007801780278037804780578067807780878097810781178127813781478157816781778187819782078217822782378247825782678277828782978307831783278337834783578367837783878397840784178427843784478457846784778487849785078517852785378547855785678577858785978607861786278637864786578667867786878697870787178727873787478757876787778787879788078817882788378847885788678877888788978907891789278937894789578967897789878997900790179027903790479057906790779087909791079117912791379147915791679177918791979207921792279237924792579267927792879297930793179327933793479357936793779387939794079417942794379447945794679477948794979507951795279537954795579567957795879597960796179627963796479657966796779687969797079717972797379747975797679777978797979807981798279837984798579867987798879897990799179927993799479957996799779987999800080018002800380048005800680078008800980108011801280138014801580168017801880198020802180228023802480258026802780288029803080318032803380348035803680378038803980408041804280438044804580468047804880498050805180528053805480558056805780588059806080618062806380648065806680678068806980708071807280738074807580768077807880798080808180828083808480858086808780888089809080918092809380948095809680978098809981008101810281038104810581068107810881098110811181128113811481158116811781188119812081218122812381248125812681278128812981308131813281338134813581368137813881398140814181428143814481458146814781488149815081518152815381548155815681578158815981608161816281638164816581668167816881698170817181728173817481758176817781788179818081818182818381848185818681878188818981908191819281938194819581968197819881998200820182028203820482058206820782088209821082118212821382148215821682178218821982208221822282238224822582268227822882298230823182328233823482358236823782388239824082418242824382448245824682478248824982508251825282538254825582568257825882598260826182628263826482658266826782688269827082718272827382748275827682778278827982808281828282838284828582868287828882898290829182928293829482958296829782988299830083018302830383048305830683078308830983108311831283138314831583168317831883198320832183228323832483258326832783288329833083318332833383348335833683378338833983408341834283438344834583468347834883498350835183528353835483558356835783588359836083618362836383648365836683678368836983708371837283738374837583768377837883798380838183828383838483858386838783888389839083918392839383948395839683978398839984008401840284038404840584068407840884098410841184128413841484158416841784188419842084218422842384248425842684278428842984308431843284338434843584368437843884398440844184428443844484458446844784488449845084518452845384548455845684578458845984608461846284638464846584668467846884698470847184728473847484758476847784788479848084818482848384848485848684878488848984908491849284938494849584968497849884998500850185028503850485058506850785088509851085118512851385148515851685178518851985208521852285238524852585268527852885298530853185328533853485358536853785388539854085418542854385448545854685478548854985508551855285538554855585568557855885598560856185628563856485658566856785688569857085718572857385748575857685778578857985808581858285838584858585868587858885898590859185928593859485958596859785988599860086018602860386048605860686078608860986108611861286138614861586168617861886198620862186228623862486258626862786288629863086318632863386348635863686378638863986408641864286438644864586468647864886498650865186528653865486558656865786588659866086618662866386648665866686678668866986708671867286738674867586768677867886798680868186828683868486858686868786888689869086918692869386948695869686978698869987008701870287038704870587068707870887098710871187128713871487158716871787188719872087218722872387248725872687278728872987308731873287338734873587368737873887398740874187428743874487458746874787488749875087518752875387548755875687578758875987608761876287638764876587668767876887698770877187728773877487758776877787788779878087818782878387848785878687878788878987908791879287938794879587968797879887998800880188028803880488058806880788088809881088118812881388148815881688178818881988208821882288238824882588268827882888298830883188328833883488358836883788388839884088418842884388448845884688478848884988508851885288538854885588568857885888598860886188628863886488658866886788688869887088718872887388748875887688778878887988808881888288838884888588868887888888898890889188928893889488958896889788988899890089018902890389048905890689078908890989108911891289138914891589168917891889198920892189228923892489258926892789288929893089318932893389348935893689378938893989408941894289438944894589468947894889498950895189528953895489558956895789588959896089618962896389648965896689678968896989708971897289738974897589768977897889798980898189828983898489858986898789888989899089918992899389948995899689978998899990009001900290039004900590069007900890099010901190129013901490159016901790189019902090219022902390249025902690279028902990309031903290339034903590369037903890399040904190429043904490459046904790489049905090519052905390549055905690579058905990609061906290639064906590669067906890699070907190729073907490759076907790789079908090819082908390849085908690879088908990909091909290939094909590969097909890999100910191029103910491059106910791089109911091119112911391149115911691179118911991209121912291239124912591269127912891299130913191329133913491359136913791389139914091419142914391449145914691479148914991509151915291539154915591569157915891599160916191629163916491659166916791689169917091719172917391749175917691779178917991809181918291839184918591869187918891899190919191929193919491959196919791989199920092019202920392049205920692079208920992109211921292139214921592169217921892199220922192229223922492259226922792289229923092319232923392349235923692379238923992409241924292439244924592469247924892499250925192529253925492559256925792589259926092619262926392649265926692679268926992709271927292739274927592769277927892799280928192829283928492859286928792889289929092919292929392949295929692979298929993009301930293039304930593069307930893099310931193129313931493159316931793189319932093219322932393249325932693279328932993309331933293339334933593369337933893399340934193429343934493459346934793489349935093519352935393549355935693579358935993609361936293639364936593669367936893699370937193729373937493759376937793789379938093819382938393849385938693879388938993909391939293939394939593969397939893999400940194029403940494059406940794089409941094119412941394149415941694179418941994209421942294239424942594269427942894299430943194329433943494359436943794389439944094419442944394449445944694479448944994509451945294539454945594569457945894599460946194629463946494659466946794689469947094719472947394749475947694779478947994809481948294839484948594869487948894899490949194929493949494959496949794989499950095019502950395049505950695079508950995109511951295139514951595169517951895199520952195229523952495259526952795289529953095319532953395349535953695379538953995409541954295439544954595469547954895499550955195529553955495559556955795589559956095619562956395649565956695679568956995709571957295739574957595769577957895799580958195829583958495859586958795889589959095919592959395949595959695979598959996009601960296039604960596069607960896099610961196129613961496159616961796189619962096219622962396249625962696279628962996309631963296339634963596369637963896399640964196429643964496459646964796489649965096519652965396549655965696579658965996609661966296639664966596669667966896699670967196729673967496759676967796789679968096819682968396849685968696879688968996909691969296939694969596969697969896999700970197029703970497059706970797089709971097119712971397149715971697179718971997209721972297239724972597269727972897299730973197329733973497359736973797389739974097419742974397449745974697479748974997509751975297539754975597569757975897599760976197629763976497659766976797689769977097719772977397749775977697779778977997809781978297839784978597869787978897899790979197929793979497959796979797989799980098019802980398049805980698079808980998109811981298139814981598169817981898199820982198229823982498259826982798289829983098319832983398349835983698379838983998409841984298439844984598469847984898499850985198529853985498559856985798589859986098619862986398649865986698679868986998709871987298739874987598769877987898799880988198829883988498859886988798889889989098919892989398949895989698979898989999009901990299039904990599069907990899099910991199129913991499159916991799189919992099219922992399249925992699279928992999309931993299339934993599369937993899399940994199429943994499459946994799489949995099519952995399549955995699579958995999609961996299639964996599669967996899699970997199729973997499759976997799789979998099819982998399849985998699879988998999909991999299939994999599969997999899991000010001100021000310004100051000610007100081000910010100111001210013100141001510016100171001810019100201002110022100231002410025100261002710028100291003010031100321003310034100351003610037100381003910040100411004210043100441004510046100471004810049100501005110052100531005410055100561005710058100591006010061100621006310064100651006610067100681006910070100711007210073100741007510076100771007810079100801008110082100831008410085100861008710088100891009010091100921009310094100951009610097100981009910100101011010210103101041010510106101071010810109101101011110112101131011410115101161011710118101191012010121101221012310124101251012610127101281012910130101311013210133101341013510136101371013810139101401014110142101431014410145101461014710148101491015010151101521015310154101551015610157101581015910160101611016210163101641016510166101671016810169101701017110172101731017410175101761017710178101791018010181101821018310184101851018610187101881018910190101911019210193101941019510196101971019810199102001020110202102031020410205102061020710208102091021010211102121021310214102151021610217102181021910220102211022210223102241022510226102271022810229102301023110232102331023410235102361023710238102391024010241102421024310244102451024610247102481024910250102511025210253102541025510256102571025810259102601026110262102631026410265102661026710268102691027010271102721027310274102751027610277102781027910280102811028210283102841028510286102871028810289102901029110292102931029410295102961029710298102991030010301103021030310304103051030610307103081030910310103111031210313103141031510316103171031810319103201032110322103231032410325103261032710328103291033010331103321033310334103351033610337103381033910340103411034210343103441034510346103471034810349103501035110352103531035410355103561035710358103591036010361103621036310364103651036610367103681036910370103711037210373103741037510376103771037810379103801038110382103831038410385103861038710388103891039010391103921039310394103951039610397103981039910400104011040210403104041040510406104071040810409104101041110412104131041410415104161041710418104191042010421104221042310424104251042610427104281042910430104311043210433104341043510436104371043810439104401044110442104431044410445104461044710448104491045010451104521045310454104551045610457104581045910460104611046210463104641046510466104671046810469104701047110472104731047410475104761047710478104791048010481104821048310484104851048610487104881048910490104911049210493104941049510496104971049810499105001050110502105031050410505105061050710508105091051010511105121051310514105151051610517105181051910520105211052210523105241052510526105271052810529105301053110532105331053410535105361053710538105391054010541105421054310544105451054610547105481054910550105511055210553105541055510556105571055810559105601056110562105631056410565105661056710568105691057010571105721057310574105751057610577105781057910580105811058210583105841058510586105871058810589105901059110592105931059410595105961059710598105991060010601106021060310604106051060610607106081060910610106111061210613106141061510616106171061810619106201062110622106231062410625106261062710628106291063010631106321063310634106351063610637106381063910640106411064210643106441064510646106471064810649106501065110652106531065410655106561065710658106591066010661106621066310664106651066610667106681066910670106711067210673106741067510676106771067810679106801068110682106831068410685106861068710688106891069010691106921069310694106951069610697106981069910700107011070210703107041070510706107071070810709107101071110712107131071410715107161071710718107191072010721107221072310724107251072610727107281072910730107311073210733107341073510736107371073810739107401074110742107431074410745107461074710748107491075010751107521075310754107551075610757107581075910760107611076210763107641076510766107671076810769107701077110772107731077410775107761077710778107791078010781107821078310784107851078610787107881078910790107911079210793107941079510796107971079810799108001080110802108031080410805108061080710808108091081010811108121081310814108151081610817108181081910820108211082210823108241082510826108271082810829108301083110832108331083410835108361083710838108391084010841108421084310844108451084610847108481084910850108511085210853108541085510856108571085810859108601086110862108631086410865108661086710868108691087010871108721087310874108751087610877108781087910880108811088210883108841088510886108871088810889108901089110892108931089410895108961089710898108991090010901109021090310904109051090610907109081090910910109111091210913109141091510916109171091810919109201092110922109231092410925109261092710928109291093010931109321093310934109351093610937109381093910940109411094210943109441094510946109471094810949109501095110952109531095410955109561095710958109591096010961109621096310964109651096610967109681096910970109711097210973109741097510976109771097810979109801098110982109831098410985109861098710988109891099010991109921099310994109951099610997109981099911000110011100211003110041100511006110071100811009110101101111012110131101411015110161101711018110191102011021110221102311024110251102611027110281102911030110311103211033110341103511036110371103811039110401104111042110431104411045110461104711048110491105011051110521105311054110551105611057110581105911060110611106211063110641106511066110671106811069110701107111072110731107411075110761107711078110791108011081110821108311084110851108611087110881108911090110911109211093110941109511096110971109811099111001110111102111031110411105111061110711108111091111011111111121111311114111151111611117111181111911120111211112211123111241112511126111271112811129111301113111132111331113411135111361113711138111391114011141111421114311144111451114611147111481114911150111511115211153111541115511156111571115811159111601116111162111631116411165111661116711168111691117011171111721117311174111751117611177111781117911180111811118211183111841118511186111871118811189111901119111192111931119411195111961119711198111991120011201112021120311204112051120611207112081120911210112111121211213112141121511216112171121811219112201122111222112231122411225112261122711228112291123011231112321123311234112351123611237112381123911240112411124211243112441124511246112471124811249112501125111252112531125411255112561125711258112591126011261112621126311264112651126611267112681126911270112711127211273112741127511276112771127811279112801128111282112831128411285112861128711288112891129011291112921129311294112951129611297112981129911300113011130211303113041130511306113071130811309113101131111312113131131411315113161131711318113191132011321113221132311324113251132611327113281132911330113311133211333113341133511336113371133811339113401134111342113431134411345113461134711348113491135011351113521135311354113551135611357113581135911360113611136211363113641136511366113671136811369113701137111372113731137411375113761137711378113791138011381113821138311384113851138611387113881138911390113911139211393113941139511396113971139811399114001140111402114031140411405114061140711408114091141011411114121141311414114151141611417114181141911420114211142211423114241142511426114271142811429114301143111432114331143411435114361143711438114391144011441114421144311444114451144611447114481144911450114511145211453114541145511456114571145811459114601146111462114631146411465114661146711468114691147011471114721147311474114751147611477114781147911480114811148211483114841148511486114871148811489114901149111492114931149411495114961149711498114991150011501115021150311504115051150611507115081150911510115111151211513115141151511516115171151811519115201152111522115231152411525115261152711528115291153011531115321153311534115351153611537115381153911540115411154211543115441154511546115471154811549115501155111552115531155411555115561155711558115591156011561115621156311564115651156611567115681156911570115711157211573115741157511576115771157811579115801158111582115831158411585115861158711588115891159011591115921159311594115951159611597115981159911600116011160211603116041160511606116071160811609116101161111612116131161411615116161161711618116191162011621116221162311624116251162611627116281162911630116311163211633116341163511636116371163811639116401164111642116431164411645116461164711648116491165011651116521165311654116551165611657116581165911660116611166211663116641166511666116671166811669116701167111672116731167411675116761167711678116791168011681116821168311684116851168611687116881168911690116911169211693116941169511696116971169811699117001170111702117031170411705117061170711708117091171011711117121171311714117151171611717117181171911720117211172211723117241172511726117271172811729117301173111732117331173411735117361173711738117391174011741117421174311744117451174611747117481174911750117511175211753117541175511756117571175811759117601176111762117631176411765117661176711768117691177011771117721177311774117751177611777117781177911780117811178211783117841178511786117871178811789117901179111792117931179411795117961179711798117991180011801118021180311804118051180611807118081180911810118111181211813118141181511816118171181811819118201182111822118231182411825118261182711828118291183011831118321183311834118351183611837118381183911840118411184211843118441184511846118471184811849118501185111852118531185411855118561185711858118591186011861118621186311864118651186611867118681186911870118711187211873118741187511876118771187811879118801188111882118831188411885118861188711888118891189011891118921189311894118951189611897118981189911900119011190211903119041190511906119071190811909119101191111912119131191411915119161191711918119191192011921119221192311924119251192611927119281192911930119311193211933119341193511936119371193811939119401194111942119431194411945119461194711948119491195011951119521195311954119551195611957119581195911960119611196211963119641196511966119671196811969119701197111972119731197411975119761197711978119791198011981119821198311984119851198611987119881198911990119911199211993119941199511996119971199811999120001200112002120031200412005120061200712008120091201012011120121201312014120151201612017120181201912020120211202212023120241202512026120271202812029120301203112032120331203412035120361203712038120391204012041120421204312044120451204612047120481204912050120511205212053120541205512056120571205812059120601206112062120631206412065120661206712068120691207012071120721207312074120751207612077120781207912080120811208212083120841208512086120871208812089120901209112092120931209412095120961209712098120991210012101121021210312104121051210612107121081210912110121111211212113121141211512116121171211812119121201212112122121231212412125121261212712128121291213012131121321213312134121351213612137121381213912140121411214212143121441214512146121471214812149121501215112152121531215412155121561215712158121591216012161121621216312164121651216612167121681216912170121711217212173121741217512176121771217812179121801218112182121831218412185121861218712188121891219012191121921219312194121951219612197121981219912200122011220212203122041220512206122071220812209122101221112212122131221412215122161221712218122191222012221122221222312224122251222612227122281222912230122311223212233122341223512236122371223812239122401224112242122431224412245122461224712248122491225012251122521225312254122551225612257122581225912260122611226212263122641226512266122671226812269122701227112272122731227412275122761227712278122791228012281122821228312284122851228612287122881228912290122911229212293122941229512296122971229812299123001230112302123031230412305123061230712308123091231012311123121231312314123151231612317123181231912320123211232212323123241232512326123271232812329123301233112332123331233412335123361233712338123391234012341123421234312344123451234612347123481234912350123511235212353123541235512356123571235812359123601236112362123631236412365123661236712368123691237012371123721237312374123751237612377123781237912380123811238212383123841238512386123871238812389123901239112392123931239412395123961239712398123991240012401124021240312404124051240612407124081240912410124111241212413124141241512416124171241812419124201242112422124231242412425124261242712428124291243012431124321243312434124351243612437124381243912440124411244212443124441244512446124471244812449124501245112452124531245412455124561245712458124591246012461124621246312464124651246612467124681246912470124711247212473124741247512476124771247812479124801248112482124831248412485124861248712488124891249012491124921249312494124951249612497124981249912500125011250212503125041250512506125071250812509125101251112512125131251412515125161251712518125191252012521125221252312524125251252612527125281252912530125311253212533125341253512536125371253812539125401254112542125431254412545125461254712548125491255012551125521255312554125551255612557125581255912560125611256212563125641256512566125671256812569125701257112572125731257412575125761257712578125791258012581125821258312584125851258612587125881258912590125911259212593125941259512596125971259812599126001260112602126031260412605126061260712608126091261012611126121261312614126151261612617126181261912620126211262212623126241262512626126271262812629126301263112632126331263412635126361263712638126391264012641126421264312644126451264612647126481264912650126511265212653126541265512656126571265812659126601266112662126631266412665126661266712668126691267012671126721267312674126751267612677126781267912680126811268212683126841268512686126871268812689126901269112692126931269412695126961269712698126991270012701127021270312704127051270612707127081270912710127111271212713127141271512716127171271812719127201272112722127231272412725127261272712728127291273012731127321273312734127351273612737127381273912740127411274212743127441274512746127471274812749127501275112752127531275412755127561275712758127591276012761127621276312764127651276612767127681276912770127711277212773127741277512776127771277812779127801278112782127831278412785127861278712788127891279012791127921279312794127951279612797127981279912800128011280212803128041280512806128071280812809128101281112812128131281412815128161281712818128191282012821128221282312824128251282612827128281282912830128311283212833128341283512836128371283812839128401284112842128431284412845128461284712848128491285012851128521285312854128551285612857128581285912860128611286212863128641286512866128671286812869128701287112872128731287412875128761287712878128791288012881128821288312884128851288612887128881288912890128911289212893128941289512896128971289812899129001290112902129031290412905129061290712908129091291012911129121291312914129151291612917129181291912920129211292212923129241292512926129271292812929129301293112932129331293412935129361293712938129391294012941129421294312944129451294612947129481294912950129511295212953129541295512956129571295812959129601296112962129631296412965129661296712968129691297012971129721297312974129751297612977129781297912980129811298212983129841298512986129871298812989129901299112992129931299412995129961299712998129991300013001130021300313004130051300613007130081300913010130111301213013130141301513016130171301813019130201302113022130231302413025130261302713028130291303013031130321303313034130351303613037130381303913040130411304213043130441304513046130471304813049130501305113052130531305413055130561305713058130591306013061130621306313064130651306613067130681306913070130711307213073130741307513076130771307813079130801308113082130831308413085130861308713088130891309013091130921309313094130951309613097130981309913100131011310213103131041310513106131071310813109131101311113112131131311413115131161311713118131191312013121131221312313124131251312613127131281312913130131311313213133131341313513136131371313813139131401314113142131431314413145131461314713148131491315013151131521315313154131551315613157131581315913160131611316213163131641316513166131671316813169131701317113172131731317413175131761317713178131791318013181131821318313184131851318613187131881318913190131911319213193131941319513196131971319813199132001320113202132031320413205132061320713208132091321013211132121321313214132151321613217132181321913220132211322213223132241322513226132271322813229132301323113232132331323413235132361323713238132391324013241132421324313244132451324613247132481324913250132511325213253132541325513256132571325813259132601326113262132631326413265132661326713268132691327013271132721327313274132751327613277132781327913280132811328213283132841328513286132871328813289132901329113292132931329413295132961329713298132991330013301133021330313304133051330613307133081330913310133111331213313133141331513316133171331813319133201332113322133231332413325133261332713328133291333013331133321333313334133351333613337133381333913340133411334213343133441334513346133471334813349133501335113352133531335413355133561335713358133591336013361133621336313364133651336613367133681336913370133711337213373133741337513376133771337813379133801338113382133831338413385133861338713388133891339013391133921339313394133951339613397133981339913400134011340213403134041340513406134071340813409134101341113412134131341413415134161341713418134191342013421134221342313424134251342613427134281342913430134311343213433134341343513436134371343813439134401344113442134431344413445134461344713448134491345013451134521345313454134551345613457134581345913460134611346213463134641346513466134671346813469134701347113472134731347413475134761347713478134791348013481134821348313484134851348613487134881348913490134911349213493134941349513496134971349813499135001350113502135031350413505135061350713508135091351013511135121351313514135151351613517135181351913520135211352213523135241352513526135271352813529135301353113532135331353413535135361353713538135391354013541135421354313544135451354613547135481354913550135511355213553135541355513556135571355813559135601356113562135631356413565135661356713568135691357013571135721357313574135751357613577135781357913580135811358213583135841358513586135871358813589135901359113592135931359413595135961359713598135991360013601136021360313604136051360613607136081360913610136111361213613136141361513616136171361813619136201362113622136231362413625136261362713628136291363013631136321363313634136351363613637136381363913640136411364213643136441364513646136471364813649136501365113652136531365413655136561365713658136591366013661136621366313664136651366613667136681366913670136711367213673136741367513676136771367813679136801368113682136831368413685136861368713688136891369013691136921369313694136951369613697136981369913700137011370213703137041370513706137071370813709137101371113712137131371413715137161371713718137191372013721137221372313724137251372613727137281372913730137311373213733137341373513736137371373813739137401374113742137431374413745137461374713748137491375013751137521375313754137551375613757137581375913760137611376213763137641376513766137671376813769137701377113772137731377413775137761377713778137791378013781137821378313784137851378613787137881378913790137911379213793137941379513796137971379813799138001380113802138031380413805138061380713808138091381013811138121381313814138151381613817138181381913820138211382213823138241382513826138271382813829138301383113832138331383413835138361383713838138391384013841138421384313844138451384613847138481384913850138511385213853138541385513856138571385813859138601386113862138631386413865138661386713868138691387013871138721387313874138751387613877138781387913880138811388213883138841388513886138871388813889138901389113892138931389413895138961389713898138991390013901139021390313904139051390613907139081390913910139111391213913139141391513916139171391813919139201392113922139231392413925139261392713928139291393013931139321393313934139351393613937139381393913940139411394213943139441394513946139471394813949139501395113952139531395413955139561395713958139591396013961139621396313964139651396613967139681396913970139711397213973139741397513976139771397813979139801398113982139831398413985139861398713988139891399013991139921399313994139951399613997139981399914000140011400214003140041400514006140071400814009140101401114012140131401414015140161401714018140191402014021140221402314024140251402614027140281402914030140311403214033140341403514036140371403814039140401404114042140431404414045140461404714048140491405014051140521405314054140551405614057140581405914060140611406214063140641406514066140671406814069140701407114072140731407414075140761407714078140791408014081140821408314084140851408614087140881408914090140911409214093140941409514096140971409814099141001410114102141031410414105141061410714108141091411014111141121411314114141151411614117141181411914120141211412214123141241412514126141271412814129141301413114132141331413414135141361413714138141391414014141141421414314144141451414614147141481414914150141511415214153141541415514156141571415814159141601416114162141631416414165141661416714168141691417014171141721417314174141751417614177141781417914180141811418214183141841418514186141871418814189141901419114192141931419414195141961419714198141991420014201142021420314204142051420614207142081420914210142111421214213142141421514216142171421814219142201422114222142231422414225142261422714228142291423014231142321423314234142351423614237142381423914240142411424214243142441424514246142471424814249142501425114252142531425414255142561425714258142591426014261142621426314264142651426614267142681426914270142711427214273142741427514276142771427814279142801428114282142831428414285142861428714288142891429014291142921429314294142951429614297142981429914300143011430214303143041430514306143071430814309143101431114312143131431414315143161431714318143191432014321143221432314324143251432614327143281432914330143311433214333143341433514336143371433814339143401434114342143431434414345143461434714348143491435014351143521435314354143551435614357143581435914360143611436214363143641436514366143671436814369143701437114372143731437414375143761437714378143791438014381143821438314384143851438614387143881438914390143911439214393143941439514396143971439814399144001440114402144031440414405144061440714408144091441014411144121441314414144151441614417144181441914420144211442214423144241442514426144271442814429144301443114432144331443414435144361443714438144391444014441144421444314444144451444614447144481444914450144511445214453144541445514456144571445814459144601446114462144631446414465144661446714468144691447014471144721447314474144751447614477144781447914480144811448214483144841448514486144871448814489144901449114492144931449414495144961449714498144991450014501145021450314504145051450614507145081450914510145111451214513145141451514516145171451814519145201452114522145231452414525145261452714528145291453014531145321453314534145351453614537145381453914540145411454214543145441454514546145471454814549145501455114552145531455414555145561455714558145591456014561145621456314564145651456614567145681456914570145711457214573145741457514576145771457814579145801458114582145831458414585145861458714588145891459014591145921459314594145951459614597145981459914600146011460214603146041460514606146071460814609146101461114612146131461414615146161461714618146191462014621146221462314624146251462614627146281462914630146311463214633146341463514636146371463814639146401464114642146431464414645146461464714648146491465014651146521465314654146551465614657146581465914660146611466214663146641466514666146671466814669146701467114672146731467414675146761467714678146791468014681146821468314684146851468614687146881468914690146911469214693146941469514696146971469814699147001470114702147031470414705147061470714708147091471014711147121471314714147151471614717147181471914720147211472214723147241472514726147271472814729147301473114732147331473414735147361473714738147391474014741147421474314744147451474614747147481474914750147511475214753147541475514756147571475814759147601476114762147631476414765147661476714768147691477014771147721477314774147751477614777147781477914780147811478214783147841478514786147871478814789147901479114792147931479414795147961479714798147991480014801148021480314804148051480614807148081480914810148111481214813148141481514816148171481814819148201482114822148231482414825148261482714828148291483014831148321483314834148351483614837148381483914840148411484214843148441484514846148471484814849148501485114852148531485414855148561485714858148591486014861148621486314864148651486614867148681486914870148711487214873148741487514876148771487814879148801488114882148831488414885148861488714888148891489014891148921489314894148951489614897148981489914900149011490214903149041490514906149071490814909149101491114912149131491414915149161491714918149191492014921149221492314924149251492614927149281492914930149311493214933149341493514936149371493814939149401494114942149431494414945149461494714948149491495014951149521495314954149551495614957149581495914960149611496214963149641496514966149671496814969149701497114972149731497414975149761497714978149791498014981149821498314984149851498614987149881498914990149911499214993149941499514996149971499814999150001500115002150031500415005150061500715008150091501015011150121501315014150151501615017150181501915020150211502215023150241502515026150271502815029150301503115032150331503415035150361503715038150391504015041150421504315044150451504615047150481504915050150511505215053150541505515056150571505815059150601506115062150631506415065150661506715068150691507015071150721507315074150751507615077150781507915080150811508215083150841508515086150871508815089150901509115092150931509415095150961509715098150991510015101151021510315104151051510615107151081510915110151111511215113151141511515116151171511815119151201512115122151231512415125151261512715128151291513015131151321513315134151351513615137151381513915140151411514215143151441514515146151471514815149151501515115152151531515415155151561515715158151591516015161151621516315164151651516615167151681516915170151711517215173151741517515176151771517815179151801518115182151831518415185151861518715188151891519015191151921519315194151951519615197151981519915200152011520215203152041520515206152071520815209152101521115212152131521415215152161521715218152191522015221152221522315224152251522615227152281522915230152311523215233152341523515236152371523815239152401524115242152431524415245152461524715248152491525015251152521525315254152551525615257152581525915260152611526215263152641526515266152671526815269152701527115272152731527415275152761527715278152791528015281152821528315284152851528615287152881528915290152911529215293152941529515296152971529815299153001530115302153031530415305153061530715308153091531015311153121531315314153151531615317153181531915320153211532215323153241532515326153271532815329153301533115332153331533415335153361533715338153391534015341153421534315344153451534615347153481534915350153511535215353153541535515356153571535815359153601536115362153631536415365153661536715368153691537015371153721537315374153751537615377153781537915380153811538215383153841538515386153871538815389153901539115392153931539415395153961539715398153991540015401154021540315404154051540615407154081540915410154111541215413154141541515416154171541815419154201542115422154231542415425154261542715428154291543015431154321543315434154351543615437154381543915440154411544215443154441544515446154471544815449154501545115452154531545415455154561545715458154591546015461154621546315464154651546615467154681546915470154711547215473154741547515476154771547815479154801548115482154831548415485154861548715488154891549015491154921549315494154951549615497154981549915500155011550215503155041550515506155071550815509155101551115512155131551415515155161551715518155191552015521155221552315524155251552615527155281552915530155311553215533155341553515536155371553815539155401554115542155431554415545155461554715548155491555015551155521555315554155551555615557155581555915560155611556215563155641556515566155671556815569155701557115572155731557415575155761557715578155791558015581155821558315584155851558615587155881558915590155911559215593155941559515596155971559815599156001560115602156031560415605156061560715608156091561015611156121561315614156151561615617156181561915620156211562215623156241562515626156271562815629156301563115632156331563415635156361563715638156391564015641156421564315644156451564615647156481564915650156511565215653156541565515656156571565815659156601566115662156631566415665156661566715668156691567015671156721567315674156751567615677156781567915680156811568215683156841568515686156871568815689156901569115692156931569415695156961569715698156991570015701157021570315704157051570615707157081570915710157111571215713157141571515716157171571815719157201572115722157231572415725157261572715728157291573015731157321573315734157351573615737157381573915740157411574215743157441574515746157471574815749157501575115752157531575415755157561575715758157591576015761157621576315764157651576615767157681576915770157711577215773157741577515776157771577815779157801578115782157831578415785157861578715788157891579015791157921579315794157951579615797157981579915800158011580215803158041580515806158071580815809158101581115812158131581415815158161581715818158191582015821158221582315824158251582615827158281582915830158311583215833158341583515836158371583815839158401584115842158431584415845158461584715848158491585015851158521585315854158551585615857158581585915860158611586215863158641586515866158671586815869158701587115872158731587415875158761587715878158791588015881158821588315884158851588615887158881588915890158911589215893158941589515896158971589815899159001590115902159031590415905159061590715908159091591015911159121591315914159151591615917159181591915920159211592215923159241592515926159271592815929159301593115932159331593415935159361593715938159391594015941159421594315944159451594615947159481594915950159511595215953159541595515956159571595815959159601596115962159631596415965159661596715968159691597015971159721597315974159751597615977159781597915980159811598215983159841598515986159871598815989159901599115992159931599415995159961599715998159991600016001160021600316004160051600616007160081600916010160111601216013160141601516016160171601816019160201602116022160231602416025160261602716028160291603016031160321603316034160351603616037160381603916040160411604216043160441604516046160471604816049160501605116052160531605416055160561605716058160591606016061160621606316064160651606616067160681606916070160711607216073160741607516076160771607816079160801608116082160831608416085160861608716088160891609016091160921609316094160951609616097160981609916100161011610216103161041610516106161071610816109161101611116112161131611416115161161611716118161191612016121161221612316124161251612616127161281612916130161311613216133161341613516136161371613816139161401614116142161431614416145161461614716148161491615016151161521615316154161551615616157161581615916160161611616216163161641616516166161671616816169161701617116172161731617416175161761617716178161791618016181161821618316184161851618616187161881618916190161911619216193161941619516196161971619816199162001620116202162031620416205162061620716208162091621016211162121621316214162151621616217162181621916220162211622216223162241622516226162271622816229162301623116232162331623416235162361623716238162391624016241162421624316244162451624616247162481624916250162511625216253162541625516256162571625816259162601626116262162631626416265162661626716268162691627016271162721627316274162751627616277162781627916280162811628216283162841628516286162871628816289162901629116292162931629416295162961629716298162991630016301163021630316304163051630616307163081630916310163111631216313163141631516316163171631816319163201632116322163231632416325163261632716328163291633016331163321633316334163351633616337163381633916340163411634216343163441634516346163471634816349163501635116352163531635416355163561635716358163591636016361163621636316364163651636616367163681636916370163711637216373163741637516376163771637816379163801638116382163831638416385163861638716388163891639016391163921639316394163951639616397163981639916400164011640216403164041640516406164071640816409164101641116412164131641416415164161641716418164191642016421164221642316424164251642616427164281642916430164311643216433164341643516436164371643816439164401644116442164431644416445164461644716448164491645016451164521645316454164551645616457164581645916460164611646216463164641646516466164671646816469164701647116472164731647416475164761647716478164791648016481164821648316484164851648616487164881648916490164911649216493164941649516496164971649816499165001650116502165031650416505165061650716508165091651016511165121651316514165151651616517165181651916520165211652216523165241652516526165271652816529165301653116532165331653416535165361653716538165391654016541165421654316544165451654616547165481654916550165511655216553165541655516556165571655816559165601656116562165631656416565165661656716568165691657016571165721657316574165751657616577165781657916580165811658216583165841658516586165871658816589165901659116592165931659416595165961659716598165991660016601166021660316604166051660616607166081660916610166111661216613166141661516616166171661816619166201662116622166231662416625166261662716628166291663016631166321663316634166351663616637166381663916640166411664216643166441664516646166471664816649166501665116652166531665416655166561665716658166591666016661166621666316664166651666616667166681666916670166711667216673166741667516676166771667816679166801668116682166831668416685166861668716688166891669016691166921669316694166951669616697166981669916700167011670216703167041670516706167071670816709167101671116712167131671416715167161671716718167191672016721167221672316724167251672616727167281672916730167311673216733167341673516736167371673816739167401674116742167431674416745167461674716748167491675016751167521675316754167551675616757167581675916760167611676216763167641676516766167671676816769167701677116772167731677416775167761677716778167791678016781167821678316784167851678616787167881678916790167911679216793167941679516796167971679816799168001680116802168031680416805168061680716808168091681016811168121681316814168151681616817168181681916820168211682216823168241682516826168271682816829168301683116832168331683416835168361683716838168391684016841168421684316844168451684616847168481684916850168511685216853168541685516856168571685816859168601686116862168631686416865168661686716868168691687016871168721687316874168751687616877168781687916880168811688216883168841688516886168871688816889168901689116892168931689416895168961689716898168991690016901169021690316904169051690616907169081690916910169111691216913169141691516916169171691816919169201692116922169231692416925169261692716928169291693016931169321693316934169351693616937169381693916940169411694216943169441694516946169471694816949169501695116952169531695416955169561695716958169591696016961169621696316964169651696616967169681696916970169711697216973169741697516976169771697816979169801698116982169831698416985169861698716988169891699016991169921699316994169951699616997169981699917000170011700217003170041700517006170071700817009170101701117012170131701417015170161701717018170191702017021170221702317024170251702617027170281702917030170311703217033170341703517036170371703817039170401704117042170431704417045170461704717048170491705017051170521705317054170551705617057170581705917060170611706217063170641706517066170671706817069170701707117072170731707417075170761707717078170791708017081170821708317084170851708617087170881708917090170911709217093170941709517096170971709817099171001710117102171031710417105171061710717108171091711017111171121711317114171151711617117171181711917120171211712217123171241712517126171271712817129171301713117132171331713417135171361713717138171391714017141171421714317144171451714617147171481714917150171511715217153171541715517156171571715817159171601716117162171631716417165171661716717168171691717017171171721717317174171751717617177171781717917180171811718217183171841718517186171871718817189171901719117192171931719417195171961719717198171991720017201172021720317204172051720617207172081720917210172111721217213172141721517216172171721817219172201722117222172231722417225172261722717228172291723017231172321723317234172351723617237172381723917240172411724217243172441724517246172471724817249172501725117252172531725417255172561725717258172591726017261172621726317264172651726617267172681726917270172711727217273172741727517276172771727817279172801728117282172831728417285172861728717288172891729017291172921729317294172951729617297172981729917300173011730217303173041730517306173071730817309173101731117312173131731417315173161731717318173191732017321173221732317324173251732617327173281732917330173311733217333173341733517336173371733817339173401734117342173431734417345173461734717348173491735017351173521735317354173551735617357173581735917360173611736217363173641736517366173671736817369173701737117372173731737417375173761737717378173791738017381173821738317384173851738617387173881738917390173911739217393173941739517396173971739817399174001740117402174031740417405174061740717408174091741017411174121741317414174151741617417174181741917420174211742217423174241742517426174271742817429174301743117432174331743417435174361743717438174391744017441174421744317444174451744617447174481744917450174511745217453174541745517456174571745817459174601746117462174631746417465174661746717468174691747017471174721747317474174751747617477174781747917480174811748217483174841748517486174871748817489174901749117492174931749417495174961749717498174991750017501175021750317504175051750617507175081750917510175111751217513175141751517516175171751817519175201752117522175231752417525175261752717528175291753017531175321753317534175351753617537175381753917540175411754217543175441754517546175471754817549175501755117552175531755417555175561755717558175591756017561175621756317564175651756617567175681756917570175711757217573175741757517576175771757817579175801758117582175831758417585175861758717588175891759017591175921759317594175951759617597175981759917600176011760217603176041760517606176071760817609176101761117612176131761417615176161761717618176191762017621176221762317624176251762617627176281762917630176311763217633176341763517636176371763817639176401764117642176431764417645176461764717648176491765017651176521765317654176551765617657176581765917660176611766217663176641766517666176671766817669176701767117672176731767417675176761767717678176791768017681176821768317684176851768617687176881768917690176911769217693176941769517696176971769817699177001770117702177031770417705177061770717708177091771017711177121771317714177151771617717177181771917720177211772217723177241772517726177271772817729177301773117732177331773417735177361773717738177391774017741177421774317744177451774617747177481774917750177511775217753177541775517756177571775817759177601776117762177631776417765177661776717768177691777017771177721777317774177751777617777177781777917780177811778217783177841778517786177871778817789177901779117792177931779417795177961779717798177991780017801178021780317804178051780617807178081780917810178111781217813178141781517816178171781817819178201782117822178231782417825178261782717828178291783017831178321783317834178351783617837178381783917840178411784217843178441784517846178471784817849178501785117852178531785417855178561785717858178591786017861178621786317864178651786617867178681786917870178711787217873178741787517876178771787817879178801788117882178831788417885178861788717888178891789017891178921789317894178951789617897178981789917900179011790217903179041790517906179071790817909179101791117912179131791417915179161791717918179191792017921179221792317924179251792617927179281792917930179311793217933179341793517936179371793817939179401794117942179431794417945179461794717948179491795017951179521795317954179551795617957179581795917960179611796217963179641796517966179671796817969179701797117972179731797417975179761797717978179791798017981179821798317984179851798617987179881798917990179911799217993179941799517996179971799817999180001800118002180031800418005180061800718008180091801018011180121801318014180151801618017180181801918020180211802218023180241802518026180271802818029180301803118032180331803418035180361803718038180391804018041180421804318044180451804618047180481804918050180511805218053180541805518056180571805818059180601806118062180631806418065180661806718068180691807018071180721807318074180751807618077180781807918080180811808218083180841808518086180871808818089180901809118092180931809418095180961809718098180991810018101181021810318104181051810618107181081810918110181111811218113181141811518116181171811818119181201812118122181231812418125181261812718128181291813018131181321813318134181351813618137181381813918140181411814218143181441814518146181471814818149181501815118152181531815418155181561815718158181591816018161181621816318164181651816618167181681816918170181711817218173181741817518176181771817818179181801818118182181831818418185181861818718188181891819018191181921819318194181951819618197181981819918200182011820218203182041820518206182071820818209182101821118212182131821418215182161821718218182191822018221182221822318224182251822618227182281822918230182311823218233182341823518236182371823818239182401824118242182431824418245182461824718248182491825018251182521825318254182551825618257182581825918260182611826218263182641826518266182671826818269182701827118272182731827418275182761827718278182791828018281182821828318284182851828618287182881828918290182911829218293182941829518296182971829818299183001830118302183031830418305183061830718308183091831018311183121831318314183151831618317183181831918320183211832218323183241832518326183271832818329183301833118332183331833418335183361833718338183391834018341183421834318344183451834618347183481834918350183511835218353183541835518356183571835818359183601836118362183631836418365183661836718368183691837018371183721837318374183751837618377183781837918380183811838218383183841838518386183871838818389183901839118392183931839418395183961839718398183991840018401184021840318404184051840618407184081840918410184111841218413184141841518416184171841818419184201842118422184231842418425184261842718428184291843018431184321843318434184351843618437184381843918440184411844218443184441844518446184471844818449184501845118452184531845418455184561845718458184591846018461184621846318464184651846618467184681846918470184711847218473184741847518476184771847818479184801848118482184831848418485184861848718488184891849018491184921849318494184951849618497184981849918500185011850218503185041850518506185071850818509185101851118512185131851418515185161851718518185191852018521185221852318524185251852618527185281852918530185311853218533185341853518536185371853818539185401854118542185431854418545185461854718548185491855018551185521855318554185551855618557185581855918560185611856218563185641856518566185671856818569185701857118572185731857418575185761857718578185791858018581185821858318584185851858618587185881858918590185911859218593185941859518596185971859818599186001860118602186031860418605186061860718608186091861018611186121861318614186151861618617186181861918620186211862218623186241862518626186271862818629186301863118632186331863418635186361863718638186391864018641186421864318644186451864618647186481864918650186511865218653186541865518656186571865818659186601866118662186631866418665186661866718668186691867018671186721867318674186751867618677186781867918680186811868218683186841868518686186871868818689186901869118692186931869418695186961869718698186991870018701187021870318704187051870618707187081870918710187111871218713187141871518716187171871818719187201872118722187231872418725187261872718728187291873018731187321873318734187351873618737187381873918740187411874218743187441874518746187471874818749187501875118752187531875418755187561875718758187591876018761187621876318764187651876618767187681876918770187711877218773187741877518776187771877818779187801878118782187831878418785187861878718788187891879018791187921879318794187951879618797187981879918800188011880218803188041880518806188071880818809188101881118812188131881418815188161881718818188191882018821188221882318824188251882618827188281882918830188311883218833188341883518836188371883818839188401884118842188431884418845188461884718848188491885018851188521885318854188551885618857188581885918860188611886218863188641886518866188671886818869188701887118872188731887418875188761887718878188791888018881188821888318884188851888618887188881888918890188911889218893188941889518896188971889818899189001890118902189031890418905189061890718908189091891018911189121891318914189151891618917189181891918920189211892218923189241892518926189271892818929189301893118932189331893418935189361893718938189391894018941189421894318944189451894618947189481894918950189511895218953189541895518956189571895818959189601896118962189631896418965189661896718968189691897018971189721897318974189751897618977189781897918980189811898218983189841898518986189871898818989189901899118992189931899418995189961899718998189991900019001190021900319004190051900619007190081900919010190111901219013190141901519016190171901819019190201902119022190231902419025190261902719028190291903019031190321903319034190351903619037190381903919040190411904219043190441904519046190471904819049190501905119052190531905419055190561905719058190591906019061190621906319064190651906619067190681906919070190711907219073190741907519076190771907819079190801908119082190831908419085190861908719088190891909019091190921909319094190951909619097190981909919100191011910219103191041910519106191071910819109191101911119112191131911419115191161911719118191191912019121191221912319124191251912619127191281912919130191311913219133191341913519136191371913819139191401914119142191431914419145191461914719148191491915019151191521915319154191551915619157191581915919160191611916219163191641916519166191671916819169191701917119172191731917419175191761917719178191791918019181191821918319184191851918619187191881918919190191911919219193191941919519196191971919819199192001920119202192031920419205192061920719208192091921019211192121921319214192151921619217192181921919220192211922219223192241922519226192271922819229192301923119232192331923419235192361923719238192391924019241192421924319244192451924619247192481924919250192511925219253192541925519256192571925819259192601926119262192631926419265192661926719268192691927019271192721927319274192751927619277192781927919280192811928219283192841928519286192871928819289192901929119292192931929419295192961929719298192991930019301193021930319304193051930619307193081930919310193111931219313193141931519316193171931819319193201932119322193231932419325193261932719328193291933019331193321933319334193351933619337193381933919340193411934219343193441934519346193471934819349193501935119352193531935419355193561935719358193591936019361193621936319364193651936619367193681936919370193711937219373193741937519376193771937819379193801938119382193831938419385193861938719388193891939019391193921939319394193951939619397193981939919400194011940219403194041940519406194071940819409194101941119412194131941419415194161941719418194191942019421194221942319424194251942619427194281942919430194311943219433194341943519436194371943819439194401944119442194431944419445194461944719448194491945019451194521945319454194551945619457194581945919460194611946219463194641946519466194671946819469194701947119472194731947419475194761947719478194791948019481194821948319484194851948619487194881948919490194911949219493194941949519496194971949819499195001950119502195031950419505195061950719508195091951019511195121951319514195151951619517195181951919520195211952219523195241952519526195271952819529195301953119532195331953419535195361953719538195391954019541195421954319544195451954619547195481954919550195511955219553195541955519556195571955819559195601956119562195631956419565195661956719568195691957019571195721957319574195751957619577195781957919580195811958219583195841958519586195871958819589195901959119592195931959419595195961959719598195991960019601196021960319604196051960619607196081960919610196111961219613196141961519616196171961819619196201962119622196231962419625196261962719628196291963019631196321963319634196351963619637196381963919640196411964219643196441964519646196471964819649196501965119652196531965419655196561965719658196591966019661196621966319664196651966619667196681966919670196711967219673196741967519676196771967819679196801968119682196831968419685196861968719688196891969019691196921969319694196951969619697196981969919700197011970219703197041970519706197071970819709197101971119712197131971419715197161971719718197191972019721197221972319724197251972619727197281972919730197311973219733197341973519736197371973819739197401974119742197431974419745197461974719748197491975019751197521975319754197551975619757197581975919760197611976219763197641976519766197671976819769197701977119772197731977419775197761977719778197791978019781197821978319784197851978619787197881978919790197911979219793197941979519796197971979819799198001980119802198031980419805198061980719808198091981019811198121981319814198151981619817198181981919820198211982219823198241982519826198271982819829198301983119832198331983419835198361983719838198391984019841198421984319844198451984619847198481984919850198511985219853198541985519856198571985819859198601986119862198631986419865198661986719868198691987019871198721987319874198751987619877198781987919880198811988219883198841988519886198871988819889198901989119892198931989419895198961989719898198991990019901199021990319904199051990619907199081990919910199111991219913199141991519916199171991819919199201992119922199231992419925199261992719928199291993019931199321993319934199351993619937199381993919940199411994219943199441994519946199471994819949199501995119952199531995419955199561995719958199591996019961199621996319964199651996619967199681996919970199711997219973199741997519976199771997819979199801998119982199831998419985199861998719988199891999019991199921999319994199951999619997199981999920000200012000220003200042000520006200072000820009200102001120012200132001420015200162001720018200192002020021200222002320024200252002620027200282002920030200312003220033200342003520036200372003820039200402004120042200432004420045200462004720048200492005020051200522005320054200552005620057200582005920060200612006220063200642006520066200672006820069200702007120072200732007420075200762007720078200792008020081200822008320084200852008620087200882008920090200912009220093200942009520096200972009820099201002010120102201032010420105201062010720108201092011020111201122011320114201152011620117201182011920120201212012220123201242012520126201272012820129201302013120132201332013420135201362013720138201392014020141201422014320144201452014620147201482014920150201512015220153201542015520156201572015820159201602016120162201632016420165201662016720168201692017020171201722017320174201752017620177201782017920180201812018220183201842018520186201872018820189201902019120192201932019420195201962019720198201992020020201202022020320204202052020620207202082020920210202112021220213202142021520216202172021820219202202022120222202232022420225202262022720228202292023020231202322023320234202352023620237202382023920240202412024220243202442024520246202472024820249202502025120252202532025420255202562025720258202592026020261202622026320264202652026620267202682026920270202712027220273202742027520276202772027820279202802028120282202832028420285202862028720288202892029020291202922029320294202952029620297202982029920300203012030220303203042030520306203072030820309203102031120312203132031420315203162031720318203192032020321203222032320324203252032620327203282032920330203312033220333203342033520336203372033820339203402034120342203432034420345203462034720348203492035020351203522035320354203552035620357203582035920360203612036220363203642036520366203672036820369203702037120372203732037420375203762037720378203792038020381203822038320384203852038620387203882038920390203912039220393203942039520396203972039820399204002040120402204032040420405204062040720408204092041020411204122041320414204152041620417204182041920420204212042220423204242042520426204272042820429204302043120432204332043420435204362043720438204392044020441204422044320444204452044620447204482044920450204512045220453204542045520456204572045820459204602046120462204632046420465204662046720468204692047020471204722047320474204752047620477204782047920480204812048220483204842048520486204872048820489204902049120492204932049420495204962049720498204992050020501205022050320504205052050620507205082050920510205112051220513205142051520516205172051820519205202052120522205232052420525205262052720528205292053020531205322053320534205352053620537205382053920540205412054220543205442054520546205472054820549205502055120552205532055420555205562055720558205592056020561205622056320564205652056620567205682056920570205712057220573205742057520576205772057820579205802058120582205832058420585205862058720588205892059020591205922059320594205952059620597205982059920600206012060220603206042060520606206072060820609206102061120612206132061420615206162061720618206192062020621206222062320624206252062620627206282062920630206312063220633206342063520636206372063820639206402064120642206432064420645206462064720648206492065020651206522065320654206552065620657206582065920660206612066220663206642066520666206672066820669206702067120672206732067420675206762067720678206792068020681206822068320684206852068620687206882068920690206912069220693206942069520696206972069820699207002070120702207032070420705207062070720708207092071020711207122071320714207152071620717207182071920720207212072220723207242072520726207272072820729207302073120732207332073420735207362073720738207392074020741207422074320744207452074620747207482074920750207512075220753207542075520756207572075820759207602076120762207632076420765207662076720768207692077020771207722077320774207752077620777207782077920780207812078220783207842078520786207872078820789207902079120792207932079420795207962079720798207992080020801208022080320804208052080620807208082080920810208112081220813208142081520816208172081820819208202082120822208232082420825208262082720828208292083020831208322083320834208352083620837208382083920840208412084220843208442084520846208472084820849208502085120852208532085420855208562085720858208592086020861208622086320864208652086620867208682086920870208712087220873208742087520876208772087820879208802088120882208832088420885208862088720888208892089020891208922089320894208952089620897208982089920900209012090220903209042090520906209072090820909209102091120912209132091420915209162091720918209192092020921209222092320924209252092620927209282092920930209312093220933209342093520936209372093820939209402094120942209432094420945209462094720948209492095020951209522095320954209552095620957209582095920960209612096220963209642096520966209672096820969209702097120972209732097420975209762097720978209792098020981209822098320984209852098620987209882098920990209912099220993209942099520996209972099820999210002100121002210032100421005210062100721008210092101021011210122101321014210152101621017210182101921020210212102221023210242102521026210272102821029210302103121032210332103421035210362103721038210392104021041210422104321044210452104621047210482104921050210512105221053210542105521056210572105821059210602106121062210632106421065210662106721068210692107021071210722107321074210752107621077210782107921080210812108221083210842108521086210872108821089210902109121092210932109421095210962109721098210992110021101211022110321104211052110621107211082110921110211112111221113211142111521116211172111821119211202112121122211232112421125211262112721128211292113021131211322113321134211352113621137211382113921140211412114221143211442114521146211472114821149211502115121152211532115421155211562115721158211592116021161211622116321164211652116621167211682116921170211712117221173211742117521176211772117821179211802118121182211832118421185211862118721188211892119021191211922119321194211952119621197211982119921200212012120221203212042120521206212072120821209212102121121212212132121421215212162121721218212192122021221212222122321224212252122621227212282122921230212312123221233212342123521236212372123821239212402124121242212432124421245212462124721248212492125021251212522125321254212552125621257212582125921260212612126221263212642126521266212672126821269212702127121272212732127421275212762127721278212792128021281212822128321284212852128621287212882128921290212912129221293212942129521296212972129821299213002130121302213032130421305213062130721308213092131021311213122131321314213152131621317213182131921320213212132221323213242132521326213272132821329213302133121332213332133421335213362133721338213392134021341213422134321344213452134621347213482134921350213512135221353213542135521356213572135821359213602136121362213632136421365213662136721368213692137021371213722137321374213752137621377213782137921380213812138221383213842138521386213872138821389213902139121392213932139421395213962139721398213992140021401214022140321404214052140621407214082140921410214112141221413214142141521416214172141821419214202142121422214232142421425214262142721428214292143021431214322143321434214352143621437214382143921440214412144221443214442144521446214472144821449214502145121452214532145421455214562145721458214592146021461214622146321464214652146621467214682146921470214712147221473214742147521476214772147821479214802148121482214832148421485214862148721488214892149021491214922149321494214952149621497214982149921500215012150221503215042150521506215072150821509215102151121512215132151421515215162151721518215192152021521215222152321524215252152621527215282152921530215312153221533215342153521536215372153821539215402154121542215432154421545215462154721548215492155021551215522155321554215552155621557215582155921560215612156221563215642156521566215672156821569215702157121572215732157421575215762157721578215792158021581215822158321584215852158621587215882158921590215912159221593215942159521596215972159821599216002160121602216032160421605216062160721608216092161021611216122161321614216152161621617216182161921620216212162221623216242162521626216272162821629216302163121632216332163421635216362163721638216392164021641216422164321644216452164621647216482164921650216512165221653216542165521656216572165821659216602166121662216632166421665216662166721668216692167021671216722167321674216752167621677216782167921680216812168221683216842168521686216872168821689216902169121692216932169421695216962169721698216992170021701217022170321704217052170621707217082170921710217112171221713217142171521716217172171821719217202172121722217232172421725217262172721728217292173021731217322173321734217352173621737217382173921740217412174221743217442174521746217472174821749217502175121752217532175421755217562175721758217592176021761217622176321764217652176621767217682176921770217712177221773217742177521776217772177821779217802178121782217832178421785217862178721788217892179021791217922179321794217952179621797217982179921800218012180221803218042180521806218072180821809218102181121812218132181421815218162181721818218192182021821218222182321824218252182621827218282182921830218312183221833218342183521836218372183821839218402184121842218432184421845218462184721848218492185021851218522185321854218552185621857218582185921860218612186221863218642186521866218672186821869218702187121872218732187421875218762187721878218792188021881218822188321884218852188621887218882188921890218912189221893218942189521896218972189821899219002190121902219032190421905219062190721908219092191021911219122191321914219152191621917219182191921920219212192221923219242192521926219272192821929219302193121932219332193421935219362193721938219392194021941219422194321944219452194621947219482194921950219512195221953219542195521956219572195821959219602196121962219632196421965219662196721968219692197021971219722197321974219752197621977219782197921980219812198221983219842198521986219872198821989219902199121992219932199421995219962199721998219992200022001220022200322004220052200622007220082200922010220112201222013220142201522016220172201822019220202202122022220232202422025220262202722028220292203022031220322203322034220352203622037220382203922040220412204222043220442204522046220472204822049220502205122052220532205422055220562205722058220592206022061220622206322064220652206622067220682206922070220712207222073220742207522076220772207822079220802208122082220832208422085220862208722088220892209022091220922209322094220952209622097220982209922100221012210222103221042210522106221072210822109221102211122112221132211422115221162211722118221192212022121221222212322124221252212622127221282212922130221312213222133221342213522136221372213822139221402214122142221432214422145221462214722148221492215022151221522215322154221552215622157221582215922160221612216222163221642216522166221672216822169221702217122172221732217422175221762217722178221792218022181221822218322184221852218622187221882218922190221912219222193221942219522196221972219822199222002220122202222032220422205222062220722208222092221022211222122221322214222152221622217222182221922220222212222222223222242222522226222272222822229222302223122232222332223422235222362223722238222392224022241222422224322244222452224622247222482224922250222512225222253222542225522256222572225822259222602226122262222632226422265222662226722268222692227022271222722227322274222752227622277222782227922280222812228222283222842228522286222872228822289222902229122292222932229422295222962229722298222992230022301223022230322304223052230622307223082230922310223112231222313223142231522316223172231822319223202232122322223232232422325223262232722328223292233022331223322233322334223352233622337223382233922340223412234222343223442234522346223472234822349223502235122352223532235422355223562235722358223592236022361223622236322364223652236622367223682236922370223712237222373223742237522376223772237822379223802238122382223832238422385223862238722388223892239022391223922239322394223952239622397223982239922400224012240222403224042240522406224072240822409224102241122412224132241422415224162241722418224192242022421224222242322424224252242622427224282242922430224312243222433224342243522436224372243822439224402244122442224432244422445224462244722448224492245022451224522245322454224552245622457224582245922460224612246222463224642246522466224672246822469224702247122472224732247422475224762247722478224792248022481224822248322484224852248622487224882248922490224912249222493224942249522496224972249822499225002250122502225032250422505225062250722508225092251022511225122251322514225152251622517225182251922520225212252222523225242252522526225272252822529225302253122532225332253422535225362253722538225392254022541225422254322544225452254622547225482254922550225512255222553225542255522556225572255822559225602256122562225632256422565225662256722568225692257022571225722257322574225752257622577225782257922580225812258222583225842258522586225872258822589225902259122592225932259422595225962259722598225992260022601226022260322604226052260622607226082260922610226112261222613226142261522616226172261822619226202262122622226232262422625226262262722628226292263022631226322263322634226352263622637226382263922640226412264222643226442264522646226472264822649226502265122652226532265422655226562265722658226592266022661226622266322664226652266622667226682266922670226712267222673226742267522676226772267822679226802268122682226832268422685226862268722688226892269022691226922269322694226952269622697226982269922700227012270222703227042270522706227072270822709227102271122712227132271422715227162271722718227192272022721227222272322724227252272622727227282272922730227312273222733227342273522736227372273822739227402274122742227432274422745227462274722748227492275022751227522275322754227552275622757227582275922760227612276222763227642276522766227672276822769227702277122772227732277422775227762277722778227792278022781227822278322784227852278622787227882278922790227912279222793227942279522796227972279822799228002280122802228032280422805228062280722808228092281022811228122281322814228152281622817228182281922820228212282222823228242282522826228272282822829228302283122832228332283422835228362283722838228392284022841228422284322844228452284622847228482284922850228512285222853228542285522856228572285822859228602286122862228632286422865228662286722868228692287022871228722287322874228752287622877228782287922880228812288222883228842288522886228872288822889228902289122892228932289422895228962289722898228992290022901229022290322904229052290622907229082290922910229112291222913229142291522916229172291822919229202292122922229232292422925229262292722928229292293022931229322293322934229352293622937229382293922940229412294222943229442294522946229472294822949229502295122952229532295422955229562295722958229592296022961229622296322964229652296622967229682296922970229712297222973229742297522976229772297822979229802298122982229832298422985229862298722988229892299022991229922299322994229952299622997229982299923000230012300223003230042300523006230072300823009230102301123012230132301423015230162301723018230192302023021230222302323024230252302623027230282302923030230312303223033230342303523036230372303823039230402304123042230432304423045230462304723048230492305023051230522305323054230552305623057230582305923060230612306223063230642306523066230672306823069230702307123072230732307423075230762307723078230792308023081230822308323084230852308623087230882308923090230912309223093230942309523096230972309823099231002310123102231032310423105231062310723108231092311023111231122311323114231152311623117231182311923120231212312223123231242312523126231272312823129231302313123132231332313423135231362313723138231392314023141231422314323144231452314623147231482314923150231512315223153231542315523156231572315823159231602316123162231632316423165231662316723168231692317023171231722317323174231752317623177231782317923180231812318223183231842318523186231872318823189231902319123192231932319423195231962319723198231992320023201232022320323204232052320623207232082320923210232112321223213232142321523216232172321823219232202322123222232232322423225232262322723228232292323023231232322323323234232352323623237232382323923240232412324223243232442324523246232472324823249232502325123252232532325423255232562325723258232592326023261232622326323264232652326623267232682326923270232712327223273232742327523276232772327823279232802328123282232832328423285232862328723288232892329023291232922329323294232952329623297232982329923300233012330223303233042330523306233072330823309233102331123312233132331423315233162331723318233192332023321233222332323324233252332623327233282332923330233312333223333233342333523336233372333823339233402334123342233432334423345233462334723348233492335023351233522335323354233552335623357233582335923360233612336223363233642336523366233672336823369233702337123372233732337423375233762337723378233792338023381233822338323384233852338623387233882338923390233912339223393233942339523396233972339823399234002340123402234032340423405234062340723408234092341023411234122341323414234152341623417234182341923420234212342223423234242342523426234272342823429234302343123432234332343423435234362343723438234392344023441234422344323444234452344623447234482344923450234512345223453234542345523456234572345823459234602346123462234632346423465234662346723468234692347023471234722347323474234752347623477234782347923480234812348223483234842348523486234872348823489234902349123492234932349423495234962349723498234992350023501235022350323504235052350623507235082350923510235112351223513235142351523516235172351823519235202352123522235232352423525235262352723528235292353023531235322353323534235352353623537235382353923540235412354223543235442354523546235472354823549235502355123552235532355423555235562355723558235592356023561235622356323564235652356623567235682356923570235712357223573235742357523576235772357823579235802358123582235832358423585235862358723588235892359023591235922359323594235952359623597235982359923600236012360223603236042360523606236072360823609236102361123612236132361423615236162361723618236192362023621236222362323624236252362623627236282362923630236312363223633236342363523636236372363823639236402364123642236432364423645236462364723648236492365023651236522365323654236552365623657236582365923660236612366223663236642366523666236672366823669236702367123672236732367423675236762367723678236792368023681236822368323684236852368623687236882368923690236912369223693236942369523696236972369823699237002370123702237032370423705237062370723708237092371023711237122371323714237152371623717237182371923720237212372223723237242372523726237272372823729237302373123732237332373423735237362373723738237392374023741237422374323744237452374623747237482374923750237512375223753237542375523756237572375823759237602376123762237632376423765237662376723768237692377023771237722377323774237752377623777237782377923780237812378223783237842378523786237872378823789237902379123792237932379423795237962379723798237992380023801238022380323804238052380623807238082380923810238112381223813238142381523816238172381823819238202382123822238232382423825238262382723828238292383023831238322383323834238352383623837238382383923840238412384223843238442384523846238472384823849238502385123852238532385423855238562385723858238592386023861238622386323864238652386623867238682386923870238712387223873238742387523876238772387823879238802388123882238832388423885238862388723888238892389023891238922389323894238952389623897238982389923900239012390223903239042390523906239072390823909239102391123912239132391423915239162391723918239192392023921239222392323924239252392623927239282392923930239312393223933239342393523936239372393823939239402394123942239432394423945239462394723948239492395023951239522395323954239552395623957239582395923960239612396223963239642396523966239672396823969239702397123972239732397423975239762397723978239792398023981239822398323984239852398623987239882398923990239912399223993239942399523996239972399823999240002400124002240032400424005240062400724008240092401024011240122401324014240152401624017240182401924020240212402224023240242402524026240272402824029240302403124032240332403424035240362403724038240392404024041240422404324044240452404624047240482404924050240512405224053240542405524056240572405824059240602406124062240632406424065240662406724068240692407024071240722407324074240752407624077240782407924080240812408224083240842408524086240872408824089240902409124092240932409424095240962409724098240992410024101241022410324104241052410624107241082410924110241112411224113241142411524116241172411824119241202412124122241232412424125241262412724128241292413024131241322413324134241352413624137241382413924140241412414224143241442414524146241472414824149241502415124152241532415424155241562415724158241592416024161241622416324164241652416624167241682416924170241712417224173241742417524176241772417824179241802418124182241832418424185241862418724188241892419024191241922419324194241952419624197241982419924200242012420224203242042420524206242072420824209242102421124212242132421424215242162421724218242192422024221242222422324224242252422624227242282422924230242312423224233242342423524236242372423824239242402424124242242432424424245242462424724248242492425024251242522425324254242552425624257242582425924260242612426224263242642426524266242672426824269242702427124272242732427424275242762427724278242792428024281242822428324284242852428624287242882428924290242912429224293242942429524296242972429824299243002430124302243032430424305243062430724308243092431024311243122431324314243152431624317243182431924320243212432224323243242432524326243272432824329243302433124332243332433424335243362433724338243392434024341243422434324344243452434624347243482434924350243512435224353243542435524356243572435824359243602436124362243632436424365243662436724368243692437024371243722437324374243752437624377 |
- /*!
- * Vuetify v3.3.11
- * Forged by John Leider
- * Released under the MIT License.
- */
- import { Fragment, reactive, computed, watchEffect, toRefs, capitalize, warn, watch, onScopeDispose, effectScope, ref, unref, provide, shallowRef, inject as inject$1, defineComponent as defineComponent$1, camelize, h, getCurrentInstance as getCurrentInstance$1, onBeforeUnmount, readonly, onDeactivated, onActivated, onMounted, toRaw, createVNode, TransitionGroup, Transition, mergeProps, onBeforeMount, nextTick, withDirectives, resolveDirective, vShow, isRef, toRef, Text, resolveDynamicComponent, Teleport, cloneVNode, createTextVNode, onBeforeUpdate, vModelText, withModifiers } from 'vue';
- // Types
- // eslint-disable-line vue/prefer-import-from-vue
- /**
- * Creates a factory function for props definitions.
- * This is used to define props in a composable then override
- * default values in an implementing component.
- *
- * @example Simplified signature
- * (props: Props) => (defaults?: Record<keyof props, any>) => Props
- *
- * @example Usage
- * const makeProps = propsFactory({
- * foo: String,
- * })
- *
- * defineComponent({
- * props: {
- * ...makeProps({
- * foo: 'a',
- * }),
- * },
- * setup (props) {
- * // would be "string | undefined", now "string" because a default has been provided
- * props.foo
- * },
- * }
- */
- function propsFactory(props, source) {
- return defaults => {
- return Object.keys(props).reduce((obj, prop) => {
- const isObjectDefinition = typeof props[prop] === 'object' && props[prop] != null && !Array.isArray(props[prop]);
- const definition = isObjectDefinition ? props[prop] : {
- type: props[prop]
- };
- if (defaults && prop in defaults) {
- obj[prop] = {
- ...definition,
- default: defaults[prop]
- };
- } else {
- obj[prop] = definition;
- }
- if (source && !obj[prop].source) {
- obj[prop].source = source;
- }
- return obj;
- }, {});
- };
- }
- // Utilities
- // Types
- // Composables
- const makeComponentProps = propsFactory({
- class: [String, Array],
- style: {
- type: [String, Array, Object],
- default: null
- }
- }, 'component');
- const IN_BROWSER = typeof window !== 'undefined';
- const SUPPORTS_INTERSECTION = IN_BROWSER && 'IntersectionObserver' in window;
- const SUPPORTS_TOUCH = IN_BROWSER && ('ontouchstart' in window || window.navigator.maxTouchPoints > 0);
- function _classPrivateFieldInitSpec(obj, privateMap, value) { _checkPrivateRedeclaration(obj, privateMap); privateMap.set(obj, value); }
- function _checkPrivateRedeclaration(obj, privateCollection) { if (privateCollection.has(obj)) { throw new TypeError("Cannot initialize the same private elements twice on an object"); } }
- function _classPrivateFieldSet(receiver, privateMap, value) { var descriptor = _classExtractFieldDescriptor(receiver, privateMap, "set"); _classApplyDescriptorSet(receiver, descriptor, value); return value; }
- function _classApplyDescriptorSet(receiver, descriptor, value) { if (descriptor.set) { descriptor.set.call(receiver, value); } else { if (!descriptor.writable) { throw new TypeError("attempted to set read only private field"); } descriptor.value = value; } }
- function _classPrivateFieldGet(receiver, privateMap) { var descriptor = _classExtractFieldDescriptor(receiver, privateMap, "get"); return _classApplyDescriptorGet(receiver, descriptor); }
- function _classExtractFieldDescriptor(receiver, privateMap, action) { if (!privateMap.has(receiver)) { throw new TypeError("attempted to " + action + " private field on non-instance"); } return privateMap.get(receiver); }
- function _classApplyDescriptorGet(receiver, descriptor) { if (descriptor.get) { return descriptor.get.call(receiver); } return descriptor.value; }
- // Types
- function getNestedValue(obj, path, fallback) {
- const last = path.length - 1;
- if (last < 0) return obj === undefined ? fallback : obj;
- for (let i = 0; i < last; i++) {
- if (obj == null) {
- return fallback;
- }
- obj = obj[path[i]];
- }
- if (obj == null) return fallback;
- return obj[path[last]] === undefined ? fallback : obj[path[last]];
- }
- function deepEqual(a, b) {
- if (a === b) return true;
- if (a instanceof Date && b instanceof Date && a.getTime() !== b.getTime()) {
- // If the values are Date, compare them as timestamps
- return false;
- }
- if (a !== Object(a) || b !== Object(b)) {
- // If the values aren't objects, they were already checked for equality
- return false;
- }
- const props = Object.keys(a);
- if (props.length !== Object.keys(b).length) {
- // Different number of props, don't bother to check
- return false;
- }
- return props.every(p => deepEqual(a[p], b[p]));
- }
- function getObjectValueByPath(obj, path, fallback) {
- // credit: http://stackoverflow.com/questions/6491463/accessing-nested-javascript-objects-with-string-key#comment55278413_6491621
- if (obj == null || !path || typeof path !== 'string') return fallback;
- if (obj[path] !== undefined) return obj[path];
- path = path.replace(/\[(\w+)\]/g, '.$1'); // convert indexes to properties
- path = path.replace(/^\./, ''); // strip a leading dot
- return getNestedValue(obj, path.split('.'), fallback);
- }
- function getPropertyFromItem(item, property, fallback) {
- if (property == null) return item === undefined ? fallback : item;
- if (item !== Object(item)) {
- if (typeof property !== 'function') return fallback;
- const value = property(item, fallback);
- return typeof value === 'undefined' ? fallback : value;
- }
- if (typeof property === 'string') return getObjectValueByPath(item, property, fallback);
- if (Array.isArray(property)) return getNestedValue(item, property, fallback);
- if (typeof property !== 'function') return fallback;
- const value = property(item, fallback);
- return typeof value === 'undefined' ? fallback : value;
- }
- function createRange(length) {
- let start = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 0;
- return Array.from({
- length
- }, (v, k) => start + k);
- }
- function convertToUnit(str) {
- let unit = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 'px';
- if (str == null || str === '') {
- return undefined;
- } else if (isNaN(+str)) {
- return String(str);
- } else if (!isFinite(+str)) {
- return undefined;
- } else {
- return `${Number(str)}${unit}`;
- }
- }
- function isObject(obj) {
- return obj !== null && typeof obj === 'object' && !Array.isArray(obj);
- }
- function refElement(obj) {
- return obj && '$el' in obj ? obj.$el : obj;
- }
- // KeyboardEvent.keyCode aliases
- const keyCodes = Object.freeze({
- enter: 13,
- tab: 9,
- delete: 46,
- esc: 27,
- space: 32,
- up: 38,
- down: 40,
- left: 37,
- right: 39,
- end: 35,
- home: 36,
- del: 46,
- backspace: 8,
- insert: 45,
- pageup: 33,
- pagedown: 34,
- shift: 16
- });
- const keyValues = Object.freeze({
- enter: 'Enter',
- tab: 'Tab',
- delete: 'Delete',
- esc: 'Escape',
- space: 'Space',
- up: 'ArrowUp',
- down: 'ArrowDown',
- left: 'ArrowLeft',
- right: 'ArrowRight',
- end: 'End',
- home: 'Home',
- del: 'Delete',
- backspace: 'Backspace',
- insert: 'Insert',
- pageup: 'PageUp',
- pagedown: 'PageDown',
- shift: 'Shift'
- });
- function keys(o) {
- return Object.keys(o);
- }
- function has(obj, key) {
- return key.every(k => obj.hasOwnProperty(k));
- }
- function pick(obj, paths, exclude) {
- const found = Object.create(null);
- const rest = Object.create(null);
- for (const key in obj) {
- if (paths.some(path => path instanceof RegExp ? path.test(key) : path === key) && !exclude?.some(path => path === key)) {
- found[key] = obj[key];
- } else {
- rest[key] = obj[key];
- }
- }
- return [found, rest];
- }
- function omit(obj, exclude) {
- const clone = {
- ...obj
- };
- exclude.forEach(prop => delete clone[prop]);
- return clone;
- }
- function only(obj, include) {
- const clone = {};
- include.forEach(prop => clone[prop] = obj[prop]);
- return clone;
- }
- /**
- * Filter attributes that should be applied to
- * the root element of a an input component. Remaining
- * attributes should be passed to the <input> element inside.
- */
- function filterInputAttrs(attrs) {
- return pick(attrs, ['class', 'style', 'id', /^data-/]);
- }
- function wrapInArray(v) {
- return v == null ? [] : Array.isArray(v) ? v : [v];
- }
- function clamp(value) {
- let min = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 0;
- let max = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : 1;
- return Math.max(min, Math.min(max, value));
- }
- function getDecimals(value) {
- const trimmedStr = value.toString().trim();
- return trimmedStr.includes('.') ? trimmedStr.length - trimmedStr.indexOf('.') - 1 : 0;
- }
- function padEnd(str, length) {
- let char = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : '0';
- return str + char.repeat(Math.max(0, length - str.length));
- }
- function chunk(str) {
- let size = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 1;
- const chunked = [];
- let index = 0;
- while (index < str.length) {
- chunked.push(str.substr(index, size));
- index += size;
- }
- return chunked;
- }
- function humanReadableFileSize(bytes) {
- let base = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 1000;
- if (bytes < base) {
- return `${bytes} B`;
- }
- const prefix = base === 1024 ? ['Ki', 'Mi', 'Gi'] : ['k', 'M', 'G'];
- let unit = -1;
- while (Math.abs(bytes) >= base && unit < prefix.length - 1) {
- bytes /= base;
- ++unit;
- }
- return `${bytes.toFixed(1)} ${prefix[unit]}B`;
- }
- function mergeDeep() {
- let source = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
- let target = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
- let arrayFn = arguments.length > 2 ? arguments[2] : undefined;
- const out = {};
- for (const key in source) {
- out[key] = source[key];
- }
- for (const key in target) {
- const sourceProperty = source[key];
- const targetProperty = target[key];
- // Only continue deep merging if
- // both properties are objects
- if (isObject(sourceProperty) && isObject(targetProperty)) {
- out[key] = mergeDeep(sourceProperty, targetProperty, arrayFn);
- continue;
- }
- if (Array.isArray(sourceProperty) && Array.isArray(targetProperty) && arrayFn) {
- out[key] = arrayFn(sourceProperty, targetProperty);
- continue;
- }
- out[key] = targetProperty;
- }
- return out;
- }
- function flattenFragments(nodes) {
- return nodes.map(node => {
- if (node.type === Fragment) {
- return flattenFragments(node.children);
- } else {
- return node;
- }
- }).flat();
- }
- function toKebabCase() {
- let str = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : '';
- if (toKebabCase.cache.has(str)) return toKebabCase.cache.get(str);
- const kebab = str.replace(/[^a-z]/gi, '-').replace(/\B([A-Z])/g, '-$1').toLowerCase();
- toKebabCase.cache.set(str, kebab);
- return kebab;
- }
- toKebabCase.cache = new Map();
- function findChildrenWithProvide(key, vnode) {
- if (!vnode || typeof vnode !== 'object') return [];
- if (Array.isArray(vnode)) {
- return vnode.map(child => findChildrenWithProvide(key, child)).flat(1);
- } else if (Array.isArray(vnode.children)) {
- return vnode.children.map(child => findChildrenWithProvide(key, child)).flat(1);
- } else if (vnode.component) {
- if (Object.getOwnPropertySymbols(vnode.component.provides).includes(key)) {
- return [vnode.component];
- } else if (vnode.component.subTree) {
- return findChildrenWithProvide(key, vnode.component.subTree).flat(1);
- }
- }
- return [];
- }
- var _arr = /*#__PURE__*/new WeakMap();
- var _pointer = /*#__PURE__*/new WeakMap();
- class CircularBuffer {
- constructor(size) {
- _classPrivateFieldInitSpec(this, _arr, {
- writable: true,
- value: []
- });
- _classPrivateFieldInitSpec(this, _pointer, {
- writable: true,
- value: 0
- });
- this.size = size;
- }
- push(val) {
- _classPrivateFieldGet(this, _arr)[_classPrivateFieldGet(this, _pointer)] = val;
- _classPrivateFieldSet(this, _pointer, (_classPrivateFieldGet(this, _pointer) + 1) % this.size);
- }
- values() {
- return _classPrivateFieldGet(this, _arr).slice(_classPrivateFieldGet(this, _pointer)).concat(_classPrivateFieldGet(this, _arr).slice(0, _classPrivateFieldGet(this, _pointer)));
- }
- }
- function getEventCoordinates(e) {
- if ('touches' in e) {
- return {
- clientX: e.touches[0].clientX,
- clientY: e.touches[0].clientY
- };
- }
- return {
- clientX: e.clientX,
- clientY: e.clientY
- };
- }
- // Only allow a single return type
- function destructComputed(getter) {
- const refs = reactive({});
- const base = computed(getter);
- watchEffect(() => {
- for (const key in base.value) {
- refs[key] = base.value[key];
- }
- }, {
- flush: 'sync'
- });
- return toRefs(refs);
- }
- /** Array.includes but value can be any type */
- function includes(arr, val) {
- return arr.includes(val);
- }
- const onRE = /^on[^a-z]/;
- const isOn = key => onRE.test(key);
- function eventName(propName) {
- return propName[2].toLowerCase() + propName.slice(3);
- }
- const EventProp = () => [Function, Array];
- function hasEvent(props, name) {
- name = 'on' + capitalize(name);
- return !!(props[name] || props[`${name}Once`] || props[`${name}Capture`] || props[`${name}OnceCapture`] || props[`${name}CaptureOnce`]);
- }
- function callEvent(handler) {
- for (var _len2 = arguments.length, args = new Array(_len2 > 1 ? _len2 - 1 : 0), _key2 = 1; _key2 < _len2; _key2++) {
- args[_key2 - 1] = arguments[_key2];
- }
- if (Array.isArray(handler)) {
- for (const h of handler) {
- h(...args);
- }
- } else if (typeof handler === 'function') {
- handler(...args);
- }
- }
- function focusableChildren(el) {
- let filterByTabIndex = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : true;
- const targets = ['button', '[href]', 'input:not([type="hidden"])', 'select', 'textarea', '[tabindex]'].map(s => `${s}${filterByTabIndex ? ':not([tabindex="-1"])' : ''}:not([disabled])`).join(', ');
- return [...el.querySelectorAll(targets)];
- }
- function getNextElement(elements, location, condition) {
- let _el;
- let idx = elements.indexOf(document.activeElement);
- const inc = location === 'next' ? 1 : -1;
- do {
- idx += inc;
- _el = elements[idx];
- } while ((!_el || _el.offsetParent == null || !(condition?.(_el) ?? true)) && idx < elements.length && idx >= 0);
- return _el;
- }
- function focusChild(el, location) {
- const focusable = focusableChildren(el);
- if (!location) {
- if (el === document.activeElement || !el.contains(document.activeElement)) {
- focusable[0]?.focus();
- }
- } else if (location === 'first') {
- focusable[0]?.focus();
- } else if (location === 'last') {
- focusable.at(-1)?.focus();
- } else if (typeof location === 'number') {
- focusable[location]?.focus();
- } else {
- const _el = getNextElement(focusable, location);
- if (_el) _el.focus();else focusChild(el, location === 'next' ? 'first' : 'last');
- }
- }
- function isEmpty(val) {
- return val === null || val === undefined || typeof val === 'string' && val.trim() === '';
- }
- function noop() {}
- /** Returns null if the selector is not supported or we can't check */
- function matchesSelector(el, selector) {
- const supportsSelector = IN_BROWSER && typeof CSS !== 'undefined' && typeof CSS.supports !== 'undefined' && CSS.supports(`selector(${selector})`);
- if (!supportsSelector) return null;
- try {
- return !!el && el.matches(selector);
- } catch (err) {
- return null;
- }
- }
- // Utilities
- const block = ['top', 'bottom'];
- const inline = ['start', 'end', 'left', 'right'];
- /** Parse a raw anchor string into an object */
- function parseAnchor(anchor, isRtl) {
- let [side, align] = anchor.split(' ');
- if (!align) {
- align = includes(block, side) ? 'start' : includes(inline, side) ? 'top' : 'center';
- }
- return {
- side: toPhysical(side, isRtl),
- align: toPhysical(align, isRtl)
- };
- }
- function toPhysical(str, isRtl) {
- if (str === 'start') return isRtl ? 'right' : 'left';
- if (str === 'end') return isRtl ? 'left' : 'right';
- return str;
- }
- function flipSide(anchor) {
- return {
- side: {
- center: 'center',
- top: 'bottom',
- bottom: 'top',
- left: 'right',
- right: 'left'
- }[anchor.side],
- align: anchor.align
- };
- }
- function flipAlign(anchor) {
- return {
- side: anchor.side,
- align: {
- center: 'center',
- top: 'bottom',
- bottom: 'top',
- left: 'right',
- right: 'left'
- }[anchor.align]
- };
- }
- function flipCorner(anchor) {
- return {
- side: anchor.align,
- align: anchor.side
- };
- }
- function getAxis(anchor) {
- return includes(block, anchor.side) ? 'y' : 'x';
- }
- class Box {
- constructor(_ref) {
- let {
- x,
- y,
- width,
- height
- } = _ref;
- this.x = x;
- this.y = y;
- this.width = width;
- this.height = height;
- }
- get top() {
- return this.y;
- }
- get bottom() {
- return this.y + this.height;
- }
- get left() {
- return this.x;
- }
- get right() {
- return this.x + this.width;
- }
- }
- function getOverflow(a, b) {
- return {
- x: {
- before: Math.max(0, b.left - a.left),
- after: Math.max(0, a.right - b.right)
- },
- y: {
- before: Math.max(0, b.top - a.top),
- after: Math.max(0, a.bottom - b.bottom)
- }
- };
- }
- // Utilities
- /** @see https://stackoverflow.com/a/57876601/2074736 */
- function nullifyTransforms(el) {
- const rect = el.getBoundingClientRect();
- const style = getComputedStyle(el);
- const tx = style.transform;
- if (tx) {
- let ta, sx, sy, dx, dy;
- if (tx.startsWith('matrix3d(')) {
- ta = tx.slice(9, -1).split(/, /);
- sx = +ta[0];
- sy = +ta[5];
- dx = +ta[12];
- dy = +ta[13];
- } else if (tx.startsWith('matrix(')) {
- ta = tx.slice(7, -1).split(/, /);
- sx = +ta[0];
- sy = +ta[3];
- dx = +ta[4];
- dy = +ta[5];
- } else {
- return new Box(rect);
- }
- const to = style.transformOrigin;
- const x = rect.x - dx - (1 - sx) * parseFloat(to);
- const y = rect.y - dy - (1 - sy) * parseFloat(to.slice(to.indexOf(' ') + 1));
- const w = sx ? rect.width / sx : el.offsetWidth + 1;
- const h = sy ? rect.height / sy : el.offsetHeight + 1;
- return new Box({
- x,
- y,
- width: w,
- height: h
- });
- } else {
- return new Box(rect);
- }
- }
- function animate(el, keyframes, options) {
- if (typeof el.animate === 'undefined') return {
- finished: Promise.resolve()
- };
- let animation;
- try {
- animation = el.animate(keyframes, options);
- } catch (err) {
- return {
- finished: Promise.resolve()
- };
- }
- if (typeof animation.finished === 'undefined') {
- animation.finished = new Promise(resolve => {
- animation.onfinish = () => {
- resolve(animation);
- };
- });
- }
- return animation;
- }
- // Utilities
- const handlers = new WeakMap();
- function bindProps(el, props) {
- Object.keys(props).forEach(k => {
- if (isOn(k)) {
- const name = eventName(k);
- const handler = handlers.get(el);
- if (props[k] == null) {
- handler?.forEach(v => {
- const [n, fn] = v;
- if (n === name) {
- el.removeEventListener(name, fn);
- handler.delete(v);
- }
- });
- } else if (!handler || ![...handler]?.some(v => v[0] === name && v[1] === props[k])) {
- el.addEventListener(name, props[k]);
- const _handler = handler || new Set();
- _handler.add([name, props[k]]);
- if (!handlers.has(el)) handlers.set(el, _handler);
- }
- } else {
- if (props[k] == null) {
- el.removeAttribute(k);
- } else {
- el.setAttribute(k, props[k]);
- }
- }
- });
- }
- function unbindProps(el, props) {
- Object.keys(props).forEach(k => {
- if (isOn(k)) {
- const name = eventName(k);
- const handler = handlers.get(el);
- handler?.forEach(v => {
- const [n, fn] = v;
- if (n === name) {
- el.removeEventListener(name, fn);
- handler.delete(v);
- }
- });
- } else {
- el.removeAttribute(k);
- }
- });
- }
- /* eslint-disable no-console */
- function consoleWarn(message) {
- warn(`Vuetify: ${message}`);
- }
- function consoleError(message) {
- warn(`Vuetify error: ${message}`);
- }
- function deprecate(original, replacement) {
- replacement = Array.isArray(replacement) ? replacement.slice(0, -1).map(s => `'${s}'`).join(', ') + ` or '${replacement.at(-1)}'` : `'${replacement}'`;
- warn(`[Vuetify UPGRADE] '${original}' is deprecated, use ${replacement} instead.`);
- }
- // Types
- const delta = 0.20689655172413793; // 6÷29
- const cielabForwardTransform = t => t > delta ** 3 ? Math.cbrt(t) : t / (3 * delta ** 2) + 4 / 29;
- const cielabReverseTransform = t => t > delta ? t ** 3 : 3 * delta ** 2 * (t - 4 / 29);
- function fromXYZ$1(xyz) {
- const transform = cielabForwardTransform;
- const transformedY = transform(xyz[1]);
- return [116 * transformedY - 16, 500 * (transform(xyz[0] / 0.95047) - transformedY), 200 * (transformedY - transform(xyz[2] / 1.08883))];
- }
- function toXYZ$1(lab) {
- const transform = cielabReverseTransform;
- const Ln = (lab[0] + 16) / 116;
- return [transform(Ln + lab[1] / 500) * 0.95047, transform(Ln), transform(Ln - lab[2] / 200) * 1.08883];
- }
- // Utilities
- // Types
- // For converting XYZ to sRGB
- const srgbForwardMatrix = [[3.2406, -1.5372, -0.4986], [-0.9689, 1.8758, 0.0415], [0.0557, -0.2040, 1.0570]];
- // Forward gamma adjust
- const srgbForwardTransform = C => C <= 0.0031308 ? C * 12.92 : 1.055 * C ** (1 / 2.4) - 0.055;
- // For converting sRGB to XYZ
- const srgbReverseMatrix = [[0.4124, 0.3576, 0.1805], [0.2126, 0.7152, 0.0722], [0.0193, 0.1192, 0.9505]];
- // Reverse gamma adjust
- const srgbReverseTransform = C => C <= 0.04045 ? C / 12.92 : ((C + 0.055) / 1.055) ** 2.4;
- function fromXYZ(xyz) {
- const rgb = Array(3);
- const transform = srgbForwardTransform;
- const matrix = srgbForwardMatrix;
- // Matrix transform, then gamma adjustment
- for (let i = 0; i < 3; ++i) {
- // Rescale back to [0, 255]
- rgb[i] = Math.round(clamp(transform(matrix[i][0] * xyz[0] + matrix[i][1] * xyz[1] + matrix[i][2] * xyz[2])) * 255);
- }
- return {
- r: rgb[0],
- g: rgb[1],
- b: rgb[2]
- };
- }
- function toXYZ(_ref) {
- let {
- r,
- g,
- b
- } = _ref;
- const xyz = [0, 0, 0];
- const transform = srgbReverseTransform;
- const matrix = srgbReverseMatrix;
- // Rescale from [0, 255] to [0, 1] then adjust sRGB gamma to linear RGB
- r = transform(r / 255);
- g = transform(g / 255);
- b = transform(b / 255);
- // Matrix color space transform
- for (let i = 0; i < 3; ++i) {
- xyz[i] = matrix[i][0] * r + matrix[i][1] * g + matrix[i][2] * b;
- }
- return xyz;
- }
- // Utilities
- // Types
- function isCssColor(color) {
- return !!color && /^(#|var\(--|(rgb|hsl)a?\()/.test(color);
- }
- const cssColorRe = /^(?<fn>(?:rgb|hsl)a?)\((?<values>.+)\)/;
- const mappers = {
- rgb: (r, g, b, a) => ({
- r,
- g,
- b,
- a
- }),
- rgba: (r, g, b, a) => ({
- r,
- g,
- b,
- a
- }),
- hsl: (h, s, l, a) => HSLtoRGB({
- h,
- s,
- l,
- a
- }),
- hsla: (h, s, l, a) => HSLtoRGB({
- h,
- s,
- l,
- a
- }),
- hsv: (h, s, v, a) => HSVtoRGB({
- h,
- s,
- v,
- a
- }),
- hsva: (h, s, v, a) => HSVtoRGB({
- h,
- s,
- v,
- a
- })
- };
- function parseColor(color) {
- if (typeof color === 'number') {
- if (isNaN(color) || color < 0 || color > 0xFFFFFF) {
- // int can't have opacity
- consoleWarn(`'${color}' is not a valid hex color`);
- }
- return {
- r: (color & 0xFF0000) >> 16,
- g: (color & 0xFF00) >> 8,
- b: color & 0xFF
- };
- } else if (typeof color === 'string' && cssColorRe.test(color)) {
- const {
- groups
- } = color.match(cssColorRe);
- const {
- fn,
- values
- } = groups;
- const realValues = values.split(/,\s*/).map(v => {
- if (v.endsWith('%') && ['hsl', 'hsla', 'hsv', 'hsva'].includes(fn)) {
- return parseFloat(v) / 100;
- } else {
- return parseFloat(v);
- }
- });
- return mappers[fn](...realValues);
- } else if (typeof color === 'string') {
- let hex = color.startsWith('#') ? color.slice(1) : color;
- if ([3, 4].includes(hex.length)) {
- hex = hex.split('').map(char => char + char).join('');
- } else if (![6, 8].includes(hex.length)) {
- consoleWarn(`'${color}' is not a valid hex(a) color`);
- }
- const int = parseInt(hex, 16);
- if (isNaN(int) || int < 0 || int > 0xFFFFFFFF) {
- consoleWarn(`'${color}' is not a valid hex(a) color`);
- }
- return HexToRGB(hex);
- } else if (typeof color === 'object') {
- if (has(color, ['r', 'g', 'b'])) {
- return color;
- } else if (has(color, ['h', 's', 'l'])) {
- return HSVtoRGB(HSLtoHSV(color));
- } else if (has(color, ['h', 's', 'v'])) {
- return HSVtoRGB(color);
- }
- }
- throw new TypeError(`Invalid color: ${color == null ? color : String(color) || color.constructor.name}\nExpected #hex, #hexa, rgb(), rgba(), hsl(), hsla(), object or number`);
- }
- /** Converts HSVA to RGBA. Based on formula from https://en.wikipedia.org/wiki/HSL_and_HSV */
- function HSVtoRGB(hsva) {
- const {
- h,
- s,
- v,
- a
- } = hsva;
- const f = n => {
- const k = (n + h / 60) % 6;
- return v - v * s * Math.max(Math.min(k, 4 - k, 1), 0);
- };
- const rgb = [f(5), f(3), f(1)].map(v => Math.round(v * 255));
- return {
- r: rgb[0],
- g: rgb[1],
- b: rgb[2],
- a
- };
- }
- function HSLtoRGB(hsla) {
- return HSVtoRGB(HSLtoHSV(hsla));
- }
- /** Converts RGBA to HSVA. Based on formula from https://en.wikipedia.org/wiki/HSL_and_HSV */
- function RGBtoHSV(rgba) {
- if (!rgba) return {
- h: 0,
- s: 1,
- v: 1,
- a: 1
- };
- const r = rgba.r / 255;
- const g = rgba.g / 255;
- const b = rgba.b / 255;
- const max = Math.max(r, g, b);
- const min = Math.min(r, g, b);
- let h = 0;
- if (max !== min) {
- if (max === r) {
- h = 60 * (0 + (g - b) / (max - min));
- } else if (max === g) {
- h = 60 * (2 + (b - r) / (max - min));
- } else if (max === b) {
- h = 60 * (4 + (r - g) / (max - min));
- }
- }
- if (h < 0) h = h + 360;
- const s = max === 0 ? 0 : (max - min) / max;
- const hsv = [h, s, max];
- return {
- h: hsv[0],
- s: hsv[1],
- v: hsv[2],
- a: rgba.a
- };
- }
- function HSVtoHSL(hsva) {
- const {
- h,
- s,
- v,
- a
- } = hsva;
- const l = v - v * s / 2;
- const sprime = l === 1 || l === 0 ? 0 : (v - l) / Math.min(l, 1 - l);
- return {
- h,
- s: sprime,
- l,
- a
- };
- }
- function HSLtoHSV(hsl) {
- const {
- h,
- s,
- l,
- a
- } = hsl;
- const v = l + s * Math.min(l, 1 - l);
- const sprime = v === 0 ? 0 : 2 - 2 * l / v;
- return {
- h,
- s: sprime,
- v,
- a
- };
- }
- function RGBtoCSS(_ref) {
- let {
- r,
- g,
- b,
- a
- } = _ref;
- return a === undefined ? `rgb(${r}, ${g}, ${b})` : `rgba(${r}, ${g}, ${b}, ${a})`;
- }
- function HSVtoCSS(hsva) {
- return RGBtoCSS(HSVtoRGB(hsva));
- }
- function toHex(v) {
- const h = Math.round(v).toString(16);
- return ('00'.substr(0, 2 - h.length) + h).toUpperCase();
- }
- function RGBtoHex(_ref2) {
- let {
- r,
- g,
- b,
- a
- } = _ref2;
- return `#${[toHex(r), toHex(g), toHex(b), a !== undefined ? toHex(Math.round(a * 255)) : ''].join('')}`;
- }
- function HexToRGB(hex) {
- hex = parseHex(hex);
- let [r, g, b, a] = chunk(hex, 2).map(c => parseInt(c, 16));
- a = a === undefined ? a : a / 255;
- return {
- r,
- g,
- b,
- a
- };
- }
- function HexToHSV(hex) {
- const rgb = HexToRGB(hex);
- return RGBtoHSV(rgb);
- }
- function HSVtoHex(hsva) {
- return RGBtoHex(HSVtoRGB(hsva));
- }
- function parseHex(hex) {
- if (hex.startsWith('#')) {
- hex = hex.slice(1);
- }
- hex = hex.replace(/([^0-9a-f])/gi, 'F');
- if (hex.length === 3 || hex.length === 4) {
- hex = hex.split('').map(x => x + x).join('');
- }
- if (hex.length !== 6) {
- hex = padEnd(padEnd(hex, 6), 8, 'F');
- }
- return hex;
- }
- function lighten(value, amount) {
- const lab = fromXYZ$1(toXYZ(value));
- lab[0] = lab[0] + amount * 10;
- return fromXYZ(toXYZ$1(lab));
- }
- function darken(value, amount) {
- const lab = fromXYZ$1(toXYZ(value));
- lab[0] = lab[0] - amount * 10;
- return fromXYZ(toXYZ$1(lab));
- }
- /**
- * Calculate the relative luminance of a given color
- * @see https://www.w3.org/TR/WCAG20/#relativeluminancedef
- */
- function getLuma(color) {
- const rgb = parseColor(color);
- return toXYZ(rgb)[1];
- }
- /**
- * Returns the contrast ratio (1-21) between two colors.
- * @see https://www.w3.org/TR/WCAG20/#contrast-ratiodef
- */
- function getContrast(first, second) {
- const l1 = getLuma(first);
- const l2 = getLuma(second);
- const light = Math.max(l1, l2);
- const dark = Math.min(l1, l2);
- return (light + 0.05) / (dark + 0.05);
- }
- // Utilities
- // Types
- function useToggleScope(source, fn) {
- let scope;
- function start() {
- scope = effectScope();
- scope.run(() => fn.length ? fn(() => {
- scope?.stop();
- start();
- }) : fn());
- }
- watch(source, active => {
- if (active && !scope) {
- start();
- } else if (!active) {
- scope?.stop();
- scope = undefined;
- }
- }, {
- immediate: true
- });
- onScopeDispose(() => {
- scope?.stop();
- });
- }
- // Composables
- // Types
- const DefaultsSymbol = Symbol.for('vuetify:defaults');
- function createDefaults(options) {
- return ref(options);
- }
- function injectDefaults() {
- const defaults = inject$1(DefaultsSymbol);
- if (!defaults) throw new Error('[Vuetify] Could not find defaults instance');
- return defaults;
- }
- function provideDefaults(defaults, options) {
- const injectedDefaults = injectDefaults();
- const providedDefaults = ref(defaults);
- const newDefaults = computed(() => {
- const disabled = unref(options?.disabled);
- if (disabled) return injectedDefaults.value;
- const scoped = unref(options?.scoped);
- const reset = unref(options?.reset);
- const root = unref(options?.root);
- let properties = mergeDeep(providedDefaults.value, {
- prev: injectedDefaults.value
- });
- if (scoped) return properties;
- if (reset || root) {
- const len = Number(reset || Infinity);
- for (let i = 0; i <= len; i++) {
- if (!properties || !('prev' in properties)) {
- break;
- }
- properties = properties.prev;
- }
- if (properties && typeof root === 'string' && root in properties) {
- properties = mergeDeep(mergeDeep(properties, {
- prev: properties
- }), properties[root]);
- }
- return properties;
- }
- return properties.prev ? mergeDeep(properties.prev, properties) : properties;
- });
- provide(DefaultsSymbol, newDefaults);
- return newDefaults;
- }
- function propIsDefined(vnode, prop) {
- return typeof vnode.props?.[prop] !== 'undefined' || typeof vnode.props?.[toKebabCase(prop)] !== 'undefined';
- }
- function internalUseDefaults() {
- let props = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
- let name = arguments.length > 1 ? arguments[1] : undefined;
- let defaults = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : injectDefaults();
- const vm = getCurrentInstance('useDefaults');
- name = name ?? vm.type.name ?? vm.type.__name;
- if (!name) {
- throw new Error('[Vuetify] Could not determine component name');
- }
- const componentDefaults = computed(() => defaults.value?.[props._as ?? name]);
- const _props = new Proxy(props, {
- get(target, prop) {
- const propValue = Reflect.get(target, prop);
- if (prop === 'class' || prop === 'style') {
- return [componentDefaults.value?.[prop], propValue].filter(v => v != null);
- } else if (typeof prop === 'string' && !propIsDefined(vm.vnode, prop)) {
- return componentDefaults.value?.[prop] ?? defaults.value?.global?.[prop] ?? propValue;
- }
- return propValue;
- }
- });
- const _subcomponentDefaults = shallowRef();
- watchEffect(() => {
- if (componentDefaults.value) {
- const subComponents = Object.entries(componentDefaults.value).filter(_ref => {
- let [key] = _ref;
- return key.startsWith(key[0].toUpperCase());
- });
- if (subComponents.length) _subcomponentDefaults.value = Object.fromEntries(subComponents);
- }
- });
- function provideSubDefaults() {
- // If subcomponent defaults are provided, override any
- // subcomponents provided by the component's setup function.
- // This uses injectSelf so must be done after the original setup to work.
- useToggleScope(_subcomponentDefaults, () => {
- provideDefaults(mergeDeep(injectSelf(DefaultsSymbol)?.value ?? {}, _subcomponentDefaults.value));
- });
- }
- return {
- props: _props,
- provideSubDefaults
- };
- }
- function useDefaults() {
- let props = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
- let name = arguments.length > 1 ? arguments[1] : undefined;
- const {
- props: _props,
- provideSubDefaults
- } = internalUseDefaults(props, name);
- provideSubDefaults();
- return _props;
- }
- // Composables
- // Types
- // Implementation
- function defineComponent(options) {
- options._setup = options._setup ?? options.setup;
- if (!options.name) {
- consoleWarn('The component is missing an explicit name, unable to generate default prop value');
- return options;
- }
- if (options._setup) {
- options.props = propsFactory(options.props ?? {}, options.name)();
- const propKeys = Object.keys(options.props);
- options.filterProps = function filterProps(props) {
- return pick(props, propKeys, ['class', 'style']);
- };
- options.props._as = String;
- options.setup = function setup(props, ctx) {
- const defaults = injectDefaults();
- // Skip props proxy if defaults are not provided
- if (!defaults.value) return options._setup(props, ctx);
- const {
- props: _props,
- provideSubDefaults
- } = internalUseDefaults(props, props._as ?? options.name, defaults);
- const setupBindings = options._setup(_props, ctx);
- provideSubDefaults();
- return setupBindings;
- };
- }
- return options;
- }
- // Implementation
- function genericComponent() {
- let exposeDefaults = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : true;
- return options => (exposeDefaults ? defineComponent : defineComponent$1)(options);
- }
- function defineFunctionalComponent(props, render) {
- render.props = props;
- return render;
- }
- // Composables
- function createSimpleFunctional(klass) {
- let tag = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 'div';
- let name = arguments.length > 2 ? arguments[2] : undefined;
- return genericComponent()({
- name: name ?? capitalize(camelize(klass.replace(/__/g, '-'))),
- props: {
- tag: {
- type: String,
- default: tag
- },
- ...makeComponentProps()
- },
- setup(props, _ref) {
- let {
- slots
- } = _ref;
- return () => {
- return h(props.tag, {
- class: [klass, props.class],
- style: props.style
- }, slots.default?.());
- };
- }
- });
- }
- /**
- * Returns:
- * - 'null' if the node is not attached to the DOM
- * - the root node (HTMLDocument | ShadowRoot) otherwise
- */
- function attachedRoot(node) {
- /* istanbul ignore next */
- if (typeof node.getRootNode !== 'function') {
- // Shadow DOM not supported (IE11), lets find the root of this node
- while (node.parentNode) node = node.parentNode;
- // The root parent is the document if the node is attached to the DOM
- if (node !== document) return null;
- return document;
- }
- const root = node.getRootNode();
- // The composed root node is the document if the node is attached to the DOM
- if (root !== document && root.getRootNode({
- composed: true
- }) !== document) return null;
- return root;
- }
- const standardEasing = 'cubic-bezier(0.4, 0, 0.2, 1)';
- const deceleratedEasing = 'cubic-bezier(0.0, 0, 0.2, 1)'; // Entering
- const acceleratedEasing = 'cubic-bezier(0.4, 0, 1, 1)'; // Leaving
- // Utilities
- // Types
- function getCurrentInstance(name, message) {
- const vm = getCurrentInstance$1();
- if (!vm) {
- throw new Error(`[Vuetify] ${name} ${message || 'must be called from inside a setup function'}`);
- }
- return vm;
- }
- function getCurrentInstanceName() {
- let name = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 'composables';
- const vm = getCurrentInstance(name).type;
- return toKebabCase(vm?.aliasName || vm?.name);
- }
- let _uid = 0;
- let _map = new WeakMap();
- function getUid() {
- const vm = getCurrentInstance('getUid');
- if (_map.has(vm)) return _map.get(vm);else {
- const uid = _uid++;
- _map.set(vm, uid);
- return uid;
- }
- }
- getUid.reset = () => {
- _uid = 0;
- _map = new WeakMap();
- };
- function getScrollParent(el) {
- let includeHidden = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : false;
- while (el) {
- if (includeHidden ? isPotentiallyScrollable(el) : hasScrollbar(el)) return el;
- el = el.parentElement;
- }
- return document.scrollingElement;
- }
- function getScrollParents(el, stopAt) {
- const elements = [];
- if (stopAt && el && !stopAt.contains(el)) return elements;
- while (el) {
- if (hasScrollbar(el)) elements.push(el);
- if (el === stopAt) break;
- el = el.parentElement;
- }
- return elements;
- }
- function hasScrollbar(el) {
- if (!el || el.nodeType !== Node.ELEMENT_NODE) return false;
- const style = window.getComputedStyle(el);
- return style.overflowY === 'scroll' || style.overflowY === 'auto' && el.scrollHeight > el.clientHeight;
- }
- function isPotentiallyScrollable(el) {
- if (!el || el.nodeType !== Node.ELEMENT_NODE) return false;
- const style = window.getComputedStyle(el);
- return ['scroll', 'auto'].includes(style.overflowY);
- }
- // Utilities
- // Types
- function injectSelf(key) {
- const {
- provides
- } = getCurrentInstance('injectSelf');
- if (provides && key in provides) {
- // TS doesn't allow symbol as index type
- return provides[key];
- }
- return undefined;
- }
- function isFixedPosition(el) {
- while (el) {
- if (window.getComputedStyle(el).position === 'fixed') {
- return true;
- }
- el = el.offsetParent;
- }
- return false;
- }
- // Utilities
- // Types
- function useRender(render) {
- const vm = getCurrentInstance('useRender');
- vm.render = render;
- }
- // Utilities
- // Types
- function useResizeObserver(callback) {
- let box = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 'content';
- const resizeRef = ref();
- const contentRect = ref();
- if (IN_BROWSER) {
- const observer = new ResizeObserver(entries => {
- callback?.(entries, observer);
- if (!entries.length) return;
- if (box === 'content') {
- contentRect.value = entries[0].contentRect;
- } else {
- contentRect.value = entries[0].target.getBoundingClientRect();
- }
- });
- onBeforeUnmount(() => {
- observer.disconnect();
- });
- watch(resizeRef, (newValue, oldValue) => {
- if (oldValue) {
- observer.unobserve(refElement(oldValue));
- contentRect.value = undefined;
- }
- if (newValue) observer.observe(refElement(newValue));
- }, {
- flush: 'post'
- });
- }
- return {
- resizeRef,
- contentRect: readonly(contentRect)
- };
- }
- // Composables
- // Types
- const VuetifyLayoutKey = Symbol.for('vuetify:layout');
- const VuetifyLayoutItemKey = Symbol.for('vuetify:layout-item');
- const ROOT_ZINDEX = 1000;
- const makeLayoutProps = propsFactory({
- overlaps: {
- type: Array,
- default: () => []
- },
- fullHeight: Boolean
- }, 'layout');
- // Composables
- const makeLayoutItemProps = propsFactory({
- name: {
- type: String
- },
- order: {
- type: [Number, String],
- default: 0
- },
- absolute: Boolean
- }, 'layout-item');
- function useLayout() {
- const layout = inject$1(VuetifyLayoutKey);
- if (!layout) throw new Error('[Vuetify] Could not find injected layout');
- return {
- getLayoutItem: layout.getLayoutItem,
- mainRect: layout.mainRect,
- mainStyles: layout.mainStyles
- };
- }
- function useLayoutItem(options) {
- const layout = inject$1(VuetifyLayoutKey);
- if (!layout) throw new Error('[Vuetify] Could not find injected layout');
- const id = options.id ?? `layout-item-${getUid()}`;
- const vm = getCurrentInstance('useLayoutItem');
- provide(VuetifyLayoutItemKey, {
- id
- });
- const isKeptAlive = shallowRef(false);
- onDeactivated(() => isKeptAlive.value = true);
- onActivated(() => isKeptAlive.value = false);
- const {
- layoutItemStyles,
- layoutItemScrimStyles
- } = layout.register(vm, {
- ...options,
- active: computed(() => isKeptAlive.value ? false : options.active.value),
- id
- });
- onBeforeUnmount(() => layout.unregister(id));
- return {
- layoutItemStyles,
- layoutRect: layout.layoutRect,
- layoutItemScrimStyles
- };
- }
- const generateLayers = (layout, positions, layoutSizes, activeItems) => {
- let previousLayer = {
- top: 0,
- left: 0,
- right: 0,
- bottom: 0
- };
- const layers = [{
- id: '',
- layer: {
- ...previousLayer
- }
- }];
- for (const id of layout) {
- const position = positions.get(id);
- const amount = layoutSizes.get(id);
- const active = activeItems.get(id);
- if (!position || !amount || !active) continue;
- const layer = {
- ...previousLayer,
- [position.value]: parseInt(previousLayer[position.value], 10) + (active.value ? parseInt(amount.value, 10) : 0)
- };
- layers.push({
- id,
- layer
- });
- previousLayer = layer;
- }
- return layers;
- };
- function createLayout(props) {
- const parentLayout = inject$1(VuetifyLayoutKey, null);
- const rootZIndex = computed(() => parentLayout ? parentLayout.rootZIndex.value - 100 : ROOT_ZINDEX);
- const registered = ref([]);
- const positions = reactive(new Map());
- const layoutSizes = reactive(new Map());
- const priorities = reactive(new Map());
- const activeItems = reactive(new Map());
- const disabledTransitions = reactive(new Map());
- const {
- resizeRef,
- contentRect: layoutRect
- } = useResizeObserver();
- const computedOverlaps = computed(() => {
- const map = new Map();
- const overlaps = props.overlaps ?? [];
- for (const overlap of overlaps.filter(item => item.includes(':'))) {
- const [top, bottom] = overlap.split(':');
- if (!registered.value.includes(top) || !registered.value.includes(bottom)) continue;
- const topPosition = positions.get(top);
- const bottomPosition = positions.get(bottom);
- const topAmount = layoutSizes.get(top);
- const bottomAmount = layoutSizes.get(bottom);
- if (!topPosition || !bottomPosition || !topAmount || !bottomAmount) continue;
- map.set(bottom, {
- position: topPosition.value,
- amount: parseInt(topAmount.value, 10)
- });
- map.set(top, {
- position: bottomPosition.value,
- amount: -parseInt(bottomAmount.value, 10)
- });
- }
- return map;
- });
- const layers = computed(() => {
- const uniquePriorities = [...new Set([...priorities.values()].map(p => p.value))].sort((a, b) => a - b);
- const layout = [];
- for (const p of uniquePriorities) {
- const items = registered.value.filter(id => priorities.get(id)?.value === p);
- layout.push(...items);
- }
- return generateLayers(layout, positions, layoutSizes, activeItems);
- });
- const transitionsEnabled = computed(() => {
- return !Array.from(disabledTransitions.values()).some(ref => ref.value);
- });
- const mainRect = computed(() => {
- return layers.value[layers.value.length - 1].layer;
- });
- const mainStyles = computed(() => {
- return {
- '--v-layout-left': convertToUnit(mainRect.value.left),
- '--v-layout-right': convertToUnit(mainRect.value.right),
- '--v-layout-top': convertToUnit(mainRect.value.top),
- '--v-layout-bottom': convertToUnit(mainRect.value.bottom),
- ...(transitionsEnabled.value ? undefined : {
- transition: 'none'
- })
- };
- });
- const items = computed(() => {
- return layers.value.slice(1).map((_ref, index) => {
- let {
- id
- } = _ref;
- const {
- layer
- } = layers.value[index];
- const size = layoutSizes.get(id);
- const position = positions.get(id);
- return {
- id,
- ...layer,
- size: Number(size.value),
- position: position.value
- };
- });
- });
- const getLayoutItem = id => {
- return items.value.find(item => item.id === id);
- };
- const rootVm = getCurrentInstance('createLayout');
- const isMounted = shallowRef(false);
- onMounted(() => {
- isMounted.value = true;
- });
- provide(VuetifyLayoutKey, {
- register: (vm, _ref2) => {
- let {
- id,
- order,
- position,
- layoutSize,
- elementSize,
- active,
- disableTransitions,
- absolute
- } = _ref2;
- priorities.set(id, order);
- positions.set(id, position);
- layoutSizes.set(id, layoutSize);
- activeItems.set(id, active);
- disableTransitions && disabledTransitions.set(id, disableTransitions);
- const instances = findChildrenWithProvide(VuetifyLayoutItemKey, rootVm?.vnode);
- const instanceIndex = instances.indexOf(vm);
- if (instanceIndex > -1) registered.value.splice(instanceIndex, 0, id);else registered.value.push(id);
- const index = computed(() => items.value.findIndex(i => i.id === id));
- const zIndex = computed(() => rootZIndex.value + layers.value.length * 2 - index.value * 2);
- const layoutItemStyles = computed(() => {
- const isHorizontal = position.value === 'left' || position.value === 'right';
- const isOppositeHorizontal = position.value === 'right';
- const isOppositeVertical = position.value === 'bottom';
- const styles = {
- [position.value]: 0,
- zIndex: zIndex.value,
- transform: `translate${isHorizontal ? 'X' : 'Y'}(${(active.value ? 0 : -110) * (isOppositeHorizontal || isOppositeVertical ? -1 : 1)}%)`,
- position: absolute.value || rootZIndex.value !== ROOT_ZINDEX ? 'absolute' : 'fixed',
- ...(transitionsEnabled.value ? undefined : {
- transition: 'none'
- })
- };
- if (!isMounted.value) return styles;
- const item = items.value[index.value];
- if (!item) throw new Error(`[Vuetify] Could not find layout item "${id}"`);
- const overlap = computedOverlaps.value.get(id);
- if (overlap) {
- item[overlap.position] += overlap.amount;
- }
- return {
- ...styles,
- height: isHorizontal ? `calc(100% - ${item.top}px - ${item.bottom}px)` : elementSize.value ? `${elementSize.value}px` : undefined,
- left: isOppositeHorizontal ? undefined : `${item.left}px`,
- right: isOppositeHorizontal ? `${item.right}px` : undefined,
- top: position.value !== 'bottom' ? `${item.top}px` : undefined,
- bottom: position.value !== 'top' ? `${item.bottom}px` : undefined,
- width: !isHorizontal ? `calc(100% - ${item.left}px - ${item.right}px)` : elementSize.value ? `${elementSize.value}px` : undefined
- };
- });
- const layoutItemScrimStyles = computed(() => ({
- zIndex: zIndex.value - 1
- }));
- return {
- layoutItemStyles,
- layoutItemScrimStyles,
- zIndex
- };
- },
- unregister: id => {
- priorities.delete(id);
- positions.delete(id);
- layoutSizes.delete(id);
- activeItems.delete(id);
- disabledTransitions.delete(id);
- registered.value = registered.value.filter(v => v !== id);
- },
- mainRect,
- mainStyles,
- getLayoutItem,
- items,
- layoutRect,
- rootZIndex
- });
- const layoutClasses = computed(() => ['v-layout', {
- 'v-layout--full-height': props.fullHeight
- }]);
- const layoutStyles = computed(() => ({
- zIndex: rootZIndex.value,
- position: parentLayout ? 'relative' : undefined,
- overflow: parentLayout ? 'hidden' : undefined
- }));
- return {
- layoutClasses,
- layoutStyles,
- getLayoutItem,
- items,
- layoutRect,
- layoutRef: resizeRef
- };
- }
- var en = {
- badge: 'Badge',
- close: 'Close',
- dataIterator: {
- noResultsText: 'No matching records found',
- loadingText: 'Loading items...'
- },
- dataTable: {
- itemsPerPageText: 'Rows per page:',
- ariaLabel: {
- sortDescending: 'Sorted descending.',
- sortAscending: 'Sorted ascending.',
- sortNone: 'Not sorted.',
- activateNone: 'Activate to remove sorting.',
- activateDescending: 'Activate to sort descending.',
- activateAscending: 'Activate to sort ascending.'
- },
- sortBy: 'Sort by'
- },
- dataFooter: {
- itemsPerPageText: 'Items per page:',
- itemsPerPageAll: 'All',
- nextPage: 'Next page',
- prevPage: 'Previous page',
- firstPage: 'First page',
- lastPage: 'Last page',
- pageText: '{0}-{1} of {2}'
- },
- dateRangeInput: {
- divider: 'to'
- },
- datePicker: {
- ok: 'OK',
- cancel: 'Cancel',
- range: {
- title: 'Select dates',
- header: 'Enter dates'
- },
- title: 'Select date',
- header: 'Enter date',
- input: {
- placeholder: 'Enter date'
- }
- },
- noDataText: 'No data available',
- carousel: {
- prev: 'Previous visual',
- next: 'Next visual',
- ariaLabel: {
- delimiter: 'Carousel slide {0} of {1}'
- }
- },
- calendar: {
- moreEvents: '{0} more'
- },
- input: {
- clear: 'Clear {0}',
- prependAction: '{0} prepended action',
- appendAction: '{0} appended action',
- otp: 'Please enter OTP character {0}'
- },
- fileInput: {
- counter: '{0} files',
- counterSize: '{0} files ({1} in total)'
- },
- timePicker: {
- am: 'AM',
- pm: 'PM'
- },
- pagination: {
- ariaLabel: {
- root: 'Pagination Navigation',
- next: 'Next page',
- previous: 'Previous page',
- page: 'Go to page {0}',
- currentPage: 'Page {0}, Current page',
- first: 'First page',
- last: 'Last page'
- }
- },
- stepper: {
- next: 'Next',
- prev: 'Previous'
- },
- rating: {
- ariaLabel: {
- item: 'Rating {0} of {1}'
- }
- },
- loading: 'Loading...',
- infiniteScroll: {
- loadMore: 'Load more',
- empty: 'No more'
- }
- };
- const defaultRtl = {
- af: false,
- ar: true,
- bg: false,
- ca: false,
- ckb: false,
- cs: false,
- de: false,
- el: false,
- en: false,
- es: false,
- et: false,
- fa: true,
- fi: false,
- fr: false,
- hr: false,
- hu: false,
- he: true,
- id: false,
- it: false,
- ja: false,
- ko: false,
- lv: false,
- lt: false,
- nl: false,
- no: false,
- pl: false,
- pt: false,
- ro: false,
- ru: false,
- sk: false,
- sl: false,
- srCyrl: false,
- srLatn: false,
- sv: false,
- th: false,
- tr: false,
- az: false,
- uk: false,
- vi: false,
- zhHans: false,
- zhHant: false
- };
- // Composables
- // Types
- // Composables
- function useProxiedModel(props, prop, defaultValue) {
- let transformIn = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : v => v;
- let transformOut = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : v => v;
- const vm = getCurrentInstance('useProxiedModel');
- const internal = ref(props[prop] !== undefined ? props[prop] : defaultValue);
- const kebabProp = toKebabCase(prop);
- const checkKebab = kebabProp !== prop;
- const isControlled = checkKebab ? computed(() => {
- void props[prop];
- return !!((vm.vnode.props?.hasOwnProperty(prop) || vm.vnode.props?.hasOwnProperty(kebabProp)) && (vm.vnode.props?.hasOwnProperty(`onUpdate:${prop}`) || vm.vnode.props?.hasOwnProperty(`onUpdate:${kebabProp}`)));
- }) : computed(() => {
- void props[prop];
- return !!(vm.vnode.props?.hasOwnProperty(prop) && vm.vnode.props?.hasOwnProperty(`onUpdate:${prop}`));
- });
- useToggleScope(() => !isControlled.value, () => {
- watch(() => props[prop], val => {
- internal.value = val;
- });
- });
- const model = computed({
- get() {
- const externalValue = props[prop];
- return transformIn(isControlled.value ? externalValue : internal.value);
- },
- set(internalValue) {
- const newValue = transformOut(internalValue);
- const value = toRaw(isControlled.value ? props[prop] : internal.value);
- if (value === newValue || transformIn(value) === internalValue) {
- return;
- }
- internal.value = newValue;
- vm?.emit(`update:${prop}`, newValue);
- }
- });
- Object.defineProperty(model, 'externalValue', {
- get: () => isControlled.value ? props[prop] : internal.value
- });
- return model;
- }
- // Composables
- // Types
- const LANG_PREFIX = '$vuetify.';
- const replace = (str, params) => {
- return str.replace(/\{(\d+)\}/g, (match, index) => {
- return String(params[+index]);
- });
- };
- const createTranslateFunction = (current, fallback, messages) => {
- return function (key) {
- for (var _len = arguments.length, params = new Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) {
- params[_key - 1] = arguments[_key];
- }
- if (!key.startsWith(LANG_PREFIX)) {
- return replace(key, params);
- }
- const shortKey = key.replace(LANG_PREFIX, '');
- const currentLocale = current.value && messages.value[current.value];
- const fallbackLocale = fallback.value && messages.value[fallback.value];
- let str = getObjectValueByPath(currentLocale, shortKey, null);
- if (!str) {
- consoleWarn(`Translation key "${key}" not found in "${current.value}", trying fallback locale`);
- str = getObjectValueByPath(fallbackLocale, shortKey, null);
- }
- if (!str) {
- consoleError(`Translation key "${key}" not found in fallback`);
- str = key;
- }
- if (typeof str !== 'string') {
- consoleError(`Translation key "${key}" has a non-string value`);
- str = key;
- }
- return replace(str, params);
- };
- };
- function createNumberFunction(current, fallback) {
- return (value, options) => {
- const numberFormat = new Intl.NumberFormat([current.value, fallback.value], options);
- return numberFormat.format(value);
- };
- }
- function useProvided(props, prop, provided) {
- const internal = useProxiedModel(props, prop, props[prop] ?? provided.value);
- // TODO: Remove when defaultValue works
- internal.value = props[prop] ?? provided.value;
- watch(provided, v => {
- if (props[prop] == null) {
- internal.value = provided.value;
- }
- });
- return internal;
- }
- function createProvideFunction(state) {
- return props => {
- const current = useProvided(props, 'locale', state.current);
- const fallback = useProvided(props, 'fallback', state.fallback);
- const messages = useProvided(props, 'messages', state.messages);
- return {
- name: 'vuetify',
- current,
- fallback,
- messages,
- t: createTranslateFunction(current, fallback, messages),
- n: createNumberFunction(current, fallback),
- provide: createProvideFunction({
- current,
- fallback,
- messages
- })
- };
- };
- }
- function createVuetifyAdapter(options) {
- const current = shallowRef(options?.locale ?? 'en');
- const fallback = shallowRef(options?.fallback ?? 'en');
- const messages = ref({
- en,
- ...options?.messages
- });
- return {
- name: 'vuetify',
- current,
- fallback,
- messages,
- t: createTranslateFunction(current, fallback, messages),
- n: createNumberFunction(current, fallback),
- provide: createProvideFunction({
- current,
- fallback,
- messages
- })
- };
- }
- // Utilities
- // Types
- const LocaleSymbol = Symbol.for('vuetify:locale');
- function isLocaleInstance(obj) {
- return obj.name != null;
- }
- function createLocale(options) {
- const i18n = options?.adapter && isLocaleInstance(options?.adapter) ? options?.adapter : createVuetifyAdapter(options);
- const rtl = createRtl(i18n, options);
- return {
- ...i18n,
- ...rtl
- };
- }
- function useLocale() {
- const locale = inject$1(LocaleSymbol);
- if (!locale) throw new Error('[Vuetify] Could not find injected locale instance');
- return locale;
- }
- function provideLocale(props) {
- const locale = inject$1(LocaleSymbol);
- if (!locale) throw new Error('[Vuetify] Could not find injected locale instance');
- const i18n = locale.provide(props);
- const rtl = provideRtl(i18n, locale.rtl, props);
- const data = {
- ...i18n,
- ...rtl
- };
- provide(LocaleSymbol, data);
- return data;
- }
- function createRtl(i18n, options) {
- const rtl = ref(options?.rtl ?? defaultRtl);
- const isRtl = computed(() => rtl.value[i18n.current.value] ?? false);
- return {
- isRtl,
- rtl,
- rtlClasses: computed(() => `v-locale--is-${isRtl.value ? 'rtl' : 'ltr'}`)
- };
- }
- function provideRtl(locale, rtl, props) {
- const isRtl = computed(() => props.rtl ?? rtl.value[locale.current.value] ?? false);
- return {
- isRtl,
- rtl,
- rtlClasses: computed(() => `v-locale--is-${isRtl.value ? 'rtl' : 'ltr'}`)
- };
- }
- function useRtl() {
- const locale = inject$1(LocaleSymbol);
- if (!locale) throw new Error('[Vuetify] Could not find injected rtl instance');
- return {
- isRtl: locale.isRtl,
- rtlClasses: locale.rtlClasses
- };
- }
- /**
- * WCAG 3.0 APCA perceptual contrast algorithm from https://github.com/Myndex/SAPC-APCA
- * @licence https://www.w3.org/Consortium/Legal/2015/copyright-software-and-document
- * @see https://www.w3.org/WAI/GL/task-forces/silver/wiki/Visual_Contrast_of_Text_Subgroup
- */
- // Types
- // MAGICAL NUMBERS
- // sRGB Conversion to Relative Luminance (Y)
- // Transfer Curve (aka "Gamma") for sRGB linearization
- // Simple power curve vs piecewise described in docs
- // Essentially, 2.4 best models actual display
- // characteristics in combination with the total method
- const mainTRC = 2.4;
- const Rco = 0.2126729; // sRGB Red Coefficient (from matrix)
- const Gco = 0.7151522; // sRGB Green Coefficient (from matrix)
- const Bco = 0.0721750; // sRGB Blue Coefficient (from matrix)
- // For Finding Raw SAPC Contrast from Relative Luminance (Y)
- // Constants for SAPC Power Curve Exponents
- // One pair for normal text, and one for reverse
- // These are the "beating heart" of SAPC
- const normBG = 0.55;
- const normTXT = 0.58;
- const revTXT = 0.57;
- const revBG = 0.62;
- // For Clamping and Scaling Values
- const blkThrs = 0.03; // Level that triggers the soft black clamp
- const blkClmp = 1.45; // Exponent for the soft black clamp curve
- const deltaYmin = 0.0005; // Lint trap
- const scaleBoW = 1.25; // Scaling for dark text on light
- const scaleWoB = 1.25; // Scaling for light text on dark
- const loConThresh = 0.078; // Threshold for new simple offset scale
- const loConFactor = 12.82051282051282; // = 1/0.078,
- const loConOffset = 0.06; // The simple offset
- const loClip = 0.001; // Output clip (lint trap #2)
- function APCAcontrast(text, background) {
- // Linearize sRGB
- const Rtxt = (text.r / 255) ** mainTRC;
- const Gtxt = (text.g / 255) ** mainTRC;
- const Btxt = (text.b / 255) ** mainTRC;
- const Rbg = (background.r / 255) ** mainTRC;
- const Gbg = (background.g / 255) ** mainTRC;
- const Bbg = (background.b / 255) ** mainTRC;
- // Apply the standard coefficients and sum to Y
- let Ytxt = Rtxt * Rco + Gtxt * Gco + Btxt * Bco;
- let Ybg = Rbg * Rco + Gbg * Gco + Bbg * Bco;
- // Soft clamp Y when near black.
- // Now clamping all colors to prevent crossover errors
- if (Ytxt <= blkThrs) Ytxt += (blkThrs - Ytxt) ** blkClmp;
- if (Ybg <= blkThrs) Ybg += (blkThrs - Ybg) ** blkClmp;
- // Return 0 Early for extremely low ∆Y (lint trap #1)
- if (Math.abs(Ybg - Ytxt) < deltaYmin) return 0.0;
- // SAPC CONTRAST
- let outputContrast; // For weighted final values
- if (Ybg > Ytxt) {
- // For normal polarity, black text on white
- // Calculate the SAPC contrast value and scale
- const SAPC = (Ybg ** normBG - Ytxt ** normTXT) * scaleBoW;
- // NEW! SAPC SmoothScale™
- // Low Contrast Smooth Scale Rollout to prevent polarity reversal
- // and also a low clip for very low contrasts (lint trap #2)
- // much of this is for very low contrasts, less than 10
- // therefore for most reversing needs, only loConOffset is important
- outputContrast = SAPC < loClip ? 0.0 : SAPC < loConThresh ? SAPC - SAPC * loConFactor * loConOffset : SAPC - loConOffset;
- } else {
- // For reverse polarity, light text on dark
- // WoB should always return negative value.
- const SAPC = (Ybg ** revBG - Ytxt ** revTXT) * scaleWoB;
- outputContrast = SAPC > -loClip ? 0.0 : SAPC > -loConThresh ? SAPC - SAPC * loConFactor * loConOffset : SAPC + loConOffset;
- }
- return outputContrast * 100;
- }
- // Utilities
- // Types
- const ThemeSymbol = Symbol.for('vuetify:theme');
- const makeThemeProps = propsFactory({
- theme: String
- }, 'theme');
- const defaultThemeOptions = {
- defaultTheme: 'light',
- variations: {
- colors: [],
- lighten: 0,
- darken: 0
- },
- themes: {
- light: {
- dark: false,
- colors: {
- background: '#FFFFFF',
- surface: '#FFFFFF',
- 'surface-variant': '#424242',
- 'on-surface-variant': '#EEEEEE',
- primary: '#6200EE',
- 'primary-darken-1': '#3700B3',
- secondary: '#03DAC6',
- 'secondary-darken-1': '#018786',
- error: '#B00020',
- info: '#2196F3',
- success: '#4CAF50',
- warning: '#FB8C00'
- },
- variables: {
- 'border-color': '#000000',
- 'border-opacity': 0.12,
- 'high-emphasis-opacity': 0.87,
- 'medium-emphasis-opacity': 0.60,
- 'disabled-opacity': 0.38,
- 'idle-opacity': 0.04,
- 'hover-opacity': 0.04,
- 'focus-opacity': 0.12,
- 'selected-opacity': 0.08,
- 'activated-opacity': 0.12,
- 'pressed-opacity': 0.12,
- 'dragged-opacity': 0.08,
- 'theme-kbd': '#212529',
- 'theme-on-kbd': '#FFFFFF',
- 'theme-code': '#F5F5F5',
- 'theme-on-code': '#000000'
- }
- },
- dark: {
- dark: true,
- colors: {
- background: '#121212',
- surface: '#212121',
- 'surface-variant': '#BDBDBD',
- 'on-surface-variant': '#424242',
- primary: '#BB86FC',
- 'primary-darken-1': '#3700B3',
- secondary: '#03DAC5',
- 'secondary-darken-1': '#03DAC5',
- error: '#CF6679',
- info: '#2196F3',
- success: '#4CAF50',
- warning: '#FB8C00'
- },
- variables: {
- 'border-color': '#FFFFFF',
- 'border-opacity': 0.12,
- 'high-emphasis-opacity': 1,
- 'medium-emphasis-opacity': 0.70,
- 'disabled-opacity': 0.50,
- 'idle-opacity': 0.10,
- 'hover-opacity': 0.04,
- 'focus-opacity': 0.12,
- 'selected-opacity': 0.08,
- 'activated-opacity': 0.12,
- 'pressed-opacity': 0.16,
- 'dragged-opacity': 0.08,
- 'theme-kbd': '#212529',
- 'theme-on-kbd': '#FFFFFF',
- 'theme-code': '#343434',
- 'theme-on-code': '#CCCCCC'
- }
- }
- }
- };
- function parseThemeOptions() {
- let options = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : defaultThemeOptions;
- if (!options) return {
- ...defaultThemeOptions,
- isDisabled: true
- };
- const themes = {};
- for (const [key, theme] of Object.entries(options.themes ?? {})) {
- const defaultTheme = theme.dark || key === 'dark' ? defaultThemeOptions.themes?.dark : defaultThemeOptions.themes?.light;
- themes[key] = mergeDeep(defaultTheme, theme);
- }
- return mergeDeep(defaultThemeOptions, {
- ...options,
- themes
- });
- }
- // Composables
- function createTheme(options) {
- const parsedOptions = parseThemeOptions(options);
- const name = ref(parsedOptions.defaultTheme);
- const themes = ref(parsedOptions.themes);
- const computedThemes = computed(() => {
- const acc = {};
- for (const [name, original] of Object.entries(themes.value)) {
- const theme = acc[name] = {
- ...original,
- colors: {
- ...original.colors
- }
- };
- if (parsedOptions.variations) {
- for (const name of parsedOptions.variations.colors) {
- const color = theme.colors[name];
- if (!color) continue;
- for (const variation of ['lighten', 'darken']) {
- const fn = variation === 'lighten' ? lighten : darken;
- for (const amount of createRange(parsedOptions.variations[variation], 1)) {
- theme.colors[`${name}-${variation}-${amount}`] = RGBtoHex(fn(parseColor(color), amount));
- }
- }
- }
- }
- for (const color of Object.keys(theme.colors)) {
- if (/^on-[a-z]/.test(color) || theme.colors[`on-${color}`]) continue;
- const onColor = `on-${color}`;
- const colorVal = parseColor(theme.colors[color]);
- const blackContrast = Math.abs(APCAcontrast(parseColor(0), colorVal));
- const whiteContrast = Math.abs(APCAcontrast(parseColor(0xffffff), colorVal));
- // TODO: warn about poor color selections
- // const contrastAsText = Math.abs(APCAcontrast(colorVal, colorToInt(theme.colors.background)))
- // const minContrast = Math.max(blackContrast, whiteContrast)
- // if (minContrast < 60) {
- // consoleInfo(`${key} theme color ${color} has poor contrast (${minContrast.toFixed()}%)`)
- // } else if (contrastAsText < 60 && !['background', 'surface'].includes(color)) {
- // consoleInfo(`${key} theme color ${color} has poor contrast as text (${contrastAsText.toFixed()}%)`)
- // }
- // Prefer white text if both have an acceptable contrast ratio
- theme.colors[onColor] = whiteContrast > Math.min(blackContrast, 50) ? '#fff' : '#000';
- }
- }
- return acc;
- });
- const current = computed(() => computedThemes.value[name.value]);
- const styles = computed(() => {
- const lines = [];
- if (current.value.dark) {
- createCssClass(lines, ':root', ['color-scheme: dark']);
- }
- createCssClass(lines, ':root', genCssVariables(current.value));
- for (const [themeName, theme] of Object.entries(computedThemes.value)) {
- createCssClass(lines, `.v-theme--${themeName}`, [`color-scheme: ${theme.dark ? 'dark' : 'normal'}`, ...genCssVariables(theme)]);
- }
- const bgLines = [];
- const fgLines = [];
- const colors = new Set(Object.values(computedThemes.value).flatMap(theme => Object.keys(theme.colors)));
- for (const key of colors) {
- if (/^on-[a-z]/.test(key)) {
- createCssClass(fgLines, `.${key}`, [`color: rgb(var(--v-theme-${key})) !important`]);
- } else {
- createCssClass(bgLines, `.bg-${key}`, [`--v-theme-overlay-multiplier: var(--v-theme-${key}-overlay-multiplier)`, `background-color: rgb(var(--v-theme-${key})) !important`, `color: rgb(var(--v-theme-on-${key})) !important`]);
- createCssClass(fgLines, `.text-${key}`, [`color: rgb(var(--v-theme-${key})) !important`]);
- createCssClass(fgLines, `.border-${key}`, [`--v-border-color: var(--v-theme-${key})`]);
- }
- }
- lines.push(...bgLines, ...fgLines);
- return lines.map((str, i) => i === 0 ? str : ` ${str}`).join('');
- });
- function getHead() {
- return {
- style: [{
- children: styles.value,
- id: 'vuetify-theme-stylesheet',
- nonce: parsedOptions.cspNonce || false
- }]
- };
- }
- function install(app) {
- if (parsedOptions.isDisabled) return;
- const head = app._context.provides.usehead;
- if (head) {
- if (head.push) {
- const entry = head.push(getHead);
- if (IN_BROWSER) {
- watch(styles, () => {
- entry.patch(getHead);
- });
- }
- } else {
- if (IN_BROWSER) {
- head.addHeadObjs(computed(getHead));
- watchEffect(() => head.updateDOM());
- } else {
- head.addHeadObjs(getHead());
- }
- }
- } else {
- let styleEl = IN_BROWSER ? document.getElementById('vuetify-theme-stylesheet') : null;
- if (IN_BROWSER) {
- watch(styles, updateStyles, {
- immediate: true
- });
- } else {
- updateStyles();
- }
- function updateStyles() {
- if (typeof document !== 'undefined' && !styleEl) {
- const el = document.createElement('style');
- el.type = 'text/css';
- el.id = 'vuetify-theme-stylesheet';
- if (parsedOptions.cspNonce) el.setAttribute('nonce', parsedOptions.cspNonce);
- styleEl = el;
- document.head.appendChild(styleEl);
- }
- if (styleEl) styleEl.innerHTML = styles.value;
- }
- }
- }
- const themeClasses = computed(() => parsedOptions.isDisabled ? undefined : `v-theme--${name.value}`);
- return {
- install,
- isDisabled: parsedOptions.isDisabled,
- name,
- themes,
- current,
- computedThemes,
- themeClasses,
- styles,
- global: {
- name,
- current
- }
- };
- }
- function provideTheme(props) {
- getCurrentInstance('provideTheme');
- const theme = inject$1(ThemeSymbol, null);
- if (!theme) throw new Error('Could not find Vuetify theme injection');
- const name = computed(() => {
- return props.theme ?? theme?.name.value;
- });
- const themeClasses = computed(() => theme.isDisabled ? undefined : `v-theme--${name.value}`);
- const newTheme = {
- ...theme,
- name,
- themeClasses
- };
- provide(ThemeSymbol, newTheme);
- return newTheme;
- }
- function useTheme() {
- getCurrentInstance('useTheme');
- const theme = inject$1(ThemeSymbol, null);
- if (!theme) throw new Error('Could not find Vuetify theme injection');
- return theme;
- }
- function createCssClass(lines, selector, content) {
- lines.push(`${selector} {\n`, ...content.map(line => ` ${line};\n`), '}\n');
- }
- function genCssVariables(theme) {
- const lightOverlay = theme.dark ? 2 : 1;
- const darkOverlay = theme.dark ? 1 : 2;
- const variables = [];
- for (const [key, value] of Object.entries(theme.colors)) {
- const rgb = parseColor(value);
- variables.push(`--v-theme-${key}: ${rgb.r},${rgb.g},${rgb.b}`);
- if (!key.startsWith('on-')) {
- variables.push(`--v-theme-${key}-overlay-multiplier: ${getLuma(value) > 0.18 ? lightOverlay : darkOverlay}`);
- }
- }
- for (const [key, value] of Object.entries(theme.variables)) {
- const color = typeof value === 'string' && value.startsWith('#') ? parseColor(value) : undefined;
- const rgb = color ? `${color.r}, ${color.g}, ${color.b}` : undefined;
- variables.push(`--v-${key}: ${rgb ?? value}`);
- }
- return variables;
- }
- const makeVAppProps = propsFactory({
- ...makeComponentProps(),
- ...makeLayoutProps({
- fullHeight: true
- }),
- ...makeThemeProps()
- }, 'VApp');
- const VApp = genericComponent()({
- name: 'VApp',
- props: makeVAppProps(),
- setup(props, _ref) {
- let {
- slots
- } = _ref;
- const theme = provideTheme(props);
- const {
- layoutClasses,
- layoutStyles,
- getLayoutItem,
- items,
- layoutRef
- } = createLayout(props);
- const {
- rtlClasses
- } = useRtl();
- useRender(() => createVNode("div", {
- "ref": layoutRef,
- "class": ['v-application', theme.themeClasses.value, layoutClasses.value, rtlClasses.value, props.class],
- "style": [layoutStyles.value, props.style]
- }, [createVNode("div", {
- "class": "v-application__wrap"
- }, [slots.default?.()])]));
- return {
- getLayoutItem,
- items,
- theme
- };
- }
- });
- // Utilities
- // Types
- // Composables
- const makeTagProps = propsFactory({
- tag: {
- type: String,
- default: 'div'
- }
- }, 'tag');
- const makeVToolbarTitleProps = propsFactory({
- text: String,
- ...makeComponentProps(),
- ...makeTagProps()
- }, 'VToolbarTitle');
- const VToolbarTitle = genericComponent()({
- name: 'VToolbarTitle',
- props: makeVToolbarTitleProps(),
- setup(props, _ref) {
- let {
- slots
- } = _ref;
- useRender(() => {
- const hasText = !!(slots.default || slots.text || props.text);
- return createVNode(props.tag, {
- "class": ['v-toolbar-title', props.class],
- "style": props.style
- }, {
- default: () => [hasText && createVNode("div", {
- "class": "v-toolbar-title__placeholder"
- }, [slots.text ? slots.text() : props.text, slots.default?.()])]
- });
- });
- return {};
- }
- });
- // Utilities
- // Types
- const makeTransitionProps$1 = propsFactory({
- disabled: Boolean,
- group: Boolean,
- hideOnLeave: Boolean,
- leaveAbsolute: Boolean,
- mode: String,
- origin: String
- }, 'transition');
- function createCssTransition(name, origin, mode) {
- return genericComponent()({
- name,
- props: makeTransitionProps$1({
- mode,
- origin
- }),
- setup(props, _ref) {
- let {
- slots
- } = _ref;
- const functions = {
- onBeforeEnter(el) {
- if (props.origin) {
- el.style.transformOrigin = props.origin;
- }
- },
- onLeave(el) {
- if (props.leaveAbsolute) {
- const {
- offsetTop,
- offsetLeft,
- offsetWidth,
- offsetHeight
- } = el;
- el._transitionInitialStyles = {
- position: el.style.position,
- top: el.style.top,
- left: el.style.left,
- width: el.style.width,
- height: el.style.height
- };
- el.style.position = 'absolute';
- el.style.top = `${offsetTop}px`;
- el.style.left = `${offsetLeft}px`;
- el.style.width = `${offsetWidth}px`;
- el.style.height = `${offsetHeight}px`;
- }
- if (props.hideOnLeave) {
- el.style.setProperty('display', 'none', 'important');
- }
- },
- onAfterLeave(el) {
- if (props.leaveAbsolute && el?._transitionInitialStyles) {
- const {
- position,
- top,
- left,
- width,
- height
- } = el._transitionInitialStyles;
- delete el._transitionInitialStyles;
- el.style.position = position || '';
- el.style.top = top || '';
- el.style.left = left || '';
- el.style.width = width || '';
- el.style.height = height || '';
- }
- }
- };
- return () => {
- const tag = props.group ? TransitionGroup : Transition;
- return h(tag, {
- name: props.disabled ? '' : name,
- css: !props.disabled,
- ...(props.group ? undefined : {
- mode: props.mode
- }),
- ...(props.disabled ? {} : functions)
- }, slots.default);
- };
- }
- });
- }
- function createJavascriptTransition(name, functions) {
- let mode = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : 'in-out';
- return genericComponent()({
- name,
- props: {
- mode: {
- type: String,
- default: mode
- },
- disabled: Boolean
- },
- setup(props, _ref2) {
- let {
- slots
- } = _ref2;
- return () => {
- return h(Transition, {
- name: props.disabled ? '' : name,
- css: !props.disabled,
- // mode: props.mode, // TODO: vuejs/vue-next#3104
- ...(props.disabled ? {} : functions)
- }, slots.default);
- };
- }
- });
- }
- // Utilities
- function ExpandTransitionGenerator () {
- let expandedParentClass = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : '';
- let x = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : false;
- const sizeProperty = x ? 'width' : 'height';
- const offsetProperty = camelize(`offset-${sizeProperty}`);
- return {
- onBeforeEnter(el) {
- el._parent = el.parentNode;
- el._initialStyle = {
- transition: el.style.transition,
- overflow: el.style.overflow,
- [sizeProperty]: el.style[sizeProperty]
- };
- },
- onEnter(el) {
- const initialStyle = el._initialStyle;
- el.style.setProperty('transition', 'none', 'important');
- // Hide overflow to account for collapsed margins in the calculated height
- el.style.overflow = 'hidden';
- const offset = `${el[offsetProperty]}px`;
- el.style[sizeProperty] = '0';
- void el.offsetHeight; // force reflow
- el.style.transition = initialStyle.transition;
- if (expandedParentClass && el._parent) {
- el._parent.classList.add(expandedParentClass);
- }
- requestAnimationFrame(() => {
- el.style[sizeProperty] = offset;
- });
- },
- onAfterEnter: resetStyles,
- onEnterCancelled: resetStyles,
- onLeave(el) {
- el._initialStyle = {
- transition: '',
- overflow: el.style.overflow,
- [sizeProperty]: el.style[sizeProperty]
- };
- el.style.overflow = 'hidden';
- el.style[sizeProperty] = `${el[offsetProperty]}px`;
- void el.offsetHeight; // force reflow
- requestAnimationFrame(() => el.style[sizeProperty] = '0');
- },
- onAfterLeave,
- onLeaveCancelled: onAfterLeave
- };
- function onAfterLeave(el) {
- if (expandedParentClass && el._parent) {
- el._parent.classList.remove(expandedParentClass);
- }
- resetStyles(el);
- }
- function resetStyles(el) {
- const size = el._initialStyle[sizeProperty];
- el.style.overflow = el._initialStyle.overflow;
- if (size != null) el.style[sizeProperty] = size;
- delete el._initialStyle;
- }
- }
- // Types
- const makeVDialogTransitionProps = propsFactory({
- target: Object
- }, 'v-dialog-transition');
- const VDialogTransition = genericComponent()({
- name: 'VDialogTransition',
- props: makeVDialogTransitionProps(),
- setup(props, _ref) {
- let {
- slots
- } = _ref;
- const functions = {
- onBeforeEnter(el) {
- el.style.pointerEvents = 'none';
- el.style.visibility = 'hidden';
- },
- async onEnter(el, done) {
- await new Promise(resolve => requestAnimationFrame(resolve));
- await new Promise(resolve => requestAnimationFrame(resolve));
- el.style.visibility = '';
- const {
- x,
- y,
- sx,
- sy,
- speed
- } = getDimensions(props.target, el);
- const animation = animate(el, [{
- transform: `translate(${x}px, ${y}px) scale(${sx}, ${sy})`,
- opacity: 0
- }, {}], {
- duration: 225 * speed,
- easing: deceleratedEasing
- });
- getChildren(el)?.forEach(el => {
- animate(el, [{
- opacity: 0
- }, {
- opacity: 0,
- offset: 0.33
- }, {}], {
- duration: 225 * 2 * speed,
- easing: standardEasing
- });
- });
- animation.finished.then(() => done());
- },
- onAfterEnter(el) {
- el.style.removeProperty('pointer-events');
- },
- onBeforeLeave(el) {
- el.style.pointerEvents = 'none';
- },
- async onLeave(el, done) {
- await new Promise(resolve => requestAnimationFrame(resolve));
- const {
- x,
- y,
- sx,
- sy,
- speed
- } = getDimensions(props.target, el);
- const animation = animate(el, [{}, {
- transform: `translate(${x}px, ${y}px) scale(${sx}, ${sy})`,
- opacity: 0
- }], {
- duration: 125 * speed,
- easing: acceleratedEasing
- });
- animation.finished.then(() => done());
- getChildren(el)?.forEach(el => {
- animate(el, [{}, {
- opacity: 0,
- offset: 0.2
- }, {
- opacity: 0
- }], {
- duration: 125 * 2 * speed,
- easing: standardEasing
- });
- });
- },
- onAfterLeave(el) {
- el.style.removeProperty('pointer-events');
- }
- };
- return () => {
- return props.target ? createVNode(Transition, mergeProps({
- "name": "dialog-transition"
- }, functions, {
- "css": false
- }), slots) : createVNode(Transition, {
- "name": "dialog-transition"
- }, slots);
- };
- }
- });
- /** Animatable children (card, sheet, list) */
- function getChildren(el) {
- const els = el.querySelector(':scope > .v-card, :scope > .v-sheet, :scope > .v-list')?.children;
- return els && [...els];
- }
- function getDimensions(target, el) {
- const targetBox = target.getBoundingClientRect();
- const elBox = nullifyTransforms(el);
- const [originX, originY] = getComputedStyle(el).transformOrigin.split(' ').map(v => parseFloat(v));
- const [anchorSide, anchorOffset] = getComputedStyle(el).getPropertyValue('--v-overlay-anchor-origin').split(' ');
- let offsetX = targetBox.left + targetBox.width / 2;
- if (anchorSide === 'left' || anchorOffset === 'left') {
- offsetX -= targetBox.width / 2;
- } else if (anchorSide === 'right' || anchorOffset === 'right') {
- offsetX += targetBox.width / 2;
- }
- let offsetY = targetBox.top + targetBox.height / 2;
- if (anchorSide === 'top' || anchorOffset === 'top') {
- offsetY -= targetBox.height / 2;
- } else if (anchorSide === 'bottom' || anchorOffset === 'bottom') {
- offsetY += targetBox.height / 2;
- }
- const tsx = targetBox.width / elBox.width;
- const tsy = targetBox.height / elBox.height;
- const maxs = Math.max(1, tsx, tsy);
- const sx = tsx / maxs || 0;
- const sy = tsy / maxs || 0;
- // Animate elements larger than 12% of the screen area up to 1.5x slower
- const asa = elBox.width * elBox.height / (window.innerWidth * window.innerHeight);
- const speed = asa > 0.12 ? Math.min(1.5, (asa - 0.12) * 10 + 1) : 1;
- return {
- x: offsetX - (originX + elBox.left),
- y: offsetY - (originY + elBox.top),
- sx,
- sy,
- speed
- };
- }
- // Component specific transitions
- const VFabTransition = createCssTransition('fab-transition', 'center center', 'out-in');
- // Generic transitions
- const VDialogBottomTransition = createCssTransition('dialog-bottom-transition');
- const VDialogTopTransition = createCssTransition('dialog-top-transition');
- const VFadeTransition = createCssTransition('fade-transition');
- const VScaleTransition = createCssTransition('scale-transition');
- const VScrollXTransition = createCssTransition('scroll-x-transition');
- const VScrollXReverseTransition = createCssTransition('scroll-x-reverse-transition');
- const VScrollYTransition = createCssTransition('scroll-y-transition');
- const VScrollYReverseTransition = createCssTransition('scroll-y-reverse-transition');
- const VSlideXTransition = createCssTransition('slide-x-transition');
- const VSlideXReverseTransition = createCssTransition('slide-x-reverse-transition');
- const VSlideYTransition = createCssTransition('slide-y-transition');
- const VSlideYReverseTransition = createCssTransition('slide-y-reverse-transition');
- // Javascript transitions
- const VExpandTransition = createJavascriptTransition('expand-transition', ExpandTransitionGenerator());
- const VExpandXTransition = createJavascriptTransition('expand-x-transition', ExpandTransitionGenerator('', true));
- // Composables
- // Types
- const makeVDefaultsProviderProps = propsFactory({
- defaults: Object,
- disabled: Boolean,
- reset: [Number, String],
- root: [Boolean, String],
- scoped: Boolean
- }, 'VDefaultsProvider');
- const VDefaultsProvider = genericComponent(false)({
- name: 'VDefaultsProvider',
- props: makeVDefaultsProviderProps(),
- setup(props, _ref) {
- let {
- slots
- } = _ref;
- const {
- defaults,
- disabled,
- reset,
- root,
- scoped
- } = toRefs(props);
- provideDefaults(defaults, {
- reset,
- root,
- scoped,
- disabled
- });
- return () => slots.default?.();
- }
- });
- // Utilities
- // Types
- // Composables
- const makeDimensionProps = propsFactory({
- height: [Number, String],
- maxHeight: [Number, String],
- maxWidth: [Number, String],
- minHeight: [Number, String],
- minWidth: [Number, String],
- width: [Number, String]
- }, 'dimension');
- function useDimension(props) {
- const dimensionStyles = computed(() => ({
- height: convertToUnit(props.height),
- maxHeight: convertToUnit(props.maxHeight),
- maxWidth: convertToUnit(props.maxWidth),
- minHeight: convertToUnit(props.minHeight),
- minWidth: convertToUnit(props.minWidth),
- width: convertToUnit(props.width)
- }));
- return {
- dimensionStyles
- };
- }
- function useAspectStyles(props) {
- return {
- aspectStyles: computed(() => {
- const ratio = Number(props.aspectRatio);
- return ratio ? {
- paddingBottom: String(1 / ratio * 100) + '%'
- } : undefined;
- })
- };
- }
- const makeVResponsiveProps = propsFactory({
- aspectRatio: [String, Number],
- contentClass: String,
- inline: Boolean,
- ...makeComponentProps(),
- ...makeDimensionProps()
- }, 'VResponsive');
- const VResponsive = genericComponent()({
- name: 'VResponsive',
- props: makeVResponsiveProps(),
- setup(props, _ref) {
- let {
- slots
- } = _ref;
- const {
- aspectStyles
- } = useAspectStyles(props);
- const {
- dimensionStyles
- } = useDimension(props);
- useRender(() => createVNode("div", {
- "class": ['v-responsive', {
- 'v-responsive--inline': props.inline
- }, props.class],
- "style": [dimensionStyles.value, props.style]
- }, [createVNode("div", {
- "class": "v-responsive__sizer",
- "style": aspectStyles.value
- }, null), slots.additional?.(), slots.default && createVNode("div", {
- "class": ['v-responsive__content', props.contentClass]
- }, [slots.default()])]));
- return {};
- }
- });
- // Utilities
- // Types
- const makeTransitionProps = propsFactory({
- transition: {
- type: [Boolean, String, Object],
- default: 'fade-transition',
- validator: val => val !== true
- }
- }, 'transition');
- const MaybeTransition = (props, _ref) => {
- let {
- slots
- } = _ref;
- const {
- transition,
- disabled,
- ...rest
- } = props;
- const {
- component = Transition,
- ...customProps
- } = typeof transition === 'object' ? transition : {};
- return h(component, mergeProps(typeof transition === 'string' ? {
- name: disabled ? '' : transition
- } : customProps, rest, {
- disabled
- }), slots);
- };
- // Utilities
- // Types
- function mounted$5(el, binding) {
- if (!SUPPORTS_INTERSECTION) return;
- const modifiers = binding.modifiers || {};
- const value = binding.value;
- const {
- handler,
- options
- } = typeof value === 'object' ? value : {
- handler: value,
- options: {}
- };
- const observer = new IntersectionObserver(function () {
- let entries = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : [];
- let observer = arguments.length > 1 ? arguments[1] : undefined;
- const _observe = el._observe?.[binding.instance.$.uid];
- if (!_observe) return; // Just in case, should never fire
- const isIntersecting = entries.some(entry => entry.isIntersecting);
- // If is not quiet or has already been
- // initted, invoke the user callback
- if (handler && (!modifiers.quiet || _observe.init) && (!modifiers.once || isIntersecting || _observe.init)) {
- handler(isIntersecting, entries, observer);
- }
- if (isIntersecting && modifiers.once) unmounted$5(el, binding);else _observe.init = true;
- }, options);
- el._observe = Object(el._observe);
- el._observe[binding.instance.$.uid] = {
- init: false,
- observer
- };
- observer.observe(el);
- }
- function unmounted$5(el, binding) {
- const observe = el._observe?.[binding.instance.$.uid];
- if (!observe) return;
- observe.observer.unobserve(el);
- delete el._observe[binding.instance.$.uid];
- }
- const Intersect = {
- mounted: mounted$5,
- unmounted: unmounted$5
- };
- // Types
- const makeVImgProps = propsFactory({
- alt: String,
- cover: Boolean,
- eager: Boolean,
- gradient: String,
- lazySrc: String,
- options: {
- type: Object,
- // For more information on types, navigate to:
- // https://developer.mozilla.org/en-US/docs/Web/API/Intersection_Observer_API
- default: () => ({
- root: undefined,
- rootMargin: undefined,
- threshold: undefined
- })
- },
- sizes: String,
- src: {
- type: [String, Object],
- default: ''
- },
- srcset: String,
- ...makeVResponsiveProps(),
- ...makeComponentProps(),
- ...makeTransitionProps()
- }, 'VImg');
- const VImg = genericComponent()({
- name: 'VImg',
- directives: {
- intersect: Intersect
- },
- props: makeVImgProps(),
- emits: {
- loadstart: value => true,
- load: value => true,
- error: value => true
- },
- setup(props, _ref) {
- let {
- emit,
- slots
- } = _ref;
- const currentSrc = shallowRef(''); // Set from srcset
- const image = ref();
- const state = shallowRef(props.eager ? 'loading' : 'idle');
- const naturalWidth = shallowRef();
- const naturalHeight = shallowRef();
- const normalisedSrc = computed(() => {
- return props.src && typeof props.src === 'object' ? {
- src: props.src.src,
- srcset: props.srcset || props.src.srcset,
- lazySrc: props.lazySrc || props.src.lazySrc,
- aspect: Number(props.aspectRatio || props.src.aspect || 0)
- } : {
- src: props.src,
- srcset: props.srcset,
- lazySrc: props.lazySrc,
- aspect: Number(props.aspectRatio || 0)
- };
- });
- const aspectRatio = computed(() => {
- return normalisedSrc.value.aspect || naturalWidth.value / naturalHeight.value || 0;
- });
- watch(() => props.src, () => {
- init(state.value !== 'idle');
- });
- watch(aspectRatio, (val, oldVal) => {
- if (!val && oldVal && image.value) {
- pollForSize(image.value);
- }
- });
- // TODO: getSrc when window width changes
- onBeforeMount(() => init());
- function init(isIntersecting) {
- if (props.eager && isIntersecting) return;
- if (SUPPORTS_INTERSECTION && !isIntersecting && !props.eager) return;
- state.value = 'loading';
- if (normalisedSrc.value.lazySrc) {
- const lazyImg = new Image();
- lazyImg.src = normalisedSrc.value.lazySrc;
- pollForSize(lazyImg, null);
- }
- if (!normalisedSrc.value.src) return;
- nextTick(() => {
- emit('loadstart', image.value?.currentSrc || normalisedSrc.value.src);
- if (image.value?.complete) {
- if (!image.value.naturalWidth) {
- onError();
- }
- if (state.value === 'error') return;
- if (!aspectRatio.value) pollForSize(image.value, null);
- onLoad();
- } else {
- if (!aspectRatio.value) pollForSize(image.value);
- getSrc();
- }
- });
- }
- function onLoad() {
- getSrc();
- state.value = 'loaded';
- emit('load', image.value?.currentSrc || normalisedSrc.value.src);
- }
- function onError() {
- state.value = 'error';
- emit('error', image.value?.currentSrc || normalisedSrc.value.src);
- }
- function getSrc() {
- const img = image.value;
- if (img) currentSrc.value = img.currentSrc || img.src;
- }
- let timer = -1;
- function pollForSize(img) {
- let timeout = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 100;
- const poll = () => {
- clearTimeout(timer);
- const {
- naturalHeight: imgHeight,
- naturalWidth: imgWidth
- } = img;
- if (imgHeight || imgWidth) {
- naturalWidth.value = imgWidth;
- naturalHeight.value = imgHeight;
- } else if (!img.complete && state.value === 'loading' && timeout != null) {
- timer = window.setTimeout(poll, timeout);
- } else if (img.currentSrc.endsWith('.svg') || img.currentSrc.startsWith('data:image/svg+xml')) {
- naturalWidth.value = 1;
- naturalHeight.value = 1;
- }
- };
- poll();
- }
- const containClasses = computed(() => ({
- 'v-img__img--cover': props.cover,
- 'v-img__img--contain': !props.cover
- }));
- const __image = () => {
- if (!normalisedSrc.value.src || state.value === 'idle') return null;
- const img = createVNode("img", {
- "class": ['v-img__img', containClasses.value],
- "src": normalisedSrc.value.src,
- "srcset": normalisedSrc.value.srcset,
- "alt": props.alt,
- "sizes": props.sizes,
- "ref": image,
- "onLoad": onLoad,
- "onError": onError
- }, null);
- const sources = slots.sources?.();
- return createVNode(MaybeTransition, {
- "transition": props.transition,
- "appear": true
- }, {
- default: () => [withDirectives(sources ? createVNode("picture", {
- "class": "v-img__picture"
- }, [sources, img]) : img, [[vShow, state.value === 'loaded']])]
- });
- };
- const __preloadImage = () => createVNode(MaybeTransition, {
- "transition": props.transition
- }, {
- default: () => [normalisedSrc.value.lazySrc && state.value !== 'loaded' && createVNode("img", {
- "class": ['v-img__img', 'v-img__img--preload', containClasses.value],
- "src": normalisedSrc.value.lazySrc,
- "alt": props.alt
- }, null)]
- });
- const __placeholder = () => {
- if (!slots.placeholder) return null;
- return createVNode(MaybeTransition, {
- "transition": props.transition,
- "appear": true
- }, {
- default: () => [(state.value === 'loading' || state.value === 'error' && !slots.error) && createVNode("div", {
- "class": "v-img__placeholder"
- }, [slots.placeholder()])]
- });
- };
- const __error = () => {
- if (!slots.error) return null;
- return createVNode(MaybeTransition, {
- "transition": props.transition,
- "appear": true
- }, {
- default: () => [state.value === 'error' && createVNode("div", {
- "class": "v-img__error"
- }, [slots.error()])]
- });
- };
- const __gradient = () => {
- if (!props.gradient) return null;
- return createVNode("div", {
- "class": "v-img__gradient",
- "style": {
- backgroundImage: `linear-gradient(${props.gradient})`
- }
- }, null);
- };
- const isBooted = shallowRef(false);
- {
- const stop = watch(aspectRatio, val => {
- if (val) {
- // Doesn't work with nextTick, idk why
- requestAnimationFrame(() => {
- requestAnimationFrame(() => {
- isBooted.value = true;
- });
- });
- stop();
- }
- });
- }
- useRender(() => {
- const [responsiveProps] = VResponsive.filterProps(props);
- return withDirectives(createVNode(VResponsive, mergeProps({
- "class": ['v-img', {
- 'v-img--booting': !isBooted.value
- }, props.class],
- "style": [{
- width: convertToUnit(props.width === 'auto' ? naturalWidth.value : props.width)
- }, props.style]
- }, responsiveProps, {
- "aspectRatio": aspectRatio.value,
- "aria-label": props.alt,
- "role": props.alt ? 'img' : undefined
- }), {
- additional: () => createVNode(Fragment, null, [createVNode(__image, null, null), createVNode(__preloadImage, null, null), createVNode(__gradient, null, null), createVNode(__placeholder, null, null), createVNode(__error, null, null)]),
- default: slots.default
- }), [[resolveDirective("intersect"), {
- handler: init,
- options: props.options
- }, null, {
- once: true
- }]]);
- });
- return {
- currentSrc,
- image,
- state,
- naturalWidth,
- naturalHeight
- };
- }
- });
- // Utilities
- // Types
- // Composables
- const makeBorderProps = propsFactory({
- border: [Boolean, Number, String]
- }, 'border');
- function useBorder(props) {
- let name = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : getCurrentInstanceName();
- const borderClasses = computed(() => {
- const border = isRef(props) ? props.value : props.border;
- const classes = [];
- if (border === true || border === '') {
- classes.push(`${name}--border`);
- } else if (typeof border === 'string' || border === 0) {
- for (const value of String(border).split(' ')) {
- classes.push(`border-${value}`);
- }
- }
- return classes;
- });
- return {
- borderClasses
- };
- }
- // Utilities
- // Types
- // Composables
- function useColor(colors) {
- return destructComputed(() => {
- const classes = [];
- const styles = {};
- if (colors.value.background) {
- if (isCssColor(colors.value.background)) {
- styles.backgroundColor = colors.value.background;
- } else {
- classes.push(`bg-${colors.value.background}`);
- }
- }
- if (colors.value.text) {
- if (isCssColor(colors.value.text)) {
- styles.color = colors.value.text;
- styles.caretColor = colors.value.text;
- } else {
- classes.push(`text-${colors.value.text}`);
- }
- }
- return {
- colorClasses: classes,
- colorStyles: styles
- };
- });
- }
- function useTextColor(props, name) {
- const colors = computed(() => ({
- text: isRef(props) ? props.value : name ? props[name] : null
- }));
- const {
- colorClasses: textColorClasses,
- colorStyles: textColorStyles
- } = useColor(colors);
- return {
- textColorClasses,
- textColorStyles
- };
- }
- function useBackgroundColor(props, name) {
- const colors = computed(() => ({
- background: isRef(props) ? props.value : name ? props[name] : null
- }));
- const {
- colorClasses: backgroundColorClasses,
- colorStyles: backgroundColorStyles
- } = useColor(colors);
- return {
- backgroundColorClasses,
- backgroundColorStyles
- };
- }
- // Utilities
- // Types
- // Composables
- const makeElevationProps = propsFactory({
- elevation: {
- type: [Number, String],
- validator(v) {
- const value = parseInt(v);
- return !isNaN(value) && value >= 0 &&
- // Material Design has a maximum elevation of 24
- // https://material.io/design/environment/elevation.html#default-elevations
- value <= 24;
- }
- }
- }, 'elevation');
- function useElevation(props) {
- const elevationClasses = computed(() => {
- const elevation = isRef(props) ? props.value : props.elevation;
- const classes = [];
- if (elevation == null) return classes;
- classes.push(`elevation-${elevation}`);
- return classes;
- });
- return {
- elevationClasses
- };
- }
- // Utilities
- // Types
- // Composables
- const makeRoundedProps = propsFactory({
- rounded: {
- type: [Boolean, Number, String],
- default: undefined
- }
- }, 'rounded');
- function useRounded(props) {
- let name = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : getCurrentInstanceName();
- const roundedClasses = computed(() => {
- const rounded = isRef(props) ? props.value : props.rounded;
- const classes = [];
- if (rounded === true || rounded === '') {
- classes.push(`${name}--rounded`);
- } else if (typeof rounded === 'string' || rounded === 0) {
- for (const value of String(rounded).split(' ')) {
- classes.push(`rounded-${value}`);
- }
- }
- return classes;
- });
- return {
- roundedClasses
- };
- }
- // Types
- const allowedDensities$1 = [null, 'prominent', 'default', 'comfortable', 'compact'];
- const makeVToolbarProps = propsFactory({
- absolute: Boolean,
- collapse: Boolean,
- color: String,
- density: {
- type: String,
- default: 'default',
- validator: v => allowedDensities$1.includes(v)
- },
- extended: Boolean,
- extensionHeight: {
- type: [Number, String],
- default: 48
- },
- flat: Boolean,
- floating: Boolean,
- height: {
- type: [Number, String],
- default: 64
- },
- image: String,
- title: String,
- ...makeBorderProps(),
- ...makeComponentProps(),
- ...makeElevationProps(),
- ...makeRoundedProps(),
- ...makeTagProps({
- tag: 'header'
- }),
- ...makeThemeProps()
- }, 'VToolbar');
- const VToolbar = genericComponent()({
- name: 'VToolbar',
- props: makeVToolbarProps(),
- setup(props, _ref) {
- let {
- slots
- } = _ref;
- const {
- backgroundColorClasses,
- backgroundColorStyles
- } = useBackgroundColor(toRef(props, 'color'));
- const {
- borderClasses
- } = useBorder(props);
- const {
- elevationClasses
- } = useElevation(props);
- const {
- roundedClasses
- } = useRounded(props);
- const {
- themeClasses
- } = provideTheme(props);
- const {
- rtlClasses
- } = useRtl();
- const isExtended = shallowRef(!!(props.extended || slots.extension?.()));
- const contentHeight = computed(() => parseInt(Number(props.height) + (props.density === 'prominent' ? Number(props.height) : 0) - (props.density === 'comfortable' ? 8 : 0) - (props.density === 'compact' ? 16 : 0), 10));
- const extensionHeight = computed(() => isExtended.value ? parseInt(Number(props.extensionHeight) + (props.density === 'prominent' ? Number(props.extensionHeight) : 0) - (props.density === 'comfortable' ? 4 : 0) - (props.density === 'compact' ? 8 : 0), 10) : 0);
- provideDefaults({
- VBtn: {
- variant: 'text'
- }
- });
- useRender(() => {
- const hasTitle = !!(props.title || slots.title);
- const hasImage = !!(slots.image || props.image);
- const extension = slots.extension?.();
- isExtended.value = !!(props.extended || extension);
- return createVNode(props.tag, {
- "class": ['v-toolbar', {
- 'v-toolbar--absolute': props.absolute,
- 'v-toolbar--collapse': props.collapse,
- 'v-toolbar--flat': props.flat,
- 'v-toolbar--floating': props.floating,
- [`v-toolbar--density-${props.density}`]: true
- }, backgroundColorClasses.value, borderClasses.value, elevationClasses.value, roundedClasses.value, themeClasses.value, rtlClasses.value, props.class],
- "style": [backgroundColorStyles.value, props.style]
- }, {
- default: () => [hasImage && createVNode("div", {
- "key": "image",
- "class": "v-toolbar__image"
- }, [!slots.image ? createVNode(VImg, {
- "key": "image-img",
- "cover": true,
- "src": props.image
- }, null) : createVNode(VDefaultsProvider, {
- "key": "image-defaults",
- "disabled": !props.image,
- "defaults": {
- VImg: {
- cover: true,
- src: props.image
- }
- }
- }, slots.image)]), createVNode(VDefaultsProvider, {
- "defaults": {
- VTabs: {
- height: convertToUnit(contentHeight.value)
- }
- }
- }, {
- default: () => [createVNode("div", {
- "class": "v-toolbar__content",
- "style": {
- height: convertToUnit(contentHeight.value)
- }
- }, [slots.prepend && createVNode("div", {
- "class": "v-toolbar__prepend"
- }, [slots.prepend?.()]), hasTitle && createVNode(VToolbarTitle, {
- "key": "title",
- "text": props.title
- }, {
- text: slots.title
- }), slots.default?.(), slots.append && createVNode("div", {
- "class": "v-toolbar__append"
- }, [slots.append?.()])])]
- }), createVNode(VDefaultsProvider, {
- "defaults": {
- VTabs: {
- height: convertToUnit(extensionHeight.value)
- }
- }
- }, {
- default: () => [createVNode(VExpandTransition, null, {
- default: () => [isExtended.value && createVNode("div", {
- "class": "v-toolbar__extension",
- "style": {
- height: convertToUnit(extensionHeight.value)
- }
- }, [extension])]
- })]
- })]
- });
- });
- return {
- contentHeight,
- extensionHeight
- };
- }
- });
- // Utilities
- // Types
- // Composables
- const makeScrollProps = propsFactory({
- scrollTarget: {
- type: String
- },
- scrollThreshold: {
- type: [String, Number],
- default: 300
- }
- }, 'scroll');
- function useScroll(props) {
- let args = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
- const {
- canScroll
- } = args;
- let previousScroll = 0;
- const target = ref(null);
- const currentScroll = shallowRef(0);
- const savedScroll = shallowRef(0);
- const currentThreshold = shallowRef(0);
- const isScrollActive = shallowRef(false);
- const isScrollingUp = shallowRef(false);
- const scrollThreshold = computed(() => {
- return Number(props.scrollThreshold);
- });
- /**
- * 1: at top
- * 0: at threshold
- */
- const scrollRatio = computed(() => {
- return clamp((scrollThreshold.value - currentScroll.value) / scrollThreshold.value || 0);
- });
- const onScroll = () => {
- const targetEl = target.value;
- if (!targetEl || canScroll && !canScroll.value) return;
- previousScroll = currentScroll.value;
- currentScroll.value = 'window' in targetEl ? targetEl.pageYOffset : targetEl.scrollTop;
- isScrollingUp.value = currentScroll.value < previousScroll;
- currentThreshold.value = Math.abs(currentScroll.value - scrollThreshold.value);
- };
- watch(isScrollingUp, () => {
- savedScroll.value = savedScroll.value || currentScroll.value;
- });
- watch(isScrollActive, () => {
- savedScroll.value = 0;
- });
- onMounted(() => {
- watch(() => props.scrollTarget, scrollTarget => {
- const newTarget = scrollTarget ? document.querySelector(scrollTarget) : window;
- if (!newTarget) {
- consoleWarn(`Unable to locate element with identifier ${scrollTarget}`);
- return;
- }
- if (newTarget === target.value) return;
- target.value?.removeEventListener('scroll', onScroll);
- target.value = newTarget;
- target.value.addEventListener('scroll', onScroll, {
- passive: true
- });
- }, {
- immediate: true
- });
- });
- onBeforeUnmount(() => {
- target.value?.removeEventListener('scroll', onScroll);
- });
- // Do we need this? If yes - seems that
- // there's no need to expose onScroll
- canScroll && watch(canScroll, onScroll, {
- immediate: true
- });
- return {
- scrollThreshold,
- currentScroll,
- currentThreshold,
- isScrollActive,
- scrollRatio,
- // required only for testing
- // probably can be removed
- // later (2 chars chlng)
- isScrollingUp,
- savedScroll
- };
- }
- // Utilities
- // Composables
- function useSsrBoot() {
- const isBooted = shallowRef(false);
- onMounted(() => {
- window.requestAnimationFrame(() => {
- isBooted.value = true;
- });
- });
- const ssrBootStyles = computed(() => !isBooted.value ? {
- transition: 'none !important'
- } : undefined);
- return {
- ssrBootStyles,
- isBooted: readonly(isBooted)
- };
- }
- // Types
- const makeVAppBarProps = propsFactory({
- scrollBehavior: String,
- modelValue: {
- type: Boolean,
- default: true
- },
- location: {
- type: String,
- default: 'top',
- validator: value => ['top', 'bottom'].includes(value)
- },
- ...makeVToolbarProps(),
- ...makeLayoutItemProps(),
- ...makeScrollProps(),
- height: {
- type: [Number, String],
- default: 64
- }
- }, 'VAppBar');
- const VAppBar = genericComponent()({
- name: 'VAppBar',
- props: makeVAppBarProps(),
- emits: {
- 'update:modelValue': value => true
- },
- setup(props, _ref) {
- let {
- slots
- } = _ref;
- const vToolbarRef = ref();
- const isActive = useProxiedModel(props, 'modelValue');
- const scrollBehavior = computed(() => {
- const behavior = new Set(props.scrollBehavior?.split(' ') ?? []);
- return {
- hide: behavior.has('hide'),
- // fullyHide: behavior.has('fully-hide'),
- inverted: behavior.has('inverted'),
- collapse: behavior.has('collapse'),
- elevate: behavior.has('elevate'),
- fadeImage: behavior.has('fade-image')
- // shrink: behavior.has('shrink'),
- };
- });
- const canScroll = computed(() => {
- const behavior = scrollBehavior.value;
- return behavior.hide ||
- // behavior.fullyHide ||
- behavior.inverted || behavior.collapse || behavior.elevate || behavior.fadeImage ||
- // behavior.shrink ||
- !isActive.value;
- });
- const {
- currentScroll,
- scrollThreshold,
- isScrollingUp,
- scrollRatio
- } = useScroll(props, {
- canScroll
- });
- const isCollapsed = computed(() => props.collapse || scrollBehavior.value.collapse && (scrollBehavior.value.inverted ? scrollRatio.value > 0 : scrollRatio.value === 0));
- const isFlat = computed(() => props.flat || scrollBehavior.value.elevate && (scrollBehavior.value.inverted ? currentScroll.value > 0 : currentScroll.value === 0));
- const opacity = computed(() => scrollBehavior.value.fadeImage ? scrollBehavior.value.inverted ? 1 - scrollRatio.value : scrollRatio.value : undefined);
- const height = computed(() => {
- if (scrollBehavior.value.hide && scrollBehavior.value.inverted) return 0;
- const height = vToolbarRef.value?.contentHeight ?? 0;
- const extensionHeight = vToolbarRef.value?.extensionHeight ?? 0;
- return height + extensionHeight;
- });
- useToggleScope(computed(() => !!props.scrollBehavior), () => {
- watchEffect(() => {
- if (scrollBehavior.value.hide) {
- if (scrollBehavior.value.inverted) {
- isActive.value = currentScroll.value > scrollThreshold.value;
- } else {
- isActive.value = isScrollingUp.value || currentScroll.value < scrollThreshold.value;
- }
- } else {
- isActive.value = true;
- }
- });
- });
- const {
- ssrBootStyles
- } = useSsrBoot();
- const {
- layoutItemStyles
- } = useLayoutItem({
- id: props.name,
- order: computed(() => parseInt(props.order, 10)),
- position: toRef(props, 'location'),
- layoutSize: height,
- elementSize: shallowRef(undefined),
- active: isActive,
- absolute: toRef(props, 'absolute')
- });
- useRender(() => {
- const [toolbarProps] = VToolbar.filterProps(props);
- return createVNode(VToolbar, mergeProps({
- "ref": vToolbarRef,
- "class": ['v-app-bar', {
- 'v-app-bar--bottom': props.location === 'bottom'
- }, props.class],
- "style": [{
- ...layoutItemStyles.value,
- '--v-toolbar-image-opacity': opacity.value,
- height: undefined,
- ...ssrBootStyles.value
- }, props.style]
- }, toolbarProps, {
- "collapse": isCollapsed.value,
- "flat": isFlat.value
- }), slots);
- });
- return {};
- }
- });
- // Utilities
- // Types
- const allowedDensities = [null, 'default', 'comfortable', 'compact'];
- // typeof allowedDensities[number] evalutes to any
- // when generating api types for whatever reason.
- // Composables
- const makeDensityProps = propsFactory({
- density: {
- type: String,
- default: 'default',
- validator: v => allowedDensities.includes(v)
- }
- }, 'density');
- function useDensity(props) {
- let name = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : getCurrentInstanceName();
- const densityClasses = computed(() => {
- return `${name}--density-${props.density}`;
- });
- return {
- densityClasses
- };
- }
- // Types
- const allowedVariants$2 = ['elevated', 'flat', 'tonal', 'outlined', 'text', 'plain'];
- function genOverlays(isClickable, name) {
- return createVNode(Fragment, null, [isClickable && createVNode("span", {
- "key": "overlay",
- "class": `${name}__overlay`
- }, null), createVNode("span", {
- "key": "underlay",
- "class": `${name}__underlay`
- }, null)]);
- }
- const makeVariantProps = propsFactory({
- color: String,
- variant: {
- type: String,
- default: 'elevated',
- validator: v => allowedVariants$2.includes(v)
- }
- }, 'variant');
- function useVariant(props) {
- let name = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : getCurrentInstanceName();
- const variantClasses = computed(() => {
- const {
- variant
- } = unref(props);
- return `${name}--variant-${variant}`;
- });
- const {
- colorClasses,
- colorStyles
- } = useColor(computed(() => {
- const {
- variant,
- color
- } = unref(props);
- return {
- [['elevated', 'flat'].includes(variant) ? 'background' : 'text']: color
- };
- }));
- return {
- colorClasses,
- colorStyles,
- variantClasses
- };
- }
- const makeVBtnGroupProps = propsFactory({
- divided: Boolean,
- ...makeBorderProps(),
- ...makeComponentProps(),
- ...makeDensityProps(),
- ...makeElevationProps(),
- ...makeRoundedProps(),
- ...makeTagProps(),
- ...makeThemeProps(),
- ...makeVariantProps()
- }, 'VBtnGroup');
- const VBtnGroup = genericComponent()({
- name: 'VBtnGroup',
- props: makeVBtnGroupProps(),
- setup(props, _ref) {
- let {
- slots
- } = _ref;
- const {
- themeClasses
- } = provideTheme(props);
- const {
- densityClasses
- } = useDensity(props);
- const {
- borderClasses
- } = useBorder(props);
- const {
- elevationClasses
- } = useElevation(props);
- const {
- roundedClasses
- } = useRounded(props);
- provideDefaults({
- VBtn: {
- height: 'auto',
- color: toRef(props, 'color'),
- density: toRef(props, 'density'),
- flat: true,
- variant: toRef(props, 'variant')
- }
- });
- useRender(() => {
- return createVNode(props.tag, {
- "class": ['v-btn-group', {
- 'v-btn-group--divided': props.divided
- }, themeClasses.value, borderClasses.value, densityClasses.value, elevationClasses.value, roundedClasses.value, props.class],
- "style": props.style
- }, slots);
- });
- }
- });
- // Composables
- // Types
- const makeGroupProps = propsFactory({
- modelValue: {
- type: null,
- default: undefined
- },
- multiple: Boolean,
- mandatory: [Boolean, String],
- max: Number,
- selectedClass: String,
- disabled: Boolean
- }, 'group');
- const makeGroupItemProps = propsFactory({
- value: null,
- disabled: Boolean,
- selectedClass: String
- }, 'group-item');
- function useGroupItem(props, injectKey) {
- let required = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : true;
- const vm = getCurrentInstance('useGroupItem');
- if (!vm) {
- throw new Error('[Vuetify] useGroupItem composable must be used inside a component setup function');
- }
- const id = getUid();
- provide(Symbol.for(`${injectKey.description}:id`), id);
- const group = inject$1(injectKey, null);
- if (!group) {
- if (!required) return group;
- throw new Error(`[Vuetify] Could not find useGroup injection with symbol ${injectKey.description}`);
- }
- const value = toRef(props, 'value');
- const disabled = computed(() => !!(group.disabled.value || props.disabled));
- group.register({
- id,
- value,
- disabled
- }, vm);
- onBeforeUnmount(() => {
- group.unregister(id);
- });
- const isSelected = computed(() => {
- return group.isSelected(id);
- });
- const selectedClass = computed(() => isSelected.value && [group.selectedClass.value, props.selectedClass]);
- watch(isSelected, value => {
- vm.emit('group:selected', {
- value
- });
- });
- return {
- id,
- isSelected,
- toggle: () => group.select(id, !isSelected.value),
- select: value => group.select(id, value),
- selectedClass,
- value,
- disabled,
- group
- };
- }
- function useGroup(props, injectKey) {
- let isUnmounted = false;
- const items = reactive([]);
- const selected = useProxiedModel(props, 'modelValue', [], v => {
- if (v == null) return [];
- return getIds(items, wrapInArray(v));
- }, v => {
- const arr = getValues(items, v);
- return props.multiple ? arr : arr[0];
- });
- const groupVm = getCurrentInstance('useGroup');
- function register(item, vm) {
- // Is there a better way to fix this typing?
- const unwrapped = item;
- const key = Symbol.for(`${injectKey.description}:id`);
- const children = findChildrenWithProvide(key, groupVm?.vnode);
- const index = children.indexOf(vm);
- if (index > -1) {
- items.splice(index, 0, unwrapped);
- } else {
- items.push(unwrapped);
- }
- }
- function unregister(id) {
- if (isUnmounted) return;
- // TODO: re-evaluate this line's importance in the future
- // should we only modify the model if mandatory is set.
- // selected.value = selected.value.filter(v => v !== id)
- forceMandatoryValue();
- const index = items.findIndex(item => item.id === id);
- items.splice(index, 1);
- }
- // If mandatory and nothing is selected, then select first non-disabled item
- function forceMandatoryValue() {
- const item = items.find(item => !item.disabled);
- if (item && props.mandatory === 'force' && !selected.value.length) {
- selected.value = [item.id];
- }
- }
- onMounted(() => {
- forceMandatoryValue();
- });
- onBeforeUnmount(() => {
- isUnmounted = true;
- });
- function select(id, value) {
- const item = items.find(item => item.id === id);
- if (value && item?.disabled) return;
- if (props.multiple) {
- const internalValue = selected.value.slice();
- const index = internalValue.findIndex(v => v === id);
- const isSelected = ~index;
- value = value ?? !isSelected;
- // We can't remove value if group is
- // mandatory, value already exists,
- // and it is the only value
- if (isSelected && props.mandatory && internalValue.length <= 1) return;
- // We can't add value if it would
- // cause max limit to be exceeded
- if (!isSelected && props.max != null && internalValue.length + 1 > props.max) return;
- if (index < 0 && value) internalValue.push(id);else if (index >= 0 && !value) internalValue.splice(index, 1);
- selected.value = internalValue;
- } else {
- const isSelected = selected.value.includes(id);
- if (props.mandatory && isSelected) return;
- selected.value = value ?? !isSelected ? [id] : [];
- }
- }
- function step(offset) {
- // getting an offset from selected value obviously won't work with multiple values
- if (props.multiple) consoleWarn('This method is not supported when using "multiple" prop');
- if (!selected.value.length) {
- const item = items.find(item => !item.disabled);
- item && (selected.value = [item.id]);
- } else {
- const currentId = selected.value[0];
- const currentIndex = items.findIndex(i => i.id === currentId);
- let newIndex = (currentIndex + offset) % items.length;
- let newItem = items[newIndex];
- while (newItem.disabled && newIndex !== currentIndex) {
- newIndex = (newIndex + offset) % items.length;
- newItem = items[newIndex];
- }
- if (newItem.disabled) return;
- selected.value = [items[newIndex].id];
- }
- }
- const state = {
- register,
- unregister,
- selected,
- select,
- disabled: toRef(props, 'disabled'),
- prev: () => step(items.length - 1),
- next: () => step(1),
- isSelected: id => selected.value.includes(id),
- selectedClass: computed(() => props.selectedClass),
- items: computed(() => items),
- getItemIndex: value => getItemIndex(items, value)
- };
- provide(injectKey, state);
- return state;
- }
- function getItemIndex(items, value) {
- const ids = getIds(items, [value]);
- if (!ids.length) return -1;
- return items.findIndex(item => item.id === ids[0]);
- }
- function getIds(items, modelValue) {
- const ids = [];
- modelValue.forEach(value => {
- const item = items.find(item => deepEqual(value, item.value));
- const itemByIndex = items[value];
- if (item?.value != null) {
- ids.push(item.id);
- } else if (itemByIndex != null) {
- ids.push(itemByIndex.id);
- }
- });
- return ids;
- }
- function getValues(items, ids) {
- const values = [];
- ids.forEach(id => {
- const itemIndex = items.findIndex(item => item.id === id);
- if (~itemIndex) {
- const item = items[itemIndex];
- values.push(item.value != null ? item.value : itemIndex);
- }
- });
- return values;
- }
- // Types
- const VBtnToggleSymbol = Symbol.for('vuetify:v-btn-toggle');
- const makeVBtnToggleProps = propsFactory({
- ...makeVBtnGroupProps(),
- ...makeGroupProps()
- }, 'VBtnToggle');
- const VBtnToggle = genericComponent()({
- name: 'VBtnToggle',
- props: makeVBtnToggleProps(),
- emits: {
- 'update:modelValue': value => true
- },
- setup(props, _ref) {
- let {
- slots
- } = _ref;
- const {
- isSelected,
- next,
- prev,
- select,
- selected
- } = useGroup(props, VBtnToggleSymbol);
- useRender(() => {
- const [btnGroupProps] = VBtnGroup.filterProps(props);
- return createVNode(VBtnGroup, mergeProps({
- "class": ['v-btn-toggle', props.class]
- }, btnGroupProps, {
- "style": props.style
- }), {
- default: () => [slots.default?.({
- isSelected,
- next,
- prev,
- select,
- selected
- })]
- });
- });
- return {
- next,
- prev,
- select
- };
- }
- });
- // Composables
- // Types
- const aliases = {
- collapse: 'mdi-chevron-up',
- complete: 'mdi-check',
- cancel: 'mdi-close-circle',
- close: 'mdi-close',
- delete: 'mdi-close-circle',
- // delete (e.g. v-chip close)
- clear: 'mdi-close-circle',
- success: 'mdi-check-circle',
- info: 'mdi-information',
- warning: 'mdi-alert-circle',
- error: 'mdi-close-circle',
- prev: 'mdi-chevron-left',
- next: 'mdi-chevron-right',
- checkboxOn: 'mdi-checkbox-marked',
- checkboxOff: 'mdi-checkbox-blank-outline',
- checkboxIndeterminate: 'mdi-minus-box',
- delimiter: 'mdi-circle',
- // for carousel
- sortAsc: 'mdi-arrow-up',
- sortDesc: 'mdi-arrow-down',
- expand: 'mdi-chevron-down',
- menu: 'mdi-menu',
- subgroup: 'mdi-menu-down',
- dropdown: 'mdi-menu-down',
- radioOn: 'mdi-radiobox-marked',
- radioOff: 'mdi-radiobox-blank',
- edit: 'mdi-pencil',
- ratingEmpty: 'mdi-star-outline',
- ratingFull: 'mdi-star',
- ratingHalf: 'mdi-star-half-full',
- loading: 'mdi-cached',
- first: 'mdi-page-first',
- last: 'mdi-page-last',
- unfold: 'mdi-unfold-more-horizontal',
- file: 'mdi-paperclip',
- plus: 'mdi-plus',
- minus: 'mdi-minus',
- calendar: 'mdi-calendar'
- };
- const mdi = {
- // Not using mergeProps here, functional components merge props by default (?)
- component: props => h(VClassIcon, {
- ...props,
- class: 'mdi'
- })
- };
- // Types
- const IconValue = [String, Function, Object, Array];
- const IconSymbol = Symbol.for('vuetify:icons');
- const makeIconProps = propsFactory({
- icon: {
- type: IconValue
- },
- // Could not remove this and use makeTagProps, types complained because it is not required
- tag: {
- type: String,
- required: true
- }
- }, 'icon');
- const VComponentIcon = genericComponent()({
- name: 'VComponentIcon',
- props: makeIconProps(),
- setup(props, _ref) {
- let {
- slots
- } = _ref;
- return () => {
- const Icon = props.icon;
- return createVNode(props.tag, null, {
- default: () => [props.icon ? createVNode(Icon, null, null) : slots.default?.()]
- });
- };
- }
- });
- const VSvgIcon = defineComponent({
- name: 'VSvgIcon',
- inheritAttrs: false,
- props: makeIconProps(),
- setup(props, _ref2) {
- let {
- attrs
- } = _ref2;
- return () => {
- return createVNode(props.tag, mergeProps(attrs, {
- "style": null
- }), {
- default: () => [createVNode("svg", {
- "class": "v-icon__svg",
- "xmlns": "http://www.w3.org/2000/svg",
- "viewBox": "0 0 24 24",
- "role": "img",
- "aria-hidden": "true"
- }, [Array.isArray(props.icon) ? props.icon.map(path => Array.isArray(path) ? createVNode("path", {
- "d": path[0],
- "fill-opacity": path[1]
- }, null) : createVNode("path", {
- "d": path
- }, null)) : createVNode("path", {
- "d": props.icon
- }, null)])]
- });
- };
- }
- });
- const VLigatureIcon = defineComponent({
- name: 'VLigatureIcon',
- props: makeIconProps(),
- setup(props) {
- return () => {
- return createVNode(props.tag, null, {
- default: () => [props.icon]
- });
- };
- }
- });
- const VClassIcon = defineComponent({
- name: 'VClassIcon',
- props: makeIconProps(),
- setup(props) {
- return () => {
- return createVNode(props.tag, {
- "class": props.icon
- }, null);
- };
- }
- });
- const defaultSets = {
- svg: {
- component: VSvgIcon
- },
- class: {
- component: VClassIcon
- }
- };
- // Composables
- function createIcons(options) {
- return mergeDeep({
- defaultSet: 'mdi',
- sets: {
- ...defaultSets,
- mdi
- },
- aliases: {
- ...aliases,
- /* eslint-disable max-len */
- vuetify: ['M8.2241 14.2009L12 21L22 3H14.4459L8.2241 14.2009Z', ['M7.26303 12.4733L7.00113 12L2 3H12.5261C12.5261 3 12.5261 3 12.5261 3L7.26303 12.4733Z', 0.6]],
- 'vuetify-outline': 'svg:M7.26 12.47 12.53 3H2L7.26 12.47ZM14.45 3 8.22 14.2 12 21 22 3H14.45ZM18.6 5 12 16.88 10.51 14.2 15.62 5ZM7.26 8.35 5.4 5H9.13L7.26 8.35Z'
- /* eslint-enable max-len */
- }
- }, options);
- }
- const useIcon = props => {
- const icons = inject$1(IconSymbol);
- if (!icons) throw new Error('Missing Vuetify Icons provide!');
- const iconData = computed(() => {
- const iconAlias = unref(props);
- if (!iconAlias) return {
- component: VComponentIcon
- };
- let icon = iconAlias;
- if (typeof icon === 'string') {
- icon = icon.trim();
- if (icon.startsWith('$')) {
- icon = icons.aliases?.[icon.slice(1)];
- }
- }
- if (!icon) throw new Error(`Could not find aliased icon "${iconAlias}"`);
- if (Array.isArray(icon)) {
- return {
- component: VSvgIcon,
- icon
- };
- } else if (typeof icon !== 'string') {
- return {
- component: VComponentIcon,
- icon
- };
- }
- const iconSetName = Object.keys(icons.sets).find(setName => typeof icon === 'string' && icon.startsWith(`${setName}:`));
- const iconName = iconSetName ? icon.slice(iconSetName.length + 1) : icon;
- const iconSet = icons.sets[iconSetName ?? icons.defaultSet];
- return {
- component: iconSet.component,
- icon: iconName
- };
- });
- return {
- iconData
- };
- };
- // Utilities
- // Types
- const predefinedSizes = ['x-small', 'small', 'default', 'large', 'x-large'];
- // Composables
- const makeSizeProps = propsFactory({
- size: {
- type: [String, Number],
- default: 'default'
- }
- }, 'size');
- function useSize(props) {
- let name = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : getCurrentInstanceName();
- return destructComputed(() => {
- let sizeClasses;
- let sizeStyles;
- if (includes(predefinedSizes, props.size)) {
- sizeClasses = `${name}--size-${props.size}`;
- } else if (props.size) {
- sizeStyles = {
- width: convertToUnit(props.size),
- height: convertToUnit(props.size)
- };
- }
- return {
- sizeClasses,
- sizeStyles
- };
- });
- }
- const makeVIconProps = propsFactory({
- color: String,
- start: Boolean,
- end: Boolean,
- icon: IconValue,
- ...makeComponentProps(),
- ...makeSizeProps(),
- ...makeTagProps({
- tag: 'i'
- }),
- ...makeThemeProps()
- }, 'VIcon');
- const VIcon = genericComponent()({
- name: 'VIcon',
- props: makeVIconProps(),
- setup(props, _ref) {
- let {
- attrs,
- slots
- } = _ref;
- const slotIcon = ref();
- const {
- themeClasses
- } = provideTheme(props);
- const {
- iconData
- } = useIcon(computed(() => slotIcon.value || props.icon));
- const {
- sizeClasses
- } = useSize(props);
- const {
- textColorClasses,
- textColorStyles
- } = useTextColor(toRef(props, 'color'));
- useRender(() => {
- const slotValue = slots.default?.();
- if (slotValue) {
- slotIcon.value = flattenFragments(slotValue).filter(node => node.type === Text && node.children && typeof node.children === 'string')[0]?.children;
- }
- return createVNode(iconData.value.component, {
- "tag": props.tag,
- "icon": iconData.value.icon,
- "class": ['v-icon', 'notranslate', themeClasses.value, sizeClasses.value, textColorClasses.value, {
- 'v-icon--clickable': !!attrs.onClick,
- 'v-icon--start': props.start,
- 'v-icon--end': props.end
- }, props.class],
- "style": [!sizeClasses.value ? {
- fontSize: convertToUnit(props.size),
- height: convertToUnit(props.size),
- width: convertToUnit(props.size)
- } : undefined, textColorStyles.value, props.style],
- "role": attrs.onClick ? 'button' : undefined,
- "aria-hidden": !attrs.onClick
- }, {
- default: () => [slotValue]
- });
- });
- return {};
- }
- });
- // Utilities
- function useIntersectionObserver(callback, options) {
- const intersectionRef = ref();
- const isIntersecting = shallowRef(false);
- if (SUPPORTS_INTERSECTION) {
- const observer = new IntersectionObserver(entries => {
- callback?.(entries, observer);
- isIntersecting.value = !!entries.find(entry => entry.isIntersecting);
- }, options);
- onBeforeUnmount(() => {
- observer.disconnect();
- });
- watch(intersectionRef, (newValue, oldValue) => {
- if (oldValue) {
- observer.unobserve(oldValue);
- isIntersecting.value = false;
- }
- if (newValue) observer.observe(newValue);
- }, {
- flush: 'post'
- });
- }
- return {
- intersectionRef,
- isIntersecting
- };
- }
- // Types
- const makeVProgressCircularProps = propsFactory({
- bgColor: String,
- color: String,
- indeterminate: [Boolean, String],
- modelValue: {
- type: [Number, String],
- default: 0
- },
- rotate: {
- type: [Number, String],
- default: 0
- },
- width: {
- type: [Number, String],
- default: 4
- },
- ...makeComponentProps(),
- ...makeSizeProps(),
- ...makeTagProps({
- tag: 'div'
- }),
- ...makeThemeProps()
- }, 'VProgressCircular');
- const VProgressCircular = genericComponent()({
- name: 'VProgressCircular',
- props: makeVProgressCircularProps(),
- setup(props, _ref) {
- let {
- slots
- } = _ref;
- const MAGIC_RADIUS_CONSTANT = 20;
- const CIRCUMFERENCE = 2 * Math.PI * MAGIC_RADIUS_CONSTANT;
- const root = ref();
- const {
- themeClasses
- } = provideTheme(props);
- const {
- sizeClasses,
- sizeStyles
- } = useSize(props);
- const {
- textColorClasses,
- textColorStyles
- } = useTextColor(toRef(props, 'color'));
- const {
- textColorClasses: underlayColorClasses,
- textColorStyles: underlayColorStyles
- } = useTextColor(toRef(props, 'bgColor'));
- const {
- intersectionRef,
- isIntersecting
- } = useIntersectionObserver();
- const {
- resizeRef,
- contentRect
- } = useResizeObserver();
- const normalizedValue = computed(() => Math.max(0, Math.min(100, parseFloat(props.modelValue))));
- const width = computed(() => Number(props.width));
- const size = computed(() => {
- // Get size from element if size prop value is small, large etc
- return sizeStyles.value ? Number(props.size) : contentRect.value ? contentRect.value.width : Math.max(width.value, 32);
- });
- const diameter = computed(() => MAGIC_RADIUS_CONSTANT / (1 - width.value / size.value) * 2);
- const strokeWidth = computed(() => width.value / size.value * diameter.value);
- const strokeDashOffset = computed(() => convertToUnit((100 - normalizedValue.value) / 100 * CIRCUMFERENCE));
- watchEffect(() => {
- intersectionRef.value = root.value;
- resizeRef.value = root.value;
- });
- useRender(() => createVNode(props.tag, {
- "ref": root,
- "class": ['v-progress-circular', {
- 'v-progress-circular--indeterminate': !!props.indeterminate,
- 'v-progress-circular--visible': isIntersecting.value,
- 'v-progress-circular--disable-shrink': props.indeterminate === 'disable-shrink'
- }, themeClasses.value, sizeClasses.value, textColorClasses.value, props.class],
- "style": [sizeStyles.value, textColorStyles.value, props.style],
- "role": "progressbar",
- "aria-valuemin": "0",
- "aria-valuemax": "100",
- "aria-valuenow": props.indeterminate ? undefined : normalizedValue.value
- }, {
- default: () => [createVNode("svg", {
- "style": {
- transform: `rotate(calc(-90deg + ${Number(props.rotate)}deg))`
- },
- "xmlns": "http://www.w3.org/2000/svg",
- "viewBox": `0 0 ${diameter.value} ${diameter.value}`
- }, [createVNode("circle", {
- "class": ['v-progress-circular__underlay', underlayColorClasses.value],
- "style": underlayColorStyles.value,
- "fill": "transparent",
- "cx": "50%",
- "cy": "50%",
- "r": MAGIC_RADIUS_CONSTANT,
- "stroke-width": strokeWidth.value,
- "stroke-dasharray": CIRCUMFERENCE,
- "stroke-dashoffset": 0
- }, null), createVNode("circle", {
- "class": "v-progress-circular__overlay",
- "fill": "transparent",
- "cx": "50%",
- "cy": "50%",
- "r": MAGIC_RADIUS_CONSTANT,
- "stroke-width": strokeWidth.value,
- "stroke-dasharray": CIRCUMFERENCE,
- "stroke-dashoffset": strokeDashOffset.value
- }, null)]), slots.default && createVNode("div", {
- "class": "v-progress-circular__content"
- }, [slots.default({
- value: normalizedValue.value
- })])]
- }));
- return {};
- }
- });
- // Composables
- // Types
- const oppositeMap = {
- center: 'center',
- top: 'bottom',
- bottom: 'top',
- left: 'right',
- right: 'left'
- };
- const makeLocationProps = propsFactory({
- location: String
- }, 'location');
- function useLocation(props) {
- let opposite = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : false;
- let offset = arguments.length > 2 ? arguments[2] : undefined;
- const {
- isRtl
- } = useRtl();
- const locationStyles = computed(() => {
- if (!props.location) return {};
- const {
- side,
- align
- } = parseAnchor(props.location.split(' ').length > 1 ? props.location : `${props.location} center`, isRtl.value);
- function getOffset(side) {
- return offset ? offset(side) : 0;
- }
- const styles = {};
- if (side !== 'center') {
- if (opposite) styles[oppositeMap[side]] = `calc(100% - ${getOffset(side)}px)`;else styles[side] = 0;
- }
- if (align !== 'center') {
- if (opposite) styles[oppositeMap[align]] = `calc(100% - ${getOffset(align)}px)`;else styles[align] = 0;
- } else {
- if (side === 'center') styles.top = styles.left = '50%';else {
- styles[{
- top: 'left',
- bottom: 'left',
- left: 'top',
- right: 'top'
- }[side]] = '50%';
- }
- styles.transform = {
- top: 'translateX(-50%)',
- bottom: 'translateX(-50%)',
- left: 'translateY(-50%)',
- right: 'translateY(-50%)',
- center: 'translate(-50%, -50%)'
- }[side];
- }
- return styles;
- });
- return {
- locationStyles
- };
- }
- const makeVProgressLinearProps = propsFactory({
- absolute: Boolean,
- active: {
- type: Boolean,
- default: true
- },
- bgColor: String,
- bgOpacity: [Number, String],
- bufferValue: {
- type: [Number, String],
- default: 0
- },
- clickable: Boolean,
- color: String,
- height: {
- type: [Number, String],
- default: 4
- },
- indeterminate: Boolean,
- max: {
- type: [Number, String],
- default: 100
- },
- modelValue: {
- type: [Number, String],
- default: 0
- },
- reverse: Boolean,
- stream: Boolean,
- striped: Boolean,
- roundedBar: Boolean,
- ...makeComponentProps(),
- ...makeLocationProps({
- location: 'top'
- }),
- ...makeRoundedProps(),
- ...makeTagProps(),
- ...makeThemeProps()
- }, 'VProgressLinear');
- const VProgressLinear = genericComponent()({
- name: 'VProgressLinear',
- props: makeVProgressLinearProps(),
- emits: {
- 'update:modelValue': value => true
- },
- setup(props, _ref) {
- let {
- slots
- } = _ref;
- const progress = useProxiedModel(props, 'modelValue');
- const {
- isRtl,
- rtlClasses
- } = useRtl();
- const {
- themeClasses
- } = provideTheme(props);
- const {
- locationStyles
- } = useLocation(props);
- const {
- textColorClasses,
- textColorStyles
- } = useTextColor(props, 'color');
- const {
- backgroundColorClasses,
- backgroundColorStyles
- } = useBackgroundColor(computed(() => props.bgColor || props.color));
- const {
- backgroundColorClasses: barColorClasses,
- backgroundColorStyles: barColorStyles
- } = useBackgroundColor(props, 'color');
- const {
- roundedClasses
- } = useRounded(props);
- const {
- intersectionRef,
- isIntersecting
- } = useIntersectionObserver();
- const max = computed(() => parseInt(props.max, 10));
- const height = computed(() => parseInt(props.height, 10));
- const normalizedBuffer = computed(() => parseFloat(props.bufferValue) / max.value * 100);
- const normalizedValue = computed(() => parseFloat(progress.value) / max.value * 100);
- const isReversed = computed(() => isRtl.value !== props.reverse);
- const transition = computed(() => props.indeterminate ? 'fade-transition' : 'slide-x-transition');
- const opacity = computed(() => {
- return props.bgOpacity == null ? props.bgOpacity : parseFloat(props.bgOpacity);
- });
- function handleClick(e) {
- if (!intersectionRef.value) return;
- const {
- left,
- right,
- width
- } = intersectionRef.value.getBoundingClientRect();
- const value = isReversed.value ? width - e.clientX + (right - width) : e.clientX - left;
- progress.value = Math.round(value / width * max.value);
- }
- useRender(() => createVNode(props.tag, {
- "ref": intersectionRef,
- "class": ['v-progress-linear', {
- 'v-progress-linear--absolute': props.absolute,
- 'v-progress-linear--active': props.active && isIntersecting.value,
- 'v-progress-linear--reverse': isReversed.value,
- 'v-progress-linear--rounded': props.rounded,
- 'v-progress-linear--rounded-bar': props.roundedBar,
- 'v-progress-linear--striped': props.striped
- }, roundedClasses.value, themeClasses.value, rtlClasses.value, props.class],
- "style": [{
- bottom: props.location === 'bottom' ? 0 : undefined,
- top: props.location === 'top' ? 0 : undefined,
- height: props.active ? convertToUnit(height.value) : 0,
- '--v-progress-linear-height': convertToUnit(height.value),
- ...locationStyles.value
- }, props.style],
- "role": "progressbar",
- "aria-hidden": props.active ? 'false' : 'true',
- "aria-valuemin": "0",
- "aria-valuemax": props.max,
- "aria-valuenow": props.indeterminate ? undefined : normalizedValue.value,
- "onClick": props.clickable && handleClick
- }, {
- default: () => [props.stream && createVNode("div", {
- "key": "stream",
- "class": ['v-progress-linear__stream', textColorClasses.value],
- "style": {
- ...textColorStyles.value,
- [isReversed.value ? 'left' : 'right']: convertToUnit(-height.value),
- borderTop: `${convertToUnit(height.value / 2)} dotted`,
- opacity: opacity.value,
- top: `calc(50% - ${convertToUnit(height.value / 4)})`,
- width: convertToUnit(100 - normalizedBuffer.value, '%'),
- '--v-progress-linear-stream-to': convertToUnit(height.value * (isReversed.value ? 1 : -1))
- }
- }, null), createVNode("div", {
- "class": ['v-progress-linear__background', backgroundColorClasses.value],
- "style": [backgroundColorStyles.value, {
- opacity: opacity.value,
- width: convertToUnit(!props.stream ? 100 : normalizedBuffer.value, '%')
- }]
- }, null), createVNode(Transition, {
- "name": transition.value
- }, {
- default: () => [!props.indeterminate ? createVNode("div", {
- "class": ['v-progress-linear__determinate', barColorClasses.value],
- "style": [barColorStyles.value, {
- width: convertToUnit(normalizedValue.value, '%')
- }]
- }, null) : createVNode("div", {
- "class": "v-progress-linear__indeterminate"
- }, [['long', 'short'].map(bar => createVNode("div", {
- "key": bar,
- "class": ['v-progress-linear__indeterminate', bar, barColorClasses.value],
- "style": barColorStyles.value
- }, null))])]
- }), slots.default && createVNode("div", {
- "class": "v-progress-linear__content"
- }, [slots.default({
- value: normalizedValue.value,
- buffer: normalizedBuffer.value
- })])]
- }));
- return {};
- }
- });
- // Types
- // Composables
- const makeLoaderProps = propsFactory({
- loading: [Boolean, String]
- }, 'loader');
- function useLoader(props) {
- let name = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : getCurrentInstanceName();
- const loaderClasses = computed(() => ({
- [`${name}--loading`]: props.loading
- }));
- return {
- loaderClasses
- };
- }
- function LoaderSlot(props, _ref) {
- let {
- slots
- } = _ref;
- return createVNode("div", {
- "class": `${props.name}__loader`
- }, [slots.default?.({
- color: props.color,
- isActive: props.active
- }) || createVNode(VProgressLinear, {
- "active": props.active,
- "color": props.color,
- "height": "2",
- "indeterminate": true
- }, null)]);
- }
- // Utilities
- // Types
- const positionValues = ['static', 'relative', 'fixed', 'absolute', 'sticky'];
- // Composables
- const makePositionProps = propsFactory({
- position: {
- type: String,
- validator: /* istanbul ignore next */v => positionValues.includes(v)
- }
- }, 'position');
- function usePosition(props) {
- let name = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : getCurrentInstanceName();
- const positionClasses = computed(() => {
- return props.position ? `${name}--${props.position}` : undefined;
- });
- return {
- positionClasses
- };
- }
- // Utilities
- function useRouter() {
- return getCurrentInstance('useRouter')?.proxy?.$router;
- }
- function useLink(props, attrs) {
- const RouterLink = resolveDynamicComponent('RouterLink');
- const isLink = computed(() => !!(props.href || props.to));
- const isClickable = computed(() => {
- return isLink?.value || hasEvent(attrs, 'click') || hasEvent(props, 'click');
- });
- if (typeof RouterLink === 'string') {
- return {
- isLink,
- isClickable,
- href: toRef(props, 'href')
- };
- }
- const link = props.to ? RouterLink.useLink(props) : undefined;
- return {
- isLink,
- isClickable,
- route: link?.route,
- navigate: link?.navigate,
- isActive: link && computed(() => props.exact ? link.isExactActive?.value : link.isActive?.value),
- href: computed(() => props.to ? link?.route.value.href : props.href)
- };
- }
- const makeRouterProps = propsFactory({
- href: String,
- replace: Boolean,
- to: [String, Object],
- exact: Boolean
- }, 'router');
- let inTransition = false;
- function useBackButton(router, cb) {
- let popped = false;
- let removeBefore;
- let removeAfter;
- if (IN_BROWSER) {
- nextTick(() => {
- window.addEventListener('popstate', onPopstate);
- removeBefore = router?.beforeEach((to, from, next) => {
- if (!inTransition) {
- setTimeout(() => popped ? cb(next) : next());
- } else {
- popped ? cb(next) : next();
- }
- inTransition = true;
- });
- removeAfter = router?.afterEach(() => {
- inTransition = false;
- });
- });
- onScopeDispose(() => {
- window.removeEventListener('popstate', onPopstate);
- removeBefore?.();
- removeAfter?.();
- });
- }
- function onPopstate(e) {
- if (e.state?.replaced) return;
- popped = true;
- setTimeout(() => popped = false);
- }
- }
- // Utilities
- // Types
- function useSelectLink(link, select) {
- watch(() => link.isActive?.value, isActive => {
- if (link.isLink.value && isActive && select) {
- nextTick(() => {
- select(true);
- });
- }
- }, {
- immediate: true
- });
- }
- // Styles
- // Types
- const stopSymbol = Symbol('rippleStop');
- const DELAY_RIPPLE = 80;
- function transform(el, value) {
- el.style.transform = value;
- el.style.webkitTransform = value;
- }
- function isTouchEvent(e) {
- return e.constructor.name === 'TouchEvent';
- }
- function isKeyboardEvent(e) {
- return e.constructor.name === 'KeyboardEvent';
- }
- const calculate = function (e, el) {
- let value = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {};
- let localX = 0;
- let localY = 0;
- if (!isKeyboardEvent(e)) {
- const offset = el.getBoundingClientRect();
- const target = isTouchEvent(e) ? e.touches[e.touches.length - 1] : e;
- localX = target.clientX - offset.left;
- localY = target.clientY - offset.top;
- }
- let radius = 0;
- let scale = 0.3;
- if (el._ripple?.circle) {
- scale = 0.15;
- radius = el.clientWidth / 2;
- radius = value.center ? radius : radius + Math.sqrt((localX - radius) ** 2 + (localY - radius) ** 2) / 4;
- } else {
- radius = Math.sqrt(el.clientWidth ** 2 + el.clientHeight ** 2) / 2;
- }
- const centerX = `${(el.clientWidth - radius * 2) / 2}px`;
- const centerY = `${(el.clientHeight - radius * 2) / 2}px`;
- const x = value.center ? centerX : `${localX - radius}px`;
- const y = value.center ? centerY : `${localY - radius}px`;
- return {
- radius,
- scale,
- x,
- y,
- centerX,
- centerY
- };
- };
- const ripples = {
- /* eslint-disable max-statements */
- show(e, el) {
- let value = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {};
- if (!el?._ripple?.enabled) {
- return;
- }
- const container = document.createElement('span');
- const animation = document.createElement('span');
- container.appendChild(animation);
- container.className = 'v-ripple__container';
- if (value.class) {
- container.className += ` ${value.class}`;
- }
- const {
- radius,
- scale,
- x,
- y,
- centerX,
- centerY
- } = calculate(e, el, value);
- const size = `${radius * 2}px`;
- animation.className = 'v-ripple__animation';
- animation.style.width = size;
- animation.style.height = size;
- el.appendChild(container);
- const computed = window.getComputedStyle(el);
- if (computed && computed.position === 'static') {
- el.style.position = 'relative';
- el.dataset.previousPosition = 'static';
- }
- animation.classList.add('v-ripple__animation--enter');
- animation.classList.add('v-ripple__animation--visible');
- transform(animation, `translate(${x}, ${y}) scale3d(${scale},${scale},${scale})`);
- animation.dataset.activated = String(performance.now());
- setTimeout(() => {
- animation.classList.remove('v-ripple__animation--enter');
- animation.classList.add('v-ripple__animation--in');
- transform(animation, `translate(${centerX}, ${centerY}) scale3d(1,1,1)`);
- }, 0);
- },
- hide(el) {
- if (!el?._ripple?.enabled) return;
- const ripples = el.getElementsByClassName('v-ripple__animation');
- if (ripples.length === 0) return;
- const animation = ripples[ripples.length - 1];
- if (animation.dataset.isHiding) return;else animation.dataset.isHiding = 'true';
- const diff = performance.now() - Number(animation.dataset.activated);
- const delay = Math.max(250 - diff, 0);
- setTimeout(() => {
- animation.classList.remove('v-ripple__animation--in');
- animation.classList.add('v-ripple__animation--out');
- setTimeout(() => {
- const ripples = el.getElementsByClassName('v-ripple__animation');
- if (ripples.length === 1 && el.dataset.previousPosition) {
- el.style.position = el.dataset.previousPosition;
- delete el.dataset.previousPosition;
- }
- if (animation.parentNode?.parentNode === el) el.removeChild(animation.parentNode);
- }, 300);
- }, delay);
- }
- };
- function isRippleEnabled(value) {
- return typeof value === 'undefined' || !!value;
- }
- function rippleShow(e) {
- const value = {};
- const element = e.currentTarget;
- if (!element?._ripple || element._ripple.touched || e[stopSymbol]) return;
- // Don't allow the event to trigger ripples on any other elements
- e[stopSymbol] = true;
- if (isTouchEvent(e)) {
- element._ripple.touched = true;
- element._ripple.isTouch = true;
- } else {
- // It's possible for touch events to fire
- // as mouse events on Android/iOS, this
- // will skip the event call if it has
- // already been registered as touch
- if (element._ripple.isTouch) return;
- }
- value.center = element._ripple.centered || isKeyboardEvent(e);
- if (element._ripple.class) {
- value.class = element._ripple.class;
- }
- if (isTouchEvent(e)) {
- // already queued that shows or hides the ripple
- if (element._ripple.showTimerCommit) return;
- element._ripple.showTimerCommit = () => {
- ripples.show(e, element, value);
- };
- element._ripple.showTimer = window.setTimeout(() => {
- if (element?._ripple?.showTimerCommit) {
- element._ripple.showTimerCommit();
- element._ripple.showTimerCommit = null;
- }
- }, DELAY_RIPPLE);
- } else {
- ripples.show(e, element, value);
- }
- }
- function rippleStop(e) {
- e[stopSymbol] = true;
- }
- function rippleHide(e) {
- const element = e.currentTarget;
- if (!element?._ripple) return;
- window.clearTimeout(element._ripple.showTimer);
- // The touch interaction occurs before the show timer is triggered.
- // We still want to show ripple effect.
- if (e.type === 'touchend' && element._ripple.showTimerCommit) {
- element._ripple.showTimerCommit();
- element._ripple.showTimerCommit = null;
- // re-queue ripple hiding
- element._ripple.showTimer = window.setTimeout(() => {
- rippleHide(e);
- });
- return;
- }
- window.setTimeout(() => {
- if (element._ripple) {
- element._ripple.touched = false;
- }
- });
- ripples.hide(element);
- }
- function rippleCancelShow(e) {
- const element = e.currentTarget;
- if (!element?._ripple) return;
- if (element._ripple.showTimerCommit) {
- element._ripple.showTimerCommit = null;
- }
- window.clearTimeout(element._ripple.showTimer);
- }
- let keyboardRipple = false;
- function keyboardRippleShow(e) {
- if (!keyboardRipple && (e.keyCode === keyCodes.enter || e.keyCode === keyCodes.space)) {
- keyboardRipple = true;
- rippleShow(e);
- }
- }
- function keyboardRippleHide(e) {
- keyboardRipple = false;
- rippleHide(e);
- }
- function focusRippleHide(e) {
- if (keyboardRipple) {
- keyboardRipple = false;
- rippleHide(e);
- }
- }
- function updateRipple(el, binding, wasEnabled) {
- const {
- value,
- modifiers
- } = binding;
- const enabled = isRippleEnabled(value);
- if (!enabled) {
- ripples.hide(el);
- }
- el._ripple = el._ripple ?? {};
- el._ripple.enabled = enabled;
- el._ripple.centered = modifiers.center;
- el._ripple.circle = modifiers.circle;
- if (isObject(value) && value.class) {
- el._ripple.class = value.class;
- }
- if (enabled && !wasEnabled) {
- if (modifiers.stop) {
- el.addEventListener('touchstart', rippleStop, {
- passive: true
- });
- el.addEventListener('mousedown', rippleStop);
- return;
- }
- el.addEventListener('touchstart', rippleShow, {
- passive: true
- });
- el.addEventListener('touchend', rippleHide, {
- passive: true
- });
- el.addEventListener('touchmove', rippleCancelShow, {
- passive: true
- });
- el.addEventListener('touchcancel', rippleHide);
- el.addEventListener('mousedown', rippleShow);
- el.addEventListener('mouseup', rippleHide);
- el.addEventListener('mouseleave', rippleHide);
- el.addEventListener('keydown', keyboardRippleShow);
- el.addEventListener('keyup', keyboardRippleHide);
- el.addEventListener('blur', focusRippleHide);
- // Anchor tags can be dragged, causes other hides to fail - #1537
- el.addEventListener('dragstart', rippleHide, {
- passive: true
- });
- } else if (!enabled && wasEnabled) {
- removeListeners(el);
- }
- }
- function removeListeners(el) {
- el.removeEventListener('mousedown', rippleShow);
- el.removeEventListener('touchstart', rippleShow);
- el.removeEventListener('touchend', rippleHide);
- el.removeEventListener('touchmove', rippleCancelShow);
- el.removeEventListener('touchcancel', rippleHide);
- el.removeEventListener('mouseup', rippleHide);
- el.removeEventListener('mouseleave', rippleHide);
- el.removeEventListener('keydown', keyboardRippleShow);
- el.removeEventListener('keyup', keyboardRippleHide);
- el.removeEventListener('dragstart', rippleHide);
- el.removeEventListener('blur', focusRippleHide);
- }
- function mounted$4(el, binding) {
- updateRipple(el, binding, false);
- }
- function unmounted$4(el) {
- delete el._ripple;
- removeListeners(el);
- }
- function updated$1(el, binding) {
- if (binding.value === binding.oldValue) {
- return;
- }
- const wasEnabled = isRippleEnabled(binding.oldValue);
- updateRipple(el, binding, wasEnabled);
- }
- const Ripple = {
- mounted: mounted$4,
- unmounted: unmounted$4,
- updated: updated$1
- };
- // Types
- const makeVBtnProps = propsFactory({
- active: {
- type: Boolean,
- default: undefined
- },
- symbol: {
- type: null,
- default: VBtnToggleSymbol
- },
- flat: Boolean,
- icon: [Boolean, String, Function, Object],
- prependIcon: IconValue,
- appendIcon: IconValue,
- block: Boolean,
- stacked: Boolean,
- ripple: {
- type: [Boolean, Object],
- default: true
- },
- text: String,
- ...makeBorderProps(),
- ...makeComponentProps(),
- ...makeDensityProps(),
- ...makeDimensionProps(),
- ...makeElevationProps(),
- ...makeGroupItemProps(),
- ...makeLoaderProps(),
- ...makeLocationProps(),
- ...makePositionProps(),
- ...makeRoundedProps(),
- ...makeRouterProps(),
- ...makeSizeProps(),
- ...makeTagProps({
- tag: 'button'
- }),
- ...makeThemeProps(),
- ...makeVariantProps({
- variant: 'elevated'
- })
- }, 'VBtn');
- const VBtn = genericComponent()({
- name: 'VBtn',
- directives: {
- Ripple
- },
- props: makeVBtnProps(),
- emits: {
- 'group:selected': val => true
- },
- setup(props, _ref) {
- let {
- attrs,
- slots
- } = _ref;
- const {
- themeClasses
- } = provideTheme(props);
- const {
- borderClasses
- } = useBorder(props);
- const {
- colorClasses,
- colorStyles,
- variantClasses
- } = useVariant(props);
- const {
- densityClasses
- } = useDensity(props);
- const {
- dimensionStyles
- } = useDimension(props);
- const {
- elevationClasses
- } = useElevation(props);
- const {
- loaderClasses
- } = useLoader(props);
- const {
- locationStyles
- } = useLocation(props);
- const {
- positionClasses
- } = usePosition(props);
- const {
- roundedClasses
- } = useRounded(props);
- const {
- sizeClasses,
- sizeStyles
- } = useSize(props);
- const group = useGroupItem(props, props.symbol, false);
- const link = useLink(props, attrs);
- const isActive = computed(() => {
- if (props.active !== undefined) {
- return props.active;
- }
- if (link.isLink.value) {
- return link.isActive?.value;
- }
- return group?.isSelected.value;
- });
- const isDisabled = computed(() => group?.disabled.value || props.disabled);
- const isElevated = computed(() => {
- return props.variant === 'elevated' && !(props.disabled || props.flat || props.border);
- });
- const valueAttr = computed(() => {
- if (props.value === undefined) return undefined;
- return Object(props.value) === props.value ? JSON.stringify(props.value, null, 0) : props.value;
- });
- function onClick(e) {
- if (isDisabled.value || link.isLink.value && (e.metaKey || e.ctrlKey || e.shiftKey || e.button !== 0 || attrs.target === '_blank')) return;
- link.navigate?.(e);
- group?.toggle();
- }
- useSelectLink(link, group?.select);
- useRender(() => {
- const Tag = link.isLink.value ? 'a' : props.tag;
- const hasPrepend = !!(props.prependIcon || slots.prepend);
- const hasAppend = !!(props.appendIcon || slots.append);
- const hasIcon = !!(props.icon && props.icon !== true);
- const hasColor = group?.isSelected.value && (!link.isLink.value || link.isActive?.value) || !group || link.isActive?.value;
- return withDirectives(createVNode(Tag, {
- "type": Tag === 'a' ? undefined : 'button',
- "class": ['v-btn', group?.selectedClass.value, {
- 'v-btn--active': isActive.value,
- 'v-btn--block': props.block,
- 'v-btn--disabled': isDisabled.value,
- 'v-btn--elevated': isElevated.value,
- 'v-btn--flat': props.flat,
- 'v-btn--icon': !!props.icon,
- 'v-btn--loading': props.loading,
- 'v-btn--stacked': props.stacked
- }, themeClasses.value, borderClasses.value, hasColor ? colorClasses.value : undefined, densityClasses.value, elevationClasses.value, loaderClasses.value, positionClasses.value, roundedClasses.value, sizeClasses.value, variantClasses.value, props.class],
- "style": [hasColor ? colorStyles.value : undefined, dimensionStyles.value, locationStyles.value, sizeStyles.value, props.style],
- "disabled": isDisabled.value || undefined,
- "href": link.href.value,
- "onClick": onClick,
- "value": valueAttr.value
- }, {
- default: () => [genOverlays(true, 'v-btn'), !props.icon && hasPrepend && createVNode("span", {
- "key": "prepend",
- "class": "v-btn__prepend"
- }, [!slots.prepend ? createVNode(VIcon, {
- "key": "prepend-icon",
- "icon": props.prependIcon
- }, null) : createVNode(VDefaultsProvider, {
- "key": "prepend-defaults",
- "disabled": !props.prependIcon,
- "defaults": {
- VIcon: {
- icon: props.prependIcon
- }
- }
- }, slots.prepend)]), createVNode("span", {
- "class": "v-btn__content",
- "data-no-activator": ""
- }, [!slots.default && hasIcon ? createVNode(VIcon, {
- "key": "content-icon",
- "icon": props.icon
- }, null) : createVNode(VDefaultsProvider, {
- "key": "content-defaults",
- "disabled": !hasIcon,
- "defaults": {
- VIcon: {
- icon: props.icon
- }
- }
- }, {
- default: () => [slots.default?.() ?? props.text]
- })]), !props.icon && hasAppend && createVNode("span", {
- "key": "append",
- "class": "v-btn__append"
- }, [!slots.append ? createVNode(VIcon, {
- "key": "append-icon",
- "icon": props.appendIcon
- }, null) : createVNode(VDefaultsProvider, {
- "key": "append-defaults",
- "disabled": !props.appendIcon,
- "defaults": {
- VIcon: {
- icon: props.appendIcon
- }
- }
- }, slots.append)]), !!props.loading && createVNode("span", {
- "key": "loader",
- "class": "v-btn__loader"
- }, [slots.loader?.() ?? createVNode(VProgressCircular, {
- "color": typeof props.loading === 'boolean' ? undefined : props.loading,
- "indeterminate": true,
- "size": "23",
- "width": "2"
- }, null)])]
- }), [[resolveDirective("ripple"), !isDisabled.value && props.ripple, null]]);
- });
- return {};
- }
- });
- // Types
- const makeVAppBarNavIconProps = propsFactory({
- ...makeVBtnProps({
- icon: '$menu',
- variant: 'text'
- })
- }, 'VAppBarNavIcon');
- const VAppBarNavIcon = genericComponent()({
- name: 'VAppBarNavIcon',
- props: makeVAppBarNavIconProps(),
- setup(props, _ref) {
- let {
- slots
- } = _ref;
- useRender(() => createVNode(VBtn, mergeProps(props, {
- "class": ['v-app-bar-nav-icon']
- }), slots));
- return {};
- }
- });
- // Types
- const VAppBarTitle = genericComponent()({
- name: 'VAppBarTitle',
- props: makeVToolbarTitleProps(),
- setup(props, _ref) {
- let {
- slots
- } = _ref;
- useRender(() => createVNode(VToolbarTitle, mergeProps(props, {
- "class": "v-app-bar-title"
- }), slots));
- return {};
- }
- });
- // Utilities
- const VAlertTitle = createSimpleFunctional('v-alert-title');
- // Types
- const allowedTypes = ['success', 'info', 'warning', 'error'];
- const makeVAlertProps = propsFactory({
- border: {
- type: [Boolean, String],
- validator: val => {
- return typeof val === 'boolean' || ['top', 'end', 'bottom', 'start'].includes(val);
- }
- },
- borderColor: String,
- closable: Boolean,
- closeIcon: {
- type: IconValue,
- default: '$close'
- },
- closeLabel: {
- type: String,
- default: '$vuetify.close'
- },
- icon: {
- type: [Boolean, String, Function, Object],
- default: null
- },
- modelValue: {
- type: Boolean,
- default: true
- },
- prominent: Boolean,
- title: String,
- text: String,
- type: {
- type: String,
- validator: val => allowedTypes.includes(val)
- },
- ...makeComponentProps(),
- ...makeDensityProps(),
- ...makeDimensionProps(),
- ...makeElevationProps(),
- ...makeLocationProps(),
- ...makePositionProps(),
- ...makeRoundedProps(),
- ...makeTagProps(),
- ...makeThemeProps(),
- ...makeVariantProps({
- variant: 'flat'
- })
- }, 'VAlert');
- const VAlert = genericComponent()({
- name: 'VAlert',
- props: makeVAlertProps(),
- emits: {
- 'click:close': e => true,
- 'update:modelValue': value => true
- },
- setup(props, _ref) {
- let {
- emit,
- slots
- } = _ref;
- const isActive = useProxiedModel(props, 'modelValue');
- const icon = computed(() => {
- if (props.icon === false) return undefined;
- if (!props.type) return props.icon;
- return props.icon ?? `$${props.type}`;
- });
- const variantProps = computed(() => ({
- color: props.color ?? props.type,
- variant: props.variant
- }));
- const {
- themeClasses
- } = provideTheme(props);
- const {
- colorClasses,
- colorStyles,
- variantClasses
- } = useVariant(variantProps);
- const {
- densityClasses
- } = useDensity(props);
- const {
- dimensionStyles
- } = useDimension(props);
- const {
- elevationClasses
- } = useElevation(props);
- const {
- locationStyles
- } = useLocation(props);
- const {
- positionClasses
- } = usePosition(props);
- const {
- roundedClasses
- } = useRounded(props);
- const {
- textColorClasses,
- textColorStyles
- } = useTextColor(toRef(props, 'borderColor'));
- const {
- t
- } = useLocale();
- const closeProps = computed(() => ({
- 'aria-label': t(props.closeLabel),
- onClick(e) {
- isActive.value = false;
- emit('click:close', e);
- }
- }));
- return () => {
- const hasPrepend = !!(slots.prepend || icon.value);
- const hasTitle = !!(slots.title || props.title);
- const hasClose = !!(slots.close || props.closable);
- return isActive.value && createVNode(props.tag, {
- "class": ['v-alert', props.border && {
- 'v-alert--border': !!props.border,
- [`v-alert--border-${props.border === true ? 'start' : props.border}`]: true
- }, {
- 'v-alert--prominent': props.prominent
- }, themeClasses.value, colorClasses.value, densityClasses.value, elevationClasses.value, positionClasses.value, roundedClasses.value, variantClasses.value, props.class],
- "style": [colorStyles.value, dimensionStyles.value, locationStyles.value, props.style],
- "role": "alert"
- }, {
- default: () => [genOverlays(false, 'v-alert'), props.border && createVNode("div", {
- "key": "border",
- "class": ['v-alert__border', textColorClasses.value],
- "style": textColorStyles.value
- }, null), hasPrepend && createVNode("div", {
- "key": "prepend",
- "class": "v-alert__prepend"
- }, [!slots.prepend ? createVNode(VIcon, {
- "key": "prepend-icon",
- "density": props.density,
- "icon": icon.value,
- "size": props.prominent ? 44 : 28
- }, null) : createVNode(VDefaultsProvider, {
- "key": "prepend-defaults",
- "disabled": !icon.value,
- "defaults": {
- VIcon: {
- density: props.density,
- icon: icon.value,
- size: props.prominent ? 44 : 28
- }
- }
- }, slots.prepend)]), createVNode("div", {
- "class": "v-alert__content"
- }, [hasTitle && createVNode(VAlertTitle, {
- "key": "title"
- }, {
- default: () => [slots.title?.() ?? props.title]
- }), slots.text?.() ?? props.text, slots.default?.()]), slots.append && createVNode("div", {
- "key": "append",
- "class": "v-alert__append"
- }, [slots.append()]), hasClose && createVNode("div", {
- "key": "close",
- "class": "v-alert__close"
- }, [!slots.close ? createVNode(VBtn, mergeProps({
- "key": "close-btn",
- "icon": props.closeIcon,
- "size": "x-small",
- "variant": "text"
- }, closeProps.value), null) : createVNode(VDefaultsProvider, {
- "key": "close-defaults",
- "defaults": {
- VBtn: {
- icon: props.closeIcon,
- size: 'x-small',
- variant: 'text'
- }
- }
- }, {
- default: () => [slots.close?.({
- props: closeProps.value
- })]
- })])]
- });
- };
- }
- });
- const makeVLabelProps = propsFactory({
- text: String,
- clickable: Boolean,
- ...makeComponentProps(),
- ...makeThemeProps()
- }, 'VLabel');
- const VLabel = genericComponent()({
- name: 'VLabel',
- props: makeVLabelProps(),
- setup(props, _ref) {
- let {
- slots
- } = _ref;
- useRender(() => createVNode("label", {
- "class": ['v-label', {
- 'v-label--clickable': props.clickable
- }, props.class],
- "style": props.style
- }, [props.text, slots.default?.()]));
- return {};
- }
- });
- // Types
- const VSelectionControlGroupSymbol = Symbol.for('vuetify:selection-control-group');
- const makeSelectionControlGroupProps = propsFactory({
- color: String,
- disabled: {
- type: Boolean,
- default: null
- },
- defaultsTarget: String,
- error: Boolean,
- id: String,
- inline: Boolean,
- falseIcon: IconValue,
- trueIcon: IconValue,
- ripple: {
- type: Boolean,
- default: true
- },
- multiple: {
- type: Boolean,
- default: null
- },
- name: String,
- readonly: Boolean,
- modelValue: null,
- type: String,
- valueComparator: {
- type: Function,
- default: deepEqual
- },
- ...makeComponentProps(),
- ...makeDensityProps(),
- ...makeThemeProps()
- }, 'SelectionControlGroup');
- const makeVSelectionControlGroupProps = propsFactory({
- ...makeSelectionControlGroupProps({
- defaultsTarget: 'VSelectionControl'
- })
- }, 'VSelectionControlGroup');
- const VSelectionControlGroup = genericComponent()({
- name: 'VSelectionControlGroup',
- props: makeVSelectionControlGroupProps(),
- emits: {
- 'update:modelValue': val => true
- },
- setup(props, _ref) {
- let {
- slots
- } = _ref;
- const modelValue = useProxiedModel(props, 'modelValue');
- const uid = getUid();
- const id = computed(() => props.id || `v-selection-control-group-${uid}`);
- const name = computed(() => props.name || id.value);
- const updateHandlers = new Set();
- provide(VSelectionControlGroupSymbol, {
- modelValue,
- forceUpdate: () => {
- updateHandlers.forEach(fn => fn());
- },
- onForceUpdate: cb => {
- updateHandlers.add(cb);
- onScopeDispose(() => {
- updateHandlers.delete(cb);
- });
- }
- });
- provideDefaults({
- [props.defaultsTarget]: {
- color: toRef(props, 'color'),
- disabled: toRef(props, 'disabled'),
- density: toRef(props, 'density'),
- error: toRef(props, 'error'),
- inline: toRef(props, 'inline'),
- modelValue,
- multiple: computed(() => !!props.multiple || props.multiple == null && Array.isArray(modelValue.value)),
- name,
- falseIcon: toRef(props, 'falseIcon'),
- trueIcon: toRef(props, 'trueIcon'),
- readonly: toRef(props, 'readonly'),
- ripple: toRef(props, 'ripple'),
- type: toRef(props, 'type'),
- valueComparator: toRef(props, 'valueComparator')
- }
- });
- useRender(() => createVNode("div", {
- "class": ['v-selection-control-group', {
- 'v-selection-control-group--inline': props.inline
- }, props.class],
- "style": props.style,
- "role": props.type === 'radio' ? 'radiogroup' : undefined
- }, [slots.default?.()]));
- return {};
- }
- });
- // Types
- const makeVSelectionControlProps = propsFactory({
- label: String,
- trueValue: null,
- falseValue: null,
- value: null,
- ...makeComponentProps(),
- ...makeSelectionControlGroupProps()
- }, 'VSelectionControl');
- function useSelectionControl(props) {
- const group = inject$1(VSelectionControlGroupSymbol, undefined);
- const {
- densityClasses
- } = useDensity(props);
- const modelValue = useProxiedModel(props, 'modelValue');
- const trueValue = computed(() => props.trueValue !== undefined ? props.trueValue : props.value !== undefined ? props.value : true);
- const falseValue = computed(() => props.falseValue !== undefined ? props.falseValue : false);
- const isMultiple = computed(() => !!props.multiple || props.multiple == null && Array.isArray(modelValue.value));
- const model = computed({
- get() {
- const val = group ? group.modelValue.value : modelValue.value;
- return isMultiple.value ? val.some(v => props.valueComparator(v, trueValue.value)) : props.valueComparator(val, trueValue.value);
- },
- set(val) {
- if (props.readonly) return;
- const currentValue = val ? trueValue.value : falseValue.value;
- let newVal = currentValue;
- if (isMultiple.value) {
- newVal = val ? [...wrapInArray(modelValue.value), currentValue] : wrapInArray(modelValue.value).filter(item => !props.valueComparator(item, trueValue.value));
- }
- if (group) {
- group.modelValue.value = newVal;
- } else {
- modelValue.value = newVal;
- }
- }
- });
- const {
- textColorClasses,
- textColorStyles
- } = useTextColor(computed(() => {
- return model.value && !props.error && !props.disabled ? props.color : undefined;
- }));
- const icon = computed(() => model.value ? props.trueIcon : props.falseIcon);
- return {
- group,
- densityClasses,
- trueValue,
- falseValue,
- model,
- textColorClasses,
- textColorStyles,
- icon
- };
- }
- const VSelectionControl = genericComponent()({
- name: 'VSelectionControl',
- directives: {
- Ripple
- },
- inheritAttrs: false,
- props: makeVSelectionControlProps(),
- emits: {
- 'update:modelValue': val => true
- },
- setup(props, _ref) {
- let {
- attrs,
- slots
- } = _ref;
- const {
- group,
- densityClasses,
- icon,
- model,
- textColorClasses,
- textColorStyles,
- trueValue
- } = useSelectionControl(props);
- const uid = getUid();
- const id = computed(() => props.id || `input-${uid}`);
- const isFocused = shallowRef(false);
- const isFocusVisible = shallowRef(false);
- const input = ref();
- group?.onForceUpdate(() => {
- if (input.value) {
- input.value.checked = model.value;
- }
- });
- function onFocus(e) {
- isFocused.value = true;
- if (matchesSelector(e.target, ':focus-visible') !== false) {
- isFocusVisible.value = true;
- }
- }
- function onBlur() {
- isFocused.value = false;
- isFocusVisible.value = false;
- }
- function onInput(e) {
- if (props.readonly && group) {
- nextTick(() => group.forceUpdate());
- }
- model.value = e.target.checked;
- }
- useRender(() => {
- const label = slots.label ? slots.label({
- label: props.label,
- props: {
- for: id.value
- }
- }) : props.label;
- const [rootAttrs, inputAttrs] = filterInputAttrs(attrs);
- return createVNode("div", mergeProps({
- "class": ['v-selection-control', {
- 'v-selection-control--dirty': model.value,
- 'v-selection-control--disabled': props.disabled,
- 'v-selection-control--error': props.error,
- 'v-selection-control--focused': isFocused.value,
- 'v-selection-control--focus-visible': isFocusVisible.value,
- 'v-selection-control--inline': props.inline
- }, densityClasses.value, props.class]
- }, rootAttrs, {
- "style": props.style
- }), [createVNode("div", {
- "class": ['v-selection-control__wrapper', textColorClasses.value],
- "style": textColorStyles.value
- }, [slots.default?.(), withDirectives(createVNode("div", {
- "class": ['v-selection-control__input']
- }, [icon.value && createVNode(VIcon, {
- "key": "icon",
- "icon": icon.value
- }, null), createVNode("input", mergeProps({
- "ref": input,
- "checked": model.value,
- "disabled": !!(props.readonly || props.disabled),
- "id": id.value,
- "onBlur": onBlur,
- "onFocus": onFocus,
- "onInput": onInput,
- "aria-disabled": !!(props.readonly || props.disabled),
- "type": props.type,
- "value": trueValue.value,
- "name": props.name,
- "aria-checked": props.type === 'checkbox' ? model.value : undefined
- }, inputAttrs), null), slots.input?.({
- model,
- textColorClasses,
- textColorStyles,
- props: {
- onFocus,
- onBlur,
- id: id.value
- }
- })]), [[resolveDirective("ripple"), props.ripple && [!props.disabled && !props.readonly, null, ['center', 'circle']]]])]), label && createVNode(VLabel, {
- "for": id.value,
- "clickable": true
- }, {
- default: () => [label]
- })]);
- });
- return {
- isFocused,
- input
- };
- }
- });
- // Types
- const makeVCheckboxBtnProps = propsFactory({
- indeterminate: Boolean,
- indeterminateIcon: {
- type: IconValue,
- default: '$checkboxIndeterminate'
- },
- ...makeVSelectionControlProps({
- falseIcon: '$checkboxOff',
- trueIcon: '$checkboxOn'
- })
- }, 'VCheckboxBtn');
- const VCheckboxBtn = genericComponent()({
- name: 'VCheckboxBtn',
- props: makeVCheckboxBtnProps(),
- emits: {
- 'update:modelValue': value => true,
- 'update:indeterminate': val => true
- },
- setup(props, _ref) {
- let {
- slots
- } = _ref;
- const indeterminate = useProxiedModel(props, 'indeterminate');
- const model = useProxiedModel(props, 'modelValue');
- function onChange(v) {
- if (indeterminate.value) {
- indeterminate.value = false;
- }
- }
- const falseIcon = computed(() => {
- return indeterminate.value ? props.indeterminateIcon : props.falseIcon;
- });
- const trueIcon = computed(() => {
- return indeterminate.value ? props.indeterminateIcon : props.trueIcon;
- });
- useRender(() => createVNode(VSelectionControl, mergeProps(props, {
- "modelValue": model.value,
- "onUpdate:modelValue": [$event => model.value = $event, onChange],
- "class": ['v-checkbox-btn', props.class],
- "style": props.style,
- "type": "checkbox",
- "falseIcon": falseIcon.value,
- "trueIcon": trueIcon.value,
- "aria-checked": indeterminate.value ? 'mixed' : undefined
- }), slots));
- return {};
- }
- });
- // Types
- function useInputIcon(props) {
- const {
- t
- } = useLocale();
- function InputIcon(_ref) {
- let {
- name
- } = _ref;
- const localeKey = {
- prepend: 'prependAction',
- prependInner: 'prependAction',
- append: 'appendAction',
- appendInner: 'appendAction',
- clear: 'clear'
- }[name];
- const listener = props[`onClick:${name}`];
- const label = listener && localeKey ? t(`$vuetify.input.${localeKey}`, props.label ?? '') : undefined;
- return createVNode(VIcon, {
- "icon": props[`${name}Icon`],
- "aria-label": label,
- "onClick": listener
- }, null);
- }
- return {
- InputIcon
- };
- }
- // Types
- const makeVMessagesProps = propsFactory({
- active: Boolean,
- color: String,
- messages: {
- type: [Array, String],
- default: () => []
- },
- ...makeComponentProps(),
- ...makeTransitionProps({
- transition: {
- component: VSlideYTransition,
- leaveAbsolute: true,
- group: true
- }
- })
- }, 'VMessages');
- const VMessages = genericComponent()({
- name: 'VMessages',
- props: makeVMessagesProps(),
- setup(props, _ref) {
- let {
- slots
- } = _ref;
- const messages = computed(() => wrapInArray(props.messages));
- const {
- textColorClasses,
- textColorStyles
- } = useTextColor(computed(() => props.color));
- useRender(() => createVNode(MaybeTransition, {
- "transition": props.transition,
- "tag": "div",
- "class": ['v-messages', textColorClasses.value, props.class],
- "style": [textColorStyles.value, props.style],
- "role": "alert",
- "aria-live": "polite"
- }, {
- default: () => [props.active && messages.value.map((message, i) => createVNode("div", {
- "class": "v-messages__message",
- "key": `${i}-${messages.value}`
- }, [slots.message ? slots.message({
- message
- }) : message]))]
- }));
- return {};
- }
- });
- // Composables
- // Types
- // Composables
- const makeFocusProps = propsFactory({
- focused: Boolean,
- 'onUpdate:focused': EventProp()
- }, 'focus');
- function useFocus(props) {
- let name = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : getCurrentInstanceName();
- const isFocused = useProxiedModel(props, 'focused');
- const focusClasses = computed(() => {
- return {
- [`${name}--focused`]: isFocused.value
- };
- });
- function focus() {
- isFocused.value = true;
- }
- function blur() {
- isFocused.value = false;
- }
- return {
- focusClasses,
- isFocused,
- focus,
- blur
- };
- }
- // Composables
- // Types
- const FormKey = Symbol.for('vuetify:form');
- const makeFormProps = propsFactory({
- disabled: Boolean,
- fastFail: Boolean,
- readonly: Boolean,
- modelValue: {
- type: Boolean,
- default: null
- },
- validateOn: {
- type: String,
- default: 'input'
- }
- }, 'form');
- function createForm(props) {
- const model = useProxiedModel(props, 'modelValue');
- const isDisabled = computed(() => props.disabled);
- const isReadonly = computed(() => props.readonly);
- const isValidating = shallowRef(false);
- const items = ref([]);
- const errors = ref([]);
- async function validate() {
- const results = [];
- let valid = true;
- errors.value = [];
- isValidating.value = true;
- for (const item of items.value) {
- const itemErrorMessages = await item.validate();
- if (itemErrorMessages.length > 0) {
- valid = false;
- results.push({
- id: item.id,
- errorMessages: itemErrorMessages
- });
- }
- if (!valid && props.fastFail) break;
- }
- errors.value = results;
- isValidating.value = false;
- return {
- valid,
- errors: errors.value
- };
- }
- function reset() {
- items.value.forEach(item => item.reset());
- }
- function resetValidation() {
- items.value.forEach(item => item.resetValidation());
- }
- watch(items, () => {
- let valid = 0;
- let invalid = 0;
- const results = [];
- for (const item of items.value) {
- if (item.isValid === false) {
- invalid++;
- results.push({
- id: item.id,
- errorMessages: item.errorMessages
- });
- } else if (item.isValid === true) valid++;
- }
- errors.value = results;
- model.value = invalid > 0 ? false : valid === items.value.length ? true : null;
- }, {
- deep: true
- });
- provide(FormKey, {
- register: _ref => {
- let {
- id,
- validate,
- reset,
- resetValidation
- } = _ref;
- if (items.value.some(item => item.id === id)) {
- consoleWarn(`Duplicate input name "${id}"`);
- }
- items.value.push({
- id,
- validate,
- reset,
- resetValidation,
- isValid: null,
- errorMessages: []
- });
- },
- unregister: id => {
- items.value = items.value.filter(item => {
- return item.id !== id;
- });
- },
- update: (id, isValid, errorMessages) => {
- const found = items.value.find(item => item.id === id);
- if (!found) return;
- found.isValid = isValid;
- found.errorMessages = errorMessages;
- },
- isDisabled,
- isReadonly,
- isValidating,
- isValid: model,
- items,
- validateOn: toRef(props, 'validateOn')
- });
- return {
- errors,
- isDisabled,
- isReadonly,
- isValidating,
- isValid: model,
- items,
- validate,
- reset,
- resetValidation
- };
- }
- function useForm() {
- return inject$1(FormKey, null);
- }
- // Composables
- // Types
- const makeValidationProps = propsFactory({
- disabled: {
- type: Boolean,
- default: null
- },
- error: Boolean,
- errorMessages: {
- type: [Array, String],
- default: () => []
- },
- maxErrors: {
- type: [Number, String],
- default: 1
- },
- name: String,
- label: String,
- readonly: {
- type: Boolean,
- default: null
- },
- rules: {
- type: Array,
- default: () => []
- },
- modelValue: null,
- validateOn: String,
- validationValue: null,
- ...makeFocusProps()
- }, 'validation');
- function useValidation(props) {
- let name = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : getCurrentInstanceName();
- let id = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : getUid();
- const model = useProxiedModel(props, 'modelValue');
- const validationModel = computed(() => props.validationValue === undefined ? model.value : props.validationValue);
- const form = useForm();
- const internalErrorMessages = ref([]);
- const isPristine = shallowRef(true);
- const isDirty = computed(() => !!(wrapInArray(model.value === '' ? null : model.value).length || wrapInArray(validationModel.value === '' ? null : validationModel.value).length));
- const isDisabled = computed(() => !!(props.disabled ?? form?.isDisabled.value));
- const isReadonly = computed(() => !!(props.readonly ?? form?.isReadonly.value));
- const errorMessages = computed(() => {
- return props.errorMessages.length ? wrapInArray(props.errorMessages).slice(0, Math.max(0, +props.maxErrors)) : internalErrorMessages.value;
- });
- const validateOn = computed(() => {
- let value = (props.validateOn ?? form?.validateOn.value) || 'input';
- if (value === 'lazy') value = 'input lazy';
- const set = new Set(value?.split(' ') ?? []);
- return {
- blur: set.has('blur') || set.has('input'),
- input: set.has('input'),
- submit: set.has('submit'),
- lazy: set.has('lazy')
- };
- });
- const isValid = computed(() => {
- if (props.error || props.errorMessages.length) return false;
- if (!props.rules.length) return true;
- if (isPristine.value) {
- return internalErrorMessages.value.length || validateOn.value.lazy ? null : true;
- } else {
- return !internalErrorMessages.value.length;
- }
- });
- const isValidating = shallowRef(false);
- const validationClasses = computed(() => {
- return {
- [`${name}--error`]: isValid.value === false,
- [`${name}--dirty`]: isDirty.value,
- [`${name}--disabled`]: isDisabled.value,
- [`${name}--readonly`]: isReadonly.value
- };
- });
- const uid = computed(() => props.name ?? unref(id));
- onBeforeMount(() => {
- form?.register({
- id: uid.value,
- validate,
- reset,
- resetValidation
- });
- });
- onBeforeUnmount(() => {
- form?.unregister(uid.value);
- });
- onMounted(async () => {
- if (!validateOn.value.lazy) {
- await validate(true);
- }
- form?.update(uid.value, isValid.value, errorMessages.value);
- });
- useToggleScope(() => validateOn.value.input, () => {
- watch(validationModel, () => {
- if (validationModel.value != null) {
- validate();
- } else if (props.focused) {
- const unwatch = watch(() => props.focused, val => {
- if (!val) validate();
- unwatch();
- });
- }
- });
- });
- useToggleScope(() => validateOn.value.blur, () => {
- watch(() => props.focused, val => {
- if (!val) validate();
- });
- });
- watch(isValid, () => {
- form?.update(uid.value, isValid.value, errorMessages.value);
- });
- function reset() {
- model.value = null;
- nextTick(resetValidation);
- }
- function resetValidation() {
- isPristine.value = true;
- if (!validateOn.value.lazy) {
- validate(true);
- } else {
- internalErrorMessages.value = [];
- }
- }
- async function validate() {
- let silent = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : false;
- const results = [];
- isValidating.value = true;
- for (const rule of props.rules) {
- if (results.length >= +(props.maxErrors ?? 1)) {
- break;
- }
- const handler = typeof rule === 'function' ? rule : () => rule;
- const result = await handler(validationModel.value);
- if (result === true) continue;
- if (result !== false && typeof result !== 'string') {
- // eslint-disable-next-line no-console
- console.warn(`${result} is not a valid value. Rule functions must return boolean true or a string.`);
- continue;
- }
- results.push(result || '');
- }
- internalErrorMessages.value = results;
- isValidating.value = false;
- isPristine.value = silent;
- return internalErrorMessages.value;
- }
- return {
- errorMessages,
- isDirty,
- isDisabled,
- isReadonly,
- isPristine,
- isValid,
- isValidating,
- reset,
- resetValidation,
- validate,
- validationClasses
- };
- }
- // Types
- const makeVInputProps = propsFactory({
- id: String,
- appendIcon: IconValue,
- centerAffix: {
- type: Boolean,
- default: true
- },
- prependIcon: IconValue,
- hideDetails: [Boolean, String],
- hint: String,
- persistentHint: Boolean,
- messages: {
- type: [Array, String],
- default: () => []
- },
- direction: {
- type: String,
- default: 'horizontal',
- validator: v => ['horizontal', 'vertical'].includes(v)
- },
- 'onClick:prepend': EventProp(),
- 'onClick:append': EventProp(),
- ...makeComponentProps(),
- ...makeDensityProps(),
- ...makeValidationProps()
- }, 'VInput');
- const VInput = genericComponent()({
- name: 'VInput',
- props: {
- ...makeVInputProps()
- },
- emits: {
- 'update:modelValue': val => true
- },
- setup(props, _ref) {
- let {
- attrs,
- slots,
- emit
- } = _ref;
- const {
- densityClasses
- } = useDensity(props);
- const {
- rtlClasses
- } = useRtl();
- const {
- InputIcon
- } = useInputIcon(props);
- const uid = getUid();
- const id = computed(() => props.id || `input-${uid}`);
- const messagesId = computed(() => `${id.value}-messages`);
- const {
- errorMessages,
- isDirty,
- isDisabled,
- isReadonly,
- isPristine,
- isValid,
- isValidating,
- reset,
- resetValidation,
- validate,
- validationClasses
- } = useValidation(props, 'v-input', id);
- const slotProps = computed(() => ({
- id,
- messagesId,
- isDirty,
- isDisabled,
- isReadonly,
- isPristine,
- isValid,
- isValidating,
- reset,
- resetValidation,
- validate
- }));
- const messages = computed(() => {
- if (props.errorMessages?.length || !isPristine.value && errorMessages.value.length) {
- return errorMessages.value;
- } else if (props.hint && (props.persistentHint || props.focused)) {
- return props.hint;
- } else {
- return props.messages;
- }
- });
- useRender(() => {
- const hasPrepend = !!(slots.prepend || props.prependIcon);
- const hasAppend = !!(slots.append || props.appendIcon);
- const hasMessages = messages.value.length > 0;
- const hasDetails = !props.hideDetails || props.hideDetails === 'auto' && (hasMessages || !!slots.details);
- return createVNode("div", {
- "class": ['v-input', `v-input--${props.direction}`, {
- 'v-input--center-affix': props.centerAffix
- }, densityClasses.value, rtlClasses.value, validationClasses.value, props.class],
- "style": props.style
- }, [hasPrepend && createVNode("div", {
- "key": "prepend",
- "class": "v-input__prepend"
- }, [slots.prepend?.(slotProps.value), props.prependIcon && createVNode(InputIcon, {
- "key": "prepend-icon",
- "name": "prepend"
- }, null)]), slots.default && createVNode("div", {
- "class": "v-input__control"
- }, [slots.default?.(slotProps.value)]), hasAppend && createVNode("div", {
- "key": "append",
- "class": "v-input__append"
- }, [props.appendIcon && createVNode(InputIcon, {
- "key": "append-icon",
- "name": "append"
- }, null), slots.append?.(slotProps.value)]), hasDetails && createVNode("div", {
- "class": "v-input__details"
- }, [createVNode(VMessages, {
- "id": messagesId.value,
- "active": hasMessages,
- "messages": messages.value
- }, {
- message: slots.message
- }), slots.details?.(slotProps.value)])]);
- });
- return {
- reset,
- resetValidation,
- validate
- };
- }
- });
- // Types
- const makeVCheckboxProps = propsFactory({
- ...makeVInputProps(),
- ...omit(makeVCheckboxBtnProps(), ['inline'])
- }, 'VCheckbox');
- const VCheckbox = genericComponent()({
- name: 'VCheckbox',
- inheritAttrs: false,
- props: makeVCheckboxProps(),
- emits: {
- 'update:modelValue': value => true,
- 'update:focused': focused => true
- },
- setup(props, _ref) {
- let {
- attrs,
- slots
- } = _ref;
- const model = useProxiedModel(props, 'modelValue');
- const {
- isFocused,
- focus,
- blur
- } = useFocus(props);
- const uid = getUid();
- const id = computed(() => props.id || `checkbox-${uid}`);
- useRender(() => {
- const [inputAttrs, controlAttrs] = filterInputAttrs(attrs);
- const [inputProps, _1] = VInput.filterProps(props);
- const [checkboxProps, _2] = VCheckboxBtn.filterProps(props);
- return createVNode(VInput, mergeProps({
- "class": ['v-checkbox', props.class]
- }, inputAttrs, inputProps, {
- "modelValue": model.value,
- "onUpdate:modelValue": $event => model.value = $event,
- "id": id.value,
- "focused": isFocused.value,
- "style": props.style
- }), {
- ...slots,
- default: _ref2 => {
- let {
- id,
- messagesId,
- isDisabled,
- isReadonly
- } = _ref2;
- return createVNode(VCheckboxBtn, mergeProps(checkboxProps, {
- "id": id.value,
- "aria-describedby": messagesId.value,
- "disabled": isDisabled.value,
- "readonly": isReadonly.value
- }, controlAttrs, {
- "modelValue": model.value,
- "onUpdate:modelValue": $event => model.value = $event,
- "onFocus": focus,
- "onBlur": blur
- }), slots);
- }
- });
- });
- return {};
- }
- });
- const makeVAvatarProps = propsFactory({
- start: Boolean,
- end: Boolean,
- icon: IconValue,
- image: String,
- ...makeComponentProps(),
- ...makeDensityProps(),
- ...makeRoundedProps(),
- ...makeSizeProps(),
- ...makeTagProps(),
- ...makeThemeProps(),
- ...makeVariantProps({
- variant: 'flat'
- })
- }, 'VAvatar');
- const VAvatar = genericComponent()({
- name: 'VAvatar',
- props: makeVAvatarProps(),
- setup(props, _ref) {
- let {
- slots
- } = _ref;
- const {
- themeClasses
- } = provideTheme(props);
- const {
- colorClasses,
- colorStyles,
- variantClasses
- } = useVariant(props);
- const {
- densityClasses
- } = useDensity(props);
- const {
- roundedClasses
- } = useRounded(props);
- const {
- sizeClasses,
- sizeStyles
- } = useSize(props);
- useRender(() => createVNode(props.tag, {
- "class": ['v-avatar', {
- 'v-avatar--start': props.start,
- 'v-avatar--end': props.end
- }, themeClasses.value, colorClasses.value, densityClasses.value, roundedClasses.value, sizeClasses.value, variantClasses.value, props.class],
- "style": [colorStyles.value, sizeStyles.value, props.style]
- }, {
- default: () => [props.image ? createVNode(VImg, {
- "key": "image",
- "src": props.image,
- "alt": "",
- "cover": true
- }, null) : props.icon ? createVNode(VIcon, {
- "key": "icon",
- "icon": props.icon
- }, null) : slots.default?.(), genOverlays(false, 'v-avatar')]
- }));
- return {};
- }
- });
- // Types
- const VChipGroupSymbol = Symbol.for('vuetify:v-chip-group');
- const makeVChipGroupProps = propsFactory({
- column: Boolean,
- filter: Boolean,
- valueComparator: {
- type: Function,
- default: deepEqual
- },
- ...makeComponentProps(),
- ...makeGroupProps({
- selectedClass: 'v-chip--selected'
- }),
- ...makeTagProps(),
- ...makeThemeProps(),
- ...makeVariantProps({
- variant: 'tonal'
- })
- }, 'VChipGroup');
- const VChipGroup = genericComponent()({
- name: 'VChipGroup',
- props: makeVChipGroupProps(),
- emits: {
- 'update:modelValue': value => true
- },
- setup(props, _ref) {
- let {
- slots
- } = _ref;
- const {
- themeClasses
- } = provideTheme(props);
- const {
- isSelected,
- select,
- next,
- prev,
- selected
- } = useGroup(props, VChipGroupSymbol);
- provideDefaults({
- VChip: {
- color: toRef(props, 'color'),
- disabled: toRef(props, 'disabled'),
- filter: toRef(props, 'filter'),
- variant: toRef(props, 'variant')
- }
- });
- useRender(() => createVNode(props.tag, {
- "class": ['v-chip-group', {
- 'v-chip-group--column': props.column
- }, themeClasses.value, props.class],
- "style": props.style
- }, {
- default: () => [slots.default?.({
- isSelected,
- select,
- next,
- prev,
- selected: selected.value
- })]
- }));
- return {};
- }
- });
- // Types
- const makeVChipProps = propsFactory({
- activeClass: String,
- appendAvatar: String,
- appendIcon: IconValue,
- closable: Boolean,
- closeIcon: {
- type: IconValue,
- default: '$delete'
- },
- closeLabel: {
- type: String,
- default: '$vuetify.close'
- },
- draggable: Boolean,
- filter: Boolean,
- filterIcon: {
- type: String,
- default: '$complete'
- },
- label: Boolean,
- link: {
- type: Boolean,
- default: undefined
- },
- pill: Boolean,
- prependAvatar: String,
- prependIcon: IconValue,
- ripple: {
- type: [Boolean, Object],
- default: true
- },
- text: String,
- modelValue: {
- type: Boolean,
- default: true
- },
- onClick: EventProp(),
- onClickOnce: EventProp(),
- ...makeBorderProps(),
- ...makeComponentProps(),
- ...makeDensityProps(),
- ...makeElevationProps(),
- ...makeGroupItemProps(),
- ...makeRoundedProps(),
- ...makeRouterProps(),
- ...makeSizeProps(),
- ...makeTagProps({
- tag: 'span'
- }),
- ...makeThemeProps(),
- ...makeVariantProps({
- variant: 'tonal'
- })
- }, 'VChip');
- const VChip = genericComponent()({
- name: 'VChip',
- directives: {
- Ripple
- },
- props: makeVChipProps(),
- emits: {
- 'click:close': e => true,
- 'update:modelValue': value => true,
- 'group:selected': val => true,
- click: e => true
- },
- setup(props, _ref) {
- let {
- attrs,
- emit,
- slots
- } = _ref;
- const {
- t
- } = useLocale();
- const {
- borderClasses
- } = useBorder(props);
- const {
- colorClasses,
- colorStyles,
- variantClasses
- } = useVariant(props);
- const {
- densityClasses
- } = useDensity(props);
- const {
- elevationClasses
- } = useElevation(props);
- const {
- roundedClasses
- } = useRounded(props);
- const {
- sizeClasses
- } = useSize(props);
- const {
- themeClasses
- } = provideTheme(props);
- const isActive = useProxiedModel(props, 'modelValue');
- const group = useGroupItem(props, VChipGroupSymbol, false);
- const link = useLink(props, attrs);
- const isLink = computed(() => props.link !== false && link.isLink.value);
- const isClickable = computed(() => !props.disabled && props.link !== false && (!!group || props.link || link.isClickable.value));
- const closeProps = computed(() => ({
- 'aria-label': t(props.closeLabel),
- onClick(e) {
- isActive.value = false;
- emit('click:close', e);
- }
- }));
- function onClick(e) {
- emit('click', e);
- if (!isClickable.value) return;
- link.navigate?.(e);
- group?.toggle();
- }
- function onKeyDown(e) {
- if (e.key === 'Enter' || e.key === ' ') {
- e.preventDefault();
- onClick(e);
- }
- }
- return () => {
- const Tag = link.isLink.value ? 'a' : props.tag;
- const hasAppendMedia = !!(props.appendIcon || props.appendAvatar);
- const hasAppend = !!(hasAppendMedia || slots.append);
- const hasClose = !!(slots.close || props.closable);
- const hasFilter = !!(slots.filter || props.filter) && group;
- const hasPrependMedia = !!(props.prependIcon || props.prependAvatar);
- const hasPrepend = !!(hasPrependMedia || slots.prepend);
- const hasColor = !group || group.isSelected.value;
- return isActive.value && withDirectives(createVNode(Tag, {
- "class": ['v-chip', {
- 'v-chip--disabled': props.disabled,
- 'v-chip--label': props.label,
- 'v-chip--link': isClickable.value,
- 'v-chip--filter': hasFilter,
- 'v-chip--pill': props.pill
- }, themeClasses.value, borderClasses.value, hasColor ? colorClasses.value : undefined, densityClasses.value, elevationClasses.value, roundedClasses.value, sizeClasses.value, variantClasses.value, group?.selectedClass.value, props.class],
- "style": [hasColor ? colorStyles.value : undefined, props.style],
- "disabled": props.disabled || undefined,
- "draggable": props.draggable,
- "href": link.href.value,
- "tabindex": isClickable.value ? 0 : undefined,
- "onClick": onClick,
- "onKeydown": isClickable.value && !isLink.value && onKeyDown
- }, {
- default: () => [genOverlays(isClickable.value, 'v-chip'), hasFilter && createVNode(VExpandXTransition, {
- "key": "filter"
- }, {
- default: () => [withDirectives(createVNode("div", {
- "class": "v-chip__filter"
- }, [!slots.filter ? createVNode(VIcon, {
- "key": "filter-icon",
- "icon": props.filterIcon
- }, null) : createVNode(VDefaultsProvider, {
- "key": "filter-defaults",
- "disabled": !props.filterIcon,
- "defaults": {
- VIcon: {
- icon: props.filterIcon
- }
- }
- }, slots.filter)]), [[vShow, group.isSelected.value]])]
- }), hasPrepend && createVNode("div", {
- "key": "prepend",
- "class": "v-chip__prepend"
- }, [!slots.prepend ? createVNode(Fragment, null, [props.prependIcon && createVNode(VIcon, {
- "key": "prepend-icon",
- "icon": props.prependIcon,
- "start": true
- }, null), props.prependAvatar && createVNode(VAvatar, {
- "key": "prepend-avatar",
- "image": props.prependAvatar,
- "start": true
- }, null)]) : createVNode(VDefaultsProvider, {
- "key": "prepend-defaults",
- "disabled": !hasPrependMedia,
- "defaults": {
- VAvatar: {
- image: props.prependAvatar,
- start: true
- },
- VIcon: {
- icon: props.prependIcon,
- start: true
- }
- }
- }, slots.prepend)]), createVNode("div", {
- "class": "v-chip__content"
- }, [slots.default?.({
- isSelected: group?.isSelected.value,
- selectedClass: group?.selectedClass.value,
- select: group?.select,
- toggle: group?.toggle,
- value: group?.value.value,
- disabled: props.disabled
- }) ?? props.text]), hasAppend && createVNode("div", {
- "key": "append",
- "class": "v-chip__append"
- }, [!slots.append ? createVNode(Fragment, null, [props.appendIcon && createVNode(VIcon, {
- "key": "append-icon",
- "end": true,
- "icon": props.appendIcon
- }, null), props.appendAvatar && createVNode(VAvatar, {
- "key": "append-avatar",
- "end": true,
- "image": props.appendAvatar
- }, null)]) : createVNode(VDefaultsProvider, {
- "key": "append-defaults",
- "disabled": !hasAppendMedia,
- "defaults": {
- VAvatar: {
- end: true,
- image: props.appendAvatar
- },
- VIcon: {
- end: true,
- icon: props.appendIcon
- }
- }
- }, slots.append)]), hasClose && createVNode("div", mergeProps({
- "key": "close",
- "class": "v-chip__close"
- }, closeProps.value), [!slots.close ? createVNode(VIcon, {
- "key": "close-icon",
- "icon": props.closeIcon,
- "size": "x-small"
- }, null) : createVNode(VDefaultsProvider, {
- "key": "close-defaults",
- "defaults": {
- VIcon: {
- icon: props.closeIcon,
- size: 'x-small'
- }
- }
- }, slots.close)])]
- }), [[resolveDirective("ripple"), isClickable.value && props.ripple, null]]);
- };
- }
- });
- // Utilities
- // List
- const ListKey = Symbol.for('vuetify:list');
- function createList() {
- const parent = inject$1(ListKey, {
- hasPrepend: shallowRef(false),
- updateHasPrepend: () => null
- });
- const data = {
- hasPrepend: shallowRef(false),
- updateHasPrepend: value => {
- if (value) data.hasPrepend.value = value;
- }
- };
- provide(ListKey, data);
- return parent;
- }
- function useList() {
- return inject$1(ListKey, null);
- }
- const singleOpenStrategy = {
- open: _ref => {
- let {
- id,
- value,
- opened,
- parents
- } = _ref;
- if (value) {
- const newOpened = new Set();
- newOpened.add(id);
- let parent = parents.get(id);
- while (parent != null) {
- newOpened.add(parent);
- parent = parents.get(parent);
- }
- return newOpened;
- } else {
- opened.delete(id);
- return opened;
- }
- },
- select: () => null
- };
- const multipleOpenStrategy = {
- open: _ref2 => {
- let {
- id,
- value,
- opened,
- parents
- } = _ref2;
- if (value) {
- let parent = parents.get(id);
- opened.add(id);
- while (parent != null && parent !== id) {
- opened.add(parent);
- parent = parents.get(parent);
- }
- return opened;
- } else {
- opened.delete(id);
- }
- return opened;
- },
- select: () => null
- };
- const listOpenStrategy = {
- open: multipleOpenStrategy.open,
- select: _ref3 => {
- let {
- id,
- value,
- opened,
- parents
- } = _ref3;
- if (!value) return opened;
- const path = [];
- let parent = parents.get(id);
- while (parent != null) {
- path.push(parent);
- parent = parents.get(parent);
- }
- return new Set(path);
- }
- };
- /* eslint-disable sonarjs/no-identical-functions */
- // Utilities
- const independentSelectStrategy = mandatory => {
- const strategy = {
- select: _ref => {
- let {
- id,
- value,
- selected
- } = _ref;
- id = toRaw(id);
- // When mandatory and we're trying to deselect when id
- // is the only currently selected item then do nothing
- if (mandatory && !value) {
- const on = Array.from(selected.entries()).reduce((arr, _ref2) => {
- let [key, value] = _ref2;
- return value === 'on' ? [...arr, key] : arr;
- }, []);
- if (on.length === 1 && on[0] === id) return selected;
- }
- selected.set(id, value ? 'on' : 'off');
- return selected;
- },
- in: (v, children, parents) => {
- let map = new Map();
- for (const id of v || []) {
- map = strategy.select({
- id,
- value: true,
- selected: new Map(map),
- children,
- parents
- });
- }
- return map;
- },
- out: v => {
- const arr = [];
- for (const [key, value] of v.entries()) {
- if (value === 'on') arr.push(key);
- }
- return arr;
- }
- };
- return strategy;
- };
- const independentSingleSelectStrategy = mandatory => {
- const parentStrategy = independentSelectStrategy(mandatory);
- const strategy = {
- select: _ref3 => {
- let {
- selected,
- id,
- ...rest
- } = _ref3;
- id = toRaw(id);
- const singleSelected = selected.has(id) ? new Map([[id, selected.get(id)]]) : new Map();
- return parentStrategy.select({
- ...rest,
- id,
- selected: singleSelected
- });
- },
- in: (v, children, parents) => {
- let map = new Map();
- if (v?.length) {
- map = parentStrategy.in(v.slice(0, 1), children, parents);
- }
- return map;
- },
- out: (v, children, parents) => {
- return parentStrategy.out(v, children, parents);
- }
- };
- return strategy;
- };
- const leafSelectStrategy = mandatory => {
- const parentStrategy = independentSelectStrategy(mandatory);
- const strategy = {
- select: _ref4 => {
- let {
- id,
- selected,
- children,
- ...rest
- } = _ref4;
- id = toRaw(id);
- if (children.has(id)) return selected;
- return parentStrategy.select({
- id,
- selected,
- children,
- ...rest
- });
- },
- in: parentStrategy.in,
- out: parentStrategy.out
- };
- return strategy;
- };
- const leafSingleSelectStrategy = mandatory => {
- const parentStrategy = independentSingleSelectStrategy(mandatory);
- const strategy = {
- select: _ref5 => {
- let {
- id,
- selected,
- children,
- ...rest
- } = _ref5;
- id = toRaw(id);
- if (children.has(id)) return selected;
- return parentStrategy.select({
- id,
- selected,
- children,
- ...rest
- });
- },
- in: parentStrategy.in,
- out: parentStrategy.out
- };
- return strategy;
- };
- const classicSelectStrategy = mandatory => {
- const strategy = {
- select: _ref6 => {
- let {
- id,
- value,
- selected,
- children,
- parents
- } = _ref6;
- id = toRaw(id);
- const original = new Map(selected);
- const items = [id];
- while (items.length) {
- const item = items.shift();
- selected.set(item, value ? 'on' : 'off');
- if (children.has(item)) {
- items.push(...children.get(item));
- }
- }
- let parent = parents.get(id);
- while (parent) {
- const childrenIds = children.get(parent);
- const everySelected = childrenIds.every(cid => selected.get(cid) === 'on');
- const noneSelected = childrenIds.every(cid => !selected.has(cid) || selected.get(cid) === 'off');
- selected.set(parent, everySelected ? 'on' : noneSelected ? 'off' : 'indeterminate');
- parent = parents.get(parent);
- }
- // If mandatory and planned deselect results in no selected
- // items then we can't do it, so return original state
- if (mandatory && !value) {
- const on = Array.from(selected.entries()).reduce((arr, _ref7) => {
- let [key, value] = _ref7;
- return value === 'on' ? [...arr, key] : arr;
- }, []);
- if (on.length === 0) return original;
- }
- return selected;
- },
- in: (v, children, parents) => {
- let map = new Map();
- for (const id of v || []) {
- map = strategy.select({
- id,
- value: true,
- selected: new Map(map),
- children,
- parents
- });
- }
- return map;
- },
- out: (v, children) => {
- const arr = [];
- for (const [key, value] of v.entries()) {
- if (value === 'on' && !children.has(key)) arr.push(key);
- }
- return arr;
- }
- };
- return strategy;
- };
- // Composables
- // Types
- const VNestedSymbol = Symbol.for('vuetify:nested');
- const emptyNested = {
- id: shallowRef(),
- root: {
- register: () => null,
- unregister: () => null,
- parents: ref(new Map()),
- children: ref(new Map()),
- open: () => null,
- openOnSelect: () => null,
- select: () => null,
- opened: ref(new Set()),
- selected: ref(new Map()),
- selectedValues: ref([])
- }
- };
- const makeNestedProps = propsFactory({
- selectStrategy: [String, Function],
- openStrategy: [String, Object],
- opened: Array,
- selected: Array,
- mandatory: Boolean
- }, 'nested');
- const useNested = props => {
- let isUnmounted = false;
- const children = ref(new Map());
- const parents = ref(new Map());
- const opened = useProxiedModel(props, 'opened', props.opened, v => new Set(v), v => [...v.values()]);
- const selectStrategy = computed(() => {
- if (typeof props.selectStrategy === 'object') return props.selectStrategy;
- switch (props.selectStrategy) {
- case 'single-leaf':
- return leafSingleSelectStrategy(props.mandatory);
- case 'leaf':
- return leafSelectStrategy(props.mandatory);
- case 'independent':
- return independentSelectStrategy(props.mandatory);
- case 'single-independent':
- return independentSingleSelectStrategy(props.mandatory);
- case 'classic':
- default:
- return classicSelectStrategy(props.mandatory);
- }
- });
- const openStrategy = computed(() => {
- if (typeof props.openStrategy === 'object') return props.openStrategy;
- switch (props.openStrategy) {
- case 'list':
- return listOpenStrategy;
- case 'single':
- return singleOpenStrategy;
- case 'multiple':
- default:
- return multipleOpenStrategy;
- }
- });
- const selected = useProxiedModel(props, 'selected', props.selected, v => selectStrategy.value.in(v, children.value, parents.value), v => selectStrategy.value.out(v, children.value, parents.value));
- onBeforeUnmount(() => {
- isUnmounted = true;
- });
- function getPath(id) {
- const path = [];
- let parent = id;
- while (parent != null) {
- path.unshift(parent);
- parent = parents.value.get(parent);
- }
- return path;
- }
- const vm = getCurrentInstance('nested');
- const nested = {
- id: shallowRef(),
- root: {
- opened,
- selected,
- selectedValues: computed(() => {
- const arr = [];
- for (const [key, value] of selected.value.entries()) {
- if (value === 'on') arr.push(key);
- }
- return arr;
- }),
- register: (id, parentId, isGroup) => {
- parentId && id !== parentId && parents.value.set(id, parentId);
- isGroup && children.value.set(id, []);
- if (parentId != null) {
- children.value.set(parentId, [...(children.value.get(parentId) || []), id]);
- }
- },
- unregister: id => {
- if (isUnmounted) return;
- children.value.delete(id);
- const parent = parents.value.get(id);
- if (parent) {
- const list = children.value.get(parent) ?? [];
- children.value.set(parent, list.filter(child => child !== id));
- }
- parents.value.delete(id);
- opened.value.delete(id);
- },
- open: (id, value, event) => {
- vm.emit('click:open', {
- id,
- value,
- path: getPath(id),
- event
- });
- const newOpened = openStrategy.value.open({
- id,
- value,
- opened: new Set(opened.value),
- children: children.value,
- parents: parents.value,
- event
- });
- newOpened && (opened.value = newOpened);
- },
- openOnSelect: (id, value, event) => {
- const newOpened = openStrategy.value.select({
- id,
- value,
- selected: new Map(selected.value),
- opened: new Set(opened.value),
- children: children.value,
- parents: parents.value,
- event
- });
- newOpened && (opened.value = newOpened);
- },
- select: (id, value, event) => {
- vm.emit('click:select', {
- id,
- value,
- path: getPath(id),
- event
- });
- const newSelected = selectStrategy.value.select({
- id,
- value,
- selected: new Map(selected.value),
- children: children.value,
- parents: parents.value,
- event
- });
- newSelected && (selected.value = newSelected);
- nested.root.openOnSelect(id, value, event);
- },
- children,
- parents
- }
- };
- provide(VNestedSymbol, nested);
- return nested.root;
- };
- const useNestedItem = (id, isGroup) => {
- const parent = inject$1(VNestedSymbol, emptyNested);
- const uidSymbol = Symbol(getUid());
- const computedId = computed(() => id.value !== undefined ? id.value : uidSymbol);
- const item = {
- ...parent,
- id: computedId,
- open: (open, e) => parent.root.open(computedId.value, open, e),
- openOnSelect: (open, e) => parent.root.openOnSelect(computedId.value, open, e),
- isOpen: computed(() => parent.root.opened.value.has(computedId.value)),
- parent: computed(() => parent.root.parents.value.get(computedId.value)),
- select: (selected, e) => parent.root.select(computedId.value, selected, e),
- isSelected: computed(() => parent.root.selected.value.get(toRaw(computedId.value)) === 'on'),
- isIndeterminate: computed(() => parent.root.selected.value.get(computedId.value) === 'indeterminate'),
- isLeaf: computed(() => !parent.root.children.value.get(computedId.value)),
- isGroupActivator: parent.isGroupActivator
- };
- !parent.isGroupActivator && parent.root.register(computedId.value, parent.id.value, isGroup);
- onBeforeUnmount(() => {
- !parent.isGroupActivator && parent.root.unregister(computedId.value);
- });
- isGroup && provide(VNestedSymbol, item);
- return item;
- };
- const useNestedGroupActivator = () => {
- const parent = inject$1(VNestedSymbol, emptyNested);
- provide(VNestedSymbol, {
- ...parent,
- isGroupActivator: true
- });
- };
- const VListGroupActivator = defineComponent({
- name: 'VListGroupActivator',
- setup(_, _ref) {
- let {
- slots
- } = _ref;
- useNestedGroupActivator();
- return () => slots.default?.();
- }
- });
- const makeVListGroupProps = propsFactory({
- /* @deprecated */
- activeColor: String,
- baseColor: String,
- color: String,
- collapseIcon: {
- type: IconValue,
- default: '$collapse'
- },
- expandIcon: {
- type: IconValue,
- default: '$expand'
- },
- prependIcon: IconValue,
- appendIcon: IconValue,
- fluid: Boolean,
- subgroup: Boolean,
- title: String,
- value: null,
- ...makeComponentProps(),
- ...makeTagProps()
- }, 'VListGroup');
- const VListGroup = genericComponent()({
- name: 'VListGroup',
- props: makeVListGroupProps(),
- setup(props, _ref2) {
- let {
- slots
- } = _ref2;
- const {
- isOpen,
- open,
- id: _id
- } = useNestedItem(toRef(props, 'value'), true);
- const id = computed(() => `v-list-group--id-${String(_id.value)}`);
- const list = useList();
- const {
- isBooted
- } = useSsrBoot();
- function onClick(e) {
- open(!isOpen.value, e);
- }
- const activatorProps = computed(() => ({
- onClick,
- class: 'v-list-group__header',
- id: id.value
- }));
- const toggleIcon = computed(() => isOpen.value ? props.collapseIcon : props.expandIcon);
- const activatorDefaults = computed(() => ({
- VListItem: {
- active: isOpen.value,
- activeColor: props.activeColor,
- baseColor: props.baseColor,
- color: props.color,
- prependIcon: props.prependIcon || props.subgroup && toggleIcon.value,
- appendIcon: props.appendIcon || !props.subgroup && toggleIcon.value,
- title: props.title,
- value: props.value
- }
- }));
- useRender(() => createVNode(props.tag, {
- "class": ['v-list-group', {
- 'v-list-group--prepend': list?.hasPrepend.value,
- 'v-list-group--fluid': props.fluid,
- 'v-list-group--subgroup': props.subgroup,
- 'v-list-group--open': isOpen.value
- }, props.class],
- "style": props.style
- }, {
- default: () => [slots.activator && createVNode(VDefaultsProvider, {
- "defaults": activatorDefaults.value
- }, {
- default: () => [createVNode(VListGroupActivator, null, {
- default: () => [slots.activator({
- props: activatorProps.value,
- isOpen: isOpen.value
- })]
- })]
- }), createVNode(MaybeTransition, {
- "transition": {
- component: VExpandTransition
- },
- "disabled": !isBooted.value
- }, {
- default: () => [withDirectives(createVNode("div", {
- "class": "v-list-group__items",
- "role": "group",
- "aria-labelledby": id.value
- }, [slots.default?.()]), [[vShow, isOpen.value]])]
- })]
- }));
- return {};
- }
- });
- // Utilities
- const VListItemSubtitle = createSimpleFunctional('v-list-item-subtitle');
- // Utilities
- const VListItemTitle = createSimpleFunctional('v-list-item-title');
- // Types
- const makeVListItemProps = propsFactory({
- active: {
- type: Boolean,
- default: undefined
- },
- activeClass: String,
- /* @deprecated */
- activeColor: String,
- appendAvatar: String,
- appendIcon: IconValue,
- baseColor: String,
- disabled: Boolean,
- lines: String,
- link: {
- type: Boolean,
- default: undefined
- },
- nav: Boolean,
- prependAvatar: String,
- prependIcon: IconValue,
- ripple: {
- type: [Boolean, Object],
- default: true
- },
- subtitle: [String, Number, Boolean],
- title: [String, Number, Boolean],
- value: null,
- onClick: EventProp(),
- onClickOnce: EventProp(),
- ...makeBorderProps(),
- ...makeComponentProps(),
- ...makeDensityProps(),
- ...makeDimensionProps(),
- ...makeElevationProps(),
- ...makeRoundedProps(),
- ...makeRouterProps(),
- ...makeTagProps(),
- ...makeThemeProps(),
- ...makeVariantProps({
- variant: 'text'
- })
- }, 'VListItem');
- const VListItem = genericComponent()({
- name: 'VListItem',
- directives: {
- Ripple
- },
- props: makeVListItemProps(),
- emits: {
- click: e => true
- },
- setup(props, _ref) {
- let {
- attrs,
- slots,
- emit
- } = _ref;
- const link = useLink(props, attrs);
- const id = computed(() => props.value === undefined ? link.href.value : props.value);
- const {
- select,
- isSelected,
- isIndeterminate,
- isGroupActivator,
- root,
- parent,
- openOnSelect
- } = useNestedItem(id, false);
- const list = useList();
- const isActive = computed(() => props.active !== false && (props.active || link.isActive?.value || isSelected.value));
- const isLink = computed(() => props.link !== false && link.isLink.value);
- const isClickable = computed(() => !props.disabled && props.link !== false && (props.link || link.isClickable.value || props.value != null && !!list));
- const roundedProps = computed(() => props.rounded || props.nav);
- const color = computed(() => props.color ?? props.activeColor);
- const variantProps = computed(() => ({
- color: isActive.value ? color.value ?? props.baseColor : props.baseColor,
- variant: props.variant
- }));
- watch(() => link.isActive?.value, val => {
- if (val && parent.value != null) {
- root.open(parent.value, true);
- }
- if (val) {
- openOnSelect(val);
- }
- }, {
- immediate: true
- });
- const {
- themeClasses
- } = provideTheme(props);
- const {
- borderClasses
- } = useBorder(props);
- const {
- colorClasses,
- colorStyles,
- variantClasses
- } = useVariant(variantProps);
- const {
- densityClasses
- } = useDensity(props);
- const {
- dimensionStyles
- } = useDimension(props);
- const {
- elevationClasses
- } = useElevation(props);
- const {
- roundedClasses
- } = useRounded(roundedProps);
- const lineClasses = computed(() => props.lines ? `v-list-item--${props.lines}-line` : undefined);
- const slotProps = computed(() => ({
- isActive: isActive.value,
- select,
- isSelected: isSelected.value,
- isIndeterminate: isIndeterminate.value
- }));
- function onClick(e) {
- emit('click', e);
- if (isGroupActivator || !isClickable.value) return;
- link.navigate?.(e);
- props.value != null && select(!isSelected.value, e);
- }
- function onKeyDown(e) {
- if (e.key === 'Enter' || e.key === ' ') {
- e.preventDefault();
- onClick(e);
- }
- }
- useRender(() => {
- const Tag = isLink.value ? 'a' : props.tag;
- const hasTitle = slots.title || props.title;
- const hasSubtitle = slots.subtitle || props.subtitle;
- const hasAppendMedia = !!(props.appendAvatar || props.appendIcon);
- const hasAppend = !!(hasAppendMedia || slots.append);
- const hasPrependMedia = !!(props.prependAvatar || props.prependIcon);
- const hasPrepend = !!(hasPrependMedia || slots.prepend);
- list?.updateHasPrepend(hasPrepend);
- if (props.activeColor) {
- deprecate('active-color', ['color', 'base-color']);
- }
- return withDirectives(createVNode(Tag, {
- "class": ['v-list-item', {
- 'v-list-item--active': isActive.value,
- 'v-list-item--disabled': props.disabled,
- 'v-list-item--link': isClickable.value,
- 'v-list-item--nav': props.nav,
- 'v-list-item--prepend': !hasPrepend && list?.hasPrepend.value,
- [`${props.activeClass}`]: props.activeClass && isActive.value
- }, themeClasses.value, borderClasses.value, colorClasses.value, densityClasses.value, elevationClasses.value, lineClasses.value, roundedClasses.value, variantClasses.value, props.class],
- "style": [colorStyles.value, dimensionStyles.value, props.style],
- "href": link.href.value,
- "tabindex": isClickable.value ? list ? -2 : 0 : undefined,
- "onClick": onClick,
- "onKeydown": isClickable.value && !isLink.value && onKeyDown
- }, {
- default: () => [genOverlays(isClickable.value || isActive.value, 'v-list-item'), hasPrepend && createVNode("div", {
- "key": "prepend",
- "class": "v-list-item__prepend"
- }, [!slots.prepend ? createVNode(Fragment, null, [props.prependAvatar && createVNode(VAvatar, {
- "key": "prepend-avatar",
- "density": props.density,
- "image": props.prependAvatar
- }, null), props.prependIcon && createVNode(VIcon, {
- "key": "prepend-icon",
- "density": props.density,
- "icon": props.prependIcon
- }, null)]) : createVNode(VDefaultsProvider, {
- "key": "prepend-defaults",
- "disabled": !hasPrependMedia,
- "defaults": {
- VAvatar: {
- density: props.density,
- image: props.prependAvatar
- },
- VIcon: {
- density: props.density,
- icon: props.prependIcon
- },
- VListItemAction: {
- start: true
- }
- }
- }, {
- default: () => [slots.prepend?.(slotProps.value)]
- })]), createVNode("div", {
- "class": "v-list-item__content",
- "data-no-activator": ""
- }, [hasTitle && createVNode(VListItemTitle, {
- "key": "title"
- }, {
- default: () => [slots.title?.({
- title: props.title
- }) ?? props.title]
- }), hasSubtitle && createVNode(VListItemSubtitle, {
- "key": "subtitle"
- }, {
- default: () => [slots.subtitle?.({
- subtitle: props.subtitle
- }) ?? props.subtitle]
- }), slots.default?.(slotProps.value)]), hasAppend && createVNode("div", {
- "key": "append",
- "class": "v-list-item__append"
- }, [!slots.append ? createVNode(Fragment, null, [props.appendIcon && createVNode(VIcon, {
- "key": "append-icon",
- "density": props.density,
- "icon": props.appendIcon
- }, null), props.appendAvatar && createVNode(VAvatar, {
- "key": "append-avatar",
- "density": props.density,
- "image": props.appendAvatar
- }, null)]) : createVNode(VDefaultsProvider, {
- "key": "append-defaults",
- "disabled": !hasAppendMedia,
- "defaults": {
- VAvatar: {
- density: props.density,
- image: props.appendAvatar
- },
- VIcon: {
- density: props.density,
- icon: props.appendIcon
- },
- VListItemAction: {
- end: true
- }
- }
- }, {
- default: () => [slots.append?.(slotProps.value)]
- })])]
- }), [[resolveDirective("ripple"), isClickable.value && props.ripple]]);
- });
- return {};
- }
- });
- const makeVListSubheaderProps = propsFactory({
- color: String,
- inset: Boolean,
- sticky: Boolean,
- title: String,
- ...makeComponentProps(),
- ...makeTagProps()
- }, 'VListSubheader');
- const VListSubheader = genericComponent()({
- name: 'VListSubheader',
- props: makeVListSubheaderProps(),
- setup(props, _ref) {
- let {
- slots
- } = _ref;
- const {
- textColorClasses,
- textColorStyles
- } = useTextColor(toRef(props, 'color'));
- useRender(() => {
- const hasText = !!(slots.default || props.title);
- return createVNode(props.tag, {
- "class": ['v-list-subheader', {
- 'v-list-subheader--inset': props.inset,
- 'v-list-subheader--sticky': props.sticky
- }, textColorClasses.value, props.class],
- "style": [{
- textColorStyles
- }, props.style]
- }, {
- default: () => [hasText && createVNode("div", {
- "class": "v-list-subheader__text"
- }, [slots.default?.() ?? props.title])]
- });
- });
- return {};
- }
- });
- const makeVDividerProps = propsFactory({
- color: String,
- inset: Boolean,
- length: [Number, String],
- thickness: [Number, String],
- vertical: Boolean,
- ...makeComponentProps(),
- ...makeThemeProps()
- }, 'VDivider');
- const VDivider = genericComponent()({
- name: 'VDivider',
- props: makeVDividerProps(),
- setup(props, _ref) {
- let {
- attrs
- } = _ref;
- const {
- themeClasses
- } = provideTheme(props);
- const {
- textColorClasses,
- textColorStyles
- } = useTextColor(toRef(props, 'color'));
- const dividerStyles = computed(() => {
- const styles = {};
- if (props.length) {
- styles[props.vertical ? 'maxHeight' : 'maxWidth'] = convertToUnit(props.length);
- }
- if (props.thickness) {
- styles[props.vertical ? 'borderRightWidth' : 'borderTopWidth'] = convertToUnit(props.thickness);
- }
- return styles;
- });
- useRender(() => createVNode("hr", {
- "class": [{
- 'v-divider': true,
- 'v-divider--inset': props.inset,
- 'v-divider--vertical': props.vertical
- }, themeClasses.value, textColorClasses.value, props.class],
- "style": [dividerStyles.value, textColorStyles.value, props.style],
- "aria-orientation": !attrs.role || attrs.role === 'separator' ? props.vertical ? 'vertical' : 'horizontal' : undefined,
- "role": `${attrs.role || 'separator'}`
- }, null));
- return {};
- }
- });
- // Types
- const makeVListChildrenProps = propsFactory({
- items: Array
- }, 'VListChildren');
- const VListChildren = genericComponent()({
- name: 'VListChildren',
- props: makeVListChildrenProps(),
- setup(props, _ref) {
- let {
- slots
- } = _ref;
- createList();
- return () => slots.default?.() ?? props.items?.map(_ref2 => {
- let {
- children,
- props: itemProps,
- type,
- raw: item
- } = _ref2;
- if (type === 'divider') {
- return slots.divider?.({
- props: itemProps
- }) ?? createVNode(VDivider, itemProps, null);
- }
- if (type === 'subheader') {
- return slots.subheader?.({
- props: itemProps
- }) ?? createVNode(VListSubheader, itemProps, null);
- }
- const slotsWithItem = {
- subtitle: slots.subtitle ? slotProps => slots.subtitle?.({
- ...slotProps,
- item
- }) : undefined,
- prepend: slots.prepend ? slotProps => slots.prepend?.({
- ...slotProps,
- item
- }) : undefined,
- append: slots.append ? slotProps => slots.append?.({
- ...slotProps,
- item
- }) : undefined,
- title: slots.title ? slotProps => slots.title?.({
- ...slotProps,
- item
- }) : undefined
- };
- const [listGroupProps, _1] = VListGroup.filterProps(itemProps);
- return children ? createVNode(VListGroup, mergeProps({
- "value": itemProps?.value
- }, listGroupProps), {
- activator: _ref3 => {
- let {
- props: activatorProps
- } = _ref3;
- return slots.header ? slots.header({
- props: {
- ...itemProps,
- ...activatorProps
- }
- }) : createVNode(VListItem, mergeProps(itemProps, activatorProps), slotsWithItem);
- },
- default: () => createVNode(VListChildren, {
- "items": children
- }, slots)
- }) : slots.item ? slots.item({
- props: itemProps
- }) : createVNode(VListItem, itemProps, slotsWithItem);
- });
- }
- });
- // Utilities
- // Types
- // Composables
- const makeItemsProps = propsFactory({
- items: {
- type: Array,
- default: () => []
- },
- itemTitle: {
- type: [String, Array, Function],
- default: 'title'
- },
- itemValue: {
- type: [String, Array, Function],
- default: 'value'
- },
- itemChildren: {
- type: [Boolean, String, Array, Function],
- default: 'children'
- },
- itemProps: {
- type: [Boolean, String, Array, Function],
- default: 'props'
- },
- returnObject: Boolean
- }, 'list-items');
- function transformItem$3(props, item) {
- const title = getPropertyFromItem(item, props.itemTitle, item);
- const value = props.returnObject ? item : getPropertyFromItem(item, props.itemValue, title);
- const children = getPropertyFromItem(item, props.itemChildren);
- const itemProps = props.itemProps === true ? typeof item === 'object' && item != null && !Array.isArray(item) ? 'children' in item ? pick(item, ['children'])[1] : item : undefined : getPropertyFromItem(item, props.itemProps);
- const _props = {
- title,
- value,
- ...itemProps
- };
- return {
- title: String(_props.title ?? ''),
- value: _props.value,
- props: _props,
- children: Array.isArray(children) ? transformItems$3(props, children) : undefined,
- raw: item
- };
- }
- function transformItems$3(props, items) {
- const array = [];
- for (const item of items) {
- array.push(transformItem$3(props, item));
- }
- return array;
- }
- function useItems(props) {
- const items = computed(() => transformItems$3(props, props.items));
- return useTransformItems(items, value => transformItem$3(props, value));
- }
- function useTransformItems(items, transform) {
- function transformIn(value) {
- return value
- // When the model value is null, returns an InternalItem based on null
- // only if null is one of the items
- .filter(v => v !== null || items.value.some(item => item.value === null)).map(v => {
- const existingItem = items.value.find(item => deepEqual(v, item.value));
- // Nullish existingItem means value is a custom input value from combobox
- // In this case, use transformItem to create an InternalItem based on value
- return existingItem ?? transform(v);
- });
- }
- function transformOut(value) {
- return value.map(_ref => {
- let {
- value
- } = _ref;
- return value;
- });
- }
- return {
- items,
- transformIn,
- transformOut
- };
- }
- // Types
- function isPrimitive(value) {
- return typeof value === 'string' || typeof value === 'number' || typeof value === 'boolean';
- }
- function transformItem$2(props, item) {
- const type = getPropertyFromItem(item, props.itemType, 'item');
- const title = isPrimitive(item) ? item : getPropertyFromItem(item, props.itemTitle);
- const value = getPropertyFromItem(item, props.itemValue, undefined);
- const children = getPropertyFromItem(item, props.itemChildren);
- const itemProps = props.itemProps === true ? pick(item, ['children'])[1] : getPropertyFromItem(item, props.itemProps);
- const _props = {
- title,
- value,
- ...itemProps
- };
- return {
- type,
- title: _props.title,
- value: _props.value,
- props: _props,
- children: type === 'item' && children ? transformItems$2(props, children) : undefined,
- raw: item
- };
- }
- function transformItems$2(props, items) {
- const array = [];
- for (const item of items) {
- array.push(transformItem$2(props, item));
- }
- return array;
- }
- function useListItems(props) {
- const items = computed(() => transformItems$2(props, props.items));
- return {
- items
- };
- }
- const makeVListProps = propsFactory({
- baseColor: String,
- /* @deprecated */
- activeColor: String,
- activeClass: String,
- bgColor: String,
- disabled: Boolean,
- lines: {
- type: [Boolean, String],
- default: 'one'
- },
- nav: Boolean,
- ...makeNestedProps({
- selectStrategy: 'single-leaf',
- openStrategy: 'list'
- }),
- ...makeBorderProps(),
- ...makeComponentProps(),
- ...makeDensityProps(),
- ...makeDimensionProps(),
- ...makeElevationProps(),
- itemType: {
- type: String,
- default: 'type'
- },
- ...makeItemsProps(),
- ...makeRoundedProps(),
- ...makeTagProps(),
- ...makeThemeProps(),
- ...makeVariantProps({
- variant: 'text'
- })
- }, 'VList');
- const VList = genericComponent()({
- name: 'VList',
- props: makeVListProps(),
- emits: {
- 'update:selected': val => true,
- 'update:opened': val => true,
- 'click:open': value => true,
- 'click:select': value => true
- },
- setup(props, _ref) {
- let {
- slots
- } = _ref;
- const {
- items
- } = useListItems(props);
- const {
- themeClasses
- } = provideTheme(props);
- const {
- backgroundColorClasses,
- backgroundColorStyles
- } = useBackgroundColor(toRef(props, 'bgColor'));
- const {
- borderClasses
- } = useBorder(props);
- const {
- densityClasses
- } = useDensity(props);
- const {
- dimensionStyles
- } = useDimension(props);
- const {
- elevationClasses
- } = useElevation(props);
- const {
- roundedClasses
- } = useRounded(props);
- const {
- open,
- select
- } = useNested(props);
- const lineClasses = computed(() => props.lines ? `v-list--${props.lines}-line` : undefined);
- const activeColor = toRef(props, 'activeColor');
- const baseColor = toRef(props, 'baseColor');
- const color = toRef(props, 'color');
- createList();
- provideDefaults({
- VListGroup: {
- activeColor,
- baseColor,
- color
- },
- VListItem: {
- activeClass: toRef(props, 'activeClass'),
- activeColor,
- baseColor,
- color,
- density: toRef(props, 'density'),
- disabled: toRef(props, 'disabled'),
- lines: toRef(props, 'lines'),
- nav: toRef(props, 'nav'),
- variant: toRef(props, 'variant')
- }
- });
- const isFocused = shallowRef(false);
- const contentRef = ref();
- function onFocusin(e) {
- isFocused.value = true;
- }
- function onFocusout(e) {
- isFocused.value = false;
- }
- function onFocus(e) {
- if (!isFocused.value && !(e.relatedTarget && contentRef.value?.contains(e.relatedTarget))) focus();
- }
- function onKeydown(e) {
- if (!contentRef.value) return;
- if (e.key === 'ArrowDown') {
- focus('next');
- } else if (e.key === 'ArrowUp') {
- focus('prev');
- } else if (e.key === 'Home') {
- focus('first');
- } else if (e.key === 'End') {
- focus('last');
- } else {
- return;
- }
- e.preventDefault();
- }
- function focus(location) {
- if (contentRef.value) {
- return focusChild(contentRef.value, location);
- }
- }
- useRender(() => {
- return createVNode(props.tag, {
- "ref": contentRef,
- "class": ['v-list', {
- 'v-list--disabled': props.disabled,
- 'v-list--nav': props.nav
- }, themeClasses.value, backgroundColorClasses.value, borderClasses.value, densityClasses.value, elevationClasses.value, lineClasses.value, roundedClasses.value, props.class],
- "style": [backgroundColorStyles.value, dimensionStyles.value, props.style],
- "tabindex": props.disabled || isFocused.value ? -1 : 0,
- "role": "listbox",
- "aria-activedescendant": undefined,
- "onFocusin": onFocusin,
- "onFocusout": onFocusout,
- "onFocus": onFocus,
- "onKeydown": onKeydown
- }, {
- default: () => [createVNode(VListChildren, {
- "items": items.value
- }, slots)]
- });
- });
- return {
- open,
- select,
- focus
- };
- }
- });
- // Utilities
- const VListImg = createSimpleFunctional('v-list-img');
- const makeVListItemActionProps = propsFactory({
- start: Boolean,
- end: Boolean,
- ...makeComponentProps(),
- ...makeTagProps()
- }, 'VListItemAction');
- const VListItemAction = genericComponent()({
- name: 'VListItemAction',
- props: makeVListItemActionProps(),
- setup(props, _ref) {
- let {
- slots
- } = _ref;
- useRender(() => createVNode(props.tag, {
- "class": ['v-list-item-action', {
- 'v-list-item-action--start': props.start,
- 'v-list-item-action--end': props.end
- }, props.class],
- "style": props.style
- }, slots));
- return {};
- }
- });
- const makeVListItemMediaProps = propsFactory({
- start: Boolean,
- end: Boolean,
- ...makeComponentProps(),
- ...makeTagProps()
- }, 'VListItemMedia');
- const VListItemMedia = genericComponent()({
- name: 'VListItemMedia',
- props: makeVListItemMediaProps(),
- setup(props, _ref) {
- let {
- slots
- } = _ref;
- useRender(() => {
- return createVNode(props.tag, {
- "class": ['v-list-item-media', {
- 'v-list-item-media--start': props.start,
- 'v-list-item-media--end': props.end
- }, props.class],
- "style": props.style
- }, slots);
- });
- return {};
- }
- });
- // Types
- /** Convert a point in local space to viewport space */
- function elementToViewport(point, offset) {
- return {
- x: point.x + offset.x,
- y: point.y + offset.y
- };
- }
- /** Get the difference between two points */
- function getOffset$1(a, b) {
- return {
- x: a.x - b.x,
- y: a.y - b.y
- };
- }
- /** Convert an anchor object to a point in local space */
- function anchorToPoint(anchor, box) {
- if (anchor.side === 'top' || anchor.side === 'bottom') {
- const {
- side,
- align
- } = anchor;
- const x = align === 'left' ? 0 : align === 'center' ? box.width / 2 : align === 'right' ? box.width : align;
- const y = side === 'top' ? 0 : side === 'bottom' ? box.height : side;
- return elementToViewport({
- x,
- y
- }, box);
- } else if (anchor.side === 'left' || anchor.side === 'right') {
- const {
- side,
- align
- } = anchor;
- const x = side === 'left' ? 0 : side === 'right' ? box.width : side;
- const y = align === 'top' ? 0 : align === 'center' ? box.height / 2 : align === 'bottom' ? box.height : align;
- return elementToViewport({
- x,
- y
- }, box);
- }
- return elementToViewport({
- x: box.width / 2,
- y: box.height / 2
- }, box);
- }
- // Composables
- // Types
- const locationStrategies = {
- static: staticLocationStrategy,
- // specific viewport position, usually centered
- connected: connectedLocationStrategy // connected to a certain element
- };
- const makeLocationStrategyProps = propsFactory({
- locationStrategy: {
- type: [String, Function],
- default: 'static',
- validator: val => typeof val === 'function' || val in locationStrategies
- },
- location: {
- type: String,
- default: 'bottom'
- },
- origin: {
- type: String,
- default: 'auto'
- },
- offset: [Number, String, Array]
- }, 'VOverlay-location-strategies');
- function useLocationStrategies(props, data) {
- const contentStyles = ref({});
- const updateLocation = ref();
- if (IN_BROWSER) {
- useToggleScope(() => !!(data.isActive.value && props.locationStrategy), reset => {
- watch(() => props.locationStrategy, reset);
- onScopeDispose(() => {
- updateLocation.value = undefined;
- });
- if (typeof props.locationStrategy === 'function') {
- updateLocation.value = props.locationStrategy(data, props, contentStyles)?.updateLocation;
- } else {
- updateLocation.value = locationStrategies[props.locationStrategy](data, props, contentStyles)?.updateLocation;
- }
- });
- window.addEventListener('resize', onResize, {
- passive: true
- });
- onScopeDispose(() => {
- window.removeEventListener('resize', onResize);
- updateLocation.value = undefined;
- });
- }
- function onResize(e) {
- updateLocation.value?.(e);
- }
- return {
- contentStyles,
- updateLocation
- };
- }
- function staticLocationStrategy() {
- // TODO
- }
- /** Get size of element ignoring max-width/max-height */
- function getIntrinsicSize(el, isRtl) {
- // const scrollables = new Map<Element, [number, number]>()
- // el.querySelectorAll('*').forEach(el => {
- // const x = el.scrollLeft
- // const y = el.scrollTop
- // if (x || y) {
- // scrollables.set(el, [x, y])
- // }
- // })
- // const initialMaxWidth = el.style.maxWidth
- // const initialMaxHeight = el.style.maxHeight
- // el.style.removeProperty('max-width')
- // el.style.removeProperty('max-height')
- if (isRtl) {
- el.style.removeProperty('left');
- } else {
- el.style.removeProperty('right');
- }
- /* eslint-disable-next-line sonarjs/prefer-immediate-return */
- const contentBox = nullifyTransforms(el);
- if (isRtl) {
- contentBox.x += parseFloat(el.style.right || 0);
- } else {
- contentBox.x -= parseFloat(el.style.left || 0);
- }
- contentBox.y -= parseFloat(el.style.top || 0);
- // el.style.maxWidth = initialMaxWidth
- // el.style.maxHeight = initialMaxHeight
- // scrollables.forEach((position, el) => {
- // el.scrollTo(...position)
- // })
- return contentBox;
- }
- function connectedLocationStrategy(data, props, contentStyles) {
- const activatorFixed = isFixedPosition(data.activatorEl.value);
- if (activatorFixed) {
- Object.assign(contentStyles.value, {
- position: 'fixed',
- top: 0,
- [data.isRtl.value ? 'right' : 'left']: 0
- });
- }
- const {
- preferredAnchor,
- preferredOrigin
- } = destructComputed(() => {
- const parsedAnchor = parseAnchor(props.location, data.isRtl.value);
- const parsedOrigin = props.origin === 'overlap' ? parsedAnchor : props.origin === 'auto' ? flipSide(parsedAnchor) : parseAnchor(props.origin, data.isRtl.value);
- // Some combinations of props may produce an invalid origin
- if (parsedAnchor.side === parsedOrigin.side && parsedAnchor.align === flipAlign(parsedOrigin).align) {
- return {
- preferredAnchor: flipCorner(parsedAnchor),
- preferredOrigin: flipCorner(parsedOrigin)
- };
- } else {
- return {
- preferredAnchor: parsedAnchor,
- preferredOrigin: parsedOrigin
- };
- }
- });
- const [minWidth, minHeight, maxWidth, maxHeight] = ['minWidth', 'minHeight', 'maxWidth', 'maxHeight'].map(key => {
- return computed(() => {
- const val = parseFloat(props[key]);
- return isNaN(val) ? Infinity : val;
- });
- });
- const offset = computed(() => {
- if (Array.isArray(props.offset)) {
- return props.offset;
- }
- if (typeof props.offset === 'string') {
- const offset = props.offset.split(' ').map(parseFloat);
- if (offset.length < 2) offset.push(0);
- return offset;
- }
- return typeof props.offset === 'number' ? [props.offset, 0] : [0, 0];
- });
- let observe = false;
- const observer = new ResizeObserver(() => {
- if (observe) updateLocation();
- });
- watch([data.activatorEl, data.contentEl], (_ref, _ref2) => {
- let [newActivatorEl, newContentEl] = _ref;
- let [oldActivatorEl, oldContentEl] = _ref2;
- if (oldActivatorEl) observer.unobserve(oldActivatorEl);
- if (newActivatorEl) observer.observe(newActivatorEl);
- if (oldContentEl) observer.unobserve(oldContentEl);
- if (newContentEl) observer.observe(newContentEl);
- }, {
- immediate: true
- });
- onScopeDispose(() => {
- observer.disconnect();
- });
- // eslint-disable-next-line max-statements
- function updateLocation() {
- observe = false;
- requestAnimationFrame(() => {
- requestAnimationFrame(() => observe = true);
- });
- if (!data.activatorEl.value || !data.contentEl.value) return;
- const targetBox = data.activatorEl.value.getBoundingClientRect();
- const contentBox = getIntrinsicSize(data.contentEl.value, data.isRtl.value);
- const scrollParents = getScrollParents(data.contentEl.value);
- const viewportMargin = 12;
- if (!scrollParents.length) {
- scrollParents.push(document.documentElement);
- if (!(data.contentEl.value.style.top && data.contentEl.value.style.left)) {
- contentBox.x -= parseFloat(document.documentElement.style.getPropertyValue('--v-body-scroll-x') || 0);
- contentBox.y -= parseFloat(document.documentElement.style.getPropertyValue('--v-body-scroll-y') || 0);
- }
- }
- const viewport = scrollParents.reduce((box, el) => {
- const rect = el.getBoundingClientRect();
- const scrollBox = new Box({
- x: el === document.documentElement ? 0 : rect.x,
- y: el === document.documentElement ? 0 : rect.y,
- width: el.clientWidth,
- height: el.clientHeight
- });
- if (box) {
- return new Box({
- x: Math.max(box.left, scrollBox.left),
- y: Math.max(box.top, scrollBox.top),
- width: Math.min(box.right, scrollBox.right) - Math.max(box.left, scrollBox.left),
- height: Math.min(box.bottom, scrollBox.bottom) - Math.max(box.top, scrollBox.top)
- });
- }
- return scrollBox;
- }, undefined);
- viewport.x += viewportMargin;
- viewport.y += viewportMargin;
- viewport.width -= viewportMargin * 2;
- viewport.height -= viewportMargin * 2;
- let placement = {
- anchor: preferredAnchor.value,
- origin: preferredOrigin.value
- };
- function checkOverflow(_placement) {
- const box = new Box(contentBox);
- const targetPoint = anchorToPoint(_placement.anchor, targetBox);
- const contentPoint = anchorToPoint(_placement.origin, box);
- let {
- x,
- y
- } = getOffset$1(targetPoint, contentPoint);
- switch (_placement.anchor.side) {
- case 'top':
- y -= offset.value[0];
- break;
- case 'bottom':
- y += offset.value[0];
- break;
- case 'left':
- x -= offset.value[0];
- break;
- case 'right':
- x += offset.value[0];
- break;
- }
- switch (_placement.anchor.align) {
- case 'top':
- y -= offset.value[1];
- break;
- case 'bottom':
- y += offset.value[1];
- break;
- case 'left':
- x -= offset.value[1];
- break;
- case 'right':
- x += offset.value[1];
- break;
- }
- box.x += x;
- box.y += y;
- box.width = Math.min(box.width, maxWidth.value);
- box.height = Math.min(box.height, maxHeight.value);
- const overflows = getOverflow(box, viewport);
- return {
- overflows,
- x,
- y
- };
- }
- let x = 0;
- let y = 0;
- const available = {
- x: 0,
- y: 0
- };
- const flipped = {
- x: false,
- y: false
- };
- let resets = -1;
- while (true) {
- if (resets++ > 10) {
- consoleError('Infinite loop detected in connectedLocationStrategy');
- break;
- }
- const {
- x: _x,
- y: _y,
- overflows
- } = checkOverflow(placement);
- x += _x;
- y += _y;
- contentBox.x += _x;
- contentBox.y += _y;
- // flip
- {
- const axis = getAxis(placement.anchor);
- const hasOverflowX = overflows.x.before || overflows.x.after;
- const hasOverflowY = overflows.y.before || overflows.y.after;
- let reset = false;
- ['x', 'y'].forEach(key => {
- if (key === 'x' && hasOverflowX && !flipped.x || key === 'y' && hasOverflowY && !flipped.y) {
- const newPlacement = {
- anchor: {
- ...placement.anchor
- },
- origin: {
- ...placement.origin
- }
- };
- const flip = key === 'x' ? axis === 'y' ? flipAlign : flipSide : axis === 'y' ? flipSide : flipAlign;
- newPlacement.anchor = flip(newPlacement.anchor);
- newPlacement.origin = flip(newPlacement.origin);
- const {
- overflows: newOverflows
- } = checkOverflow(newPlacement);
- if (newOverflows[key].before <= overflows[key].before && newOverflows[key].after <= overflows[key].after || newOverflows[key].before + newOverflows[key].after < (overflows[key].before + overflows[key].after) / 2) {
- placement = newPlacement;
- reset = flipped[key] = true;
- }
- }
- });
- if (reset) continue;
- }
- // shift
- if (overflows.x.before) {
- x += overflows.x.before;
- contentBox.x += overflows.x.before;
- }
- if (overflows.x.after) {
- x -= overflows.x.after;
- contentBox.x -= overflows.x.after;
- }
- if (overflows.y.before) {
- y += overflows.y.before;
- contentBox.y += overflows.y.before;
- }
- if (overflows.y.after) {
- y -= overflows.y.after;
- contentBox.y -= overflows.y.after;
- }
- // size
- {
- const overflows = getOverflow(contentBox, viewport);
- available.x = viewport.width - overflows.x.before - overflows.x.after;
- available.y = viewport.height - overflows.y.before - overflows.y.after;
- x += overflows.x.before;
- contentBox.x += overflows.x.before;
- y += overflows.y.before;
- contentBox.y += overflows.y.before;
- }
- break;
- }
- const axis = getAxis(placement.anchor);
- Object.assign(contentStyles.value, {
- '--v-overlay-anchor-origin': `${placement.anchor.side} ${placement.anchor.align}`,
- transformOrigin: `${placement.origin.side} ${placement.origin.align}`,
- // transform: `translate(${pixelRound(x)}px, ${pixelRound(y)}px)`,
- top: convertToUnit(pixelRound(y)),
- left: data.isRtl.value ? undefined : convertToUnit(pixelRound(x)),
- right: data.isRtl.value ? convertToUnit(pixelRound(-x)) : undefined,
- minWidth: convertToUnit(axis === 'y' ? Math.min(minWidth.value, targetBox.width) : minWidth.value),
- maxWidth: convertToUnit(pixelCeil(clamp(available.x, minWidth.value === Infinity ? 0 : minWidth.value, maxWidth.value))),
- maxHeight: convertToUnit(pixelCeil(clamp(available.y, minHeight.value === Infinity ? 0 : minHeight.value, maxHeight.value)))
- });
- return {
- available,
- contentBox
- };
- }
- watch(() => [preferredAnchor.value, preferredOrigin.value, props.offset, props.minWidth, props.minHeight, props.maxWidth, props.maxHeight], () => updateLocation());
- nextTick(() => {
- const result = updateLocation();
- // TODO: overflowing content should only require a single updateLocation call
- // Icky hack to make sure the content is positioned consistently
- if (!result) return;
- const {
- available,
- contentBox
- } = result;
- if (contentBox.height > available.y) {
- requestAnimationFrame(() => {
- updateLocation();
- requestAnimationFrame(() => {
- updateLocation();
- });
- });
- }
- });
- return {
- updateLocation
- };
- }
- function pixelRound(val) {
- return Math.round(val * devicePixelRatio) / devicePixelRatio;
- }
- function pixelCeil(val) {
- return Math.ceil(val * devicePixelRatio) / devicePixelRatio;
- }
- let clean = true;
- const frames = [];
- /**
- * Schedule a task to run in an animation frame on its own
- * This is useful for heavy tasks that may cause jank if all ran together
- */
- function requestNewFrame(cb) {
- if (!clean || frames.length) {
- frames.push(cb);
- run();
- } else {
- clean = false;
- cb();
- run();
- }
- }
- let raf = -1;
- function run() {
- cancelAnimationFrame(raf);
- raf = requestAnimationFrame(() => {
- const frame = frames.shift();
- if (frame) frame();
- if (frames.length) run();else clean = true;
- });
- }
- // Utilities
- // Types
- const scrollStrategies = {
- none: null,
- close: closeScrollStrategy,
- block: blockScrollStrategy,
- reposition: repositionScrollStrategy
- };
- const makeScrollStrategyProps = propsFactory({
- scrollStrategy: {
- type: [String, Function],
- default: 'block',
- validator: val => typeof val === 'function' || val in scrollStrategies
- }
- }, 'VOverlay-scroll-strategies');
- function useScrollStrategies(props, data) {
- if (!IN_BROWSER) return;
- let scope;
- watchEffect(async () => {
- scope?.stop();
- if (!(data.isActive.value && props.scrollStrategy)) return;
- scope = effectScope();
- await nextTick();
- scope.active && scope.run(() => {
- if (typeof props.scrollStrategy === 'function') {
- props.scrollStrategy(data, props, scope);
- } else {
- scrollStrategies[props.scrollStrategy]?.(data, props, scope);
- }
- });
- });
- onScopeDispose(() => {
- scope?.stop();
- });
- }
- function closeScrollStrategy(data) {
- function onScroll(e) {
- data.isActive.value = false;
- }
- bindScroll(data.activatorEl.value ?? data.contentEl.value, onScroll);
- }
- function blockScrollStrategy(data, props) {
- const offsetParent = data.root.value?.offsetParent;
- const scrollElements = [...new Set([...getScrollParents(data.activatorEl.value, props.contained ? offsetParent : undefined), ...getScrollParents(data.contentEl.value, props.contained ? offsetParent : undefined)])].filter(el => !el.classList.contains('v-overlay-scroll-blocked'));
- const scrollbarWidth = window.innerWidth - document.documentElement.offsetWidth;
- const scrollableParent = (el => hasScrollbar(el) && el)(offsetParent || document.documentElement);
- if (scrollableParent) {
- data.root.value.classList.add('v-overlay--scroll-blocked');
- }
- scrollElements.forEach((el, i) => {
- el.style.setProperty('--v-body-scroll-x', convertToUnit(-el.scrollLeft));
- el.style.setProperty('--v-body-scroll-y', convertToUnit(-el.scrollTop));
- if (el !== document.documentElement) {
- el.style.setProperty('--v-scrollbar-offset', convertToUnit(scrollbarWidth));
- }
- el.classList.add('v-overlay-scroll-blocked');
- });
- onScopeDispose(() => {
- scrollElements.forEach((el, i) => {
- const x = parseFloat(el.style.getPropertyValue('--v-body-scroll-x'));
- const y = parseFloat(el.style.getPropertyValue('--v-body-scroll-y'));
- el.style.removeProperty('--v-body-scroll-x');
- el.style.removeProperty('--v-body-scroll-y');
- el.style.removeProperty('--v-scrollbar-offset');
- el.classList.remove('v-overlay-scroll-blocked');
- el.scrollLeft = -x;
- el.scrollTop = -y;
- });
- if (scrollableParent) {
- data.root.value.classList.remove('v-overlay--scroll-blocked');
- }
- });
- }
- function repositionScrollStrategy(data, props, scope) {
- let slow = false;
- let raf = -1;
- let ric = -1;
- function update(e) {
- requestNewFrame(() => {
- const start = performance.now();
- data.updateLocation.value?.(e);
- const time = performance.now() - start;
- slow = time / (1000 / 60) > 2;
- });
- }
- ric = (typeof requestIdleCallback === 'undefined' ? cb => cb() : requestIdleCallback)(() => {
- scope.run(() => {
- bindScroll(data.activatorEl.value ?? data.contentEl.value, e => {
- if (slow) {
- // If the position calculation is slow,
- // defer updates until scrolling is finished.
- // Browsers usually fire one scroll event per frame so
- // we just wait until we've got two frames without an event
- cancelAnimationFrame(raf);
- raf = requestAnimationFrame(() => {
- raf = requestAnimationFrame(() => {
- update(e);
- });
- });
- } else {
- update(e);
- }
- });
- });
- });
- onScopeDispose(() => {
- typeof cancelIdleCallback !== 'undefined' && cancelIdleCallback(ric);
- cancelAnimationFrame(raf);
- });
- }
- /** @private */
- function bindScroll(el, onScroll) {
- const scrollElements = [document, ...getScrollParents(el)];
- scrollElements.forEach(el => {
- el.addEventListener('scroll', onScroll, {
- passive: true
- });
- });
- onScopeDispose(() => {
- scrollElements.forEach(el => {
- el.removeEventListener('scroll', onScroll);
- });
- });
- }
- // Types
- const VMenuSymbol = Symbol.for('vuetify:v-menu');
- // Utilities
- // Types
- // Composables
- const makeDelayProps = propsFactory({
- closeDelay: [Number, String],
- openDelay: [Number, String]
- }, 'delay');
- function useDelay(props, cb) {
- const delays = {};
- const runDelayFactory = prop => () => {
- // istanbul ignore next
- if (!IN_BROWSER) return Promise.resolve(true);
- const active = prop === 'openDelay';
- delays.closeDelay && window.clearTimeout(delays.closeDelay);
- delete delays.closeDelay;
- delays.openDelay && window.clearTimeout(delays.openDelay);
- delete delays.openDelay;
- return new Promise(resolve => {
- const delay = parseInt(props[prop] ?? 0, 10);
- delays[prop] = window.setTimeout(() => {
- cb?.(active);
- resolve(active);
- }, delay);
- });
- };
- return {
- runCloseDelay: runDelayFactory('closeDelay'),
- runOpenDelay: runDelayFactory('openDelay')
- };
- }
- // Components
- // Types
- const makeActivatorProps = propsFactory({
- activator: [String, Object],
- activatorProps: {
- type: Object,
- default: () => ({})
- },
- openOnClick: {
- type: Boolean,
- default: undefined
- },
- openOnHover: Boolean,
- openOnFocus: {
- type: Boolean,
- default: undefined
- },
- closeOnContentClick: Boolean,
- ...makeDelayProps()
- }, 'VOverlay-activator');
- function useActivator(props, _ref) {
- let {
- isActive,
- isTop
- } = _ref;
- const activatorEl = ref();
- let isHovered = false;
- let isFocused = false;
- let firstEnter = true;
- const openOnFocus = computed(() => props.openOnFocus || props.openOnFocus == null && props.openOnHover);
- const openOnClick = computed(() => props.openOnClick || props.openOnClick == null && !props.openOnHover && !openOnFocus.value);
- const {
- runOpenDelay,
- runCloseDelay
- } = useDelay(props, value => {
- if (value === (props.openOnHover && isHovered || openOnFocus.value && isFocused) && !(props.openOnHover && isActive.value && !isTop.value)) {
- if (isActive.value !== value) {
- firstEnter = true;
- }
- isActive.value = value;
- }
- });
- const availableEvents = {
- onClick: e => {
- e.stopPropagation();
- activatorEl.value = e.currentTarget || e.target;
- isActive.value = !isActive.value;
- },
- onMouseenter: e => {
- if (e.sourceCapabilities?.firesTouchEvents) return;
- isHovered = true;
- activatorEl.value = e.currentTarget || e.target;
- runOpenDelay();
- },
- onMouseleave: e => {
- isHovered = false;
- runCloseDelay();
- },
- onFocus: e => {
- if (matchesSelector(e.target, ':focus-visible') === false) return;
- isFocused = true;
- e.stopPropagation();
- activatorEl.value = e.currentTarget || e.target;
- runOpenDelay();
- },
- onBlur: e => {
- isFocused = false;
- e.stopPropagation();
- runCloseDelay();
- }
- };
- const activatorEvents = computed(() => {
- const events = {};
- if (openOnClick.value) {
- events.onClick = availableEvents.onClick;
- }
- if (props.openOnHover) {
- events.onMouseenter = availableEvents.onMouseenter;
- events.onMouseleave = availableEvents.onMouseleave;
- }
- if (openOnFocus.value) {
- events.onFocus = availableEvents.onFocus;
- events.onBlur = availableEvents.onBlur;
- }
- return events;
- });
- const contentEvents = computed(() => {
- const events = {};
- if (props.openOnHover) {
- events.onMouseenter = () => {
- isHovered = true;
- runOpenDelay();
- };
- events.onMouseleave = () => {
- isHovered = false;
- runCloseDelay();
- };
- }
- if (openOnFocus.value) {
- events.onFocusin = () => {
- isFocused = true;
- runOpenDelay();
- };
- events.onFocusout = () => {
- isFocused = false;
- runCloseDelay();
- };
- }
- if (props.closeOnContentClick) {
- const menu = inject$1(VMenuSymbol, null);
- events.onClick = () => {
- isActive.value = false;
- menu?.closeParents();
- };
- }
- return events;
- });
- const scrimEvents = computed(() => {
- const events = {};
- if (props.openOnHover) {
- events.onMouseenter = () => {
- if (firstEnter) {
- isHovered = true;
- firstEnter = false;
- runOpenDelay();
- }
- };
- events.onMouseleave = () => {
- isHovered = false;
- runCloseDelay();
- };
- }
- return events;
- });
- watch(isTop, val => {
- if (val && (props.openOnHover && !isHovered && (!openOnFocus.value || !isFocused) || openOnFocus.value && !isFocused && (!props.openOnHover || !isHovered))) {
- isActive.value = false;
- }
- });
- const activatorRef = ref();
- watchEffect(() => {
- if (!activatorRef.value) return;
- nextTick(() => {
- activatorEl.value = refElement(activatorRef.value);
- });
- });
- const vm = getCurrentInstance('useActivator');
- let scope;
- watch(() => !!props.activator, val => {
- if (val && IN_BROWSER) {
- scope = effectScope();
- scope.run(() => {
- _useActivator(props, vm, {
- activatorEl,
- activatorEvents
- });
- });
- } else if (scope) {
- scope.stop();
- }
- }, {
- flush: 'post',
- immediate: true
- });
- onScopeDispose(() => {
- scope?.stop();
- });
- return {
- activatorEl,
- activatorRef,
- activatorEvents,
- contentEvents,
- scrimEvents
- };
- }
- function _useActivator(props, vm, _ref2) {
- let {
- activatorEl,
- activatorEvents
- } = _ref2;
- watch(() => props.activator, (val, oldVal) => {
- if (oldVal && val !== oldVal) {
- const activator = getActivator(oldVal);
- activator && unbindActivatorProps(activator);
- }
- if (val) {
- nextTick(() => bindActivatorProps());
- }
- }, {
- immediate: true
- });
- watch(() => props.activatorProps, () => {
- bindActivatorProps();
- });
- onScopeDispose(() => {
- unbindActivatorProps();
- });
- function bindActivatorProps() {
- let el = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : getActivator();
- let _props = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : props.activatorProps;
- if (!el) return;
- bindProps(el, mergeProps(activatorEvents.value, _props));
- }
- function unbindActivatorProps() {
- let el = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : getActivator();
- let _props = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : props.activatorProps;
- if (!el) return;
- unbindProps(el, mergeProps(activatorEvents.value, _props));
- }
- function getActivator() {
- let selector = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : props.activator;
- let activator;
- if (selector) {
- if (selector === 'parent') {
- let el = vm?.proxy?.$el?.parentNode;
- while (el.hasAttribute('data-no-activator')) {
- el = el.parentNode;
- }
- activator = el;
- } else if (typeof selector === 'string') {
- // Selector
- activator = document.querySelector(selector);
- } else if ('$el' in selector) {
- // Component (ref)
- activator = selector.$el;
- } else {
- // HTMLElement | Element
- activator = selector;
- }
- }
- // The activator should only be a valid element (Ignore comments and text nodes)
- activatorEl.value = activator?.nodeType === Node.ELEMENT_NODE ? activator : null;
- return activatorEl.value;
- }
- }
- // Utilities
- // Types
- const breakpoints = ['sm', 'md', 'lg', 'xl', 'xxl']; // no xs
- const DisplaySymbol = Symbol.for('vuetify:display');
- const defaultDisplayOptions = {
- mobileBreakpoint: 'lg',
- thresholds: {
- xs: 0,
- sm: 600,
- md: 960,
- lg: 1280,
- xl: 1920,
- xxl: 2560
- }
- };
- const parseDisplayOptions = function () {
- let options = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : defaultDisplayOptions;
- return mergeDeep(defaultDisplayOptions, options);
- };
- function getClientWidth(ssr) {
- return IN_BROWSER && !ssr ? window.innerWidth : typeof ssr === 'object' && ssr.clientWidth || 0;
- }
- function getClientHeight(ssr) {
- return IN_BROWSER && !ssr ? window.innerHeight : typeof ssr === 'object' && ssr.clientHeight || 0;
- }
- function getPlatform(ssr) {
- const userAgent = IN_BROWSER && !ssr ? window.navigator.userAgent : 'ssr';
- function match(regexp) {
- return Boolean(userAgent.match(regexp));
- }
- const android = match(/android/i);
- const ios = match(/iphone|ipad|ipod/i);
- const cordova = match(/cordova/i);
- const electron = match(/electron/i);
- const chrome = match(/chrome/i);
- const edge = match(/edge/i);
- const firefox = match(/firefox/i);
- const opera = match(/opera/i);
- const win = match(/win/i);
- const mac = match(/mac/i);
- const linux = match(/linux/i);
- return {
- android,
- ios,
- cordova,
- electron,
- chrome,
- edge,
- firefox,
- opera,
- win,
- mac,
- linux,
- touch: SUPPORTS_TOUCH,
- ssr: userAgent === 'ssr'
- };
- }
- function createDisplay(options, ssr) {
- const {
- thresholds,
- mobileBreakpoint
- } = parseDisplayOptions(options);
- const height = shallowRef(getClientHeight(ssr));
- const platform = shallowRef(getPlatform(ssr));
- const state = reactive({});
- const width = shallowRef(getClientWidth(ssr));
- function updateSize() {
- height.value = getClientHeight();
- width.value = getClientWidth();
- }
- function update() {
- updateSize();
- platform.value = getPlatform();
- }
- // eslint-disable-next-line max-statements
- watchEffect(() => {
- const xs = width.value < thresholds.sm;
- const sm = width.value < thresholds.md && !xs;
- const md = width.value < thresholds.lg && !(sm || xs);
- const lg = width.value < thresholds.xl && !(md || sm || xs);
- const xl = width.value < thresholds.xxl && !(lg || md || sm || xs);
- const xxl = width.value >= thresholds.xxl;
- const name = xs ? 'xs' : sm ? 'sm' : md ? 'md' : lg ? 'lg' : xl ? 'xl' : 'xxl';
- const breakpointValue = typeof mobileBreakpoint === 'number' ? mobileBreakpoint : thresholds[mobileBreakpoint];
- const mobile = width.value < breakpointValue;
- state.xs = xs;
- state.sm = sm;
- state.md = md;
- state.lg = lg;
- state.xl = xl;
- state.xxl = xxl;
- state.smAndUp = !xs;
- state.mdAndUp = !(xs || sm);
- state.lgAndUp = !(xs || sm || md);
- state.xlAndUp = !(xs || sm || md || lg);
- state.smAndDown = !(md || lg || xl || xxl);
- state.mdAndDown = !(lg || xl || xxl);
- state.lgAndDown = !(xl || xxl);
- state.xlAndDown = !xxl;
- state.name = name;
- state.height = height.value;
- state.width = width.value;
- state.mobile = mobile;
- state.mobileBreakpoint = mobileBreakpoint;
- state.platform = platform.value;
- state.thresholds = thresholds;
- });
- if (IN_BROWSER) {
- window.addEventListener('resize', updateSize, {
- passive: true
- });
- }
- return {
- ...toRefs(state),
- update,
- ssr: !!ssr
- };
- }
- function useDisplay() {
- const display = inject$1(DisplaySymbol);
- if (!display) throw new Error('Could not find Vuetify display injection');
- return display;
- }
- // Composables
- function useHydration() {
- if (!IN_BROWSER) return shallowRef(false);
- const {
- ssr
- } = useDisplay();
- if (ssr) {
- const isMounted = shallowRef(false);
- onMounted(() => {
- isMounted.value = true;
- });
- return isMounted;
- } else {
- return shallowRef(true);
- }
- }
- // Utilities
- // Types
- const makeLazyProps = propsFactory({
- eager: Boolean
- }, 'lazy');
- function useLazy(props, active) {
- const isBooted = shallowRef(false);
- const hasContent = computed(() => isBooted.value || props.eager || active.value);
- watch(active, () => isBooted.value = true);
- function onAfterLeave() {
- if (!props.eager) isBooted.value = false;
- }
- return {
- isBooted,
- hasContent,
- onAfterLeave
- };
- }
- // Utilities
- function useScopeId() {
- const vm = getCurrentInstance('useScopeId');
- const scopeId = vm.vnode.scopeId;
- return {
- scopeId: scopeId ? {
- [scopeId]: ''
- } : undefined
- };
- }
- // Composables
- // Types
- const StackSymbol = Symbol.for('vuetify:stack');
- const globalStack = reactive([]);
- function useStack(isActive, zIndex, disableGlobalStack) {
- const vm = getCurrentInstance('useStack');
- const createStackEntry = !disableGlobalStack;
- const parent = inject$1(StackSymbol, undefined);
- const stack = reactive({
- activeChildren: new Set()
- });
- provide(StackSymbol, stack);
- const _zIndex = shallowRef(+zIndex.value);
- useToggleScope(isActive, () => {
- const lastZIndex = globalStack.at(-1)?.[1];
- _zIndex.value = lastZIndex ? lastZIndex + 10 : +zIndex.value;
- if (createStackEntry) {
- globalStack.push([vm.uid, _zIndex.value]);
- }
- parent?.activeChildren.add(vm.uid);
- onScopeDispose(() => {
- if (createStackEntry) {
- const idx = toRaw(globalStack).findIndex(v => v[0] === vm.uid);
- globalStack.splice(idx, 1);
- }
- parent?.activeChildren.delete(vm.uid);
- });
- });
- const globalTop = shallowRef(true);
- if (createStackEntry) {
- watchEffect(() => {
- const _isTop = globalStack.at(-1)?.[0] === vm.uid;
- setTimeout(() => globalTop.value = _isTop);
- });
- }
- const localTop = computed(() => !stack.activeChildren.size);
- return {
- globalTop: readonly(globalTop),
- localTop,
- stackStyles: computed(() => ({
- zIndex: _zIndex.value
- }))
- };
- }
- // Utilities
- // Types
- function useTeleport(target) {
- const teleportTarget = computed(() => {
- const _target = target.value;
- if (_target === true || !IN_BROWSER) return undefined;
- const targetElement = _target === false ? document.body : typeof _target === 'string' ? document.querySelector(_target) : _target;
- if (targetElement == null) {
- warn(`Unable to locate target ${_target}`);
- return undefined;
- }
- let container = targetElement.querySelector(':scope > .v-overlay-container');
- if (!container) {
- container = document.createElement('div');
- container.className = 'v-overlay-container';
- targetElement.appendChild(container);
- }
- return container;
- });
- return {
- teleportTarget
- };
- }
- // Utilities
- // Types
- function defaultConditional() {
- return true;
- }
- function checkEvent(e, el, binding) {
- // The include element callbacks below can be expensive
- // so we should avoid calling them when we're not active.
- // Explicitly check for false to allow fallback compatibility
- // with non-toggleable components
- if (!e || checkIsActive(e, binding) === false) return false;
- // If we're clicking inside the shadowroot, then the app root doesn't get the same
- // level of introspection as to _what_ we're clicking. We want to check to see if
- // our target is the shadowroot parent container, and if it is, ignore.
- const root = attachedRoot(el);
- if (typeof ShadowRoot !== 'undefined' && root instanceof ShadowRoot && root.host === e.target) return false;
- // Check if additional elements were passed to be included in check
- // (click must be outside all included elements, if any)
- const elements = (typeof binding.value === 'object' && binding.value.include || (() => []))();
- // Add the root element for the component this directive was defined on
- elements.push(el);
- // Check if it's a click outside our elements, and then if our callback returns true.
- // Non-toggleable components should take action in their callback and return falsy.
- // Toggleable can return true if it wants to deactivate.
- // Note that, because we're in the capture phase, this callback will occur before
- // the bubbling click event on any outside elements.
- return !elements.some(el => el?.contains(e.target));
- }
- function checkIsActive(e, binding) {
- const isActive = typeof binding.value === 'object' && binding.value.closeConditional || defaultConditional;
- return isActive(e);
- }
- function directive(e, el, binding) {
- const handler = typeof binding.value === 'function' ? binding.value : binding.value.handler;
- el._clickOutside.lastMousedownWasOutside && checkEvent(e, el, binding) && setTimeout(() => {
- checkIsActive(e, binding) && handler && handler(e);
- }, 0);
- }
- function handleShadow(el, callback) {
- const root = attachedRoot(el);
- callback(document);
- if (typeof ShadowRoot !== 'undefined' && root instanceof ShadowRoot) {
- callback(root);
- }
- }
- const ClickOutside = {
- // [data-app] may not be found
- // if using bind, inserted makes
- // sure that the root element is
- // available, iOS does not support
- // clicks on body
- mounted(el, binding) {
- const onClick = e => directive(e, el, binding);
- const onMousedown = e => {
- el._clickOutside.lastMousedownWasOutside = checkEvent(e, el, binding);
- };
- handleShadow(el, app => {
- app.addEventListener('click', onClick, true);
- app.addEventListener('mousedown', onMousedown, true);
- });
- if (!el._clickOutside) {
- el._clickOutside = {
- lastMousedownWasOutside: false
- };
- }
- el._clickOutside[binding.instance.$.uid] = {
- onClick,
- onMousedown
- };
- },
- unmounted(el, binding) {
- if (!el._clickOutside) return;
- handleShadow(el, app => {
- if (!app || !el._clickOutside?.[binding.instance.$.uid]) return;
- const {
- onClick,
- onMousedown
- } = el._clickOutside[binding.instance.$.uid];
- app.removeEventListener('click', onClick, true);
- app.removeEventListener('mousedown', onMousedown, true);
- });
- delete el._clickOutside[binding.instance.$.uid];
- }
- };
- // Types
- function Scrim(props) {
- const {
- modelValue,
- color,
- ...rest
- } = props;
- return createVNode(Transition, {
- "name": "fade-transition",
- "appear": true
- }, {
- default: () => [props.modelValue && createVNode("div", mergeProps({
- "class": ['v-overlay__scrim', props.color.backgroundColorClasses.value],
- "style": props.color.backgroundColorStyles.value
- }, rest), null)]
- });
- }
- const makeVOverlayProps = propsFactory({
- absolute: Boolean,
- attach: [Boolean, String, Object],
- closeOnBack: {
- type: Boolean,
- default: true
- },
- contained: Boolean,
- contentClass: null,
- contentProps: null,
- disabled: Boolean,
- noClickAnimation: Boolean,
- modelValue: Boolean,
- persistent: Boolean,
- scrim: {
- type: [Boolean, String],
- default: true
- },
- zIndex: {
- type: [Number, String],
- default: 2000
- },
- ...makeActivatorProps(),
- ...makeComponentProps(),
- ...makeDimensionProps(),
- ...makeLazyProps(),
- ...makeLocationStrategyProps(),
- ...makeScrollStrategyProps(),
- ...makeThemeProps(),
- ...makeTransitionProps()
- }, 'VOverlay');
- const VOverlay = genericComponent()({
- name: 'VOverlay',
- directives: {
- ClickOutside
- },
- inheritAttrs: false,
- props: {
- _disableGlobalStack: Boolean,
- ...makeVOverlayProps()
- },
- emits: {
- 'click:outside': e => true,
- 'update:modelValue': value => true,
- afterLeave: () => true
- },
- setup(props, _ref) {
- let {
- slots,
- attrs,
- emit
- } = _ref;
- const model = useProxiedModel(props, 'modelValue');
- const isActive = computed({
- get: () => model.value,
- set: v => {
- if (!(v && props.disabled)) model.value = v;
- }
- });
- const {
- teleportTarget
- } = useTeleport(computed(() => props.attach || props.contained));
- const {
- themeClasses
- } = provideTheme(props);
- const {
- rtlClasses,
- isRtl
- } = useRtl();
- const {
- hasContent,
- onAfterLeave
- } = useLazy(props, isActive);
- const scrimColor = useBackgroundColor(computed(() => {
- return typeof props.scrim === 'string' ? props.scrim : null;
- }));
- const {
- globalTop,
- localTop,
- stackStyles
- } = useStack(isActive, toRef(props, 'zIndex'), props._disableGlobalStack);
- const {
- activatorEl,
- activatorRef,
- activatorEvents,
- contentEvents,
- scrimEvents
- } = useActivator(props, {
- isActive,
- isTop: localTop
- });
- const {
- dimensionStyles
- } = useDimension(props);
- const isMounted = useHydration();
- const {
- scopeId
- } = useScopeId();
- watch(() => props.disabled, v => {
- if (v) isActive.value = false;
- });
- const root = ref();
- const contentEl = ref();
- const {
- contentStyles,
- updateLocation
- } = useLocationStrategies(props, {
- isRtl,
- contentEl,
- activatorEl,
- isActive
- });
- useScrollStrategies(props, {
- root,
- contentEl,
- activatorEl,
- isActive,
- updateLocation
- });
- function onClickOutside(e) {
- emit('click:outside', e);
- if (!props.persistent) isActive.value = false;else animateClick();
- }
- function closeConditional() {
- return isActive.value && globalTop.value;
- }
- IN_BROWSER && watch(isActive, val => {
- if (val) {
- window.addEventListener('keydown', onKeydown);
- } else {
- window.removeEventListener('keydown', onKeydown);
- }
- }, {
- immediate: true
- });
- function onKeydown(e) {
- if (e.key === 'Escape' && globalTop.value) {
- if (!props.persistent) {
- isActive.value = false;
- if (contentEl.value?.contains(document.activeElement)) {
- activatorEl.value?.focus();
- }
- } else animateClick();
- }
- }
- const router = useRouter();
- useToggleScope(() => props.closeOnBack, () => {
- useBackButton(router, next => {
- if (globalTop.value && isActive.value) {
- next(false);
- if (!props.persistent) isActive.value = false;else animateClick();
- } else {
- next();
- }
- });
- });
- const top = ref();
- watch(() => isActive.value && (props.absolute || props.contained) && teleportTarget.value == null, val => {
- if (val) {
- const scrollParent = getScrollParent(root.value);
- if (scrollParent && scrollParent !== document.scrollingElement) {
- top.value = scrollParent.scrollTop;
- }
- }
- });
- // Add a quick "bounce" animation to the content
- function animateClick() {
- if (props.noClickAnimation) return;
- contentEl.value && animate(contentEl.value, [{
- transformOrigin: 'center'
- }, {
- transform: 'scale(1.03)'
- }, {
- transformOrigin: 'center'
- }], {
- duration: 150,
- easing: standardEasing
- });
- }
- useRender(() => createVNode(Fragment, null, [slots.activator?.({
- isActive: isActive.value,
- props: mergeProps({
- ref: activatorRef
- }, activatorEvents.value, props.activatorProps)
- }), isMounted.value && hasContent.value && createVNode(Teleport, {
- "disabled": !teleportTarget.value,
- "to": teleportTarget.value
- }, {
- default: () => [createVNode("div", mergeProps({
- "class": ['v-overlay', {
- 'v-overlay--absolute': props.absolute || props.contained,
- 'v-overlay--active': isActive.value,
- 'v-overlay--contained': props.contained
- }, themeClasses.value, rtlClasses.value, props.class],
- "style": [stackStyles.value, {
- top: convertToUnit(top.value)
- }, props.style],
- "ref": root
- }, scopeId, attrs), [createVNode(Scrim, mergeProps({
- "color": scrimColor,
- "modelValue": isActive.value && !!props.scrim
- }, scrimEvents.value), null), createVNode(MaybeTransition, {
- "appear": true,
- "persisted": true,
- "transition": props.transition,
- "target": activatorEl.value,
- "onAfterLeave": () => {
- onAfterLeave();
- emit('afterLeave');
- }
- }, {
- default: () => [withDirectives(createVNode("div", mergeProps({
- "ref": contentEl,
- "class": ['v-overlay__content', props.contentClass],
- "style": [dimensionStyles.value, contentStyles.value]
- }, contentEvents.value, props.contentProps), [slots.default?.({
- isActive
- })]), [[vShow, isActive.value], [resolveDirective("click-outside"), {
- handler: onClickOutside,
- closeConditional,
- include: () => [activatorEl.value]
- }]])]
- })])]
- })]));
- return {
- activatorEl,
- animateClick,
- contentEl,
- globalTop,
- localTop,
- updateLocation
- };
- }
- });
- // Types
- const Refs = Symbol('Forwarded refs');
- /** Omit properties starting with P */
- function getDescriptor(obj, key) {
- let currentObj = obj;
- while (currentObj) {
- const descriptor = Reflect.getOwnPropertyDescriptor(currentObj, key);
- if (descriptor) return descriptor;
- currentObj = Object.getPrototypeOf(currentObj);
- }
- return undefined;
- }
- function forwardRefs(target) {
- for (var _len = arguments.length, refs = new Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) {
- refs[_key - 1] = arguments[_key];
- }
- target[Refs] = refs;
- return new Proxy(target, {
- get(target, key) {
- if (Reflect.has(target, key)) {
- return Reflect.get(target, key);
- }
- // Skip internal properties
- if (typeof key === 'symbol' || key.startsWith('__')) return;
- for (const ref of refs) {
- if (ref.value && Reflect.has(ref.value, key)) {
- const val = Reflect.get(ref.value, key);
- return typeof val === 'function' ? val.bind(ref.value) : val;
- }
- }
- },
- has(target, key) {
- if (Reflect.has(target, key)) {
- return true;
- }
- // Skip internal properties
- if (typeof key === 'symbol' || key.startsWith('__')) return false;
- for (const ref of refs) {
- if (ref.value && Reflect.has(ref.value, key)) {
- return true;
- }
- }
- return false;
- },
- set(target, key, value) {
- if (Reflect.has(target, key)) {
- return Reflect.set(target, key, value);
- }
- // Skip internal properties
- if (typeof key === 'symbol' || key.startsWith('__')) return false;
- for (const ref of refs) {
- if (ref.value && Reflect.has(ref.value, key)) {
- return Reflect.set(ref.value, key, value);
- }
- }
- return false;
- },
- getOwnPropertyDescriptor(target, key) {
- const descriptor = Reflect.getOwnPropertyDescriptor(target, key);
- if (descriptor) return descriptor;
- // Skip internal properties
- if (typeof key === 'symbol' || key.startsWith('__')) return;
- // Check each ref's own properties
- for (const ref of refs) {
- if (!ref.value) continue;
- const descriptor = getDescriptor(ref.value, key) ?? ('_' in ref.value ? getDescriptor(ref.value._?.setupState, key) : undefined);
- if (descriptor) return descriptor;
- }
- // Recursive search up each ref's prototype
- for (const ref of refs) {
- const childRefs = ref.value && ref.value[Refs];
- if (!childRefs) continue;
- const queue = childRefs.slice();
- while (queue.length) {
- const ref = queue.shift();
- const descriptor = getDescriptor(ref.value, key);
- if (descriptor) return descriptor;
- const childRefs = ref.value && ref.value[Refs];
- if (childRefs) queue.push(...childRefs);
- }
- }
- return undefined;
- }
- });
- }
- // Types
- const makeVMenuProps = propsFactory({
- // TODO
- // disableKeys: Boolean,
- id: String,
- ...omit(makeVOverlayProps({
- closeDelay: 250,
- closeOnContentClick: true,
- locationStrategy: 'connected',
- openDelay: 300,
- scrim: false,
- scrollStrategy: 'reposition',
- transition: {
- component: VDialogTransition
- }
- }), ['absolute'])
- }, 'VMenu');
- const VMenu = genericComponent()({
- name: 'VMenu',
- props: makeVMenuProps(),
- emits: {
- 'update:modelValue': value => true
- },
- setup(props, _ref) {
- let {
- slots
- } = _ref;
- const isActive = useProxiedModel(props, 'modelValue');
- const {
- scopeId
- } = useScopeId();
- const uid = getUid();
- const id = computed(() => props.id || `v-menu-${uid}`);
- const overlay = ref();
- const parent = inject$1(VMenuSymbol, null);
- const openChildren = shallowRef(0);
- provide(VMenuSymbol, {
- register() {
- ++openChildren.value;
- },
- unregister() {
- --openChildren.value;
- },
- closeParents() {
- setTimeout(() => {
- if (!openChildren.value) {
- isActive.value = false;
- parent?.closeParents();
- }
- }, 40);
- }
- });
- function onFocusIn(e) {
- const before = e.relatedTarget;
- const after = e.target;
- if (before !== after && overlay.value?.contentEl &&
- // We're the topmost menu
- overlay.value?.globalTop &&
- // It isn't the document or the menu body
- ![document, overlay.value.contentEl].includes(after) &&
- // It isn't inside the menu body
- !overlay.value.contentEl.contains(after)) {
- const focusable = focusableChildren(overlay.value.contentEl);
- focusable[0]?.focus();
- }
- }
- watch(isActive, val => {
- if (val) {
- parent?.register();
- document.addEventListener('focusin', onFocusIn, {
- once: true
- });
- } else {
- parent?.unregister();
- document.removeEventListener('focusin', onFocusIn);
- }
- });
- function onClickOutside() {
- parent?.closeParents();
- }
- function onKeydown(e) {
- if (props.disabled) return;
- if (e.key === 'Tab') {
- const nextElement = getNextElement(focusableChildren(overlay.value?.contentEl, false), e.shiftKey ? 'prev' : 'next', el => el.tabIndex >= 0);
- if (!nextElement) {
- isActive.value = false;
- overlay.value?.activatorEl?.focus();
- }
- }
- }
- function onActivatorKeydown(e) {
- if (props.disabled) return;
- const el = overlay.value?.contentEl;
- if (el && isActive.value) {
- if (e.key === 'ArrowDown') {
- e.preventDefault();
- focusChild(el, 'next');
- } else if (e.key === 'ArrowUp') {
- e.preventDefault();
- focusChild(el, 'prev');
- }
- } else if (['ArrowDown', 'ArrowUp'].includes(e.key)) {
- isActive.value = true;
- e.preventDefault();
- setTimeout(() => setTimeout(() => onActivatorKeydown(e)));
- }
- }
- const activatorProps = computed(() => mergeProps({
- 'aria-haspopup': 'menu',
- 'aria-expanded': String(isActive.value),
- 'aria-owns': id.value,
- onKeydown: onActivatorKeydown
- }, props.activatorProps));
- useRender(() => {
- const [overlayProps] = VOverlay.filterProps(props);
- return createVNode(VOverlay, mergeProps({
- "ref": overlay,
- "class": ['v-menu', props.class],
- "style": props.style
- }, overlayProps, {
- "modelValue": isActive.value,
- "onUpdate:modelValue": $event => isActive.value = $event,
- "absolute": true,
- "activatorProps": activatorProps.value,
- "onClick:outside": onClickOutside,
- "onKeydown": onKeydown
- }, scopeId), {
- activator: slots.activator,
- default: function () {
- for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) {
- args[_key] = arguments[_key];
- }
- return createVNode(VDefaultsProvider, {
- "root": "VMenu"
- }, {
- default: () => [slots.default?.(...args)]
- });
- }
- });
- });
- return forwardRefs({
- id,
- ΨopenChildren: openChildren
- }, overlay);
- }
- });
- // Types
- const makeVCounterProps = propsFactory({
- active: Boolean,
- max: [Number, String],
- value: {
- type: [Number, String],
- default: 0
- },
- ...makeComponentProps(),
- ...makeTransitionProps({
- transition: {
- component: VSlideYTransition
- }
- })
- }, 'VCounter');
- const VCounter = genericComponent()({
- name: 'VCounter',
- functional: true,
- props: makeVCounterProps(),
- setup(props, _ref) {
- let {
- slots
- } = _ref;
- const counter = computed(() => {
- return props.max ? `${props.value} / ${props.max}` : String(props.value);
- });
- useRender(() => createVNode(MaybeTransition, {
- "transition": props.transition
- }, {
- default: () => [withDirectives(createVNode("div", {
- "class": ['v-counter', props.class],
- "style": props.style
- }, [slots.default ? slots.default({
- counter: counter.value,
- max: props.max,
- value: props.value
- }) : counter.value]), [[vShow, props.active]])]
- }));
- return {};
- }
- });
- const makeVFieldLabelProps = propsFactory({
- floating: Boolean,
- ...makeComponentProps()
- }, 'VFieldLabel');
- const VFieldLabel = genericComponent()({
- name: 'VFieldLabel',
- props: makeVFieldLabelProps(),
- setup(props, _ref) {
- let {
- slots
- } = _ref;
- useRender(() => createVNode(VLabel, {
- "class": ['v-field-label', {
- 'v-field-label--floating': props.floating
- }, props.class],
- "style": props.style,
- "aria-hidden": props.floating || undefined
- }, slots));
- return {};
- }
- });
- // Types
- const allowedVariants$1 = ['underlined', 'outlined', 'filled', 'solo', 'solo-inverted', 'solo-filled', 'plain'];
- const makeVFieldProps = propsFactory({
- appendInnerIcon: IconValue,
- bgColor: String,
- clearable: Boolean,
- clearIcon: {
- type: IconValue,
- default: '$clear'
- },
- active: Boolean,
- centerAffix: {
- type: Boolean,
- default: undefined
- },
- color: String,
- baseColor: String,
- dirty: Boolean,
- disabled: {
- type: Boolean,
- default: null
- },
- error: Boolean,
- flat: Boolean,
- label: String,
- persistentClear: Boolean,
- prependInnerIcon: IconValue,
- reverse: Boolean,
- singleLine: Boolean,
- variant: {
- type: String,
- default: 'filled',
- validator: v => allowedVariants$1.includes(v)
- },
- 'onClick:clear': EventProp(),
- 'onClick:appendInner': EventProp(),
- 'onClick:prependInner': EventProp(),
- ...makeComponentProps(),
- ...makeLoaderProps(),
- ...makeRoundedProps(),
- ...makeThemeProps()
- }, 'VField');
- const VField = genericComponent()({
- name: 'VField',
- inheritAttrs: false,
- props: {
- id: String,
- ...makeFocusProps(),
- ...makeVFieldProps()
- },
- emits: {
- 'update:focused': focused => true,
- 'update:modelValue': val => true
- },
- setup(props, _ref) {
- let {
- attrs,
- emit,
- slots
- } = _ref;
- const {
- themeClasses
- } = provideTheme(props);
- const {
- loaderClasses
- } = useLoader(props);
- const {
- focusClasses,
- isFocused,
- focus,
- blur
- } = useFocus(props);
- const {
- InputIcon
- } = useInputIcon(props);
- const {
- roundedClasses
- } = useRounded(props);
- const {
- rtlClasses
- } = useRtl();
- const isActive = computed(() => props.dirty || props.active);
- const hasLabel = computed(() => !props.singleLine && !!(props.label || slots.label));
- const uid = getUid();
- const id = computed(() => props.id || `input-${uid}`);
- const messagesId = computed(() => `${id.value}-messages`);
- const labelRef = ref();
- const floatingLabelRef = ref();
- const controlRef = ref();
- const isPlainOrUnderlined = computed(() => ['plain', 'underlined'].includes(props.variant));
- const {
- backgroundColorClasses,
- backgroundColorStyles
- } = useBackgroundColor(toRef(props, 'bgColor'));
- const {
- textColorClasses,
- textColorStyles
- } = useTextColor(computed(() => {
- return props.error || props.disabled ? undefined : isActive.value && isFocused.value ? props.color : props.baseColor;
- }));
- watch(isActive, val => {
- if (hasLabel.value) {
- const el = labelRef.value.$el;
- const targetEl = floatingLabelRef.value.$el;
- requestAnimationFrame(() => {
- const rect = nullifyTransforms(el);
- const targetRect = targetEl.getBoundingClientRect();
- const x = targetRect.x - rect.x;
- const y = targetRect.y - rect.y - (rect.height / 2 - targetRect.height / 2);
- const targetWidth = targetRect.width / 0.75;
- const width = Math.abs(targetWidth - rect.width) > 1 ? {
- maxWidth: convertToUnit(targetWidth)
- } : undefined;
- const style = getComputedStyle(el);
- const targetStyle = getComputedStyle(targetEl);
- const duration = parseFloat(style.transitionDuration) * 1000 || 150;
- const scale = parseFloat(targetStyle.getPropertyValue('--v-field-label-scale'));
- const color = targetStyle.getPropertyValue('color');
- el.style.visibility = 'visible';
- targetEl.style.visibility = 'hidden';
- animate(el, {
- transform: `translate(${x}px, ${y}px) scale(${scale})`,
- color,
- ...width
- }, {
- duration,
- easing: standardEasing,
- direction: val ? 'normal' : 'reverse'
- }).finished.then(() => {
- el.style.removeProperty('visibility');
- targetEl.style.removeProperty('visibility');
- });
- });
- }
- }, {
- flush: 'post'
- });
- const slotProps = computed(() => ({
- isActive,
- isFocused,
- controlRef,
- blur,
- focus
- }));
- function onClick(e) {
- if (e.target !== document.activeElement) {
- e.preventDefault();
- }
- }
- useRender(() => {
- const isOutlined = props.variant === 'outlined';
- const hasPrepend = slots['prepend-inner'] || props.prependInnerIcon;
- const hasClear = !!(props.clearable || slots.clear);
- const hasAppend = !!(slots['append-inner'] || props.appendInnerIcon || hasClear);
- const label = slots.label ? slots.label({
- ...slotProps.value,
- label: props.label,
- props: {
- for: id.value
- }
- }) : props.label;
- return createVNode("div", mergeProps({
- "class": ['v-field', {
- 'v-field--active': isActive.value,
- 'v-field--appended': hasAppend,
- 'v-field--center-affix': props.centerAffix ?? !isPlainOrUnderlined.value,
- 'v-field--disabled': props.disabled,
- 'v-field--dirty': props.dirty,
- 'v-field--error': props.error,
- 'v-field--flat': props.flat,
- 'v-field--has-background': !!props.bgColor,
- 'v-field--persistent-clear': props.persistentClear,
- 'v-field--prepended': hasPrepend,
- 'v-field--reverse': props.reverse,
- 'v-field--single-line': props.singleLine,
- 'v-field--no-label': !label,
- [`v-field--variant-${props.variant}`]: true
- }, themeClasses.value, backgroundColorClasses.value, focusClasses.value, loaderClasses.value, roundedClasses.value, rtlClasses.value, props.class],
- "style": [backgroundColorStyles.value, textColorStyles.value, props.style],
- "onClick": onClick
- }, attrs), [createVNode("div", {
- "class": "v-field__overlay"
- }, null), createVNode(LoaderSlot, {
- "name": "v-field",
- "active": !!props.loading,
- "color": props.error ? 'error' : typeof props.loading === 'string' ? props.loading : props.color
- }, {
- default: slots.loader
- }), hasPrepend && createVNode("div", {
- "key": "prepend",
- "class": "v-field__prepend-inner"
- }, [props.prependInnerIcon && createVNode(InputIcon, {
- "key": "prepend-icon",
- "name": "prependInner"
- }, null), slots['prepend-inner']?.(slotProps.value)]), createVNode("div", {
- "class": "v-field__field",
- "data-no-activator": ""
- }, [['filled', 'solo', 'solo-inverted', 'solo-filled'].includes(props.variant) && hasLabel.value && createVNode(VFieldLabel, {
- "key": "floating-label",
- "ref": floatingLabelRef,
- "class": [textColorClasses.value],
- "floating": true,
- "for": id.value
- }, {
- default: () => [label]
- }), createVNode(VFieldLabel, {
- "ref": labelRef,
- "for": id.value
- }, {
- default: () => [label]
- }), slots.default?.({
- ...slotProps.value,
- props: {
- id: id.value,
- class: 'v-field__input',
- 'aria-describedby': messagesId.value
- },
- focus,
- blur
- })]), hasClear && createVNode(VExpandXTransition, {
- "key": "clear"
- }, {
- default: () => [withDirectives(createVNode("div", {
- "class": "v-field__clearable",
- "onMousedown": e => {
- e.preventDefault();
- e.stopPropagation();
- }
- }, [slots.clear ? slots.clear() : createVNode(InputIcon, {
- "name": "clear"
- }, null)]), [[vShow, props.dirty]])]
- }), hasAppend && createVNode("div", {
- "key": "append",
- "class": "v-field__append-inner"
- }, [slots['append-inner']?.(slotProps.value), props.appendInnerIcon && createVNode(InputIcon, {
- "key": "append-icon",
- "name": "appendInner"
- }, null)]), createVNode("div", {
- "class": ['v-field__outline', textColorClasses.value]
- }, [isOutlined && createVNode(Fragment, null, [createVNode("div", {
- "class": "v-field__outline__start"
- }, null), hasLabel.value && createVNode("div", {
- "class": "v-field__outline__notch"
- }, [createVNode(VFieldLabel, {
- "ref": floatingLabelRef,
- "floating": true,
- "for": id.value
- }, {
- default: () => [label]
- })]), createVNode("div", {
- "class": "v-field__outline__end"
- }, null)]), isPlainOrUnderlined.value && hasLabel.value && createVNode(VFieldLabel, {
- "ref": floatingLabelRef,
- "floating": true,
- "for": id.value
- }, {
- default: () => [label]
- })])]);
- });
- return {
- controlRef
- };
- }
- });
- // TODO: this is kinda slow, might be better to implicitly inherit props instead
- function filterFieldProps(attrs) {
- const keys = Object.keys(VField.props).filter(k => !isOn(k) && k !== 'class' && k !== 'style');
- return pick(attrs, keys);
- }
- // Types
- const activeTypes = ['color', 'file', 'time', 'date', 'datetime-local', 'week', 'month'];
- const makeVTextFieldProps = propsFactory({
- autofocus: Boolean,
- counter: [Boolean, Number, String],
- counterValue: Function,
- prefix: String,
- placeholder: String,
- persistentPlaceholder: Boolean,
- persistentCounter: Boolean,
- suffix: String,
- type: {
- type: String,
- default: 'text'
- },
- modelModifiers: Object,
- ...makeVInputProps(),
- ...makeVFieldProps()
- }, 'VTextField');
- const VTextField = genericComponent()({
- name: 'VTextField',
- directives: {
- Intersect
- },
- inheritAttrs: false,
- props: makeVTextFieldProps(),
- emits: {
- 'click:control': e => true,
- 'mousedown:control': e => true,
- 'update:focused': focused => true,
- 'update:modelValue': val => true
- },
- setup(props, _ref) {
- let {
- attrs,
- emit,
- slots
- } = _ref;
- const model = useProxiedModel(props, 'modelValue');
- const {
- isFocused,
- focus,
- blur
- } = useFocus(props);
- const counterValue = computed(() => {
- return typeof props.counterValue === 'function' ? props.counterValue(model.value) : (model.value ?? '').toString().length;
- });
- const max = computed(() => {
- if (attrs.maxlength) return attrs.maxlength;
- if (!props.counter || typeof props.counter !== 'number' && typeof props.counter !== 'string') return undefined;
- return props.counter;
- });
- const isPlainOrUnderlined = computed(() => ['plain', 'underlined'].includes(props.variant));
- function onIntersect(isIntersecting, entries) {
- if (!props.autofocus || !isIntersecting) return;
- entries[0].target?.focus?.();
- }
- const vInputRef = ref();
- const vFieldRef = ref();
- const inputRef = ref();
- const isActive = computed(() => activeTypes.includes(props.type) || props.persistentPlaceholder || isFocused.value || props.active);
- function onFocus() {
- if (inputRef.value !== document.activeElement) {
- inputRef.value?.focus();
- }
- if (!isFocused.value) focus();
- }
- function onControlMousedown(e) {
- emit('mousedown:control', e);
- if (e.target === inputRef.value) return;
- onFocus();
- e.preventDefault();
- }
- function onControlClick(e) {
- onFocus();
- emit('click:control', e);
- }
- function onClear(e) {
- e.stopPropagation();
- onFocus();
- nextTick(() => {
- model.value = null;
- callEvent(props['onClick:clear'], e);
- });
- }
- function onInput(e) {
- const el = e.target;
- model.value = el.value;
- if (props.modelModifiers?.trim && ['text', 'search', 'password', 'tel', 'url'].includes(props.type)) {
- const caretPosition = [el.selectionStart, el.selectionEnd];
- nextTick(() => {
- el.selectionStart = caretPosition[0];
- el.selectionEnd = caretPosition[1];
- });
- }
- }
- useRender(() => {
- const hasCounter = !!(slots.counter || props.counter || props.counterValue);
- const hasDetails = !!(hasCounter || slots.details);
- const [rootAttrs, inputAttrs] = filterInputAttrs(attrs);
- const [{
- modelValue: _,
- ...inputProps
- }] = VInput.filterProps(props);
- const [fieldProps] = filterFieldProps(props);
- return createVNode(VInput, mergeProps({
- "ref": vInputRef,
- "modelValue": model.value,
- "onUpdate:modelValue": $event => model.value = $event,
- "class": ['v-text-field', {
- 'v-text-field--prefixed': props.prefix,
- 'v-text-field--suffixed': props.suffix,
- 'v-text-field--plain-underlined': ['plain', 'underlined'].includes(props.variant)
- }, props.class],
- "style": props.style
- }, rootAttrs, inputProps, {
- "centerAffix": !isPlainOrUnderlined.value,
- "focused": isFocused.value
- }), {
- ...slots,
- default: _ref2 => {
- let {
- id,
- isDisabled,
- isDirty,
- isReadonly,
- isValid
- } = _ref2;
- return createVNode(VField, mergeProps({
- "ref": vFieldRef,
- "onMousedown": onControlMousedown,
- "onClick": onControlClick,
- "onClick:clear": onClear,
- "onClick:prependInner": props['onClick:prependInner'],
- "onClick:appendInner": props['onClick:appendInner'],
- "role": "textbox"
- }, fieldProps, {
- "id": id.value,
- "active": isActive.value || isDirty.value,
- "dirty": isDirty.value || props.dirty,
- "disabled": isDisabled.value,
- "focused": isFocused.value,
- "error": isValid.value === false
- }), {
- ...slots,
- default: _ref3 => {
- let {
- props: {
- class: fieldClass,
- ...slotProps
- }
- } = _ref3;
- const inputNode = withDirectives(createVNode("input", mergeProps({
- "ref": inputRef,
- "value": model.value,
- "onInput": onInput,
- "autofocus": props.autofocus,
- "readonly": isReadonly.value,
- "disabled": isDisabled.value,
- "name": props.name,
- "placeholder": props.placeholder,
- "size": 1,
- "type": props.type,
- "onFocus": onFocus,
- "onBlur": blur
- }, slotProps, inputAttrs), null), [[resolveDirective("intersect"), {
- handler: onIntersect
- }, null, {
- once: true
- }]]);
- return createVNode(Fragment, null, [props.prefix && createVNode("span", {
- "class": "v-text-field__prefix"
- }, [createVNode("span", {
- "class": "v-text-field__prefix__text"
- }, [props.prefix])]), createVNode("div", {
- "class": fieldClass,
- "data-no-activator": ""
- }, [slots.default ? createVNode(Fragment, null, [slots.default(), inputNode]) : cloneVNode(inputNode)]), props.suffix && createVNode("span", {
- "class": "v-text-field__suffix"
- }, [createVNode("span", {
- "class": "v-text-field__suffix__text"
- }, [props.suffix])])]);
- }
- });
- },
- details: hasDetails ? slotProps => createVNode(Fragment, null, [slots.details?.(slotProps), hasCounter && createVNode(Fragment, null, [createVNode("span", null, null), createVNode(VCounter, {
- "active": props.persistentCounter || isFocused.value,
- "value": counterValue.value,
- "max": max.value
- }, slots.counter)])]) : undefined
- });
- });
- return forwardRefs({}, vInputRef, vFieldRef, inputRef);
- }
- });
- // Types
- const makeVVirtualScrollItemProps = propsFactory({
- renderless: Boolean,
- ...makeComponentProps()
- }, 'VVirtualScrollItem');
- const VVirtualScrollItem = genericComponent()({
- name: 'VVirtualScrollItem',
- inheritAttrs: false,
- props: makeVVirtualScrollItemProps(),
- emits: {
- 'update:height': height => true
- },
- setup(props, _ref) {
- let {
- attrs,
- emit,
- slots
- } = _ref;
- const {
- resizeRef,
- contentRect
- } = useResizeObserver(undefined, 'border');
- watch(() => contentRect.value?.height, height => {
- if (height != null) emit('update:height', height);
- });
- useRender(() => props.renderless ? createVNode(Fragment, null, [slots.default?.({
- itemRef: resizeRef
- })]) : createVNode("div", mergeProps({
- "ref": resizeRef,
- "class": ['v-virtual-scroll__item', props.class],
- "style": props.style
- }, attrs), [slots.default?.()]));
- }
- });
- // Composables
- // Types
- const UP = -1;
- const DOWN = 1;
- const makeVirtualProps = propsFactory({
- itemHeight: {
- type: [Number, String],
- default: 48
- }
- }, 'virtual');
- function useVirtual(props, items, offset) {
- const first = shallowRef(0);
- const baseItemHeight = shallowRef(props.itemHeight);
- const itemHeight = computed({
- get: () => parseInt(baseItemHeight.value ?? 0, 10),
- set(val) {
- baseItemHeight.value = val;
- }
- });
- const containerRef = ref();
- const {
- resizeRef,
- contentRect
- } = useResizeObserver();
- watchEffect(() => {
- resizeRef.value = containerRef.value;
- });
- const display = useDisplay();
- const sizeMap = new Map();
- let sizes = Array.from({
- length: items.value.length
- });
- const visibleItems = computed(() => {
- const height = (!contentRect.value || containerRef.value === document.documentElement ? display.height.value : contentRect.value.height) - (offset?.value ?? 0);
- return Math.ceil(height / itemHeight.value * 1.7 + 1);
- });
- function handleItemResize(index, height) {
- itemHeight.value = Math.max(itemHeight.value, height);
- sizes[index] = height;
- sizeMap.set(items.value[index], height);
- }
- function calculateOffset(index) {
- return sizes.slice(0, index).reduce((acc, val) => acc + (val || itemHeight.value), 0);
- }
- function calculateMidPointIndex(scrollTop) {
- const end = items.value.length;
- let middle = 0;
- let middleOffset = 0;
- while (middleOffset < scrollTop && middle < end) {
- middleOffset += sizes[middle++] || itemHeight.value;
- }
- return middle - 1;
- }
- let lastScrollTop = 0;
- function handleScroll() {
- if (!containerRef.value || !contentRect.value) return;
- const height = contentRect.value.height - 56;
- const scrollTop = containerRef.value.scrollTop;
- const direction = scrollTop < lastScrollTop ? UP : DOWN;
- const midPointIndex = calculateMidPointIndex(scrollTop + height / 2);
- const buffer = Math.round(visibleItems.value / 3);
- const firstIndex = midPointIndex - buffer;
- const lastIndex = first.value + buffer * 2 - 1;
- if (direction === UP && midPointIndex <= lastIndex) {
- first.value = clamp(firstIndex, 0, items.value.length);
- } else if (direction === DOWN && midPointIndex >= lastIndex) {
- first.value = clamp(firstIndex, 0, items.value.length - visibleItems.value);
- }
- lastScrollTop = scrollTop;
- }
- function scrollToIndex(index) {
- if (!containerRef.value) return;
- const offset = calculateOffset(index);
- containerRef.value.scrollTop = offset;
- }
- const last = computed(() => Math.min(items.value.length, first.value + visibleItems.value));
- const computedItems = computed(() => {
- return items.value.slice(first.value, last.value).map((item, index) => ({
- raw: item,
- index: index + first.value
- }));
- });
- const paddingTop = computed(() => calculateOffset(first.value));
- const paddingBottom = computed(() => calculateOffset(items.value.length) - calculateOffset(last.value));
- watch(() => items.value.length, () => {
- sizes = createRange(items.value.length).map(() => itemHeight.value);
- sizeMap.forEach((height, item) => {
- const index = items.value.indexOf(item);
- if (index === -1) {
- sizeMap.delete(item);
- } else {
- sizes[index] = height;
- }
- });
- });
- return {
- containerRef,
- computedItems,
- itemHeight,
- paddingTop,
- paddingBottom,
- scrollToIndex,
- handleScroll,
- handleItemResize
- };
- }
- // Types
- const makeVVirtualScrollProps = propsFactory({
- items: {
- type: Array,
- default: () => []
- },
- renderless: Boolean,
- ...makeVirtualProps(),
- ...makeComponentProps(),
- ...makeDimensionProps()
- }, 'VVirtualScroll');
- const VVirtualScroll = genericComponent()({
- name: 'VVirtualScroll',
- props: makeVVirtualScrollProps(),
- setup(props, _ref) {
- let {
- slots
- } = _ref;
- const vm = getCurrentInstance('VVirtualScroll');
- const {
- dimensionStyles
- } = useDimension(props);
- const {
- containerRef,
- handleScroll,
- handleItemResize,
- scrollToIndex,
- paddingTop,
- paddingBottom,
- computedItems
- } = useVirtual(props, toRef(props, 'items'));
- useToggleScope(() => props.renderless, () => {
- onMounted(() => {
- containerRef.value = getScrollParent(vm.vnode.el, true);
- containerRef.value?.addEventListener('scroll', handleScroll);
- });
- onScopeDispose(() => {
- containerRef.value?.removeEventListener('scroll', handleScroll);
- });
- });
- useRender(() => {
- const children = computedItems.value.map(item => createVNode(VVirtualScrollItem, {
- "key": item.index,
- "renderless": props.renderless,
- "onUpdate:height": height => handleItemResize(item.index, height)
- }, {
- default: slotProps => slots.default?.({
- item: item.raw,
- index: item.index,
- ...slotProps
- })
- }));
- return props.renderless ? createVNode(Fragment, null, [createVNode("div", {
- "class": "v-virtual-scroll__spacer",
- "style": {
- paddingTop: convertToUnit(paddingTop.value)
- }
- }, null), children, createVNode("div", {
- "class": "v-virtual-scroll__spacer",
- "style": {
- paddingBottom: convertToUnit(paddingBottom.value)
- }
- }, null)]) : createVNode("div", {
- "ref": containerRef,
- "class": ['v-virtual-scroll', props.class],
- "onScroll": handleScroll,
- "style": [dimensionStyles.value, props.style]
- }, [createVNode("div", {
- "class": "v-virtual-scroll__container",
- "style": {
- paddingTop: convertToUnit(paddingTop.value),
- paddingBottom: convertToUnit(paddingBottom.value)
- }
- }, [children])]);
- });
- return {
- scrollToIndex
- };
- }
- });
- // Utilities
- // Types
- function useScrolling(listRef, textFieldRef) {
- const isScrolling = shallowRef(false);
- let scrollTimeout;
- function onListScroll(e) {
- cancelAnimationFrame(scrollTimeout);
- isScrolling.value = true;
- scrollTimeout = requestAnimationFrame(() => {
- scrollTimeout = requestAnimationFrame(() => {
- isScrolling.value = false;
- });
- });
- }
- async function finishScrolling() {
- await new Promise(resolve => requestAnimationFrame(resolve));
- await new Promise(resolve => requestAnimationFrame(resolve));
- await new Promise(resolve => requestAnimationFrame(resolve));
- await new Promise(resolve => {
- if (isScrolling.value) {
- const stop = watch(isScrolling, () => {
- stop();
- resolve();
- });
- } else resolve();
- });
- }
- async function onListKeydown(e) {
- if (e.key === 'Tab') {
- textFieldRef.value?.focus();
- }
- if (!['PageDown', 'PageUp', 'Home', 'End'].includes(e.key)) return;
- const el = listRef.value?.$el;
- if (!el) return;
- if (e.key === 'Home' || e.key === 'End') {
- el.scrollTo({
- top: e.key === 'Home' ? 0 : el.scrollHeight,
- behavior: 'smooth'
- });
- }
- await finishScrolling();
- const children = el.querySelectorAll(':scope > :not(.v-virtual-scroll__spacer)');
- if (e.key === 'PageDown' || e.key === 'Home') {
- const top = el.getBoundingClientRect().top;
- for (const child of children) {
- if (child.getBoundingClientRect().top >= top) {
- child.focus();
- break;
- }
- }
- } else {
- const bottom = el.getBoundingClientRect().bottom;
- for (const child of [...children].reverse()) {
- if (child.getBoundingClientRect().bottom <= bottom) {
- child.focus();
- break;
- }
- }
- }
- }
- return {
- onListScroll,
- onListKeydown
- };
- }
- // Types
- const makeSelectProps = propsFactory({
- chips: Boolean,
- closableChips: Boolean,
- eager: Boolean,
- hideNoData: Boolean,
- hideSelected: Boolean,
- menu: Boolean,
- menuIcon: {
- type: IconValue,
- default: '$dropdown'
- },
- menuProps: {
- type: Object
- },
- multiple: Boolean,
- noDataText: {
- type: String,
- default: '$vuetify.noDataText'
- },
- openOnClear: Boolean,
- valueComparator: {
- type: Function,
- default: deepEqual
- },
- itemColor: String,
- ...makeItemsProps({
- itemChildren: false
- })
- }, 'Select');
- const makeVSelectProps = propsFactory({
- ...makeSelectProps(),
- ...omit(makeVTextFieldProps({
- modelValue: null
- }), ['validationValue', 'dirty', 'appendInnerIcon']),
- ...makeTransitionProps({
- transition: {
- component: VDialogTransition
- }
- })
- }, 'VSelect');
- const VSelect = genericComponent()({
- name: 'VSelect',
- props: makeVSelectProps(),
- emits: {
- 'update:focused': focused => true,
- 'update:modelValue': val => true,
- 'update:menu': val => true
- },
- setup(props, _ref) {
- let {
- slots
- } = _ref;
- const {
- t
- } = useLocale();
- const vTextFieldRef = ref();
- const vMenuRef = ref();
- const _menu = useProxiedModel(props, 'menu');
- const menu = computed({
- get: () => _menu.value,
- set: v => {
- if (_menu.value && !v && vMenuRef.value?.ΨopenChildren) return;
- _menu.value = v;
- }
- });
- const {
- items,
- transformIn,
- transformOut
- } = useItems(props);
- const model = useProxiedModel(props, 'modelValue', [], v => transformIn(v === null ? [null] : wrapInArray(v)), v => {
- const transformed = transformOut(v);
- return props.multiple ? transformed : transformed[0] ?? null;
- });
- const form = useForm();
- const selections = computed(() => {
- return model.value.map(v => {
- return items.value.find(item => {
- const itemRawValue = getPropertyFromItem(item.raw, props.itemValue);
- const modelRawValue = getPropertyFromItem(v.raw, props.itemValue);
- if (itemRawValue === undefined || modelRawValue === undefined) return false;
- return props.returnObject ? props.valueComparator(itemRawValue, modelRawValue) : props.valueComparator(item.value, v.value);
- }) || v;
- });
- });
- const selected = computed(() => selections.value.map(selection => selection.props.value));
- const isFocused = shallowRef(false);
- let keyboardLookupPrefix = '';
- let keyboardLookupLastTime;
- const displayItems = computed(() => {
- if (props.hideSelected) {
- return items.value.filter(item => !selections.value.some(s => s === item));
- }
- return items.value;
- });
- const menuDisabled = computed(() => props.hideNoData && !items.value.length || props.readonly || form?.isReadonly.value);
- const listRef = ref();
- const {
- onListScroll,
- onListKeydown
- } = useScrolling(listRef, vTextFieldRef);
- function onClear(e) {
- if (props.openOnClear) {
- menu.value = true;
- }
- }
- function onMousedownControl() {
- if (menuDisabled.value) return;
- menu.value = !menu.value;
- }
- function onKeydown(e) {
- if (!e.key || props.readonly || form?.isReadonly.value) return;
- if (['Enter', ' ', 'ArrowDown', 'ArrowUp', 'Home', 'End'].includes(e.key)) {
- e.preventDefault();
- }
- if (['Enter', 'ArrowDown', ' '].includes(e.key)) {
- menu.value = true;
- }
- if (['Escape', 'Tab'].includes(e.key)) {
- menu.value = false;
- }
- if (e.key === 'Home') {
- listRef.value?.focus('first');
- } else if (e.key === 'End') {
- listRef.value?.focus('last');
- }
- // html select hotkeys
- const KEYBOARD_LOOKUP_THRESHOLD = 1000; // milliseconds
- function checkPrintable(e) {
- const isPrintableChar = e.key.length === 1;
- const noModifier = !e.ctrlKey && !e.metaKey && !e.altKey;
- return isPrintableChar && noModifier;
- }
- if (props.multiple || !checkPrintable(e)) return;
- const now = performance.now();
- if (now - keyboardLookupLastTime > KEYBOARD_LOOKUP_THRESHOLD) {
- keyboardLookupPrefix = '';
- }
- keyboardLookupPrefix += e.key.toLowerCase();
- keyboardLookupLastTime = now;
- const item = items.value.find(item => item.title.toLowerCase().startsWith(keyboardLookupPrefix));
- if (item !== undefined) {
- model.value = [item];
- }
- }
- function select(item) {
- if (props.multiple) {
- const index = selected.value.findIndex(selection => props.valueComparator(selection, item.value));
- if (index === -1) {
- model.value = [...model.value, item];
- } else {
- const value = [...model.value];
- value.splice(index, 1);
- model.value = value;
- }
- } else {
- model.value = [item];
- menu.value = false;
- }
- }
- function onBlur(e) {
- if (!listRef.value?.$el.contains(e.relatedTarget)) {
- menu.value = false;
- }
- }
- function onAfterLeave() {
- if (isFocused.value) {
- vTextFieldRef.value?.focus();
- }
- }
- function onFocusin(e) {
- isFocused.value = true;
- }
- function onModelUpdate(v) {
- if (v == null) model.value = [];else if (matchesSelector(vTextFieldRef.value, ':autofill') || matchesSelector(vTextFieldRef.value, ':-webkit-autofill')) {
- const item = items.value.find(item => item.title === v);
- if (item) {
- select(item);
- }
- } else if (vTextFieldRef.value) {
- vTextFieldRef.value.value = '';
- }
- }
- useRender(() => {
- const hasChips = !!(props.chips || slots.chip);
- const hasList = !!(!props.hideNoData || displayItems.value.length || slots['prepend-item'] || slots['append-item'] || slots['no-data']);
- const isDirty = model.value.length > 0;
- const [textFieldProps] = VTextField.filterProps(props);
- const placeholder = isDirty || !isFocused.value && props.label && !props.persistentPlaceholder ? undefined : props.placeholder;
- return createVNode(VTextField, mergeProps({
- "ref": vTextFieldRef
- }, textFieldProps, {
- "modelValue": model.value.map(v => v.props.value).join(', '),
- "onUpdate:modelValue": onModelUpdate,
- "focused": isFocused.value,
- "onUpdate:focused": $event => isFocused.value = $event,
- "validationValue": model.externalValue,
- "dirty": isDirty,
- "class": ['v-select', {
- 'v-select--active-menu': menu.value,
- 'v-select--chips': !!props.chips,
- [`v-select--${props.multiple ? 'multiple' : 'single'}`]: true,
- 'v-select--selected': model.value.length,
- 'v-select--selection-slot': !!slots.selection
- }, props.class],
- "style": props.style,
- "inputmode": "none",
- "placeholder": placeholder,
- "onClick:clear": onClear,
- "onMousedown:control": onMousedownControl,
- "onBlur": onBlur,
- "onKeydown": onKeydown
- }), {
- ...slots,
- default: () => createVNode(Fragment, null, [createVNode(VMenu, mergeProps({
- "ref": vMenuRef,
- "modelValue": menu.value,
- "onUpdate:modelValue": $event => menu.value = $event,
- "activator": "parent",
- "contentClass": "v-select__content",
- "disabled": menuDisabled.value,
- "eager": props.eager,
- "maxHeight": 310,
- "openOnClick": false,
- "closeOnContentClick": false,
- "transition": props.transition,
- "onAfterLeave": onAfterLeave
- }, props.menuProps), {
- default: () => [hasList && createVNode(VList, {
- "ref": listRef,
- "selected": selected.value,
- "selectStrategy": props.multiple ? 'independent' : 'single-independent',
- "onMousedown": e => e.preventDefault(),
- "onKeydown": onListKeydown,
- "onFocusin": onFocusin,
- "onScrollPassive": onListScroll,
- "tabindex": "-1",
- "color": props.itemColor ?? props.color
- }, {
- default: () => [slots['prepend-item']?.(), !displayItems.value.length && !props.hideNoData && (slots['no-data']?.() ?? createVNode(VListItem, {
- "title": t(props.noDataText)
- }, null)), createVNode(VVirtualScroll, {
- "renderless": true,
- "items": displayItems.value
- }, {
- default: _ref2 => {
- let {
- item,
- index,
- itemRef
- } = _ref2;
- const itemProps = mergeProps(item.props, {
- ref: itemRef,
- key: index,
- onClick: () => select(item)
- });
- return slots.item?.({
- item,
- index,
- props: itemProps
- }) ?? createVNode(VListItem, itemProps, {
- prepend: _ref3 => {
- let {
- isSelected
- } = _ref3;
- return createVNode(Fragment, null, [props.multiple && !props.hideSelected ? createVNode(VCheckboxBtn, {
- "key": item.value,
- "modelValue": isSelected,
- "ripple": false,
- "tabindex": "-1"
- }, null) : undefined, item.props.prependIcon && createVNode(VIcon, {
- "icon": item.props.prependIcon
- }, null)]);
- }
- });
- }
- }), slots['append-item']?.()]
- })]
- }), selections.value.map((item, index) => {
- function onChipClose(e) {
- e.stopPropagation();
- e.preventDefault();
- select(item);
- }
- const slotProps = {
- 'onClick:close': onChipClose,
- onMousedown(e) {
- e.preventDefault();
- e.stopPropagation();
- },
- modelValue: true,
- 'onUpdate:modelValue': undefined
- };
- return createVNode("div", {
- "key": item.value,
- "class": "v-select__selection"
- }, [hasChips ? !slots.chip ? createVNode(VChip, mergeProps({
- "key": "chip",
- "closable": props.closableChips,
- "size": "small",
- "text": item.title
- }, slotProps), null) : createVNode(VDefaultsProvider, {
- "key": "chip-defaults",
- "defaults": {
- VChip: {
- closable: props.closableChips,
- size: 'small',
- text: item.title
- }
- }
- }, {
- default: () => [slots.chip?.({
- item,
- index,
- props: slotProps
- })]
- }) : slots.selection?.({
- item,
- index
- }) ?? createVNode("span", {
- "class": "v-select__selection-text"
- }, [item.title, props.multiple && index < selections.value.length - 1 && createVNode("span", {
- "class": "v-select__selection-comma"
- }, [createTextVNode(",")])])]);
- })]),
- 'append-inner': function () {
- for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) {
- args[_key] = arguments[_key];
- }
- return createVNode(Fragment, null, [slots['append-inner']?.(...args), props.menuIcon ? createVNode(VIcon, {
- "class": "v-select__menu-icon",
- "icon": props.menuIcon
- }, null) : undefined]);
- }
- });
- });
- return forwardRefs({
- isFocused,
- menu,
- select
- }, vTextFieldRef);
- }
- });
- /* eslint-disable max-statements */
- /* eslint-disable no-labels */
- // Types
- // Composables
- const defaultFilter = (value, query, item) => {
- if (value == null || query == null) return -1;
- return value.toString().toLocaleLowerCase().indexOf(query.toString().toLocaleLowerCase());
- };
- const makeFilterProps = propsFactory({
- customFilter: Function,
- customKeyFilter: Object,
- filterKeys: [Array, String],
- filterMode: {
- type: String,
- default: 'intersection'
- },
- noFilter: Boolean
- }, 'filter');
- function filterItems(items, query, options) {
- const array = [];
- // always ensure we fall back to a functioning filter
- const filter = options?.default ?? defaultFilter;
- const keys = options?.filterKeys ? wrapInArray(options.filterKeys) : false;
- const customFiltersLength = Object.keys(options?.customKeyFilter ?? {}).length;
- if (!items?.length) return array;
- loop: for (let i = 0; i < items.length; i++) {
- const item = items[i];
- const customMatches = {};
- const defaultMatches = {};
- let match = -1;
- if (query && !options?.noFilter) {
- if (typeof item === 'object') {
- const filterKeys = keys || Object.keys(item);
- for (const key of filterKeys) {
- const value = getPropertyFromItem(item, key, item);
- const keyFilter = options?.customKeyFilter?.[key];
- match = keyFilter ? keyFilter(value, query, item) : filter(value, query, item);
- if (match !== -1 && match !== false) {
- if (keyFilter) customMatches[key] = match;else defaultMatches[key] = match;
- } else if (options?.filterMode === 'every') {
- continue loop;
- }
- }
- } else {
- match = filter(item, query, item);
- if (match !== -1 && match !== false) {
- defaultMatches.title = match;
- }
- }
- const defaultMatchesLength = Object.keys(defaultMatches).length;
- const customMatchesLength = Object.keys(customMatches).length;
- if (!defaultMatchesLength && !customMatchesLength) continue;
- if (options?.filterMode === 'union' && customMatchesLength !== customFiltersLength && !defaultMatchesLength) continue;
- if (options?.filterMode === 'intersection' && (customMatchesLength !== customFiltersLength || !defaultMatchesLength)) continue;
- }
- array.push({
- index: i,
- matches: {
- ...defaultMatches,
- ...customMatches
- }
- });
- }
- return array;
- }
- function useFilter(props, items, query, options) {
- const filteredItems = ref([]);
- const filteredMatches = ref(new Map());
- const transformedItems = computed(() => options?.transform ? unref(items).map(options?.transform) : unref(items));
- watchEffect(() => {
- const _query = typeof query === 'function' ? query() : unref(query);
- const strQuery = typeof _query !== 'string' && typeof _query !== 'number' ? '' : String(_query);
- const results = filterItems(transformedItems.value, strQuery, {
- customKeyFilter: props.customKeyFilter,
- default: props.customFilter,
- filterKeys: props.filterKeys,
- filterMode: props.filterMode,
- noFilter: props.noFilter
- });
- const originalItems = unref(items);
- const _filteredItems = [];
- const _filteredMatches = new Map();
- results.forEach(_ref => {
- let {
- index,
- matches
- } = _ref;
- const item = originalItems[index];
- _filteredItems.push(item);
- _filteredMatches.set(item.value, matches);
- });
- filteredItems.value = _filteredItems;
- filteredMatches.value = _filteredMatches;
- });
- function getMatches(item) {
- return filteredMatches.value.get(item.value);
- }
- return {
- filteredItems,
- filteredMatches,
- getMatches
- };
- }
- // Types
- function highlightResult$1(text, matches, length) {
- if (matches == null) return text;
- if (Array.isArray(matches)) throw new Error('Multiple matches is not implemented');
- return typeof matches === 'number' && ~matches ? createVNode(Fragment, null, [createVNode("span", {
- "class": "v-autocomplete__unmask"
- }, [text.substr(0, matches)]), createVNode("span", {
- "class": "v-autocomplete__mask"
- }, [text.substr(matches, length)]), createVNode("span", {
- "class": "v-autocomplete__unmask"
- }, [text.substr(matches + length)])]) : text;
- }
- const makeVAutocompleteProps = propsFactory({
- autoSelectFirst: {
- type: [Boolean, String]
- },
- search: String,
- ...makeFilterProps({
- filterKeys: ['title']
- }),
- ...makeSelectProps(),
- ...omit(makeVTextFieldProps({
- modelValue: null
- }), ['validationValue', 'dirty', 'appendInnerIcon']),
- ...makeTransitionProps({
- transition: false
- })
- }, 'VAutocomplete');
- const VAutocomplete = genericComponent()({
- name: 'VAutocomplete',
- props: makeVAutocompleteProps(),
- emits: {
- 'update:focused': focused => true,
- 'update:search': val => true,
- 'update:modelValue': val => true,
- 'update:menu': val => true
- },
- setup(props, _ref) {
- let {
- slots
- } = _ref;
- const {
- t
- } = useLocale();
- const vTextFieldRef = ref();
- const isFocused = shallowRef(false);
- const isPristine = shallowRef(true);
- const listHasFocus = shallowRef(false);
- const vMenuRef = ref();
- const _menu = useProxiedModel(props, 'menu');
- const menu = computed({
- get: () => _menu.value,
- set: v => {
- if (_menu.value && !v && vMenuRef.value?.ΨopenChildren) return;
- _menu.value = v;
- }
- });
- const selectionIndex = shallowRef(-1);
- const color = computed(() => vTextFieldRef.value?.color);
- const {
- items,
- transformIn,
- transformOut
- } = useItems(props);
- const {
- textColorClasses,
- textColorStyles
- } = useTextColor(color);
- const search = useProxiedModel(props, 'search', '');
- const model = useProxiedModel(props, 'modelValue', [], v => transformIn(v === null ? [null] : wrapInArray(v)), v => {
- const transformed = transformOut(v);
- return props.multiple ? transformed : transformed[0] ?? null;
- });
- const form = useForm();
- const {
- filteredItems,
- getMatches
- } = useFilter(props, items, () => isPristine.value ? '' : search.value);
- const selections = computed(() => {
- return model.value.map(v => {
- return items.value.find(item => {
- const itemRawValue = getPropertyFromItem(item.raw, props.itemValue);
- const modelRawValue = getPropertyFromItem(v.raw, props.itemValue);
- if (itemRawValue === undefined || modelRawValue === undefined) return false;
- return props.returnObject ? props.valueComparator(itemRawValue, modelRawValue) : props.valueComparator(item.value, v.value);
- }) || v;
- });
- });
- const displayItems = computed(() => {
- if (props.hideSelected) {
- return filteredItems.value.filter(filteredItem => !selections.value.some(s => s.value === filteredItem.value));
- }
- return filteredItems.value;
- });
- const selected = computed(() => selections.value.map(selection => selection.props.value));
- const selection = computed(() => selections.value[selectionIndex.value]);
- const highlightFirst = computed(() => {
- const selectFirst = props.autoSelectFirst === true || props.autoSelectFirst === 'exact' && search.value === displayItems.value[0]?.title;
- return selectFirst && displayItems.value.length > 0 && !isPristine.value && !listHasFocus.value;
- });
- const menuDisabled = computed(() => props.hideNoData && !items.value.length || props.readonly || form?.isReadonly.value);
- const listRef = ref();
- const {
- onListScroll,
- onListKeydown
- } = useScrolling(listRef, vTextFieldRef);
- function onClear(e) {
- if (props.openOnClear) {
- menu.value = true;
- }
- search.value = '';
- }
- function onMousedownControl() {
- if (menuDisabled.value) return;
- menu.value = true;
- }
- function onMousedownMenuIcon(e) {
- if (menuDisabled.value) return;
- if (isFocused.value) {
- e.preventDefault();
- e.stopPropagation();
- }
- menu.value = !menu.value;
- }
- function onKeydown(e) {
- if (props.readonly || form?.isReadonly.value) return;
- const selectionStart = vTextFieldRef.value.selectionStart;
- const length = selected.value.length;
- if (selectionIndex.value > -1 || ['Enter', 'ArrowDown', 'ArrowUp'].includes(e.key)) {
- e.preventDefault();
- }
- if (['Enter', 'ArrowDown'].includes(e.key)) {
- menu.value = true;
- }
- if (['Escape'].includes(e.key)) {
- menu.value = false;
- }
- if (highlightFirst.value && ['Enter', 'Tab'].includes(e.key)) {
- select(filteredItems.value[0]);
- }
- if (e.key === 'ArrowDown' && highlightFirst.value) {
- listRef.value?.focus('next');
- }
- if (!props.multiple) return;
- if (['Backspace', 'Delete'].includes(e.key)) {
- if (selectionIndex.value < 0) {
- if (e.key === 'Backspace' && !search.value) {
- selectionIndex.value = length - 1;
- }
- return;
- }
- const originalSelectionIndex = selectionIndex.value;
- if (selection.value) select(selection.value);
- selectionIndex.value = originalSelectionIndex >= length - 1 ? length - 2 : originalSelectionIndex;
- }
- if (e.key === 'ArrowLeft') {
- if (selectionIndex.value < 0 && selectionStart > 0) return;
- const prev = selectionIndex.value > -1 ? selectionIndex.value - 1 : length - 1;
- if (selections.value[prev]) {
- selectionIndex.value = prev;
- } else {
- selectionIndex.value = -1;
- vTextFieldRef.value.setSelectionRange(search.value?.length, search.value?.length);
- }
- }
- if (e.key === 'ArrowRight') {
- if (selectionIndex.value < 0) return;
- const next = selectionIndex.value + 1;
- if (selections.value[next]) {
- selectionIndex.value = next;
- } else {
- selectionIndex.value = -1;
- vTextFieldRef.value.setSelectionRange(0, 0);
- }
- }
- }
- function onInput(e) {
- search.value = e.target.value;
- }
- function onChange(e) {
- if (matchesSelector(vTextFieldRef.value, ':autofill') || matchesSelector(vTextFieldRef.value, ':-webkit-autofill')) {
- const item = items.value.find(item => item.title === e.target.value);
- if (item) {
- select(item);
- }
- }
- }
- function onAfterLeave() {
- if (isFocused.value) {
- isPristine.value = true;
- vTextFieldRef.value?.focus();
- }
- }
- function onFocusin(e) {
- isFocused.value = true;
- setTimeout(() => {
- listHasFocus.value = true;
- });
- }
- function onFocusout(e) {
- listHasFocus.value = false;
- }
- function onUpdateModelValue(v) {
- if (v == null || v === '' && !props.multiple) model.value = [];
- }
- const isSelecting = shallowRef(false);
- function select(item) {
- if (props.multiple) {
- const index = selected.value.findIndex(selection => props.valueComparator(selection, item.value));
- if (index === -1) {
- model.value = [...model.value, item];
- } else {
- const value = [...model.value];
- value.splice(index, 1);
- model.value = value;
- }
- } else {
- model.value = [item];
- isSelecting.value = true;
- search.value = item.title;
- menu.value = false;
- isPristine.value = true;
- nextTick(() => isSelecting.value = false);
- }
- }
- watch(isFocused, (val, oldVal) => {
- if (val === oldVal) return;
- if (val) {
- isSelecting.value = true;
- search.value = props.multiple ? '' : String(selections.value.at(-1)?.props.title ?? '');
- isPristine.value = true;
- nextTick(() => isSelecting.value = false);
- } else {
- if (!props.multiple && !search.value) model.value = [];else if (highlightFirst.value && !listHasFocus.value && !selections.value.some(_ref2 => {
- let {
- value
- } = _ref2;
- return value === displayItems.value[0].value;
- })) {
- select(displayItems.value[0]);
- }
- menu.value = false;
- search.value = '';
- selectionIndex.value = -1;
- }
- });
- watch(search, val => {
- if (!isFocused.value || isSelecting.value) return;
- if (val) menu.value = true;
- isPristine.value = !val;
- });
- useRender(() => {
- const hasChips = !!(props.chips || slots.chip);
- const hasList = !!(!props.hideNoData || displayItems.value.length || slots['prepend-item'] || slots['append-item'] || slots['no-data']);
- const isDirty = model.value.length > 0;
- const [textFieldProps] = VTextField.filterProps(props);
- return createVNode(VTextField, mergeProps({
- "ref": vTextFieldRef
- }, textFieldProps, {
- "modelValue": search.value,
- "onUpdate:modelValue": onUpdateModelValue,
- "focused": isFocused.value,
- "onUpdate:focused": $event => isFocused.value = $event,
- "validationValue": model.externalValue,
- "dirty": isDirty,
- "onInput": onInput,
- "onChange": onChange,
- "class": ['v-autocomplete', `v-autocomplete--${props.multiple ? 'multiple' : 'single'}`, {
- 'v-autocomplete--active-menu': menu.value,
- 'v-autocomplete--chips': !!props.chips,
- 'v-autocomplete--selection-slot': !!slots.selection,
- 'v-autocomplete--selecting-index': selectionIndex.value > -1
- }, props.class],
- "style": props.style,
- "readonly": props.readonly,
- "placeholder": isDirty ? undefined : props.placeholder,
- "onClick:clear": onClear,
- "onMousedown:control": onMousedownControl,
- "onKeydown": onKeydown
- }), {
- ...slots,
- default: () => createVNode(Fragment, null, [createVNode(VMenu, mergeProps({
- "ref": vMenuRef,
- "modelValue": menu.value,
- "onUpdate:modelValue": $event => menu.value = $event,
- "activator": "parent",
- "contentClass": "v-autocomplete__content",
- "disabled": menuDisabled.value,
- "eager": props.eager,
- "maxHeight": 310,
- "openOnClick": false,
- "closeOnContentClick": false,
- "transition": props.transition,
- "onAfterLeave": onAfterLeave
- }, props.menuProps), {
- default: () => [hasList && createVNode(VList, {
- "ref": listRef,
- "selected": selected.value,
- "selectStrategy": props.multiple ? 'independent' : 'single-independent',
- "onMousedown": e => e.preventDefault(),
- "onKeydown": onListKeydown,
- "onFocusin": onFocusin,
- "onFocusout": onFocusout,
- "onScrollPassive": onListScroll,
- "tabindex": "-1",
- "color": props.itemColor ?? props.color
- }, {
- default: () => [slots['prepend-item']?.(), !displayItems.value.length && !props.hideNoData && (slots['no-data']?.() ?? createVNode(VListItem, {
- "title": t(props.noDataText)
- }, null)), createVNode(VVirtualScroll, {
- "renderless": true,
- "items": displayItems.value
- }, {
- default: _ref3 => {
- let {
- item,
- index,
- itemRef
- } = _ref3;
- const itemProps = mergeProps(item.props, {
- ref: itemRef,
- key: index,
- active: highlightFirst.value && index === 0 ? true : undefined,
- onClick: () => select(item)
- });
- return slots.item?.({
- item,
- index,
- props: itemProps
- }) ?? createVNode(VListItem, itemProps, {
- prepend: _ref4 => {
- let {
- isSelected
- } = _ref4;
- return createVNode(Fragment, null, [props.multiple && !props.hideSelected ? createVNode(VCheckboxBtn, {
- "key": item.value,
- "modelValue": isSelected,
- "ripple": false,
- "tabindex": "-1"
- }, null) : undefined, item.props.prependIcon && createVNode(VIcon, {
- "icon": item.props.prependIcon
- }, null)]);
- },
- title: () => {
- return isPristine.value ? item.title : highlightResult$1(item.title, getMatches(item)?.title, search.value?.length ?? 0);
- }
- });
- }
- }), slots['append-item']?.()]
- })]
- }), selections.value.map((item, index) => {
- function onChipClose(e) {
- e.stopPropagation();
- e.preventDefault();
- select(item);
- }
- const slotProps = {
- 'onClick:close': onChipClose,
- onMousedown(e) {
- e.preventDefault();
- e.stopPropagation();
- },
- modelValue: true,
- 'onUpdate:modelValue': undefined
- };
- return createVNode("div", {
- "key": item.value,
- "class": ['v-autocomplete__selection', index === selectionIndex.value && ['v-autocomplete__selection--selected', textColorClasses.value]],
- "style": index === selectionIndex.value ? textColorStyles.value : {}
- }, [hasChips ? !slots.chip ? createVNode(VChip, mergeProps({
- "key": "chip",
- "closable": props.closableChips,
- "size": "small",
- "text": item.title
- }, slotProps), null) : createVNode(VDefaultsProvider, {
- "key": "chip-defaults",
- "defaults": {
- VChip: {
- closable: props.closableChips,
- size: 'small',
- text: item.title
- }
- }
- }, {
- default: () => [slots.chip?.({
- item,
- index,
- props: slotProps
- })]
- }) : slots.selection?.({
- item,
- index
- }) ?? createVNode("span", {
- "class": "v-autocomplete__selection-text"
- }, [item.title, props.multiple && index < selections.value.length - 1 && createVNode("span", {
- "class": "v-autocomplete__selection-comma"
- }, [createTextVNode(",")])])]);
- })]),
- 'append-inner': function () {
- for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) {
- args[_key] = arguments[_key];
- }
- return createVNode(Fragment, null, [slots['append-inner']?.(...args), props.menuIcon ? createVNode(VIcon, {
- "class": "v-autocomplete__menu-icon",
- "icon": props.menuIcon,
- "onMousedown": onMousedownMenuIcon,
- "onClick": noop
- }, null) : undefined]);
- }
- });
- });
- return forwardRefs({
- isFocused,
- isPristine,
- menu,
- search,
- filteredItems,
- select
- }, vTextFieldRef);
- }
- });
- const makeVBadgeProps = propsFactory({
- bordered: Boolean,
- color: String,
- content: [Number, String],
- dot: Boolean,
- floating: Boolean,
- icon: IconValue,
- inline: Boolean,
- label: {
- type: String,
- default: '$vuetify.badge'
- },
- max: [Number, String],
- modelValue: {
- type: Boolean,
- default: true
- },
- offsetX: [Number, String],
- offsetY: [Number, String],
- textColor: String,
- ...makeComponentProps(),
- ...makeLocationProps({
- location: 'top end'
- }),
- ...makeRoundedProps(),
- ...makeTagProps(),
- ...makeThemeProps(),
- ...makeTransitionProps({
- transition: 'scale-rotate-transition'
- })
- }, 'VBadge');
- const VBadge = genericComponent()({
- name: 'VBadge',
- inheritAttrs: false,
- props: makeVBadgeProps(),
- setup(props, ctx) {
- const {
- backgroundColorClasses,
- backgroundColorStyles
- } = useBackgroundColor(toRef(props, 'color'));
- const {
- roundedClasses
- } = useRounded(props);
- const {
- t
- } = useLocale();
- const {
- textColorClasses,
- textColorStyles
- } = useTextColor(toRef(props, 'textColor'));
- const {
- themeClasses
- } = useTheme();
- const {
- locationStyles
- } = useLocation(props, true, side => {
- const base = props.floating ? props.dot ? 2 : 4 : props.dot ? 8 : 12;
- return base + (['top', 'bottom'].includes(side) ? +(props.offsetY ?? 0) : ['left', 'right'].includes(side) ? +(props.offsetX ?? 0) : 0);
- });
- useRender(() => {
- const value = Number(props.content);
- const content = !props.max || isNaN(value) ? props.content : value <= +props.max ? value : `${props.max}+`;
- const [badgeAttrs, attrs] = pick(ctx.attrs, ['aria-atomic', 'aria-label', 'aria-live', 'role', 'title']);
- return createVNode(props.tag, mergeProps({
- "class": ['v-badge', {
- 'v-badge--bordered': props.bordered,
- 'v-badge--dot': props.dot,
- 'v-badge--floating': props.floating,
- 'v-badge--inline': props.inline
- }, props.class]
- }, attrs, {
- "style": props.style
- }), {
- default: () => [createVNode("div", {
- "class": "v-badge__wrapper"
- }, [ctx.slots.default?.(), createVNode(MaybeTransition, {
- "transition": props.transition
- }, {
- default: () => [withDirectives(createVNode("span", mergeProps({
- "class": ['v-badge__badge', themeClasses.value, backgroundColorClasses.value, roundedClasses.value, textColorClasses.value],
- "style": [backgroundColorStyles.value, textColorStyles.value, props.inline ? {} : locationStyles.value],
- "aria-atomic": "true",
- "aria-label": t(props.label, value),
- "aria-live": "polite",
- "role": "status"
- }, badgeAttrs), [props.dot ? undefined : ctx.slots.badge ? ctx.slots.badge?.() : props.icon ? createVNode(VIcon, {
- "icon": props.icon
- }, null) : content]), [[vShow, props.modelValue]])]
- })])]
- });
- });
- return {};
- }
- });
- const makeVBannerActionsProps = propsFactory({
- color: String,
- density: String,
- ...makeComponentProps()
- }, 'VBannerActions');
- const VBannerActions = genericComponent()({
- name: 'VBannerActions',
- props: makeVBannerActionsProps(),
- setup(props, _ref) {
- let {
- slots
- } = _ref;
- provideDefaults({
- VBtn: {
- color: props.color,
- density: props.density,
- variant: 'text'
- }
- });
- useRender(() => createVNode("div", {
- "class": ['v-banner-actions', props.class],
- "style": props.style
- }, [slots.default?.()]));
- return {};
- }
- });
- // Utilities
- const VBannerText = createSimpleFunctional('v-banner-text');
- // Types
- const makeVBannerProps = propsFactory({
- avatar: String,
- color: String,
- icon: IconValue,
- lines: String,
- stacked: Boolean,
- sticky: Boolean,
- text: String,
- ...makeBorderProps(),
- ...makeComponentProps(),
- ...makeDensityProps(),
- ...makeDimensionProps(),
- ...makeElevationProps(),
- ...makeLocationProps(),
- ...makePositionProps(),
- ...makeRoundedProps(),
- ...makeTagProps(),
- ...makeThemeProps()
- }, 'VBanner');
- const VBanner = genericComponent()({
- name: 'VBanner',
- props: makeVBannerProps(),
- setup(props, _ref) {
- let {
- slots
- } = _ref;
- const {
- borderClasses
- } = useBorder(props);
- const {
- densityClasses
- } = useDensity(props);
- const {
- mobile
- } = useDisplay();
- const {
- dimensionStyles
- } = useDimension(props);
- const {
- elevationClasses
- } = useElevation(props);
- const {
- locationStyles
- } = useLocation(props);
- const {
- positionClasses
- } = usePosition(props);
- const {
- roundedClasses
- } = useRounded(props);
- const {
- themeClasses
- } = provideTheme(props);
- const color = toRef(props, 'color');
- const density = toRef(props, 'density');
- provideDefaults({
- VBannerActions: {
- color,
- density
- }
- });
- useRender(() => {
- const hasText = !!(props.text || slots.text);
- const hasPrependMedia = !!(props.avatar || props.icon);
- const hasPrepend = !!(hasPrependMedia || slots.prepend);
- return createVNode(props.tag, {
- "class": ['v-banner', {
- 'v-banner--stacked': props.stacked || mobile.value,
- 'v-banner--sticky': props.sticky,
- [`v-banner--${props.lines}-line`]: !!props.lines
- }, borderClasses.value, densityClasses.value, elevationClasses.value, positionClasses.value, roundedClasses.value, themeClasses.value, props.class],
- "style": [dimensionStyles.value, locationStyles.value, props.style],
- "role": "banner"
- }, {
- default: () => [hasPrepend && createVNode("div", {
- "key": "prepend",
- "class": "v-banner__prepend"
- }, [!slots.prepend ? createVNode(VAvatar, {
- "key": "prepend-avatar",
- "color": color.value,
- "density": density.value,
- "icon": props.icon,
- "image": props.avatar
- }, null) : createVNode(VDefaultsProvider, {
- "key": "prepend-defaults",
- "disabled": !hasPrependMedia,
- "defaults": {
- VAvatar: {
- color: color.value,
- density: density.value,
- icon: props.icon,
- image: props.avatar
- }
- }
- }, slots.prepend)]), createVNode("div", {
- "class": "v-banner__content"
- }, [hasText && createVNode(VBannerText, {
- "key": "text"
- }, {
- default: () => [slots.text?.() ?? props.text]
- }), slots.default?.()]), slots.actions && createVNode(VBannerActions, {
- "key": "actions"
- }, slots.actions)]
- });
- });
- }
- });
- const makeVBottomNavigationProps = propsFactory({
- bgColor: String,
- color: String,
- grow: Boolean,
- mode: {
- type: String,
- validator: v => !v || ['horizontal', 'shift'].includes(v)
- },
- height: {
- type: [Number, String],
- default: 56
- },
- active: {
- type: Boolean,
- default: true
- },
- ...makeBorderProps(),
- ...makeComponentProps(),
- ...makeDensityProps(),
- ...makeElevationProps(),
- ...makeRoundedProps(),
- ...makeLayoutItemProps({
- name: 'bottom-navigation'
- }),
- ...makeTagProps({
- tag: 'header'
- }),
- ...makeGroupProps({
- modelValue: true,
- selectedClass: 'v-btn--selected'
- }),
- ...makeThemeProps()
- }, 'VBottomNavigation');
- const VBottomNavigation = genericComponent()({
- name: 'VBottomNavigation',
- props: makeVBottomNavigationProps(),
- emits: {
- 'update:modelValue': value => true
- },
- setup(props, _ref) {
- let {
- slots
- } = _ref;
- const {
- themeClasses
- } = useTheme();
- const {
- borderClasses
- } = useBorder(props);
- const {
- backgroundColorClasses,
- backgroundColorStyles
- } = useBackgroundColor(toRef(props, 'bgColor'));
- const {
- densityClasses
- } = useDensity(props);
- const {
- elevationClasses
- } = useElevation(props);
- const {
- roundedClasses
- } = useRounded(props);
- const {
- ssrBootStyles
- } = useSsrBoot();
- const height = computed(() => Number(props.height) - (props.density === 'comfortable' ? 8 : 0) - (props.density === 'compact' ? 16 : 0));
- const isActive = toRef(props, 'active');
- const {
- layoutItemStyles
- } = useLayoutItem({
- id: props.name,
- order: computed(() => parseInt(props.order, 10)),
- position: computed(() => 'bottom'),
- layoutSize: computed(() => isActive.value ? height.value : 0),
- elementSize: height,
- active: isActive,
- absolute: toRef(props, 'absolute')
- });
- useGroup(props, VBtnToggleSymbol);
- provideDefaults({
- VBtn: {
- color: toRef(props, 'color'),
- density: toRef(props, 'density'),
- stacked: computed(() => props.mode !== 'horizontal'),
- variant: 'text'
- }
- }, {
- scoped: true
- });
- useRender(() => {
- return createVNode(props.tag, {
- "class": ['v-bottom-navigation', {
- 'v-bottom-navigation--active': isActive.value,
- 'v-bottom-navigation--grow': props.grow,
- 'v-bottom-navigation--shift': props.mode === 'shift'
- }, themeClasses.value, backgroundColorClasses.value, borderClasses.value, densityClasses.value, elevationClasses.value, roundedClasses.value, props.class],
- "style": [backgroundColorStyles.value, layoutItemStyles.value, {
- height: convertToUnit(height.value),
- transform: `translateY(${convertToUnit(!isActive.value ? 100 : 0, '%')})`
- }, ssrBootStyles.value, props.style]
- }, {
- default: () => [slots.default && createVNode("div", {
- "class": "v-bottom-navigation__content"
- }, [slots.default()])]
- });
- });
- return {};
- }
- });
- const makeVBreadcrumbsDividerProps = propsFactory({
- divider: [Number, String],
- ...makeComponentProps()
- }, 'VBreadcrumbsDivider');
- const VBreadcrumbsDivider = genericComponent()({
- name: 'VBreadcrumbsDivider',
- props: makeVBreadcrumbsDividerProps(),
- setup(props, _ref) {
- let {
- slots
- } = _ref;
- useRender(() => createVNode("li", {
- "class": ['v-breadcrumbs-divider', props.class],
- "style": props.style
- }, [slots?.default?.() ?? props.divider]));
- return {};
- }
- });
- const makeVBreadcrumbsItemProps = propsFactory({
- active: Boolean,
- activeClass: String,
- activeColor: String,
- color: String,
- disabled: Boolean,
- title: String,
- ...makeComponentProps(),
- ...makeRouterProps(),
- ...makeTagProps({
- tag: 'li'
- })
- }, 'VBreadcrumbsItem');
- const VBreadcrumbsItem = genericComponent()({
- name: 'VBreadcrumbsItem',
- props: makeVBreadcrumbsItemProps(),
- setup(props, _ref) {
- let {
- slots,
- attrs
- } = _ref;
- const link = useLink(props, attrs);
- const isActive = computed(() => props.active || link.isActive?.value);
- const color = computed(() => isActive.value ? props.activeColor : props.color);
- const {
- textColorClasses,
- textColorStyles
- } = useTextColor(color);
- useRender(() => {
- return createVNode(props.tag, {
- "class": ['v-breadcrumbs-item', {
- 'v-breadcrumbs-item--active': isActive.value,
- 'v-breadcrumbs-item--disabled': props.disabled,
- [`${props.activeClass}`]: isActive.value && props.activeClass
- }, textColorClasses.value, props.class],
- "style": [textColorStyles.value, props.style],
- "aria-current": isActive.value ? 'page' : undefined
- }, {
- default: () => [!link.isLink.value ? slots.default?.() ?? props.title : createVNode("a", {
- "class": "v-breadcrumbs-item--link",
- "href": link.href.value,
- "aria-current": isActive.value ? 'page' : undefined,
- "onClick": link.navigate
- }, [slots.default?.() ?? props.title])]
- });
- });
- return {};
- }
- });
- // Types
- const makeVBreadcrumbsProps = propsFactory({
- activeClass: String,
- activeColor: String,
- bgColor: String,
- color: String,
- disabled: Boolean,
- divider: {
- type: String,
- default: '/'
- },
- icon: IconValue,
- items: {
- type: Array,
- default: () => []
- },
- ...makeComponentProps(),
- ...makeDensityProps(),
- ...makeRoundedProps(),
- ...makeTagProps({
- tag: 'ul'
- })
- }, 'VBreadcrumbs');
- const VBreadcrumbs = genericComponent()({
- name: 'VBreadcrumbs',
- props: makeVBreadcrumbsProps(),
- setup(props, _ref) {
- let {
- slots
- } = _ref;
- const {
- backgroundColorClasses,
- backgroundColorStyles
- } = useBackgroundColor(toRef(props, 'bgColor'));
- const {
- densityClasses
- } = useDensity(props);
- const {
- roundedClasses
- } = useRounded(props);
- provideDefaults({
- VBreadcrumbsDivider: {
- divider: toRef(props, 'divider')
- },
- VBreadcrumbsItem: {
- activeClass: toRef(props, 'activeClass'),
- activeColor: toRef(props, 'activeColor'),
- color: toRef(props, 'color'),
- disabled: toRef(props, 'disabled')
- }
- });
- const items = computed(() => props.items.map(item => {
- return typeof item === 'string' ? {
- item: {
- title: item
- },
- raw: item
- } : {
- item,
- raw: item
- };
- }));
- useRender(() => {
- const hasPrepend = !!(slots.prepend || props.icon);
- return createVNode(props.tag, {
- "class": ['v-breadcrumbs', backgroundColorClasses.value, densityClasses.value, roundedClasses.value, props.class],
- "style": [backgroundColorStyles.value, props.style]
- }, {
- default: () => [hasPrepend && createVNode("li", {
- "key": "prepend",
- "class": "v-breadcrumbs__prepend"
- }, [!slots.prepend ? createVNode(VIcon, {
- "key": "prepend-icon",
- "start": true,
- "icon": props.icon
- }, null) : createVNode(VDefaultsProvider, {
- "key": "prepend-defaults",
- "disabled": !props.icon,
- "defaults": {
- VIcon: {
- icon: props.icon,
- start: true
- }
- }
- }, slots.prepend)]), items.value.map((_ref2, index, array) => {
- let {
- item,
- raw
- } = _ref2;
- return createVNode(Fragment, null, [createVNode(VBreadcrumbsItem, mergeProps({
- "key": item.title,
- "disabled": index >= array.length - 1
- }, item), {
- default: slots.title ? () => slots.title?.({
- item: raw,
- index
- }) : undefined
- }), index < array.length - 1 && createVNode(VBreadcrumbsDivider, null, {
- default: slots.divider ? () => slots.divider?.({
- item: raw,
- index
- }) : undefined
- })]);
- }), slots.default?.()]
- });
- });
- return {};
- }
- });
- const VCardActions = genericComponent()({
- name: 'VCardActions',
- props: makeComponentProps(),
- setup(props, _ref) {
- let {
- slots
- } = _ref;
- provideDefaults({
- VBtn: {
- variant: 'text'
- }
- });
- useRender(() => createVNode("div", {
- "class": ['v-card-actions', props.class],
- "style": props.style
- }, [slots.default?.()]));
- return {};
- }
- });
- // Utilities
- const VCardSubtitle = createSimpleFunctional('v-card-subtitle');
- // Utilities
- const VCardTitle = createSimpleFunctional('v-card-title');
- const makeCardItemProps = propsFactory({
- appendAvatar: String,
- appendIcon: IconValue,
- prependAvatar: String,
- prependIcon: IconValue,
- subtitle: String,
- title: String,
- ...makeComponentProps(),
- ...makeDensityProps()
- }, 'VCardItem');
- const VCardItem = genericComponent()({
- name: 'VCardItem',
- props: makeCardItemProps(),
- setup(props, _ref) {
- let {
- slots
- } = _ref;
- useRender(() => {
- const hasPrependMedia = !!(props.prependAvatar || props.prependIcon);
- const hasPrepend = !!(hasPrependMedia || slots.prepend);
- const hasAppendMedia = !!(props.appendAvatar || props.appendIcon);
- const hasAppend = !!(hasAppendMedia || slots.append);
- const hasTitle = !!(props.title || slots.title);
- const hasSubtitle = !!(props.subtitle || slots.subtitle);
- return createVNode("div", {
- "class": ['v-card-item', props.class],
- "style": props.style
- }, [hasPrepend && createVNode("div", {
- "key": "prepend",
- "class": "v-card-item__prepend"
- }, [!slots.prepend ? hasPrependMedia && createVNode(VAvatar, {
- "key": "prepend-avatar",
- "density": props.density,
- "icon": props.prependIcon,
- "image": props.prependAvatar
- }, null) : createVNode(VDefaultsProvider, {
- "key": "prepend-defaults",
- "disabled": !hasPrependMedia,
- "defaults": {
- VAvatar: {
- density: props.density,
- icon: props.prependIcon,
- image: props.prependAvatar
- }
- }
- }, slots.prepend)]), createVNode("div", {
- "class": "v-card-item__content"
- }, [hasTitle && createVNode(VCardTitle, {
- "key": "title"
- }, {
- default: () => [slots.title?.() ?? props.title]
- }), hasSubtitle && createVNode(VCardSubtitle, {
- "key": "subtitle"
- }, {
- default: () => [slots.subtitle?.() ?? props.subtitle]
- }), slots.default?.()]), hasAppend && createVNode("div", {
- "key": "append",
- "class": "v-card-item__append"
- }, [!slots.append ? hasAppendMedia && createVNode(VAvatar, {
- "key": "append-avatar",
- "density": props.density,
- "icon": props.appendIcon,
- "image": props.appendAvatar
- }, null) : createVNode(VDefaultsProvider, {
- "key": "append-defaults",
- "disabled": !hasAppendMedia,
- "defaults": {
- VAvatar: {
- density: props.density,
- icon: props.appendIcon,
- image: props.appendAvatar
- }
- }
- }, slots.append)])]);
- });
- return {};
- }
- });
- // Utilities
- const VCardText = createSimpleFunctional('v-card-text');
- // Types
- const makeVCardProps = propsFactory({
- appendAvatar: String,
- appendIcon: IconValue,
- disabled: Boolean,
- flat: Boolean,
- hover: Boolean,
- image: String,
- link: {
- type: Boolean,
- default: undefined
- },
- prependAvatar: String,
- prependIcon: IconValue,
- ripple: {
- type: [Boolean, Object],
- default: true
- },
- subtitle: String,
- text: String,
- title: String,
- ...makeBorderProps(),
- ...makeComponentProps(),
- ...makeDensityProps(),
- ...makeDimensionProps(),
- ...makeElevationProps(),
- ...makeLoaderProps(),
- ...makeLocationProps(),
- ...makePositionProps(),
- ...makeRoundedProps(),
- ...makeRouterProps(),
- ...makeTagProps(),
- ...makeThemeProps(),
- ...makeVariantProps({
- variant: 'elevated'
- })
- }, 'VCard');
- const VCard = genericComponent()({
- name: 'VCard',
- directives: {
- Ripple
- },
- props: makeVCardProps(),
- setup(props, _ref) {
- let {
- attrs,
- slots
- } = _ref;
- const {
- themeClasses
- } = provideTheme(props);
- const {
- borderClasses
- } = useBorder(props);
- const {
- colorClasses,
- colorStyles,
- variantClasses
- } = useVariant(props);
- const {
- densityClasses
- } = useDensity(props);
- const {
- dimensionStyles
- } = useDimension(props);
- const {
- elevationClasses
- } = useElevation(props);
- const {
- loaderClasses
- } = useLoader(props);
- const {
- locationStyles
- } = useLocation(props);
- const {
- positionClasses
- } = usePosition(props);
- const {
- roundedClasses
- } = useRounded(props);
- const link = useLink(props, attrs);
- const isLink = computed(() => props.link !== false && link.isLink.value);
- const isClickable = computed(() => !props.disabled && props.link !== false && (props.link || link.isClickable.value));
- useRender(() => {
- const Tag = isLink.value ? 'a' : props.tag;
- const hasTitle = !!(slots.title || props.title);
- const hasSubtitle = !!(slots.subtitle || props.subtitle);
- const hasHeader = hasTitle || hasSubtitle;
- const hasAppend = !!(slots.append || props.appendAvatar || props.appendIcon);
- const hasPrepend = !!(slots.prepend || props.prependAvatar || props.prependIcon);
- const hasImage = !!(slots.image || props.image);
- const hasCardItem = hasHeader || hasPrepend || hasAppend;
- const hasText = !!(slots.text || props.text);
- return withDirectives(createVNode(Tag, {
- "class": ['v-card', {
- 'v-card--disabled': props.disabled,
- 'v-card--flat': props.flat,
- 'v-card--hover': props.hover && !(props.disabled || props.flat),
- 'v-card--link': isClickable.value
- }, themeClasses.value, borderClasses.value, colorClasses.value, densityClasses.value, elevationClasses.value, loaderClasses.value, positionClasses.value, roundedClasses.value, variantClasses.value, props.class],
- "style": [colorStyles.value, dimensionStyles.value, locationStyles.value, props.style],
- "href": link.href.value,
- "onClick": isClickable.value && link.navigate,
- "tabindex": props.disabled ? -1 : undefined
- }, {
- default: () => [hasImage && createVNode("div", {
- "key": "image",
- "class": "v-card__image"
- }, [!slots.image ? createVNode(VImg, {
- "key": "image-img",
- "cover": true,
- "src": props.image
- }, null) : createVNode(VDefaultsProvider, {
- "key": "image-defaults",
- "disabled": !props.image,
- "defaults": {
- VImg: {
- cover: true,
- src: props.image
- }
- }
- }, slots.image)]), createVNode(LoaderSlot, {
- "name": "v-card",
- "active": !!props.loading,
- "color": typeof props.loading === 'boolean' ? undefined : props.loading
- }, {
- default: slots.loader
- }), hasCardItem && createVNode(VCardItem, {
- "key": "item",
- "prependAvatar": props.prependAvatar,
- "prependIcon": props.prependIcon,
- "title": props.title,
- "subtitle": props.subtitle,
- "appendAvatar": props.appendAvatar,
- "appendIcon": props.appendIcon
- }, {
- default: slots.item,
- prepend: slots.prepend,
- title: slots.title,
- subtitle: slots.subtitle,
- append: slots.append
- }), hasText && createVNode(VCardText, {
- "key": "text"
- }, {
- default: () => [slots.text?.() ?? props.text]
- }), slots.default?.(), slots.actions && createVNode(VCardActions, null, {
- default: slots.actions
- }), genOverlays(isClickable.value, 'v-card')]
- }), [[resolveDirective("ripple"), isClickable.value && props.ripple]]);
- });
- return {};
- }
- });
- // Utilities
- // Types
- const handleGesture = wrapper => {
- const {
- touchstartX,
- touchendX,
- touchstartY,
- touchendY
- } = wrapper;
- const dirRatio = 0.5;
- const minDistance = 16;
- wrapper.offsetX = touchendX - touchstartX;
- wrapper.offsetY = touchendY - touchstartY;
- if (Math.abs(wrapper.offsetY) < dirRatio * Math.abs(wrapper.offsetX)) {
- wrapper.left && touchendX < touchstartX - minDistance && wrapper.left(wrapper);
- wrapper.right && touchendX > touchstartX + minDistance && wrapper.right(wrapper);
- }
- if (Math.abs(wrapper.offsetX) < dirRatio * Math.abs(wrapper.offsetY)) {
- wrapper.up && touchendY < touchstartY - minDistance && wrapper.up(wrapper);
- wrapper.down && touchendY > touchstartY + minDistance && wrapper.down(wrapper);
- }
- };
- function touchstart(event, wrapper) {
- const touch = event.changedTouches[0];
- wrapper.touchstartX = touch.clientX;
- wrapper.touchstartY = touch.clientY;
- wrapper.start?.({
- originalEvent: event,
- ...wrapper
- });
- }
- function touchend(event, wrapper) {
- const touch = event.changedTouches[0];
- wrapper.touchendX = touch.clientX;
- wrapper.touchendY = touch.clientY;
- wrapper.end?.({
- originalEvent: event,
- ...wrapper
- });
- handleGesture(wrapper);
- }
- function touchmove(event, wrapper) {
- const touch = event.changedTouches[0];
- wrapper.touchmoveX = touch.clientX;
- wrapper.touchmoveY = touch.clientY;
- wrapper.move?.({
- originalEvent: event,
- ...wrapper
- });
- }
- function createHandlers() {
- let value = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
- const wrapper = {
- touchstartX: 0,
- touchstartY: 0,
- touchendX: 0,
- touchendY: 0,
- touchmoveX: 0,
- touchmoveY: 0,
- offsetX: 0,
- offsetY: 0,
- left: value.left,
- right: value.right,
- up: value.up,
- down: value.down,
- start: value.start,
- move: value.move,
- end: value.end
- };
- return {
- touchstart: e => touchstart(e, wrapper),
- touchend: e => touchend(e, wrapper),
- touchmove: e => touchmove(e, wrapper)
- };
- }
- function mounted$3(el, binding) {
- const value = binding.value;
- const target = value?.parent ? el.parentElement : el;
- const options = value?.options ?? {
- passive: true
- };
- const uid = binding.instance?.$.uid; // TODO: use custom uid generator
- if (!target || !uid) return;
- const handlers = createHandlers(binding.value);
- target._touchHandlers = target._touchHandlers ?? Object.create(null);
- target._touchHandlers[uid] = handlers;
- keys(handlers).forEach(eventName => {
- target.addEventListener(eventName, handlers[eventName], options);
- });
- }
- function unmounted$3(el, binding) {
- const target = binding.value?.parent ? el.parentElement : el;
- const uid = binding.instance?.$.uid;
- if (!target?._touchHandlers || !uid) return;
- const handlers = target._touchHandlers[uid];
- keys(handlers).forEach(eventName => {
- target.removeEventListener(eventName, handlers[eventName]);
- });
- delete target._touchHandlers[uid];
- }
- const Touch = {
- mounted: mounted$3,
- unmounted: unmounted$3
- };
- // Types
- const VWindowSymbol = Symbol.for('vuetify:v-window');
- const VWindowGroupSymbol = Symbol.for('vuetify:v-window-group');
- const makeVWindowProps = propsFactory({
- continuous: Boolean,
- nextIcon: {
- type: [Boolean, String, Function, Object],
- default: '$next'
- },
- prevIcon: {
- type: [Boolean, String, Function, Object],
- default: '$prev'
- },
- reverse: Boolean,
- showArrows: {
- type: [Boolean, String],
- validator: v => typeof v === 'boolean' || v === 'hover'
- },
- touch: {
- type: [Object, Boolean],
- default: undefined
- },
- direction: {
- type: String,
- default: 'horizontal'
- },
- modelValue: null,
- disabled: Boolean,
- selectedClass: {
- type: String,
- default: 'v-window-item--active'
- },
- // TODO: mandatory should probably not be exposed but do this for now
- mandatory: {
- type: [Boolean, String],
- default: 'force'
- },
- ...makeComponentProps(),
- ...makeTagProps(),
- ...makeThemeProps()
- }, 'VWindow');
- const VWindow = genericComponent()({
- name: 'VWindow',
- directives: {
- Touch
- },
- props: makeVWindowProps(),
- emits: {
- 'update:modelValue': v => true
- },
- setup(props, _ref) {
- let {
- slots
- } = _ref;
- const {
- themeClasses
- } = provideTheme(props);
- const {
- isRtl
- } = useRtl();
- const {
- t
- } = useLocale();
- const group = useGroup(props, VWindowGroupSymbol);
- const rootRef = ref();
- const isRtlReverse = computed(() => isRtl.value ? !props.reverse : props.reverse);
- const isReversed = shallowRef(false);
- const transition = computed(() => {
- const axis = props.direction === 'vertical' ? 'y' : 'x';
- const reverse = isRtlReverse.value ? !isReversed.value : isReversed.value;
- const direction = reverse ? '-reverse' : '';
- return `v-window-${axis}${direction}-transition`;
- });
- const transitionCount = shallowRef(0);
- const transitionHeight = ref(undefined);
- const activeIndex = computed(() => {
- return group.items.value.findIndex(item => group.selected.value.includes(item.id));
- });
- watch(activeIndex, (newVal, oldVal) => {
- const itemsLength = group.items.value.length;
- const lastIndex = itemsLength - 1;
- if (itemsLength <= 2) {
- isReversed.value = newVal < oldVal;
- } else if (newVal === lastIndex && oldVal === 0) {
- isReversed.value = true;
- } else if (newVal === 0 && oldVal === lastIndex) {
- isReversed.value = false;
- } else {
- isReversed.value = newVal < oldVal;
- }
- });
- provide(VWindowSymbol, {
- transition,
- isReversed,
- transitionCount,
- transitionHeight,
- rootRef
- });
- const canMoveBack = computed(() => props.continuous || activeIndex.value !== 0);
- const canMoveForward = computed(() => props.continuous || activeIndex.value !== group.items.value.length - 1);
- function prev() {
- canMoveBack.value && group.prev();
- }
- function next() {
- canMoveForward.value && group.next();
- }
- const arrows = computed(() => {
- const arrows = [];
- const prevProps = {
- icon: isRtl.value ? props.nextIcon : props.prevIcon,
- class: `v-window__${isRtlReverse.value ? 'right' : 'left'}`,
- onClick: group.prev,
- ariaLabel: t('$vuetify.carousel.prev')
- };
- arrows.push(canMoveBack.value ? slots.prev ? slots.prev({
- props: prevProps
- }) : createVNode(VBtn, prevProps, null) : createVNode("div", null, null));
- const nextProps = {
- icon: isRtl.value ? props.prevIcon : props.nextIcon,
- class: `v-window__${isRtlReverse.value ? 'left' : 'right'}`,
- onClick: group.next,
- ariaLabel: t('$vuetify.carousel.next')
- };
- arrows.push(canMoveForward.value ? slots.next ? slots.next({
- props: nextProps
- }) : createVNode(VBtn, nextProps, null) : createVNode("div", null, null));
- return arrows;
- });
- const touchOptions = computed(() => {
- if (props.touch === false) return props.touch;
- const options = {
- left: () => {
- isRtlReverse.value ? prev() : next();
- },
- right: () => {
- isRtlReverse.value ? next() : prev();
- },
- start: _ref2 => {
- let {
- originalEvent
- } = _ref2;
- originalEvent.stopPropagation();
- }
- };
- return {
- ...options,
- ...(props.touch === true ? {} : props.touch)
- };
- });
- useRender(() => withDirectives(createVNode(props.tag, {
- "ref": rootRef,
- "class": ['v-window', {
- 'v-window--show-arrows-on-hover': props.showArrows === 'hover'
- }, themeClasses.value, props.class],
- "style": props.style
- }, {
- default: () => [createVNode("div", {
- "class": "v-window__container",
- "style": {
- height: transitionHeight.value
- }
- }, [slots.default?.({
- group
- }), props.showArrows !== false && createVNode("div", {
- "class": "v-window__controls"
- }, [arrows.value])]), slots.additional?.({
- group
- })]
- }), [[resolveDirective("touch"), touchOptions.value]]));
- return {
- group
- };
- }
- });
- // Types
- const makeVCarouselProps = propsFactory({
- color: String,
- cycle: Boolean,
- delimiterIcon: {
- type: IconValue,
- default: '$delimiter'
- },
- height: {
- type: [Number, String],
- default: 500
- },
- hideDelimiters: Boolean,
- hideDelimiterBackground: Boolean,
- interval: {
- type: [Number, String],
- default: 6000,
- validator: value => Number(value) > 0
- },
- progress: [Boolean, String],
- verticalDelimiters: [Boolean, String],
- ...makeVWindowProps({
- continuous: true,
- mandatory: 'force',
- showArrows: true
- })
- }, 'VCarousel');
- const VCarousel = genericComponent()({
- name: 'VCarousel',
- props: makeVCarouselProps(),
- emits: {
- 'update:modelValue': val => true
- },
- setup(props, _ref) {
- let {
- slots
- } = _ref;
- const model = useProxiedModel(props, 'modelValue');
- const {
- t
- } = useLocale();
- const windowRef = ref();
- let slideTimeout = -1;
- watch(model, restartTimeout);
- watch(() => props.interval, restartTimeout);
- watch(() => props.cycle, val => {
- if (val) restartTimeout();else window.clearTimeout(slideTimeout);
- });
- onMounted(startTimeout);
- function startTimeout() {
- if (!props.cycle || !windowRef.value) return;
- slideTimeout = window.setTimeout(windowRef.value.group.next, +props.interval > 0 ? +props.interval : 6000);
- }
- function restartTimeout() {
- window.clearTimeout(slideTimeout);
- window.requestAnimationFrame(startTimeout);
- }
- useRender(() => {
- const [windowProps] = VWindow.filterProps(props);
- return createVNode(VWindow, mergeProps({
- "ref": windowRef
- }, windowProps, {
- "modelValue": model.value,
- "onUpdate:modelValue": $event => model.value = $event,
- "class": ['v-carousel', {
- 'v-carousel--hide-delimiter-background': props.hideDelimiterBackground,
- 'v-carousel--vertical-delimiters': props.verticalDelimiters
- }, props.class],
- "style": [{
- height: convertToUnit(props.height)
- }, props.style]
- }), {
- default: slots.default,
- additional: _ref2 => {
- let {
- group
- } = _ref2;
- return createVNode(Fragment, null, [!props.hideDelimiters && createVNode("div", {
- "class": "v-carousel__controls",
- "style": {
- left: props.verticalDelimiters === 'left' && props.verticalDelimiters ? 0 : 'auto',
- right: props.verticalDelimiters === 'right' ? 0 : 'auto'
- }
- }, [group.items.value.length > 0 && createVNode(VDefaultsProvider, {
- "defaults": {
- VBtn: {
- color: props.color,
- icon: props.delimiterIcon,
- size: 'x-small',
- variant: 'text'
- }
- },
- "scoped": true
- }, {
- default: () => [group.items.value.map((item, index) => {
- const props = {
- id: `carousel-item-${item.id}`,
- 'aria-label': t('$vuetify.carousel.ariaLabel.delimiter', index + 1, group.items.value.length),
- class: [group.isSelected(item.id) && 'v-btn--active'],
- onClick: () => group.select(item.id, true)
- };
- return slots.item ? slots.item({
- props,
- item
- }) : createVNode(VBtn, mergeProps(item, props), null);
- })]
- })]), props.progress && createVNode(VProgressLinear, {
- "class": "v-carousel__progress",
- "color": typeof props.progress === 'string' ? props.progress : undefined,
- "modelValue": (group.getItemIndex(model.value) + 1) / group.items.value.length * 100
- }, null)]);
- },
- prev: slots.prev,
- next: slots.next
- });
- });
- return {};
- }
- });
- const makeVWindowItemProps = propsFactory({
- reverseTransition: {
- type: [Boolean, String],
- default: undefined
- },
- transition: {
- type: [Boolean, String],
- default: undefined
- },
- ...makeComponentProps(),
- ...makeGroupItemProps(),
- ...makeLazyProps()
- }, 'VWindowItem');
- const VWindowItem = genericComponent()({
- name: 'VWindowItem',
- directives: {
- Touch
- },
- props: makeVWindowItemProps(),
- emits: {
- 'group:selected': val => true
- },
- setup(props, _ref) {
- let {
- slots
- } = _ref;
- const window = inject$1(VWindowSymbol);
- const groupItem = useGroupItem(props, VWindowGroupSymbol);
- const {
- isBooted
- } = useSsrBoot();
- if (!window || !groupItem) throw new Error('[Vuetify] VWindowItem must be used inside VWindow');
- const isTransitioning = shallowRef(false);
- const hasTransition = computed(() => isBooted.value && (window.isReversed.value ? props.reverseTransition !== false : props.transition !== false));
- function onAfterTransition() {
- if (!isTransitioning.value || !window) {
- return;
- }
- // Finalize transition state.
- isTransitioning.value = false;
- if (window.transitionCount.value > 0) {
- window.transitionCount.value -= 1;
- // Remove container height if we are out of transition.
- if (window.transitionCount.value === 0) {
- window.transitionHeight.value = undefined;
- }
- }
- }
- function onBeforeTransition() {
- if (isTransitioning.value || !window) {
- return;
- }
- // Initialize transition state here.
- isTransitioning.value = true;
- if (window.transitionCount.value === 0) {
- // Set initial height for height transition.
- window.transitionHeight.value = convertToUnit(window.rootRef.value?.clientHeight);
- }
- window.transitionCount.value += 1;
- }
- function onTransitionCancelled() {
- onAfterTransition(); // This should have the same path as normal transition end.
- }
- function onEnterTransition(el) {
- if (!isTransitioning.value) {
- return;
- }
- nextTick(() => {
- // Do not set height if no transition or cancelled.
- if (!hasTransition.value || !isTransitioning.value || !window) {
- return;
- }
- // Set transition target height.
- window.transitionHeight.value = convertToUnit(el.clientHeight);
- });
- }
- const transition = computed(() => {
- const name = window.isReversed.value ? props.reverseTransition : props.transition;
- return !hasTransition.value ? false : {
- name: typeof name !== 'string' ? window.transition.value : name,
- onBeforeEnter: onBeforeTransition,
- onAfterEnter: onAfterTransition,
- onEnterCancelled: onTransitionCancelled,
- onBeforeLeave: onBeforeTransition,
- onAfterLeave: onAfterTransition,
- onLeaveCancelled: onTransitionCancelled,
- onEnter: onEnterTransition
- };
- });
- const {
- hasContent
- } = useLazy(props, groupItem.isSelected);
- useRender(() => createVNode(MaybeTransition, {
- "transition": transition.value,
- "disabled": !isBooted.value
- }, {
- default: () => [withDirectives(createVNode("div", {
- "class": ['v-window-item', groupItem.selectedClass.value, props.class],
- "style": props.style
- }, [hasContent.value && slots.default?.()]), [[vShow, groupItem.isSelected.value]])]
- }));
- return {
- groupItem
- };
- }
- });
- // Types
- const makeVCarouselItemProps = propsFactory({
- ...makeVImgProps(),
- ...makeVWindowItemProps()
- }, 'VCarouselItem');
- const VCarouselItem = genericComponent()({
- name: 'VCarouselItem',
- inheritAttrs: false,
- props: makeVCarouselItemProps(),
- setup(props, _ref) {
- let {
- slots,
- attrs
- } = _ref;
- useRender(() => {
- const [imgProps] = VImg.filterProps(props);
- const [windowItemProps] = VWindowItem.filterProps(props);
- return createVNode(VWindowItem, mergeProps({
- "class": "v-carousel-item"
- }, windowItemProps), {
- default: () => [createVNode(VImg, mergeProps(attrs, imgProps), slots)]
- });
- });
- }
- });
- // Styles
- const VCode = createSimpleFunctional('v-code');
- // Types
- const makeVColorPickerCanvasProps = propsFactory({
- color: {
- type: Object
- },
- disabled: Boolean,
- dotSize: {
- type: [Number, String],
- default: 10
- },
- height: {
- type: [Number, String],
- default: 150
- },
- width: {
- type: [Number, String],
- default: 300
- },
- ...makeComponentProps()
- }, 'VColorPickerCanvas');
- const VColorPickerCanvas = defineComponent({
- name: 'VColorPickerCanvas',
- props: makeVColorPickerCanvasProps(),
- emits: {
- 'update:color': color => true,
- 'update:position': hue => true
- },
- setup(props, _ref) {
- let {
- emit
- } = _ref;
- const isInteracting = shallowRef(false);
- const isOutsideUpdate = shallowRef(false);
- const dotPosition = ref({
- x: 0,
- y: 0
- });
- const dotStyles = computed(() => {
- const {
- x,
- y
- } = dotPosition.value;
- const radius = parseInt(props.dotSize, 10) / 2;
- return {
- width: convertToUnit(props.dotSize),
- height: convertToUnit(props.dotSize),
- transform: `translate(${convertToUnit(x - radius)}, ${convertToUnit(y - radius)})`
- };
- });
- const canvasRef = ref();
- const canvasWidth = shallowRef(parseFloat(props.width));
- const canvasHeight = shallowRef(parseFloat(props.height));
- const {
- resizeRef
- } = useResizeObserver(entries => {
- if (!resizeRef.value?.offsetParent) return;
- const {
- width,
- height
- } = entries[0].contentRect;
- canvasWidth.value = width;
- canvasHeight.value = height;
- });
- function updateDotPosition(x, y, rect) {
- const {
- left,
- top,
- width,
- height
- } = rect;
- dotPosition.value = {
- x: clamp(x - left, 0, width),
- y: clamp(y - top, 0, height)
- };
- }
- function handleClick(e) {
- if (props.disabled || !canvasRef.value) return;
- updateDotPosition(e.clientX, e.clientY, canvasRef.value.getBoundingClientRect());
- }
- function handleMouseDown(e) {
- // To prevent selection while moving cursor
- e.preventDefault();
- if (props.disabled) return;
- isInteracting.value = true;
- window.addEventListener('mousemove', handleMouseMove);
- window.addEventListener('mouseup', handleMouseUp);
- window.addEventListener('touchmove', handleMouseMove);
- window.addEventListener('touchend', handleMouseUp);
- }
- function handleMouseMove(e) {
- if (props.disabled || !canvasRef.value) return;
- isInteracting.value = true;
- const coords = getEventCoordinates(e);
- updateDotPosition(coords.clientX, coords.clientY, canvasRef.value.getBoundingClientRect());
- }
- function handleMouseUp() {
- window.removeEventListener('mousemove', handleMouseMove);
- window.removeEventListener('mouseup', handleMouseUp);
- window.removeEventListener('touchmove', handleMouseMove);
- window.removeEventListener('touchend', handleMouseUp);
- }
- watch(dotPosition, () => {
- if (isOutsideUpdate.value) {
- isOutsideUpdate.value = false;
- return;
- }
- if (!canvasRef.value) return;
- const {
- x,
- y
- } = dotPosition.value;
- emit('update:color', {
- h: props.color?.h ?? 0,
- s: clamp(x, 0, canvasWidth.value) / canvasWidth.value,
- v: 1 - clamp(y, 0, canvasHeight.value) / canvasHeight.value,
- a: props.color?.a ?? 1
- });
- });
- function updateCanvas() {
- if (!canvasRef.value) return;
- const canvas = canvasRef.value;
- const ctx = canvas.getContext('2d');
- if (!ctx) return;
- const saturationGradient = ctx.createLinearGradient(0, 0, canvas.width, 0);
- saturationGradient.addColorStop(0, 'hsla(0, 0%, 100%, 1)'); // white
- saturationGradient.addColorStop(1, `hsla(${props.color?.h ?? 0}, 100%, 50%, 1)`);
- ctx.fillStyle = saturationGradient;
- ctx.fillRect(0, 0, canvas.width, canvas.height);
- const valueGradient = ctx.createLinearGradient(0, 0, 0, canvas.height);
- valueGradient.addColorStop(0, 'hsla(0, 0%, 100%, 0)'); // transparent
- valueGradient.addColorStop(1, 'hsla(0, 0%, 0%, 1)'); // black
- ctx.fillStyle = valueGradient;
- ctx.fillRect(0, 0, canvas.width, canvas.height);
- }
- watch(() => props.color?.h, updateCanvas, {
- immediate: true
- });
- watch(() => [canvasWidth.value, canvasHeight.value], (newVal, oldVal) => {
- updateCanvas();
- dotPosition.value = {
- x: dotPosition.value.x * newVal[0] / oldVal[0],
- y: dotPosition.value.y * newVal[1] / oldVal[1]
- };
- }, {
- flush: 'post'
- });
- watch(() => props.color, () => {
- if (isInteracting.value) {
- isInteracting.value = false;
- return;
- }
- isOutsideUpdate.value = true;
- dotPosition.value = props.color ? {
- x: props.color.s * canvasWidth.value,
- y: (1 - props.color.v) * canvasHeight.value
- } : {
- x: 0,
- y: 0
- };
- }, {
- deep: true,
- immediate: true
- });
- onMounted(() => updateCanvas());
- useRender(() => createVNode("div", {
- "ref": resizeRef,
- "class": ['v-color-picker-canvas', props.class],
- "style": props.style,
- "onClick": handleClick,
- "onMousedown": handleMouseDown,
- "onTouchstart": handleMouseDown
- }, [createVNode("canvas", {
- "ref": canvasRef,
- "width": canvasWidth.value,
- "height": canvasHeight.value
- }, null), props.color && createVNode("div", {
- "class": ['v-color-picker-canvas__dot', {
- 'v-color-picker-canvas__dot--disabled': props.disabled
- }],
- "style": dotStyles.value
- }, null)]));
- return {};
- }
- });
- // Utilities
- // Types
- function stripAlpha(color, stripAlpha) {
- if (stripAlpha) {
- const {
- a,
- ...rest
- } = color;
- return rest;
- }
- return color;
- }
- function extractColor(color, input) {
- if (input == null || typeof input === 'string') {
- const hex = HSVtoHex(color);
- if (color.a === 1) return hex.slice(0, 7);else return hex;
- }
- if (typeof input === 'object') {
- let converted;
- if (has(input, ['r', 'g', 'b'])) converted = HSVtoRGB(color);else if (has(input, ['h', 's', 'l'])) converted = HSVtoHSL(color);else if (has(input, ['h', 's', 'v'])) converted = color;
- return stripAlpha(converted, !has(input, ['a']) && color.a === 1);
- }
- return color;
- }
- const nullColor = {
- h: 0,
- s: 0,
- v: 1,
- a: 1
- };
- const rgba = {
- inputProps: {
- type: 'number',
- min: 0
- },
- inputs: [{
- label: 'R',
- max: 255,
- step: 1,
- getValue: c => Math.round(c.r),
- getColor: (c, v) => ({
- ...c,
- r: Number(v)
- })
- }, {
- label: 'G',
- max: 255,
- step: 1,
- getValue: c => Math.round(c.g),
- getColor: (c, v) => ({
- ...c,
- g: Number(v)
- })
- }, {
- label: 'B',
- max: 255,
- step: 1,
- getValue: c => Math.round(c.b),
- getColor: (c, v) => ({
- ...c,
- b: Number(v)
- })
- }, {
- label: 'A',
- max: 1,
- step: 0.01,
- getValue: _ref => {
- let {
- a
- } = _ref;
- return a != null ? Math.round(a * 100) / 100 : 1;
- },
- getColor: (c, v) => ({
- ...c,
- a: Number(v)
- })
- }],
- to: HSVtoRGB,
- from: RGBtoHSV
- };
- const rgb = {
- ...rgba,
- inputs: rgba.inputs?.slice(0, 3)
- };
- const hsla = {
- inputProps: {
- type: 'number',
- min: 0
- },
- inputs: [{
- label: 'H',
- max: 360,
- step: 1,
- getValue: c => Math.round(c.h),
- getColor: (c, v) => ({
- ...c,
- h: Number(v)
- })
- }, {
- label: 'S',
- max: 1,
- step: 0.01,
- getValue: c => Math.round(c.s * 100) / 100,
- getColor: (c, v) => ({
- ...c,
- s: Number(v)
- })
- }, {
- label: 'L',
- max: 1,
- step: 0.01,
- getValue: c => Math.round(c.l * 100) / 100,
- getColor: (c, v) => ({
- ...c,
- l: Number(v)
- })
- }, {
- label: 'A',
- max: 1,
- step: 0.01,
- getValue: _ref2 => {
- let {
- a
- } = _ref2;
- return a != null ? Math.round(a * 100) / 100 : 1;
- },
- getColor: (c, v) => ({
- ...c,
- a: Number(v)
- })
- }],
- to: HSVtoHSL,
- from: HSLtoHSV
- };
- const hsl = {
- ...hsla,
- inputs: hsla.inputs.slice(0, 3)
- };
- const hexa = {
- inputProps: {
- type: 'text'
- },
- inputs: [{
- label: 'HEXA',
- getValue: c => c,
- getColor: (c, v) => v
- }],
- to: HSVtoHex,
- from: HexToHSV
- };
- const hex = {
- ...hexa,
- inputs: [{
- label: 'HEX',
- getValue: c => c.slice(0, 7),
- getColor: (c, v) => v
- }]
- };
- const modes = {
- rgb,
- rgba,
- hsl,
- hsla,
- hex,
- hexa
- };
- // Types
- const VColorPickerInput = _ref => {
- let {
- label,
- ...rest
- } = _ref;
- return createVNode("div", {
- "class": "v-color-picker-edit__input"
- }, [createVNode("input", rest, null), createVNode("span", null, [label])]);
- };
- const makeVColorPickerEditProps = propsFactory({
- color: Object,
- disabled: Boolean,
- mode: {
- type: String,
- default: 'rgba',
- validator: v => Object.keys(modes).includes(v)
- },
- modes: {
- type: Array,
- default: () => Object.keys(modes),
- validator: v => Array.isArray(v) && v.every(m => Object.keys(modes).includes(m))
- },
- ...makeComponentProps()
- }, 'VColorPickerEdit');
- const VColorPickerEdit = defineComponent({
- name: 'VColorPickerEdit',
- props: makeVColorPickerEditProps(),
- emits: {
- 'update:color': color => true,
- 'update:mode': mode => true
- },
- setup(props, _ref2) {
- let {
- emit
- } = _ref2;
- const enabledModes = computed(() => {
- return props.modes.map(key => ({
- ...modes[key],
- name: key
- }));
- });
- const inputs = computed(() => {
- const mode = enabledModes.value.find(m => m.name === props.mode);
- if (!mode) return [];
- const color = props.color ? mode.to(props.color) : null;
- return mode.inputs?.map(_ref3 => {
- let {
- getValue,
- getColor,
- ...inputProps
- } = _ref3;
- return {
- ...mode.inputProps,
- ...inputProps,
- disabled: props.disabled,
- value: color && getValue(color),
- onChange: e => {
- const target = e.target;
- if (!target) return;
- emit('update:color', mode.from(getColor(color ?? nullColor, target.value)));
- }
- };
- });
- });
- useRender(() => createVNode("div", {
- "class": ['v-color-picker-edit', props.class],
- "style": props.style
- }, [inputs.value?.map(props => createVNode(VColorPickerInput, props, null)), enabledModes.value.length > 1 && createVNode(VBtn, {
- "icon": "$unfold",
- "size": "x-small",
- "variant": "plain",
- "onClick": () => {
- const mi = enabledModes.value.findIndex(m => m.name === props.mode);
- emit('update:mode', enabledModes.value[(mi + 1) % enabledModes.value.length].name);
- }
- }, null)]));
- return {};
- }
- });
- /* eslint-disable max-statements */
- // Composables
- // Types
- const VSliderSymbol = Symbol.for('vuetify:v-slider');
- function getOffset(e, el, direction) {
- const vertical = direction === 'vertical';
- const rect = el.getBoundingClientRect();
- const touch = 'touches' in e ? e.touches[0] : e;
- return vertical ? touch.clientY - (rect.top + rect.height / 2) : touch.clientX - (rect.left + rect.width / 2);
- }
- function getPosition(e, position) {
- if ('touches' in e && e.touches.length) return e.touches[0][position];else if ('changedTouches' in e && e.changedTouches.length) return e.changedTouches[0][position];else return e[position];
- }
- const makeSliderProps = propsFactory({
- disabled: {
- type: Boolean,
- default: null
- },
- error: Boolean,
- readonly: {
- type: Boolean,
- default: null
- },
- max: {
- type: [Number, String],
- default: 100
- },
- min: {
- type: [Number, String],
- default: 0
- },
- step: {
- type: [Number, String],
- default: 0
- },
- thumbColor: String,
- thumbLabel: {
- type: [Boolean, String],
- default: undefined,
- validator: v => typeof v === 'boolean' || v === 'always'
- },
- thumbSize: {
- type: [Number, String],
- default: 20
- },
- showTicks: {
- type: [Boolean, String],
- default: false,
- validator: v => typeof v === 'boolean' || v === 'always'
- },
- ticks: {
- type: [Array, Object]
- },
- tickSize: {
- type: [Number, String],
- default: 2
- },
- color: String,
- trackColor: String,
- trackFillColor: String,
- trackSize: {
- type: [Number, String],
- default: 4
- },
- direction: {
- type: String,
- default: 'horizontal',
- validator: v => ['vertical', 'horizontal'].includes(v)
- },
- reverse: Boolean,
- ...makeRoundedProps(),
- ...makeElevationProps({
- elevation: 2
- })
- }, 'Slider');
- const useSteps = props => {
- const min = computed(() => parseFloat(props.min));
- const max = computed(() => parseFloat(props.max));
- const step = computed(() => +props.step > 0 ? parseFloat(props.step) : 0);
- const decimals = computed(() => Math.max(getDecimals(step.value), getDecimals(min.value)));
- function roundValue(value) {
- value = parseFloat(value);
- if (step.value <= 0) return value;
- const clamped = clamp(value, min.value, max.value);
- const offset = min.value % step.value;
- const newValue = Math.round((clamped - offset) / step.value) * step.value + offset;
- return parseFloat(Math.min(newValue, max.value).toFixed(decimals.value));
- }
- return {
- min,
- max,
- step,
- decimals,
- roundValue
- };
- };
- const useSlider = _ref => {
- let {
- props,
- steps,
- onSliderStart,
- onSliderMove,
- onSliderEnd,
- getActiveThumb
- } = _ref;
- const {
- isRtl
- } = useRtl();
- const isReversed = toRef(props, 'reverse');
- const horizontalDirection = computed(() => {
- let hd = isRtl.value ? 'rtl' : 'ltr';
- if (props.reverse) {
- hd = hd === 'rtl' ? 'ltr' : 'rtl';
- }
- return hd;
- });
- const {
- min,
- max,
- step,
- decimals,
- roundValue
- } = steps;
- const thumbSize = computed(() => parseInt(props.thumbSize, 10));
- const tickSize = computed(() => parseInt(props.tickSize, 10));
- const trackSize = computed(() => parseInt(props.trackSize, 10));
- const numTicks = computed(() => (max.value - min.value) / step.value);
- const disabled = toRef(props, 'disabled');
- const vertical = computed(() => props.direction === 'vertical');
- const thumbColor = computed(() => props.error || props.disabled ? undefined : props.thumbColor ?? props.color);
- const trackColor = computed(() => props.error || props.disabled ? undefined : props.trackColor ?? props.color);
- const trackFillColor = computed(() => props.error || props.disabled ? undefined : props.trackFillColor ?? props.color);
- const mousePressed = shallowRef(false);
- const startOffset = shallowRef(0);
- const trackContainerRef = ref();
- const activeThumbRef = ref();
- function parseMouseMove(e) {
- const vertical = props.direction === 'vertical';
- const start = vertical ? 'top' : 'left';
- const length = vertical ? 'height' : 'width';
- const position = vertical ? 'clientY' : 'clientX';
- const {
- [start]: trackStart,
- [length]: trackLength
- } = trackContainerRef.value?.$el.getBoundingClientRect();
- const clickOffset = getPosition(e, position);
- // It is possible for left to be NaN, force to number
- let clickPos = Math.min(Math.max((clickOffset - trackStart - startOffset.value) / trackLength, 0), 1) || 0;
- if (vertical || horizontalDirection.value === 'rtl') clickPos = 1 - clickPos;
- return roundValue(min.value + clickPos * (max.value - min.value));
- }
- const handleStop = e => {
- onSliderEnd({
- value: parseMouseMove(e)
- });
- mousePressed.value = false;
- startOffset.value = 0;
- };
- const handleStart = e => {
- activeThumbRef.value = getActiveThumb(e);
- if (!activeThumbRef.value) return;
- activeThumbRef.value.focus();
- mousePressed.value = true;
- if (activeThumbRef.value.contains(e.target)) {
- startOffset.value = getOffset(e, activeThumbRef.value, props.direction);
- } else {
- startOffset.value = 0;
- onSliderMove({
- value: parseMouseMove(e)
- });
- }
- onSliderStart({
- value: parseMouseMove(e)
- });
- };
- const moveListenerOptions = {
- passive: true,
- capture: true
- };
- function onMouseMove(e) {
- onSliderMove({
- value: parseMouseMove(e)
- });
- }
- function onSliderMouseUp(e) {
- e.stopPropagation();
- e.preventDefault();
- handleStop(e);
- window.removeEventListener('mousemove', onMouseMove, moveListenerOptions);
- window.removeEventListener('mouseup', onSliderMouseUp);
- }
- function onSliderTouchend(e) {
- handleStop(e);
- window.removeEventListener('touchmove', onMouseMove, moveListenerOptions);
- e.target?.removeEventListener('touchend', onSliderTouchend);
- }
- function onSliderTouchstart(e) {
- handleStart(e);
- window.addEventListener('touchmove', onMouseMove, moveListenerOptions);
- e.target?.addEventListener('touchend', onSliderTouchend, {
- passive: false
- });
- }
- function onSliderMousedown(e) {
- e.preventDefault();
- handleStart(e);
- window.addEventListener('mousemove', onMouseMove, moveListenerOptions);
- window.addEventListener('mouseup', onSliderMouseUp, {
- passive: false
- });
- }
- const position = val => {
- const percentage = (val - min.value) / (max.value - min.value) * 100;
- return clamp(isNaN(percentage) ? 0 : percentage, 0, 100);
- };
- const showTicks = toRef(props, 'showTicks');
- const parsedTicks = computed(() => {
- if (!showTicks.value) return [];
- if (!props.ticks) {
- return numTicks.value !== Infinity ? createRange(numTicks.value + 1).map(t => {
- const value = min.value + t * step.value;
- return {
- value,
- position: position(value)
- };
- }) : [];
- }
- if (Array.isArray(props.ticks)) return props.ticks.map(t => ({
- value: t,
- position: position(t),
- label: t.toString()
- }));
- return Object.keys(props.ticks).map(key => ({
- value: parseFloat(key),
- position: position(parseFloat(key)),
- label: props.ticks[key]
- }));
- });
- const hasLabels = computed(() => parsedTicks.value.some(_ref2 => {
- let {
- label
- } = _ref2;
- return !!label;
- }));
- const data = {
- activeThumbRef,
- color: toRef(props, 'color'),
- decimals,
- disabled,
- direction: toRef(props, 'direction'),
- elevation: toRef(props, 'elevation'),
- hasLabels,
- horizontalDirection,
- isReversed,
- min,
- max,
- mousePressed,
- numTicks,
- onSliderMousedown,
- onSliderTouchstart,
- parsedTicks,
- parseMouseMove,
- position,
- readonly: toRef(props, 'readonly'),
- rounded: toRef(props, 'rounded'),
- roundValue,
- showTicks,
- startOffset,
- step,
- thumbSize,
- thumbColor,
- thumbLabel: toRef(props, 'thumbLabel'),
- ticks: toRef(props, 'ticks'),
- tickSize,
- trackColor,
- trackContainerRef,
- trackFillColor,
- trackSize,
- vertical
- };
- provide(VSliderSymbol, data);
- return data;
- };
- // Types
- const makeVSliderThumbProps = propsFactory({
- focused: Boolean,
- max: {
- type: Number,
- required: true
- },
- min: {
- type: Number,
- required: true
- },
- modelValue: {
- type: Number,
- required: true
- },
- position: {
- type: Number,
- required: true
- },
- ripple: {
- type: [Boolean, Object],
- default: true
- },
- ...makeComponentProps()
- }, 'VSliderThumb');
- const VSliderThumb = genericComponent()({
- name: 'VSliderThumb',
- directives: {
- Ripple
- },
- props: makeVSliderThumbProps(),
- emits: {
- 'update:modelValue': v => true
- },
- setup(props, _ref) {
- let {
- slots,
- emit
- } = _ref;
- const slider = inject$1(VSliderSymbol);
- const {
- rtlClasses
- } = useRtl();
- if (!slider) throw new Error('[Vuetify] v-slider-thumb must be used inside v-slider or v-range-slider');
- const {
- thumbColor,
- step,
- vertical,
- disabled,
- thumbSize,
- thumbLabel,
- direction,
- readonly,
- elevation,
- isReversed,
- horizontalDirection,
- mousePressed,
- decimals
- } = slider;
- const {
- textColorClasses,
- textColorStyles
- } = useTextColor(thumbColor);
- const {
- pageup,
- pagedown,
- end,
- home,
- left,
- right,
- down,
- up
- } = keyValues;
- const relevantKeys = [pageup, pagedown, end, home, left, right, down, up];
- const multipliers = computed(() => {
- if (step.value) return [1, 2, 3];else return [1, 5, 10];
- });
- function parseKeydown(e, value) {
- if (!relevantKeys.includes(e.key)) return;
- e.preventDefault();
- const _step = step.value || 0.1;
- const steps = (props.max - props.min) / _step;
- if ([left, right, down, up].includes(e.key)) {
- const increase = horizontalDirection.value === 'rtl' ? [left, up] : [right, up];
- const direction = increase.includes(e.key) ? 1 : -1;
- const multiplier = e.shiftKey ? 2 : e.ctrlKey ? 1 : 0;
- value = value + direction * _step * multipliers.value[multiplier];
- } else if (e.key === home) {
- value = props.min;
- } else if (e.key === end) {
- value = props.max;
- } else {
- const direction = e.key === pagedown ? 1 : -1;
- value = value - direction * _step * (steps > 100 ? steps / 10 : 10);
- }
- return Math.max(props.min, Math.min(props.max, value));
- }
- function onKeydown(e) {
- const newValue = parseKeydown(e, props.modelValue);
- newValue != null && emit('update:modelValue', newValue);
- }
- useRender(() => {
- const positionPercentage = convertToUnit(vertical.value || isReversed.value ? 100 - props.position : props.position, '%');
- const {
- elevationClasses
- } = useElevation(computed(() => !disabled.value ? elevation.value : undefined));
- return createVNode("div", {
- "class": ['v-slider-thumb', {
- 'v-slider-thumb--focused': props.focused,
- 'v-slider-thumb--pressed': props.focused && mousePressed.value
- }, props.class, rtlClasses.value],
- "style": [{
- '--v-slider-thumb-position': positionPercentage,
- '--v-slider-thumb-size': convertToUnit(thumbSize.value)
- }, props.style],
- "role": "slider",
- "tabindex": disabled.value ? -1 : 0,
- "aria-valuemin": props.min,
- "aria-valuemax": props.max,
- "aria-valuenow": props.modelValue,
- "aria-readonly": !!readonly.value,
- "aria-orientation": direction.value,
- "onKeydown": !readonly.value ? onKeydown : undefined
- }, [createVNode("div", {
- "class": ['v-slider-thumb__surface', textColorClasses.value, elevationClasses.value],
- "style": {
- ...textColorStyles.value
- }
- }, null), withDirectives(createVNode("div", {
- "class": ['v-slider-thumb__ripple', textColorClasses.value],
- "style": textColorStyles.value
- }, null), [[resolveDirective("ripple"), props.ripple, null, {
- circle: true,
- center: true
- }]]), createVNode(VScaleTransition, {
- "origin": "bottom center"
- }, {
- default: () => [withDirectives(createVNode("div", {
- "class": "v-slider-thumb__label-container"
- }, [createVNode("div", {
- "class": ['v-slider-thumb__label']
- }, [createVNode("div", null, [slots['thumb-label']?.({
- modelValue: props.modelValue
- }) ?? props.modelValue.toFixed(step.value ? decimals.value : 1)])])]), [[vShow, thumbLabel.value && props.focused || thumbLabel.value === 'always']])]
- })]);
- });
- return {};
- }
- });
- // Types
- const makeVSliderTrackProps = propsFactory({
- start: {
- type: Number,
- required: true
- },
- stop: {
- type: Number,
- required: true
- },
- ...makeComponentProps()
- }, 'VSliderTrack');
- const VSliderTrack = genericComponent()({
- name: 'VSliderTrack',
- props: makeVSliderTrackProps(),
- emits: {},
- setup(props, _ref) {
- let {
- slots
- } = _ref;
- const slider = inject$1(VSliderSymbol);
- if (!slider) throw new Error('[Vuetify] v-slider-track must be inside v-slider or v-range-slider');
- const {
- color,
- horizontalDirection,
- parsedTicks,
- rounded,
- showTicks,
- tickSize,
- trackColor,
- trackFillColor,
- trackSize,
- vertical,
- min,
- max
- } = slider;
- const {
- roundedClasses
- } = useRounded(rounded);
- const {
- backgroundColorClasses: trackFillColorClasses,
- backgroundColorStyles: trackFillColorStyles
- } = useBackgroundColor(trackFillColor);
- const {
- backgroundColorClasses: trackColorClasses,
- backgroundColorStyles: trackColorStyles
- } = useBackgroundColor(trackColor);
- const startDir = computed(() => `inset-${vertical.value ? 'block-end' : 'inline-start'}`);
- const endDir = computed(() => vertical.value ? 'height' : 'width');
- const backgroundStyles = computed(() => {
- return {
- [startDir.value]: '0%',
- [endDir.value]: '100%'
- };
- });
- const trackFillWidth = computed(() => props.stop - props.start);
- const trackFillStyles = computed(() => {
- return {
- [startDir.value]: convertToUnit(props.start, '%'),
- [endDir.value]: convertToUnit(trackFillWidth.value, '%')
- };
- });
- const computedTicks = computed(() => {
- if (!showTicks.value) return [];
- const ticks = vertical.value ? parsedTicks.value.slice().reverse() : parsedTicks.value;
- return ticks.map((tick, index) => {
- const directionProperty = vertical.value ? 'bottom' : 'margin-inline-start';
- const directionValue = tick.value !== min.value && tick.value !== max.value ? convertToUnit(tick.position, '%') : undefined;
- return createVNode("div", {
- "key": tick.value,
- "class": ['v-slider-track__tick', {
- 'v-slider-track__tick--filled': tick.position >= props.start && tick.position <= props.stop,
- 'v-slider-track__tick--first': tick.value === min.value,
- 'v-slider-track__tick--last': tick.value === max.value
- }],
- "style": {
- [directionProperty]: directionValue
- }
- }, [(tick.label || slots['tick-label']) && createVNode("div", {
- "class": "v-slider-track__tick-label"
- }, [slots['tick-label']?.({
- tick,
- index
- }) ?? tick.label])]);
- });
- });
- useRender(() => {
- return createVNode("div", {
- "class": ['v-slider-track', roundedClasses.value, props.class],
- "style": [{
- '--v-slider-track-size': convertToUnit(trackSize.value),
- '--v-slider-tick-size': convertToUnit(tickSize.value),
- direction: !vertical.value ? horizontalDirection.value : undefined
- }, props.style]
- }, [createVNode("div", {
- "class": ['v-slider-track__background', trackColorClasses.value, {
- 'v-slider-track__background--opacity': !!color.value || !trackFillColor.value
- }],
- "style": {
- ...backgroundStyles.value,
- ...trackColorStyles.value
- }
- }, null), createVNode("div", {
- "class": ['v-slider-track__fill', trackFillColorClasses.value],
- "style": {
- ...trackFillStyles.value,
- ...trackFillColorStyles.value
- }
- }, null), showTicks.value && createVNode("div", {
- "class": ['v-slider-track__ticks', {
- 'v-slider-track__ticks--always-show': showTicks.value === 'always'
- }]
- }, [computedTicks.value])]);
- });
- return {};
- }
- });
- // Types
- const makeVSliderProps = propsFactory({
- ...makeFocusProps(),
- ...makeSliderProps(),
- ...makeVInputProps(),
- modelValue: {
- type: [Number, String],
- default: 0
- }
- }, 'VSlider');
- const VSlider = genericComponent()({
- name: 'VSlider',
- props: makeVSliderProps(),
- emits: {
- 'update:focused': value => true,
- 'update:modelValue': v => true,
- start: value => true,
- end: value => true
- },
- setup(props, _ref) {
- let {
- slots,
- emit
- } = _ref;
- const thumbContainerRef = ref();
- const {
- rtlClasses
- } = useRtl();
- const steps = useSteps(props);
- const model = useProxiedModel(props, 'modelValue', undefined, value => {
- return steps.roundValue(value == null ? steps.min.value : value);
- });
- const {
- min,
- max,
- mousePressed,
- roundValue,
- onSliderMousedown,
- onSliderTouchstart,
- trackContainerRef,
- position,
- hasLabels,
- readonly
- } = useSlider({
- props,
- steps,
- onSliderStart: () => {
- emit('start', model.value);
- },
- onSliderEnd: _ref2 => {
- let {
- value
- } = _ref2;
- const roundedValue = roundValue(value);
- model.value = roundedValue;
- emit('end', roundedValue);
- },
- onSliderMove: _ref3 => {
- let {
- value
- } = _ref3;
- return model.value = roundValue(value);
- },
- getActiveThumb: () => thumbContainerRef.value?.$el
- });
- const {
- isFocused,
- focus,
- blur
- } = useFocus(props);
- const trackStop = computed(() => position(model.value));
- useRender(() => {
- const [inputProps, _] = VInput.filterProps(props);
- const hasPrepend = !!(props.label || slots.label || slots.prepend);
- return createVNode(VInput, mergeProps({
- "class": ['v-slider', {
- 'v-slider--has-labels': !!slots['tick-label'] || hasLabels.value,
- 'v-slider--focused': isFocused.value,
- 'v-slider--pressed': mousePressed.value,
- 'v-slider--disabled': props.disabled
- }, rtlClasses.value, props.class],
- "style": props.style
- }, inputProps, {
- "focused": isFocused.value
- }), {
- ...slots,
- prepend: hasPrepend ? slotProps => createVNode(Fragment, null, [slots.label?.(slotProps) ?? props.label ? createVNode(VLabel, {
- "id": slotProps.id.value,
- "class": "v-slider__label",
- "text": props.label
- }, null) : undefined, slots.prepend?.(slotProps)]) : undefined,
- default: _ref4 => {
- let {
- id,
- messagesId
- } = _ref4;
- return createVNode("div", {
- "class": "v-slider__container",
- "onMousedown": !readonly.value ? onSliderMousedown : undefined,
- "onTouchstartPassive": !readonly.value ? onSliderTouchstart : undefined
- }, [createVNode("input", {
- "id": id.value,
- "name": props.name || id.value,
- "disabled": !!props.disabled,
- "readonly": !!props.readonly,
- "tabindex": "-1",
- "value": model.value
- }, null), createVNode(VSliderTrack, {
- "ref": trackContainerRef,
- "start": 0,
- "stop": trackStop.value
- }, {
- 'tick-label': slots['tick-label']
- }), createVNode(VSliderThumb, {
- "ref": thumbContainerRef,
- "aria-describedby": messagesId.value,
- "focused": isFocused.value,
- "min": min.value,
- "max": max.value,
- "modelValue": model.value,
- "onUpdate:modelValue": v => model.value = v,
- "position": trackStop.value,
- "elevation": props.elevation,
- "onFocus": focus,
- "onBlur": blur
- }, {
- 'thumb-label': slots['thumb-label']
- })]);
- }
- });
- });
- return {};
- }
- });
- // Types
- const makeVColorPickerPreviewProps = propsFactory({
- color: {
- type: Object
- },
- disabled: Boolean,
- hideAlpha: Boolean,
- ...makeComponentProps()
- }, 'VColorPickerPreview');
- const VColorPickerPreview = defineComponent({
- name: 'VColorPickerPreview',
- props: makeVColorPickerPreviewProps(),
- emits: {
- 'update:color': color => true
- },
- setup(props, _ref) {
- let {
- emit
- } = _ref;
- useRender(() => createVNode("div", {
- "class": ['v-color-picker-preview', {
- 'v-color-picker-preview--hide-alpha': props.hideAlpha
- }, props.class],
- "style": props.style
- }, [createVNode("div", {
- "class": "v-color-picker-preview__dot"
- }, [createVNode("div", {
- "style": {
- background: HSVtoCSS(props.color ?? nullColor)
- }
- }, null)]), createVNode("div", {
- "class": "v-color-picker-preview__sliders"
- }, [createVNode(VSlider, {
- "class": "v-color-picker-preview__track v-color-picker-preview__hue",
- "modelValue": props.color?.h,
- "onUpdate:modelValue": h => emit('update:color', {
- ...(props.color ?? nullColor),
- h
- }),
- "step": 0,
- "min": 0,
- "max": 360,
- "disabled": props.disabled,
- "thumbSize": 14,
- "trackSize": 8,
- "trackFillColor": "white",
- "hideDetails": true
- }, null), !props.hideAlpha && createVNode(VSlider, {
- "class": "v-color-picker-preview__track v-color-picker-preview__alpha",
- "modelValue": props.color?.a ?? 1,
- "onUpdate:modelValue": a => emit('update:color', {
- ...(props.color ?? nullColor),
- a
- }),
- "step": 1 / 256,
- "min": 0,
- "max": 1,
- "disabled": props.disabled,
- "thumbSize": 14,
- "trackSize": 8,
- "trackFillColor": "white",
- "hideDetails": true
- }, null)])]));
- return {};
- }
- });
- const red = Object.freeze({
- base: '#f44336',
- lighten5: '#ffebee',
- lighten4: '#ffcdd2',
- lighten3: '#ef9a9a',
- lighten2: '#e57373',
- lighten1: '#ef5350',
- darken1: '#e53935',
- darken2: '#d32f2f',
- darken3: '#c62828',
- darken4: '#b71c1c',
- accent1: '#ff8a80',
- accent2: '#ff5252',
- accent3: '#ff1744',
- accent4: '#d50000'
- });
- const pink = Object.freeze({
- base: '#e91e63',
- lighten5: '#fce4ec',
- lighten4: '#f8bbd0',
- lighten3: '#f48fb1',
- lighten2: '#f06292',
- lighten1: '#ec407a',
- darken1: '#d81b60',
- darken2: '#c2185b',
- darken3: '#ad1457',
- darken4: '#880e4f',
- accent1: '#ff80ab',
- accent2: '#ff4081',
- accent3: '#f50057',
- accent4: '#c51162'
- });
- const purple = Object.freeze({
- base: '#9c27b0',
- lighten5: '#f3e5f5',
- lighten4: '#e1bee7',
- lighten3: '#ce93d8',
- lighten2: '#ba68c8',
- lighten1: '#ab47bc',
- darken1: '#8e24aa',
- darken2: '#7b1fa2',
- darken3: '#6a1b9a',
- darken4: '#4a148c',
- accent1: '#ea80fc',
- accent2: '#e040fb',
- accent3: '#d500f9',
- accent4: '#aa00ff'
- });
- const deepPurple = Object.freeze({
- base: '#673ab7',
- lighten5: '#ede7f6',
- lighten4: '#d1c4e9',
- lighten3: '#b39ddb',
- lighten2: '#9575cd',
- lighten1: '#7e57c2',
- darken1: '#5e35b1',
- darken2: '#512da8',
- darken3: '#4527a0',
- darken4: '#311b92',
- accent1: '#b388ff',
- accent2: '#7c4dff',
- accent3: '#651fff',
- accent4: '#6200ea'
- });
- const indigo = Object.freeze({
- base: '#3f51b5',
- lighten5: '#e8eaf6',
- lighten4: '#c5cae9',
- lighten3: '#9fa8da',
- lighten2: '#7986cb',
- lighten1: '#5c6bc0',
- darken1: '#3949ab',
- darken2: '#303f9f',
- darken3: '#283593',
- darken4: '#1a237e',
- accent1: '#8c9eff',
- accent2: '#536dfe',
- accent3: '#3d5afe',
- accent4: '#304ffe'
- });
- const blue = Object.freeze({
- base: '#2196f3',
- lighten5: '#e3f2fd',
- lighten4: '#bbdefb',
- lighten3: '#90caf9',
- lighten2: '#64b5f6',
- lighten1: '#42a5f5',
- darken1: '#1e88e5',
- darken2: '#1976d2',
- darken3: '#1565c0',
- darken4: '#0d47a1',
- accent1: '#82b1ff',
- accent2: '#448aff',
- accent3: '#2979ff',
- accent4: '#2962ff'
- });
- const lightBlue = Object.freeze({
- base: '#03a9f4',
- lighten5: '#e1f5fe',
- lighten4: '#b3e5fc',
- lighten3: '#81d4fa',
- lighten2: '#4fc3f7',
- lighten1: '#29b6f6',
- darken1: '#039be5',
- darken2: '#0288d1',
- darken3: '#0277bd',
- darken4: '#01579b',
- accent1: '#80d8ff',
- accent2: '#40c4ff',
- accent3: '#00b0ff',
- accent4: '#0091ea'
- });
- const cyan = Object.freeze({
- base: '#00bcd4',
- lighten5: '#e0f7fa',
- lighten4: '#b2ebf2',
- lighten3: '#80deea',
- lighten2: '#4dd0e1',
- lighten1: '#26c6da',
- darken1: '#00acc1',
- darken2: '#0097a7',
- darken3: '#00838f',
- darken4: '#006064',
- accent1: '#84ffff',
- accent2: '#18ffff',
- accent3: '#00e5ff',
- accent4: '#00b8d4'
- });
- const teal = Object.freeze({
- base: '#009688',
- lighten5: '#e0f2f1',
- lighten4: '#b2dfdb',
- lighten3: '#80cbc4',
- lighten2: '#4db6ac',
- lighten1: '#26a69a',
- darken1: '#00897b',
- darken2: '#00796b',
- darken3: '#00695c',
- darken4: '#004d40',
- accent1: '#a7ffeb',
- accent2: '#64ffda',
- accent3: '#1de9b6',
- accent4: '#00bfa5'
- });
- const green = Object.freeze({
- base: '#4caf50',
- lighten5: '#e8f5e9',
- lighten4: '#c8e6c9',
- lighten3: '#a5d6a7',
- lighten2: '#81c784',
- lighten1: '#66bb6a',
- darken1: '#43a047',
- darken2: '#388e3c',
- darken3: '#2e7d32',
- darken4: '#1b5e20',
- accent1: '#b9f6ca',
- accent2: '#69f0ae',
- accent3: '#00e676',
- accent4: '#00c853'
- });
- const lightGreen = Object.freeze({
- base: '#8bc34a',
- lighten5: '#f1f8e9',
- lighten4: '#dcedc8',
- lighten3: '#c5e1a5',
- lighten2: '#aed581',
- lighten1: '#9ccc65',
- darken1: '#7cb342',
- darken2: '#689f38',
- darken3: '#558b2f',
- darken4: '#33691e',
- accent1: '#ccff90',
- accent2: '#b2ff59',
- accent3: '#76ff03',
- accent4: '#64dd17'
- });
- const lime = Object.freeze({
- base: '#cddc39',
- lighten5: '#f9fbe7',
- lighten4: '#f0f4c3',
- lighten3: '#e6ee9c',
- lighten2: '#dce775',
- lighten1: '#d4e157',
- darken1: '#c0ca33',
- darken2: '#afb42b',
- darken3: '#9e9d24',
- darken4: '#827717',
- accent1: '#f4ff81',
- accent2: '#eeff41',
- accent3: '#c6ff00',
- accent4: '#aeea00'
- });
- const yellow = Object.freeze({
- base: '#ffeb3b',
- lighten5: '#fffde7',
- lighten4: '#fff9c4',
- lighten3: '#fff59d',
- lighten2: '#fff176',
- lighten1: '#ffee58',
- darken1: '#fdd835',
- darken2: '#fbc02d',
- darken3: '#f9a825',
- darken4: '#f57f17',
- accent1: '#ffff8d',
- accent2: '#ffff00',
- accent3: '#ffea00',
- accent4: '#ffd600'
- });
- const amber = Object.freeze({
- base: '#ffc107',
- lighten5: '#fff8e1',
- lighten4: '#ffecb3',
- lighten3: '#ffe082',
- lighten2: '#ffd54f',
- lighten1: '#ffca28',
- darken1: '#ffb300',
- darken2: '#ffa000',
- darken3: '#ff8f00',
- darken4: '#ff6f00',
- accent1: '#ffe57f',
- accent2: '#ffd740',
- accent3: '#ffc400',
- accent4: '#ffab00'
- });
- const orange = Object.freeze({
- base: '#ff9800',
- lighten5: '#fff3e0',
- lighten4: '#ffe0b2',
- lighten3: '#ffcc80',
- lighten2: '#ffb74d',
- lighten1: '#ffa726',
- darken1: '#fb8c00',
- darken2: '#f57c00',
- darken3: '#ef6c00',
- darken4: '#e65100',
- accent1: '#ffd180',
- accent2: '#ffab40',
- accent3: '#ff9100',
- accent4: '#ff6d00'
- });
- const deepOrange = Object.freeze({
- base: '#ff5722',
- lighten5: '#fbe9e7',
- lighten4: '#ffccbc',
- lighten3: '#ffab91',
- lighten2: '#ff8a65',
- lighten1: '#ff7043',
- darken1: '#f4511e',
- darken2: '#e64a19',
- darken3: '#d84315',
- darken4: '#bf360c',
- accent1: '#ff9e80',
- accent2: '#ff6e40',
- accent3: '#ff3d00',
- accent4: '#dd2c00'
- });
- const brown = Object.freeze({
- base: '#795548',
- lighten5: '#efebe9',
- lighten4: '#d7ccc8',
- lighten3: '#bcaaa4',
- lighten2: '#a1887f',
- lighten1: '#8d6e63',
- darken1: '#6d4c41',
- darken2: '#5d4037',
- darken3: '#4e342e',
- darken4: '#3e2723'
- });
- const blueGrey = Object.freeze({
- base: '#607d8b',
- lighten5: '#eceff1',
- lighten4: '#cfd8dc',
- lighten3: '#b0bec5',
- lighten2: '#90a4ae',
- lighten1: '#78909c',
- darken1: '#546e7a',
- darken2: '#455a64',
- darken3: '#37474f',
- darken4: '#263238'
- });
- const grey = Object.freeze({
- base: '#9e9e9e',
- lighten5: '#fafafa',
- lighten4: '#f5f5f5',
- lighten3: '#eeeeee',
- lighten2: '#e0e0e0',
- lighten1: '#bdbdbd',
- darken1: '#757575',
- darken2: '#616161',
- darken3: '#424242',
- darken4: '#212121'
- });
- const shades = Object.freeze({
- black: '#000000',
- white: '#ffffff',
- transparent: '#ffffff00'
- });
- var colors = Object.freeze({
- red,
- pink,
- purple,
- deepPurple,
- indigo,
- blue,
- lightBlue,
- cyan,
- teal,
- green,
- lightGreen,
- lime,
- yellow,
- amber,
- orange,
- deepOrange,
- brown,
- blueGrey,
- grey,
- shades
- });
- // Types
- const makeVColorPickerSwatchesProps = propsFactory({
- swatches: {
- type: Array,
- default: () => parseDefaultColors(colors)
- },
- disabled: Boolean,
- color: Object,
- maxHeight: [Number, String],
- ...makeComponentProps()
- }, 'VColorPickerSwatches');
- function parseDefaultColors(colors) {
- return Object.keys(colors).map(key => {
- const color = colors[key];
- return color.base ? [color.base, color.darken4, color.darken3, color.darken2, color.darken1, color.lighten1, color.lighten2, color.lighten3, color.lighten4, color.lighten5] : [color.black, color.white, color.transparent];
- });
- }
- const VColorPickerSwatches = defineComponent({
- name: 'VColorPickerSwatches',
- props: makeVColorPickerSwatchesProps(),
- emits: {
- 'update:color': color => true
- },
- setup(props, _ref) {
- let {
- emit
- } = _ref;
- useRender(() => createVNode("div", {
- "class": ['v-color-picker-swatches', props.class],
- "style": [{
- maxHeight: convertToUnit(props.maxHeight)
- }, props.style]
- }, [createVNode("div", null, [props.swatches.map(swatch => createVNode("div", {
- "class": "v-color-picker-swatches__swatch"
- }, [swatch.map(color => {
- const rgba = parseColor(color);
- const hsva = RGBtoHSV(rgba);
- const background = RGBtoCSS(rgba);
- return createVNode("div", {
- "class": "v-color-picker-swatches__color",
- "onClick": () => hsva && emit('update:color', hsva)
- }, [createVNode("div", {
- "style": {
- background
- }
- }, [props.color && deepEqual(props.color, hsva) ? createVNode(VIcon, {
- "size": "x-small",
- "icon": "$success",
- "color": getContrast(color, '#FFFFFF') > 2 ? 'white' : 'black'
- }, null) : undefined])]);
- })]))])]));
- return {};
- }
- });
- const makeVSheetProps = propsFactory({
- color: String,
- ...makeBorderProps(),
- ...makeComponentProps(),
- ...makeDimensionProps(),
- ...makeElevationProps(),
- ...makeLocationProps(),
- ...makePositionProps(),
- ...makeRoundedProps(),
- ...makeTagProps(),
- ...makeThemeProps()
- }, 'VSheet');
- const VSheet = genericComponent()({
- name: 'VSheet',
- props: makeVSheetProps(),
- setup(props, _ref) {
- let {
- slots
- } = _ref;
- const {
- themeClasses
- } = provideTheme(props);
- const {
- backgroundColorClasses,
- backgroundColorStyles
- } = useBackgroundColor(toRef(props, 'color'));
- const {
- borderClasses
- } = useBorder(props);
- const {
- dimensionStyles
- } = useDimension(props);
- const {
- elevationClasses
- } = useElevation(props);
- const {
- locationStyles
- } = useLocation(props);
- const {
- positionClasses
- } = usePosition(props);
- const {
- roundedClasses
- } = useRounded(props);
- useRender(() => createVNode(props.tag, {
- "class": ['v-sheet', themeClasses.value, backgroundColorClasses.value, borderClasses.value, elevationClasses.value, positionClasses.value, roundedClasses.value, props.class],
- "style": [backgroundColorStyles.value, dimensionStyles.value, locationStyles.value, props.style]
- }, slots));
- return {};
- }
- });
- // Types
- const makeVColorPickerProps = propsFactory({
- canvasHeight: {
- type: [String, Number],
- default: 150
- },
- disabled: Boolean,
- dotSize: {
- type: [Number, String],
- default: 10
- },
- hideCanvas: Boolean,
- hideSliders: Boolean,
- hideInputs: Boolean,
- mode: {
- type: String,
- default: 'rgba',
- validator: v => Object.keys(modes).includes(v)
- },
- modes: {
- type: Array,
- default: () => Object.keys(modes),
- validator: v => Array.isArray(v) && v.every(m => Object.keys(modes).includes(m))
- },
- showSwatches: Boolean,
- swatches: Array,
- swatchesMaxHeight: {
- type: [Number, String],
- default: 150
- },
- modelValue: {
- type: [Object, String]
- },
- ...omit(makeVSheetProps({
- width: 300
- }), ['height', 'location', 'minHeight', 'maxHeight', 'minWidth', 'maxWidth'])
- }, 'VColorPicker');
- const VColorPicker = defineComponent({
- name: 'VColorPicker',
- props: makeVColorPickerProps(),
- emits: {
- 'update:modelValue': color => true,
- 'update:mode': mode => true
- },
- setup(props) {
- const mode = useProxiedModel(props, 'mode');
- const lastPickedColor = ref(null);
- const currentColor = useProxiedModel(props, 'modelValue', undefined, v => {
- if (v == null || v === '') return null;
- let c;
- try {
- c = RGBtoHSV(parseColor(v));
- } catch (err) {
- consoleWarn(err);
- return null;
- }
- if (lastPickedColor.value) {
- c = {
- ...c,
- h: lastPickedColor.value.h
- };
- lastPickedColor.value = null;
- }
- return c;
- }, v => {
- if (!v) return null;
- return extractColor(v, props.modelValue);
- });
- const {
- rtlClasses
- } = useRtl();
- const updateColor = hsva => {
- currentColor.value = hsva;
- lastPickedColor.value = hsva;
- };
- onMounted(() => {
- if (!props.modes.includes(mode.value)) mode.value = props.modes[0];
- });
- provideDefaults({
- VSlider: {
- color: undefined,
- trackColor: undefined,
- trackFillColor: undefined
- }
- });
- useRender(() => {
- const [sheetProps] = VSheet.filterProps(props);
- return createVNode(VSheet, mergeProps({
- "rounded": props.rounded,
- "elevation": props.elevation,
- "theme": props.theme,
- "class": ['v-color-picker', rtlClasses.value, props.class],
- "style": [{
- '--v-color-picker-color-hsv': HSVtoCSS({
- ...(currentColor.value ?? nullColor),
- a: 1
- })
- }, props.style]
- }, sheetProps, {
- "maxWidth": props.width
- }), {
- default: () => [!props.hideCanvas && createVNode(VColorPickerCanvas, {
- "key": "canvas",
- "color": currentColor.value,
- "onUpdate:color": updateColor,
- "disabled": props.disabled,
- "dotSize": props.dotSize,
- "width": props.width,
- "height": props.canvasHeight
- }, null), (!props.hideSliders || !props.hideInputs) && createVNode("div", {
- "key": "controls",
- "class": "v-color-picker__controls"
- }, [!props.hideSliders && createVNode(VColorPickerPreview, {
- "key": "preview",
- "color": currentColor.value,
- "onUpdate:color": updateColor,
- "hideAlpha": !mode.value.endsWith('a'),
- "disabled": props.disabled
- }, null), !props.hideInputs && createVNode(VColorPickerEdit, {
- "key": "edit",
- "modes": props.modes,
- "mode": mode.value,
- "onUpdate:mode": m => mode.value = m,
- "color": currentColor.value,
- "onUpdate:color": updateColor,
- "disabled": props.disabled
- }, null)]), props.showSwatches && createVNode(VColorPickerSwatches, {
- "key": "swatches",
- "color": currentColor.value,
- "onUpdate:color": updateColor,
- "maxHeight": props.swatchesMaxHeight,
- "swatches": props.swatches,
- "disabled": props.disabled
- }, null)]
- });
- });
- return {};
- }
- });
- // Types
- function highlightResult(text, matches, length) {
- if (matches == null) return text;
- if (Array.isArray(matches)) throw new Error('Multiple matches is not implemented');
- return typeof matches === 'number' && ~matches ? createVNode(Fragment, null, [createVNode("span", {
- "class": "v-combobox__unmask"
- }, [text.substr(0, matches)]), createVNode("span", {
- "class": "v-combobox__mask"
- }, [text.substr(matches, length)]), createVNode("span", {
- "class": "v-combobox__unmask"
- }, [text.substr(matches + length)])]) : text;
- }
- const makeVComboboxProps = propsFactory({
- autoSelectFirst: {
- type: [Boolean, String]
- },
- delimiters: Array,
- ...makeFilterProps({
- filterKeys: ['title']
- }),
- ...makeSelectProps({
- hideNoData: true,
- returnObject: true
- }),
- ...omit(makeVTextFieldProps({
- modelValue: null
- }), ['validationValue', 'dirty', 'appendInnerIcon']),
- ...makeTransitionProps({
- transition: false
- })
- }, 'VCombobox');
- const VCombobox = genericComponent()({
- name: 'VCombobox',
- props: makeVComboboxProps(),
- emits: {
- 'update:focused': focused => true,
- 'update:modelValue': val => true,
- 'update:search': val => true,
- 'update:menu': val => true
- },
- setup(props, _ref) {
- let {
- emit,
- slots
- } = _ref;
- const {
- t
- } = useLocale();
- const vTextFieldRef = ref();
- const isFocused = shallowRef(false);
- const isPristine = shallowRef(true);
- const listHasFocus = shallowRef(false);
- const vMenuRef = ref();
- const _menu = useProxiedModel(props, 'menu');
- const menu = computed({
- get: () => _menu.value,
- set: v => {
- if (_menu.value && !v && vMenuRef.value?.ΨopenChildren) return;
- _menu.value = v;
- }
- });
- const selectionIndex = shallowRef(-1);
- let cleared = false;
- const color = computed(() => vTextFieldRef.value?.color);
- const {
- items,
- transformIn,
- transformOut
- } = useItems(props);
- const {
- textColorClasses,
- textColorStyles
- } = useTextColor(color);
- const model = useProxiedModel(props, 'modelValue', [], v => transformIn(wrapInArray(v)), v => {
- const transformed = transformOut(v);
- return props.multiple ? transformed : transformed[0] ?? null;
- });
- const form = useForm();
- const _search = shallowRef(!props.multiple ? model.value[0]?.title ?? '' : '');
- const search = computed({
- get: () => {
- return _search.value;
- },
- set: val => {
- _search.value = val;
- if (!props.multiple) {
- model.value = [transformItem$3(props, val)];
- }
- if (val && props.multiple && props.delimiters?.length) {
- const values = val.split(new RegExp(`(?:${props.delimiters.join('|')})+`));
- if (values.length > 1) {
- values.forEach(v => {
- v = v.trim();
- if (v) select(transformItem$3(props, v));
- });
- _search.value = '';
- }
- }
- if (!val) selectionIndex.value = -1;
- isPristine.value = !val;
- }
- });
- watch(_search, value => {
- if (cleared) {
- // wait for clear to finish, VTextField sets _search to null
- // then search computed triggers and updates _search to ''
- nextTick(() => cleared = false);
- } else if (isFocused.value && !menu.value) {
- menu.value = true;
- }
- emit('update:search', value);
- });
- watch(model, value => {
- if (!props.multiple) {
- _search.value = value[0]?.title ?? '';
- }
- });
- const {
- filteredItems,
- getMatches
- } = useFilter(props, items, () => isPristine.value ? '' : search.value);
- const selections = computed(() => {
- return model.value.map(v => {
- return items.value.find(item => {
- const itemRawValue = getPropertyFromItem(item.raw, props.itemValue);
- const modelRawValue = getPropertyFromItem(v.raw, props.itemValue);
- if (itemRawValue === undefined || modelRawValue === undefined) return false;
- return props.returnObject ? props.valueComparator(itemRawValue, modelRawValue) : props.valueComparator(item.value, v.value);
- }) || v;
- });
- });
- const displayItems = computed(() => {
- if (props.hideSelected) {
- return filteredItems.value.filter(filteredItem => !selections.value.some(s => s.value === filteredItem.value));
- }
- return filteredItems.value;
- });
- const selected = computed(() => selections.value.map(selection => selection.props.value));
- const selection = computed(() => selections.value[selectionIndex.value]);
- const highlightFirst = computed(() => {
- const selectFirst = props.autoSelectFirst === true || props.autoSelectFirst === 'exact' && search.value === displayItems.value[0]?.title;
- return selectFirst && displayItems.value.length > 0 && !isPristine.value && !listHasFocus.value;
- });
- const menuDisabled = computed(() => props.hideNoData && !items.value.length || props.readonly || form?.isReadonly.value);
- const listRef = ref();
- const {
- onListScroll,
- onListKeydown
- } = useScrolling(listRef, vTextFieldRef);
- function onClear(e) {
- cleared = true;
- if (props.openOnClear) {
- menu.value = true;
- }
- }
- function onMousedownControl() {
- if (menuDisabled.value) return;
- menu.value = true;
- }
- function onMousedownMenuIcon(e) {
- if (menuDisabled.value) return;
- if (isFocused.value) {
- e.preventDefault();
- e.stopPropagation();
- }
- menu.value = !menu.value;
- }
- function onKeydown(e) {
- if (props.readonly || form?.isReadonly.value) return;
- const selectionStart = vTextFieldRef.value.selectionStart;
- const length = selected.value.length;
- if (selectionIndex.value > -1 || ['Enter', 'ArrowDown', 'ArrowUp'].includes(e.key)) {
- e.preventDefault();
- }
- if (['Enter', 'ArrowDown'].includes(e.key)) {
- menu.value = true;
- }
- if (['Escape'].includes(e.key)) {
- menu.value = false;
- }
- if (['Enter', 'Escape', 'Tab'].includes(e.key)) {
- if (highlightFirst.value && ['Enter', 'Tab'].includes(e.key)) {
- select(filteredItems.value[0]);
- }
- isPristine.value = true;
- }
- if (e.key === 'ArrowDown' && highlightFirst.value) {
- listRef.value?.focus('next');
- }
- if (!props.multiple) return;
- if (['Backspace', 'Delete'].includes(e.key)) {
- if (selectionIndex.value < 0) {
- if (e.key === 'Backspace' && !search.value) {
- selectionIndex.value = length - 1;
- }
- return;
- }
- const originalSelectionIndex = selectionIndex.value;
- if (selection.value) select(selection.value);
- selectionIndex.value = originalSelectionIndex >= length - 1 ? length - 2 : originalSelectionIndex;
- }
- if (e.key === 'ArrowLeft') {
- if (selectionIndex.value < 0 && selectionStart > 0) return;
- const prev = selectionIndex.value > -1 ? selectionIndex.value - 1 : length - 1;
- if (selections.value[prev]) {
- selectionIndex.value = prev;
- } else {
- selectionIndex.value = -1;
- vTextFieldRef.value.setSelectionRange(search.value.length, search.value.length);
- }
- }
- if (e.key === 'ArrowRight') {
- if (selectionIndex.value < 0) return;
- const next = selectionIndex.value + 1;
- if (selections.value[next]) {
- selectionIndex.value = next;
- } else {
- selectionIndex.value = -1;
- vTextFieldRef.value.setSelectionRange(0, 0);
- }
- }
- if (e.key === 'Enter' && search.value) {
- select(transformItem$3(props, search.value));
- search.value = '';
- }
- }
- function onAfterLeave() {
- if (isFocused.value) {
- isPristine.value = true;
- vTextFieldRef.value?.focus();
- }
- }
- function select(item) {
- if (props.multiple) {
- const index = selected.value.findIndex(selection => props.valueComparator(selection, item.value));
- if (index === -1) {
- model.value = [...model.value, item];
- } else {
- const value = [...model.value];
- value.splice(index, 1);
- model.value = value;
- }
- search.value = '';
- } else {
- model.value = [item];
- _search.value = item.title;
- // watch for search watcher to trigger
- nextTick(() => {
- menu.value = false;
- isPristine.value = true;
- });
- }
- }
- function onFocusin(e) {
- isFocused.value = true;
- setTimeout(() => {
- listHasFocus.value = true;
- });
- }
- function onFocusout(e) {
- listHasFocus.value = false;
- }
- function onUpdateModelValue(v) {
- if (v == null || v === '' && !props.multiple) model.value = [];
- }
- watch(filteredItems, val => {
- if (!val.length && props.hideNoData) menu.value = false;
- });
- watch(isFocused, (val, oldVal) => {
- if (val || val === oldVal) return;
- selectionIndex.value = -1;
- menu.value = false;
- if (highlightFirst.value && !listHasFocus.value && !selections.value.some(_ref2 => {
- let {
- value
- } = _ref2;
- return value === displayItems.value[0].value;
- })) {
- select(displayItems.value[0]);
- } else if (props.multiple && search.value) {
- model.value = [...model.value, transformItem$3(props, search.value)];
- search.value = '';
- }
- });
- useRender(() => {
- const hasChips = !!(props.chips || slots.chip);
- const hasList = !!(!props.hideNoData || displayItems.value.length || slots['prepend-item'] || slots['append-item'] || slots['no-data']);
- const isDirty = model.value.length > 0;
- const [textFieldProps] = VTextField.filterProps(props);
- return createVNode(VTextField, mergeProps({
- "ref": vTextFieldRef
- }, textFieldProps, {
- "modelValue": search.value,
- "onUpdate:modelValue": [$event => search.value = $event, onUpdateModelValue],
- "focused": isFocused.value,
- "onUpdate:focused": $event => isFocused.value = $event,
- "validationValue": model.externalValue,
- "dirty": isDirty,
- "class": ['v-combobox', {
- 'v-combobox--active-menu': menu.value,
- 'v-combobox--chips': !!props.chips,
- 'v-combobox--selection-slot': !!slots.selection,
- 'v-combobox--selecting-index': selectionIndex.value > -1,
- [`v-combobox--${props.multiple ? 'multiple' : 'single'}`]: true
- }, props.class],
- "style": props.style,
- "readonly": props.readonly,
- "placeholder": isDirty ? undefined : props.placeholder,
- "onClick:clear": onClear,
- "onMousedown:control": onMousedownControl,
- "onKeydown": onKeydown
- }), {
- ...slots,
- default: () => createVNode(Fragment, null, [createVNode(VMenu, mergeProps({
- "ref": vMenuRef,
- "modelValue": menu.value,
- "onUpdate:modelValue": $event => menu.value = $event,
- "activator": "parent",
- "contentClass": "v-combobox__content",
- "disabled": menuDisabled.value,
- "eager": props.eager,
- "maxHeight": 310,
- "openOnClick": false,
- "closeOnContentClick": false,
- "transition": props.transition,
- "onAfterLeave": onAfterLeave
- }, props.menuProps), {
- default: () => [hasList && createVNode(VList, {
- "ref": listRef,
- "selected": selected.value,
- "selectStrategy": props.multiple ? 'independent' : 'single-independent',
- "onMousedown": e => e.preventDefault(),
- "onKeydown": onListKeydown,
- "onFocusin": onFocusin,
- "onFocusout": onFocusout,
- "onScrollPassive": onListScroll,
- "tabindex": "-1",
- "color": props.itemColor ?? props.color
- }, {
- default: () => [slots['prepend-item']?.(), !displayItems.value.length && !props.hideNoData && (slots['no-data']?.() ?? createVNode(VListItem, {
- "title": t(props.noDataText)
- }, null)), createVNode(VVirtualScroll, {
- "renderless": true,
- "items": displayItems.value
- }, {
- default: _ref3 => {
- let {
- item,
- index,
- itemRef
- } = _ref3;
- const itemProps = mergeProps(item.props, {
- ref: itemRef,
- key: index,
- active: highlightFirst.value && index === 0 ? true : undefined,
- onClick: () => select(item)
- });
- return slots.item?.({
- item,
- index,
- props: itemProps
- }) ?? createVNode(VListItem, itemProps, {
- prepend: _ref4 => {
- let {
- isSelected
- } = _ref4;
- return createVNode(Fragment, null, [props.multiple && !props.hideSelected ? createVNode(VCheckboxBtn, {
- "key": item.value,
- "modelValue": isSelected,
- "ripple": false,
- "tabindex": "-1"
- }, null) : undefined, item.props.prependIcon && createVNode(VIcon, {
- "icon": item.props.prependIcon
- }, null)]);
- },
- title: () => {
- return isPristine.value ? item.title : highlightResult(item.title, getMatches(item)?.title, search.value?.length ?? 0);
- }
- });
- }
- }), slots['append-item']?.()]
- })]
- }), selections.value.map((item, index) => {
- function onChipClose(e) {
- e.stopPropagation();
- e.preventDefault();
- select(item);
- }
- const slotProps = {
- 'onClick:close': onChipClose,
- onMousedown(e) {
- e.preventDefault();
- e.stopPropagation();
- },
- modelValue: true,
- 'onUpdate:modelValue': undefined
- };
- return createVNode("div", {
- "key": item.value,
- "class": ['v-combobox__selection', index === selectionIndex.value && ['v-combobox__selection--selected', textColorClasses.value]],
- "style": index === selectionIndex.value ? textColorStyles.value : {}
- }, [hasChips ? !slots.chip ? createVNode(VChip, mergeProps({
- "key": "chip",
- "closable": props.closableChips,
- "size": "small",
- "text": item.title
- }, slotProps), null) : createVNode(VDefaultsProvider, {
- "key": "chip-defaults",
- "defaults": {
- VChip: {
- closable: props.closableChips,
- size: 'small',
- text: item.title
- }
- }
- }, {
- default: () => [slots.chip?.({
- item,
- index,
- props: slotProps
- })]
- }) : slots.selection?.({
- item,
- index
- }) ?? createVNode("span", {
- "class": "v-combobox__selection-text"
- }, [item.title, props.multiple && index < selections.value.length - 1 && createVNode("span", {
- "class": "v-combobox__selection-comma"
- }, [createTextVNode(",")])])]);
- })]),
- 'append-inner': function () {
- for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) {
- args[_key] = arguments[_key];
- }
- return createVNode(Fragment, null, [slots['append-inner']?.(...args), (!props.hideNoData || props.items.length) && props.menuIcon ? createVNode(VIcon, {
- "class": "v-combobox__menu-icon",
- "icon": props.menuIcon,
- "onMousedown": onMousedownMenuIcon,
- "onClick": noop
- }, null) : undefined]);
- }
- });
- });
- return forwardRefs({
- isFocused,
- isPristine,
- menu,
- search,
- selectionIndex,
- filteredItems,
- select
- }, vTextFieldRef);
- }
- });
- // Types
- const makeVDialogProps = propsFactory({
- fullscreen: Boolean,
- retainFocus: {
- type: Boolean,
- default: true
- },
- scrollable: Boolean,
- ...makeVOverlayProps({
- origin: 'center center',
- scrollStrategy: 'block',
- transition: {
- component: VDialogTransition
- },
- zIndex: 2400
- })
- }, 'VDialog');
- const VDialog = genericComponent()({
- name: 'VDialog',
- props: makeVDialogProps(),
- emits: {
- 'update:modelValue': value => true
- },
- setup(props, _ref) {
- let {
- slots
- } = _ref;
- const isActive = useProxiedModel(props, 'modelValue');
- const {
- scopeId
- } = useScopeId();
- const overlay = ref();
- function onFocusin(e) {
- const before = e.relatedTarget;
- const after = e.target;
- if (before !== after && overlay.value?.contentEl &&
- // We're the topmost dialog
- overlay.value?.globalTop &&
- // It isn't the document or the dialog body
- ![document, overlay.value.contentEl].includes(after) &&
- // It isn't inside the dialog body
- !overlay.value.contentEl.contains(after)) {
- const focusable = focusableChildren(overlay.value.contentEl);
- if (!focusable.length) return;
- const firstElement = focusable[0];
- const lastElement = focusable[focusable.length - 1];
- if (before === firstElement) {
- lastElement.focus();
- } else {
- firstElement.focus();
- }
- }
- }
- if (IN_BROWSER) {
- watch(() => isActive.value && props.retainFocus, val => {
- val ? document.addEventListener('focusin', onFocusin) : document.removeEventListener('focusin', onFocusin);
- }, {
- immediate: true
- });
- }
- watch(isActive, async val => {
- await nextTick();
- if (val) {
- overlay.value.contentEl?.focus({
- preventScroll: true
- });
- } else {
- overlay.value.activatorEl?.focus({
- preventScroll: true
- });
- }
- });
- const activatorProps = computed(() => mergeProps({
- 'aria-haspopup': 'dialog',
- 'aria-expanded': String(isActive.value)
- }, props.activatorProps));
- useRender(() => {
- const [overlayProps] = VOverlay.filterProps(props);
- return createVNode(VOverlay, mergeProps({
- "ref": overlay,
- "class": ['v-dialog', {
- 'v-dialog--fullscreen': props.fullscreen,
- 'v-dialog--scrollable': props.scrollable
- }, props.class],
- "style": props.style
- }, overlayProps, {
- "modelValue": isActive.value,
- "onUpdate:modelValue": $event => isActive.value = $event,
- "aria-modal": "true",
- "activatorProps": activatorProps.value,
- "role": "dialog"
- }, scopeId), {
- activator: slots.activator,
- default: function () {
- for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) {
- args[_key] = arguments[_key];
- }
- return createVNode(VDefaultsProvider, {
- "root": "VDialog"
- }, {
- default: () => [slots.default?.(...args)]
- });
- }
- });
- });
- return forwardRefs({}, overlay);
- }
- });
- // Types
- const VExpansionPanelSymbol = Symbol.for('vuetify:v-expansion-panel');
- const allowedVariants = ['default', 'accordion', 'inset', 'popout'];
- const makeVExpansionPanelsProps = propsFactory({
- color: String,
- variant: {
- type: String,
- default: 'default',
- validator: v => allowedVariants.includes(v)
- },
- readonly: Boolean,
- ...makeComponentProps(),
- ...makeGroupProps(),
- ...makeTagProps(),
- ...makeThemeProps()
- }, 'VExpansionPanels');
- const VExpansionPanels = genericComponent()({
- name: 'VExpansionPanels',
- props: makeVExpansionPanelsProps(),
- emits: {
- 'update:modelValue': val => true
- },
- setup(props, _ref) {
- let {
- slots
- } = _ref;
- useGroup(props, VExpansionPanelSymbol);
- const {
- themeClasses
- } = provideTheme(props);
- const variantClass = computed(() => props.variant && `v-expansion-panels--variant-${props.variant}`);
- provideDefaults({
- VExpansionPanel: {
- color: toRef(props, 'color')
- },
- VExpansionPanelTitle: {
- readonly: toRef(props, 'readonly')
- }
- });
- useRender(() => createVNode(props.tag, {
- "class": ['v-expansion-panels', themeClasses.value, variantClass.value, props.class],
- "style": props.style
- }, slots));
- return {};
- }
- });
- const makeVExpansionPanelTextProps = propsFactory({
- ...makeComponentProps(),
- ...makeLazyProps()
- }, 'VExpansionPanelText');
- const VExpansionPanelText = genericComponent()({
- name: 'VExpansionPanelText',
- props: makeVExpansionPanelTextProps(),
- setup(props, _ref) {
- let {
- slots
- } = _ref;
- const expansionPanel = inject$1(VExpansionPanelSymbol);
- if (!expansionPanel) throw new Error('[Vuetify] v-expansion-panel-text needs to be placed inside v-expansion-panel');
- const {
- hasContent,
- onAfterLeave
- } = useLazy(props, expansionPanel.isSelected);
- useRender(() => createVNode(VExpandTransition, {
- "onAfterLeave": onAfterLeave
- }, {
- default: () => [withDirectives(createVNode("div", {
- "class": ['v-expansion-panel-text', props.class],
- "style": props.style
- }, [slots.default && hasContent.value && createVNode("div", {
- "class": "v-expansion-panel-text__wrapper"
- }, [slots.default?.()])]), [[vShow, expansionPanel.isSelected.value]])]
- }));
- return {};
- }
- });
- // Types
- const makeVExpansionPanelTitleProps = propsFactory({
- color: String,
- expandIcon: {
- type: IconValue,
- default: '$expand'
- },
- collapseIcon: {
- type: IconValue,
- default: '$collapse'
- },
- hideActions: Boolean,
- ripple: {
- type: [Boolean, Object],
- default: false
- },
- readonly: Boolean,
- ...makeComponentProps()
- }, 'VExpansionPanelTitle');
- const VExpansionPanelTitle = genericComponent()({
- name: 'VExpansionPanelTitle',
- directives: {
- Ripple
- },
- props: makeVExpansionPanelTitleProps(),
- setup(props, _ref) {
- let {
- slots
- } = _ref;
- const expansionPanel = inject$1(VExpansionPanelSymbol);
- if (!expansionPanel) throw new Error('[Vuetify] v-expansion-panel-title needs to be placed inside v-expansion-panel');
- const {
- backgroundColorClasses,
- backgroundColorStyles
- } = useBackgroundColor(props, 'color');
- const slotProps = computed(() => ({
- collapseIcon: props.collapseIcon,
- disabled: expansionPanel.disabled.value,
- expanded: expansionPanel.isSelected.value,
- expandIcon: props.expandIcon,
- readonly: props.readonly
- }));
- useRender(() => withDirectives(createVNode("button", {
- "class": ['v-expansion-panel-title', {
- 'v-expansion-panel-title--active': expansionPanel.isSelected.value
- }, backgroundColorClasses.value, props.class],
- "style": [backgroundColorStyles.value, props.style],
- "type": "button",
- "tabindex": expansionPanel.disabled.value ? -1 : undefined,
- "disabled": expansionPanel.disabled.value,
- "aria-expanded": expansionPanel.isSelected.value,
- "onClick": !props.readonly ? expansionPanel.toggle : undefined
- }, [createVNode("span", {
- "class": "v-expansion-panel-title__overlay"
- }, null), slots.default?.(slotProps.value), !props.hideActions && createVNode("span", {
- "class": "v-expansion-panel-title__icon"
- }, [slots.actions ? slots.actions(slotProps.value) : createVNode(VIcon, {
- "icon": expansionPanel.isSelected.value ? props.collapseIcon : props.expandIcon
- }, null)])]), [[resolveDirective("ripple"), props.ripple]]));
- return {};
- }
- });
- const makeVExpansionPanelProps = propsFactory({
- title: String,
- text: String,
- bgColor: String,
- ...makeComponentProps(),
- ...makeElevationProps(),
- ...makeGroupItemProps(),
- ...makeLazyProps(),
- ...makeRoundedProps(),
- ...makeTagProps(),
- ...makeVExpansionPanelTitleProps()
- }, 'VExpansionPanel');
- const VExpansionPanel = genericComponent()({
- name: 'VExpansionPanel',
- props: makeVExpansionPanelProps(),
- emits: {
- 'group:selected': val => true
- },
- setup(props, _ref) {
- let {
- slots
- } = _ref;
- const groupItem = useGroupItem(props, VExpansionPanelSymbol);
- const {
- backgroundColorClasses,
- backgroundColorStyles
- } = useBackgroundColor(props, 'bgColor');
- const {
- elevationClasses
- } = useElevation(props);
- const {
- roundedClasses
- } = useRounded(props);
- const isDisabled = computed(() => groupItem?.disabled.value || props.disabled);
- const selectedIndices = computed(() => groupItem.group.items.value.reduce((arr, item, index) => {
- if (groupItem.group.selected.value.includes(item.id)) arr.push(index);
- return arr;
- }, []));
- const isBeforeSelected = computed(() => {
- const index = groupItem.group.items.value.findIndex(item => item.id === groupItem.id);
- return !groupItem.isSelected.value && selectedIndices.value.some(selectedIndex => selectedIndex - index === 1);
- });
- const isAfterSelected = computed(() => {
- const index = groupItem.group.items.value.findIndex(item => item.id === groupItem.id);
- return !groupItem.isSelected.value && selectedIndices.value.some(selectedIndex => selectedIndex - index === -1);
- });
- provide(VExpansionPanelSymbol, groupItem);
- provideDefaults({
- VExpansionPanelText: {
- eager: toRef(props, 'eager')
- }
- });
- useRender(() => {
- const hasText = !!(slots.text || props.text);
- const hasTitle = !!(slots.title || props.title);
- return createVNode(props.tag, {
- "class": ['v-expansion-panel', {
- 'v-expansion-panel--active': groupItem.isSelected.value,
- 'v-expansion-panel--before-active': isBeforeSelected.value,
- 'v-expansion-panel--after-active': isAfterSelected.value,
- 'v-expansion-panel--disabled': isDisabled.value
- }, roundedClasses.value, backgroundColorClasses.value, props.class],
- "style": [backgroundColorStyles.value, props.style]
- }, {
- default: () => [createVNode("div", {
- "class": ['v-expansion-panel__shadow', ...elevationClasses.value]
- }, null), hasTitle && createVNode(VExpansionPanelTitle, {
- "key": "title",
- "collapseIcon": props.collapseIcon,
- "color": props.color,
- "expandIcon": props.expandIcon,
- "hideActions": props.hideActions,
- "ripple": props.ripple
- }, {
- default: () => [slots.title ? slots.title() : props.title]
- }), hasText && createVNode(VExpansionPanelText, {
- "key": "text"
- }, {
- default: () => [slots.text ? slots.text() : props.text]
- }), slots.default?.()]
- });
- });
- return {};
- }
- });
- // Types
- const makeVFileInputProps = propsFactory({
- chips: Boolean,
- counter: Boolean,
- counterSizeString: {
- type: String,
- default: '$vuetify.fileInput.counterSize'
- },
- counterString: {
- type: String,
- default: '$vuetify.fileInput.counter'
- },
- multiple: Boolean,
- showSize: {
- type: [Boolean, Number],
- default: false,
- validator: v => {
- return typeof v === 'boolean' || [1000, 1024].includes(v);
- }
- },
- ...makeVInputProps({
- prependIcon: '$file'
- }),
- modelValue: {
- type: Array,
- default: () => [],
- validator: val => {
- return wrapInArray(val).every(v => v != null && typeof v === 'object');
- }
- },
- ...makeVFieldProps({
- clearable: true
- })
- }, 'VFileInput');
- const VFileInput = genericComponent()({
- name: 'VFileInput',
- inheritAttrs: false,
- props: makeVFileInputProps(),
- emits: {
- 'click:control': e => true,
- 'mousedown:control': e => true,
- 'update:focused': focused => true,
- 'update:modelValue': files => true
- },
- setup(props, _ref) {
- let {
- attrs,
- emit,
- slots
- } = _ref;
- const {
- t
- } = useLocale();
- const model = useProxiedModel(props, 'modelValue');
- const {
- isFocused,
- focus,
- blur
- } = useFocus(props);
- const base = computed(() => typeof props.showSize !== 'boolean' ? props.showSize : undefined);
- const totalBytes = computed(() => (model.value ?? []).reduce((bytes, _ref2) => {
- let {
- size = 0
- } = _ref2;
- return bytes + size;
- }, 0));
- const totalBytesReadable = computed(() => humanReadableFileSize(totalBytes.value, base.value));
- const fileNames = computed(() => (model.value ?? []).map(file => {
- const {
- name = '',
- size = 0
- } = file;
- return !props.showSize ? name : `${name} (${humanReadableFileSize(size, base.value)})`;
- }));
- const counterValue = computed(() => {
- const fileCount = model.value?.length ?? 0;
- if (props.showSize) return t(props.counterSizeString, fileCount, totalBytesReadable.value);else return t(props.counterString, fileCount);
- });
- const vInputRef = ref();
- const vFieldRef = ref();
- const inputRef = ref();
- const isActive = computed(() => isFocused.value || props.active);
- const isPlainOrUnderlined = computed(() => ['plain', 'underlined'].includes(props.variant));
- function onFocus() {
- if (inputRef.value !== document.activeElement) {
- inputRef.value?.focus();
- }
- if (!isFocused.value) focus();
- }
- function onClickPrepend(e) {
- onControlClick(e);
- }
- function onControlMousedown(e) {
- emit('mousedown:control', e);
- }
- function onControlClick(e) {
- inputRef.value?.click();
- emit('click:control', e);
- }
- function onClear(e) {
- e.stopPropagation();
- onFocus();
- nextTick(() => {
- model.value = [];
- callEvent(props['onClick:clear'], e);
- });
- }
- watch(model, newValue => {
- const hasModelReset = !Array.isArray(newValue) || !newValue.length;
- if (hasModelReset && inputRef.value) {
- inputRef.value.value = '';
- }
- });
- useRender(() => {
- const hasCounter = !!(slots.counter || props.counter);
- const hasDetails = !!(hasCounter || slots.details);
- const [rootAttrs, inputAttrs] = filterInputAttrs(attrs);
- const [{
- modelValue: _,
- ...inputProps
- }] = VInput.filterProps(props);
- const [fieldProps] = filterFieldProps(props);
- return createVNode(VInput, mergeProps({
- "ref": vInputRef,
- "modelValue": model.value,
- "onUpdate:modelValue": $event => model.value = $event,
- "class": ['v-file-input', {
- 'v-text-field--plain-underlined': isPlainOrUnderlined.value
- }, props.class],
- "style": props.style,
- "onClick:prepend": onClickPrepend
- }, rootAttrs, inputProps, {
- "centerAffix": !isPlainOrUnderlined.value,
- "focused": isFocused.value
- }), {
- ...slots,
- default: _ref3 => {
- let {
- id,
- isDisabled,
- isDirty,
- isReadonly,
- isValid
- } = _ref3;
- return createVNode(VField, mergeProps({
- "ref": vFieldRef,
- "prepend-icon": props.prependIcon,
- "onMousedown": onControlMousedown,
- "onClick": onControlClick,
- "onClick:clear": onClear,
- "onClick:prependInner": props['onClick:prependInner'],
- "onClick:appendInner": props['onClick:appendInner']
- }, fieldProps, {
- "id": id.value,
- "active": isActive.value || isDirty.value,
- "dirty": isDirty.value,
- "disabled": isDisabled.value,
- "focused": isFocused.value,
- "error": isValid.value === false
- }), {
- ...slots,
- default: _ref4 => {
- let {
- props: {
- class: fieldClass,
- ...slotProps
- }
- } = _ref4;
- return createVNode(Fragment, null, [createVNode("input", mergeProps({
- "ref": inputRef,
- "type": "file",
- "readonly": isReadonly.value,
- "disabled": isDisabled.value,
- "multiple": props.multiple,
- "name": props.name,
- "onClick": e => {
- e.stopPropagation();
- if (isReadonly.value) e.preventDefault();
- onFocus();
- },
- "onChange": e => {
- if (!e.target) return;
- const target = e.target;
- model.value = [...(target.files ?? [])];
- },
- "onFocus": onFocus,
- "onBlur": blur
- }, slotProps, inputAttrs), null), createVNode("div", {
- "class": fieldClass
- }, [!!model.value?.length && (slots.selection ? slots.selection({
- fileNames: fileNames.value,
- totalBytes: totalBytes.value,
- totalBytesReadable: totalBytesReadable.value
- }) : props.chips ? fileNames.value.map(text => createVNode(VChip, {
- "key": text,
- "size": "small",
- "color": props.color
- }, {
- default: () => [text]
- })) : fileNames.value.join(', '))])]);
- }
- });
- },
- details: hasDetails ? slotProps => createVNode(Fragment, null, [slots.details?.(slotProps), hasCounter && createVNode(Fragment, null, [createVNode("span", null, null), createVNode(VCounter, {
- "active": !!model.value?.length,
- "value": counterValue.value
- }, slots.counter)])]) : undefined
- });
- });
- return forwardRefs({}, vInputRef, vFieldRef, inputRef);
- }
- });
- const makeVFooterProps = propsFactory({
- app: Boolean,
- color: String,
- height: {
- type: [Number, String],
- default: 'auto'
- },
- ...makeBorderProps(),
- ...makeComponentProps(),
- ...makeElevationProps(),
- ...makeLayoutItemProps(),
- ...makeRoundedProps(),
- ...makeTagProps({
- tag: 'footer'
- }),
- ...makeThemeProps()
- }, 'VFooter');
- const VFooter = genericComponent()({
- name: 'VFooter',
- props: makeVFooterProps(),
- setup(props, _ref) {
- let {
- slots
- } = _ref;
- const {
- themeClasses
- } = provideTheme(props);
- const {
- backgroundColorClasses,
- backgroundColorStyles
- } = useBackgroundColor(toRef(props, 'color'));
- const {
- borderClasses
- } = useBorder(props);
- const {
- elevationClasses
- } = useElevation(props);
- const {
- roundedClasses
- } = useRounded(props);
- const autoHeight = shallowRef(32);
- const {
- resizeRef
- } = useResizeObserver(entries => {
- if (!entries.length) return;
- autoHeight.value = entries[0].target.clientHeight;
- });
- const height = computed(() => props.height === 'auto' ? autoHeight.value : parseInt(props.height, 10));
- const {
- layoutItemStyles
- } = useLayoutItem({
- id: props.name,
- order: computed(() => parseInt(props.order, 10)),
- position: computed(() => 'bottom'),
- layoutSize: height,
- elementSize: computed(() => props.height === 'auto' ? undefined : height.value),
- active: computed(() => props.app),
- absolute: toRef(props, 'absolute')
- });
- useRender(() => createVNode(props.tag, {
- "ref": resizeRef,
- "class": ['v-footer', themeClasses.value, backgroundColorClasses.value, borderClasses.value, elevationClasses.value, roundedClasses.value, props.class],
- "style": [backgroundColorStyles.value, props.app ? layoutItemStyles.value : {
- height: convertToUnit(props.height)
- }, props.style]
- }, slots));
- return {};
- }
- });
- // Types
- const makeVFormProps = propsFactory({
- ...makeComponentProps(),
- ...makeFormProps()
- }, 'VForm');
- const VForm = genericComponent()({
- name: 'VForm',
- props: makeVFormProps(),
- emits: {
- 'update:modelValue': val => true,
- submit: e => true
- },
- setup(props, _ref) {
- let {
- slots,
- emit
- } = _ref;
- const form = createForm(props);
- const formRef = ref();
- function onReset(e) {
- e.preventDefault();
- form.reset();
- }
- function onSubmit(_e) {
- const e = _e;
- const ready = form.validate();
- e.then = ready.then.bind(ready);
- e.catch = ready.catch.bind(ready);
- e.finally = ready.finally.bind(ready);
- emit('submit', e);
- if (!e.defaultPrevented) {
- ready.then(_ref2 => {
- let {
- valid
- } = _ref2;
- if (valid) {
- formRef.value?.submit();
- }
- });
- }
- e.preventDefault();
- }
- useRender(() => createVNode("form", {
- "ref": formRef,
- "class": ['v-form', props.class],
- "style": props.style,
- "novalidate": true,
- "onReset": onReset,
- "onSubmit": onSubmit
- }, [slots.default?.(form)]));
- return forwardRefs(form, formRef);
- }
- });
- const makeVContainerProps = propsFactory({
- fluid: {
- type: Boolean,
- default: false
- },
- ...makeComponentProps(),
- ...makeTagProps()
- }, 'VContainer');
- const VContainer = genericComponent()({
- name: 'VContainer',
- props: makeVContainerProps(),
- setup(props, _ref) {
- let {
- slots
- } = _ref;
- const {
- rtlClasses
- } = useRtl();
- useRender(() => createVNode(props.tag, {
- "class": ['v-container', {
- 'v-container--fluid': props.fluid
- }, rtlClasses.value, props.class],
- "style": props.style
- }, slots));
- return {};
- }
- });
- // Styles
- // Types
- const breakpointProps = (() => {
- return breakpoints.reduce((props, val) => {
- props[val] = {
- type: [Boolean, String, Number],
- default: false
- };
- return props;
- }, {});
- })();
- const offsetProps = (() => {
- return breakpoints.reduce((props, val) => {
- const offsetKey = 'offset' + capitalize(val);
- props[offsetKey] = {
- type: [String, Number],
- default: null
- };
- return props;
- }, {});
- })();
- const orderProps = (() => {
- return breakpoints.reduce((props, val) => {
- const orderKey = 'order' + capitalize(val);
- props[orderKey] = {
- type: [String, Number],
- default: null
- };
- return props;
- }, {});
- })();
- const propMap$1 = {
- col: Object.keys(breakpointProps),
- offset: Object.keys(offsetProps),
- order: Object.keys(orderProps)
- };
- function breakpointClass$1(type, prop, val) {
- let className = type;
- if (val == null || val === false) {
- return undefined;
- }
- if (prop) {
- const breakpoint = prop.replace(type, '');
- className += `-${breakpoint}`;
- }
- if (type === 'col') {
- className = 'v-' + className;
- }
- // Handling the boolean style prop when accepting [Boolean, String, Number]
- // means Vue will not convert <v-col sm></v-col> to sm: true for us.
- // Since the default is false, an empty string indicates the prop's presence.
- if (type === 'col' && (val === '' || val === true)) {
- // .v-col-md
- return className.toLowerCase();
- }
- // .order-md-6
- className += `-${val}`;
- return className.toLowerCase();
- }
- const ALIGN_SELF_VALUES = ['auto', 'start', 'end', 'center', 'baseline', 'stretch'];
- const makeVColProps = propsFactory({
- cols: {
- type: [Boolean, String, Number],
- default: false
- },
- ...breakpointProps,
- offset: {
- type: [String, Number],
- default: null
- },
- ...offsetProps,
- order: {
- type: [String, Number],
- default: null
- },
- ...orderProps,
- alignSelf: {
- type: String,
- default: null,
- validator: str => ALIGN_SELF_VALUES.includes(str)
- },
- ...makeComponentProps(),
- ...makeTagProps()
- }, 'VCol');
- const VCol = genericComponent()({
- name: 'VCol',
- props: makeVColProps(),
- setup(props, _ref) {
- let {
- slots
- } = _ref;
- const classes = computed(() => {
- const classList = [];
- // Loop through `col`, `offset`, `order` breakpoint props
- let type;
- for (type in propMap$1) {
- propMap$1[type].forEach(prop => {
- const value = props[prop];
- const className = breakpointClass$1(type, prop, value);
- if (className) classList.push(className);
- });
- }
- const hasColClasses = classList.some(className => className.startsWith('v-col-'));
- classList.push({
- // Default to .v-col if no other col-{bp}-* classes generated nor `cols` specified.
- 'v-col': !hasColClasses || !props.cols,
- [`v-col-${props.cols}`]: props.cols,
- [`offset-${props.offset}`]: props.offset,
- [`order-${props.order}`]: props.order,
- [`align-self-${props.alignSelf}`]: props.alignSelf
- });
- return classList;
- });
- return () => h(props.tag, {
- class: [classes.value, props.class],
- style: props.style
- }, slots.default?.());
- }
- });
- // Styles
- // Types
- const ALIGNMENT = ['start', 'end', 'center'];
- const SPACE = ['space-between', 'space-around', 'space-evenly'];
- function makeRowProps(prefix, def) {
- return breakpoints.reduce((props, val) => {
- const prefixKey = prefix + capitalize(val);
- props[prefixKey] = def();
- return props;
- }, {});
- }
- const ALIGN_VALUES = [...ALIGNMENT, 'baseline', 'stretch'];
- const alignValidator = str => ALIGN_VALUES.includes(str);
- const alignProps = makeRowProps('align', () => ({
- type: String,
- default: null,
- validator: alignValidator
- }));
- const JUSTIFY_VALUES = [...ALIGNMENT, ...SPACE];
- const justifyValidator = str => JUSTIFY_VALUES.includes(str);
- const justifyProps = makeRowProps('justify', () => ({
- type: String,
- default: null,
- validator: justifyValidator
- }));
- const ALIGN_CONTENT_VALUES = [...ALIGNMENT, ...SPACE, 'stretch'];
- const alignContentValidator = str => ALIGN_CONTENT_VALUES.includes(str);
- const alignContentProps = makeRowProps('alignContent', () => ({
- type: String,
- default: null,
- validator: alignContentValidator
- }));
- const propMap = {
- align: Object.keys(alignProps),
- justify: Object.keys(justifyProps),
- alignContent: Object.keys(alignContentProps)
- };
- const classMap = {
- align: 'align',
- justify: 'justify',
- alignContent: 'align-content'
- };
- function breakpointClass(type, prop, val) {
- let className = classMap[type];
- if (val == null) {
- return undefined;
- }
- if (prop) {
- // alignSm -> Sm
- const breakpoint = prop.replace(type, '');
- className += `-${breakpoint}`;
- }
- // .align-items-sm-center
- className += `-${val}`;
- return className.toLowerCase();
- }
- const makeVRowProps = propsFactory({
- dense: Boolean,
- noGutters: Boolean,
- align: {
- type: String,
- default: null,
- validator: alignValidator
- },
- ...alignProps,
- justify: {
- type: String,
- default: null,
- validator: justifyValidator
- },
- ...justifyProps,
- alignContent: {
- type: String,
- default: null,
- validator: alignContentValidator
- },
- ...alignContentProps,
- ...makeComponentProps(),
- ...makeTagProps()
- }, 'VRow');
- const VRow = genericComponent()({
- name: 'VRow',
- props: makeVRowProps(),
- setup(props, _ref) {
- let {
- slots
- } = _ref;
- const classes = computed(() => {
- const classList = [];
- // Loop through `align`, `justify`, `alignContent` breakpoint props
- let type;
- for (type in propMap) {
- propMap[type].forEach(prop => {
- const value = props[prop];
- const className = breakpointClass(type, prop, value);
- if (className) classList.push(className);
- });
- }
- classList.push({
- 'v-row--no-gutters': props.noGutters,
- 'v-row--dense': props.dense,
- [`align-${props.align}`]: props.align,
- [`justify-${props.justify}`]: props.justify,
- [`align-content-${props.alignContent}`]: props.alignContent
- });
- return classList;
- });
- return () => h(props.tag, {
- class: ['v-row', classes.value, props.class],
- style: props.style
- }, slots.default?.());
- }
- });
- // Utilities
- const VSpacer = createSimpleFunctional('flex-grow-1', 'div', 'VSpacer');
- // Composables
- const makeVHoverProps = propsFactory({
- disabled: Boolean,
- modelValue: {
- type: Boolean,
- default: undefined
- },
- ...makeDelayProps()
- }, 'VHover');
- const VHover = genericComponent()({
- name: 'VHover',
- props: makeVHoverProps(),
- emits: {
- 'update:modelValue': value => true
- },
- setup(props, _ref) {
- let {
- slots
- } = _ref;
- const isHovering = useProxiedModel(props, 'modelValue');
- const {
- runOpenDelay,
- runCloseDelay
- } = useDelay(props, value => !props.disabled && (isHovering.value = value));
- return () => slots.default?.({
- isHovering: isHovering.value,
- props: {
- onMouseenter: runOpenDelay,
- onMouseleave: runCloseDelay
- }
- });
- }
- });
- const VItemGroupSymbol = Symbol.for('vuetify:v-item-group');
- const makeVItemGroupProps = propsFactory({
- ...makeComponentProps(),
- ...makeGroupProps({
- selectedClass: 'v-item--selected'
- }),
- ...makeTagProps(),
- ...makeThemeProps()
- }, 'VItemGroup');
- const VItemGroup = genericComponent()({
- name: 'VItemGroup',
- props: makeVItemGroupProps(),
- emits: {
- 'update:modelValue': value => true
- },
- setup(props, _ref) {
- let {
- slots
- } = _ref;
- const {
- themeClasses
- } = provideTheme(props);
- const {
- isSelected,
- select,
- next,
- prev,
- selected
- } = useGroup(props, VItemGroupSymbol);
- return () => createVNode(props.tag, {
- "class": ['v-item-group', themeClasses.value, props.class],
- "style": props.style
- }, {
- default: () => [slots.default?.({
- isSelected,
- select,
- next,
- prev,
- selected: selected.value
- })]
- });
- }
- });
- // Composables
- const VItem = genericComponent()({
- name: 'VItem',
- props: makeGroupItemProps(),
- emits: {
- 'group:selected': val => true
- },
- setup(props, _ref) {
- let {
- slots
- } = _ref;
- const {
- isSelected,
- select,
- toggle,
- selectedClass,
- value,
- disabled
- } = useGroupItem(props, VItemGroupSymbol);
- return () => slots.default?.({
- isSelected: isSelected.value,
- selectedClass: selectedClass.value,
- select,
- toggle,
- value: value.value,
- disabled: disabled.value
- });
- }
- });
- // Styles
- const VKbd = createSimpleFunctional('v-kbd');
- const makeVLayoutProps = propsFactory({
- ...makeComponentProps(),
- ...makeLayoutProps()
- }, 'VLayout');
- const VLayout = genericComponent()({
- name: 'VLayout',
- props: makeVLayoutProps(),
- setup(props, _ref) {
- let {
- slots
- } = _ref;
- const {
- layoutClasses,
- layoutStyles,
- getLayoutItem,
- items,
- layoutRef
- } = createLayout(props);
- useRender(() => createVNode("div", {
- "ref": layoutRef,
- "class": [layoutClasses.value, props.class],
- "style": [layoutStyles.value, props.style]
- }, [slots.default?.()]));
- return {
- getLayoutItem,
- items
- };
- }
- });
- // Types
- const makeVLayoutItemProps = propsFactory({
- position: {
- type: String,
- required: true
- },
- size: {
- type: [Number, String],
- default: 300
- },
- modelValue: Boolean,
- ...makeComponentProps(),
- ...makeLayoutItemProps()
- }, 'VLayoutItem');
- const VLayoutItem = genericComponent()({
- name: 'VLayoutItem',
- props: makeVLayoutItemProps(),
- setup(props, _ref) {
- let {
- slots
- } = _ref;
- const {
- layoutItemStyles
- } = useLayoutItem({
- id: props.name,
- order: computed(() => parseInt(props.order, 10)),
- position: toRef(props, 'position'),
- elementSize: toRef(props, 'size'),
- layoutSize: toRef(props, 'size'),
- active: toRef(props, 'modelValue'),
- absolute: toRef(props, 'absolute')
- });
- return () => createVNode("div", {
- "class": ['v-layout-item', props.class],
- "style": [layoutItemStyles.value, props.style]
- }, [slots.default?.()]);
- }
- });
- // Types
- const makeVLazyProps = propsFactory({
- modelValue: Boolean,
- options: {
- type: Object,
- // For more information on types, navigate to:
- // https://developer.mozilla.org/en-US/docs/Web/API/Intersection_Observer_API
- default: () => ({
- root: undefined,
- rootMargin: undefined,
- threshold: undefined
- })
- },
- ...makeComponentProps(),
- ...makeDimensionProps(),
- ...makeTagProps(),
- ...makeTransitionProps({
- transition: 'fade-transition'
- })
- }, 'VLazy');
- const VLazy = genericComponent()({
- name: 'VLazy',
- directives: {
- intersect: Intersect
- },
- props: makeVLazyProps(),
- emits: {
- 'update:modelValue': value => true
- },
- setup(props, _ref) {
- let {
- slots
- } = _ref;
- const {
- dimensionStyles
- } = useDimension(props);
- const isActive = useProxiedModel(props, 'modelValue');
- function onIntersect(isIntersecting) {
- if (isActive.value) return;
- isActive.value = isIntersecting;
- }
- useRender(() => withDirectives(createVNode(props.tag, {
- "class": ['v-lazy', props.class],
- "style": [dimensionStyles.value, props.style]
- }, {
- default: () => [isActive.value && createVNode(MaybeTransition, {
- "transition": props.transition,
- "appear": true
- }, {
- default: () => [slots.default?.()]
- })]
- }), [[resolveDirective("intersect"), {
- handler: onIntersect,
- options: props.options
- }, null]]));
- return {};
- }
- });
- const makeVLocaleProviderProps = propsFactory({
- locale: String,
- fallbackLocale: String,
- messages: Object,
- rtl: {
- type: Boolean,
- default: undefined
- },
- ...makeComponentProps()
- }, 'VLocaleProvider');
- const VLocaleProvider = genericComponent()({
- name: 'VLocaleProvider',
- props: makeVLocaleProviderProps(),
- setup(props, _ref) {
- let {
- slots
- } = _ref;
- const {
- rtlClasses
- } = provideLocale(props);
- useRender(() => createVNode("div", {
- "class": ['v-locale-provider', rtlClasses.value, props.class],
- "style": props.style
- }, [slots.default?.()]));
- return {};
- }
- });
- const makeVMainProps = propsFactory({
- scrollable: Boolean,
- ...makeComponentProps(),
- ...makeTagProps({
- tag: 'main'
- })
- }, 'VMain');
- const VMain = genericComponent()({
- name: 'VMain',
- props: makeVMainProps(),
- setup(props, _ref) {
- let {
- slots
- } = _ref;
- const {
- mainStyles
- } = useLayout();
- const {
- ssrBootStyles
- } = useSsrBoot();
- useRender(() => createVNode(props.tag, {
- "class": ['v-main', {
- 'v-main--scrollable': props.scrollable
- }, props.class],
- "style": [mainStyles.value, ssrBootStyles.value, props.style]
- }, {
- default: () => [props.scrollable ? createVNode("div", {
- "class": "v-main__scroller"
- }, [slots.default?.()]) : slots.default?.()]
- }));
- return {};
- }
- });
- // Utilities
- // Types
- function useSticky(_ref) {
- let {
- rootEl,
- isSticky,
- layoutItemStyles
- } = _ref;
- const isStuck = shallowRef(false);
- const stuckPosition = shallowRef(0);
- const stickyStyles = computed(() => {
- const side = typeof isStuck.value === 'boolean' ? 'top' : isStuck.value;
- return [isSticky.value ? {
- top: 'auto',
- bottom: 'auto',
- height: undefined
- } : undefined, isStuck.value ? {
- [side]: convertToUnit(stuckPosition.value)
- } : {
- top: layoutItemStyles.value.top
- }];
- });
- onMounted(() => {
- watch(isSticky, val => {
- if (val) {
- window.addEventListener('scroll', onScroll, {
- passive: true
- });
- } else {
- window.removeEventListener('scroll', onScroll);
- }
- }, {
- immediate: true
- });
- });
- onBeforeUnmount(() => {
- window.removeEventListener('scroll', onScroll);
- });
- let lastScrollTop = 0;
- function onScroll() {
- const direction = lastScrollTop > window.scrollY ? 'up' : 'down';
- const rect = rootEl.value.getBoundingClientRect();
- const layoutTop = parseFloat(layoutItemStyles.value.top ?? 0);
- const top = window.scrollY - Math.max(0, stuckPosition.value - layoutTop);
- const bottom = rect.height + Math.max(stuckPosition.value, layoutTop) - window.scrollY - window.innerHeight;
- const bodyScroll = parseFloat(getComputedStyle(rootEl.value).getPropertyValue('--v-body-scroll-y')) || 0;
- if (rect.height < window.innerHeight - layoutTop) {
- isStuck.value = 'top';
- stuckPosition.value = layoutTop;
- } else if (direction === 'up' && isStuck.value === 'bottom' || direction === 'down' && isStuck.value === 'top') {
- stuckPosition.value = window.scrollY + rect.top - bodyScroll;
- isStuck.value = true;
- } else if (direction === 'down' && bottom <= 0) {
- stuckPosition.value = 0;
- isStuck.value = 'bottom';
- } else if (direction === 'up' && top <= 0) {
- if (!bodyScroll) {
- stuckPosition.value = rect.top + top;
- isStuck.value = 'top';
- } else if (isStuck.value !== 'top') {
- stuckPosition.value = -top + bodyScroll + layoutTop;
- isStuck.value = 'top';
- }
- }
- lastScrollTop = window.scrollY;
- }
- return {
- isStuck,
- stickyStyles
- };
- }
- // Utilities
- const HORIZON = 100; // ms
- const HISTORY = 20; // number of samples to keep
- /** @see https://android.googlesource.com/platform/frameworks/native/+/master/libs/input/VelocityTracker.cpp */
- function kineticEnergyToVelocity(work) {
- const sqrt2 = 1.41421356237;
- return (work < 0 ? -1.0 : 1.0) * Math.sqrt(Math.abs(work)) * sqrt2;
- }
- /**
- * Returns pointer velocity in px/s
- */
- function calculateImpulseVelocity(samples) {
- // The input should be in reversed time order (most recent sample at index i=0)
- if (samples.length < 2) {
- // if 0 or 1 points, velocity is zero
- return 0;
- }
- // if (samples[1].t > samples[0].t) {
- // // Algorithm will still work, but not perfectly
- // consoleWarn('Samples provided to calculateImpulseVelocity in the wrong order')
- // }
- if (samples.length === 2) {
- // if 2 points, basic linear calculation
- if (samples[1].t === samples[0].t) {
- // consoleWarn(`Events have identical time stamps t=${samples[0].t}, setting velocity = 0`)
- return 0;
- }
- return (samples[1].d - samples[0].d) / (samples[1].t - samples[0].t);
- }
- // Guaranteed to have at least 3 points here
- // start with the oldest sample and go forward in time
- let work = 0;
- for (let i = samples.length - 1; i > 0; i--) {
- if (samples[i].t === samples[i - 1].t) {
- // consoleWarn(`Events have identical time stamps t=${samples[i].t}, skipping sample`)
- continue;
- }
- const vprev = kineticEnergyToVelocity(work); // v[i-1]
- const vcurr = (samples[i].d - samples[i - 1].d) / (samples[i].t - samples[i - 1].t); // v[i]
- work += (vcurr - vprev) * Math.abs(vcurr);
- if (i === samples.length - 1) {
- work *= 0.5;
- }
- }
- return kineticEnergyToVelocity(work) * 1000;
- }
- function useVelocity() {
- const touches = {};
- function addMovement(e) {
- Array.from(e.changedTouches).forEach(touch => {
- const samples = touches[touch.identifier] ?? (touches[touch.identifier] = new CircularBuffer(HISTORY));
- samples.push([e.timeStamp, touch]);
- });
- }
- function endTouch(e) {
- Array.from(e.changedTouches).forEach(touch => {
- delete touches[touch.identifier];
- });
- }
- function getVelocity(id) {
- const samples = touches[id]?.values().reverse();
- if (!samples) {
- throw new Error(`No samples for touch id ${id}`);
- }
- const newest = samples[0];
- const x = [];
- const y = [];
- for (const val of samples) {
- if (newest[0] - val[0] > HORIZON) break;
- x.push({
- t: val[0],
- d: val[1].clientX
- });
- y.push({
- t: val[0],
- d: val[1].clientY
- });
- }
- return {
- x: calculateImpulseVelocity(x),
- y: calculateImpulseVelocity(y),
- get direction() {
- const {
- x,
- y
- } = this;
- const [absX, absY] = [Math.abs(x), Math.abs(y)];
- return absX > absY && x >= 0 ? 'right' : absX > absY && x <= 0 ? 'left' : absY > absX && y >= 0 ? 'down' : absY > absX && y <= 0 ? 'up' : oops$1();
- }
- };
- }
- return {
- addMovement,
- endTouch,
- getVelocity
- };
- }
- function oops$1() {
- throw new Error();
- }
- // Composables
- // Types
- function useTouch(_ref) {
- let {
- isActive,
- isTemporary,
- width,
- touchless,
- position
- } = _ref;
- onMounted(() => {
- window.addEventListener('touchstart', onTouchstart, {
- passive: true
- });
- window.addEventListener('touchmove', onTouchmove, {
- passive: false
- });
- window.addEventListener('touchend', onTouchend, {
- passive: true
- });
- });
- onBeforeUnmount(() => {
- window.removeEventListener('touchstart', onTouchstart);
- window.removeEventListener('touchmove', onTouchmove);
- window.removeEventListener('touchend', onTouchend);
- });
- const isHorizontal = computed(() => ['left', 'right'].includes(position.value));
- const {
- addMovement,
- endTouch,
- getVelocity
- } = useVelocity();
- let maybeDragging = false;
- const isDragging = shallowRef(false);
- const dragProgress = shallowRef(0);
- const offset = shallowRef(0);
- let start;
- function getOffset(pos, active) {
- return (position.value === 'left' ? pos : position.value === 'right' ? document.documentElement.clientWidth - pos : position.value === 'top' ? pos : position.value === 'bottom' ? document.documentElement.clientHeight - pos : oops()) - (active ? width.value : 0);
- }
- function getProgress(pos) {
- let limit = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : true;
- const progress = position.value === 'left' ? (pos - offset.value) / width.value : position.value === 'right' ? (document.documentElement.clientWidth - pos - offset.value) / width.value : position.value === 'top' ? (pos - offset.value) / width.value : position.value === 'bottom' ? (document.documentElement.clientHeight - pos - offset.value) / width.value : oops();
- return limit ? Math.max(0, Math.min(1, progress)) : progress;
- }
- function onTouchstart(e) {
- if (touchless.value) return;
- const touchX = e.changedTouches[0].clientX;
- const touchY = e.changedTouches[0].clientY;
- const touchZone = 25;
- const inTouchZone = position.value === 'left' ? touchX < touchZone : position.value === 'right' ? touchX > document.documentElement.clientWidth - touchZone : position.value === 'top' ? touchY < touchZone : position.value === 'bottom' ? touchY > document.documentElement.clientHeight - touchZone : oops();
- const inElement = isActive.value && (position.value === 'left' ? touchX < width.value : position.value === 'right' ? touchX > document.documentElement.clientWidth - width.value : position.value === 'top' ? touchY < width.value : position.value === 'bottom' ? touchY > document.documentElement.clientHeight - width.value : oops());
- if (inTouchZone || inElement || isActive.value && isTemporary.value) {
- maybeDragging = true;
- start = [touchX, touchY];
- offset.value = getOffset(isHorizontal.value ? touchX : touchY, isActive.value);
- dragProgress.value = getProgress(isHorizontal.value ? touchX : touchY);
- endTouch(e);
- addMovement(e);
- }
- }
- function onTouchmove(e) {
- const touchX = e.changedTouches[0].clientX;
- const touchY = e.changedTouches[0].clientY;
- if (maybeDragging) {
- if (!e.cancelable) {
- maybeDragging = false;
- return;
- }
- const dx = Math.abs(touchX - start[0]);
- const dy = Math.abs(touchY - start[1]);
- const thresholdMet = isHorizontal.value ? dx > dy && dx > 3 : dy > dx && dy > 3;
- if (thresholdMet) {
- isDragging.value = true;
- maybeDragging = false;
- } else if ((isHorizontal.value ? dy : dx) > 3) {
- maybeDragging = false;
- }
- }
- if (!isDragging.value) return;
- e.preventDefault();
- addMovement(e);
- const progress = getProgress(isHorizontal.value ? touchX : touchY, false);
- dragProgress.value = Math.max(0, Math.min(1, progress));
- if (progress > 1) {
- offset.value = getOffset(isHorizontal.value ? touchX : touchY, true);
- } else if (progress < 0) {
- offset.value = getOffset(isHorizontal.value ? touchX : touchY, false);
- }
- }
- function onTouchend(e) {
- maybeDragging = false;
- if (!isDragging.value) return;
- addMovement(e);
- isDragging.value = false;
- const velocity = getVelocity(e.changedTouches[0].identifier);
- const vx = Math.abs(velocity.x);
- const vy = Math.abs(velocity.y);
- const thresholdMet = isHorizontal.value ? vx > vy && vx > 400 : vy > vx && vy > 3;
- if (thresholdMet) {
- isActive.value = velocity.direction === ({
- left: 'right',
- right: 'left',
- top: 'down',
- bottom: 'up'
- }[position.value] || oops());
- } else {
- isActive.value = dragProgress.value > 0.5;
- }
- }
- const dragStyles = computed(() => {
- return isDragging.value ? {
- transform: position.value === 'left' ? `translateX(calc(-100% + ${dragProgress.value * width.value}px))` : position.value === 'right' ? `translateX(calc(100% - ${dragProgress.value * width.value}px))` : position.value === 'top' ? `translateY(calc(-100% + ${dragProgress.value * width.value}px))` : position.value === 'bottom' ? `translateY(calc(100% - ${dragProgress.value * width.value}px))` : oops(),
- transition: 'none'
- } : undefined;
- });
- return {
- isDragging,
- dragProgress,
- dragStyles
- };
- }
- function oops() {
- throw new Error();
- }
- // Types
- const locations = ['start', 'end', 'left', 'right', 'top', 'bottom'];
- const makeVNavigationDrawerProps = propsFactory({
- color: String,
- disableResizeWatcher: Boolean,
- disableRouteWatcher: Boolean,
- expandOnHover: Boolean,
- floating: Boolean,
- modelValue: {
- type: Boolean,
- default: null
- },
- permanent: Boolean,
- rail: {
- type: Boolean,
- default: null
- },
- railWidth: {
- type: [Number, String],
- default: 56
- },
- scrim: {
- type: [Boolean, String],
- default: true
- },
- image: String,
- temporary: Boolean,
- touchless: Boolean,
- width: {
- type: [Number, String],
- default: 256
- },
- location: {
- type: String,
- default: 'start',
- validator: value => locations.includes(value)
- },
- sticky: Boolean,
- ...makeBorderProps(),
- ...makeComponentProps(),
- ...makeElevationProps(),
- ...makeLayoutItemProps(),
- ...makeRoundedProps(),
- ...makeTagProps({
- tag: 'nav'
- }),
- ...makeThemeProps()
- }, 'VNavigationDrawer');
- const VNavigationDrawer = genericComponent()({
- name: 'VNavigationDrawer',
- props: makeVNavigationDrawerProps(),
- emits: {
- 'update:modelValue': val => true,
- 'update:rail': val => true
- },
- setup(props, _ref) {
- let {
- attrs,
- emit,
- slots
- } = _ref;
- const {
- isRtl
- } = useRtl();
- const {
- themeClasses
- } = provideTheme(props);
- const {
- borderClasses
- } = useBorder(props);
- const {
- backgroundColorClasses,
- backgroundColorStyles
- } = useBackgroundColor(toRef(props, 'color'));
- const {
- elevationClasses
- } = useElevation(props);
- const {
- mobile
- } = useDisplay();
- const {
- roundedClasses
- } = useRounded(props);
- const router = useRouter();
- const isActive = useProxiedModel(props, 'modelValue', null, v => !!v);
- const {
- ssrBootStyles
- } = useSsrBoot();
- const {
- scopeId
- } = useScopeId();
- const rootEl = ref();
- const isHovering = shallowRef(false);
- const width = computed(() => {
- return props.rail && props.expandOnHover && isHovering.value ? Number(props.width) : Number(props.rail ? props.railWidth : props.width);
- });
- const location = computed(() => {
- return toPhysical(props.location, isRtl.value);
- });
- const isTemporary = computed(() => !props.permanent && (mobile.value || props.temporary));
- const isSticky = computed(() => props.sticky && !isTemporary.value && location.value !== 'bottom');
- if (props.expandOnHover && props.rail != null) {
- watch(isHovering, val => emit('update:rail', !val));
- }
- if (!props.disableResizeWatcher) {
- watch(isTemporary, val => !props.permanent && nextTick(() => isActive.value = !val));
- }
- if (!props.disableRouteWatcher && router) {
- watch(router.currentRoute, () => isTemporary.value && (isActive.value = false));
- }
- watch(() => props.permanent, val => {
- if (val) isActive.value = true;
- });
- onBeforeMount(() => {
- if (props.modelValue != null || isTemporary.value) return;
- isActive.value = props.permanent || !mobile.value;
- });
- const {
- isDragging,
- dragProgress,
- dragStyles
- } = useTouch({
- isActive,
- isTemporary,
- width,
- touchless: toRef(props, 'touchless'),
- position: location
- });
- const layoutSize = computed(() => {
- const size = isTemporary.value ? 0 : props.rail && props.expandOnHover ? Number(props.railWidth) : width.value;
- return isDragging.value ? size * dragProgress.value : size;
- });
- const {
- layoutItemStyles,
- layoutItemScrimStyles
- } = useLayoutItem({
- id: props.name,
- order: computed(() => parseInt(props.order, 10)),
- position: location,
- layoutSize,
- elementSize: width,
- active: computed(() => isActive.value || isDragging.value),
- disableTransitions: computed(() => isDragging.value),
- absolute: computed(() =>
- // eslint-disable-next-line @typescript-eslint/no-use-before-define
- props.absolute || isSticky.value && typeof isStuck.value !== 'string')
- });
- const {
- isStuck,
- stickyStyles
- } = useSticky({
- rootEl,
- isSticky,
- layoutItemStyles
- });
- const scrimColor = useBackgroundColor(computed(() => {
- return typeof props.scrim === 'string' ? props.scrim : null;
- }));
- const scrimStyles = computed(() => ({
- ...(isDragging.value ? {
- opacity: dragProgress.value * 0.2,
- transition: 'none'
- } : undefined),
- ...layoutItemScrimStyles.value
- }));
- provideDefaults({
- VList: {
- bgColor: 'transparent'
- }
- });
- function onMouseenter() {
- isHovering.value = true;
- }
- function onMouseleave() {
- isHovering.value = false;
- }
- useRender(() => {
- const hasImage = slots.image || props.image;
- return createVNode(Fragment, null, [createVNode(props.tag, mergeProps({
- "ref": rootEl,
- "onMouseenter": onMouseenter,
- "onMouseleave": onMouseleave,
- "class": ['v-navigation-drawer', `v-navigation-drawer--${location.value}`, {
- 'v-navigation-drawer--expand-on-hover': props.expandOnHover,
- 'v-navigation-drawer--floating': props.floating,
- 'v-navigation-drawer--is-hovering': isHovering.value,
- 'v-navigation-drawer--rail': props.rail,
- 'v-navigation-drawer--temporary': isTemporary.value,
- 'v-navigation-drawer--active': isActive.value,
- 'v-navigation-drawer--sticky': isSticky.value
- }, themeClasses.value, backgroundColorClasses.value, borderClasses.value, elevationClasses.value, roundedClasses.value, props.class],
- "style": [backgroundColorStyles.value, layoutItemStyles.value, dragStyles.value, ssrBootStyles.value, stickyStyles.value, props.style]
- }, scopeId, attrs), {
- default: () => [hasImage && createVNode("div", {
- "key": "image",
- "class": "v-navigation-drawer__img"
- }, [slots.image ? slots.image?.({
- image: props.image
- }) : createVNode("img", {
- "src": props.image,
- "alt": ""
- }, null)]), slots.prepend && createVNode("div", {
- "class": "v-navigation-drawer__prepend"
- }, [slots.prepend?.()]), createVNode("div", {
- "class": "v-navigation-drawer__content"
- }, [slots.default?.()]), slots.append && createVNode("div", {
- "class": "v-navigation-drawer__append"
- }, [slots.append?.()])]
- }), createVNode(Transition, {
- "name": "fade-transition"
- }, {
- default: () => [isTemporary.value && (isDragging.value || isActive.value) && !!props.scrim && createVNode("div", mergeProps({
- "class": ['v-navigation-drawer__scrim', scrimColor.backgroundColorClasses.value],
- "style": [scrimStyles.value, scrimColor.backgroundColorStyles.value],
- "onClick": () => isActive.value = false
- }, scopeId), null)]
- })]);
- });
- return {
- isStuck
- };
- }
- });
- // Composables
- const VNoSsr = defineComponent({
- name: 'VNoSsr',
- setup(_, _ref) {
- let {
- slots
- } = _ref;
- const show = useHydration();
- return () => show.value && slots.default?.();
- }
- });
- // Utilities
- // Types
- function useRefs() {
- const refs = ref([]);
- onBeforeUpdate(() => refs.value = []);
- function updateRef(e, i) {
- refs.value[i] = e;
- }
- return {
- refs,
- updateRef
- };
- }
- // Types
- const makeVPaginationProps = propsFactory({
- activeColor: String,
- start: {
- type: [Number, String],
- default: 1
- },
- modelValue: {
- type: Number,
- default: props => props.start
- },
- disabled: Boolean,
- length: {
- type: [Number, String],
- default: 1,
- validator: val => val % 1 === 0
- },
- totalVisible: [Number, String],
- firstIcon: {
- type: IconValue,
- default: '$first'
- },
- prevIcon: {
- type: IconValue,
- default: '$prev'
- },
- nextIcon: {
- type: IconValue,
- default: '$next'
- },
- lastIcon: {
- type: IconValue,
- default: '$last'
- },
- ariaLabel: {
- type: String,
- default: '$vuetify.pagination.ariaLabel.root'
- },
- pageAriaLabel: {
- type: String,
- default: '$vuetify.pagination.ariaLabel.page'
- },
- currentPageAriaLabel: {
- type: String,
- default: '$vuetify.pagination.ariaLabel.currentPage'
- },
- firstAriaLabel: {
- type: String,
- default: '$vuetify.pagination.ariaLabel.first'
- },
- previousAriaLabel: {
- type: String,
- default: '$vuetify.pagination.ariaLabel.previous'
- },
- nextAriaLabel: {
- type: String,
- default: '$vuetify.pagination.ariaLabel.next'
- },
- lastAriaLabel: {
- type: String,
- default: '$vuetify.pagination.ariaLabel.last'
- },
- ellipsis: {
- type: String,
- default: '...'
- },
- showFirstLastPage: Boolean,
- ...makeBorderProps(),
- ...makeComponentProps(),
- ...makeDensityProps(),
- ...makeElevationProps(),
- ...makeRoundedProps(),
- ...makeSizeProps(),
- ...makeTagProps({
- tag: 'nav'
- }),
- ...makeThemeProps(),
- ...makeVariantProps({
- variant: 'text'
- })
- }, 'VPagination');
- const VPagination = genericComponent()({
- name: 'VPagination',
- props: makeVPaginationProps(),
- emits: {
- 'update:modelValue': value => true,
- first: value => true,
- prev: value => true,
- next: value => true,
- last: value => true
- },
- setup(props, _ref) {
- let {
- slots,
- emit
- } = _ref;
- const page = useProxiedModel(props, 'modelValue');
- const {
- t,
- n
- } = useLocale();
- const {
- isRtl
- } = useRtl();
- const {
- themeClasses
- } = provideTheme(props);
- const {
- width
- } = useDisplay();
- const maxButtons = shallowRef(-1);
- provideDefaults(undefined, {
- scoped: true
- });
- const {
- resizeRef
- } = useResizeObserver(entries => {
- if (!entries.length) return;
- const {
- target,
- contentRect
- } = entries[0];
- const firstItem = target.querySelector('.v-pagination__list > *');
- if (!firstItem) return;
- const totalWidth = contentRect.width;
- const itemWidth = firstItem.offsetWidth + parseFloat(getComputedStyle(firstItem).marginRight) * 2;
- maxButtons.value = getMax(totalWidth, itemWidth);
- });
- const length = computed(() => parseInt(props.length, 10));
- const start = computed(() => parseInt(props.start, 10));
- const totalVisible = computed(() => {
- if (props.totalVisible) return parseInt(props.totalVisible, 10);else if (maxButtons.value >= 0) return maxButtons.value;
- return getMax(width.value, 58);
- });
- function getMax(totalWidth, itemWidth) {
- const minButtons = props.showFirstLastPage ? 5 : 3;
- return Math.max(0, Math.floor(
- // Round to two decimal places to avoid floating point errors
- +((totalWidth - itemWidth * minButtons) / itemWidth).toFixed(2)));
- }
- const range = computed(() => {
- if (length.value <= 0 || isNaN(length.value) || length.value > Number.MAX_SAFE_INTEGER) return [];
- if (totalVisible.value <= 1) return [page.value];
- if (length.value <= totalVisible.value) {
- return createRange(length.value, start.value);
- }
- const even = totalVisible.value % 2 === 0;
- const middle = even ? totalVisible.value / 2 : Math.floor(totalVisible.value / 2);
- const left = even ? middle : middle + 1;
- const right = length.value - middle;
- if (left - page.value >= 0) {
- return [...createRange(Math.max(1, totalVisible.value - 1), start.value), props.ellipsis, length.value];
- } else if (page.value - right >= (even ? 1 : 0)) {
- const rangeLength = totalVisible.value - 1;
- const rangeStart = length.value - rangeLength + start.value;
- return [start.value, props.ellipsis, ...createRange(rangeLength, rangeStart)];
- } else {
- const rangeLength = Math.max(1, totalVisible.value - 3);
- const rangeStart = rangeLength === 1 ? page.value : page.value - Math.ceil(rangeLength / 2) + start.value;
- return [start.value, props.ellipsis, ...createRange(rangeLength, rangeStart), props.ellipsis, length.value];
- }
- });
- // TODO: 'first' | 'prev' | 'next' | 'last' does not work here?
- function setValue(e, value, event) {
- e.preventDefault();
- page.value = value;
- event && emit(event, value);
- }
- const {
- refs,
- updateRef
- } = useRefs();
- provideDefaults({
- VPaginationBtn: {
- color: toRef(props, 'color'),
- border: toRef(props, 'border'),
- density: toRef(props, 'density'),
- size: toRef(props, 'size'),
- variant: toRef(props, 'variant'),
- rounded: toRef(props, 'rounded'),
- elevation: toRef(props, 'elevation')
- }
- });
- const items = computed(() => {
- return range.value.map((item, index) => {
- const ref = e => updateRef(e, index);
- if (typeof item === 'string') {
- return {
- isActive: false,
- key: `ellipsis-${index}`,
- page: item,
- props: {
- ref,
- ellipsis: true,
- icon: true,
- disabled: true
- }
- };
- } else {
- const isActive = item === page.value;
- return {
- isActive,
- key: item,
- page: n(item),
- props: {
- ref,
- ellipsis: false,
- icon: true,
- disabled: !!props.disabled || +props.length < 2,
- color: isActive ? props.activeColor : props.color,
- ariaCurrent: isActive,
- ariaLabel: t(isActive ? props.currentPageAriaLabel : props.pageAriaLabel, item),
- onClick: e => setValue(e, item)
- }
- };
- }
- });
- });
- const controls = computed(() => {
- const prevDisabled = !!props.disabled || page.value <= start.value;
- const nextDisabled = !!props.disabled || page.value >= start.value + length.value - 1;
- return {
- first: props.showFirstLastPage ? {
- icon: isRtl.value ? props.lastIcon : props.firstIcon,
- onClick: e => setValue(e, start.value, 'first'),
- disabled: prevDisabled,
- ariaLabel: t(props.firstAriaLabel),
- ariaDisabled: prevDisabled
- } : undefined,
- prev: {
- icon: isRtl.value ? props.nextIcon : props.prevIcon,
- onClick: e => setValue(e, page.value - 1, 'prev'),
- disabled: prevDisabled,
- ariaLabel: t(props.previousAriaLabel),
- ariaDisabled: prevDisabled
- },
- next: {
- icon: isRtl.value ? props.prevIcon : props.nextIcon,
- onClick: e => setValue(e, page.value + 1, 'next'),
- disabled: nextDisabled,
- ariaLabel: t(props.nextAriaLabel),
- ariaDisabled: nextDisabled
- },
- last: props.showFirstLastPage ? {
- icon: isRtl.value ? props.firstIcon : props.lastIcon,
- onClick: e => setValue(e, start.value + length.value - 1, 'last'),
- disabled: nextDisabled,
- ariaLabel: t(props.lastAriaLabel),
- ariaDisabled: nextDisabled
- } : undefined
- };
- });
- function updateFocus() {
- const currentIndex = page.value - start.value;
- refs.value[currentIndex]?.$el.focus();
- }
- function onKeydown(e) {
- if (e.key === keyValues.left && !props.disabled && page.value > +props.start) {
- page.value = page.value - 1;
- nextTick(updateFocus);
- } else if (e.key === keyValues.right && !props.disabled && page.value < start.value + length.value - 1) {
- page.value = page.value + 1;
- nextTick(updateFocus);
- }
- }
- useRender(() => createVNode(props.tag, {
- "ref": resizeRef,
- "class": ['v-pagination', themeClasses.value, props.class],
- "style": props.style,
- "role": "navigation",
- "aria-label": t(props.ariaLabel),
- "onKeydown": onKeydown,
- "data-test": "v-pagination-root"
- }, {
- default: () => [createVNode("ul", {
- "class": "v-pagination__list"
- }, [props.showFirstLastPage && createVNode("li", {
- "key": "first",
- "class": "v-pagination__first",
- "data-test": "v-pagination-first"
- }, [slots.first ? slots.first(controls.value.first) : createVNode(VBtn, mergeProps({
- "_as": "VPaginationBtn"
- }, controls.value.first), null)]), createVNode("li", {
- "key": "prev",
- "class": "v-pagination__prev",
- "data-test": "v-pagination-prev"
- }, [slots.prev ? slots.prev(controls.value.prev) : createVNode(VBtn, mergeProps({
- "_as": "VPaginationBtn"
- }, controls.value.prev), null)]), items.value.map((item, index) => createVNode("li", {
- "key": item.key,
- "class": ['v-pagination__item', {
- 'v-pagination__item--is-active': item.isActive
- }],
- "data-test": "v-pagination-item"
- }, [slots.item ? slots.item(item) : createVNode(VBtn, mergeProps({
- "_as": "VPaginationBtn"
- }, item.props), {
- default: () => [item.page]
- })])), createVNode("li", {
- "key": "next",
- "class": "v-pagination__next",
- "data-test": "v-pagination-next"
- }, [slots.next ? slots.next(controls.value.next) : createVNode(VBtn, mergeProps({
- "_as": "VPaginationBtn"
- }, controls.value.next), null)]), props.showFirstLastPage && createVNode("li", {
- "key": "last",
- "class": "v-pagination__last",
- "data-test": "v-pagination-last"
- }, [slots.last ? slots.last(controls.value.last) : createVNode(VBtn, mergeProps({
- "_as": "VPaginationBtn"
- }, controls.value.last), null)])])]
- }));
- return {};
- }
- });
- // Types
- function floor(val) {
- return Math.floor(Math.abs(val)) * Math.sign(val);
- }
- const makeVParallaxProps = propsFactory({
- scale: {
- type: [Number, String],
- default: 0.5
- },
- ...makeComponentProps()
- }, 'VParallax');
- const VParallax = genericComponent()({
- name: 'VParallax',
- props: makeVParallaxProps(),
- setup(props, _ref) {
- let {
- slots
- } = _ref;
- const {
- intersectionRef,
- isIntersecting
- } = useIntersectionObserver();
- const {
- resizeRef,
- contentRect
- } = useResizeObserver();
- const {
- height: displayHeight
- } = useDisplay();
- const root = ref();
- watchEffect(() => {
- intersectionRef.value = resizeRef.value = root.value?.$el;
- });
- let scrollParent;
- watch(isIntersecting, val => {
- if (val) {
- scrollParent = getScrollParent(intersectionRef.value);
- scrollParent = scrollParent === document.scrollingElement ? document : scrollParent;
- scrollParent.addEventListener('scroll', onScroll, {
- passive: true
- });
- onScroll();
- } else {
- scrollParent.removeEventListener('scroll', onScroll);
- }
- });
- onBeforeUnmount(() => {
- scrollParent?.removeEventListener('scroll', onScroll);
- });
- watch(displayHeight, onScroll);
- watch(() => contentRect.value?.height, onScroll);
- const scale = computed(() => {
- return 1 - clamp(+props.scale);
- });
- let frame = -1;
- function onScroll() {
- if (!isIntersecting.value) return;
- cancelAnimationFrame(frame);
- frame = requestAnimationFrame(() => {
- const el = (root.value?.$el).querySelector('.v-img__img');
- if (!el) return;
- const scrollHeight = scrollParent instanceof Document ? document.documentElement.clientHeight : scrollParent.clientHeight;
- const scrollPos = scrollParent instanceof Document ? window.scrollY : scrollParent.scrollTop;
- const top = intersectionRef.value.getBoundingClientRect().top + scrollPos;
- const height = contentRect.value.height;
- const center = top + (height - scrollHeight) / 2;
- const translate = floor((scrollPos - center) * scale.value);
- const sizeScale = Math.max(1, (scale.value * (scrollHeight - height) + height) / height);
- el.style.setProperty('transform', `translateY(${translate}px) scale(${sizeScale})`);
- });
- }
- useRender(() => createVNode(VImg, {
- "class": ['v-parallax', {
- 'v-parallax--active': isIntersecting.value
- }, props.class],
- "style": props.style,
- "ref": root,
- "cover": true,
- "onLoadstart": onScroll,
- "onLoad": onScroll
- }, slots));
- return {};
- }
- });
- // Types
- const makeVRadioProps = propsFactory({
- ...makeVSelectionControlProps({
- falseIcon: '$radioOff',
- trueIcon: '$radioOn'
- })
- }, 'VRadio');
- const VRadio = genericComponent()({
- name: 'VRadio',
- props: makeVRadioProps(),
- setup(props, _ref) {
- let {
- slots
- } = _ref;
- useRender(() => createVNode(VSelectionControl, mergeProps(props, {
- "class": ['v-radio', props.class],
- "style": props.style,
- "type": "radio"
- }), slots));
- return {};
- }
- });
- // Types
- const makeVRadioGroupProps = propsFactory({
- height: {
- type: [Number, String],
- default: 'auto'
- },
- ...makeVInputProps(),
- ...omit(makeSelectionControlGroupProps(), ['multiple']),
- trueIcon: {
- type: IconValue,
- default: '$radioOn'
- },
- falseIcon: {
- type: IconValue,
- default: '$radioOff'
- },
- type: {
- type: String,
- default: 'radio'
- }
- }, 'VRadioGroup');
- const VRadioGroup = genericComponent()({
- name: 'VRadioGroup',
- inheritAttrs: false,
- props: makeVRadioGroupProps(),
- emits: {
- 'update:modelValue': val => true
- },
- setup(props, _ref) {
- let {
- attrs,
- slots
- } = _ref;
- const uid = getUid();
- const id = computed(() => props.id || `radio-group-${uid}`);
- const model = useProxiedModel(props, 'modelValue');
- useRender(() => {
- const [inputAttrs, controlAttrs] = filterInputAttrs(attrs);
- const [inputProps, _1] = VInput.filterProps(props);
- const [controlProps, _2] = VSelectionControl.filterProps(props);
- const label = slots.label ? slots.label({
- label: props.label,
- props: {
- for: id.value
- }
- }) : props.label;
- return createVNode(VInput, mergeProps({
- "class": ['v-radio-group', props.class],
- "style": props.style
- }, inputAttrs, inputProps, {
- "modelValue": model.value,
- "onUpdate:modelValue": $event => model.value = $event,
- "id": id.value
- }), {
- ...slots,
- default: _ref2 => {
- let {
- id,
- messagesId,
- isDisabled,
- isReadonly
- } = _ref2;
- return createVNode(Fragment, null, [label && createVNode(VLabel, {
- "id": id.value
- }, {
- default: () => [label]
- }), createVNode(VSelectionControlGroup, mergeProps(controlProps, {
- "id": id.value,
- "aria-describedby": messagesId.value,
- "defaultsTarget": "VRadio",
- "trueIcon": props.trueIcon,
- "falseIcon": props.falseIcon,
- "type": props.type,
- "disabled": isDisabled.value,
- "readonly": isReadonly.value,
- "aria-labelledby": label ? id.value : undefined,
- "multiple": false
- }, controlAttrs, {
- "modelValue": model.value,
- "onUpdate:modelValue": $event => model.value = $event
- }), slots)]);
- }
- });
- });
- return {};
- }
- });
- // Types
- const makeVRangeSliderProps = propsFactory({
- ...makeFocusProps(),
- ...makeVInputProps(),
- ...makeSliderProps(),
- strict: Boolean,
- modelValue: {
- type: Array,
- default: () => [0, 0]
- }
- }, 'VRangeSlider');
- const VRangeSlider = genericComponent()({
- name: 'VRangeSlider',
- props: makeVRangeSliderProps(),
- emits: {
- 'update:focused': value => true,
- 'update:modelValue': value => true,
- end: value => true,
- start: value => true
- },
- setup(props, _ref) {
- let {
- slots,
- emit
- } = _ref;
- const startThumbRef = ref();
- const stopThumbRef = ref();
- const inputRef = ref();
- const {
- rtlClasses
- } = useRtl();
- function getActiveThumb(e) {
- if (!startThumbRef.value || !stopThumbRef.value) return;
- const startOffset = getOffset(e, startThumbRef.value.$el, props.direction);
- const stopOffset = getOffset(e, stopThumbRef.value.$el, props.direction);
- const a = Math.abs(startOffset);
- const b = Math.abs(stopOffset);
- return a < b || a === b && startOffset < 0 ? startThumbRef.value.$el : stopThumbRef.value.$el;
- }
- const steps = useSteps(props);
- const model = useProxiedModel(props, 'modelValue', undefined, arr => {
- if (!arr?.length) return [0, 0];
- return arr.map(value => steps.roundValue(value));
- });
- const {
- activeThumbRef,
- hasLabels,
- max,
- min,
- mousePressed,
- onSliderMousedown,
- onSliderTouchstart,
- position,
- trackContainerRef
- } = useSlider({
- props,
- steps,
- onSliderStart: () => {
- emit('start', model.value);
- },
- onSliderEnd: _ref2 => {
- let {
- value
- } = _ref2;
- const newValue = activeThumbRef.value === startThumbRef.value?.$el ? [value, model.value[1]] : [model.value[0], value];
- if (!props.strict && newValue[0] < newValue[1]) {
- model.value = newValue;
- }
- emit('end', model.value);
- },
- onSliderMove: _ref3 => {
- let {
- value
- } = _ref3;
- const [start, stop] = model.value;
- if (!props.strict && start === stop && start !== min.value) {
- activeThumbRef.value = value > start ? stopThumbRef.value?.$el : startThumbRef.value?.$el;
- activeThumbRef.value?.focus();
- }
- if (activeThumbRef.value === startThumbRef.value?.$el) {
- model.value = [Math.min(value, stop), stop];
- } else {
- model.value = [start, Math.max(start, value)];
- }
- },
- getActiveThumb
- });
- const {
- isFocused,
- focus,
- blur
- } = useFocus(props);
- const trackStart = computed(() => position(model.value[0]));
- const trackStop = computed(() => position(model.value[1]));
- useRender(() => {
- const [inputProps, _] = VInput.filterProps(props);
- const hasPrepend = !!(props.label || slots.label || slots.prepend);
- return createVNode(VInput, mergeProps({
- "class": ['v-slider', 'v-range-slider', {
- 'v-slider--has-labels': !!slots['tick-label'] || hasLabels.value,
- 'v-slider--focused': isFocused.value,
- 'v-slider--pressed': mousePressed.value,
- 'v-slider--disabled': props.disabled
- }, rtlClasses.value, props.class],
- "style": props.style,
- "ref": inputRef
- }, inputProps, {
- "focused": isFocused.value
- }), {
- ...slots,
- prepend: hasPrepend ? slotProps => createVNode(Fragment, null, [slots.label?.(slotProps) ?? props.label ? createVNode(VLabel, {
- "class": "v-slider__label",
- "text": props.label
- }, null) : undefined, slots.prepend?.(slotProps)]) : undefined,
- default: _ref4 => {
- let {
- id,
- messagesId
- } = _ref4;
- return createVNode("div", {
- "class": "v-slider__container",
- "onMousedown": onSliderMousedown,
- "onTouchstartPassive": onSliderTouchstart
- }, [createVNode("input", {
- "id": `${id.value}_start`,
- "name": props.name || id.value,
- "disabled": !!props.disabled,
- "readonly": !!props.readonly,
- "tabindex": "-1",
- "value": model.value[0]
- }, null), createVNode("input", {
- "id": `${id.value}_stop`,
- "name": props.name || id.value,
- "disabled": !!props.disabled,
- "readonly": !!props.readonly,
- "tabindex": "-1",
- "value": model.value[1]
- }, null), createVNode(VSliderTrack, {
- "ref": trackContainerRef,
- "start": trackStart.value,
- "stop": trackStop.value
- }, {
- 'tick-label': slots['tick-label']
- }), createVNode(VSliderThumb, {
- "ref": startThumbRef,
- "aria-describedby": messagesId.value,
- "focused": isFocused && activeThumbRef.value === startThumbRef.value?.$el,
- "modelValue": model.value[0],
- "onUpdate:modelValue": v => model.value = [v, model.value[1]],
- "onFocus": e => {
- focus();
- activeThumbRef.value = startThumbRef.value?.$el;
- // Make sure second thumb is focused if
- // the thumbs are on top of each other
- // and they are both at minimum value
- // but only if focused from outside.
- if (model.value[0] === model.value[1] && model.value[1] === min.value && e.relatedTarget !== stopThumbRef.value?.$el) {
- startThumbRef.value?.$el.blur();
- stopThumbRef.value?.$el.focus();
- }
- },
- "onBlur": () => {
- blur();
- activeThumbRef.value = undefined;
- },
- "min": min.value,
- "max": model.value[1],
- "position": trackStart.value
- }, {
- 'thumb-label': slots['thumb-label']
- }), createVNode(VSliderThumb, {
- "ref": stopThumbRef,
- "aria-describedby": messagesId.value,
- "focused": isFocused && activeThumbRef.value === stopThumbRef.value?.$el,
- "modelValue": model.value[1],
- "onUpdate:modelValue": v => model.value = [model.value[0], v],
- "onFocus": e => {
- focus();
- activeThumbRef.value = stopThumbRef.value?.$el;
- // Make sure first thumb is focused if
- // the thumbs are on top of each other
- // and they are both at maximum value
- // but only if focused from outside.
- if (model.value[0] === model.value[1] && model.value[0] === max.value && e.relatedTarget !== startThumbRef.value?.$el) {
- stopThumbRef.value?.$el.blur();
- startThumbRef.value?.$el.focus();
- }
- },
- "onBlur": () => {
- blur();
- activeThumbRef.value = undefined;
- },
- "min": model.value[0],
- "max": max.value,
- "position": trackStop.value
- }, {
- 'thumb-label': slots['thumb-label']
- })]);
- }
- });
- });
- return {};
- }
- });
- // Types
- const makeVRatingProps = propsFactory({
- name: String,
- itemAriaLabel: {
- type: String,
- default: '$vuetify.rating.ariaLabel.item'
- },
- activeColor: String,
- color: String,
- clearable: Boolean,
- disabled: Boolean,
- emptyIcon: {
- type: IconValue,
- default: '$ratingEmpty'
- },
- fullIcon: {
- type: IconValue,
- default: '$ratingFull'
- },
- halfIncrements: Boolean,
- hover: Boolean,
- length: {
- type: [Number, String],
- default: 5
- },
- readonly: Boolean,
- modelValue: {
- type: [Number, String],
- default: 0
- },
- itemLabels: Array,
- itemLabelPosition: {
- type: String,
- default: 'top',
- validator: v => ['top', 'bottom'].includes(v)
- },
- ripple: Boolean,
- ...makeComponentProps(),
- ...makeDensityProps(),
- ...makeSizeProps(),
- ...makeTagProps(),
- ...makeThemeProps()
- }, 'VRating');
- const VRating = genericComponent()({
- name: 'VRating',
- props: makeVRatingProps(),
- emits: {
- 'update:modelValue': value => true
- },
- setup(props, _ref) {
- let {
- slots
- } = _ref;
- const {
- t
- } = useLocale();
- const {
- themeClasses
- } = provideTheme(props);
- const rating = useProxiedModel(props, 'modelValue');
- const normalizedValue = computed(() => clamp(parseFloat(rating.value), 0, +props.length));
- const range = computed(() => createRange(Number(props.length), 1));
- const increments = computed(() => range.value.flatMap(v => props.halfIncrements ? [v - 0.5, v] : [v]));
- const hoverIndex = shallowRef(-1);
- const itemState = computed(() => increments.value.map(value => {
- const isHovering = props.hover && hoverIndex.value > -1;
- const isFilled = normalizedValue.value >= value;
- const isHovered = hoverIndex.value >= value;
- const isFullIcon = isHovering ? isHovered : isFilled;
- const icon = isFullIcon ? props.fullIcon : props.emptyIcon;
- const activeColor = props.activeColor ?? props.color;
- const color = isFilled || isHovered ? activeColor : props.color;
- return {
- isFilled,
- isHovered,
- icon,
- color
- };
- }));
- const eventState = computed(() => [0, ...increments.value].map(value => {
- function onMouseenter() {
- hoverIndex.value = value;
- }
- function onMouseleave() {
- hoverIndex.value = -1;
- }
- function onClick() {
- if (props.disabled || props.readonly) return;
- rating.value = normalizedValue.value === value && props.clearable ? 0 : value;
- }
- return {
- onMouseenter: props.hover ? onMouseenter : undefined,
- onMouseleave: props.hover ? onMouseleave : undefined,
- onClick
- };
- }));
- const name = computed(() => props.name ?? `v-rating-${getUid()}`);
- function VRatingItem(_ref2) {
- let {
- value,
- index,
- showStar = true
- } = _ref2;
- const {
- onMouseenter,
- onMouseleave,
- onClick
- } = eventState.value[index + 1];
- const id = `${name.value}-${String(value).replace('.', '-')}`;
- const btnProps = {
- color: itemState.value[index]?.color,
- density: props.density,
- disabled: props.disabled,
- icon: itemState.value[index]?.icon,
- ripple: props.ripple,
- size: props.size,
- variant: 'plain'
- };
- return createVNode(Fragment, null, [createVNode("label", {
- "for": id,
- "class": {
- 'v-rating__item--half': props.halfIncrements && value % 1 > 0,
- 'v-rating__item--full': props.halfIncrements && value % 1 === 0
- },
- "onMouseenter": onMouseenter,
- "onMouseleave": onMouseleave,
- "onClick": onClick
- }, [createVNode("span", {
- "class": "v-rating__hidden"
- }, [t(props.itemAriaLabel, value, props.length)]), !showStar ? undefined : slots.item ? slots.item({
- ...itemState.value[index],
- props: btnProps,
- value,
- index,
- rating: normalizedValue.value
- }) : createVNode(VBtn, mergeProps({
- "aria-label": t(props.itemAriaLabel, value, props.length)
- }, btnProps), null)]), createVNode("input", {
- "class": "v-rating__hidden",
- "name": name.value,
- "id": id,
- "type": "radio",
- "value": value,
- "checked": normalizedValue.value === value,
- "tabindex": -1,
- "readonly": props.readonly,
- "disabled": props.disabled
- }, null)]);
- }
- function createLabel(labelProps) {
- if (slots['item-label']) return slots['item-label'](labelProps);
- if (labelProps.label) return createVNode("span", null, [labelProps.label]);
- return createVNode("span", null, [createTextVNode("\xA0")]);
- }
- useRender(() => {
- const hasLabels = !!props.itemLabels?.length || slots['item-label'];
- return createVNode(props.tag, {
- "class": ['v-rating', {
- 'v-rating--hover': props.hover,
- 'v-rating--readonly': props.readonly
- }, themeClasses.value, props.class],
- "style": props.style
- }, {
- default: () => [createVNode(VRatingItem, {
- "value": 0,
- "index": -1,
- "showStar": false
- }, null), range.value.map((value, i) => createVNode("div", {
- "class": "v-rating__wrapper"
- }, [hasLabels && props.itemLabelPosition === 'top' ? createLabel({
- value,
- index: i,
- label: props.itemLabels?.[i]
- }) : undefined, createVNode("div", {
- "class": "v-rating__item"
- }, [props.halfIncrements ? createVNode(Fragment, null, [createVNode(VRatingItem, {
- "value": value - 0.5,
- "index": i * 2
- }, null), createVNode(VRatingItem, {
- "value": value,
- "index": i * 2 + 1
- }, null)]) : createVNode(VRatingItem, {
- "value": value,
- "index": i
- }, null)]), hasLabels && props.itemLabelPosition === 'bottom' ? createLabel({
- value,
- index: i,
- label: props.itemLabels?.[i]
- }) : undefined]))]
- });
- });
- return {};
- }
- });
- function bias(val) {
- const c = 0.501;
- const x = Math.abs(val);
- return Math.sign(val) * (x / ((1 / c - 2) * (1 - x) + 1));
- }
- function calculateUpdatedOffset(_ref) {
- let {
- selectedElement,
- containerSize,
- contentSize,
- isRtl,
- currentScrollOffset,
- isHorizontal
- } = _ref;
- const clientSize = isHorizontal ? selectedElement.clientWidth : selectedElement.clientHeight;
- const offsetStart = isHorizontal ? selectedElement.offsetLeft : selectedElement.offsetTop;
- const adjustedOffsetStart = isRtl && isHorizontal ? contentSize - offsetStart - clientSize : offsetStart;
- const totalSize = containerSize + currentScrollOffset;
- const itemOffset = clientSize + adjustedOffsetStart;
- const additionalOffset = clientSize * 0.4;
- if (adjustedOffsetStart <= currentScrollOffset) {
- currentScrollOffset = Math.max(adjustedOffsetStart - additionalOffset, 0);
- } else if (totalSize <= itemOffset) {
- currentScrollOffset = Math.min(currentScrollOffset - (totalSize - itemOffset - additionalOffset), contentSize - containerSize);
- }
- return currentScrollOffset;
- }
- function calculateCenteredOffset(_ref2) {
- let {
- selectedElement,
- containerSize,
- contentSize,
- isRtl,
- isHorizontal
- } = _ref2;
- const clientSize = isHorizontal ? selectedElement.clientWidth : selectedElement.clientHeight;
- const offsetStart = isHorizontal ? selectedElement.offsetLeft : selectedElement.offsetTop;
- const offsetCentered = isRtl && isHorizontal ? contentSize - offsetStart - clientSize / 2 - containerSize / 2 : offsetStart + clientSize / 2 - containerSize / 2;
- return Math.min(contentSize - containerSize, Math.max(0, offsetCentered));
- }
- // Types
- const VSlideGroupSymbol = Symbol.for('vuetify:v-slide-group');
- const makeVSlideGroupProps = propsFactory({
- centerActive: Boolean,
- direction: {
- type: String,
- default: 'horizontal'
- },
- symbol: {
- type: null,
- default: VSlideGroupSymbol
- },
- nextIcon: {
- type: IconValue,
- default: '$next'
- },
- prevIcon: {
- type: IconValue,
- default: '$prev'
- },
- showArrows: {
- type: [Boolean, String],
- validator: v => typeof v === 'boolean' || ['always', 'desktop', 'mobile'].includes(v)
- },
- ...makeComponentProps(),
- ...makeTagProps(),
- ...makeGroupProps({
- selectedClass: 'v-slide-group-item--active'
- })
- }, 'VSlideGroup');
- const VSlideGroup = genericComponent()({
- name: 'VSlideGroup',
- props: makeVSlideGroupProps(),
- emits: {
- 'update:modelValue': value => true
- },
- setup(props, _ref) {
- let {
- slots
- } = _ref;
- const {
- isRtl
- } = useRtl();
- const {
- mobile
- } = useDisplay();
- const group = useGroup(props, props.symbol);
- const isOverflowing = shallowRef(false);
- const scrollOffset = shallowRef(0);
- const containerSize = shallowRef(0);
- const contentSize = shallowRef(0);
- const isHorizontal = computed(() => props.direction === 'horizontal');
- const {
- resizeRef: containerRef,
- contentRect: containerRect
- } = useResizeObserver();
- const {
- resizeRef: contentRef,
- contentRect
- } = useResizeObserver();
- const firstSelectedIndex = computed(() => {
- if (!group.selected.value.length) return -1;
- return group.items.value.findIndex(item => item.id === group.selected.value[0]);
- });
- const lastSelectedIndex = computed(() => {
- if (!group.selected.value.length) return -1;
- return group.items.value.findIndex(item => item.id === group.selected.value[group.selected.value.length - 1]);
- });
- if (IN_BROWSER) {
- let frame = -1;
- watch(() => [group.selected.value, containerRect.value, contentRect.value, isHorizontal.value], () => {
- cancelAnimationFrame(frame);
- frame = requestAnimationFrame(() => {
- if (containerRect.value && contentRect.value) {
- const sizeProperty = isHorizontal.value ? 'width' : 'height';
- containerSize.value = containerRect.value[sizeProperty];
- contentSize.value = contentRect.value[sizeProperty];
- isOverflowing.value = containerSize.value + 1 < contentSize.value;
- }
- if (firstSelectedIndex.value >= 0 && contentRef.value) {
- // TODO: Is this too naive? Should we store element references in group composable?
- const selectedElement = contentRef.value.children[lastSelectedIndex.value];
- if (firstSelectedIndex.value === 0 || !isOverflowing.value) {
- scrollOffset.value = 0;
- } else if (props.centerActive) {
- scrollOffset.value = calculateCenteredOffset({
- selectedElement,
- containerSize: containerSize.value,
- contentSize: contentSize.value,
- isRtl: isRtl.value,
- isHorizontal: isHorizontal.value
- });
- } else if (isOverflowing.value) {
- scrollOffset.value = calculateUpdatedOffset({
- selectedElement,
- containerSize: containerSize.value,
- contentSize: contentSize.value,
- isRtl: isRtl.value,
- currentScrollOffset: scrollOffset.value,
- isHorizontal: isHorizontal.value
- });
- }
- }
- });
- });
- }
- const disableTransition = shallowRef(false);
- let startTouch = 0;
- let startOffset = 0;
- function onTouchstart(e) {
- const sizeProperty = isHorizontal.value ? 'clientX' : 'clientY';
- const sign = isRtl.value && isHorizontal.value ? -1 : 1;
- startOffset = sign * scrollOffset.value;
- startTouch = e.touches[0][sizeProperty];
- disableTransition.value = true;
- }
- function onTouchmove(e) {
- if (!isOverflowing.value) return;
- const sizeProperty = isHorizontal.value ? 'clientX' : 'clientY';
- const sign = isRtl.value && isHorizontal.value ? -1 : 1;
- scrollOffset.value = sign * (startOffset + startTouch - e.touches[0][sizeProperty]);
- }
- function onTouchend(e) {
- const maxScrollOffset = contentSize.value - containerSize.value;
- if (scrollOffset.value < 0 || !isOverflowing.value) {
- scrollOffset.value = 0;
- } else if (scrollOffset.value >= maxScrollOffset) {
- scrollOffset.value = maxScrollOffset;
- }
- disableTransition.value = false;
- }
- function onScroll() {
- if (!containerRef.value) return;
- containerRef.value[isHorizontal.value ? 'scrollLeft' : 'scrollTop'] = 0;
- }
- const isFocused = shallowRef(false);
- function onFocusin(e) {
- isFocused.value = true;
- if (!isOverflowing.value || !contentRef.value) return;
- // Focused element is likely to be the root of an item, so a
- // breadth-first search will probably find it in the first iteration
- for (const el of e.composedPath()) {
- for (const item of contentRef.value.children) {
- if (item === el) {
- scrollOffset.value = calculateUpdatedOffset({
- selectedElement: item,
- containerSize: containerSize.value,
- contentSize: contentSize.value,
- isRtl: isRtl.value,
- currentScrollOffset: scrollOffset.value,
- isHorizontal: isHorizontal.value
- });
- return;
- }
- }
- }
- }
- function onFocusout(e) {
- isFocused.value = false;
- }
- function onFocus(e) {
- if (!isFocused.value && !(e.relatedTarget && contentRef.value?.contains(e.relatedTarget))) focus();
- }
- function onKeydown(e) {
- if (!contentRef.value) return;
- if (isHorizontal.value) {
- if (e.key === 'ArrowRight') {
- focus(isRtl.value ? 'prev' : 'next');
- } else if (e.key === 'ArrowLeft') {
- focus(isRtl.value ? 'next' : 'prev');
- }
- } else {
- if (e.key === 'ArrowDown') {
- focus('next');
- } else if (e.key === 'ArrowUp') {
- focus('prev');
- }
- }
- if (e.key === 'Home') {
- focus('first');
- } else if (e.key === 'End') {
- focus('last');
- }
- }
- function focus(location) {
- if (!contentRef.value) return;
- if (!location) {
- const focusable = focusableChildren(contentRef.value);
- focusable[0]?.focus();
- } else if (location === 'next') {
- const el = contentRef.value.querySelector(':focus')?.nextElementSibling;
- if (el) el.focus();else focus('first');
- } else if (location === 'prev') {
- const el = contentRef.value.querySelector(':focus')?.previousElementSibling;
- if (el) el.focus();else focus('last');
- } else if (location === 'first') {
- contentRef.value.firstElementChild?.focus();
- } else if (location === 'last') {
- contentRef.value.lastElementChild?.focus();
- }
- }
- function scrollTo(location) {
- const newAbsoluteOffset = scrollOffset.value + (location === 'prev' ? -1 : 1) * containerSize.value;
- scrollOffset.value = clamp(newAbsoluteOffset, 0, contentSize.value - containerSize.value);
- }
- const contentStyles = computed(() => {
- // This adds friction when scrolling the 'wrong' way when at max offset
- let scrollAmount = scrollOffset.value > contentSize.value - containerSize.value ? -(contentSize.value - containerSize.value) + bias(contentSize.value - containerSize.value - scrollOffset.value) : -scrollOffset.value;
- // This adds friction when scrolling the 'wrong' way when at min offset
- if (scrollOffset.value <= 0) {
- scrollAmount = bias(-scrollOffset.value);
- }
- const sign = isRtl.value && isHorizontal.value ? -1 : 1;
- return {
- transform: `translate${isHorizontal.value ? 'X' : 'Y'}(${sign * scrollAmount}px)`,
- transition: disableTransition.value ? 'none' : '',
- willChange: disableTransition.value ? 'transform' : ''
- };
- });
- const slotProps = computed(() => ({
- next: group.next,
- prev: group.prev,
- select: group.select,
- isSelected: group.isSelected
- }));
- const hasAffixes = computed(() => {
- switch (props.showArrows) {
- // Always show arrows on desktop & mobile
- case 'always':
- return true;
- // Always show arrows on desktop
- case 'desktop':
- return !mobile.value;
- // Show arrows on mobile when overflowing.
- // This matches the default 2.2 behavior
- case true:
- return isOverflowing.value || Math.abs(scrollOffset.value) > 0;
- // Always show on mobile
- case 'mobile':
- return mobile.value || isOverflowing.value || Math.abs(scrollOffset.value) > 0;
- // https://material.io/components/tabs#scrollable-tabs
- // Always show arrows when
- // overflowed on desktop
- default:
- return !mobile.value && (isOverflowing.value || Math.abs(scrollOffset.value) > 0);
- }
- });
- const hasPrev = computed(() => {
- return Math.abs(scrollOffset.value) > 0;
- });
- const hasNext = computed(() => {
- // Check one scroll ahead to know the width of right-most item
- return contentSize.value > Math.abs(scrollOffset.value) + containerSize.value;
- });
- useRender(() => createVNode(props.tag, {
- "class": ['v-slide-group', {
- 'v-slide-group--vertical': !isHorizontal.value,
- 'v-slide-group--has-affixes': hasAffixes.value,
- 'v-slide-group--is-overflowing': isOverflowing.value
- }, props.class],
- "style": props.style,
- "tabindex": isFocused.value || group.selected.value.length ? -1 : 0,
- "onFocus": onFocus
- }, {
- default: () => [hasAffixes.value && createVNode("div", {
- "key": "prev",
- "class": ['v-slide-group__prev', {
- 'v-slide-group__prev--disabled': !hasPrev.value
- }],
- "onClick": () => scrollTo('prev')
- }, [slots.prev?.(slotProps.value) ?? createVNode(VFadeTransition, null, {
- default: () => [createVNode(VIcon, {
- "icon": isRtl.value ? props.nextIcon : props.prevIcon
- }, null)]
- })]), createVNode("div", {
- "key": "container",
- "ref": containerRef,
- "class": "v-slide-group__container",
- "onScroll": onScroll
- }, [createVNode("div", {
- "ref": contentRef,
- "class": "v-slide-group__content",
- "style": contentStyles.value,
- "onTouchstartPassive": onTouchstart,
- "onTouchmovePassive": onTouchmove,
- "onTouchendPassive": onTouchend,
- "onFocusin": onFocusin,
- "onFocusout": onFocusout,
- "onKeydown": onKeydown
- }, [slots.default?.(slotProps.value)])]), hasAffixes.value && createVNode("div", {
- "key": "next",
- "class": ['v-slide-group__next', {
- 'v-slide-group__next--disabled': !hasNext.value
- }],
- "onClick": () => scrollTo('next')
- }, [slots.next?.(slotProps.value) ?? createVNode(VFadeTransition, null, {
- default: () => [createVNode(VIcon, {
- "icon": isRtl.value ? props.prevIcon : props.nextIcon
- }, null)]
- })])]
- }));
- return {
- selected: group.selected,
- scrollTo,
- scrollOffset,
- focus
- };
- }
- });
- // Composables
- // Types
- const VSlideGroupItem = genericComponent()({
- name: 'VSlideGroupItem',
- props: makeGroupItemProps(),
- emits: {
- 'group:selected': val => true
- },
- setup(props, _ref) {
- let {
- slots
- } = _ref;
- const slideGroupItem = useGroupItem(props, VSlideGroupSymbol);
- return () => slots.default?.({
- isSelected: slideGroupItem.isSelected.value,
- select: slideGroupItem.select,
- toggle: slideGroupItem.toggle,
- selectedClass: slideGroupItem.selectedClass.value
- });
- }
- });
- const makeVSnackbarProps = propsFactory({
- multiLine: Boolean,
- timeout: {
- type: [Number, String],
- default: 5000
- },
- vertical: Boolean,
- ...makeLocationProps({
- location: 'bottom'
- }),
- ...makePositionProps(),
- ...makeRoundedProps(),
- ...makeVariantProps(),
- ...makeThemeProps(),
- ...omit(makeVOverlayProps({
- transition: 'v-snackbar-transition'
- }), ['persistent', 'noClickAnimation', 'scrim', 'scrollStrategy'])
- }, 'VSnackbar');
- const VSnackbar = genericComponent()({
- name: 'VSnackbar',
- props: makeVSnackbarProps(),
- emits: {
- 'update:modelValue': v => true
- },
- setup(props, _ref) {
- let {
- slots
- } = _ref;
- const isActive = useProxiedModel(props, 'modelValue');
- const {
- locationStyles
- } = useLocation(props);
- const {
- positionClasses
- } = usePosition(props);
- const {
- scopeId
- } = useScopeId();
- const {
- themeClasses
- } = provideTheme(props);
- const {
- colorClasses,
- colorStyles,
- variantClasses
- } = useVariant(props);
- const {
- roundedClasses
- } = useRounded(props);
- const overlay = ref();
- watch(isActive, startTimeout);
- watch(() => props.timeout, startTimeout);
- onMounted(() => {
- if (isActive.value) startTimeout();
- });
- let activeTimeout = -1;
- function startTimeout() {
- window.clearTimeout(activeTimeout);
- const timeout = Number(props.timeout);
- if (!isActive.value || timeout === -1) return;
- activeTimeout = window.setTimeout(() => {
- isActive.value = false;
- }, timeout);
- }
- function onPointerenter() {
- window.clearTimeout(activeTimeout);
- }
- useRender(() => {
- const [overlayProps] = VOverlay.filterProps(props);
- return createVNode(VOverlay, mergeProps({
- "ref": overlay,
- "class": ['v-snackbar', {
- 'v-snackbar--active': isActive.value,
- 'v-snackbar--multi-line': props.multiLine && !props.vertical,
- 'v-snackbar--vertical': props.vertical
- }, positionClasses.value, props.class],
- "style": props.style
- }, overlayProps, {
- "modelValue": isActive.value,
- "onUpdate:modelValue": $event => isActive.value = $event,
- "contentProps": mergeProps({
- class: ['v-snackbar__wrapper', themeClasses.value, colorClasses.value, roundedClasses.value, variantClasses.value],
- style: [locationStyles.value, colorStyles.value],
- onPointerenter,
- onPointerleave: startTimeout
- }, overlayProps.contentProps),
- "persistent": true,
- "noClickAnimation": true,
- "scrim": false,
- "scrollStrategy": "none",
- "_disableGlobalStack": true
- }, scopeId), {
- default: () => [genOverlays(false, 'v-snackbar'), slots.default && createVNode("div", {
- "class": "v-snackbar__content",
- "role": "status",
- "aria-live": "polite"
- }, [slots.default()]), slots.actions && createVNode(VDefaultsProvider, {
- "defaults": {
- VBtn: {
- variant: 'text',
- ripple: false
- }
- }
- }, {
- default: () => [createVNode("div", {
- "class": "v-snackbar__actions"
- }, [slots.actions()])]
- })],
- activator: slots.activator
- });
- });
- return forwardRefs({}, overlay);
- }
- });
- // Types
- const makeVSwitchProps = propsFactory({
- indeterminate: Boolean,
- inset: Boolean,
- flat: Boolean,
- loading: {
- type: [Boolean, String],
- default: false
- },
- ...makeVInputProps(),
- ...makeVSelectionControlProps()
- }, 'VSwitch');
- const VSwitch = genericComponent()({
- name: 'VSwitch',
- inheritAttrs: false,
- props: makeVSwitchProps(),
- emits: {
- 'update:focused': focused => true,
- 'update:modelValue': () => true,
- 'update:indeterminate': val => true
- },
- setup(props, _ref) {
- let {
- attrs,
- slots
- } = _ref;
- const indeterminate = useProxiedModel(props, 'indeterminate');
- const model = useProxiedModel(props, 'modelValue');
- const {
- loaderClasses
- } = useLoader(props);
- const {
- isFocused,
- focus,
- blur
- } = useFocus(props);
- const loaderColor = computed(() => {
- return typeof props.loading === 'string' && props.loading !== '' ? props.loading : props.color;
- });
- const uid = getUid();
- const id = computed(() => props.id || `switch-${uid}`);
- function onChange() {
- if (indeterminate.value) {
- indeterminate.value = false;
- }
- }
- useRender(() => {
- const [inputAttrs, controlAttrs] = filterInputAttrs(attrs);
- const [inputProps, _1] = VInput.filterProps(props);
- const [controlProps, _2] = VSelectionControl.filterProps(props);
- const control = ref();
- function onClick(e) {
- e.stopPropagation();
- e.preventDefault();
- control.value?.input?.click();
- }
- return createVNode(VInput, mergeProps({
- "class": ['v-switch', {
- 'v-switch--inset': props.inset
- }, {
- 'v-switch--indeterminate': indeterminate.value
- }, loaderClasses.value, props.class],
- "style": props.style
- }, inputAttrs, inputProps, {
- "id": id.value,
- "focused": isFocused.value
- }), {
- ...slots,
- default: _ref2 => {
- let {
- id,
- messagesId,
- isDisabled,
- isReadonly,
- isValid
- } = _ref2;
- return createVNode(VSelectionControl, mergeProps({
- "ref": control
- }, controlProps, {
- "modelValue": model.value,
- "onUpdate:modelValue": [$event => model.value = $event, onChange],
- "id": id.value,
- "aria-describedby": messagesId.value,
- "type": "checkbox",
- "aria-checked": indeterminate.value ? 'mixed' : undefined,
- "disabled": isDisabled.value,
- "readonly": isReadonly.value,
- "onFocus": focus,
- "onBlur": blur
- }, controlAttrs), {
- ...slots,
- default: () => createVNode("div", {
- "class": "v-switch__track",
- "onClick": onClick
- }, null),
- input: _ref3 => {
- let {
- textColorClasses,
- textColorStyles
- } = _ref3;
- return createVNode("div", {
- "class": ['v-switch__thumb', textColorClasses.value],
- "style": textColorStyles.value
- }, [props.loading && createVNode(LoaderSlot, {
- "name": "v-switch",
- "active": true,
- "color": isValid.value === false ? undefined : loaderColor.value
- }, {
- default: slotProps => slots.loader ? slots.loader(slotProps) : createVNode(VProgressCircular, {
- "active": slotProps.isActive,
- "color": slotProps.color,
- "indeterminate": true,
- "size": "16",
- "width": "2"
- }, null)
- })]);
- }
- });
- }
- });
- });
- return {};
- }
- });
- const makeVSystemBarProps = propsFactory({
- color: String,
- height: [Number, String],
- window: Boolean,
- ...makeComponentProps(),
- ...makeElevationProps(),
- ...makeLayoutItemProps(),
- ...makeRoundedProps(),
- ...makeTagProps(),
- ...makeThemeProps()
- }, 'VSystemBar');
- const VSystemBar = genericComponent()({
- name: 'VSystemBar',
- props: makeVSystemBarProps(),
- setup(props, _ref) {
- let {
- slots
- } = _ref;
- const {
- themeClasses
- } = provideTheme(props);
- const {
- backgroundColorClasses,
- backgroundColorStyles
- } = useBackgroundColor(toRef(props, 'color'));
- const {
- elevationClasses
- } = useElevation(props);
- const {
- roundedClasses
- } = useRounded(props);
- const {
- ssrBootStyles
- } = useSsrBoot();
- const height = computed(() => props.height ?? (props.window ? 32 : 24));
- const {
- layoutItemStyles
- } = useLayoutItem({
- id: props.name,
- order: computed(() => parseInt(props.order, 10)),
- position: shallowRef('top'),
- layoutSize: height,
- elementSize: height,
- active: computed(() => true),
- absolute: toRef(props, 'absolute')
- });
- useRender(() => createVNode(props.tag, {
- "class": ['v-system-bar', {
- 'v-system-bar--window': props.window
- }, themeClasses.value, backgroundColorClasses.value, elevationClasses.value, roundedClasses.value, props.class],
- "style": [backgroundColorStyles.value, layoutItemStyles.value, ssrBootStyles.value, props.style]
- }, slots));
- return {};
- }
- });
- // Types
- const VTabsSymbol = Symbol.for('vuetify:v-tabs');
- // Types
- const makeVTabProps = propsFactory({
- fixed: Boolean,
- sliderColor: String,
- hideSlider: Boolean,
- direction: {
- type: String,
- default: 'horizontal'
- },
- ...omit(makeVBtnProps({
- selectedClass: 'v-tab--selected',
- variant: 'text'
- }), ['active', 'block', 'flat', 'location', 'position', 'symbol'])
- }, 'VTab');
- const VTab = genericComponent()({
- name: 'VTab',
- props: makeVTabProps(),
- setup(props, _ref) {
- let {
- slots,
- attrs
- } = _ref;
- const {
- textColorClasses: sliderColorClasses,
- textColorStyles: sliderColorStyles
- } = useTextColor(props, 'sliderColor');
- const isHorizontal = computed(() => props.direction === 'horizontal');
- const isSelected = shallowRef(false);
- const rootEl = ref();
- const sliderEl = ref();
- function updateSlider(_ref2) {
- let {
- value
- } = _ref2;
- isSelected.value = value;
- if (value) {
- const prevEl = rootEl.value?.$el.parentElement?.querySelector('.v-tab--selected .v-tab__slider');
- const nextEl = sliderEl.value;
- if (!prevEl || !nextEl) return;
- const color = getComputedStyle(prevEl).color;
- const prevBox = prevEl.getBoundingClientRect();
- const nextBox = nextEl.getBoundingClientRect();
- const xy = isHorizontal.value ? 'x' : 'y';
- const XY = isHorizontal.value ? 'X' : 'Y';
- const rightBottom = isHorizontal.value ? 'right' : 'bottom';
- const widthHeight = isHorizontal.value ? 'width' : 'height';
- const prevPos = prevBox[xy];
- const nextPos = nextBox[xy];
- const delta = prevPos > nextPos ? prevBox[rightBottom] - nextBox[rightBottom] : prevBox[xy] - nextBox[xy];
- const origin = Math.sign(delta) > 0 ? isHorizontal.value ? 'right' : 'bottom' : Math.sign(delta) < 0 ? isHorizontal.value ? 'left' : 'top' : 'center';
- const size = Math.abs(delta) + (Math.sign(delta) < 0 ? prevBox[widthHeight] : nextBox[widthHeight]);
- const scale = size / Math.max(prevBox[widthHeight], nextBox[widthHeight]);
- const initialScale = prevBox[widthHeight] / nextBox[widthHeight];
- const sigma = 1.5;
- animate(nextEl, {
- backgroundColor: [color, 'currentcolor'],
- transform: [`translate${XY}(${delta}px) scale${XY}(${initialScale})`, `translate${XY}(${delta / sigma}px) scale${XY}(${(scale - 1) / sigma + 1})`, 'none'],
- transformOrigin: Array(3).fill(origin)
- }, {
- duration: 225,
- easing: standardEasing
- });
- }
- }
- useRender(() => {
- const [btnProps] = VBtn.filterProps(props);
- return createVNode(VBtn, mergeProps({
- "symbol": VTabsSymbol,
- "ref": rootEl,
- "class": ['v-tab', props.class],
- "style": props.style,
- "tabindex": isSelected.value ? 0 : -1,
- "role": "tab",
- "aria-selected": String(isSelected.value),
- "active": false,
- "block": props.fixed,
- "maxWidth": props.fixed ? 300 : undefined,
- "rounded": 0
- }, btnProps, attrs, {
- "onGroup:selected": updateSlider
- }), {
- default: () => [slots.default?.() ?? props.text, !props.hideSlider && createVNode("div", {
- "ref": sliderEl,
- "class": ['v-tab__slider', sliderColorClasses.value],
- "style": sliderColorStyles.value
- }, null)]
- });
- });
- return {};
- }
- });
- function parseItems(items) {
- if (!items) return [];
- return items.map(item => {
- if (typeof item === 'string') return {
- title: item,
- value: item
- };
- return item;
- });
- }
- const makeVTabsProps = propsFactory({
- alignTabs: {
- type: String,
- default: 'start'
- },
- color: String,
- fixedTabs: Boolean,
- items: {
- type: Array,
- default: () => []
- },
- stacked: Boolean,
- bgColor: String,
- grow: Boolean,
- height: {
- type: [Number, String],
- default: undefined
- },
- hideSlider: Boolean,
- sliderColor: String,
- ...makeVSlideGroupProps({
- mandatory: 'force'
- }),
- ...makeDensityProps(),
- ...makeTagProps()
- }, 'VTabs');
- const VTabs = genericComponent()({
- name: 'VTabs',
- props: makeVTabsProps(),
- emits: {
- 'update:modelValue': v => true
- },
- setup(props, _ref) {
- let {
- slots
- } = _ref;
- const model = useProxiedModel(props, 'modelValue');
- const parsedItems = computed(() => parseItems(props.items));
- const {
- densityClasses
- } = useDensity(props);
- const {
- backgroundColorClasses,
- backgroundColorStyles
- } = useBackgroundColor(toRef(props, 'bgColor'));
- provideDefaults({
- VTab: {
- color: toRef(props, 'color'),
- direction: toRef(props, 'direction'),
- stacked: toRef(props, 'stacked'),
- fixed: toRef(props, 'fixedTabs'),
- sliderColor: toRef(props, 'sliderColor'),
- hideSlider: toRef(props, 'hideSlider')
- }
- });
- useRender(() => {
- const [slideGroupProps] = VSlideGroup.filterProps(props);
- return createVNode(VSlideGroup, mergeProps(slideGroupProps, {
- "modelValue": model.value,
- "onUpdate:modelValue": $event => model.value = $event,
- "class": ['v-tabs', `v-tabs--${props.direction}`, `v-tabs--align-tabs-${props.alignTabs}`, {
- 'v-tabs--fixed-tabs': props.fixedTabs,
- 'v-tabs--grow': props.grow,
- 'v-tabs--stacked': props.stacked
- }, densityClasses.value, backgroundColorClasses.value, props.class],
- "style": [{
- '--v-tabs-height': convertToUnit(props.height)
- }, backgroundColorStyles.value, props.style],
- "role": "tablist",
- "symbol": VTabsSymbol
- }), {
- default: () => [slots.default ? slots.default() : parsedItems.value.map(item => createVNode(VTab, mergeProps(item, {
- "key": item.title
- }), null))]
- });
- });
- return {};
- }
- });
- const makeVTableProps = propsFactory({
- fixedHeader: Boolean,
- fixedFooter: Boolean,
- height: [Number, String],
- hover: Boolean,
- ...makeComponentProps(),
- ...makeDensityProps(),
- ...makeTagProps(),
- ...makeThemeProps()
- }, 'VTable');
- const VTable = genericComponent()({
- name: 'VTable',
- props: makeVTableProps(),
- setup(props, _ref) {
- let {
- slots
- } = _ref;
- const {
- themeClasses
- } = provideTheme(props);
- const {
- densityClasses
- } = useDensity(props);
- useRender(() => createVNode(props.tag, {
- "class": ['v-table', {
- 'v-table--fixed-height': !!props.height,
- 'v-table--fixed-header': props.fixedHeader,
- 'v-table--fixed-footer': props.fixedFooter,
- 'v-table--has-top': !!slots.top,
- 'v-table--has-bottom': !!slots.bottom,
- 'v-table--hover': props.hover
- }, themeClasses.value, densityClasses.value, props.class],
- "style": props.style
- }, {
- default: () => [slots.top?.(), slots.default ? createVNode("div", {
- "class": "v-table__wrapper",
- "style": {
- height: convertToUnit(props.height)
- }
- }, [createVNode("table", null, [slots.default()])]) : slots.wrapper?.(), slots.bottom?.()]
- }));
- return {};
- }
- });
- // Types
- const makeVTextareaProps = propsFactory({
- autoGrow: Boolean,
- autofocus: Boolean,
- counter: [Boolean, Number, String],
- counterValue: Function,
- prefix: String,
- placeholder: String,
- persistentPlaceholder: Boolean,
- persistentCounter: Boolean,
- noResize: Boolean,
- rows: {
- type: [Number, String],
- default: 5,
- validator: v => !isNaN(parseFloat(v))
- },
- maxRows: {
- type: [Number, String],
- validator: v => !isNaN(parseFloat(v))
- },
- suffix: String,
- modelModifiers: Object,
- ...makeVInputProps(),
- ...makeVFieldProps()
- }, 'VTextarea');
- const VTextarea = genericComponent()({
- name: 'VTextarea',
- directives: {
- Intersect
- },
- inheritAttrs: false,
- props: makeVTextareaProps(),
- emits: {
- 'click:control': e => true,
- 'mousedown:control': e => true,
- 'update:focused': focused => true,
- 'update:modelValue': val => true
- },
- setup(props, _ref) {
- let {
- attrs,
- emit,
- slots
- } = _ref;
- const model = useProxiedModel(props, 'modelValue');
- const {
- isFocused,
- focus,
- blur
- } = useFocus(props);
- const counterValue = computed(() => {
- return typeof props.counterValue === 'function' ? props.counterValue(model.value) : (model.value || '').toString().length;
- });
- const max = computed(() => {
- if (attrs.maxlength) return attrs.maxlength;
- if (!props.counter || typeof props.counter !== 'number' && typeof props.counter !== 'string') return undefined;
- return props.counter;
- });
- function onIntersect(isIntersecting, entries) {
- if (!props.autofocus || !isIntersecting) return;
- entries[0].target?.focus?.();
- }
- const vInputRef = ref();
- const vFieldRef = ref();
- const controlHeight = shallowRef('');
- const textareaRef = ref();
- const isActive = computed(() => props.persistentPlaceholder || isFocused.value || props.active);
- function onFocus() {
- if (textareaRef.value !== document.activeElement) {
- textareaRef.value?.focus();
- }
- if (!isFocused.value) focus();
- }
- function onControlClick(e) {
- onFocus();
- emit('click:control', e);
- }
- function onControlMousedown(e) {
- emit('mousedown:control', e);
- }
- function onClear(e) {
- e.stopPropagation();
- onFocus();
- nextTick(() => {
- model.value = '';
- callEvent(props['onClick:clear'], e);
- });
- }
- function onInput(e) {
- const el = e.target;
- model.value = el.value;
- if (props.modelModifiers?.trim) {
- const caretPosition = [el.selectionStart, el.selectionEnd];
- nextTick(() => {
- el.selectionStart = caretPosition[0];
- el.selectionEnd = caretPosition[1];
- });
- }
- }
- const sizerRef = ref();
- const rows = ref(+props.rows);
- const isPlainOrUnderlined = computed(() => ['plain', 'underlined'].includes(props.variant));
- watchEffect(() => {
- if (!props.autoGrow) rows.value = +props.rows;
- });
- function calculateInputHeight() {
- if (!props.autoGrow) return;
- nextTick(() => {
- if (!sizerRef.value || !vFieldRef.value) return;
- const style = getComputedStyle(sizerRef.value);
- const fieldStyle = getComputedStyle(vFieldRef.value.$el);
- const padding = parseFloat(style.getPropertyValue('--v-field-padding-top')) + parseFloat(style.getPropertyValue('--v-input-padding-top')) + parseFloat(style.getPropertyValue('--v-field-padding-bottom'));
- const height = sizerRef.value.scrollHeight;
- const lineHeight = parseFloat(style.lineHeight);
- const minHeight = Math.max(parseFloat(props.rows) * lineHeight + padding, parseFloat(fieldStyle.getPropertyValue('--v-input-control-height')));
- const maxHeight = parseFloat(props.maxRows) * lineHeight + padding || Infinity;
- const newHeight = clamp(height ?? 0, minHeight, maxHeight);
- rows.value = Math.floor((newHeight - padding) / lineHeight);
- controlHeight.value = convertToUnit(newHeight);
- });
- }
- onMounted(calculateInputHeight);
- watch(model, calculateInputHeight);
- watch(() => props.rows, calculateInputHeight);
- watch(() => props.maxRows, calculateInputHeight);
- watch(() => props.density, calculateInputHeight);
- let observer;
- watch(sizerRef, val => {
- if (val) {
- observer = new ResizeObserver(calculateInputHeight);
- observer.observe(sizerRef.value);
- } else {
- observer?.disconnect();
- }
- });
- onBeforeUnmount(() => {
- observer?.disconnect();
- });
- useRender(() => {
- const hasCounter = !!(slots.counter || props.counter || props.counterValue);
- const hasDetails = !!(hasCounter || slots.details);
- const [rootAttrs, inputAttrs] = filterInputAttrs(attrs);
- const [{
- modelValue: _,
- ...inputProps
- }] = VInput.filterProps(props);
- const [fieldProps] = filterFieldProps(props);
- return createVNode(VInput, mergeProps({
- "ref": vInputRef,
- "modelValue": model.value,
- "onUpdate:modelValue": $event => model.value = $event,
- "class": ['v-textarea v-text-field', {
- 'v-textarea--prefixed': props.prefix,
- 'v-textarea--suffixed': props.suffix,
- 'v-text-field--prefixed': props.prefix,
- 'v-text-field--suffixed': props.suffix,
- 'v-textarea--auto-grow': props.autoGrow,
- 'v-textarea--no-resize': props.noResize || props.autoGrow,
- 'v-text-field--plain-underlined': isPlainOrUnderlined.value
- }, props.class],
- "style": props.style
- }, rootAttrs, inputProps, {
- "centerAffix": rows.value === 1 && !isPlainOrUnderlined.value,
- "focused": isFocused.value
- }), {
- ...slots,
- default: _ref2 => {
- let {
- isDisabled,
- isDirty,
- isReadonly,
- isValid
- } = _ref2;
- return createVNode(VField, mergeProps({
- "ref": vFieldRef,
- "style": {
- '--v-textarea-control-height': controlHeight.value
- },
- "onClick": onControlClick,
- "onMousedown": onControlMousedown,
- "onClick:clear": onClear,
- "onClick:prependInner": props['onClick:prependInner'],
- "onClick:appendInner": props['onClick:appendInner'],
- "role": "textbox"
- }, fieldProps, {
- "active": isActive.value || isDirty.value,
- "centerAffix": rows.value === 1 && !isPlainOrUnderlined.value,
- "dirty": isDirty.value || props.dirty,
- "disabled": isDisabled.value,
- "focused": isFocused.value,
- "error": isValid.value === false
- }), {
- ...slots,
- default: _ref3 => {
- let {
- props: {
- class: fieldClass,
- ...slotProps
- }
- } = _ref3;
- return createVNode(Fragment, null, [props.prefix && createVNode("span", {
- "class": "v-text-field__prefix"
- }, [props.prefix]), withDirectives(createVNode("textarea", mergeProps({
- "ref": textareaRef,
- "class": fieldClass,
- "value": model.value,
- "onInput": onInput,
- "autofocus": props.autofocus,
- "readonly": isReadonly.value,
- "disabled": isDisabled.value,
- "placeholder": props.placeholder,
- "rows": props.rows,
- "name": props.name,
- "onFocus": onFocus,
- "onBlur": blur
- }, slotProps, inputAttrs), null), [[resolveDirective("intersect"), {
- handler: onIntersect
- }, null, {
- once: true
- }]]), props.autoGrow && withDirectives(createVNode("textarea", {
- "class": [fieldClass, 'v-textarea__sizer'],
- "onUpdate:modelValue": $event => model.value = $event,
- "ref": sizerRef,
- "readonly": true,
- "aria-hidden": "true"
- }, null), [[vModelText, model.value]]), props.suffix && createVNode("span", {
- "class": "v-text-field__suffix"
- }, [props.suffix])]);
- }
- });
- },
- details: hasDetails ? slotProps => createVNode(Fragment, null, [slots.details?.(slotProps), hasCounter && createVNode(Fragment, null, [createVNode("span", null, null), createVNode(VCounter, {
- "active": props.persistentCounter || isFocused.value,
- "value": counterValue.value,
- "max": max.value
- }, slots.counter)])]) : undefined
- });
- });
- return forwardRefs({}, vInputRef, vFieldRef, textareaRef);
- }
- });
- const makeVThemeProviderProps = propsFactory({
- withBackground: Boolean,
- ...makeComponentProps(),
- ...makeThemeProps(),
- ...makeTagProps()
- }, 'VThemeProvider');
- const VThemeProvider = genericComponent()({
- name: 'VThemeProvider',
- props: makeVThemeProviderProps(),
- setup(props, _ref) {
- let {
- slots
- } = _ref;
- const {
- themeClasses
- } = provideTheme(props);
- return () => {
- if (!props.withBackground) return slots.default?.();
- return createVNode(props.tag, {
- "class": ['v-theme-provider', themeClasses.value, props.class],
- "style": props.style
- }, {
- default: () => [slots.default?.()]
- });
- };
- }
- });
- // Types
- const makeVTimelineProps = propsFactory({
- align: {
- type: String,
- default: 'center',
- validator: v => ['center', 'start'].includes(v)
- },
- direction: {
- type: String,
- default: 'vertical',
- validator: v => ['vertical', 'horizontal'].includes(v)
- },
- justify: {
- type: String,
- default: 'auto',
- validator: v => ['auto', 'center'].includes(v)
- },
- side: {
- type: String,
- validator: v => v == null || ['start', 'end'].includes(v)
- },
- lineInset: {
- type: [String, Number],
- default: 0
- },
- lineThickness: {
- type: [String, Number],
- default: 2
- },
- lineColor: String,
- truncateLine: {
- type: String,
- validator: v => ['start', 'end', 'both'].includes(v)
- },
- ...makeComponentProps(),
- ...makeDensityProps(),
- ...makeTagProps(),
- ...makeThemeProps()
- }, 'VTimeline');
- const VTimeline = genericComponent()({
- name: 'VTimeline',
- props: makeVTimelineProps(),
- setup(props, _ref) {
- let {
- slots
- } = _ref;
- const {
- themeClasses
- } = provideTheme(props);
- const {
- densityClasses
- } = useDensity(props);
- const {
- rtlClasses
- } = useRtl();
- provideDefaults({
- VTimelineDivider: {
- lineColor: toRef(props, 'lineColor')
- },
- VTimelineItem: {
- density: toRef(props, 'density'),
- lineInset: toRef(props, 'lineInset')
- }
- });
- const sideClasses = computed(() => {
- const side = props.side ? props.side : props.density !== 'default' ? 'end' : null;
- return side && `v-timeline--side-${side}`;
- });
- const truncateClasses = computed(() => {
- const classes = ['v-timeline--truncate-line-start', 'v-timeline--truncate-line-end'];
- switch (props.truncateLine) {
- case 'both':
- return classes;
- case 'start':
- return classes[0];
- case 'end':
- return classes[1];
- default:
- return null;
- }
- });
- useRender(() => createVNode(props.tag, {
- "class": ['v-timeline', `v-timeline--${props.direction}`, `v-timeline--align-${props.align}`, `v-timeline--justify-${props.justify}`, truncateClasses.value, {
- 'v-timeline--inset-line': !!props.lineInset
- }, themeClasses.value, densityClasses.value, sideClasses.value, rtlClasses.value, props.class],
- "style": [{
- '--v-timeline-line-thickness': convertToUnit(props.lineThickness)
- }, props.style]
- }, slots));
- return {};
- }
- });
- const makeVTimelineDividerProps = propsFactory({
- dotColor: String,
- fillDot: Boolean,
- hideDot: Boolean,
- icon: IconValue,
- iconColor: String,
- lineColor: String,
- ...makeComponentProps(),
- ...makeRoundedProps(),
- ...makeSizeProps(),
- ...makeElevationProps()
- }, 'VTimelineDivider');
- const VTimelineDivider = genericComponent()({
- name: 'VTimelineDivider',
- props: makeVTimelineDividerProps(),
- setup(props, _ref) {
- let {
- slots
- } = _ref;
- const {
- sizeClasses,
- sizeStyles
- } = useSize(props, 'v-timeline-divider__dot');
- const {
- backgroundColorStyles,
- backgroundColorClasses
- } = useBackgroundColor(toRef(props, 'dotColor'));
- const {
- roundedClasses
- } = useRounded(props, 'v-timeline-divider__dot');
- const {
- elevationClasses
- } = useElevation(props);
- const {
- backgroundColorClasses: lineColorClasses,
- backgroundColorStyles: lineColorStyles
- } = useBackgroundColor(toRef(props, 'lineColor'));
- useRender(() => createVNode("div", {
- "class": ['v-timeline-divider', {
- 'v-timeline-divider--fill-dot': props.fillDot
- }, props.class],
- "style": props.style
- }, [createVNode("div", {
- "class": ['v-timeline-divider__before', lineColorClasses.value],
- "style": lineColorStyles.value
- }, null), !props.hideDot && createVNode("div", {
- "key": "dot",
- "class": ['v-timeline-divider__dot', elevationClasses.value, roundedClasses.value, sizeClasses.value],
- "style": sizeStyles.value
- }, [createVNode("div", {
- "class": ['v-timeline-divider__inner-dot', backgroundColorClasses.value, roundedClasses.value],
- "style": backgroundColorStyles.value
- }, [!slots.default ? createVNode(VIcon, {
- "key": "icon",
- "color": props.iconColor,
- "icon": props.icon,
- "size": props.size
- }, null) : createVNode(VDefaultsProvider, {
- "key": "icon-defaults",
- "disabled": !props.icon,
- "defaults": {
- VIcon: {
- color: props.iconColor,
- icon: props.icon,
- size: props.size
- }
- }
- }, slots.default)])]), createVNode("div", {
- "class": ['v-timeline-divider__after', lineColorClasses.value],
- "style": lineColorStyles.value
- }, null)]));
- return {};
- }
- });
- // Types
- const makeVTimelineItemProps = propsFactory({
- density: String,
- dotColor: String,
- fillDot: Boolean,
- hideDot: Boolean,
- hideOpposite: {
- type: Boolean,
- default: undefined
- },
- icon: IconValue,
- iconColor: String,
- lineInset: [Number, String],
- ...makeComponentProps(),
- ...makeDimensionProps(),
- ...makeElevationProps(),
- ...makeRoundedProps(),
- ...makeSizeProps(),
- ...makeTagProps()
- }, 'VTimelineItem');
- const VTimelineItem = genericComponent()({
- name: 'VTimelineItem',
- props: makeVTimelineItemProps(),
- setup(props, _ref) {
- let {
- slots
- } = _ref;
- const {
- dimensionStyles
- } = useDimension(props);
- const dotSize = shallowRef(0);
- const dotRef = ref();
- watch(dotRef, newValue => {
- if (!newValue) return;
- dotSize.value = newValue.$el.querySelector('.v-timeline-divider__dot')?.getBoundingClientRect().width ?? 0;
- }, {
- flush: 'post'
- });
- useRender(() => createVNode("div", {
- "class": ['v-timeline-item', {
- 'v-timeline-item--fill-dot': props.fillDot
- }, props.class],
- "style": [{
- '--v-timeline-dot-size': convertToUnit(dotSize.value),
- '--v-timeline-line-inset': props.lineInset ? `calc(var(--v-timeline-dot-size) / 2 + ${convertToUnit(props.lineInset)})` : convertToUnit(0)
- }, props.style]
- }, [createVNode("div", {
- "class": "v-timeline-item__body",
- "style": dimensionStyles.value
- }, [slots.default?.()]), createVNode(VTimelineDivider, {
- "ref": dotRef,
- "hideDot": props.hideDot,
- "icon": props.icon,
- "iconColor": props.iconColor,
- "size": props.size,
- "elevation": props.elevation,
- "dotColor": props.dotColor,
- "fillDot": props.fillDot,
- "rounded": props.rounded
- }, {
- default: slots.icon
- }), props.density !== 'compact' && createVNode("div", {
- "class": "v-timeline-item__opposite"
- }, [!props.hideOpposite && slots.opposite?.()])]));
- return {};
- }
- });
- const makeVToolbarItemsProps = propsFactory({
- ...makeComponentProps(),
- ...makeVariantProps({
- variant: 'text'
- })
- }, 'VToolbarItems');
- const VToolbarItems = genericComponent()({
- name: 'VToolbarItems',
- props: makeVToolbarItemsProps(),
- setup(props, _ref) {
- let {
- slots
- } = _ref;
- provideDefaults({
- VBtn: {
- color: toRef(props, 'color'),
- height: 'inherit',
- variant: toRef(props, 'variant')
- }
- });
- useRender(() => createVNode("div", {
- "class": ['v-toolbar-items', props.class],
- "style": props.style
- }, [slots.default?.()]));
- return {};
- }
- });
- // Types
- const makeVTooltipProps = propsFactory({
- id: String,
- text: String,
- ...omit(makeVOverlayProps({
- closeOnBack: false,
- location: 'end',
- locationStrategy: 'connected',
- eager: true,
- minWidth: 0,
- offset: 10,
- openOnClick: false,
- openOnHover: true,
- origin: 'auto',
- scrim: false,
- scrollStrategy: 'reposition',
- transition: false
- }), ['absolute', 'persistent'])
- }, 'VTooltip');
- const VTooltip = genericComponent()({
- name: 'VTooltip',
- props: makeVTooltipProps(),
- emits: {
- 'update:modelValue': value => true
- },
- setup(props, _ref) {
- let {
- slots
- } = _ref;
- const isActive = useProxiedModel(props, 'modelValue');
- const {
- scopeId
- } = useScopeId();
- const uid = getUid();
- const id = computed(() => props.id || `v-tooltip-${uid}`);
- const overlay = ref();
- const location = computed(() => {
- return props.location.split(' ').length > 1 ? props.location : props.location + ' center';
- });
- const origin = computed(() => {
- return props.origin === 'auto' || props.origin === 'overlap' || props.origin.split(' ').length > 1 || props.location.split(' ').length > 1 ? props.origin : props.origin + ' center';
- });
- const transition = computed(() => {
- if (props.transition) return props.transition;
- return isActive.value ? 'scale-transition' : 'fade-transition';
- });
- const activatorProps = computed(() => mergeProps({
- 'aria-describedby': id.value
- }, props.activatorProps));
- useRender(() => {
- const [overlayProps] = VOverlay.filterProps(props);
- return createVNode(VOverlay, mergeProps({
- "ref": overlay,
- "class": ['v-tooltip', props.class],
- "style": props.style,
- "id": id.value
- }, overlayProps, {
- "modelValue": isActive.value,
- "onUpdate:modelValue": $event => isActive.value = $event,
- "transition": transition.value,
- "absolute": true,
- "location": location.value,
- "origin": origin.value,
- "persistent": true,
- "role": "tooltip",
- "activatorProps": activatorProps.value,
- "_disableGlobalStack": true
- }, scopeId), {
- activator: slots.activator,
- default: function () {
- for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) {
- args[_key] = arguments[_key];
- }
- return slots.default?.(...args) ?? props.text;
- }
- });
- });
- return forwardRefs({}, overlay);
- }
- });
- // Composables
- const VValidation = genericComponent()({
- name: 'VValidation',
- props: makeValidationProps(),
- emits: {
- 'update:modelValue': val => true
- },
- setup(props, _ref) {
- let {
- slots
- } = _ref;
- const validation = useValidation(props, 'validation');
- return () => slots.default?.(validation);
- }
- });
- // Types
- const makeVBottomSheetProps = propsFactory({
- inset: Boolean,
- ...makeVDialogProps({
- contentClass: 'v-bottom-sheet__content',
- transition: 'bottom-sheet-transition'
- })
- }, 'VBottomSheet');
- const VBottomSheet = genericComponent()({
- name: 'VBottomSheet',
- props: makeVBottomSheetProps(),
- emits: {
- 'update:modelValue': value => true
- },
- setup(props, _ref) {
- let {
- slots
- } = _ref;
- const isActive = useProxiedModel(props, 'modelValue');
- useRender(() => {
- const [dialogProps] = VDialog.filterProps(props);
- return createVNode(VDialog, mergeProps(dialogProps, {
- "modelValue": isActive.value,
- "onUpdate:modelValue": $event => isActive.value = $event,
- "class": ['v-bottom-sheet', {
- 'v-bottom-sheet--inset': props.inset
- }]
- }), slots);
- });
- return {};
- }
- });
- // Utilities
- // Types
- // Composables
- const makeDataIteratorItemsProps = propsFactory({
- items: {
- type: Array,
- default: () => []
- },
- itemValue: {
- type: [String, Array, Function],
- default: 'id'
- },
- itemSelectable: {
- type: [String, Array, Function],
- default: null
- },
- returnObject: Boolean
- }, 'DataIterator-items');
- function transformItem$1(props, item) {
- const value = props.returnObject ? item : getPropertyFromItem(item, props.itemValue);
- const selectable = getPropertyFromItem(item, props.itemSelectable, true);
- return {
- type: 'item',
- value,
- selectable,
- raw: item
- };
- }
- function transformItems$1(props, items) {
- const array = [];
- for (const item of items) {
- array.push(transformItem$1(props, item));
- }
- return array;
- }
- function useDataIteratorItems(props) {
- const items = computed(() => transformItems$1(props, props.items));
- return {
- items
- };
- }
- // Composables
- // Types
- const makeDataTableExpandProps = propsFactory({
- expandOnClick: Boolean,
- showExpand: Boolean,
- expanded: {
- type: Array,
- default: () => []
- }
- }, 'DataTable-expand');
- const VDataTableExpandedKey = Symbol.for('vuetify:datatable:expanded');
- function provideExpanded(props) {
- const expandOnClick = toRef(props, 'expandOnClick');
- const expanded = useProxiedModel(props, 'expanded', props.expanded, v => {
- return new Set(v);
- }, v => {
- return [...v.values()];
- });
- function expand(item, value) {
- const newExpanded = new Set(expanded.value);
- if (!value) {
- newExpanded.delete(item.value);
- } else {
- newExpanded.add(item.value);
- }
- expanded.value = newExpanded;
- }
- function isExpanded(item) {
- return expanded.value.has(item.value);
- }
- function toggleExpand(item) {
- expand(item, !isExpanded(item));
- }
- const data = {
- expand,
- expanded,
- expandOnClick,
- isExpanded,
- toggleExpand
- };
- provide(VDataTableExpandedKey, data);
- return data;
- }
- function useExpanded() {
- const data = inject$1(VDataTableExpandedKey);
- if (!data) throw new Error('foo');
- return data;
- }
- // Composables
- // Types
- const makeDataTableGroupProps = propsFactory({
- groupBy: {
- type: Array,
- default: () => []
- }
- }, 'DataTable-group');
- const VDataTableGroupSymbol = Symbol.for('vuetify:data-table-group');
- function createGroupBy(props) {
- const groupBy = useProxiedModel(props, 'groupBy');
- return {
- groupBy
- };
- }
- function provideGroupBy(options) {
- const {
- groupBy,
- sortBy
- } = options;
- const opened = ref(new Set());
- const sortByWithGroups = computed(() => {
- return groupBy.value.map(val => ({
- ...val,
- order: val.order ?? false
- })).concat(sortBy.value);
- });
- function isGroupOpen(group) {
- return opened.value.has(group.id);
- }
- function toggleGroup(group) {
- const newOpened = new Set(opened.value);
- if (!isGroupOpen(group)) newOpened.add(group.id);else newOpened.delete(group.id);
- opened.value = newOpened;
- }
- function extractRows(items) {
- function dive(group) {
- const arr = [];
- for (const item of group.items) {
- if ('type' in item && item.type === 'group') {
- arr.push(...dive(item));
- } else {
- arr.push(item);
- }
- }
- return arr;
- }
- return dive({
- type: 'group',
- items,
- id: 'dummy',
- key: 'dummy',
- value: 'dummy',
- depth: 0
- });
- }
- // onBeforeMount(() => {
- // for (const key of groupedItems.value.keys()) {
- // opened.value.add(key)
- // }
- // })
- const data = {
- sortByWithGroups,
- toggleGroup,
- opened,
- groupBy,
- extractRows,
- isGroupOpen
- };
- provide(VDataTableGroupSymbol, data);
- return data;
- }
- function useGroupBy() {
- const data = inject$1(VDataTableGroupSymbol);
- if (!data) throw new Error('Missing group!');
- return data;
- }
- function groupItemsByProperty(items, groupBy) {
- if (!items.length) return [];
- const groups = new Map();
- for (const item of items) {
- const value = getObjectValueByPath(item.raw, groupBy);
- if (!groups.has(value)) {
- groups.set(value, []);
- }
- groups.get(value).push(item);
- }
- return groups;
- }
- function groupItems(items, groupBy) {
- let depth = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : 0;
- let prefix = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : 'root';
- if (!groupBy.length) return [];
- const groupedItems = groupItemsByProperty(items, groupBy[0]);
- const groups = [];
- const rest = groupBy.slice(1);
- groupedItems.forEach((items, value) => {
- const key = groupBy[0];
- const id = `${prefix}_${key}_${value}`;
- groups.push({
- depth,
- id,
- key,
- value,
- items: rest.length ? groupItems(items, rest, depth + 1, id) : items,
- type: 'group'
- });
- });
- return groups;
- }
- function flattenItems(items, opened) {
- const flatItems = [];
- for (const item of items) {
- // TODO: make this better
- if ('type' in item && item.type === 'group') {
- if (item.value != null) {
- flatItems.push(item);
- }
- if (opened.has(item.id) || item.value == null) {
- flatItems.push(...flattenItems(item.items, opened));
- }
- } else {
- flatItems.push(item);
- }
- }
- return flatItems;
- }
- function useGroupedItems(items, groupBy, opened) {
- const flatItems = computed(() => {
- if (!groupBy.value.length) return items.value;
- const groupedItems = groupItems(items.value, groupBy.value.map(item => item.key));
- return flattenItems(groupedItems, opened.value);
- });
- return {
- flatItems
- };
- }
- // Utilities
- // Types
- function useOptions(_ref) {
- let {
- page,
- itemsPerPage,
- sortBy,
- groupBy,
- search
- } = _ref;
- const vm = getCurrentInstance('VDataTable');
- const options = computed(() => ({
- page: page.value,
- itemsPerPage: itemsPerPage.value,
- sortBy: sortBy.value,
- groupBy: groupBy.value,
- search: search.value
- }));
- // Reset page when searching
- watch(() => search?.value, () => {
- page.value = 1;
- });
- let oldOptions = null;
- watch(options, () => {
- if (deepEqual(oldOptions, options.value)) return;
- vm.emit('update:options', options.value);
- oldOptions = options.value;
- }, {
- deep: true,
- immediate: true
- });
- }
- // Composables
- // Types
- const makeDataTablePaginateProps = propsFactory({
- page: {
- type: [Number, String],
- default: 1
- },
- itemsPerPage: {
- type: [Number, String],
- default: 10
- }
- }, 'DataTable-paginate');
- const VDataTablePaginationSymbol = Symbol.for('vuetify:data-table-pagination');
- function createPagination(props) {
- const page = useProxiedModel(props, 'page', undefined, value => +(value ?? 1));
- const itemsPerPage = useProxiedModel(props, 'itemsPerPage', undefined, value => +(value ?? 10));
- return {
- page,
- itemsPerPage
- };
- }
- function providePagination(options) {
- const {
- page,
- itemsPerPage,
- itemsLength
- } = options;
- const startIndex = computed(() => {
- if (itemsPerPage.value === -1) return 0;
- return itemsPerPage.value * (page.value - 1);
- });
- const stopIndex = computed(() => {
- if (itemsPerPage.value === -1) return itemsLength.value;
- return Math.min(itemsLength.value, startIndex.value + itemsPerPage.value);
- });
- const pageCount = computed(() => {
- if (itemsPerPage.value === -1 || itemsLength.value === 0) return 1;
- return Math.ceil(itemsLength.value / itemsPerPage.value);
- });
- watchEffect(() => {
- if (page.value > pageCount.value) {
- page.value = pageCount.value;
- }
- });
- function setItemsPerPage(value) {
- itemsPerPage.value = value;
- page.value = 1;
- }
- function nextPage() {
- page.value = clamp(page.value + 1, 1, pageCount.value);
- }
- function prevPage() {
- page.value = clamp(page.value - 1, 1, pageCount.value);
- }
- function setPage(value) {
- page.value = clamp(value, 1, pageCount.value);
- }
- const data = {
- page,
- itemsPerPage,
- startIndex,
- stopIndex,
- pageCount,
- itemsLength,
- nextPage,
- prevPage,
- setPage,
- setItemsPerPage
- };
- provide(VDataTablePaginationSymbol, data);
- return data;
- }
- function usePagination() {
- const data = inject$1(VDataTablePaginationSymbol);
- if (!data) throw new Error('Missing pagination!');
- return data;
- }
- function usePaginatedItems(options) {
- const {
- items,
- startIndex,
- stopIndex,
- itemsPerPage
- } = options;
- const paginatedItems = computed(() => {
- if (itemsPerPage.value <= 0) return items.value;
- return items.value.slice(startIndex.value, stopIndex.value);
- });
- return {
- paginatedItems
- };
- }
- // Composables
- // Types
- const singleSelectStrategy = {
- showSelectAll: false,
- allSelected: () => [],
- select: _ref => {
- let {
- items,
- value
- } = _ref;
- return new Set(value ? [items[0]?.value] : []);
- },
- selectAll: _ref2 => {
- let {
- selected
- } = _ref2;
- return selected;
- }
- };
- const pageSelectStrategy = {
- showSelectAll: true,
- allSelected: _ref3 => {
- let {
- currentPage
- } = _ref3;
- return currentPage;
- },
- select: _ref4 => {
- let {
- items,
- value,
- selected
- } = _ref4;
- for (const item of items) {
- if (value) selected.add(item.value);else selected.delete(item.value);
- }
- return selected;
- },
- selectAll: _ref5 => {
- let {
- value,
- currentPage,
- selected
- } = _ref5;
- return pageSelectStrategy.select({
- items: currentPage,
- value,
- selected
- });
- }
- };
- const allSelectStrategy = {
- showSelectAll: true,
- allSelected: _ref6 => {
- let {
- allItems
- } = _ref6;
- return allItems;
- },
- select: _ref7 => {
- let {
- items,
- value,
- selected
- } = _ref7;
- for (const item of items) {
- if (value) selected.add(item.value);else selected.delete(item.value);
- }
- return selected;
- },
- selectAll: _ref8 => {
- let {
- value,
- allItems,
- selected
- } = _ref8;
- return allSelectStrategy.select({
- items: allItems,
- value,
- selected
- });
- }
- };
- const makeDataTableSelectProps = propsFactory({
- showSelect: Boolean,
- selectStrategy: {
- type: [String, Object],
- default: 'page'
- },
- modelValue: {
- type: Array,
- default: () => []
- }
- }, 'DataTable-select');
- const VDataTableSelectionSymbol = Symbol.for('vuetify:data-table-selection');
- function provideSelection(props, _ref9) {
- let {
- allItems,
- currentPage
- } = _ref9;
- const selected = useProxiedModel(props, 'modelValue', props.modelValue, v => {
- return new Set(v);
- }, v => {
- return [...v.values()];
- });
- const allSelectable = computed(() => allItems.value.filter(item => item.selectable));
- const currentPageSelectable = computed(() => currentPage.value.filter(item => item.selectable));
- const selectStrategy = computed(() => {
- if (typeof props.selectStrategy === 'object') return props.selectStrategy;
- switch (props.selectStrategy) {
- case 'single':
- return singleSelectStrategy;
- case 'all':
- return allSelectStrategy;
- case 'page':
- default:
- return pageSelectStrategy;
- }
- });
- function isSelected(items) {
- return wrapInArray(items).every(item => selected.value.has(item.value));
- }
- function isSomeSelected(items) {
- return wrapInArray(items).some(item => selected.value.has(item.value));
- }
- function select(items, value) {
- const newSelected = selectStrategy.value.select({
- items,
- value,
- selected: new Set(selected.value)
- });
- selected.value = newSelected;
- }
- function toggleSelect(item) {
- select([item], !isSelected([item]));
- }
- function selectAll(value) {
- const newSelected = selectStrategy.value.selectAll({
- value,
- allItems: allSelectable.value,
- currentPage: currentPageSelectable.value,
- selected: new Set(selected.value)
- });
- selected.value = newSelected;
- }
- const someSelected = computed(() => selected.value.size > 0);
- const allSelected = computed(() => {
- const items = selectStrategy.value.allSelected({
- allItems: allSelectable.value,
- currentPage: currentPageSelectable.value
- });
- return isSelected(items);
- });
- const data = {
- toggleSelect,
- select,
- selectAll,
- isSelected,
- isSomeSelected,
- someSelected,
- allSelected,
- showSelectAll: selectStrategy.value.showSelectAll
- };
- provide(VDataTableSelectionSymbol, data);
- return data;
- }
- function useSelection() {
- const data = inject$1(VDataTableSelectionSymbol);
- if (!data) throw new Error('Missing selection!');
- return data;
- }
- // Composables
- // Types
- const makeDataTableSortProps = propsFactory({
- sortBy: {
- type: Array,
- default: () => []
- },
- customKeySort: Object,
- multiSort: Boolean,
- mustSort: Boolean
- }, 'DataTable-sort');
- const VDataTableSortSymbol = Symbol.for('vuetify:data-table-sort');
- function createSort(props) {
- const sortBy = useProxiedModel(props, 'sortBy');
- const mustSort = toRef(props, 'mustSort');
- const multiSort = toRef(props, 'multiSort');
- return {
- sortBy,
- mustSort,
- multiSort
- };
- }
- function provideSort(options) {
- const {
- sortBy,
- mustSort,
- multiSort,
- page
- } = options;
- const toggleSort = column => {
- let newSortBy = sortBy.value.map(x => ({
- ...x
- })) ?? [];
- const item = newSortBy.find(x => x.key === column.key);
- if (!item) {
- if (multiSort.value) newSortBy = [...newSortBy, {
- key: column.key,
- order: 'asc'
- }];else newSortBy = [{
- key: column.key,
- order: 'asc'
- }];
- } else if (item.order === 'desc') {
- if (mustSort.value) {
- item.order = 'asc';
- } else {
- newSortBy = newSortBy.filter(x => x.key !== column.key);
- }
- } else {
- item.order = 'desc';
- }
- sortBy.value = newSortBy;
- if (page) page.value = 1;
- };
- function isSorted(column) {
- return !!sortBy.value.find(item => item.key === column.key);
- }
- const data = {
- sortBy,
- toggleSort,
- isSorted
- };
- provide(VDataTableSortSymbol, data);
- return data;
- }
- function useSort() {
- const data = inject$1(VDataTableSortSymbol);
- if (!data) throw new Error('Missing sort!');
- return data;
- }
- function useSortedItems(props, items, sortBy) {
- const locale = useLocale();
- const sortedItems = computed(() => {
- if (!sortBy.value.length) return items.value;
- return sortItems(items.value, sortBy.value, locale.current.value, props.customKeySort);
- });
- return {
- sortedItems
- };
- }
- function sortItems(items, sortByItems, locale, customSorters) {
- const stringCollator = new Intl.Collator(locale, {
- sensitivity: 'accent',
- usage: 'sort'
- });
- return [...items].sort((a, b) => {
- for (let i = 0; i < sortByItems.length; i++) {
- const sortKey = sortByItems[i].key;
- const sortOrder = sortByItems[i].order ?? 'asc';
- if (sortOrder === false) continue;
- let sortA = getObjectValueByPath(a.raw, sortKey);
- let sortB = getObjectValueByPath(b.raw, sortKey);
- if (sortOrder === 'desc') {
- [sortA, sortB] = [sortB, sortA];
- }
- if (customSorters?.[sortKey]) {
- const customResult = customSorters[sortKey](sortA, sortB);
- if (!customResult) continue;
- return customResult;
- }
- // Dates should be compared numerically
- if (sortA instanceof Date && sortB instanceof Date) {
- return sortA.getTime() - sortB.getTime();
- }
- [sortA, sortB] = [sortA, sortB].map(s => s != null ? s.toString().toLocaleLowerCase() : s);
- if (sortA !== sortB) {
- if (isEmpty(sortA) && isEmpty(sortB)) return 0;
- if (isEmpty(sortA)) return -1;
- if (isEmpty(sortB)) return 1;
- if (!isNaN(sortA) && !isNaN(sortB)) return Number(sortA) - Number(sortB);
- return stringCollator.compare(sortA, sortB);
- }
- }
- return 0;
- });
- }
- // Types
- const makeVDataIteratorProps = propsFactory({
- search: String,
- loading: Boolean,
- ...makeComponentProps(),
- ...makeDataIteratorItemsProps(),
- ...makeDataTableSelectProps(),
- ...makeDataTableSortProps(),
- ...makeDataTablePaginateProps({
- itemsPerPage: 5
- }),
- ...makeDataTableExpandProps(),
- ...makeDataTableGroupProps(),
- ...makeFilterProps(),
- ...makeTagProps()
- }, 'VDataIterator');
- const VDataIterator = genericComponent()({
- name: 'VDataIterator',
- props: makeVDataIteratorProps(),
- emits: {
- 'update:modelValue': value => true,
- 'update:groupBy': value => true,
- 'update:page': value => true,
- 'update:itemsPerPage': value => true,
- 'update:sortBy': value => true,
- 'update:options': value => true,
- 'update:expanded': value => true
- },
- setup(props, _ref) {
- let {
- slots
- } = _ref;
- const groupBy = useProxiedModel(props, 'groupBy');
- const search = toRef(props, 'search');
- const {
- items
- } = useDataIteratorItems(props);
- const {
- filteredItems
- } = useFilter(props, items, search, {
- transform: item => item.raw
- });
- const {
- sortBy,
- multiSort,
- mustSort
- } = createSort(props);
- const {
- page,
- itemsPerPage
- } = createPagination(props);
- const {
- toggleSort
- } = provideSort({
- sortBy,
- multiSort,
- mustSort,
- page
- });
- const {
- sortByWithGroups,
- opened,
- extractRows,
- isGroupOpen,
- toggleGroup
- } = provideGroupBy({
- groupBy,
- sortBy
- });
- const {
- sortedItems
- } = useSortedItems(props, filteredItems, sortByWithGroups);
- const {
- flatItems
- } = useGroupedItems(sortedItems, groupBy, opened);
- const itemsLength = computed(() => flatItems.value.length);
- const {
- startIndex,
- stopIndex,
- pageCount,
- prevPage,
- nextPage,
- setItemsPerPage,
- setPage
- } = providePagination({
- page,
- itemsPerPage,
- itemsLength
- });
- const {
- paginatedItems
- } = usePaginatedItems({
- items: flatItems,
- startIndex,
- stopIndex,
- itemsPerPage
- });
- const paginatedItemsWithoutGroups = computed(() => extractRows(paginatedItems.value));
- const {
- isSelected,
- select,
- selectAll,
- toggleSelect
- } = provideSelection(props, {
- allItems: items,
- currentPage: paginatedItemsWithoutGroups
- });
- const {
- isExpanded,
- toggleExpand
- } = provideExpanded(props);
- useOptions({
- page,
- itemsPerPage,
- sortBy,
- groupBy,
- search
- });
- const slotProps = computed(() => ({
- page: page.value,
- itemsPerPage: itemsPerPage.value,
- sortBy: sortBy.value,
- pageCount: pageCount.value,
- toggleSort,
- prevPage,
- nextPage,
- setPage,
- setItemsPerPage,
- isSelected,
- select,
- selectAll,
- toggleSelect,
- isExpanded,
- toggleExpand,
- isGroupOpen,
- toggleGroup,
- items: paginatedItemsWithoutGroups.value,
- groupedItems: paginatedItems.value
- }));
- useRender(() => createVNode(props.tag, {
- "class": ['v-data-iterator', props.class],
- "style": props.style
- }, {
- default: () => [slots.header?.(slotProps.value), !paginatedItems.value.length ? slots['no-data']?.() : slots.default?.(slotProps.value), slots.footer?.(slotProps.value)]
- }));
- return {};
- }
- });
- // Types
- const makeVDataTableFooterProps = propsFactory({
- prevIcon: {
- type: String,
- default: '$prev'
- },
- nextIcon: {
- type: String,
- default: '$next'
- },
- firstIcon: {
- type: String,
- default: '$first'
- },
- lastIcon: {
- type: String,
- default: '$last'
- },
- itemsPerPageText: {
- type: String,
- default: '$vuetify.dataFooter.itemsPerPageText'
- },
- pageText: {
- type: String,
- default: '$vuetify.dataFooter.pageText'
- },
- firstPageLabel: {
- type: String,
- default: '$vuetify.dataFooter.firstPage'
- },
- prevPageLabel: {
- type: String,
- default: '$vuetify.dataFooter.prevPage'
- },
- nextPageLabel: {
- type: String,
- default: '$vuetify.dataFooter.nextPage'
- },
- lastPageLabel: {
- type: String,
- default: '$vuetify.dataFooter.lastPage'
- },
- itemsPerPageOptions: {
- type: Array,
- default: () => [{
- value: 10,
- title: '10'
- }, {
- value: 25,
- title: '25'
- }, {
- value: 50,
- title: '50'
- }, {
- value: 100,
- title: '100'
- }, {
- value: -1,
- title: '$vuetify.dataFooter.itemsPerPageAll'
- }]
- },
- showCurrentPage: Boolean
- }, 'VDataTableFooter');
- const VDataTableFooter = genericComponent()({
- name: 'VDataTableFooter',
- props: makeVDataTableFooterProps(),
- setup(props, _ref) {
- let {
- slots
- } = _ref;
- const {
- t
- } = useLocale();
- const {
- page,
- pageCount,
- startIndex,
- stopIndex,
- itemsLength,
- itemsPerPage,
- setItemsPerPage
- } = usePagination();
- const itemsPerPageOptions = computed(() => props.itemsPerPageOptions.map(option => ({
- ...option,
- title: t(option.title)
- })));
- return () => createVNode("div", {
- "class": "v-data-table-footer"
- }, [slots.prepend?.(), createVNode("div", {
- "class": "v-data-table-footer__items-per-page"
- }, [createVNode("span", null, [t(props.itemsPerPageText)]), createVNode(VSelect, {
- "items": itemsPerPageOptions.value,
- "modelValue": itemsPerPage.value,
- "onUpdate:modelValue": v => setItemsPerPage(Number(v)),
- "density": "compact",
- "variant": "outlined",
- "hide-details": true
- }, null)]), createVNode("div", {
- "class": "v-data-table-footer__info"
- }, [createVNode("div", null, [t(props.pageText, !itemsLength.value ? 0 : startIndex.value + 1, stopIndex.value, itemsLength.value)])]), createVNode("div", {
- "class": "v-data-table-footer__pagination"
- }, [createVNode(VBtn, {
- "icon": props.firstIcon,
- "variant": "plain",
- "onClick": () => page.value = 1,
- "disabled": page.value === 1,
- "aria-label": t(props.firstPageLabel)
- }, null), createVNode(VBtn, {
- "icon": props.prevIcon,
- "variant": "plain",
- "onClick": () => page.value = Math.max(1, page.value - 1),
- "disabled": page.value === 1,
- "aria-label": t(props.prevPageLabel)
- }, null), props.showCurrentPage && createVNode("span", {
- "key": "page",
- "class": "v-data-table-footer__page"
- }, [page.value]), createVNode(VBtn, {
- "icon": props.nextIcon,
- "variant": "plain",
- "onClick": () => page.value = Math.min(pageCount.value, page.value + 1),
- "disabled": page.value === pageCount.value,
- "aria-label": t(props.nextPageLabel)
- }, null), createVNode(VBtn, {
- "icon": props.lastIcon,
- "variant": "plain",
- "onClick": () => page.value = pageCount.value,
- "disabled": page.value === pageCount.value,
- "aria-label": t(props.lastPageLabel)
- }, null)])]);
- }
- });
- // Types
- const VDataTableColumn = defineFunctionalComponent({
- align: {
- type: String,
- default: 'start'
- },
- fixed: Boolean,
- fixedOffset: [Number, String],
- height: [Number, String],
- lastFixed: Boolean,
- noPadding: Boolean,
- tag: String,
- width: [Number, String]
- }, (props, _ref) => {
- let {
- slots,
- attrs
- } = _ref;
- const Tag = props.tag ?? 'td';
- return createVNode(Tag, mergeProps({
- "class": ['v-data-table__td', {
- 'v-data-table-column--fixed': props.fixed,
- 'v-data-table-column--last-fixed': props.lastFixed,
- 'v-data-table-column--no-padding': props.noPadding
- }, `v-data-table-column--align-${props.align}`],
- "style": {
- height: convertToUnit(props.height),
- width: convertToUnit(props.width),
- left: convertToUnit(props.fixedOffset || null)
- }
- }, attrs), {
- default: () => [slots.default?.()]
- });
- });
- // Utilities
- // Types
- const makeDataTableHeaderProps = propsFactory({
- headers: {
- type: Array,
- default: () => []
- }
- }, 'DataTable-header');
- const VDataTableHeadersSymbol = Symbol.for('vuetify:data-table-headers');
- function createHeaders(props, options) {
- const headers = ref([]);
- const columns = ref([]);
- watchEffect(() => {
- const wrapped = !props.headers.length ? [] : Array.isArray(props.headers[0]) ? props.headers : [props.headers];
- const flat = wrapped.flatMap((row, index) => row.map(column => ({
- column,
- row: index
- })));
- const rowCount = wrapped.length;
- const defaultHeader = {
- title: '',
- sortable: false
- };
- const defaultActionHeader = {
- ...defaultHeader,
- width: 48
- };
- if (options?.groupBy?.value.length) {
- const index = flat.findIndex(_ref => {
- let {
- column
- } = _ref;
- return column.key === 'data-table-group';
- });
- if (index < 0) flat.unshift({
- column: {
- ...defaultHeader,
- key: 'data-table-group',
- title: 'Group',
- rowspan: rowCount
- },
- row: 0
- });else flat.splice(index, 1, {
- column: {
- ...defaultHeader,
- ...flat[index].column
- },
- row: flat[index].row
- });
- }
- if (options?.showSelect?.value) {
- const index = flat.findIndex(_ref2 => {
- let {
- column
- } = _ref2;
- return column.key === 'data-table-select';
- });
- if (index < 0) flat.unshift({
- column: {
- ...defaultActionHeader,
- key: 'data-table-select',
- rowspan: rowCount
- },
- row: 0
- });else flat.splice(index, 1, {
- column: {
- ...defaultActionHeader,
- ...flat[index].column
- },
- row: flat[index].row
- });
- }
- if (options?.showExpand?.value) {
- const index = flat.findIndex(_ref3 => {
- let {
- column
- } = _ref3;
- return column.key === 'data-table-expand';
- });
- if (index < 0) flat.push({
- column: {
- ...defaultActionHeader,
- key: 'data-table-expand',
- rowspan: rowCount
- },
- row: 0
- });else flat.splice(index, 1, {
- column: {
- ...defaultActionHeader,
- ...flat[index].column
- },
- row: flat[index].row
- });
- }
- const fixedRows = createRange(rowCount).map(() => []);
- const fixedOffsets = createRange(rowCount).fill(0);
- flat.forEach(_ref4 => {
- let {
- column,
- row
- } = _ref4;
- let key = column.key;
- if (key == null) {
- consoleWarn('The header key value must not be null or undefined');
- key = '';
- }
- for (let i = row; i <= row + (column.rowspan ?? 1) - 1; i++) {
- fixedRows[i].push({
- ...column,
- key,
- fixedOffset: fixedOffsets[i],
- sortable: column.sortable ?? !!column.key
- });
- fixedOffsets[i] += Number(column.width ?? 0);
- }
- });
- fixedRows.forEach(row => {
- for (let i = row.length; i--; i >= 0) {
- if (row[i].fixed) {
- row[i].lastFixed = true;
- return;
- }
- }
- });
- const seen = new Set();
- headers.value = fixedRows.map(row => {
- const filtered = [];
- for (const column of row) {
- if (!seen.has(column.key)) {
- seen.add(column.key);
- filtered.push(column);
- }
- }
- return filtered;
- });
- columns.value = fixedRows.at(-1) ?? [];
- });
- const data = {
- headers,
- columns
- };
- provide(VDataTableHeadersSymbol, data);
- return data;
- }
- function useHeaders() {
- const data = inject$1(VDataTableHeadersSymbol);
- if (!data) throw new Error('Missing headers!');
- return data;
- }
- // Types
- const makeVDataTableHeadersProps = propsFactory({
- color: String,
- sticky: Boolean,
- multiSort: Boolean,
- sortAscIcon: {
- type: IconValue,
- default: '$sortAsc'
- },
- sortDescIcon: {
- type: IconValue,
- default: '$sortDesc'
- },
- ...makeLoaderProps()
- }, 'VDataTableHeaders');
- const VDataTableHeaders = genericComponent()({
- name: 'VDataTableHeaders',
- props: makeVDataTableHeadersProps(),
- setup(props, _ref) {
- let {
- slots,
- emit
- } = _ref;
- const {
- toggleSort,
- sortBy,
- isSorted
- } = useSort();
- const {
- someSelected,
- allSelected,
- selectAll,
- showSelectAll
- } = useSelection();
- const {
- columns,
- headers
- } = useHeaders();
- const {
- loaderClasses
- } = useLoader(props);
- const getFixedStyles = (column, y) => {
- if (!props.sticky && !column.fixed) return undefined;
- return {
- position: 'sticky',
- zIndex: column.fixed ? 4 : props.sticky ? 3 : undefined,
- // TODO: This needs to account for possible previous fixed columns.
- left: column.fixed ? convertToUnit(column.fixedOffset) : undefined,
- // TODO: This needs to account for possible row/colspan of previous columns
- top: props.sticky ? `calc(var(--v-table-header-height) * ${y})` : undefined
- };
- };
- function getSortIcon(column) {
- const item = sortBy.value.find(item => item.key === column.key);
- if (!item) return props.sortAscIcon;
- return item.order === 'asc' ? props.sortAscIcon : props.sortDescIcon;
- }
- const {
- backgroundColorClasses,
- backgroundColorStyles
- } = useBackgroundColor(props, 'color');
- const slotProps = computed(() => ({
- headers: headers.value,
- columns: columns.value,
- toggleSort,
- isSorted,
- sortBy: sortBy.value,
- someSelected: someSelected.value,
- allSelected: allSelected.value,
- selectAll,
- getSortIcon,
- getFixedStyles
- }));
- const VDataTableHeaderCell = _ref2 => {
- let {
- column,
- x,
- y
- } = _ref2;
- const noPadding = column.key === 'data-table-select' || column.key === 'data-table-expand';
- return createVNode(VDataTableColumn, {
- "tag": "th",
- "align": column.align,
- "class": ['v-data-table__th', {
- 'v-data-table__th--sortable': column.sortable,
- 'v-data-table__th--sorted': isSorted(column)
- }, loaderClasses.value],
- "style": {
- width: convertToUnit(column.width),
- minWidth: convertToUnit(column.width),
- ...getFixedStyles(column, y)
- },
- "colspan": column.colspan,
- "rowspan": column.rowspan,
- "onClick": column.sortable ? () => toggleSort(column) : undefined,
- "lastFixed": column.lastFixed,
- "noPadding": noPadding
- }, {
- default: () => {
- const columnSlotName = `column.${column.key}`;
- const columnSlotProps = {
- column,
- selectAll,
- isSorted,
- toggleSort,
- sortBy: sortBy.value,
- someSelected: someSelected.value,
- allSelected: allSelected.value,
- getSortIcon
- };
- if (slots[columnSlotName]) return slots[columnSlotName](columnSlotProps);
- if (column.key === 'data-table-select') {
- return slots['column.data-table-select']?.(columnSlotProps) ?? (showSelectAll && createVNode(VCheckboxBtn, {
- "modelValue": allSelected.value,
- "indeterminate": someSelected.value && !allSelected.value,
- "onUpdate:modelValue": selectAll
- }, null));
- }
- return createVNode("div", {
- "class": "v-data-table-header__content"
- }, [createVNode("span", null, [column.title]), column.sortable && createVNode(VIcon, {
- "key": "icon",
- "class": "v-data-table-header__sort-icon",
- "icon": getSortIcon(column)
- }, null), props.multiSort && isSorted(column) && createVNode("div", {
- "key": "badge",
- "class": ['v-data-table-header__sort-badge', ...backgroundColorClasses.value],
- "style": backgroundColorStyles.value
- }, [sortBy.value.findIndex(x => x.key === column.key) + 1])]);
- }
- });
- };
- useRender(() => {
- return createVNode(Fragment, null, [slots.headers ? slots.headers(slotProps.value) : headers.value.map((row, y) => createVNode("tr", null, [row.map((column, x) => createVNode(VDataTableHeaderCell, {
- "column": column,
- "x": x,
- "y": y
- }, null))])), props.loading && createVNode("tr", {
- "class": "v-data-table-progress"
- }, [createVNode("th", {
- "colspan": columns.value.length
- }, [createVNode(LoaderSlot, {
- "name": "v-data-table-progress",
- "active": true,
- "color": typeof props.loading === 'boolean' ? undefined : props.loading,
- "indeterminate": true
- }, {
- default: slots.loader
- })])])]);
- });
- }
- });
- // Types
- const makeVDataTableGroupHeaderRowProps = propsFactory({
- item: {
- type: Object,
- required: true
- }
- }, 'VDataTableGroupHeaderRow');
- const VDataTableGroupHeaderRow = genericComponent()({
- name: 'VDataTableGroupHeaderRow',
- props: makeVDataTableGroupHeaderRowProps(),
- setup(props, _ref) {
- let {
- slots
- } = _ref;
- const {
- isGroupOpen,
- toggleGroup,
- extractRows
- } = useGroupBy();
- const {
- isSelected,
- isSomeSelected,
- select
- } = useSelection();
- const {
- columns
- } = useHeaders();
- const rows = computed(() => {
- return extractRows([props.item]);
- });
- return () => createVNode("tr", {
- "class": "v-data-table-group-header-row",
- "style": {
- '--v-data-table-group-header-row-depth': props.item.depth
- }
- }, [columns.value.map(column => {
- if (column.key === 'data-table-group') {
- const icon = isGroupOpen(props.item) ? '$expand' : '$next';
- const onClick = () => toggleGroup(props.item);
- return slots['data-table-group']?.({
- item: props.item,
- count: rows.value.length,
- props: {
- icon,
- onClick
- }
- }) ?? createVNode(VDataTableColumn, {
- "class": "v-data-table-group-header-row__column"
- }, {
- default: () => [createVNode(VBtn, {
- "size": "small",
- "variant": "text",
- "icon": icon,
- "onClick": onClick
- }, null), createVNode("span", null, [props.item.value]), createVNode("span", null, [createTextVNode("("), rows.value.length, createTextVNode(")")])]
- });
- }
- if (column.key === 'data-table-select') {
- const modelValue = isSelected(rows.value);
- const indeterminate = isSomeSelected(rows.value) && !modelValue;
- const selectGroup = v => select(rows.value, v);
- return slots['data-table-select']?.({
- props: {
- modelValue,
- indeterminate,
- 'onUpdate:modelValue': selectGroup
- }
- }) ?? createVNode("td", null, [createVNode(VCheckboxBtn, {
- "modelValue": modelValue,
- "indeterminate": indeterminate,
- "onUpdate:modelValue": selectGroup
- }, null)]);
- }
- return createVNode("td", null, null);
- })]);
- }
- });
- // Types
- const makeVDataTableRowProps = propsFactory({
- index: Number,
- item: Object,
- onClick: Function
- }, 'VDataTableRow');
- const VDataTableRow = defineComponent({
- name: 'VDataTableRow',
- props: makeVDataTableRowProps(),
- setup(props, _ref) {
- let {
- slots
- } = _ref;
- const {
- isSelected,
- toggleSelect
- } = useSelection();
- const {
- isExpanded,
- toggleExpand
- } = useExpanded();
- const {
- columns
- } = useHeaders();
- useRender(() => createVNode("tr", {
- "class": ['v-data-table__tr', {
- 'v-data-table__tr--clickable': !!props.onClick
- }],
- "onClick": props.onClick
- }, [props.item && columns.value.map((column, i) => createVNode(VDataTableColumn, {
- "align": column.align,
- "fixed": column.fixed,
- "fixedOffset": column.fixedOffset,
- "lastFixed": column.lastFixed,
- "noPadding": column.key === 'data-table-select' || column.key === 'data-table-expand',
- "width": column.width
- }, {
- default: () => {
- const item = props.item;
- const slotName = `item.${column.key}`;
- const slotProps = {
- index: props.index,
- item: props.item,
- columns: columns.value,
- isSelected,
- toggleSelect,
- isExpanded,
- toggleExpand
- };
- if (slots[slotName]) return slots[slotName](slotProps);
- if (column.key === 'data-table-select') {
- return slots['item.data-table-select']?.(slotProps) ?? createVNode(VCheckboxBtn, {
- "disabled": !item.selectable,
- "modelValue": isSelected([item]),
- "onClick": withModifiers(() => toggleSelect(item), ['stop'])
- }, null);
- }
- if (column.key === 'data-table-expand') {
- return slots['item.data-table-expand']?.(slotProps) ?? createVNode(VBtn, {
- "icon": isExpanded(item) ? '$collapse' : '$expand',
- "size": "small",
- "variant": "text",
- "onClick": withModifiers(() => toggleExpand(item), ['stop'])
- }, null);
- }
- return getPropertyFromItem(item.columns, column.key);
- }
- }))]));
- }
- });
- // Types
- const makeVDataTableRowsProps = propsFactory({
- loading: [Boolean, String],
- loadingText: {
- type: String,
- default: '$vuetify.dataIterator.loadingText'
- },
- hideNoData: Boolean,
- items: {
- type: Array,
- default: () => []
- },
- noDataText: {
- type: String,
- default: '$vuetify.noDataText'
- },
- rowHeight: Number,
- 'onClick:row': Function
- }, 'VDataTableRows');
- const VDataTableRows = genericComponent()({
- name: 'VDataTableRows',
- props: makeVDataTableRowsProps(),
- setup(props, _ref) {
- let {
- emit,
- slots
- } = _ref;
- const {
- columns
- } = useHeaders();
- const {
- expandOnClick,
- toggleExpand,
- isExpanded
- } = useExpanded();
- const {
- isSelected,
- toggleSelect
- } = useSelection();
- const {
- toggleGroup,
- isGroupOpen
- } = useGroupBy();
- const {
- t
- } = useLocale();
- useRender(() => {
- if (props.loading && slots.loading) {
- return createVNode("tr", {
- "class": "v-data-table-rows-loading",
- "key": "loading"
- }, [createVNode("td", {
- "colspan": columns.value.length
- }, [slots.loading()])]);
- }
- if (!props.loading && !props.items.length && !props.hideNoData) {
- return createVNode("tr", {
- "class": "v-data-table-rows-no-data",
- "key": "no-data"
- }, [createVNode("td", {
- "colspan": columns.value.length
- }, [slots['no-data']?.() ?? t(props.noDataText)])]);
- }
- return createVNode(Fragment, null, [props.items.map((item, index) => {
- if (item.type === 'group') {
- return slots['group-header'] ? slots['group-header']({
- index,
- item,
- columns: columns.value,
- isExpanded,
- toggleExpand,
- isSelected,
- toggleSelect,
- toggleGroup,
- isGroupOpen
- }) : createVNode(VDataTableGroupHeaderRow, {
- "key": `group-header_${item.id}`,
- "item": item
- }, slots);
- }
- const slotProps = {
- index,
- item,
- columns: columns.value,
- isExpanded,
- toggleExpand,
- isSelected,
- toggleSelect
- };
- const itemSlotProps = {
- ...slotProps,
- props: {
- key: `item_${item.key ?? item.index}`,
- onClick: expandOnClick.value || props['onClick:row'] ? event => {
- if (expandOnClick.value) {
- toggleExpand(item);
- }
- props['onClick:row']?.(event, {
- item
- });
- } : undefined,
- index,
- item
- }
- };
- return createVNode(Fragment, null, [slots.item ? slots.item(itemSlotProps) : createVNode(VDataTableRow, itemSlotProps.props, slots), isExpanded(item) && slots['expanded-row']?.(slotProps)]);
- })]);
- });
- return {};
- }
- });
- // Utilities
- // Types
- // Composables
- const makeDataTableItemsProps = propsFactory({
- items: {
- type: Array,
- default: () => []
- },
- itemValue: {
- type: [String, Array, Function],
- default: 'id'
- },
- itemSelectable: {
- type: [String, Array, Function],
- default: null
- },
- returnObject: Boolean
- }, 'DataTable-items');
- function transformItem(props, item, index, columns) {
- const value = props.returnObject ? item : getPropertyFromItem(item, props.itemValue);
- const selectable = getPropertyFromItem(item, props.itemSelectable, true);
- const itemColumns = columns.reduce((obj, column) => {
- obj[column.key] = getPropertyFromItem(item, column.value ?? column.key);
- return obj;
- }, {});
- return {
- type: 'item',
- key: props.returnObject ? getPropertyFromItem(item, props.itemValue) : value,
- index,
- value,
- selectable,
- columns: itemColumns,
- raw: item
- };
- }
- function transformItems(props, items, columns) {
- return items.map((item, index) => transformItem(props, item, index, columns));
- }
- function useDataTableItems(props, columns) {
- const items = computed(() => transformItems(props, props.items, columns.value));
- return {
- items
- };
- }
- // Types
- const makeDataTableProps = propsFactory({
- ...makeVDataTableRowsProps(),
- width: [String, Number],
- search: String,
- ...makeDataTableExpandProps(),
- ...makeDataTableGroupProps(),
- ...makeDataTableHeaderProps(),
- ...makeDataTableItemsProps(),
- ...makeDataTableSelectProps(),
- ...makeDataTableSortProps(),
- ...makeVDataTableHeadersProps(),
- ...makeVTableProps()
- }, 'DataTable');
- const makeVDataTableProps = propsFactory({
- ...makeDataTablePaginateProps(),
- ...makeDataTableProps(),
- ...makeFilterProps(),
- ...makeVDataTableFooterProps()
- }, 'VDataTable');
- const VDataTable = genericComponent()({
- name: 'VDataTable',
- props: makeVDataTableProps(),
- emits: {
- 'update:modelValue': value => true,
- 'update:page': value => true,
- 'update:itemsPerPage': value => true,
- 'update:sortBy': value => true,
- 'update:options': value => true,
- 'update:groupBy': value => true,
- 'update:expanded': value => true
- },
- setup(props, _ref) {
- let {
- emit,
- slots
- } = _ref;
- const {
- groupBy
- } = createGroupBy(props);
- const {
- sortBy,
- multiSort,
- mustSort
- } = createSort(props);
- const {
- page,
- itemsPerPage
- } = createPagination(props);
- const {
- columns,
- headers
- } = createHeaders(props, {
- groupBy,
- showSelect: toRef(props, 'showSelect'),
- showExpand: toRef(props, 'showExpand')
- });
- const {
- items
- } = useDataTableItems(props, columns);
- const search = toRef(props, 'search');
- const {
- filteredItems
- } = useFilter(props, items, search, {
- transform: item => item.columns
- });
- const {
- toggleSort
- } = provideSort({
- sortBy,
- multiSort,
- mustSort,
- page
- });
- const {
- sortByWithGroups,
- opened,
- extractRows,
- isGroupOpen,
- toggleGroup
- } = provideGroupBy({
- groupBy,
- sortBy
- });
- const {
- sortedItems
- } = useSortedItems(props, filteredItems, sortByWithGroups);
- const {
- flatItems
- } = useGroupedItems(sortedItems, groupBy, opened);
- const itemsLength = computed(() => flatItems.value.length);
- const {
- startIndex,
- stopIndex,
- pageCount,
- setItemsPerPage
- } = providePagination({
- page,
- itemsPerPage,
- itemsLength
- });
- const {
- paginatedItems
- } = usePaginatedItems({
- items: flatItems,
- startIndex,
- stopIndex,
- itemsPerPage
- });
- const paginatedItemsWithoutGroups = computed(() => extractRows(paginatedItems.value));
- const {
- isSelected,
- select,
- selectAll,
- toggleSelect,
- someSelected,
- allSelected
- } = provideSelection(props, {
- allItems: items,
- currentPage: paginatedItemsWithoutGroups
- });
- const {
- isExpanded,
- toggleExpand
- } = provideExpanded(props);
- useOptions({
- page,
- itemsPerPage,
- sortBy,
- groupBy,
- search
- });
- provideDefaults({
- VDataTableRows: {
- hideNoData: toRef(props, 'hideNoData'),
- noDataText: toRef(props, 'noDataText'),
- loading: toRef(props, 'loading'),
- loadingText: toRef(props, 'loadingText')
- }
- });
- const slotProps = computed(() => ({
- page: page.value,
- itemsPerPage: itemsPerPage.value,
- sortBy: sortBy.value,
- pageCount: pageCount.value,
- toggleSort,
- setItemsPerPage,
- someSelected: someSelected.value,
- allSelected: allSelected.value,
- isSelected,
- select,
- selectAll,
- toggleSelect,
- isExpanded,
- toggleExpand,
- isGroupOpen,
- toggleGroup,
- items: paginatedItemsWithoutGroups.value,
- groupedItems: paginatedItems.value,
- columns: columns.value,
- headers: headers.value
- }));
- useRender(() => {
- const [dataTableFooterProps] = VDataTableFooter.filterProps(props);
- const [dataTableHeadersProps] = VDataTableHeaders.filterProps(props);
- const [dataTableRowsProps] = VDataTableRows.filterProps(props);
- const [tableProps] = VTable.filterProps(props);
- return createVNode(VTable, mergeProps({
- "class": ['v-data-table', {
- 'v-data-table--show-select': props.showSelect,
- 'v-data-table--loading': props.loading
- }, props.class],
- "style": props.style
- }, tableProps), {
- top: () => slots.top?.(slotProps.value),
- default: () => slots.default ? slots.default(slotProps.value) : createVNode(Fragment, null, [slots.colgroup?.(slotProps.value), createVNode("thead", null, [createVNode(VDataTableHeaders, dataTableHeadersProps, slots)]), slots.thead?.(slotProps.value), createVNode("tbody", null, [slots.body ? slots.body(slotProps.value) : createVNode(VDataTableRows, mergeProps(dataTableRowsProps, {
- "items": paginatedItems.value
- }), slots)]), slots.tbody?.(slotProps.value), slots.tfoot?.(slotProps.value)]),
- bottom: () => slots.bottom ? slots.bottom(slotProps.value) : createVNode(Fragment, null, [createVNode(VDataTableFooter, dataTableFooterProps, {
- prepend: slots['footer.prepend']
- })])
- });
- });
- return {};
- }
- });
- // Types
- const makeVDataTableVirtualProps = propsFactory({
- ...makeDataTableProps(),
- ...makeDataTableGroupProps(),
- ...makeVirtualProps(),
- ...makeFilterProps()
- }, 'VDataTableVirtual');
- const VDataTableVirtual = genericComponent()({
- name: 'VDataTableVirtual',
- props: makeVDataTableVirtualProps(),
- emits: {
- 'update:modelValue': value => true,
- 'update:sortBy': value => true,
- 'update:options': value => true,
- 'update:groupBy': value => true,
- 'update:expanded': value => true,
- 'click:row': (e, value) => true
- },
- setup(props, _ref) {
- let {
- emit,
- slots
- } = _ref;
- const {
- groupBy
- } = createGroupBy(props);
- const {
- sortBy,
- multiSort,
- mustSort
- } = createSort(props);
- const {
- columns,
- headers
- } = createHeaders(props, {
- groupBy,
- showSelect: toRef(props, 'showSelect'),
- showExpand: toRef(props, 'showExpand')
- });
- const {
- items
- } = useDataTableItems(props, columns);
- const search = toRef(props, 'search');
- const {
- filteredItems
- } = useFilter(props, items, search, {
- transform: item => item.columns
- });
- const {
- toggleSort
- } = provideSort({
- sortBy,
- multiSort,
- mustSort
- });
- const {
- sortByWithGroups,
- opened,
- extractRows,
- isGroupOpen,
- toggleGroup
- } = provideGroupBy({
- groupBy,
- sortBy
- });
- const {
- sortedItems
- } = useSortedItems(props, filteredItems, sortByWithGroups);
- const {
- flatItems
- } = useGroupedItems(sortedItems, groupBy, opened);
- const allItems = computed(() => extractRows(flatItems.value));
- const {
- isSelected,
- select,
- selectAll,
- toggleSelect,
- someSelected,
- allSelected
- } = provideSelection(props, {
- allItems,
- currentPage: allItems
- });
- const {
- isExpanded,
- toggleExpand
- } = provideExpanded(props);
- const headerHeight = computed(() => headers.value.length * 56);
- const {
- containerRef,
- paddingTop,
- paddingBottom,
- computedItems,
- handleItemResize,
- handleScroll
- } = useVirtual(props, flatItems, headerHeight);
- const displayItems = computed(() => computedItems.value.map(item => item.raw));
- useOptions({
- sortBy,
- page: shallowRef(1),
- itemsPerPage: shallowRef(-1),
- groupBy,
- search
- });
- provideDefaults({
- VDataTableRows: {
- hideNoData: toRef(props, 'hideNoData'),
- noDataText: toRef(props, 'noDataText'),
- loading: toRef(props, 'loading'),
- loadingText: toRef(props, 'loadingText')
- }
- });
- const slotProps = computed(() => ({
- sortBy: sortBy.value,
- toggleSort,
- someSelected: someSelected.value,
- allSelected: allSelected.value,
- isSelected,
- select,
- selectAll,
- toggleSelect,
- isExpanded,
- toggleExpand,
- isGroupOpen,
- toggleGroup,
- items: allItems.value,
- groupedItems: flatItems.value,
- columns: columns.value,
- headers: headers.value
- }));
- useRender(() => {
- const [dataTableHeadersProps] = VDataTableHeaders.filterProps(props);
- const [dataTableRowsProps] = VDataTableRows.filterProps(props);
- const [tableProps] = VTable.filterProps(props);
- return createVNode(VTable, mergeProps({
- "class": ['v-data-table', {
- 'v-data-table--loading': props.loading
- }, props.class],
- "style": props.style
- }, tableProps), {
- top: () => slots.top?.(slotProps.value),
- wrapper: () => createVNode("div", {
- "ref": containerRef,
- "onScroll": handleScroll,
- "class": "v-table__wrapper",
- "style": {
- height: convertToUnit(props.height)
- }
- }, [createVNode("table", null, [createVNode("thead", null, [createVNode(VDataTableHeaders, mergeProps(dataTableHeadersProps, {
- "sticky": props.fixedHeader
- }), slots)]), createVNode("tbody", null, [createVNode("tr", {
- "style": {
- height: convertToUnit(paddingTop.value),
- border: 0
- }
- }, [createVNode("td", {
- "colspan": columns.value.length,
- "style": {
- height: convertToUnit(paddingTop.value),
- border: 0
- }
- }, null)]), createVNode(VDataTableRows, mergeProps(dataTableRowsProps, {
- "items": displayItems.value
- }), {
- ...slots,
- item: itemSlotProps => createVNode(VVirtualScrollItem, {
- "key": itemSlotProps.item.index,
- "renderless": true,
- "onUpdate:height": height => handleItemResize(itemSlotProps.item.index, height)
- }, {
- default: _ref2 => {
- let {
- itemRef
- } = _ref2;
- return slots.item?.({
- ...itemSlotProps,
- itemRef
- }) ?? createVNode(VDataTableRow, mergeProps(itemSlotProps.props, {
- "ref": itemRef,
- "key": itemSlotProps.item.index
- }), slots);
- }
- })
- }), createVNode("tr", {
- "style": {
- height: convertToUnit(paddingBottom.value),
- border: 0
- }
- }, [createVNode("td", {
- "colspan": columns.value.length,
- "style": {
- height: convertToUnit(paddingBottom.value),
- border: 0
- }
- }, null)])])])]),
- bottom: () => slots.bottom?.(slotProps.value)
- });
- });
- }
- });
- // Types
- const makeVDataTableServerProps = propsFactory({
- itemsLength: {
- type: [Number, String],
- required: true
- },
- ...makeDataTablePaginateProps(),
- ...makeDataTableProps(),
- ...makeVDataTableFooterProps()
- }, 'VDataTableServer');
- const VDataTableServer = genericComponent()({
- name: 'VDataTableServer',
- props: makeVDataTableServerProps(),
- emits: {
- 'update:modelValue': value => true,
- 'update:page': page => true,
- 'update:itemsPerPage': page => true,
- 'update:sortBy': sortBy => true,
- 'update:options': options => true,
- 'update:expanded': options => true,
- 'update:groupBy': value => true,
- 'click:row': (e, value) => true
- },
- setup(props, _ref) {
- let {
- emit,
- slots
- } = _ref;
- const {
- groupBy
- } = createGroupBy(props);
- const {
- sortBy,
- multiSort,
- mustSort
- } = createSort(props);
- const {
- page,
- itemsPerPage
- } = createPagination(props);
- const itemsLength = computed(() => parseInt(props.itemsLength, 10));
- const {
- columns,
- headers
- } = createHeaders(props, {
- groupBy,
- showSelect: toRef(props, 'showSelect'),
- showExpand: toRef(props, 'showExpand')
- });
- const {
- items
- } = useDataTableItems(props, columns);
- const {
- toggleSort
- } = provideSort({
- sortBy,
- multiSort,
- mustSort,
- page
- });
- const {
- opened,
- isGroupOpen,
- toggleGroup,
- extractRows
- } = provideGroupBy({
- groupBy,
- sortBy
- });
- const {
- pageCount,
- setItemsPerPage
- } = providePagination({
- page,
- itemsPerPage,
- itemsLength
- });
- const {
- flatItems
- } = useGroupedItems(items, groupBy, opened);
- const {
- isSelected,
- select,
- selectAll,
- toggleSelect,
- someSelected,
- allSelected
- } = provideSelection(props, {
- allItems: items,
- currentPage: items
- });
- const {
- isExpanded,
- toggleExpand
- } = provideExpanded(props);
- const itemsWithoutGroups = computed(() => extractRows(items.value));
- useOptions({
- page,
- itemsPerPage,
- sortBy,
- groupBy,
- search: toRef(props, 'search')
- });
- provide('v-data-table', {
- toggleSort,
- sortBy
- });
- provideDefaults({
- VDataTableRows: {
- hideNoData: toRef(props, 'hideNoData'),
- noDataText: toRef(props, 'noDataText'),
- loading: toRef(props, 'loading'),
- loadingText: toRef(props, 'loadingText')
- }
- });
- const slotProps = computed(() => ({
- page: page.value,
- itemsPerPage: itemsPerPage.value,
- sortBy: sortBy.value,
- pageCount: pageCount.value,
- toggleSort,
- setItemsPerPage,
- someSelected: someSelected.value,
- allSelected: allSelected.value,
- isSelected,
- select,
- selectAll,
- toggleSelect,
- isExpanded,
- toggleExpand,
- isGroupOpen,
- toggleGroup,
- items: itemsWithoutGroups.value,
- groupedItems: flatItems.value,
- columns: columns.value,
- headers: headers.value
- }));
- useRender(() => {
- const [dataTableFooterProps] = VDataTableFooter.filterProps(props);
- const [dataTableHeadersProps] = VDataTableHeaders.filterProps(props);
- const [dataTableRowsProps] = VDataTableRows.filterProps(props);
- const [tableProps] = VTable.filterProps(props);
- return createVNode(VTable, mergeProps({
- "class": ['v-data-table', {
- 'v-data-table--loading': props.loading
- }, props.class],
- "style": props.style
- }, tableProps), {
- top: () => slots.top?.(slotProps.value),
- default: () => slots.default ? slots.default(slotProps.value) : createVNode(Fragment, null, [slots.colgroup?.(slotProps.value), createVNode("thead", {
- "class": "v-data-table__thead",
- "role": "rowgroup"
- }, [createVNode(VDataTableHeaders, mergeProps(dataTableHeadersProps, {
- "sticky": props.fixedHeader
- }), slots)]), slots.thead?.(slotProps.value), createVNode("tbody", {
- "class": "v-data-table__tbody",
- "role": "rowgroup"
- }, [slots.body ? slots.body(slotProps.value) : createVNode(VDataTableRows, mergeProps(dataTableRowsProps, {
- "items": flatItems.value
- }), slots)]), slots.tbody?.(slotProps.value), slots.tfoot?.(slotProps.value)]),
- bottom: () => slots.bottom ? slots.bottom(slotProps.value) : createVNode(VDataTableFooter, dataTableFooterProps, {
- prepend: slots['footer.prepend']
- })
- });
- });
- }
- });
- // Utilities
- // Types
- const firstDay = {
- '001': 1,
- AD: 1,
- AE: 6,
- AF: 6,
- AG: 0,
- AI: 1,
- AL: 1,
- AM: 1,
- AN: 1,
- AR: 1,
- AS: 0,
- AT: 1,
- AU: 1,
- AX: 1,
- AZ: 1,
- BA: 1,
- BD: 0,
- BE: 1,
- BG: 1,
- BH: 6,
- BM: 1,
- BN: 1,
- BR: 0,
- BS: 0,
- BT: 0,
- BW: 0,
- BY: 1,
- BZ: 0,
- CA: 0,
- CH: 1,
- CL: 1,
- CM: 1,
- CN: 1,
- CO: 0,
- CR: 1,
- CY: 1,
- CZ: 1,
- DE: 1,
- DJ: 6,
- DK: 1,
- DM: 0,
- DO: 0,
- DZ: 6,
- EC: 1,
- EE: 1,
- EG: 6,
- ES: 1,
- ET: 0,
- FI: 1,
- FJ: 1,
- FO: 1,
- FR: 1,
- GB: 1,
- 'GB-alt-variant': 0,
- GE: 1,
- GF: 1,
- GP: 1,
- GR: 1,
- GT: 0,
- GU: 0,
- HK: 0,
- HN: 0,
- HR: 1,
- HU: 1,
- ID: 0,
- IE: 1,
- IL: 0,
- IN: 0,
- IQ: 6,
- IR: 6,
- IS: 1,
- IT: 1,
- JM: 0,
- JO: 6,
- JP: 0,
- KE: 0,
- KG: 1,
- KH: 0,
- KR: 0,
- KW: 6,
- KZ: 1,
- LA: 0,
- LB: 1,
- LI: 1,
- LK: 1,
- LT: 1,
- LU: 1,
- LV: 1,
- LY: 6,
- MC: 1,
- MD: 1,
- ME: 1,
- MH: 0,
- MK: 1,
- MM: 0,
- MN: 1,
- MO: 0,
- MQ: 1,
- MT: 0,
- MV: 5,
- MX: 0,
- MY: 1,
- MZ: 0,
- NI: 0,
- NL: 1,
- NO: 1,
- NP: 0,
- NZ: 1,
- OM: 6,
- PA: 0,
- PE: 0,
- PH: 0,
- PK: 0,
- PL: 1,
- PR: 0,
- PT: 0,
- PY: 0,
- QA: 6,
- RE: 1,
- RO: 1,
- RS: 1,
- RU: 1,
- SA: 0,
- SD: 6,
- SE: 1,
- SG: 0,
- SI: 1,
- SK: 1,
- SM: 1,
- SV: 0,
- SY: 6,
- TH: 0,
- TJ: 1,
- TM: 1,
- TR: 1,
- TT: 0,
- TW: 0,
- UA: 1,
- UM: 0,
- US: 0,
- UY: 1,
- UZ: 1,
- VA: 1,
- VE: 0,
- VI: 0,
- VN: 1,
- WS: 0,
- XK: 1,
- YE: 0,
- ZA: 0,
- ZW: 0
- };
- function getWeekArray(date, locale) {
- const weeks = [];
- let currentWeek = [];
- const firstDayOfMonth = startOfMonth(date);
- const lastDayOfMonth = endOfMonth(date);
- const firstDayWeekIndex = firstDayOfMonth.getDay() - firstDay[locale.slice(-2).toUpperCase()];
- const lastDayWeekIndex = lastDayOfMonth.getDay() - firstDay[locale.slice(-2).toUpperCase()];
- for (let i = 0; i < firstDayWeekIndex; i++) {
- const adjacentDay = new Date(firstDayOfMonth);
- adjacentDay.setDate(adjacentDay.getDate() - (firstDayWeekIndex - i));
- currentWeek.push(adjacentDay);
- }
- for (let i = 1; i <= lastDayOfMonth.getDate(); i++) {
- const day = new Date(date.getFullYear(), date.getMonth(), i);
- // Add the day to the current week
- currentWeek.push(day);
- // If the current week has 7 days, add it to the weeks array and start a new week
- if (currentWeek.length === 7) {
- weeks.push(currentWeek);
- currentWeek = [];
- }
- }
- for (let i = 1; i < 7 - lastDayWeekIndex; i++) {
- const adjacentDay = new Date(lastDayOfMonth);
- adjacentDay.setDate(adjacentDay.getDate() + i);
- currentWeek.push(adjacentDay);
- }
- weeks.push(currentWeek);
- return weeks;
- }
- function startOfMonth(date) {
- return new Date(date.getFullYear(), date.getMonth(), 1);
- }
- function endOfMonth(date) {
- return new Date(date.getFullYear(), date.getMonth() + 1, 0);
- }
- function parseLocalDate(value) {
- const parts = value.split('-').map(Number);
- // new Date() uses local time zone when passing individual date component values
- return new Date(parts[0], parts[1] - 1, parts[2]);
- }
- const _YYYMMDD = /([12]\d{3}-([1-9]|0[1-9]|1[0-2])-([1-9]|0[1-9]|[12]\d|3[01]))/;
- function date(value) {
- if (value == null) return new Date();
- if (value instanceof Date) return value;
- if (typeof value === 'string') {
- let parsed;
- if (_YYYMMDD.test(value)) {
- return parseLocalDate(value);
- } else {
- parsed = Date.parse(value);
- }
- if (!isNaN(parsed)) return new Date(parsed);
- }
- return null;
- }
- const sundayJanuarySecond2000 = new Date(2000, 0, 2);
- function getWeekdays(locale) {
- const daysFromSunday = firstDay[locale.slice(-2).toUpperCase()];
- return createRange(7).map(i => {
- const weekday = new Date(sundayJanuarySecond2000);
- weekday.setDate(sundayJanuarySecond2000.getDate() + daysFromSunday + i);
- return new Intl.DateTimeFormat(locale, {
- weekday: 'short'
- }).format(weekday);
- });
- }
- function format(value, formatString, locale) {
- const date = new Date(value);
- let options = {};
- switch (formatString) {
- case 'fullDateWithWeekday':
- options = {
- weekday: 'long',
- day: 'numeric',
- month: 'long',
- year: 'numeric'
- };
- break;
- case 'normalDateWithWeekday':
- options = {
- weekday: 'short',
- day: 'numeric',
- month: 'short'
- };
- break;
- case 'keyboardDate':
- options = {};
- break;
- case 'monthAndDate':
- options = {
- month: 'long',
- day: 'numeric'
- };
- break;
- case 'monthAndYear':
- options = {
- month: 'long',
- year: 'numeric'
- };
- break;
- case 'dayOfMonth':
- options = {
- day: 'numeric'
- };
- break;
- default:
- options = {
- timeZone: 'UTC',
- timeZoneName: 'short'
- };
- }
- return new Intl.DateTimeFormat(locale, options).format(date);
- }
- function addDays(date, amount) {
- const d = new Date(date);
- d.setDate(d.getDate() + amount);
- return d;
- }
- function addMonths(date, amount) {
- const d = new Date(date);
- d.setMonth(d.getMonth() + amount);
- return d;
- }
- function getYear(date) {
- return date.getFullYear();
- }
- function getMonth(date) {
- return date.getMonth();
- }
- function startOfYear(date) {
- return new Date(date.getFullYear(), 0, 1);
- }
- function endOfYear(date) {
- return new Date(date.getFullYear(), 11, 31);
- }
- function isWithinRange(date, range) {
- return isAfter(date, range[0]) && isBefore(date, range[1]);
- }
- function isValid(date) {
- const d = new Date(date);
- return d instanceof Date && !isNaN(d.getTime());
- }
- function isAfter(date, comparing) {
- return date.getTime() > comparing.getTime();
- }
- function isBefore(date, comparing) {
- return date.getTime() < comparing.getTime();
- }
- function isEqual(date, comparing) {
- return date.getTime() === comparing.getTime();
- }
- function isSameDay(date, comparing) {
- return date.getDate() === comparing.getDate() && date.getMonth() === comparing.getMonth() && date.getFullYear() === comparing.getFullYear();
- }
- function isSameMonth(date, comparing) {
- return date.getMonth() === comparing.getMonth() && date.getFullYear() === comparing.getFullYear();
- }
- function getDiff(date, comparing, unit) {
- const d = new Date(date);
- const c = new Date(comparing);
- if (unit === 'month') {
- return d.getMonth() - c.getMonth() + (d.getFullYear() - c.getFullYear()) * 12;
- }
- return Math.floor((d.getTime() - c.getTime()) / (1000 * 60 * 60 * 24));
- }
- function setYear(date, year) {
- const d = new Date(date);
- d.setFullYear(year);
- return d;
- }
- class VuetifyDateAdapter {
- constructor(options) {
- this.locale = options.locale;
- }
- date(value) {
- return date(value);
- }
- toJsDate(date) {
- return date;
- }
- addDays(date, amount) {
- return addDays(date, amount);
- }
- addMonths(date, amount) {
- return addMonths(date, amount);
- }
- getWeekArray(date) {
- return getWeekArray(date, this.locale);
- }
- startOfMonth(date) {
- return startOfMonth(date);
- }
- endOfMonth(date) {
- return endOfMonth(date);
- }
- format(date, formatString) {
- return format(date, formatString, this.locale);
- }
- isEqual(date, comparing) {
- return isEqual(date, comparing);
- }
- isValid(date) {
- return isValid(date);
- }
- isWithinRange(date, range) {
- return isWithinRange(date, range);
- }
- isAfter(date, comparing) {
- return isAfter(date, comparing);
- }
- isBefore(date, comparing) {
- return !isAfter(date, comparing) && !isEqual(date, comparing);
- }
- isSameDay(date, comparing) {
- return isSameDay(date, comparing);
- }
- isSameMonth(date, comparing) {
- return isSameMonth(date, comparing);
- }
- setYear(date, year) {
- return setYear(date, year);
- }
- getDiff(date, comparing, unit) {
- return getDiff(date, comparing, unit);
- }
- getWeekdays() {
- return getWeekdays(this.locale);
- }
- getYear(date) {
- return getYear(date);
- }
- getMonth(date) {
- return getMonth(date);
- }
- startOfYear(date) {
- return startOfYear(date);
- }
- endOfYear(date) {
- return endOfYear(date);
- }
- }
- // Composables
- // Types
- const DateAdapterSymbol = Symbol.for('vuetify:date-adapter');
- function createDate(options) {
- return mergeDeep({
- adapter: VuetifyDateAdapter,
- locale: {
- af: 'af-ZA',
- // ar: '', # not the same value for all variants
- bg: 'bg-BG',
- ca: 'ca-ES',
- ckb: '',
- cs: '',
- de: 'de-DE',
- el: 'el-GR',
- en: 'en-US',
- // es: '', # not the same value for all variants
- et: 'et-EE',
- fa: 'fa-IR',
- fi: 'fi-FI',
- // fr: '', #not the same value for all variants
- hr: 'hr-HR',
- hu: 'hu-HU',
- he: 'he-IL',
- id: 'id-ID',
- it: 'it-IT',
- ja: 'ja-JP',
- ko: 'ko-KR',
- lv: 'lv-LV',
- lt: 'lt-LT',
- nl: 'nl-NL',
- no: 'nn-NO',
- pl: 'pl-PL',
- pt: 'pt-PT',
- ro: 'ro-RO',
- ru: 'ru-RU',
- sk: 'sk-SK',
- sl: 'sl-SI',
- srCyrl: 'sr-SP',
- srLatn: 'sr-SP',
- sv: 'sv-SE',
- th: 'th-TH',
- tr: 'tr-TR',
- az: 'az-AZ',
- uk: 'uk-UA',
- vi: 'vi-VN',
- zhHans: 'zh-CN',
- zhHant: 'zh-TW'
- }
- }, options);
- }
- function useDate() {
- const date = inject$1(DateAdapterSymbol);
- const locale = useLocale();
- if (!date) throw new Error('[Vuetify] Could not find injected date');
- const instance = reactive(typeof date.adapter === 'function'
- // eslint-disable-next-line new-cap
- ? new date.adapter({
- locale: date.locale?.[locale.current.value] ?? locale.current.value
- }) : date.adapter);
- watch(locale.current, value => {
- const newLocale = date.locale ? date.locale[value] : value;
- instance.locale = newLocale ?? instance.locale;
- });
- return instance;
- }
- function toIso(adapter, value) {
- const date = adapter.toJsDate(value);
- return `${date.getFullYear()}-${date.getMonth() + 1}-${date.getDate()}`;
- }
- function getMondayOfFirstWeekOfYear(year) {
- return new Date(year, 0, 1);
- }
- // https://stackoverflow.com/questions/274861/how-do-i-calculate-the-week-number-given-a-date/275024#275024
- function getWeek(adapter, value) {
- const date = adapter.toJsDate(value);
- let year = date.getFullYear();
- let d1w1 = getMondayOfFirstWeekOfYear(year);
- if (date < d1w1) {
- year = year - 1;
- d1w1 = getMondayOfFirstWeekOfYear(year);
- } else {
- const tv = getMondayOfFirstWeekOfYear(year + 1);
- if (date >= tv) {
- year = year + 1;
- d1w1 = tv;
- }
- }
- const diffTime = Math.abs(date.getTime() - d1w1.getTime());
- const diffDays = Math.ceil(diffTime / (1000 * 60 * 60 * 24));
- return Math.floor(diffDays / 7) + 1;
- }
- // Composables
- // Types
- const makeDateProps = propsFactory({
- modelValue: {
- type: null,
- default: () => []
- },
- displayDate: {
- type: null,
- default: null
- },
- inputMode: {
- type: String,
- default: 'calendar'
- },
- viewMode: {
- type: String,
- default: 'month'
- },
- format: String
- }, 'date');
- const dateEmits = {
- 'update:modelValue': date => true,
- 'update:displayDate': date => true,
- 'update:focused': focused => true,
- 'update:inputMode': inputMode => true,
- 'update:viewMode': viewMode => true
- };
- function createDateInput(props, isRange) {
- const adapter = useDate();
- const model = useProxiedModel(props, 'modelValue', [], v => {
- if (v == null) return [];
- const arr = wrapInArray(v).filter(v => !!v);
- return arr.map(adapter.date);
- }, v => {
- const arr = wrapInArray(v);
- const formatted = props.format ? arr.map(d => adapter.format(d, props.format)) : arr;
- if (isRange) return formatted;
- return formatted[0];
- });
- const inputMode = useProxiedModel(props, 'inputMode');
- const viewMode = useProxiedModel(props, 'viewMode');
- const displayDate = useProxiedModel(props, 'displayDate', model.value.length ? model.value[0] : adapter.date());
- function parseKeyboardDate(input, fallback) {
- const date = adapter.date(input);
- return adapter.isValid(date) ? date : fallback;
- }
- return {
- model,
- adapter,
- inputMode,
- viewMode,
- displayDate,
- parseKeyboardDate
- };
- }
- const makeVDatePickerControlsProps = propsFactory({
- nextIcon: {
- type: [String],
- default: '$next'
- },
- prevIcon: {
- type: [String],
- default: '$prev'
- },
- expandIcon: {
- type: [String],
- default: '$expand'
- },
- collapseIcon: {
- type: [String],
- default: '$collapse'
- },
- range: {
- default: false,
- type: [Boolean, String],
- validator: v => v === false || ['start', 'end'].includes(v)
- },
- ...omit(makeDateProps(), ['modelValue', 'inputMode'])
- }, 'VDatePickerControls');
- const VDatePickerControls = genericComponent()({
- name: 'VDatePickerControls',
- props: makeVDatePickerControlsProps(),
- emits: {
- ...omit(dateEmits, ['update:modelValue', 'update:inputMode'])
- },
- setup(props, _ref) {
- let {
- emit
- } = _ref;
- const adapter = useDate();
- const monthAndYear = computed(() => {
- const month = props.range === 'end' ? adapter.addMonths(props.displayDate, 1) : props.displayDate;
- return adapter.format(month, 'monthAndYear');
- });
- useRender(() => {
- const prevBtn = createVNode(VBtn, {
- "variant": "text",
- "icon": props.prevIcon,
- "onClick": () => emit('update:displayDate', adapter.addMonths(props.displayDate, -1))
- }, null);
- const nextBtn = createVNode(VBtn, {
- "variant": "text",
- "icon": props.nextIcon,
- "onClick": () => emit('update:displayDate', adapter.addMonths(props.displayDate, 1))
- }, null);
- return createVNode("div", {
- "class": "v-date-picker-controls"
- }, [props.viewMode === 'month' && props.range === 'start' && prevBtn, !!props.range && createVNode(VSpacer, {
- "key": "range-spacer"
- }, null), createVNode("div", {
- "class": "v-date-picker-controls__date"
- }, [monthAndYear.value]), createVNode(VBtn, {
- "key": "expand-btn",
- "variant": "text",
- "icon": props.viewMode === 'month' ? props.expandIcon : props.collapseIcon,
- "onClick": () => emit('update:viewMode', props.viewMode === 'month' ? 'year' : 'month')
- }, null), createVNode(VSpacer, null, null), props.viewMode === 'month' && !props.range && createVNode("div", {
- "class": "v-date-picker-controls__month",
- "key": "month-buttons"
- }, [prevBtn, nextBtn]), props.viewMode === 'month' && props.range === 'end' && nextBtn]);
- });
- return {};
- }
- });
- // Composables
- // Types
- const DatePickerSymbol = Symbol.for('vuetify:date-picker');
- function createDatePicker(props) {
- const hoverDate = ref();
- const hoverMonth = ref();
- const isDragging = ref(false);
- const dragHandle = ref(null);
- const hasScrolled = ref(false);
- provide(DatePickerSymbol, {
- hoverDate,
- hoverMonth,
- isDragging,
- dragHandle,
- hasScrolled
- });
- // TODO: This composable should probably not live in DateInput
- const {
- model,
- displayDate,
- viewMode,
- inputMode
- } = createDateInput(props, !!props.multiple);
- return {
- hoverDate,
- hoverMonth,
- isDragging,
- dragHandle,
- hasScrolled,
- model,
- displayDate,
- viewMode,
- inputMode
- };
- }
- function useDatePicker() {
- const datePicker = inject$1(DatePickerSymbol);
- if (!datePicker) throw new Error('foo');
- return datePicker;
- }
- const makeVDatePickerMonthProps = propsFactory({
- color: String,
- showAdjacentMonths: Boolean,
- hideWeekdays: Boolean,
- showWeek: Boolean,
- hoverDate: null,
- multiple: Boolean,
- side: {
- type: String
- },
- ...omit(makeDateProps(), ['inputMode', 'viewMode'])
- }, 'VDatePickerMonth');
- const VDatePickerMonth = genericComponent()({
- name: 'VDatePickerMonth',
- props: makeVDatePickerMonthProps({
- color: 'surface-variant'
- }),
- emits: {
- ...omit(dateEmits, ['update:inputMode', 'update:viewMode']),
- 'update:hoverDate': date => true
- },
- setup(props, _ref) {
- let {
- emit,
- slots
- } = _ref;
- const adapter = useDate();
- const {
- isDragging,
- dragHandle,
- hasScrolled
- } = useDatePicker();
- const month = computed(() => props.displayDate);
- const findClosestDate = (date, dates) => {
- const {
- isSameDay,
- getDiff
- } = adapter;
- const [startDate, endDate] = dates;
- if (isSameDay(startDate, endDate)) {
- return getDiff(date, startDate, 'days') > 0 ? endDate : startDate;
- }
- const distStart = Math.abs(getDiff(date, startDate));
- const distEnd = Math.abs(getDiff(date, endDate));
- return distStart < distEnd ? startDate : endDate;
- };
- // const hoverRange = computed<[any, any] | null>(() => {
- // if (!props.hoverDate) return null
- // const closestDate = findClosestDate(props.hoverDate, props.modelValue)
- // if (!closestDate) return null
- // return adapter.isAfter(props.hoverDate, closestDate) ? [closestDate, props.hoverDate] : [props.hoverDate, closestDate]
- // })
- const weeksInMonth = computed(() => {
- const weeks = adapter.getWeekArray(month.value);
- const days = weeks.flat();
- // Make sure there's always 6 weeks in month (6 * 7 days)
- // But only do it if we're not hiding adjacent months?
- const daysInMonth = 6 * 7;
- if (days.length < daysInMonth && props.showAdjacentMonths) {
- const lastDay = days[days.length - 1];
- let week = [];
- for (let day = 1; day <= daysInMonth - days.length; day++) {
- week.push(adapter.addDays(lastDay, day));
- if (day % 7 === 0) {
- weeks.push(week);
- week = [];
- }
- }
- }
- return weeks;
- });
- const daysInMonth = computed(() => {
- const validDates = props.modelValue.filter(v => !!v);
- const isRange = validDates.length > 1;
- const days = weeksInMonth.value.flat();
- const today = adapter.date();
- const startDate = validDates[0];
- const endDate = validDates[1];
- return days.map((date, index) => {
- const isStart = startDate && adapter.isSameDay(date, startDate);
- const isEnd = endDate && adapter.isSameDay(date, endDate);
- const isAdjacent = !adapter.isSameMonth(date, month.value);
- const isSame = validDates.length === 2 && adapter.isSameDay(startDate, endDate);
- return {
- date,
- isoDate: toIso(adapter, date),
- formatted: adapter.format(date, 'keyboardDate'),
- year: adapter.getYear(date),
- month: adapter.getMonth(date),
- isWeekStart: index % 7 === 0,
- isWeekEnd: index % 7 === 6,
- isSelected: isStart || isEnd,
- isStart,
- isEnd,
- isToday: adapter.isSameDay(date, today),
- isAdjacent,
- isHidden: isAdjacent && !props.showAdjacentMonths,
- inRange: isRange && !isSame && (isStart || isEnd || validDates.length === 2 && adapter.isWithinRange(date, validDates)),
- // isHovered: props.hoverDate === date,
- // inHover: hoverRange.value && isWithinRange(date, hoverRange.value),
- isHovered: false,
- inHover: false,
- localized: adapter.format(date, 'dayOfMonth')
- };
- });
- });
- const weeks = computed(() => {
- return weeksInMonth.value.map(week => {
- return getWeek(adapter, week[0]);
- });
- });
- const {
- backgroundColorClasses,
- backgroundColorStyles
- } = useBackgroundColor(props, 'color');
- function selectDate(date) {
- let newModel = props.modelValue.slice();
- if (props.multiple) {
- if (isDragging.value && dragHandle.value != null) {
- const otherIndex = (dragHandle.value + 1) % 2;
- const fn = otherIndex === 0 ? 'isBefore' : 'isAfter';
- if (adapter[fn](date, newModel[otherIndex])) {
- newModel[dragHandle.value] = newModel[otherIndex];
- newModel[otherIndex] = date;
- dragHandle.value = otherIndex;
- } else {
- newModel[dragHandle.value] = date;
- }
- } else {
- if (newModel.find(d => adapter.isSameDay(d, date))) {
- newModel = newModel.filter(v => !adapter.isSameDay(v, date));
- } else if (newModel.length === 2) {
- let index;
- if (!props.side || adapter.isSameMonth(newModel[0], newModel[1])) {
- const closest = findClosestDate(date, newModel);
- index = newModel.indexOf(closest);
- } else {
- index = props.side === 'start' ? 0 : props.side === 'end' ? 1 : undefined;
- }
- newModel = newModel.map((v, i) => i === index ? date : v);
- } else {
- if (newModel[0] && adapter.isBefore(newModel[0], date)) {
- newModel = [newModel[0], date];
- } else {
- newModel = [date, newModel[0]];
- }
- }
- }
- } else {
- newModel = [date];
- }
- emit('update:modelValue', newModel.filter(v => !!v));
- }
- const daysRef = ref();
- function findElement(el) {
- if (!el || el === daysRef.value) return null;
- if ('vDate' in el.dataset) {
- return adapter.date(el.dataset.vDate);
- }
- return findElement(el.parentElement);
- }
- function findDate(e) {
- const x = 'changedTouches' in e ? e.changedTouches[0]?.clientX : e.clientX;
- const y = 'changedTouches' in e ? e.changedTouches[0]?.clientY : e.clientY;
- const el = document.elementFromPoint(x, y);
- return findElement(el);
- }
- let canDrag = false;
- function handleMousedown(e) {
- hasScrolled.value = false;
- const selected = findDate(e);
- if (!selected) return;
- const modelIndex = props.modelValue.findIndex(d => adapter.isEqual(d, selected));
- if (modelIndex >= 0) {
- canDrag = true;
- dragHandle.value = modelIndex;
- window.addEventListener('touchmove', handleTouchmove, {
- passive: false
- });
- window.addEventListener('mousemove', handleTouchmove, {
- passive: false
- });
- e.preventDefault();
- }
- window.addEventListener('touchend', handleTouchend, {
- passive: false
- });
- window.addEventListener('mouseup', handleTouchend, {
- passive: false
- });
- }
- function handleTouchmove(e) {
- if (!canDrag) return;
- e.preventDefault();
- isDragging.value = true;
- const over = findDate(e);
- if (!over) return;
- selectDate(over);
- }
- function handleTouchend(e) {
- if (e.cancelable) e.preventDefault();
- window.removeEventListener('touchmove', handleTouchmove);
- window.removeEventListener('mousemove', handleTouchmove);
- window.removeEventListener('touchend', handleTouchend);
- window.removeEventListener('mouseup', handleTouchend);
- const end = findDate(e);
- if (!end) return;
- if (!hasScrolled.value) {
- selectDate(end);
- }
- isDragging.value = false;
- dragHandle.value = null;
- canDrag = false;
- }
- return () => createVNode("div", {
- "class": "v-date-picker-month"
- }, [props.showWeek && createVNode("div", {
- "key": "weeks",
- "class": "v-date-picker-month__weeks"
- }, [!props.hideWeekdays && createVNode("div", {
- "key": "hide-week-days",
- "class": "v-date-picker-month__day"
- }, [createTextVNode("\xA0")]), weeks.value.map(week => createVNode("div", {
- "class": ['v-date-picker-month__day', 'v-date-picker-month__day--adjacent']
- }, [week]))]), createVNode("div", {
- "ref": daysRef,
- "class": "v-date-picker-month__days",
- "onMousedown": handleMousedown,
- "onTouchstart": handleMousedown
- }, [!props.hideWeekdays && adapter.getWeekdays().map(weekDay => createVNode("div", {
- "class": ['v-date-picker-month__day', 'v-date-picker-month__weekday']
- }, [weekDay.charAt(0)])), daysInMonth.value.map((item, index) => createVNode("div", {
- "class": ['v-date-picker-month__day', {
- 'v-date-picker-month__day--selected': item.isSelected,
- 'v-date-picker-month__day--start': item.isStart,
- 'v-date-picker-month__day--end': item.isEnd,
- 'v-date-picker-month__day--adjacent': item.isAdjacent,
- 'v-date-picker-month__day--hide-adjacent': item.isHidden,
- 'v-date-picker-month__day--week-start': item.isWeekStart,
- 'v-date-picker-month__day--week-end': item.isWeekEnd,
- 'v-date-picker-month__day--hovered': item.isHovered
- }],
- "data-v-date": !item.isHidden ? item.isoDate : undefined
- }, [item.inRange && createVNode("div", {
- "key": "in-range",
- "class": ['v-date-picker-month__day--range', backgroundColorClasses.value],
- "style": backgroundColorStyles.value
- }, null), item.inHover && !item.isStart && !item.isEnd && !item.isHovered && !item.inRange && createVNode("div", {
- "key": "in-hover",
- "class": "v-date-picker-month__day--hover"
- }, null), (props.showAdjacentMonths || !item.isAdjacent) && createVNode(VBtn, {
- "icon": true,
- "ripple": false,
- "variant": (item.isToday || item.isHovered) && !item.isSelected ? 'outlined' : 'flat',
- "active": item.isSelected,
- "color": item.isSelected || item.isToday ? props.color : item.isHovered ? undefined : 'transparent'
- }, {
- default: () => [item.localized]
- })]))])]);
- }
- });
- const makeVDatePickerYearsProps = propsFactory({
- color: String,
- min: Number,
- max: Number,
- height: [String, Number],
- displayDate: null
- }, 'VDatePickerYears');
- const VDatePickerYears = genericComponent()({
- name: 'VDatePickerYears',
- props: makeVDatePickerYearsProps(),
- emits: {
- 'update:displayDate': date => true,
- 'update:viewMode': date => true
- },
- setup(props, _ref) {
- let {
- emit
- } = _ref;
- const adapter = useDate();
- const displayYear = computed(() => adapter.getYear(props.displayDate ?? new Date()));
- const years = computed(() => {
- const min = props.min ?? displayYear.value - 50 - 2;
- const max = props.max ?? displayYear.value + 50;
- return createRange(max - min, min);
- });
- const yearRef = ref();
- onMounted(() => {
- yearRef.value?.$el.scrollIntoView({
- block: 'center'
- });
- });
- useRender(() => createVNode("div", {
- "class": "v-date-picker-years",
- "style": {
- height: convertToUnit(props.height)
- }
- }, [createVNode("div", {
- "class": "v-date-picker-years__content"
- }, [years.value.map(year => createVNode(VBtn, {
- "ref": year === displayYear.value ? yearRef : undefined,
- "variant": year === displayYear.value ? 'flat' : 'text',
- "rounded": "xl",
- "active": year === displayYear.value,
- "color": year === displayYear.value ? props.color : undefined,
- "onClick": () => {
- emit('update:displayDate', adapter.setYear(props.displayDate, year));
- emit('update:viewMode', 'month');
- }
- }, {
- default: () => [year]
- }))])]));
- return {};
- }
- });
- // Types
- const makeVDateCardProps = propsFactory({
- cancelText: {
- type: String,
- default: '$vuetify.datePicker.cancel'
- },
- okText: {
- type: String,
- default: '$vuetify.datePicker.ok'
- },
- inputMode: {
- type: String,
- default: 'calendar'
- },
- hideActions: Boolean,
- ...makeVDatePickerControlsProps(),
- ...makeVDatePickerMonthProps(),
- ...makeVDatePickerYearsProps(),
- ...makeTransitionProps({
- transition: {
- component: VFadeTransition,
- leaveAbsolute: true
- }
- })
- }, 'VDateCard');
- const VDateCard = genericComponent()({
- name: 'VDateCard',
- props: makeVDateCardProps(),
- emits: {
- save: () => true,
- cancel: () => true,
- 'update:displayDate': value => true,
- 'update:inputMode': value => true,
- 'update:modelValue': value => true,
- 'update:viewMode': mode => true
- },
- setup(props, _ref) {
- let {
- emit,
- slots
- } = _ref;
- const model = useProxiedModel(props, 'modelValue');
- const {
- t
- } = useLocale();
- createDatePicker(props);
- function onDisplayUpdate(val) {
- emit('update:displayDate', val);
- }
- function onViewModeUpdate(val) {
- emit('update:viewMode', val);
- }
- function onSave() {
- emit('update:modelValue', model.value);
- emit('save');
- }
- function onCancel() {
- emit('cancel');
- }
- useRender(() => {
- const [cardProps] = VCard.filterProps(props);
- const [datePickerControlsProps] = VDatePickerControls.filterProps(props);
- const [datePickerMonthProps] = VDatePickerMonth.filterProps(props);
- const [datePickerYearsProps] = VDatePickerYears.filterProps(props);
- const hasActions = !props.hideActions || !!slots.actions;
- return createVNode(VCard, mergeProps(cardProps, {
- "class": "v-date-card"
- }), {
- ...slots,
- default: () => createVNode(Fragment, null, [createVNode(VDatePickerControls, mergeProps(datePickerControlsProps, {
- "onUpdate:displayDate": onDisplayUpdate,
- "onUpdate:viewMode": onViewModeUpdate
- }), null), createVNode(MaybeTransition, {
- "transition": props.transition
- }, {
- default: () => [props.viewMode === 'month' ? createVNode(VDatePickerMonth, mergeProps(datePickerMonthProps, {
- "modelValue": model.value,
- "onUpdate:modelValue": $event => model.value = $event,
- "onUpdate:displayDate": onDisplayUpdate
- }), null) : createVNode(VDatePickerYears, mergeProps(datePickerYearsProps, {
- "onUpdate:displayDate": onDisplayUpdate,
- "onUpdate:viewMode": onViewModeUpdate
- }), null)]
- })]),
- actions: !hasActions ? undefined : () => createVNode(Fragment, null, [slots.actions?.() ?? createVNode(Fragment, null, [createVNode(VBtn, {
- "onClick": onCancel,
- "text": t(props.cancelText)
- }, null), createVNode(VBtn, {
- "onClick": onSave,
- "text": t(props.okText)
- }, null)])])
- });
- });
- return {};
- }
- });
- // Types
- const makeVDatePickerHeaderProps = propsFactory({
- appendIcon: String,
- color: String,
- header: String,
- transition: String
- }, 'VDatePickerHeader');
- const VDatePickerHeader = genericComponent()({
- name: 'VDatePickerHeader',
- props: makeVDatePickerHeaderProps(),
- emits: {
- 'click:append': () => true
- },
- setup(props, _ref) {
- let {
- emit,
- slots
- } = _ref;
- const {
- backgroundColorClasses,
- backgroundColorStyles
- } = useBackgroundColor(props, 'color');
- function onClickAppend() {
- emit('click:append');
- }
- useRender(() => {
- const hasContent = !!(slots.default || props.header);
- const hasAppend = !!(slots.append || props.appendIcon);
- return createVNode("div", {
- "class": ['v-date-picker-header', backgroundColorClasses.value],
- "style": backgroundColorStyles.value
- }, [slots.prepend && createVNode("div", {
- "key": "prepend",
- "class": "v-date-picker-header__prepend"
- }, [slots.prepend()]), hasContent && createVNode(MaybeTransition, {
- "key": "content",
- "name": props.transition
- }, {
- default: () => [createVNode("div", {
- "key": props.header,
- "class": "v-date-picker-header__content"
- }, [slots.default?.() ?? props.header])]
- }), hasAppend && createVNode("div", {
- "class": "v-date-picker-header__append"
- }, [!slots.append ? createVNode(VBtn, {
- "key": "append-btn",
- "icon": props.appendIcon,
- "variant": "text",
- "onClick": onClickAppend
- }, null) : createVNode(VDefaultsProvider, {
- "key": "append-defaults",
- "disabled": !props.appendIcon,
- "defaults": {
- VBtn: {
- icon: props.appendIcon,
- variant: 'text'
- }
- }
- }, {
- default: () => [slots.append?.()]
- })])]);
- });
- return {};
- }
- });
- // Utilities
- const VPickerTitle = createSimpleFunctional('v-picker-title');
- // Types
- const makeVPickerProps = propsFactory({
- landscape: Boolean,
- title: String,
- ...omit(makeVSheetProps(), ['color'])
- }, 'VPicker');
- const VPicker = genericComponent()({
- name: 'VPicker',
- props: makeVPickerProps(),
- setup(props, _ref) {
- let {
- slots
- } = _ref;
- useRender(() => {
- const [sheetProps] = VSheet.filterProps(props);
- const hasTitle = !!(props.title || slots.title);
- return createVNode(VSheet, mergeProps(sheetProps, {
- "class": ['v-picker', {
- 'v-picker--landscape': props.landscape,
- 'v-picker--with-actions': !!slots.actions
- }, props.class],
- "style": props.style
- }), {
- default: () => [hasTitle && createVNode(VPickerTitle, {
- "key": "picker-title"
- }, {
- default: () => [slots.title?.() ?? props.title]
- }), slots.header && createVNode("div", {
- "class": "v-picker__header"
- }, [slots.header()]), createVNode("div", {
- "class": "v-picker__body"
- }, [slots.default?.()]), slots.actions?.()[0]?.children && createVNode("div", {
- "class": "v-picker__actions"
- }, [slots.actions()])]
- });
- });
- return {};
- }
- });
- // Types
- const makeVDatePickerProps = propsFactory({
- calendarIcon: {
- type: String,
- default: '$calendar'
- },
- keyboardIcon: {
- type: String,
- default: '$edit'
- },
- cancelText: {
- type: String,
- default: '$vuetify.datePicker.cancel'
- },
- okText: {
- type: String,
- default: '$vuetify.datePicker.ok'
- },
- inputText: {
- type: String,
- default: '$vuetify.datePicker.input.placeholder'
- },
- header: {
- type: String,
- default: '$vuetify.datePicker.header'
- },
- hideActions: Boolean,
- ...makeDateProps(),
- ...makeVDatePickerControlsProps(),
- ...makeVDatePickerMonthProps(),
- ...makeVDatePickerYearsProps(),
- ...makeVPickerProps({
- title: '$vuetify.datePicker.title'
- })
- }, 'VDatePicker');
- const VDatePicker = genericComponent()({
- name: 'VDatePicker',
- props: makeVDatePickerProps(),
- emits: {
- 'click:cancel': () => true,
- 'click:save': () => true,
- ...dateEmits
- },
- setup(props, _ref) {
- let {
- emit,
- slots
- } = _ref;
- const adapter = useDate();
- const {
- t
- } = useLocale();
- const {
- model,
- displayDate,
- viewMode,
- inputMode
- } = createDatePicker(props);
- const isReversing = shallowRef(false);
- const inputModel = computed(() => model.value.length ? adapter.format(model.value[0], 'keyboardDate') : '');
- const title = computed(() => t(props.title));
- const header = computed(() => model.value.length ? adapter.format(model.value[0], 'normalDateWithWeekday') : t(props.header));
- const headerIcon = computed(() => inputMode.value === 'calendar' ? props.keyboardIcon : props.calendarIcon);
- const headerTransition = computed(() => `date-picker-header${isReversing.value ? '-reverse' : ''}-transition`);
- watch(inputModel, () => {
- const {
- isValid,
- date
- } = adapter;
- model.value = isValid(inputModel.value) ? [date(inputModel.value)] : [];
- });
- watch(model, (val, oldVal) => {
- if (props.hideActions) {
- emit('update:modelValue', val);
- }
- if (val[0] && oldVal[0]) {
- isReversing.value = adapter.isBefore(val[0], oldVal[0]);
- }
- });
- function onClickCancel() {
- emit('click:cancel');
- }
- function onClickSave() {
- emit('click:save');
- emit('update:modelValue', model.value);
- }
- function onClickAppend() {
- inputMode.value = inputMode.value === 'calendar' ? 'keyboard' : 'calendar';
- }
- const headerSlotProps = computed(() => ({
- header: header.value,
- appendIcon: headerIcon.value,
- transition: headerTransition.value,
- 'onClick:append': onClickAppend
- }));
- useRender(() => {
- const [pickerProps] = VPicker.filterProps(props);
- const [datePickerControlsProps] = VDatePickerControls.filterProps(props);
- const [datePickerMonthProps] = VDatePickerMonth.filterProps(props);
- const [datePickerYearsProps] = VDatePickerYears.filterProps(props);
- return createVNode(VPicker, mergeProps(pickerProps, {
- "class": ['v-date-picker', props.class],
- "style": props.style,
- "title": title.value,
- "width": props.showWeek ? 408 : 360
- }), {
- header: () => slots.header?.(headerSlotProps.value) ?? createVNode(VDatePickerHeader, mergeProps({
- "key": "header"
- }, headerSlotProps.value), null),
- default: () => inputMode.value === 'calendar' ? createVNode(Fragment, null, [createVNode(VDatePickerControls, mergeProps(datePickerControlsProps, {
- "displayDate": displayDate.value,
- "onUpdate:displayDate": $event => displayDate.value = $event,
- "viewMode": viewMode.value,
- "onUpdate:viewMode": $event => viewMode.value = $event
- }), null), createVNode(VFadeTransition, {
- "hideOnLeave": true
- }, {
- default: () => [viewMode.value === 'month' ? createVNode(VDatePickerMonth, mergeProps({
- "key": "date-picker-month"
- }, datePickerMonthProps, {
- "modelValue": model.value,
- "onUpdate:modelValue": $event => model.value = $event,
- "displayDate": displayDate.value,
- "onUpdate:displayDate": $event => displayDate.value = $event
- }), null) : createVNode(VDatePickerYears, mergeProps({
- "key": "date-picker-years"
- }, datePickerYearsProps, {
- "displayDate": displayDate.value,
- "onUpdate:displayDate": $event => displayDate.value = $event,
- "viewMode": viewMode.value,
- "onUpdate:viewMode": $event => viewMode.value = $event
- }), null)]
- })]) : createVNode("div", {
- "class": "v-date-picker__input"
- }, [createVNode(VTextField, {
- "modelValue": inputModel.value,
- "onUpdate:modelValue": $event => inputModel.value = $event,
- "label": t(props.inputText),
- "placeholder": "dd/mm/yyyy"
- }, null)]),
- actions: () => !props.hideActions ? createVNode("div", null, [createVNode(VBtn, {
- "variant": "text",
- "color": props.color,
- "onClick": onClickCancel,
- "text": t(props.cancelText)
- }, null), createVNode(VBtn, {
- "variant": "text",
- "color": props.color,
- "onClick": onClickSave,
- "text": t(props.okText)
- }, null)]) : undefined
- });
- });
- return {};
- }
- });
- // Types
- const makeVInfiniteScrollProps = propsFactory({
- color: String,
- direction: {
- type: String,
- default: 'vertical',
- validator: v => ['vertical', 'horizontal'].includes(v)
- },
- side: {
- type: String,
- default: 'end',
- validator: v => ['start', 'end', 'both'].includes(v)
- },
- mode: {
- type: String,
- default: 'intersect',
- validator: v => ['intersect', 'manual'].includes(v)
- },
- margin: [Number, String],
- loadMoreText: {
- type: String,
- default: '$vuetify.infiniteScroll.loadMore'
- },
- emptyText: {
- type: String,
- default: '$vuetify.infiniteScroll.empty'
- },
- ...makeDimensionProps(),
- ...makeTagProps()
- }, 'VInfiniteScroll');
- const VInfiniteScrollIntersect = defineComponent({
- name: 'VInfiniteScrollIntersect',
- props: {
- side: {
- type: String,
- required: true
- },
- rootRef: null,
- rootMargin: String
- },
- emits: {
- intersect: (side, isIntersecting) => true
- },
- setup(props, _ref) {
- let {
- emit
- } = _ref;
- const {
- intersectionRef,
- isIntersecting
- } = useIntersectionObserver(entries => {}, props.rootMargin ? {
- rootMargin: props.rootMargin
- } : undefined);
- watch(isIntersecting, async val => {
- emit('intersect', props.side, val);
- });
- useRender(() => createVNode("div", {
- "class": "v-infinite-scroll-intersect",
- "ref": intersectionRef
- }, [createTextVNode("\xA0")]));
- return {};
- }
- });
- const VInfiniteScroll = genericComponent()({
- name: 'VInfiniteScroll',
- props: makeVInfiniteScrollProps(),
- emits: {
- load: options => true
- },
- setup(props, _ref2) {
- let {
- slots,
- emit
- } = _ref2;
- const rootEl = ref();
- const startStatus = shallowRef('ok');
- const endStatus = shallowRef('ok');
- const margin = computed(() => convertToUnit(props.margin));
- const isIntersecting = shallowRef(false);
- function setScrollAmount(amount) {
- if (!rootEl.value) return;
- const property = props.direction === 'vertical' ? 'scrollTop' : 'scrollLeft';
- rootEl.value[property] = amount;
- }
- function getScrollAmount() {
- if (!rootEl.value) return 0;
- const property = props.direction === 'vertical' ? 'scrollTop' : 'scrollLeft';
- return rootEl.value[property];
- }
- function getScrollSize() {
- if (!rootEl.value) return 0;
- const property = props.direction === 'vertical' ? 'scrollHeight' : 'scrollWidth';
- return rootEl.value[property];
- }
- function getContainerSize() {
- if (!rootEl.value) return 0;
- const property = props.direction === 'vertical' ? 'clientHeight' : 'clientWidth';
- return rootEl.value[property];
- }
- onMounted(() => {
- if (!rootEl.value) return;
- if (props.side === 'start') {
- setScrollAmount(getScrollSize());
- } else if (props.side === 'both') {
- setScrollAmount(getScrollSize() / 2 - getContainerSize() / 2);
- }
- });
- function setStatus(side, status) {
- if (side === 'start') {
- startStatus.value = status;
- } else if (side === 'end') {
- endStatus.value = status;
- }
- }
- function getStatus(side) {
- return side === 'start' ? startStatus.value : endStatus.value;
- }
- let previousScrollSize = 0;
- function handleIntersect(side, _isIntersecting) {
- isIntersecting.value = _isIntersecting;
- if (isIntersecting.value) {
- intersecting(side);
- }
- }
- function intersecting(side) {
- if (props.mode !== 'manual' && !isIntersecting.value) return;
- const status = getStatus(side);
- if (!rootEl.value || status === 'loading') return;
- previousScrollSize = getScrollSize();
- setStatus(side, 'loading');
- function done(status) {
- setStatus(side, status);
- nextTick(() => {
- if (status === 'empty' || status === 'error') return;
- if (status === 'ok' && side === 'start') {
- setScrollAmount(getScrollSize() - previousScrollSize + getScrollAmount());
- }
- if (props.mode !== 'manual') {
- nextTick(() => {
- window.requestAnimationFrame(() => {
- window.requestAnimationFrame(() => {
- window.requestAnimationFrame(() => {
- intersecting(side);
- });
- });
- });
- });
- }
- });
- }
- emit('load', {
- side,
- done
- });
- }
- const {
- t
- } = useLocale();
- function renderSide(side, status) {
- if (props.side !== side && props.side !== 'both') return;
- const onClick = () => intersecting(side);
- const slotProps = {
- side,
- props: {
- onClick,
- color: props.color
- }
- };
- if (status === 'error') return slots.error?.(slotProps);
- if (status === 'empty') return slots.empty?.(slotProps) ?? createVNode("div", null, [t(props.emptyText)]);
- if (props.mode === 'manual') {
- if (status === 'loading') {
- return slots.loading?.(slotProps) ?? createVNode(VProgressCircular, {
- "indeterminate": true,
- "color": props.color
- }, null);
- }
- return slots['load-more']?.(slotProps) ?? createVNode(VBtn, {
- "variant": "outlined",
- "color": props.color,
- "onClick": onClick
- }, {
- default: () => [t(props.loadMoreText)]
- });
- }
- return slots.loading?.(slotProps) ?? createVNode(VProgressCircular, {
- "indeterminate": true,
- "color": props.color
- }, null);
- }
- const {
- dimensionStyles
- } = useDimension(props);
- useRender(() => {
- const Tag = props.tag;
- const hasStartIntersect = props.side === 'start' || props.side === 'both';
- const hasEndIntersect = props.side === 'end' || props.side === 'both';
- const intersectMode = props.mode === 'intersect';
- return createVNode(Tag, {
- "ref": rootEl,
- "class": ['v-infinite-scroll', `v-infinite-scroll--${props.direction}`, {
- 'v-infinite-scroll--start': hasStartIntersect,
- 'v-infinite-scroll--end': hasEndIntersect
- }],
- "style": dimensionStyles.value
- }, {
- default: () => [createVNode("div", {
- "class": "v-infinite-scroll__side"
- }, [renderSide('start', startStatus.value)]), rootEl.value && hasStartIntersect && intersectMode && createVNode(VInfiniteScrollIntersect, {
- "key": "start",
- "side": "start",
- "onIntersect": handleIntersect,
- "rootRef": rootEl.value,
- "rootMargin": margin.value
- }, null), slots.default?.(), rootEl.value && hasEndIntersect && intersectMode && createVNode(VInfiniteScrollIntersect, {
- "key": "end",
- "side": "end",
- "onIntersect": handleIntersect,
- "rootRef": rootEl.value,
- "rootMargin": margin.value
- }, null), createVNode("div", {
- "class": "v-infinite-scroll__side"
- }, [renderSide('end', endStatus.value)])]
- });
- });
- }
- });
- // Types
- const makeVOtpInputProps = propsFactory({
- autofocus: Boolean,
- divider: String,
- focusAll: Boolean,
- label: {
- type: String,
- default: '$vuetify.input.otp'
- },
- length: {
- type: [Number, String],
- default: 6
- },
- modelValue: {
- type: [Number, String],
- default: undefined
- },
- placeholder: String,
- type: {
- type: String,
- default: 'text'
- },
- ...makeDimensionProps(),
- ...makeFocusProps(),
- ...only(makeVFieldProps({
- variant: 'outlined'
- }), ['baseColor', 'bgColor', 'class', 'color', 'disabled', 'error', 'loading', 'rounded', 'style', 'theme', 'variant'])
- }, 'VOtpInput');
- const VOtpInput = genericComponent()({
- name: 'VOtpInput',
- props: makeVOtpInputProps(),
- emits: {
- finish: val => true,
- 'update:focused': val => true,
- 'update:modelValue': val => true
- },
- setup(props, _ref) {
- let {
- emit,
- slots
- } = _ref;
- const {
- dimensionStyles
- } = useDimension(props);
- const {
- isFocused,
- focus,
- blur
- } = useFocus(props);
- const model = useProxiedModel(props, 'modelValue', '', val => String(val).split(''), val => val.join(''));
- const {
- t
- } = useLocale();
- const fields = computed(() => Array(Number(props.length)).fill(0));
- const focusIndex = ref(-1);
- const contentRef = ref();
- const inputRef = ref([]);
- const current = computed(() => inputRef.value[focusIndex.value]);
- function onInput() {
- const array = model.value.slice();
- const value = current.value.value;
- array[focusIndex.value] = value;
- model.value = array;
- }
- function onKeydown(e) {
- const array = model.value.slice();
- const index = focusIndex.value;
- let target = null;
- if (e.key === 'ArrowLeft') {
- target = 'prev';
- } else if (e.key === 'ArrowRight') {
- target = 'next';
- } else if (e.key === 'Backspace') {
- if (focusIndex.value > 0) {
- target = 'prev';
- }
- } else if (e.key === 'Delete') {
- array[focusIndex.value] = '';
- model.value = array;
- requestAnimationFrame(() => {
- inputRef.value[index].select();
- });
- } else if (props.type === 'number' && isNaN(parseInt(e.key))) {
- return;
- } else if (focusIndex.value > model.value.length) {
- target = model.value.length + 1;
- } else if (focusIndex.value + 1 !== Number(props.length)) {
- target = 'next';
- } else {
- requestAnimationFrame(() => current.value?.blur());
- return;
- }
- requestAnimationFrame(() => {
- if (target != null) {
- focusChild(contentRef.value, target);
- }
- });
- }
- function onPaste(index, e) {
- e.preventDefault();
- e.stopPropagation();
- model.value = (e?.clipboardData?.getData('Text') ?? '').split('');
- inputRef.value?.[index].blur();
- }
- function reset() {
- model.value = [];
- }
- function onFocus(e, index) {
- focus();
- focusIndex.value = index;
- }
- function onBlur() {
- blur();
- focusIndex.value = -1;
- }
- provideDefaults({
- VField: {
- disabled: computed(() => props.disabled),
- error: computed(() => props.error),
- variant: computed(() => props.variant)
- }
- }, {
- scoped: true
- });
- watch(model, val => {
- if (val.length === props.length) emit('finish', val.join(''));
- }, {
- deep: true
- });
- watch(focusIndex, val => {
- if (val < 0) return;
- IN_BROWSER && window.requestAnimationFrame(() => {
- inputRef.value[val].select();
- });
- });
- useRender(() => {
- return createVNode("div", {
- "class": ['v-otp-input', {
- 'v-otp-input--divided': !!props.divider
- }, props.class],
- "style": [props.style]
- }, [createVNode("div", {
- "ref": contentRef,
- "class": "v-otp-input__content",
- "style": [dimensionStyles.value]
- }, [fields.value.map((_, i) => createVNode(Fragment, null, [props.divider && i !== 0 && createVNode("span", {
- "class": "v-otp-input__divider"
- }, [props.divider]), createVNode(VField, {
- "focused": isFocused.value && props.focusAll || focusIndex.value === i,
- "key": i
- }, {
- ...slots,
- default: () => {
- return createVNode("input", {
- "ref": val => inputRef.value[i] = val,
- "aria-label": t(props.label, i + 1),
- "autofocus": i === 0 && props.autofocus,
- "autocomplete": "one-time-code",
- "class": ['v-otp-input__field'],
- "inputmode": "text",
- "min": props.type === 'number' ? 0 : undefined,
- "maxlength": "1",
- "placeholder": props.placeholder,
- "type": props.type,
- "value": model.value[i],
- "onInput": onInput,
- "onFocus": e => onFocus(e, i),
- "onBlur": onBlur,
- "onKeydown": onKeydown,
- "onPaste": event => onPaste(i, event)
- }, null);
- }
- })])), createVNode(VOverlay, {
- "contained": true,
- "content-class": "v-otp-input__loader",
- "model-value": !!props.loading,
- "persistent": true
- }, {
- default: () => [slots.loader?.() ?? createVNode(VProgressCircular, {
- "color": typeof props.loading === 'boolean' ? undefined : props.loading,
- "indeterminate": true,
- "size": "24",
- "width": "2"
- }, null)]
- }), slots.default?.()])]);
- });
- return {
- blur: () => {
- inputRef.value?.some(input => input.blur());
- },
- focus: () => {
- inputRef.value?.[0].focus();
- },
- reset,
- isFocused
- };
- }
- });
- // Types
- const rootTypes = {
- actions: 'button@2',
- article: 'heading, paragraph',
- avatar: 'avatar',
- button: 'button',
- card: 'image, heading',
- 'card-avatar': 'image, list-item-avatar',
- chip: 'chip',
- 'date-picker': 'list-item, heading, divider, date-picker-options, date-picker-days, actions',
- 'date-picker-options': 'text, avatar@2',
- 'date-picker-days': 'avatar@28',
- divider: 'divider',
- heading: 'heading',
- image: 'image',
- 'list-item': 'text',
- 'list-item-avatar': 'avatar, text',
- 'list-item-two-line': 'sentences',
- 'list-item-avatar-two-line': 'avatar, sentences',
- 'list-item-three-line': 'paragraph',
- 'list-item-avatar-three-line': 'avatar, paragraph',
- paragraph: 'text@3',
- sentences: 'text@2',
- subtitle: 'text',
- table: 'table-heading, table-thead, table-tbody, table-tfoot',
- 'table-heading': 'chip, text',
- 'table-thead': 'heading@6',
- 'table-tbody': 'table-row-divider@6',
- 'table-row-divider': 'table-row, divider',
- 'table-row': 'text@6',
- 'table-tfoot': 'text@2, avatar@2',
- text: 'text'
- };
- function genBone(type) {
- let children = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : [];
- return createVNode("div", {
- "class": ['v-skeleton-loader__bone', `v-skeleton-loader__${type}`]
- }, [children]);
- }
- function genBones(bone) {
- // e.g. 'text@3'
- const [type, length] = bone.split('@');
- // Generate a length array based upon
- // value after @ in the bone string
- return Array.from({
- length
- }).map(() => genStructure(type));
- }
- function genStructure(type) {
- let children = [];
- if (!type) return children;
- // TODO: figure out a better way to type this
- const bone = rootTypes[type];
- // End of recursion, do nothing
- /* eslint-disable-next-line no-empty, brace-style */
- if (type === bone) ;
- // Array of values - e.g. 'heading, paragraph, text@2'
- else if (type.includes(',')) return mapBones(type);
- // Array of values - e.g. 'paragraph@4'
- else if (type.includes('@')) return genBones(type);
- // Array of values - e.g. 'card@2'
- else if (bone.includes(',')) children = mapBones(bone);
- // Array of values - e.g. 'list-item@2'
- else if (bone.includes('@')) children = genBones(bone);
- // Single value - e.g. 'card-heading'
- else if (bone) children.push(genStructure(bone));
- return [genBone(type, children)];
- }
- function mapBones(bones) {
- // Remove spaces and return array of structures
- return bones.replace(/\s/g, '').split(',').map(genStructure);
- }
- const makeVSkeletonLoaderProps = propsFactory({
- boilerplate: Boolean,
- color: String,
- loading: Boolean,
- loadingText: {
- type: String,
- default: '$vuetify.loading'
- },
- type: {
- type: [String, Array],
- default: 'image'
- },
- ...makeDimensionProps(),
- ...makeElevationProps(),
- ...makeThemeProps()
- }, 'VSkeletonLoader');
- const VSkeletonLoader = genericComponent()({
- name: 'VSkeletonLoader',
- props: makeVSkeletonLoaderProps(),
- setup(props, _ref) {
- let {
- slots
- } = _ref;
- const {
- backgroundColorClasses,
- backgroundColorStyles
- } = useBackgroundColor(toRef(props, 'color'));
- const {
- dimensionStyles
- } = useDimension(props);
- const {
- elevationClasses
- } = useElevation(props);
- const {
- themeClasses
- } = provideTheme(props);
- const {
- t
- } = useLocale();
- const items = computed(() => genStructure(wrapInArray(props.type).join(',')));
- useRender(() => {
- const isLoading = !slots.default || props.loading;
- return createVNode("div", {
- "class": ['v-skeleton-loader', {
- 'v-skeleton-loader--boilerplate': props.boilerplate
- }, themeClasses.value, backgroundColorClasses.value, elevationClasses.value],
- "style": [backgroundColorStyles.value, isLoading ? dimensionStyles.value : {}],
- "aria-busy": !props.boilerplate ? isLoading : undefined,
- "aria-live": !props.boilerplate ? 'polite' : undefined,
- "aria-label": !props.boilerplate ? t(props.loadingText) : undefined,
- "role": !props.boilerplate ? 'alert' : undefined
- }, [isLoading ? items.value : slots.default?.()]);
- });
- return {};
- }
- });
- // Types
- const makeVStepperActionsProps = propsFactory({
- color: String,
- disabled: {
- type: [Boolean, String],
- default: false
- },
- prevText: {
- type: String,
- default: '$vuetify.stepper.prev'
- },
- nextText: {
- type: String,
- default: '$vuetify.stepper.next'
- }
- }, 'VStepperActions');
- const VStepperActions = genericComponent()({
- name: 'VStepperActions',
- props: makeVStepperActionsProps(),
- emits: {
- 'click:prev': () => true,
- 'click:next': () => true
- },
- setup(props, _ref) {
- let {
- emit,
- slots
- } = _ref;
- const {
- t
- } = useLocale();
- function onClickPrev() {
- emit('click:prev');
- }
- function onClickNext() {
- emit('click:next');
- }
- useRender(() => {
- return createVNode("div", {
- "class": "v-stepper-actions"
- }, [createVNode(VBtn, {
- "disabled": ['prev', true].includes(props.disabled),
- "text": t(props.prevText),
- "variant": "text",
- "onClick": onClickPrev
- }, null), createVNode(VBtn, {
- "disabled": ['next', true].includes(props.disabled),
- "color": props.color,
- "text": t(props.nextText),
- "variant": "tonal",
- "onClick": onClickNext
- }, null)]);
- });
- return {};
- }
- });
- // Utilities
- const VStepperHeader = createSimpleFunctional('v-stepper-header');
- // Types
- const makeVStepperItemProps = propsFactory({
- color: String,
- title: String,
- subtitle: String,
- complete: Boolean,
- completeIcon: {
- type: String,
- default: '$complete'
- },
- editable: Boolean,
- editIcon: {
- type: String,
- default: '$edit'
- },
- error: Boolean,
- errorIcon: {
- type: String,
- default: '$error'
- },
- icon: String,
- ripple: {
- type: [Boolean, Object],
- default: true
- },
- rules: {
- type: Array,
- default: () => []
- },
- ...makeGroupItemProps()
- }, 'VStepperItem');
- const VStepperItem = genericComponent()({
- name: 'VStepperItem',
- directives: {
- Ripple
- },
- props: makeVStepperItemProps(),
- emits: {
- 'group:selected': val => true
- },
- setup(props, _ref) {
- let {
- slots
- } = _ref;
- const group = useGroupItem(props, VStepperSymbol, true);
- const step = computed(() => group?.value.value ?? props.value);
- const isValid = computed(() => props.rules.every(handler => handler() === true));
- const canEdit = computed(() => !props.disabled && props.editable);
- const hasError = computed(() => props.error || !isValid.value);
- const hasCompleted = computed(() => props.complete || props.rules.length > 0 && isValid.value);
- const icon = computed(() => {
- if (hasError.value) return props.errorIcon;
- if (hasCompleted.value) return props.completeIcon;
- if (props.editable) return props.editIcon;
- return props.icon;
- });
- const slotProps = computed(() => ({
- canEdit: canEdit.value,
- hasError: hasError.value,
- hasCompleted: hasCompleted.value,
- title: props.title,
- subtitle: props.subtitle,
- step: step.value,
- value: props.value
- }));
- useRender(() => {
- const hasColor = (!group || group.isSelected.value || hasCompleted.value || canEdit.value) && !hasError.value && !props.disabled;
- const hasTitle = !!(props.title || slots.title);
- const hasSubtitle = !!(props.subtitle || slots.subtitle);
- function onClick() {
- group?.toggle();
- }
- return withDirectives(createVNode("button", {
- "class": ['v-stepper-item', {
- 'v-stepper-item--complete': hasCompleted.value,
- 'v-stepper-item--disabled': props.disabled,
- 'v-stepper-item--error': hasError.value
- }, group?.selectedClass.value],
- "disabled": !props.editable,
- "onClick": onClick
- }, [createVNode(VAvatar, {
- "key": "stepper-avatar",
- "class": "v-stepper-item__avatar",
- "color": hasColor ? props.color : undefined,
- "size": 24
- }, {
- default: () => [slots.icon?.(slotProps.value) ?? (icon.value ? createVNode(VIcon, {
- "icon": icon.value
- }, null) : step.value)]
- }), createVNode("div", {
- "class": "v-stepper-item__content"
- }, [hasTitle && createVNode("div", {
- "key": "title",
- "class": "v-stepper-item__title"
- }, [slots.title?.(slotProps.value) ?? props.title]), hasSubtitle && createVNode("div", {
- "key": "subtitle",
- "class": "v-stepper-item__subtitle"
- }, [slots.subtitle?.(slotProps.value) ?? props.subtitle]), slots.default?.(slotProps.value)])]), [[resolveDirective("ripple"), props.ripple && props.editable, null]]);
- });
- return {};
- }
- });
- // Types
- const VStepperSymbol$1 = Symbol.for('vuetify:v-stepper');
- const makeVStepperWindowProps = propsFactory({
- ...makeVWindowProps({
- mandatory: false
- })
- }, 'VStepperWindow');
- const VStepperWindow = genericComponent()({
- name: 'VStepperWindow',
- props: makeVStepperWindowProps(),
- emits: {
- 'update:modelValue': v => true
- },
- setup(props, _ref) {
- let {
- slots
- } = _ref;
- const group = inject$1(VStepperSymbol$1, null);
- const _model = useProxiedModel(props, 'modelValue');
- const model = computed({
- get() {
- // Always return modelValue if defined
- // or if not within a VStepper group
- if (_model.value != null || !group) return _model.value;
- // If inside of a VStepper, find the currently selected
- // item by id. Item value may be assigned by its index
- return group.items.value.find(item => group.selected.value.includes(item.id))?.value;
- },
- set(val) {
- _model.value = val;
- }
- });
- useRender(() => {
- const [windowProps] = VWindow.filterProps(props);
- return createVNode(VWindow, mergeProps(windowProps, {
- "modelValue": model.value,
- "onUpdate:modelValue": $event => model.value = $event,
- "class": "v-stepper-window"
- }), slots);
- });
- return {};
- }
- });
- const makeVStepperWindowItemProps = propsFactory({
- ...makeVWindowItemProps()
- }, 'VStepperWindowItem');
- const VStepperWindowItem = genericComponent()({
- name: 'VStepperWindowItem',
- props: makeVStepperWindowItemProps(),
- setup(props, _ref) {
- let {
- slots
- } = _ref;
- useRender(() => {
- const [windowItemProps] = VWindowItem.filterProps(props);
- return createVNode(VWindowItem, mergeProps(windowItemProps, {
- "class": "v-stepper-window-item"
- }), slots);
- });
- return {};
- }
- });
- // Types
- const VStepperSymbol = Symbol.for('vuetify:v-stepper');
- const makeVStepperProps = propsFactory({
- altLabels: Boolean,
- bgColor: String,
- editable: Boolean,
- hideActions: Boolean,
- items: {
- type: Array,
- default: () => []
- },
- itemTitle: {
- type: String,
- default: 'title'
- },
- itemValue: {
- type: String,
- default: 'value'
- },
- mobile: Boolean,
- nonLinear: Boolean,
- flat: Boolean,
- ...makeGroupProps({
- mandatory: 'force',
- selectedClass: 'v-stepper-item--selected'
- }),
- ...omit(makeVSheetProps(), ['color']),
- ...makeVStepperActionsProps()
- }, 'VStepper');
- const VStepper = genericComponent()({
- name: 'VStepper',
- props: makeVStepperProps(),
- emits: {
- 'update:modelValue': v => true
- },
- setup(props, _ref) {
- let {
- slots
- } = _ref;
- // TODO: fix typing
- const {
- items: _items,
- next,
- prev,
- selected
- } = useGroup(props, VStepperSymbol);
- const {
- editable,
- prevText,
- nextText
- } = toRefs(props);
- const items = computed(() => props.items.map((item, index) => {
- const title = getPropertyFromItem(item, props.itemTitle, item);
- const value = getPropertyFromItem(item, props.itemValue, index + 1);
- return {
- title,
- value,
- raw: item
- };
- }));
- const activeIndex = computed(() => {
- return _items.value.findIndex(item => selected.value.includes(item.id));
- });
- const disabled = computed(() => {
- if (props.disabled) return props.disabled;
- if (activeIndex.value === 0) return 'prev';
- if (activeIndex.value === _items.value.length - 1) return 'next';
- return false;
- });
- provideDefaults({
- VStepperItem: {
- editable,
- prevText,
- nextText
- },
- VStepperActions: {
- disabled
- }
- });
- useRender(() => {
- const [sheetProps] = VSheet.filterProps(props);
- const [stepperActionProps] = VStepperActions.filterProps(props);
- const hasHeader = !!(slots.header || props.items.length);
- const hasWindow = props.items.length > 0;
- const hasActions = !props.hideActions && !!(hasWindow || slots.actions);
- return createVNode(VSheet, mergeProps(sheetProps, {
- "class": ['v-stepper', {
- 'v-stepper--alt-labels': props.altLabels,
- 'v-stepper--flat': props.flat,
- 'v-stepper--non-linear': props.nonLinear,
- 'v-stepper--mobile': props.mobile
- }, props.class],
- "style": props.style
- }), {
- default: () => [hasHeader && createVNode(VStepperHeader, {
- "key": "stepper-header"
- }, {
- default: () => [items.value.map((item, index) => createVNode(Fragment, null, [!!index && createVNode(VDivider, null, null), createVNode(VStepperItem, item, {
- default: slots[`header-item.${item.value}`] ?? slots.header,
- icon: slots.icon,
- title: slots.title,
- subtitle: slots.subtitle
- })]))]
- }), hasWindow && createVNode(VStepperWindow, {
- "key": "stepper-window"
- }, {
- default: () => [items.value.map(item => createVNode(VStepperWindowItem, {
- "value": item.value
- }, {
- default: () => slots[`item.${item.value}`]?.(item) ?? slots.item?.(item)
- }))]
- }), slots.default?.({
- prev,
- next
- }), hasActions && (slots.actions?.({
- next,
- prev
- }) ?? createVNode(VStepperActions, mergeProps({
- "key": "stepper-actions"
- }, stepperActionProps, {
- "onClick:prev": prev,
- "onClick:next": next
- }), null))]
- });
- });
- return {
- prev,
- next
- };
- }
- });
- var components = /*#__PURE__*/Object.freeze({
- __proto__: null,
- VAlert: VAlert,
- VAlertTitle: VAlertTitle,
- VApp: VApp,
- VAppBar: VAppBar,
- VAppBarNavIcon: VAppBarNavIcon,
- VAppBarTitle: VAppBarTitle,
- VAutocomplete: VAutocomplete,
- VAvatar: VAvatar,
- VBadge: VBadge,
- VBanner: VBanner,
- VBannerActions: VBannerActions,
- VBannerText: VBannerText,
- VBottomNavigation: VBottomNavigation,
- VBottomSheet: VBottomSheet,
- VBreadcrumbs: VBreadcrumbs,
- VBreadcrumbsDivider: VBreadcrumbsDivider,
- VBreadcrumbsItem: VBreadcrumbsItem,
- VBtn: VBtn,
- VBtnGroup: VBtnGroup,
- VBtnToggle: VBtnToggle,
- VCard: VCard,
- VCardActions: VCardActions,
- VCardItem: VCardItem,
- VCardSubtitle: VCardSubtitle,
- VCardText: VCardText,
- VCardTitle: VCardTitle,
- VCarousel: VCarousel,
- VCarouselItem: VCarouselItem,
- VCheckbox: VCheckbox,
- VCheckboxBtn: VCheckboxBtn,
- VChip: VChip,
- VChipGroup: VChipGroup,
- VClassIcon: VClassIcon,
- VCode: VCode,
- VCol: VCol,
- VColorPicker: VColorPicker,
- VCombobox: VCombobox,
- VComponentIcon: VComponentIcon,
- VContainer: VContainer,
- VCounter: VCounter,
- VDataIterator: VDataIterator,
- VDataTable: VDataTable,
- VDataTableFooter: VDataTableFooter,
- VDataTableRow: VDataTableRow,
- VDataTableRows: VDataTableRows,
- VDataTableServer: VDataTableServer,
- VDataTableVirtual: VDataTableVirtual,
- VDateCard: VDateCard,
- VDatePicker: VDatePicker,
- VDatePickerControls: VDatePickerControls,
- VDatePickerHeader: VDatePickerHeader,
- VDatePickerMonth: VDatePickerMonth,
- VDatePickerYears: VDatePickerYears,
- VDefaultsProvider: VDefaultsProvider,
- VDialog: VDialog,
- VDialogBottomTransition: VDialogBottomTransition,
- VDialogTopTransition: VDialogTopTransition,
- VDialogTransition: VDialogTransition,
- VDivider: VDivider,
- VExpandTransition: VExpandTransition,
- VExpandXTransition: VExpandXTransition,
- VExpansionPanel: VExpansionPanel,
- VExpansionPanelText: VExpansionPanelText,
- VExpansionPanelTitle: VExpansionPanelTitle,
- VExpansionPanels: VExpansionPanels,
- VFabTransition: VFabTransition,
- VFadeTransition: VFadeTransition,
- VField: VField,
- VFieldLabel: VFieldLabel,
- VFileInput: VFileInput,
- VFooter: VFooter,
- VForm: VForm,
- VHover: VHover,
- VIcon: VIcon,
- VImg: VImg,
- VInfiniteScroll: VInfiniteScroll,
- VInput: VInput,
- VItem: VItem,
- VItemGroup: VItemGroup,
- VKbd: VKbd,
- VLabel: VLabel,
- VLayout: VLayout,
- VLayoutItem: VLayoutItem,
- VLazy: VLazy,
- VLigatureIcon: VLigatureIcon,
- VList: VList,
- VListGroup: VListGroup,
- VListImg: VListImg,
- VListItem: VListItem,
- VListItemAction: VListItemAction,
- VListItemMedia: VListItemMedia,
- VListItemSubtitle: VListItemSubtitle,
- VListItemTitle: VListItemTitle,
- VListSubheader: VListSubheader,
- VLocaleProvider: VLocaleProvider,
- VMain: VMain,
- VMenu: VMenu,
- VMessages: VMessages,
- VNavigationDrawer: VNavigationDrawer,
- VNoSsr: VNoSsr,
- VOtpInput: VOtpInput,
- VOverlay: VOverlay,
- VPagination: VPagination,
- VParallax: VParallax,
- VPicker: VPicker,
- VPickerTitle: VPickerTitle,
- VProgressCircular: VProgressCircular,
- VProgressLinear: VProgressLinear,
- VRadio: VRadio,
- VRadioGroup: VRadioGroup,
- VRangeSlider: VRangeSlider,
- VRating: VRating,
- VResponsive: VResponsive,
- VRow: VRow,
- VScaleTransition: VScaleTransition,
- VScrollXReverseTransition: VScrollXReverseTransition,
- VScrollXTransition: VScrollXTransition,
- VScrollYReverseTransition: VScrollYReverseTransition,
- VScrollYTransition: VScrollYTransition,
- VSelect: VSelect,
- VSelectionControl: VSelectionControl,
- VSelectionControlGroup: VSelectionControlGroup,
- VSheet: VSheet,
- VSkeletonLoader: VSkeletonLoader,
- VSlideGroup: VSlideGroup,
- VSlideGroupItem: VSlideGroupItem,
- VSlideXReverseTransition: VSlideXReverseTransition,
- VSlideXTransition: VSlideXTransition,
- VSlideYReverseTransition: VSlideYReverseTransition,
- VSlideYTransition: VSlideYTransition,
- VSlider: VSlider,
- VSnackbar: VSnackbar,
- VSpacer: VSpacer,
- VStepper: VStepper,
- VStepperActions: VStepperActions,
- VStepperHeader: VStepperHeader,
- VStepperItem: VStepperItem,
- VStepperWindow: VStepperWindow,
- VStepperWindowItem: VStepperWindowItem,
- VSvgIcon: VSvgIcon,
- VSwitch: VSwitch,
- VSystemBar: VSystemBar,
- VTab: VTab,
- VTable: VTable,
- VTabs: VTabs,
- VTextField: VTextField,
- VTextarea: VTextarea,
- VThemeProvider: VThemeProvider,
- VTimeline: VTimeline,
- VTimelineItem: VTimelineItem,
- VToolbar: VToolbar,
- VToolbarItems: VToolbarItems,
- VToolbarTitle: VToolbarTitle,
- VTooltip: VTooltip,
- VValidation: VValidation,
- VVirtualScroll: VVirtualScroll,
- VWindow: VWindow,
- VWindowItem: VWindowItem
- });
- // Types
- function mounted$2(el, binding) {
- const modifiers = binding.modifiers || {};
- const value = binding.value;
- const {
- once,
- immediate,
- ...modifierKeys
- } = modifiers;
- const defaultValue = !Object.keys(modifierKeys).length;
- const {
- handler,
- options
- } = typeof value === 'object' ? value : {
- handler: value,
- options: {
- attributes: modifierKeys?.attr ?? defaultValue,
- characterData: modifierKeys?.char ?? defaultValue,
- childList: modifierKeys?.child ?? defaultValue,
- subtree: modifierKeys?.sub ?? defaultValue
- }
- };
- const observer = new MutationObserver(function () {
- let mutations = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : [];
- let observer = arguments.length > 1 ? arguments[1] : undefined;
- handler?.(mutations, observer);
- if (once) unmounted$2(el, binding);
- });
- if (immediate) handler?.([], observer);
- el._mutate = Object(el._mutate);
- el._mutate[binding.instance.$.uid] = {
- observer
- };
- observer.observe(el, options);
- }
- function unmounted$2(el, binding) {
- if (!el._mutate?.[binding.instance.$.uid]) return;
- el._mutate[binding.instance.$.uid].observer.disconnect();
- delete el._mutate[binding.instance.$.uid];
- }
- const Mutate = {
- mounted: mounted$2,
- unmounted: unmounted$2
- };
- // Types
- function mounted$1(el, binding) {
- const handler = binding.value;
- const options = {
- passive: !binding.modifiers?.active
- };
- window.addEventListener('resize', handler, options);
- el._onResize = Object(el._onResize);
- el._onResize[binding.instance.$.uid] = {
- handler,
- options
- };
- if (!binding.modifiers?.quiet) {
- handler();
- }
- }
- function unmounted$1(el, binding) {
- if (!el._onResize?.[binding.instance.$.uid]) return;
- const {
- handler,
- options
- } = el._onResize[binding.instance.$.uid];
- window.removeEventListener('resize', handler, options);
- delete el._onResize[binding.instance.$.uid];
- }
- const Resize = {
- mounted: mounted$1,
- unmounted: unmounted$1
- };
- // Types
- function mounted(el, binding) {
- const {
- self = false
- } = binding.modifiers ?? {};
- const value = binding.value;
- const options = typeof value === 'object' && value.options || {
- passive: true
- };
- const handler = typeof value === 'function' || 'handleEvent' in value ? value : value.handler;
- const target = self ? el : binding.arg ? document.querySelector(binding.arg) : window;
- if (!target) return;
- target.addEventListener('scroll', handler, options);
- el._onScroll = Object(el._onScroll);
- el._onScroll[binding.instance.$.uid] = {
- handler,
- options,
- // Don't reference self
- target: self ? undefined : target
- };
- }
- function unmounted(el, binding) {
- if (!el._onScroll?.[binding.instance.$.uid]) return;
- const {
- handler,
- options,
- target = el
- } = el._onScroll[binding.instance.$.uid];
- target.removeEventListener('scroll', handler, options);
- delete el._onScroll[binding.instance.$.uid];
- }
- function updated(el, binding) {
- if (binding.value === binding.oldValue) return;
- unmounted(el, binding);
- mounted(el, binding);
- }
- const Scroll = {
- mounted,
- unmounted,
- updated
- };
- var directives = /*#__PURE__*/Object.freeze({
- __proto__: null,
- ClickOutside: ClickOutside,
- Intersect: Intersect,
- Mutate: Mutate,
- Resize: Resize,
- Ripple: Ripple,
- Scroll: Scroll,
- Touch: Touch
- });
- // Composables
- function createVuetify$1() {
- let vuetify = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
- const {
- blueprint,
- ...rest
- } = vuetify;
- const options = mergeDeep(blueprint, rest);
- const {
- aliases = {},
- components = {},
- directives = {}
- } = options;
- const defaults = createDefaults(options.defaults);
- const display = createDisplay(options.display, options.ssr);
- const theme = createTheme(options.theme);
- const icons = createIcons(options.icons);
- const locale = createLocale(options.locale);
- const date = createDate(options.date);
- const install = app => {
- for (const key in directives) {
- app.directive(key, directives[key]);
- }
- for (const key in components) {
- app.component(key, components[key]);
- }
- for (const key in aliases) {
- app.component(key, defineComponent({
- ...aliases[key],
- name: key,
- aliasName: aliases[key].name
- }));
- }
- theme.install(app);
- app.provide(DefaultsSymbol, defaults);
- app.provide(DisplaySymbol, display);
- app.provide(ThemeSymbol, theme);
- app.provide(IconSymbol, icons);
- app.provide(LocaleSymbol, locale);
- app.provide(DateAdapterSymbol, date);
- if (IN_BROWSER && options.ssr) {
- if (app.$nuxt) {
- app.$nuxt.hook('app:suspense:resolve', () => {
- display.update();
- });
- } else {
- const {
- mount
- } = app;
- app.mount = function () {
- const vm = mount(...arguments);
- nextTick(() => display.update());
- app.mount = mount;
- return vm;
- };
- }
- }
- getUid.reset();
- if (typeof __VUE_OPTIONS_API__ !== 'boolean' || __VUE_OPTIONS_API__) {
- app.mixin({
- computed: {
- $vuetify() {
- return reactive({
- defaults: inject.call(this, DefaultsSymbol),
- display: inject.call(this, DisplaySymbol),
- theme: inject.call(this, ThemeSymbol),
- icons: inject.call(this, IconSymbol),
- locale: inject.call(this, LocaleSymbol),
- date: inject.call(this, DateAdapterSymbol)
- });
- }
- }
- });
- }
- };
- return {
- install,
- defaults,
- display,
- theme,
- icons,
- locale,
- date
- };
- }
- const version$1 = "3.3.11";
- createVuetify$1.version = version$1;
- // Vue's inject() can only be used in setup
- function inject(key) {
- const vm = this.$;
- const provides = vm.parent?.provides ?? vm.vnode.appContext?.provides;
- if (provides && key in provides) {
- return provides[key];
- }
- }
- /* eslint-disable local-rules/sort-imports */
- const version = "3.3.11";
- /* eslint-disable local-rules/sort-imports */
- const createVuetify = function () {
- let options = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
- return createVuetify$1({
- components,
- directives,
- ...options
- });
- };
- export { components, createVuetify, directives, useDefaults, useDisplay, useLayout, useLocale, useRtl, useTheme, version };
- //# sourceMappingURL=vuetify-labs.esm.js.map
|