vuetify.js 881 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353235423552356235723582359236023612362236323642365236623672368236923702371237223732374237523762377237823792380238123822383238423852386238723882389239023912392239323942395239623972398239924002401240224032404240524062407240824092410241124122413241424152416241724182419242024212422242324242425242624272428242924302431243224332434243524362437243824392440244124422443244424452446244724482449245024512452245324542455245624572458245924602461246224632464246524662467246824692470247124722473247424752476247724782479248024812482248324842485248624872488248924902491249224932494249524962497249824992500250125022503250425052506250725082509251025112512251325142515251625172518251925202521252225232524252525262527252825292530253125322533253425352536253725382539254025412542254325442545254625472548254925502551255225532554255525562557255825592560256125622563256425652566256725682569257025712572257325742575257625772578257925802581258225832584258525862587258825892590259125922593259425952596259725982599260026012602260326042605260626072608260926102611261226132614261526162617261826192620262126222623262426252626262726282629263026312632263326342635263626372638263926402641264226432644264526462647264826492650265126522653265426552656265726582659266026612662266326642665266626672668266926702671267226732674267526762677267826792680268126822683268426852686268726882689269026912692269326942695269626972698269927002701270227032704270527062707270827092710271127122713271427152716271727182719272027212722272327242725272627272728272927302731273227332734273527362737273827392740274127422743274427452746274727482749275027512752275327542755275627572758275927602761276227632764276527662767276827692770277127722773277427752776277727782779278027812782278327842785278627872788278927902791279227932794279527962797279827992800280128022803280428052806280728082809281028112812281328142815281628172818281928202821282228232824282528262827282828292830283128322833283428352836283728382839284028412842284328442845284628472848284928502851285228532854285528562857285828592860286128622863286428652866286728682869287028712872287328742875287628772878287928802881288228832884288528862887288828892890289128922893289428952896289728982899290029012902290329042905290629072908290929102911291229132914291529162917291829192920292129222923292429252926292729282929293029312932293329342935293629372938293929402941294229432944294529462947294829492950295129522953295429552956295729582959296029612962296329642965296629672968296929702971297229732974297529762977297829792980298129822983298429852986298729882989299029912992299329942995299629972998299930003001300230033004300530063007300830093010301130123013301430153016301730183019302030213022302330243025302630273028302930303031303230333034303530363037303830393040304130423043304430453046304730483049305030513052305330543055305630573058305930603061306230633064306530663067306830693070307130723073307430753076307730783079308030813082308330843085308630873088308930903091309230933094309530963097309830993100310131023103310431053106310731083109311031113112311331143115311631173118311931203121312231233124312531263127312831293130313131323133313431353136313731383139314031413142314331443145314631473148314931503151315231533154315531563157315831593160316131623163316431653166316731683169317031713172317331743175317631773178317931803181318231833184318531863187318831893190319131923193319431953196319731983199320032013202320332043205320632073208320932103211321232133214321532163217321832193220322132223223322432253226322732283229323032313232323332343235323632373238323932403241324232433244324532463247324832493250325132523253325432553256325732583259326032613262326332643265326632673268326932703271327232733274327532763277327832793280328132823283328432853286328732883289329032913292329332943295329632973298329933003301330233033304330533063307330833093310331133123313331433153316331733183319332033213322332333243325332633273328332933303331333233333334333533363337333833393340334133423343334433453346334733483349335033513352335333543355335633573358335933603361336233633364336533663367336833693370337133723373337433753376337733783379338033813382338333843385338633873388338933903391339233933394339533963397339833993400340134023403340434053406340734083409341034113412341334143415341634173418341934203421342234233424342534263427342834293430343134323433343434353436343734383439344034413442344334443445344634473448344934503451345234533454345534563457345834593460346134623463346434653466346734683469347034713472347334743475347634773478347934803481348234833484348534863487348834893490349134923493349434953496349734983499350035013502350335043505350635073508350935103511351235133514351535163517351835193520352135223523352435253526352735283529353035313532353335343535353635373538353935403541354235433544354535463547354835493550355135523553355435553556355735583559356035613562356335643565356635673568356935703571357235733574357535763577357835793580358135823583358435853586358735883589359035913592359335943595359635973598359936003601360236033604360536063607360836093610361136123613361436153616361736183619362036213622362336243625362636273628362936303631363236333634363536363637363836393640364136423643364436453646364736483649365036513652365336543655365636573658365936603661366236633664366536663667366836693670367136723673367436753676367736783679368036813682368336843685368636873688368936903691369236933694369536963697369836993700370137023703370437053706370737083709371037113712371337143715371637173718371937203721372237233724372537263727372837293730373137323733373437353736373737383739374037413742374337443745374637473748374937503751375237533754375537563757375837593760376137623763376437653766376737683769377037713772377337743775377637773778377937803781378237833784378537863787378837893790379137923793379437953796379737983799380038013802380338043805380638073808380938103811381238133814381538163817381838193820382138223823382438253826382738283829383038313832383338343835383638373838383938403841384238433844384538463847384838493850385138523853385438553856385738583859386038613862386338643865386638673868386938703871387238733874387538763877387838793880388138823883388438853886388738883889389038913892389338943895389638973898389939003901390239033904390539063907390839093910391139123913391439153916391739183919392039213922392339243925392639273928392939303931393239333934393539363937393839393940394139423943394439453946394739483949395039513952395339543955395639573958395939603961396239633964396539663967396839693970397139723973397439753976397739783979398039813982398339843985398639873988398939903991399239933994399539963997399839994000400140024003400440054006400740084009401040114012401340144015401640174018401940204021402240234024402540264027402840294030403140324033403440354036403740384039404040414042404340444045404640474048404940504051405240534054405540564057405840594060406140624063406440654066406740684069407040714072407340744075407640774078407940804081408240834084408540864087408840894090409140924093409440954096409740984099410041014102410341044105410641074108410941104111411241134114411541164117411841194120412141224123412441254126412741284129413041314132413341344135413641374138413941404141414241434144414541464147414841494150415141524153415441554156415741584159416041614162416341644165416641674168416941704171417241734174417541764177417841794180418141824183418441854186418741884189419041914192419341944195419641974198419942004201420242034204420542064207420842094210421142124213421442154216421742184219422042214222422342244225422642274228422942304231423242334234423542364237423842394240424142424243424442454246424742484249425042514252425342544255425642574258425942604261426242634264426542664267426842694270427142724273427442754276427742784279428042814282428342844285428642874288428942904291429242934294429542964297429842994300430143024303430443054306430743084309431043114312431343144315431643174318431943204321432243234324432543264327432843294330433143324333433443354336433743384339434043414342434343444345434643474348434943504351435243534354435543564357435843594360436143624363436443654366436743684369437043714372437343744375437643774378437943804381438243834384438543864387438843894390439143924393439443954396439743984399440044014402440344044405440644074408440944104411441244134414441544164417441844194420442144224423442444254426442744284429443044314432443344344435443644374438443944404441444244434444444544464447444844494450445144524453445444554456445744584459446044614462446344644465446644674468446944704471447244734474447544764477447844794480448144824483448444854486448744884489449044914492449344944495449644974498449945004501450245034504450545064507450845094510451145124513451445154516451745184519452045214522452345244525452645274528452945304531453245334534453545364537453845394540454145424543454445454546454745484549455045514552455345544555455645574558455945604561456245634564456545664567456845694570457145724573457445754576457745784579458045814582458345844585458645874588458945904591459245934594459545964597459845994600460146024603460446054606460746084609461046114612461346144615461646174618461946204621462246234624462546264627462846294630463146324633463446354636463746384639464046414642464346444645464646474648464946504651465246534654465546564657465846594660466146624663466446654666466746684669467046714672467346744675467646774678467946804681468246834684468546864687468846894690469146924693469446954696469746984699470047014702470347044705470647074708470947104711471247134714471547164717471847194720472147224723472447254726472747284729473047314732473347344735473647374738473947404741474247434744474547464747474847494750475147524753475447554756475747584759476047614762476347644765476647674768476947704771477247734774477547764777477847794780478147824783478447854786478747884789479047914792479347944795479647974798479948004801480248034804480548064807480848094810481148124813481448154816481748184819482048214822482348244825482648274828482948304831483248334834483548364837483848394840484148424843484448454846484748484849485048514852485348544855485648574858485948604861486248634864486548664867486848694870487148724873487448754876487748784879488048814882488348844885488648874888488948904891489248934894489548964897489848994900490149024903490449054906490749084909491049114912491349144915491649174918491949204921492249234924492549264927492849294930493149324933493449354936493749384939494049414942494349444945494649474948494949504951495249534954495549564957495849594960496149624963496449654966496749684969497049714972497349744975497649774978497949804981498249834984498549864987498849894990499149924993499449954996499749984999500050015002500350045005500650075008500950105011501250135014501550165017501850195020502150225023502450255026502750285029503050315032503350345035503650375038503950405041504250435044504550465047504850495050505150525053505450555056505750585059506050615062506350645065506650675068506950705071507250735074507550765077507850795080508150825083508450855086508750885089509050915092509350945095509650975098509951005101510251035104510551065107510851095110511151125113511451155116511751185119512051215122512351245125512651275128512951305131513251335134513551365137513851395140514151425143514451455146514751485149515051515152515351545155515651575158515951605161516251635164516551665167516851695170517151725173517451755176517751785179518051815182518351845185518651875188518951905191519251935194519551965197519851995200520152025203520452055206520752085209521052115212521352145215521652175218521952205221522252235224522552265227522852295230523152325233523452355236523752385239524052415242524352445245524652475248524952505251525252535254525552565257525852595260526152625263526452655266526752685269527052715272527352745275527652775278527952805281528252835284528552865287528852895290529152925293529452955296529752985299530053015302530353045305530653075308530953105311531253135314531553165317531853195320532153225323532453255326532753285329533053315332533353345335533653375338533953405341534253435344534553465347534853495350535153525353535453555356535753585359536053615362536353645365536653675368536953705371537253735374537553765377537853795380538153825383538453855386538753885389539053915392539353945395539653975398539954005401540254035404540554065407540854095410541154125413541454155416541754185419542054215422542354245425542654275428542954305431543254335434543554365437543854395440544154425443544454455446544754485449545054515452545354545455545654575458545954605461546254635464546554665467546854695470547154725473547454755476547754785479548054815482548354845485548654875488548954905491549254935494549554965497549854995500550155025503550455055506550755085509551055115512551355145515551655175518551955205521552255235524552555265527552855295530553155325533553455355536553755385539554055415542554355445545554655475548554955505551555255535554555555565557555855595560556155625563556455655566556755685569557055715572557355745575557655775578557955805581558255835584558555865587558855895590559155925593559455955596559755985599560056015602560356045605560656075608560956105611561256135614561556165617561856195620562156225623562456255626562756285629563056315632563356345635563656375638563956405641564256435644564556465647564856495650565156525653565456555656565756585659566056615662566356645665566656675668566956705671567256735674567556765677567856795680568156825683568456855686568756885689569056915692569356945695569656975698569957005701570257035704570557065707570857095710571157125713571457155716571757185719572057215722572357245725572657275728572957305731573257335734573557365737573857395740574157425743574457455746574757485749575057515752575357545755575657575758575957605761576257635764576557665767576857695770577157725773577457755776577757785779578057815782578357845785578657875788578957905791579257935794579557965797579857995800580158025803580458055806580758085809581058115812581358145815581658175818581958205821582258235824582558265827582858295830583158325833583458355836583758385839584058415842584358445845584658475848584958505851585258535854585558565857585858595860586158625863586458655866586758685869587058715872587358745875587658775878587958805881588258835884588558865887588858895890589158925893589458955896589758985899590059015902590359045905590659075908590959105911591259135914591559165917591859195920592159225923592459255926592759285929593059315932593359345935593659375938593959405941594259435944594559465947594859495950595159525953595459555956595759585959596059615962596359645965596659675968596959705971597259735974597559765977597859795980598159825983598459855986598759885989599059915992599359945995599659975998599960006001600260036004600560066007600860096010601160126013601460156016601760186019602060216022602360246025602660276028602960306031603260336034603560366037603860396040604160426043604460456046604760486049605060516052605360546055605660576058605960606061606260636064606560666067606860696070607160726073607460756076607760786079608060816082608360846085608660876088608960906091609260936094609560966097609860996100610161026103610461056106610761086109611061116112611361146115611661176118611961206121612261236124612561266127612861296130613161326133613461356136613761386139614061416142614361446145614661476148614961506151615261536154615561566157615861596160616161626163616461656166616761686169617061716172617361746175617661776178617961806181618261836184618561866187618861896190619161926193619461956196619761986199620062016202620362046205620662076208620962106211621262136214621562166217621862196220622162226223622462256226622762286229623062316232623362346235623662376238623962406241624262436244624562466247624862496250625162526253625462556256625762586259626062616262626362646265626662676268626962706271627262736274627562766277627862796280628162826283628462856286628762886289629062916292629362946295629662976298629963006301630263036304630563066307630863096310631163126313631463156316631763186319632063216322632363246325632663276328632963306331633263336334633563366337633863396340634163426343634463456346634763486349635063516352635363546355635663576358635963606361636263636364636563666367636863696370637163726373637463756376637763786379638063816382638363846385638663876388638963906391639263936394639563966397639863996400640164026403640464056406640764086409641064116412641364146415641664176418641964206421642264236424642564266427642864296430643164326433643464356436643764386439644064416442644364446445644664476448644964506451645264536454645564566457645864596460646164626463646464656466646764686469647064716472647364746475647664776478647964806481648264836484648564866487648864896490649164926493649464956496649764986499650065016502650365046505650665076508650965106511651265136514651565166517651865196520652165226523652465256526652765286529653065316532653365346535653665376538653965406541654265436544654565466547654865496550655165526553655465556556655765586559656065616562656365646565656665676568656965706571657265736574657565766577657865796580658165826583658465856586658765886589659065916592659365946595659665976598659966006601660266036604660566066607660866096610661166126613661466156616661766186619662066216622662366246625662666276628662966306631663266336634663566366637663866396640664166426643664466456646664766486649665066516652665366546655665666576658665966606661666266636664666566666667666866696670667166726673667466756676667766786679668066816682668366846685668666876688668966906691669266936694669566966697669866996700670167026703670467056706670767086709671067116712671367146715671667176718671967206721672267236724672567266727672867296730673167326733673467356736673767386739674067416742674367446745674667476748674967506751675267536754675567566757675867596760676167626763676467656766676767686769677067716772677367746775677667776778677967806781678267836784678567866787678867896790679167926793679467956796679767986799680068016802680368046805680668076808680968106811681268136814681568166817681868196820682168226823682468256826682768286829683068316832683368346835683668376838683968406841684268436844684568466847684868496850685168526853685468556856685768586859686068616862686368646865686668676868686968706871687268736874687568766877687868796880688168826883688468856886688768886889689068916892689368946895689668976898689969006901690269036904690569066907690869096910691169126913691469156916691769186919692069216922692369246925692669276928692969306931693269336934693569366937693869396940694169426943694469456946694769486949695069516952695369546955695669576958695969606961696269636964696569666967696869696970697169726973697469756976697769786979698069816982698369846985698669876988698969906991699269936994699569966997699869997000700170027003700470057006700770087009701070117012701370147015701670177018701970207021702270237024702570267027702870297030703170327033703470357036703770387039704070417042704370447045704670477048704970507051705270537054705570567057705870597060706170627063706470657066706770687069707070717072707370747075707670777078707970807081708270837084708570867087708870897090709170927093709470957096709770987099710071017102710371047105710671077108710971107111711271137114711571167117711871197120712171227123712471257126712771287129713071317132713371347135713671377138713971407141714271437144714571467147714871497150715171527153715471557156715771587159716071617162716371647165716671677168716971707171717271737174717571767177717871797180718171827183718471857186718771887189719071917192719371947195719671977198719972007201720272037204720572067207720872097210721172127213721472157216721772187219722072217222722372247225722672277228722972307231723272337234723572367237723872397240724172427243724472457246724772487249725072517252725372547255725672577258725972607261726272637264726572667267726872697270727172727273727472757276727772787279728072817282728372847285728672877288728972907291729272937294729572967297729872997300730173027303730473057306730773087309731073117312731373147315731673177318731973207321732273237324732573267327732873297330733173327333733473357336733773387339734073417342734373447345734673477348734973507351735273537354735573567357735873597360736173627363736473657366736773687369737073717372737373747375737673777378737973807381738273837384738573867387738873897390739173927393739473957396739773987399740074017402740374047405740674077408740974107411741274137414741574167417741874197420742174227423742474257426742774287429743074317432743374347435743674377438743974407441744274437444744574467447744874497450745174527453745474557456745774587459746074617462746374647465746674677468746974707471747274737474747574767477747874797480748174827483748474857486748774887489749074917492749374947495749674977498749975007501750275037504750575067507750875097510751175127513751475157516751775187519752075217522752375247525752675277528752975307531753275337534753575367537753875397540754175427543754475457546754775487549755075517552755375547555755675577558755975607561756275637564756575667567756875697570757175727573757475757576757775787579758075817582758375847585758675877588758975907591759275937594759575967597759875997600760176027603760476057606760776087609761076117612761376147615761676177618761976207621762276237624762576267627762876297630763176327633763476357636763776387639764076417642764376447645764676477648764976507651765276537654765576567657765876597660766176627663766476657666766776687669767076717672767376747675767676777678767976807681768276837684768576867687768876897690769176927693769476957696769776987699770077017702770377047705770677077708770977107711771277137714771577167717771877197720772177227723772477257726772777287729773077317732773377347735773677377738773977407741774277437744774577467747774877497750775177527753775477557756775777587759776077617762776377647765776677677768776977707771777277737774777577767777777877797780778177827783778477857786778777887789779077917792779377947795779677977798779978007801780278037804780578067807780878097810781178127813781478157816781778187819782078217822782378247825782678277828782978307831783278337834783578367837783878397840784178427843784478457846784778487849785078517852785378547855785678577858785978607861786278637864786578667867786878697870787178727873787478757876787778787879788078817882788378847885788678877888788978907891789278937894789578967897789878997900790179027903790479057906790779087909791079117912791379147915791679177918791979207921792279237924792579267927792879297930793179327933793479357936793779387939794079417942794379447945794679477948794979507951795279537954795579567957795879597960796179627963796479657966796779687969797079717972797379747975797679777978797979807981798279837984798579867987798879897990799179927993799479957996799779987999800080018002800380048005800680078008800980108011801280138014801580168017801880198020802180228023802480258026802780288029803080318032803380348035803680378038803980408041804280438044804580468047804880498050805180528053805480558056805780588059806080618062806380648065806680678068806980708071807280738074807580768077807880798080808180828083808480858086808780888089809080918092809380948095809680978098809981008101810281038104810581068107810881098110811181128113811481158116811781188119812081218122812381248125812681278128812981308131813281338134813581368137813881398140814181428143814481458146814781488149815081518152815381548155815681578158815981608161816281638164816581668167816881698170817181728173817481758176817781788179818081818182818381848185818681878188818981908191819281938194819581968197819881998200820182028203820482058206820782088209821082118212821382148215821682178218821982208221822282238224822582268227822882298230823182328233823482358236823782388239824082418242824382448245824682478248824982508251825282538254825582568257825882598260826182628263826482658266826782688269827082718272827382748275827682778278827982808281828282838284828582868287828882898290829182928293829482958296829782988299830083018302830383048305830683078308830983108311831283138314831583168317831883198320832183228323832483258326832783288329833083318332833383348335833683378338833983408341834283438344834583468347834883498350835183528353835483558356835783588359836083618362836383648365836683678368836983708371837283738374837583768377837883798380838183828383838483858386838783888389839083918392839383948395839683978398839984008401840284038404840584068407840884098410841184128413841484158416841784188419842084218422842384248425842684278428842984308431843284338434843584368437843884398440844184428443844484458446844784488449845084518452845384548455845684578458845984608461846284638464846584668467846884698470847184728473847484758476847784788479848084818482848384848485848684878488848984908491849284938494849584968497849884998500850185028503850485058506850785088509851085118512851385148515851685178518851985208521852285238524852585268527852885298530853185328533853485358536853785388539854085418542854385448545854685478548854985508551855285538554855585568557855885598560856185628563856485658566856785688569857085718572857385748575857685778578857985808581858285838584858585868587858885898590859185928593859485958596859785988599860086018602860386048605860686078608860986108611861286138614861586168617861886198620862186228623862486258626862786288629863086318632863386348635863686378638863986408641864286438644864586468647864886498650865186528653865486558656865786588659866086618662866386648665866686678668866986708671867286738674867586768677867886798680868186828683868486858686868786888689869086918692869386948695869686978698869987008701870287038704870587068707870887098710871187128713871487158716871787188719872087218722872387248725872687278728872987308731873287338734873587368737873887398740874187428743874487458746874787488749875087518752875387548755875687578758875987608761876287638764876587668767876887698770877187728773877487758776877787788779878087818782878387848785878687878788878987908791879287938794879587968797879887998800880188028803880488058806880788088809881088118812881388148815881688178818881988208821882288238824882588268827882888298830883188328833883488358836883788388839884088418842884388448845884688478848884988508851885288538854885588568857885888598860886188628863886488658866886788688869887088718872887388748875887688778878887988808881888288838884888588868887888888898890889188928893889488958896889788988899890089018902890389048905890689078908890989108911891289138914891589168917891889198920892189228923892489258926892789288929893089318932893389348935893689378938893989408941894289438944894589468947894889498950895189528953895489558956895789588959896089618962896389648965896689678968896989708971897289738974897589768977897889798980898189828983898489858986898789888989899089918992899389948995899689978998899990009001900290039004900590069007900890099010901190129013901490159016901790189019902090219022902390249025902690279028902990309031903290339034903590369037903890399040904190429043904490459046904790489049905090519052905390549055905690579058905990609061906290639064906590669067906890699070907190729073907490759076907790789079908090819082908390849085908690879088908990909091909290939094909590969097909890999100910191029103910491059106910791089109911091119112911391149115911691179118911991209121912291239124912591269127912891299130913191329133913491359136913791389139914091419142914391449145914691479148914991509151915291539154915591569157915891599160916191629163916491659166916791689169917091719172917391749175917691779178917991809181918291839184918591869187918891899190919191929193919491959196919791989199920092019202920392049205920692079208920992109211921292139214921592169217921892199220922192229223922492259226922792289229923092319232923392349235923692379238923992409241924292439244924592469247924892499250925192529253925492559256925792589259926092619262926392649265926692679268926992709271927292739274927592769277927892799280928192829283928492859286928792889289929092919292929392949295929692979298929993009301930293039304930593069307930893099310931193129313931493159316931793189319932093219322932393249325932693279328932993309331933293339334933593369337933893399340934193429343934493459346934793489349935093519352935393549355935693579358935993609361936293639364936593669367936893699370937193729373937493759376937793789379938093819382938393849385938693879388938993909391939293939394939593969397939893999400940194029403940494059406940794089409941094119412941394149415941694179418941994209421942294239424942594269427942894299430943194329433943494359436943794389439944094419442944394449445944694479448944994509451945294539454945594569457945894599460946194629463946494659466946794689469947094719472947394749475947694779478947994809481948294839484948594869487948894899490949194929493949494959496949794989499950095019502950395049505950695079508950995109511951295139514951595169517951895199520952195229523952495259526952795289529953095319532953395349535953695379538953995409541954295439544954595469547954895499550955195529553955495559556955795589559956095619562956395649565956695679568956995709571957295739574957595769577957895799580958195829583958495859586958795889589959095919592959395949595959695979598959996009601960296039604960596069607960896099610961196129613961496159616961796189619962096219622962396249625962696279628962996309631963296339634963596369637963896399640964196429643964496459646964796489649965096519652965396549655965696579658965996609661966296639664966596669667966896699670967196729673967496759676967796789679968096819682968396849685968696879688968996909691969296939694969596969697969896999700970197029703970497059706970797089709971097119712971397149715971697179718971997209721972297239724972597269727972897299730973197329733973497359736973797389739974097419742974397449745974697479748974997509751975297539754975597569757975897599760976197629763976497659766976797689769977097719772977397749775977697779778977997809781978297839784978597869787978897899790979197929793979497959796979797989799980098019802980398049805980698079808980998109811981298139814981598169817981898199820982198229823982498259826982798289829983098319832983398349835983698379838983998409841984298439844984598469847984898499850985198529853985498559856985798589859986098619862986398649865986698679868986998709871987298739874987598769877987898799880988198829883988498859886988798889889989098919892989398949895989698979898989999009901990299039904990599069907990899099910991199129913991499159916991799189919992099219922992399249925992699279928992999309931993299339934993599369937993899399940994199429943994499459946994799489949995099519952995399549955995699579958995999609961996299639964996599669967996899699970997199729973997499759976997799789979998099819982998399849985998699879988998999909991999299939994999599969997999899991000010001100021000310004100051000610007100081000910010100111001210013100141001510016100171001810019100201002110022100231002410025100261002710028100291003010031100321003310034100351003610037100381003910040100411004210043100441004510046100471004810049100501005110052100531005410055100561005710058100591006010061100621006310064100651006610067100681006910070100711007210073100741007510076100771007810079100801008110082100831008410085100861008710088100891009010091100921009310094100951009610097100981009910100101011010210103101041010510106101071010810109101101011110112101131011410115101161011710118101191012010121101221012310124101251012610127101281012910130101311013210133101341013510136101371013810139101401014110142101431014410145101461014710148101491015010151101521015310154101551015610157101581015910160101611016210163101641016510166101671016810169101701017110172101731017410175101761017710178101791018010181101821018310184101851018610187101881018910190101911019210193101941019510196101971019810199102001020110202102031020410205102061020710208102091021010211102121021310214102151021610217102181021910220102211022210223102241022510226102271022810229102301023110232102331023410235102361023710238102391024010241102421024310244102451024610247102481024910250102511025210253102541025510256102571025810259102601026110262102631026410265102661026710268102691027010271102721027310274102751027610277102781027910280102811028210283102841028510286102871028810289102901029110292102931029410295102961029710298102991030010301103021030310304103051030610307103081030910310103111031210313103141031510316103171031810319103201032110322103231032410325103261032710328103291033010331103321033310334103351033610337103381033910340103411034210343103441034510346103471034810349103501035110352103531035410355103561035710358103591036010361103621036310364103651036610367103681036910370103711037210373103741037510376103771037810379103801038110382103831038410385103861038710388103891039010391103921039310394103951039610397103981039910400104011040210403104041040510406104071040810409104101041110412104131041410415104161041710418104191042010421104221042310424104251042610427104281042910430104311043210433104341043510436104371043810439104401044110442104431044410445104461044710448104491045010451104521045310454104551045610457104581045910460104611046210463104641046510466104671046810469104701047110472104731047410475104761047710478104791048010481104821048310484104851048610487104881048910490104911049210493104941049510496104971049810499105001050110502105031050410505105061050710508105091051010511105121051310514105151051610517105181051910520105211052210523105241052510526105271052810529105301053110532105331053410535105361053710538105391054010541105421054310544105451054610547105481054910550105511055210553105541055510556105571055810559105601056110562105631056410565105661056710568105691057010571105721057310574105751057610577105781057910580105811058210583105841058510586105871058810589105901059110592105931059410595105961059710598105991060010601106021060310604106051060610607106081060910610106111061210613106141061510616106171061810619106201062110622106231062410625106261062710628106291063010631106321063310634106351063610637106381063910640106411064210643106441064510646106471064810649106501065110652106531065410655106561065710658106591066010661106621066310664106651066610667106681066910670106711067210673106741067510676106771067810679106801068110682106831068410685106861068710688106891069010691106921069310694106951069610697106981069910700107011070210703107041070510706107071070810709107101071110712107131071410715107161071710718107191072010721107221072310724107251072610727107281072910730107311073210733107341073510736107371073810739107401074110742107431074410745107461074710748107491075010751107521075310754107551075610757107581075910760107611076210763107641076510766107671076810769107701077110772107731077410775107761077710778107791078010781107821078310784107851078610787107881078910790107911079210793107941079510796107971079810799108001080110802108031080410805108061080710808108091081010811108121081310814108151081610817108181081910820108211082210823108241082510826108271082810829108301083110832108331083410835108361083710838108391084010841108421084310844108451084610847108481084910850108511085210853108541085510856108571085810859108601086110862108631086410865108661086710868108691087010871108721087310874108751087610877108781087910880108811088210883108841088510886108871088810889108901089110892108931089410895108961089710898108991090010901109021090310904109051090610907109081090910910109111091210913109141091510916109171091810919109201092110922109231092410925109261092710928109291093010931109321093310934109351093610937109381093910940109411094210943109441094510946109471094810949109501095110952109531095410955109561095710958109591096010961109621096310964109651096610967109681096910970109711097210973109741097510976109771097810979109801098110982109831098410985109861098710988109891099010991109921099310994109951099610997109981099911000110011100211003110041100511006110071100811009110101101111012110131101411015110161101711018110191102011021110221102311024110251102611027110281102911030110311103211033110341103511036110371103811039110401104111042110431104411045110461104711048110491105011051110521105311054110551105611057110581105911060110611106211063110641106511066110671106811069110701107111072110731107411075110761107711078110791108011081110821108311084110851108611087110881108911090110911109211093110941109511096110971109811099111001110111102111031110411105111061110711108111091111011111111121111311114111151111611117111181111911120111211112211123111241112511126111271112811129111301113111132111331113411135111361113711138111391114011141111421114311144111451114611147111481114911150111511115211153111541115511156111571115811159111601116111162111631116411165111661116711168111691117011171111721117311174111751117611177111781117911180111811118211183111841118511186111871118811189111901119111192111931119411195111961119711198111991120011201112021120311204112051120611207112081120911210112111121211213112141121511216112171121811219112201122111222112231122411225112261122711228112291123011231112321123311234112351123611237112381123911240112411124211243112441124511246112471124811249112501125111252112531125411255112561125711258112591126011261112621126311264112651126611267112681126911270112711127211273112741127511276112771127811279112801128111282112831128411285112861128711288112891129011291112921129311294112951129611297112981129911300113011130211303113041130511306113071130811309113101131111312113131131411315113161131711318113191132011321113221132311324113251132611327113281132911330113311133211333113341133511336113371133811339113401134111342113431134411345113461134711348113491135011351113521135311354113551135611357113581135911360113611136211363113641136511366113671136811369113701137111372113731137411375113761137711378113791138011381113821138311384113851138611387113881138911390113911139211393113941139511396113971139811399114001140111402114031140411405114061140711408114091141011411114121141311414114151141611417114181141911420114211142211423114241142511426114271142811429114301143111432114331143411435114361143711438114391144011441114421144311444114451144611447114481144911450114511145211453114541145511456114571145811459114601146111462114631146411465114661146711468114691147011471114721147311474114751147611477114781147911480114811148211483114841148511486114871148811489114901149111492114931149411495114961149711498114991150011501115021150311504115051150611507115081150911510115111151211513115141151511516115171151811519115201152111522115231152411525115261152711528115291153011531115321153311534115351153611537115381153911540115411154211543115441154511546115471154811549115501155111552115531155411555115561155711558115591156011561115621156311564115651156611567115681156911570115711157211573115741157511576115771157811579115801158111582115831158411585115861158711588115891159011591115921159311594115951159611597115981159911600116011160211603116041160511606116071160811609116101161111612116131161411615116161161711618116191162011621116221162311624116251162611627116281162911630116311163211633116341163511636116371163811639116401164111642116431164411645116461164711648116491165011651116521165311654116551165611657116581165911660116611166211663116641166511666116671166811669116701167111672116731167411675116761167711678116791168011681116821168311684116851168611687116881168911690116911169211693116941169511696116971169811699117001170111702117031170411705117061170711708117091171011711117121171311714117151171611717117181171911720117211172211723117241172511726117271172811729117301173111732117331173411735117361173711738117391174011741117421174311744117451174611747117481174911750117511175211753117541175511756117571175811759117601176111762117631176411765117661176711768117691177011771117721177311774117751177611777117781177911780117811178211783117841178511786117871178811789117901179111792117931179411795117961179711798117991180011801118021180311804118051180611807118081180911810118111181211813118141181511816118171181811819118201182111822118231182411825118261182711828118291183011831118321183311834118351183611837118381183911840118411184211843118441184511846118471184811849118501185111852118531185411855118561185711858118591186011861118621186311864118651186611867118681186911870118711187211873118741187511876118771187811879118801188111882118831188411885118861188711888118891189011891118921189311894118951189611897118981189911900119011190211903119041190511906119071190811909119101191111912119131191411915119161191711918119191192011921119221192311924119251192611927119281192911930119311193211933119341193511936119371193811939119401194111942119431194411945119461194711948119491195011951119521195311954119551195611957119581195911960119611196211963119641196511966119671196811969119701197111972119731197411975119761197711978119791198011981119821198311984119851198611987119881198911990119911199211993119941199511996119971199811999120001200112002120031200412005120061200712008120091201012011120121201312014120151201612017120181201912020120211202212023120241202512026120271202812029120301203112032120331203412035120361203712038120391204012041120421204312044120451204612047120481204912050120511205212053120541205512056120571205812059120601206112062120631206412065120661206712068120691207012071120721207312074120751207612077120781207912080120811208212083120841208512086120871208812089120901209112092120931209412095120961209712098120991210012101121021210312104121051210612107121081210912110121111211212113121141211512116121171211812119121201212112122121231212412125121261212712128121291213012131121321213312134121351213612137121381213912140121411214212143121441214512146121471214812149121501215112152121531215412155121561215712158121591216012161121621216312164121651216612167121681216912170121711217212173121741217512176121771217812179121801218112182121831218412185121861218712188121891219012191121921219312194121951219612197121981219912200122011220212203122041220512206122071220812209122101221112212122131221412215122161221712218122191222012221122221222312224122251222612227122281222912230122311223212233122341223512236122371223812239122401224112242122431224412245122461224712248122491225012251122521225312254122551225612257122581225912260122611226212263122641226512266122671226812269122701227112272122731227412275122761227712278122791228012281122821228312284122851228612287122881228912290122911229212293122941229512296122971229812299123001230112302123031230412305123061230712308123091231012311123121231312314123151231612317123181231912320123211232212323123241232512326123271232812329123301233112332123331233412335123361233712338123391234012341123421234312344123451234612347123481234912350123511235212353123541235512356123571235812359123601236112362123631236412365123661236712368123691237012371123721237312374123751237612377123781237912380123811238212383123841238512386123871238812389123901239112392123931239412395123961239712398123991240012401124021240312404124051240612407124081240912410124111241212413124141241512416124171241812419124201242112422124231242412425124261242712428124291243012431124321243312434124351243612437124381243912440124411244212443124441244512446124471244812449124501245112452124531245412455124561245712458124591246012461124621246312464124651246612467124681246912470124711247212473124741247512476124771247812479124801248112482124831248412485124861248712488124891249012491124921249312494124951249612497124981249912500125011250212503125041250512506125071250812509125101251112512125131251412515125161251712518125191252012521125221252312524125251252612527125281252912530125311253212533125341253512536125371253812539125401254112542125431254412545125461254712548125491255012551125521255312554125551255612557125581255912560125611256212563125641256512566125671256812569125701257112572125731257412575125761257712578125791258012581125821258312584125851258612587125881258912590125911259212593125941259512596125971259812599126001260112602126031260412605126061260712608126091261012611126121261312614126151261612617126181261912620126211262212623126241262512626126271262812629126301263112632126331263412635126361263712638126391264012641126421264312644126451264612647126481264912650126511265212653126541265512656126571265812659126601266112662126631266412665126661266712668126691267012671126721267312674126751267612677126781267912680126811268212683126841268512686126871268812689126901269112692126931269412695126961269712698126991270012701127021270312704127051270612707127081270912710127111271212713127141271512716127171271812719127201272112722127231272412725127261272712728127291273012731127321273312734127351273612737127381273912740127411274212743127441274512746127471274812749127501275112752127531275412755127561275712758127591276012761127621276312764127651276612767127681276912770127711277212773127741277512776127771277812779127801278112782127831278412785127861278712788127891279012791127921279312794127951279612797127981279912800128011280212803128041280512806128071280812809128101281112812128131281412815128161281712818128191282012821128221282312824128251282612827128281282912830128311283212833128341283512836128371283812839128401284112842128431284412845128461284712848128491285012851128521285312854128551285612857128581285912860128611286212863128641286512866128671286812869128701287112872128731287412875128761287712878128791288012881128821288312884128851288612887128881288912890128911289212893128941289512896128971289812899129001290112902129031290412905129061290712908129091291012911129121291312914129151291612917129181291912920129211292212923129241292512926129271292812929129301293112932129331293412935129361293712938129391294012941129421294312944129451294612947129481294912950129511295212953129541295512956129571295812959129601296112962129631296412965129661296712968129691297012971129721297312974129751297612977129781297912980129811298212983129841298512986129871298812989129901299112992129931299412995129961299712998129991300013001130021300313004130051300613007130081300913010130111301213013130141301513016130171301813019130201302113022130231302413025130261302713028130291303013031130321303313034130351303613037130381303913040130411304213043130441304513046130471304813049130501305113052130531305413055130561305713058130591306013061130621306313064130651306613067130681306913070130711307213073130741307513076130771307813079130801308113082130831308413085130861308713088130891309013091130921309313094130951309613097130981309913100131011310213103131041310513106131071310813109131101311113112131131311413115131161311713118131191312013121131221312313124131251312613127131281312913130131311313213133131341313513136131371313813139131401314113142131431314413145131461314713148131491315013151131521315313154131551315613157131581315913160131611316213163131641316513166131671316813169131701317113172131731317413175131761317713178131791318013181131821318313184131851318613187131881318913190131911319213193131941319513196131971319813199132001320113202132031320413205132061320713208132091321013211132121321313214132151321613217132181321913220132211322213223132241322513226132271322813229132301323113232132331323413235132361323713238132391324013241132421324313244132451324613247132481324913250132511325213253132541325513256132571325813259132601326113262132631326413265132661326713268132691327013271132721327313274132751327613277132781327913280132811328213283132841328513286132871328813289132901329113292132931329413295132961329713298132991330013301133021330313304133051330613307133081330913310133111331213313133141331513316133171331813319133201332113322133231332413325133261332713328133291333013331133321333313334133351333613337133381333913340133411334213343133441334513346133471334813349133501335113352133531335413355133561335713358133591336013361133621336313364133651336613367133681336913370133711337213373133741337513376133771337813379133801338113382133831338413385133861338713388133891339013391133921339313394133951339613397133981339913400134011340213403134041340513406134071340813409134101341113412134131341413415134161341713418134191342013421134221342313424134251342613427134281342913430134311343213433134341343513436134371343813439134401344113442134431344413445134461344713448134491345013451134521345313454134551345613457134581345913460134611346213463134641346513466134671346813469134701347113472134731347413475134761347713478134791348013481134821348313484134851348613487134881348913490134911349213493134941349513496134971349813499135001350113502135031350413505135061350713508135091351013511135121351313514135151351613517135181351913520135211352213523135241352513526135271352813529135301353113532135331353413535135361353713538135391354013541135421354313544135451354613547135481354913550135511355213553135541355513556135571355813559135601356113562135631356413565135661356713568135691357013571135721357313574135751357613577135781357913580135811358213583135841358513586135871358813589135901359113592135931359413595135961359713598135991360013601136021360313604136051360613607136081360913610136111361213613136141361513616136171361813619136201362113622136231362413625136261362713628136291363013631136321363313634136351363613637136381363913640136411364213643136441364513646136471364813649136501365113652136531365413655136561365713658136591366013661136621366313664136651366613667136681366913670136711367213673136741367513676136771367813679136801368113682136831368413685136861368713688136891369013691136921369313694136951369613697136981369913700137011370213703137041370513706137071370813709137101371113712137131371413715137161371713718137191372013721137221372313724137251372613727137281372913730137311373213733137341373513736137371373813739137401374113742137431374413745137461374713748137491375013751137521375313754137551375613757137581375913760137611376213763137641376513766137671376813769137701377113772137731377413775137761377713778137791378013781137821378313784137851378613787137881378913790137911379213793137941379513796137971379813799138001380113802138031380413805138061380713808138091381013811138121381313814138151381613817138181381913820138211382213823138241382513826138271382813829138301383113832138331383413835138361383713838138391384013841138421384313844138451384613847138481384913850138511385213853138541385513856138571385813859138601386113862138631386413865138661386713868138691387013871138721387313874138751387613877138781387913880138811388213883138841388513886138871388813889138901389113892138931389413895138961389713898138991390013901139021390313904139051390613907139081390913910139111391213913139141391513916139171391813919139201392113922139231392413925139261392713928139291393013931139321393313934139351393613937139381393913940139411394213943139441394513946139471394813949139501395113952139531395413955139561395713958139591396013961139621396313964139651396613967139681396913970139711397213973139741397513976139771397813979139801398113982139831398413985139861398713988139891399013991139921399313994139951399613997139981399914000140011400214003140041400514006140071400814009140101401114012140131401414015140161401714018140191402014021140221402314024140251402614027140281402914030140311403214033140341403514036140371403814039140401404114042140431404414045140461404714048140491405014051140521405314054140551405614057140581405914060140611406214063140641406514066140671406814069140701407114072140731407414075140761407714078140791408014081140821408314084140851408614087140881408914090140911409214093140941409514096140971409814099141001410114102141031410414105141061410714108141091411014111141121411314114141151411614117141181411914120141211412214123141241412514126141271412814129141301413114132141331413414135141361413714138141391414014141141421414314144141451414614147141481414914150141511415214153141541415514156141571415814159141601416114162141631416414165141661416714168141691417014171141721417314174141751417614177141781417914180141811418214183141841418514186141871418814189141901419114192141931419414195141961419714198141991420014201142021420314204142051420614207142081420914210142111421214213142141421514216142171421814219142201422114222142231422414225142261422714228142291423014231142321423314234142351423614237142381423914240142411424214243142441424514246142471424814249142501425114252142531425414255142561425714258142591426014261142621426314264142651426614267142681426914270142711427214273142741427514276142771427814279142801428114282142831428414285142861428714288142891429014291142921429314294142951429614297142981429914300143011430214303143041430514306143071430814309143101431114312143131431414315143161431714318143191432014321143221432314324143251432614327143281432914330143311433214333143341433514336143371433814339143401434114342143431434414345143461434714348143491435014351143521435314354143551435614357143581435914360143611436214363143641436514366143671436814369143701437114372143731437414375143761437714378143791438014381143821438314384143851438614387143881438914390143911439214393143941439514396143971439814399144001440114402144031440414405144061440714408144091441014411144121441314414144151441614417144181441914420144211442214423144241442514426144271442814429144301443114432144331443414435144361443714438144391444014441144421444314444144451444614447144481444914450144511445214453144541445514456144571445814459144601446114462144631446414465144661446714468144691447014471144721447314474144751447614477144781447914480144811448214483144841448514486144871448814489144901449114492144931449414495144961449714498144991450014501145021450314504145051450614507145081450914510145111451214513145141451514516145171451814519145201452114522145231452414525145261452714528145291453014531145321453314534145351453614537145381453914540145411454214543145441454514546145471454814549145501455114552145531455414555145561455714558145591456014561145621456314564145651456614567145681456914570145711457214573145741457514576145771457814579145801458114582145831458414585145861458714588145891459014591145921459314594145951459614597145981459914600146011460214603146041460514606146071460814609146101461114612146131461414615146161461714618146191462014621146221462314624146251462614627146281462914630146311463214633146341463514636146371463814639146401464114642146431464414645146461464714648146491465014651146521465314654146551465614657146581465914660146611466214663146641466514666146671466814669146701467114672146731467414675146761467714678146791468014681146821468314684146851468614687146881468914690146911469214693146941469514696146971469814699147001470114702147031470414705147061470714708147091471014711147121471314714147151471614717147181471914720147211472214723147241472514726147271472814729147301473114732147331473414735147361473714738147391474014741147421474314744147451474614747147481474914750147511475214753147541475514756147571475814759147601476114762147631476414765147661476714768147691477014771147721477314774147751477614777147781477914780147811478214783147841478514786147871478814789147901479114792147931479414795147961479714798147991480014801148021480314804148051480614807148081480914810148111481214813148141481514816148171481814819148201482114822148231482414825148261482714828148291483014831148321483314834148351483614837148381483914840148411484214843148441484514846148471484814849148501485114852148531485414855148561485714858148591486014861148621486314864148651486614867148681486914870148711487214873148741487514876148771487814879148801488114882148831488414885148861488714888148891489014891148921489314894148951489614897148981489914900149011490214903149041490514906149071490814909149101491114912149131491414915149161491714918149191492014921149221492314924149251492614927149281492914930149311493214933149341493514936149371493814939149401494114942149431494414945149461494714948149491495014951149521495314954149551495614957149581495914960149611496214963149641496514966149671496814969149701497114972149731497414975149761497714978149791498014981149821498314984149851498614987149881498914990149911499214993149941499514996149971499814999150001500115002150031500415005150061500715008150091501015011150121501315014150151501615017150181501915020150211502215023150241502515026150271502815029150301503115032150331503415035150361503715038150391504015041150421504315044150451504615047150481504915050150511505215053150541505515056150571505815059150601506115062150631506415065150661506715068150691507015071150721507315074150751507615077150781507915080150811508215083150841508515086150871508815089150901509115092150931509415095150961509715098150991510015101151021510315104151051510615107151081510915110151111511215113151141511515116151171511815119151201512115122151231512415125151261512715128151291513015131151321513315134151351513615137151381513915140151411514215143151441514515146151471514815149151501515115152151531515415155151561515715158151591516015161151621516315164151651516615167151681516915170151711517215173151741517515176151771517815179151801518115182151831518415185151861518715188151891519015191151921519315194151951519615197151981519915200152011520215203152041520515206152071520815209152101521115212152131521415215152161521715218152191522015221152221522315224152251522615227152281522915230152311523215233152341523515236152371523815239152401524115242152431524415245152461524715248152491525015251152521525315254152551525615257152581525915260152611526215263152641526515266152671526815269152701527115272152731527415275152761527715278152791528015281152821528315284152851528615287152881528915290152911529215293152941529515296152971529815299153001530115302153031530415305153061530715308153091531015311153121531315314153151531615317153181531915320153211532215323153241532515326153271532815329153301533115332153331533415335153361533715338153391534015341153421534315344153451534615347153481534915350153511535215353153541535515356153571535815359153601536115362153631536415365153661536715368153691537015371153721537315374153751537615377153781537915380153811538215383153841538515386153871538815389153901539115392153931539415395153961539715398153991540015401154021540315404154051540615407154081540915410154111541215413154141541515416154171541815419154201542115422154231542415425154261542715428154291543015431154321543315434154351543615437154381543915440154411544215443154441544515446154471544815449154501545115452154531545415455154561545715458154591546015461154621546315464154651546615467154681546915470154711547215473154741547515476154771547815479154801548115482154831548415485154861548715488154891549015491154921549315494154951549615497154981549915500155011550215503155041550515506155071550815509155101551115512155131551415515155161551715518155191552015521155221552315524155251552615527155281552915530155311553215533155341553515536155371553815539155401554115542155431554415545155461554715548155491555015551155521555315554155551555615557155581555915560155611556215563155641556515566155671556815569155701557115572155731557415575155761557715578155791558015581155821558315584155851558615587155881558915590155911559215593155941559515596155971559815599156001560115602156031560415605156061560715608156091561015611156121561315614156151561615617156181561915620156211562215623156241562515626156271562815629156301563115632156331563415635156361563715638156391564015641156421564315644156451564615647156481564915650156511565215653156541565515656156571565815659156601566115662156631566415665156661566715668156691567015671156721567315674156751567615677156781567915680156811568215683156841568515686156871568815689156901569115692156931569415695156961569715698156991570015701157021570315704157051570615707157081570915710157111571215713157141571515716157171571815719157201572115722157231572415725157261572715728157291573015731157321573315734157351573615737157381573915740157411574215743157441574515746157471574815749157501575115752157531575415755157561575715758157591576015761157621576315764157651576615767157681576915770157711577215773157741577515776157771577815779157801578115782157831578415785157861578715788157891579015791157921579315794157951579615797157981579915800158011580215803158041580515806158071580815809158101581115812158131581415815158161581715818158191582015821158221582315824158251582615827158281582915830158311583215833158341583515836158371583815839158401584115842158431584415845158461584715848158491585015851158521585315854158551585615857158581585915860158611586215863158641586515866158671586815869158701587115872158731587415875158761587715878158791588015881158821588315884158851588615887158881588915890158911589215893158941589515896158971589815899159001590115902159031590415905159061590715908159091591015911159121591315914159151591615917159181591915920159211592215923159241592515926159271592815929159301593115932159331593415935159361593715938159391594015941159421594315944159451594615947159481594915950159511595215953159541595515956159571595815959159601596115962159631596415965159661596715968159691597015971159721597315974159751597615977159781597915980159811598215983159841598515986159871598815989159901599115992159931599415995159961599715998159991600016001160021600316004160051600616007160081600916010160111601216013160141601516016160171601816019160201602116022160231602416025160261602716028160291603016031160321603316034160351603616037160381603916040160411604216043160441604516046160471604816049160501605116052160531605416055160561605716058160591606016061160621606316064160651606616067160681606916070160711607216073160741607516076160771607816079160801608116082160831608416085160861608716088160891609016091160921609316094160951609616097160981609916100161011610216103161041610516106161071610816109161101611116112161131611416115161161611716118161191612016121161221612316124161251612616127161281612916130161311613216133161341613516136161371613816139161401614116142161431614416145161461614716148161491615016151161521615316154161551615616157161581615916160161611616216163161641616516166161671616816169161701617116172161731617416175161761617716178161791618016181161821618316184161851618616187161881618916190161911619216193161941619516196161971619816199162001620116202162031620416205162061620716208162091621016211162121621316214162151621616217162181621916220162211622216223162241622516226162271622816229162301623116232162331623416235162361623716238162391624016241162421624316244162451624616247162481624916250162511625216253162541625516256162571625816259162601626116262162631626416265162661626716268162691627016271162721627316274162751627616277162781627916280162811628216283162841628516286162871628816289162901629116292162931629416295162961629716298162991630016301163021630316304163051630616307163081630916310163111631216313163141631516316163171631816319163201632116322163231632416325163261632716328163291633016331163321633316334163351633616337163381633916340163411634216343163441634516346163471634816349163501635116352163531635416355163561635716358163591636016361163621636316364163651636616367163681636916370163711637216373163741637516376163771637816379163801638116382163831638416385163861638716388163891639016391163921639316394163951639616397163981639916400164011640216403164041640516406164071640816409164101641116412164131641416415164161641716418164191642016421164221642316424164251642616427164281642916430164311643216433164341643516436164371643816439164401644116442164431644416445164461644716448164491645016451164521645316454164551645616457164581645916460164611646216463164641646516466164671646816469164701647116472164731647416475164761647716478164791648016481164821648316484164851648616487164881648916490164911649216493164941649516496164971649816499165001650116502165031650416505165061650716508165091651016511165121651316514165151651616517165181651916520165211652216523165241652516526165271652816529165301653116532165331653416535165361653716538165391654016541165421654316544165451654616547165481654916550165511655216553165541655516556165571655816559165601656116562165631656416565165661656716568165691657016571165721657316574165751657616577165781657916580165811658216583165841658516586165871658816589165901659116592165931659416595165961659716598165991660016601166021660316604166051660616607166081660916610166111661216613166141661516616166171661816619166201662116622166231662416625166261662716628166291663016631166321663316634166351663616637166381663916640166411664216643166441664516646166471664816649166501665116652166531665416655166561665716658166591666016661166621666316664166651666616667166681666916670166711667216673166741667516676166771667816679166801668116682166831668416685166861668716688166891669016691166921669316694166951669616697166981669916700167011670216703167041670516706167071670816709167101671116712167131671416715167161671716718167191672016721167221672316724167251672616727167281672916730167311673216733167341673516736167371673816739167401674116742167431674416745167461674716748167491675016751167521675316754167551675616757167581675916760167611676216763167641676516766167671676816769167701677116772167731677416775167761677716778167791678016781167821678316784167851678616787167881678916790167911679216793167941679516796167971679816799168001680116802168031680416805168061680716808168091681016811168121681316814168151681616817168181681916820168211682216823168241682516826168271682816829168301683116832168331683416835168361683716838168391684016841168421684316844168451684616847168481684916850168511685216853168541685516856168571685816859168601686116862168631686416865168661686716868168691687016871168721687316874168751687616877168781687916880168811688216883168841688516886168871688816889168901689116892168931689416895168961689716898168991690016901169021690316904169051690616907169081690916910169111691216913169141691516916169171691816919169201692116922169231692416925169261692716928169291693016931169321693316934169351693616937169381693916940169411694216943169441694516946169471694816949169501695116952169531695416955169561695716958169591696016961169621696316964169651696616967169681696916970169711697216973169741697516976169771697816979169801698116982169831698416985169861698716988169891699016991169921699316994169951699616997169981699917000170011700217003170041700517006170071700817009170101701117012170131701417015170161701717018170191702017021170221702317024170251702617027170281702917030170311703217033170341703517036170371703817039170401704117042170431704417045170461704717048170491705017051170521705317054170551705617057170581705917060170611706217063170641706517066170671706817069170701707117072170731707417075170761707717078170791708017081170821708317084170851708617087170881708917090170911709217093170941709517096170971709817099171001710117102171031710417105171061710717108171091711017111171121711317114171151711617117171181711917120171211712217123171241712517126171271712817129171301713117132171331713417135171361713717138171391714017141171421714317144171451714617147171481714917150171511715217153171541715517156171571715817159171601716117162171631716417165171661716717168171691717017171171721717317174171751717617177171781717917180171811718217183171841718517186171871718817189171901719117192171931719417195171961719717198171991720017201172021720317204172051720617207172081720917210172111721217213172141721517216172171721817219172201722117222172231722417225172261722717228172291723017231172321723317234172351723617237172381723917240172411724217243172441724517246172471724817249172501725117252172531725417255172561725717258172591726017261172621726317264172651726617267172681726917270172711727217273172741727517276172771727817279172801728117282172831728417285172861728717288172891729017291172921729317294172951729617297172981729917300173011730217303173041730517306173071730817309173101731117312173131731417315173161731717318173191732017321173221732317324173251732617327173281732917330173311733217333173341733517336173371733817339173401734117342173431734417345173461734717348173491735017351173521735317354173551735617357173581735917360173611736217363173641736517366173671736817369173701737117372173731737417375173761737717378173791738017381173821738317384173851738617387173881738917390173911739217393173941739517396173971739817399174001740117402174031740417405174061740717408174091741017411174121741317414174151741617417174181741917420174211742217423174241742517426174271742817429174301743117432174331743417435174361743717438174391744017441174421744317444174451744617447174481744917450174511745217453174541745517456174571745817459174601746117462174631746417465174661746717468174691747017471174721747317474174751747617477174781747917480174811748217483174841748517486174871748817489174901749117492174931749417495174961749717498174991750017501175021750317504175051750617507175081750917510175111751217513175141751517516175171751817519175201752117522175231752417525175261752717528175291753017531175321753317534175351753617537175381753917540175411754217543175441754517546175471754817549175501755117552175531755417555175561755717558175591756017561175621756317564175651756617567175681756917570175711757217573175741757517576175771757817579175801758117582175831758417585175861758717588175891759017591175921759317594175951759617597175981759917600176011760217603176041760517606176071760817609176101761117612176131761417615176161761717618176191762017621176221762317624176251762617627176281762917630176311763217633176341763517636176371763817639176401764117642176431764417645176461764717648176491765017651176521765317654176551765617657176581765917660176611766217663176641766517666176671766817669176701767117672176731767417675176761767717678176791768017681176821768317684176851768617687176881768917690176911769217693176941769517696176971769817699177001770117702177031770417705177061770717708177091771017711177121771317714177151771617717177181771917720177211772217723177241772517726177271772817729177301773117732177331773417735177361773717738177391774017741177421774317744177451774617747177481774917750177511775217753177541775517756177571775817759177601776117762177631776417765177661776717768177691777017771177721777317774177751777617777177781777917780177811778217783177841778517786177871778817789177901779117792177931779417795177961779717798177991780017801178021780317804178051780617807178081780917810178111781217813178141781517816178171781817819178201782117822178231782417825178261782717828178291783017831178321783317834178351783617837178381783917840178411784217843178441784517846178471784817849178501785117852178531785417855178561785717858178591786017861178621786317864178651786617867178681786917870178711787217873178741787517876178771787817879178801788117882178831788417885178861788717888178891789017891178921789317894178951789617897178981789917900179011790217903179041790517906179071790817909179101791117912179131791417915179161791717918179191792017921179221792317924179251792617927179281792917930179311793217933179341793517936179371793817939179401794117942179431794417945179461794717948179491795017951179521795317954179551795617957179581795917960179611796217963179641796517966179671796817969179701797117972179731797417975179761797717978179791798017981179821798317984179851798617987179881798917990179911799217993179941799517996179971799817999180001800118002180031800418005180061800718008180091801018011180121801318014180151801618017180181801918020180211802218023180241802518026180271802818029180301803118032180331803418035180361803718038180391804018041180421804318044180451804618047180481804918050180511805218053180541805518056180571805818059180601806118062180631806418065180661806718068180691807018071180721807318074180751807618077180781807918080180811808218083180841808518086180871808818089180901809118092180931809418095180961809718098180991810018101181021810318104181051810618107181081810918110181111811218113181141811518116181171811818119181201812118122181231812418125181261812718128181291813018131181321813318134181351813618137181381813918140181411814218143181441814518146181471814818149181501815118152181531815418155181561815718158181591816018161181621816318164181651816618167181681816918170181711817218173181741817518176181771817818179181801818118182181831818418185181861818718188181891819018191181921819318194181951819618197181981819918200182011820218203182041820518206182071820818209182101821118212182131821418215182161821718218182191822018221182221822318224182251822618227182281822918230182311823218233182341823518236182371823818239182401824118242182431824418245182461824718248182491825018251182521825318254182551825618257182581825918260182611826218263182641826518266182671826818269182701827118272182731827418275182761827718278182791828018281182821828318284182851828618287182881828918290182911829218293182941829518296182971829818299183001830118302183031830418305183061830718308183091831018311183121831318314183151831618317183181831918320183211832218323183241832518326183271832818329183301833118332183331833418335183361833718338183391834018341183421834318344183451834618347183481834918350183511835218353183541835518356183571835818359183601836118362183631836418365183661836718368183691837018371183721837318374183751837618377183781837918380183811838218383183841838518386183871838818389183901839118392183931839418395183961839718398183991840018401184021840318404184051840618407184081840918410184111841218413184141841518416184171841818419184201842118422184231842418425184261842718428184291843018431184321843318434184351843618437184381843918440184411844218443184441844518446184471844818449184501845118452184531845418455184561845718458184591846018461184621846318464184651846618467184681846918470184711847218473184741847518476184771847818479184801848118482184831848418485184861848718488184891849018491184921849318494184951849618497184981849918500185011850218503185041850518506185071850818509185101851118512185131851418515185161851718518185191852018521185221852318524185251852618527185281852918530185311853218533185341853518536185371853818539185401854118542185431854418545185461854718548185491855018551185521855318554185551855618557185581855918560185611856218563185641856518566185671856818569185701857118572185731857418575185761857718578185791858018581185821858318584185851858618587185881858918590185911859218593185941859518596185971859818599186001860118602186031860418605186061860718608186091861018611186121861318614186151861618617186181861918620186211862218623186241862518626186271862818629186301863118632186331863418635186361863718638186391864018641186421864318644186451864618647186481864918650186511865218653186541865518656186571865818659186601866118662186631866418665186661866718668186691867018671186721867318674186751867618677186781867918680186811868218683186841868518686186871868818689186901869118692186931869418695186961869718698186991870018701187021870318704187051870618707187081870918710187111871218713187141871518716187171871818719187201872118722187231872418725187261872718728187291873018731187321873318734187351873618737187381873918740187411874218743187441874518746187471874818749187501875118752187531875418755187561875718758187591876018761187621876318764187651876618767187681876918770187711877218773187741877518776187771877818779187801878118782187831878418785187861878718788187891879018791187921879318794187951879618797187981879918800188011880218803188041880518806188071880818809188101881118812188131881418815188161881718818188191882018821188221882318824188251882618827188281882918830188311883218833188341883518836188371883818839188401884118842188431884418845188461884718848188491885018851188521885318854188551885618857188581885918860188611886218863188641886518866188671886818869188701887118872188731887418875188761887718878188791888018881188821888318884188851888618887188881888918890188911889218893188941889518896188971889818899189001890118902189031890418905189061890718908189091891018911189121891318914189151891618917189181891918920189211892218923189241892518926189271892818929189301893118932189331893418935189361893718938189391894018941189421894318944189451894618947189481894918950189511895218953189541895518956189571895818959189601896118962189631896418965189661896718968189691897018971189721897318974189751897618977189781897918980189811898218983189841898518986189871898818989189901899118992189931899418995189961899718998189991900019001190021900319004190051900619007190081900919010190111901219013190141901519016190171901819019190201902119022190231902419025190261902719028190291903019031190321903319034190351903619037190381903919040190411904219043190441904519046190471904819049190501905119052190531905419055190561905719058190591906019061190621906319064190651906619067190681906919070190711907219073190741907519076190771907819079190801908119082190831908419085190861908719088190891909019091190921909319094190951909619097190981909919100191011910219103191041910519106191071910819109191101911119112191131911419115191161911719118191191912019121191221912319124191251912619127191281912919130191311913219133191341913519136191371913819139191401914119142191431914419145191461914719148191491915019151191521915319154191551915619157191581915919160191611916219163191641916519166191671916819169191701917119172191731917419175191761917719178191791918019181191821918319184191851918619187191881918919190191911919219193191941919519196191971919819199192001920119202192031920419205192061920719208192091921019211192121921319214192151921619217192181921919220192211922219223192241922519226192271922819229192301923119232192331923419235192361923719238192391924019241192421924319244192451924619247192481924919250192511925219253192541925519256192571925819259192601926119262192631926419265192661926719268192691927019271192721927319274192751927619277192781927919280192811928219283192841928519286192871928819289192901929119292192931929419295192961929719298192991930019301193021930319304193051930619307193081930919310193111931219313193141931519316193171931819319193201932119322193231932419325193261932719328193291933019331193321933319334193351933619337193381933919340193411934219343193441934519346193471934819349193501935119352193531935419355193561935719358193591936019361193621936319364193651936619367193681936919370193711937219373193741937519376193771937819379193801938119382193831938419385193861938719388193891939019391193921939319394193951939619397193981939919400194011940219403194041940519406194071940819409194101941119412194131941419415194161941719418194191942019421194221942319424194251942619427194281942919430194311943219433194341943519436194371943819439194401944119442194431944419445194461944719448194491945019451194521945319454194551945619457194581945919460194611946219463194641946519466194671946819469194701947119472194731947419475194761947719478194791948019481194821948319484194851948619487194881948919490194911949219493194941949519496194971949819499195001950119502195031950419505195061950719508195091951019511195121951319514195151951619517195181951919520195211952219523195241952519526195271952819529195301953119532195331953419535195361953719538195391954019541195421954319544195451954619547195481954919550195511955219553195541955519556195571955819559195601956119562195631956419565195661956719568195691957019571195721957319574195751957619577195781957919580195811958219583195841958519586195871958819589195901959119592195931959419595195961959719598195991960019601196021960319604196051960619607196081960919610196111961219613196141961519616196171961819619196201962119622196231962419625196261962719628196291963019631196321963319634196351963619637196381963919640196411964219643196441964519646196471964819649196501965119652196531965419655196561965719658196591966019661196621966319664196651966619667196681966919670196711967219673196741967519676196771967819679196801968119682196831968419685196861968719688196891969019691196921969319694196951969619697196981969919700197011970219703197041970519706197071970819709197101971119712197131971419715197161971719718197191972019721197221972319724197251972619727197281972919730197311973219733197341973519736197371973819739197401974119742197431974419745197461974719748197491975019751197521975319754197551975619757197581975919760197611976219763197641976519766197671976819769197701977119772197731977419775197761977719778197791978019781197821978319784197851978619787197881978919790197911979219793197941979519796197971979819799198001980119802198031980419805198061980719808198091981019811198121981319814198151981619817198181981919820198211982219823198241982519826198271982819829198301983119832198331983419835198361983719838198391984019841198421984319844198451984619847198481984919850198511985219853198541985519856198571985819859198601986119862198631986419865198661986719868198691987019871198721987319874198751987619877198781987919880198811988219883198841988519886198871988819889198901989119892198931989419895198961989719898198991990019901199021990319904199051990619907199081990919910199111991219913199141991519916199171991819919199201992119922199231992419925199261992719928199291993019931199321993319934199351993619937199381993919940199411994219943199441994519946199471994819949199501995119952199531995419955199561995719958199591996019961199621996319964199651996619967199681996919970199711997219973199741997519976199771997819979199801998119982199831998419985199861998719988199891999019991199921999319994199951999619997199981999920000200012000220003200042000520006200072000820009200102001120012200132001420015200162001720018200192002020021200222002320024200252002620027200282002920030200312003220033200342003520036200372003820039200402004120042200432004420045200462004720048200492005020051200522005320054200552005620057200582005920060200612006220063200642006520066200672006820069200702007120072200732007420075200762007720078200792008020081200822008320084200852008620087200882008920090200912009220093200942009520096200972009820099201002010120102201032010420105201062010720108201092011020111201122011320114201152011620117201182011920120201212012220123201242012520126201272012820129201302013120132201332013420135201362013720138201392014020141201422014320144201452014620147201482014920150201512015220153201542015520156201572015820159201602016120162201632016420165201662016720168201692017020171201722017320174201752017620177201782017920180201812018220183201842018520186201872018820189201902019120192201932019420195201962019720198201992020020201202022020320204202052020620207202082020920210202112021220213202142021520216202172021820219202202022120222202232022420225202262022720228202292023020231202322023320234202352023620237202382023920240202412024220243202442024520246202472024820249202502025120252202532025420255202562025720258202592026020261202622026320264202652026620267202682026920270202712027220273202742027520276202772027820279202802028120282202832028420285202862028720288202892029020291202922029320294202952029620297202982029920300203012030220303203042030520306203072030820309203102031120312203132031420315203162031720318203192032020321203222032320324203252032620327203282032920330203312033220333203342033520336203372033820339203402034120342203432034420345203462034720348203492035020351203522035320354203552035620357203582035920360203612036220363203642036520366203672036820369203702037120372203732037420375203762037720378203792038020381203822038320384203852038620387203882038920390203912039220393203942039520396203972039820399204002040120402204032040420405204062040720408204092041020411204122041320414204152041620417204182041920420204212042220423204242042520426204272042820429204302043120432204332043420435204362043720438204392044020441204422044320444204452044620447204482044920450204512045220453204542045520456204572045820459204602046120462204632046420465204662046720468204692047020471204722047320474204752047620477204782047920480204812048220483204842048520486204872048820489204902049120492204932049420495204962049720498204992050020501205022050320504205052050620507205082050920510205112051220513205142051520516205172051820519205202052120522205232052420525205262052720528205292053020531205322053320534205352053620537205382053920540205412054220543205442054520546205472054820549205502055120552205532055420555205562055720558205592056020561205622056320564205652056620567205682056920570205712057220573205742057520576205772057820579205802058120582205832058420585205862058720588205892059020591205922059320594205952059620597205982059920600206012060220603206042060520606206072060820609206102061120612206132061420615206162061720618206192062020621206222062320624206252062620627206282062920630206312063220633206342063520636206372063820639206402064120642206432064420645206462064720648206492065020651206522065320654206552065620657206582065920660206612066220663206642066520666206672066820669206702067120672206732067420675206762067720678206792068020681206822068320684206852068620687206882068920690206912069220693206942069520696206972069820699207002070120702207032070420705207062070720708207092071020711207122071320714207152071620717207182071920720207212072220723207242072520726207272072820729207302073120732207332073420735207362073720738207392074020741207422074320744207452074620747207482074920750207512075220753207542075520756207572075820759207602076120762207632076420765207662076720768207692077020771207722077320774207752077620777207782077920780207812078220783207842078520786207872078820789207902079120792207932079420795207962079720798207992080020801208022080320804208052080620807208082080920810208112081220813208142081520816208172081820819208202082120822208232082420825208262082720828208292083020831208322083320834208352083620837208382083920840208412084220843208442084520846208472084820849208502085120852208532085420855208562085720858208592086020861208622086320864208652086620867208682086920870208712087220873208742087520876208772087820879208802088120882208832088420885208862088720888208892089020891208922089320894208952089620897208982089920900209012090220903209042090520906209072090820909209102091120912209132091420915209162091720918209192092020921209222092320924209252092620927209282092920930209312093220933209342093520936209372093820939209402094120942209432094420945209462094720948209492095020951209522095320954209552095620957209582095920960209612096220963209642096520966209672096820969209702097120972209732097420975209762097720978209792098020981209822098320984209852098620987209882098920990209912099220993209942099520996209972099820999210002100121002210032100421005210062100721008210092101021011210122101321014210152101621017210182101921020210212102221023210242102521026210272102821029210302103121032210332103421035210362103721038210392104021041210422104321044210452104621047210482104921050210512105221053210542105521056210572105821059210602106121062210632106421065210662106721068210692107021071210722107321074210752107621077210782107921080210812108221083210842108521086210872108821089210902109121092210932109421095210962109721098210992110021101211022110321104211052110621107211082110921110211112111221113211142111521116211172111821119211202112121122211232112421125211262112721128211292113021131211322113321134211352113621137211382113921140211412114221143211442114521146211472114821149211502115121152211532115421155211562115721158211592116021161211622116321164211652116621167211682116921170211712117221173211742117521176211772117821179211802118121182211832118421185211862118721188211892119021191211922119321194211952119621197211982119921200212012120221203212042120521206212072120821209212102121121212212132121421215212162121721218212192122021221212222122321224212252122621227212282122921230212312123221233212342123521236212372123821239212402124121242212432124421245212462124721248212492125021251212522125321254212552125621257212582125921260212612126221263212642126521266212672126821269212702127121272212732127421275212762127721278212792128021281212822128321284212852128621287212882128921290212912129221293212942129521296212972129821299213002130121302213032130421305213062130721308213092131021311213122131321314213152131621317213182131921320213212132221323213242132521326213272132821329213302133121332213332133421335213362133721338213392134021341213422134321344213452134621347213482134921350213512135221353213542135521356213572135821359213602136121362213632136421365213662136721368213692137021371213722137321374213752137621377213782137921380213812138221383213842138521386213872138821389213902139121392213932139421395213962139721398213992140021401214022140321404214052140621407214082140921410214112141221413214142141521416214172141821419214202142121422214232142421425214262142721428214292143021431214322143321434214352143621437214382143921440214412144221443214442144521446214472144821449214502145121452214532145421455214562145721458214592146021461214622146321464214652146621467214682146921470214712147221473214742147521476214772147821479214802148121482214832148421485214862148721488214892149021491214922149321494214952149621497214982149921500215012150221503215042150521506215072150821509215102151121512215132151421515215162151721518215192152021521215222152321524215252152621527215282152921530215312153221533215342153521536215372153821539215402154121542215432154421545215462154721548215492155021551215522155321554215552155621557215582155921560215612156221563215642156521566215672156821569215702157121572215732157421575215762157721578215792158021581215822158321584215852158621587215882158921590215912159221593215942159521596215972159821599216002160121602216032160421605216062160721608216092161021611216122161321614216152161621617216182161921620216212162221623216242162521626216272162821629216302163121632216332163421635216362163721638216392164021641216422164321644216452164621647216482164921650216512165221653216542165521656216572165821659216602166121662216632166421665216662166721668216692167021671216722167321674216752167621677216782167921680216812168221683216842168521686216872168821689216902169121692216932169421695216962169721698216992170021701217022170321704217052170621707217082170921710217112171221713217142171521716217172171821719217202172121722217232172421725217262172721728217292173021731217322173321734217352173621737217382173921740217412174221743217442174521746217472174821749217502175121752217532175421755217562175721758217592176021761217622176321764217652176621767217682176921770217712177221773217742177521776217772177821779217802178121782217832178421785217862178721788217892179021791217922179321794217952179621797217982179921800218012180221803218042180521806218072180821809218102181121812218132181421815218162181721818218192182021821218222182321824218252182621827218282182921830218312183221833218342183521836218372183821839218402184121842218432184421845218462184721848218492185021851218522185321854218552185621857218582185921860218612186221863218642186521866218672186821869218702187121872218732187421875218762187721878218792188021881218822188321884218852188621887218882188921890218912189221893218942189521896218972189821899219002190121902219032190421905219062190721908219092191021911219122191321914219152191621917219182191921920219212192221923219242192521926219272192821929219302193121932219332193421935219362193721938219392194021941219422194321944219452194621947219482194921950219512195221953219542195521956219572195821959219602196121962219632196421965219662196721968219692197021971219722197321974219752197621977219782197921980219812198221983219842198521986219872198821989219902199121992219932199421995219962199721998219992200022001220022200322004220052200622007220082200922010220112201222013220142201522016220172201822019220202202122022220232202422025220262202722028220292203022031220322203322034220352203622037220382203922040220412204222043220442204522046220472204822049220502205122052220532205422055220562205722058220592206022061220622206322064220652206622067220682206922070220712207222073220742207522076220772207822079220802208122082220832208422085220862208722088220892209022091220922209322094220952209622097220982209922100221012210222103221042210522106221072210822109221102211122112221132211422115221162211722118221192212022121221222212322124221252212622127221282212922130221312213222133221342213522136221372213822139221402214122142221432214422145221462214722148221492215022151221522215322154221552215622157221582215922160221612216222163221642216522166221672216822169221702217122172221732217422175221762217722178221792218022181221822218322184221852218622187221882218922190221912219222193221942219522196221972219822199222002220122202222032220422205222062220722208222092221022211222122221322214222152221622217222182221922220222212222222223222242222522226222272222822229222302223122232222332223422235222362223722238222392224022241222422224322244222452224622247222482224922250222512225222253222542225522256222572225822259222602226122262222632226422265222662226722268222692227022271222722227322274222752227622277222782227922280222812228222283222842228522286222872228822289222902229122292222932229422295222962229722298222992230022301223022230322304223052230622307223082230922310223112231222313223142231522316223172231822319223202232122322223232232422325223262232722328223292233022331223322233322334223352233622337223382233922340223412234222343223442234522346223472234822349223502235122352223532235422355223562235722358223592236022361223622236322364223652236622367223682236922370223712237222373223742237522376223772237822379223802238122382223832238422385223862238722388223892239022391223922239322394223952239622397223982239922400224012240222403224042240522406224072240822409224102241122412224132241422415224162241722418224192242022421224222242322424224252242622427224282242922430224312243222433224342243522436224372243822439224402244122442224432244422445224462244722448224492245022451224522245322454224552245622457224582245922460224612246222463224642246522466224672246822469224702247122472224732247422475224762247722478224792248022481224822248322484224852248622487224882248922490224912249222493224942249522496224972249822499225002250122502225032250422505225062250722508225092251022511225122251322514225152251622517225182251922520225212252222523225242252522526225272252822529225302253122532225332253422535225362253722538225392254022541225422254322544225452254622547225482254922550225512255222553225542255522556225572255822559225602256122562225632256422565225662256722568225692257022571225722257322574225752257622577225782257922580225812258222583225842258522586225872258822589225902259122592225932259422595225962259722598225992260022601226022260322604226052260622607226082260922610226112261222613226142261522616226172261822619226202262122622226232262422625226262262722628226292263022631226322263322634226352263622637226382263922640226412264222643226442264522646226472264822649226502265122652226532265422655226562265722658226592266022661226622266322664226652266622667226682266922670226712267222673226742267522676226772267822679226802268122682226832268422685226862268722688226892269022691226922269322694226952269622697226982269922700227012270222703227042270522706227072270822709227102271122712227132271422715227162271722718227192272022721227222272322724227252272622727227282272922730227312273222733227342273522736227372273822739227402274122742227432274422745227462274722748227492275022751227522275322754227552275622757227582275922760227612276222763227642276522766227672276822769227702277122772227732277422775227762277722778227792278022781227822278322784227852278622787227882278922790227912279222793227942279522796227972279822799228002280122802228032280422805228062280722808228092281022811228122281322814228152281622817228182281922820228212282222823228242282522826228272282822829228302283122832228332283422835228362283722838228392284022841228422284322844228452284622847228482284922850228512285222853228542285522856228572285822859228602286122862228632286422865228662286722868228692287022871228722287322874228752287622877228782287922880228812288222883228842288522886228872288822889228902289122892228932289422895228962289722898228992290022901229022290322904229052290622907229082290922910229112291222913229142291522916229172291822919229202292122922229232292422925229262292722928229292293022931229322293322934229352293622937229382293922940229412294222943229442294522946229472294822949229502295122952229532295422955229562295722958229592296022961229622296322964229652296622967229682296922970229712297222973229742297522976229772297822979229802298122982229832298422985229862298722988229892299022991229922299322994229952299622997229982299923000230012300223003230042300523006230072300823009230102301123012230132301423015230162301723018230192302023021230222302323024230252302623027230282302923030230312303223033230342303523036230372303823039230402304123042230432304423045230462304723048230492305023051230522305323054230552305623057230582305923060230612306223063230642306523066230672306823069230702307123072230732307423075230762307723078230792308023081230822308323084230852308623087230882308923090230912309223093230942309523096230972309823099231002310123102231032310423105231062310723108231092311023111231122311323114231152311623117231182311923120231212312223123231242312523126231272312823129231302313123132231332313423135231362313723138231392314023141231422314323144231452314623147231482314923150231512315223153231542315523156231572315823159231602316123162231632316423165231662316723168231692317023171231722317323174231752317623177231782317923180231812318223183231842318523186231872318823189231902319123192231932319423195231962319723198231992320023201232022320323204232052320623207232082320923210232112321223213232142321523216232172321823219232202322123222232232322423225232262322723228232292323023231232322323323234232352323623237232382323923240232412324223243232442324523246232472324823249232502325123252232532325423255232562325723258232592326023261232622326323264232652326623267232682326923270232712327223273232742327523276232772327823279232802328123282232832328423285232862328723288232892329023291232922329323294232952329623297232982329923300233012330223303233042330523306233072330823309233102331123312233132331423315233162331723318233192332023321233222332323324233252332623327233282332923330233312333223333233342333523336233372333823339233402334123342233432334423345233462334723348233492335023351233522335323354233552335623357233582335923360233612336223363233642336523366233672336823369233702337123372233732337423375233762337723378233792338023381233822338323384233852338623387233882338923390233912339223393233942339523396233972339823399234002340123402234032340423405234062340723408234092341023411234122341323414234152341623417234182341923420234212342223423234242342523426234272342823429234302343123432234332343423435234362343723438234392344023441234422344323444234452344623447234482344923450234512345223453234542345523456234572345823459234602346123462234632346423465234662346723468234692347023471234722347323474234752347623477234782347923480234812348223483234842348523486234872348823489234902349123492234932349423495234962349723498234992350023501235022350323504235052350623507235082350923510235112351223513235142351523516235172351823519235202352123522235232352423525235262352723528235292353023531235322353323534235352353623537235382353923540235412354223543235442354523546235472354823549235502355123552235532355423555235562355723558235592356023561235622356323564235652356623567235682356923570235712357223573235742357523576235772357823579235802358123582235832358423585235862358723588235892359023591235922359323594235952359623597235982359923600236012360223603236042360523606236072360823609236102361123612236132361423615236162361723618236192362023621236222362323624236252362623627236282362923630236312363223633236342363523636236372363823639236402364123642236432364423645236462364723648236492365023651236522365323654236552365623657236582365923660236612366223663236642366523666236672366823669236702367123672236732367423675236762367723678236792368023681236822368323684236852368623687236882368923690236912369223693236942369523696236972369823699237002370123702237032370423705237062370723708237092371023711237122371323714237152371623717237182371923720237212372223723237242372523726237272372823729237302373123732237332373423735237362373723738237392374023741237422374323744237452374623747237482374923750237512375223753237542375523756237572375823759237602376123762237632376423765237662376723768237692377023771237722377323774237752377623777237782377923780237812378223783237842378523786237872378823789237902379123792237932379423795237962379723798237992380023801238022380323804238052380623807238082380923810238112381223813238142381523816238172381823819238202382123822238232382423825238262382723828238292383023831238322383323834238352383623837238382383923840238412384223843238442384523846238472384823849238502385123852238532385423855238562385723858238592386023861238622386323864238652386623867238682386923870238712387223873238742387523876238772387823879238802388123882238832388423885238862388723888238892389023891238922389323894238952389623897238982389923900239012390223903239042390523906239072390823909239102391123912239132391423915239162391723918239192392023921239222392323924239252392623927239282392923930239312393223933239342393523936239372393823939239402394123942239432394423945239462394723948239492395023951239522395323954239552395623957239582395923960239612396223963239642396523966239672396823969239702397123972239732397423975239762397723978239792398023981239822398323984239852398623987239882398923990239912399223993239942399523996239972399823999240002400124002240032400424005240062400724008240092401024011240122401324014240152401624017240182401924020240212402224023240242402524026240272402824029240302403124032240332403424035240362403724038240392404024041240422404324044240452404624047240482404924050240512405224053240542405524056240572405824059240602406124062240632406424065240662406724068240692407024071240722407324074240752407624077240782407924080240812408224083240842408524086240872408824089240902409124092240932409424095240962409724098240992410024101241022410324104241052410624107241082410924110241112411224113241142411524116241172411824119241202412124122241232412424125241262412724128241292413024131241322413324134241352413624137241382413924140241412414224143241442414524146241472414824149241502415124152241532415424155241562415724158241592416024161241622416324164241652416624167241682416924170241712417224173241742417524176241772417824179241802418124182241832418424185241862418724188241892419024191241922419324194241952419624197241982419924200242012420224203242042420524206242072420824209242102421124212242132421424215242162421724218242192422024221242222422324224242252422624227242282422924230242312423224233242342423524236242372423824239242402424124242242432424424245242462424724248242492425024251242522425324254242552425624257242582425924260242612426224263242642426524266242672426824269242702427124272242732427424275242762427724278242792428024281242822428324284242852428624287242882428924290242912429224293242942429524296242972429824299243002430124302243032430424305243062430724308243092431024311243122431324314243152431624317243182431924320243212432224323243242432524326243272432824329243302433124332243332433424335243362433724338243392434024341243422434324344243452434624347243482434924350243512435224353243542435524356243572435824359243602436124362243632436424365243662436724368243692437024371243722437324374243752437624377243782437924380243812438224383243842438524386243872438824389243902439124392243932439424395243962439724398243992440024401244022440324404244052440624407244082440924410244112441224413244142441524416244172441824419244202442124422244232442424425244262442724428244292443024431244322443324434244352443624437244382443924440244412444224443244442444524446244472444824449244502445124452244532445424455244562445724458244592446024461244622446324464244652446624467244682446924470244712447224473244742447524476244772447824479244802448124482244832448424485244862448724488244892449024491244922449324494244952449624497244982449924500245012450224503245042450524506245072450824509245102451124512245132451424515245162451724518245192452024521245222452324524245252452624527245282452924530245312453224533245342453524536245372453824539245402454124542245432454424545245462454724548245492455024551245522455324554245552455624557245582455924560245612456224563245642456524566245672456824569245702457124572245732457424575245762457724578245792458024581245822458324584245852458624587245882458924590245912459224593245942459524596245972459824599246002460124602246032460424605246062460724608246092461024611246122461324614246152461624617246182461924620246212462224623246242462524626246272462824629246302463124632246332463424635246362463724638246392464024641246422464324644246452464624647246482464924650246512465224653246542465524656246572465824659246602466124662246632466424665246662466724668246692467024671246722467324674246752467624677246782467924680246812468224683246842468524686246872468824689246902469124692246932469424695246962469724698246992470024701247022470324704247052470624707247082470924710247112471224713247142471524716247172471824719247202472124722247232472424725247262472724728247292473024731247322473324734247352473624737247382473924740247412474224743247442474524746247472474824749247502475124752247532475424755247562475724758247592476024761247622476324764247652476624767247682476924770247712477224773247742477524776247772477824779247802478124782247832478424785247862478724788247892479024791247922479324794247952479624797247982479924800248012480224803248042480524806248072480824809248102481124812248132481424815248162481724818248192482024821248222482324824248252482624827248282482924830248312483224833248342483524836248372483824839248402484124842248432484424845248462484724848248492485024851248522485324854248552485624857248582485924860248612486224863248642486524866248672486824869248702487124872248732487424875248762487724878248792488024881248822488324884248852488624887248882488924890248912489224893248942489524896248972489824899249002490124902249032490424905249062490724908249092491024911249122491324914249152491624917249182491924920249212492224923249242492524926249272492824929249302493124932249332493424935249362493724938249392494024941249422494324944249452494624947249482494924950249512495224953249542495524956249572495824959249602496124962249632496424965249662496724968249692497024971249722497324974249752497624977249782497924980249812498224983249842498524986249872498824989249902499124992249932499424995249962499724998249992500025001250022500325004250052500625007250082500925010250112501225013250142501525016250172501825019250202502125022250232502425025250262502725028250292503025031250322503325034250352503625037250382503925040250412504225043250442504525046250472504825049250502505125052250532505425055250562505725058250592506025061250622506325064250652506625067250682506925070250712507225073250742507525076250772507825079250802508125082250832508425085250862508725088250892509025091250922509325094250952509625097250982509925100251012510225103251042510525106251072510825109251102511125112251132511425115251162511725118251192512025121251222512325124251252512625127251282512925130251312513225133251342513525136251372513825139251402514125142251432514425145251462514725148251492515025151251522515325154251552515625157251582515925160251612516225163251642516525166251672516825169251702517125172251732517425175251762517725178251792518025181251822518325184251852518625187251882518925190251912519225193251942519525196251972519825199252002520125202252032520425205252062520725208252092521025211252122521325214252152521625217252182521925220252212522225223252242522525226252272522825229252302523125232252332523425235252362523725238252392524025241252422524325244252452524625247252482524925250252512525225253252542525525256252572525825259252602526125262252632526425265252662526725268252692527025271252722527325274252752527625277252782527925280252812528225283252842528525286252872528825289252902529125292252932529425295252962529725298252992530025301253022530325304253052530625307253082530925310253112531225313253142531525316253172531825319253202532125322253232532425325253262532725328253292533025331253322533325334253352533625337253382533925340253412534225343253442534525346253472534825349253502535125352253532535425355253562535725358253592536025361253622536325364253652536625367253682536925370253712537225373253742537525376253772537825379253802538125382253832538425385253862538725388253892539025391253922539325394253952539625397253982539925400254012540225403254042540525406254072540825409254102541125412254132541425415254162541725418254192542025421254222542325424254252542625427254282542925430254312543225433254342543525436254372543825439254402544125442254432544425445254462544725448254492545025451254522545325454254552545625457254582545925460254612546225463254642546525466254672546825469254702547125472254732547425475254762547725478254792548025481254822548325484254852548625487254882548925490254912549225493254942549525496254972549825499255002550125502255032550425505255062550725508255092551025511255122551325514255152551625517255182551925520255212552225523255242552525526255272552825529255302553125532255332553425535255362553725538255392554025541255422554325544255452554625547255482554925550255512555225553255542555525556255572555825559255602556125562255632556425565255662556725568255692557025571255722557325574255752557625577255782557925580255812558225583255842558525586255872558825589255902559125592255932559425595255962559725598255992560025601256022560325604256052560625607256082560925610256112561225613256142561525616256172561825619256202562125622256232562425625256262562725628256292563025631256322563325634256352563625637256382563925640256412564225643256442564525646256472564825649256502565125652256532565425655256562565725658256592566025661256622566325664256652566625667256682566925670256712567225673256742567525676256772567825679256802568125682256832568425685256862568725688256892569025691256922569325694256952569625697256982569925700257012570225703257042570525706257072570825709257102571125712257132571425715257162571725718257192572025721257222572325724257252572625727257282572925730257312573225733257342573525736257372573825739257402574125742257432574425745257462574725748257492575025751257522575325754257552575625757257582575925760257612576225763257642576525766257672576825769257702577125772257732577425775257762577725778257792578025781257822578325784257852578625787257882578925790257912579225793257942579525796257972579825799258002580125802258032580425805258062580725808258092581025811258122581325814258152581625817258182581925820258212582225823258242582525826258272582825829258302583125832258332583425835258362583725838258392584025841258422584325844258452584625847258482584925850258512585225853258542585525856258572585825859258602586125862258632586425865258662586725868258692587025871258722587325874258752587625877258782587925880258812588225883258842588525886258872588825889258902589125892258932589425895258962589725898258992590025901259022590325904259052590625907259082590925910259112591225913259142591525916259172591825919259202592125922259232592425925259262592725928259292593025931259322593325934259352593625937259382593925940259412594225943259442594525946259472594825949259502595125952259532595425955259562595725958259592596025961259622596325964259652596625967259682596925970259712597225973259742597525976259772597825979259802598125982259832598425985259862598725988259892599025991259922599325994259952599625997259982599926000260012600226003260042600526006260072600826009260102601126012260132601426015260162601726018260192602026021260222602326024260252602626027260282602926030260312603226033260342603526036260372603826039260402604126042260432604426045260462604726048260492605026051260522605326054260552605626057260582605926060260612606226063260642606526066260672606826069260702607126072260732607426075260762607726078260792608026081260822608326084260852608626087260882608926090260912609226093260942609526096260972609826099261002610126102261032610426105261062610726108261092611026111261122611326114261152611626117261182611926120261212612226123261242612526126261272612826129261302613126132261332613426135261362613726138261392614026141261422614326144261452614626147261482614926150261512615226153261542615526156261572615826159261602616126162261632616426165261662616726168261692617026171261722617326174261752617626177261782617926180261812618226183261842618526186261872618826189261902619126192261932619426195261962619726198261992620026201262022620326204262052620626207262082620926210262112621226213262142621526216262172621826219262202622126222262232622426225262262622726228262292623026231262322623326234262352623626237262382623926240262412624226243262442624526246262472624826249262502625126252262532625426255262562625726258262592626026261262622626326264262652626626267262682626926270262712627226273262742627526276262772627826279262802628126282262832628426285262862628726288262892629026291262922629326294262952629626297262982629926300263012630226303263042630526306263072630826309263102631126312263132631426315263162631726318263192632026321263222632326324263252632626327263282632926330263312633226333263342633526336263372633826339263402634126342263432634426345263462634726348263492635026351263522635326354263552635626357263582635926360263612636226363263642636526366263672636826369263702637126372263732637426375263762637726378263792638026381263822638326384263852638626387263882638926390263912639226393263942639526396263972639826399264002640126402264032640426405264062640726408264092641026411264122641326414264152641626417264182641926420264212642226423264242642526426264272642826429264302643126432264332643426435264362643726438264392644026441264422644326444264452644626447264482644926450264512645226453264542645526456264572645826459264602646126462264632646426465264662646726468264692647026471264722647326474264752647626477264782647926480264812648226483264842648526486264872648826489264902649126492264932649426495264962649726498264992650026501265022650326504265052650626507265082650926510265112651226513265142651526516265172651826519265202652126522265232652426525265262652726528265292653026531265322653326534265352653626537265382653926540265412654226543265442654526546265472654826549265502655126552265532655426555265562655726558265592656026561265622656326564265652656626567265682656926570265712657226573265742657526576265772657826579265802658126582265832658426585265862658726588265892659026591265922659326594265952659626597265982659926600266012660226603266042660526606266072660826609266102661126612266132661426615266162661726618266192662026621266222662326624266252662626627266282662926630266312663226633266342663526636266372663826639266402664126642266432664426645266462664726648266492665026651266522665326654266552665626657266582665926660266612666226663266642666526666266672666826669266702667126672266732667426675266762667726678266792668026681266822668326684266852668626687266882668926690266912669226693266942669526696266972669826699267002670126702267032670426705267062670726708267092671026711267122671326714267152671626717267182671926720267212672226723267242672526726267272672826729267302673126732267332673426735267362673726738267392674026741267422674326744267452674626747267482674926750267512675226753267542675526756267572675826759267602676126762267632676426765267662676726768267692677026771267722677326774267752677626777267782677926780267812678226783267842678526786267872678826789267902679126792267932679426795267962679726798267992680026801268022680326804268052680626807268082680926810268112681226813268142681526816268172681826819268202682126822268232682426825268262682726828268292683026831268322683326834268352683626837268382683926840268412684226843268442684526846268472684826849268502685126852268532685426855268562685726858268592686026861268622686326864268652686626867268682686926870268712687226873268742687526876268772687826879268802688126882268832688426885268862688726888268892689026891268922689326894268952689626897268982689926900269012690226903269042690526906269072690826909269102691126912269132691426915269162691726918269192692026921269222692326924269252692626927269282692926930269312693226933269342693526936269372693826939269402694126942269432694426945269462694726948269492695026951269522695326954269552695626957269582695926960269612696226963269642696526966269672696826969269702697126972269732697426975269762697726978269792698026981269822698326984269852698626987269882698926990269912699226993269942699526996269972699826999270002700127002270032700427005270062700727008270092701027011270122701327014270152701627017270182701927020270212702227023270242702527026270272702827029270302703127032270332703427035270362703727038270392704027041270422704327044270452704627047270482704927050270512705227053270542705527056270572705827059270602706127062270632706427065270662706727068270692707027071270722707327074270752707627077270782707927080270812708227083270842708527086270872708827089270902709127092270932709427095270962709727098270992710027101271022710327104271052710627107271082710927110271112711227113271142711527116271172711827119271202712127122271232712427125271262712727128271292713027131271322713327134271352713627137271382713927140271412714227143271442714527146271472714827149271502715127152271532715427155271562715727158271592716027161271622716327164271652716627167271682716927170271712717227173271742717527176271772717827179271802718127182271832718427185271862718727188271892719027191271922719327194271952719627197271982719927200272012720227203272042720527206272072720827209272102721127212272132721427215272162721727218272192722027221272222722327224272252722627227272282722927230272312723227233272342723527236272372723827239272402724127242272432724427245272462724727248272492725027251272522725327254272552725627257272582725927260272612726227263272642726527266272672726827269272702727127272272732727427275272762727727278272792728027281272822728327284272852728627287272882728927290272912729227293272942729527296272972729827299273002730127302273032730427305273062730727308273092731027311273122731327314273152731627317273182731927320273212732227323273242732527326273272732827329273302733127332273332733427335273362733727338273392734027341273422734327344273452734627347273482734927350273512735227353273542735527356273572735827359273602736127362273632736427365273662736727368273692737027371273722737327374273752737627377273782737927380273812738227383273842738527386273872738827389273902739127392273932739427395273962739727398273992740027401274022740327404274052740627407274082740927410274112741227413274142741527416274172741827419274202742127422274232742427425274262742727428274292743027431274322743327434274352743627437274382743927440274412744227443274442744527446274472744827449274502745127452274532745427455274562745727458274592746027461274622746327464274652746627467274682746927470274712747227473274742747527476274772747827479274802748127482274832748427485274862748727488274892749027491274922749327494274952749627497274982749927500275012750227503275042750527506275072750827509275102751127512275132751427515275162751727518275192752027521275222752327524275252752627527275282752927530275312753227533275342753527536275372753827539275402754127542275432754427545275462754727548275492755027551275522755327554275552755627557275582755927560275612756227563275642756527566275672756827569275702757127572275732757427575275762757727578275792758027581275822758327584275852758627587275882758927590275912759227593275942759527596275972759827599276002760127602276032760427605276062760727608276092761027611276122761327614276152761627617276182761927620276212762227623276242762527626276272762827629276302763127632276332763427635276362763727638276392764027641276422764327644276452764627647276482764927650276512765227653276542765527656276572765827659276602766127662276632766427665276662766727668276692767027671276722767327674276752767627677276782767927680276812768227683276842768527686276872768827689276902769127692276932769427695276962769727698276992770027701277022770327704277052770627707277082770927710277112771227713277142771527716277172771827719277202772127722277232772427725277262772727728277292773027731277322773327734277352773627737277382773927740277412774227743277442774527746277472774827749277502775127752277532775427755277562775727758277592776027761277622776327764277652776627767277682776927770277712777227773277742777527776277772777827779277802778127782277832778427785277862778727788277892779027791277922779327794277952779627797277982779927800278012780227803278042780527806278072780827809278102781127812278132781427815278162781727818278192782027821278222782327824278252782627827278282782927830278312783227833278342783527836278372783827839278402784127842278432784427845278462784727848278492785027851278522785327854278552785627857278582785927860278612786227863278642786527866278672786827869278702787127872278732787427875278762787727878278792788027881278822788327884278852788627887278882788927890278912789227893278942789527896278972789827899279002790127902279032790427905279062790727908279092791027911279122791327914279152791627917279182791927920279212792227923279242792527926279272792827929279302793127932279332793427935279362793727938279392794027941279422794327944279452794627947279482794927950279512795227953279542795527956279572795827959279602796127962279632796427965279662796727968279692797027971279722797327974279752797627977279782797927980279812798227983279842798527986279872798827989279902799127992279932799427995279962799727998279992800028001280022800328004280052800628007280082800928010280112801228013280142801528016280172801828019280202802128022280232802428025280262802728028280292803028031280322803328034280352803628037280382803928040280412804228043280442804528046280472804828049280502805128052280532805428055280562805728058280592806028061280622806328064280652806628067280682806928070280712807228073280742807528076280772807828079280802808128082280832808428085280862808728088280892809028091280922809328094280952809628097280982809928100281012810228103281042810528106281072810828109281102811128112281132811428115281162811728118281192812028121281222812328124281252812628127281282812928130281312813228133281342813528136281372813828139281402814128142281432814428145281462814728148281492815028151281522815328154281552815628157281582815928160281612816228163281642816528166281672816828169281702817128172281732817428175281762817728178281792818028181281822818328184281852818628187281882818928190281912819228193281942819528196281972819828199282002820128202282032820428205282062820728208282092821028211282122821328214282152821628217282182821928220282212822228223282242822528226282272822828229282302823128232282332823428235282362823728238282392824028241282422824328244282452824628247282482824928250282512825228253282542825528256282572825828259282602826128262282632826428265282662826728268282692827028271282722827328274282752827628277282782827928280282812828228283282842828528286282872828828289282902829128292282932829428295282962829728298282992830028301283022830328304283052830628307283082830928310283112831228313283142831528316283172831828319283202832128322283232832428325283262832728328283292833028331283322833328334
  1. /*!
  2. * Vuetify v3.7.6
  3. * Forged by John Leider
  4. * Released under the MIT License.
  5. */
  6. (function (global, factory) {
  7. typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports, require('vue')) :
  8. typeof define === 'function' && define.amd ? define(['exports', 'vue'], factory) :
  9. (global = typeof globalThis !== 'undefined' ? globalThis : global || self, factory(global.Vuetify = {}, global.Vue));
  10. })(this, (function (exports, vue) { 'use strict';
  11. const IN_BROWSER = typeof window !== 'undefined';
  12. const SUPPORTS_INTERSECTION = IN_BROWSER && 'IntersectionObserver' in window;
  13. const SUPPORTS_TOUCH = IN_BROWSER && ('ontouchstart' in window || window.navigator.maxTouchPoints > 0);
  14. const SUPPORTS_EYE_DROPPER = IN_BROWSER && 'EyeDropper' in window;
  15. function _classPrivateFieldInitSpec(e, t, a) { _checkPrivateRedeclaration(e, t), t.set(e, a); }
  16. function _checkPrivateRedeclaration(e, t) { if (t.has(e)) throw new TypeError("Cannot initialize the same private elements twice on an object"); }
  17. function _classPrivateFieldSet(s, a, r) { return s.set(_assertClassBrand(s, a), r), r; }
  18. function _classPrivateFieldGet(s, a) { return s.get(_assertClassBrand(s, a)); }
  19. function _assertClassBrand(e, t, n) { if ("function" == typeof e ? e === t : e.has(t)) return arguments.length < 3 ? t : n; throw new TypeError("Private element is not present on this object"); }
  20. // Types
  21. function getNestedValue(obj, path, fallback) {
  22. const last = path.length - 1;
  23. if (last < 0) return obj === undefined ? fallback : obj;
  24. for (let i = 0; i < last; i++) {
  25. if (obj == null) {
  26. return fallback;
  27. }
  28. obj = obj[path[i]];
  29. }
  30. if (obj == null) return fallback;
  31. return obj[path[last]] === undefined ? fallback : obj[path[last]];
  32. }
  33. function deepEqual(a, b) {
  34. if (a === b) return true;
  35. if (a instanceof Date && b instanceof Date && a.getTime() !== b.getTime()) {
  36. // If the values are Date, compare them as timestamps
  37. return false;
  38. }
  39. if (a !== Object(a) || b !== Object(b)) {
  40. // If the values aren't objects, they were already checked for equality
  41. return false;
  42. }
  43. const props = Object.keys(a);
  44. if (props.length !== Object.keys(b).length) {
  45. // Different number of props, don't bother to check
  46. return false;
  47. }
  48. return props.every(p => deepEqual(a[p], b[p]));
  49. }
  50. function getObjectValueByPath(obj, path, fallback) {
  51. // credit: http://stackoverflow.com/questions/6491463/accessing-nested-javascript-objects-with-string-key#comment55278413_6491621
  52. if (obj == null || !path || typeof path !== 'string') return fallback;
  53. if (obj[path] !== undefined) return obj[path];
  54. path = path.replace(/\[(\w+)\]/g, '.$1'); // convert indexes to properties
  55. path = path.replace(/^\./, ''); // strip a leading dot
  56. return getNestedValue(obj, path.split('.'), fallback);
  57. }
  58. function getPropertyFromItem(item, property, fallback) {
  59. if (property === true) return item === undefined ? fallback : item;
  60. if (property == null || typeof property === 'boolean') return fallback;
  61. if (item !== Object(item)) {
  62. if (typeof property !== 'function') return fallback;
  63. const value = property(item, fallback);
  64. return typeof value === 'undefined' ? fallback : value;
  65. }
  66. if (typeof property === 'string') return getObjectValueByPath(item, property, fallback);
  67. if (Array.isArray(property)) return getNestedValue(item, property, fallback);
  68. if (typeof property !== 'function') return fallback;
  69. const value = property(item, fallback);
  70. return typeof value === 'undefined' ? fallback : value;
  71. }
  72. function createRange(length) {
  73. let start = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 0;
  74. return Array.from({
  75. length
  76. }, (v, k) => start + k);
  77. }
  78. function convertToUnit(str) {
  79. let unit = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 'px';
  80. if (str == null || str === '') {
  81. return undefined;
  82. } else if (isNaN(+str)) {
  83. return String(str);
  84. } else if (!isFinite(+str)) {
  85. return undefined;
  86. } else {
  87. return `${Number(str)}${unit}`;
  88. }
  89. }
  90. function isObject(obj) {
  91. return obj !== null && typeof obj === 'object' && !Array.isArray(obj);
  92. }
  93. function isPlainObject(obj) {
  94. let proto;
  95. return obj !== null && typeof obj === 'object' && ((proto = Object.getPrototypeOf(obj)) === Object.prototype || proto === null);
  96. }
  97. function refElement(obj) {
  98. if (obj && '$el' in obj) {
  99. const el = obj.$el;
  100. if (el?.nodeType === Node.TEXT_NODE) {
  101. // Multi-root component, use the first element
  102. return el.nextElementSibling;
  103. }
  104. return el;
  105. }
  106. return obj;
  107. }
  108. // KeyboardEvent.keyCode aliases
  109. const keyCodes = Object.freeze({
  110. enter: 13,
  111. tab: 9,
  112. delete: 46,
  113. esc: 27,
  114. space: 32,
  115. up: 38,
  116. down: 40,
  117. left: 37,
  118. right: 39,
  119. end: 35,
  120. home: 36,
  121. del: 46,
  122. backspace: 8,
  123. insert: 45,
  124. pageup: 33,
  125. pagedown: 34,
  126. shift: 16
  127. });
  128. const keyValues = Object.freeze({
  129. enter: 'Enter',
  130. tab: 'Tab',
  131. delete: 'Delete',
  132. esc: 'Escape',
  133. space: 'Space',
  134. up: 'ArrowUp',
  135. down: 'ArrowDown',
  136. left: 'ArrowLeft',
  137. right: 'ArrowRight',
  138. end: 'End',
  139. home: 'Home',
  140. del: 'Delete',
  141. backspace: 'Backspace',
  142. insert: 'Insert',
  143. pageup: 'PageUp',
  144. pagedown: 'PageDown',
  145. shift: 'Shift'
  146. });
  147. function keys(o) {
  148. return Object.keys(o);
  149. }
  150. function has(obj, key) {
  151. return key.every(k => obj.hasOwnProperty(k));
  152. }
  153. // Array of keys
  154. function pick(obj, paths) {
  155. const found = {};
  156. const keys = new Set(Object.keys(obj));
  157. for (const path of paths) {
  158. if (keys.has(path)) {
  159. found[path] = obj[path];
  160. }
  161. }
  162. return found;
  163. }
  164. // Array of keys
  165. // Array of keys or RegExp to test keys against
  166. function pickWithRest(obj, paths, exclude) {
  167. const found = Object.create(null);
  168. const rest = Object.create(null);
  169. for (const key in obj) {
  170. if (paths.some(path => path instanceof RegExp ? path.test(key) : path === key) && !exclude?.some(path => path === key)) {
  171. found[key] = obj[key];
  172. } else {
  173. rest[key] = obj[key];
  174. }
  175. }
  176. return [found, rest];
  177. }
  178. function omit(obj, exclude) {
  179. const clone = {
  180. ...obj
  181. };
  182. exclude.forEach(prop => delete clone[prop]);
  183. return clone;
  184. }
  185. function only(obj, include) {
  186. const clone = {};
  187. include.forEach(prop => clone[prop] = obj[prop]);
  188. return clone;
  189. }
  190. const onRE = /^on[^a-z]/;
  191. const isOn = key => onRE.test(key);
  192. const bubblingEvents = ['onAfterscriptexecute', 'onAnimationcancel', 'onAnimationend', 'onAnimationiteration', 'onAnimationstart', 'onAuxclick', 'onBeforeinput', 'onBeforescriptexecute', 'onChange', 'onClick', 'onCompositionend', 'onCompositionstart', 'onCompositionupdate', 'onContextmenu', 'onCopy', 'onCut', 'onDblclick', 'onFocusin', 'onFocusout', 'onFullscreenchange', 'onFullscreenerror', 'onGesturechange', 'onGestureend', 'onGesturestart', 'onGotpointercapture', 'onInput', 'onKeydown', 'onKeypress', 'onKeyup', 'onLostpointercapture', 'onMousedown', 'onMousemove', 'onMouseout', 'onMouseover', 'onMouseup', 'onMousewheel', 'onPaste', 'onPointercancel', 'onPointerdown', 'onPointerenter', 'onPointerleave', 'onPointermove', 'onPointerout', 'onPointerover', 'onPointerup', 'onReset', 'onSelect', 'onSubmit', 'onTouchcancel', 'onTouchend', 'onTouchmove', 'onTouchstart', 'onTransitioncancel', 'onTransitionend', 'onTransitionrun', 'onTransitionstart', 'onWheel'];
  193. const compositionIgnoreKeys = ['ArrowUp', 'ArrowDown', 'ArrowRight', 'ArrowLeft', 'Enter', 'Escape', 'Tab', ' '];
  194. function isComposingIgnoreKey(e) {
  195. return e.isComposing && compositionIgnoreKeys.includes(e.key);
  196. }
  197. /**
  198. * Filter attributes that should be applied to
  199. * the root element of an input component. Remaining
  200. * attributes should be passed to the <input> element inside.
  201. */
  202. function filterInputAttrs(attrs) {
  203. const [events, props] = pickWithRest(attrs, [onRE]);
  204. const inputEvents = omit(events, bubblingEvents);
  205. const [rootAttrs, inputAttrs] = pickWithRest(props, ['class', 'style', 'id', /^data-/]);
  206. Object.assign(rootAttrs, events);
  207. Object.assign(inputAttrs, inputEvents);
  208. return [rootAttrs, inputAttrs];
  209. }
  210. function wrapInArray(v) {
  211. return v == null ? [] : Array.isArray(v) ? v : [v];
  212. }
  213. function debounce(fn, delay) {
  214. let timeoutId = 0;
  215. const wrap = function () {
  216. for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) {
  217. args[_key] = arguments[_key];
  218. }
  219. clearTimeout(timeoutId);
  220. timeoutId = setTimeout(() => fn(...args), vue.unref(delay));
  221. };
  222. wrap.clear = () => {
  223. clearTimeout(timeoutId);
  224. };
  225. wrap.immediate = fn;
  226. return wrap;
  227. }
  228. function clamp(value) {
  229. let min = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 0;
  230. let max = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : 1;
  231. return Math.max(min, Math.min(max, value));
  232. }
  233. function getDecimals(value) {
  234. const trimmedStr = value.toString().trim();
  235. return trimmedStr.includes('.') ? trimmedStr.length - trimmedStr.indexOf('.') - 1 : 0;
  236. }
  237. function padEnd(str, length) {
  238. let char = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : '0';
  239. return str + char.repeat(Math.max(0, length - str.length));
  240. }
  241. function padStart(str, length) {
  242. let char = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : '0';
  243. return char.repeat(Math.max(0, length - str.length)) + str;
  244. }
  245. function chunk(str) {
  246. let size = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 1;
  247. const chunked = [];
  248. let index = 0;
  249. while (index < str.length) {
  250. chunked.push(str.substr(index, size));
  251. index += size;
  252. }
  253. return chunked;
  254. }
  255. function humanReadableFileSize(bytes) {
  256. let base = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 1000;
  257. if (bytes < base) {
  258. return `${bytes} B`;
  259. }
  260. const prefix = base === 1024 ? ['Ki', 'Mi', 'Gi'] : ['k', 'M', 'G'];
  261. let unit = -1;
  262. while (Math.abs(bytes) >= base && unit < prefix.length - 1) {
  263. bytes /= base;
  264. ++unit;
  265. }
  266. return `${bytes.toFixed(1)} ${prefix[unit]}B`;
  267. }
  268. function mergeDeep() {
  269. let source = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
  270. let target = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
  271. let arrayFn = arguments.length > 2 ? arguments[2] : undefined;
  272. const out = {};
  273. for (const key in source) {
  274. out[key] = source[key];
  275. }
  276. for (const key in target) {
  277. const sourceProperty = source[key];
  278. const targetProperty = target[key];
  279. // Only continue deep merging if
  280. // both properties are plain objects
  281. if (isPlainObject(sourceProperty) && isPlainObject(targetProperty)) {
  282. out[key] = mergeDeep(sourceProperty, targetProperty, arrayFn);
  283. continue;
  284. }
  285. if (arrayFn && Array.isArray(sourceProperty) && Array.isArray(targetProperty)) {
  286. out[key] = arrayFn(sourceProperty, targetProperty);
  287. continue;
  288. }
  289. out[key] = targetProperty;
  290. }
  291. return out;
  292. }
  293. function flattenFragments(nodes) {
  294. return nodes.map(node => {
  295. if (node.type === vue.Fragment) {
  296. return flattenFragments(node.children);
  297. } else {
  298. return node;
  299. }
  300. }).flat();
  301. }
  302. function toKebabCase() {
  303. let str = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : '';
  304. if (toKebabCase.cache.has(str)) return toKebabCase.cache.get(str);
  305. const kebab = str.replace(/[^a-z]/gi, '-').replace(/\B([A-Z])/g, '-$1').toLowerCase();
  306. toKebabCase.cache.set(str, kebab);
  307. return kebab;
  308. }
  309. toKebabCase.cache = new Map();
  310. function findChildrenWithProvide(key, vnode) {
  311. if (!vnode || typeof vnode !== 'object') return [];
  312. if (Array.isArray(vnode)) {
  313. return vnode.map(child => findChildrenWithProvide(key, child)).flat(1);
  314. } else if (vnode.suspense) {
  315. return findChildrenWithProvide(key, vnode.ssContent);
  316. } else if (Array.isArray(vnode.children)) {
  317. return vnode.children.map(child => findChildrenWithProvide(key, child)).flat(1);
  318. } else if (vnode.component) {
  319. if (Object.getOwnPropertySymbols(vnode.component.provides).includes(key)) {
  320. return [vnode.component];
  321. } else if (vnode.component.subTree) {
  322. return findChildrenWithProvide(key, vnode.component.subTree).flat(1);
  323. }
  324. }
  325. return [];
  326. }
  327. var _arr = /*#__PURE__*/new WeakMap();
  328. var _pointer = /*#__PURE__*/new WeakMap();
  329. class CircularBuffer {
  330. constructor(size) {
  331. _classPrivateFieldInitSpec(this, _arr, []);
  332. _classPrivateFieldInitSpec(this, _pointer, 0);
  333. this.size = size;
  334. }
  335. push(val) {
  336. _classPrivateFieldGet(_arr, this)[_classPrivateFieldGet(_pointer, this)] = val;
  337. _classPrivateFieldSet(_pointer, this, (_classPrivateFieldGet(_pointer, this) + 1) % this.size);
  338. }
  339. values() {
  340. return _classPrivateFieldGet(_arr, this).slice(_classPrivateFieldGet(_pointer, this)).concat(_classPrivateFieldGet(_arr, this).slice(0, _classPrivateFieldGet(_pointer, this)));
  341. }
  342. }
  343. function getEventCoordinates(e) {
  344. if ('touches' in e) {
  345. return {
  346. clientX: e.touches[0].clientX,
  347. clientY: e.touches[0].clientY
  348. };
  349. }
  350. return {
  351. clientX: e.clientX,
  352. clientY: e.clientY
  353. };
  354. }
  355. // Only allow a single return type
  356. /**
  357. * Convert a computed ref to a record of refs.
  358. * The getter function must always return an object with the same keys.
  359. */
  360. function destructComputed(getter) {
  361. const refs = vue.reactive({});
  362. const base = vue.computed(getter);
  363. vue.watchEffect(() => {
  364. for (const key in base.value) {
  365. refs[key] = base.value[key];
  366. }
  367. }, {
  368. flush: 'sync'
  369. });
  370. return vue.toRefs(refs);
  371. }
  372. /** Array.includes but value can be any type */
  373. function includes(arr, val) {
  374. return arr.includes(val);
  375. }
  376. function eventName(propName) {
  377. return propName[2].toLowerCase() + propName.slice(3);
  378. }
  379. const EventProp = () => [Function, Array];
  380. function hasEvent(props, name) {
  381. name = 'on' + vue.capitalize(name);
  382. return !!(props[name] || props[`${name}Once`] || props[`${name}Capture`] || props[`${name}OnceCapture`] || props[`${name}CaptureOnce`]);
  383. }
  384. function callEvent(handler) {
  385. for (var _len2 = arguments.length, args = new Array(_len2 > 1 ? _len2 - 1 : 0), _key2 = 1; _key2 < _len2; _key2++) {
  386. args[_key2 - 1] = arguments[_key2];
  387. }
  388. if (Array.isArray(handler)) {
  389. for (const h of handler) {
  390. h(...args);
  391. }
  392. } else if (typeof handler === 'function') {
  393. handler(...args);
  394. }
  395. }
  396. function focusableChildren(el) {
  397. let filterByTabIndex = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : true;
  398. const targets = ['button', '[href]', 'input:not([type="hidden"])', 'select', 'textarea', '[tabindex]'].map(s => `${s}${filterByTabIndex ? ':not([tabindex="-1"])' : ''}:not([disabled])`).join(', ');
  399. return [...el.querySelectorAll(targets)];
  400. }
  401. function getNextElement(elements, location, condition) {
  402. let _el;
  403. let idx = elements.indexOf(document.activeElement);
  404. const inc = location === 'next' ? 1 : -1;
  405. do {
  406. idx += inc;
  407. _el = elements[idx];
  408. } while ((!_el || _el.offsetParent == null || !(condition?.(_el) ?? true)) && idx < elements.length && idx >= 0);
  409. return _el;
  410. }
  411. function focusChild(el, location) {
  412. const focusable = focusableChildren(el);
  413. if (!location) {
  414. if (el === document.activeElement || !el.contains(document.activeElement)) {
  415. focusable[0]?.focus();
  416. }
  417. } else if (location === 'first') {
  418. focusable[0]?.focus();
  419. } else if (location === 'last') {
  420. focusable.at(-1)?.focus();
  421. } else if (typeof location === 'number') {
  422. focusable[location]?.focus();
  423. } else {
  424. const _el = getNextElement(focusable, location);
  425. if (_el) _el.focus();else focusChild(el, location === 'next' ? 'first' : 'last');
  426. }
  427. }
  428. function isEmpty(val) {
  429. return val === null || val === undefined || typeof val === 'string' && val.trim() === '';
  430. }
  431. function noop() {}
  432. /** Returns null if the selector is not supported or we can't check */
  433. function matchesSelector(el, selector) {
  434. const supportsSelector = IN_BROWSER && typeof CSS !== 'undefined' && typeof CSS.supports !== 'undefined' && CSS.supports(`selector(${selector})`);
  435. if (!supportsSelector) return null;
  436. try {
  437. return !!el && el.matches(selector);
  438. } catch (err) {
  439. return null;
  440. }
  441. }
  442. function ensureValidVNode(vnodes) {
  443. return vnodes.some(child => {
  444. if (!vue.isVNode(child)) return true;
  445. if (child.type === vue.Comment) return false;
  446. return child.type !== vue.Fragment || ensureValidVNode(child.children);
  447. }) ? vnodes : null;
  448. }
  449. function defer(timeout, cb) {
  450. if (!IN_BROWSER || timeout === 0) {
  451. cb();
  452. return () => {};
  453. }
  454. const timeoutId = window.setTimeout(cb, timeout);
  455. return () => window.clearTimeout(timeoutId);
  456. }
  457. function isClickInsideElement(event, targetDiv) {
  458. const mouseX = event.clientX;
  459. const mouseY = event.clientY;
  460. const divRect = targetDiv.getBoundingClientRect();
  461. const divLeft = divRect.left;
  462. const divTop = divRect.top;
  463. const divRight = divRect.right;
  464. const divBottom = divRect.bottom;
  465. return mouseX >= divLeft && mouseX <= divRight && mouseY >= divTop && mouseY <= divBottom;
  466. }
  467. function templateRef() {
  468. const el = vue.shallowRef();
  469. const fn = target => {
  470. el.value = target;
  471. };
  472. Object.defineProperty(fn, 'value', {
  473. enumerable: true,
  474. get: () => el.value,
  475. set: val => el.value = val
  476. });
  477. Object.defineProperty(fn, 'el', {
  478. enumerable: true,
  479. get: () => refElement(el.value)
  480. });
  481. return fn;
  482. }
  483. function checkPrintable(e) {
  484. const isPrintableChar = e.key.length === 1;
  485. const noModifier = !e.ctrlKey && !e.metaKey && !e.altKey;
  486. return isPrintableChar && noModifier;
  487. }
  488. // Utilities
  489. const block = ['top', 'bottom'];
  490. const inline = ['start', 'end', 'left', 'right'];
  491. /** Parse a raw anchor string into an object */
  492. function parseAnchor(anchor, isRtl) {
  493. let [side, align] = anchor.split(' ');
  494. if (!align) {
  495. align = includes(block, side) ? 'start' : includes(inline, side) ? 'top' : 'center';
  496. }
  497. return {
  498. side: toPhysical(side, isRtl),
  499. align: toPhysical(align, isRtl)
  500. };
  501. }
  502. function toPhysical(str, isRtl) {
  503. if (str === 'start') return isRtl ? 'right' : 'left';
  504. if (str === 'end') return isRtl ? 'left' : 'right';
  505. return str;
  506. }
  507. function flipSide(anchor) {
  508. return {
  509. side: {
  510. center: 'center',
  511. top: 'bottom',
  512. bottom: 'top',
  513. left: 'right',
  514. right: 'left'
  515. }[anchor.side],
  516. align: anchor.align
  517. };
  518. }
  519. function flipAlign(anchor) {
  520. return {
  521. side: anchor.side,
  522. align: {
  523. center: 'center',
  524. top: 'bottom',
  525. bottom: 'top',
  526. left: 'right',
  527. right: 'left'
  528. }[anchor.align]
  529. };
  530. }
  531. function flipCorner(anchor) {
  532. return {
  533. side: anchor.align,
  534. align: anchor.side
  535. };
  536. }
  537. function getAxis(anchor) {
  538. return includes(block, anchor.side) ? 'y' : 'x';
  539. }
  540. class Box {
  541. constructor(_ref) {
  542. let {
  543. x,
  544. y,
  545. width,
  546. height
  547. } = _ref;
  548. this.x = x;
  549. this.y = y;
  550. this.width = width;
  551. this.height = height;
  552. }
  553. get top() {
  554. return this.y;
  555. }
  556. get bottom() {
  557. return this.y + this.height;
  558. }
  559. get left() {
  560. return this.x;
  561. }
  562. get right() {
  563. return this.x + this.width;
  564. }
  565. }
  566. function getOverflow(a, b) {
  567. return {
  568. x: {
  569. before: Math.max(0, b.left - a.left),
  570. after: Math.max(0, a.right - b.right)
  571. },
  572. y: {
  573. before: Math.max(0, b.top - a.top),
  574. after: Math.max(0, a.bottom - b.bottom)
  575. }
  576. };
  577. }
  578. function getTargetBox(target) {
  579. if (Array.isArray(target)) {
  580. return new Box({
  581. x: target[0],
  582. y: target[1],
  583. width: 0,
  584. height: 0
  585. });
  586. } else {
  587. return target.getBoundingClientRect();
  588. }
  589. }
  590. // Utilities
  591. /** @see https://stackoverflow.com/a/57876601/2074736 */
  592. function nullifyTransforms(el) {
  593. const rect = el.getBoundingClientRect();
  594. const style = getComputedStyle(el);
  595. const tx = style.transform;
  596. if (tx) {
  597. let ta, sx, sy, dx, dy;
  598. if (tx.startsWith('matrix3d(')) {
  599. ta = tx.slice(9, -1).split(/, /);
  600. sx = +ta[0];
  601. sy = +ta[5];
  602. dx = +ta[12];
  603. dy = +ta[13];
  604. } else if (tx.startsWith('matrix(')) {
  605. ta = tx.slice(7, -1).split(/, /);
  606. sx = +ta[0];
  607. sy = +ta[3];
  608. dx = +ta[4];
  609. dy = +ta[5];
  610. } else {
  611. return new Box(rect);
  612. }
  613. const to = style.transformOrigin;
  614. const x = rect.x - dx - (1 - sx) * parseFloat(to);
  615. const y = rect.y - dy - (1 - sy) * parseFloat(to.slice(to.indexOf(' ') + 1));
  616. const w = sx ? rect.width / sx : el.offsetWidth + 1;
  617. const h = sy ? rect.height / sy : el.offsetHeight + 1;
  618. return new Box({
  619. x,
  620. y,
  621. width: w,
  622. height: h
  623. });
  624. } else {
  625. return new Box(rect);
  626. }
  627. }
  628. function animate(el, keyframes, options) {
  629. if (typeof el.animate === 'undefined') return {
  630. finished: Promise.resolve()
  631. };
  632. let animation;
  633. try {
  634. animation = el.animate(keyframes, options);
  635. } catch (err) {
  636. return {
  637. finished: Promise.resolve()
  638. };
  639. }
  640. if (typeof animation.finished === 'undefined') {
  641. animation.finished = new Promise(resolve => {
  642. animation.onfinish = () => {
  643. resolve(animation);
  644. };
  645. });
  646. }
  647. return animation;
  648. }
  649. // Utilities
  650. const handlers = new WeakMap();
  651. function bindProps(el, props) {
  652. Object.keys(props).forEach(k => {
  653. if (isOn(k)) {
  654. const name = eventName(k);
  655. const handler = handlers.get(el);
  656. if (props[k] == null) {
  657. handler?.forEach(v => {
  658. const [n, fn] = v;
  659. if (n === name) {
  660. el.removeEventListener(name, fn);
  661. handler.delete(v);
  662. }
  663. });
  664. } else if (!handler || ![...handler]?.some(v => v[0] === name && v[1] === props[k])) {
  665. el.addEventListener(name, props[k]);
  666. const _handler = handler || new Set();
  667. _handler.add([name, props[k]]);
  668. if (!handlers.has(el)) handlers.set(el, _handler);
  669. }
  670. } else {
  671. if (props[k] == null) {
  672. el.removeAttribute(k);
  673. } else {
  674. el.setAttribute(k, props[k]);
  675. }
  676. }
  677. });
  678. }
  679. function unbindProps(el, props) {
  680. Object.keys(props).forEach(k => {
  681. if (isOn(k)) {
  682. const name = eventName(k);
  683. const handler = handlers.get(el);
  684. handler?.forEach(v => {
  685. const [n, fn] = v;
  686. if (n === name) {
  687. el.removeEventListener(name, fn);
  688. handler.delete(v);
  689. }
  690. });
  691. } else {
  692. el.removeAttribute(k);
  693. }
  694. });
  695. }
  696. /**
  697. * WCAG 3.0 APCA perceptual contrast algorithm from https://github.com/Myndex/SAPC-APCA
  698. * @licence https://www.w3.org/Consortium/Legal/2015/copyright-software-and-document
  699. * @see https://www.w3.org/WAI/GL/task-forces/silver/wiki/Visual_Contrast_of_Text_Subgroup
  700. */
  701. // Types
  702. // MAGICAL NUMBERS
  703. // sRGB Conversion to Relative Luminance (Y)
  704. // Transfer Curve (aka "Gamma") for sRGB linearization
  705. // Simple power curve vs piecewise described in docs
  706. // Essentially, 2.4 best models actual display
  707. // characteristics in combination with the total method
  708. const mainTRC = 2.4;
  709. const Rco = 0.2126729; // sRGB Red Coefficient (from matrix)
  710. const Gco = 0.7151522; // sRGB Green Coefficient (from matrix)
  711. const Bco = 0.0721750; // sRGB Blue Coefficient (from matrix)
  712. // For Finding Raw SAPC Contrast from Relative Luminance (Y)
  713. // Constants for SAPC Power Curve Exponents
  714. // One pair for normal text, and one for reverse
  715. // These are the "beating heart" of SAPC
  716. const normBG = 0.55;
  717. const normTXT = 0.58;
  718. const revTXT = 0.57;
  719. const revBG = 0.62;
  720. // For Clamping and Scaling Values
  721. const blkThrs = 0.03; // Level that triggers the soft black clamp
  722. const blkClmp = 1.45; // Exponent for the soft black clamp curve
  723. const deltaYmin = 0.0005; // Lint trap
  724. const scaleBoW = 1.25; // Scaling for dark text on light
  725. const scaleWoB = 1.25; // Scaling for light text on dark
  726. const loConThresh = 0.078; // Threshold for new simple offset scale
  727. const loConFactor = 12.82051282051282; // = 1/0.078,
  728. const loConOffset = 0.06; // The simple offset
  729. const loClip = 0.001; // Output clip (lint trap #2)
  730. function APCAcontrast(text, background) {
  731. // Linearize sRGB
  732. const Rtxt = (text.r / 255) ** mainTRC;
  733. const Gtxt = (text.g / 255) ** mainTRC;
  734. const Btxt = (text.b / 255) ** mainTRC;
  735. const Rbg = (background.r / 255) ** mainTRC;
  736. const Gbg = (background.g / 255) ** mainTRC;
  737. const Bbg = (background.b / 255) ** mainTRC;
  738. // Apply the standard coefficients and sum to Y
  739. let Ytxt = Rtxt * Rco + Gtxt * Gco + Btxt * Bco;
  740. let Ybg = Rbg * Rco + Gbg * Gco + Bbg * Bco;
  741. // Soft clamp Y when near black.
  742. // Now clamping all colors to prevent crossover errors
  743. if (Ytxt <= blkThrs) Ytxt += (blkThrs - Ytxt) ** blkClmp;
  744. if (Ybg <= blkThrs) Ybg += (blkThrs - Ybg) ** blkClmp;
  745. // Return 0 Early for extremely low ∆Y (lint trap #1)
  746. if (Math.abs(Ybg - Ytxt) < deltaYmin) return 0.0;
  747. // SAPC CONTRAST
  748. let outputContrast; // For weighted final values
  749. if (Ybg > Ytxt) {
  750. // For normal polarity, black text on white
  751. // Calculate the SAPC contrast value and scale
  752. const SAPC = (Ybg ** normBG - Ytxt ** normTXT) * scaleBoW;
  753. // NEW! SAPC SmoothScale™
  754. // Low Contrast Smooth Scale Rollout to prevent polarity reversal
  755. // and also a low clip for very low contrasts (lint trap #2)
  756. // much of this is for very low contrasts, less than 10
  757. // therefore for most reversing needs, only loConOffset is important
  758. outputContrast = SAPC < loClip ? 0.0 : SAPC < loConThresh ? SAPC - SAPC * loConFactor * loConOffset : SAPC - loConOffset;
  759. } else {
  760. // For reverse polarity, light text on dark
  761. // WoB should always return negative value.
  762. const SAPC = (Ybg ** revBG - Ytxt ** revTXT) * scaleWoB;
  763. outputContrast = SAPC > -loClip ? 0.0 : SAPC > -loConThresh ? SAPC - SAPC * loConFactor * loConOffset : SAPC + loConOffset;
  764. }
  765. return outputContrast * 100;
  766. }
  767. /* eslint-disable no-console */
  768. function consoleWarn(message) {
  769. vue.warn(`Vuetify: ${message}`);
  770. }
  771. function consoleError(message) {
  772. vue.warn(`Vuetify error: ${message}`);
  773. }
  774. function deprecate(original, replacement) {
  775. replacement = Array.isArray(replacement) ? replacement.slice(0, -1).map(s => `'${s}'`).join(', ') + ` or '${replacement.at(-1)}'` : `'${replacement}'`;
  776. vue.warn(`[Vuetify UPGRADE] '${original}' is deprecated, use ${replacement} instead.`);
  777. }
  778. // Types
  779. const delta = 0.20689655172413793; // 6÷29
  780. const cielabForwardTransform = t => t > delta ** 3 ? Math.cbrt(t) : t / (3 * delta ** 2) + 4 / 29;
  781. const cielabReverseTransform = t => t > delta ? t ** 3 : 3 * delta ** 2 * (t - 4 / 29);
  782. function fromXYZ$1(xyz) {
  783. const transform = cielabForwardTransform;
  784. const transformedY = transform(xyz[1]);
  785. return [116 * transformedY - 16, 500 * (transform(xyz[0] / 0.95047) - transformedY), 200 * (transformedY - transform(xyz[2] / 1.08883))];
  786. }
  787. function toXYZ$1(lab) {
  788. const transform = cielabReverseTransform;
  789. const Ln = (lab[0] + 16) / 116;
  790. return [transform(Ln + lab[1] / 500) * 0.95047, transform(Ln), transform(Ln - lab[2] / 200) * 1.08883];
  791. }
  792. // Utilities
  793. // Types
  794. // For converting XYZ to sRGB
  795. const srgbForwardMatrix = [[3.2406, -1.5372, -0.4986], [-0.9689, 1.8758, 0.0415], [0.0557, -0.2040, 1.0570]];
  796. // Forward gamma adjust
  797. const srgbForwardTransform = C => C <= 0.0031308 ? C * 12.92 : 1.055 * C ** (1 / 2.4) - 0.055;
  798. // For converting sRGB to XYZ
  799. const srgbReverseMatrix = [[0.4124, 0.3576, 0.1805], [0.2126, 0.7152, 0.0722], [0.0193, 0.1192, 0.9505]];
  800. // Reverse gamma adjust
  801. const srgbReverseTransform = C => C <= 0.04045 ? C / 12.92 : ((C + 0.055) / 1.055) ** 2.4;
  802. function fromXYZ(xyz) {
  803. const rgb = Array(3);
  804. const transform = srgbForwardTransform;
  805. const matrix = srgbForwardMatrix;
  806. // Matrix transform, then gamma adjustment
  807. for (let i = 0; i < 3; ++i) {
  808. // Rescale back to [0, 255]
  809. rgb[i] = Math.round(clamp(transform(matrix[i][0] * xyz[0] + matrix[i][1] * xyz[1] + matrix[i][2] * xyz[2])) * 255);
  810. }
  811. return {
  812. r: rgb[0],
  813. g: rgb[1],
  814. b: rgb[2]
  815. };
  816. }
  817. function toXYZ(_ref) {
  818. let {
  819. r,
  820. g,
  821. b
  822. } = _ref;
  823. const xyz = [0, 0, 0];
  824. const transform = srgbReverseTransform;
  825. const matrix = srgbReverseMatrix;
  826. // Rescale from [0, 255] to [0, 1] then adjust sRGB gamma to linear RGB
  827. r = transform(r / 255);
  828. g = transform(g / 255);
  829. b = transform(b / 255);
  830. // Matrix color space transform
  831. for (let i = 0; i < 3; ++i) {
  832. xyz[i] = matrix[i][0] * r + matrix[i][1] * g + matrix[i][2] * b;
  833. }
  834. return xyz;
  835. }
  836. // Utilities
  837. // Types
  838. function isCssColor(color) {
  839. return !!color && /^(#|var\(--|(rgb|hsl)a?\()/.test(color);
  840. }
  841. function isParsableColor(color) {
  842. return isCssColor(color) && !/^((rgb|hsl)a?\()?var\(--/.test(color);
  843. }
  844. const cssColorRe = /^(?<fn>(?:rgb|hsl)a?)\((?<values>.+)\)/;
  845. const mappers = {
  846. rgb: (r, g, b, a) => ({
  847. r,
  848. g,
  849. b,
  850. a
  851. }),
  852. rgba: (r, g, b, a) => ({
  853. r,
  854. g,
  855. b,
  856. a
  857. }),
  858. hsl: (h, s, l, a) => HSLtoRGB({
  859. h,
  860. s,
  861. l,
  862. a
  863. }),
  864. hsla: (h, s, l, a) => HSLtoRGB({
  865. h,
  866. s,
  867. l,
  868. a
  869. }),
  870. hsv: (h, s, v, a) => HSVtoRGB({
  871. h,
  872. s,
  873. v,
  874. a
  875. }),
  876. hsva: (h, s, v, a) => HSVtoRGB({
  877. h,
  878. s,
  879. v,
  880. a
  881. })
  882. };
  883. function parseColor(color) {
  884. if (typeof color === 'number') {
  885. if (isNaN(color) || color < 0 || color > 0xFFFFFF) {
  886. // int can't have opacity
  887. consoleWarn(`'${color}' is not a valid hex color`);
  888. }
  889. return {
  890. r: (color & 0xFF0000) >> 16,
  891. g: (color & 0xFF00) >> 8,
  892. b: color & 0xFF
  893. };
  894. } else if (typeof color === 'string' && cssColorRe.test(color)) {
  895. const {
  896. groups
  897. } = color.match(cssColorRe);
  898. const {
  899. fn,
  900. values
  901. } = groups;
  902. const realValues = values.split(/,\s*/).map(v => {
  903. if (v.endsWith('%') && ['hsl', 'hsla', 'hsv', 'hsva'].includes(fn)) {
  904. return parseFloat(v) / 100;
  905. } else {
  906. return parseFloat(v);
  907. }
  908. });
  909. return mappers[fn](...realValues);
  910. } else if (typeof color === 'string') {
  911. let hex = color.startsWith('#') ? color.slice(1) : color;
  912. if ([3, 4].includes(hex.length)) {
  913. hex = hex.split('').map(char => char + char).join('');
  914. } else if (![6, 8].includes(hex.length)) {
  915. consoleWarn(`'${color}' is not a valid hex(a) color`);
  916. }
  917. const int = parseInt(hex, 16);
  918. if (isNaN(int) || int < 0 || int > 0xFFFFFFFF) {
  919. consoleWarn(`'${color}' is not a valid hex(a) color`);
  920. }
  921. return HexToRGB(hex);
  922. } else if (typeof color === 'object') {
  923. if (has(color, ['r', 'g', 'b'])) {
  924. return color;
  925. } else if (has(color, ['h', 's', 'l'])) {
  926. return HSVtoRGB(HSLtoHSV(color));
  927. } else if (has(color, ['h', 's', 'v'])) {
  928. return HSVtoRGB(color);
  929. }
  930. }
  931. throw new TypeError(`Invalid color: ${color == null ? color : String(color) || color.constructor.name}\nExpected #hex, #hexa, rgb(), rgba(), hsl(), hsla(), object or number`);
  932. }
  933. /** Converts HSVA to RGBA. Based on formula from https://en.wikipedia.org/wiki/HSL_and_HSV */
  934. function HSVtoRGB(hsva) {
  935. const {
  936. h,
  937. s,
  938. v,
  939. a
  940. } = hsva;
  941. const f = n => {
  942. const k = (n + h / 60) % 6;
  943. return v - v * s * Math.max(Math.min(k, 4 - k, 1), 0);
  944. };
  945. const rgb = [f(5), f(3), f(1)].map(v => Math.round(v * 255));
  946. return {
  947. r: rgb[0],
  948. g: rgb[1],
  949. b: rgb[2],
  950. a
  951. };
  952. }
  953. function HSLtoRGB(hsla) {
  954. return HSVtoRGB(HSLtoHSV(hsla));
  955. }
  956. /** Converts RGBA to HSVA. Based on formula from https://en.wikipedia.org/wiki/HSL_and_HSV */
  957. function RGBtoHSV(rgba) {
  958. if (!rgba) return {
  959. h: 0,
  960. s: 1,
  961. v: 1,
  962. a: 1
  963. };
  964. const r = rgba.r / 255;
  965. const g = rgba.g / 255;
  966. const b = rgba.b / 255;
  967. const max = Math.max(r, g, b);
  968. const min = Math.min(r, g, b);
  969. let h = 0;
  970. if (max !== min) {
  971. if (max === r) {
  972. h = 60 * (0 + (g - b) / (max - min));
  973. } else if (max === g) {
  974. h = 60 * (2 + (b - r) / (max - min));
  975. } else if (max === b) {
  976. h = 60 * (4 + (r - g) / (max - min));
  977. }
  978. }
  979. if (h < 0) h = h + 360;
  980. const s = max === 0 ? 0 : (max - min) / max;
  981. const hsv = [h, s, max];
  982. return {
  983. h: hsv[0],
  984. s: hsv[1],
  985. v: hsv[2],
  986. a: rgba.a
  987. };
  988. }
  989. function HSVtoHSL(hsva) {
  990. const {
  991. h,
  992. s,
  993. v,
  994. a
  995. } = hsva;
  996. const l = v - v * s / 2;
  997. const sprime = l === 1 || l === 0 ? 0 : (v - l) / Math.min(l, 1 - l);
  998. return {
  999. h,
  1000. s: sprime,
  1001. l,
  1002. a
  1003. };
  1004. }
  1005. function HSLtoHSV(hsl) {
  1006. const {
  1007. h,
  1008. s,
  1009. l,
  1010. a
  1011. } = hsl;
  1012. const v = l + s * Math.min(l, 1 - l);
  1013. const sprime = v === 0 ? 0 : 2 - 2 * l / v;
  1014. return {
  1015. h,
  1016. s: sprime,
  1017. v,
  1018. a
  1019. };
  1020. }
  1021. function RGBtoCSS(_ref) {
  1022. let {
  1023. r,
  1024. g,
  1025. b,
  1026. a
  1027. } = _ref;
  1028. return a === undefined ? `rgb(${r}, ${g}, ${b})` : `rgba(${r}, ${g}, ${b}, ${a})`;
  1029. }
  1030. function HSVtoCSS(hsva) {
  1031. return RGBtoCSS(HSVtoRGB(hsva));
  1032. }
  1033. function toHex(v) {
  1034. const h = Math.round(v).toString(16);
  1035. return ('00'.substr(0, 2 - h.length) + h).toUpperCase();
  1036. }
  1037. function RGBtoHex(_ref2) {
  1038. let {
  1039. r,
  1040. g,
  1041. b,
  1042. a
  1043. } = _ref2;
  1044. return `#${[toHex(r), toHex(g), toHex(b), a !== undefined ? toHex(Math.round(a * 255)) : ''].join('')}`;
  1045. }
  1046. function HexToRGB(hex) {
  1047. hex = parseHex(hex);
  1048. let [r, g, b, a] = chunk(hex, 2).map(c => parseInt(c, 16));
  1049. a = a === undefined ? a : a / 255;
  1050. return {
  1051. r,
  1052. g,
  1053. b,
  1054. a
  1055. };
  1056. }
  1057. function HexToHSV(hex) {
  1058. const rgb = HexToRGB(hex);
  1059. return RGBtoHSV(rgb);
  1060. }
  1061. function HSVtoHex(hsva) {
  1062. return RGBtoHex(HSVtoRGB(hsva));
  1063. }
  1064. function parseHex(hex) {
  1065. if (hex.startsWith('#')) {
  1066. hex = hex.slice(1);
  1067. }
  1068. hex = hex.replace(/([^0-9a-f])/gi, 'F');
  1069. if (hex.length === 3 || hex.length === 4) {
  1070. hex = hex.split('').map(x => x + x).join('');
  1071. }
  1072. if (hex.length !== 6) {
  1073. hex = padEnd(padEnd(hex, 6), 8, 'F');
  1074. }
  1075. return hex;
  1076. }
  1077. function lighten(value, amount) {
  1078. const lab = fromXYZ$1(toXYZ(value));
  1079. lab[0] = lab[0] + amount * 10;
  1080. return fromXYZ(toXYZ$1(lab));
  1081. }
  1082. function darken(value, amount) {
  1083. const lab = fromXYZ$1(toXYZ(value));
  1084. lab[0] = lab[0] - amount * 10;
  1085. return fromXYZ(toXYZ$1(lab));
  1086. }
  1087. /**
  1088. * Calculate the relative luminance of a given color
  1089. * @see https://www.w3.org/TR/WCAG20/#relativeluminancedef
  1090. */
  1091. function getLuma(color) {
  1092. const rgb = parseColor(color);
  1093. return toXYZ(rgb)[1];
  1094. }
  1095. /**
  1096. * Returns the contrast ratio (1-21) between two colors.
  1097. * @see https://www.w3.org/TR/WCAG20/#contrast-ratiodef
  1098. */
  1099. function getContrast(first, second) {
  1100. const l1 = getLuma(first);
  1101. const l2 = getLuma(second);
  1102. const light = Math.max(l1, l2);
  1103. const dark = Math.min(l1, l2);
  1104. return (light + 0.05) / (dark + 0.05);
  1105. }
  1106. function getForeground(color) {
  1107. const blackContrast = Math.abs(APCAcontrast(parseColor(0), parseColor(color)));
  1108. const whiteContrast = Math.abs(APCAcontrast(parseColor(0xffffff), parseColor(color)));
  1109. // TODO: warn about poor color selections
  1110. // const contrastAsText = Math.abs(APCAcontrast(colorVal, colorToInt(theme.colors.background)))
  1111. // const minContrast = Math.max(blackContrast, whiteContrast)
  1112. // if (minContrast < 60) {
  1113. // consoleInfo(`${key} theme color ${color} has poor contrast (${minContrast.toFixed()}%)`)
  1114. // } else if (contrastAsText < 60 && !['background', 'surface'].includes(color)) {
  1115. // consoleInfo(`${key} theme color ${color} has poor contrast as text (${contrastAsText.toFixed()}%)`)
  1116. // }
  1117. // Prefer white text if both have an acceptable contrast ratio
  1118. return whiteContrast > Math.min(blackContrast, 50) ? '#fff' : '#000';
  1119. }
  1120. // Types
  1121. // eslint-disable-line vue/prefer-import-from-vue
  1122. /**
  1123. * Creates a factory function for props definitions.
  1124. * This is used to define props in a composable then override
  1125. * default values in an implementing component.
  1126. *
  1127. * @example Simplified signature
  1128. * (props: Props) => (defaults?: Record<keyof props, any>) => Props
  1129. *
  1130. * @example Usage
  1131. * const makeProps = propsFactory({
  1132. * foo: String,
  1133. * })
  1134. *
  1135. * defineComponent({
  1136. * props: {
  1137. * ...makeProps({
  1138. * foo: 'a',
  1139. * }),
  1140. * },
  1141. * setup (props) {
  1142. * // would be "string | undefined", now "string" because a default has been provided
  1143. * props.foo
  1144. * },
  1145. * }
  1146. */
  1147. function propsFactory(props, source) {
  1148. return defaults => {
  1149. return Object.keys(props).reduce((obj, prop) => {
  1150. const isObjectDefinition = typeof props[prop] === 'object' && props[prop] != null && !Array.isArray(props[prop]);
  1151. const definition = isObjectDefinition ? props[prop] : {
  1152. type: props[prop]
  1153. };
  1154. if (defaults && prop in defaults) {
  1155. obj[prop] = {
  1156. ...definition,
  1157. default: defaults[prop]
  1158. };
  1159. } else {
  1160. obj[prop] = definition;
  1161. }
  1162. if (source && !obj[prop].source) {
  1163. obj[prop].source = source;
  1164. }
  1165. return obj;
  1166. }, {});
  1167. };
  1168. }
  1169. /**
  1170. * Like `Partial<T>` but doesn't care what the value is
  1171. */
  1172. // Copied from Vue
  1173. // Utilities
  1174. // Types
  1175. // Composables
  1176. const makeComponentProps = propsFactory({
  1177. class: [String, Array, Object],
  1178. style: {
  1179. type: [String, Array, Object],
  1180. default: null
  1181. }
  1182. }, 'component');
  1183. // Utilities
  1184. // Types
  1185. function getCurrentInstance(name, message) {
  1186. const vm = vue.getCurrentInstance();
  1187. if (!vm) {
  1188. throw new Error(`[Vuetify] ${name} ${message || 'must be called from inside a setup function'}`);
  1189. }
  1190. return vm;
  1191. }
  1192. function getCurrentInstanceName() {
  1193. let name = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 'composables';
  1194. const vm = getCurrentInstance(name).type;
  1195. return toKebabCase(vm?.aliasName || vm?.name);
  1196. }
  1197. let _uid = 0;
  1198. let _map = new WeakMap();
  1199. function getUid() {
  1200. const vm = getCurrentInstance('getUid');
  1201. if (_map.has(vm)) return _map.get(vm);else {
  1202. const uid = _uid++;
  1203. _map.set(vm, uid);
  1204. return uid;
  1205. }
  1206. }
  1207. getUid.reset = () => {
  1208. _uid = 0;
  1209. _map = new WeakMap();
  1210. };
  1211. // Utilities
  1212. // Types
  1213. function injectSelf(key) {
  1214. let vm = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : getCurrentInstance('injectSelf');
  1215. const {
  1216. provides
  1217. } = vm;
  1218. if (provides && key in provides) {
  1219. // TS doesn't allow symbol as index type
  1220. return provides[key];
  1221. }
  1222. return undefined;
  1223. }
  1224. // Utilities
  1225. // Types
  1226. const DefaultsSymbol = Symbol.for('vuetify:defaults');
  1227. function createDefaults(options) {
  1228. return vue.ref(options);
  1229. }
  1230. function injectDefaults() {
  1231. const defaults = vue.inject(DefaultsSymbol);
  1232. if (!defaults) throw new Error('[Vuetify] Could not find defaults instance');
  1233. return defaults;
  1234. }
  1235. function provideDefaults(defaults, options) {
  1236. const injectedDefaults = injectDefaults();
  1237. const providedDefaults = vue.ref(defaults);
  1238. const newDefaults = vue.computed(() => {
  1239. const disabled = vue.unref(options?.disabled);
  1240. if (disabled) return injectedDefaults.value;
  1241. const scoped = vue.unref(options?.scoped);
  1242. const reset = vue.unref(options?.reset);
  1243. const root = vue.unref(options?.root);
  1244. if (providedDefaults.value == null && !(scoped || reset || root)) return injectedDefaults.value;
  1245. let properties = mergeDeep(providedDefaults.value, {
  1246. prev: injectedDefaults.value
  1247. });
  1248. if (scoped) return properties;
  1249. if (reset || root) {
  1250. const len = Number(reset || Infinity);
  1251. for (let i = 0; i <= len; i++) {
  1252. if (!properties || !('prev' in properties)) {
  1253. break;
  1254. }
  1255. properties = properties.prev;
  1256. }
  1257. if (properties && typeof root === 'string' && root in properties) {
  1258. properties = mergeDeep(mergeDeep(properties, {
  1259. prev: properties
  1260. }), properties[root]);
  1261. }
  1262. return properties;
  1263. }
  1264. return properties.prev ? mergeDeep(properties.prev, properties) : properties;
  1265. });
  1266. vue.provide(DefaultsSymbol, newDefaults);
  1267. return newDefaults;
  1268. }
  1269. function propIsDefined(vnode, prop) {
  1270. return typeof vnode.props?.[prop] !== 'undefined' || typeof vnode.props?.[toKebabCase(prop)] !== 'undefined';
  1271. }
  1272. function internalUseDefaults() {
  1273. let props = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
  1274. let name = arguments.length > 1 ? arguments[1] : undefined;
  1275. let defaults = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : injectDefaults();
  1276. const vm = getCurrentInstance('useDefaults');
  1277. name = name ?? vm.type.name ?? vm.type.__name;
  1278. if (!name) {
  1279. throw new Error('[Vuetify] Could not determine component name');
  1280. }
  1281. const componentDefaults = vue.computed(() => defaults.value?.[props._as ?? name]);
  1282. const _props = new Proxy(props, {
  1283. get(target, prop) {
  1284. const propValue = Reflect.get(target, prop);
  1285. if (prop === 'class' || prop === 'style') {
  1286. return [componentDefaults.value?.[prop], propValue].filter(v => v != null);
  1287. } else if (typeof prop === 'string' && !propIsDefined(vm.vnode, prop)) {
  1288. return componentDefaults.value?.[prop] !== undefined ? componentDefaults.value?.[prop] : defaults.value?.global?.[prop] !== undefined ? defaults.value?.global?.[prop] : propValue;
  1289. }
  1290. return propValue;
  1291. }
  1292. });
  1293. const _subcomponentDefaults = vue.shallowRef();
  1294. vue.watchEffect(() => {
  1295. if (componentDefaults.value) {
  1296. const subComponents = Object.entries(componentDefaults.value).filter(_ref => {
  1297. let [key] = _ref;
  1298. return key.startsWith(key[0].toUpperCase());
  1299. });
  1300. _subcomponentDefaults.value = subComponents.length ? Object.fromEntries(subComponents) : undefined;
  1301. } else {
  1302. _subcomponentDefaults.value = undefined;
  1303. }
  1304. });
  1305. function provideSubDefaults() {
  1306. const injected = injectSelf(DefaultsSymbol, vm);
  1307. vue.provide(DefaultsSymbol, vue.computed(() => {
  1308. return _subcomponentDefaults.value ? mergeDeep(injected?.value ?? {}, _subcomponentDefaults.value) : injected?.value;
  1309. }));
  1310. }
  1311. return {
  1312. props: _props,
  1313. provideSubDefaults
  1314. };
  1315. }
  1316. function useDefaults() {
  1317. let props = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
  1318. let name = arguments.length > 1 ? arguments[1] : undefined;
  1319. const {
  1320. props: _props,
  1321. provideSubDefaults
  1322. } = internalUseDefaults(props, name);
  1323. provideSubDefaults();
  1324. return _props;
  1325. }
  1326. // Composables
  1327. // Types
  1328. // No props
  1329. // Object Props
  1330. // Implementation
  1331. function defineComponent(options) {
  1332. options._setup = options._setup ?? options.setup;
  1333. if (!options.name) {
  1334. consoleWarn('The component is missing an explicit name, unable to generate default prop value');
  1335. return options;
  1336. }
  1337. if (options._setup) {
  1338. options.props = propsFactory(options.props ?? {}, options.name)();
  1339. const propKeys = Object.keys(options.props).filter(key => key !== 'class' && key !== 'style');
  1340. options.filterProps = function filterProps(props) {
  1341. return pick(props, propKeys);
  1342. };
  1343. options.props._as = String;
  1344. options.setup = function setup(props, ctx) {
  1345. const defaults = injectDefaults();
  1346. // Skip props proxy if defaults are not provided
  1347. if (!defaults.value) return options._setup(props, ctx);
  1348. const {
  1349. props: _props,
  1350. provideSubDefaults
  1351. } = internalUseDefaults(props, props._as ?? options.name, defaults);
  1352. const setupBindings = options._setup(_props, ctx);
  1353. provideSubDefaults();
  1354. return setupBindings;
  1355. };
  1356. }
  1357. return options;
  1358. }
  1359. // No argument - simple default slot
  1360. // Generic constructor argument - generic props and slots
  1361. // Slots argument - simple slots
  1362. // Implementation
  1363. function genericComponent() {
  1364. let exposeDefaults = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : true;
  1365. return options => (exposeDefaults ? defineComponent : vue.defineComponent)(options);
  1366. }
  1367. function defineFunctionalComponent(props, render) {
  1368. render.props = props;
  1369. return render;
  1370. }
  1371. // Adds a filterProps method to the component options
  1372. // https://github.com/vuejs/core/pull/10557
  1373. // not a vue Component
  1374. // Composables
  1375. function createSimpleFunctional(klass) {
  1376. let tag = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 'div';
  1377. let name = arguments.length > 2 ? arguments[2] : undefined;
  1378. return genericComponent()({
  1379. name: name ?? vue.capitalize(vue.camelize(klass.replace(/__/g, '-'))),
  1380. props: {
  1381. tag: {
  1382. type: String,
  1383. default: tag
  1384. },
  1385. ...makeComponentProps()
  1386. },
  1387. setup(props, _ref) {
  1388. let {
  1389. slots
  1390. } = _ref;
  1391. return () => {
  1392. return vue.h(props.tag, {
  1393. class: [klass, props.class],
  1394. style: props.style
  1395. }, slots.default?.());
  1396. };
  1397. }
  1398. });
  1399. }
  1400. /**
  1401. * Returns:
  1402. * - 'null' if the node is not attached to the DOM
  1403. * - the root node (HTMLDocument | ShadowRoot) otherwise
  1404. */
  1405. function attachedRoot(node) {
  1406. /* istanbul ignore next */
  1407. if (typeof node.getRootNode !== 'function') {
  1408. // Shadow DOM not supported (IE11), lets find the root of this node
  1409. while (node.parentNode) node = node.parentNode;
  1410. // The root parent is the document if the node is attached to the DOM
  1411. if (node !== document) return null;
  1412. return document;
  1413. }
  1414. const root = node.getRootNode();
  1415. // The composed root node is the document if the node is attached to the DOM
  1416. if (root !== document && root.getRootNode({
  1417. composed: true
  1418. }) !== document) return null;
  1419. return root;
  1420. }
  1421. const standardEasing = 'cubic-bezier(0.4, 0, 0.2, 1)';
  1422. const deceleratedEasing = 'cubic-bezier(0.0, 0, 0.2, 1)'; // Entering
  1423. const acceleratedEasing = 'cubic-bezier(0.4, 0, 1, 1)'; // Leaving
  1424. // Utilities
  1425. function getPrefixedEventHandlers(attrs, suffix, getData) {
  1426. return Object.keys(attrs).filter(key => isOn(key) && key.endsWith(suffix)).reduce((acc, key) => {
  1427. acc[key.slice(0, -suffix.length)] = event => attrs[key](event, getData(event));
  1428. return acc;
  1429. }, {});
  1430. }
  1431. function getScrollParent(el) {
  1432. let includeHidden = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : false;
  1433. while (el) {
  1434. if (includeHidden ? isPotentiallyScrollable(el) : hasScrollbar(el)) return el;
  1435. el = el.parentElement;
  1436. }
  1437. return document.scrollingElement;
  1438. }
  1439. function getScrollParents(el, stopAt) {
  1440. const elements = [];
  1441. if (stopAt && el && !stopAt.contains(el)) return elements;
  1442. while (el) {
  1443. if (hasScrollbar(el)) elements.push(el);
  1444. if (el === stopAt) break;
  1445. el = el.parentElement;
  1446. }
  1447. return elements;
  1448. }
  1449. function hasScrollbar(el) {
  1450. if (!el || el.nodeType !== Node.ELEMENT_NODE) return false;
  1451. const style = window.getComputedStyle(el);
  1452. return style.overflowY === 'scroll' || style.overflowY === 'auto' && el.scrollHeight > el.clientHeight;
  1453. }
  1454. function isPotentiallyScrollable(el) {
  1455. if (!el || el.nodeType !== Node.ELEMENT_NODE) return false;
  1456. const style = window.getComputedStyle(el);
  1457. return ['scroll', 'auto'].includes(style.overflowY);
  1458. }
  1459. function isFixedPosition(el) {
  1460. while (el) {
  1461. if (window.getComputedStyle(el).position === 'fixed') {
  1462. return true;
  1463. }
  1464. el = el.offsetParent;
  1465. }
  1466. return false;
  1467. }
  1468. // Utilities
  1469. // Types
  1470. function useRender(render) {
  1471. const vm = getCurrentInstance('useRender');
  1472. vm.render = render;
  1473. }
  1474. // Types
  1475. const IconValue = [String, Function, Object, Array];
  1476. const IconSymbol = Symbol.for('vuetify:icons');
  1477. const makeIconProps = propsFactory({
  1478. icon: {
  1479. type: IconValue
  1480. },
  1481. // Could not remove this and use makeTagProps, types complained because it is not required
  1482. tag: {
  1483. type: String,
  1484. required: true
  1485. }
  1486. }, 'icon');
  1487. const VComponentIcon = genericComponent()({
  1488. name: 'VComponentIcon',
  1489. props: makeIconProps(),
  1490. setup(props, _ref) {
  1491. let {
  1492. slots
  1493. } = _ref;
  1494. return () => {
  1495. const Icon = props.icon;
  1496. return vue.createVNode(props.tag, null, {
  1497. default: () => [props.icon ? vue.createVNode(Icon, null, null) : slots.default?.()]
  1498. });
  1499. };
  1500. }
  1501. });
  1502. const VSvgIcon = defineComponent({
  1503. name: 'VSvgIcon',
  1504. inheritAttrs: false,
  1505. props: makeIconProps(),
  1506. setup(props, _ref2) {
  1507. let {
  1508. attrs
  1509. } = _ref2;
  1510. return () => {
  1511. return vue.createVNode(props.tag, vue.mergeProps(attrs, {
  1512. "style": null
  1513. }), {
  1514. default: () => [vue.createVNode("svg", {
  1515. "class": "v-icon__svg",
  1516. "xmlns": "http://www.w3.org/2000/svg",
  1517. "viewBox": "0 0 24 24",
  1518. "role": "img",
  1519. "aria-hidden": "true"
  1520. }, [Array.isArray(props.icon) ? props.icon.map(path => Array.isArray(path) ? vue.createVNode("path", {
  1521. "d": path[0],
  1522. "fill-opacity": path[1]
  1523. }, null) : vue.createVNode("path", {
  1524. "d": path
  1525. }, null)) : vue.createVNode("path", {
  1526. "d": props.icon
  1527. }, null)])]
  1528. });
  1529. };
  1530. }
  1531. });
  1532. const VLigatureIcon = defineComponent({
  1533. name: 'VLigatureIcon',
  1534. props: makeIconProps(),
  1535. setup(props) {
  1536. return () => {
  1537. return vue.createVNode(props.tag, null, {
  1538. default: () => [props.icon]
  1539. });
  1540. };
  1541. }
  1542. });
  1543. const VClassIcon = defineComponent({
  1544. name: 'VClassIcon',
  1545. props: makeIconProps(),
  1546. setup(props) {
  1547. return () => {
  1548. return vue.createVNode(props.tag, {
  1549. "class": props.icon
  1550. }, null);
  1551. };
  1552. }
  1553. });
  1554. function genDefaults$3() {
  1555. return {
  1556. svg: {
  1557. component: VSvgIcon
  1558. },
  1559. class: {
  1560. component: VClassIcon
  1561. }
  1562. };
  1563. }
  1564. // Composables
  1565. function createIcons(options) {
  1566. const sets = genDefaults$3();
  1567. const defaultSet = options?.defaultSet ?? 'mdi';
  1568. if (defaultSet === 'mdi' && !sets.mdi) {
  1569. sets.mdi = mdi;
  1570. }
  1571. return mergeDeep({
  1572. defaultSet,
  1573. sets,
  1574. aliases: {
  1575. ...aliases,
  1576. /* eslint-disable max-len */
  1577. 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]],
  1578. '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',
  1579. 'vuetify-play': ['m6.376 13.184-4.11-7.192C1.505 4.66 2.467 3 4.003 3h8.532l-.953 1.576-.006.01-.396.677c-.429.732-.214 1.507.194 2.015.404.503 1.092.878 1.869.806a3.72 3.72 0 0 1 1.005.022c.276.053.434.143.523.237.138.146.38.635-.25 2.09-.893 1.63-1.553 1.722-1.847 1.677-.213-.033-.468-.158-.756-.406a4.95 4.95 0 0 1-.8-.927c-.39-.564-1.04-.84-1.66-.846-.625-.006-1.316.27-1.693.921l-.478.826-.911 1.506Z', ['M9.093 11.552c.046-.079.144-.15.32-.148a.53.53 0 0 1 .43.207c.285.414.636.847 1.046 1.2.405.35.914.662 1.516.754 1.334.205 2.502-.698 3.48-2.495l.014-.028.013-.03c.687-1.574.774-2.852-.005-3.675-.37-.391-.861-.586-1.333-.676a5.243 5.243 0 0 0-1.447-.044c-.173.016-.393-.073-.54-.257-.145-.18-.127-.316-.082-.392l.393-.672L14.287 3h5.71c1.536 0 2.499 1.659 1.737 2.992l-7.997 13.996c-.768 1.344-2.706 1.344-3.473 0l-3.037-5.314 1.377-2.278.004-.006.004-.007.481-.831Z', 0.6]]
  1580. /* eslint-enable max-len */
  1581. }
  1582. }, options);
  1583. }
  1584. const useIcon = props => {
  1585. const icons = vue.inject(IconSymbol);
  1586. if (!icons) throw new Error('Missing Vuetify Icons provide!');
  1587. const iconData = vue.computed(() => {
  1588. const iconAlias = vue.unref(props);
  1589. if (!iconAlias) return {
  1590. component: VComponentIcon
  1591. };
  1592. let icon = iconAlias;
  1593. if (typeof icon === 'string') {
  1594. icon = icon.trim();
  1595. if (icon.startsWith('$')) {
  1596. icon = icons.aliases?.[icon.slice(1)];
  1597. }
  1598. }
  1599. if (!icon) consoleWarn(`Could not find aliased icon "${iconAlias}"`);
  1600. if (Array.isArray(icon)) {
  1601. return {
  1602. component: VSvgIcon,
  1603. icon
  1604. };
  1605. } else if (typeof icon !== 'string') {
  1606. return {
  1607. component: VComponentIcon,
  1608. icon
  1609. };
  1610. }
  1611. const iconSetName = Object.keys(icons.sets).find(setName => typeof icon === 'string' && icon.startsWith(`${setName}:`));
  1612. const iconName = iconSetName ? icon.slice(iconSetName.length + 1) : icon;
  1613. const iconSet = icons.sets[iconSetName ?? icons.defaultSet];
  1614. return {
  1615. component: iconSet.component,
  1616. icon: iconName
  1617. };
  1618. });
  1619. return {
  1620. iconData
  1621. };
  1622. };
  1623. // Composables
  1624. // Types
  1625. const aliases = {
  1626. collapse: 'mdi-chevron-up',
  1627. complete: 'mdi-check',
  1628. cancel: 'mdi-close-circle',
  1629. close: 'mdi-close',
  1630. delete: 'mdi-close-circle',
  1631. // delete (e.g. v-chip close)
  1632. clear: 'mdi-close-circle',
  1633. success: 'mdi-check-circle',
  1634. info: 'mdi-information',
  1635. warning: 'mdi-alert-circle',
  1636. error: 'mdi-close-circle',
  1637. prev: 'mdi-chevron-left',
  1638. next: 'mdi-chevron-right',
  1639. checkboxOn: 'mdi-checkbox-marked',
  1640. checkboxOff: 'mdi-checkbox-blank-outline',
  1641. checkboxIndeterminate: 'mdi-minus-box',
  1642. delimiter: 'mdi-circle',
  1643. // for carousel
  1644. sortAsc: 'mdi-arrow-up',
  1645. sortDesc: 'mdi-arrow-down',
  1646. expand: 'mdi-chevron-down',
  1647. menu: 'mdi-menu',
  1648. subgroup: 'mdi-menu-down',
  1649. dropdown: 'mdi-menu-down',
  1650. radioOn: 'mdi-radiobox-marked',
  1651. radioOff: 'mdi-radiobox-blank',
  1652. edit: 'mdi-pencil',
  1653. ratingEmpty: 'mdi-star-outline',
  1654. ratingFull: 'mdi-star',
  1655. ratingHalf: 'mdi-star-half-full',
  1656. loading: 'mdi-cached',
  1657. first: 'mdi-page-first',
  1658. last: 'mdi-page-last',
  1659. unfold: 'mdi-unfold-more-horizontal',
  1660. file: 'mdi-paperclip',
  1661. plus: 'mdi-plus',
  1662. minus: 'mdi-minus',
  1663. calendar: 'mdi-calendar',
  1664. treeviewCollapse: 'mdi-menu-down',
  1665. treeviewExpand: 'mdi-menu-right',
  1666. eyeDropper: 'mdi-eyedropper',
  1667. upload: 'mdi-cloud-upload'
  1668. };
  1669. const mdi = {
  1670. // Not using mergeProps here, functional components merge props by default (?)
  1671. component: props => vue.h(VClassIcon, {
  1672. ...props,
  1673. class: 'mdi'
  1674. })
  1675. };
  1676. // Icons
  1677. // Types
  1678. const md1 = {
  1679. defaults: {
  1680. global: {
  1681. rounded: 'sm'
  1682. },
  1683. VAvatar: {
  1684. rounded: 'circle'
  1685. },
  1686. VAutocomplete: {
  1687. variant: 'underlined'
  1688. },
  1689. VBanner: {
  1690. color: 'primary'
  1691. },
  1692. VBtn: {
  1693. color: 'primary',
  1694. rounded: 0
  1695. },
  1696. VCheckbox: {
  1697. color: 'secondary'
  1698. },
  1699. VCombobox: {
  1700. variant: 'underlined'
  1701. },
  1702. VSelect: {
  1703. variant: 'underlined'
  1704. },
  1705. VSlider: {
  1706. color: 'primary'
  1707. },
  1708. VTabs: {
  1709. color: 'primary'
  1710. },
  1711. VTextarea: {
  1712. variant: 'underlined'
  1713. },
  1714. VTextField: {
  1715. variant: 'underlined'
  1716. },
  1717. VToolbar: {
  1718. VBtn: {
  1719. color: null
  1720. }
  1721. }
  1722. },
  1723. icons: {
  1724. defaultSet: 'mdi',
  1725. sets: {
  1726. mdi
  1727. }
  1728. },
  1729. theme: {
  1730. themes: {
  1731. light: {
  1732. colors: {
  1733. primary: '#3F51B5',
  1734. 'primary-darken-1': '#303F9F',
  1735. 'primary-lighten-1': '#C5CAE9',
  1736. secondary: '#FF4081',
  1737. 'secondary-darken-1': '#F50057',
  1738. 'secondary-lighten-1': '#FF80AB',
  1739. accent: '#009688'
  1740. }
  1741. }
  1742. }
  1743. }
  1744. };
  1745. // Icons
  1746. // Types
  1747. const md2 = {
  1748. defaults: {
  1749. global: {
  1750. rounded: 'md'
  1751. },
  1752. VAvatar: {
  1753. rounded: 'circle'
  1754. },
  1755. VAutocomplete: {
  1756. variant: 'filled'
  1757. },
  1758. VBanner: {
  1759. color: 'primary'
  1760. },
  1761. VBtn: {
  1762. color: 'primary'
  1763. },
  1764. VCheckbox: {
  1765. color: 'secondary'
  1766. },
  1767. VCombobox: {
  1768. variant: 'filled'
  1769. },
  1770. VSelect: {
  1771. variant: 'filled'
  1772. },
  1773. VSlider: {
  1774. color: 'primary'
  1775. },
  1776. VTabs: {
  1777. color: 'primary'
  1778. },
  1779. VTextarea: {
  1780. variant: 'filled'
  1781. },
  1782. VTextField: {
  1783. variant: 'filled'
  1784. },
  1785. VToolbar: {
  1786. VBtn: {
  1787. color: null
  1788. }
  1789. }
  1790. },
  1791. icons: {
  1792. defaultSet: 'mdi',
  1793. sets: {
  1794. mdi
  1795. }
  1796. },
  1797. theme: {
  1798. themes: {
  1799. light: {
  1800. colors: {
  1801. primary: '#6200EE',
  1802. 'primary-darken-1': '#3700B3',
  1803. secondary: '#03DAC6',
  1804. 'secondary-darken-1': '#018786',
  1805. error: '#B00020'
  1806. }
  1807. }
  1808. }
  1809. }
  1810. };
  1811. // Icons
  1812. // Types
  1813. const md3 = {
  1814. defaults: {
  1815. VAppBar: {
  1816. flat: true
  1817. },
  1818. VAutocomplete: {
  1819. variant: 'filled'
  1820. },
  1821. VBanner: {
  1822. color: 'primary'
  1823. },
  1824. VBottomSheet: {
  1825. contentClass: 'rounded-t-xl overflow-hidden'
  1826. },
  1827. VBtn: {
  1828. color: 'primary',
  1829. rounded: 'xl'
  1830. },
  1831. VBtnGroup: {
  1832. rounded: 'xl',
  1833. VBtn: {
  1834. rounded: null
  1835. }
  1836. },
  1837. VCard: {
  1838. rounded: 'lg'
  1839. },
  1840. VCheckbox: {
  1841. color: 'secondary',
  1842. inset: true
  1843. },
  1844. VChip: {
  1845. rounded: 'sm'
  1846. },
  1847. VCombobox: {
  1848. variant: 'filled'
  1849. },
  1850. VNavigationDrawer: {
  1851. // VList: {
  1852. // nav: true,
  1853. // VListItem: {
  1854. // rounded: 'xl',
  1855. // },
  1856. // },
  1857. },
  1858. VSelect: {
  1859. variant: 'filled'
  1860. },
  1861. VSlider: {
  1862. color: 'primary'
  1863. },
  1864. VTabs: {
  1865. color: 'primary'
  1866. },
  1867. VTextarea: {
  1868. variant: 'filled'
  1869. },
  1870. VTextField: {
  1871. variant: 'filled'
  1872. },
  1873. VToolbar: {
  1874. VBtn: {
  1875. color: null
  1876. }
  1877. }
  1878. },
  1879. icons: {
  1880. defaultSet: 'mdi',
  1881. sets: {
  1882. mdi
  1883. }
  1884. },
  1885. theme: {
  1886. themes: {
  1887. light: {
  1888. colors: {
  1889. primary: '#6750a4',
  1890. secondary: '#b4b0bb',
  1891. tertiary: '#7d5260',
  1892. error: '#b3261e',
  1893. surface: '#fffbfe'
  1894. }
  1895. }
  1896. }
  1897. }
  1898. };
  1899. var index = /*#__PURE__*/Object.freeze({
  1900. __proto__: null,
  1901. md1: md1,
  1902. md2: md2,
  1903. md3: md3
  1904. });
  1905. // Utilities
  1906. // Types
  1907. function useResizeObserver(callback) {
  1908. let box = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 'content';
  1909. const resizeRef = templateRef();
  1910. const contentRect = vue.ref();
  1911. if (IN_BROWSER) {
  1912. const observer = new ResizeObserver(entries => {
  1913. callback?.(entries, observer);
  1914. if (!entries.length) return;
  1915. if (box === 'content') {
  1916. contentRect.value = entries[0].contentRect;
  1917. } else {
  1918. contentRect.value = entries[0].target.getBoundingClientRect();
  1919. }
  1920. });
  1921. vue.onBeforeUnmount(() => {
  1922. observer.disconnect();
  1923. });
  1924. vue.watch(() => resizeRef.el, (newValue, oldValue) => {
  1925. if (oldValue) {
  1926. observer.unobserve(oldValue);
  1927. contentRect.value = undefined;
  1928. }
  1929. if (newValue) observer.observe(newValue);
  1930. }, {
  1931. flush: 'post'
  1932. });
  1933. }
  1934. return {
  1935. resizeRef,
  1936. contentRect: vue.readonly(contentRect)
  1937. };
  1938. }
  1939. // Composables
  1940. // Types
  1941. const VuetifyLayoutKey = Symbol.for('vuetify:layout');
  1942. const VuetifyLayoutItemKey = Symbol.for('vuetify:layout-item');
  1943. const ROOT_ZINDEX = 1000;
  1944. const makeLayoutProps = propsFactory({
  1945. overlaps: {
  1946. type: Array,
  1947. default: () => []
  1948. },
  1949. fullHeight: Boolean
  1950. }, 'layout');
  1951. // Composables
  1952. const makeLayoutItemProps = propsFactory({
  1953. name: {
  1954. type: String
  1955. },
  1956. order: {
  1957. type: [Number, String],
  1958. default: 0
  1959. },
  1960. absolute: Boolean
  1961. }, 'layout-item');
  1962. function useLayout() {
  1963. const layout = vue.inject(VuetifyLayoutKey);
  1964. if (!layout) throw new Error('[Vuetify] Could not find injected layout');
  1965. return {
  1966. getLayoutItem: layout.getLayoutItem,
  1967. mainRect: layout.mainRect,
  1968. mainStyles: layout.mainStyles
  1969. };
  1970. }
  1971. function useLayoutItem(options) {
  1972. const layout = vue.inject(VuetifyLayoutKey);
  1973. if (!layout) throw new Error('[Vuetify] Could not find injected layout');
  1974. const id = options.id ?? `layout-item-${getUid()}`;
  1975. const vm = getCurrentInstance('useLayoutItem');
  1976. vue.provide(VuetifyLayoutItemKey, {
  1977. id
  1978. });
  1979. const isKeptAlive = vue.shallowRef(false);
  1980. vue.onDeactivated(() => isKeptAlive.value = true);
  1981. vue.onActivated(() => isKeptAlive.value = false);
  1982. const {
  1983. layoutItemStyles,
  1984. layoutItemScrimStyles
  1985. } = layout.register(vm, {
  1986. ...options,
  1987. active: vue.computed(() => isKeptAlive.value ? false : options.active.value),
  1988. id
  1989. });
  1990. vue.onBeforeUnmount(() => layout.unregister(id));
  1991. return {
  1992. layoutItemStyles,
  1993. layoutRect: layout.layoutRect,
  1994. layoutItemScrimStyles
  1995. };
  1996. }
  1997. const generateLayers = (layout, positions, layoutSizes, activeItems) => {
  1998. let previousLayer = {
  1999. top: 0,
  2000. left: 0,
  2001. right: 0,
  2002. bottom: 0
  2003. };
  2004. const layers = [{
  2005. id: '',
  2006. layer: {
  2007. ...previousLayer
  2008. }
  2009. }];
  2010. for (const id of layout) {
  2011. const position = positions.get(id);
  2012. const amount = layoutSizes.get(id);
  2013. const active = activeItems.get(id);
  2014. if (!position || !amount || !active) continue;
  2015. const layer = {
  2016. ...previousLayer,
  2017. [position.value]: parseInt(previousLayer[position.value], 10) + (active.value ? parseInt(amount.value, 10) : 0)
  2018. };
  2019. layers.push({
  2020. id,
  2021. layer
  2022. });
  2023. previousLayer = layer;
  2024. }
  2025. return layers;
  2026. };
  2027. function createLayout(props) {
  2028. const parentLayout = vue.inject(VuetifyLayoutKey, null);
  2029. const rootZIndex = vue.computed(() => parentLayout ? parentLayout.rootZIndex.value - 100 : ROOT_ZINDEX);
  2030. const registered = vue.ref([]);
  2031. const positions = vue.reactive(new Map());
  2032. const layoutSizes = vue.reactive(new Map());
  2033. const priorities = vue.reactive(new Map());
  2034. const activeItems = vue.reactive(new Map());
  2035. const disabledTransitions = vue.reactive(new Map());
  2036. const {
  2037. resizeRef,
  2038. contentRect: layoutRect
  2039. } = useResizeObserver();
  2040. const computedOverlaps = vue.computed(() => {
  2041. const map = new Map();
  2042. const overlaps = props.overlaps ?? [];
  2043. for (const overlap of overlaps.filter(item => item.includes(':'))) {
  2044. const [top, bottom] = overlap.split(':');
  2045. if (!registered.value.includes(top) || !registered.value.includes(bottom)) continue;
  2046. const topPosition = positions.get(top);
  2047. const bottomPosition = positions.get(bottom);
  2048. const topAmount = layoutSizes.get(top);
  2049. const bottomAmount = layoutSizes.get(bottom);
  2050. if (!topPosition || !bottomPosition || !topAmount || !bottomAmount) continue;
  2051. map.set(bottom, {
  2052. position: topPosition.value,
  2053. amount: parseInt(topAmount.value, 10)
  2054. });
  2055. map.set(top, {
  2056. position: bottomPosition.value,
  2057. amount: -parseInt(bottomAmount.value, 10)
  2058. });
  2059. }
  2060. return map;
  2061. });
  2062. const layers = vue.computed(() => {
  2063. const uniquePriorities = [...new Set([...priorities.values()].map(p => p.value))].sort((a, b) => a - b);
  2064. const layout = [];
  2065. for (const p of uniquePriorities) {
  2066. const items = registered.value.filter(id => priorities.get(id)?.value === p);
  2067. layout.push(...items);
  2068. }
  2069. return generateLayers(layout, positions, layoutSizes, activeItems);
  2070. });
  2071. const transitionsEnabled = vue.computed(() => {
  2072. return !Array.from(disabledTransitions.values()).some(ref => ref.value);
  2073. });
  2074. const mainRect = vue.computed(() => {
  2075. return layers.value[layers.value.length - 1].layer;
  2076. });
  2077. const mainStyles = vue.computed(() => {
  2078. return {
  2079. '--v-layout-left': convertToUnit(mainRect.value.left),
  2080. '--v-layout-right': convertToUnit(mainRect.value.right),
  2081. '--v-layout-top': convertToUnit(mainRect.value.top),
  2082. '--v-layout-bottom': convertToUnit(mainRect.value.bottom),
  2083. ...(transitionsEnabled.value ? undefined : {
  2084. transition: 'none'
  2085. })
  2086. };
  2087. });
  2088. const items = vue.computed(() => {
  2089. return layers.value.slice(1).map((_ref, index) => {
  2090. let {
  2091. id
  2092. } = _ref;
  2093. const {
  2094. layer
  2095. } = layers.value[index];
  2096. const size = layoutSizes.get(id);
  2097. const position = positions.get(id);
  2098. return {
  2099. id,
  2100. ...layer,
  2101. size: Number(size.value),
  2102. position: position.value
  2103. };
  2104. });
  2105. });
  2106. const getLayoutItem = id => {
  2107. return items.value.find(item => item.id === id);
  2108. };
  2109. const rootVm = getCurrentInstance('createLayout');
  2110. const isMounted = vue.shallowRef(false);
  2111. vue.onMounted(() => {
  2112. isMounted.value = true;
  2113. });
  2114. vue.provide(VuetifyLayoutKey, {
  2115. register: (vm, _ref2) => {
  2116. let {
  2117. id,
  2118. order,
  2119. position,
  2120. layoutSize,
  2121. elementSize,
  2122. active,
  2123. disableTransitions,
  2124. absolute
  2125. } = _ref2;
  2126. priorities.set(id, order);
  2127. positions.set(id, position);
  2128. layoutSizes.set(id, layoutSize);
  2129. activeItems.set(id, active);
  2130. disableTransitions && disabledTransitions.set(id, disableTransitions);
  2131. const instances = findChildrenWithProvide(VuetifyLayoutItemKey, rootVm?.vnode);
  2132. const instanceIndex = instances.indexOf(vm);
  2133. if (instanceIndex > -1) registered.value.splice(instanceIndex, 0, id);else registered.value.push(id);
  2134. const index = vue.computed(() => items.value.findIndex(i => i.id === id));
  2135. const zIndex = vue.computed(() => rootZIndex.value + layers.value.length * 2 - index.value * 2);
  2136. const layoutItemStyles = vue.computed(() => {
  2137. const isHorizontal = position.value === 'left' || position.value === 'right';
  2138. const isOppositeHorizontal = position.value === 'right';
  2139. const isOppositeVertical = position.value === 'bottom';
  2140. const size = elementSize.value ?? layoutSize.value;
  2141. const unit = size === 0 ? '%' : 'px';
  2142. const styles = {
  2143. [position.value]: 0,
  2144. zIndex: zIndex.value,
  2145. transform: `translate${isHorizontal ? 'X' : 'Y'}(${(active.value ? 0 : -(size === 0 ? 100 : size)) * (isOppositeHorizontal || isOppositeVertical ? -1 : 1)}${unit})`,
  2146. position: absolute.value || rootZIndex.value !== ROOT_ZINDEX ? 'absolute' : 'fixed',
  2147. ...(transitionsEnabled.value ? undefined : {
  2148. transition: 'none'
  2149. })
  2150. };
  2151. if (!isMounted.value) return styles;
  2152. const item = items.value[index.value];
  2153. if (!item) throw new Error(`[Vuetify] Could not find layout item "${id}"`);
  2154. const overlap = computedOverlaps.value.get(id);
  2155. if (overlap) {
  2156. item[overlap.position] += overlap.amount;
  2157. }
  2158. return {
  2159. ...styles,
  2160. height: isHorizontal ? `calc(100% - ${item.top}px - ${item.bottom}px)` : elementSize.value ? `${elementSize.value}px` : undefined,
  2161. left: isOppositeHorizontal ? undefined : `${item.left}px`,
  2162. right: isOppositeHorizontal ? `${item.right}px` : undefined,
  2163. top: position.value !== 'bottom' ? `${item.top}px` : undefined,
  2164. bottom: position.value !== 'top' ? `${item.bottom}px` : undefined,
  2165. width: !isHorizontal ? `calc(100% - ${item.left}px - ${item.right}px)` : elementSize.value ? `${elementSize.value}px` : undefined
  2166. };
  2167. });
  2168. const layoutItemScrimStyles = vue.computed(() => ({
  2169. zIndex: zIndex.value - 1
  2170. }));
  2171. return {
  2172. layoutItemStyles,
  2173. layoutItemScrimStyles,
  2174. zIndex
  2175. };
  2176. },
  2177. unregister: id => {
  2178. priorities.delete(id);
  2179. positions.delete(id);
  2180. layoutSizes.delete(id);
  2181. activeItems.delete(id);
  2182. disabledTransitions.delete(id);
  2183. registered.value = registered.value.filter(v => v !== id);
  2184. },
  2185. mainRect,
  2186. mainStyles,
  2187. getLayoutItem,
  2188. items,
  2189. layoutRect,
  2190. rootZIndex
  2191. });
  2192. const layoutClasses = vue.computed(() => ['v-layout', {
  2193. 'v-layout--full-height': props.fullHeight
  2194. }]);
  2195. const layoutStyles = vue.computed(() => ({
  2196. zIndex: parentLayout ? rootZIndex.value : undefined,
  2197. position: parentLayout ? 'relative' : undefined,
  2198. overflow: parentLayout ? 'hidden' : undefined
  2199. }));
  2200. return {
  2201. layoutClasses,
  2202. layoutStyles,
  2203. getLayoutItem,
  2204. items,
  2205. layoutRect,
  2206. layoutRef: resizeRef
  2207. };
  2208. }
  2209. // Utilities
  2210. // Types
  2211. function useToggleScope(source, fn) {
  2212. let scope;
  2213. function start() {
  2214. scope = vue.effectScope();
  2215. scope.run(() => fn.length ? fn(() => {
  2216. scope?.stop();
  2217. start();
  2218. }) : fn());
  2219. }
  2220. vue.watch(source, active => {
  2221. if (active && !scope) {
  2222. start();
  2223. } else if (!active) {
  2224. scope?.stop();
  2225. scope = undefined;
  2226. }
  2227. }, {
  2228. immediate: true
  2229. });
  2230. vue.onScopeDispose(() => {
  2231. scope?.stop();
  2232. });
  2233. }
  2234. // Composables
  2235. // Types
  2236. // Composables
  2237. function useProxiedModel(props, prop, defaultValue) {
  2238. let transformIn = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : v => v;
  2239. let transformOut = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : v => v;
  2240. const vm = getCurrentInstance('useProxiedModel');
  2241. const internal = vue.ref(props[prop] !== undefined ? props[prop] : defaultValue);
  2242. const kebabProp = toKebabCase(prop);
  2243. const checkKebab = kebabProp !== prop;
  2244. const isControlled = checkKebab ? vue.computed(() => {
  2245. void props[prop];
  2246. return !!((vm.vnode.props?.hasOwnProperty(prop) || vm.vnode.props?.hasOwnProperty(kebabProp)) && (vm.vnode.props?.hasOwnProperty(`onUpdate:${prop}`) || vm.vnode.props?.hasOwnProperty(`onUpdate:${kebabProp}`)));
  2247. }) : vue.computed(() => {
  2248. void props[prop];
  2249. return !!(vm.vnode.props?.hasOwnProperty(prop) && vm.vnode.props?.hasOwnProperty(`onUpdate:${prop}`));
  2250. });
  2251. useToggleScope(() => !isControlled.value, () => {
  2252. vue.watch(() => props[prop], val => {
  2253. internal.value = val;
  2254. });
  2255. });
  2256. const model = vue.computed({
  2257. get() {
  2258. const externalValue = props[prop];
  2259. return transformIn(isControlled.value ? externalValue : internal.value);
  2260. },
  2261. set(internalValue) {
  2262. const newValue = transformOut(internalValue);
  2263. const value = vue.toRaw(isControlled.value ? props[prop] : internal.value);
  2264. if (value === newValue || transformIn(value) === internalValue) {
  2265. return;
  2266. }
  2267. internal.value = newValue;
  2268. vm?.emit(`update:${prop}`, newValue);
  2269. }
  2270. });
  2271. Object.defineProperty(model, 'externalValue', {
  2272. get: () => isControlled.value ? props[prop] : internal.value
  2273. });
  2274. return model;
  2275. }
  2276. var en = {
  2277. badge: 'Badge',
  2278. open: 'Open',
  2279. close: 'Close',
  2280. dismiss: 'Dismiss',
  2281. confirmEdit: {
  2282. ok: 'OK',
  2283. cancel: 'Cancel'
  2284. },
  2285. dataIterator: {
  2286. noResultsText: 'No matching records found',
  2287. loadingText: 'Loading items...'
  2288. },
  2289. dataTable: {
  2290. itemsPerPageText: 'Rows per page:',
  2291. ariaLabel: {
  2292. sortDescending: 'Sorted descending.',
  2293. sortAscending: 'Sorted ascending.',
  2294. sortNone: 'Not sorted.',
  2295. activateNone: 'Activate to remove sorting.',
  2296. activateDescending: 'Activate to sort descending.',
  2297. activateAscending: 'Activate to sort ascending.'
  2298. },
  2299. sortBy: 'Sort by'
  2300. },
  2301. dataFooter: {
  2302. itemsPerPageText: 'Items per page:',
  2303. itemsPerPageAll: 'All',
  2304. nextPage: 'Next page',
  2305. prevPage: 'Previous page',
  2306. firstPage: 'First page',
  2307. lastPage: 'Last page',
  2308. pageText: '{0}-{1} of {2}'
  2309. },
  2310. dateRangeInput: {
  2311. divider: 'to'
  2312. },
  2313. datePicker: {
  2314. itemsSelected: '{0} selected',
  2315. range: {
  2316. title: 'Select dates',
  2317. header: 'Enter dates'
  2318. },
  2319. title: 'Select date',
  2320. header: 'Enter date',
  2321. input: {
  2322. placeholder: 'Enter date'
  2323. }
  2324. },
  2325. noDataText: 'No data available',
  2326. carousel: {
  2327. prev: 'Previous visual',
  2328. next: 'Next visual',
  2329. ariaLabel: {
  2330. delimiter: 'Carousel slide {0} of {1}'
  2331. }
  2332. },
  2333. calendar: {
  2334. moreEvents: '{0} more',
  2335. today: 'Today'
  2336. },
  2337. input: {
  2338. clear: 'Clear {0}',
  2339. prependAction: '{0} prepended action',
  2340. appendAction: '{0} appended action',
  2341. otp: 'Please enter OTP character {0}'
  2342. },
  2343. fileInput: {
  2344. counter: '{0} files',
  2345. counterSize: '{0} files ({1} in total)'
  2346. },
  2347. fileUpload: {
  2348. title: 'Drag and drop files here',
  2349. divider: 'or',
  2350. browse: 'Browse Files'
  2351. },
  2352. timePicker: {
  2353. am: 'AM',
  2354. pm: 'PM',
  2355. title: 'Select Time'
  2356. },
  2357. pagination: {
  2358. ariaLabel: {
  2359. root: 'Pagination Navigation',
  2360. next: 'Next page',
  2361. previous: 'Previous page',
  2362. page: 'Go to page {0}',
  2363. currentPage: 'Page {0}, Current page',
  2364. first: 'First page',
  2365. last: 'Last page'
  2366. }
  2367. },
  2368. stepper: {
  2369. next: 'Next',
  2370. prev: 'Previous'
  2371. },
  2372. rating: {
  2373. ariaLabel: {
  2374. item: 'Rating {0} of {1}'
  2375. }
  2376. },
  2377. loading: 'Loading...',
  2378. infiniteScroll: {
  2379. loadMore: 'Load more',
  2380. empty: 'No more'
  2381. }
  2382. };
  2383. // Composables
  2384. // Types
  2385. const LANG_PREFIX = '$vuetify.';
  2386. const replace = (str, params) => {
  2387. return str.replace(/\{(\d+)\}/g, (match, index) => {
  2388. return String(params[+index]);
  2389. });
  2390. };
  2391. const createTranslateFunction = (current, fallback, messages) => {
  2392. return function (key) {
  2393. for (var _len = arguments.length, params = new Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) {
  2394. params[_key - 1] = arguments[_key];
  2395. }
  2396. if (!key.startsWith(LANG_PREFIX)) {
  2397. return replace(key, params);
  2398. }
  2399. const shortKey = key.replace(LANG_PREFIX, '');
  2400. const currentLocale = current.value && messages.value[current.value];
  2401. const fallbackLocale = fallback.value && messages.value[fallback.value];
  2402. let str = getObjectValueByPath(currentLocale, shortKey, null);
  2403. if (!str) {
  2404. consoleWarn(`Translation key "${key}" not found in "${current.value}", trying fallback locale`);
  2405. str = getObjectValueByPath(fallbackLocale, shortKey, null);
  2406. }
  2407. if (!str) {
  2408. consoleError(`Translation key "${key}" not found in fallback`);
  2409. str = key;
  2410. }
  2411. if (typeof str !== 'string') {
  2412. consoleError(`Translation key "${key}" has a non-string value`);
  2413. str = key;
  2414. }
  2415. return replace(str, params);
  2416. };
  2417. };
  2418. function createNumberFunction(current, fallback) {
  2419. return (value, options) => {
  2420. const numberFormat = new Intl.NumberFormat([current.value, fallback.value], options);
  2421. return numberFormat.format(value);
  2422. };
  2423. }
  2424. function useProvided(props, prop, provided) {
  2425. const internal = useProxiedModel(props, prop, props[prop] ?? provided.value);
  2426. // TODO: Remove when defaultValue works
  2427. internal.value = props[prop] ?? provided.value;
  2428. vue.watch(provided, v => {
  2429. if (props[prop] == null) {
  2430. internal.value = provided.value;
  2431. }
  2432. });
  2433. return internal;
  2434. }
  2435. function createProvideFunction(state) {
  2436. return props => {
  2437. const current = useProvided(props, 'locale', state.current);
  2438. const fallback = useProvided(props, 'fallback', state.fallback);
  2439. const messages = useProvided(props, 'messages', state.messages);
  2440. return {
  2441. name: 'vuetify',
  2442. current,
  2443. fallback,
  2444. messages,
  2445. t: createTranslateFunction(current, fallback, messages),
  2446. n: createNumberFunction(current, fallback),
  2447. provide: createProvideFunction({
  2448. current,
  2449. fallback,
  2450. messages
  2451. })
  2452. };
  2453. };
  2454. }
  2455. function createVuetifyAdapter(options) {
  2456. const current = vue.shallowRef(options?.locale ?? 'en');
  2457. const fallback = vue.shallowRef(options?.fallback ?? 'en');
  2458. const messages = vue.ref({
  2459. en,
  2460. ...options?.messages
  2461. });
  2462. return {
  2463. name: 'vuetify',
  2464. current,
  2465. fallback,
  2466. messages,
  2467. t: createTranslateFunction(current, fallback, messages),
  2468. n: createNumberFunction(current, fallback),
  2469. provide: createProvideFunction({
  2470. current,
  2471. fallback,
  2472. messages
  2473. })
  2474. };
  2475. }
  2476. // Utilities
  2477. // Types
  2478. const LocaleSymbol = Symbol.for('vuetify:locale');
  2479. function isLocaleInstance(obj) {
  2480. return obj.name != null;
  2481. }
  2482. function createLocale(options) {
  2483. const i18n = options?.adapter && isLocaleInstance(options?.adapter) ? options?.adapter : createVuetifyAdapter(options);
  2484. const rtl = createRtl(i18n, options);
  2485. return {
  2486. ...i18n,
  2487. ...rtl
  2488. };
  2489. }
  2490. function useLocale() {
  2491. const locale = vue.inject(LocaleSymbol);
  2492. if (!locale) throw new Error('[Vuetify] Could not find injected locale instance');
  2493. return locale;
  2494. }
  2495. function provideLocale(props) {
  2496. const locale = vue.inject(LocaleSymbol);
  2497. if (!locale) throw new Error('[Vuetify] Could not find injected locale instance');
  2498. const i18n = locale.provide(props);
  2499. const rtl = provideRtl(i18n, locale.rtl, props);
  2500. const data = {
  2501. ...i18n,
  2502. ...rtl
  2503. };
  2504. vue.provide(LocaleSymbol, data);
  2505. return data;
  2506. }
  2507. function genDefaults$2() {
  2508. return {
  2509. af: false,
  2510. ar: true,
  2511. bg: false,
  2512. ca: false,
  2513. ckb: false,
  2514. cs: false,
  2515. de: false,
  2516. el: false,
  2517. en: false,
  2518. es: false,
  2519. et: false,
  2520. fa: true,
  2521. fi: false,
  2522. fr: false,
  2523. hr: false,
  2524. hu: false,
  2525. he: true,
  2526. id: false,
  2527. it: false,
  2528. ja: false,
  2529. km: false,
  2530. ko: false,
  2531. lv: false,
  2532. lt: false,
  2533. nl: false,
  2534. no: false,
  2535. pl: false,
  2536. pt: false,
  2537. ro: false,
  2538. ru: false,
  2539. sk: false,
  2540. sl: false,
  2541. srCyrl: false,
  2542. srLatn: false,
  2543. sv: false,
  2544. th: false,
  2545. tr: false,
  2546. az: false,
  2547. uk: false,
  2548. vi: false,
  2549. zhHans: false,
  2550. zhHant: false
  2551. };
  2552. }
  2553. function createRtl(i18n, options) {
  2554. const rtl = vue.ref(options?.rtl ?? genDefaults$2());
  2555. const isRtl = vue.computed(() => rtl.value[i18n.current.value] ?? false);
  2556. return {
  2557. isRtl,
  2558. rtl,
  2559. rtlClasses: vue.computed(() => `v-locale--is-${isRtl.value ? 'rtl' : 'ltr'}`)
  2560. };
  2561. }
  2562. function provideRtl(locale, rtl, props) {
  2563. const isRtl = vue.computed(() => props.rtl ?? rtl.value[locale.current.value] ?? false);
  2564. return {
  2565. isRtl,
  2566. rtl,
  2567. rtlClasses: vue.computed(() => `v-locale--is-${isRtl.value ? 'rtl' : 'ltr'}`)
  2568. };
  2569. }
  2570. function useRtl() {
  2571. const locale = vue.inject(LocaleSymbol);
  2572. if (!locale) throw new Error('[Vuetify] Could not find injected rtl instance');
  2573. return {
  2574. isRtl: locale.isRtl,
  2575. rtlClasses: locale.rtlClasses
  2576. };
  2577. }
  2578. // Utilities
  2579. // Types
  2580. const ThemeSymbol = Symbol.for('vuetify:theme');
  2581. const makeThemeProps = propsFactory({
  2582. theme: String
  2583. }, 'theme');
  2584. function genDefaults$1() {
  2585. return {
  2586. defaultTheme: 'light',
  2587. variations: {
  2588. colors: [],
  2589. lighten: 0,
  2590. darken: 0
  2591. },
  2592. themes: {
  2593. light: {
  2594. dark: false,
  2595. colors: {
  2596. background: '#FFFFFF',
  2597. surface: '#FFFFFF',
  2598. 'surface-bright': '#FFFFFF',
  2599. 'surface-light': '#EEEEEE',
  2600. 'surface-variant': '#424242',
  2601. 'on-surface-variant': '#EEEEEE',
  2602. primary: '#1867C0',
  2603. 'primary-darken-1': '#1F5592',
  2604. secondary: '#48A9A6',
  2605. 'secondary-darken-1': '#018786',
  2606. error: '#B00020',
  2607. info: '#2196F3',
  2608. success: '#4CAF50',
  2609. warning: '#FB8C00'
  2610. },
  2611. variables: {
  2612. 'border-color': '#000000',
  2613. 'border-opacity': 0.12,
  2614. 'high-emphasis-opacity': 0.87,
  2615. 'medium-emphasis-opacity': 0.60,
  2616. 'disabled-opacity': 0.38,
  2617. 'idle-opacity': 0.04,
  2618. 'hover-opacity': 0.04,
  2619. 'focus-opacity': 0.12,
  2620. 'selected-opacity': 0.08,
  2621. 'activated-opacity': 0.12,
  2622. 'pressed-opacity': 0.12,
  2623. 'dragged-opacity': 0.08,
  2624. 'theme-kbd': '#212529',
  2625. 'theme-on-kbd': '#FFFFFF',
  2626. 'theme-code': '#F5F5F5',
  2627. 'theme-on-code': '#000000'
  2628. }
  2629. },
  2630. dark: {
  2631. dark: true,
  2632. colors: {
  2633. background: '#121212',
  2634. surface: '#212121',
  2635. 'surface-bright': '#ccbfd6',
  2636. 'surface-light': '#424242',
  2637. 'surface-variant': '#a3a3a3',
  2638. 'on-surface-variant': '#424242',
  2639. primary: '#2196F3',
  2640. 'primary-darken-1': '#277CC1',
  2641. secondary: '#54B6B2',
  2642. 'secondary-darken-1': '#48A9A6',
  2643. error: '#CF6679',
  2644. info: '#2196F3',
  2645. success: '#4CAF50',
  2646. warning: '#FB8C00'
  2647. },
  2648. variables: {
  2649. 'border-color': '#FFFFFF',
  2650. 'border-opacity': 0.12,
  2651. 'high-emphasis-opacity': 1,
  2652. 'medium-emphasis-opacity': 0.70,
  2653. 'disabled-opacity': 0.50,
  2654. 'idle-opacity': 0.10,
  2655. 'hover-opacity': 0.04,
  2656. 'focus-opacity': 0.12,
  2657. 'selected-opacity': 0.08,
  2658. 'activated-opacity': 0.12,
  2659. 'pressed-opacity': 0.16,
  2660. 'dragged-opacity': 0.08,
  2661. 'theme-kbd': '#212529',
  2662. 'theme-on-kbd': '#FFFFFF',
  2663. 'theme-code': '#343434',
  2664. 'theme-on-code': '#CCCCCC'
  2665. }
  2666. }
  2667. }
  2668. };
  2669. }
  2670. function parseThemeOptions() {
  2671. let options = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : genDefaults$1();
  2672. const defaults = genDefaults$1();
  2673. if (!options) return {
  2674. ...defaults,
  2675. isDisabled: true
  2676. };
  2677. const themes = {};
  2678. for (const [key, theme] of Object.entries(options.themes ?? {})) {
  2679. const defaultTheme = theme.dark || key === 'dark' ? defaults.themes?.dark : defaults.themes?.light;
  2680. themes[key] = mergeDeep(defaultTheme, theme);
  2681. }
  2682. return mergeDeep(defaults, {
  2683. ...options,
  2684. themes
  2685. });
  2686. }
  2687. // Composables
  2688. function createTheme(options) {
  2689. const parsedOptions = parseThemeOptions(options);
  2690. const name = vue.ref(parsedOptions.defaultTheme);
  2691. const themes = vue.ref(parsedOptions.themes);
  2692. const computedThemes = vue.computed(() => {
  2693. const acc = {};
  2694. for (const [name, original] of Object.entries(themes.value)) {
  2695. const theme = acc[name] = {
  2696. ...original,
  2697. colors: {
  2698. ...original.colors
  2699. }
  2700. };
  2701. if (parsedOptions.variations) {
  2702. for (const name of parsedOptions.variations.colors) {
  2703. const color = theme.colors[name];
  2704. if (!color) continue;
  2705. for (const variation of ['lighten', 'darken']) {
  2706. const fn = variation === 'lighten' ? lighten : darken;
  2707. for (const amount of createRange(parsedOptions.variations[variation], 1)) {
  2708. theme.colors[`${name}-${variation}-${amount}`] = RGBtoHex(fn(parseColor(color), amount));
  2709. }
  2710. }
  2711. }
  2712. }
  2713. for (const color of Object.keys(theme.colors)) {
  2714. if (/^on-[a-z]/.test(color) || theme.colors[`on-${color}`]) continue;
  2715. const onColor = `on-${color}`;
  2716. const colorVal = parseColor(theme.colors[color]);
  2717. theme.colors[onColor] = getForeground(colorVal);
  2718. }
  2719. }
  2720. return acc;
  2721. });
  2722. const current = vue.computed(() => computedThemes.value[name.value]);
  2723. const styles = vue.computed(() => {
  2724. const lines = [];
  2725. if (current.value?.dark) {
  2726. createCssClass(lines, ':root', ['color-scheme: dark']);
  2727. }
  2728. createCssClass(lines, ':root', genCssVariables(current.value));
  2729. for (const [themeName, theme] of Object.entries(computedThemes.value)) {
  2730. createCssClass(lines, `.v-theme--${themeName}`, [`color-scheme: ${theme.dark ? 'dark' : 'normal'}`, ...genCssVariables(theme)]);
  2731. }
  2732. const bgLines = [];
  2733. const fgLines = [];
  2734. const colors = new Set(Object.values(computedThemes.value).flatMap(theme => Object.keys(theme.colors)));
  2735. for (const key of colors) {
  2736. if (/^on-[a-z]/.test(key)) {
  2737. createCssClass(fgLines, `.${key}`, [`color: rgb(var(--v-theme-${key})) !important`]);
  2738. } else {
  2739. 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`]);
  2740. createCssClass(fgLines, `.text-${key}`, [`color: rgb(var(--v-theme-${key})) !important`]);
  2741. createCssClass(fgLines, `.border-${key}`, [`--v-border-color: var(--v-theme-${key})`]);
  2742. }
  2743. }
  2744. lines.push(...bgLines, ...fgLines);
  2745. return lines.map((str, i) => i === 0 ? str : ` ${str}`).join('');
  2746. });
  2747. function getHead() {
  2748. return {
  2749. style: [{
  2750. children: styles.value,
  2751. id: 'vuetify-theme-stylesheet',
  2752. nonce: parsedOptions.cspNonce || false
  2753. }]
  2754. };
  2755. }
  2756. function install(app) {
  2757. if (parsedOptions.isDisabled) return;
  2758. const head = app._context.provides.usehead;
  2759. if (head) {
  2760. if (head.push) {
  2761. const entry = head.push(getHead);
  2762. if (IN_BROWSER) {
  2763. vue.watch(styles, () => {
  2764. entry.patch(getHead);
  2765. });
  2766. }
  2767. } else {
  2768. if (IN_BROWSER) {
  2769. head.addHeadObjs(vue.computed(getHead));
  2770. vue.watchEffect(() => head.updateDOM());
  2771. } else {
  2772. head.addHeadObjs(getHead());
  2773. }
  2774. }
  2775. } else {
  2776. let styleEl = IN_BROWSER ? document.getElementById('vuetify-theme-stylesheet') : null;
  2777. if (IN_BROWSER) {
  2778. vue.watch(styles, updateStyles, {
  2779. immediate: true
  2780. });
  2781. } else {
  2782. updateStyles();
  2783. }
  2784. function updateStyles() {
  2785. if (typeof document !== 'undefined' && !styleEl) {
  2786. const el = document.createElement('style');
  2787. el.type = 'text/css';
  2788. el.id = 'vuetify-theme-stylesheet';
  2789. if (parsedOptions.cspNonce) el.setAttribute('nonce', parsedOptions.cspNonce);
  2790. styleEl = el;
  2791. document.head.appendChild(styleEl);
  2792. }
  2793. if (styleEl) styleEl.innerHTML = styles.value;
  2794. }
  2795. }
  2796. }
  2797. const themeClasses = vue.computed(() => parsedOptions.isDisabled ? undefined : `v-theme--${name.value}`);
  2798. return {
  2799. install,
  2800. isDisabled: parsedOptions.isDisabled,
  2801. name,
  2802. themes,
  2803. current,
  2804. computedThemes,
  2805. themeClasses,
  2806. styles,
  2807. global: {
  2808. name,
  2809. current
  2810. }
  2811. };
  2812. }
  2813. function provideTheme(props) {
  2814. getCurrentInstance('provideTheme');
  2815. const theme = vue.inject(ThemeSymbol, null);
  2816. if (!theme) throw new Error('Could not find Vuetify theme injection');
  2817. const name = vue.computed(() => {
  2818. return props.theme ?? theme.name.value;
  2819. });
  2820. const current = vue.computed(() => theme.themes.value[name.value]);
  2821. const themeClasses = vue.computed(() => theme.isDisabled ? undefined : `v-theme--${name.value}`);
  2822. const newTheme = {
  2823. ...theme,
  2824. name,
  2825. current,
  2826. themeClasses
  2827. };
  2828. vue.provide(ThemeSymbol, newTheme);
  2829. return newTheme;
  2830. }
  2831. function useTheme() {
  2832. getCurrentInstance('useTheme');
  2833. const theme = vue.inject(ThemeSymbol, null);
  2834. if (!theme) throw new Error('Could not find Vuetify theme injection');
  2835. return theme;
  2836. }
  2837. function createCssClass(lines, selector, content) {
  2838. lines.push(`${selector} {\n`, ...content.map(line => ` ${line};\n`), '}\n');
  2839. }
  2840. function genCssVariables(theme) {
  2841. const lightOverlay = theme.dark ? 2 : 1;
  2842. const darkOverlay = theme.dark ? 1 : 2;
  2843. const variables = [];
  2844. for (const [key, value] of Object.entries(theme.colors)) {
  2845. const rgb = parseColor(value);
  2846. variables.push(`--v-theme-${key}: ${rgb.r},${rgb.g},${rgb.b}`);
  2847. if (!key.startsWith('on-')) {
  2848. variables.push(`--v-theme-${key}-overlay-multiplier: ${getLuma(value) > 0.18 ? lightOverlay : darkOverlay}`);
  2849. }
  2850. }
  2851. for (const [key, value] of Object.entries(theme.variables)) {
  2852. const color = typeof value === 'string' && value.startsWith('#') ? parseColor(value) : undefined;
  2853. const rgb = color ? `${color.r}, ${color.g}, ${color.b}` : undefined;
  2854. variables.push(`--v-${key}: ${rgb ?? value}`);
  2855. }
  2856. return variables;
  2857. }
  2858. const makeVAppProps = propsFactory({
  2859. ...makeComponentProps(),
  2860. ...makeLayoutProps({
  2861. fullHeight: true
  2862. }),
  2863. ...makeThemeProps()
  2864. }, 'VApp');
  2865. const VApp = genericComponent()({
  2866. name: 'VApp',
  2867. props: makeVAppProps(),
  2868. setup(props, _ref) {
  2869. let {
  2870. slots
  2871. } = _ref;
  2872. const theme = provideTheme(props);
  2873. const {
  2874. layoutClasses,
  2875. getLayoutItem,
  2876. items,
  2877. layoutRef
  2878. } = createLayout(props);
  2879. const {
  2880. rtlClasses
  2881. } = useRtl();
  2882. useRender(() => vue.createVNode("div", {
  2883. "ref": layoutRef,
  2884. "class": ['v-application', theme.themeClasses.value, layoutClasses.value, rtlClasses.value, props.class],
  2885. "style": [props.style]
  2886. }, [vue.createVNode("div", {
  2887. "class": "v-application__wrap"
  2888. }, [slots.default?.()])]));
  2889. return {
  2890. getLayoutItem,
  2891. items,
  2892. theme
  2893. };
  2894. }
  2895. });
  2896. // Utilities
  2897. // Types
  2898. // Composables
  2899. const makeTagProps = propsFactory({
  2900. tag: {
  2901. type: String,
  2902. default: 'div'
  2903. }
  2904. }, 'tag');
  2905. const makeVToolbarTitleProps = propsFactory({
  2906. text: String,
  2907. ...makeComponentProps(),
  2908. ...makeTagProps()
  2909. }, 'VToolbarTitle');
  2910. const VToolbarTitle = genericComponent()({
  2911. name: 'VToolbarTitle',
  2912. props: makeVToolbarTitleProps(),
  2913. setup(props, _ref) {
  2914. let {
  2915. slots
  2916. } = _ref;
  2917. useRender(() => {
  2918. const hasText = !!(slots.default || slots.text || props.text);
  2919. return vue.createVNode(props.tag, {
  2920. "class": ['v-toolbar-title', props.class],
  2921. "style": props.style
  2922. }, {
  2923. default: () => [hasText && vue.createVNode("div", {
  2924. "class": "v-toolbar-title__placeholder"
  2925. }, [slots.text ? slots.text() : props.text, slots.default?.()])]
  2926. });
  2927. });
  2928. return {};
  2929. }
  2930. });
  2931. // Utilities
  2932. // Types
  2933. const makeTransitionProps$1 = propsFactory({
  2934. disabled: Boolean,
  2935. group: Boolean,
  2936. hideOnLeave: Boolean,
  2937. leaveAbsolute: Boolean,
  2938. mode: String,
  2939. origin: String
  2940. }, 'transition');
  2941. function createCssTransition(name, origin, mode) {
  2942. return genericComponent()({
  2943. name,
  2944. props: makeTransitionProps$1({
  2945. mode,
  2946. origin
  2947. }),
  2948. setup(props, _ref) {
  2949. let {
  2950. slots
  2951. } = _ref;
  2952. const functions = {
  2953. onBeforeEnter(el) {
  2954. if (props.origin) {
  2955. el.style.transformOrigin = props.origin;
  2956. }
  2957. },
  2958. onLeave(el) {
  2959. if (props.leaveAbsolute) {
  2960. const {
  2961. offsetTop,
  2962. offsetLeft,
  2963. offsetWidth,
  2964. offsetHeight
  2965. } = el;
  2966. el._transitionInitialStyles = {
  2967. position: el.style.position,
  2968. top: el.style.top,
  2969. left: el.style.left,
  2970. width: el.style.width,
  2971. height: el.style.height
  2972. };
  2973. el.style.position = 'absolute';
  2974. el.style.top = `${offsetTop}px`;
  2975. el.style.left = `${offsetLeft}px`;
  2976. el.style.width = `${offsetWidth}px`;
  2977. el.style.height = `${offsetHeight}px`;
  2978. }
  2979. if (props.hideOnLeave) {
  2980. el.style.setProperty('display', 'none', 'important');
  2981. }
  2982. },
  2983. onAfterLeave(el) {
  2984. if (props.leaveAbsolute && el?._transitionInitialStyles) {
  2985. const {
  2986. position,
  2987. top,
  2988. left,
  2989. width,
  2990. height
  2991. } = el._transitionInitialStyles;
  2992. delete el._transitionInitialStyles;
  2993. el.style.position = position || '';
  2994. el.style.top = top || '';
  2995. el.style.left = left || '';
  2996. el.style.width = width || '';
  2997. el.style.height = height || '';
  2998. }
  2999. }
  3000. };
  3001. return () => {
  3002. const tag = props.group ? vue.TransitionGroup : vue.Transition;
  3003. return vue.h(tag, {
  3004. name: props.disabled ? '' : name,
  3005. css: !props.disabled,
  3006. ...(props.group ? undefined : {
  3007. mode: props.mode
  3008. }),
  3009. ...(props.disabled ? {} : functions)
  3010. }, slots.default);
  3011. };
  3012. }
  3013. });
  3014. }
  3015. function createJavascriptTransition(name, functions) {
  3016. let mode = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : 'in-out';
  3017. return genericComponent()({
  3018. name,
  3019. props: {
  3020. mode: {
  3021. type: String,
  3022. default: mode
  3023. },
  3024. disabled: Boolean,
  3025. group: Boolean
  3026. },
  3027. setup(props, _ref2) {
  3028. let {
  3029. slots
  3030. } = _ref2;
  3031. const tag = props.group ? vue.TransitionGroup : vue.Transition;
  3032. return () => {
  3033. return vue.h(tag, {
  3034. name: props.disabled ? '' : name,
  3035. css: !props.disabled,
  3036. // mode: props.mode, // TODO: vuejs/vue-next#3104
  3037. ...(props.disabled ? {} : functions)
  3038. }, slots.default);
  3039. };
  3040. }
  3041. });
  3042. }
  3043. // Utilities
  3044. function ExpandTransitionGenerator () {
  3045. let expandedParentClass = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : '';
  3046. let x = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : false;
  3047. const sizeProperty = x ? 'width' : 'height';
  3048. const offsetProperty = vue.camelize(`offset-${sizeProperty}`);
  3049. return {
  3050. onBeforeEnter(el) {
  3051. el._parent = el.parentNode;
  3052. el._initialStyle = {
  3053. transition: el.style.transition,
  3054. overflow: el.style.overflow,
  3055. [sizeProperty]: el.style[sizeProperty]
  3056. };
  3057. },
  3058. onEnter(el) {
  3059. const initialStyle = el._initialStyle;
  3060. el.style.setProperty('transition', 'none', 'important');
  3061. // Hide overflow to account for collapsed margins in the calculated height
  3062. el.style.overflow = 'hidden';
  3063. const offset = `${el[offsetProperty]}px`;
  3064. el.style[sizeProperty] = '0';
  3065. void el.offsetHeight; // force reflow
  3066. el.style.transition = initialStyle.transition;
  3067. if (expandedParentClass && el._parent) {
  3068. el._parent.classList.add(expandedParentClass);
  3069. }
  3070. requestAnimationFrame(() => {
  3071. el.style[sizeProperty] = offset;
  3072. });
  3073. },
  3074. onAfterEnter: resetStyles,
  3075. onEnterCancelled: resetStyles,
  3076. onLeave(el) {
  3077. el._initialStyle = {
  3078. transition: '',
  3079. overflow: el.style.overflow,
  3080. [sizeProperty]: el.style[sizeProperty]
  3081. };
  3082. el.style.overflow = 'hidden';
  3083. el.style[sizeProperty] = `${el[offsetProperty]}px`;
  3084. void el.offsetHeight; // force reflow
  3085. requestAnimationFrame(() => el.style[sizeProperty] = '0');
  3086. },
  3087. onAfterLeave,
  3088. onLeaveCancelled: onAfterLeave
  3089. };
  3090. function onAfterLeave(el) {
  3091. if (expandedParentClass && el._parent) {
  3092. el._parent.classList.remove(expandedParentClass);
  3093. }
  3094. resetStyles(el);
  3095. }
  3096. function resetStyles(el) {
  3097. const size = el._initialStyle[sizeProperty];
  3098. el.style.overflow = el._initialStyle.overflow;
  3099. if (size != null) el.style[sizeProperty] = size;
  3100. delete el._initialStyle;
  3101. }
  3102. }
  3103. // Types
  3104. const makeVDialogTransitionProps = propsFactory({
  3105. target: [Object, Array]
  3106. }, 'v-dialog-transition');
  3107. const VDialogTransition = genericComponent()({
  3108. name: 'VDialogTransition',
  3109. props: makeVDialogTransitionProps(),
  3110. setup(props, _ref) {
  3111. let {
  3112. slots
  3113. } = _ref;
  3114. const functions = {
  3115. onBeforeEnter(el) {
  3116. el.style.pointerEvents = 'none';
  3117. el.style.visibility = 'hidden';
  3118. },
  3119. async onEnter(el, done) {
  3120. await new Promise(resolve => requestAnimationFrame(resolve));
  3121. await new Promise(resolve => requestAnimationFrame(resolve));
  3122. el.style.visibility = '';
  3123. const {
  3124. x,
  3125. y,
  3126. sx,
  3127. sy,
  3128. speed
  3129. } = getDimensions(props.target, el);
  3130. const animation = animate(el, [{
  3131. transform: `translate(${x}px, ${y}px) scale(${sx}, ${sy})`,
  3132. opacity: 0
  3133. }, {}], {
  3134. duration: 225 * speed,
  3135. easing: deceleratedEasing
  3136. });
  3137. getChildren(el)?.forEach(el => {
  3138. animate(el, [{
  3139. opacity: 0
  3140. }, {
  3141. opacity: 0,
  3142. offset: 0.33
  3143. }, {}], {
  3144. duration: 225 * 2 * speed,
  3145. easing: standardEasing
  3146. });
  3147. });
  3148. animation.finished.then(() => done());
  3149. },
  3150. onAfterEnter(el) {
  3151. el.style.removeProperty('pointer-events');
  3152. },
  3153. onBeforeLeave(el) {
  3154. el.style.pointerEvents = 'none';
  3155. },
  3156. async onLeave(el, done) {
  3157. await new Promise(resolve => requestAnimationFrame(resolve));
  3158. const {
  3159. x,
  3160. y,
  3161. sx,
  3162. sy,
  3163. speed
  3164. } = getDimensions(props.target, el);
  3165. const animation = animate(el, [{}, {
  3166. transform: `translate(${x}px, ${y}px) scale(${sx}, ${sy})`,
  3167. opacity: 0
  3168. }], {
  3169. duration: 125 * speed,
  3170. easing: acceleratedEasing
  3171. });
  3172. animation.finished.then(() => done());
  3173. getChildren(el)?.forEach(el => {
  3174. animate(el, [{}, {
  3175. opacity: 0,
  3176. offset: 0.2
  3177. }, {
  3178. opacity: 0
  3179. }], {
  3180. duration: 125 * 2 * speed,
  3181. easing: standardEasing
  3182. });
  3183. });
  3184. },
  3185. onAfterLeave(el) {
  3186. el.style.removeProperty('pointer-events');
  3187. }
  3188. };
  3189. return () => {
  3190. return props.target ? vue.createVNode(vue.Transition, vue.mergeProps({
  3191. "name": "dialog-transition"
  3192. }, functions, {
  3193. "css": false
  3194. }), slots) : vue.createVNode(vue.Transition, {
  3195. "name": "dialog-transition"
  3196. }, slots);
  3197. };
  3198. }
  3199. });
  3200. /** Animatable children (card, sheet, list) */
  3201. function getChildren(el) {
  3202. const els = el.querySelector(':scope > .v-card, :scope > .v-sheet, :scope > .v-list')?.children;
  3203. return els && [...els];
  3204. }
  3205. function getDimensions(target, el) {
  3206. const targetBox = getTargetBox(target);
  3207. const elBox = nullifyTransforms(el);
  3208. const [originX, originY] = getComputedStyle(el).transformOrigin.split(' ').map(v => parseFloat(v));
  3209. const [anchorSide, anchorOffset] = getComputedStyle(el).getPropertyValue('--v-overlay-anchor-origin').split(' ');
  3210. let offsetX = targetBox.left + targetBox.width / 2;
  3211. if (anchorSide === 'left' || anchorOffset === 'left') {
  3212. offsetX -= targetBox.width / 2;
  3213. } else if (anchorSide === 'right' || anchorOffset === 'right') {
  3214. offsetX += targetBox.width / 2;
  3215. }
  3216. let offsetY = targetBox.top + targetBox.height / 2;
  3217. if (anchorSide === 'top' || anchorOffset === 'top') {
  3218. offsetY -= targetBox.height / 2;
  3219. } else if (anchorSide === 'bottom' || anchorOffset === 'bottom') {
  3220. offsetY += targetBox.height / 2;
  3221. }
  3222. const tsx = targetBox.width / elBox.width;
  3223. const tsy = targetBox.height / elBox.height;
  3224. const maxs = Math.max(1, tsx, tsy);
  3225. const sx = tsx / maxs || 0;
  3226. const sy = tsy / maxs || 0;
  3227. // Animate elements larger than 12% of the screen area up to 1.5x slower
  3228. const asa = elBox.width * elBox.height / (window.innerWidth * window.innerHeight);
  3229. const speed = asa > 0.12 ? Math.min(1.5, (asa - 0.12) * 10 + 1) : 1;
  3230. return {
  3231. x: offsetX - (originX + elBox.left),
  3232. y: offsetY - (originY + elBox.top),
  3233. sx,
  3234. sy,
  3235. speed
  3236. };
  3237. }
  3238. // Component specific transitions
  3239. const VFabTransition = createCssTransition('fab-transition', 'center center', 'out-in');
  3240. // Generic transitions
  3241. const VDialogBottomTransition = createCssTransition('dialog-bottom-transition');
  3242. const VDialogTopTransition = createCssTransition('dialog-top-transition');
  3243. const VFadeTransition = createCssTransition('fade-transition');
  3244. const VScaleTransition = createCssTransition('scale-transition');
  3245. const VScrollXTransition = createCssTransition('scroll-x-transition');
  3246. const VScrollXReverseTransition = createCssTransition('scroll-x-reverse-transition');
  3247. const VScrollYTransition = createCssTransition('scroll-y-transition');
  3248. const VScrollYReverseTransition = createCssTransition('scroll-y-reverse-transition');
  3249. const VSlideXTransition = createCssTransition('slide-x-transition');
  3250. const VSlideXReverseTransition = createCssTransition('slide-x-reverse-transition');
  3251. const VSlideYTransition = createCssTransition('slide-y-transition');
  3252. const VSlideYReverseTransition = createCssTransition('slide-y-reverse-transition');
  3253. // Javascript transitions
  3254. const VExpandTransition = createJavascriptTransition('expand-transition', ExpandTransitionGenerator());
  3255. const VExpandXTransition = createJavascriptTransition('expand-x-transition', ExpandTransitionGenerator('', true));
  3256. // Composables
  3257. // Types
  3258. const makeVDefaultsProviderProps = propsFactory({
  3259. defaults: Object,
  3260. disabled: Boolean,
  3261. reset: [Number, String],
  3262. root: [Boolean, String],
  3263. scoped: Boolean
  3264. }, 'VDefaultsProvider');
  3265. const VDefaultsProvider = genericComponent(false)({
  3266. name: 'VDefaultsProvider',
  3267. props: makeVDefaultsProviderProps(),
  3268. setup(props, _ref) {
  3269. let {
  3270. slots
  3271. } = _ref;
  3272. const {
  3273. defaults,
  3274. disabled,
  3275. reset,
  3276. root,
  3277. scoped
  3278. } = vue.toRefs(props);
  3279. provideDefaults(defaults, {
  3280. reset,
  3281. root,
  3282. scoped,
  3283. disabled
  3284. });
  3285. return () => slots.default?.();
  3286. }
  3287. });
  3288. // Utilities
  3289. // Types
  3290. // Composables
  3291. const makeDimensionProps = propsFactory({
  3292. height: [Number, String],
  3293. maxHeight: [Number, String],
  3294. maxWidth: [Number, String],
  3295. minHeight: [Number, String],
  3296. minWidth: [Number, String],
  3297. width: [Number, String]
  3298. }, 'dimension');
  3299. function useDimension(props) {
  3300. const dimensionStyles = vue.computed(() => {
  3301. const styles = {};
  3302. const height = convertToUnit(props.height);
  3303. const maxHeight = convertToUnit(props.maxHeight);
  3304. const maxWidth = convertToUnit(props.maxWidth);
  3305. const minHeight = convertToUnit(props.minHeight);
  3306. const minWidth = convertToUnit(props.minWidth);
  3307. const width = convertToUnit(props.width);
  3308. if (height != null) styles.height = height;
  3309. if (maxHeight != null) styles.maxHeight = maxHeight;
  3310. if (maxWidth != null) styles.maxWidth = maxWidth;
  3311. if (minHeight != null) styles.minHeight = minHeight;
  3312. if (minWidth != null) styles.minWidth = minWidth;
  3313. if (width != null) styles.width = width;
  3314. return styles;
  3315. });
  3316. return {
  3317. dimensionStyles
  3318. };
  3319. }
  3320. function useAspectStyles(props) {
  3321. return {
  3322. aspectStyles: vue.computed(() => {
  3323. const ratio = Number(props.aspectRatio);
  3324. return ratio ? {
  3325. paddingBottom: String(1 / ratio * 100) + '%'
  3326. } : undefined;
  3327. })
  3328. };
  3329. }
  3330. const makeVResponsiveProps = propsFactory({
  3331. aspectRatio: [String, Number],
  3332. contentClass: null,
  3333. inline: Boolean,
  3334. ...makeComponentProps(),
  3335. ...makeDimensionProps()
  3336. }, 'VResponsive');
  3337. const VResponsive = genericComponent()({
  3338. name: 'VResponsive',
  3339. props: makeVResponsiveProps(),
  3340. setup(props, _ref) {
  3341. let {
  3342. slots
  3343. } = _ref;
  3344. const {
  3345. aspectStyles
  3346. } = useAspectStyles(props);
  3347. const {
  3348. dimensionStyles
  3349. } = useDimension(props);
  3350. useRender(() => vue.createVNode("div", {
  3351. "class": ['v-responsive', {
  3352. 'v-responsive--inline': props.inline
  3353. }, props.class],
  3354. "style": [dimensionStyles.value, props.style]
  3355. }, [vue.createVNode("div", {
  3356. "class": "v-responsive__sizer",
  3357. "style": aspectStyles.value
  3358. }, null), slots.additional?.(), slots.default && vue.createVNode("div", {
  3359. "class": ['v-responsive__content', props.contentClass]
  3360. }, [slots.default()])]));
  3361. return {};
  3362. }
  3363. });
  3364. // Utilities
  3365. // Types
  3366. // Composables
  3367. function useColor(colors) {
  3368. return destructComputed(() => {
  3369. const classes = [];
  3370. const styles = {};
  3371. if (colors.value.background) {
  3372. if (isCssColor(colors.value.background)) {
  3373. styles.backgroundColor = colors.value.background;
  3374. if (!colors.value.text && isParsableColor(colors.value.background)) {
  3375. const backgroundColor = parseColor(colors.value.background);
  3376. if (backgroundColor.a == null || backgroundColor.a === 1) {
  3377. const textColor = getForeground(backgroundColor);
  3378. styles.color = textColor;
  3379. styles.caretColor = textColor;
  3380. }
  3381. }
  3382. } else {
  3383. classes.push(`bg-${colors.value.background}`);
  3384. }
  3385. }
  3386. if (colors.value.text) {
  3387. if (isCssColor(colors.value.text)) {
  3388. styles.color = colors.value.text;
  3389. styles.caretColor = colors.value.text;
  3390. } else {
  3391. classes.push(`text-${colors.value.text}`);
  3392. }
  3393. }
  3394. return {
  3395. colorClasses: classes,
  3396. colorStyles: styles
  3397. };
  3398. });
  3399. }
  3400. function useTextColor(props, name) {
  3401. const colors = vue.computed(() => ({
  3402. text: vue.isRef(props) ? props.value : name ? props[name] : null
  3403. }));
  3404. const {
  3405. colorClasses: textColorClasses,
  3406. colorStyles: textColorStyles
  3407. } = useColor(colors);
  3408. return {
  3409. textColorClasses,
  3410. textColorStyles
  3411. };
  3412. }
  3413. function useBackgroundColor(props, name) {
  3414. const colors = vue.computed(() => ({
  3415. background: vue.isRef(props) ? props.value : name ? props[name] : null
  3416. }));
  3417. const {
  3418. colorClasses: backgroundColorClasses,
  3419. colorStyles: backgroundColorStyles
  3420. } = useColor(colors);
  3421. return {
  3422. backgroundColorClasses,
  3423. backgroundColorStyles
  3424. };
  3425. }
  3426. // Utilities
  3427. // Types
  3428. // Composables
  3429. const makeRoundedProps = propsFactory({
  3430. rounded: {
  3431. type: [Boolean, Number, String],
  3432. default: undefined
  3433. },
  3434. tile: Boolean
  3435. }, 'rounded');
  3436. function useRounded(props) {
  3437. let name = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : getCurrentInstanceName();
  3438. const roundedClasses = vue.computed(() => {
  3439. const rounded = vue.isRef(props) ? props.value : props.rounded;
  3440. const tile = vue.isRef(props) ? props.value : props.tile;
  3441. const classes = [];
  3442. if (rounded === true || rounded === '') {
  3443. classes.push(`${name}--rounded`);
  3444. } else if (typeof rounded === 'string' || rounded === 0) {
  3445. for (const value of String(rounded).split(' ')) {
  3446. classes.push(`rounded-${value}`);
  3447. }
  3448. } else if (tile || rounded === false) {
  3449. classes.push('rounded-0');
  3450. }
  3451. return classes;
  3452. });
  3453. return {
  3454. roundedClasses
  3455. };
  3456. }
  3457. // Utilities
  3458. // Types
  3459. const makeTransitionProps = propsFactory({
  3460. transition: {
  3461. type: [Boolean, String, Object],
  3462. default: 'fade-transition',
  3463. validator: val => val !== true
  3464. }
  3465. }, 'transition');
  3466. const MaybeTransition = (props, _ref) => {
  3467. let {
  3468. slots
  3469. } = _ref;
  3470. const {
  3471. transition,
  3472. disabled,
  3473. group,
  3474. ...rest
  3475. } = props;
  3476. const {
  3477. component = group ? vue.TransitionGroup : vue.Transition,
  3478. ...customProps
  3479. } = typeof transition === 'object' ? transition : {};
  3480. return vue.h(component, vue.mergeProps(typeof transition === 'string' ? {
  3481. name: disabled ? '' : transition
  3482. } : customProps, typeof transition === 'string' ? {} : Object.fromEntries(Object.entries({
  3483. disabled,
  3484. group
  3485. }).filter(_ref2 => {
  3486. let [_, v] = _ref2;
  3487. return v !== undefined;
  3488. })), rest), slots);
  3489. };
  3490. // Utilities
  3491. // Types
  3492. function mounted$5(el, binding) {
  3493. if (!SUPPORTS_INTERSECTION) return;
  3494. const modifiers = binding.modifiers || {};
  3495. const value = binding.value;
  3496. const {
  3497. handler,
  3498. options
  3499. } = typeof value === 'object' ? value : {
  3500. handler: value,
  3501. options: {}
  3502. };
  3503. const observer = new IntersectionObserver(function () {
  3504. let entries = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : [];
  3505. let observer = arguments.length > 1 ? arguments[1] : undefined;
  3506. const _observe = el._observe?.[binding.instance.$.uid];
  3507. if (!_observe) return; // Just in case, should never fire
  3508. const isIntersecting = entries.some(entry => entry.isIntersecting);
  3509. // If is not quiet or has already been
  3510. // initted, invoke the user callback
  3511. if (handler && (!modifiers.quiet || _observe.init) && (!modifiers.once || isIntersecting || _observe.init)) {
  3512. handler(isIntersecting, entries, observer);
  3513. }
  3514. if (isIntersecting && modifiers.once) unmounted$5(el, binding);else _observe.init = true;
  3515. }, options);
  3516. el._observe = Object(el._observe);
  3517. el._observe[binding.instance.$.uid] = {
  3518. init: false,
  3519. observer
  3520. };
  3521. observer.observe(el);
  3522. }
  3523. function unmounted$5(el, binding) {
  3524. const observe = el._observe?.[binding.instance.$.uid];
  3525. if (!observe) return;
  3526. observe.observer.unobserve(el);
  3527. delete el._observe[binding.instance.$.uid];
  3528. }
  3529. const Intersect = {
  3530. mounted: mounted$5,
  3531. unmounted: unmounted$5
  3532. };
  3533. // Types
  3534. // not intended for public use, this is passed in by vuetify-loader
  3535. const makeVImgProps = propsFactory({
  3536. absolute: Boolean,
  3537. alt: String,
  3538. cover: Boolean,
  3539. color: String,
  3540. draggable: {
  3541. type: [Boolean, String],
  3542. default: undefined
  3543. },
  3544. eager: Boolean,
  3545. gradient: String,
  3546. lazySrc: String,
  3547. options: {
  3548. type: Object,
  3549. // For more information on types, navigate to:
  3550. // https://developer.mozilla.org/en-US/docs/Web/API/Intersection_Observer_API
  3551. default: () => ({
  3552. root: undefined,
  3553. rootMargin: undefined,
  3554. threshold: undefined
  3555. })
  3556. },
  3557. sizes: String,
  3558. src: {
  3559. type: [String, Object],
  3560. default: ''
  3561. },
  3562. crossorigin: String,
  3563. referrerpolicy: String,
  3564. srcset: String,
  3565. position: String,
  3566. ...makeVResponsiveProps(),
  3567. ...makeComponentProps(),
  3568. ...makeRoundedProps(),
  3569. ...makeTransitionProps()
  3570. }, 'VImg');
  3571. const VImg = genericComponent()({
  3572. name: 'VImg',
  3573. directives: {
  3574. intersect: Intersect
  3575. },
  3576. props: makeVImgProps(),
  3577. emits: {
  3578. loadstart: value => true,
  3579. load: value => true,
  3580. error: value => true
  3581. },
  3582. setup(props, _ref) {
  3583. let {
  3584. emit,
  3585. slots
  3586. } = _ref;
  3587. const {
  3588. backgroundColorClasses,
  3589. backgroundColorStyles
  3590. } = useBackgroundColor(vue.toRef(props, 'color'));
  3591. const {
  3592. roundedClasses
  3593. } = useRounded(props);
  3594. const vm = getCurrentInstance('VImg');
  3595. const currentSrc = vue.shallowRef(''); // Set from srcset
  3596. const image = vue.ref();
  3597. const state = vue.shallowRef(props.eager ? 'loading' : 'idle');
  3598. const naturalWidth = vue.shallowRef();
  3599. const naturalHeight = vue.shallowRef();
  3600. const normalisedSrc = vue.computed(() => {
  3601. return props.src && typeof props.src === 'object' ? {
  3602. src: props.src.src,
  3603. srcset: props.srcset || props.src.srcset,
  3604. lazySrc: props.lazySrc || props.src.lazySrc,
  3605. aspect: Number(props.aspectRatio || props.src.aspect || 0)
  3606. } : {
  3607. src: props.src,
  3608. srcset: props.srcset,
  3609. lazySrc: props.lazySrc,
  3610. aspect: Number(props.aspectRatio || 0)
  3611. };
  3612. });
  3613. const aspectRatio = vue.computed(() => {
  3614. return normalisedSrc.value.aspect || naturalWidth.value / naturalHeight.value || 0;
  3615. });
  3616. vue.watch(() => props.src, () => {
  3617. init(state.value !== 'idle');
  3618. });
  3619. vue.watch(aspectRatio, (val, oldVal) => {
  3620. if (!val && oldVal && image.value) {
  3621. pollForSize(image.value);
  3622. }
  3623. });
  3624. // TODO: getSrc when window width changes
  3625. vue.onBeforeMount(() => init());
  3626. function init(isIntersecting) {
  3627. if (props.eager && isIntersecting) return;
  3628. if (SUPPORTS_INTERSECTION && !isIntersecting && !props.eager) return;
  3629. state.value = 'loading';
  3630. if (normalisedSrc.value.lazySrc) {
  3631. const lazyImg = new Image();
  3632. lazyImg.src = normalisedSrc.value.lazySrc;
  3633. pollForSize(lazyImg, null);
  3634. }
  3635. if (!normalisedSrc.value.src) return;
  3636. vue.nextTick(() => {
  3637. emit('loadstart', image.value?.currentSrc || normalisedSrc.value.src);
  3638. setTimeout(() => {
  3639. if (vm.isUnmounted) return;
  3640. if (image.value?.complete) {
  3641. if (!image.value.naturalWidth) {
  3642. onError();
  3643. }
  3644. if (state.value === 'error') return;
  3645. if (!aspectRatio.value) pollForSize(image.value, null);
  3646. if (state.value === 'loading') onLoad();
  3647. } else {
  3648. if (!aspectRatio.value) pollForSize(image.value);
  3649. getSrc();
  3650. }
  3651. });
  3652. });
  3653. }
  3654. function onLoad() {
  3655. if (vm.isUnmounted) return;
  3656. getSrc();
  3657. pollForSize(image.value);
  3658. state.value = 'loaded';
  3659. emit('load', image.value?.currentSrc || normalisedSrc.value.src);
  3660. }
  3661. function onError() {
  3662. if (vm.isUnmounted) return;
  3663. state.value = 'error';
  3664. emit('error', image.value?.currentSrc || normalisedSrc.value.src);
  3665. }
  3666. function getSrc() {
  3667. const img = image.value;
  3668. if (img) currentSrc.value = img.currentSrc || img.src;
  3669. }
  3670. let timer = -1;
  3671. vue.onBeforeUnmount(() => {
  3672. clearTimeout(timer);
  3673. });
  3674. function pollForSize(img) {
  3675. let timeout = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 100;
  3676. const poll = () => {
  3677. clearTimeout(timer);
  3678. if (vm.isUnmounted) return;
  3679. const {
  3680. naturalHeight: imgHeight,
  3681. naturalWidth: imgWidth
  3682. } = img;
  3683. if (imgHeight || imgWidth) {
  3684. naturalWidth.value = imgWidth;
  3685. naturalHeight.value = imgHeight;
  3686. } else if (!img.complete && state.value === 'loading' && timeout != null) {
  3687. timer = window.setTimeout(poll, timeout);
  3688. } else if (img.currentSrc.endsWith('.svg') || img.currentSrc.startsWith('data:image/svg+xml')) {
  3689. naturalWidth.value = 1;
  3690. naturalHeight.value = 1;
  3691. }
  3692. };
  3693. poll();
  3694. }
  3695. const containClasses = vue.computed(() => ({
  3696. 'v-img__img--cover': props.cover,
  3697. 'v-img__img--contain': !props.cover
  3698. }));
  3699. const __image = () => {
  3700. if (!normalisedSrc.value.src || state.value === 'idle') return null;
  3701. const img = vue.createVNode("img", {
  3702. "class": ['v-img__img', containClasses.value],
  3703. "style": {
  3704. objectPosition: props.position
  3705. },
  3706. "src": normalisedSrc.value.src,
  3707. "srcset": normalisedSrc.value.srcset,
  3708. "alt": props.alt,
  3709. "crossorigin": props.crossorigin,
  3710. "referrerpolicy": props.referrerpolicy,
  3711. "draggable": props.draggable,
  3712. "sizes": props.sizes,
  3713. "ref": image,
  3714. "onLoad": onLoad,
  3715. "onError": onError
  3716. }, null);
  3717. const sources = slots.sources?.();
  3718. return vue.createVNode(MaybeTransition, {
  3719. "transition": props.transition,
  3720. "appear": true
  3721. }, {
  3722. default: () => [vue.withDirectives(sources ? vue.createVNode("picture", {
  3723. "class": "v-img__picture"
  3724. }, [sources, img]) : img, [[vue.vShow, state.value === 'loaded']])]
  3725. });
  3726. };
  3727. const __preloadImage = () => vue.createVNode(MaybeTransition, {
  3728. "transition": props.transition
  3729. }, {
  3730. default: () => [normalisedSrc.value.lazySrc && state.value !== 'loaded' && vue.createVNode("img", {
  3731. "class": ['v-img__img', 'v-img__img--preload', containClasses.value],
  3732. "style": {
  3733. objectPosition: props.position
  3734. },
  3735. "src": normalisedSrc.value.lazySrc,
  3736. "alt": props.alt,
  3737. "crossorigin": props.crossorigin,
  3738. "referrerpolicy": props.referrerpolicy,
  3739. "draggable": props.draggable
  3740. }, null)]
  3741. });
  3742. const __placeholder = () => {
  3743. if (!slots.placeholder) return null;
  3744. return vue.createVNode(MaybeTransition, {
  3745. "transition": props.transition,
  3746. "appear": true
  3747. }, {
  3748. default: () => [(state.value === 'loading' || state.value === 'error' && !slots.error) && vue.createVNode("div", {
  3749. "class": "v-img__placeholder"
  3750. }, [slots.placeholder()])]
  3751. });
  3752. };
  3753. const __error = () => {
  3754. if (!slots.error) return null;
  3755. return vue.createVNode(MaybeTransition, {
  3756. "transition": props.transition,
  3757. "appear": true
  3758. }, {
  3759. default: () => [state.value === 'error' && vue.createVNode("div", {
  3760. "class": "v-img__error"
  3761. }, [slots.error()])]
  3762. });
  3763. };
  3764. const __gradient = () => {
  3765. if (!props.gradient) return null;
  3766. return vue.createVNode("div", {
  3767. "class": "v-img__gradient",
  3768. "style": {
  3769. backgroundImage: `linear-gradient(${props.gradient})`
  3770. }
  3771. }, null);
  3772. };
  3773. const isBooted = vue.shallowRef(false);
  3774. {
  3775. const stop = vue.watch(aspectRatio, val => {
  3776. if (val) {
  3777. // Doesn't work with nextTick, idk why
  3778. requestAnimationFrame(() => {
  3779. requestAnimationFrame(() => {
  3780. isBooted.value = true;
  3781. });
  3782. });
  3783. stop();
  3784. }
  3785. });
  3786. }
  3787. useRender(() => {
  3788. const responsiveProps = VResponsive.filterProps(props);
  3789. return vue.withDirectives(vue.createVNode(VResponsive, vue.mergeProps({
  3790. "class": ['v-img', {
  3791. 'v-img--absolute': props.absolute,
  3792. 'v-img--booting': !isBooted.value
  3793. }, backgroundColorClasses.value, roundedClasses.value, props.class],
  3794. "style": [{
  3795. width: convertToUnit(props.width === 'auto' ? naturalWidth.value : props.width)
  3796. }, backgroundColorStyles.value, props.style]
  3797. }, responsiveProps, {
  3798. "aspectRatio": aspectRatio.value,
  3799. "aria-label": props.alt,
  3800. "role": props.alt ? 'img' : undefined
  3801. }), {
  3802. additional: () => vue.createVNode(vue.Fragment, null, [vue.createVNode(__image, null, null), vue.createVNode(__preloadImage, null, null), vue.createVNode(__gradient, null, null), vue.createVNode(__placeholder, null, null), vue.createVNode(__error, null, null)]),
  3803. default: slots.default
  3804. }), [[vue.resolveDirective("intersect"), {
  3805. handler: init,
  3806. options: props.options
  3807. }, null, {
  3808. once: true
  3809. }]]);
  3810. });
  3811. return {
  3812. currentSrc,
  3813. image,
  3814. state,
  3815. naturalWidth,
  3816. naturalHeight
  3817. };
  3818. }
  3819. });
  3820. // Utilities
  3821. // Types
  3822. // Composables
  3823. const makeBorderProps = propsFactory({
  3824. border: [Boolean, Number, String]
  3825. }, 'border');
  3826. function useBorder(props) {
  3827. let name = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : getCurrentInstanceName();
  3828. const borderClasses = vue.computed(() => {
  3829. const border = vue.isRef(props) ? props.value : props.border;
  3830. const classes = [];
  3831. if (border === true || border === '') {
  3832. classes.push(`${name}--border`);
  3833. } else if (typeof border === 'string' || border === 0) {
  3834. for (const value of String(border).split(' ')) {
  3835. classes.push(`border-${value}`);
  3836. }
  3837. }
  3838. return classes;
  3839. });
  3840. return {
  3841. borderClasses
  3842. };
  3843. }
  3844. // Utilities
  3845. // Types
  3846. // Composables
  3847. const makeElevationProps = propsFactory({
  3848. elevation: {
  3849. type: [Number, String],
  3850. validator(v) {
  3851. const value = parseInt(v);
  3852. return !isNaN(value) && value >= 0 &&
  3853. // Material Design has a maximum elevation of 24
  3854. // https://material.io/design/environment/elevation.html#default-elevations
  3855. value <= 24;
  3856. }
  3857. }
  3858. }, 'elevation');
  3859. function useElevation(props) {
  3860. const elevationClasses = vue.computed(() => {
  3861. const elevation = vue.isRef(props) ? props.value : props.elevation;
  3862. const classes = [];
  3863. if (elevation == null) return classes;
  3864. classes.push(`elevation-${elevation}`);
  3865. return classes;
  3866. });
  3867. return {
  3868. elevationClasses
  3869. };
  3870. }
  3871. // Types
  3872. const allowedDensities$1 = [null, 'prominent', 'default', 'comfortable', 'compact'];
  3873. const makeVToolbarProps = propsFactory({
  3874. absolute: Boolean,
  3875. collapse: Boolean,
  3876. color: String,
  3877. density: {
  3878. type: String,
  3879. default: 'default',
  3880. validator: v => allowedDensities$1.includes(v)
  3881. },
  3882. extended: Boolean,
  3883. extensionHeight: {
  3884. type: [Number, String],
  3885. default: 48
  3886. },
  3887. flat: Boolean,
  3888. floating: Boolean,
  3889. height: {
  3890. type: [Number, String],
  3891. default: 64
  3892. },
  3893. image: String,
  3894. title: String,
  3895. ...makeBorderProps(),
  3896. ...makeComponentProps(),
  3897. ...makeElevationProps(),
  3898. ...makeRoundedProps(),
  3899. ...makeTagProps({
  3900. tag: 'header'
  3901. }),
  3902. ...makeThemeProps()
  3903. }, 'VToolbar');
  3904. const VToolbar = genericComponent()({
  3905. name: 'VToolbar',
  3906. props: makeVToolbarProps(),
  3907. setup(props, _ref) {
  3908. let {
  3909. slots
  3910. } = _ref;
  3911. const {
  3912. backgroundColorClasses,
  3913. backgroundColorStyles
  3914. } = useBackgroundColor(vue.toRef(props, 'color'));
  3915. const {
  3916. borderClasses
  3917. } = useBorder(props);
  3918. const {
  3919. elevationClasses
  3920. } = useElevation(props);
  3921. const {
  3922. roundedClasses
  3923. } = useRounded(props);
  3924. const {
  3925. themeClasses
  3926. } = provideTheme(props);
  3927. const {
  3928. rtlClasses
  3929. } = useRtl();
  3930. const isExtended = vue.shallowRef(!!(props.extended || slots.extension?.()));
  3931. const contentHeight = vue.computed(() => parseInt(Number(props.height) + (props.density === 'prominent' ? Number(props.height) : 0) - (props.density === 'comfortable' ? 8 : 0) - (props.density === 'compact' ? 16 : 0), 10));
  3932. const extensionHeight = vue.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);
  3933. provideDefaults({
  3934. VBtn: {
  3935. variant: 'text'
  3936. }
  3937. });
  3938. useRender(() => {
  3939. const hasTitle = !!(props.title || slots.title);
  3940. const hasImage = !!(slots.image || props.image);
  3941. const extension = slots.extension?.();
  3942. isExtended.value = !!(props.extended || extension);
  3943. return vue.createVNode(props.tag, {
  3944. "class": ['v-toolbar', {
  3945. 'v-toolbar--absolute': props.absolute,
  3946. 'v-toolbar--collapse': props.collapse,
  3947. 'v-toolbar--flat': props.flat,
  3948. 'v-toolbar--floating': props.floating,
  3949. [`v-toolbar--density-${props.density}`]: true
  3950. }, backgroundColorClasses.value, borderClasses.value, elevationClasses.value, roundedClasses.value, themeClasses.value, rtlClasses.value, props.class],
  3951. "style": [backgroundColorStyles.value, props.style]
  3952. }, {
  3953. default: () => [hasImage && vue.createVNode("div", {
  3954. "key": "image",
  3955. "class": "v-toolbar__image"
  3956. }, [!slots.image ? vue.createVNode(VImg, {
  3957. "key": "image-img",
  3958. "cover": true,
  3959. "src": props.image
  3960. }, null) : vue.createVNode(VDefaultsProvider, {
  3961. "key": "image-defaults",
  3962. "disabled": !props.image,
  3963. "defaults": {
  3964. VImg: {
  3965. cover: true,
  3966. src: props.image
  3967. }
  3968. }
  3969. }, slots.image)]), vue.createVNode(VDefaultsProvider, {
  3970. "defaults": {
  3971. VTabs: {
  3972. height: convertToUnit(contentHeight.value)
  3973. }
  3974. }
  3975. }, {
  3976. default: () => [vue.createVNode("div", {
  3977. "class": "v-toolbar__content",
  3978. "style": {
  3979. height: convertToUnit(contentHeight.value)
  3980. }
  3981. }, [slots.prepend && vue.createVNode("div", {
  3982. "class": "v-toolbar__prepend"
  3983. }, [slots.prepend?.()]), hasTitle && vue.createVNode(VToolbarTitle, {
  3984. "key": "title",
  3985. "text": props.title
  3986. }, {
  3987. text: slots.title
  3988. }), slots.default?.(), slots.append && vue.createVNode("div", {
  3989. "class": "v-toolbar__append"
  3990. }, [slots.append?.()])])]
  3991. }), vue.createVNode(VDefaultsProvider, {
  3992. "defaults": {
  3993. VTabs: {
  3994. height: convertToUnit(extensionHeight.value)
  3995. }
  3996. }
  3997. }, {
  3998. default: () => [vue.createVNode(VExpandTransition, null, {
  3999. default: () => [isExtended.value && vue.createVNode("div", {
  4000. "class": "v-toolbar__extension",
  4001. "style": {
  4002. height: convertToUnit(extensionHeight.value)
  4003. }
  4004. }, [extension])]
  4005. })]
  4006. })]
  4007. });
  4008. });
  4009. return {
  4010. contentHeight,
  4011. extensionHeight
  4012. };
  4013. }
  4014. });
  4015. // Utilities
  4016. // Types
  4017. // Composables
  4018. const makeScrollProps = propsFactory({
  4019. scrollTarget: {
  4020. type: String
  4021. },
  4022. scrollThreshold: {
  4023. type: [String, Number],
  4024. default: 300
  4025. }
  4026. }, 'scroll');
  4027. function useScroll(props) {
  4028. let args = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
  4029. const {
  4030. canScroll
  4031. } = args;
  4032. let previousScroll = 0;
  4033. let previousScrollHeight = 0;
  4034. const target = vue.ref(null);
  4035. const currentScroll = vue.shallowRef(0);
  4036. const savedScroll = vue.shallowRef(0);
  4037. const currentThreshold = vue.shallowRef(0);
  4038. const isScrollActive = vue.shallowRef(false);
  4039. const isScrollingUp = vue.shallowRef(false);
  4040. const scrollThreshold = vue.computed(() => {
  4041. return Number(props.scrollThreshold);
  4042. });
  4043. /**
  4044. * 1: at top
  4045. * 0: at threshold
  4046. */
  4047. const scrollRatio = vue.computed(() => {
  4048. return clamp((scrollThreshold.value - currentScroll.value) / scrollThreshold.value || 0);
  4049. });
  4050. const onScroll = () => {
  4051. const targetEl = target.value;
  4052. if (!targetEl || canScroll && !canScroll.value) return;
  4053. previousScroll = currentScroll.value;
  4054. currentScroll.value = 'window' in targetEl ? targetEl.pageYOffset : targetEl.scrollTop;
  4055. const currentScrollHeight = targetEl instanceof Window ? document.documentElement.scrollHeight : targetEl.scrollHeight;
  4056. if (previousScrollHeight !== currentScrollHeight) {
  4057. previousScrollHeight = currentScrollHeight;
  4058. return;
  4059. }
  4060. isScrollingUp.value = currentScroll.value < previousScroll;
  4061. currentThreshold.value = Math.abs(currentScroll.value - scrollThreshold.value);
  4062. };
  4063. vue.watch(isScrollingUp, () => {
  4064. savedScroll.value = savedScroll.value || currentScroll.value;
  4065. });
  4066. vue.watch(isScrollActive, () => {
  4067. savedScroll.value = 0;
  4068. });
  4069. vue.onMounted(() => {
  4070. vue.watch(() => props.scrollTarget, scrollTarget => {
  4071. const newTarget = scrollTarget ? document.querySelector(scrollTarget) : window;
  4072. if (!newTarget) {
  4073. consoleWarn(`Unable to locate element with identifier ${scrollTarget}`);
  4074. return;
  4075. }
  4076. if (newTarget === target.value) return;
  4077. target.value?.removeEventListener('scroll', onScroll);
  4078. target.value = newTarget;
  4079. target.value.addEventListener('scroll', onScroll, {
  4080. passive: true
  4081. });
  4082. }, {
  4083. immediate: true
  4084. });
  4085. });
  4086. vue.onBeforeUnmount(() => {
  4087. target.value?.removeEventListener('scroll', onScroll);
  4088. });
  4089. // Do we need this? If yes - seems that
  4090. // there's no need to expose onScroll
  4091. canScroll && vue.watch(canScroll, onScroll, {
  4092. immediate: true
  4093. });
  4094. return {
  4095. scrollThreshold,
  4096. currentScroll,
  4097. currentThreshold,
  4098. isScrollActive,
  4099. scrollRatio,
  4100. // required only for testing
  4101. // probably can be removed
  4102. // later (2 chars chlng)
  4103. isScrollingUp,
  4104. savedScroll
  4105. };
  4106. }
  4107. // Utilities
  4108. // Composables
  4109. function useSsrBoot() {
  4110. const isBooted = vue.shallowRef(false);
  4111. vue.onMounted(() => {
  4112. window.requestAnimationFrame(() => {
  4113. isBooted.value = true;
  4114. });
  4115. });
  4116. const ssrBootStyles = vue.computed(() => !isBooted.value ? {
  4117. transition: 'none !important'
  4118. } : undefined);
  4119. return {
  4120. ssrBootStyles,
  4121. isBooted: vue.readonly(isBooted)
  4122. };
  4123. }
  4124. // Types
  4125. const makeVAppBarProps = propsFactory({
  4126. scrollBehavior: String,
  4127. modelValue: {
  4128. type: Boolean,
  4129. default: true
  4130. },
  4131. location: {
  4132. type: String,
  4133. default: 'top',
  4134. validator: value => ['top', 'bottom'].includes(value)
  4135. },
  4136. ...makeVToolbarProps(),
  4137. ...makeLayoutItemProps(),
  4138. ...makeScrollProps(),
  4139. height: {
  4140. type: [Number, String],
  4141. default: 64
  4142. }
  4143. }, 'VAppBar');
  4144. const VAppBar = genericComponent()({
  4145. name: 'VAppBar',
  4146. props: makeVAppBarProps(),
  4147. emits: {
  4148. 'update:modelValue': value => true
  4149. },
  4150. setup(props, _ref) {
  4151. let {
  4152. slots
  4153. } = _ref;
  4154. const vToolbarRef = vue.ref();
  4155. const isActive = useProxiedModel(props, 'modelValue');
  4156. const scrollBehavior = vue.computed(() => {
  4157. const behavior = new Set(props.scrollBehavior?.split(' ') ?? []);
  4158. return {
  4159. hide: behavior.has('hide'),
  4160. fullyHide: behavior.has('fully-hide'),
  4161. inverted: behavior.has('inverted'),
  4162. collapse: behavior.has('collapse'),
  4163. elevate: behavior.has('elevate'),
  4164. fadeImage: behavior.has('fade-image')
  4165. // shrink: behavior.has('shrink'),
  4166. };
  4167. });
  4168. const canScroll = vue.computed(() => {
  4169. const behavior = scrollBehavior.value;
  4170. return behavior.hide || behavior.fullyHide || behavior.inverted || behavior.collapse || behavior.elevate || behavior.fadeImage ||
  4171. // behavior.shrink ||
  4172. !isActive.value;
  4173. });
  4174. const {
  4175. currentScroll,
  4176. scrollThreshold,
  4177. isScrollingUp,
  4178. scrollRatio
  4179. } = useScroll(props, {
  4180. canScroll
  4181. });
  4182. const canHide = vue.computed(() => scrollBehavior.value.hide || scrollBehavior.value.fullyHide);
  4183. const isCollapsed = vue.computed(() => props.collapse || scrollBehavior.value.collapse && (scrollBehavior.value.inverted ? scrollRatio.value > 0 : scrollRatio.value === 0));
  4184. const isFlat = vue.computed(() => props.flat || scrollBehavior.value.fullyHide && !isActive.value || scrollBehavior.value.elevate && (scrollBehavior.value.inverted ? currentScroll.value > 0 : currentScroll.value === 0));
  4185. const opacity = vue.computed(() => scrollBehavior.value.fadeImage ? scrollBehavior.value.inverted ? 1 - scrollRatio.value : scrollRatio.value : undefined);
  4186. const height = vue.computed(() => {
  4187. if (scrollBehavior.value.hide && scrollBehavior.value.inverted) return 0;
  4188. const height = vToolbarRef.value?.contentHeight ?? 0;
  4189. const extensionHeight = vToolbarRef.value?.extensionHeight ?? 0;
  4190. if (!canHide.value) return height + extensionHeight;
  4191. return currentScroll.value < scrollThreshold.value || scrollBehavior.value.fullyHide ? height + extensionHeight : height;
  4192. });
  4193. useToggleScope(vue.computed(() => !!props.scrollBehavior), () => {
  4194. vue.watchEffect(() => {
  4195. if (canHide.value) {
  4196. if (scrollBehavior.value.inverted) {
  4197. isActive.value = currentScroll.value > scrollThreshold.value;
  4198. } else {
  4199. isActive.value = isScrollingUp.value || currentScroll.value < scrollThreshold.value;
  4200. }
  4201. } else {
  4202. isActive.value = true;
  4203. }
  4204. });
  4205. });
  4206. const {
  4207. ssrBootStyles
  4208. } = useSsrBoot();
  4209. const {
  4210. layoutItemStyles
  4211. } = useLayoutItem({
  4212. id: props.name,
  4213. order: vue.computed(() => parseInt(props.order, 10)),
  4214. position: vue.toRef(props, 'location'),
  4215. layoutSize: height,
  4216. elementSize: vue.shallowRef(undefined),
  4217. active: isActive,
  4218. absolute: vue.toRef(props, 'absolute')
  4219. });
  4220. useRender(() => {
  4221. const toolbarProps = VToolbar.filterProps(props);
  4222. return vue.createVNode(VToolbar, vue.mergeProps({
  4223. "ref": vToolbarRef,
  4224. "class": ['v-app-bar', {
  4225. 'v-app-bar--bottom': props.location === 'bottom'
  4226. }, props.class],
  4227. "style": [{
  4228. ...layoutItemStyles.value,
  4229. '--v-toolbar-image-opacity': opacity.value,
  4230. height: undefined,
  4231. ...ssrBootStyles.value
  4232. }, props.style]
  4233. }, toolbarProps, {
  4234. "collapse": isCollapsed.value,
  4235. "flat": isFlat.value
  4236. }), slots);
  4237. });
  4238. return {};
  4239. }
  4240. });
  4241. // Utilities
  4242. // Types
  4243. const allowedDensities = [null, 'default', 'comfortable', 'compact'];
  4244. // typeof allowedDensities[number] evalutes to any
  4245. // when generating api types for whatever reason.
  4246. // Composables
  4247. const makeDensityProps = propsFactory({
  4248. density: {
  4249. type: String,
  4250. default: 'default',
  4251. validator: v => allowedDensities.includes(v)
  4252. }
  4253. }, 'density');
  4254. function useDensity(props) {
  4255. let name = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : getCurrentInstanceName();
  4256. const densityClasses = vue.computed(() => {
  4257. return `${name}--density-${props.density}`;
  4258. });
  4259. return {
  4260. densityClasses
  4261. };
  4262. }
  4263. // Types
  4264. const allowedVariants$2 = ['elevated', 'flat', 'tonal', 'outlined', 'text', 'plain'];
  4265. function genOverlays(isClickable, name) {
  4266. return vue.createVNode(vue.Fragment, null, [isClickable && vue.createVNode("span", {
  4267. "key": "overlay",
  4268. "class": `${name}__overlay`
  4269. }, null), vue.createVNode("span", {
  4270. "key": "underlay",
  4271. "class": `${name}__underlay`
  4272. }, null)]);
  4273. }
  4274. const makeVariantProps = propsFactory({
  4275. color: String,
  4276. variant: {
  4277. type: String,
  4278. default: 'elevated',
  4279. validator: v => allowedVariants$2.includes(v)
  4280. }
  4281. }, 'variant');
  4282. function useVariant(props) {
  4283. let name = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : getCurrentInstanceName();
  4284. const variantClasses = vue.computed(() => {
  4285. const {
  4286. variant
  4287. } = vue.unref(props);
  4288. return `${name}--variant-${variant}`;
  4289. });
  4290. const {
  4291. colorClasses,
  4292. colorStyles
  4293. } = useColor(vue.computed(() => {
  4294. const {
  4295. variant,
  4296. color
  4297. } = vue.unref(props);
  4298. return {
  4299. [['elevated', 'flat'].includes(variant) ? 'background' : 'text']: color
  4300. };
  4301. }));
  4302. return {
  4303. colorClasses,
  4304. colorStyles,
  4305. variantClasses
  4306. };
  4307. }
  4308. const makeVBtnGroupProps = propsFactory({
  4309. baseColor: String,
  4310. divided: Boolean,
  4311. ...makeBorderProps(),
  4312. ...makeComponentProps(),
  4313. ...makeDensityProps(),
  4314. ...makeElevationProps(),
  4315. ...makeRoundedProps(),
  4316. ...makeTagProps(),
  4317. ...makeThemeProps(),
  4318. ...makeVariantProps()
  4319. }, 'VBtnGroup');
  4320. const VBtnGroup = genericComponent()({
  4321. name: 'VBtnGroup',
  4322. props: makeVBtnGroupProps(),
  4323. setup(props, _ref) {
  4324. let {
  4325. slots
  4326. } = _ref;
  4327. const {
  4328. themeClasses
  4329. } = provideTheme(props);
  4330. const {
  4331. densityClasses
  4332. } = useDensity(props);
  4333. const {
  4334. borderClasses
  4335. } = useBorder(props);
  4336. const {
  4337. elevationClasses
  4338. } = useElevation(props);
  4339. const {
  4340. roundedClasses
  4341. } = useRounded(props);
  4342. provideDefaults({
  4343. VBtn: {
  4344. height: 'auto',
  4345. baseColor: vue.toRef(props, 'baseColor'),
  4346. color: vue.toRef(props, 'color'),
  4347. density: vue.toRef(props, 'density'),
  4348. flat: true,
  4349. variant: vue.toRef(props, 'variant')
  4350. }
  4351. });
  4352. useRender(() => {
  4353. return vue.createVNode(props.tag, {
  4354. "class": ['v-btn-group', {
  4355. 'v-btn-group--divided': props.divided
  4356. }, themeClasses.value, borderClasses.value, densityClasses.value, elevationClasses.value, roundedClasses.value, props.class],
  4357. "style": props.style
  4358. }, slots);
  4359. });
  4360. }
  4361. });
  4362. // Composables
  4363. // Types
  4364. const makeGroupProps = propsFactory({
  4365. modelValue: {
  4366. type: null,
  4367. default: undefined
  4368. },
  4369. multiple: Boolean,
  4370. mandatory: [Boolean, String],
  4371. max: Number,
  4372. selectedClass: String,
  4373. disabled: Boolean
  4374. }, 'group');
  4375. const makeGroupItemProps = propsFactory({
  4376. value: null,
  4377. disabled: Boolean,
  4378. selectedClass: String
  4379. }, 'group-item');
  4380. // Composables
  4381. function useGroupItem(props, injectKey) {
  4382. let required = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : true;
  4383. const vm = getCurrentInstance('useGroupItem');
  4384. if (!vm) {
  4385. throw new Error('[Vuetify] useGroupItem composable must be used inside a component setup function');
  4386. }
  4387. const id = getUid();
  4388. vue.provide(Symbol.for(`${injectKey.description}:id`), id);
  4389. const group = vue.inject(injectKey, null);
  4390. if (!group) {
  4391. if (!required) return group;
  4392. throw new Error(`[Vuetify] Could not find useGroup injection with symbol ${injectKey.description}`);
  4393. }
  4394. const value = vue.toRef(props, 'value');
  4395. const disabled = vue.computed(() => !!(group.disabled.value || props.disabled));
  4396. group.register({
  4397. id,
  4398. value,
  4399. disabled
  4400. }, vm);
  4401. vue.onBeforeUnmount(() => {
  4402. group.unregister(id);
  4403. });
  4404. const isSelected = vue.computed(() => {
  4405. return group.isSelected(id);
  4406. });
  4407. const isFirst = vue.computed(() => {
  4408. return group.items.value[0].id === id;
  4409. });
  4410. const isLast = vue.computed(() => {
  4411. return group.items.value[group.items.value.length - 1].id === id;
  4412. });
  4413. const selectedClass = vue.computed(() => isSelected.value && [group.selectedClass.value, props.selectedClass]);
  4414. vue.watch(isSelected, value => {
  4415. vm.emit('group:selected', {
  4416. value
  4417. });
  4418. }, {
  4419. flush: 'sync'
  4420. });
  4421. return {
  4422. id,
  4423. isSelected,
  4424. isFirst,
  4425. isLast,
  4426. toggle: () => group.select(id, !isSelected.value),
  4427. select: value => group.select(id, value),
  4428. selectedClass,
  4429. value,
  4430. disabled,
  4431. group
  4432. };
  4433. }
  4434. function useGroup(props, injectKey) {
  4435. let isUnmounted = false;
  4436. const items = vue.reactive([]);
  4437. const selected = useProxiedModel(props, 'modelValue', [], v => {
  4438. if (v == null) return [];
  4439. return getIds(items, wrapInArray(v));
  4440. }, v => {
  4441. const arr = getValues(items, v);
  4442. return props.multiple ? arr : arr[0];
  4443. });
  4444. const groupVm = getCurrentInstance('useGroup');
  4445. function register(item, vm) {
  4446. // Is there a better way to fix this typing?
  4447. const unwrapped = item;
  4448. const key = Symbol.for(`${injectKey.description}:id`);
  4449. const children = findChildrenWithProvide(key, groupVm?.vnode);
  4450. const index = children.indexOf(vm);
  4451. if (vue.unref(unwrapped.value) == null) {
  4452. unwrapped.value = index;
  4453. unwrapped.useIndexAsValue = true;
  4454. }
  4455. if (index > -1) {
  4456. items.splice(index, 0, unwrapped);
  4457. } else {
  4458. items.push(unwrapped);
  4459. }
  4460. }
  4461. function unregister(id) {
  4462. if (isUnmounted) return;
  4463. // TODO: re-evaluate this line's importance in the future
  4464. // should we only modify the model if mandatory is set.
  4465. // selected.value = selected.value.filter(v => v !== id)
  4466. forceMandatoryValue();
  4467. const index = items.findIndex(item => item.id === id);
  4468. items.splice(index, 1);
  4469. }
  4470. // If mandatory and nothing is selected, then select first non-disabled item
  4471. function forceMandatoryValue() {
  4472. const item = items.find(item => !item.disabled);
  4473. if (item && props.mandatory === 'force' && !selected.value.length) {
  4474. selected.value = [item.id];
  4475. }
  4476. }
  4477. vue.onMounted(() => {
  4478. forceMandatoryValue();
  4479. });
  4480. vue.onBeforeUnmount(() => {
  4481. isUnmounted = true;
  4482. });
  4483. vue.onUpdated(() => {
  4484. // #19655 update the items that use the index as the value.
  4485. for (let i = 0; i < items.length; i++) {
  4486. if (items[i].useIndexAsValue) {
  4487. items[i].value = i;
  4488. }
  4489. }
  4490. });
  4491. function select(id, value) {
  4492. const item = items.find(item => item.id === id);
  4493. if (value && item?.disabled) return;
  4494. if (props.multiple) {
  4495. const internalValue = selected.value.slice();
  4496. const index = internalValue.findIndex(v => v === id);
  4497. const isSelected = ~index;
  4498. value = value ?? !isSelected;
  4499. // We can't remove value if group is
  4500. // mandatory, value already exists,
  4501. // and it is the only value
  4502. if (isSelected && props.mandatory && internalValue.length <= 1) return;
  4503. // We can't add value if it would
  4504. // cause max limit to be exceeded
  4505. if (!isSelected && props.max != null && internalValue.length + 1 > props.max) return;
  4506. if (index < 0 && value) internalValue.push(id);else if (index >= 0 && !value) internalValue.splice(index, 1);
  4507. selected.value = internalValue;
  4508. } else {
  4509. const isSelected = selected.value.includes(id);
  4510. if (props.mandatory && isSelected) return;
  4511. selected.value = value ?? !isSelected ? [id] : [];
  4512. }
  4513. }
  4514. function step(offset) {
  4515. // getting an offset from selected value obviously won't work with multiple values
  4516. if (props.multiple) consoleWarn('This method is not supported when using "multiple" prop');
  4517. if (!selected.value.length) {
  4518. const item = items.find(item => !item.disabled);
  4519. item && (selected.value = [item.id]);
  4520. } else {
  4521. const currentId = selected.value[0];
  4522. const currentIndex = items.findIndex(i => i.id === currentId);
  4523. let newIndex = (currentIndex + offset) % items.length;
  4524. let newItem = items[newIndex];
  4525. while (newItem.disabled && newIndex !== currentIndex) {
  4526. newIndex = (newIndex + offset) % items.length;
  4527. newItem = items[newIndex];
  4528. }
  4529. if (newItem.disabled) return;
  4530. selected.value = [items[newIndex].id];
  4531. }
  4532. }
  4533. const state = {
  4534. register,
  4535. unregister,
  4536. selected,
  4537. select,
  4538. disabled: vue.toRef(props, 'disabled'),
  4539. prev: () => step(items.length - 1),
  4540. next: () => step(1),
  4541. isSelected: id => selected.value.includes(id),
  4542. selectedClass: vue.computed(() => props.selectedClass),
  4543. items: vue.computed(() => items),
  4544. getItemIndex: value => getItemIndex(items, value)
  4545. };
  4546. vue.provide(injectKey, state);
  4547. return state;
  4548. }
  4549. function getItemIndex(items, value) {
  4550. const ids = getIds(items, [value]);
  4551. if (!ids.length) return -1;
  4552. return items.findIndex(item => item.id === ids[0]);
  4553. }
  4554. function getIds(items, modelValue) {
  4555. const ids = [];
  4556. modelValue.forEach(value => {
  4557. const item = items.find(item => deepEqual(value, item.value));
  4558. const itemByIndex = items[value];
  4559. if (item?.value != null) {
  4560. ids.push(item.id);
  4561. } else if (itemByIndex != null) {
  4562. ids.push(itemByIndex.id);
  4563. }
  4564. });
  4565. return ids;
  4566. }
  4567. function getValues(items, ids) {
  4568. const values = [];
  4569. ids.forEach(id => {
  4570. const itemIndex = items.findIndex(item => item.id === id);
  4571. if (~itemIndex) {
  4572. const item = items[itemIndex];
  4573. values.push(item.value != null ? item.value : itemIndex);
  4574. }
  4575. });
  4576. return values;
  4577. }
  4578. // Types
  4579. const VBtnToggleSymbol = Symbol.for('vuetify:v-btn-toggle');
  4580. const makeVBtnToggleProps = propsFactory({
  4581. ...makeVBtnGroupProps(),
  4582. ...makeGroupProps()
  4583. }, 'VBtnToggle');
  4584. const VBtnToggle = genericComponent()({
  4585. name: 'VBtnToggle',
  4586. props: makeVBtnToggleProps(),
  4587. emits: {
  4588. 'update:modelValue': value => true
  4589. },
  4590. setup(props, _ref) {
  4591. let {
  4592. slots
  4593. } = _ref;
  4594. const {
  4595. isSelected,
  4596. next,
  4597. prev,
  4598. select,
  4599. selected
  4600. } = useGroup(props, VBtnToggleSymbol);
  4601. useRender(() => {
  4602. const btnGroupProps = VBtnGroup.filterProps(props);
  4603. return vue.createVNode(VBtnGroup, vue.mergeProps({
  4604. "class": ['v-btn-toggle', props.class]
  4605. }, btnGroupProps, {
  4606. "style": props.style
  4607. }), {
  4608. default: () => [slots.default?.({
  4609. isSelected,
  4610. next,
  4611. prev,
  4612. select,
  4613. selected
  4614. })]
  4615. });
  4616. });
  4617. return {
  4618. next,
  4619. prev,
  4620. select
  4621. };
  4622. }
  4623. });
  4624. // Utilities
  4625. // Types
  4626. const predefinedSizes = ['x-small', 'small', 'default', 'large', 'x-large'];
  4627. // Composables
  4628. const makeSizeProps = propsFactory({
  4629. size: {
  4630. type: [String, Number],
  4631. default: 'default'
  4632. }
  4633. }, 'size');
  4634. function useSize(props) {
  4635. let name = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : getCurrentInstanceName();
  4636. return destructComputed(() => {
  4637. let sizeClasses;
  4638. let sizeStyles;
  4639. if (includes(predefinedSizes, props.size)) {
  4640. sizeClasses = `${name}--size-${props.size}`;
  4641. } else if (props.size) {
  4642. sizeStyles = {
  4643. width: convertToUnit(props.size),
  4644. height: convertToUnit(props.size)
  4645. };
  4646. }
  4647. return {
  4648. sizeClasses,
  4649. sizeStyles
  4650. };
  4651. });
  4652. }
  4653. const makeVIconProps = propsFactory({
  4654. color: String,
  4655. disabled: Boolean,
  4656. start: Boolean,
  4657. end: Boolean,
  4658. icon: IconValue,
  4659. ...makeComponentProps(),
  4660. ...makeSizeProps(),
  4661. ...makeTagProps({
  4662. tag: 'i'
  4663. }),
  4664. ...makeThemeProps()
  4665. }, 'VIcon');
  4666. const VIcon = genericComponent()({
  4667. name: 'VIcon',
  4668. props: makeVIconProps(),
  4669. setup(props, _ref) {
  4670. let {
  4671. attrs,
  4672. slots
  4673. } = _ref;
  4674. const slotIcon = vue.ref();
  4675. const {
  4676. themeClasses
  4677. } = provideTheme(props);
  4678. const {
  4679. iconData
  4680. } = useIcon(vue.computed(() => slotIcon.value || props.icon));
  4681. const {
  4682. sizeClasses
  4683. } = useSize(props);
  4684. const {
  4685. textColorClasses,
  4686. textColorStyles
  4687. } = useTextColor(vue.toRef(props, 'color'));
  4688. useRender(() => {
  4689. const slotValue = slots.default?.();
  4690. if (slotValue) {
  4691. slotIcon.value = flattenFragments(slotValue).filter(node => node.type === vue.Text && node.children && typeof node.children === 'string')[0]?.children;
  4692. }
  4693. const hasClick = !!(attrs.onClick || attrs.onClickOnce);
  4694. return vue.createVNode(iconData.value.component, {
  4695. "tag": props.tag,
  4696. "icon": iconData.value.icon,
  4697. "class": ['v-icon', 'notranslate', themeClasses.value, sizeClasses.value, textColorClasses.value, {
  4698. 'v-icon--clickable': hasClick,
  4699. 'v-icon--disabled': props.disabled,
  4700. 'v-icon--start': props.start,
  4701. 'v-icon--end': props.end
  4702. }, props.class],
  4703. "style": [!sizeClasses.value ? {
  4704. fontSize: convertToUnit(props.size),
  4705. height: convertToUnit(props.size),
  4706. width: convertToUnit(props.size)
  4707. } : undefined, textColorStyles.value, props.style],
  4708. "role": hasClick ? 'button' : undefined,
  4709. "aria-hidden": !hasClick,
  4710. "tabindex": hasClick ? props.disabled ? -1 : 0 : undefined
  4711. }, {
  4712. default: () => [slotValue]
  4713. });
  4714. });
  4715. return {};
  4716. }
  4717. });
  4718. // Utilities
  4719. function useIntersectionObserver(callback, options) {
  4720. const intersectionRef = vue.ref();
  4721. const isIntersecting = vue.shallowRef(false);
  4722. if (SUPPORTS_INTERSECTION) {
  4723. const observer = new IntersectionObserver(entries => {
  4724. callback?.(entries, observer);
  4725. isIntersecting.value = !!entries.find(entry => entry.isIntersecting);
  4726. }, options);
  4727. vue.onBeforeUnmount(() => {
  4728. observer.disconnect();
  4729. });
  4730. vue.watch(intersectionRef, (newValue, oldValue) => {
  4731. if (oldValue) {
  4732. observer.unobserve(oldValue);
  4733. isIntersecting.value = false;
  4734. }
  4735. if (newValue) observer.observe(newValue);
  4736. }, {
  4737. flush: 'post'
  4738. });
  4739. }
  4740. return {
  4741. intersectionRef,
  4742. isIntersecting
  4743. };
  4744. }
  4745. // Types
  4746. const makeVProgressCircularProps = propsFactory({
  4747. bgColor: String,
  4748. color: String,
  4749. indeterminate: [Boolean, String],
  4750. modelValue: {
  4751. type: [Number, String],
  4752. default: 0
  4753. },
  4754. rotate: {
  4755. type: [Number, String],
  4756. default: 0
  4757. },
  4758. width: {
  4759. type: [Number, String],
  4760. default: 4
  4761. },
  4762. ...makeComponentProps(),
  4763. ...makeSizeProps(),
  4764. ...makeTagProps({
  4765. tag: 'div'
  4766. }),
  4767. ...makeThemeProps()
  4768. }, 'VProgressCircular');
  4769. const VProgressCircular = genericComponent()({
  4770. name: 'VProgressCircular',
  4771. props: makeVProgressCircularProps(),
  4772. setup(props, _ref) {
  4773. let {
  4774. slots
  4775. } = _ref;
  4776. const MAGIC_RADIUS_CONSTANT = 20;
  4777. const CIRCUMFERENCE = 2 * Math.PI * MAGIC_RADIUS_CONSTANT;
  4778. const root = vue.ref();
  4779. const {
  4780. themeClasses
  4781. } = provideTheme(props);
  4782. const {
  4783. sizeClasses,
  4784. sizeStyles
  4785. } = useSize(props);
  4786. const {
  4787. textColorClasses,
  4788. textColorStyles
  4789. } = useTextColor(vue.toRef(props, 'color'));
  4790. const {
  4791. textColorClasses: underlayColorClasses,
  4792. textColorStyles: underlayColorStyles
  4793. } = useTextColor(vue.toRef(props, 'bgColor'));
  4794. const {
  4795. intersectionRef,
  4796. isIntersecting
  4797. } = useIntersectionObserver();
  4798. const {
  4799. resizeRef,
  4800. contentRect
  4801. } = useResizeObserver();
  4802. const normalizedValue = vue.computed(() => Math.max(0, Math.min(100, parseFloat(props.modelValue))));
  4803. const width = vue.computed(() => Number(props.width));
  4804. const size = vue.computed(() => {
  4805. // Get size from element if size prop value is small, large etc
  4806. return sizeStyles.value ? Number(props.size) : contentRect.value ? contentRect.value.width : Math.max(width.value, 32);
  4807. });
  4808. const diameter = vue.computed(() => MAGIC_RADIUS_CONSTANT / (1 - width.value / size.value) * 2);
  4809. const strokeWidth = vue.computed(() => width.value / size.value * diameter.value);
  4810. const strokeDashOffset = vue.computed(() => convertToUnit((100 - normalizedValue.value) / 100 * CIRCUMFERENCE));
  4811. vue.watchEffect(() => {
  4812. intersectionRef.value = root.value;
  4813. resizeRef.value = root.value;
  4814. });
  4815. useRender(() => vue.createVNode(props.tag, {
  4816. "ref": root,
  4817. "class": ['v-progress-circular', {
  4818. 'v-progress-circular--indeterminate': !!props.indeterminate,
  4819. 'v-progress-circular--visible': isIntersecting.value,
  4820. 'v-progress-circular--disable-shrink': props.indeterminate === 'disable-shrink'
  4821. }, themeClasses.value, sizeClasses.value, textColorClasses.value, props.class],
  4822. "style": [sizeStyles.value, textColorStyles.value, props.style],
  4823. "role": "progressbar",
  4824. "aria-valuemin": "0",
  4825. "aria-valuemax": "100",
  4826. "aria-valuenow": props.indeterminate ? undefined : normalizedValue.value
  4827. }, {
  4828. default: () => [vue.createVNode("svg", {
  4829. "style": {
  4830. transform: `rotate(calc(-90deg + ${Number(props.rotate)}deg))`
  4831. },
  4832. "xmlns": "http://www.w3.org/2000/svg",
  4833. "viewBox": `0 0 ${diameter.value} ${diameter.value}`
  4834. }, [vue.createVNode("circle", {
  4835. "class": ['v-progress-circular__underlay', underlayColorClasses.value],
  4836. "style": underlayColorStyles.value,
  4837. "fill": "transparent",
  4838. "cx": "50%",
  4839. "cy": "50%",
  4840. "r": MAGIC_RADIUS_CONSTANT,
  4841. "stroke-width": strokeWidth.value,
  4842. "stroke-dasharray": CIRCUMFERENCE,
  4843. "stroke-dashoffset": 0
  4844. }, null), vue.createVNode("circle", {
  4845. "class": "v-progress-circular__overlay",
  4846. "fill": "transparent",
  4847. "cx": "50%",
  4848. "cy": "50%",
  4849. "r": MAGIC_RADIUS_CONSTANT,
  4850. "stroke-width": strokeWidth.value,
  4851. "stroke-dasharray": CIRCUMFERENCE,
  4852. "stroke-dashoffset": strokeDashOffset.value
  4853. }, null)]), slots.default && vue.createVNode("div", {
  4854. "class": "v-progress-circular__content"
  4855. }, [slots.default({
  4856. value: normalizedValue.value
  4857. })])]
  4858. }));
  4859. return {};
  4860. }
  4861. });
  4862. // Composables
  4863. // Types
  4864. const oppositeMap = {
  4865. center: 'center',
  4866. top: 'bottom',
  4867. bottom: 'top',
  4868. left: 'right',
  4869. right: 'left'
  4870. };
  4871. const makeLocationProps = propsFactory({
  4872. location: String
  4873. }, 'location');
  4874. function useLocation(props) {
  4875. let opposite = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : false;
  4876. let offset = arguments.length > 2 ? arguments[2] : undefined;
  4877. const {
  4878. isRtl
  4879. } = useRtl();
  4880. const locationStyles = vue.computed(() => {
  4881. if (!props.location) return {};
  4882. const {
  4883. side,
  4884. align
  4885. } = parseAnchor(props.location.split(' ').length > 1 ? props.location : `${props.location} center`, isRtl.value);
  4886. function getOffset(side) {
  4887. return offset ? offset(side) : 0;
  4888. }
  4889. const styles = {};
  4890. if (side !== 'center') {
  4891. if (opposite) styles[oppositeMap[side]] = `calc(100% - ${getOffset(side)}px)`;else styles[side] = 0;
  4892. }
  4893. if (align !== 'center') {
  4894. if (opposite) styles[oppositeMap[align]] = `calc(100% - ${getOffset(align)}px)`;else styles[align] = 0;
  4895. } else {
  4896. if (side === 'center') styles.top = styles.left = '50%';else {
  4897. styles[{
  4898. top: 'left',
  4899. bottom: 'left',
  4900. left: 'top',
  4901. right: 'top'
  4902. }[side]] = '50%';
  4903. }
  4904. styles.transform = {
  4905. top: 'translateX(-50%)',
  4906. bottom: 'translateX(-50%)',
  4907. left: 'translateY(-50%)',
  4908. right: 'translateY(-50%)',
  4909. center: 'translate(-50%, -50%)'
  4910. }[side];
  4911. }
  4912. return styles;
  4913. });
  4914. return {
  4915. locationStyles
  4916. };
  4917. }
  4918. const makeVProgressLinearProps = propsFactory({
  4919. absolute: Boolean,
  4920. active: {
  4921. type: Boolean,
  4922. default: true
  4923. },
  4924. bgColor: String,
  4925. bgOpacity: [Number, String],
  4926. bufferValue: {
  4927. type: [Number, String],
  4928. default: 0
  4929. },
  4930. bufferColor: String,
  4931. bufferOpacity: [Number, String],
  4932. clickable: Boolean,
  4933. color: String,
  4934. height: {
  4935. type: [Number, String],
  4936. default: 4
  4937. },
  4938. indeterminate: Boolean,
  4939. max: {
  4940. type: [Number, String],
  4941. default: 100
  4942. },
  4943. modelValue: {
  4944. type: [Number, String],
  4945. default: 0
  4946. },
  4947. opacity: [Number, String],
  4948. reverse: Boolean,
  4949. stream: Boolean,
  4950. striped: Boolean,
  4951. roundedBar: Boolean,
  4952. ...makeComponentProps(),
  4953. ...makeLocationProps({
  4954. location: 'top'
  4955. }),
  4956. ...makeRoundedProps(),
  4957. ...makeTagProps(),
  4958. ...makeThemeProps()
  4959. }, 'VProgressLinear');
  4960. const VProgressLinear = genericComponent()({
  4961. name: 'VProgressLinear',
  4962. props: makeVProgressLinearProps(),
  4963. emits: {
  4964. 'update:modelValue': value => true
  4965. },
  4966. setup(props, _ref) {
  4967. let {
  4968. slots
  4969. } = _ref;
  4970. const progress = useProxiedModel(props, 'modelValue');
  4971. const {
  4972. isRtl,
  4973. rtlClasses
  4974. } = useRtl();
  4975. const {
  4976. themeClasses
  4977. } = provideTheme(props);
  4978. const {
  4979. locationStyles
  4980. } = useLocation(props);
  4981. const {
  4982. textColorClasses,
  4983. textColorStyles
  4984. } = useTextColor(props, 'color');
  4985. const {
  4986. backgroundColorClasses,
  4987. backgroundColorStyles
  4988. } = useBackgroundColor(vue.computed(() => props.bgColor || props.color));
  4989. const {
  4990. backgroundColorClasses: bufferColorClasses,
  4991. backgroundColorStyles: bufferColorStyles
  4992. } = useBackgroundColor(vue.computed(() => props.bufferColor || props.bgColor || props.color));
  4993. const {
  4994. backgroundColorClasses: barColorClasses,
  4995. backgroundColorStyles: barColorStyles
  4996. } = useBackgroundColor(props, 'color');
  4997. const {
  4998. roundedClasses
  4999. } = useRounded(props);
  5000. const {
  5001. intersectionRef,
  5002. isIntersecting
  5003. } = useIntersectionObserver();
  5004. const max = vue.computed(() => parseFloat(props.max));
  5005. const height = vue.computed(() => parseFloat(props.height));
  5006. const normalizedBuffer = vue.computed(() => clamp(parseFloat(props.bufferValue) / max.value * 100, 0, 100));
  5007. const normalizedValue = vue.computed(() => clamp(parseFloat(progress.value) / max.value * 100, 0, 100));
  5008. const isReversed = vue.computed(() => isRtl.value !== props.reverse);
  5009. const transition = vue.computed(() => props.indeterminate ? 'fade-transition' : 'slide-x-transition');
  5010. const isForcedColorsModeActive = IN_BROWSER && window.matchMedia?.('(forced-colors: active)').matches;
  5011. function handleClick(e) {
  5012. if (!intersectionRef.value) return;
  5013. const {
  5014. left,
  5015. right,
  5016. width
  5017. } = intersectionRef.value.getBoundingClientRect();
  5018. const value = isReversed.value ? width - e.clientX + (right - width) : e.clientX - left;
  5019. progress.value = Math.round(value / width * max.value);
  5020. }
  5021. useRender(() => vue.createVNode(props.tag, {
  5022. "ref": intersectionRef,
  5023. "class": ['v-progress-linear', {
  5024. 'v-progress-linear--absolute': props.absolute,
  5025. 'v-progress-linear--active': props.active && isIntersecting.value,
  5026. 'v-progress-linear--reverse': isReversed.value,
  5027. 'v-progress-linear--rounded': props.rounded,
  5028. 'v-progress-linear--rounded-bar': props.roundedBar,
  5029. 'v-progress-linear--striped': props.striped
  5030. }, roundedClasses.value, themeClasses.value, rtlClasses.value, props.class],
  5031. "style": [{
  5032. bottom: props.location === 'bottom' ? 0 : undefined,
  5033. top: props.location === 'top' ? 0 : undefined,
  5034. height: props.active ? convertToUnit(height.value) : 0,
  5035. '--v-progress-linear-height': convertToUnit(height.value),
  5036. ...(props.absolute ? locationStyles.value : {})
  5037. }, props.style],
  5038. "role": "progressbar",
  5039. "aria-hidden": props.active ? 'false' : 'true',
  5040. "aria-valuemin": "0",
  5041. "aria-valuemax": props.max,
  5042. "aria-valuenow": props.indeterminate ? undefined : normalizedValue.value,
  5043. "onClick": props.clickable && handleClick
  5044. }, {
  5045. default: () => [props.stream && vue.createVNode("div", {
  5046. "key": "stream",
  5047. "class": ['v-progress-linear__stream', textColorClasses.value],
  5048. "style": {
  5049. ...textColorStyles.value,
  5050. [isReversed.value ? 'left' : 'right']: convertToUnit(-height.value),
  5051. borderTop: `${convertToUnit(height.value / 2)} dotted`,
  5052. opacity: parseFloat(props.bufferOpacity),
  5053. top: `calc(50% - ${convertToUnit(height.value / 4)})`,
  5054. width: convertToUnit(100 - normalizedBuffer.value, '%'),
  5055. '--v-progress-linear-stream-to': convertToUnit(height.value * (isReversed.value ? 1 : -1))
  5056. }
  5057. }, null), vue.createVNode("div", {
  5058. "class": ['v-progress-linear__background', !isForcedColorsModeActive ? backgroundColorClasses.value : undefined],
  5059. "style": [backgroundColorStyles.value, {
  5060. opacity: parseFloat(props.bgOpacity),
  5061. width: props.stream ? 0 : undefined
  5062. }]
  5063. }, null), vue.createVNode("div", {
  5064. "class": ['v-progress-linear__buffer', !isForcedColorsModeActive ? bufferColorClasses.value : undefined],
  5065. "style": [bufferColorStyles.value, {
  5066. opacity: parseFloat(props.bufferOpacity),
  5067. width: convertToUnit(normalizedBuffer.value, '%')
  5068. }]
  5069. }, null), vue.createVNode(vue.Transition, {
  5070. "name": transition.value
  5071. }, {
  5072. default: () => [!props.indeterminate ? vue.createVNode("div", {
  5073. "class": ['v-progress-linear__determinate', !isForcedColorsModeActive ? barColorClasses.value : undefined],
  5074. "style": [barColorStyles.value, {
  5075. width: convertToUnit(normalizedValue.value, '%')
  5076. }]
  5077. }, null) : vue.createVNode("div", {
  5078. "class": "v-progress-linear__indeterminate"
  5079. }, [['long', 'short'].map(bar => vue.createVNode("div", {
  5080. "key": bar,
  5081. "class": ['v-progress-linear__indeterminate', bar, !isForcedColorsModeActive ? barColorClasses.value : undefined],
  5082. "style": barColorStyles.value
  5083. }, null))])]
  5084. }), slots.default && vue.createVNode("div", {
  5085. "class": "v-progress-linear__content"
  5086. }, [slots.default({
  5087. value: normalizedValue.value,
  5088. buffer: normalizedBuffer.value
  5089. })])]
  5090. }));
  5091. return {};
  5092. }
  5093. });
  5094. // Types
  5095. // Composables
  5096. const makeLoaderProps = propsFactory({
  5097. loading: [Boolean, String]
  5098. }, 'loader');
  5099. function useLoader(props) {
  5100. let name = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : getCurrentInstanceName();
  5101. const loaderClasses = vue.computed(() => ({
  5102. [`${name}--loading`]: props.loading
  5103. }));
  5104. return {
  5105. loaderClasses
  5106. };
  5107. }
  5108. function LoaderSlot(props, _ref) {
  5109. let {
  5110. slots
  5111. } = _ref;
  5112. return vue.createVNode("div", {
  5113. "class": `${props.name}__loader`
  5114. }, [slots.default?.({
  5115. color: props.color,
  5116. isActive: props.active
  5117. }) || vue.createVNode(VProgressLinear, {
  5118. "absolute": props.absolute,
  5119. "active": props.active,
  5120. "color": props.color,
  5121. "height": "2",
  5122. "indeterminate": true
  5123. }, null)]);
  5124. }
  5125. // Utilities
  5126. // Types
  5127. const positionValues = ['static', 'relative', 'fixed', 'absolute', 'sticky'];
  5128. // Composables
  5129. const makePositionProps = propsFactory({
  5130. position: {
  5131. type: String,
  5132. validator: /* istanbul ignore next */v => positionValues.includes(v)
  5133. }
  5134. }, 'position');
  5135. function usePosition(props) {
  5136. let name = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : getCurrentInstanceName();
  5137. const positionClasses = vue.computed(() => {
  5138. return props.position ? `${name}--${props.position}` : undefined;
  5139. });
  5140. return {
  5141. positionClasses
  5142. };
  5143. }
  5144. // Utilities
  5145. // Types
  5146. function useRoute() {
  5147. const vm = getCurrentInstance('useRoute');
  5148. return vue.computed(() => vm?.proxy?.$route);
  5149. }
  5150. function useRouter() {
  5151. return getCurrentInstance('useRouter')?.proxy?.$router;
  5152. }
  5153. function useLink(props, attrs) {
  5154. const RouterLink = vue.resolveDynamicComponent('RouterLink');
  5155. const isLink = vue.computed(() => !!(props.href || props.to));
  5156. const isClickable = vue.computed(() => {
  5157. return isLink?.value || hasEvent(attrs, 'click') || hasEvent(props, 'click');
  5158. });
  5159. if (typeof RouterLink === 'string' || !('useLink' in RouterLink)) {
  5160. const href = vue.toRef(props, 'href');
  5161. return {
  5162. isLink,
  5163. isClickable,
  5164. href,
  5165. linkProps: vue.reactive({
  5166. href
  5167. })
  5168. };
  5169. }
  5170. // vue-router useLink `to` prop needs to be reactive and useLink will crash if undefined
  5171. const linkProps = vue.computed(() => ({
  5172. ...props,
  5173. to: vue.toRef(() => props.to || '')
  5174. }));
  5175. const routerLink = RouterLink.useLink(linkProps.value);
  5176. // Actual link needs to be undefined when to prop is not used
  5177. const link = vue.computed(() => props.to ? routerLink : undefined);
  5178. const route = useRoute();
  5179. const isActive = vue.computed(() => {
  5180. if (!link.value) return false;
  5181. if (!props.exact) return link.value.isActive?.value ?? false;
  5182. if (!route.value) return link.value.isExactActive?.value ?? false;
  5183. return link.value.isExactActive?.value && deepEqual(link.value.route.value.query, route.value.query);
  5184. });
  5185. const href = vue.computed(() => props.to ? link.value?.route.value.href : props.href);
  5186. return {
  5187. isLink,
  5188. isClickable,
  5189. isActive,
  5190. route: link.value?.route,
  5191. navigate: link.value?.navigate,
  5192. href,
  5193. linkProps: vue.reactive({
  5194. href,
  5195. 'aria-current': vue.computed(() => isActive.value ? 'page' : undefined)
  5196. })
  5197. };
  5198. }
  5199. const makeRouterProps = propsFactory({
  5200. href: String,
  5201. replace: Boolean,
  5202. to: [String, Object],
  5203. exact: Boolean
  5204. }, 'router');
  5205. let inTransition = false;
  5206. function useBackButton(router, cb) {
  5207. let popped = false;
  5208. let removeBefore;
  5209. let removeAfter;
  5210. if (IN_BROWSER) {
  5211. vue.nextTick(() => {
  5212. window.addEventListener('popstate', onPopstate);
  5213. removeBefore = router?.beforeEach((to, from, next) => {
  5214. if (!inTransition) {
  5215. setTimeout(() => popped ? cb(next) : next());
  5216. } else {
  5217. popped ? cb(next) : next();
  5218. }
  5219. inTransition = true;
  5220. });
  5221. removeAfter = router?.afterEach(() => {
  5222. inTransition = false;
  5223. });
  5224. });
  5225. vue.onScopeDispose(() => {
  5226. window.removeEventListener('popstate', onPopstate);
  5227. removeBefore?.();
  5228. removeAfter?.();
  5229. });
  5230. }
  5231. function onPopstate(e) {
  5232. if (e.state?.replaced) return;
  5233. popped = true;
  5234. setTimeout(() => popped = false);
  5235. }
  5236. }
  5237. // Utilities
  5238. // Types
  5239. function useSelectLink(link, select) {
  5240. vue.watch(() => link.isActive?.value, isActive => {
  5241. if (link.isLink.value && isActive && select) {
  5242. vue.nextTick(() => {
  5243. select(true);
  5244. });
  5245. }
  5246. }, {
  5247. immediate: true
  5248. });
  5249. }
  5250. // Styles
  5251. // Types
  5252. const stopSymbol = Symbol('rippleStop');
  5253. const DELAY_RIPPLE = 80;
  5254. function transform(el, value) {
  5255. el.style.transform = value;
  5256. el.style.webkitTransform = value;
  5257. }
  5258. function isTouchEvent(e) {
  5259. return e.constructor.name === 'TouchEvent';
  5260. }
  5261. function isKeyboardEvent(e) {
  5262. return e.constructor.name === 'KeyboardEvent';
  5263. }
  5264. const calculate = function (e, el) {
  5265. let value = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {};
  5266. let localX = 0;
  5267. let localY = 0;
  5268. if (!isKeyboardEvent(e)) {
  5269. const offset = el.getBoundingClientRect();
  5270. const target = isTouchEvent(e) ? e.touches[e.touches.length - 1] : e;
  5271. localX = target.clientX - offset.left;
  5272. localY = target.clientY - offset.top;
  5273. }
  5274. let radius = 0;
  5275. let scale = 0.3;
  5276. if (el._ripple?.circle) {
  5277. scale = 0.15;
  5278. radius = el.clientWidth / 2;
  5279. radius = value.center ? radius : radius + Math.sqrt((localX - radius) ** 2 + (localY - radius) ** 2) / 4;
  5280. } else {
  5281. radius = Math.sqrt(el.clientWidth ** 2 + el.clientHeight ** 2) / 2;
  5282. }
  5283. const centerX = `${(el.clientWidth - radius * 2) / 2}px`;
  5284. const centerY = `${(el.clientHeight - radius * 2) / 2}px`;
  5285. const x = value.center ? centerX : `${localX - radius}px`;
  5286. const y = value.center ? centerY : `${localY - radius}px`;
  5287. return {
  5288. radius,
  5289. scale,
  5290. x,
  5291. y,
  5292. centerX,
  5293. centerY
  5294. };
  5295. };
  5296. const ripples = {
  5297. /* eslint-disable max-statements */
  5298. show(e, el) {
  5299. let value = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {};
  5300. if (!el?._ripple?.enabled) {
  5301. return;
  5302. }
  5303. const container = document.createElement('span');
  5304. const animation = document.createElement('span');
  5305. container.appendChild(animation);
  5306. container.className = 'v-ripple__container';
  5307. if (value.class) {
  5308. container.className += ` ${value.class}`;
  5309. }
  5310. const {
  5311. radius,
  5312. scale,
  5313. x,
  5314. y,
  5315. centerX,
  5316. centerY
  5317. } = calculate(e, el, value);
  5318. const size = `${radius * 2}px`;
  5319. animation.className = 'v-ripple__animation';
  5320. animation.style.width = size;
  5321. animation.style.height = size;
  5322. el.appendChild(container);
  5323. const computed = window.getComputedStyle(el);
  5324. if (computed && computed.position === 'static') {
  5325. el.style.position = 'relative';
  5326. el.dataset.previousPosition = 'static';
  5327. }
  5328. animation.classList.add('v-ripple__animation--enter');
  5329. animation.classList.add('v-ripple__animation--visible');
  5330. transform(animation, `translate(${x}, ${y}) scale3d(${scale},${scale},${scale})`);
  5331. animation.dataset.activated = String(performance.now());
  5332. setTimeout(() => {
  5333. animation.classList.remove('v-ripple__animation--enter');
  5334. animation.classList.add('v-ripple__animation--in');
  5335. transform(animation, `translate(${centerX}, ${centerY}) scale3d(1,1,1)`);
  5336. }, 0);
  5337. },
  5338. hide(el) {
  5339. if (!el?._ripple?.enabled) return;
  5340. const ripples = el.getElementsByClassName('v-ripple__animation');
  5341. if (ripples.length === 0) return;
  5342. const animation = ripples[ripples.length - 1];
  5343. if (animation.dataset.isHiding) return;else animation.dataset.isHiding = 'true';
  5344. const diff = performance.now() - Number(animation.dataset.activated);
  5345. const delay = Math.max(250 - diff, 0);
  5346. setTimeout(() => {
  5347. animation.classList.remove('v-ripple__animation--in');
  5348. animation.classList.add('v-ripple__animation--out');
  5349. setTimeout(() => {
  5350. const ripples = el.getElementsByClassName('v-ripple__animation');
  5351. if (ripples.length === 1 && el.dataset.previousPosition) {
  5352. el.style.position = el.dataset.previousPosition;
  5353. delete el.dataset.previousPosition;
  5354. }
  5355. if (animation.parentNode?.parentNode === el) el.removeChild(animation.parentNode);
  5356. }, 300);
  5357. }, delay);
  5358. }
  5359. };
  5360. function isRippleEnabled(value) {
  5361. return typeof value === 'undefined' || !!value;
  5362. }
  5363. function rippleShow(e) {
  5364. const value = {};
  5365. const element = e.currentTarget;
  5366. if (!element?._ripple || element._ripple.touched || e[stopSymbol]) return;
  5367. // Don't allow the event to trigger ripples on any other elements
  5368. e[stopSymbol] = true;
  5369. if (isTouchEvent(e)) {
  5370. element._ripple.touched = true;
  5371. element._ripple.isTouch = true;
  5372. } else {
  5373. // It's possible for touch events to fire
  5374. // as mouse events on Android/iOS, this
  5375. // will skip the event call if it has
  5376. // already been registered as touch
  5377. if (element._ripple.isTouch) return;
  5378. }
  5379. value.center = element._ripple.centered || isKeyboardEvent(e);
  5380. if (element._ripple.class) {
  5381. value.class = element._ripple.class;
  5382. }
  5383. if (isTouchEvent(e)) {
  5384. // already queued that shows or hides the ripple
  5385. if (element._ripple.showTimerCommit) return;
  5386. element._ripple.showTimerCommit = () => {
  5387. ripples.show(e, element, value);
  5388. };
  5389. element._ripple.showTimer = window.setTimeout(() => {
  5390. if (element?._ripple?.showTimerCommit) {
  5391. element._ripple.showTimerCommit();
  5392. element._ripple.showTimerCommit = null;
  5393. }
  5394. }, DELAY_RIPPLE);
  5395. } else {
  5396. ripples.show(e, element, value);
  5397. }
  5398. }
  5399. function rippleStop(e) {
  5400. e[stopSymbol] = true;
  5401. }
  5402. function rippleHide(e) {
  5403. const element = e.currentTarget;
  5404. if (!element?._ripple) return;
  5405. window.clearTimeout(element._ripple.showTimer);
  5406. // The touch interaction occurs before the show timer is triggered.
  5407. // We still want to show ripple effect.
  5408. if (e.type === 'touchend' && element._ripple.showTimerCommit) {
  5409. element._ripple.showTimerCommit();
  5410. element._ripple.showTimerCommit = null;
  5411. // re-queue ripple hiding
  5412. element._ripple.showTimer = window.setTimeout(() => {
  5413. rippleHide(e);
  5414. });
  5415. return;
  5416. }
  5417. window.setTimeout(() => {
  5418. if (element._ripple) {
  5419. element._ripple.touched = false;
  5420. }
  5421. });
  5422. ripples.hide(element);
  5423. }
  5424. function rippleCancelShow(e) {
  5425. const element = e.currentTarget;
  5426. if (!element?._ripple) return;
  5427. if (element._ripple.showTimerCommit) {
  5428. element._ripple.showTimerCommit = null;
  5429. }
  5430. window.clearTimeout(element._ripple.showTimer);
  5431. }
  5432. let keyboardRipple = false;
  5433. function keyboardRippleShow(e) {
  5434. if (!keyboardRipple && (e.keyCode === keyCodes.enter || e.keyCode === keyCodes.space)) {
  5435. keyboardRipple = true;
  5436. rippleShow(e);
  5437. }
  5438. }
  5439. function keyboardRippleHide(e) {
  5440. keyboardRipple = false;
  5441. rippleHide(e);
  5442. }
  5443. function focusRippleHide(e) {
  5444. if (keyboardRipple) {
  5445. keyboardRipple = false;
  5446. rippleHide(e);
  5447. }
  5448. }
  5449. function updateRipple(el, binding, wasEnabled) {
  5450. const {
  5451. value,
  5452. modifiers
  5453. } = binding;
  5454. const enabled = isRippleEnabled(value);
  5455. if (!enabled) {
  5456. ripples.hide(el);
  5457. }
  5458. el._ripple = el._ripple ?? {};
  5459. el._ripple.enabled = enabled;
  5460. el._ripple.centered = modifiers.center;
  5461. el._ripple.circle = modifiers.circle;
  5462. if (isObject(value) && value.class) {
  5463. el._ripple.class = value.class;
  5464. }
  5465. if (enabled && !wasEnabled) {
  5466. if (modifiers.stop) {
  5467. el.addEventListener('touchstart', rippleStop, {
  5468. passive: true
  5469. });
  5470. el.addEventListener('mousedown', rippleStop);
  5471. return;
  5472. }
  5473. el.addEventListener('touchstart', rippleShow, {
  5474. passive: true
  5475. });
  5476. el.addEventListener('touchend', rippleHide, {
  5477. passive: true
  5478. });
  5479. el.addEventListener('touchmove', rippleCancelShow, {
  5480. passive: true
  5481. });
  5482. el.addEventListener('touchcancel', rippleHide);
  5483. el.addEventListener('mousedown', rippleShow);
  5484. el.addEventListener('mouseup', rippleHide);
  5485. el.addEventListener('mouseleave', rippleHide);
  5486. el.addEventListener('keydown', keyboardRippleShow);
  5487. el.addEventListener('keyup', keyboardRippleHide);
  5488. el.addEventListener('blur', focusRippleHide);
  5489. // Anchor tags can be dragged, causes other hides to fail - #1537
  5490. el.addEventListener('dragstart', rippleHide, {
  5491. passive: true
  5492. });
  5493. } else if (!enabled && wasEnabled) {
  5494. removeListeners(el);
  5495. }
  5496. }
  5497. function removeListeners(el) {
  5498. el.removeEventListener('mousedown', rippleShow);
  5499. el.removeEventListener('touchstart', rippleShow);
  5500. el.removeEventListener('touchend', rippleHide);
  5501. el.removeEventListener('touchmove', rippleCancelShow);
  5502. el.removeEventListener('touchcancel', rippleHide);
  5503. el.removeEventListener('mouseup', rippleHide);
  5504. el.removeEventListener('mouseleave', rippleHide);
  5505. el.removeEventListener('keydown', keyboardRippleShow);
  5506. el.removeEventListener('keyup', keyboardRippleHide);
  5507. el.removeEventListener('dragstart', rippleHide);
  5508. el.removeEventListener('blur', focusRippleHide);
  5509. }
  5510. function mounted$4(el, binding) {
  5511. updateRipple(el, binding, false);
  5512. }
  5513. function unmounted$4(el) {
  5514. delete el._ripple;
  5515. removeListeners(el);
  5516. }
  5517. function updated$1(el, binding) {
  5518. if (binding.value === binding.oldValue) {
  5519. return;
  5520. }
  5521. const wasEnabled = isRippleEnabled(binding.oldValue);
  5522. updateRipple(el, binding, wasEnabled);
  5523. }
  5524. const Ripple = {
  5525. mounted: mounted$4,
  5526. unmounted: unmounted$4,
  5527. updated: updated$1
  5528. };
  5529. // Types
  5530. const makeVBtnProps = propsFactory({
  5531. active: {
  5532. type: Boolean,
  5533. default: undefined
  5534. },
  5535. activeColor: String,
  5536. baseColor: String,
  5537. symbol: {
  5538. type: null,
  5539. default: VBtnToggleSymbol
  5540. },
  5541. flat: Boolean,
  5542. icon: [Boolean, String, Function, Object],
  5543. prependIcon: IconValue,
  5544. appendIcon: IconValue,
  5545. block: Boolean,
  5546. readonly: Boolean,
  5547. slim: Boolean,
  5548. stacked: Boolean,
  5549. ripple: {
  5550. type: [Boolean, Object],
  5551. default: true
  5552. },
  5553. text: String,
  5554. ...makeBorderProps(),
  5555. ...makeComponentProps(),
  5556. ...makeDensityProps(),
  5557. ...makeDimensionProps(),
  5558. ...makeElevationProps(),
  5559. ...makeGroupItemProps(),
  5560. ...makeLoaderProps(),
  5561. ...makeLocationProps(),
  5562. ...makePositionProps(),
  5563. ...makeRoundedProps(),
  5564. ...makeRouterProps(),
  5565. ...makeSizeProps(),
  5566. ...makeTagProps({
  5567. tag: 'button'
  5568. }),
  5569. ...makeThemeProps(),
  5570. ...makeVariantProps({
  5571. variant: 'elevated'
  5572. })
  5573. }, 'VBtn');
  5574. const VBtn = genericComponent()({
  5575. name: 'VBtn',
  5576. props: makeVBtnProps(),
  5577. emits: {
  5578. 'group:selected': val => true
  5579. },
  5580. setup(props, _ref) {
  5581. let {
  5582. attrs,
  5583. slots
  5584. } = _ref;
  5585. const {
  5586. themeClasses
  5587. } = provideTheme(props);
  5588. const {
  5589. borderClasses
  5590. } = useBorder(props);
  5591. const {
  5592. densityClasses
  5593. } = useDensity(props);
  5594. const {
  5595. dimensionStyles
  5596. } = useDimension(props);
  5597. const {
  5598. elevationClasses
  5599. } = useElevation(props);
  5600. const {
  5601. loaderClasses
  5602. } = useLoader(props);
  5603. const {
  5604. locationStyles
  5605. } = useLocation(props);
  5606. const {
  5607. positionClasses
  5608. } = usePosition(props);
  5609. const {
  5610. roundedClasses
  5611. } = useRounded(props);
  5612. const {
  5613. sizeClasses,
  5614. sizeStyles
  5615. } = useSize(props);
  5616. const group = useGroupItem(props, props.symbol, false);
  5617. const link = useLink(props, attrs);
  5618. const isActive = vue.computed(() => {
  5619. if (props.active !== undefined) {
  5620. return props.active;
  5621. }
  5622. if (link.isLink.value) {
  5623. return link.isActive?.value;
  5624. }
  5625. return group?.isSelected.value;
  5626. });
  5627. const color = vue.computed(() => isActive.value ? props.activeColor ?? props.color : props.color);
  5628. const variantProps = vue.computed(() => {
  5629. const showColor = group?.isSelected.value && (!link.isLink.value || link.isActive?.value) || !group || link.isActive?.value;
  5630. return {
  5631. color: showColor ? color.value ?? props.baseColor : props.baseColor,
  5632. variant: props.variant
  5633. };
  5634. });
  5635. const {
  5636. colorClasses,
  5637. colorStyles,
  5638. variantClasses
  5639. } = useVariant(variantProps);
  5640. const isDisabled = vue.computed(() => group?.disabled.value || props.disabled);
  5641. const isElevated = vue.computed(() => {
  5642. return props.variant === 'elevated' && !(props.disabled || props.flat || props.border);
  5643. });
  5644. const valueAttr = vue.computed(() => {
  5645. if (props.value === undefined || typeof props.value === 'symbol') return undefined;
  5646. return Object(props.value) === props.value ? JSON.stringify(props.value, null, 0) : props.value;
  5647. });
  5648. function onClick(e) {
  5649. if (isDisabled.value || link.isLink.value && (e.metaKey || e.ctrlKey || e.shiftKey || e.button !== 0 || attrs.target === '_blank')) return;
  5650. link.navigate?.(e);
  5651. group?.toggle();
  5652. }
  5653. useSelectLink(link, group?.select);
  5654. useRender(() => {
  5655. const Tag = link.isLink.value ? 'a' : props.tag;
  5656. const hasPrepend = !!(props.prependIcon || slots.prepend);
  5657. const hasAppend = !!(props.appendIcon || slots.append);
  5658. const hasIcon = !!(props.icon && props.icon !== true);
  5659. return vue.withDirectives(vue.createVNode(Tag, vue.mergeProps({
  5660. "type": Tag === 'a' ? undefined : 'button',
  5661. "class": ['v-btn', group?.selectedClass.value, {
  5662. 'v-btn--active': isActive.value,
  5663. 'v-btn--block': props.block,
  5664. 'v-btn--disabled': isDisabled.value,
  5665. 'v-btn--elevated': isElevated.value,
  5666. 'v-btn--flat': props.flat,
  5667. 'v-btn--icon': !!props.icon,
  5668. 'v-btn--loading': props.loading,
  5669. 'v-btn--readonly': props.readonly,
  5670. 'v-btn--slim': props.slim,
  5671. 'v-btn--stacked': props.stacked
  5672. }, themeClasses.value, borderClasses.value, colorClasses.value, densityClasses.value, elevationClasses.value, loaderClasses.value, positionClasses.value, roundedClasses.value, sizeClasses.value, variantClasses.value, props.class],
  5673. "style": [colorStyles.value, dimensionStyles.value, locationStyles.value, sizeStyles.value, props.style],
  5674. "aria-busy": props.loading ? true : undefined,
  5675. "disabled": isDisabled.value || undefined,
  5676. "tabindex": props.loading || props.readonly ? -1 : undefined,
  5677. "onClick": onClick,
  5678. "value": valueAttr.value
  5679. }, link.linkProps), {
  5680. default: () => [genOverlays(true, 'v-btn'), !props.icon && hasPrepend && vue.createVNode("span", {
  5681. "key": "prepend",
  5682. "class": "v-btn__prepend"
  5683. }, [!slots.prepend ? vue.createVNode(VIcon, {
  5684. "key": "prepend-icon",
  5685. "icon": props.prependIcon
  5686. }, null) : vue.createVNode(VDefaultsProvider, {
  5687. "key": "prepend-defaults",
  5688. "disabled": !props.prependIcon,
  5689. "defaults": {
  5690. VIcon: {
  5691. icon: props.prependIcon
  5692. }
  5693. }
  5694. }, slots.prepend)]), vue.createVNode("span", {
  5695. "class": "v-btn__content",
  5696. "data-no-activator": ""
  5697. }, [!slots.default && hasIcon ? vue.createVNode(VIcon, {
  5698. "key": "content-icon",
  5699. "icon": props.icon
  5700. }, null) : vue.createVNode(VDefaultsProvider, {
  5701. "key": "content-defaults",
  5702. "disabled": !hasIcon,
  5703. "defaults": {
  5704. VIcon: {
  5705. icon: props.icon
  5706. }
  5707. }
  5708. }, {
  5709. default: () => [slots.default?.() ?? props.text]
  5710. })]), !props.icon && hasAppend && vue.createVNode("span", {
  5711. "key": "append",
  5712. "class": "v-btn__append"
  5713. }, [!slots.append ? vue.createVNode(VIcon, {
  5714. "key": "append-icon",
  5715. "icon": props.appendIcon
  5716. }, null) : vue.createVNode(VDefaultsProvider, {
  5717. "key": "append-defaults",
  5718. "disabled": !props.appendIcon,
  5719. "defaults": {
  5720. VIcon: {
  5721. icon: props.appendIcon
  5722. }
  5723. }
  5724. }, slots.append)]), !!props.loading && vue.createVNode("span", {
  5725. "key": "loader",
  5726. "class": "v-btn__loader"
  5727. }, [slots.loader?.() ?? vue.createVNode(VProgressCircular, {
  5728. "color": typeof props.loading === 'boolean' ? undefined : props.loading,
  5729. "indeterminate": true,
  5730. "width": "2"
  5731. }, null)])]
  5732. }), [[Ripple, !isDisabled.value && props.ripple, '', {
  5733. center: !!props.icon
  5734. }]]);
  5735. });
  5736. return {
  5737. group
  5738. };
  5739. }
  5740. });
  5741. // Types
  5742. const makeVAppBarNavIconProps = propsFactory({
  5743. ...makeVBtnProps({
  5744. icon: '$menu',
  5745. variant: 'text'
  5746. })
  5747. }, 'VAppBarNavIcon');
  5748. const VAppBarNavIcon = genericComponent()({
  5749. name: 'VAppBarNavIcon',
  5750. props: makeVAppBarNavIconProps(),
  5751. setup(props, _ref) {
  5752. let {
  5753. slots
  5754. } = _ref;
  5755. useRender(() => vue.createVNode(VBtn, vue.mergeProps(props, {
  5756. "class": ['v-app-bar-nav-icon']
  5757. }), slots));
  5758. return {};
  5759. }
  5760. });
  5761. // Types
  5762. const VAppBarTitle = genericComponent()({
  5763. name: 'VAppBarTitle',
  5764. props: makeVToolbarTitleProps(),
  5765. setup(props, _ref) {
  5766. let {
  5767. slots
  5768. } = _ref;
  5769. useRender(() => vue.createVNode(VToolbarTitle, vue.mergeProps(props, {
  5770. "class": "v-app-bar-title"
  5771. }), slots));
  5772. return {};
  5773. }
  5774. });
  5775. // Utilities
  5776. const VAlertTitle = createSimpleFunctional('v-alert-title');
  5777. // Types
  5778. const allowedTypes = ['success', 'info', 'warning', 'error'];
  5779. const makeVAlertProps = propsFactory({
  5780. border: {
  5781. type: [Boolean, String],
  5782. validator: val => {
  5783. return typeof val === 'boolean' || ['top', 'end', 'bottom', 'start'].includes(val);
  5784. }
  5785. },
  5786. borderColor: String,
  5787. closable: Boolean,
  5788. closeIcon: {
  5789. type: IconValue,
  5790. default: '$close'
  5791. },
  5792. closeLabel: {
  5793. type: String,
  5794. default: '$vuetify.close'
  5795. },
  5796. icon: {
  5797. type: [Boolean, String, Function, Object],
  5798. default: null
  5799. },
  5800. modelValue: {
  5801. type: Boolean,
  5802. default: true
  5803. },
  5804. prominent: Boolean,
  5805. title: String,
  5806. text: String,
  5807. type: {
  5808. type: String,
  5809. validator: val => allowedTypes.includes(val)
  5810. },
  5811. ...makeComponentProps(),
  5812. ...makeDensityProps(),
  5813. ...makeDimensionProps(),
  5814. ...makeElevationProps(),
  5815. ...makeLocationProps(),
  5816. ...makePositionProps(),
  5817. ...makeRoundedProps(),
  5818. ...makeTagProps(),
  5819. ...makeThemeProps(),
  5820. ...makeVariantProps({
  5821. variant: 'flat'
  5822. })
  5823. }, 'VAlert');
  5824. const VAlert = genericComponent()({
  5825. name: 'VAlert',
  5826. props: makeVAlertProps(),
  5827. emits: {
  5828. 'click:close': e => true,
  5829. 'update:modelValue': value => true
  5830. },
  5831. setup(props, _ref) {
  5832. let {
  5833. emit,
  5834. slots
  5835. } = _ref;
  5836. const isActive = useProxiedModel(props, 'modelValue');
  5837. const icon = vue.computed(() => {
  5838. if (props.icon === false) return undefined;
  5839. if (!props.type) return props.icon;
  5840. return props.icon ?? `$${props.type}`;
  5841. });
  5842. const variantProps = vue.computed(() => ({
  5843. color: props.color ?? props.type,
  5844. variant: props.variant
  5845. }));
  5846. const {
  5847. themeClasses
  5848. } = provideTheme(props);
  5849. const {
  5850. colorClasses,
  5851. colorStyles,
  5852. variantClasses
  5853. } = useVariant(variantProps);
  5854. const {
  5855. densityClasses
  5856. } = useDensity(props);
  5857. const {
  5858. dimensionStyles
  5859. } = useDimension(props);
  5860. const {
  5861. elevationClasses
  5862. } = useElevation(props);
  5863. const {
  5864. locationStyles
  5865. } = useLocation(props);
  5866. const {
  5867. positionClasses
  5868. } = usePosition(props);
  5869. const {
  5870. roundedClasses
  5871. } = useRounded(props);
  5872. const {
  5873. textColorClasses,
  5874. textColorStyles
  5875. } = useTextColor(vue.toRef(props, 'borderColor'));
  5876. const {
  5877. t
  5878. } = useLocale();
  5879. const closeProps = vue.computed(() => ({
  5880. 'aria-label': t(props.closeLabel),
  5881. onClick(e) {
  5882. isActive.value = false;
  5883. emit('click:close', e);
  5884. }
  5885. }));
  5886. return () => {
  5887. const hasPrepend = !!(slots.prepend || icon.value);
  5888. const hasTitle = !!(slots.title || props.title);
  5889. const hasClose = !!(slots.close || props.closable);
  5890. return isActive.value && vue.createVNode(props.tag, {
  5891. "class": ['v-alert', props.border && {
  5892. 'v-alert--border': !!props.border,
  5893. [`v-alert--border-${props.border === true ? 'start' : props.border}`]: true
  5894. }, {
  5895. 'v-alert--prominent': props.prominent
  5896. }, themeClasses.value, colorClasses.value, densityClasses.value, elevationClasses.value, positionClasses.value, roundedClasses.value, variantClasses.value, props.class],
  5897. "style": [colorStyles.value, dimensionStyles.value, locationStyles.value, props.style],
  5898. "role": "alert"
  5899. }, {
  5900. default: () => [genOverlays(false, 'v-alert'), props.border && vue.createVNode("div", {
  5901. "key": "border",
  5902. "class": ['v-alert__border', textColorClasses.value],
  5903. "style": textColorStyles.value
  5904. }, null), hasPrepend && vue.createVNode("div", {
  5905. "key": "prepend",
  5906. "class": "v-alert__prepend"
  5907. }, [!slots.prepend ? vue.createVNode(VIcon, {
  5908. "key": "prepend-icon",
  5909. "density": props.density,
  5910. "icon": icon.value,
  5911. "size": props.prominent ? 44 : 28
  5912. }, null) : vue.createVNode(VDefaultsProvider, {
  5913. "key": "prepend-defaults",
  5914. "disabled": !icon.value,
  5915. "defaults": {
  5916. VIcon: {
  5917. density: props.density,
  5918. icon: icon.value,
  5919. size: props.prominent ? 44 : 28
  5920. }
  5921. }
  5922. }, slots.prepend)]), vue.createVNode("div", {
  5923. "class": "v-alert__content"
  5924. }, [hasTitle && vue.createVNode(VAlertTitle, {
  5925. "key": "title"
  5926. }, {
  5927. default: () => [slots.title?.() ?? props.title]
  5928. }), slots.text?.() ?? props.text, slots.default?.()]), slots.append && vue.createVNode("div", {
  5929. "key": "append",
  5930. "class": "v-alert__append"
  5931. }, [slots.append()]), hasClose && vue.createVNode("div", {
  5932. "key": "close",
  5933. "class": "v-alert__close"
  5934. }, [!slots.close ? vue.createVNode(VBtn, vue.mergeProps({
  5935. "key": "close-btn",
  5936. "icon": props.closeIcon,
  5937. "size": "x-small",
  5938. "variant": "text"
  5939. }, closeProps.value), null) : vue.createVNode(VDefaultsProvider, {
  5940. "key": "close-defaults",
  5941. "defaults": {
  5942. VBtn: {
  5943. icon: props.closeIcon,
  5944. size: 'x-small',
  5945. variant: 'text'
  5946. }
  5947. }
  5948. }, {
  5949. default: () => [slots.close?.({
  5950. props: closeProps.value
  5951. })]
  5952. })])]
  5953. });
  5954. };
  5955. }
  5956. });
  5957. const makeVAvatarProps = propsFactory({
  5958. start: Boolean,
  5959. end: Boolean,
  5960. icon: IconValue,
  5961. image: String,
  5962. text: String,
  5963. ...makeBorderProps(),
  5964. ...makeComponentProps(),
  5965. ...makeDensityProps(),
  5966. ...makeRoundedProps(),
  5967. ...makeSizeProps(),
  5968. ...makeTagProps(),
  5969. ...makeThemeProps(),
  5970. ...makeVariantProps({
  5971. variant: 'flat'
  5972. })
  5973. }, 'VAvatar');
  5974. const VAvatar = genericComponent()({
  5975. name: 'VAvatar',
  5976. props: makeVAvatarProps(),
  5977. setup(props, _ref) {
  5978. let {
  5979. slots
  5980. } = _ref;
  5981. const {
  5982. themeClasses
  5983. } = provideTheme(props);
  5984. const {
  5985. borderClasses
  5986. } = useBorder(props);
  5987. const {
  5988. colorClasses,
  5989. colorStyles,
  5990. variantClasses
  5991. } = useVariant(props);
  5992. const {
  5993. densityClasses
  5994. } = useDensity(props);
  5995. const {
  5996. roundedClasses
  5997. } = useRounded(props);
  5998. const {
  5999. sizeClasses,
  6000. sizeStyles
  6001. } = useSize(props);
  6002. useRender(() => vue.createVNode(props.tag, {
  6003. "class": ['v-avatar', {
  6004. 'v-avatar--start': props.start,
  6005. 'v-avatar--end': props.end
  6006. }, themeClasses.value, borderClasses.value, colorClasses.value, densityClasses.value, roundedClasses.value, sizeClasses.value, variantClasses.value, props.class],
  6007. "style": [colorStyles.value, sizeStyles.value, props.style]
  6008. }, {
  6009. default: () => [!slots.default ? props.image ? vue.createVNode(VImg, {
  6010. "key": "image",
  6011. "src": props.image,
  6012. "alt": "",
  6013. "cover": true
  6014. }, null) : props.icon ? vue.createVNode(VIcon, {
  6015. "key": "icon",
  6016. "icon": props.icon
  6017. }, null) : props.text : vue.createVNode(VDefaultsProvider, {
  6018. "key": "content-defaults",
  6019. "defaults": {
  6020. VImg: {
  6021. cover: true,
  6022. src: props.image
  6023. },
  6024. VIcon: {
  6025. icon: props.icon
  6026. }
  6027. }
  6028. }, {
  6029. default: () => [slots.default()]
  6030. }), genOverlays(false, 'v-avatar')]
  6031. }));
  6032. return {};
  6033. }
  6034. });
  6035. const makeVLabelProps = propsFactory({
  6036. text: String,
  6037. onClick: EventProp(),
  6038. ...makeComponentProps(),
  6039. ...makeThemeProps()
  6040. }, 'VLabel');
  6041. const VLabel = genericComponent()({
  6042. name: 'VLabel',
  6043. props: makeVLabelProps(),
  6044. setup(props, _ref) {
  6045. let {
  6046. slots
  6047. } = _ref;
  6048. useRender(() => vue.createVNode("label", {
  6049. "class": ['v-label', {
  6050. 'v-label--clickable': !!props.onClick
  6051. }, props.class],
  6052. "style": props.style,
  6053. "onClick": props.onClick
  6054. }, [props.text, slots.default?.()]));
  6055. return {};
  6056. }
  6057. });
  6058. // Types
  6059. const VSelectionControlGroupSymbol = Symbol.for('vuetify:selection-control-group');
  6060. const makeSelectionControlGroupProps = propsFactory({
  6061. color: String,
  6062. disabled: {
  6063. type: Boolean,
  6064. default: null
  6065. },
  6066. defaultsTarget: String,
  6067. error: Boolean,
  6068. id: String,
  6069. inline: Boolean,
  6070. falseIcon: IconValue,
  6071. trueIcon: IconValue,
  6072. ripple: {
  6073. type: [Boolean, Object],
  6074. default: true
  6075. },
  6076. multiple: {
  6077. type: Boolean,
  6078. default: null
  6079. },
  6080. name: String,
  6081. readonly: {
  6082. type: Boolean,
  6083. default: null
  6084. },
  6085. modelValue: null,
  6086. type: String,
  6087. valueComparator: {
  6088. type: Function,
  6089. default: deepEqual
  6090. },
  6091. ...makeComponentProps(),
  6092. ...makeDensityProps(),
  6093. ...makeThemeProps()
  6094. }, 'SelectionControlGroup');
  6095. const makeVSelectionControlGroupProps = propsFactory({
  6096. ...makeSelectionControlGroupProps({
  6097. defaultsTarget: 'VSelectionControl'
  6098. })
  6099. }, 'VSelectionControlGroup');
  6100. const VSelectionControlGroup = genericComponent()({
  6101. name: 'VSelectionControlGroup',
  6102. props: makeVSelectionControlGroupProps(),
  6103. emits: {
  6104. 'update:modelValue': value => true
  6105. },
  6106. setup(props, _ref) {
  6107. let {
  6108. slots
  6109. } = _ref;
  6110. const modelValue = useProxiedModel(props, 'modelValue');
  6111. const uid = getUid();
  6112. const id = vue.computed(() => props.id || `v-selection-control-group-${uid}`);
  6113. const name = vue.computed(() => props.name || id.value);
  6114. const updateHandlers = new Set();
  6115. vue.provide(VSelectionControlGroupSymbol, {
  6116. modelValue,
  6117. forceUpdate: () => {
  6118. updateHandlers.forEach(fn => fn());
  6119. },
  6120. onForceUpdate: cb => {
  6121. updateHandlers.add(cb);
  6122. vue.onScopeDispose(() => {
  6123. updateHandlers.delete(cb);
  6124. });
  6125. }
  6126. });
  6127. provideDefaults({
  6128. [props.defaultsTarget]: {
  6129. color: vue.toRef(props, 'color'),
  6130. disabled: vue.toRef(props, 'disabled'),
  6131. density: vue.toRef(props, 'density'),
  6132. error: vue.toRef(props, 'error'),
  6133. inline: vue.toRef(props, 'inline'),
  6134. modelValue,
  6135. multiple: vue.computed(() => !!props.multiple || props.multiple == null && Array.isArray(modelValue.value)),
  6136. name,
  6137. falseIcon: vue.toRef(props, 'falseIcon'),
  6138. trueIcon: vue.toRef(props, 'trueIcon'),
  6139. readonly: vue.toRef(props, 'readonly'),
  6140. ripple: vue.toRef(props, 'ripple'),
  6141. type: vue.toRef(props, 'type'),
  6142. valueComparator: vue.toRef(props, 'valueComparator')
  6143. }
  6144. });
  6145. useRender(() => vue.createVNode("div", {
  6146. "class": ['v-selection-control-group', {
  6147. 'v-selection-control-group--inline': props.inline
  6148. }, props.class],
  6149. "style": props.style,
  6150. "role": props.type === 'radio' ? 'radiogroup' : undefined
  6151. }, [slots.default?.()]));
  6152. return {};
  6153. }
  6154. });
  6155. // Types
  6156. const makeVSelectionControlProps = propsFactory({
  6157. label: String,
  6158. baseColor: String,
  6159. trueValue: null,
  6160. falseValue: null,
  6161. value: null,
  6162. ...makeComponentProps(),
  6163. ...makeSelectionControlGroupProps()
  6164. }, 'VSelectionControl');
  6165. function useSelectionControl(props) {
  6166. const group = vue.inject(VSelectionControlGroupSymbol, undefined);
  6167. const {
  6168. densityClasses
  6169. } = useDensity(props);
  6170. const modelValue = useProxiedModel(props, 'modelValue');
  6171. const trueValue = vue.computed(() => props.trueValue !== undefined ? props.trueValue : props.value !== undefined ? props.value : true);
  6172. const falseValue = vue.computed(() => props.falseValue !== undefined ? props.falseValue : false);
  6173. const isMultiple = vue.computed(() => !!props.multiple || props.multiple == null && Array.isArray(modelValue.value));
  6174. const model = vue.computed({
  6175. get() {
  6176. const val = group ? group.modelValue.value : modelValue.value;
  6177. return isMultiple.value ? wrapInArray(val).some(v => props.valueComparator(v, trueValue.value)) : props.valueComparator(val, trueValue.value);
  6178. },
  6179. set(val) {
  6180. if (props.readonly) return;
  6181. const currentValue = val ? trueValue.value : falseValue.value;
  6182. let newVal = currentValue;
  6183. if (isMultiple.value) {
  6184. newVal = val ? [...wrapInArray(modelValue.value), currentValue] : wrapInArray(modelValue.value).filter(item => !props.valueComparator(item, trueValue.value));
  6185. }
  6186. if (group) {
  6187. group.modelValue.value = newVal;
  6188. } else {
  6189. modelValue.value = newVal;
  6190. }
  6191. }
  6192. });
  6193. const {
  6194. textColorClasses,
  6195. textColorStyles
  6196. } = useTextColor(vue.computed(() => {
  6197. if (props.error || props.disabled) return undefined;
  6198. return model.value ? props.color : props.baseColor;
  6199. }));
  6200. const {
  6201. backgroundColorClasses,
  6202. backgroundColorStyles
  6203. } = useBackgroundColor(vue.computed(() => {
  6204. return model.value && !props.error && !props.disabled ? props.color : props.baseColor;
  6205. }));
  6206. const icon = vue.computed(() => model.value ? props.trueIcon : props.falseIcon);
  6207. return {
  6208. group,
  6209. densityClasses,
  6210. trueValue,
  6211. falseValue,
  6212. model,
  6213. textColorClasses,
  6214. textColorStyles,
  6215. backgroundColorClasses,
  6216. backgroundColorStyles,
  6217. icon
  6218. };
  6219. }
  6220. const VSelectionControl = genericComponent()({
  6221. name: 'VSelectionControl',
  6222. directives: {
  6223. Ripple
  6224. },
  6225. inheritAttrs: false,
  6226. props: makeVSelectionControlProps(),
  6227. emits: {
  6228. 'update:modelValue': value => true
  6229. },
  6230. setup(props, _ref) {
  6231. let {
  6232. attrs,
  6233. slots
  6234. } = _ref;
  6235. const {
  6236. group,
  6237. densityClasses,
  6238. icon,
  6239. model,
  6240. textColorClasses,
  6241. textColorStyles,
  6242. backgroundColorClasses,
  6243. backgroundColorStyles,
  6244. trueValue
  6245. } = useSelectionControl(props);
  6246. const uid = getUid();
  6247. const isFocused = vue.shallowRef(false);
  6248. const isFocusVisible = vue.shallowRef(false);
  6249. const input = vue.ref();
  6250. const id = vue.computed(() => props.id || `input-${uid}`);
  6251. const isInteractive = vue.computed(() => !props.disabled && !props.readonly);
  6252. group?.onForceUpdate(() => {
  6253. if (input.value) {
  6254. input.value.checked = model.value;
  6255. }
  6256. });
  6257. function onFocus(e) {
  6258. if (!isInteractive.value) return;
  6259. isFocused.value = true;
  6260. if (matchesSelector(e.target, ':focus-visible') !== false) {
  6261. isFocusVisible.value = true;
  6262. }
  6263. }
  6264. function onBlur() {
  6265. isFocused.value = false;
  6266. isFocusVisible.value = false;
  6267. }
  6268. function onClickLabel(e) {
  6269. e.stopPropagation();
  6270. }
  6271. function onInput(e) {
  6272. if (!isInteractive.value) {
  6273. if (input.value) {
  6274. // model value is not updated when input is not interactive
  6275. // but the internal checked state of the input is still updated,
  6276. // so here it's value is restored
  6277. input.value.checked = model.value;
  6278. }
  6279. return;
  6280. }
  6281. if (props.readonly && group) {
  6282. vue.nextTick(() => group.forceUpdate());
  6283. }
  6284. model.value = e.target.checked;
  6285. }
  6286. useRender(() => {
  6287. const label = slots.label ? slots.label({
  6288. label: props.label,
  6289. props: {
  6290. for: id.value
  6291. }
  6292. }) : props.label;
  6293. const [rootAttrs, inputAttrs] = filterInputAttrs(attrs);
  6294. const inputNode = vue.createVNode("input", vue.mergeProps({
  6295. "ref": input,
  6296. "checked": model.value,
  6297. "disabled": !!props.disabled,
  6298. "id": id.value,
  6299. "onBlur": onBlur,
  6300. "onFocus": onFocus,
  6301. "onInput": onInput,
  6302. "aria-disabled": !!props.disabled,
  6303. "aria-label": props.label,
  6304. "type": props.type,
  6305. "value": trueValue.value,
  6306. "name": props.name,
  6307. "aria-checked": props.type === 'checkbox' ? model.value : undefined
  6308. }, inputAttrs), null);
  6309. return vue.createVNode("div", vue.mergeProps({
  6310. "class": ['v-selection-control', {
  6311. 'v-selection-control--dirty': model.value,
  6312. 'v-selection-control--disabled': props.disabled,
  6313. 'v-selection-control--error': props.error,
  6314. 'v-selection-control--focused': isFocused.value,
  6315. 'v-selection-control--focus-visible': isFocusVisible.value,
  6316. 'v-selection-control--inline': props.inline
  6317. }, densityClasses.value, props.class]
  6318. }, rootAttrs, {
  6319. "style": props.style
  6320. }), [vue.createVNode("div", {
  6321. "class": ['v-selection-control__wrapper', textColorClasses.value],
  6322. "style": textColorStyles.value
  6323. }, [slots.default?.({
  6324. backgroundColorClasses,
  6325. backgroundColorStyles
  6326. }), vue.withDirectives(vue.createVNode("div", {
  6327. "class": ['v-selection-control__input']
  6328. }, [slots.input?.({
  6329. model,
  6330. textColorClasses,
  6331. textColorStyles,
  6332. backgroundColorClasses,
  6333. backgroundColorStyles,
  6334. inputNode,
  6335. icon: icon.value,
  6336. props: {
  6337. onFocus,
  6338. onBlur,
  6339. id: id.value
  6340. }
  6341. }) ?? vue.createVNode(vue.Fragment, null, [icon.value && vue.createVNode(VIcon, {
  6342. "key": "icon",
  6343. "icon": icon.value
  6344. }, null), inputNode])]), [[vue.resolveDirective("ripple"), props.ripple && [!props.disabled && !props.readonly, null, ['center', 'circle']]]])]), label && vue.createVNode(VLabel, {
  6345. "for": id.value,
  6346. "onClick": onClickLabel
  6347. }, {
  6348. default: () => [label]
  6349. })]);
  6350. });
  6351. return {
  6352. isFocused,
  6353. input
  6354. };
  6355. }
  6356. });
  6357. // Types
  6358. const makeVCheckboxBtnProps = propsFactory({
  6359. indeterminate: Boolean,
  6360. indeterminateIcon: {
  6361. type: IconValue,
  6362. default: '$checkboxIndeterminate'
  6363. },
  6364. ...makeVSelectionControlProps({
  6365. falseIcon: '$checkboxOff',
  6366. trueIcon: '$checkboxOn'
  6367. })
  6368. }, 'VCheckboxBtn');
  6369. const VCheckboxBtn = genericComponent()({
  6370. name: 'VCheckboxBtn',
  6371. props: makeVCheckboxBtnProps(),
  6372. emits: {
  6373. 'update:modelValue': value => true,
  6374. 'update:indeterminate': value => true
  6375. },
  6376. setup(props, _ref) {
  6377. let {
  6378. slots
  6379. } = _ref;
  6380. const indeterminate = useProxiedModel(props, 'indeterminate');
  6381. const model = useProxiedModel(props, 'modelValue');
  6382. function onChange(v) {
  6383. if (indeterminate.value) {
  6384. indeterminate.value = false;
  6385. }
  6386. }
  6387. const falseIcon = vue.computed(() => {
  6388. return indeterminate.value ? props.indeterminateIcon : props.falseIcon;
  6389. });
  6390. const trueIcon = vue.computed(() => {
  6391. return indeterminate.value ? props.indeterminateIcon : props.trueIcon;
  6392. });
  6393. useRender(() => {
  6394. const controlProps = omit(VSelectionControl.filterProps(props), ['modelValue']);
  6395. return vue.createVNode(VSelectionControl, vue.mergeProps(controlProps, {
  6396. "modelValue": model.value,
  6397. "onUpdate:modelValue": [$event => model.value = $event, onChange],
  6398. "class": ['v-checkbox-btn', props.class],
  6399. "style": props.style,
  6400. "type": "checkbox",
  6401. "falseIcon": falseIcon.value,
  6402. "trueIcon": trueIcon.value,
  6403. "aria-checked": indeterminate.value ? 'mixed' : undefined
  6404. }), slots);
  6405. });
  6406. return {};
  6407. }
  6408. });
  6409. // Types
  6410. function useInputIcon(props) {
  6411. const {
  6412. t
  6413. } = useLocale();
  6414. function InputIcon(_ref) {
  6415. let {
  6416. name
  6417. } = _ref;
  6418. const localeKey = {
  6419. prepend: 'prependAction',
  6420. prependInner: 'prependAction',
  6421. append: 'appendAction',
  6422. appendInner: 'appendAction',
  6423. clear: 'clear'
  6424. }[name];
  6425. const listener = props[`onClick:${name}`];
  6426. const label = listener && localeKey ? t(`$vuetify.input.${localeKey}`, props.label ?? '') : undefined;
  6427. return vue.createVNode(VIcon, {
  6428. "icon": props[`${name}Icon`],
  6429. "aria-label": label,
  6430. "onClick": listener
  6431. }, null);
  6432. }
  6433. return {
  6434. InputIcon
  6435. };
  6436. }
  6437. // Types
  6438. const makeVMessagesProps = propsFactory({
  6439. active: Boolean,
  6440. color: String,
  6441. messages: {
  6442. type: [Array, String],
  6443. default: () => []
  6444. },
  6445. ...makeComponentProps(),
  6446. ...makeTransitionProps({
  6447. transition: {
  6448. component: VSlideYTransition,
  6449. leaveAbsolute: true,
  6450. group: true
  6451. }
  6452. })
  6453. }, 'VMessages');
  6454. const VMessages = genericComponent()({
  6455. name: 'VMessages',
  6456. props: makeVMessagesProps(),
  6457. setup(props, _ref) {
  6458. let {
  6459. slots
  6460. } = _ref;
  6461. const messages = vue.computed(() => wrapInArray(props.messages));
  6462. const {
  6463. textColorClasses,
  6464. textColorStyles
  6465. } = useTextColor(vue.computed(() => props.color));
  6466. useRender(() => vue.createVNode(MaybeTransition, {
  6467. "transition": props.transition,
  6468. "tag": "div",
  6469. "class": ['v-messages', textColorClasses.value, props.class],
  6470. "style": [textColorStyles.value, props.style],
  6471. "role": "alert",
  6472. "aria-live": "polite"
  6473. }, {
  6474. default: () => [props.active && messages.value.map((message, i) => vue.createVNode("div", {
  6475. "class": "v-messages__message",
  6476. "key": `${i}-${messages.value}`
  6477. }, [slots.message ? slots.message({
  6478. message
  6479. }) : message]))]
  6480. }));
  6481. return {};
  6482. }
  6483. });
  6484. // Composables
  6485. // Types
  6486. // Composables
  6487. const makeFocusProps = propsFactory({
  6488. focused: Boolean,
  6489. 'onUpdate:focused': EventProp()
  6490. }, 'focus');
  6491. function useFocus(props) {
  6492. let name = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : getCurrentInstanceName();
  6493. const isFocused = useProxiedModel(props, 'focused');
  6494. const focusClasses = vue.computed(() => {
  6495. return {
  6496. [`${name}--focused`]: isFocused.value
  6497. };
  6498. });
  6499. function focus() {
  6500. isFocused.value = true;
  6501. }
  6502. function blur() {
  6503. isFocused.value = false;
  6504. }
  6505. return {
  6506. focusClasses,
  6507. isFocused,
  6508. focus,
  6509. blur
  6510. };
  6511. }
  6512. // Composables
  6513. // Types
  6514. const FormKey = Symbol.for('vuetify:form');
  6515. const makeFormProps = propsFactory({
  6516. disabled: Boolean,
  6517. fastFail: Boolean,
  6518. readonly: Boolean,
  6519. modelValue: {
  6520. type: Boolean,
  6521. default: null
  6522. },
  6523. validateOn: {
  6524. type: String,
  6525. default: 'input'
  6526. }
  6527. }, 'form');
  6528. function createForm(props) {
  6529. const model = useProxiedModel(props, 'modelValue');
  6530. const isDisabled = vue.computed(() => props.disabled);
  6531. const isReadonly = vue.computed(() => props.readonly);
  6532. const isValidating = vue.shallowRef(false);
  6533. const items = vue.ref([]);
  6534. const errors = vue.ref([]);
  6535. async function validate() {
  6536. const results = [];
  6537. let valid = true;
  6538. errors.value = [];
  6539. isValidating.value = true;
  6540. for (const item of items.value) {
  6541. const itemErrorMessages = await item.validate();
  6542. if (itemErrorMessages.length > 0) {
  6543. valid = false;
  6544. results.push({
  6545. id: item.id,
  6546. errorMessages: itemErrorMessages
  6547. });
  6548. }
  6549. if (!valid && props.fastFail) break;
  6550. }
  6551. errors.value = results;
  6552. isValidating.value = false;
  6553. return {
  6554. valid,
  6555. errors: errors.value
  6556. };
  6557. }
  6558. function reset() {
  6559. items.value.forEach(item => item.reset());
  6560. }
  6561. function resetValidation() {
  6562. items.value.forEach(item => item.resetValidation());
  6563. }
  6564. vue.watch(items, () => {
  6565. let valid = 0;
  6566. let invalid = 0;
  6567. const results = [];
  6568. for (const item of items.value) {
  6569. if (item.isValid === false) {
  6570. invalid++;
  6571. results.push({
  6572. id: item.id,
  6573. errorMessages: item.errorMessages
  6574. });
  6575. } else if (item.isValid === true) valid++;
  6576. }
  6577. errors.value = results;
  6578. model.value = invalid > 0 ? false : valid === items.value.length ? true : null;
  6579. }, {
  6580. deep: true,
  6581. flush: 'post'
  6582. });
  6583. vue.provide(FormKey, {
  6584. register: _ref => {
  6585. let {
  6586. id,
  6587. vm,
  6588. validate,
  6589. reset,
  6590. resetValidation
  6591. } = _ref;
  6592. if (items.value.some(item => item.id === id)) {
  6593. consoleWarn(`Duplicate input name "${id}"`);
  6594. }
  6595. items.value.push({
  6596. id,
  6597. validate,
  6598. reset,
  6599. resetValidation,
  6600. vm: vue.markRaw(vm),
  6601. isValid: null,
  6602. errorMessages: []
  6603. });
  6604. },
  6605. unregister: id => {
  6606. items.value = items.value.filter(item => {
  6607. return item.id !== id;
  6608. });
  6609. },
  6610. update: (id, isValid, errorMessages) => {
  6611. const found = items.value.find(item => item.id === id);
  6612. if (!found) return;
  6613. found.isValid = isValid;
  6614. found.errorMessages = errorMessages;
  6615. },
  6616. isDisabled,
  6617. isReadonly,
  6618. isValidating,
  6619. isValid: model,
  6620. items,
  6621. validateOn: vue.toRef(props, 'validateOn')
  6622. });
  6623. return {
  6624. errors,
  6625. isDisabled,
  6626. isReadonly,
  6627. isValidating,
  6628. isValid: model,
  6629. items,
  6630. validate,
  6631. reset,
  6632. resetValidation
  6633. };
  6634. }
  6635. function useForm(props) {
  6636. const form = vue.inject(FormKey, null);
  6637. return {
  6638. ...form,
  6639. isReadonly: vue.computed(() => !!(props?.readonly ?? form?.isReadonly.value)),
  6640. isDisabled: vue.computed(() => !!(props?.disabled ?? form?.isDisabled.value))
  6641. };
  6642. }
  6643. // Composables
  6644. // Types
  6645. const makeValidationProps = propsFactory({
  6646. disabled: {
  6647. type: Boolean,
  6648. default: null
  6649. },
  6650. error: Boolean,
  6651. errorMessages: {
  6652. type: [Array, String],
  6653. default: () => []
  6654. },
  6655. maxErrors: {
  6656. type: [Number, String],
  6657. default: 1
  6658. },
  6659. name: String,
  6660. label: String,
  6661. readonly: {
  6662. type: Boolean,
  6663. default: null
  6664. },
  6665. rules: {
  6666. type: Array,
  6667. default: () => []
  6668. },
  6669. modelValue: null,
  6670. validateOn: String,
  6671. validationValue: null,
  6672. ...makeFocusProps()
  6673. }, 'validation');
  6674. function useValidation(props) {
  6675. let name = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : getCurrentInstanceName();
  6676. let id = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : getUid();
  6677. const model = useProxiedModel(props, 'modelValue');
  6678. const validationModel = vue.computed(() => props.validationValue === undefined ? model.value : props.validationValue);
  6679. const form = useForm(props);
  6680. const internalErrorMessages = vue.ref([]);
  6681. const isPristine = vue.shallowRef(true);
  6682. const isDirty = vue.computed(() => !!(wrapInArray(model.value === '' ? null : model.value).length || wrapInArray(validationModel.value === '' ? null : validationModel.value).length));
  6683. const errorMessages = vue.computed(() => {
  6684. return props.errorMessages?.length ? wrapInArray(props.errorMessages).concat(internalErrorMessages.value).slice(0, Math.max(0, +props.maxErrors)) : internalErrorMessages.value;
  6685. });
  6686. const validateOn = vue.computed(() => {
  6687. let value = (props.validateOn ?? form.validateOn?.value) || 'input';
  6688. if (value === 'lazy') value = 'input lazy';
  6689. if (value === 'eager') value = 'input eager';
  6690. const set = new Set(value?.split(' ') ?? []);
  6691. return {
  6692. input: set.has('input'),
  6693. blur: set.has('blur') || set.has('input') || set.has('invalid-input'),
  6694. invalidInput: set.has('invalid-input'),
  6695. lazy: set.has('lazy'),
  6696. eager: set.has('eager')
  6697. };
  6698. });
  6699. const isValid = vue.computed(() => {
  6700. if (props.error || props.errorMessages?.length) return false;
  6701. if (!props.rules.length) return true;
  6702. if (isPristine.value) {
  6703. return internalErrorMessages.value.length || validateOn.value.lazy ? null : true;
  6704. } else {
  6705. return !internalErrorMessages.value.length;
  6706. }
  6707. });
  6708. const isValidating = vue.shallowRef(false);
  6709. const validationClasses = vue.computed(() => {
  6710. return {
  6711. [`${name}--error`]: isValid.value === false,
  6712. [`${name}--dirty`]: isDirty.value,
  6713. [`${name}--disabled`]: form.isDisabled.value,
  6714. [`${name}--readonly`]: form.isReadonly.value
  6715. };
  6716. });
  6717. const vm = getCurrentInstance('validation');
  6718. const uid = vue.computed(() => props.name ?? vue.unref(id));
  6719. vue.onBeforeMount(() => {
  6720. form.register?.({
  6721. id: uid.value,
  6722. vm,
  6723. validate,
  6724. reset,
  6725. resetValidation
  6726. });
  6727. });
  6728. vue.onBeforeUnmount(() => {
  6729. form.unregister?.(uid.value);
  6730. });
  6731. vue.onMounted(async () => {
  6732. if (!validateOn.value.lazy) {
  6733. await validate(!validateOn.value.eager);
  6734. }
  6735. form.update?.(uid.value, isValid.value, errorMessages.value);
  6736. });
  6737. useToggleScope(() => validateOn.value.input || validateOn.value.invalidInput && isValid.value === false, () => {
  6738. vue.watch(validationModel, () => {
  6739. if (validationModel.value != null) {
  6740. validate();
  6741. } else if (props.focused) {
  6742. const unwatch = vue.watch(() => props.focused, val => {
  6743. if (!val) validate();
  6744. unwatch();
  6745. });
  6746. }
  6747. });
  6748. });
  6749. useToggleScope(() => validateOn.value.blur, () => {
  6750. vue.watch(() => props.focused, val => {
  6751. if (!val) validate();
  6752. });
  6753. });
  6754. vue.watch([isValid, errorMessages], () => {
  6755. form.update?.(uid.value, isValid.value, errorMessages.value);
  6756. });
  6757. async function reset() {
  6758. model.value = null;
  6759. await vue.nextTick();
  6760. await resetValidation();
  6761. }
  6762. async function resetValidation() {
  6763. isPristine.value = true;
  6764. if (!validateOn.value.lazy) {
  6765. await validate(!validateOn.value.eager);
  6766. } else {
  6767. internalErrorMessages.value = [];
  6768. }
  6769. }
  6770. async function validate() {
  6771. let silent = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : false;
  6772. const results = [];
  6773. isValidating.value = true;
  6774. for (const rule of props.rules) {
  6775. if (results.length >= +(props.maxErrors ?? 1)) {
  6776. break;
  6777. }
  6778. const handler = typeof rule === 'function' ? rule : () => rule;
  6779. const result = await handler(validationModel.value);
  6780. if (result === true) continue;
  6781. if (result !== false && typeof result !== 'string') {
  6782. // eslint-disable-next-line no-console
  6783. console.warn(`${result} is not a valid value. Rule functions must return boolean true or a string.`);
  6784. continue;
  6785. }
  6786. results.push(result || '');
  6787. }
  6788. internalErrorMessages.value = results;
  6789. isValidating.value = false;
  6790. isPristine.value = silent;
  6791. return internalErrorMessages.value;
  6792. }
  6793. return {
  6794. errorMessages,
  6795. isDirty,
  6796. isDisabled: form.isDisabled,
  6797. isReadonly: form.isReadonly,
  6798. isPristine,
  6799. isValid,
  6800. isValidating,
  6801. reset,
  6802. resetValidation,
  6803. validate,
  6804. validationClasses
  6805. };
  6806. }
  6807. // Types
  6808. const makeVInputProps = propsFactory({
  6809. id: String,
  6810. appendIcon: IconValue,
  6811. centerAffix: {
  6812. type: Boolean,
  6813. default: true
  6814. },
  6815. prependIcon: IconValue,
  6816. hideDetails: [Boolean, String],
  6817. hideSpinButtons: Boolean,
  6818. hint: String,
  6819. persistentHint: Boolean,
  6820. messages: {
  6821. type: [Array, String],
  6822. default: () => []
  6823. },
  6824. direction: {
  6825. type: String,
  6826. default: 'horizontal',
  6827. validator: v => ['horizontal', 'vertical'].includes(v)
  6828. },
  6829. 'onClick:prepend': EventProp(),
  6830. 'onClick:append': EventProp(),
  6831. ...makeComponentProps(),
  6832. ...makeDensityProps(),
  6833. ...only(makeDimensionProps(), ['maxWidth', 'minWidth', 'width']),
  6834. ...makeThemeProps(),
  6835. ...makeValidationProps()
  6836. }, 'VInput');
  6837. const VInput = genericComponent()({
  6838. name: 'VInput',
  6839. props: {
  6840. ...makeVInputProps()
  6841. },
  6842. emits: {
  6843. 'update:modelValue': value => true
  6844. },
  6845. setup(props, _ref) {
  6846. let {
  6847. attrs,
  6848. slots,
  6849. emit
  6850. } = _ref;
  6851. const {
  6852. densityClasses
  6853. } = useDensity(props);
  6854. const {
  6855. dimensionStyles
  6856. } = useDimension(props);
  6857. const {
  6858. themeClasses
  6859. } = provideTheme(props);
  6860. const {
  6861. rtlClasses
  6862. } = useRtl();
  6863. const {
  6864. InputIcon
  6865. } = useInputIcon(props);
  6866. const uid = getUid();
  6867. const id = vue.computed(() => props.id || `input-${uid}`);
  6868. const messagesId = vue.computed(() => `${id.value}-messages`);
  6869. const {
  6870. errorMessages,
  6871. isDirty,
  6872. isDisabled,
  6873. isReadonly,
  6874. isPristine,
  6875. isValid,
  6876. isValidating,
  6877. reset,
  6878. resetValidation,
  6879. validate,
  6880. validationClasses
  6881. } = useValidation(props, 'v-input', id);
  6882. const slotProps = vue.computed(() => ({
  6883. id,
  6884. messagesId,
  6885. isDirty,
  6886. isDisabled,
  6887. isReadonly,
  6888. isPristine,
  6889. isValid,
  6890. isValidating,
  6891. reset,
  6892. resetValidation,
  6893. validate
  6894. }));
  6895. const messages = vue.computed(() => {
  6896. if (props.errorMessages?.length || !isPristine.value && errorMessages.value.length) {
  6897. return errorMessages.value;
  6898. } else if (props.hint && (props.persistentHint || props.focused)) {
  6899. return props.hint;
  6900. } else {
  6901. return props.messages;
  6902. }
  6903. });
  6904. useRender(() => {
  6905. const hasPrepend = !!(slots.prepend || props.prependIcon);
  6906. const hasAppend = !!(slots.append || props.appendIcon);
  6907. const hasMessages = messages.value.length > 0;
  6908. const hasDetails = !props.hideDetails || props.hideDetails === 'auto' && (hasMessages || !!slots.details);
  6909. return vue.createVNode("div", {
  6910. "class": ['v-input', `v-input--${props.direction}`, {
  6911. 'v-input--center-affix': props.centerAffix,
  6912. 'v-input--hide-spin-buttons': props.hideSpinButtons
  6913. }, densityClasses.value, themeClasses.value, rtlClasses.value, validationClasses.value, props.class],
  6914. "style": [dimensionStyles.value, props.style]
  6915. }, [hasPrepend && vue.createVNode("div", {
  6916. "key": "prepend",
  6917. "class": "v-input__prepend"
  6918. }, [slots.prepend?.(slotProps.value), props.prependIcon && vue.createVNode(InputIcon, {
  6919. "key": "prepend-icon",
  6920. "name": "prepend"
  6921. }, null)]), slots.default && vue.createVNode("div", {
  6922. "class": "v-input__control"
  6923. }, [slots.default?.(slotProps.value)]), hasAppend && vue.createVNode("div", {
  6924. "key": "append",
  6925. "class": "v-input__append"
  6926. }, [props.appendIcon && vue.createVNode(InputIcon, {
  6927. "key": "append-icon",
  6928. "name": "append"
  6929. }, null), slots.append?.(slotProps.value)]), hasDetails && vue.createVNode("div", {
  6930. "class": "v-input__details"
  6931. }, [vue.createVNode(VMessages, {
  6932. "id": messagesId.value,
  6933. "active": hasMessages,
  6934. "messages": messages.value
  6935. }, {
  6936. message: slots.message
  6937. }), slots.details?.(slotProps.value)])]);
  6938. });
  6939. return {
  6940. reset,
  6941. resetValidation,
  6942. validate,
  6943. isValid,
  6944. errorMessages
  6945. };
  6946. }
  6947. });
  6948. // Types
  6949. const makeVCheckboxProps = propsFactory({
  6950. ...makeVInputProps(),
  6951. ...omit(makeVCheckboxBtnProps(), ['inline'])
  6952. }, 'VCheckbox');
  6953. const VCheckbox = genericComponent()({
  6954. name: 'VCheckbox',
  6955. inheritAttrs: false,
  6956. props: makeVCheckboxProps(),
  6957. emits: {
  6958. 'update:modelValue': value => true,
  6959. 'update:focused': focused => true
  6960. },
  6961. setup(props, _ref) {
  6962. let {
  6963. attrs,
  6964. slots
  6965. } = _ref;
  6966. const model = useProxiedModel(props, 'modelValue');
  6967. const {
  6968. isFocused,
  6969. focus,
  6970. blur
  6971. } = useFocus(props);
  6972. const uid = getUid();
  6973. const id = vue.computed(() => props.id || `checkbox-${uid}`);
  6974. useRender(() => {
  6975. const [rootAttrs, controlAttrs] = filterInputAttrs(attrs);
  6976. const inputProps = VInput.filterProps(props);
  6977. const checkboxProps = VCheckboxBtn.filterProps(props);
  6978. return vue.createVNode(VInput, vue.mergeProps({
  6979. "class": ['v-checkbox', props.class]
  6980. }, rootAttrs, inputProps, {
  6981. "modelValue": model.value,
  6982. "onUpdate:modelValue": $event => model.value = $event,
  6983. "id": id.value,
  6984. "focused": isFocused.value,
  6985. "style": props.style
  6986. }), {
  6987. ...slots,
  6988. default: _ref2 => {
  6989. let {
  6990. id,
  6991. messagesId,
  6992. isDisabled,
  6993. isReadonly,
  6994. isValid
  6995. } = _ref2;
  6996. return vue.createVNode(VCheckboxBtn, vue.mergeProps(checkboxProps, {
  6997. "id": id.value,
  6998. "aria-describedby": messagesId.value,
  6999. "disabled": isDisabled.value,
  7000. "readonly": isReadonly.value
  7001. }, controlAttrs, {
  7002. "error": isValid.value === false,
  7003. "modelValue": model.value,
  7004. "onUpdate:modelValue": $event => model.value = $event,
  7005. "onFocus": focus,
  7006. "onBlur": blur
  7007. }), slots);
  7008. }
  7009. });
  7010. });
  7011. return {};
  7012. }
  7013. });
  7014. // Utilities
  7015. // Types
  7016. const breakpoints = ['sm', 'md', 'lg', 'xl', 'xxl']; // no xs
  7017. const DisplaySymbol = Symbol.for('vuetify:display');
  7018. const defaultDisplayOptions = {
  7019. mobileBreakpoint: 'lg',
  7020. thresholds: {
  7021. xs: 0,
  7022. sm: 600,
  7023. md: 960,
  7024. lg: 1280,
  7025. xl: 1920,
  7026. xxl: 2560
  7027. }
  7028. };
  7029. const parseDisplayOptions = function () {
  7030. let options = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : defaultDisplayOptions;
  7031. return mergeDeep(defaultDisplayOptions, options);
  7032. };
  7033. function getClientWidth(ssr) {
  7034. return IN_BROWSER && !ssr ? window.innerWidth : typeof ssr === 'object' && ssr.clientWidth || 0;
  7035. }
  7036. function getClientHeight(ssr) {
  7037. return IN_BROWSER && !ssr ? window.innerHeight : typeof ssr === 'object' && ssr.clientHeight || 0;
  7038. }
  7039. function getPlatform(ssr) {
  7040. const userAgent = IN_BROWSER && !ssr ? window.navigator.userAgent : 'ssr';
  7041. function match(regexp) {
  7042. return Boolean(userAgent.match(regexp));
  7043. }
  7044. const android = match(/android/i);
  7045. const ios = match(/iphone|ipad|ipod/i);
  7046. const cordova = match(/cordova/i);
  7047. const electron = match(/electron/i);
  7048. const chrome = match(/chrome/i);
  7049. const edge = match(/edge/i);
  7050. const firefox = match(/firefox/i);
  7051. const opera = match(/opera/i);
  7052. const win = match(/win/i);
  7053. const mac = match(/mac/i);
  7054. const linux = match(/linux/i);
  7055. return {
  7056. android,
  7057. ios,
  7058. cordova,
  7059. electron,
  7060. chrome,
  7061. edge,
  7062. firefox,
  7063. opera,
  7064. win,
  7065. mac,
  7066. linux,
  7067. touch: SUPPORTS_TOUCH,
  7068. ssr: userAgent === 'ssr'
  7069. };
  7070. }
  7071. function createDisplay(options, ssr) {
  7072. const {
  7073. thresholds,
  7074. mobileBreakpoint
  7075. } = parseDisplayOptions(options);
  7076. const height = vue.shallowRef(getClientHeight(ssr));
  7077. const platform = vue.shallowRef(getPlatform(ssr));
  7078. const state = vue.reactive({});
  7079. const width = vue.shallowRef(getClientWidth(ssr));
  7080. function updateSize() {
  7081. height.value = getClientHeight();
  7082. width.value = getClientWidth();
  7083. }
  7084. function update() {
  7085. updateSize();
  7086. platform.value = getPlatform();
  7087. }
  7088. // eslint-disable-next-line max-statements
  7089. vue.watchEffect(() => {
  7090. const xs = width.value < thresholds.sm;
  7091. const sm = width.value < thresholds.md && !xs;
  7092. const md = width.value < thresholds.lg && !(sm || xs);
  7093. const lg = width.value < thresholds.xl && !(md || sm || xs);
  7094. const xl = width.value < thresholds.xxl && !(lg || md || sm || xs);
  7095. const xxl = width.value >= thresholds.xxl;
  7096. const name = xs ? 'xs' : sm ? 'sm' : md ? 'md' : lg ? 'lg' : xl ? 'xl' : 'xxl';
  7097. const breakpointValue = typeof mobileBreakpoint === 'number' ? mobileBreakpoint : thresholds[mobileBreakpoint];
  7098. const mobile = width.value < breakpointValue;
  7099. state.xs = xs;
  7100. state.sm = sm;
  7101. state.md = md;
  7102. state.lg = lg;
  7103. state.xl = xl;
  7104. state.xxl = xxl;
  7105. state.smAndUp = !xs;
  7106. state.mdAndUp = !(xs || sm);
  7107. state.lgAndUp = !(xs || sm || md);
  7108. state.xlAndUp = !(xs || sm || md || lg);
  7109. state.smAndDown = !(md || lg || xl || xxl);
  7110. state.mdAndDown = !(lg || xl || xxl);
  7111. state.lgAndDown = !(xl || xxl);
  7112. state.xlAndDown = !xxl;
  7113. state.name = name;
  7114. state.height = height.value;
  7115. state.width = width.value;
  7116. state.mobile = mobile;
  7117. state.mobileBreakpoint = mobileBreakpoint;
  7118. state.platform = platform.value;
  7119. state.thresholds = thresholds;
  7120. });
  7121. if (IN_BROWSER) {
  7122. window.addEventListener('resize', updateSize, {
  7123. passive: true
  7124. });
  7125. }
  7126. return {
  7127. ...vue.toRefs(state),
  7128. update,
  7129. ssr: !!ssr
  7130. };
  7131. }
  7132. const makeDisplayProps = propsFactory({
  7133. mobile: {
  7134. type: Boolean,
  7135. default: false
  7136. },
  7137. mobileBreakpoint: [Number, String]
  7138. }, 'display');
  7139. function useDisplay() {
  7140. let props = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
  7141. let name = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : getCurrentInstanceName();
  7142. const display = vue.inject(DisplaySymbol);
  7143. if (!display) throw new Error('Could not find Vuetify display injection');
  7144. const mobile = vue.computed(() => {
  7145. if (props.mobile != null) return props.mobile;
  7146. if (!props.mobileBreakpoint) return display.mobile.value;
  7147. const breakpointValue = typeof props.mobileBreakpoint === 'number' ? props.mobileBreakpoint : display.thresholds.value[props.mobileBreakpoint];
  7148. return display.width.value < breakpointValue;
  7149. });
  7150. const displayClasses = vue.computed(() => {
  7151. if (!name) return {};
  7152. return {
  7153. [`${name}--mobile`]: mobile.value
  7154. };
  7155. });
  7156. return {
  7157. ...display,
  7158. displayClasses,
  7159. mobile
  7160. };
  7161. }
  7162. // Utilities
  7163. // Types
  7164. const GoToSymbol = Symbol.for('vuetify:goto');
  7165. function genDefaults() {
  7166. return {
  7167. container: undefined,
  7168. duration: 300,
  7169. layout: false,
  7170. offset: 0,
  7171. easing: 'easeInOutCubic',
  7172. patterns: {
  7173. linear: t => t,
  7174. easeInQuad: t => t ** 2,
  7175. easeOutQuad: t => t * (2 - t),
  7176. easeInOutQuad: t => t < 0.5 ? 2 * t ** 2 : -1 + (4 - 2 * t) * t,
  7177. easeInCubic: t => t ** 3,
  7178. easeOutCubic: t => --t ** 3 + 1,
  7179. easeInOutCubic: t => t < 0.5 ? 4 * t ** 3 : (t - 1) * (2 * t - 2) * (2 * t - 2) + 1,
  7180. easeInQuart: t => t ** 4,
  7181. easeOutQuart: t => 1 - --t ** 4,
  7182. easeInOutQuart: t => t < 0.5 ? 8 * t ** 4 : 1 - 8 * --t ** 4,
  7183. easeInQuint: t => t ** 5,
  7184. easeOutQuint: t => 1 + --t ** 5,
  7185. easeInOutQuint: t => t < 0.5 ? 16 * t ** 5 : 1 + 16 * --t ** 5
  7186. }
  7187. };
  7188. }
  7189. function getContainer(el) {
  7190. return getTarget$1(el) ?? (document.scrollingElement || document.body);
  7191. }
  7192. function getTarget$1(el) {
  7193. return typeof el === 'string' ? document.querySelector(el) : refElement(el);
  7194. }
  7195. function getOffset$2(target, horizontal, rtl) {
  7196. if (typeof target === 'number') return horizontal && rtl ? -target : target;
  7197. let el = getTarget$1(target);
  7198. let totalOffset = 0;
  7199. while (el) {
  7200. totalOffset += horizontal ? el.offsetLeft : el.offsetTop;
  7201. el = el.offsetParent;
  7202. }
  7203. return totalOffset;
  7204. }
  7205. function createGoTo(options, locale) {
  7206. return {
  7207. rtl: locale.isRtl,
  7208. options: mergeDeep(genDefaults(), options)
  7209. };
  7210. }
  7211. async function scrollTo(_target, _options, horizontal, goTo) {
  7212. const property = horizontal ? 'scrollLeft' : 'scrollTop';
  7213. const options = mergeDeep(goTo?.options ?? genDefaults(), _options);
  7214. const rtl = goTo?.rtl.value;
  7215. const target = (typeof _target === 'number' ? _target : getTarget$1(_target)) ?? 0;
  7216. const container = options.container === 'parent' && target instanceof HTMLElement ? target.parentElement : getContainer(options.container);
  7217. const ease = typeof options.easing === 'function' ? options.easing : options.patterns[options.easing];
  7218. if (!ease) throw new TypeError(`Easing function "${options.easing}" not found.`);
  7219. let targetLocation;
  7220. if (typeof target === 'number') {
  7221. targetLocation = getOffset$2(target, horizontal, rtl);
  7222. } else {
  7223. targetLocation = getOffset$2(target, horizontal, rtl) - getOffset$2(container, horizontal, rtl);
  7224. if (options.layout) {
  7225. const styles = window.getComputedStyle(target);
  7226. const layoutOffset = styles.getPropertyValue('--v-layout-top');
  7227. if (layoutOffset) targetLocation -= parseInt(layoutOffset, 10);
  7228. }
  7229. }
  7230. targetLocation += options.offset;
  7231. targetLocation = clampTarget(container, targetLocation, !!rtl, !!horizontal);
  7232. const startLocation = container[property] ?? 0;
  7233. if (targetLocation === startLocation) return Promise.resolve(targetLocation);
  7234. const startTime = performance.now();
  7235. return new Promise(resolve => requestAnimationFrame(function step(currentTime) {
  7236. const timeElapsed = currentTime - startTime;
  7237. const progress = timeElapsed / options.duration;
  7238. const location = Math.floor(startLocation + (targetLocation - startLocation) * ease(clamp(progress, 0, 1)));
  7239. container[property] = location;
  7240. // Allow for some jitter if target time has elapsed
  7241. if (progress >= 1 && Math.abs(location - container[property]) < 10) {
  7242. return resolve(targetLocation);
  7243. } else if (progress > 2) {
  7244. // The target might not be reachable
  7245. consoleWarn('Scroll target is not reachable');
  7246. return resolve(container[property]);
  7247. }
  7248. requestAnimationFrame(step);
  7249. }));
  7250. }
  7251. function useGoTo() {
  7252. let _options = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
  7253. const goToInstance = vue.inject(GoToSymbol);
  7254. const {
  7255. isRtl
  7256. } = useRtl();
  7257. if (!goToInstance) throw new Error('[Vuetify] Could not find injected goto instance');
  7258. const goTo = {
  7259. ...goToInstance,
  7260. // can be set via VLocaleProvider
  7261. rtl: vue.computed(() => goToInstance.rtl.value || isRtl.value)
  7262. };
  7263. async function go(target, options) {
  7264. return scrollTo(target, mergeDeep(_options, options), false, goTo);
  7265. }
  7266. go.horizontal = async (target, options) => {
  7267. return scrollTo(target, mergeDeep(_options, options), true, goTo);
  7268. };
  7269. return go;
  7270. }
  7271. /**
  7272. * Clamp target value to achieve a smooth scroll animation
  7273. * when the value goes outside the scroll container size
  7274. */
  7275. function clampTarget(container, value, rtl, horizontal) {
  7276. const {
  7277. scrollWidth,
  7278. scrollHeight
  7279. } = container;
  7280. const [containerWidth, containerHeight] = container === document.scrollingElement ? [window.innerWidth, window.innerHeight] : [container.offsetWidth, container.offsetHeight];
  7281. let min;
  7282. let max;
  7283. if (horizontal) {
  7284. if (rtl) {
  7285. min = -(scrollWidth - containerWidth);
  7286. max = 0;
  7287. } else {
  7288. min = 0;
  7289. max = scrollWidth - containerWidth;
  7290. }
  7291. } else {
  7292. min = 0;
  7293. max = scrollHeight + -containerHeight;
  7294. }
  7295. return Math.max(Math.min(value, max), min);
  7296. }
  7297. function calculateUpdatedTarget(_ref) {
  7298. let {
  7299. selectedElement,
  7300. containerElement,
  7301. isRtl,
  7302. isHorizontal
  7303. } = _ref;
  7304. const containerSize = getOffsetSize(isHorizontal, containerElement);
  7305. const scrollPosition = getScrollPosition(isHorizontal, isRtl, containerElement);
  7306. const childrenSize = getOffsetSize(isHorizontal, selectedElement);
  7307. const childrenStartPosition = getOffsetPosition(isHorizontal, selectedElement);
  7308. const additionalOffset = childrenSize * 0.4;
  7309. if (scrollPosition > childrenStartPosition) {
  7310. return childrenStartPosition - additionalOffset;
  7311. } else if (scrollPosition + containerSize < childrenStartPosition + childrenSize) {
  7312. return childrenStartPosition - containerSize + childrenSize + additionalOffset;
  7313. }
  7314. return scrollPosition;
  7315. }
  7316. function calculateCenteredTarget(_ref2) {
  7317. let {
  7318. selectedElement,
  7319. containerElement,
  7320. isHorizontal
  7321. } = _ref2;
  7322. const containerOffsetSize = getOffsetSize(isHorizontal, containerElement);
  7323. const childrenOffsetPosition = getOffsetPosition(isHorizontal, selectedElement);
  7324. const childrenOffsetSize = getOffsetSize(isHorizontal, selectedElement);
  7325. return childrenOffsetPosition - containerOffsetSize / 2 + childrenOffsetSize / 2;
  7326. }
  7327. function getScrollSize(isHorizontal, element) {
  7328. const key = isHorizontal ? 'scrollWidth' : 'scrollHeight';
  7329. return element?.[key] || 0;
  7330. }
  7331. function getClientSize(isHorizontal, element) {
  7332. const key = isHorizontal ? 'clientWidth' : 'clientHeight';
  7333. return element?.[key] || 0;
  7334. }
  7335. function getScrollPosition(isHorizontal, rtl, element) {
  7336. if (!element) {
  7337. return 0;
  7338. }
  7339. const {
  7340. scrollLeft,
  7341. offsetWidth,
  7342. scrollWidth
  7343. } = element;
  7344. if (isHorizontal) {
  7345. return rtl ? scrollWidth - offsetWidth + scrollLeft : scrollLeft;
  7346. }
  7347. return element.scrollTop;
  7348. }
  7349. function getOffsetSize(isHorizontal, element) {
  7350. const key = isHorizontal ? 'offsetWidth' : 'offsetHeight';
  7351. return element?.[key] || 0;
  7352. }
  7353. function getOffsetPosition(isHorizontal, element) {
  7354. const key = isHorizontal ? 'offsetLeft' : 'offsetTop';
  7355. return element?.[key] || 0;
  7356. }
  7357. // Types
  7358. const VSlideGroupSymbol = Symbol.for('vuetify:v-slide-group');
  7359. const makeVSlideGroupProps = propsFactory({
  7360. centerActive: Boolean,
  7361. direction: {
  7362. type: String,
  7363. default: 'horizontal'
  7364. },
  7365. symbol: {
  7366. type: null,
  7367. default: VSlideGroupSymbol
  7368. },
  7369. nextIcon: {
  7370. type: IconValue,
  7371. default: '$next'
  7372. },
  7373. prevIcon: {
  7374. type: IconValue,
  7375. default: '$prev'
  7376. },
  7377. showArrows: {
  7378. type: [Boolean, String],
  7379. validator: v => typeof v === 'boolean' || ['always', 'desktop', 'mobile'].includes(v)
  7380. },
  7381. ...makeComponentProps(),
  7382. ...makeDisplayProps({
  7383. mobile: null
  7384. }),
  7385. ...makeTagProps(),
  7386. ...makeGroupProps({
  7387. selectedClass: 'v-slide-group-item--active'
  7388. })
  7389. }, 'VSlideGroup');
  7390. const VSlideGroup = genericComponent()({
  7391. name: 'VSlideGroup',
  7392. props: makeVSlideGroupProps(),
  7393. emits: {
  7394. 'update:modelValue': value => true
  7395. },
  7396. setup(props, _ref) {
  7397. let {
  7398. slots
  7399. } = _ref;
  7400. const {
  7401. isRtl
  7402. } = useRtl();
  7403. const {
  7404. displayClasses,
  7405. mobile
  7406. } = useDisplay(props);
  7407. const group = useGroup(props, props.symbol);
  7408. const isOverflowing = vue.shallowRef(false);
  7409. const scrollOffset = vue.shallowRef(0);
  7410. const containerSize = vue.shallowRef(0);
  7411. const contentSize = vue.shallowRef(0);
  7412. const isHorizontal = vue.computed(() => props.direction === 'horizontal');
  7413. const {
  7414. resizeRef: containerRef,
  7415. contentRect: containerRect
  7416. } = useResizeObserver();
  7417. const {
  7418. resizeRef: contentRef,
  7419. contentRect
  7420. } = useResizeObserver();
  7421. const goTo = useGoTo();
  7422. const goToOptions = vue.computed(() => {
  7423. return {
  7424. container: containerRef.el,
  7425. duration: 200,
  7426. easing: 'easeOutQuart'
  7427. };
  7428. });
  7429. const firstSelectedIndex = vue.computed(() => {
  7430. if (!group.selected.value.length) return -1;
  7431. return group.items.value.findIndex(item => item.id === group.selected.value[0]);
  7432. });
  7433. const lastSelectedIndex = vue.computed(() => {
  7434. if (!group.selected.value.length) return -1;
  7435. return group.items.value.findIndex(item => item.id === group.selected.value[group.selected.value.length - 1]);
  7436. });
  7437. if (IN_BROWSER) {
  7438. let frame = -1;
  7439. vue.watch(() => [group.selected.value, containerRect.value, contentRect.value, isHorizontal.value], () => {
  7440. cancelAnimationFrame(frame);
  7441. frame = requestAnimationFrame(() => {
  7442. if (containerRect.value && contentRect.value) {
  7443. const sizeProperty = isHorizontal.value ? 'width' : 'height';
  7444. containerSize.value = containerRect.value[sizeProperty];
  7445. contentSize.value = contentRect.value[sizeProperty];
  7446. isOverflowing.value = containerSize.value + 1 < contentSize.value;
  7447. }
  7448. if (firstSelectedIndex.value >= 0 && contentRef.el) {
  7449. // TODO: Is this too naive? Should we store element references in group composable?
  7450. const selectedElement = contentRef.el.children[lastSelectedIndex.value];
  7451. scrollToChildren(selectedElement, props.centerActive);
  7452. }
  7453. });
  7454. });
  7455. }
  7456. const isFocused = vue.shallowRef(false);
  7457. function scrollToChildren(children, center) {
  7458. let target = 0;
  7459. if (center) {
  7460. target = calculateCenteredTarget({
  7461. containerElement: containerRef.el,
  7462. isHorizontal: isHorizontal.value,
  7463. selectedElement: children
  7464. });
  7465. } else {
  7466. target = calculateUpdatedTarget({
  7467. containerElement: containerRef.el,
  7468. isHorizontal: isHorizontal.value,
  7469. isRtl: isRtl.value,
  7470. selectedElement: children
  7471. });
  7472. }
  7473. scrollToPosition(target);
  7474. }
  7475. function scrollToPosition(newPosition) {
  7476. if (!IN_BROWSER || !containerRef.el) return;
  7477. const offsetSize = getOffsetSize(isHorizontal.value, containerRef.el);
  7478. const scrollPosition = getScrollPosition(isHorizontal.value, isRtl.value, containerRef.el);
  7479. const scrollSize = getScrollSize(isHorizontal.value, containerRef.el);
  7480. if (scrollSize <= offsetSize ||
  7481. // Prevent scrolling by only a couple of pixels, which doesn't look smooth
  7482. Math.abs(newPosition - scrollPosition) < 16) return;
  7483. if (isHorizontal.value && isRtl.value && containerRef.el) {
  7484. const {
  7485. scrollWidth,
  7486. offsetWidth: containerWidth
  7487. } = containerRef.el;
  7488. newPosition = scrollWidth - containerWidth - newPosition;
  7489. }
  7490. if (isHorizontal.value) {
  7491. goTo.horizontal(newPosition, goToOptions.value);
  7492. } else {
  7493. goTo(newPosition, goToOptions.value);
  7494. }
  7495. }
  7496. function onScroll(e) {
  7497. const {
  7498. scrollTop,
  7499. scrollLeft
  7500. } = e.target;
  7501. scrollOffset.value = isHorizontal.value ? scrollLeft : scrollTop;
  7502. }
  7503. function onFocusin(e) {
  7504. isFocused.value = true;
  7505. if (!isOverflowing.value || !contentRef.el) return;
  7506. // Focused element is likely to be the root of an item, so a
  7507. // breadth-first search will probably find it in the first iteration
  7508. for (const el of e.composedPath()) {
  7509. for (const item of contentRef.el.children) {
  7510. if (item === el) {
  7511. scrollToChildren(item);
  7512. return;
  7513. }
  7514. }
  7515. }
  7516. }
  7517. function onFocusout(e) {
  7518. isFocused.value = false;
  7519. }
  7520. // Affix clicks produce onFocus that we have to ignore to avoid extra scrollToChildren
  7521. let ignoreFocusEvent = false;
  7522. function onFocus(e) {
  7523. if (!ignoreFocusEvent && !isFocused.value && !(e.relatedTarget && contentRef.el?.contains(e.relatedTarget))) focus();
  7524. ignoreFocusEvent = false;
  7525. }
  7526. function onFocusAffixes() {
  7527. ignoreFocusEvent = true;
  7528. }
  7529. function onKeydown(e) {
  7530. if (!contentRef.el) return;
  7531. function toFocus(location) {
  7532. e.preventDefault();
  7533. focus(location);
  7534. }
  7535. if (isHorizontal.value) {
  7536. if (e.key === 'ArrowRight') {
  7537. toFocus(isRtl.value ? 'prev' : 'next');
  7538. } else if (e.key === 'ArrowLeft') {
  7539. toFocus(isRtl.value ? 'next' : 'prev');
  7540. }
  7541. } else {
  7542. if (e.key === 'ArrowDown') {
  7543. toFocus('next');
  7544. } else if (e.key === 'ArrowUp') {
  7545. toFocus('prev');
  7546. }
  7547. }
  7548. if (e.key === 'Home') {
  7549. toFocus('first');
  7550. } else if (e.key === 'End') {
  7551. toFocus('last');
  7552. }
  7553. }
  7554. function focus(location) {
  7555. if (!contentRef.el) return;
  7556. let el;
  7557. if (!location) {
  7558. const focusable = focusableChildren(contentRef.el);
  7559. el = focusable[0];
  7560. } else if (location === 'next') {
  7561. el = contentRef.el.querySelector(':focus')?.nextElementSibling;
  7562. if (!el) return focus('first');
  7563. } else if (location === 'prev') {
  7564. el = contentRef.el.querySelector(':focus')?.previousElementSibling;
  7565. if (!el) return focus('last');
  7566. } else if (location === 'first') {
  7567. el = contentRef.el.firstElementChild;
  7568. } else if (location === 'last') {
  7569. el = contentRef.el.lastElementChild;
  7570. }
  7571. if (el) {
  7572. el.focus({
  7573. preventScroll: true
  7574. });
  7575. }
  7576. }
  7577. function scrollTo(location) {
  7578. const direction = isHorizontal.value && isRtl.value ? -1 : 1;
  7579. const offsetStep = (location === 'prev' ? -direction : direction) * containerSize.value;
  7580. let newPosition = scrollOffset.value + offsetStep;
  7581. // TODO: improve it
  7582. if (isHorizontal.value && isRtl.value && containerRef.el) {
  7583. const {
  7584. scrollWidth,
  7585. offsetWidth: containerWidth
  7586. } = containerRef.el;
  7587. newPosition += scrollWidth - containerWidth;
  7588. }
  7589. scrollToPosition(newPosition);
  7590. }
  7591. const slotProps = vue.computed(() => ({
  7592. next: group.next,
  7593. prev: group.prev,
  7594. select: group.select,
  7595. isSelected: group.isSelected
  7596. }));
  7597. const hasAffixes = vue.computed(() => {
  7598. switch (props.showArrows) {
  7599. // Always show arrows on desktop & mobile
  7600. case 'always':
  7601. return true;
  7602. // Always show arrows on desktop
  7603. case 'desktop':
  7604. return !mobile.value;
  7605. // Show arrows on mobile when overflowing.
  7606. // This matches the default 2.2 behavior
  7607. case true:
  7608. return isOverflowing.value || Math.abs(scrollOffset.value) > 0;
  7609. // Always show on mobile
  7610. case 'mobile':
  7611. return mobile.value || isOverflowing.value || Math.abs(scrollOffset.value) > 0;
  7612. // https://material.io/components/tabs#scrollable-tabs
  7613. // Always show arrows when
  7614. // overflowed on desktop
  7615. default:
  7616. return !mobile.value && (isOverflowing.value || Math.abs(scrollOffset.value) > 0);
  7617. }
  7618. });
  7619. const hasPrev = vue.computed(() => {
  7620. // 1 pixel in reserve, may be lost after rounding
  7621. return Math.abs(scrollOffset.value) > 1;
  7622. });
  7623. const hasNext = vue.computed(() => {
  7624. if (!containerRef.value) return false;
  7625. const scrollSize = getScrollSize(isHorizontal.value, containerRef.el);
  7626. const clientSize = getClientSize(isHorizontal.value, containerRef.el);
  7627. const scrollSizeMax = scrollSize - clientSize;
  7628. // 1 pixel in reserve, may be lost after rounding
  7629. return scrollSizeMax - Math.abs(scrollOffset.value) > 1;
  7630. });
  7631. useRender(() => vue.createVNode(props.tag, {
  7632. "class": ['v-slide-group', {
  7633. 'v-slide-group--vertical': !isHorizontal.value,
  7634. 'v-slide-group--has-affixes': hasAffixes.value,
  7635. 'v-slide-group--is-overflowing': isOverflowing.value
  7636. }, displayClasses.value, props.class],
  7637. "style": props.style,
  7638. "tabindex": isFocused.value || group.selected.value.length ? -1 : 0,
  7639. "onFocus": onFocus
  7640. }, {
  7641. default: () => [hasAffixes.value && vue.createVNode("div", {
  7642. "key": "prev",
  7643. "class": ['v-slide-group__prev', {
  7644. 'v-slide-group__prev--disabled': !hasPrev.value
  7645. }],
  7646. "onMousedown": onFocusAffixes,
  7647. "onClick": () => hasPrev.value && scrollTo('prev')
  7648. }, [slots.prev?.(slotProps.value) ?? vue.createVNode(VFadeTransition, null, {
  7649. default: () => [vue.createVNode(VIcon, {
  7650. "icon": isRtl.value ? props.nextIcon : props.prevIcon
  7651. }, null)]
  7652. })]), vue.createVNode("div", {
  7653. "key": "container",
  7654. "ref": containerRef,
  7655. "class": "v-slide-group__container",
  7656. "onScroll": onScroll
  7657. }, [vue.createVNode("div", {
  7658. "ref": contentRef,
  7659. "class": "v-slide-group__content",
  7660. "onFocusin": onFocusin,
  7661. "onFocusout": onFocusout,
  7662. "onKeydown": onKeydown
  7663. }, [slots.default?.(slotProps.value)])]), hasAffixes.value && vue.createVNode("div", {
  7664. "key": "next",
  7665. "class": ['v-slide-group__next', {
  7666. 'v-slide-group__next--disabled': !hasNext.value
  7667. }],
  7668. "onMousedown": onFocusAffixes,
  7669. "onClick": () => hasNext.value && scrollTo('next')
  7670. }, [slots.next?.(slotProps.value) ?? vue.createVNode(VFadeTransition, null, {
  7671. default: () => [vue.createVNode(VIcon, {
  7672. "icon": isRtl.value ? props.prevIcon : props.nextIcon
  7673. }, null)]
  7674. })])]
  7675. }));
  7676. return {
  7677. selected: group.selected,
  7678. scrollTo,
  7679. scrollOffset,
  7680. focus,
  7681. hasPrev,
  7682. hasNext
  7683. };
  7684. }
  7685. });
  7686. // Types
  7687. const VChipGroupSymbol = Symbol.for('vuetify:v-chip-group');
  7688. const makeVChipGroupProps = propsFactory({
  7689. column: Boolean,
  7690. filter: Boolean,
  7691. valueComparator: {
  7692. type: Function,
  7693. default: deepEqual
  7694. },
  7695. ...makeVSlideGroupProps(),
  7696. ...makeComponentProps(),
  7697. ...makeGroupProps({
  7698. selectedClass: 'v-chip--selected'
  7699. }),
  7700. ...makeTagProps(),
  7701. ...makeThemeProps(),
  7702. ...makeVariantProps({
  7703. variant: 'tonal'
  7704. })
  7705. }, 'VChipGroup');
  7706. const VChipGroup = genericComponent()({
  7707. name: 'VChipGroup',
  7708. props: makeVChipGroupProps(),
  7709. emits: {
  7710. 'update:modelValue': value => true
  7711. },
  7712. setup(props, _ref) {
  7713. let {
  7714. slots
  7715. } = _ref;
  7716. const {
  7717. themeClasses
  7718. } = provideTheme(props);
  7719. const {
  7720. isSelected,
  7721. select,
  7722. next,
  7723. prev,
  7724. selected
  7725. } = useGroup(props, VChipGroupSymbol);
  7726. provideDefaults({
  7727. VChip: {
  7728. color: vue.toRef(props, 'color'),
  7729. disabled: vue.toRef(props, 'disabled'),
  7730. filter: vue.toRef(props, 'filter'),
  7731. variant: vue.toRef(props, 'variant')
  7732. }
  7733. });
  7734. useRender(() => {
  7735. const slideGroupProps = VSlideGroup.filterProps(props);
  7736. return vue.createVNode(VSlideGroup, vue.mergeProps(slideGroupProps, {
  7737. "class": ['v-chip-group', {
  7738. 'v-chip-group--column': props.column
  7739. }, themeClasses.value, props.class],
  7740. "style": props.style
  7741. }), {
  7742. default: () => [slots.default?.({
  7743. isSelected,
  7744. select,
  7745. next,
  7746. prev,
  7747. selected: selected.value
  7748. })]
  7749. });
  7750. });
  7751. return {};
  7752. }
  7753. });
  7754. // Types
  7755. const makeVChipProps = propsFactory({
  7756. activeClass: String,
  7757. appendAvatar: String,
  7758. appendIcon: IconValue,
  7759. closable: Boolean,
  7760. closeIcon: {
  7761. type: IconValue,
  7762. default: '$delete'
  7763. },
  7764. closeLabel: {
  7765. type: String,
  7766. default: '$vuetify.close'
  7767. },
  7768. draggable: Boolean,
  7769. filter: Boolean,
  7770. filterIcon: {
  7771. type: IconValue,
  7772. default: '$complete'
  7773. },
  7774. label: Boolean,
  7775. link: {
  7776. type: Boolean,
  7777. default: undefined
  7778. },
  7779. pill: Boolean,
  7780. prependAvatar: String,
  7781. prependIcon: IconValue,
  7782. ripple: {
  7783. type: [Boolean, Object],
  7784. default: true
  7785. },
  7786. text: String,
  7787. modelValue: {
  7788. type: Boolean,
  7789. default: true
  7790. },
  7791. onClick: EventProp(),
  7792. onClickOnce: EventProp(),
  7793. ...makeBorderProps(),
  7794. ...makeComponentProps(),
  7795. ...makeDensityProps(),
  7796. ...makeElevationProps(),
  7797. ...makeGroupItemProps(),
  7798. ...makeRoundedProps(),
  7799. ...makeRouterProps(),
  7800. ...makeSizeProps(),
  7801. ...makeTagProps({
  7802. tag: 'span'
  7803. }),
  7804. ...makeThemeProps(),
  7805. ...makeVariantProps({
  7806. variant: 'tonal'
  7807. })
  7808. }, 'VChip');
  7809. const VChip = genericComponent()({
  7810. name: 'VChip',
  7811. directives: {
  7812. Ripple
  7813. },
  7814. props: makeVChipProps(),
  7815. emits: {
  7816. 'click:close': e => true,
  7817. 'update:modelValue': value => true,
  7818. 'group:selected': val => true,
  7819. click: e => true
  7820. },
  7821. setup(props, _ref) {
  7822. let {
  7823. attrs,
  7824. emit,
  7825. slots
  7826. } = _ref;
  7827. const {
  7828. t
  7829. } = useLocale();
  7830. const {
  7831. borderClasses
  7832. } = useBorder(props);
  7833. const {
  7834. colorClasses,
  7835. colorStyles,
  7836. variantClasses
  7837. } = useVariant(props);
  7838. const {
  7839. densityClasses
  7840. } = useDensity(props);
  7841. const {
  7842. elevationClasses
  7843. } = useElevation(props);
  7844. const {
  7845. roundedClasses
  7846. } = useRounded(props);
  7847. const {
  7848. sizeClasses
  7849. } = useSize(props);
  7850. const {
  7851. themeClasses
  7852. } = provideTheme(props);
  7853. const isActive = useProxiedModel(props, 'modelValue');
  7854. const group = useGroupItem(props, VChipGroupSymbol, false);
  7855. const link = useLink(props, attrs);
  7856. const isLink = vue.computed(() => props.link !== false && link.isLink.value);
  7857. const isClickable = vue.computed(() => !props.disabled && props.link !== false && (!!group || props.link || link.isClickable.value));
  7858. const closeProps = vue.computed(() => ({
  7859. 'aria-label': t(props.closeLabel),
  7860. onClick(e) {
  7861. e.preventDefault();
  7862. e.stopPropagation();
  7863. isActive.value = false;
  7864. emit('click:close', e);
  7865. }
  7866. }));
  7867. function onClick(e) {
  7868. emit('click', e);
  7869. if (!isClickable.value) return;
  7870. link.navigate?.(e);
  7871. group?.toggle();
  7872. }
  7873. function onKeyDown(e) {
  7874. if (e.key === 'Enter' || e.key === ' ') {
  7875. e.preventDefault();
  7876. onClick(e);
  7877. }
  7878. }
  7879. return () => {
  7880. const Tag = link.isLink.value ? 'a' : props.tag;
  7881. const hasAppendMedia = !!(props.appendIcon || props.appendAvatar);
  7882. const hasAppend = !!(hasAppendMedia || slots.append);
  7883. const hasClose = !!(slots.close || props.closable);
  7884. const hasFilter = !!(slots.filter || props.filter) && group;
  7885. const hasPrependMedia = !!(props.prependIcon || props.prependAvatar);
  7886. const hasPrepend = !!(hasPrependMedia || slots.prepend);
  7887. const hasColor = !group || group.isSelected.value;
  7888. return isActive.value && vue.withDirectives(vue.createVNode(Tag, vue.mergeProps({
  7889. "class": ['v-chip', {
  7890. 'v-chip--disabled': props.disabled,
  7891. 'v-chip--label': props.label,
  7892. 'v-chip--link': isClickable.value,
  7893. 'v-chip--filter': hasFilter,
  7894. 'v-chip--pill': props.pill,
  7895. [`${props.activeClass}`]: props.activeClass && link.isActive?.value
  7896. }, themeClasses.value, borderClasses.value, hasColor ? colorClasses.value : undefined, densityClasses.value, elevationClasses.value, roundedClasses.value, sizeClasses.value, variantClasses.value, group?.selectedClass.value, props.class],
  7897. "style": [hasColor ? colorStyles.value : undefined, props.style],
  7898. "disabled": props.disabled || undefined,
  7899. "draggable": props.draggable,
  7900. "tabindex": isClickable.value ? 0 : undefined,
  7901. "onClick": onClick,
  7902. "onKeydown": isClickable.value && !isLink.value && onKeyDown
  7903. }, link.linkProps), {
  7904. default: () => [genOverlays(isClickable.value, 'v-chip'), hasFilter && vue.createVNode(VExpandXTransition, {
  7905. "key": "filter"
  7906. }, {
  7907. default: () => [vue.withDirectives(vue.createVNode("div", {
  7908. "class": "v-chip__filter"
  7909. }, [!slots.filter ? vue.createVNode(VIcon, {
  7910. "key": "filter-icon",
  7911. "icon": props.filterIcon
  7912. }, null) : vue.createVNode(VDefaultsProvider, {
  7913. "key": "filter-defaults",
  7914. "disabled": !props.filterIcon,
  7915. "defaults": {
  7916. VIcon: {
  7917. icon: props.filterIcon
  7918. }
  7919. }
  7920. }, slots.filter)]), [[vue.vShow, group.isSelected.value]])]
  7921. }), hasPrepend && vue.createVNode("div", {
  7922. "key": "prepend",
  7923. "class": "v-chip__prepend"
  7924. }, [!slots.prepend ? vue.createVNode(vue.Fragment, null, [props.prependIcon && vue.createVNode(VIcon, {
  7925. "key": "prepend-icon",
  7926. "icon": props.prependIcon,
  7927. "start": true
  7928. }, null), props.prependAvatar && vue.createVNode(VAvatar, {
  7929. "key": "prepend-avatar",
  7930. "image": props.prependAvatar,
  7931. "start": true
  7932. }, null)]) : vue.createVNode(VDefaultsProvider, {
  7933. "key": "prepend-defaults",
  7934. "disabled": !hasPrependMedia,
  7935. "defaults": {
  7936. VAvatar: {
  7937. image: props.prependAvatar,
  7938. start: true
  7939. },
  7940. VIcon: {
  7941. icon: props.prependIcon,
  7942. start: true
  7943. }
  7944. }
  7945. }, slots.prepend)]), vue.createVNode("div", {
  7946. "class": "v-chip__content",
  7947. "data-no-activator": ""
  7948. }, [slots.default?.({
  7949. isSelected: group?.isSelected.value,
  7950. selectedClass: group?.selectedClass.value,
  7951. select: group?.select,
  7952. toggle: group?.toggle,
  7953. value: group?.value.value,
  7954. disabled: props.disabled
  7955. }) ?? props.text]), hasAppend && vue.createVNode("div", {
  7956. "key": "append",
  7957. "class": "v-chip__append"
  7958. }, [!slots.append ? vue.createVNode(vue.Fragment, null, [props.appendIcon && vue.createVNode(VIcon, {
  7959. "key": "append-icon",
  7960. "end": true,
  7961. "icon": props.appendIcon
  7962. }, null), props.appendAvatar && vue.createVNode(VAvatar, {
  7963. "key": "append-avatar",
  7964. "end": true,
  7965. "image": props.appendAvatar
  7966. }, null)]) : vue.createVNode(VDefaultsProvider, {
  7967. "key": "append-defaults",
  7968. "disabled": !hasAppendMedia,
  7969. "defaults": {
  7970. VAvatar: {
  7971. end: true,
  7972. image: props.appendAvatar
  7973. },
  7974. VIcon: {
  7975. end: true,
  7976. icon: props.appendIcon
  7977. }
  7978. }
  7979. }, slots.append)]), hasClose && vue.createVNode("button", vue.mergeProps({
  7980. "key": "close",
  7981. "class": "v-chip__close",
  7982. "type": "button",
  7983. "data-testid": "close-chip"
  7984. }, closeProps.value), [!slots.close ? vue.createVNode(VIcon, {
  7985. "key": "close-icon",
  7986. "icon": props.closeIcon,
  7987. "size": "x-small"
  7988. }, null) : vue.createVNode(VDefaultsProvider, {
  7989. "key": "close-defaults",
  7990. "defaults": {
  7991. VIcon: {
  7992. icon: props.closeIcon,
  7993. size: 'x-small'
  7994. }
  7995. }
  7996. }, slots.close)])]
  7997. }), [[vue.resolveDirective("ripple"), isClickable.value && props.ripple, null]]);
  7998. };
  7999. }
  8000. });
  8001. // Utilities
  8002. // List
  8003. const ListKey = Symbol.for('vuetify:list');
  8004. function createList() {
  8005. const parent = vue.inject(ListKey, {
  8006. hasPrepend: vue.shallowRef(false),
  8007. updateHasPrepend: () => null
  8008. });
  8009. const data = {
  8010. hasPrepend: vue.shallowRef(false),
  8011. updateHasPrepend: value => {
  8012. if (value) data.hasPrepend.value = value;
  8013. }
  8014. };
  8015. vue.provide(ListKey, data);
  8016. return parent;
  8017. }
  8018. function useList() {
  8019. return vue.inject(ListKey, null);
  8020. }
  8021. /* eslint-disable sonarjs/no-identical-functions */
  8022. // Utilities
  8023. const independentActiveStrategy = mandatory => {
  8024. const strategy = {
  8025. activate: _ref => {
  8026. let {
  8027. id,
  8028. value,
  8029. activated
  8030. } = _ref;
  8031. id = vue.toRaw(id);
  8032. // When mandatory and we're trying to deselect when id
  8033. // is the only currently selected item then do nothing
  8034. if (mandatory && !value && activated.size === 1 && activated.has(id)) return activated;
  8035. if (value) {
  8036. activated.add(id);
  8037. } else {
  8038. activated.delete(id);
  8039. }
  8040. return activated;
  8041. },
  8042. in: (v, children, parents) => {
  8043. let set = new Set();
  8044. if (v != null) {
  8045. for (const id of wrapInArray(v)) {
  8046. set = strategy.activate({
  8047. id,
  8048. value: true,
  8049. activated: new Set(set),
  8050. children,
  8051. parents
  8052. });
  8053. }
  8054. }
  8055. return set;
  8056. },
  8057. out: v => {
  8058. return Array.from(v);
  8059. }
  8060. };
  8061. return strategy;
  8062. };
  8063. const independentSingleActiveStrategy = mandatory => {
  8064. const parentStrategy = independentActiveStrategy(mandatory);
  8065. const strategy = {
  8066. activate: _ref2 => {
  8067. let {
  8068. activated,
  8069. id,
  8070. ...rest
  8071. } = _ref2;
  8072. id = vue.toRaw(id);
  8073. const singleSelected = activated.has(id) ? new Set([id]) : new Set();
  8074. return parentStrategy.activate({
  8075. ...rest,
  8076. id,
  8077. activated: singleSelected
  8078. });
  8079. },
  8080. in: (v, children, parents) => {
  8081. let set = new Set();
  8082. if (v != null) {
  8083. const arr = wrapInArray(v);
  8084. if (arr.length) {
  8085. set = parentStrategy.in(arr.slice(0, 1), children, parents);
  8086. }
  8087. }
  8088. return set;
  8089. },
  8090. out: (v, children, parents) => {
  8091. return parentStrategy.out(v, children, parents);
  8092. }
  8093. };
  8094. return strategy;
  8095. };
  8096. const leafActiveStrategy = mandatory => {
  8097. const parentStrategy = independentActiveStrategy(mandatory);
  8098. const strategy = {
  8099. activate: _ref3 => {
  8100. let {
  8101. id,
  8102. activated,
  8103. children,
  8104. ...rest
  8105. } = _ref3;
  8106. id = vue.toRaw(id);
  8107. if (children.has(id)) return activated;
  8108. return parentStrategy.activate({
  8109. id,
  8110. activated,
  8111. children,
  8112. ...rest
  8113. });
  8114. },
  8115. in: parentStrategy.in,
  8116. out: parentStrategy.out
  8117. };
  8118. return strategy;
  8119. };
  8120. const leafSingleActiveStrategy = mandatory => {
  8121. const parentStrategy = independentSingleActiveStrategy(mandatory);
  8122. const strategy = {
  8123. activate: _ref4 => {
  8124. let {
  8125. id,
  8126. activated,
  8127. children,
  8128. ...rest
  8129. } = _ref4;
  8130. id = vue.toRaw(id);
  8131. if (children.has(id)) return activated;
  8132. return parentStrategy.activate({
  8133. id,
  8134. activated,
  8135. children,
  8136. ...rest
  8137. });
  8138. },
  8139. in: parentStrategy.in,
  8140. out: parentStrategy.out
  8141. };
  8142. return strategy;
  8143. };
  8144. const singleOpenStrategy = {
  8145. open: _ref => {
  8146. let {
  8147. id,
  8148. value,
  8149. opened,
  8150. parents
  8151. } = _ref;
  8152. if (value) {
  8153. const newOpened = new Set();
  8154. newOpened.add(id);
  8155. let parent = parents.get(id);
  8156. while (parent != null) {
  8157. newOpened.add(parent);
  8158. parent = parents.get(parent);
  8159. }
  8160. return newOpened;
  8161. } else {
  8162. opened.delete(id);
  8163. return opened;
  8164. }
  8165. },
  8166. select: () => null
  8167. };
  8168. const multipleOpenStrategy = {
  8169. open: _ref2 => {
  8170. let {
  8171. id,
  8172. value,
  8173. opened,
  8174. parents
  8175. } = _ref2;
  8176. if (value) {
  8177. let parent = parents.get(id);
  8178. opened.add(id);
  8179. while (parent != null && parent !== id) {
  8180. opened.add(parent);
  8181. parent = parents.get(parent);
  8182. }
  8183. return opened;
  8184. } else {
  8185. opened.delete(id);
  8186. }
  8187. return opened;
  8188. },
  8189. select: () => null
  8190. };
  8191. const listOpenStrategy = {
  8192. open: multipleOpenStrategy.open,
  8193. select: _ref3 => {
  8194. let {
  8195. id,
  8196. value,
  8197. opened,
  8198. parents
  8199. } = _ref3;
  8200. if (!value) return opened;
  8201. const path = [];
  8202. let parent = parents.get(id);
  8203. while (parent != null) {
  8204. path.push(parent);
  8205. parent = parents.get(parent);
  8206. }
  8207. return new Set(path);
  8208. }
  8209. };
  8210. /* eslint-disable sonarjs/no-identical-functions */
  8211. // Utilities
  8212. const independentSelectStrategy = mandatory => {
  8213. const strategy = {
  8214. select: _ref => {
  8215. let {
  8216. id,
  8217. value,
  8218. selected
  8219. } = _ref;
  8220. id = vue.toRaw(id);
  8221. // When mandatory and we're trying to deselect when id
  8222. // is the only currently selected item then do nothing
  8223. if (mandatory && !value) {
  8224. const on = Array.from(selected.entries()).reduce((arr, _ref2) => {
  8225. let [key, value] = _ref2;
  8226. if (value === 'on') arr.push(key);
  8227. return arr;
  8228. }, []);
  8229. if (on.length === 1 && on[0] === id) return selected;
  8230. }
  8231. selected.set(id, value ? 'on' : 'off');
  8232. return selected;
  8233. },
  8234. in: (v, children, parents) => {
  8235. let map = new Map();
  8236. for (const id of v || []) {
  8237. map = strategy.select({
  8238. id,
  8239. value: true,
  8240. selected: new Map(map),
  8241. children,
  8242. parents
  8243. });
  8244. }
  8245. return map;
  8246. },
  8247. out: v => {
  8248. const arr = [];
  8249. for (const [key, value] of v.entries()) {
  8250. if (value === 'on') arr.push(key);
  8251. }
  8252. return arr;
  8253. }
  8254. };
  8255. return strategy;
  8256. };
  8257. const independentSingleSelectStrategy = mandatory => {
  8258. const parentStrategy = independentSelectStrategy(mandatory);
  8259. const strategy = {
  8260. select: _ref3 => {
  8261. let {
  8262. selected,
  8263. id,
  8264. ...rest
  8265. } = _ref3;
  8266. id = vue.toRaw(id);
  8267. const singleSelected = selected.has(id) ? new Map([[id, selected.get(id)]]) : new Map();
  8268. return parentStrategy.select({
  8269. ...rest,
  8270. id,
  8271. selected: singleSelected
  8272. });
  8273. },
  8274. in: (v, children, parents) => {
  8275. let map = new Map();
  8276. if (v?.length) {
  8277. map = parentStrategy.in(v.slice(0, 1), children, parents);
  8278. }
  8279. return map;
  8280. },
  8281. out: (v, children, parents) => {
  8282. return parentStrategy.out(v, children, parents);
  8283. }
  8284. };
  8285. return strategy;
  8286. };
  8287. const leafSelectStrategy = mandatory => {
  8288. const parentStrategy = independentSelectStrategy(mandatory);
  8289. const strategy = {
  8290. select: _ref4 => {
  8291. let {
  8292. id,
  8293. selected,
  8294. children,
  8295. ...rest
  8296. } = _ref4;
  8297. id = vue.toRaw(id);
  8298. if (children.has(id)) return selected;
  8299. return parentStrategy.select({
  8300. id,
  8301. selected,
  8302. children,
  8303. ...rest
  8304. });
  8305. },
  8306. in: parentStrategy.in,
  8307. out: parentStrategy.out
  8308. };
  8309. return strategy;
  8310. };
  8311. const leafSingleSelectStrategy = mandatory => {
  8312. const parentStrategy = independentSingleSelectStrategy(mandatory);
  8313. const strategy = {
  8314. select: _ref5 => {
  8315. let {
  8316. id,
  8317. selected,
  8318. children,
  8319. ...rest
  8320. } = _ref5;
  8321. id = vue.toRaw(id);
  8322. if (children.has(id)) return selected;
  8323. return parentStrategy.select({
  8324. id,
  8325. selected,
  8326. children,
  8327. ...rest
  8328. });
  8329. },
  8330. in: parentStrategy.in,
  8331. out: parentStrategy.out
  8332. };
  8333. return strategy;
  8334. };
  8335. const classicSelectStrategy = mandatory => {
  8336. const strategy = {
  8337. select: _ref6 => {
  8338. let {
  8339. id,
  8340. value,
  8341. selected,
  8342. children,
  8343. parents
  8344. } = _ref6;
  8345. id = vue.toRaw(id);
  8346. const original = new Map(selected);
  8347. const items = [id];
  8348. while (items.length) {
  8349. const item = items.shift();
  8350. selected.set(vue.toRaw(item), value ? 'on' : 'off');
  8351. if (children.has(item)) {
  8352. items.push(...children.get(item));
  8353. }
  8354. }
  8355. let parent = vue.toRaw(parents.get(id));
  8356. while (parent) {
  8357. const childrenIds = children.get(parent);
  8358. const everySelected = childrenIds.every(cid => selected.get(vue.toRaw(cid)) === 'on');
  8359. const noneSelected = childrenIds.every(cid => !selected.has(vue.toRaw(cid)) || selected.get(vue.toRaw(cid)) === 'off');
  8360. selected.set(parent, everySelected ? 'on' : noneSelected ? 'off' : 'indeterminate');
  8361. parent = vue.toRaw(parents.get(parent));
  8362. }
  8363. // If mandatory and planned deselect results in no selected
  8364. // items then we can't do it, so return original state
  8365. if (mandatory && !value) {
  8366. const on = Array.from(selected.entries()).reduce((arr, _ref7) => {
  8367. let [key, value] = _ref7;
  8368. if (value === 'on') arr.push(key);
  8369. return arr;
  8370. }, []);
  8371. if (on.length === 0) return original;
  8372. }
  8373. return selected;
  8374. },
  8375. in: (v, children, parents) => {
  8376. let map = new Map();
  8377. for (const id of v || []) {
  8378. map = strategy.select({
  8379. id,
  8380. value: true,
  8381. selected: new Map(map),
  8382. children,
  8383. parents
  8384. });
  8385. }
  8386. return map;
  8387. },
  8388. out: (v, children) => {
  8389. const arr = [];
  8390. for (const [key, value] of v.entries()) {
  8391. if (value === 'on' && !children.has(key)) arr.push(key);
  8392. }
  8393. return arr;
  8394. }
  8395. };
  8396. return strategy;
  8397. };
  8398. // Composables
  8399. // Types
  8400. const VNestedSymbol = Symbol.for('vuetify:nested');
  8401. const emptyNested = {
  8402. id: vue.shallowRef(),
  8403. root: {
  8404. register: () => null,
  8405. unregister: () => null,
  8406. parents: vue.ref(new Map()),
  8407. children: vue.ref(new Map()),
  8408. open: () => null,
  8409. openOnSelect: () => null,
  8410. activate: () => null,
  8411. select: () => null,
  8412. activatable: vue.ref(false),
  8413. selectable: vue.ref(false),
  8414. opened: vue.ref(new Set()),
  8415. activated: vue.ref(new Set()),
  8416. selected: vue.ref(new Map()),
  8417. selectedValues: vue.ref([]),
  8418. getPath: () => []
  8419. }
  8420. };
  8421. const makeNestedProps = propsFactory({
  8422. activatable: Boolean,
  8423. selectable: Boolean,
  8424. activeStrategy: [String, Function, Object],
  8425. selectStrategy: [String, Function, Object],
  8426. openStrategy: [String, Object],
  8427. opened: null,
  8428. activated: null,
  8429. selected: null,
  8430. mandatory: Boolean
  8431. }, 'nested');
  8432. const useNested = props => {
  8433. let isUnmounted = false;
  8434. const children = vue.ref(new Map());
  8435. const parents = vue.ref(new Map());
  8436. const opened = useProxiedModel(props, 'opened', props.opened, v => new Set(v), v => [...v.values()]);
  8437. const activeStrategy = vue.computed(() => {
  8438. if (typeof props.activeStrategy === 'object') return props.activeStrategy;
  8439. if (typeof props.activeStrategy === 'function') return props.activeStrategy(props.mandatory);
  8440. switch (props.activeStrategy) {
  8441. case 'leaf':
  8442. return leafActiveStrategy(props.mandatory);
  8443. case 'single-leaf':
  8444. return leafSingleActiveStrategy(props.mandatory);
  8445. case 'independent':
  8446. return independentActiveStrategy(props.mandatory);
  8447. case 'single-independent':
  8448. default:
  8449. return independentSingleActiveStrategy(props.mandatory);
  8450. }
  8451. });
  8452. const selectStrategy = vue.computed(() => {
  8453. if (typeof props.selectStrategy === 'object') return props.selectStrategy;
  8454. if (typeof props.selectStrategy === 'function') return props.selectStrategy(props.mandatory);
  8455. switch (props.selectStrategy) {
  8456. case 'single-leaf':
  8457. return leafSingleSelectStrategy(props.mandatory);
  8458. case 'leaf':
  8459. return leafSelectStrategy(props.mandatory);
  8460. case 'independent':
  8461. return independentSelectStrategy(props.mandatory);
  8462. case 'single-independent':
  8463. return independentSingleSelectStrategy(props.mandatory);
  8464. case 'classic':
  8465. default:
  8466. return classicSelectStrategy(props.mandatory);
  8467. }
  8468. });
  8469. const openStrategy = vue.computed(() => {
  8470. if (typeof props.openStrategy === 'object') return props.openStrategy;
  8471. switch (props.openStrategy) {
  8472. case 'list':
  8473. return listOpenStrategy;
  8474. case 'single':
  8475. return singleOpenStrategy;
  8476. case 'multiple':
  8477. default:
  8478. return multipleOpenStrategy;
  8479. }
  8480. });
  8481. const activated = useProxiedModel(props, 'activated', props.activated, v => activeStrategy.value.in(v, children.value, parents.value), v => activeStrategy.value.out(v, children.value, parents.value));
  8482. 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));
  8483. vue.onBeforeUnmount(() => {
  8484. isUnmounted = true;
  8485. });
  8486. function getPath(id) {
  8487. const path = [];
  8488. let parent = id;
  8489. while (parent != null) {
  8490. path.unshift(parent);
  8491. parent = parents.value.get(parent);
  8492. }
  8493. return path;
  8494. }
  8495. const vm = getCurrentInstance('nested');
  8496. const nodeIds = new Set();
  8497. const nested = {
  8498. id: vue.shallowRef(),
  8499. root: {
  8500. opened,
  8501. activatable: vue.toRef(props, 'activatable'),
  8502. selectable: vue.toRef(props, 'selectable'),
  8503. activated,
  8504. selected,
  8505. selectedValues: vue.computed(() => {
  8506. const arr = [];
  8507. for (const [key, value] of selected.value.entries()) {
  8508. if (value === 'on') arr.push(key);
  8509. }
  8510. return arr;
  8511. }),
  8512. register: (id, parentId, isGroup) => {
  8513. if (nodeIds.has(id)) {
  8514. const path = getPath(id).map(String).join(' -> ');
  8515. const newPath = getPath(parentId).concat(id).map(String).join(' -> ');
  8516. consoleError(`Multiple nodes with the same ID\n\t${path}\n\t${newPath}`);
  8517. return;
  8518. } else {
  8519. nodeIds.add(id);
  8520. }
  8521. parentId && id !== parentId && parents.value.set(id, parentId);
  8522. isGroup && children.value.set(id, []);
  8523. if (parentId != null) {
  8524. children.value.set(parentId, [...(children.value.get(parentId) || []), id]);
  8525. }
  8526. },
  8527. unregister: id => {
  8528. if (isUnmounted) return;
  8529. nodeIds.delete(id);
  8530. children.value.delete(id);
  8531. const parent = parents.value.get(id);
  8532. if (parent) {
  8533. const list = children.value.get(parent) ?? [];
  8534. children.value.set(parent, list.filter(child => child !== id));
  8535. }
  8536. parents.value.delete(id);
  8537. },
  8538. open: (id, value, event) => {
  8539. vm.emit('click:open', {
  8540. id,
  8541. value,
  8542. path: getPath(id),
  8543. event
  8544. });
  8545. const newOpened = openStrategy.value.open({
  8546. id,
  8547. value,
  8548. opened: new Set(opened.value),
  8549. children: children.value,
  8550. parents: parents.value,
  8551. event
  8552. });
  8553. newOpened && (opened.value = newOpened);
  8554. },
  8555. openOnSelect: (id, value, event) => {
  8556. const newOpened = openStrategy.value.select({
  8557. id,
  8558. value,
  8559. selected: new Map(selected.value),
  8560. opened: new Set(opened.value),
  8561. children: children.value,
  8562. parents: parents.value,
  8563. event
  8564. });
  8565. newOpened && (opened.value = newOpened);
  8566. },
  8567. select: (id, value, event) => {
  8568. vm.emit('click:select', {
  8569. id,
  8570. value,
  8571. path: getPath(id),
  8572. event
  8573. });
  8574. const newSelected = selectStrategy.value.select({
  8575. id,
  8576. value,
  8577. selected: new Map(selected.value),
  8578. children: children.value,
  8579. parents: parents.value,
  8580. event
  8581. });
  8582. newSelected && (selected.value = newSelected);
  8583. nested.root.openOnSelect(id, value, event);
  8584. },
  8585. activate: (id, value, event) => {
  8586. if (!props.activatable) {
  8587. return nested.root.select(id, true, event);
  8588. }
  8589. vm.emit('click:activate', {
  8590. id,
  8591. value,
  8592. path: getPath(id),
  8593. event
  8594. });
  8595. const newActivated = activeStrategy.value.activate({
  8596. id,
  8597. value,
  8598. activated: new Set(activated.value),
  8599. children: children.value,
  8600. parents: parents.value,
  8601. event
  8602. });
  8603. newActivated && (activated.value = newActivated);
  8604. },
  8605. children,
  8606. parents,
  8607. getPath
  8608. }
  8609. };
  8610. vue.provide(VNestedSymbol, nested);
  8611. return nested.root;
  8612. };
  8613. const useNestedItem = (id, isGroup) => {
  8614. const parent = vue.inject(VNestedSymbol, emptyNested);
  8615. const uidSymbol = Symbol(getUid());
  8616. const computedId = vue.computed(() => id.value !== undefined ? id.value : uidSymbol);
  8617. const item = {
  8618. ...parent,
  8619. id: computedId,
  8620. open: (open, e) => parent.root.open(computedId.value, open, e),
  8621. openOnSelect: (open, e) => parent.root.openOnSelect(computedId.value, open, e),
  8622. isOpen: vue.computed(() => parent.root.opened.value.has(computedId.value)),
  8623. parent: vue.computed(() => parent.root.parents.value.get(computedId.value)),
  8624. activate: (activated, e) => parent.root.activate(computedId.value, activated, e),
  8625. isActivated: vue.computed(() => parent.root.activated.value.has(vue.toRaw(computedId.value))),
  8626. select: (selected, e) => parent.root.select(computedId.value, selected, e),
  8627. isSelected: vue.computed(() => parent.root.selected.value.get(vue.toRaw(computedId.value)) === 'on'),
  8628. isIndeterminate: vue.computed(() => parent.root.selected.value.get(computedId.value) === 'indeterminate'),
  8629. isLeaf: vue.computed(() => !parent.root.children.value.get(computedId.value)),
  8630. isGroupActivator: parent.isGroupActivator
  8631. };
  8632. vue.onBeforeMount(() => {
  8633. !parent.isGroupActivator && parent.root.register(computedId.value, parent.id.value, isGroup);
  8634. });
  8635. vue.onBeforeUnmount(() => {
  8636. !parent.isGroupActivator && parent.root.unregister(computedId.value);
  8637. });
  8638. isGroup && vue.provide(VNestedSymbol, item);
  8639. return item;
  8640. };
  8641. const useNestedGroupActivator = () => {
  8642. const parent = vue.inject(VNestedSymbol, emptyNested);
  8643. vue.provide(VNestedSymbol, {
  8644. ...parent,
  8645. isGroupActivator: true
  8646. });
  8647. };
  8648. const VListGroupActivator = defineComponent({
  8649. name: 'VListGroupActivator',
  8650. setup(_, _ref) {
  8651. let {
  8652. slots
  8653. } = _ref;
  8654. useNestedGroupActivator();
  8655. return () => slots.default?.();
  8656. }
  8657. });
  8658. const makeVListGroupProps = propsFactory({
  8659. /* @deprecated */
  8660. activeColor: String,
  8661. baseColor: String,
  8662. color: String,
  8663. collapseIcon: {
  8664. type: IconValue,
  8665. default: '$collapse'
  8666. },
  8667. expandIcon: {
  8668. type: IconValue,
  8669. default: '$expand'
  8670. },
  8671. prependIcon: IconValue,
  8672. appendIcon: IconValue,
  8673. fluid: Boolean,
  8674. subgroup: Boolean,
  8675. title: String,
  8676. value: null,
  8677. ...makeComponentProps(),
  8678. ...makeTagProps()
  8679. }, 'VListGroup');
  8680. const VListGroup = genericComponent()({
  8681. name: 'VListGroup',
  8682. props: makeVListGroupProps(),
  8683. setup(props, _ref2) {
  8684. let {
  8685. slots
  8686. } = _ref2;
  8687. const {
  8688. isOpen,
  8689. open,
  8690. id: _id
  8691. } = useNestedItem(vue.toRef(props, 'value'), true);
  8692. const id = vue.computed(() => `v-list-group--id-${String(_id.value)}`);
  8693. const list = useList();
  8694. const {
  8695. isBooted
  8696. } = useSsrBoot();
  8697. function onClick(e) {
  8698. e.stopPropagation();
  8699. open(!isOpen.value, e);
  8700. }
  8701. const activatorProps = vue.computed(() => ({
  8702. onClick,
  8703. class: 'v-list-group__header',
  8704. id: id.value
  8705. }));
  8706. const toggleIcon = vue.computed(() => isOpen.value ? props.collapseIcon : props.expandIcon);
  8707. const activatorDefaults = vue.computed(() => ({
  8708. VListItem: {
  8709. active: isOpen.value,
  8710. activeColor: props.activeColor,
  8711. baseColor: props.baseColor,
  8712. color: props.color,
  8713. prependIcon: props.prependIcon || props.subgroup && toggleIcon.value,
  8714. appendIcon: props.appendIcon || !props.subgroup && toggleIcon.value,
  8715. title: props.title,
  8716. value: props.value
  8717. }
  8718. }));
  8719. useRender(() => vue.createVNode(props.tag, {
  8720. "class": ['v-list-group', {
  8721. 'v-list-group--prepend': list?.hasPrepend.value,
  8722. 'v-list-group--fluid': props.fluid,
  8723. 'v-list-group--subgroup': props.subgroup,
  8724. 'v-list-group--open': isOpen.value
  8725. }, props.class],
  8726. "style": props.style
  8727. }, {
  8728. default: () => [slots.activator && vue.createVNode(VDefaultsProvider, {
  8729. "defaults": activatorDefaults.value
  8730. }, {
  8731. default: () => [vue.createVNode(VListGroupActivator, null, {
  8732. default: () => [slots.activator({
  8733. props: activatorProps.value,
  8734. isOpen: isOpen.value
  8735. })]
  8736. })]
  8737. }), vue.createVNode(MaybeTransition, {
  8738. "transition": {
  8739. component: VExpandTransition
  8740. },
  8741. "disabled": !isBooted.value
  8742. }, {
  8743. default: () => [vue.withDirectives(vue.createVNode("div", {
  8744. "class": "v-list-group__items",
  8745. "role": "group",
  8746. "aria-labelledby": id.value
  8747. }, [slots.default?.()]), [[vue.vShow, isOpen.value]])]
  8748. })]
  8749. }));
  8750. return {
  8751. isOpen
  8752. };
  8753. }
  8754. });
  8755. const makeVListItemSubtitleProps = propsFactory({
  8756. opacity: [Number, String],
  8757. ...makeComponentProps(),
  8758. ...makeTagProps()
  8759. }, 'VListItemSubtitle');
  8760. const VListItemSubtitle = genericComponent()({
  8761. name: 'VListItemSubtitle',
  8762. props: makeVListItemSubtitleProps(),
  8763. setup(props, _ref) {
  8764. let {
  8765. slots
  8766. } = _ref;
  8767. useRender(() => vue.createVNode(props.tag, {
  8768. "class": ['v-list-item-subtitle', props.class],
  8769. "style": [{
  8770. '--v-list-item-subtitle-opacity': props.opacity
  8771. }, props.style]
  8772. }, slots));
  8773. return {};
  8774. }
  8775. });
  8776. // Utilities
  8777. const VListItemTitle = createSimpleFunctional('v-list-item-title');
  8778. // Types
  8779. const makeVListItemProps = propsFactory({
  8780. active: {
  8781. type: Boolean,
  8782. default: undefined
  8783. },
  8784. activeClass: String,
  8785. /* @deprecated */
  8786. activeColor: String,
  8787. appendAvatar: String,
  8788. appendIcon: IconValue,
  8789. baseColor: String,
  8790. disabled: Boolean,
  8791. lines: [Boolean, String],
  8792. link: {
  8793. type: Boolean,
  8794. default: undefined
  8795. },
  8796. nav: Boolean,
  8797. prependAvatar: String,
  8798. prependIcon: IconValue,
  8799. ripple: {
  8800. type: [Boolean, Object],
  8801. default: true
  8802. },
  8803. slim: Boolean,
  8804. subtitle: [String, Number],
  8805. title: [String, Number],
  8806. value: null,
  8807. onClick: EventProp(),
  8808. onClickOnce: EventProp(),
  8809. ...makeBorderProps(),
  8810. ...makeComponentProps(),
  8811. ...makeDensityProps(),
  8812. ...makeDimensionProps(),
  8813. ...makeElevationProps(),
  8814. ...makeRoundedProps(),
  8815. ...makeRouterProps(),
  8816. ...makeTagProps(),
  8817. ...makeThemeProps(),
  8818. ...makeVariantProps({
  8819. variant: 'text'
  8820. })
  8821. }, 'VListItem');
  8822. const VListItem = genericComponent()({
  8823. name: 'VListItem',
  8824. directives: {
  8825. Ripple
  8826. },
  8827. props: makeVListItemProps(),
  8828. emits: {
  8829. click: e => true
  8830. },
  8831. setup(props, _ref) {
  8832. let {
  8833. attrs,
  8834. slots,
  8835. emit
  8836. } = _ref;
  8837. const link = useLink(props, attrs);
  8838. const id = vue.computed(() => props.value === undefined ? link.href.value : props.value);
  8839. const {
  8840. activate,
  8841. isActivated,
  8842. select,
  8843. isOpen,
  8844. isSelected,
  8845. isIndeterminate,
  8846. isGroupActivator,
  8847. root,
  8848. parent,
  8849. openOnSelect,
  8850. id: uid
  8851. } = useNestedItem(id, false);
  8852. const list = useList();
  8853. const isActive = vue.computed(() => props.active !== false && (props.active || link.isActive?.value || (root.activatable.value ? isActivated.value : isSelected.value)));
  8854. const isLink = vue.computed(() => props.link !== false && link.isLink.value);
  8855. const isSelectable = vue.computed(() => !!list && (root.selectable.value || root.activatable.value || props.value != null));
  8856. const isClickable = vue.computed(() => !props.disabled && props.link !== false && (props.link || link.isClickable.value || isSelectable.value));
  8857. const roundedProps = vue.computed(() => props.rounded || props.nav);
  8858. const color = vue.computed(() => props.color ?? props.activeColor);
  8859. const variantProps = vue.computed(() => ({
  8860. color: isActive.value ? color.value ?? props.baseColor : props.baseColor,
  8861. variant: props.variant
  8862. }));
  8863. // useNestedItem doesn't call register until beforeMount,
  8864. // so this can't be an immediate watcher as we don't know parent yet
  8865. vue.watch(() => link.isActive?.value, val => {
  8866. if (!val) return;
  8867. handleActiveLink();
  8868. });
  8869. vue.onBeforeMount(() => {
  8870. if (link.isActive?.value) handleActiveLink();
  8871. });
  8872. function handleActiveLink() {
  8873. if (parent.value != null) {
  8874. root.open(parent.value, true);
  8875. }
  8876. openOnSelect(true);
  8877. }
  8878. const {
  8879. themeClasses
  8880. } = provideTheme(props);
  8881. const {
  8882. borderClasses
  8883. } = useBorder(props);
  8884. const {
  8885. colorClasses,
  8886. colorStyles,
  8887. variantClasses
  8888. } = useVariant(variantProps);
  8889. const {
  8890. densityClasses
  8891. } = useDensity(props);
  8892. const {
  8893. dimensionStyles
  8894. } = useDimension(props);
  8895. const {
  8896. elevationClasses
  8897. } = useElevation(props);
  8898. const {
  8899. roundedClasses
  8900. } = useRounded(roundedProps);
  8901. const lineClasses = vue.computed(() => props.lines ? `v-list-item--${props.lines}-line` : undefined);
  8902. const slotProps = vue.computed(() => ({
  8903. isActive: isActive.value,
  8904. select,
  8905. isOpen: isOpen.value,
  8906. isSelected: isSelected.value,
  8907. isIndeterminate: isIndeterminate.value
  8908. }));
  8909. function onClick(e) {
  8910. emit('click', e);
  8911. if (!isClickable.value) return;
  8912. link.navigate?.(e);
  8913. if (isGroupActivator) return;
  8914. if (root.activatable.value) {
  8915. activate(!isActivated.value, e);
  8916. } else if (root.selectable.value) {
  8917. select(!isSelected.value, e);
  8918. } else if (props.value != null) {
  8919. select(!isSelected.value, e);
  8920. }
  8921. }
  8922. function onKeyDown(e) {
  8923. if (e.key === 'Enter' || e.key === ' ') {
  8924. e.preventDefault();
  8925. e.target.dispatchEvent(new MouseEvent('click', e));
  8926. }
  8927. }
  8928. useRender(() => {
  8929. const Tag = isLink.value ? 'a' : props.tag;
  8930. const hasTitle = slots.title || props.title != null;
  8931. const hasSubtitle = slots.subtitle || props.subtitle != null;
  8932. const hasAppendMedia = !!(props.appendAvatar || props.appendIcon);
  8933. const hasAppend = !!(hasAppendMedia || slots.append);
  8934. const hasPrependMedia = !!(props.prependAvatar || props.prependIcon);
  8935. const hasPrepend = !!(hasPrependMedia || slots.prepend);
  8936. list?.updateHasPrepend(hasPrepend);
  8937. if (props.activeColor) {
  8938. deprecate('active-color', ['color', 'base-color']);
  8939. }
  8940. return vue.withDirectives(vue.createVNode(Tag, vue.mergeProps({
  8941. "class": ['v-list-item', {
  8942. 'v-list-item--active': isActive.value,
  8943. 'v-list-item--disabled': props.disabled,
  8944. 'v-list-item--link': isClickable.value,
  8945. 'v-list-item--nav': props.nav,
  8946. 'v-list-item--prepend': !hasPrepend && list?.hasPrepend.value,
  8947. 'v-list-item--slim': props.slim,
  8948. [`${props.activeClass}`]: props.activeClass && isActive.value
  8949. }, themeClasses.value, borderClasses.value, colorClasses.value, densityClasses.value, elevationClasses.value, lineClasses.value, roundedClasses.value, variantClasses.value, props.class],
  8950. "style": [colorStyles.value, dimensionStyles.value, props.style],
  8951. "tabindex": isClickable.value ? list ? -2 : 0 : undefined,
  8952. "aria-selected": isSelectable.value ? root.activatable.value ? isActivated.value : root.selectable.value ? isSelected.value : isActive.value : undefined,
  8953. "onClick": onClick,
  8954. "onKeydown": isClickable.value && !isLink.value && onKeyDown
  8955. }, link.linkProps), {
  8956. default: () => [genOverlays(isClickable.value || isActive.value, 'v-list-item'), hasPrepend && vue.createVNode("div", {
  8957. "key": "prepend",
  8958. "class": "v-list-item__prepend"
  8959. }, [!slots.prepend ? vue.createVNode(vue.Fragment, null, [props.prependAvatar && vue.createVNode(VAvatar, {
  8960. "key": "prepend-avatar",
  8961. "density": props.density,
  8962. "image": props.prependAvatar
  8963. }, null), props.prependIcon && vue.createVNode(VIcon, {
  8964. "key": "prepend-icon",
  8965. "density": props.density,
  8966. "icon": props.prependIcon
  8967. }, null)]) : vue.createVNode(VDefaultsProvider, {
  8968. "key": "prepend-defaults",
  8969. "disabled": !hasPrependMedia,
  8970. "defaults": {
  8971. VAvatar: {
  8972. density: props.density,
  8973. image: props.prependAvatar
  8974. },
  8975. VIcon: {
  8976. density: props.density,
  8977. icon: props.prependIcon
  8978. },
  8979. VListItemAction: {
  8980. start: true
  8981. }
  8982. }
  8983. }, {
  8984. default: () => [slots.prepend?.(slotProps.value)]
  8985. }), vue.createVNode("div", {
  8986. "class": "v-list-item__spacer"
  8987. }, null)]), vue.createVNode("div", {
  8988. "class": "v-list-item__content",
  8989. "data-no-activator": ""
  8990. }, [hasTitle && vue.createVNode(VListItemTitle, {
  8991. "key": "title"
  8992. }, {
  8993. default: () => [slots.title?.({
  8994. title: props.title
  8995. }) ?? props.title]
  8996. }), hasSubtitle && vue.createVNode(VListItemSubtitle, {
  8997. "key": "subtitle"
  8998. }, {
  8999. default: () => [slots.subtitle?.({
  9000. subtitle: props.subtitle
  9001. }) ?? props.subtitle]
  9002. }), slots.default?.(slotProps.value)]), hasAppend && vue.createVNode("div", {
  9003. "key": "append",
  9004. "class": "v-list-item__append"
  9005. }, [!slots.append ? vue.createVNode(vue.Fragment, null, [props.appendIcon && vue.createVNode(VIcon, {
  9006. "key": "append-icon",
  9007. "density": props.density,
  9008. "icon": props.appendIcon
  9009. }, null), props.appendAvatar && vue.createVNode(VAvatar, {
  9010. "key": "append-avatar",
  9011. "density": props.density,
  9012. "image": props.appendAvatar
  9013. }, null)]) : vue.createVNode(VDefaultsProvider, {
  9014. "key": "append-defaults",
  9015. "disabled": !hasAppendMedia,
  9016. "defaults": {
  9017. VAvatar: {
  9018. density: props.density,
  9019. image: props.appendAvatar
  9020. },
  9021. VIcon: {
  9022. density: props.density,
  9023. icon: props.appendIcon
  9024. },
  9025. VListItemAction: {
  9026. end: true
  9027. }
  9028. }
  9029. }, {
  9030. default: () => [slots.append?.(slotProps.value)]
  9031. }), vue.createVNode("div", {
  9032. "class": "v-list-item__spacer"
  9033. }, null)])]
  9034. }), [[vue.resolveDirective("ripple"), isClickable.value && props.ripple]]);
  9035. });
  9036. return {
  9037. activate,
  9038. isActivated,
  9039. isGroupActivator,
  9040. isSelected,
  9041. list,
  9042. select,
  9043. root,
  9044. id: uid
  9045. };
  9046. }
  9047. });
  9048. const makeVListSubheaderProps = propsFactory({
  9049. color: String,
  9050. inset: Boolean,
  9051. sticky: Boolean,
  9052. title: String,
  9053. ...makeComponentProps(),
  9054. ...makeTagProps()
  9055. }, 'VListSubheader');
  9056. const VListSubheader = genericComponent()({
  9057. name: 'VListSubheader',
  9058. props: makeVListSubheaderProps(),
  9059. setup(props, _ref) {
  9060. let {
  9061. slots
  9062. } = _ref;
  9063. const {
  9064. textColorClasses,
  9065. textColorStyles
  9066. } = useTextColor(vue.toRef(props, 'color'));
  9067. useRender(() => {
  9068. const hasText = !!(slots.default || props.title);
  9069. return vue.createVNode(props.tag, {
  9070. "class": ['v-list-subheader', {
  9071. 'v-list-subheader--inset': props.inset,
  9072. 'v-list-subheader--sticky': props.sticky
  9073. }, textColorClasses.value, props.class],
  9074. "style": [{
  9075. textColorStyles
  9076. }, props.style]
  9077. }, {
  9078. default: () => [hasText && vue.createVNode("div", {
  9079. "class": "v-list-subheader__text"
  9080. }, [slots.default?.() ?? props.title])]
  9081. });
  9082. });
  9083. return {};
  9084. }
  9085. });
  9086. const makeVDividerProps = propsFactory({
  9087. color: String,
  9088. inset: Boolean,
  9089. length: [Number, String],
  9090. opacity: [Number, String],
  9091. thickness: [Number, String],
  9092. vertical: Boolean,
  9093. ...makeComponentProps(),
  9094. ...makeThemeProps()
  9095. }, 'VDivider');
  9096. const VDivider = genericComponent()({
  9097. name: 'VDivider',
  9098. props: makeVDividerProps(),
  9099. setup(props, _ref) {
  9100. let {
  9101. attrs,
  9102. slots
  9103. } = _ref;
  9104. const {
  9105. themeClasses
  9106. } = provideTheme(props);
  9107. const {
  9108. textColorClasses,
  9109. textColorStyles
  9110. } = useTextColor(vue.toRef(props, 'color'));
  9111. const dividerStyles = vue.computed(() => {
  9112. const styles = {};
  9113. if (props.length) {
  9114. styles[props.vertical ? 'height' : 'width'] = convertToUnit(props.length);
  9115. }
  9116. if (props.thickness) {
  9117. styles[props.vertical ? 'borderRightWidth' : 'borderTopWidth'] = convertToUnit(props.thickness);
  9118. }
  9119. return styles;
  9120. });
  9121. useRender(() => {
  9122. const divider = vue.createVNode("hr", {
  9123. "class": [{
  9124. 'v-divider': true,
  9125. 'v-divider--inset': props.inset,
  9126. 'v-divider--vertical': props.vertical
  9127. }, themeClasses.value, textColorClasses.value, props.class],
  9128. "style": [dividerStyles.value, textColorStyles.value, {
  9129. '--v-border-opacity': props.opacity
  9130. }, props.style],
  9131. "aria-orientation": !attrs.role || attrs.role === 'separator' ? props.vertical ? 'vertical' : 'horizontal' : undefined,
  9132. "role": `${attrs.role || 'separator'}`
  9133. }, null);
  9134. if (!slots.default) return divider;
  9135. return vue.createVNode("div", {
  9136. "class": ['v-divider__wrapper', {
  9137. 'v-divider__wrapper--vertical': props.vertical,
  9138. 'v-divider__wrapper--inset': props.inset
  9139. }]
  9140. }, [divider, vue.createVNode("div", {
  9141. "class": "v-divider__content"
  9142. }, [slots.default()]), divider]);
  9143. });
  9144. return {};
  9145. }
  9146. });
  9147. // Types
  9148. const makeVListChildrenProps = propsFactory({
  9149. items: Array,
  9150. returnObject: Boolean
  9151. }, 'VListChildren');
  9152. const VListChildren = genericComponent()({
  9153. name: 'VListChildren',
  9154. props: makeVListChildrenProps(),
  9155. setup(props, _ref) {
  9156. let {
  9157. slots
  9158. } = _ref;
  9159. createList();
  9160. return () => slots.default?.() ?? props.items?.map(_ref2 => {
  9161. let {
  9162. children,
  9163. props: itemProps,
  9164. type,
  9165. raw: item
  9166. } = _ref2;
  9167. if (type === 'divider') {
  9168. return slots.divider?.({
  9169. props: itemProps
  9170. }) ?? vue.createVNode(VDivider, itemProps, null);
  9171. }
  9172. if (type === 'subheader') {
  9173. return slots.subheader?.({
  9174. props: itemProps
  9175. }) ?? vue.createVNode(VListSubheader, itemProps, null);
  9176. }
  9177. const slotsWithItem = {
  9178. subtitle: slots.subtitle ? slotProps => slots.subtitle?.({
  9179. ...slotProps,
  9180. item
  9181. }) : undefined,
  9182. prepend: slots.prepend ? slotProps => slots.prepend?.({
  9183. ...slotProps,
  9184. item
  9185. }) : undefined,
  9186. append: slots.append ? slotProps => slots.append?.({
  9187. ...slotProps,
  9188. item
  9189. }) : undefined,
  9190. title: slots.title ? slotProps => slots.title?.({
  9191. ...slotProps,
  9192. item
  9193. }) : undefined
  9194. };
  9195. const listGroupProps = VListGroup.filterProps(itemProps);
  9196. return children ? vue.createVNode(VListGroup, vue.mergeProps({
  9197. "value": itemProps?.value
  9198. }, listGroupProps), {
  9199. activator: _ref3 => {
  9200. let {
  9201. props: activatorProps
  9202. } = _ref3;
  9203. const listItemProps = {
  9204. ...itemProps,
  9205. ...activatorProps,
  9206. value: props.returnObject ? item : itemProps.value
  9207. };
  9208. return slots.header ? slots.header({
  9209. props: listItemProps
  9210. }) : vue.createVNode(VListItem, listItemProps, slotsWithItem);
  9211. },
  9212. default: () => vue.createVNode(VListChildren, {
  9213. "items": children,
  9214. "returnObject": props.returnObject
  9215. }, slots)
  9216. }) : slots.item ? slots.item({
  9217. props: itemProps
  9218. }) : vue.createVNode(VListItem, vue.mergeProps(itemProps, {
  9219. "value": props.returnObject ? item : itemProps.value
  9220. }), slotsWithItem);
  9221. });
  9222. }
  9223. });
  9224. // Utilities
  9225. // Types
  9226. // Composables
  9227. const makeItemsProps = propsFactory({
  9228. items: {
  9229. type: Array,
  9230. default: () => []
  9231. },
  9232. itemTitle: {
  9233. type: [String, Array, Function],
  9234. default: 'title'
  9235. },
  9236. itemValue: {
  9237. type: [String, Array, Function],
  9238. default: 'value'
  9239. },
  9240. itemChildren: {
  9241. type: [Boolean, String, Array, Function],
  9242. default: 'children'
  9243. },
  9244. itemProps: {
  9245. type: [Boolean, String, Array, Function],
  9246. default: 'props'
  9247. },
  9248. returnObject: Boolean,
  9249. valueComparator: {
  9250. type: Function,
  9251. default: deepEqual
  9252. }
  9253. }, 'list-items');
  9254. function transformItem$3(props, item) {
  9255. const title = getPropertyFromItem(item, props.itemTitle, item);
  9256. const value = getPropertyFromItem(item, props.itemValue, title);
  9257. const children = getPropertyFromItem(item, props.itemChildren);
  9258. const itemProps = props.itemProps === true ? typeof item === 'object' && item != null && !Array.isArray(item) ? 'children' in item ? omit(item, ['children']) : item : undefined : getPropertyFromItem(item, props.itemProps);
  9259. const _props = {
  9260. title,
  9261. value,
  9262. ...itemProps
  9263. };
  9264. return {
  9265. title: String(_props.title ?? ''),
  9266. value: _props.value,
  9267. props: _props,
  9268. children: Array.isArray(children) ? transformItems$3(props, children) : undefined,
  9269. raw: item
  9270. };
  9271. }
  9272. function transformItems$3(props, items) {
  9273. const array = [];
  9274. for (const item of items) {
  9275. array.push(transformItem$3(props, item));
  9276. }
  9277. return array;
  9278. }
  9279. function useItems(props) {
  9280. const items = vue.computed(() => transformItems$3(props, props.items));
  9281. const hasNullItem = vue.computed(() => items.value.some(item => item.value === null));
  9282. function transformIn(value) {
  9283. if (!hasNullItem.value) {
  9284. // When the model value is null, return an InternalItem
  9285. // based on null only if null is one of the items
  9286. value = value.filter(v => v !== null);
  9287. }
  9288. return value.map(v => {
  9289. if (props.returnObject && typeof v === 'string') {
  9290. // String model value means value is a custom input value from combobox
  9291. // Don't look up existing items if the model value is a string
  9292. return transformItem$3(props, v);
  9293. }
  9294. return items.value.find(item => props.valueComparator(v, item.value)) || transformItem$3(props, v);
  9295. });
  9296. }
  9297. function transformOut(value) {
  9298. return props.returnObject ? value.map(_ref => {
  9299. let {
  9300. raw
  9301. } = _ref;
  9302. return raw;
  9303. }) : value.map(_ref2 => {
  9304. let {
  9305. value
  9306. } = _ref2;
  9307. return value;
  9308. });
  9309. }
  9310. return {
  9311. items,
  9312. transformIn,
  9313. transformOut
  9314. };
  9315. }
  9316. // Types
  9317. function isPrimitive(value) {
  9318. return typeof value === 'string' || typeof value === 'number' || typeof value === 'boolean';
  9319. }
  9320. function transformItem$2(props, item) {
  9321. const type = getPropertyFromItem(item, props.itemType, 'item');
  9322. const title = isPrimitive(item) ? item : getPropertyFromItem(item, props.itemTitle);
  9323. const value = getPropertyFromItem(item, props.itemValue, undefined);
  9324. const children = getPropertyFromItem(item, props.itemChildren);
  9325. const itemProps = props.itemProps === true ? omit(item, ['children']) : getPropertyFromItem(item, props.itemProps);
  9326. const _props = {
  9327. title,
  9328. value,
  9329. ...itemProps
  9330. };
  9331. return {
  9332. type,
  9333. title: _props.title,
  9334. value: _props.value,
  9335. props: _props,
  9336. children: type === 'item' && children ? transformItems$2(props, children) : undefined,
  9337. raw: item
  9338. };
  9339. }
  9340. function transformItems$2(props, items) {
  9341. const array = [];
  9342. for (const item of items) {
  9343. array.push(transformItem$2(props, item));
  9344. }
  9345. return array;
  9346. }
  9347. function useListItems(props) {
  9348. const items = vue.computed(() => transformItems$2(props, props.items));
  9349. return {
  9350. items
  9351. };
  9352. }
  9353. const makeVListProps = propsFactory({
  9354. baseColor: String,
  9355. /* @deprecated */
  9356. activeColor: String,
  9357. activeClass: String,
  9358. bgColor: String,
  9359. disabled: Boolean,
  9360. expandIcon: IconValue,
  9361. collapseIcon: IconValue,
  9362. lines: {
  9363. type: [Boolean, String],
  9364. default: 'one'
  9365. },
  9366. slim: Boolean,
  9367. nav: Boolean,
  9368. 'onClick:open': EventProp(),
  9369. 'onClick:select': EventProp(),
  9370. 'onUpdate:opened': EventProp(),
  9371. ...makeNestedProps({
  9372. selectStrategy: 'single-leaf',
  9373. openStrategy: 'list'
  9374. }),
  9375. ...makeBorderProps(),
  9376. ...makeComponentProps(),
  9377. ...makeDensityProps(),
  9378. ...makeDimensionProps(),
  9379. ...makeElevationProps(),
  9380. itemType: {
  9381. type: String,
  9382. default: 'type'
  9383. },
  9384. ...makeItemsProps(),
  9385. ...makeRoundedProps(),
  9386. ...makeTagProps(),
  9387. ...makeThemeProps(),
  9388. ...makeVariantProps({
  9389. variant: 'text'
  9390. })
  9391. }, 'VList');
  9392. const VList = genericComponent()({
  9393. name: 'VList',
  9394. props: makeVListProps(),
  9395. emits: {
  9396. 'update:selected': value => true,
  9397. 'update:activated': value => true,
  9398. 'update:opened': value => true,
  9399. 'click:open': value => true,
  9400. 'click:activate': value => true,
  9401. 'click:select': value => true
  9402. },
  9403. setup(props, _ref) {
  9404. let {
  9405. slots
  9406. } = _ref;
  9407. const {
  9408. items
  9409. } = useListItems(props);
  9410. const {
  9411. themeClasses
  9412. } = provideTheme(props);
  9413. const {
  9414. backgroundColorClasses,
  9415. backgroundColorStyles
  9416. } = useBackgroundColor(vue.toRef(props, 'bgColor'));
  9417. const {
  9418. borderClasses
  9419. } = useBorder(props);
  9420. const {
  9421. densityClasses
  9422. } = useDensity(props);
  9423. const {
  9424. dimensionStyles
  9425. } = useDimension(props);
  9426. const {
  9427. elevationClasses
  9428. } = useElevation(props);
  9429. const {
  9430. roundedClasses
  9431. } = useRounded(props);
  9432. const {
  9433. children,
  9434. open,
  9435. parents,
  9436. select,
  9437. getPath
  9438. } = useNested(props);
  9439. const lineClasses = vue.computed(() => props.lines ? `v-list--${props.lines}-line` : undefined);
  9440. const activeColor = vue.toRef(props, 'activeColor');
  9441. const baseColor = vue.toRef(props, 'baseColor');
  9442. const color = vue.toRef(props, 'color');
  9443. createList();
  9444. provideDefaults({
  9445. VListGroup: {
  9446. activeColor,
  9447. baseColor,
  9448. color,
  9449. expandIcon: vue.toRef(props, 'expandIcon'),
  9450. collapseIcon: vue.toRef(props, 'collapseIcon')
  9451. },
  9452. VListItem: {
  9453. activeClass: vue.toRef(props, 'activeClass'),
  9454. activeColor,
  9455. baseColor,
  9456. color,
  9457. density: vue.toRef(props, 'density'),
  9458. disabled: vue.toRef(props, 'disabled'),
  9459. lines: vue.toRef(props, 'lines'),
  9460. nav: vue.toRef(props, 'nav'),
  9461. slim: vue.toRef(props, 'slim'),
  9462. variant: vue.toRef(props, 'variant')
  9463. }
  9464. });
  9465. const isFocused = vue.shallowRef(false);
  9466. const contentRef = vue.ref();
  9467. function onFocusin(e) {
  9468. isFocused.value = true;
  9469. }
  9470. function onFocusout(e) {
  9471. isFocused.value = false;
  9472. }
  9473. function onFocus(e) {
  9474. if (!isFocused.value && !(e.relatedTarget && contentRef.value?.contains(e.relatedTarget))) focus();
  9475. }
  9476. function onKeydown(e) {
  9477. const target = e.target;
  9478. if (!contentRef.value || ['INPUT', 'TEXTAREA'].includes(target.tagName)) return;
  9479. if (e.key === 'ArrowDown') {
  9480. focus('next');
  9481. } else if (e.key === 'ArrowUp') {
  9482. focus('prev');
  9483. } else if (e.key === 'Home') {
  9484. focus('first');
  9485. } else if (e.key === 'End') {
  9486. focus('last');
  9487. } else {
  9488. return;
  9489. }
  9490. e.preventDefault();
  9491. }
  9492. function onMousedown(e) {
  9493. isFocused.value = true;
  9494. }
  9495. function focus(location) {
  9496. if (contentRef.value) {
  9497. return focusChild(contentRef.value, location);
  9498. }
  9499. }
  9500. useRender(() => {
  9501. return vue.createVNode(props.tag, {
  9502. "ref": contentRef,
  9503. "class": ['v-list', {
  9504. 'v-list--disabled': props.disabled,
  9505. 'v-list--nav': props.nav,
  9506. 'v-list--slim': props.slim
  9507. }, themeClasses.value, backgroundColorClasses.value, borderClasses.value, densityClasses.value, elevationClasses.value, lineClasses.value, roundedClasses.value, props.class],
  9508. "style": [backgroundColorStyles.value, dimensionStyles.value, props.style],
  9509. "tabindex": props.disabled || isFocused.value ? -1 : 0,
  9510. "role": "listbox",
  9511. "aria-activedescendant": undefined,
  9512. "onFocusin": onFocusin,
  9513. "onFocusout": onFocusout,
  9514. "onFocus": onFocus,
  9515. "onKeydown": onKeydown,
  9516. "onMousedown": onMousedown
  9517. }, {
  9518. default: () => [vue.createVNode(VListChildren, {
  9519. "items": items.value,
  9520. "returnObject": props.returnObject
  9521. }, slots)]
  9522. });
  9523. });
  9524. return {
  9525. open,
  9526. select,
  9527. focus,
  9528. children,
  9529. parents,
  9530. getPath
  9531. };
  9532. }
  9533. });
  9534. // Utilities
  9535. const VListImg = createSimpleFunctional('v-list-img');
  9536. const makeVListItemActionProps = propsFactory({
  9537. start: Boolean,
  9538. end: Boolean,
  9539. ...makeComponentProps(),
  9540. ...makeTagProps()
  9541. }, 'VListItemAction');
  9542. const VListItemAction = genericComponent()({
  9543. name: 'VListItemAction',
  9544. props: makeVListItemActionProps(),
  9545. setup(props, _ref) {
  9546. let {
  9547. slots
  9548. } = _ref;
  9549. useRender(() => vue.createVNode(props.tag, {
  9550. "class": ['v-list-item-action', {
  9551. 'v-list-item-action--start': props.start,
  9552. 'v-list-item-action--end': props.end
  9553. }, props.class],
  9554. "style": props.style
  9555. }, slots));
  9556. return {};
  9557. }
  9558. });
  9559. const makeVListItemMediaProps = propsFactory({
  9560. start: Boolean,
  9561. end: Boolean,
  9562. ...makeComponentProps(),
  9563. ...makeTagProps()
  9564. }, 'VListItemMedia');
  9565. const VListItemMedia = genericComponent()({
  9566. name: 'VListItemMedia',
  9567. props: makeVListItemMediaProps(),
  9568. setup(props, _ref) {
  9569. let {
  9570. slots
  9571. } = _ref;
  9572. useRender(() => {
  9573. return vue.createVNode(props.tag, {
  9574. "class": ['v-list-item-media', {
  9575. 'v-list-item-media--start': props.start,
  9576. 'v-list-item-media--end': props.end
  9577. }, props.class],
  9578. "style": props.style
  9579. }, slots);
  9580. });
  9581. return {};
  9582. }
  9583. });
  9584. // Types
  9585. /** Convert a point in local space to viewport space */
  9586. function elementToViewport(point, offset) {
  9587. return {
  9588. x: point.x + offset.x,
  9589. y: point.y + offset.y
  9590. };
  9591. }
  9592. /** Get the difference between two points */
  9593. function getOffset$1(a, b) {
  9594. return {
  9595. x: a.x - b.x,
  9596. y: a.y - b.y
  9597. };
  9598. }
  9599. /** Convert an anchor object to a point in local space */
  9600. function anchorToPoint(anchor, box) {
  9601. if (anchor.side === 'top' || anchor.side === 'bottom') {
  9602. const {
  9603. side,
  9604. align
  9605. } = anchor;
  9606. const x = align === 'left' ? 0 : align === 'center' ? box.width / 2 : align === 'right' ? box.width : align;
  9607. const y = side === 'top' ? 0 : side === 'bottom' ? box.height : side;
  9608. return elementToViewport({
  9609. x,
  9610. y
  9611. }, box);
  9612. } else if (anchor.side === 'left' || anchor.side === 'right') {
  9613. const {
  9614. side,
  9615. align
  9616. } = anchor;
  9617. const x = side === 'left' ? 0 : side === 'right' ? box.width : side;
  9618. const y = align === 'top' ? 0 : align === 'center' ? box.height / 2 : align === 'bottom' ? box.height : align;
  9619. return elementToViewport({
  9620. x,
  9621. y
  9622. }, box);
  9623. }
  9624. return elementToViewport({
  9625. x: box.width / 2,
  9626. y: box.height / 2
  9627. }, box);
  9628. }
  9629. // Composables
  9630. // Types
  9631. const locationStrategies = {
  9632. static: staticLocationStrategy,
  9633. // specific viewport position, usually centered
  9634. connected: connectedLocationStrategy // connected to a certain element
  9635. };
  9636. const makeLocationStrategyProps = propsFactory({
  9637. locationStrategy: {
  9638. type: [String, Function],
  9639. default: 'static',
  9640. validator: val => typeof val === 'function' || val in locationStrategies
  9641. },
  9642. location: {
  9643. type: String,
  9644. default: 'bottom'
  9645. },
  9646. origin: {
  9647. type: String,
  9648. default: 'auto'
  9649. },
  9650. offset: [Number, String, Array]
  9651. }, 'VOverlay-location-strategies');
  9652. function useLocationStrategies(props, data) {
  9653. const contentStyles = vue.ref({});
  9654. const updateLocation = vue.ref();
  9655. if (IN_BROWSER) {
  9656. useToggleScope(() => !!(data.isActive.value && props.locationStrategy), reset => {
  9657. vue.watch(() => props.locationStrategy, reset);
  9658. vue.onScopeDispose(() => {
  9659. window.removeEventListener('resize', onResize);
  9660. updateLocation.value = undefined;
  9661. });
  9662. window.addEventListener('resize', onResize, {
  9663. passive: true
  9664. });
  9665. if (typeof props.locationStrategy === 'function') {
  9666. updateLocation.value = props.locationStrategy(data, props, contentStyles)?.updateLocation;
  9667. } else {
  9668. updateLocation.value = locationStrategies[props.locationStrategy](data, props, contentStyles)?.updateLocation;
  9669. }
  9670. });
  9671. }
  9672. function onResize(e) {
  9673. updateLocation.value?.(e);
  9674. }
  9675. return {
  9676. contentStyles,
  9677. updateLocation
  9678. };
  9679. }
  9680. function staticLocationStrategy() {
  9681. // TODO
  9682. }
  9683. /** Get size of element ignoring max-width/max-height */
  9684. function getIntrinsicSize(el, isRtl) {
  9685. // const scrollables = new Map<Element, [number, number]>()
  9686. // el.querySelectorAll('*').forEach(el => {
  9687. // const x = el.scrollLeft
  9688. // const y = el.scrollTop
  9689. // if (x || y) {
  9690. // scrollables.set(el, [x, y])
  9691. // }
  9692. // })
  9693. // const initialMaxWidth = el.style.maxWidth
  9694. // const initialMaxHeight = el.style.maxHeight
  9695. // el.style.removeProperty('max-width')
  9696. // el.style.removeProperty('max-height')
  9697. /* eslint-disable-next-line sonarjs/prefer-immediate-return */
  9698. const contentBox = nullifyTransforms(el);
  9699. if (isRtl) {
  9700. contentBox.x += parseFloat(el.style.right || 0);
  9701. } else {
  9702. contentBox.x -= parseFloat(el.style.left || 0);
  9703. }
  9704. contentBox.y -= parseFloat(el.style.top || 0);
  9705. // el.style.maxWidth = initialMaxWidth
  9706. // el.style.maxHeight = initialMaxHeight
  9707. // scrollables.forEach((position, el) => {
  9708. // el.scrollTo(...position)
  9709. // })
  9710. return contentBox;
  9711. }
  9712. function connectedLocationStrategy(data, props, contentStyles) {
  9713. const activatorFixed = Array.isArray(data.target.value) || isFixedPosition(data.target.value);
  9714. if (activatorFixed) {
  9715. Object.assign(contentStyles.value, {
  9716. position: 'fixed',
  9717. top: 0,
  9718. [data.isRtl.value ? 'right' : 'left']: 0
  9719. });
  9720. }
  9721. const {
  9722. preferredAnchor,
  9723. preferredOrigin
  9724. } = destructComputed(() => {
  9725. const parsedAnchor = parseAnchor(props.location, data.isRtl.value);
  9726. const parsedOrigin = props.origin === 'overlap' ? parsedAnchor : props.origin === 'auto' ? flipSide(parsedAnchor) : parseAnchor(props.origin, data.isRtl.value);
  9727. // Some combinations of props may produce an invalid origin
  9728. if (parsedAnchor.side === parsedOrigin.side && parsedAnchor.align === flipAlign(parsedOrigin).align) {
  9729. return {
  9730. preferredAnchor: flipCorner(parsedAnchor),
  9731. preferredOrigin: flipCorner(parsedOrigin)
  9732. };
  9733. } else {
  9734. return {
  9735. preferredAnchor: parsedAnchor,
  9736. preferredOrigin: parsedOrigin
  9737. };
  9738. }
  9739. });
  9740. const [minWidth, minHeight, maxWidth, maxHeight] = ['minWidth', 'minHeight', 'maxWidth', 'maxHeight'].map(key => {
  9741. return vue.computed(() => {
  9742. const val = parseFloat(props[key]);
  9743. return isNaN(val) ? Infinity : val;
  9744. });
  9745. });
  9746. const offset = vue.computed(() => {
  9747. if (Array.isArray(props.offset)) {
  9748. return props.offset;
  9749. }
  9750. if (typeof props.offset === 'string') {
  9751. const offset = props.offset.split(' ').map(parseFloat);
  9752. if (offset.length < 2) offset.push(0);
  9753. return offset;
  9754. }
  9755. return typeof props.offset === 'number' ? [props.offset, 0] : [0, 0];
  9756. });
  9757. let observe = false;
  9758. const observer = new ResizeObserver(() => {
  9759. if (observe) updateLocation();
  9760. });
  9761. vue.watch([data.target, data.contentEl], (_ref, _ref2) => {
  9762. let [newTarget, newContentEl] = _ref;
  9763. let [oldTarget, oldContentEl] = _ref2;
  9764. if (oldTarget && !Array.isArray(oldTarget)) observer.unobserve(oldTarget);
  9765. if (newTarget && !Array.isArray(newTarget)) observer.observe(newTarget);
  9766. if (oldContentEl) observer.unobserve(oldContentEl);
  9767. if (newContentEl) observer.observe(newContentEl);
  9768. }, {
  9769. immediate: true
  9770. });
  9771. vue.onScopeDispose(() => {
  9772. observer.disconnect();
  9773. });
  9774. // eslint-disable-next-line max-statements
  9775. function updateLocation() {
  9776. observe = false;
  9777. requestAnimationFrame(() => observe = true);
  9778. if (!data.target.value || !data.contentEl.value) return;
  9779. const targetBox = getTargetBox(data.target.value);
  9780. const contentBox = getIntrinsicSize(data.contentEl.value, data.isRtl.value);
  9781. const scrollParents = getScrollParents(data.contentEl.value);
  9782. const viewportMargin = 12;
  9783. if (!scrollParents.length) {
  9784. scrollParents.push(document.documentElement);
  9785. if (!(data.contentEl.value.style.top && data.contentEl.value.style.left)) {
  9786. contentBox.x -= parseFloat(document.documentElement.style.getPropertyValue('--v-body-scroll-x') || 0);
  9787. contentBox.y -= parseFloat(document.documentElement.style.getPropertyValue('--v-body-scroll-y') || 0);
  9788. }
  9789. }
  9790. const viewport = scrollParents.reduce((box, el) => {
  9791. const rect = el.getBoundingClientRect();
  9792. const scrollBox = new Box({
  9793. x: el === document.documentElement ? 0 : rect.x,
  9794. y: el === document.documentElement ? 0 : rect.y,
  9795. width: el.clientWidth,
  9796. height: el.clientHeight
  9797. });
  9798. if (box) {
  9799. return new Box({
  9800. x: Math.max(box.left, scrollBox.left),
  9801. y: Math.max(box.top, scrollBox.top),
  9802. width: Math.min(box.right, scrollBox.right) - Math.max(box.left, scrollBox.left),
  9803. height: Math.min(box.bottom, scrollBox.bottom) - Math.max(box.top, scrollBox.top)
  9804. });
  9805. }
  9806. return scrollBox;
  9807. }, undefined);
  9808. viewport.x += viewportMargin;
  9809. viewport.y += viewportMargin;
  9810. viewport.width -= viewportMargin * 2;
  9811. viewport.height -= viewportMargin * 2;
  9812. let placement = {
  9813. anchor: preferredAnchor.value,
  9814. origin: preferredOrigin.value
  9815. };
  9816. function checkOverflow(_placement) {
  9817. const box = new Box(contentBox);
  9818. const targetPoint = anchorToPoint(_placement.anchor, targetBox);
  9819. const contentPoint = anchorToPoint(_placement.origin, box);
  9820. let {
  9821. x,
  9822. y
  9823. } = getOffset$1(targetPoint, contentPoint);
  9824. switch (_placement.anchor.side) {
  9825. case 'top':
  9826. y -= offset.value[0];
  9827. break;
  9828. case 'bottom':
  9829. y += offset.value[0];
  9830. break;
  9831. case 'left':
  9832. x -= offset.value[0];
  9833. break;
  9834. case 'right':
  9835. x += offset.value[0];
  9836. break;
  9837. }
  9838. switch (_placement.anchor.align) {
  9839. case 'top':
  9840. y -= offset.value[1];
  9841. break;
  9842. case 'bottom':
  9843. y += offset.value[1];
  9844. break;
  9845. case 'left':
  9846. x -= offset.value[1];
  9847. break;
  9848. case 'right':
  9849. x += offset.value[1];
  9850. break;
  9851. }
  9852. box.x += x;
  9853. box.y += y;
  9854. box.width = Math.min(box.width, maxWidth.value);
  9855. box.height = Math.min(box.height, maxHeight.value);
  9856. const overflows = getOverflow(box, viewport);
  9857. return {
  9858. overflows,
  9859. x,
  9860. y
  9861. };
  9862. }
  9863. let x = 0;
  9864. let y = 0;
  9865. const available = {
  9866. x: 0,
  9867. y: 0
  9868. };
  9869. const flipped = {
  9870. x: false,
  9871. y: false
  9872. };
  9873. let resets = -1;
  9874. while (true) {
  9875. if (resets++ > 10) {
  9876. consoleError('Infinite loop detected in connectedLocationStrategy');
  9877. break;
  9878. }
  9879. const {
  9880. x: _x,
  9881. y: _y,
  9882. overflows
  9883. } = checkOverflow(placement);
  9884. x += _x;
  9885. y += _y;
  9886. contentBox.x += _x;
  9887. contentBox.y += _y;
  9888. // flip
  9889. {
  9890. const axis = getAxis(placement.anchor);
  9891. const hasOverflowX = overflows.x.before || overflows.x.after;
  9892. const hasOverflowY = overflows.y.before || overflows.y.after;
  9893. let reset = false;
  9894. ['x', 'y'].forEach(key => {
  9895. if (key === 'x' && hasOverflowX && !flipped.x || key === 'y' && hasOverflowY && !flipped.y) {
  9896. const newPlacement = {
  9897. anchor: {
  9898. ...placement.anchor
  9899. },
  9900. origin: {
  9901. ...placement.origin
  9902. }
  9903. };
  9904. const flip = key === 'x' ? axis === 'y' ? flipAlign : flipSide : axis === 'y' ? flipSide : flipAlign;
  9905. newPlacement.anchor = flip(newPlacement.anchor);
  9906. newPlacement.origin = flip(newPlacement.origin);
  9907. const {
  9908. overflows: newOverflows
  9909. } = checkOverflow(newPlacement);
  9910. 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) {
  9911. placement = newPlacement;
  9912. reset = flipped[key] = true;
  9913. }
  9914. }
  9915. });
  9916. if (reset) continue;
  9917. }
  9918. // shift
  9919. if (overflows.x.before) {
  9920. x += overflows.x.before;
  9921. contentBox.x += overflows.x.before;
  9922. }
  9923. if (overflows.x.after) {
  9924. x -= overflows.x.after;
  9925. contentBox.x -= overflows.x.after;
  9926. }
  9927. if (overflows.y.before) {
  9928. y += overflows.y.before;
  9929. contentBox.y += overflows.y.before;
  9930. }
  9931. if (overflows.y.after) {
  9932. y -= overflows.y.after;
  9933. contentBox.y -= overflows.y.after;
  9934. }
  9935. // size
  9936. {
  9937. const overflows = getOverflow(contentBox, viewport);
  9938. available.x = viewport.width - overflows.x.before - overflows.x.after;
  9939. available.y = viewport.height - overflows.y.before - overflows.y.after;
  9940. x += overflows.x.before;
  9941. contentBox.x += overflows.x.before;
  9942. y += overflows.y.before;
  9943. contentBox.y += overflows.y.before;
  9944. }
  9945. break;
  9946. }
  9947. const axis = getAxis(placement.anchor);
  9948. Object.assign(contentStyles.value, {
  9949. '--v-overlay-anchor-origin': `${placement.anchor.side} ${placement.anchor.align}`,
  9950. transformOrigin: `${placement.origin.side} ${placement.origin.align}`,
  9951. // transform: `translate(${pixelRound(x)}px, ${pixelRound(y)}px)`,
  9952. top: convertToUnit(pixelRound(y)),
  9953. left: data.isRtl.value ? undefined : convertToUnit(pixelRound(x)),
  9954. right: data.isRtl.value ? convertToUnit(pixelRound(-x)) : undefined,
  9955. minWidth: convertToUnit(axis === 'y' ? Math.min(minWidth.value, targetBox.width) : minWidth.value),
  9956. maxWidth: convertToUnit(pixelCeil(clamp(available.x, minWidth.value === Infinity ? 0 : minWidth.value, maxWidth.value))),
  9957. maxHeight: convertToUnit(pixelCeil(clamp(available.y, minHeight.value === Infinity ? 0 : minHeight.value, maxHeight.value)))
  9958. });
  9959. return {
  9960. available,
  9961. contentBox
  9962. };
  9963. }
  9964. vue.watch(() => [preferredAnchor.value, preferredOrigin.value, props.offset, props.minWidth, props.minHeight, props.maxWidth, props.maxHeight], () => updateLocation());
  9965. vue.nextTick(() => {
  9966. const result = updateLocation();
  9967. // TODO: overflowing content should only require a single updateLocation call
  9968. // Icky hack to make sure the content is positioned consistently
  9969. if (!result) return;
  9970. const {
  9971. available,
  9972. contentBox
  9973. } = result;
  9974. if (contentBox.height > available.y) {
  9975. requestAnimationFrame(() => {
  9976. updateLocation();
  9977. requestAnimationFrame(() => {
  9978. updateLocation();
  9979. });
  9980. });
  9981. }
  9982. });
  9983. return {
  9984. updateLocation
  9985. };
  9986. }
  9987. function pixelRound(val) {
  9988. return Math.round(val * devicePixelRatio) / devicePixelRatio;
  9989. }
  9990. function pixelCeil(val) {
  9991. return Math.ceil(val * devicePixelRatio) / devicePixelRatio;
  9992. }
  9993. let clean = true;
  9994. const frames = [];
  9995. /**
  9996. * Schedule a task to run in an animation frame on its own
  9997. * This is useful for heavy tasks that may cause jank if all ran together
  9998. */
  9999. function requestNewFrame(cb) {
  10000. if (!clean || frames.length) {
  10001. frames.push(cb);
  10002. run();
  10003. } else {
  10004. clean = false;
  10005. cb();
  10006. run();
  10007. }
  10008. }
  10009. let raf = -1;
  10010. function run() {
  10011. cancelAnimationFrame(raf);
  10012. raf = requestAnimationFrame(() => {
  10013. const frame = frames.shift();
  10014. if (frame) frame();
  10015. if (frames.length) run();else clean = true;
  10016. });
  10017. }
  10018. // Utilities
  10019. // Types
  10020. const scrollStrategies = {
  10021. none: null,
  10022. close: closeScrollStrategy,
  10023. block: blockScrollStrategy,
  10024. reposition: repositionScrollStrategy
  10025. };
  10026. const makeScrollStrategyProps = propsFactory({
  10027. scrollStrategy: {
  10028. type: [String, Function],
  10029. default: 'block',
  10030. validator: val => typeof val === 'function' || val in scrollStrategies
  10031. }
  10032. }, 'VOverlay-scroll-strategies');
  10033. function useScrollStrategies(props, data) {
  10034. if (!IN_BROWSER) return;
  10035. let scope;
  10036. vue.watchEffect(async () => {
  10037. scope?.stop();
  10038. if (!(data.isActive.value && props.scrollStrategy)) return;
  10039. scope = vue.effectScope();
  10040. await new Promise(resolve => setTimeout(resolve));
  10041. scope.active && scope.run(() => {
  10042. if (typeof props.scrollStrategy === 'function') {
  10043. props.scrollStrategy(data, props, scope);
  10044. } else {
  10045. scrollStrategies[props.scrollStrategy]?.(data, props, scope);
  10046. }
  10047. });
  10048. });
  10049. vue.onScopeDispose(() => {
  10050. scope?.stop();
  10051. });
  10052. }
  10053. function closeScrollStrategy(data) {
  10054. function onScroll(e) {
  10055. data.isActive.value = false;
  10056. }
  10057. bindScroll(data.targetEl.value ?? data.contentEl.value, onScroll);
  10058. }
  10059. function blockScrollStrategy(data, props) {
  10060. const offsetParent = data.root.value?.offsetParent;
  10061. const scrollElements = [...new Set([...getScrollParents(data.targetEl.value, props.contained ? offsetParent : undefined), ...getScrollParents(data.contentEl.value, props.contained ? offsetParent : undefined)])].filter(el => !el.classList.contains('v-overlay-scroll-blocked'));
  10062. const scrollbarWidth = window.innerWidth - document.documentElement.offsetWidth;
  10063. const scrollableParent = (el => hasScrollbar(el) && el)(offsetParent || document.documentElement);
  10064. if (scrollableParent) {
  10065. data.root.value.classList.add('v-overlay--scroll-blocked');
  10066. }
  10067. scrollElements.forEach((el, i) => {
  10068. el.style.setProperty('--v-body-scroll-x', convertToUnit(-el.scrollLeft));
  10069. el.style.setProperty('--v-body-scroll-y', convertToUnit(-el.scrollTop));
  10070. if (el !== document.documentElement) {
  10071. el.style.setProperty('--v-scrollbar-offset', convertToUnit(scrollbarWidth));
  10072. }
  10073. el.classList.add('v-overlay-scroll-blocked');
  10074. });
  10075. vue.onScopeDispose(() => {
  10076. scrollElements.forEach((el, i) => {
  10077. const x = parseFloat(el.style.getPropertyValue('--v-body-scroll-x'));
  10078. const y = parseFloat(el.style.getPropertyValue('--v-body-scroll-y'));
  10079. const scrollBehavior = el.style.scrollBehavior;
  10080. el.style.scrollBehavior = 'auto';
  10081. el.style.removeProperty('--v-body-scroll-x');
  10082. el.style.removeProperty('--v-body-scroll-y');
  10083. el.style.removeProperty('--v-scrollbar-offset');
  10084. el.classList.remove('v-overlay-scroll-blocked');
  10085. el.scrollLeft = -x;
  10086. el.scrollTop = -y;
  10087. el.style.scrollBehavior = scrollBehavior;
  10088. });
  10089. if (scrollableParent) {
  10090. data.root.value.classList.remove('v-overlay--scroll-blocked');
  10091. }
  10092. });
  10093. }
  10094. function repositionScrollStrategy(data, props, scope) {
  10095. let slow = false;
  10096. let raf = -1;
  10097. let ric = -1;
  10098. function update(e) {
  10099. requestNewFrame(() => {
  10100. const start = performance.now();
  10101. data.updateLocation.value?.(e);
  10102. const time = performance.now() - start;
  10103. slow = time / (1000 / 60) > 2;
  10104. });
  10105. }
  10106. ric = (typeof requestIdleCallback === 'undefined' ? cb => cb() : requestIdleCallback)(() => {
  10107. scope.run(() => {
  10108. bindScroll(data.targetEl.value ?? data.contentEl.value, e => {
  10109. if (slow) {
  10110. // If the position calculation is slow,
  10111. // defer updates until scrolling is finished.
  10112. // Browsers usually fire one scroll event per frame so
  10113. // we just wait until we've got two frames without an event
  10114. cancelAnimationFrame(raf);
  10115. raf = requestAnimationFrame(() => {
  10116. raf = requestAnimationFrame(() => {
  10117. update(e);
  10118. });
  10119. });
  10120. } else {
  10121. update(e);
  10122. }
  10123. });
  10124. });
  10125. });
  10126. vue.onScopeDispose(() => {
  10127. typeof cancelIdleCallback !== 'undefined' && cancelIdleCallback(ric);
  10128. cancelAnimationFrame(raf);
  10129. });
  10130. }
  10131. /** @private */
  10132. function bindScroll(el, onScroll) {
  10133. const scrollElements = [document, ...getScrollParents(el)];
  10134. scrollElements.forEach(el => {
  10135. el.addEventListener('scroll', onScroll, {
  10136. passive: true
  10137. });
  10138. });
  10139. vue.onScopeDispose(() => {
  10140. scrollElements.forEach(el => {
  10141. el.removeEventListener('scroll', onScroll);
  10142. });
  10143. });
  10144. }
  10145. // Types
  10146. const VMenuSymbol = Symbol.for('vuetify:v-menu');
  10147. // Utilities
  10148. // Types
  10149. // Composables
  10150. const makeDelayProps = propsFactory({
  10151. closeDelay: [Number, String],
  10152. openDelay: [Number, String]
  10153. }, 'delay');
  10154. function useDelay(props, cb) {
  10155. let clearDelay = () => {};
  10156. function runDelay(isOpening) {
  10157. clearDelay?.();
  10158. const delay = Number(isOpening ? props.openDelay : props.closeDelay);
  10159. return new Promise(resolve => {
  10160. clearDelay = defer(delay, () => {
  10161. cb?.(isOpening);
  10162. resolve(isOpening);
  10163. });
  10164. });
  10165. }
  10166. function runOpenDelay() {
  10167. return runDelay(true);
  10168. }
  10169. function runCloseDelay() {
  10170. return runDelay(false);
  10171. }
  10172. return {
  10173. clearDelay,
  10174. runOpenDelay,
  10175. runCloseDelay
  10176. };
  10177. }
  10178. // Components
  10179. // Types
  10180. const makeActivatorProps = propsFactory({
  10181. target: [String, Object],
  10182. activator: [String, Object],
  10183. activatorProps: {
  10184. type: Object,
  10185. default: () => ({})
  10186. },
  10187. openOnClick: {
  10188. type: Boolean,
  10189. default: undefined
  10190. },
  10191. openOnHover: Boolean,
  10192. openOnFocus: {
  10193. type: Boolean,
  10194. default: undefined
  10195. },
  10196. closeOnContentClick: Boolean,
  10197. ...makeDelayProps()
  10198. }, 'VOverlay-activator');
  10199. function useActivator(props, _ref) {
  10200. let {
  10201. isActive,
  10202. isTop,
  10203. contentEl
  10204. } = _ref;
  10205. const vm = getCurrentInstance('useActivator');
  10206. const activatorEl = vue.ref();
  10207. let isHovered = false;
  10208. let isFocused = false;
  10209. let firstEnter = true;
  10210. const openOnFocus = vue.computed(() => props.openOnFocus || props.openOnFocus == null && props.openOnHover);
  10211. const openOnClick = vue.computed(() => props.openOnClick || props.openOnClick == null && !props.openOnHover && !openOnFocus.value);
  10212. const {
  10213. runOpenDelay,
  10214. runCloseDelay
  10215. } = useDelay(props, value => {
  10216. if (value === (props.openOnHover && isHovered || openOnFocus.value && isFocused) && !(props.openOnHover && isActive.value && !isTop.value)) {
  10217. if (isActive.value !== value) {
  10218. firstEnter = true;
  10219. }
  10220. isActive.value = value;
  10221. }
  10222. });
  10223. const cursorTarget = vue.ref();
  10224. const availableEvents = {
  10225. onClick: e => {
  10226. e.stopPropagation();
  10227. activatorEl.value = e.currentTarget || e.target;
  10228. if (!isActive.value) {
  10229. cursorTarget.value = [e.clientX, e.clientY];
  10230. }
  10231. isActive.value = !isActive.value;
  10232. },
  10233. onMouseenter: e => {
  10234. if (e.sourceCapabilities?.firesTouchEvents) return;
  10235. isHovered = true;
  10236. activatorEl.value = e.currentTarget || e.target;
  10237. runOpenDelay();
  10238. },
  10239. onMouseleave: e => {
  10240. isHovered = false;
  10241. runCloseDelay();
  10242. },
  10243. onFocus: e => {
  10244. if (matchesSelector(e.target, ':focus-visible') === false) return;
  10245. isFocused = true;
  10246. e.stopPropagation();
  10247. activatorEl.value = e.currentTarget || e.target;
  10248. runOpenDelay();
  10249. },
  10250. onBlur: e => {
  10251. isFocused = false;
  10252. e.stopPropagation();
  10253. runCloseDelay();
  10254. }
  10255. };
  10256. const activatorEvents = vue.computed(() => {
  10257. const events = {};
  10258. if (openOnClick.value) {
  10259. events.onClick = availableEvents.onClick;
  10260. }
  10261. if (props.openOnHover) {
  10262. events.onMouseenter = availableEvents.onMouseenter;
  10263. events.onMouseleave = availableEvents.onMouseleave;
  10264. }
  10265. if (openOnFocus.value) {
  10266. events.onFocus = availableEvents.onFocus;
  10267. events.onBlur = availableEvents.onBlur;
  10268. }
  10269. return events;
  10270. });
  10271. const contentEvents = vue.computed(() => {
  10272. const events = {};
  10273. if (props.openOnHover) {
  10274. events.onMouseenter = () => {
  10275. isHovered = true;
  10276. runOpenDelay();
  10277. };
  10278. events.onMouseleave = () => {
  10279. isHovered = false;
  10280. runCloseDelay();
  10281. };
  10282. }
  10283. if (openOnFocus.value) {
  10284. events.onFocusin = () => {
  10285. isFocused = true;
  10286. runOpenDelay();
  10287. };
  10288. events.onFocusout = () => {
  10289. isFocused = false;
  10290. runCloseDelay();
  10291. };
  10292. }
  10293. if (props.closeOnContentClick) {
  10294. const menu = vue.inject(VMenuSymbol, null);
  10295. events.onClick = () => {
  10296. isActive.value = false;
  10297. menu?.closeParents();
  10298. };
  10299. }
  10300. return events;
  10301. });
  10302. const scrimEvents = vue.computed(() => {
  10303. const events = {};
  10304. if (props.openOnHover) {
  10305. events.onMouseenter = () => {
  10306. if (firstEnter) {
  10307. isHovered = true;
  10308. firstEnter = false;
  10309. runOpenDelay();
  10310. }
  10311. };
  10312. events.onMouseleave = () => {
  10313. isHovered = false;
  10314. runCloseDelay();
  10315. };
  10316. }
  10317. return events;
  10318. });
  10319. vue.watch(isTop, val => {
  10320. if (val && (props.openOnHover && !isHovered && (!openOnFocus.value || !isFocused) || openOnFocus.value && !isFocused && (!props.openOnHover || !isHovered)) && !contentEl.value?.contains(document.activeElement)) {
  10321. isActive.value = false;
  10322. }
  10323. });
  10324. vue.watch(isActive, val => {
  10325. if (!val) {
  10326. setTimeout(() => {
  10327. cursorTarget.value = undefined;
  10328. });
  10329. }
  10330. }, {
  10331. flush: 'post'
  10332. });
  10333. const activatorRef = templateRef();
  10334. vue.watchEffect(() => {
  10335. if (!activatorRef.value) return;
  10336. vue.nextTick(() => {
  10337. activatorEl.value = activatorRef.el;
  10338. });
  10339. });
  10340. const targetRef = templateRef();
  10341. const target = vue.computed(() => {
  10342. if (props.target === 'cursor' && cursorTarget.value) return cursorTarget.value;
  10343. if (targetRef.value) return targetRef.el;
  10344. return getTarget(props.target, vm) || activatorEl.value;
  10345. });
  10346. const targetEl = vue.computed(() => {
  10347. return Array.isArray(target.value) ? undefined : target.value;
  10348. });
  10349. let scope;
  10350. vue.watch(() => !!props.activator, val => {
  10351. if (val && IN_BROWSER) {
  10352. scope = vue.effectScope();
  10353. scope.run(() => {
  10354. _useActivator(props, vm, {
  10355. activatorEl,
  10356. activatorEvents
  10357. });
  10358. });
  10359. } else if (scope) {
  10360. scope.stop();
  10361. }
  10362. }, {
  10363. flush: 'post',
  10364. immediate: true
  10365. });
  10366. vue.onScopeDispose(() => {
  10367. scope?.stop();
  10368. });
  10369. return {
  10370. activatorEl,
  10371. activatorRef,
  10372. target,
  10373. targetEl,
  10374. targetRef,
  10375. activatorEvents,
  10376. contentEvents,
  10377. scrimEvents
  10378. };
  10379. }
  10380. function _useActivator(props, vm, _ref2) {
  10381. let {
  10382. activatorEl,
  10383. activatorEvents
  10384. } = _ref2;
  10385. vue.watch(() => props.activator, (val, oldVal) => {
  10386. if (oldVal && val !== oldVal) {
  10387. const activator = getActivator(oldVal);
  10388. activator && unbindActivatorProps(activator);
  10389. }
  10390. if (val) {
  10391. vue.nextTick(() => bindActivatorProps());
  10392. }
  10393. }, {
  10394. immediate: true
  10395. });
  10396. vue.watch(() => props.activatorProps, () => {
  10397. bindActivatorProps();
  10398. });
  10399. vue.onScopeDispose(() => {
  10400. unbindActivatorProps();
  10401. });
  10402. function bindActivatorProps() {
  10403. let el = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : getActivator();
  10404. let _props = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : props.activatorProps;
  10405. if (!el) return;
  10406. bindProps(el, vue.mergeProps(activatorEvents.value, _props));
  10407. }
  10408. function unbindActivatorProps() {
  10409. let el = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : getActivator();
  10410. let _props = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : props.activatorProps;
  10411. if (!el) return;
  10412. unbindProps(el, vue.mergeProps(activatorEvents.value, _props));
  10413. }
  10414. function getActivator() {
  10415. let selector = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : props.activator;
  10416. const activator = getTarget(selector, vm);
  10417. // The activator should only be a valid element (Ignore comments and text nodes)
  10418. activatorEl.value = activator?.nodeType === Node.ELEMENT_NODE ? activator : undefined;
  10419. return activatorEl.value;
  10420. }
  10421. }
  10422. function getTarget(selector, vm) {
  10423. if (!selector) return;
  10424. let target;
  10425. if (selector === 'parent') {
  10426. let el = vm?.proxy?.$el?.parentNode;
  10427. while (el?.hasAttribute('data-no-activator')) {
  10428. el = el.parentNode;
  10429. }
  10430. target = el;
  10431. } else if (typeof selector === 'string') {
  10432. // Selector
  10433. target = document.querySelector(selector);
  10434. } else if ('$el' in selector) {
  10435. // Component (ref)
  10436. target = selector.$el;
  10437. } else {
  10438. // HTMLElement | Element | [x, y]
  10439. target = selector;
  10440. }
  10441. return target;
  10442. }
  10443. // Composables
  10444. function useHydration() {
  10445. if (!IN_BROWSER) return vue.shallowRef(false);
  10446. const {
  10447. ssr
  10448. } = useDisplay();
  10449. if (ssr) {
  10450. const isMounted = vue.shallowRef(false);
  10451. vue.onMounted(() => {
  10452. isMounted.value = true;
  10453. });
  10454. return isMounted;
  10455. } else {
  10456. return vue.shallowRef(true);
  10457. }
  10458. }
  10459. // Utilities
  10460. // Types
  10461. const makeLazyProps = propsFactory({
  10462. eager: Boolean
  10463. }, 'lazy');
  10464. function useLazy(props, active) {
  10465. const isBooted = vue.shallowRef(false);
  10466. const hasContent = vue.computed(() => isBooted.value || props.eager || active.value);
  10467. vue.watch(active, () => isBooted.value = true);
  10468. function onAfterLeave() {
  10469. if (!props.eager) isBooted.value = false;
  10470. }
  10471. return {
  10472. isBooted,
  10473. hasContent,
  10474. onAfterLeave
  10475. };
  10476. }
  10477. // Utilities
  10478. function useScopeId() {
  10479. const vm = getCurrentInstance('useScopeId');
  10480. const scopeId = vm.vnode.scopeId;
  10481. return {
  10482. scopeId: scopeId ? {
  10483. [scopeId]: ''
  10484. } : undefined
  10485. };
  10486. }
  10487. // Composables
  10488. // Types
  10489. const StackSymbol = Symbol.for('vuetify:stack');
  10490. const globalStack = vue.reactive([]);
  10491. function useStack(isActive, zIndex, disableGlobalStack) {
  10492. const vm = getCurrentInstance('useStack');
  10493. const createStackEntry = !disableGlobalStack;
  10494. const parent = vue.inject(StackSymbol, undefined);
  10495. const stack = vue.reactive({
  10496. activeChildren: new Set()
  10497. });
  10498. vue.provide(StackSymbol, stack);
  10499. const _zIndex = vue.shallowRef(+zIndex.value);
  10500. useToggleScope(isActive, () => {
  10501. const lastZIndex = globalStack.at(-1)?.[1];
  10502. _zIndex.value = lastZIndex ? lastZIndex + 10 : +zIndex.value;
  10503. if (createStackEntry) {
  10504. globalStack.push([vm.uid, _zIndex.value]);
  10505. }
  10506. parent?.activeChildren.add(vm.uid);
  10507. vue.onScopeDispose(() => {
  10508. if (createStackEntry) {
  10509. const idx = vue.toRaw(globalStack).findIndex(v => v[0] === vm.uid);
  10510. globalStack.splice(idx, 1);
  10511. }
  10512. parent?.activeChildren.delete(vm.uid);
  10513. });
  10514. });
  10515. const globalTop = vue.shallowRef(true);
  10516. if (createStackEntry) {
  10517. vue.watchEffect(() => {
  10518. const _isTop = globalStack.at(-1)?.[0] === vm.uid;
  10519. setTimeout(() => globalTop.value = _isTop);
  10520. });
  10521. }
  10522. const localTop = vue.computed(() => !stack.activeChildren.size);
  10523. return {
  10524. globalTop: vue.readonly(globalTop),
  10525. localTop,
  10526. stackStyles: vue.computed(() => ({
  10527. zIndex: _zIndex.value
  10528. }))
  10529. };
  10530. }
  10531. // Utilities
  10532. function useTeleport(target) {
  10533. const teleportTarget = vue.computed(() => {
  10534. const _target = target();
  10535. if (_target === true || !IN_BROWSER) return undefined;
  10536. const targetElement = _target === false ? document.body : typeof _target === 'string' ? document.querySelector(_target) : _target;
  10537. if (targetElement == null) {
  10538. vue.warn(`Unable to locate target ${_target}`);
  10539. return undefined;
  10540. }
  10541. let container = [...targetElement.children].find(el => el.matches('.v-overlay-container'));
  10542. if (!container) {
  10543. container = document.createElement('div');
  10544. container.className = 'v-overlay-container';
  10545. targetElement.appendChild(container);
  10546. }
  10547. return container;
  10548. });
  10549. return {
  10550. teleportTarget
  10551. };
  10552. }
  10553. // Utilities
  10554. // Types
  10555. function defaultConditional() {
  10556. return true;
  10557. }
  10558. function checkEvent(e, el, binding) {
  10559. // The include element callbacks below can be expensive
  10560. // so we should avoid calling them when we're not active.
  10561. // Explicitly check for false to allow fallback compatibility
  10562. // with non-toggleable components
  10563. if (!e || checkIsActive(e, binding) === false) return false;
  10564. // If we're clicking inside the shadowroot, then the app root doesn't get the same
  10565. // level of introspection as to _what_ we're clicking. We want to check to see if
  10566. // our target is the shadowroot parent container, and if it is, ignore.
  10567. const root = attachedRoot(el);
  10568. if (typeof ShadowRoot !== 'undefined' && root instanceof ShadowRoot && root.host === e.target) return false;
  10569. // Check if additional elements were passed to be included in check
  10570. // (click must be outside all included elements, if any)
  10571. const elements = (typeof binding.value === 'object' && binding.value.include || (() => []))();
  10572. // Add the root element for the component this directive was defined on
  10573. elements.push(el);
  10574. // Check if it's a click outside our elements, and then if our callback returns true.
  10575. // Non-toggleable components should take action in their callback and return falsy.
  10576. // Toggleable can return true if it wants to deactivate.
  10577. // Note that, because we're in the capture phase, this callback will occur before
  10578. // the bubbling click event on any outside elements.
  10579. return !elements.some(el => el?.contains(e.target));
  10580. }
  10581. function checkIsActive(e, binding) {
  10582. const isActive = typeof binding.value === 'object' && binding.value.closeConditional || defaultConditional;
  10583. return isActive(e);
  10584. }
  10585. function directive(e, el, binding) {
  10586. const handler = typeof binding.value === 'function' ? binding.value : binding.value.handler;
  10587. // Clicks in the Shadow DOM change their target while using setTimeout, so the original target is saved here
  10588. e.shadowTarget = e.target;
  10589. el._clickOutside.lastMousedownWasOutside && checkEvent(e, el, binding) && setTimeout(() => {
  10590. checkIsActive(e, binding) && handler && handler(e);
  10591. }, 0);
  10592. }
  10593. function handleShadow(el, callback) {
  10594. const root = attachedRoot(el);
  10595. callback(document);
  10596. if (typeof ShadowRoot !== 'undefined' && root instanceof ShadowRoot) {
  10597. callback(root);
  10598. }
  10599. }
  10600. const ClickOutside = {
  10601. // [data-app] may not be found
  10602. // if using bind, inserted makes
  10603. // sure that the root element is
  10604. // available, iOS does not support
  10605. // clicks on body
  10606. mounted(el, binding) {
  10607. const onClick = e => directive(e, el, binding);
  10608. const onMousedown = e => {
  10609. el._clickOutside.lastMousedownWasOutside = checkEvent(e, el, binding);
  10610. };
  10611. handleShadow(el, app => {
  10612. app.addEventListener('click', onClick, true);
  10613. app.addEventListener('mousedown', onMousedown, true);
  10614. });
  10615. if (!el._clickOutside) {
  10616. el._clickOutside = {
  10617. lastMousedownWasOutside: false
  10618. };
  10619. }
  10620. el._clickOutside[binding.instance.$.uid] = {
  10621. onClick,
  10622. onMousedown
  10623. };
  10624. },
  10625. beforeUnmount(el, binding) {
  10626. if (!el._clickOutside) return;
  10627. handleShadow(el, app => {
  10628. if (!app || !el._clickOutside?.[binding.instance.$.uid]) return;
  10629. const {
  10630. onClick,
  10631. onMousedown
  10632. } = el._clickOutside[binding.instance.$.uid];
  10633. app.removeEventListener('click', onClick, true);
  10634. app.removeEventListener('mousedown', onMousedown, true);
  10635. });
  10636. delete el._clickOutside[binding.instance.$.uid];
  10637. }
  10638. };
  10639. // Types
  10640. function Scrim(props) {
  10641. const {
  10642. modelValue,
  10643. color,
  10644. ...rest
  10645. } = props;
  10646. return vue.createVNode(vue.Transition, {
  10647. "name": "fade-transition",
  10648. "appear": true
  10649. }, {
  10650. default: () => [props.modelValue && vue.createVNode("div", vue.mergeProps({
  10651. "class": ['v-overlay__scrim', props.color.backgroundColorClasses.value],
  10652. "style": props.color.backgroundColorStyles.value
  10653. }, rest), null)]
  10654. });
  10655. }
  10656. const makeVOverlayProps = propsFactory({
  10657. absolute: Boolean,
  10658. attach: [Boolean, String, Object],
  10659. closeOnBack: {
  10660. type: Boolean,
  10661. default: true
  10662. },
  10663. contained: Boolean,
  10664. contentClass: null,
  10665. contentProps: null,
  10666. disabled: Boolean,
  10667. opacity: [Number, String],
  10668. noClickAnimation: Boolean,
  10669. modelValue: Boolean,
  10670. persistent: Boolean,
  10671. scrim: {
  10672. type: [Boolean, String],
  10673. default: true
  10674. },
  10675. zIndex: {
  10676. type: [Number, String],
  10677. default: 2000
  10678. },
  10679. ...makeActivatorProps(),
  10680. ...makeComponentProps(),
  10681. ...makeDimensionProps(),
  10682. ...makeLazyProps(),
  10683. ...makeLocationStrategyProps(),
  10684. ...makeScrollStrategyProps(),
  10685. ...makeThemeProps(),
  10686. ...makeTransitionProps()
  10687. }, 'VOverlay');
  10688. const VOverlay = genericComponent()({
  10689. name: 'VOverlay',
  10690. directives: {
  10691. ClickOutside
  10692. },
  10693. inheritAttrs: false,
  10694. props: {
  10695. _disableGlobalStack: Boolean,
  10696. ...makeVOverlayProps()
  10697. },
  10698. emits: {
  10699. 'click:outside': e => true,
  10700. 'update:modelValue': value => true,
  10701. afterEnter: () => true,
  10702. afterLeave: () => true
  10703. },
  10704. setup(props, _ref) {
  10705. let {
  10706. slots,
  10707. attrs,
  10708. emit
  10709. } = _ref;
  10710. const vm = getCurrentInstance('VOverlay');
  10711. const root = vue.ref();
  10712. const scrimEl = vue.ref();
  10713. const contentEl = vue.ref();
  10714. const model = useProxiedModel(props, 'modelValue');
  10715. const isActive = vue.computed({
  10716. get: () => model.value,
  10717. set: v => {
  10718. if (!(v && props.disabled)) model.value = v;
  10719. }
  10720. });
  10721. const {
  10722. themeClasses
  10723. } = provideTheme(props);
  10724. const {
  10725. rtlClasses,
  10726. isRtl
  10727. } = useRtl();
  10728. const {
  10729. hasContent,
  10730. onAfterLeave: _onAfterLeave
  10731. } = useLazy(props, isActive);
  10732. const scrimColor = useBackgroundColor(vue.computed(() => {
  10733. return typeof props.scrim === 'string' ? props.scrim : null;
  10734. }));
  10735. const {
  10736. globalTop,
  10737. localTop,
  10738. stackStyles
  10739. } = useStack(isActive, vue.toRef(props, 'zIndex'), props._disableGlobalStack);
  10740. const {
  10741. activatorEl,
  10742. activatorRef,
  10743. target,
  10744. targetEl,
  10745. targetRef,
  10746. activatorEvents,
  10747. contentEvents,
  10748. scrimEvents
  10749. } = useActivator(props, {
  10750. isActive,
  10751. isTop: localTop,
  10752. contentEl
  10753. });
  10754. const {
  10755. teleportTarget
  10756. } = useTeleport(() => {
  10757. const target = props.attach || props.contained;
  10758. if (target) return target;
  10759. const rootNode = activatorEl?.value?.getRootNode() || vm.proxy?.$el?.getRootNode();
  10760. if (rootNode instanceof ShadowRoot) return rootNode;
  10761. return false;
  10762. });
  10763. const {
  10764. dimensionStyles
  10765. } = useDimension(props);
  10766. const isMounted = useHydration();
  10767. const {
  10768. scopeId
  10769. } = useScopeId();
  10770. vue.watch(() => props.disabled, v => {
  10771. if (v) isActive.value = false;
  10772. });
  10773. const {
  10774. contentStyles,
  10775. updateLocation
  10776. } = useLocationStrategies(props, {
  10777. isRtl,
  10778. contentEl,
  10779. target,
  10780. isActive
  10781. });
  10782. useScrollStrategies(props, {
  10783. root,
  10784. contentEl,
  10785. targetEl,
  10786. isActive,
  10787. updateLocation
  10788. });
  10789. function onClickOutside(e) {
  10790. emit('click:outside', e);
  10791. if (!props.persistent) isActive.value = false;else animateClick();
  10792. }
  10793. function closeConditional(e) {
  10794. return isActive.value && globalTop.value && (
  10795. // If using scrim, only close if clicking on it rather than anything opened on top
  10796. !props.scrim || e.target === scrimEl.value || e instanceof MouseEvent && e.shadowTarget === scrimEl.value);
  10797. }
  10798. IN_BROWSER && vue.watch(isActive, val => {
  10799. if (val) {
  10800. window.addEventListener('keydown', onKeydown);
  10801. } else {
  10802. window.removeEventListener('keydown', onKeydown);
  10803. }
  10804. }, {
  10805. immediate: true
  10806. });
  10807. vue.onBeforeUnmount(() => {
  10808. if (!IN_BROWSER) return;
  10809. window.removeEventListener('keydown', onKeydown);
  10810. });
  10811. function onKeydown(e) {
  10812. if (e.key === 'Escape' && globalTop.value) {
  10813. if (!props.persistent) {
  10814. isActive.value = false;
  10815. if (contentEl.value?.contains(document.activeElement)) {
  10816. activatorEl.value?.focus();
  10817. }
  10818. } else animateClick();
  10819. }
  10820. }
  10821. const router = useRouter();
  10822. useToggleScope(() => props.closeOnBack, () => {
  10823. useBackButton(router, next => {
  10824. if (globalTop.value && isActive.value) {
  10825. next(false);
  10826. if (!props.persistent) isActive.value = false;else animateClick();
  10827. } else {
  10828. next();
  10829. }
  10830. });
  10831. });
  10832. const top = vue.ref();
  10833. vue.watch(() => isActive.value && (props.absolute || props.contained) && teleportTarget.value == null, val => {
  10834. if (val) {
  10835. const scrollParent = getScrollParent(root.value);
  10836. if (scrollParent && scrollParent !== document.scrollingElement) {
  10837. top.value = scrollParent.scrollTop;
  10838. }
  10839. }
  10840. });
  10841. // Add a quick "bounce" animation to the content
  10842. function animateClick() {
  10843. if (props.noClickAnimation) return;
  10844. contentEl.value && animate(contentEl.value, [{
  10845. transformOrigin: 'center'
  10846. }, {
  10847. transform: 'scale(1.03)'
  10848. }, {
  10849. transformOrigin: 'center'
  10850. }], {
  10851. duration: 150,
  10852. easing: standardEasing
  10853. });
  10854. }
  10855. function onAfterEnter() {
  10856. emit('afterEnter');
  10857. }
  10858. function onAfterLeave() {
  10859. _onAfterLeave();
  10860. emit('afterLeave');
  10861. }
  10862. useRender(() => vue.createVNode(vue.Fragment, null, [slots.activator?.({
  10863. isActive: isActive.value,
  10864. targetRef,
  10865. props: vue.mergeProps({
  10866. ref: activatorRef
  10867. }, activatorEvents.value, props.activatorProps)
  10868. }), isMounted.value && hasContent.value && vue.createVNode(vue.Teleport, {
  10869. "disabled": !teleportTarget.value,
  10870. "to": teleportTarget.value
  10871. }, {
  10872. default: () => [vue.createVNode("div", vue.mergeProps({
  10873. "class": ['v-overlay', {
  10874. 'v-overlay--absolute': props.absolute || props.contained,
  10875. 'v-overlay--active': isActive.value,
  10876. 'v-overlay--contained': props.contained
  10877. }, themeClasses.value, rtlClasses.value, props.class],
  10878. "style": [stackStyles.value, {
  10879. '--v-overlay-opacity': props.opacity,
  10880. top: convertToUnit(top.value)
  10881. }, props.style],
  10882. "ref": root
  10883. }, scopeId, attrs), [vue.createVNode(Scrim, vue.mergeProps({
  10884. "color": scrimColor,
  10885. "modelValue": isActive.value && !!props.scrim,
  10886. "ref": scrimEl
  10887. }, scrimEvents.value), null), vue.createVNode(MaybeTransition, {
  10888. "appear": true,
  10889. "persisted": true,
  10890. "transition": props.transition,
  10891. "target": target.value,
  10892. "onAfterEnter": onAfterEnter,
  10893. "onAfterLeave": onAfterLeave
  10894. }, {
  10895. default: () => [vue.withDirectives(vue.createVNode("div", vue.mergeProps({
  10896. "ref": contentEl,
  10897. "class": ['v-overlay__content', props.contentClass],
  10898. "style": [dimensionStyles.value, contentStyles.value]
  10899. }, contentEvents.value, props.contentProps), [slots.default?.({
  10900. isActive
  10901. })]), [[vue.vShow, isActive.value], [vue.resolveDirective("click-outside"), {
  10902. handler: onClickOutside,
  10903. closeConditional,
  10904. include: () => [activatorEl.value]
  10905. }]])]
  10906. })])]
  10907. })]));
  10908. return {
  10909. activatorEl,
  10910. scrimEl,
  10911. target,
  10912. animateClick,
  10913. contentEl,
  10914. globalTop,
  10915. localTop,
  10916. updateLocation
  10917. };
  10918. }
  10919. });
  10920. // Types
  10921. const Refs = Symbol('Forwarded refs');
  10922. /** Omit properties starting with P */
  10923. /** Omit keyof $props from T */
  10924. function getDescriptor(obj, key) {
  10925. let currentObj = obj;
  10926. while (currentObj) {
  10927. const descriptor = Reflect.getOwnPropertyDescriptor(currentObj, key);
  10928. if (descriptor) return descriptor;
  10929. currentObj = Object.getPrototypeOf(currentObj);
  10930. }
  10931. return undefined;
  10932. }
  10933. function forwardRefs(target) {
  10934. for (var _len = arguments.length, refs = new Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) {
  10935. refs[_key - 1] = arguments[_key];
  10936. }
  10937. target[Refs] = refs;
  10938. return new Proxy(target, {
  10939. get(target, key) {
  10940. if (Reflect.has(target, key)) {
  10941. return Reflect.get(target, key);
  10942. }
  10943. // Skip internal properties
  10944. if (typeof key === 'symbol' || key.startsWith('$') || key.startsWith('__')) return;
  10945. for (const ref of refs) {
  10946. if (ref.value && Reflect.has(ref.value, key)) {
  10947. const val = Reflect.get(ref.value, key);
  10948. return typeof val === 'function' ? val.bind(ref.value) : val;
  10949. }
  10950. }
  10951. },
  10952. has(target, key) {
  10953. if (Reflect.has(target, key)) {
  10954. return true;
  10955. }
  10956. // Skip internal properties
  10957. if (typeof key === 'symbol' || key.startsWith('$') || key.startsWith('__')) return false;
  10958. for (const ref of refs) {
  10959. if (ref.value && Reflect.has(ref.value, key)) {
  10960. return true;
  10961. }
  10962. }
  10963. return false;
  10964. },
  10965. set(target, key, value) {
  10966. if (Reflect.has(target, key)) {
  10967. return Reflect.set(target, key, value);
  10968. }
  10969. // Skip internal properties
  10970. if (typeof key === 'symbol' || key.startsWith('$') || key.startsWith('__')) return false;
  10971. for (const ref of refs) {
  10972. if (ref.value && Reflect.has(ref.value, key)) {
  10973. return Reflect.set(ref.value, key, value);
  10974. }
  10975. }
  10976. return false;
  10977. },
  10978. getOwnPropertyDescriptor(target, key) {
  10979. const descriptor = Reflect.getOwnPropertyDescriptor(target, key);
  10980. if (descriptor) return descriptor;
  10981. // Skip internal properties
  10982. if (typeof key === 'symbol' || key.startsWith('$') || key.startsWith('__')) return;
  10983. // Check each ref's own properties
  10984. for (const ref of refs) {
  10985. if (!ref.value) continue;
  10986. const descriptor = getDescriptor(ref.value, key) ?? ('_' in ref.value ? getDescriptor(ref.value._?.setupState, key) : undefined);
  10987. if (descriptor) return descriptor;
  10988. }
  10989. // Recursive search up each ref's prototype
  10990. for (const ref of refs) {
  10991. const childRefs = ref.value && ref.value[Refs];
  10992. if (!childRefs) continue;
  10993. const queue = childRefs.slice();
  10994. while (queue.length) {
  10995. const ref = queue.shift();
  10996. const descriptor = getDescriptor(ref.value, key);
  10997. if (descriptor) return descriptor;
  10998. const childRefs = ref.value && ref.value[Refs];
  10999. if (childRefs) queue.push(...childRefs);
  11000. }
  11001. }
  11002. return undefined;
  11003. }
  11004. });
  11005. }
  11006. // Types
  11007. const makeVMenuProps = propsFactory({
  11008. // TODO
  11009. // disableKeys: Boolean,
  11010. id: String,
  11011. submenu: Boolean,
  11012. ...omit(makeVOverlayProps({
  11013. closeDelay: 250,
  11014. closeOnContentClick: true,
  11015. locationStrategy: 'connected',
  11016. location: undefined,
  11017. openDelay: 300,
  11018. scrim: false,
  11019. scrollStrategy: 'reposition',
  11020. transition: {
  11021. component: VDialogTransition
  11022. }
  11023. }), ['absolute'])
  11024. }, 'VMenu');
  11025. const VMenu = genericComponent()({
  11026. name: 'VMenu',
  11027. props: makeVMenuProps(),
  11028. emits: {
  11029. 'update:modelValue': value => true
  11030. },
  11031. setup(props, _ref) {
  11032. let {
  11033. slots
  11034. } = _ref;
  11035. const isActive = useProxiedModel(props, 'modelValue');
  11036. const {
  11037. scopeId
  11038. } = useScopeId();
  11039. const {
  11040. isRtl
  11041. } = useRtl();
  11042. const uid = getUid();
  11043. const id = vue.computed(() => props.id || `v-menu-${uid}`);
  11044. const overlay = vue.ref();
  11045. const parent = vue.inject(VMenuSymbol, null);
  11046. const openChildren = vue.shallowRef(new Set());
  11047. vue.provide(VMenuSymbol, {
  11048. register() {
  11049. openChildren.value.add(uid);
  11050. },
  11051. unregister() {
  11052. openChildren.value.delete(uid);
  11053. },
  11054. closeParents(e) {
  11055. setTimeout(() => {
  11056. if (!openChildren.value.size && !props.persistent && (e == null || overlay.value?.contentEl && !isClickInsideElement(e, overlay.value.contentEl))) {
  11057. isActive.value = false;
  11058. parent?.closeParents();
  11059. }
  11060. }, 40);
  11061. }
  11062. });
  11063. vue.onBeforeUnmount(() => {
  11064. parent?.unregister();
  11065. document.removeEventListener('focusin', onFocusIn);
  11066. });
  11067. vue.onDeactivated(() => isActive.value = false);
  11068. async function onFocusIn(e) {
  11069. const before = e.relatedTarget;
  11070. const after = e.target;
  11071. await vue.nextTick();
  11072. if (isActive.value && before !== after && overlay.value?.contentEl &&
  11073. // We're the topmost menu
  11074. overlay.value?.globalTop &&
  11075. // It isn't the document or the menu body
  11076. ![document, overlay.value.contentEl].includes(after) &&
  11077. // It isn't inside the menu body
  11078. !overlay.value.contentEl.contains(after)) {
  11079. const focusable = focusableChildren(overlay.value.contentEl);
  11080. focusable[0]?.focus();
  11081. }
  11082. }
  11083. vue.watch(isActive, val => {
  11084. if (val) {
  11085. parent?.register();
  11086. if (IN_BROWSER) {
  11087. document.addEventListener('focusin', onFocusIn, {
  11088. once: true
  11089. });
  11090. }
  11091. } else {
  11092. parent?.unregister();
  11093. if (IN_BROWSER) {
  11094. document.removeEventListener('focusin', onFocusIn);
  11095. }
  11096. }
  11097. }, {
  11098. immediate: true
  11099. });
  11100. function onClickOutside(e) {
  11101. parent?.closeParents(e);
  11102. }
  11103. function onKeydown(e) {
  11104. if (props.disabled) return;
  11105. if (e.key === 'Tab' || e.key === 'Enter' && !props.closeOnContentClick) {
  11106. if (e.key === 'Enter' && (e.target instanceof HTMLTextAreaElement || e.target instanceof HTMLInputElement && !!e.target.closest('form'))) return;
  11107. if (e.key === 'Enter') e.preventDefault();
  11108. const nextElement = getNextElement(focusableChildren(overlay.value?.contentEl, false), e.shiftKey ? 'prev' : 'next', el => el.tabIndex >= 0);
  11109. if (!nextElement) {
  11110. isActive.value = false;
  11111. overlay.value?.activatorEl?.focus();
  11112. }
  11113. } else if (props.submenu && e.key === (isRtl.value ? 'ArrowRight' : 'ArrowLeft')) {
  11114. isActive.value = false;
  11115. overlay.value?.activatorEl?.focus();
  11116. }
  11117. }
  11118. function onActivatorKeydown(e) {
  11119. if (props.disabled) return;
  11120. const el = overlay.value?.contentEl;
  11121. if (el && isActive.value) {
  11122. if (e.key === 'ArrowDown') {
  11123. e.preventDefault();
  11124. e.stopImmediatePropagation();
  11125. focusChild(el, 'next');
  11126. } else if (e.key === 'ArrowUp') {
  11127. e.preventDefault();
  11128. e.stopImmediatePropagation();
  11129. focusChild(el, 'prev');
  11130. } else if (props.submenu) {
  11131. if (e.key === (isRtl.value ? 'ArrowRight' : 'ArrowLeft')) {
  11132. isActive.value = false;
  11133. } else if (e.key === (isRtl.value ? 'ArrowLeft' : 'ArrowRight')) {
  11134. e.preventDefault();
  11135. focusChild(el, 'first');
  11136. }
  11137. }
  11138. } else if (props.submenu ? e.key === (isRtl.value ? 'ArrowLeft' : 'ArrowRight') : ['ArrowDown', 'ArrowUp'].includes(e.key)) {
  11139. isActive.value = true;
  11140. e.preventDefault();
  11141. setTimeout(() => setTimeout(() => onActivatorKeydown(e)));
  11142. }
  11143. }
  11144. const activatorProps = vue.computed(() => vue.mergeProps({
  11145. 'aria-haspopup': 'menu',
  11146. 'aria-expanded': String(isActive.value),
  11147. 'aria-owns': id.value,
  11148. onKeydown: onActivatorKeydown
  11149. }, props.activatorProps));
  11150. useRender(() => {
  11151. const overlayProps = VOverlay.filterProps(props);
  11152. return vue.createVNode(VOverlay, vue.mergeProps({
  11153. "ref": overlay,
  11154. "id": id.value,
  11155. "class": ['v-menu', props.class],
  11156. "style": props.style
  11157. }, overlayProps, {
  11158. "modelValue": isActive.value,
  11159. "onUpdate:modelValue": $event => isActive.value = $event,
  11160. "absolute": true,
  11161. "activatorProps": activatorProps.value,
  11162. "location": props.location ?? (props.submenu ? 'end' : 'bottom'),
  11163. "onClick:outside": onClickOutside,
  11164. "onKeydown": onKeydown
  11165. }, scopeId), {
  11166. activator: slots.activator,
  11167. default: function () {
  11168. for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) {
  11169. args[_key] = arguments[_key];
  11170. }
  11171. return vue.createVNode(VDefaultsProvider, {
  11172. "root": "VMenu"
  11173. }, {
  11174. default: () => [slots.default?.(...args)]
  11175. });
  11176. }
  11177. });
  11178. });
  11179. return forwardRefs({
  11180. id,
  11181. ΨopenChildren: openChildren
  11182. }, overlay);
  11183. }
  11184. });
  11185. // Types
  11186. const makeVCounterProps = propsFactory({
  11187. active: Boolean,
  11188. disabled: Boolean,
  11189. max: [Number, String],
  11190. value: {
  11191. type: [Number, String],
  11192. default: 0
  11193. },
  11194. ...makeComponentProps(),
  11195. ...makeTransitionProps({
  11196. transition: {
  11197. component: VSlideYTransition
  11198. }
  11199. })
  11200. }, 'VCounter');
  11201. const VCounter = genericComponent()({
  11202. name: 'VCounter',
  11203. functional: true,
  11204. props: makeVCounterProps(),
  11205. setup(props, _ref) {
  11206. let {
  11207. slots
  11208. } = _ref;
  11209. const counter = vue.computed(() => {
  11210. return props.max ? `${props.value} / ${props.max}` : String(props.value);
  11211. });
  11212. useRender(() => vue.createVNode(MaybeTransition, {
  11213. "transition": props.transition
  11214. }, {
  11215. default: () => [vue.withDirectives(vue.createVNode("div", {
  11216. "class": ['v-counter', {
  11217. 'text-error': props.max && !props.disabled && parseFloat(props.value) > parseFloat(props.max)
  11218. }, props.class],
  11219. "style": props.style
  11220. }, [slots.default ? slots.default({
  11221. counter: counter.value,
  11222. max: props.max,
  11223. value: props.value
  11224. }) : counter.value]), [[vue.vShow, props.active]])]
  11225. }));
  11226. return {};
  11227. }
  11228. });
  11229. const makeVFieldLabelProps = propsFactory({
  11230. floating: Boolean,
  11231. ...makeComponentProps()
  11232. }, 'VFieldLabel');
  11233. const VFieldLabel = genericComponent()({
  11234. name: 'VFieldLabel',
  11235. props: makeVFieldLabelProps(),
  11236. setup(props, _ref) {
  11237. let {
  11238. slots
  11239. } = _ref;
  11240. useRender(() => vue.createVNode(VLabel, {
  11241. "class": ['v-field-label', {
  11242. 'v-field-label--floating': props.floating
  11243. }, props.class],
  11244. "style": props.style,
  11245. "aria-hidden": props.floating || undefined
  11246. }, slots));
  11247. return {};
  11248. }
  11249. });
  11250. // Types
  11251. const allowedVariants$1 = ['underlined', 'outlined', 'filled', 'solo', 'solo-inverted', 'solo-filled', 'plain'];
  11252. const makeVFieldProps = propsFactory({
  11253. appendInnerIcon: IconValue,
  11254. bgColor: String,
  11255. clearable: Boolean,
  11256. clearIcon: {
  11257. type: IconValue,
  11258. default: '$clear'
  11259. },
  11260. active: Boolean,
  11261. centerAffix: {
  11262. type: Boolean,
  11263. default: undefined
  11264. },
  11265. color: String,
  11266. baseColor: String,
  11267. dirty: Boolean,
  11268. disabled: {
  11269. type: Boolean,
  11270. default: null
  11271. },
  11272. error: Boolean,
  11273. flat: Boolean,
  11274. label: String,
  11275. persistentClear: Boolean,
  11276. prependInnerIcon: IconValue,
  11277. reverse: Boolean,
  11278. singleLine: Boolean,
  11279. variant: {
  11280. type: String,
  11281. default: 'filled',
  11282. validator: v => allowedVariants$1.includes(v)
  11283. },
  11284. 'onClick:clear': EventProp(),
  11285. 'onClick:appendInner': EventProp(),
  11286. 'onClick:prependInner': EventProp(),
  11287. ...makeComponentProps(),
  11288. ...makeLoaderProps(),
  11289. ...makeRoundedProps(),
  11290. ...makeThemeProps()
  11291. }, 'VField');
  11292. const VField = genericComponent()({
  11293. name: 'VField',
  11294. inheritAttrs: false,
  11295. props: {
  11296. id: String,
  11297. ...makeFocusProps(),
  11298. ...makeVFieldProps()
  11299. },
  11300. emits: {
  11301. 'update:focused': focused => true,
  11302. 'update:modelValue': value => true
  11303. },
  11304. setup(props, _ref) {
  11305. let {
  11306. attrs,
  11307. emit,
  11308. slots
  11309. } = _ref;
  11310. const {
  11311. themeClasses
  11312. } = provideTheme(props);
  11313. const {
  11314. loaderClasses
  11315. } = useLoader(props);
  11316. const {
  11317. focusClasses,
  11318. isFocused,
  11319. focus,
  11320. blur
  11321. } = useFocus(props);
  11322. const {
  11323. InputIcon
  11324. } = useInputIcon(props);
  11325. const {
  11326. roundedClasses
  11327. } = useRounded(props);
  11328. const {
  11329. rtlClasses
  11330. } = useRtl();
  11331. const isActive = vue.computed(() => props.dirty || props.active);
  11332. const hasLabel = vue.computed(() => !props.singleLine && !!(props.label || slots.label));
  11333. const uid = getUid();
  11334. const id = vue.computed(() => props.id || `input-${uid}`);
  11335. const messagesId = vue.computed(() => `${id.value}-messages`);
  11336. const labelRef = vue.ref();
  11337. const floatingLabelRef = vue.ref();
  11338. const controlRef = vue.ref();
  11339. const isPlainOrUnderlined = vue.computed(() => ['plain', 'underlined'].includes(props.variant));
  11340. const {
  11341. backgroundColorClasses,
  11342. backgroundColorStyles
  11343. } = useBackgroundColor(vue.toRef(props, 'bgColor'));
  11344. const {
  11345. textColorClasses,
  11346. textColorStyles
  11347. } = useTextColor(vue.computed(() => {
  11348. return props.error || props.disabled ? undefined : isActive.value && isFocused.value ? props.color : props.baseColor;
  11349. }));
  11350. vue.watch(isActive, val => {
  11351. if (hasLabel.value) {
  11352. const el = labelRef.value.$el;
  11353. const targetEl = floatingLabelRef.value.$el;
  11354. requestAnimationFrame(() => {
  11355. const rect = nullifyTransforms(el);
  11356. const targetRect = targetEl.getBoundingClientRect();
  11357. const x = targetRect.x - rect.x;
  11358. const y = targetRect.y - rect.y - (rect.height / 2 - targetRect.height / 2);
  11359. const targetWidth = targetRect.width / 0.75;
  11360. const width = Math.abs(targetWidth - rect.width) > 1 ? {
  11361. maxWidth: convertToUnit(targetWidth)
  11362. } : undefined;
  11363. const style = getComputedStyle(el);
  11364. const targetStyle = getComputedStyle(targetEl);
  11365. const duration = parseFloat(style.transitionDuration) * 1000 || 150;
  11366. const scale = parseFloat(targetStyle.getPropertyValue('--v-field-label-scale'));
  11367. const color = targetStyle.getPropertyValue('color');
  11368. el.style.visibility = 'visible';
  11369. targetEl.style.visibility = 'hidden';
  11370. animate(el, {
  11371. transform: `translate(${x}px, ${y}px) scale(${scale})`,
  11372. color,
  11373. ...width
  11374. }, {
  11375. duration,
  11376. easing: standardEasing,
  11377. direction: val ? 'normal' : 'reverse'
  11378. }).finished.then(() => {
  11379. el.style.removeProperty('visibility');
  11380. targetEl.style.removeProperty('visibility');
  11381. });
  11382. });
  11383. }
  11384. }, {
  11385. flush: 'post'
  11386. });
  11387. const slotProps = vue.computed(() => ({
  11388. isActive,
  11389. isFocused,
  11390. controlRef,
  11391. blur,
  11392. focus
  11393. }));
  11394. function onClick(e) {
  11395. if (e.target !== document.activeElement) {
  11396. e.preventDefault();
  11397. }
  11398. }
  11399. function onKeydownClear(e) {
  11400. if (e.key !== 'Enter' && e.key !== ' ') return;
  11401. e.preventDefault();
  11402. e.stopPropagation();
  11403. props['onClick:clear']?.(new MouseEvent('click'));
  11404. }
  11405. useRender(() => {
  11406. const isOutlined = props.variant === 'outlined';
  11407. const hasPrepend = !!(slots['prepend-inner'] || props.prependInnerIcon);
  11408. const hasClear = !!(props.clearable || slots.clear);
  11409. const hasAppend = !!(slots['append-inner'] || props.appendInnerIcon || hasClear);
  11410. const label = () => slots.label ? slots.label({
  11411. ...slotProps.value,
  11412. label: props.label,
  11413. props: {
  11414. for: id.value
  11415. }
  11416. }) : props.label;
  11417. return vue.createVNode("div", vue.mergeProps({
  11418. "class": ['v-field', {
  11419. 'v-field--active': isActive.value,
  11420. 'v-field--appended': hasAppend,
  11421. 'v-field--center-affix': props.centerAffix ?? !isPlainOrUnderlined.value,
  11422. 'v-field--disabled': props.disabled,
  11423. 'v-field--dirty': props.dirty,
  11424. 'v-field--error': props.error,
  11425. 'v-field--flat': props.flat,
  11426. 'v-field--has-background': !!props.bgColor,
  11427. 'v-field--persistent-clear': props.persistentClear,
  11428. 'v-field--prepended': hasPrepend,
  11429. 'v-field--reverse': props.reverse,
  11430. 'v-field--single-line': props.singleLine,
  11431. 'v-field--no-label': !label(),
  11432. [`v-field--variant-${props.variant}`]: true
  11433. }, themeClasses.value, backgroundColorClasses.value, focusClasses.value, loaderClasses.value, roundedClasses.value, rtlClasses.value, props.class],
  11434. "style": [backgroundColorStyles.value, props.style],
  11435. "onClick": onClick
  11436. }, attrs), [vue.createVNode("div", {
  11437. "class": "v-field__overlay"
  11438. }, null), vue.createVNode(LoaderSlot, {
  11439. "name": "v-field",
  11440. "active": !!props.loading,
  11441. "color": props.error ? 'error' : typeof props.loading === 'string' ? props.loading : props.color
  11442. }, {
  11443. default: slots.loader
  11444. }), hasPrepend && vue.createVNode("div", {
  11445. "key": "prepend",
  11446. "class": "v-field__prepend-inner"
  11447. }, [props.prependInnerIcon && vue.createVNode(InputIcon, {
  11448. "key": "prepend-icon",
  11449. "name": "prependInner"
  11450. }, null), slots['prepend-inner']?.(slotProps.value)]), vue.createVNode("div", {
  11451. "class": "v-field__field",
  11452. "data-no-activator": ""
  11453. }, [['filled', 'solo', 'solo-inverted', 'solo-filled'].includes(props.variant) && hasLabel.value && vue.createVNode(VFieldLabel, {
  11454. "key": "floating-label",
  11455. "ref": floatingLabelRef,
  11456. "class": [textColorClasses.value],
  11457. "floating": true,
  11458. "for": id.value,
  11459. "style": textColorStyles.value
  11460. }, {
  11461. default: () => [label()]
  11462. }), hasLabel.value && vue.createVNode(VFieldLabel, {
  11463. "key": "label",
  11464. "ref": labelRef,
  11465. "for": id.value
  11466. }, {
  11467. default: () => [label()]
  11468. }), slots.default?.({
  11469. ...slotProps.value,
  11470. props: {
  11471. id: id.value,
  11472. class: 'v-field__input',
  11473. 'aria-describedby': messagesId.value
  11474. },
  11475. focus,
  11476. blur
  11477. })]), hasClear && vue.createVNode(VExpandXTransition, {
  11478. "key": "clear"
  11479. }, {
  11480. default: () => [vue.withDirectives(vue.createVNode("div", {
  11481. "class": "v-field__clearable",
  11482. "onMousedown": e => {
  11483. e.preventDefault();
  11484. e.stopPropagation();
  11485. }
  11486. }, [vue.createVNode(VDefaultsProvider, {
  11487. "defaults": {
  11488. VIcon: {
  11489. icon: props.clearIcon
  11490. }
  11491. }
  11492. }, {
  11493. default: () => [slots.clear ? slots.clear({
  11494. ...slotProps.value,
  11495. props: {
  11496. onKeydown: onKeydownClear,
  11497. onFocus: focus,
  11498. onBlur: blur,
  11499. onClick: props['onClick:clear']
  11500. }
  11501. }) : vue.createVNode(InputIcon, {
  11502. "name": "clear",
  11503. "onKeydown": onKeydownClear,
  11504. "onFocus": focus,
  11505. "onBlur": blur
  11506. }, null)]
  11507. })]), [[vue.vShow, props.dirty]])]
  11508. }), hasAppend && vue.createVNode("div", {
  11509. "key": "append",
  11510. "class": "v-field__append-inner"
  11511. }, [slots['append-inner']?.(slotProps.value), props.appendInnerIcon && vue.createVNode(InputIcon, {
  11512. "key": "append-icon",
  11513. "name": "appendInner"
  11514. }, null)]), vue.createVNode("div", {
  11515. "class": ['v-field__outline', textColorClasses.value],
  11516. "style": textColorStyles.value
  11517. }, [isOutlined && vue.createVNode(vue.Fragment, null, [vue.createVNode("div", {
  11518. "class": "v-field__outline__start"
  11519. }, null), hasLabel.value && vue.createVNode("div", {
  11520. "class": "v-field__outline__notch"
  11521. }, [vue.createVNode(VFieldLabel, {
  11522. "ref": floatingLabelRef,
  11523. "floating": true,
  11524. "for": id.value
  11525. }, {
  11526. default: () => [label()]
  11527. })]), vue.createVNode("div", {
  11528. "class": "v-field__outline__end"
  11529. }, null)]), isPlainOrUnderlined.value && hasLabel.value && vue.createVNode(VFieldLabel, {
  11530. "ref": floatingLabelRef,
  11531. "floating": true,
  11532. "for": id.value
  11533. }, {
  11534. default: () => [label()]
  11535. })])]);
  11536. });
  11537. return {
  11538. controlRef
  11539. };
  11540. }
  11541. });
  11542. // TODO: this is kinda slow, might be better to implicitly inherit props instead
  11543. function filterFieldProps(attrs) {
  11544. const keys = Object.keys(VField.props).filter(k => !isOn(k) && k !== 'class' && k !== 'style');
  11545. return pick(attrs, keys);
  11546. }
  11547. // Types
  11548. const activeTypes = ['color', 'file', 'time', 'date', 'datetime-local', 'week', 'month'];
  11549. const makeVTextFieldProps = propsFactory({
  11550. autofocus: Boolean,
  11551. counter: [Boolean, Number, String],
  11552. counterValue: [Number, Function],
  11553. prefix: String,
  11554. placeholder: String,
  11555. persistentPlaceholder: Boolean,
  11556. persistentCounter: Boolean,
  11557. suffix: String,
  11558. role: String,
  11559. type: {
  11560. type: String,
  11561. default: 'text'
  11562. },
  11563. modelModifiers: Object,
  11564. ...makeVInputProps(),
  11565. ...makeVFieldProps()
  11566. }, 'VTextField');
  11567. const VTextField = genericComponent()({
  11568. name: 'VTextField',
  11569. directives: {
  11570. Intersect
  11571. },
  11572. inheritAttrs: false,
  11573. props: makeVTextFieldProps(),
  11574. emits: {
  11575. 'click:control': e => true,
  11576. 'mousedown:control': e => true,
  11577. 'update:focused': focused => true,
  11578. 'update:modelValue': val => true
  11579. },
  11580. setup(props, _ref) {
  11581. let {
  11582. attrs,
  11583. emit,
  11584. slots
  11585. } = _ref;
  11586. const model = useProxiedModel(props, 'modelValue');
  11587. const {
  11588. isFocused,
  11589. focus,
  11590. blur
  11591. } = useFocus(props);
  11592. const counterValue = vue.computed(() => {
  11593. return typeof props.counterValue === 'function' ? props.counterValue(model.value) : typeof props.counterValue === 'number' ? props.counterValue : (model.value ?? '').toString().length;
  11594. });
  11595. const max = vue.computed(() => {
  11596. if (attrs.maxlength) return attrs.maxlength;
  11597. if (!props.counter || typeof props.counter !== 'number' && typeof props.counter !== 'string') return undefined;
  11598. return props.counter;
  11599. });
  11600. const isPlainOrUnderlined = vue.computed(() => ['plain', 'underlined'].includes(props.variant));
  11601. function onIntersect(isIntersecting, entries) {
  11602. if (!props.autofocus || !isIntersecting) return;
  11603. entries[0].target?.focus?.();
  11604. }
  11605. const vInputRef = vue.ref();
  11606. const vFieldRef = vue.ref();
  11607. const inputRef = vue.ref();
  11608. const isActive = vue.computed(() => activeTypes.includes(props.type) || props.persistentPlaceholder || isFocused.value || props.active);
  11609. function onFocus() {
  11610. if (inputRef.value !== document.activeElement) {
  11611. inputRef.value?.focus();
  11612. }
  11613. if (!isFocused.value) focus();
  11614. }
  11615. function onControlMousedown(e) {
  11616. emit('mousedown:control', e);
  11617. if (e.target === inputRef.value) return;
  11618. onFocus();
  11619. e.preventDefault();
  11620. }
  11621. function onControlClick(e) {
  11622. onFocus();
  11623. emit('click:control', e);
  11624. }
  11625. function onClear(e) {
  11626. e.stopPropagation();
  11627. onFocus();
  11628. vue.nextTick(() => {
  11629. model.value = null;
  11630. callEvent(props['onClick:clear'], e);
  11631. });
  11632. }
  11633. function onInput(e) {
  11634. const el = e.target;
  11635. model.value = el.value;
  11636. if (props.modelModifiers?.trim && ['text', 'search', 'password', 'tel', 'url'].includes(props.type)) {
  11637. const caretPosition = [el.selectionStart, el.selectionEnd];
  11638. vue.nextTick(() => {
  11639. el.selectionStart = caretPosition[0];
  11640. el.selectionEnd = caretPosition[1];
  11641. });
  11642. }
  11643. }
  11644. useRender(() => {
  11645. const hasCounter = !!(slots.counter || props.counter !== false && props.counter != null);
  11646. const hasDetails = !!(hasCounter || slots.details);
  11647. const [rootAttrs, inputAttrs] = filterInputAttrs(attrs);
  11648. const {
  11649. modelValue: _,
  11650. ...inputProps
  11651. } = VInput.filterProps(props);
  11652. const fieldProps = filterFieldProps(props);
  11653. return vue.createVNode(VInput, vue.mergeProps({
  11654. "ref": vInputRef,
  11655. "modelValue": model.value,
  11656. "onUpdate:modelValue": $event => model.value = $event,
  11657. "class": ['v-text-field', {
  11658. 'v-text-field--prefixed': props.prefix,
  11659. 'v-text-field--suffixed': props.suffix,
  11660. 'v-input--plain-underlined': isPlainOrUnderlined.value
  11661. }, props.class],
  11662. "style": props.style
  11663. }, rootAttrs, inputProps, {
  11664. "centerAffix": !isPlainOrUnderlined.value,
  11665. "focused": isFocused.value
  11666. }), {
  11667. ...slots,
  11668. default: _ref2 => {
  11669. let {
  11670. id,
  11671. isDisabled,
  11672. isDirty,
  11673. isReadonly,
  11674. isValid
  11675. } = _ref2;
  11676. return vue.createVNode(VField, vue.mergeProps({
  11677. "ref": vFieldRef,
  11678. "onMousedown": onControlMousedown,
  11679. "onClick": onControlClick,
  11680. "onClick:clear": onClear,
  11681. "onClick:prependInner": props['onClick:prependInner'],
  11682. "onClick:appendInner": props['onClick:appendInner'],
  11683. "role": props.role
  11684. }, fieldProps, {
  11685. "id": id.value,
  11686. "active": isActive.value || isDirty.value,
  11687. "dirty": isDirty.value || props.dirty,
  11688. "disabled": isDisabled.value,
  11689. "focused": isFocused.value,
  11690. "error": isValid.value === false
  11691. }), {
  11692. ...slots,
  11693. default: _ref3 => {
  11694. let {
  11695. props: {
  11696. class: fieldClass,
  11697. ...slotProps
  11698. }
  11699. } = _ref3;
  11700. const inputNode = vue.withDirectives(vue.createVNode("input", vue.mergeProps({
  11701. "ref": inputRef,
  11702. "value": model.value,
  11703. "onInput": onInput,
  11704. "autofocus": props.autofocus,
  11705. "readonly": isReadonly.value,
  11706. "disabled": isDisabled.value,
  11707. "name": props.name,
  11708. "placeholder": props.placeholder,
  11709. "size": 1,
  11710. "type": props.type,
  11711. "onFocus": onFocus,
  11712. "onBlur": blur
  11713. }, slotProps, inputAttrs), null), [[vue.resolveDirective("intersect"), {
  11714. handler: onIntersect
  11715. }, null, {
  11716. once: true
  11717. }]]);
  11718. return vue.createVNode(vue.Fragment, null, [props.prefix && vue.createVNode("span", {
  11719. "class": "v-text-field__prefix"
  11720. }, [vue.createVNode("span", {
  11721. "class": "v-text-field__prefix__text"
  11722. }, [props.prefix])]), slots.default ? vue.createVNode("div", {
  11723. "class": fieldClass,
  11724. "data-no-activator": ""
  11725. }, [slots.default(), inputNode]) : vue.cloneVNode(inputNode, {
  11726. class: fieldClass
  11727. }), props.suffix && vue.createVNode("span", {
  11728. "class": "v-text-field__suffix"
  11729. }, [vue.createVNode("span", {
  11730. "class": "v-text-field__suffix__text"
  11731. }, [props.suffix])])]);
  11732. }
  11733. });
  11734. },
  11735. details: hasDetails ? slotProps => vue.createVNode(vue.Fragment, null, [slots.details?.(slotProps), hasCounter && vue.createVNode(vue.Fragment, null, [vue.createVNode("span", null, null), vue.createVNode(VCounter, {
  11736. "active": props.persistentCounter || isFocused.value,
  11737. "value": counterValue.value,
  11738. "max": max.value,
  11739. "disabled": props.disabled
  11740. }, slots.counter)])]) : undefined
  11741. });
  11742. });
  11743. return forwardRefs({}, vInputRef, vFieldRef, inputRef);
  11744. }
  11745. });
  11746. // Types
  11747. const makeVVirtualScrollItemProps = propsFactory({
  11748. renderless: Boolean,
  11749. ...makeComponentProps()
  11750. }, 'VVirtualScrollItem');
  11751. const VVirtualScrollItem = genericComponent()({
  11752. name: 'VVirtualScrollItem',
  11753. inheritAttrs: false,
  11754. props: makeVVirtualScrollItemProps(),
  11755. emits: {
  11756. 'update:height': height => true
  11757. },
  11758. setup(props, _ref) {
  11759. let {
  11760. attrs,
  11761. emit,
  11762. slots
  11763. } = _ref;
  11764. const {
  11765. resizeRef,
  11766. contentRect
  11767. } = useResizeObserver(undefined, 'border');
  11768. vue.watch(() => contentRect.value?.height, height => {
  11769. if (height != null) emit('update:height', height);
  11770. });
  11771. useRender(() => props.renderless ? vue.createVNode(vue.Fragment, null, [slots.default?.({
  11772. itemRef: resizeRef
  11773. })]) : vue.createVNode("div", vue.mergeProps({
  11774. "ref": resizeRef,
  11775. "class": ['v-virtual-scroll__item', props.class],
  11776. "style": props.style
  11777. }, attrs), [slots.default?.()]));
  11778. }
  11779. });
  11780. // Composables
  11781. // Types
  11782. const UP = -1;
  11783. const DOWN = 1;
  11784. /** Determines how large each batch of items should be */
  11785. const BUFFER_PX = 100;
  11786. const makeVirtualProps = propsFactory({
  11787. itemHeight: {
  11788. type: [Number, String],
  11789. default: null
  11790. },
  11791. height: [Number, String]
  11792. }, 'virtual');
  11793. function useVirtual(props, items) {
  11794. const display = useDisplay();
  11795. const itemHeight = vue.shallowRef(0);
  11796. vue.watchEffect(() => {
  11797. itemHeight.value = parseFloat(props.itemHeight || 0);
  11798. });
  11799. const first = vue.shallowRef(0);
  11800. const last = vue.shallowRef(Math.ceil(
  11801. // Assume 16px items filling the entire screen height if
  11802. // not provided. This is probably incorrect but it minimises
  11803. // the chance of ending up with empty space at the bottom.
  11804. // The default value is set here to avoid poisoning getSize()
  11805. (parseInt(props.height) || display.height.value) / (itemHeight.value || 16)) || 1);
  11806. const paddingTop = vue.shallowRef(0);
  11807. const paddingBottom = vue.shallowRef(0);
  11808. /** The scrollable element */
  11809. const containerRef = vue.ref();
  11810. /** An element marking the top of the scrollable area,
  11811. * used to add an offset if there's padding or other elements above the virtual list */
  11812. const markerRef = vue.ref();
  11813. /** markerRef's offsetTop, lazily evaluated */
  11814. let markerOffset = 0;
  11815. const {
  11816. resizeRef,
  11817. contentRect
  11818. } = useResizeObserver();
  11819. vue.watchEffect(() => {
  11820. resizeRef.value = containerRef.value;
  11821. });
  11822. const viewportHeight = vue.computed(() => {
  11823. return containerRef.value === document.documentElement ? display.height.value : contentRect.value?.height || parseInt(props.height) || 0;
  11824. });
  11825. /** All static elements have been rendered and we have an assumed item height */
  11826. const hasInitialRender = vue.computed(() => {
  11827. return !!(containerRef.value && markerRef.value && viewportHeight.value && itemHeight.value);
  11828. });
  11829. let sizes = Array.from({
  11830. length: items.value.length
  11831. });
  11832. let offsets = Array.from({
  11833. length: items.value.length
  11834. });
  11835. const updateTime = vue.shallowRef(0);
  11836. let targetScrollIndex = -1;
  11837. function getSize(index) {
  11838. return sizes[index] || itemHeight.value;
  11839. }
  11840. const updateOffsets = debounce(() => {
  11841. const start = performance.now();
  11842. offsets[0] = 0;
  11843. const length = items.value.length;
  11844. for (let i = 1; i <= length - 1; i++) {
  11845. offsets[i] = (offsets[i - 1] || 0) + getSize(i - 1);
  11846. }
  11847. updateTime.value = Math.max(updateTime.value, performance.now() - start);
  11848. }, updateTime);
  11849. const unwatch = vue.watch(hasInitialRender, v => {
  11850. if (!v) return;
  11851. // First render is complete, update offsets and visible
  11852. // items in case our assumed item height was incorrect
  11853. unwatch();
  11854. markerOffset = markerRef.value.offsetTop;
  11855. updateOffsets.immediate();
  11856. calculateVisibleItems();
  11857. if (!~targetScrollIndex) return;
  11858. vue.nextTick(() => {
  11859. IN_BROWSER && window.requestAnimationFrame(() => {
  11860. scrollToIndex(targetScrollIndex);
  11861. targetScrollIndex = -1;
  11862. });
  11863. });
  11864. });
  11865. vue.onScopeDispose(() => {
  11866. updateOffsets.clear();
  11867. });
  11868. function handleItemResize(index, height) {
  11869. const prevHeight = sizes[index];
  11870. const prevMinHeight = itemHeight.value;
  11871. itemHeight.value = prevMinHeight ? Math.min(itemHeight.value, height) : height;
  11872. if (prevHeight !== height || prevMinHeight !== itemHeight.value) {
  11873. sizes[index] = height;
  11874. updateOffsets();
  11875. }
  11876. }
  11877. function calculateOffset(index) {
  11878. index = clamp(index, 0, items.value.length - 1);
  11879. return offsets[index] || 0;
  11880. }
  11881. function calculateIndex(scrollTop) {
  11882. return binaryClosest(offsets, scrollTop);
  11883. }
  11884. let lastScrollTop = 0;
  11885. let scrollVelocity = 0;
  11886. let lastScrollTime = 0;
  11887. vue.watch(viewportHeight, (val, oldVal) => {
  11888. if (oldVal) {
  11889. calculateVisibleItems();
  11890. if (val < oldVal) {
  11891. requestAnimationFrame(() => {
  11892. scrollVelocity = 0;
  11893. calculateVisibleItems();
  11894. });
  11895. }
  11896. }
  11897. });
  11898. let scrollTimeout = -1;
  11899. function handleScroll() {
  11900. if (!containerRef.value || !markerRef.value) return;
  11901. const scrollTop = containerRef.value.scrollTop;
  11902. const scrollTime = performance.now();
  11903. const scrollDeltaT = scrollTime - lastScrollTime;
  11904. if (scrollDeltaT > 500) {
  11905. scrollVelocity = Math.sign(scrollTop - lastScrollTop);
  11906. // Not super important, only update at the
  11907. // start of a scroll sequence to avoid reflows
  11908. markerOffset = markerRef.value.offsetTop;
  11909. } else {
  11910. scrollVelocity = scrollTop - lastScrollTop;
  11911. }
  11912. lastScrollTop = scrollTop;
  11913. lastScrollTime = scrollTime;
  11914. window.clearTimeout(scrollTimeout);
  11915. scrollTimeout = window.setTimeout(handleScrollend, 500);
  11916. calculateVisibleItems();
  11917. }
  11918. function handleScrollend() {
  11919. if (!containerRef.value || !markerRef.value) return;
  11920. scrollVelocity = 0;
  11921. lastScrollTime = 0;
  11922. window.clearTimeout(scrollTimeout);
  11923. calculateVisibleItems();
  11924. }
  11925. let raf = -1;
  11926. function calculateVisibleItems() {
  11927. cancelAnimationFrame(raf);
  11928. raf = requestAnimationFrame(_calculateVisibleItems);
  11929. }
  11930. function _calculateVisibleItems() {
  11931. if (!containerRef.value || !viewportHeight.value) return;
  11932. const scrollTop = lastScrollTop - markerOffset;
  11933. const direction = Math.sign(scrollVelocity);
  11934. const startPx = Math.max(0, scrollTop - BUFFER_PX);
  11935. const start = clamp(calculateIndex(startPx), 0, items.value.length);
  11936. const endPx = scrollTop + viewportHeight.value + BUFFER_PX;
  11937. const end = clamp(calculateIndex(endPx) + 1, start + 1, items.value.length);
  11938. if (
  11939. // Only update the side we're scrolling towards,
  11940. // the other side will be updated incidentally
  11941. (direction !== UP || start < first.value) && (direction !== DOWN || end > last.value)) {
  11942. const topOverflow = calculateOffset(first.value) - calculateOffset(start);
  11943. const bottomOverflow = calculateOffset(end) - calculateOffset(last.value);
  11944. const bufferOverflow = Math.max(topOverflow, bottomOverflow);
  11945. if (bufferOverflow > BUFFER_PX) {
  11946. first.value = start;
  11947. last.value = end;
  11948. } else {
  11949. // Only update the side that's reached its limit if there's still buffer left
  11950. if (start <= 0) first.value = start;
  11951. if (end >= items.value.length) last.value = end;
  11952. }
  11953. }
  11954. paddingTop.value = calculateOffset(first.value);
  11955. paddingBottom.value = calculateOffset(items.value.length) - calculateOffset(last.value);
  11956. }
  11957. function scrollToIndex(index) {
  11958. const offset = calculateOffset(index);
  11959. if (!containerRef.value || index && !offset) {
  11960. targetScrollIndex = index;
  11961. } else {
  11962. containerRef.value.scrollTop = offset;
  11963. }
  11964. }
  11965. const computedItems = vue.computed(() => {
  11966. return items.value.slice(first.value, last.value).map((item, index) => ({
  11967. raw: item,
  11968. index: index + first.value,
  11969. key: isObject(item) && 'value' in item ? item.value : index + first.value
  11970. }));
  11971. });
  11972. vue.watch(items, () => {
  11973. sizes = Array.from({
  11974. length: items.value.length
  11975. });
  11976. offsets = Array.from({
  11977. length: items.value.length
  11978. });
  11979. updateOffsets.immediate();
  11980. calculateVisibleItems();
  11981. }, {
  11982. deep: true
  11983. });
  11984. return {
  11985. calculateVisibleItems,
  11986. containerRef,
  11987. markerRef,
  11988. computedItems,
  11989. paddingTop,
  11990. paddingBottom,
  11991. scrollToIndex,
  11992. handleScroll,
  11993. handleScrollend,
  11994. handleItemResize
  11995. };
  11996. }
  11997. // https://gist.github.com/robertleeplummerjr/1cc657191d34ecd0a324
  11998. function binaryClosest(arr, val) {
  11999. let high = arr.length - 1;
  12000. let low = 0;
  12001. let mid = 0;
  12002. let item = null;
  12003. let target = -1;
  12004. if (arr[high] < val) {
  12005. return high;
  12006. }
  12007. while (low <= high) {
  12008. mid = low + high >> 1;
  12009. item = arr[mid];
  12010. if (item > val) {
  12011. high = mid - 1;
  12012. } else if (item < val) {
  12013. target = mid;
  12014. low = mid + 1;
  12015. } else if (item === val) {
  12016. return mid;
  12017. } else {
  12018. return low;
  12019. }
  12020. }
  12021. return target;
  12022. }
  12023. // Types
  12024. const makeVVirtualScrollProps = propsFactory({
  12025. items: {
  12026. type: Array,
  12027. default: () => []
  12028. },
  12029. renderless: Boolean,
  12030. ...makeVirtualProps(),
  12031. ...makeComponentProps(),
  12032. ...makeDimensionProps()
  12033. }, 'VVirtualScroll');
  12034. const VVirtualScroll = genericComponent()({
  12035. name: 'VVirtualScroll',
  12036. props: makeVVirtualScrollProps(),
  12037. setup(props, _ref) {
  12038. let {
  12039. slots
  12040. } = _ref;
  12041. const vm = getCurrentInstance('VVirtualScroll');
  12042. const {
  12043. dimensionStyles
  12044. } = useDimension(props);
  12045. const {
  12046. calculateVisibleItems,
  12047. containerRef,
  12048. markerRef,
  12049. handleScroll,
  12050. handleScrollend,
  12051. handleItemResize,
  12052. scrollToIndex,
  12053. paddingTop,
  12054. paddingBottom,
  12055. computedItems
  12056. } = useVirtual(props, vue.toRef(props, 'items'));
  12057. useToggleScope(() => props.renderless, () => {
  12058. function handleListeners() {
  12059. let add = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : false;
  12060. const method = add ? 'addEventListener' : 'removeEventListener';
  12061. if (containerRef.value === document.documentElement) {
  12062. document[method]('scroll', handleScroll, {
  12063. passive: true
  12064. });
  12065. document[method]('scrollend', handleScrollend);
  12066. } else {
  12067. containerRef.value?.[method]('scroll', handleScroll, {
  12068. passive: true
  12069. });
  12070. containerRef.value?.[method]('scrollend', handleScrollend);
  12071. }
  12072. }
  12073. vue.onMounted(() => {
  12074. containerRef.value = getScrollParent(vm.vnode.el, true);
  12075. handleListeners(true);
  12076. });
  12077. vue.onScopeDispose(handleListeners);
  12078. });
  12079. useRender(() => {
  12080. const children = computedItems.value.map(item => vue.createVNode(VVirtualScrollItem, {
  12081. "key": item.key,
  12082. "renderless": props.renderless,
  12083. "onUpdate:height": height => handleItemResize(item.index, height)
  12084. }, {
  12085. default: slotProps => slots.default?.({
  12086. item: item.raw,
  12087. index: item.index,
  12088. ...slotProps
  12089. })
  12090. }));
  12091. return props.renderless ? vue.createVNode(vue.Fragment, null, [vue.createVNode("div", {
  12092. "ref": markerRef,
  12093. "class": "v-virtual-scroll__spacer",
  12094. "style": {
  12095. paddingTop: convertToUnit(paddingTop.value)
  12096. }
  12097. }, null), children, vue.createVNode("div", {
  12098. "class": "v-virtual-scroll__spacer",
  12099. "style": {
  12100. paddingBottom: convertToUnit(paddingBottom.value)
  12101. }
  12102. }, null)]) : vue.createVNode("div", {
  12103. "ref": containerRef,
  12104. "class": ['v-virtual-scroll', props.class],
  12105. "onScrollPassive": handleScroll,
  12106. "onScrollend": handleScrollend,
  12107. "style": [dimensionStyles.value, props.style]
  12108. }, [vue.createVNode("div", {
  12109. "ref": markerRef,
  12110. "class": "v-virtual-scroll__container",
  12111. "style": {
  12112. paddingTop: convertToUnit(paddingTop.value),
  12113. paddingBottom: convertToUnit(paddingBottom.value)
  12114. }
  12115. }, [children])]);
  12116. });
  12117. return {
  12118. calculateVisibleItems,
  12119. scrollToIndex
  12120. };
  12121. }
  12122. });
  12123. // Utilities
  12124. // Types
  12125. function useScrolling(listRef, textFieldRef) {
  12126. const isScrolling = vue.shallowRef(false);
  12127. let scrollTimeout;
  12128. function onListScroll(e) {
  12129. cancelAnimationFrame(scrollTimeout);
  12130. isScrolling.value = true;
  12131. scrollTimeout = requestAnimationFrame(() => {
  12132. scrollTimeout = requestAnimationFrame(() => {
  12133. isScrolling.value = false;
  12134. });
  12135. });
  12136. }
  12137. async function finishScrolling() {
  12138. await new Promise(resolve => requestAnimationFrame(resolve));
  12139. await new Promise(resolve => requestAnimationFrame(resolve));
  12140. await new Promise(resolve => requestAnimationFrame(resolve));
  12141. await new Promise(resolve => {
  12142. if (isScrolling.value) {
  12143. const stop = vue.watch(isScrolling, () => {
  12144. stop();
  12145. resolve();
  12146. });
  12147. } else resolve();
  12148. });
  12149. }
  12150. async function onListKeydown(e) {
  12151. if (e.key === 'Tab') {
  12152. textFieldRef.value?.focus();
  12153. }
  12154. if (!['PageDown', 'PageUp', 'Home', 'End'].includes(e.key)) return;
  12155. const el = listRef.value?.$el;
  12156. if (!el) return;
  12157. if (e.key === 'Home' || e.key === 'End') {
  12158. el.scrollTo({
  12159. top: e.key === 'Home' ? 0 : el.scrollHeight,
  12160. behavior: 'smooth'
  12161. });
  12162. }
  12163. await finishScrolling();
  12164. const children = el.querySelectorAll(':scope > :not(.v-virtual-scroll__spacer)');
  12165. if (e.key === 'PageDown' || e.key === 'Home') {
  12166. const top = el.getBoundingClientRect().top;
  12167. for (const child of children) {
  12168. if (child.getBoundingClientRect().top >= top) {
  12169. child.focus();
  12170. break;
  12171. }
  12172. }
  12173. } else {
  12174. const bottom = el.getBoundingClientRect().bottom;
  12175. for (const child of [...children].reverse()) {
  12176. if (child.getBoundingClientRect().bottom <= bottom) {
  12177. child.focus();
  12178. break;
  12179. }
  12180. }
  12181. }
  12182. }
  12183. return {
  12184. onScrollPassive: onListScroll,
  12185. onKeydown: onListKeydown
  12186. }; // typescript doesn't know about vue's event merging
  12187. }
  12188. // Types
  12189. const makeSelectProps = propsFactory({
  12190. chips: Boolean,
  12191. closableChips: Boolean,
  12192. closeText: {
  12193. type: String,
  12194. default: '$vuetify.close'
  12195. },
  12196. openText: {
  12197. type: String,
  12198. default: '$vuetify.open'
  12199. },
  12200. eager: Boolean,
  12201. hideNoData: Boolean,
  12202. hideSelected: Boolean,
  12203. listProps: {
  12204. type: Object
  12205. },
  12206. menu: Boolean,
  12207. menuIcon: {
  12208. type: IconValue,
  12209. default: '$dropdown'
  12210. },
  12211. menuProps: {
  12212. type: Object
  12213. },
  12214. multiple: Boolean,
  12215. noDataText: {
  12216. type: String,
  12217. default: '$vuetify.noDataText'
  12218. },
  12219. openOnClear: Boolean,
  12220. itemColor: String,
  12221. ...makeItemsProps({
  12222. itemChildren: false
  12223. })
  12224. }, 'Select');
  12225. const makeVSelectProps = propsFactory({
  12226. ...makeSelectProps(),
  12227. ...omit(makeVTextFieldProps({
  12228. modelValue: null,
  12229. role: 'combobox'
  12230. }), ['validationValue', 'dirty', 'appendInnerIcon']),
  12231. ...makeTransitionProps({
  12232. transition: {
  12233. component: VDialogTransition
  12234. }
  12235. })
  12236. }, 'VSelect');
  12237. const VSelect = genericComponent()({
  12238. name: 'VSelect',
  12239. props: makeVSelectProps(),
  12240. emits: {
  12241. 'update:focused': focused => true,
  12242. 'update:modelValue': value => true,
  12243. 'update:menu': ue => true
  12244. },
  12245. setup(props, _ref) {
  12246. let {
  12247. slots
  12248. } = _ref;
  12249. const {
  12250. t
  12251. } = useLocale();
  12252. const vTextFieldRef = vue.ref();
  12253. const vMenuRef = vue.ref();
  12254. const vVirtualScrollRef = vue.ref();
  12255. const _menu = useProxiedModel(props, 'menu');
  12256. const menu = vue.computed({
  12257. get: () => _menu.value,
  12258. set: v => {
  12259. if (_menu.value && !v && vMenuRef.value?.ΨopenChildren.size) return;
  12260. _menu.value = v;
  12261. }
  12262. });
  12263. const {
  12264. items,
  12265. transformIn,
  12266. transformOut
  12267. } = useItems(props);
  12268. const model = useProxiedModel(props, 'modelValue', [], v => transformIn(v === null ? [null] : wrapInArray(v)), v => {
  12269. const transformed = transformOut(v);
  12270. return props.multiple ? transformed : transformed[0] ?? null;
  12271. });
  12272. const counterValue = vue.computed(() => {
  12273. return typeof props.counterValue === 'function' ? props.counterValue(model.value) : typeof props.counterValue === 'number' ? props.counterValue : model.value.length;
  12274. });
  12275. const form = useForm(props);
  12276. const selectedValues = vue.computed(() => model.value.map(selection => selection.value));
  12277. const isFocused = vue.shallowRef(false);
  12278. const label = vue.computed(() => menu.value ? props.closeText : props.openText);
  12279. let keyboardLookupPrefix = '';
  12280. let keyboardLookupLastTime;
  12281. const displayItems = vue.computed(() => {
  12282. if (props.hideSelected) {
  12283. return items.value.filter(item => !model.value.some(s => props.valueComparator(s, item)));
  12284. }
  12285. return items.value;
  12286. });
  12287. const menuDisabled = vue.computed(() => props.hideNoData && !displayItems.value.length || form.isReadonly.value || form.isDisabled.value);
  12288. const computedMenuProps = vue.computed(() => {
  12289. return {
  12290. ...props.menuProps,
  12291. activatorProps: {
  12292. ...(props.menuProps?.activatorProps || {}),
  12293. 'aria-haspopup': 'listbox' // Set aria-haspopup to 'listbox'
  12294. }
  12295. };
  12296. });
  12297. const listRef = vue.ref();
  12298. const listEvents = useScrolling(listRef, vTextFieldRef);
  12299. function onClear(e) {
  12300. if (props.openOnClear) {
  12301. menu.value = true;
  12302. }
  12303. }
  12304. function onMousedownControl() {
  12305. if (menuDisabled.value) return;
  12306. menu.value = !menu.value;
  12307. }
  12308. function onListKeydown(e) {
  12309. if (checkPrintable(e)) {
  12310. onKeydown(e);
  12311. }
  12312. }
  12313. function onKeydown(e) {
  12314. if (!e.key || form.isReadonly.value) return;
  12315. if (['Enter', ' ', 'ArrowDown', 'ArrowUp', 'Home', 'End'].includes(e.key)) {
  12316. e.preventDefault();
  12317. }
  12318. if (['Enter', 'ArrowDown', ' '].includes(e.key)) {
  12319. menu.value = true;
  12320. }
  12321. if (['Escape', 'Tab'].includes(e.key)) {
  12322. menu.value = false;
  12323. }
  12324. if (e.key === 'Home') {
  12325. listRef.value?.focus('first');
  12326. } else if (e.key === 'End') {
  12327. listRef.value?.focus('last');
  12328. }
  12329. // html select hotkeys
  12330. const KEYBOARD_LOOKUP_THRESHOLD = 1000; // milliseconds
  12331. if (props.multiple || !checkPrintable(e)) return;
  12332. const now = performance.now();
  12333. if (now - keyboardLookupLastTime > KEYBOARD_LOOKUP_THRESHOLD) {
  12334. keyboardLookupPrefix = '';
  12335. }
  12336. keyboardLookupPrefix += e.key.toLowerCase();
  12337. keyboardLookupLastTime = now;
  12338. const item = items.value.find(item => item.title.toLowerCase().startsWith(keyboardLookupPrefix));
  12339. if (item !== undefined) {
  12340. model.value = [item];
  12341. const index = displayItems.value.indexOf(item);
  12342. IN_BROWSER && window.requestAnimationFrame(() => {
  12343. index >= 0 && vVirtualScrollRef.value?.scrollToIndex(index);
  12344. });
  12345. }
  12346. }
  12347. /** @param set - null means toggle */
  12348. function select(item) {
  12349. let set = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : true;
  12350. if (item.props.disabled) return;
  12351. if (props.multiple) {
  12352. const index = model.value.findIndex(selection => props.valueComparator(selection.value, item.value));
  12353. const add = set == null ? !~index : set;
  12354. if (~index) {
  12355. const value = add ? [...model.value, item] : [...model.value];
  12356. value.splice(index, 1);
  12357. model.value = value;
  12358. } else if (add) {
  12359. model.value = [...model.value, item];
  12360. }
  12361. } else {
  12362. const add = set !== false;
  12363. model.value = add ? [item] : [];
  12364. vue.nextTick(() => {
  12365. menu.value = false;
  12366. });
  12367. }
  12368. }
  12369. function onBlur(e) {
  12370. if (!listRef.value?.$el.contains(e.relatedTarget)) {
  12371. menu.value = false;
  12372. }
  12373. }
  12374. function onAfterEnter() {
  12375. if (props.eager) {
  12376. vVirtualScrollRef.value?.calculateVisibleItems();
  12377. }
  12378. }
  12379. function onAfterLeave() {
  12380. if (isFocused.value) {
  12381. vTextFieldRef.value?.focus();
  12382. }
  12383. }
  12384. function onFocusin(e) {
  12385. isFocused.value = true;
  12386. }
  12387. function onModelUpdate(v) {
  12388. if (v == null) model.value = [];else if (matchesSelector(vTextFieldRef.value, ':autofill') || matchesSelector(vTextFieldRef.value, ':-webkit-autofill')) {
  12389. const item = items.value.find(item => item.title === v);
  12390. if (item) {
  12391. select(item);
  12392. }
  12393. } else if (vTextFieldRef.value) {
  12394. vTextFieldRef.value.value = '';
  12395. }
  12396. }
  12397. vue.watch(menu, () => {
  12398. if (!props.hideSelected && menu.value && model.value.length) {
  12399. const index = displayItems.value.findIndex(item => model.value.some(s => props.valueComparator(s.value, item.value)));
  12400. IN_BROWSER && window.requestAnimationFrame(() => {
  12401. index >= 0 && vVirtualScrollRef.value?.scrollToIndex(index);
  12402. });
  12403. }
  12404. });
  12405. vue.watch(() => props.items, (newVal, oldVal) => {
  12406. if (menu.value) return;
  12407. if (isFocused.value && !oldVal.length && newVal.length) {
  12408. menu.value = true;
  12409. }
  12410. });
  12411. useRender(() => {
  12412. const hasChips = !!(props.chips || slots.chip);
  12413. const hasList = !!(!props.hideNoData || displayItems.value.length || slots['prepend-item'] || slots['append-item'] || slots['no-data']);
  12414. const isDirty = model.value.length > 0;
  12415. const textFieldProps = VTextField.filterProps(props);
  12416. const placeholder = isDirty || !isFocused.value && props.label && !props.persistentPlaceholder ? undefined : props.placeholder;
  12417. return vue.createVNode(VTextField, vue.mergeProps({
  12418. "ref": vTextFieldRef
  12419. }, textFieldProps, {
  12420. "modelValue": model.value.map(v => v.props.value).join(', '),
  12421. "onUpdate:modelValue": onModelUpdate,
  12422. "focused": isFocused.value,
  12423. "onUpdate:focused": $event => isFocused.value = $event,
  12424. "validationValue": model.externalValue,
  12425. "counterValue": counterValue.value,
  12426. "dirty": isDirty,
  12427. "class": ['v-select', {
  12428. 'v-select--active-menu': menu.value,
  12429. 'v-select--chips': !!props.chips,
  12430. [`v-select--${props.multiple ? 'multiple' : 'single'}`]: true,
  12431. 'v-select--selected': model.value.length,
  12432. 'v-select--selection-slot': !!slots.selection
  12433. }, props.class],
  12434. "style": props.style,
  12435. "inputmode": "none",
  12436. "placeholder": placeholder,
  12437. "onClick:clear": onClear,
  12438. "onMousedown:control": onMousedownControl,
  12439. "onBlur": onBlur,
  12440. "onKeydown": onKeydown,
  12441. "aria-label": t(label.value),
  12442. "title": t(label.value)
  12443. }), {
  12444. ...slots,
  12445. default: () => vue.createVNode(vue.Fragment, null, [vue.createVNode(VMenu, vue.mergeProps({
  12446. "ref": vMenuRef,
  12447. "modelValue": menu.value,
  12448. "onUpdate:modelValue": $event => menu.value = $event,
  12449. "activator": "parent",
  12450. "contentClass": "v-select__content",
  12451. "disabled": menuDisabled.value,
  12452. "eager": props.eager,
  12453. "maxHeight": 310,
  12454. "openOnClick": false,
  12455. "closeOnContentClick": false,
  12456. "transition": props.transition,
  12457. "onAfterEnter": onAfterEnter,
  12458. "onAfterLeave": onAfterLeave
  12459. }, computedMenuProps.value), {
  12460. default: () => [hasList && vue.createVNode(VList, vue.mergeProps({
  12461. "ref": listRef,
  12462. "selected": selectedValues.value,
  12463. "selectStrategy": props.multiple ? 'independent' : 'single-independent',
  12464. "onMousedown": e => e.preventDefault(),
  12465. "onKeydown": onListKeydown,
  12466. "onFocusin": onFocusin,
  12467. "tabindex": "-1",
  12468. "aria-live": "polite",
  12469. "color": props.itemColor ?? props.color
  12470. }, listEvents, props.listProps), {
  12471. default: () => [slots['prepend-item']?.(), !displayItems.value.length && !props.hideNoData && (slots['no-data']?.() ?? vue.createVNode(VListItem, {
  12472. "key": "no-data",
  12473. "title": t(props.noDataText)
  12474. }, null)), vue.createVNode(VVirtualScroll, {
  12475. "ref": vVirtualScrollRef,
  12476. "renderless": true,
  12477. "items": displayItems.value
  12478. }, {
  12479. default: _ref2 => {
  12480. let {
  12481. item,
  12482. index,
  12483. itemRef
  12484. } = _ref2;
  12485. const itemProps = vue.mergeProps(item.props, {
  12486. ref: itemRef,
  12487. key: item.value,
  12488. onClick: () => select(item, null)
  12489. });
  12490. return slots.item?.({
  12491. item,
  12492. index,
  12493. props: itemProps
  12494. }) ?? vue.createVNode(VListItem, vue.mergeProps(itemProps, {
  12495. "role": "option"
  12496. }), {
  12497. prepend: _ref3 => {
  12498. let {
  12499. isSelected
  12500. } = _ref3;
  12501. return vue.createVNode(vue.Fragment, null, [props.multiple && !props.hideSelected ? vue.createVNode(VCheckboxBtn, {
  12502. "key": item.value,
  12503. "modelValue": isSelected,
  12504. "ripple": false,
  12505. "tabindex": "-1"
  12506. }, null) : undefined, item.props.prependAvatar && vue.createVNode(VAvatar, {
  12507. "image": item.props.prependAvatar
  12508. }, null), item.props.prependIcon && vue.createVNode(VIcon, {
  12509. "icon": item.props.prependIcon
  12510. }, null)]);
  12511. }
  12512. });
  12513. }
  12514. }), slots['append-item']?.()]
  12515. })]
  12516. }), model.value.map((item, index) => {
  12517. function onChipClose(e) {
  12518. e.stopPropagation();
  12519. e.preventDefault();
  12520. select(item, false);
  12521. }
  12522. const slotProps = {
  12523. 'onClick:close': onChipClose,
  12524. onKeydown(e) {
  12525. if (e.key !== 'Enter' && e.key !== ' ') return;
  12526. e.preventDefault();
  12527. e.stopPropagation();
  12528. onChipClose(e);
  12529. },
  12530. onMousedown(e) {
  12531. e.preventDefault();
  12532. e.stopPropagation();
  12533. },
  12534. modelValue: true,
  12535. 'onUpdate:modelValue': undefined
  12536. };
  12537. const hasSlot = hasChips ? !!slots.chip : !!slots.selection;
  12538. const slotContent = hasSlot ? ensureValidVNode(hasChips ? slots.chip({
  12539. item,
  12540. index,
  12541. props: slotProps
  12542. }) : slots.selection({
  12543. item,
  12544. index
  12545. })) : undefined;
  12546. if (hasSlot && !slotContent) return undefined;
  12547. return vue.createVNode("div", {
  12548. "key": item.value,
  12549. "class": "v-select__selection"
  12550. }, [hasChips ? !slots.chip ? vue.createVNode(VChip, vue.mergeProps({
  12551. "key": "chip",
  12552. "closable": props.closableChips,
  12553. "size": "small",
  12554. "text": item.title,
  12555. "disabled": item.props.disabled
  12556. }, slotProps), null) : vue.createVNode(VDefaultsProvider, {
  12557. "key": "chip-defaults",
  12558. "defaults": {
  12559. VChip: {
  12560. closable: props.closableChips,
  12561. size: 'small',
  12562. text: item.title
  12563. }
  12564. }
  12565. }, {
  12566. default: () => [slotContent]
  12567. }) : slotContent ?? vue.createVNode("span", {
  12568. "class": "v-select__selection-text"
  12569. }, [item.title, props.multiple && index < model.value.length - 1 && vue.createVNode("span", {
  12570. "class": "v-select__selection-comma"
  12571. }, [vue.createTextVNode(",")])])]);
  12572. })]),
  12573. 'append-inner': function () {
  12574. for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) {
  12575. args[_key] = arguments[_key];
  12576. }
  12577. return vue.createVNode(vue.Fragment, null, [slots['append-inner']?.(...args), props.menuIcon ? vue.createVNode(VIcon, {
  12578. "class": "v-select__menu-icon",
  12579. "icon": props.menuIcon
  12580. }, null) : undefined]);
  12581. }
  12582. });
  12583. });
  12584. return forwardRefs({
  12585. isFocused,
  12586. menu,
  12587. select
  12588. }, vTextFieldRef);
  12589. }
  12590. });
  12591. /* eslint-disable max-statements */
  12592. /* eslint-disable no-labels */
  12593. // Types
  12594. /**
  12595. * - match without highlight
  12596. * - single match (index), length already known
  12597. * - single match (start, end)
  12598. * - multiple matches (start, end), probably shouldn't overlap
  12599. */
  12600. // Composables
  12601. const defaultFilter = (value, query, item) => {
  12602. if (value == null || query == null) return -1;
  12603. return value.toString().toLocaleLowerCase().indexOf(query.toString().toLocaleLowerCase());
  12604. };
  12605. const makeFilterProps = propsFactory({
  12606. customFilter: Function,
  12607. customKeyFilter: Object,
  12608. filterKeys: [Array, String],
  12609. filterMode: {
  12610. type: String,
  12611. default: 'intersection'
  12612. },
  12613. noFilter: Boolean
  12614. }, 'filter');
  12615. function filterItems(items, query, options) {
  12616. const array = [];
  12617. // always ensure we fall back to a functioning filter
  12618. const filter = options?.default ?? defaultFilter;
  12619. const keys = options?.filterKeys ? wrapInArray(options.filterKeys) : false;
  12620. const customFiltersLength = Object.keys(options?.customKeyFilter ?? {}).length;
  12621. if (!items?.length) return array;
  12622. loop: for (let i = 0; i < items.length; i++) {
  12623. const [item, transformed = item] = wrapInArray(items[i]);
  12624. const customMatches = {};
  12625. const defaultMatches = {};
  12626. let match = -1;
  12627. if ((query || customFiltersLength > 0) && !options?.noFilter) {
  12628. if (typeof item === 'object') {
  12629. const filterKeys = keys || Object.keys(transformed);
  12630. for (const key of filterKeys) {
  12631. const value = getPropertyFromItem(transformed, key);
  12632. const keyFilter = options?.customKeyFilter?.[key];
  12633. match = keyFilter ? keyFilter(value, query, item) : filter(value, query, item);
  12634. if (match !== -1 && match !== false) {
  12635. if (keyFilter) customMatches[key] = match;else defaultMatches[key] = match;
  12636. } else if (options?.filterMode === 'every') {
  12637. continue loop;
  12638. }
  12639. }
  12640. } else {
  12641. match = filter(item, query, item);
  12642. if (match !== -1 && match !== false) {
  12643. defaultMatches.title = match;
  12644. }
  12645. }
  12646. const defaultMatchesLength = Object.keys(defaultMatches).length;
  12647. const customMatchesLength = Object.keys(customMatches).length;
  12648. if (!defaultMatchesLength && !customMatchesLength) continue;
  12649. if (options?.filterMode === 'union' && customMatchesLength !== customFiltersLength && !defaultMatchesLength) continue;
  12650. if (options?.filterMode === 'intersection' && (customMatchesLength !== customFiltersLength || !defaultMatchesLength)) continue;
  12651. }
  12652. array.push({
  12653. index: i,
  12654. matches: {
  12655. ...defaultMatches,
  12656. ...customMatches
  12657. }
  12658. });
  12659. }
  12660. return array;
  12661. }
  12662. function useFilter(props, items, query, options) {
  12663. const filteredItems = vue.ref([]);
  12664. const filteredMatches = vue.ref(new Map());
  12665. const transformedItems = vue.computed(() => options?.transform ? vue.unref(items).map(item => [item, options.transform(item)]) : vue.unref(items));
  12666. vue.watchEffect(() => {
  12667. const _query = typeof query === 'function' ? query() : vue.unref(query);
  12668. const strQuery = typeof _query !== 'string' && typeof _query !== 'number' ? '' : String(_query);
  12669. const results = filterItems(transformedItems.value, strQuery, {
  12670. customKeyFilter: {
  12671. ...props.customKeyFilter,
  12672. ...vue.unref(options?.customKeyFilter)
  12673. },
  12674. default: props.customFilter,
  12675. filterKeys: props.filterKeys,
  12676. filterMode: props.filterMode,
  12677. noFilter: props.noFilter
  12678. });
  12679. const originalItems = vue.unref(items);
  12680. const _filteredItems = [];
  12681. const _filteredMatches = new Map();
  12682. results.forEach(_ref => {
  12683. let {
  12684. index,
  12685. matches
  12686. } = _ref;
  12687. const item = originalItems[index];
  12688. _filteredItems.push(item);
  12689. _filteredMatches.set(item.value, matches);
  12690. });
  12691. filteredItems.value = _filteredItems;
  12692. filteredMatches.value = _filteredMatches;
  12693. });
  12694. function getMatches(item) {
  12695. return filteredMatches.value.get(item.value);
  12696. }
  12697. return {
  12698. filteredItems,
  12699. filteredMatches,
  12700. getMatches
  12701. };
  12702. }
  12703. // Types
  12704. function highlightResult$1(text, matches, length) {
  12705. if (matches == null) return text;
  12706. if (Array.isArray(matches)) throw new Error('Multiple matches is not implemented');
  12707. return typeof matches === 'number' && ~matches ? vue.createVNode(vue.Fragment, null, [vue.createVNode("span", {
  12708. "class": "v-autocomplete__unmask"
  12709. }, [text.substr(0, matches)]), vue.createVNode("span", {
  12710. "class": "v-autocomplete__mask"
  12711. }, [text.substr(matches, length)]), vue.createVNode("span", {
  12712. "class": "v-autocomplete__unmask"
  12713. }, [text.substr(matches + length)])]) : text;
  12714. }
  12715. const makeVAutocompleteProps = propsFactory({
  12716. autoSelectFirst: {
  12717. type: [Boolean, String]
  12718. },
  12719. clearOnSelect: Boolean,
  12720. search: String,
  12721. ...makeFilterProps({
  12722. filterKeys: ['title']
  12723. }),
  12724. ...makeSelectProps(),
  12725. ...omit(makeVTextFieldProps({
  12726. modelValue: null,
  12727. role: 'combobox'
  12728. }), ['validationValue', 'dirty', 'appendInnerIcon']),
  12729. ...makeTransitionProps({
  12730. transition: false
  12731. })
  12732. }, 'VAutocomplete');
  12733. const VAutocomplete = genericComponent()({
  12734. name: 'VAutocomplete',
  12735. props: makeVAutocompleteProps(),
  12736. emits: {
  12737. 'update:focused': focused => true,
  12738. 'update:search': value => true,
  12739. 'update:modelValue': value => true,
  12740. 'update:menu': value => true
  12741. },
  12742. setup(props, _ref) {
  12743. let {
  12744. slots
  12745. } = _ref;
  12746. const {
  12747. t
  12748. } = useLocale();
  12749. const vTextFieldRef = vue.ref();
  12750. const isFocused = vue.shallowRef(false);
  12751. const isPristine = vue.shallowRef(true);
  12752. const listHasFocus = vue.shallowRef(false);
  12753. const vMenuRef = vue.ref();
  12754. const vVirtualScrollRef = vue.ref();
  12755. const _menu = useProxiedModel(props, 'menu');
  12756. const menu = vue.computed({
  12757. get: () => _menu.value,
  12758. set: v => {
  12759. if (_menu.value && !v && vMenuRef.value?.ΨopenChildren.size) return;
  12760. _menu.value = v;
  12761. }
  12762. });
  12763. const selectionIndex = vue.shallowRef(-1);
  12764. const color = vue.computed(() => vTextFieldRef.value?.color);
  12765. const label = vue.computed(() => menu.value ? props.closeText : props.openText);
  12766. const {
  12767. items,
  12768. transformIn,
  12769. transformOut
  12770. } = useItems(props);
  12771. const {
  12772. textColorClasses,
  12773. textColorStyles
  12774. } = useTextColor(color);
  12775. const search = useProxiedModel(props, 'search', '');
  12776. const model = useProxiedModel(props, 'modelValue', [], v => transformIn(v === null ? [null] : wrapInArray(v)), v => {
  12777. const transformed = transformOut(v);
  12778. return props.multiple ? transformed : transformed[0] ?? null;
  12779. });
  12780. const counterValue = vue.computed(() => {
  12781. return typeof props.counterValue === 'function' ? props.counterValue(model.value) : typeof props.counterValue === 'number' ? props.counterValue : model.value.length;
  12782. });
  12783. const form = useForm(props);
  12784. const {
  12785. filteredItems,
  12786. getMatches
  12787. } = useFilter(props, items, () => isPristine.value ? '' : search.value);
  12788. const displayItems = vue.computed(() => {
  12789. if (props.hideSelected) {
  12790. return filteredItems.value.filter(filteredItem => !model.value.some(s => s.value === filteredItem.value));
  12791. }
  12792. return filteredItems.value;
  12793. });
  12794. const hasChips = vue.computed(() => !!(props.chips || slots.chip));
  12795. const hasSelectionSlot = vue.computed(() => hasChips.value || !!slots.selection);
  12796. const selectedValues = vue.computed(() => model.value.map(selection => selection.props.value));
  12797. const highlightFirst = vue.computed(() => {
  12798. const selectFirst = props.autoSelectFirst === true || props.autoSelectFirst === 'exact' && search.value === displayItems.value[0]?.title;
  12799. return selectFirst && displayItems.value.length > 0 && !isPristine.value && !listHasFocus.value;
  12800. });
  12801. const menuDisabled = vue.computed(() => props.hideNoData && !displayItems.value.length || form.isReadonly.value || form.isDisabled.value);
  12802. const listRef = vue.ref();
  12803. const listEvents = useScrolling(listRef, vTextFieldRef);
  12804. function onClear(e) {
  12805. if (props.openOnClear) {
  12806. menu.value = true;
  12807. }
  12808. search.value = '';
  12809. }
  12810. function onMousedownControl() {
  12811. if (menuDisabled.value) return;
  12812. menu.value = true;
  12813. }
  12814. function onMousedownMenuIcon(e) {
  12815. if (menuDisabled.value) return;
  12816. if (isFocused.value) {
  12817. e.preventDefault();
  12818. e.stopPropagation();
  12819. }
  12820. menu.value = !menu.value;
  12821. }
  12822. function onListKeydown(e) {
  12823. if (checkPrintable(e)) {
  12824. vTextFieldRef.value?.focus();
  12825. }
  12826. }
  12827. function onKeydown(e) {
  12828. if (form.isReadonly.value) return;
  12829. const selectionStart = vTextFieldRef.value.selectionStart;
  12830. const length = model.value.length;
  12831. if (selectionIndex.value > -1 || ['Enter', 'ArrowDown', 'ArrowUp'].includes(e.key)) {
  12832. e.preventDefault();
  12833. }
  12834. if (['Enter', 'ArrowDown'].includes(e.key)) {
  12835. menu.value = true;
  12836. }
  12837. if (['Escape'].includes(e.key)) {
  12838. menu.value = false;
  12839. }
  12840. if (highlightFirst.value && ['Enter', 'Tab'].includes(e.key) && !model.value.some(_ref2 => {
  12841. let {
  12842. value
  12843. } = _ref2;
  12844. return value === displayItems.value[0].value;
  12845. })) {
  12846. select(displayItems.value[0]);
  12847. }
  12848. if (e.key === 'ArrowDown' && highlightFirst.value) {
  12849. listRef.value?.focus('next');
  12850. }
  12851. if (['Backspace', 'Delete'].includes(e.key)) {
  12852. if (!props.multiple && hasSelectionSlot.value && model.value.length > 0 && !search.value) return select(model.value[0], false);
  12853. if (~selectionIndex.value) {
  12854. const originalSelectionIndex = selectionIndex.value;
  12855. select(model.value[selectionIndex.value], false);
  12856. selectionIndex.value = originalSelectionIndex >= length - 1 ? length - 2 : originalSelectionIndex;
  12857. } else if (e.key === 'Backspace' && !search.value) {
  12858. selectionIndex.value = length - 1;
  12859. }
  12860. }
  12861. if (!props.multiple) return;
  12862. if (e.key === 'ArrowLeft') {
  12863. if (selectionIndex.value < 0 && selectionStart > 0) return;
  12864. const prev = selectionIndex.value > -1 ? selectionIndex.value - 1 : length - 1;
  12865. if (model.value[prev]) {
  12866. selectionIndex.value = prev;
  12867. } else {
  12868. selectionIndex.value = -1;
  12869. vTextFieldRef.value.setSelectionRange(search.value?.length, search.value?.length);
  12870. }
  12871. }
  12872. if (e.key === 'ArrowRight') {
  12873. if (selectionIndex.value < 0) return;
  12874. const next = selectionIndex.value + 1;
  12875. if (model.value[next]) {
  12876. selectionIndex.value = next;
  12877. } else {
  12878. selectionIndex.value = -1;
  12879. vTextFieldRef.value.setSelectionRange(0, 0);
  12880. }
  12881. }
  12882. }
  12883. function onChange(e) {
  12884. if (matchesSelector(vTextFieldRef.value, ':autofill') || matchesSelector(vTextFieldRef.value, ':-webkit-autofill')) {
  12885. const item = items.value.find(item => item.title === e.target.value);
  12886. if (item) {
  12887. select(item);
  12888. }
  12889. }
  12890. }
  12891. function onAfterEnter() {
  12892. if (props.eager) {
  12893. vVirtualScrollRef.value?.calculateVisibleItems();
  12894. }
  12895. }
  12896. function onAfterLeave() {
  12897. if (isFocused.value) {
  12898. isPristine.value = true;
  12899. vTextFieldRef.value?.focus();
  12900. }
  12901. }
  12902. function onFocusin(e) {
  12903. isFocused.value = true;
  12904. setTimeout(() => {
  12905. listHasFocus.value = true;
  12906. });
  12907. }
  12908. function onFocusout(e) {
  12909. listHasFocus.value = false;
  12910. }
  12911. function onUpdateModelValue(v) {
  12912. if (v == null || v === '' && !props.multiple && !hasSelectionSlot.value) model.value = [];
  12913. }
  12914. const isSelecting = vue.shallowRef(false);
  12915. /** @param set - null means toggle */
  12916. function select(item) {
  12917. let set = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : true;
  12918. if (!item || item.props.disabled) return;
  12919. if (props.multiple) {
  12920. const index = model.value.findIndex(selection => props.valueComparator(selection.value, item.value));
  12921. const add = set == null ? !~index : set;
  12922. if (~index) {
  12923. const value = add ? [...model.value, item] : [...model.value];
  12924. value.splice(index, 1);
  12925. model.value = value;
  12926. } else if (add) {
  12927. model.value = [...model.value, item];
  12928. }
  12929. if (props.clearOnSelect) {
  12930. search.value = '';
  12931. }
  12932. } else {
  12933. const add = set !== false;
  12934. model.value = add ? [item] : [];
  12935. search.value = add && !hasSelectionSlot.value ? item.title : '';
  12936. // watch for search watcher to trigger
  12937. vue.nextTick(() => {
  12938. menu.value = false;
  12939. isPristine.value = true;
  12940. });
  12941. }
  12942. }
  12943. vue.watch(isFocused, (val, oldVal) => {
  12944. if (val === oldVal) return;
  12945. if (val) {
  12946. isSelecting.value = true;
  12947. search.value = props.multiple || hasSelectionSlot.value ? '' : String(model.value.at(-1)?.props.title ?? '');
  12948. isPristine.value = true;
  12949. vue.nextTick(() => isSelecting.value = false);
  12950. } else {
  12951. if (!props.multiple && search.value == null) model.value = [];
  12952. menu.value = false;
  12953. if (!model.value.some(_ref3 => {
  12954. let {
  12955. title
  12956. } = _ref3;
  12957. return title === search.value;
  12958. })) search.value = '';
  12959. selectionIndex.value = -1;
  12960. }
  12961. });
  12962. vue.watch(search, val => {
  12963. if (!isFocused.value || isSelecting.value) return;
  12964. if (val) menu.value = true;
  12965. isPristine.value = !val;
  12966. });
  12967. vue.watch(menu, () => {
  12968. if (!props.hideSelected && menu.value && model.value.length) {
  12969. const index = displayItems.value.findIndex(item => model.value.some(s => item.value === s.value));
  12970. IN_BROWSER && window.requestAnimationFrame(() => {
  12971. index >= 0 && vVirtualScrollRef.value?.scrollToIndex(index);
  12972. });
  12973. }
  12974. });
  12975. vue.watch(() => props.items, (newVal, oldVal) => {
  12976. if (menu.value) return;
  12977. if (isFocused.value && !oldVal.length && newVal.length) {
  12978. menu.value = true;
  12979. }
  12980. });
  12981. useRender(() => {
  12982. const hasList = !!(!props.hideNoData || displayItems.value.length || slots['prepend-item'] || slots['append-item'] || slots['no-data']);
  12983. const isDirty = model.value.length > 0;
  12984. const textFieldProps = VTextField.filterProps(props);
  12985. return vue.createVNode(VTextField, vue.mergeProps({
  12986. "ref": vTextFieldRef
  12987. }, textFieldProps, {
  12988. "modelValue": search.value,
  12989. "onUpdate:modelValue": [$event => search.value = $event, onUpdateModelValue],
  12990. "focused": isFocused.value,
  12991. "onUpdate:focused": $event => isFocused.value = $event,
  12992. "validationValue": model.externalValue,
  12993. "counterValue": counterValue.value,
  12994. "dirty": isDirty,
  12995. "onChange": onChange,
  12996. "class": ['v-autocomplete', `v-autocomplete--${props.multiple ? 'multiple' : 'single'}`, {
  12997. 'v-autocomplete--active-menu': menu.value,
  12998. 'v-autocomplete--chips': !!props.chips,
  12999. 'v-autocomplete--selection-slot': !!hasSelectionSlot.value,
  13000. 'v-autocomplete--selecting-index': selectionIndex.value > -1
  13001. }, props.class],
  13002. "style": props.style,
  13003. "readonly": form.isReadonly.value,
  13004. "placeholder": isDirty ? undefined : props.placeholder,
  13005. "onClick:clear": onClear,
  13006. "onMousedown:control": onMousedownControl,
  13007. "onKeydown": onKeydown
  13008. }), {
  13009. ...slots,
  13010. default: () => vue.createVNode(vue.Fragment, null, [vue.createVNode(VMenu, vue.mergeProps({
  13011. "ref": vMenuRef,
  13012. "modelValue": menu.value,
  13013. "onUpdate:modelValue": $event => menu.value = $event,
  13014. "activator": "parent",
  13015. "contentClass": "v-autocomplete__content",
  13016. "disabled": menuDisabled.value,
  13017. "eager": props.eager,
  13018. "maxHeight": 310,
  13019. "openOnClick": false,
  13020. "closeOnContentClick": false,
  13021. "transition": props.transition,
  13022. "onAfterEnter": onAfterEnter,
  13023. "onAfterLeave": onAfterLeave
  13024. }, props.menuProps), {
  13025. default: () => [hasList && vue.createVNode(VList, vue.mergeProps({
  13026. "ref": listRef,
  13027. "selected": selectedValues.value,
  13028. "selectStrategy": props.multiple ? 'independent' : 'single-independent',
  13029. "onMousedown": e => e.preventDefault(),
  13030. "onKeydown": onListKeydown,
  13031. "onFocusin": onFocusin,
  13032. "onFocusout": onFocusout,
  13033. "tabindex": "-1",
  13034. "aria-live": "polite",
  13035. "color": props.itemColor ?? props.color
  13036. }, listEvents, props.listProps), {
  13037. default: () => [slots['prepend-item']?.(), !displayItems.value.length && !props.hideNoData && (slots['no-data']?.() ?? vue.createVNode(VListItem, {
  13038. "key": "no-data",
  13039. "title": t(props.noDataText)
  13040. }, null)), vue.createVNode(VVirtualScroll, {
  13041. "ref": vVirtualScrollRef,
  13042. "renderless": true,
  13043. "items": displayItems.value
  13044. }, {
  13045. default: _ref4 => {
  13046. let {
  13047. item,
  13048. index,
  13049. itemRef
  13050. } = _ref4;
  13051. const itemProps = vue.mergeProps(item.props, {
  13052. ref: itemRef,
  13053. key: item.value,
  13054. active: highlightFirst.value && index === 0 ? true : undefined,
  13055. onClick: () => select(item, null)
  13056. });
  13057. return slots.item?.({
  13058. item,
  13059. index,
  13060. props: itemProps
  13061. }) ?? vue.createVNode(VListItem, vue.mergeProps(itemProps, {
  13062. "role": "option"
  13063. }), {
  13064. prepend: _ref5 => {
  13065. let {
  13066. isSelected
  13067. } = _ref5;
  13068. return vue.createVNode(vue.Fragment, null, [props.multiple && !props.hideSelected ? vue.createVNode(VCheckboxBtn, {
  13069. "key": item.value,
  13070. "modelValue": isSelected,
  13071. "ripple": false,
  13072. "tabindex": "-1"
  13073. }, null) : undefined, item.props.prependAvatar && vue.createVNode(VAvatar, {
  13074. "image": item.props.prependAvatar
  13075. }, null), item.props.prependIcon && vue.createVNode(VIcon, {
  13076. "icon": item.props.prependIcon
  13077. }, null)]);
  13078. },
  13079. title: () => {
  13080. return isPristine.value ? item.title : highlightResult$1(item.title, getMatches(item)?.title, search.value?.length ?? 0);
  13081. }
  13082. });
  13083. }
  13084. }), slots['append-item']?.()]
  13085. })]
  13086. }), model.value.map((item, index) => {
  13087. function onChipClose(e) {
  13088. e.stopPropagation();
  13089. e.preventDefault();
  13090. select(item, false);
  13091. }
  13092. const slotProps = {
  13093. 'onClick:close': onChipClose,
  13094. onKeydown(e) {
  13095. if (e.key !== 'Enter' && e.key !== ' ') return;
  13096. e.preventDefault();
  13097. e.stopPropagation();
  13098. onChipClose(e);
  13099. },
  13100. onMousedown(e) {
  13101. e.preventDefault();
  13102. e.stopPropagation();
  13103. },
  13104. modelValue: true,
  13105. 'onUpdate:modelValue': undefined
  13106. };
  13107. const hasSlot = hasChips.value ? !!slots.chip : !!slots.selection;
  13108. const slotContent = hasSlot ? ensureValidVNode(hasChips.value ? slots.chip({
  13109. item,
  13110. index,
  13111. props: slotProps
  13112. }) : slots.selection({
  13113. item,
  13114. index
  13115. })) : undefined;
  13116. if (hasSlot && !slotContent) return undefined;
  13117. return vue.createVNode("div", {
  13118. "key": item.value,
  13119. "class": ['v-autocomplete__selection', index === selectionIndex.value && ['v-autocomplete__selection--selected', textColorClasses.value]],
  13120. "style": index === selectionIndex.value ? textColorStyles.value : {}
  13121. }, [hasChips.value ? !slots.chip ? vue.createVNode(VChip, vue.mergeProps({
  13122. "key": "chip",
  13123. "closable": props.closableChips,
  13124. "size": "small",
  13125. "text": item.title,
  13126. "disabled": item.props.disabled
  13127. }, slotProps), null) : vue.createVNode(VDefaultsProvider, {
  13128. "key": "chip-defaults",
  13129. "defaults": {
  13130. VChip: {
  13131. closable: props.closableChips,
  13132. size: 'small',
  13133. text: item.title
  13134. }
  13135. }
  13136. }, {
  13137. default: () => [slotContent]
  13138. }) : slotContent ?? vue.createVNode("span", {
  13139. "class": "v-autocomplete__selection-text"
  13140. }, [item.title, props.multiple && index < model.value.length - 1 && vue.createVNode("span", {
  13141. "class": "v-autocomplete__selection-comma"
  13142. }, [vue.createTextVNode(",")])])]);
  13143. })]),
  13144. 'append-inner': function () {
  13145. for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) {
  13146. args[_key] = arguments[_key];
  13147. }
  13148. return vue.createVNode(vue.Fragment, null, [slots['append-inner']?.(...args), props.menuIcon ? vue.createVNode(VIcon, {
  13149. "class": "v-autocomplete__menu-icon",
  13150. "icon": props.menuIcon,
  13151. "onMousedown": onMousedownMenuIcon,
  13152. "onClick": noop,
  13153. "aria-label": t(label.value),
  13154. "title": t(label.value),
  13155. "tabindex": "-1"
  13156. }, null) : undefined]);
  13157. }
  13158. });
  13159. });
  13160. return forwardRefs({
  13161. isFocused,
  13162. isPristine,
  13163. menu,
  13164. search,
  13165. filteredItems,
  13166. select
  13167. }, vTextFieldRef);
  13168. }
  13169. });
  13170. const makeVBadgeProps = propsFactory({
  13171. bordered: Boolean,
  13172. color: String,
  13173. content: [Number, String],
  13174. dot: Boolean,
  13175. floating: Boolean,
  13176. icon: IconValue,
  13177. inline: Boolean,
  13178. label: {
  13179. type: String,
  13180. default: '$vuetify.badge'
  13181. },
  13182. max: [Number, String],
  13183. modelValue: {
  13184. type: Boolean,
  13185. default: true
  13186. },
  13187. offsetX: [Number, String],
  13188. offsetY: [Number, String],
  13189. textColor: String,
  13190. ...makeComponentProps(),
  13191. ...makeLocationProps({
  13192. location: 'top end'
  13193. }),
  13194. ...makeRoundedProps(),
  13195. ...makeTagProps(),
  13196. ...makeThemeProps(),
  13197. ...makeTransitionProps({
  13198. transition: 'scale-rotate-transition'
  13199. })
  13200. }, 'VBadge');
  13201. const VBadge = genericComponent()({
  13202. name: 'VBadge',
  13203. inheritAttrs: false,
  13204. props: makeVBadgeProps(),
  13205. setup(props, ctx) {
  13206. const {
  13207. backgroundColorClasses,
  13208. backgroundColorStyles
  13209. } = useBackgroundColor(vue.toRef(props, 'color'));
  13210. const {
  13211. roundedClasses
  13212. } = useRounded(props);
  13213. const {
  13214. t
  13215. } = useLocale();
  13216. const {
  13217. textColorClasses,
  13218. textColorStyles
  13219. } = useTextColor(vue.toRef(props, 'textColor'));
  13220. const {
  13221. themeClasses
  13222. } = useTheme();
  13223. const {
  13224. locationStyles
  13225. } = useLocation(props, true, side => {
  13226. const base = props.floating ? props.dot ? 2 : 4 : props.dot ? 8 : 12;
  13227. return base + (['top', 'bottom'].includes(side) ? +(props.offsetY ?? 0) : ['left', 'right'].includes(side) ? +(props.offsetX ?? 0) : 0);
  13228. });
  13229. useRender(() => {
  13230. const value = Number(props.content);
  13231. const content = !props.max || isNaN(value) ? props.content : value <= +props.max ? value : `${props.max}+`;
  13232. const [badgeAttrs, attrs] = pickWithRest(ctx.attrs, ['aria-atomic', 'aria-label', 'aria-live', 'role', 'title']);
  13233. return vue.createVNode(props.tag, vue.mergeProps({
  13234. "class": ['v-badge', {
  13235. 'v-badge--bordered': props.bordered,
  13236. 'v-badge--dot': props.dot,
  13237. 'v-badge--floating': props.floating,
  13238. 'v-badge--inline': props.inline
  13239. }, props.class]
  13240. }, attrs, {
  13241. "style": props.style
  13242. }), {
  13243. default: () => [vue.createVNode("div", {
  13244. "class": "v-badge__wrapper"
  13245. }, [ctx.slots.default?.(), vue.createVNode(MaybeTransition, {
  13246. "transition": props.transition
  13247. }, {
  13248. default: () => [vue.withDirectives(vue.createVNode("span", vue.mergeProps({
  13249. "class": ['v-badge__badge', themeClasses.value, backgroundColorClasses.value, roundedClasses.value, textColorClasses.value],
  13250. "style": [backgroundColorStyles.value, textColorStyles.value, props.inline ? {} : locationStyles.value],
  13251. "aria-atomic": "true",
  13252. "aria-label": t(props.label, value),
  13253. "aria-live": "polite",
  13254. "role": "status"
  13255. }, badgeAttrs), [props.dot ? undefined : ctx.slots.badge ? ctx.slots.badge?.() : props.icon ? vue.createVNode(VIcon, {
  13256. "icon": props.icon
  13257. }, null) : content]), [[vue.vShow, props.modelValue]])]
  13258. })])]
  13259. });
  13260. });
  13261. return {};
  13262. }
  13263. });
  13264. const makeVBannerActionsProps = propsFactory({
  13265. color: String,
  13266. density: String,
  13267. ...makeComponentProps()
  13268. }, 'VBannerActions');
  13269. const VBannerActions = genericComponent()({
  13270. name: 'VBannerActions',
  13271. props: makeVBannerActionsProps(),
  13272. setup(props, _ref) {
  13273. let {
  13274. slots
  13275. } = _ref;
  13276. provideDefaults({
  13277. VBtn: {
  13278. color: props.color,
  13279. density: props.density,
  13280. slim: true,
  13281. variant: 'text'
  13282. }
  13283. });
  13284. useRender(() => vue.createVNode("div", {
  13285. "class": ['v-banner-actions', props.class],
  13286. "style": props.style
  13287. }, [slots.default?.()]));
  13288. return {};
  13289. }
  13290. });
  13291. // Utilities
  13292. const VBannerText = createSimpleFunctional('v-banner-text');
  13293. // Types
  13294. const makeVBannerProps = propsFactory({
  13295. avatar: String,
  13296. bgColor: String,
  13297. color: String,
  13298. icon: IconValue,
  13299. lines: String,
  13300. stacked: Boolean,
  13301. sticky: Boolean,
  13302. text: String,
  13303. ...makeBorderProps(),
  13304. ...makeComponentProps(),
  13305. ...makeDensityProps(),
  13306. ...makeDimensionProps(),
  13307. ...makeDisplayProps({
  13308. mobile: null
  13309. }),
  13310. ...makeElevationProps(),
  13311. ...makeLocationProps(),
  13312. ...makePositionProps(),
  13313. ...makeRoundedProps(),
  13314. ...makeTagProps(),
  13315. ...makeThemeProps()
  13316. }, 'VBanner');
  13317. const VBanner = genericComponent()({
  13318. name: 'VBanner',
  13319. props: makeVBannerProps(),
  13320. setup(props, _ref) {
  13321. let {
  13322. slots
  13323. } = _ref;
  13324. const {
  13325. backgroundColorClasses,
  13326. backgroundColorStyles
  13327. } = useBackgroundColor(props, 'bgColor');
  13328. const {
  13329. borderClasses
  13330. } = useBorder(props);
  13331. const {
  13332. densityClasses
  13333. } = useDensity(props);
  13334. const {
  13335. displayClasses,
  13336. mobile
  13337. } = useDisplay(props);
  13338. const {
  13339. dimensionStyles
  13340. } = useDimension(props);
  13341. const {
  13342. elevationClasses
  13343. } = useElevation(props);
  13344. const {
  13345. locationStyles
  13346. } = useLocation(props);
  13347. const {
  13348. positionClasses
  13349. } = usePosition(props);
  13350. const {
  13351. roundedClasses
  13352. } = useRounded(props);
  13353. const {
  13354. themeClasses
  13355. } = provideTheme(props);
  13356. const color = vue.toRef(props, 'color');
  13357. const density = vue.toRef(props, 'density');
  13358. provideDefaults({
  13359. VBannerActions: {
  13360. color,
  13361. density
  13362. }
  13363. });
  13364. useRender(() => {
  13365. const hasText = !!(props.text || slots.text);
  13366. const hasPrependMedia = !!(props.avatar || props.icon);
  13367. const hasPrepend = !!(hasPrependMedia || slots.prepend);
  13368. return vue.createVNode(props.tag, {
  13369. "class": ['v-banner', {
  13370. 'v-banner--stacked': props.stacked || mobile.value,
  13371. 'v-banner--sticky': props.sticky,
  13372. [`v-banner--${props.lines}-line`]: !!props.lines
  13373. }, themeClasses.value, backgroundColorClasses.value, borderClasses.value, densityClasses.value, displayClasses.value, elevationClasses.value, positionClasses.value, roundedClasses.value, props.class],
  13374. "style": [backgroundColorStyles.value, dimensionStyles.value, locationStyles.value, props.style],
  13375. "role": "banner"
  13376. }, {
  13377. default: () => [hasPrepend && vue.createVNode("div", {
  13378. "key": "prepend",
  13379. "class": "v-banner__prepend"
  13380. }, [!slots.prepend ? vue.createVNode(VAvatar, {
  13381. "key": "prepend-avatar",
  13382. "color": color.value,
  13383. "density": density.value,
  13384. "icon": props.icon,
  13385. "image": props.avatar
  13386. }, null) : vue.createVNode(VDefaultsProvider, {
  13387. "key": "prepend-defaults",
  13388. "disabled": !hasPrependMedia,
  13389. "defaults": {
  13390. VAvatar: {
  13391. color: color.value,
  13392. density: density.value,
  13393. icon: props.icon,
  13394. image: props.avatar
  13395. }
  13396. }
  13397. }, slots.prepend)]), vue.createVNode("div", {
  13398. "class": "v-banner__content"
  13399. }, [hasText && vue.createVNode(VBannerText, {
  13400. "key": "text"
  13401. }, {
  13402. default: () => [slots.text?.() ?? props.text]
  13403. }), slots.default?.()]), slots.actions && vue.createVNode(VBannerActions, {
  13404. "key": "actions"
  13405. }, slots.actions)]
  13406. });
  13407. });
  13408. }
  13409. });
  13410. // Types
  13411. const makeVBottomNavigationProps = propsFactory({
  13412. baseColor: String,
  13413. bgColor: String,
  13414. color: String,
  13415. grow: Boolean,
  13416. mode: {
  13417. type: String,
  13418. validator: v => !v || ['horizontal', 'shift'].includes(v)
  13419. },
  13420. height: {
  13421. type: [Number, String],
  13422. default: 56
  13423. },
  13424. active: {
  13425. type: Boolean,
  13426. default: true
  13427. },
  13428. ...makeBorderProps(),
  13429. ...makeComponentProps(),
  13430. ...makeDensityProps(),
  13431. ...makeElevationProps(),
  13432. ...makeRoundedProps(),
  13433. ...makeLayoutItemProps({
  13434. name: 'bottom-navigation'
  13435. }),
  13436. ...makeTagProps({
  13437. tag: 'header'
  13438. }),
  13439. ...makeGroupProps({
  13440. selectedClass: 'v-btn--selected'
  13441. }),
  13442. ...makeThemeProps()
  13443. }, 'VBottomNavigation');
  13444. const VBottomNavigation = genericComponent()({
  13445. name: 'VBottomNavigation',
  13446. props: makeVBottomNavigationProps(),
  13447. emits: {
  13448. 'update:active': value => true,
  13449. 'update:modelValue': value => true
  13450. },
  13451. setup(props, _ref) {
  13452. let {
  13453. slots
  13454. } = _ref;
  13455. const {
  13456. themeClasses
  13457. } = useTheme();
  13458. const {
  13459. borderClasses
  13460. } = useBorder(props);
  13461. const {
  13462. backgroundColorClasses,
  13463. backgroundColorStyles
  13464. } = useBackgroundColor(vue.toRef(props, 'bgColor'));
  13465. const {
  13466. densityClasses
  13467. } = useDensity(props);
  13468. const {
  13469. elevationClasses
  13470. } = useElevation(props);
  13471. const {
  13472. roundedClasses
  13473. } = useRounded(props);
  13474. const {
  13475. ssrBootStyles
  13476. } = useSsrBoot();
  13477. const height = vue.computed(() => Number(props.height) - (props.density === 'comfortable' ? 8 : 0) - (props.density === 'compact' ? 16 : 0));
  13478. const isActive = useProxiedModel(props, 'active', props.active);
  13479. const {
  13480. layoutItemStyles
  13481. } = useLayoutItem({
  13482. id: props.name,
  13483. order: vue.computed(() => parseInt(props.order, 10)),
  13484. position: vue.computed(() => 'bottom'),
  13485. layoutSize: vue.computed(() => isActive.value ? height.value : 0),
  13486. elementSize: height,
  13487. active: isActive,
  13488. absolute: vue.toRef(props, 'absolute')
  13489. });
  13490. useGroup(props, VBtnToggleSymbol);
  13491. provideDefaults({
  13492. VBtn: {
  13493. baseColor: vue.toRef(props, 'baseColor'),
  13494. color: vue.toRef(props, 'color'),
  13495. density: vue.toRef(props, 'density'),
  13496. stacked: vue.computed(() => props.mode !== 'horizontal'),
  13497. variant: 'text'
  13498. }
  13499. }, {
  13500. scoped: true
  13501. });
  13502. useRender(() => {
  13503. return vue.createVNode(props.tag, {
  13504. "class": ['v-bottom-navigation', {
  13505. 'v-bottom-navigation--active': isActive.value,
  13506. 'v-bottom-navigation--grow': props.grow,
  13507. 'v-bottom-navigation--shift': props.mode === 'shift'
  13508. }, themeClasses.value, backgroundColorClasses.value, borderClasses.value, densityClasses.value, elevationClasses.value, roundedClasses.value, props.class],
  13509. "style": [backgroundColorStyles.value, layoutItemStyles.value, {
  13510. height: convertToUnit(height.value)
  13511. }, ssrBootStyles.value, props.style]
  13512. }, {
  13513. default: () => [slots.default && vue.createVNode("div", {
  13514. "class": "v-bottom-navigation__content"
  13515. }, [slots.default()])]
  13516. });
  13517. });
  13518. return {};
  13519. }
  13520. });
  13521. // Types
  13522. const makeVDialogProps = propsFactory({
  13523. fullscreen: Boolean,
  13524. retainFocus: {
  13525. type: Boolean,
  13526. default: true
  13527. },
  13528. scrollable: Boolean,
  13529. ...makeVOverlayProps({
  13530. origin: 'center center',
  13531. scrollStrategy: 'block',
  13532. transition: {
  13533. component: VDialogTransition
  13534. },
  13535. zIndex: 2400
  13536. })
  13537. }, 'VDialog');
  13538. const VDialog = genericComponent()({
  13539. name: 'VDialog',
  13540. props: makeVDialogProps(),
  13541. emits: {
  13542. 'update:modelValue': value => true,
  13543. afterEnter: () => true,
  13544. afterLeave: () => true
  13545. },
  13546. setup(props, _ref) {
  13547. let {
  13548. emit,
  13549. slots
  13550. } = _ref;
  13551. const isActive = useProxiedModel(props, 'modelValue');
  13552. const {
  13553. scopeId
  13554. } = useScopeId();
  13555. const overlay = vue.ref();
  13556. function onFocusin(e) {
  13557. const before = e.relatedTarget;
  13558. const after = e.target;
  13559. if (before !== after && overlay.value?.contentEl &&
  13560. // We're the topmost dialog
  13561. overlay.value?.globalTop &&
  13562. // It isn't the document or the dialog body
  13563. ![document, overlay.value.contentEl].includes(after) &&
  13564. // It isn't inside the dialog body
  13565. !overlay.value.contentEl.contains(after)) {
  13566. const focusable = focusableChildren(overlay.value.contentEl);
  13567. if (!focusable.length) return;
  13568. const firstElement = focusable[0];
  13569. const lastElement = focusable[focusable.length - 1];
  13570. if (before === firstElement) {
  13571. lastElement.focus();
  13572. } else {
  13573. firstElement.focus();
  13574. }
  13575. }
  13576. }
  13577. vue.onBeforeUnmount(() => {
  13578. document.removeEventListener('focusin', onFocusin);
  13579. });
  13580. if (IN_BROWSER) {
  13581. vue.watch(() => isActive.value && props.retainFocus, val => {
  13582. val ? document.addEventListener('focusin', onFocusin) : document.removeEventListener('focusin', onFocusin);
  13583. }, {
  13584. immediate: true
  13585. });
  13586. }
  13587. function onAfterEnter() {
  13588. emit('afterEnter');
  13589. if (overlay.value?.contentEl && !overlay.value.contentEl.contains(document.activeElement)) {
  13590. overlay.value.contentEl.focus({
  13591. preventScroll: true
  13592. });
  13593. }
  13594. }
  13595. function onAfterLeave() {
  13596. emit('afterLeave');
  13597. }
  13598. vue.watch(isActive, async val => {
  13599. if (!val) {
  13600. await vue.nextTick();
  13601. overlay.value.activatorEl?.focus({
  13602. preventScroll: true
  13603. });
  13604. }
  13605. });
  13606. useRender(() => {
  13607. const overlayProps = VOverlay.filterProps(props);
  13608. const activatorProps = vue.mergeProps({
  13609. 'aria-haspopup': 'dialog'
  13610. }, props.activatorProps);
  13611. const contentProps = vue.mergeProps({
  13612. tabindex: -1
  13613. }, props.contentProps);
  13614. return vue.createVNode(VOverlay, vue.mergeProps({
  13615. "ref": overlay,
  13616. "class": ['v-dialog', {
  13617. 'v-dialog--fullscreen': props.fullscreen,
  13618. 'v-dialog--scrollable': props.scrollable
  13619. }, props.class],
  13620. "style": props.style
  13621. }, overlayProps, {
  13622. "modelValue": isActive.value,
  13623. "onUpdate:modelValue": $event => isActive.value = $event,
  13624. "aria-modal": "true",
  13625. "activatorProps": activatorProps,
  13626. "contentProps": contentProps,
  13627. "height": !props.fullscreen ? props.height : undefined,
  13628. "width": !props.fullscreen ? props.width : undefined,
  13629. "maxHeight": !props.fullscreen ? props.maxHeight : undefined,
  13630. "maxWidth": !props.fullscreen ? props.maxWidth : undefined,
  13631. "role": "dialog",
  13632. "onAfterEnter": onAfterEnter,
  13633. "onAfterLeave": onAfterLeave
  13634. }, scopeId), {
  13635. activator: slots.activator,
  13636. default: function () {
  13637. for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) {
  13638. args[_key] = arguments[_key];
  13639. }
  13640. return vue.createVNode(VDefaultsProvider, {
  13641. "root": "VDialog"
  13642. }, {
  13643. default: () => [slots.default?.(...args)]
  13644. });
  13645. }
  13646. });
  13647. });
  13648. return forwardRefs({}, overlay);
  13649. }
  13650. });
  13651. // Types
  13652. const makeVBottomSheetProps = propsFactory({
  13653. inset: Boolean,
  13654. ...makeVDialogProps({
  13655. transition: 'bottom-sheet-transition'
  13656. })
  13657. }, 'VBottomSheet');
  13658. const VBottomSheet = genericComponent()({
  13659. name: 'VBottomSheet',
  13660. props: makeVBottomSheetProps(),
  13661. emits: {
  13662. 'update:modelValue': value => true
  13663. },
  13664. setup(props, _ref) {
  13665. let {
  13666. slots
  13667. } = _ref;
  13668. const isActive = useProxiedModel(props, 'modelValue');
  13669. useRender(() => {
  13670. const dialogProps = VDialog.filterProps(props);
  13671. return vue.createVNode(VDialog, vue.mergeProps(dialogProps, {
  13672. "contentClass": ['v-bottom-sheet__content', props.contentClass],
  13673. "modelValue": isActive.value,
  13674. "onUpdate:modelValue": $event => isActive.value = $event,
  13675. "class": ['v-bottom-sheet', {
  13676. 'v-bottom-sheet--inset': props.inset
  13677. }, props.class],
  13678. "style": props.style
  13679. }), slots);
  13680. });
  13681. return {};
  13682. }
  13683. });
  13684. const makeVBreadcrumbsDividerProps = propsFactory({
  13685. divider: [Number, String],
  13686. ...makeComponentProps()
  13687. }, 'VBreadcrumbsDivider');
  13688. const VBreadcrumbsDivider = genericComponent()({
  13689. name: 'VBreadcrumbsDivider',
  13690. props: makeVBreadcrumbsDividerProps(),
  13691. setup(props, _ref) {
  13692. let {
  13693. slots
  13694. } = _ref;
  13695. useRender(() => vue.createVNode("li", {
  13696. "class": ['v-breadcrumbs-divider', props.class],
  13697. "style": props.style
  13698. }, [slots?.default?.() ?? props.divider]));
  13699. return {};
  13700. }
  13701. });
  13702. const makeVBreadcrumbsItemProps = propsFactory({
  13703. active: Boolean,
  13704. activeClass: String,
  13705. activeColor: String,
  13706. color: String,
  13707. disabled: Boolean,
  13708. title: String,
  13709. ...makeComponentProps(),
  13710. ...makeRouterProps(),
  13711. ...makeTagProps({
  13712. tag: 'li'
  13713. })
  13714. }, 'VBreadcrumbsItem');
  13715. const VBreadcrumbsItem = genericComponent()({
  13716. name: 'VBreadcrumbsItem',
  13717. props: makeVBreadcrumbsItemProps(),
  13718. setup(props, _ref) {
  13719. let {
  13720. slots,
  13721. attrs
  13722. } = _ref;
  13723. const link = useLink(props, attrs);
  13724. const isActive = vue.computed(() => props.active || link.isActive?.value);
  13725. const color = vue.computed(() => isActive.value ? props.activeColor : props.color);
  13726. const {
  13727. textColorClasses,
  13728. textColorStyles
  13729. } = useTextColor(color);
  13730. useRender(() => {
  13731. return vue.createVNode(props.tag, {
  13732. "class": ['v-breadcrumbs-item', {
  13733. 'v-breadcrumbs-item--active': isActive.value,
  13734. 'v-breadcrumbs-item--disabled': props.disabled,
  13735. [`${props.activeClass}`]: isActive.value && props.activeClass
  13736. }, textColorClasses.value, props.class],
  13737. "style": [textColorStyles.value, props.style],
  13738. "aria-current": isActive.value ? 'page' : undefined
  13739. }, {
  13740. default: () => [!link.isLink.value ? slots.default?.() ?? props.title : vue.createVNode("a", vue.mergeProps({
  13741. "class": "v-breadcrumbs-item--link",
  13742. "onClick": link.navigate
  13743. }, link.linkProps), [slots.default?.() ?? props.title])]
  13744. });
  13745. });
  13746. return {};
  13747. }
  13748. });
  13749. // Types
  13750. const makeVBreadcrumbsProps = propsFactory({
  13751. activeClass: String,
  13752. activeColor: String,
  13753. bgColor: String,
  13754. color: String,
  13755. disabled: Boolean,
  13756. divider: {
  13757. type: String,
  13758. default: '/'
  13759. },
  13760. icon: IconValue,
  13761. items: {
  13762. type: Array,
  13763. default: () => []
  13764. },
  13765. ...makeComponentProps(),
  13766. ...makeDensityProps(),
  13767. ...makeRoundedProps(),
  13768. ...makeTagProps({
  13769. tag: 'ul'
  13770. })
  13771. }, 'VBreadcrumbs');
  13772. const VBreadcrumbs = genericComponent()({
  13773. name: 'VBreadcrumbs',
  13774. props: makeVBreadcrumbsProps(),
  13775. setup(props, _ref) {
  13776. let {
  13777. slots
  13778. } = _ref;
  13779. const {
  13780. backgroundColorClasses,
  13781. backgroundColorStyles
  13782. } = useBackgroundColor(vue.toRef(props, 'bgColor'));
  13783. const {
  13784. densityClasses
  13785. } = useDensity(props);
  13786. const {
  13787. roundedClasses
  13788. } = useRounded(props);
  13789. provideDefaults({
  13790. VBreadcrumbsDivider: {
  13791. divider: vue.toRef(props, 'divider')
  13792. },
  13793. VBreadcrumbsItem: {
  13794. activeClass: vue.toRef(props, 'activeClass'),
  13795. activeColor: vue.toRef(props, 'activeColor'),
  13796. color: vue.toRef(props, 'color'),
  13797. disabled: vue.toRef(props, 'disabled')
  13798. }
  13799. });
  13800. const items = vue.computed(() => props.items.map(item => {
  13801. return typeof item === 'string' ? {
  13802. item: {
  13803. title: item
  13804. },
  13805. raw: item
  13806. } : {
  13807. item,
  13808. raw: item
  13809. };
  13810. }));
  13811. useRender(() => {
  13812. const hasPrepend = !!(slots.prepend || props.icon);
  13813. return vue.createVNode(props.tag, {
  13814. "class": ['v-breadcrumbs', backgroundColorClasses.value, densityClasses.value, roundedClasses.value, props.class],
  13815. "style": [backgroundColorStyles.value, props.style]
  13816. }, {
  13817. default: () => [hasPrepend && vue.createVNode("li", {
  13818. "key": "prepend",
  13819. "class": "v-breadcrumbs__prepend"
  13820. }, [!slots.prepend ? vue.createVNode(VIcon, {
  13821. "key": "prepend-icon",
  13822. "start": true,
  13823. "icon": props.icon
  13824. }, null) : vue.createVNode(VDefaultsProvider, {
  13825. "key": "prepend-defaults",
  13826. "disabled": !props.icon,
  13827. "defaults": {
  13828. VIcon: {
  13829. icon: props.icon,
  13830. start: true
  13831. }
  13832. }
  13833. }, slots.prepend)]), items.value.map((_ref2, index, array) => {
  13834. let {
  13835. item,
  13836. raw
  13837. } = _ref2;
  13838. return vue.createVNode(vue.Fragment, null, [slots.item?.({
  13839. item,
  13840. index
  13841. }) ?? vue.createVNode(VBreadcrumbsItem, vue.mergeProps({
  13842. "key": index,
  13843. "disabled": index >= array.length - 1
  13844. }, typeof item === 'string' ? {
  13845. title: item
  13846. } : item), {
  13847. default: slots.title ? () => slots.title?.({
  13848. item,
  13849. index
  13850. }) : undefined
  13851. }), index < array.length - 1 && vue.createVNode(VBreadcrumbsDivider, null, {
  13852. default: slots.divider ? () => slots.divider?.({
  13853. item: raw,
  13854. index
  13855. }) : undefined
  13856. })]);
  13857. }), slots.default?.()]
  13858. });
  13859. });
  13860. return {};
  13861. }
  13862. });
  13863. const VCardActions = genericComponent()({
  13864. name: 'VCardActions',
  13865. props: makeComponentProps(),
  13866. setup(props, _ref) {
  13867. let {
  13868. slots
  13869. } = _ref;
  13870. provideDefaults({
  13871. VBtn: {
  13872. slim: true,
  13873. variant: 'text'
  13874. }
  13875. });
  13876. useRender(() => vue.createVNode("div", {
  13877. "class": ['v-card-actions', props.class],
  13878. "style": props.style
  13879. }, [slots.default?.()]));
  13880. return {};
  13881. }
  13882. });
  13883. const makeVCardSubtitleProps = propsFactory({
  13884. opacity: [Number, String],
  13885. ...makeComponentProps(),
  13886. ...makeTagProps()
  13887. }, 'VCardSubtitle');
  13888. const VCardSubtitle = genericComponent()({
  13889. name: 'VCardSubtitle',
  13890. props: makeVCardSubtitleProps(),
  13891. setup(props, _ref) {
  13892. let {
  13893. slots
  13894. } = _ref;
  13895. useRender(() => vue.createVNode(props.tag, {
  13896. "class": ['v-card-subtitle', props.class],
  13897. "style": [{
  13898. '--v-card-subtitle-opacity': props.opacity
  13899. }, props.style]
  13900. }, slots));
  13901. return {};
  13902. }
  13903. });
  13904. // Utilities
  13905. const VCardTitle = createSimpleFunctional('v-card-title');
  13906. const makeCardItemProps = propsFactory({
  13907. appendAvatar: String,
  13908. appendIcon: IconValue,
  13909. prependAvatar: String,
  13910. prependIcon: IconValue,
  13911. subtitle: [String, Number],
  13912. title: [String, Number],
  13913. ...makeComponentProps(),
  13914. ...makeDensityProps()
  13915. }, 'VCardItem');
  13916. const VCardItem = genericComponent()({
  13917. name: 'VCardItem',
  13918. props: makeCardItemProps(),
  13919. setup(props, _ref) {
  13920. let {
  13921. slots
  13922. } = _ref;
  13923. useRender(() => {
  13924. const hasPrependMedia = !!(props.prependAvatar || props.prependIcon);
  13925. const hasPrepend = !!(hasPrependMedia || slots.prepend);
  13926. const hasAppendMedia = !!(props.appendAvatar || props.appendIcon);
  13927. const hasAppend = !!(hasAppendMedia || slots.append);
  13928. const hasTitle = !!(props.title != null || slots.title);
  13929. const hasSubtitle = !!(props.subtitle != null || slots.subtitle);
  13930. return vue.createVNode("div", {
  13931. "class": ['v-card-item', props.class],
  13932. "style": props.style
  13933. }, [hasPrepend && vue.createVNode("div", {
  13934. "key": "prepend",
  13935. "class": "v-card-item__prepend"
  13936. }, [!slots.prepend ? vue.createVNode(vue.Fragment, null, [props.prependAvatar && vue.createVNode(VAvatar, {
  13937. "key": "prepend-avatar",
  13938. "density": props.density,
  13939. "image": props.prependAvatar
  13940. }, null), props.prependIcon && vue.createVNode(VIcon, {
  13941. "key": "prepend-icon",
  13942. "density": props.density,
  13943. "icon": props.prependIcon
  13944. }, null)]) : vue.createVNode(VDefaultsProvider, {
  13945. "key": "prepend-defaults",
  13946. "disabled": !hasPrependMedia,
  13947. "defaults": {
  13948. VAvatar: {
  13949. density: props.density,
  13950. image: props.prependAvatar
  13951. },
  13952. VIcon: {
  13953. density: props.density,
  13954. icon: props.prependIcon
  13955. }
  13956. }
  13957. }, slots.prepend)]), vue.createVNode("div", {
  13958. "class": "v-card-item__content"
  13959. }, [hasTitle && vue.createVNode(VCardTitle, {
  13960. "key": "title"
  13961. }, {
  13962. default: () => [slots.title?.() ?? props.title]
  13963. }), hasSubtitle && vue.createVNode(VCardSubtitle, {
  13964. "key": "subtitle"
  13965. }, {
  13966. default: () => [slots.subtitle?.() ?? props.subtitle]
  13967. }), slots.default?.()]), hasAppend && vue.createVNode("div", {
  13968. "key": "append",
  13969. "class": "v-card-item__append"
  13970. }, [!slots.append ? vue.createVNode(vue.Fragment, null, [props.appendIcon && vue.createVNode(VIcon, {
  13971. "key": "append-icon",
  13972. "density": props.density,
  13973. "icon": props.appendIcon
  13974. }, null), props.appendAvatar && vue.createVNode(VAvatar, {
  13975. "key": "append-avatar",
  13976. "density": props.density,
  13977. "image": props.appendAvatar
  13978. }, null)]) : vue.createVNode(VDefaultsProvider, {
  13979. "key": "append-defaults",
  13980. "disabled": !hasAppendMedia,
  13981. "defaults": {
  13982. VAvatar: {
  13983. density: props.density,
  13984. image: props.appendAvatar
  13985. },
  13986. VIcon: {
  13987. density: props.density,
  13988. icon: props.appendIcon
  13989. }
  13990. }
  13991. }, slots.append)])]);
  13992. });
  13993. return {};
  13994. }
  13995. });
  13996. const makeVCardTextProps = propsFactory({
  13997. opacity: [Number, String],
  13998. ...makeComponentProps(),
  13999. ...makeTagProps()
  14000. }, 'VCardText');
  14001. const VCardText = genericComponent()({
  14002. name: 'VCardText',
  14003. props: makeVCardTextProps(),
  14004. setup(props, _ref) {
  14005. let {
  14006. slots
  14007. } = _ref;
  14008. useRender(() => vue.createVNode(props.tag, {
  14009. "class": ['v-card-text', props.class],
  14010. "style": [{
  14011. '--v-card-text-opacity': props.opacity
  14012. }, props.style]
  14013. }, slots));
  14014. return {};
  14015. }
  14016. });
  14017. // Types
  14018. const makeVCardProps = propsFactory({
  14019. appendAvatar: String,
  14020. appendIcon: IconValue,
  14021. disabled: Boolean,
  14022. flat: Boolean,
  14023. hover: Boolean,
  14024. image: String,
  14025. link: {
  14026. type: Boolean,
  14027. default: undefined
  14028. },
  14029. prependAvatar: String,
  14030. prependIcon: IconValue,
  14031. ripple: {
  14032. type: [Boolean, Object],
  14033. default: true
  14034. },
  14035. subtitle: [String, Number],
  14036. text: [String, Number],
  14037. title: [String, Number],
  14038. ...makeBorderProps(),
  14039. ...makeComponentProps(),
  14040. ...makeDensityProps(),
  14041. ...makeDimensionProps(),
  14042. ...makeElevationProps(),
  14043. ...makeLoaderProps(),
  14044. ...makeLocationProps(),
  14045. ...makePositionProps(),
  14046. ...makeRoundedProps(),
  14047. ...makeRouterProps(),
  14048. ...makeTagProps(),
  14049. ...makeThemeProps(),
  14050. ...makeVariantProps({
  14051. variant: 'elevated'
  14052. })
  14053. }, 'VCard');
  14054. const VCard = genericComponent()({
  14055. name: 'VCard',
  14056. directives: {
  14057. Ripple
  14058. },
  14059. props: makeVCardProps(),
  14060. setup(props, _ref) {
  14061. let {
  14062. attrs,
  14063. slots
  14064. } = _ref;
  14065. const {
  14066. themeClasses
  14067. } = provideTheme(props);
  14068. const {
  14069. borderClasses
  14070. } = useBorder(props);
  14071. const {
  14072. colorClasses,
  14073. colorStyles,
  14074. variantClasses
  14075. } = useVariant(props);
  14076. const {
  14077. densityClasses
  14078. } = useDensity(props);
  14079. const {
  14080. dimensionStyles
  14081. } = useDimension(props);
  14082. const {
  14083. elevationClasses
  14084. } = useElevation(props);
  14085. const {
  14086. loaderClasses
  14087. } = useLoader(props);
  14088. const {
  14089. locationStyles
  14090. } = useLocation(props);
  14091. const {
  14092. positionClasses
  14093. } = usePosition(props);
  14094. const {
  14095. roundedClasses
  14096. } = useRounded(props);
  14097. const link = useLink(props, attrs);
  14098. const isLink = vue.computed(() => props.link !== false && link.isLink.value);
  14099. const isClickable = vue.computed(() => !props.disabled && props.link !== false && (props.link || link.isClickable.value));
  14100. useRender(() => {
  14101. const Tag = isLink.value ? 'a' : props.tag;
  14102. const hasTitle = !!(slots.title || props.title != null);
  14103. const hasSubtitle = !!(slots.subtitle || props.subtitle != null);
  14104. const hasHeader = hasTitle || hasSubtitle;
  14105. const hasAppend = !!(slots.append || props.appendAvatar || props.appendIcon);
  14106. const hasPrepend = !!(slots.prepend || props.prependAvatar || props.prependIcon);
  14107. const hasImage = !!(slots.image || props.image);
  14108. const hasCardItem = hasHeader || hasPrepend || hasAppend;
  14109. const hasText = !!(slots.text || props.text != null);
  14110. return vue.withDirectives(vue.createVNode(Tag, vue.mergeProps({
  14111. "class": ['v-card', {
  14112. 'v-card--disabled': props.disabled,
  14113. 'v-card--flat': props.flat,
  14114. 'v-card--hover': props.hover && !(props.disabled || props.flat),
  14115. 'v-card--link': isClickable.value
  14116. }, themeClasses.value, borderClasses.value, colorClasses.value, densityClasses.value, elevationClasses.value, loaderClasses.value, positionClasses.value, roundedClasses.value, variantClasses.value, props.class],
  14117. "style": [colorStyles.value, dimensionStyles.value, locationStyles.value, props.style],
  14118. "onClick": isClickable.value && link.navigate,
  14119. "tabindex": props.disabled ? -1 : undefined
  14120. }, link.linkProps), {
  14121. default: () => [hasImage && vue.createVNode("div", {
  14122. "key": "image",
  14123. "class": "v-card__image"
  14124. }, [!slots.image ? vue.createVNode(VImg, {
  14125. "key": "image-img",
  14126. "cover": true,
  14127. "src": props.image
  14128. }, null) : vue.createVNode(VDefaultsProvider, {
  14129. "key": "image-defaults",
  14130. "disabled": !props.image,
  14131. "defaults": {
  14132. VImg: {
  14133. cover: true,
  14134. src: props.image
  14135. }
  14136. }
  14137. }, slots.image)]), vue.createVNode(LoaderSlot, {
  14138. "name": "v-card",
  14139. "active": !!props.loading,
  14140. "color": typeof props.loading === 'boolean' ? undefined : props.loading
  14141. }, {
  14142. default: slots.loader
  14143. }), hasCardItem && vue.createVNode(VCardItem, {
  14144. "key": "item",
  14145. "prependAvatar": props.prependAvatar,
  14146. "prependIcon": props.prependIcon,
  14147. "title": props.title,
  14148. "subtitle": props.subtitle,
  14149. "appendAvatar": props.appendAvatar,
  14150. "appendIcon": props.appendIcon
  14151. }, {
  14152. default: slots.item,
  14153. prepend: slots.prepend,
  14154. title: slots.title,
  14155. subtitle: slots.subtitle,
  14156. append: slots.append
  14157. }), hasText && vue.createVNode(VCardText, {
  14158. "key": "text"
  14159. }, {
  14160. default: () => [slots.text?.() ?? props.text]
  14161. }), slots.default?.(), slots.actions && vue.createVNode(VCardActions, null, {
  14162. default: slots.actions
  14163. }), genOverlays(isClickable.value, 'v-card')]
  14164. }), [[vue.resolveDirective("ripple"), isClickable.value && props.ripple]]);
  14165. });
  14166. return {};
  14167. }
  14168. });
  14169. // Utilities
  14170. // Types
  14171. const handleGesture = wrapper => {
  14172. const {
  14173. touchstartX,
  14174. touchendX,
  14175. touchstartY,
  14176. touchendY
  14177. } = wrapper;
  14178. const dirRatio = 0.5;
  14179. const minDistance = 16;
  14180. wrapper.offsetX = touchendX - touchstartX;
  14181. wrapper.offsetY = touchendY - touchstartY;
  14182. if (Math.abs(wrapper.offsetY) < dirRatio * Math.abs(wrapper.offsetX)) {
  14183. wrapper.left && touchendX < touchstartX - minDistance && wrapper.left(wrapper);
  14184. wrapper.right && touchendX > touchstartX + minDistance && wrapper.right(wrapper);
  14185. }
  14186. if (Math.abs(wrapper.offsetX) < dirRatio * Math.abs(wrapper.offsetY)) {
  14187. wrapper.up && touchendY < touchstartY - minDistance && wrapper.up(wrapper);
  14188. wrapper.down && touchendY > touchstartY + minDistance && wrapper.down(wrapper);
  14189. }
  14190. };
  14191. function touchstart(event, wrapper) {
  14192. const touch = event.changedTouches[0];
  14193. wrapper.touchstartX = touch.clientX;
  14194. wrapper.touchstartY = touch.clientY;
  14195. wrapper.start?.({
  14196. originalEvent: event,
  14197. ...wrapper
  14198. });
  14199. }
  14200. function touchend(event, wrapper) {
  14201. const touch = event.changedTouches[0];
  14202. wrapper.touchendX = touch.clientX;
  14203. wrapper.touchendY = touch.clientY;
  14204. wrapper.end?.({
  14205. originalEvent: event,
  14206. ...wrapper
  14207. });
  14208. handleGesture(wrapper);
  14209. }
  14210. function touchmove(event, wrapper) {
  14211. const touch = event.changedTouches[0];
  14212. wrapper.touchmoveX = touch.clientX;
  14213. wrapper.touchmoveY = touch.clientY;
  14214. wrapper.move?.({
  14215. originalEvent: event,
  14216. ...wrapper
  14217. });
  14218. }
  14219. function createHandlers() {
  14220. let value = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
  14221. const wrapper = {
  14222. touchstartX: 0,
  14223. touchstartY: 0,
  14224. touchendX: 0,
  14225. touchendY: 0,
  14226. touchmoveX: 0,
  14227. touchmoveY: 0,
  14228. offsetX: 0,
  14229. offsetY: 0,
  14230. left: value.left,
  14231. right: value.right,
  14232. up: value.up,
  14233. down: value.down,
  14234. start: value.start,
  14235. move: value.move,
  14236. end: value.end
  14237. };
  14238. return {
  14239. touchstart: e => touchstart(e, wrapper),
  14240. touchend: e => touchend(e, wrapper),
  14241. touchmove: e => touchmove(e, wrapper)
  14242. };
  14243. }
  14244. function mounted$3(el, binding) {
  14245. const value = binding.value;
  14246. const target = value?.parent ? el.parentElement : el;
  14247. const options = value?.options ?? {
  14248. passive: true
  14249. };
  14250. const uid = binding.instance?.$.uid; // TODO: use custom uid generator
  14251. if (!target || !uid) return;
  14252. const handlers = createHandlers(binding.value);
  14253. target._touchHandlers = target._touchHandlers ?? Object.create(null);
  14254. target._touchHandlers[uid] = handlers;
  14255. keys(handlers).forEach(eventName => {
  14256. target.addEventListener(eventName, handlers[eventName], options);
  14257. });
  14258. }
  14259. function unmounted$3(el, binding) {
  14260. const target = binding.value?.parent ? el.parentElement : el;
  14261. const uid = binding.instance?.$.uid;
  14262. if (!target?._touchHandlers || !uid) return;
  14263. const handlers = target._touchHandlers[uid];
  14264. keys(handlers).forEach(eventName => {
  14265. target.removeEventListener(eventName, handlers[eventName]);
  14266. });
  14267. delete target._touchHandlers[uid];
  14268. }
  14269. const Touch = {
  14270. mounted: mounted$3,
  14271. unmounted: unmounted$3
  14272. };
  14273. // Types
  14274. const VWindowSymbol = Symbol.for('vuetify:v-window');
  14275. const VWindowGroupSymbol = Symbol.for('vuetify:v-window-group');
  14276. const makeVWindowProps = propsFactory({
  14277. continuous: Boolean,
  14278. nextIcon: {
  14279. type: [Boolean, String, Function, Object],
  14280. default: '$next'
  14281. },
  14282. prevIcon: {
  14283. type: [Boolean, String, Function, Object],
  14284. default: '$prev'
  14285. },
  14286. reverse: Boolean,
  14287. showArrows: {
  14288. type: [Boolean, String],
  14289. validator: v => typeof v === 'boolean' || v === 'hover'
  14290. },
  14291. touch: {
  14292. type: [Object, Boolean],
  14293. default: undefined
  14294. },
  14295. direction: {
  14296. type: String,
  14297. default: 'horizontal'
  14298. },
  14299. modelValue: null,
  14300. disabled: Boolean,
  14301. selectedClass: {
  14302. type: String,
  14303. default: 'v-window-item--active'
  14304. },
  14305. // TODO: mandatory should probably not be exposed but do this for now
  14306. mandatory: {
  14307. type: [Boolean, String],
  14308. default: 'force'
  14309. },
  14310. ...makeComponentProps(),
  14311. ...makeTagProps(),
  14312. ...makeThemeProps()
  14313. }, 'VWindow');
  14314. const VWindow = genericComponent()({
  14315. name: 'VWindow',
  14316. directives: {
  14317. Touch
  14318. },
  14319. props: makeVWindowProps(),
  14320. emits: {
  14321. 'update:modelValue': value => true
  14322. },
  14323. setup(props, _ref) {
  14324. let {
  14325. slots
  14326. } = _ref;
  14327. const {
  14328. themeClasses
  14329. } = provideTheme(props);
  14330. const {
  14331. isRtl
  14332. } = useRtl();
  14333. const {
  14334. t
  14335. } = useLocale();
  14336. const group = useGroup(props, VWindowGroupSymbol);
  14337. const rootRef = vue.ref();
  14338. const isRtlReverse = vue.computed(() => isRtl.value ? !props.reverse : props.reverse);
  14339. const isReversed = vue.shallowRef(false);
  14340. const transition = vue.computed(() => {
  14341. const axis = props.direction === 'vertical' ? 'y' : 'x';
  14342. const reverse = isRtlReverse.value ? !isReversed.value : isReversed.value;
  14343. const direction = reverse ? '-reverse' : '';
  14344. return `v-window-${axis}${direction}-transition`;
  14345. });
  14346. const transitionCount = vue.shallowRef(0);
  14347. const transitionHeight = vue.ref(undefined);
  14348. const activeIndex = vue.computed(() => {
  14349. return group.items.value.findIndex(item => group.selected.value.includes(item.id));
  14350. });
  14351. vue.watch(activeIndex, (newVal, oldVal) => {
  14352. const itemsLength = group.items.value.length;
  14353. const lastIndex = itemsLength - 1;
  14354. if (itemsLength <= 2) {
  14355. isReversed.value = newVal < oldVal;
  14356. } else if (newVal === lastIndex && oldVal === 0) {
  14357. isReversed.value = true;
  14358. } else if (newVal === 0 && oldVal === lastIndex) {
  14359. isReversed.value = false;
  14360. } else {
  14361. isReversed.value = newVal < oldVal;
  14362. }
  14363. });
  14364. vue.provide(VWindowSymbol, {
  14365. transition,
  14366. isReversed,
  14367. transitionCount,
  14368. transitionHeight,
  14369. rootRef
  14370. });
  14371. const canMoveBack = vue.computed(() => props.continuous || activeIndex.value !== 0);
  14372. const canMoveForward = vue.computed(() => props.continuous || activeIndex.value !== group.items.value.length - 1);
  14373. function prev() {
  14374. canMoveBack.value && group.prev();
  14375. }
  14376. function next() {
  14377. canMoveForward.value && group.next();
  14378. }
  14379. const arrows = vue.computed(() => {
  14380. const arrows = [];
  14381. const prevProps = {
  14382. icon: isRtl.value ? props.nextIcon : props.prevIcon,
  14383. class: `v-window__${isRtlReverse.value ? 'right' : 'left'}`,
  14384. onClick: group.prev,
  14385. 'aria-label': t('$vuetify.carousel.prev')
  14386. };
  14387. arrows.push(canMoveBack.value ? slots.prev ? slots.prev({
  14388. props: prevProps
  14389. }) : vue.createVNode(VBtn, prevProps, null) : vue.createVNode("div", null, null));
  14390. const nextProps = {
  14391. icon: isRtl.value ? props.prevIcon : props.nextIcon,
  14392. class: `v-window__${isRtlReverse.value ? 'left' : 'right'}`,
  14393. onClick: group.next,
  14394. 'aria-label': t('$vuetify.carousel.next')
  14395. };
  14396. arrows.push(canMoveForward.value ? slots.next ? slots.next({
  14397. props: nextProps
  14398. }) : vue.createVNode(VBtn, nextProps, null) : vue.createVNode("div", null, null));
  14399. return arrows;
  14400. });
  14401. const touchOptions = vue.computed(() => {
  14402. if (props.touch === false) return props.touch;
  14403. const options = {
  14404. left: () => {
  14405. isRtlReverse.value ? prev() : next();
  14406. },
  14407. right: () => {
  14408. isRtlReverse.value ? next() : prev();
  14409. },
  14410. start: _ref2 => {
  14411. let {
  14412. originalEvent
  14413. } = _ref2;
  14414. originalEvent.stopPropagation();
  14415. }
  14416. };
  14417. return {
  14418. ...options,
  14419. ...(props.touch === true ? {} : props.touch)
  14420. };
  14421. });
  14422. useRender(() => vue.withDirectives(vue.createVNode(props.tag, {
  14423. "ref": rootRef,
  14424. "class": ['v-window', {
  14425. 'v-window--show-arrows-on-hover': props.showArrows === 'hover'
  14426. }, themeClasses.value, props.class],
  14427. "style": props.style
  14428. }, {
  14429. default: () => [vue.createVNode("div", {
  14430. "class": "v-window__container",
  14431. "style": {
  14432. height: transitionHeight.value
  14433. }
  14434. }, [slots.default?.({
  14435. group
  14436. }), props.showArrows !== false && vue.createVNode("div", {
  14437. "class": "v-window__controls"
  14438. }, [arrows.value])]), slots.additional?.({
  14439. group
  14440. })]
  14441. }), [[vue.resolveDirective("touch"), touchOptions.value]]));
  14442. return {
  14443. group
  14444. };
  14445. }
  14446. });
  14447. // Types
  14448. const makeVCarouselProps = propsFactory({
  14449. color: String,
  14450. cycle: Boolean,
  14451. delimiterIcon: {
  14452. type: IconValue,
  14453. default: '$delimiter'
  14454. },
  14455. height: {
  14456. type: [Number, String],
  14457. default: 500
  14458. },
  14459. hideDelimiters: Boolean,
  14460. hideDelimiterBackground: Boolean,
  14461. interval: {
  14462. type: [Number, String],
  14463. default: 6000,
  14464. validator: value => Number(value) > 0
  14465. },
  14466. progress: [Boolean, String],
  14467. verticalDelimiters: [Boolean, String],
  14468. ...makeVWindowProps({
  14469. continuous: true,
  14470. mandatory: 'force',
  14471. showArrows: true
  14472. })
  14473. }, 'VCarousel');
  14474. const VCarousel = genericComponent()({
  14475. name: 'VCarousel',
  14476. props: makeVCarouselProps(),
  14477. emits: {
  14478. 'update:modelValue': value => true
  14479. },
  14480. setup(props, _ref) {
  14481. let {
  14482. slots
  14483. } = _ref;
  14484. const model = useProxiedModel(props, 'modelValue');
  14485. const {
  14486. t
  14487. } = useLocale();
  14488. const windowRef = vue.ref();
  14489. let slideTimeout = -1;
  14490. vue.watch(model, restartTimeout);
  14491. vue.watch(() => props.interval, restartTimeout);
  14492. vue.watch(() => props.cycle, val => {
  14493. if (val) restartTimeout();else window.clearTimeout(slideTimeout);
  14494. });
  14495. vue.onMounted(startTimeout);
  14496. function startTimeout() {
  14497. if (!props.cycle || !windowRef.value) return;
  14498. slideTimeout = window.setTimeout(windowRef.value.group.next, +props.interval > 0 ? +props.interval : 6000);
  14499. }
  14500. function restartTimeout() {
  14501. window.clearTimeout(slideTimeout);
  14502. window.requestAnimationFrame(startTimeout);
  14503. }
  14504. useRender(() => {
  14505. const windowProps = VWindow.filterProps(props);
  14506. return vue.createVNode(VWindow, vue.mergeProps({
  14507. "ref": windowRef
  14508. }, windowProps, {
  14509. "modelValue": model.value,
  14510. "onUpdate:modelValue": $event => model.value = $event,
  14511. "class": ['v-carousel', {
  14512. 'v-carousel--hide-delimiter-background': props.hideDelimiterBackground,
  14513. 'v-carousel--vertical-delimiters': props.verticalDelimiters
  14514. }, props.class],
  14515. "style": [{
  14516. height: convertToUnit(props.height)
  14517. }, props.style]
  14518. }), {
  14519. default: slots.default,
  14520. additional: _ref2 => {
  14521. let {
  14522. group
  14523. } = _ref2;
  14524. return vue.createVNode(vue.Fragment, null, [!props.hideDelimiters && vue.createVNode("div", {
  14525. "class": "v-carousel__controls",
  14526. "style": {
  14527. left: props.verticalDelimiters === 'left' && props.verticalDelimiters ? 0 : 'auto',
  14528. right: props.verticalDelimiters === 'right' ? 0 : 'auto'
  14529. }
  14530. }, [group.items.value.length > 0 && vue.createVNode(VDefaultsProvider, {
  14531. "defaults": {
  14532. VBtn: {
  14533. color: props.color,
  14534. icon: props.delimiterIcon,
  14535. size: 'x-small',
  14536. variant: 'text'
  14537. }
  14538. },
  14539. "scoped": true
  14540. }, {
  14541. default: () => [group.items.value.map((item, index) => {
  14542. const props = {
  14543. id: `carousel-item-${item.id}`,
  14544. 'aria-label': t('$vuetify.carousel.ariaLabel.delimiter', index + 1, group.items.value.length),
  14545. class: ['v-carousel__controls__item', group.isSelected(item.id) && 'v-btn--active'],
  14546. onClick: () => group.select(item.id, true)
  14547. };
  14548. return slots.item ? slots.item({
  14549. props,
  14550. item
  14551. }) : vue.createVNode(VBtn, vue.mergeProps(item, props), null);
  14552. })]
  14553. })]), props.progress && vue.createVNode(VProgressLinear, {
  14554. "class": "v-carousel__progress",
  14555. "color": typeof props.progress === 'string' ? props.progress : undefined,
  14556. "modelValue": (group.getItemIndex(model.value) + 1) / group.items.value.length * 100
  14557. }, null)]);
  14558. },
  14559. prev: slots.prev,
  14560. next: slots.next
  14561. });
  14562. });
  14563. return {};
  14564. }
  14565. });
  14566. const makeVWindowItemProps = propsFactory({
  14567. reverseTransition: {
  14568. type: [Boolean, String],
  14569. default: undefined
  14570. },
  14571. transition: {
  14572. type: [Boolean, String],
  14573. default: undefined
  14574. },
  14575. ...makeComponentProps(),
  14576. ...makeGroupItemProps(),
  14577. ...makeLazyProps()
  14578. }, 'VWindowItem');
  14579. const VWindowItem = genericComponent()({
  14580. name: 'VWindowItem',
  14581. directives: {
  14582. Touch
  14583. },
  14584. props: makeVWindowItemProps(),
  14585. emits: {
  14586. 'group:selected': val => true
  14587. },
  14588. setup(props, _ref) {
  14589. let {
  14590. slots
  14591. } = _ref;
  14592. const window = vue.inject(VWindowSymbol);
  14593. const groupItem = useGroupItem(props, VWindowGroupSymbol);
  14594. const {
  14595. isBooted
  14596. } = useSsrBoot();
  14597. if (!window || !groupItem) throw new Error('[Vuetify] VWindowItem must be used inside VWindow');
  14598. const isTransitioning = vue.shallowRef(false);
  14599. const hasTransition = vue.computed(() => isBooted.value && (window.isReversed.value ? props.reverseTransition !== false : props.transition !== false));
  14600. function onAfterTransition() {
  14601. if (!isTransitioning.value || !window) {
  14602. return;
  14603. }
  14604. // Finalize transition state.
  14605. isTransitioning.value = false;
  14606. if (window.transitionCount.value > 0) {
  14607. window.transitionCount.value -= 1;
  14608. // Remove container height if we are out of transition.
  14609. if (window.transitionCount.value === 0) {
  14610. window.transitionHeight.value = undefined;
  14611. }
  14612. }
  14613. }
  14614. function onBeforeTransition() {
  14615. if (isTransitioning.value || !window) {
  14616. return;
  14617. }
  14618. // Initialize transition state here.
  14619. isTransitioning.value = true;
  14620. if (window.transitionCount.value === 0) {
  14621. // Set initial height for height transition.
  14622. window.transitionHeight.value = convertToUnit(window.rootRef.value?.clientHeight);
  14623. }
  14624. window.transitionCount.value += 1;
  14625. }
  14626. function onTransitionCancelled() {
  14627. onAfterTransition(); // This should have the same path as normal transition end.
  14628. }
  14629. function onEnterTransition(el) {
  14630. if (!isTransitioning.value) {
  14631. return;
  14632. }
  14633. vue.nextTick(() => {
  14634. // Do not set height if no transition or cancelled.
  14635. if (!hasTransition.value || !isTransitioning.value || !window) {
  14636. return;
  14637. }
  14638. // Set transition target height.
  14639. window.transitionHeight.value = convertToUnit(el.clientHeight);
  14640. });
  14641. }
  14642. const transition = vue.computed(() => {
  14643. const name = window.isReversed.value ? props.reverseTransition : props.transition;
  14644. return !hasTransition.value ? false : {
  14645. name: typeof name !== 'string' ? window.transition.value : name,
  14646. onBeforeEnter: onBeforeTransition,
  14647. onAfterEnter: onAfterTransition,
  14648. onEnterCancelled: onTransitionCancelled,
  14649. onBeforeLeave: onBeforeTransition,
  14650. onAfterLeave: onAfterTransition,
  14651. onLeaveCancelled: onTransitionCancelled,
  14652. onEnter: onEnterTransition
  14653. };
  14654. });
  14655. const {
  14656. hasContent
  14657. } = useLazy(props, groupItem.isSelected);
  14658. useRender(() => vue.createVNode(MaybeTransition, {
  14659. "transition": transition.value,
  14660. "disabled": !isBooted.value
  14661. }, {
  14662. default: () => [vue.withDirectives(vue.createVNode("div", {
  14663. "class": ['v-window-item', groupItem.selectedClass.value, props.class],
  14664. "style": props.style
  14665. }, [hasContent.value && slots.default?.()]), [[vue.vShow, groupItem.isSelected.value]])]
  14666. }));
  14667. return {
  14668. groupItem
  14669. };
  14670. }
  14671. });
  14672. // Types
  14673. const makeVCarouselItemProps = propsFactory({
  14674. ...makeVImgProps(),
  14675. ...makeVWindowItemProps()
  14676. }, 'VCarouselItem');
  14677. const VCarouselItem = genericComponent()({
  14678. name: 'VCarouselItem',
  14679. inheritAttrs: false,
  14680. props: makeVCarouselItemProps(),
  14681. setup(props, _ref) {
  14682. let {
  14683. slots,
  14684. attrs
  14685. } = _ref;
  14686. useRender(() => {
  14687. const imgProps = VImg.filterProps(props);
  14688. const windowItemProps = VWindowItem.filterProps(props);
  14689. return vue.createVNode(VWindowItem, vue.mergeProps({
  14690. "class": ['v-carousel-item', props.class]
  14691. }, windowItemProps), {
  14692. default: () => [vue.createVNode(VImg, vue.mergeProps(attrs, imgProps), slots)]
  14693. });
  14694. });
  14695. }
  14696. });
  14697. // Styles
  14698. const VCode = createSimpleFunctional('v-code', 'code');
  14699. // Types
  14700. const makeVColorPickerCanvasProps = propsFactory({
  14701. color: {
  14702. type: Object
  14703. },
  14704. disabled: Boolean,
  14705. dotSize: {
  14706. type: [Number, String],
  14707. default: 10
  14708. },
  14709. height: {
  14710. type: [Number, String],
  14711. default: 150
  14712. },
  14713. width: {
  14714. type: [Number, String],
  14715. default: 300
  14716. },
  14717. ...makeComponentProps()
  14718. }, 'VColorPickerCanvas');
  14719. const VColorPickerCanvas = defineComponent({
  14720. name: 'VColorPickerCanvas',
  14721. props: makeVColorPickerCanvasProps(),
  14722. emits: {
  14723. 'update:color': color => true,
  14724. 'update:position': hue => true
  14725. },
  14726. setup(props, _ref) {
  14727. let {
  14728. emit
  14729. } = _ref;
  14730. const isInteracting = vue.shallowRef(false);
  14731. const canvasRef = vue.ref();
  14732. const canvasWidth = vue.shallowRef(parseFloat(props.width));
  14733. const canvasHeight = vue.shallowRef(parseFloat(props.height));
  14734. const _dotPosition = vue.ref({
  14735. x: 0,
  14736. y: 0
  14737. });
  14738. const dotPosition = vue.computed({
  14739. get: () => _dotPosition.value,
  14740. set(val) {
  14741. if (!canvasRef.value) return;
  14742. const {
  14743. x,
  14744. y
  14745. } = val;
  14746. _dotPosition.value = val;
  14747. emit('update:color', {
  14748. h: props.color?.h ?? 0,
  14749. s: clamp(x, 0, canvasWidth.value) / canvasWidth.value,
  14750. v: 1 - clamp(y, 0, canvasHeight.value) / canvasHeight.value,
  14751. a: props.color?.a ?? 1
  14752. });
  14753. }
  14754. });
  14755. const dotStyles = vue.computed(() => {
  14756. const {
  14757. x,
  14758. y
  14759. } = dotPosition.value;
  14760. const radius = parseInt(props.dotSize, 10) / 2;
  14761. return {
  14762. width: convertToUnit(props.dotSize),
  14763. height: convertToUnit(props.dotSize),
  14764. transform: `translate(${convertToUnit(x - radius)}, ${convertToUnit(y - radius)})`
  14765. };
  14766. });
  14767. const {
  14768. resizeRef
  14769. } = useResizeObserver(entries => {
  14770. if (!resizeRef.el?.offsetParent) return;
  14771. const {
  14772. width,
  14773. height
  14774. } = entries[0].contentRect;
  14775. canvasWidth.value = width;
  14776. canvasHeight.value = height;
  14777. });
  14778. function updateDotPosition(x, y, rect) {
  14779. const {
  14780. left,
  14781. top,
  14782. width,
  14783. height
  14784. } = rect;
  14785. dotPosition.value = {
  14786. x: clamp(x - left, 0, width),
  14787. y: clamp(y - top, 0, height)
  14788. };
  14789. }
  14790. function handleMouseDown(e) {
  14791. if (e.type === 'mousedown') {
  14792. // Prevent text selection while dragging
  14793. e.preventDefault();
  14794. }
  14795. if (props.disabled) return;
  14796. handleMouseMove(e);
  14797. window.addEventListener('mousemove', handleMouseMove);
  14798. window.addEventListener('mouseup', handleMouseUp);
  14799. window.addEventListener('touchmove', handleMouseMove);
  14800. window.addEventListener('touchend', handleMouseUp);
  14801. }
  14802. function handleMouseMove(e) {
  14803. if (props.disabled || !canvasRef.value) return;
  14804. isInteracting.value = true;
  14805. const coords = getEventCoordinates(e);
  14806. updateDotPosition(coords.clientX, coords.clientY, canvasRef.value.getBoundingClientRect());
  14807. }
  14808. function handleMouseUp() {
  14809. window.removeEventListener('mousemove', handleMouseMove);
  14810. window.removeEventListener('mouseup', handleMouseUp);
  14811. window.removeEventListener('touchmove', handleMouseMove);
  14812. window.removeEventListener('touchend', handleMouseUp);
  14813. }
  14814. function updateCanvas() {
  14815. if (!canvasRef.value) return;
  14816. const canvas = canvasRef.value;
  14817. const ctx = canvas.getContext('2d');
  14818. if (!ctx) return;
  14819. const saturationGradient = ctx.createLinearGradient(0, 0, canvas.width, 0);
  14820. saturationGradient.addColorStop(0, 'hsla(0, 0%, 100%, 1)'); // white
  14821. saturationGradient.addColorStop(1, `hsla(${props.color?.h ?? 0}, 100%, 50%, 1)`);
  14822. ctx.fillStyle = saturationGradient;
  14823. ctx.fillRect(0, 0, canvas.width, canvas.height);
  14824. const valueGradient = ctx.createLinearGradient(0, 0, 0, canvas.height);
  14825. valueGradient.addColorStop(0, 'hsla(0, 0%, 0%, 0)'); // transparent
  14826. valueGradient.addColorStop(1, 'hsla(0, 0%, 0%, 1)'); // black
  14827. ctx.fillStyle = valueGradient;
  14828. ctx.fillRect(0, 0, canvas.width, canvas.height);
  14829. }
  14830. vue.watch(() => props.color?.h, updateCanvas, {
  14831. immediate: true
  14832. });
  14833. vue.watch(() => [canvasWidth.value, canvasHeight.value], (newVal, oldVal) => {
  14834. updateCanvas();
  14835. _dotPosition.value = {
  14836. x: dotPosition.value.x * newVal[0] / oldVal[0],
  14837. y: dotPosition.value.y * newVal[1] / oldVal[1]
  14838. };
  14839. }, {
  14840. flush: 'post'
  14841. });
  14842. vue.watch(() => props.color, () => {
  14843. if (isInteracting.value) {
  14844. isInteracting.value = false;
  14845. return;
  14846. }
  14847. _dotPosition.value = props.color ? {
  14848. x: props.color.s * canvasWidth.value,
  14849. y: (1 - props.color.v) * canvasHeight.value
  14850. } : {
  14851. x: 0,
  14852. y: 0
  14853. };
  14854. }, {
  14855. deep: true,
  14856. immediate: true
  14857. });
  14858. vue.onMounted(() => updateCanvas());
  14859. useRender(() => vue.createVNode("div", {
  14860. "ref": resizeRef,
  14861. "class": ['v-color-picker-canvas', props.class],
  14862. "style": props.style,
  14863. "onMousedown": handleMouseDown,
  14864. "onTouchstartPassive": handleMouseDown
  14865. }, [vue.createVNode("canvas", {
  14866. "ref": canvasRef,
  14867. "width": canvasWidth.value,
  14868. "height": canvasHeight.value
  14869. }, null), props.color && vue.createVNode("div", {
  14870. "class": ['v-color-picker-canvas__dot', {
  14871. 'v-color-picker-canvas__dot--disabled': props.disabled
  14872. }],
  14873. "style": dotStyles.value
  14874. }, null)]));
  14875. return {};
  14876. }
  14877. });
  14878. // Utilities
  14879. // Types
  14880. function stripAlpha(color, stripAlpha) {
  14881. if (stripAlpha) {
  14882. const {
  14883. a,
  14884. ...rest
  14885. } = color;
  14886. return rest;
  14887. }
  14888. return color;
  14889. }
  14890. function extractColor(color, input) {
  14891. if (input == null || typeof input === 'string') {
  14892. const hex = HSVtoHex(color);
  14893. if (color.a === 1) return hex.slice(0, 7);else return hex;
  14894. }
  14895. if (typeof input === 'object') {
  14896. let converted;
  14897. 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;
  14898. return stripAlpha(converted, !has(input, ['a']) && color.a === 1);
  14899. }
  14900. return color;
  14901. }
  14902. const nullColor = {
  14903. h: 0,
  14904. s: 0,
  14905. v: 0,
  14906. a: 1
  14907. };
  14908. const rgba = {
  14909. inputProps: {
  14910. type: 'number',
  14911. min: 0
  14912. },
  14913. inputs: [{
  14914. label: 'R',
  14915. max: 255,
  14916. step: 1,
  14917. getValue: c => Math.round(c.r),
  14918. getColor: (c, v) => ({
  14919. ...c,
  14920. r: Number(v)
  14921. })
  14922. }, {
  14923. label: 'G',
  14924. max: 255,
  14925. step: 1,
  14926. getValue: c => Math.round(c.g),
  14927. getColor: (c, v) => ({
  14928. ...c,
  14929. g: Number(v)
  14930. })
  14931. }, {
  14932. label: 'B',
  14933. max: 255,
  14934. step: 1,
  14935. getValue: c => Math.round(c.b),
  14936. getColor: (c, v) => ({
  14937. ...c,
  14938. b: Number(v)
  14939. })
  14940. }, {
  14941. label: 'A',
  14942. max: 1,
  14943. step: 0.01,
  14944. getValue: _ref => {
  14945. let {
  14946. a
  14947. } = _ref;
  14948. return a != null ? Math.round(a * 100) / 100 : 1;
  14949. },
  14950. getColor: (c, v) => ({
  14951. ...c,
  14952. a: Number(v)
  14953. })
  14954. }],
  14955. to: HSVtoRGB,
  14956. from: RGBtoHSV
  14957. };
  14958. const rgb = {
  14959. ...rgba,
  14960. inputs: rgba.inputs?.slice(0, 3)
  14961. };
  14962. const hsla = {
  14963. inputProps: {
  14964. type: 'number',
  14965. min: 0
  14966. },
  14967. inputs: [{
  14968. label: 'H',
  14969. max: 360,
  14970. step: 1,
  14971. getValue: c => Math.round(c.h),
  14972. getColor: (c, v) => ({
  14973. ...c,
  14974. h: Number(v)
  14975. })
  14976. }, {
  14977. label: 'S',
  14978. max: 1,
  14979. step: 0.01,
  14980. getValue: c => Math.round(c.s * 100) / 100,
  14981. getColor: (c, v) => ({
  14982. ...c,
  14983. s: Number(v)
  14984. })
  14985. }, {
  14986. label: 'L',
  14987. max: 1,
  14988. step: 0.01,
  14989. getValue: c => Math.round(c.l * 100) / 100,
  14990. getColor: (c, v) => ({
  14991. ...c,
  14992. l: Number(v)
  14993. })
  14994. }, {
  14995. label: 'A',
  14996. max: 1,
  14997. step: 0.01,
  14998. getValue: _ref2 => {
  14999. let {
  15000. a
  15001. } = _ref2;
  15002. return a != null ? Math.round(a * 100) / 100 : 1;
  15003. },
  15004. getColor: (c, v) => ({
  15005. ...c,
  15006. a: Number(v)
  15007. })
  15008. }],
  15009. to: HSVtoHSL,
  15010. from: HSLtoHSV
  15011. };
  15012. const hsl = {
  15013. ...hsla,
  15014. inputs: hsla.inputs.slice(0, 3)
  15015. };
  15016. const hexa = {
  15017. inputProps: {
  15018. type: 'text'
  15019. },
  15020. inputs: [{
  15021. label: 'HEXA',
  15022. getValue: c => c,
  15023. getColor: (c, v) => v
  15024. }],
  15025. to: HSVtoHex,
  15026. from: HexToHSV
  15027. };
  15028. const hex = {
  15029. ...hexa,
  15030. inputs: [{
  15031. label: 'HEX',
  15032. getValue: c => c.slice(0, 7),
  15033. getColor: (c, v) => v
  15034. }]
  15035. };
  15036. const modes = {
  15037. rgb,
  15038. rgba,
  15039. hsl,
  15040. hsla,
  15041. hex,
  15042. hexa
  15043. };
  15044. // Types
  15045. const VColorPickerInput = _ref => {
  15046. let {
  15047. label,
  15048. ...rest
  15049. } = _ref;
  15050. return vue.createVNode("div", {
  15051. "class": "v-color-picker-edit__input"
  15052. }, [vue.createVNode("input", rest, null), vue.createVNode("span", null, [label])]);
  15053. };
  15054. const makeVColorPickerEditProps = propsFactory({
  15055. color: Object,
  15056. disabled: Boolean,
  15057. mode: {
  15058. type: String,
  15059. default: 'rgba',
  15060. validator: v => Object.keys(modes).includes(v)
  15061. },
  15062. modes: {
  15063. type: Array,
  15064. default: () => Object.keys(modes),
  15065. validator: v => Array.isArray(v) && v.every(m => Object.keys(modes).includes(m))
  15066. },
  15067. ...makeComponentProps()
  15068. }, 'VColorPickerEdit');
  15069. const VColorPickerEdit = defineComponent({
  15070. name: 'VColorPickerEdit',
  15071. props: makeVColorPickerEditProps(),
  15072. emits: {
  15073. 'update:color': color => true,
  15074. 'update:mode': mode => true
  15075. },
  15076. setup(props, _ref2) {
  15077. let {
  15078. emit
  15079. } = _ref2;
  15080. const enabledModes = vue.computed(() => {
  15081. return props.modes.map(key => ({
  15082. ...modes[key],
  15083. name: key
  15084. }));
  15085. });
  15086. const inputs = vue.computed(() => {
  15087. const mode = enabledModes.value.find(m => m.name === props.mode);
  15088. if (!mode) return [];
  15089. const color = props.color ? mode.to(props.color) : null;
  15090. return mode.inputs?.map(_ref3 => {
  15091. let {
  15092. getValue,
  15093. getColor,
  15094. ...inputProps
  15095. } = _ref3;
  15096. return {
  15097. ...mode.inputProps,
  15098. ...inputProps,
  15099. disabled: props.disabled,
  15100. value: color && getValue(color),
  15101. onChange: e => {
  15102. const target = e.target;
  15103. if (!target) return;
  15104. emit('update:color', mode.from(getColor(color ?? mode.to(nullColor), target.value)));
  15105. }
  15106. };
  15107. });
  15108. });
  15109. useRender(() => vue.createVNode("div", {
  15110. "class": ['v-color-picker-edit', props.class],
  15111. "style": props.style
  15112. }, [inputs.value?.map(props => vue.createVNode(VColorPickerInput, props, null)), enabledModes.value.length > 1 && vue.createVNode(VBtn, {
  15113. "icon": "$unfold",
  15114. "size": "x-small",
  15115. "variant": "plain",
  15116. "onClick": () => {
  15117. const mi = enabledModes.value.findIndex(m => m.name === props.mode);
  15118. emit('update:mode', enabledModes.value[(mi + 1) % enabledModes.value.length].name);
  15119. }
  15120. }, null)]));
  15121. return {};
  15122. }
  15123. });
  15124. /* eslint-disable max-statements */
  15125. // Composables
  15126. // Types
  15127. const VSliderSymbol = Symbol.for('vuetify:v-slider');
  15128. function getOffset(e, el, direction) {
  15129. const vertical = direction === 'vertical';
  15130. const rect = el.getBoundingClientRect();
  15131. const touch = 'touches' in e ? e.touches[0] : e;
  15132. return vertical ? touch.clientY - (rect.top + rect.height / 2) : touch.clientX - (rect.left + rect.width / 2);
  15133. }
  15134. function getPosition(e, position) {
  15135. 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];
  15136. }
  15137. const makeSliderProps = propsFactory({
  15138. disabled: {
  15139. type: Boolean,
  15140. default: null
  15141. },
  15142. error: Boolean,
  15143. readonly: {
  15144. type: Boolean,
  15145. default: null
  15146. },
  15147. max: {
  15148. type: [Number, String],
  15149. default: 100
  15150. },
  15151. min: {
  15152. type: [Number, String],
  15153. default: 0
  15154. },
  15155. step: {
  15156. type: [Number, String],
  15157. default: 0
  15158. },
  15159. thumbColor: String,
  15160. thumbLabel: {
  15161. type: [Boolean, String],
  15162. default: undefined,
  15163. validator: v => typeof v === 'boolean' || v === 'always'
  15164. },
  15165. thumbSize: {
  15166. type: [Number, String],
  15167. default: 20
  15168. },
  15169. showTicks: {
  15170. type: [Boolean, String],
  15171. default: false,
  15172. validator: v => typeof v === 'boolean' || v === 'always'
  15173. },
  15174. ticks: {
  15175. type: [Array, Object]
  15176. },
  15177. tickSize: {
  15178. type: [Number, String],
  15179. default: 2
  15180. },
  15181. color: String,
  15182. trackColor: String,
  15183. trackFillColor: String,
  15184. trackSize: {
  15185. type: [Number, String],
  15186. default: 4
  15187. },
  15188. direction: {
  15189. type: String,
  15190. default: 'horizontal',
  15191. validator: v => ['vertical', 'horizontal'].includes(v)
  15192. },
  15193. reverse: Boolean,
  15194. ...makeRoundedProps(),
  15195. ...makeElevationProps({
  15196. elevation: 2
  15197. }),
  15198. ripple: {
  15199. type: Boolean,
  15200. default: true
  15201. }
  15202. }, 'Slider');
  15203. const useSteps = props => {
  15204. const min = vue.computed(() => parseFloat(props.min));
  15205. const max = vue.computed(() => parseFloat(props.max));
  15206. const step = vue.computed(() => +props.step > 0 ? parseFloat(props.step) : 0);
  15207. const decimals = vue.computed(() => Math.max(getDecimals(step.value), getDecimals(min.value)));
  15208. function roundValue(value) {
  15209. value = parseFloat(value);
  15210. if (step.value <= 0) return value;
  15211. const clamped = clamp(value, min.value, max.value);
  15212. const offset = min.value % step.value;
  15213. const newValue = Math.round((clamped - offset) / step.value) * step.value + offset;
  15214. return parseFloat(Math.min(newValue, max.value).toFixed(decimals.value));
  15215. }
  15216. return {
  15217. min,
  15218. max,
  15219. step,
  15220. decimals,
  15221. roundValue
  15222. };
  15223. };
  15224. const useSlider = _ref => {
  15225. let {
  15226. props,
  15227. steps,
  15228. onSliderStart,
  15229. onSliderMove,
  15230. onSliderEnd,
  15231. getActiveThumb
  15232. } = _ref;
  15233. const {
  15234. isRtl
  15235. } = useRtl();
  15236. const isReversed = vue.toRef(props, 'reverse');
  15237. const vertical = vue.computed(() => props.direction === 'vertical');
  15238. const indexFromEnd = vue.computed(() => vertical.value !== isReversed.value);
  15239. const {
  15240. min,
  15241. max,
  15242. step,
  15243. decimals,
  15244. roundValue
  15245. } = steps;
  15246. const thumbSize = vue.computed(() => parseInt(props.thumbSize, 10));
  15247. const tickSize = vue.computed(() => parseInt(props.tickSize, 10));
  15248. const trackSize = vue.computed(() => parseInt(props.trackSize, 10));
  15249. const numTicks = vue.computed(() => (max.value - min.value) / step.value);
  15250. const disabled = vue.toRef(props, 'disabled');
  15251. const thumbColor = vue.computed(() => props.error || props.disabled ? undefined : props.thumbColor ?? props.color);
  15252. const trackColor = vue.computed(() => props.error || props.disabled ? undefined : props.trackColor ?? props.color);
  15253. const trackFillColor = vue.computed(() => props.error || props.disabled ? undefined : props.trackFillColor ?? props.color);
  15254. const mousePressed = vue.shallowRef(false);
  15255. const startOffset = vue.shallowRef(0);
  15256. const trackContainerRef = vue.ref();
  15257. const activeThumbRef = vue.ref();
  15258. function parseMouseMove(e) {
  15259. const vertical = props.direction === 'vertical';
  15260. const start = vertical ? 'top' : 'left';
  15261. const length = vertical ? 'height' : 'width';
  15262. const position = vertical ? 'clientY' : 'clientX';
  15263. const {
  15264. [start]: trackStart,
  15265. [length]: trackLength
  15266. } = trackContainerRef.value?.$el.getBoundingClientRect();
  15267. const clickOffset = getPosition(e, position);
  15268. // It is possible for left to be NaN, force to number
  15269. let clickPos = Math.min(Math.max((clickOffset - trackStart - startOffset.value) / trackLength, 0), 1) || 0;
  15270. if (vertical ? indexFromEnd.value : indexFromEnd.value !== isRtl.value) clickPos = 1 - clickPos;
  15271. return roundValue(min.value + clickPos * (max.value - min.value));
  15272. }
  15273. const handleStop = e => {
  15274. onSliderEnd({
  15275. value: parseMouseMove(e)
  15276. });
  15277. mousePressed.value = false;
  15278. startOffset.value = 0;
  15279. };
  15280. const handleStart = e => {
  15281. activeThumbRef.value = getActiveThumb(e);
  15282. if (!activeThumbRef.value) return;
  15283. activeThumbRef.value.focus();
  15284. mousePressed.value = true;
  15285. if (activeThumbRef.value.contains(e.target)) {
  15286. startOffset.value = getOffset(e, activeThumbRef.value, props.direction);
  15287. } else {
  15288. startOffset.value = 0;
  15289. onSliderMove({
  15290. value: parseMouseMove(e)
  15291. });
  15292. }
  15293. onSliderStart({
  15294. value: parseMouseMove(e)
  15295. });
  15296. };
  15297. const moveListenerOptions = {
  15298. passive: true,
  15299. capture: true
  15300. };
  15301. function onMouseMove(e) {
  15302. onSliderMove({
  15303. value: parseMouseMove(e)
  15304. });
  15305. }
  15306. function onSliderMouseUp(e) {
  15307. e.stopPropagation();
  15308. e.preventDefault();
  15309. handleStop(e);
  15310. window.removeEventListener('mousemove', onMouseMove, moveListenerOptions);
  15311. window.removeEventListener('mouseup', onSliderMouseUp);
  15312. }
  15313. function onSliderTouchend(e) {
  15314. handleStop(e);
  15315. window.removeEventListener('touchmove', onMouseMove, moveListenerOptions);
  15316. e.target?.removeEventListener('touchend', onSliderTouchend);
  15317. }
  15318. function onSliderTouchstart(e) {
  15319. handleStart(e);
  15320. window.addEventListener('touchmove', onMouseMove, moveListenerOptions);
  15321. e.target?.addEventListener('touchend', onSliderTouchend, {
  15322. passive: false
  15323. });
  15324. }
  15325. function onSliderMousedown(e) {
  15326. e.preventDefault();
  15327. handleStart(e);
  15328. window.addEventListener('mousemove', onMouseMove, moveListenerOptions);
  15329. window.addEventListener('mouseup', onSliderMouseUp, {
  15330. passive: false
  15331. });
  15332. }
  15333. const position = val => {
  15334. const percentage = (val - min.value) / (max.value - min.value) * 100;
  15335. return clamp(isNaN(percentage) ? 0 : percentage, 0, 100);
  15336. };
  15337. const showTicks = vue.toRef(props, 'showTicks');
  15338. const parsedTicks = vue.computed(() => {
  15339. if (!showTicks.value) return [];
  15340. if (!props.ticks) {
  15341. return numTicks.value !== Infinity ? createRange(numTicks.value + 1).map(t => {
  15342. const value = min.value + t * step.value;
  15343. return {
  15344. value,
  15345. position: position(value)
  15346. };
  15347. }) : [];
  15348. }
  15349. if (Array.isArray(props.ticks)) return props.ticks.map(t => ({
  15350. value: t,
  15351. position: position(t),
  15352. label: t.toString()
  15353. }));
  15354. return Object.keys(props.ticks).map(key => ({
  15355. value: parseFloat(key),
  15356. position: position(parseFloat(key)),
  15357. label: props.ticks[key]
  15358. }));
  15359. });
  15360. const hasLabels = vue.computed(() => parsedTicks.value.some(_ref2 => {
  15361. let {
  15362. label
  15363. } = _ref2;
  15364. return !!label;
  15365. }));
  15366. const data = {
  15367. activeThumbRef,
  15368. color: vue.toRef(props, 'color'),
  15369. decimals,
  15370. disabled,
  15371. direction: vue.toRef(props, 'direction'),
  15372. elevation: vue.toRef(props, 'elevation'),
  15373. hasLabels,
  15374. isReversed,
  15375. indexFromEnd,
  15376. min,
  15377. max,
  15378. mousePressed,
  15379. numTicks,
  15380. onSliderMousedown,
  15381. onSliderTouchstart,
  15382. parsedTicks,
  15383. parseMouseMove,
  15384. position,
  15385. readonly: vue.toRef(props, 'readonly'),
  15386. rounded: vue.toRef(props, 'rounded'),
  15387. roundValue,
  15388. showTicks,
  15389. startOffset,
  15390. step,
  15391. thumbSize,
  15392. thumbColor,
  15393. thumbLabel: vue.toRef(props, 'thumbLabel'),
  15394. ticks: vue.toRef(props, 'ticks'),
  15395. tickSize,
  15396. trackColor,
  15397. trackContainerRef,
  15398. trackFillColor,
  15399. trackSize,
  15400. vertical
  15401. };
  15402. vue.provide(VSliderSymbol, data);
  15403. return data;
  15404. };
  15405. // Types
  15406. const makeVSliderThumbProps = propsFactory({
  15407. focused: Boolean,
  15408. max: {
  15409. type: Number,
  15410. required: true
  15411. },
  15412. min: {
  15413. type: Number,
  15414. required: true
  15415. },
  15416. modelValue: {
  15417. type: Number,
  15418. required: true
  15419. },
  15420. position: {
  15421. type: Number,
  15422. required: true
  15423. },
  15424. ripple: {
  15425. type: [Boolean, Object],
  15426. default: true
  15427. },
  15428. name: String,
  15429. ...makeComponentProps()
  15430. }, 'VSliderThumb');
  15431. const VSliderThumb = genericComponent()({
  15432. name: 'VSliderThumb',
  15433. directives: {
  15434. Ripple
  15435. },
  15436. props: makeVSliderThumbProps(),
  15437. emits: {
  15438. 'update:modelValue': v => true
  15439. },
  15440. setup(props, _ref) {
  15441. let {
  15442. slots,
  15443. emit
  15444. } = _ref;
  15445. const slider = vue.inject(VSliderSymbol);
  15446. const {
  15447. isRtl,
  15448. rtlClasses
  15449. } = useRtl();
  15450. if (!slider) throw new Error('[Vuetify] v-slider-thumb must be used inside v-slider or v-range-slider');
  15451. const {
  15452. thumbColor,
  15453. step,
  15454. disabled,
  15455. thumbSize,
  15456. thumbLabel,
  15457. direction,
  15458. isReversed,
  15459. vertical,
  15460. readonly,
  15461. elevation,
  15462. mousePressed,
  15463. decimals,
  15464. indexFromEnd
  15465. } = slider;
  15466. const elevationProps = vue.computed(() => !disabled.value ? elevation.value : undefined);
  15467. const {
  15468. elevationClasses
  15469. } = useElevation(elevationProps);
  15470. const {
  15471. textColorClasses,
  15472. textColorStyles
  15473. } = useTextColor(thumbColor);
  15474. const {
  15475. pageup,
  15476. pagedown,
  15477. end,
  15478. home,
  15479. left,
  15480. right,
  15481. down,
  15482. up
  15483. } = keyValues;
  15484. const relevantKeys = [pageup, pagedown, end, home, left, right, down, up];
  15485. const multipliers = vue.computed(() => {
  15486. if (step.value) return [1, 2, 3];else return [1, 5, 10];
  15487. });
  15488. function parseKeydown(e, value) {
  15489. if (!relevantKeys.includes(e.key)) return;
  15490. e.preventDefault();
  15491. const _step = step.value || 0.1;
  15492. const steps = (props.max - props.min) / _step;
  15493. if ([left, right, down, up].includes(e.key)) {
  15494. const increase = vertical.value ? [isRtl.value ? left : right, isReversed.value ? down : up] : indexFromEnd.value !== isRtl.value ? [left, up] : [right, up];
  15495. const direction = increase.includes(e.key) ? 1 : -1;
  15496. const multiplier = e.shiftKey ? 2 : e.ctrlKey ? 1 : 0;
  15497. value = value + direction * _step * multipliers.value[multiplier];
  15498. } else if (e.key === home) {
  15499. value = props.min;
  15500. } else if (e.key === end) {
  15501. value = props.max;
  15502. } else {
  15503. const direction = e.key === pagedown ? 1 : -1;
  15504. value = value - direction * _step * (steps > 100 ? steps / 10 : 10);
  15505. }
  15506. return Math.max(props.min, Math.min(props.max, value));
  15507. }
  15508. function onKeydown(e) {
  15509. const newValue = parseKeydown(e, props.modelValue);
  15510. newValue != null && emit('update:modelValue', newValue);
  15511. }
  15512. useRender(() => {
  15513. const positionPercentage = convertToUnit(indexFromEnd.value ? 100 - props.position : props.position, '%');
  15514. return vue.createVNode("div", {
  15515. "class": ['v-slider-thumb', {
  15516. 'v-slider-thumb--focused': props.focused,
  15517. 'v-slider-thumb--pressed': props.focused && mousePressed.value
  15518. }, props.class, rtlClasses.value],
  15519. "style": [{
  15520. '--v-slider-thumb-position': positionPercentage,
  15521. '--v-slider-thumb-size': convertToUnit(thumbSize.value)
  15522. }, props.style],
  15523. "role": "slider",
  15524. "tabindex": disabled.value ? -1 : 0,
  15525. "aria-label": props.name,
  15526. "aria-valuemin": props.min,
  15527. "aria-valuemax": props.max,
  15528. "aria-valuenow": props.modelValue,
  15529. "aria-readonly": !!readonly.value,
  15530. "aria-orientation": direction.value,
  15531. "onKeydown": !readonly.value ? onKeydown : undefined
  15532. }, [vue.createVNode("div", {
  15533. "class": ['v-slider-thumb__surface', textColorClasses.value, elevationClasses.value],
  15534. "style": {
  15535. ...textColorStyles.value
  15536. }
  15537. }, null), vue.withDirectives(vue.createVNode("div", {
  15538. "class": ['v-slider-thumb__ripple', textColorClasses.value],
  15539. "style": textColorStyles.value
  15540. }, null), [[vue.resolveDirective("ripple"), props.ripple, null, {
  15541. circle: true,
  15542. center: true
  15543. }]]), vue.createVNode(VScaleTransition, {
  15544. "origin": "bottom center"
  15545. }, {
  15546. default: () => [vue.withDirectives(vue.createVNode("div", {
  15547. "class": "v-slider-thumb__label-container"
  15548. }, [vue.createVNode("div", {
  15549. "class": ['v-slider-thumb__label']
  15550. }, [vue.createVNode("div", null, [slots['thumb-label']?.({
  15551. modelValue: props.modelValue
  15552. }) ?? props.modelValue.toFixed(step.value ? decimals.value : 1)])])]), [[vue.vShow, thumbLabel.value && props.focused || thumbLabel.value === 'always']])]
  15553. })]);
  15554. });
  15555. return {};
  15556. }
  15557. });
  15558. // Types
  15559. const makeVSliderTrackProps = propsFactory({
  15560. start: {
  15561. type: Number,
  15562. required: true
  15563. },
  15564. stop: {
  15565. type: Number,
  15566. required: true
  15567. },
  15568. ...makeComponentProps()
  15569. }, 'VSliderTrack');
  15570. const VSliderTrack = genericComponent()({
  15571. name: 'VSliderTrack',
  15572. props: makeVSliderTrackProps(),
  15573. emits: {},
  15574. setup(props, _ref) {
  15575. let {
  15576. slots
  15577. } = _ref;
  15578. const slider = vue.inject(VSliderSymbol);
  15579. if (!slider) throw new Error('[Vuetify] v-slider-track must be inside v-slider or v-range-slider');
  15580. const {
  15581. color,
  15582. parsedTicks,
  15583. rounded,
  15584. showTicks,
  15585. tickSize,
  15586. trackColor,
  15587. trackFillColor,
  15588. trackSize,
  15589. vertical,
  15590. min,
  15591. max,
  15592. indexFromEnd
  15593. } = slider;
  15594. const {
  15595. roundedClasses
  15596. } = useRounded(rounded);
  15597. const {
  15598. backgroundColorClasses: trackFillColorClasses,
  15599. backgroundColorStyles: trackFillColorStyles
  15600. } = useBackgroundColor(trackFillColor);
  15601. const {
  15602. backgroundColorClasses: trackColorClasses,
  15603. backgroundColorStyles: trackColorStyles
  15604. } = useBackgroundColor(trackColor);
  15605. const startDir = vue.computed(() => `inset-${vertical.value ? 'block' : 'inline'}-${indexFromEnd.value ? 'end' : 'start'}`);
  15606. const endDir = vue.computed(() => vertical.value ? 'height' : 'width');
  15607. const backgroundStyles = vue.computed(() => {
  15608. return {
  15609. [startDir.value]: '0%',
  15610. [endDir.value]: '100%'
  15611. };
  15612. });
  15613. const trackFillWidth = vue.computed(() => props.stop - props.start);
  15614. const trackFillStyles = vue.computed(() => {
  15615. return {
  15616. [startDir.value]: convertToUnit(props.start, '%'),
  15617. [endDir.value]: convertToUnit(trackFillWidth.value, '%')
  15618. };
  15619. });
  15620. const computedTicks = vue.computed(() => {
  15621. if (!showTicks.value) return [];
  15622. const ticks = vertical.value ? parsedTicks.value.slice().reverse() : parsedTicks.value;
  15623. return ticks.map((tick, index) => {
  15624. const directionValue = tick.value !== min.value && tick.value !== max.value ? convertToUnit(tick.position, '%') : undefined;
  15625. return vue.createVNode("div", {
  15626. "key": tick.value,
  15627. "class": ['v-slider-track__tick', {
  15628. 'v-slider-track__tick--filled': tick.position >= props.start && tick.position <= props.stop,
  15629. 'v-slider-track__tick--first': tick.value === min.value,
  15630. 'v-slider-track__tick--last': tick.value === max.value
  15631. }],
  15632. "style": {
  15633. [startDir.value]: directionValue
  15634. }
  15635. }, [(tick.label || slots['tick-label']) && vue.createVNode("div", {
  15636. "class": "v-slider-track__tick-label"
  15637. }, [slots['tick-label']?.({
  15638. tick,
  15639. index
  15640. }) ?? tick.label])]);
  15641. });
  15642. });
  15643. useRender(() => {
  15644. return vue.createVNode("div", {
  15645. "class": ['v-slider-track', roundedClasses.value, props.class],
  15646. "style": [{
  15647. '--v-slider-track-size': convertToUnit(trackSize.value),
  15648. '--v-slider-tick-size': convertToUnit(tickSize.value)
  15649. }, props.style]
  15650. }, [vue.createVNode("div", {
  15651. "class": ['v-slider-track__background', trackColorClasses.value, {
  15652. 'v-slider-track__background--opacity': !!color.value || !trackFillColor.value
  15653. }],
  15654. "style": {
  15655. ...backgroundStyles.value,
  15656. ...trackColorStyles.value
  15657. }
  15658. }, null), vue.createVNode("div", {
  15659. "class": ['v-slider-track__fill', trackFillColorClasses.value],
  15660. "style": {
  15661. ...trackFillStyles.value,
  15662. ...trackFillColorStyles.value
  15663. }
  15664. }, null), showTicks.value && vue.createVNode("div", {
  15665. "class": ['v-slider-track__ticks', {
  15666. 'v-slider-track__ticks--always-show': showTicks.value === 'always'
  15667. }]
  15668. }, [computedTicks.value])]);
  15669. });
  15670. return {};
  15671. }
  15672. });
  15673. // Types
  15674. const makeVSliderProps = propsFactory({
  15675. ...makeFocusProps(),
  15676. ...makeSliderProps(),
  15677. ...makeVInputProps(),
  15678. modelValue: {
  15679. type: [Number, String],
  15680. default: 0
  15681. }
  15682. }, 'VSlider');
  15683. const VSlider = genericComponent()({
  15684. name: 'VSlider',
  15685. props: makeVSliderProps(),
  15686. emits: {
  15687. 'update:focused': value => true,
  15688. 'update:modelValue': v => true,
  15689. start: value => true,
  15690. end: value => true
  15691. },
  15692. setup(props, _ref) {
  15693. let {
  15694. slots,
  15695. emit
  15696. } = _ref;
  15697. const thumbContainerRef = vue.ref();
  15698. const {
  15699. rtlClasses
  15700. } = useRtl();
  15701. const steps = useSteps(props);
  15702. const model = useProxiedModel(props, 'modelValue', undefined, value => {
  15703. return steps.roundValue(value == null ? steps.min.value : value);
  15704. });
  15705. const {
  15706. min,
  15707. max,
  15708. mousePressed,
  15709. roundValue,
  15710. onSliderMousedown,
  15711. onSliderTouchstart,
  15712. trackContainerRef,
  15713. position,
  15714. hasLabels,
  15715. readonly
  15716. } = useSlider({
  15717. props,
  15718. steps,
  15719. onSliderStart: () => {
  15720. emit('start', model.value);
  15721. },
  15722. onSliderEnd: _ref2 => {
  15723. let {
  15724. value
  15725. } = _ref2;
  15726. const roundedValue = roundValue(value);
  15727. model.value = roundedValue;
  15728. emit('end', roundedValue);
  15729. },
  15730. onSliderMove: _ref3 => {
  15731. let {
  15732. value
  15733. } = _ref3;
  15734. return model.value = roundValue(value);
  15735. },
  15736. getActiveThumb: () => thumbContainerRef.value?.$el
  15737. });
  15738. const {
  15739. isFocused,
  15740. focus,
  15741. blur
  15742. } = useFocus(props);
  15743. const trackStop = vue.computed(() => position(model.value));
  15744. useRender(() => {
  15745. const inputProps = VInput.filterProps(props);
  15746. const hasPrepend = !!(props.label || slots.label || slots.prepend);
  15747. return vue.createVNode(VInput, vue.mergeProps({
  15748. "class": ['v-slider', {
  15749. 'v-slider--has-labels': !!slots['tick-label'] || hasLabels.value,
  15750. 'v-slider--focused': isFocused.value,
  15751. 'v-slider--pressed': mousePressed.value,
  15752. 'v-slider--disabled': props.disabled
  15753. }, rtlClasses.value, props.class],
  15754. "style": props.style
  15755. }, inputProps, {
  15756. "focused": isFocused.value
  15757. }), {
  15758. ...slots,
  15759. prepend: hasPrepend ? slotProps => vue.createVNode(vue.Fragment, null, [slots.label?.(slotProps) ?? (props.label ? vue.createVNode(VLabel, {
  15760. "id": slotProps.id.value,
  15761. "class": "v-slider__label",
  15762. "text": props.label
  15763. }, null) : undefined), slots.prepend?.(slotProps)]) : undefined,
  15764. default: _ref4 => {
  15765. let {
  15766. id,
  15767. messagesId
  15768. } = _ref4;
  15769. return vue.createVNode("div", {
  15770. "class": "v-slider__container",
  15771. "onMousedown": !readonly.value ? onSliderMousedown : undefined,
  15772. "onTouchstartPassive": !readonly.value ? onSliderTouchstart : undefined
  15773. }, [vue.createVNode("input", {
  15774. "id": id.value,
  15775. "name": props.name || id.value,
  15776. "disabled": !!props.disabled,
  15777. "readonly": !!props.readonly,
  15778. "tabindex": "-1",
  15779. "value": model.value
  15780. }, null), vue.createVNode(VSliderTrack, {
  15781. "ref": trackContainerRef,
  15782. "start": 0,
  15783. "stop": trackStop.value
  15784. }, {
  15785. 'tick-label': slots['tick-label']
  15786. }), vue.createVNode(VSliderThumb, {
  15787. "ref": thumbContainerRef,
  15788. "aria-describedby": messagesId.value,
  15789. "focused": isFocused.value,
  15790. "min": min.value,
  15791. "max": max.value,
  15792. "modelValue": model.value,
  15793. "onUpdate:modelValue": v => model.value = v,
  15794. "position": trackStop.value,
  15795. "elevation": props.elevation,
  15796. "onFocus": focus,
  15797. "onBlur": blur,
  15798. "ripple": props.ripple,
  15799. "name": props.name
  15800. }, {
  15801. 'thumb-label': slots['thumb-label']
  15802. })]);
  15803. }
  15804. });
  15805. });
  15806. return {};
  15807. }
  15808. });
  15809. // Types
  15810. const makeVColorPickerPreviewProps = propsFactory({
  15811. color: {
  15812. type: Object
  15813. },
  15814. disabled: Boolean,
  15815. hideAlpha: Boolean,
  15816. ...makeComponentProps()
  15817. }, 'VColorPickerPreview');
  15818. const VColorPickerPreview = defineComponent({
  15819. name: 'VColorPickerPreview',
  15820. props: makeVColorPickerPreviewProps(),
  15821. emits: {
  15822. 'update:color': color => true
  15823. },
  15824. setup(props, _ref) {
  15825. let {
  15826. emit
  15827. } = _ref;
  15828. const abortController = new AbortController();
  15829. vue.onUnmounted(() => abortController.abort());
  15830. async function openEyeDropper() {
  15831. if (!SUPPORTS_EYE_DROPPER) return;
  15832. const eyeDropper = new window.EyeDropper();
  15833. try {
  15834. const result = await eyeDropper.open({
  15835. signal: abortController.signal
  15836. });
  15837. const colorHexValue = HexToHSV(result.sRGBHex);
  15838. emit('update:color', {
  15839. ...(props.color ?? nullColor),
  15840. ...colorHexValue
  15841. });
  15842. } catch (e) {}
  15843. }
  15844. useRender(() => vue.createVNode("div", {
  15845. "class": ['v-color-picker-preview', {
  15846. 'v-color-picker-preview--hide-alpha': props.hideAlpha
  15847. }, props.class],
  15848. "style": props.style
  15849. }, [SUPPORTS_EYE_DROPPER && vue.createVNode("div", {
  15850. "class": "v-color-picker-preview__eye-dropper",
  15851. "key": "eyeDropper"
  15852. }, [vue.createVNode(VBtn, {
  15853. "onClick": openEyeDropper,
  15854. "icon": "$eyeDropper",
  15855. "variant": "plain",
  15856. "density": "comfortable"
  15857. }, null)]), vue.createVNode("div", {
  15858. "class": "v-color-picker-preview__dot"
  15859. }, [vue.createVNode("div", {
  15860. "style": {
  15861. background: HSVtoCSS(props.color ?? nullColor)
  15862. }
  15863. }, null)]), vue.createVNode("div", {
  15864. "class": "v-color-picker-preview__sliders"
  15865. }, [vue.createVNode(VSlider, {
  15866. "class": "v-color-picker-preview__track v-color-picker-preview__hue",
  15867. "modelValue": props.color?.h,
  15868. "onUpdate:modelValue": h => emit('update:color', {
  15869. ...(props.color ?? nullColor),
  15870. h
  15871. }),
  15872. "step": 0,
  15873. "min": 0,
  15874. "max": 360,
  15875. "disabled": props.disabled,
  15876. "thumbSize": 14,
  15877. "trackSize": 8,
  15878. "trackFillColor": "white",
  15879. "hideDetails": true
  15880. }, null), !props.hideAlpha && vue.createVNode(VSlider, {
  15881. "class": "v-color-picker-preview__track v-color-picker-preview__alpha",
  15882. "modelValue": props.color?.a ?? 1,
  15883. "onUpdate:modelValue": a => emit('update:color', {
  15884. ...(props.color ?? nullColor),
  15885. a
  15886. }),
  15887. "step": 1 / 256,
  15888. "min": 0,
  15889. "max": 1,
  15890. "disabled": props.disabled,
  15891. "thumbSize": 14,
  15892. "trackSize": 8,
  15893. "trackFillColor": "white",
  15894. "hideDetails": true
  15895. }, null)])]));
  15896. return {};
  15897. }
  15898. });
  15899. const red = {
  15900. base: '#f44336',
  15901. lighten5: '#ffebee',
  15902. lighten4: '#ffcdd2',
  15903. lighten3: '#ef9a9a',
  15904. lighten2: '#e57373',
  15905. lighten1: '#ef5350',
  15906. darken1: '#e53935',
  15907. darken2: '#d32f2f',
  15908. darken3: '#c62828',
  15909. darken4: '#b71c1c',
  15910. accent1: '#ff8a80',
  15911. accent2: '#ff5252',
  15912. accent3: '#ff1744',
  15913. accent4: '#d50000'
  15914. };
  15915. const pink = {
  15916. base: '#e91e63',
  15917. lighten5: '#fce4ec',
  15918. lighten4: '#f8bbd0',
  15919. lighten3: '#f48fb1',
  15920. lighten2: '#f06292',
  15921. lighten1: '#ec407a',
  15922. darken1: '#d81b60',
  15923. darken2: '#c2185b',
  15924. darken3: '#ad1457',
  15925. darken4: '#880e4f',
  15926. accent1: '#ff80ab',
  15927. accent2: '#ff4081',
  15928. accent3: '#f50057',
  15929. accent4: '#c51162'
  15930. };
  15931. const purple = {
  15932. base: '#9c27b0',
  15933. lighten5: '#f3e5f5',
  15934. lighten4: '#e1bee7',
  15935. lighten3: '#ce93d8',
  15936. lighten2: '#ba68c8',
  15937. lighten1: '#ab47bc',
  15938. darken1: '#8e24aa',
  15939. darken2: '#7b1fa2',
  15940. darken3: '#6a1b9a',
  15941. darken4: '#4a148c',
  15942. accent1: '#ea80fc',
  15943. accent2: '#e040fb',
  15944. accent3: '#d500f9',
  15945. accent4: '#aa00ff'
  15946. };
  15947. const deepPurple = {
  15948. base: '#673ab7',
  15949. lighten5: '#ede7f6',
  15950. lighten4: '#d1c4e9',
  15951. lighten3: '#b39ddb',
  15952. lighten2: '#9575cd',
  15953. lighten1: '#7e57c2',
  15954. darken1: '#5e35b1',
  15955. darken2: '#512da8',
  15956. darken3: '#4527a0',
  15957. darken4: '#311b92',
  15958. accent1: '#b388ff',
  15959. accent2: '#7c4dff',
  15960. accent3: '#651fff',
  15961. accent4: '#6200ea'
  15962. };
  15963. const indigo = {
  15964. base: '#3f51b5',
  15965. lighten5: '#e8eaf6',
  15966. lighten4: '#c5cae9',
  15967. lighten3: '#9fa8da',
  15968. lighten2: '#7986cb',
  15969. lighten1: '#5c6bc0',
  15970. darken1: '#3949ab',
  15971. darken2: '#303f9f',
  15972. darken3: '#283593',
  15973. darken4: '#1a237e',
  15974. accent1: '#8c9eff',
  15975. accent2: '#536dfe',
  15976. accent3: '#3d5afe',
  15977. accent4: '#304ffe'
  15978. };
  15979. const blue = {
  15980. base: '#2196f3',
  15981. lighten5: '#e3f2fd',
  15982. lighten4: '#bbdefb',
  15983. lighten3: '#90caf9',
  15984. lighten2: '#64b5f6',
  15985. lighten1: '#42a5f5',
  15986. darken1: '#1e88e5',
  15987. darken2: '#1976d2',
  15988. darken3: '#1565c0',
  15989. darken4: '#0d47a1',
  15990. accent1: '#82b1ff',
  15991. accent2: '#448aff',
  15992. accent3: '#2979ff',
  15993. accent4: '#2962ff'
  15994. };
  15995. const lightBlue = {
  15996. base: '#03a9f4',
  15997. lighten5: '#e1f5fe',
  15998. lighten4: '#b3e5fc',
  15999. lighten3: '#81d4fa',
  16000. lighten2: '#4fc3f7',
  16001. lighten1: '#29b6f6',
  16002. darken1: '#039be5',
  16003. darken2: '#0288d1',
  16004. darken3: '#0277bd',
  16005. darken4: '#01579b',
  16006. accent1: '#80d8ff',
  16007. accent2: '#40c4ff',
  16008. accent3: '#00b0ff',
  16009. accent4: '#0091ea'
  16010. };
  16011. const cyan = {
  16012. base: '#00bcd4',
  16013. lighten5: '#e0f7fa',
  16014. lighten4: '#b2ebf2',
  16015. lighten3: '#80deea',
  16016. lighten2: '#4dd0e1',
  16017. lighten1: '#26c6da',
  16018. darken1: '#00acc1',
  16019. darken2: '#0097a7',
  16020. darken3: '#00838f',
  16021. darken4: '#006064',
  16022. accent1: '#84ffff',
  16023. accent2: '#18ffff',
  16024. accent3: '#00e5ff',
  16025. accent4: '#00b8d4'
  16026. };
  16027. const teal = {
  16028. base: '#009688',
  16029. lighten5: '#e0f2f1',
  16030. lighten4: '#b2dfdb',
  16031. lighten3: '#80cbc4',
  16032. lighten2: '#4db6ac',
  16033. lighten1: '#26a69a',
  16034. darken1: '#00897b',
  16035. darken2: '#00796b',
  16036. darken3: '#00695c',
  16037. darken4: '#004d40',
  16038. accent1: '#a7ffeb',
  16039. accent2: '#64ffda',
  16040. accent3: '#1de9b6',
  16041. accent4: '#00bfa5'
  16042. };
  16043. const green = {
  16044. base: '#4caf50',
  16045. lighten5: '#e8f5e9',
  16046. lighten4: '#c8e6c9',
  16047. lighten3: '#a5d6a7',
  16048. lighten2: '#81c784',
  16049. lighten1: '#66bb6a',
  16050. darken1: '#43a047',
  16051. darken2: '#388e3c',
  16052. darken3: '#2e7d32',
  16053. darken4: '#1b5e20',
  16054. accent1: '#b9f6ca',
  16055. accent2: '#69f0ae',
  16056. accent3: '#00e676',
  16057. accent4: '#00c853'
  16058. };
  16059. const lightGreen = {
  16060. base: '#8bc34a',
  16061. lighten5: '#f1f8e9',
  16062. lighten4: '#dcedc8',
  16063. lighten3: '#c5e1a5',
  16064. lighten2: '#aed581',
  16065. lighten1: '#9ccc65',
  16066. darken1: '#7cb342',
  16067. darken2: '#689f38',
  16068. darken3: '#558b2f',
  16069. darken4: '#33691e',
  16070. accent1: '#ccff90',
  16071. accent2: '#b2ff59',
  16072. accent3: '#76ff03',
  16073. accent4: '#64dd17'
  16074. };
  16075. const lime = {
  16076. base: '#cddc39',
  16077. lighten5: '#f9fbe7',
  16078. lighten4: '#f0f4c3',
  16079. lighten3: '#e6ee9c',
  16080. lighten2: '#dce775',
  16081. lighten1: '#d4e157',
  16082. darken1: '#c0ca33',
  16083. darken2: '#afb42b',
  16084. darken3: '#9e9d24',
  16085. darken4: '#827717',
  16086. accent1: '#f4ff81',
  16087. accent2: '#eeff41',
  16088. accent3: '#c6ff00',
  16089. accent4: '#aeea00'
  16090. };
  16091. const yellow = {
  16092. base: '#ffeb3b',
  16093. lighten5: '#fffde7',
  16094. lighten4: '#fff9c4',
  16095. lighten3: '#fff59d',
  16096. lighten2: '#fff176',
  16097. lighten1: '#ffee58',
  16098. darken1: '#fdd835',
  16099. darken2: '#fbc02d',
  16100. darken3: '#f9a825',
  16101. darken4: '#f57f17',
  16102. accent1: '#ffff8d',
  16103. accent2: '#ffff00',
  16104. accent3: '#ffea00',
  16105. accent4: '#ffd600'
  16106. };
  16107. const amber = {
  16108. base: '#ffc107',
  16109. lighten5: '#fff8e1',
  16110. lighten4: '#ffecb3',
  16111. lighten3: '#ffe082',
  16112. lighten2: '#ffd54f',
  16113. lighten1: '#ffca28',
  16114. darken1: '#ffb300',
  16115. darken2: '#ffa000',
  16116. darken3: '#ff8f00',
  16117. darken4: '#ff6f00',
  16118. accent1: '#ffe57f',
  16119. accent2: '#ffd740',
  16120. accent3: '#ffc400',
  16121. accent4: '#ffab00'
  16122. };
  16123. const orange = {
  16124. base: '#ff9800',
  16125. lighten5: '#fff3e0',
  16126. lighten4: '#ffe0b2',
  16127. lighten3: '#ffcc80',
  16128. lighten2: '#ffb74d',
  16129. lighten1: '#ffa726',
  16130. darken1: '#fb8c00',
  16131. darken2: '#f57c00',
  16132. darken3: '#ef6c00',
  16133. darken4: '#e65100',
  16134. accent1: '#ffd180',
  16135. accent2: '#ffab40',
  16136. accent3: '#ff9100',
  16137. accent4: '#ff6d00'
  16138. };
  16139. const deepOrange = {
  16140. base: '#ff5722',
  16141. lighten5: '#fbe9e7',
  16142. lighten4: '#ffccbc',
  16143. lighten3: '#ffab91',
  16144. lighten2: '#ff8a65',
  16145. lighten1: '#ff7043',
  16146. darken1: '#f4511e',
  16147. darken2: '#e64a19',
  16148. darken3: '#d84315',
  16149. darken4: '#bf360c',
  16150. accent1: '#ff9e80',
  16151. accent2: '#ff6e40',
  16152. accent3: '#ff3d00',
  16153. accent4: '#dd2c00'
  16154. };
  16155. const brown = {
  16156. base: '#795548',
  16157. lighten5: '#efebe9',
  16158. lighten4: '#d7ccc8',
  16159. lighten3: '#bcaaa4',
  16160. lighten2: '#a1887f',
  16161. lighten1: '#8d6e63',
  16162. darken1: '#6d4c41',
  16163. darken2: '#5d4037',
  16164. darken3: '#4e342e',
  16165. darken4: '#3e2723'
  16166. };
  16167. const blueGrey = {
  16168. base: '#607d8b',
  16169. lighten5: '#eceff1',
  16170. lighten4: '#cfd8dc',
  16171. lighten3: '#b0bec5',
  16172. lighten2: '#90a4ae',
  16173. lighten1: '#78909c',
  16174. darken1: '#546e7a',
  16175. darken2: '#455a64',
  16176. darken3: '#37474f',
  16177. darken4: '#263238'
  16178. };
  16179. const grey = {
  16180. base: '#9e9e9e',
  16181. lighten5: '#fafafa',
  16182. lighten4: '#f5f5f5',
  16183. lighten3: '#eeeeee',
  16184. lighten2: '#e0e0e0',
  16185. lighten1: '#bdbdbd',
  16186. darken1: '#757575',
  16187. darken2: '#616161',
  16188. darken3: '#424242',
  16189. darken4: '#212121'
  16190. };
  16191. const shades = {
  16192. black: '#000000',
  16193. white: '#ffffff',
  16194. transparent: '#ffffff00'
  16195. };
  16196. var colors = {
  16197. red,
  16198. pink,
  16199. purple,
  16200. deepPurple,
  16201. indigo,
  16202. blue,
  16203. lightBlue,
  16204. cyan,
  16205. teal,
  16206. green,
  16207. lightGreen,
  16208. lime,
  16209. yellow,
  16210. amber,
  16211. orange,
  16212. deepOrange,
  16213. brown,
  16214. blueGrey,
  16215. grey,
  16216. shades
  16217. };
  16218. // Types
  16219. const makeVColorPickerSwatchesProps = propsFactory({
  16220. swatches: {
  16221. type: Array,
  16222. default: () => parseDefaultColors(colors)
  16223. },
  16224. disabled: Boolean,
  16225. color: Object,
  16226. maxHeight: [Number, String],
  16227. ...makeComponentProps()
  16228. }, 'VColorPickerSwatches');
  16229. function parseDefaultColors(colors) {
  16230. return Object.keys(colors).map(key => {
  16231. const color = colors[key];
  16232. 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];
  16233. });
  16234. }
  16235. const VColorPickerSwatches = defineComponent({
  16236. name: 'VColorPickerSwatches',
  16237. props: makeVColorPickerSwatchesProps(),
  16238. emits: {
  16239. 'update:color': color => true
  16240. },
  16241. setup(props, _ref) {
  16242. let {
  16243. emit
  16244. } = _ref;
  16245. useRender(() => vue.createVNode("div", {
  16246. "class": ['v-color-picker-swatches', props.class],
  16247. "style": [{
  16248. maxHeight: convertToUnit(props.maxHeight)
  16249. }, props.style]
  16250. }, [vue.createVNode("div", null, [props.swatches.map(swatch => vue.createVNode("div", {
  16251. "class": "v-color-picker-swatches__swatch"
  16252. }, [swatch.map(color => {
  16253. const rgba = parseColor(color);
  16254. const hsva = RGBtoHSV(rgba);
  16255. const background = RGBtoCSS(rgba);
  16256. return vue.createVNode("div", {
  16257. "class": "v-color-picker-swatches__color",
  16258. "onClick": () => hsva && emit('update:color', hsva)
  16259. }, [vue.createVNode("div", {
  16260. "style": {
  16261. background
  16262. }
  16263. }, [props.color && deepEqual(props.color, hsva) ? vue.createVNode(VIcon, {
  16264. "size": "x-small",
  16265. "icon": "$success",
  16266. "color": getContrast(color, '#FFFFFF') > 2 ? 'white' : 'black'
  16267. }, null) : undefined])]);
  16268. })]))])]));
  16269. return {};
  16270. }
  16271. });
  16272. const makeVSheetProps = propsFactory({
  16273. color: String,
  16274. ...makeBorderProps(),
  16275. ...makeComponentProps(),
  16276. ...makeDimensionProps(),
  16277. ...makeElevationProps(),
  16278. ...makeLocationProps(),
  16279. ...makePositionProps(),
  16280. ...makeRoundedProps(),
  16281. ...makeTagProps(),
  16282. ...makeThemeProps()
  16283. }, 'VSheet');
  16284. const VSheet = genericComponent()({
  16285. name: 'VSheet',
  16286. props: makeVSheetProps(),
  16287. setup(props, _ref) {
  16288. let {
  16289. slots
  16290. } = _ref;
  16291. const {
  16292. themeClasses
  16293. } = provideTheme(props);
  16294. const {
  16295. backgroundColorClasses,
  16296. backgroundColorStyles
  16297. } = useBackgroundColor(vue.toRef(props, 'color'));
  16298. const {
  16299. borderClasses
  16300. } = useBorder(props);
  16301. const {
  16302. dimensionStyles
  16303. } = useDimension(props);
  16304. const {
  16305. elevationClasses
  16306. } = useElevation(props);
  16307. const {
  16308. locationStyles
  16309. } = useLocation(props);
  16310. const {
  16311. positionClasses
  16312. } = usePosition(props);
  16313. const {
  16314. roundedClasses
  16315. } = useRounded(props);
  16316. useRender(() => vue.createVNode(props.tag, {
  16317. "class": ['v-sheet', themeClasses.value, backgroundColorClasses.value, borderClasses.value, elevationClasses.value, positionClasses.value, roundedClasses.value, props.class],
  16318. "style": [backgroundColorStyles.value, dimensionStyles.value, locationStyles.value, props.style]
  16319. }, slots));
  16320. return {};
  16321. }
  16322. });
  16323. // Types
  16324. const makeVColorPickerProps = propsFactory({
  16325. canvasHeight: {
  16326. type: [String, Number],
  16327. default: 150
  16328. },
  16329. disabled: Boolean,
  16330. dotSize: {
  16331. type: [Number, String],
  16332. default: 10
  16333. },
  16334. hideCanvas: Boolean,
  16335. hideSliders: Boolean,
  16336. hideInputs: Boolean,
  16337. mode: {
  16338. type: String,
  16339. default: 'rgba',
  16340. validator: v => Object.keys(modes).includes(v)
  16341. },
  16342. modes: {
  16343. type: Array,
  16344. default: () => Object.keys(modes),
  16345. validator: v => Array.isArray(v) && v.every(m => Object.keys(modes).includes(m))
  16346. },
  16347. showSwatches: Boolean,
  16348. swatches: Array,
  16349. swatchesMaxHeight: {
  16350. type: [Number, String],
  16351. default: 150
  16352. },
  16353. modelValue: {
  16354. type: [Object, String]
  16355. },
  16356. ...omit(makeVSheetProps({
  16357. width: 300
  16358. }), ['height', 'location', 'minHeight', 'maxHeight', 'minWidth', 'maxWidth'])
  16359. }, 'VColorPicker');
  16360. const VColorPicker = defineComponent({
  16361. name: 'VColorPicker',
  16362. props: makeVColorPickerProps(),
  16363. emits: {
  16364. 'update:modelValue': color => true,
  16365. 'update:mode': mode => true
  16366. },
  16367. setup(props) {
  16368. const mode = useProxiedModel(props, 'mode');
  16369. const hue = vue.ref(null);
  16370. const model = useProxiedModel(props, 'modelValue', undefined, v => {
  16371. if (v == null || v === '') return null;
  16372. let c;
  16373. try {
  16374. c = RGBtoHSV(parseColor(v));
  16375. } catch (err) {
  16376. consoleWarn(err);
  16377. return null;
  16378. }
  16379. return c;
  16380. }, v => {
  16381. if (!v) return null;
  16382. return extractColor(v, props.modelValue);
  16383. });
  16384. const currentColor = vue.computed(() => {
  16385. return model.value ? {
  16386. ...model.value,
  16387. h: hue.value ?? model.value.h
  16388. } : null;
  16389. });
  16390. const {
  16391. rtlClasses
  16392. } = useRtl();
  16393. let externalChange = true;
  16394. vue.watch(model, v => {
  16395. if (!externalChange) {
  16396. // prevent hue shift from rgb conversion inaccuracy
  16397. externalChange = true;
  16398. return;
  16399. }
  16400. if (!v) return;
  16401. hue.value = v.h;
  16402. }, {
  16403. immediate: true
  16404. });
  16405. const updateColor = hsva => {
  16406. externalChange = false;
  16407. hue.value = hsva.h;
  16408. model.value = hsva;
  16409. };
  16410. vue.onBeforeMount(() => {
  16411. if (!props.modes.includes(mode.value)) mode.value = props.modes[0];
  16412. });
  16413. provideDefaults({
  16414. VSlider: {
  16415. color: undefined,
  16416. trackColor: undefined,
  16417. trackFillColor: undefined
  16418. }
  16419. });
  16420. useRender(() => {
  16421. const sheetProps = VSheet.filterProps(props);
  16422. return vue.createVNode(VSheet, vue.mergeProps({
  16423. "rounded": props.rounded,
  16424. "elevation": props.elevation,
  16425. "theme": props.theme,
  16426. "class": ['v-color-picker', rtlClasses.value, props.class],
  16427. "style": [{
  16428. '--v-color-picker-color-hsv': HSVtoCSS({
  16429. ...(currentColor.value ?? nullColor),
  16430. a: 1
  16431. })
  16432. }, props.style]
  16433. }, sheetProps, {
  16434. "maxWidth": props.width
  16435. }), {
  16436. default: () => [!props.hideCanvas && vue.createVNode(VColorPickerCanvas, {
  16437. "key": "canvas",
  16438. "color": currentColor.value,
  16439. "onUpdate:color": updateColor,
  16440. "disabled": props.disabled,
  16441. "dotSize": props.dotSize,
  16442. "width": props.width,
  16443. "height": props.canvasHeight
  16444. }, null), (!props.hideSliders || !props.hideInputs) && vue.createVNode("div", {
  16445. "key": "controls",
  16446. "class": "v-color-picker__controls"
  16447. }, [!props.hideSliders && vue.createVNode(VColorPickerPreview, {
  16448. "key": "preview",
  16449. "color": currentColor.value,
  16450. "onUpdate:color": updateColor,
  16451. "hideAlpha": !mode.value.endsWith('a'),
  16452. "disabled": props.disabled
  16453. }, null), !props.hideInputs && vue.createVNode(VColorPickerEdit, {
  16454. "key": "edit",
  16455. "modes": props.modes,
  16456. "mode": mode.value,
  16457. "onUpdate:mode": m => mode.value = m,
  16458. "color": currentColor.value,
  16459. "onUpdate:color": updateColor,
  16460. "disabled": props.disabled
  16461. }, null)]), props.showSwatches && vue.createVNode(VColorPickerSwatches, {
  16462. "key": "swatches",
  16463. "color": currentColor.value,
  16464. "onUpdate:color": updateColor,
  16465. "maxHeight": props.swatchesMaxHeight,
  16466. "swatches": props.swatches,
  16467. "disabled": props.disabled
  16468. }, null)]
  16469. });
  16470. });
  16471. return {};
  16472. }
  16473. });
  16474. // Types
  16475. function highlightResult(text, matches, length) {
  16476. if (matches == null) return text;
  16477. if (Array.isArray(matches)) throw new Error('Multiple matches is not implemented');
  16478. return typeof matches === 'number' && ~matches ? vue.createVNode(vue.Fragment, null, [vue.createVNode("span", {
  16479. "class": "v-combobox__unmask"
  16480. }, [text.substr(0, matches)]), vue.createVNode("span", {
  16481. "class": "v-combobox__mask"
  16482. }, [text.substr(matches, length)]), vue.createVNode("span", {
  16483. "class": "v-combobox__unmask"
  16484. }, [text.substr(matches + length)])]) : text;
  16485. }
  16486. const makeVComboboxProps = propsFactory({
  16487. autoSelectFirst: {
  16488. type: [Boolean, String]
  16489. },
  16490. clearOnSelect: {
  16491. type: Boolean,
  16492. default: true
  16493. },
  16494. delimiters: Array,
  16495. ...makeFilterProps({
  16496. filterKeys: ['title']
  16497. }),
  16498. ...makeSelectProps({
  16499. hideNoData: true,
  16500. returnObject: true
  16501. }),
  16502. ...omit(makeVTextFieldProps({
  16503. modelValue: null,
  16504. role: 'combobox'
  16505. }), ['validationValue', 'dirty', 'appendInnerIcon']),
  16506. ...makeTransitionProps({
  16507. transition: false
  16508. })
  16509. }, 'VCombobox');
  16510. const VCombobox = genericComponent()({
  16511. name: 'VCombobox',
  16512. props: makeVComboboxProps(),
  16513. emits: {
  16514. 'update:focused': focused => true,
  16515. 'update:modelValue': value => true,
  16516. 'update:search': value => true,
  16517. 'update:menu': value => true
  16518. },
  16519. setup(props, _ref) {
  16520. let {
  16521. emit,
  16522. slots
  16523. } = _ref;
  16524. const {
  16525. t
  16526. } = useLocale();
  16527. const vTextFieldRef = vue.ref();
  16528. const isFocused = vue.shallowRef(false);
  16529. const isPristine = vue.shallowRef(true);
  16530. const listHasFocus = vue.shallowRef(false);
  16531. const vMenuRef = vue.ref();
  16532. const vVirtualScrollRef = vue.ref();
  16533. const _menu = useProxiedModel(props, 'menu');
  16534. const menu = vue.computed({
  16535. get: () => _menu.value,
  16536. set: v => {
  16537. if (_menu.value && !v && vMenuRef.value?.ΨopenChildren.size) return;
  16538. _menu.value = v;
  16539. }
  16540. });
  16541. const selectionIndex = vue.shallowRef(-1);
  16542. let cleared = false;
  16543. const color = vue.computed(() => vTextFieldRef.value?.color);
  16544. const label = vue.computed(() => menu.value ? props.closeText : props.openText);
  16545. const {
  16546. items,
  16547. transformIn,
  16548. transformOut
  16549. } = useItems(props);
  16550. const {
  16551. textColorClasses,
  16552. textColorStyles
  16553. } = useTextColor(color);
  16554. const model = useProxiedModel(props, 'modelValue', [], v => transformIn(wrapInArray(v)), v => {
  16555. const transformed = transformOut(v);
  16556. return props.multiple ? transformed : transformed[0] ?? null;
  16557. });
  16558. const form = useForm(props);
  16559. const hasChips = vue.computed(() => !!(props.chips || slots.chip));
  16560. const hasSelectionSlot = vue.computed(() => hasChips.value || !!slots.selection);
  16561. const _search = vue.shallowRef(!props.multiple && !hasSelectionSlot.value ? model.value[0]?.title ?? '' : '');
  16562. const search = vue.computed({
  16563. get: () => {
  16564. return _search.value;
  16565. },
  16566. set: val => {
  16567. _search.value = val ?? '';
  16568. if (!props.multiple && !hasSelectionSlot.value) {
  16569. model.value = [transformItem$3(props, val)];
  16570. }
  16571. if (val && props.multiple && props.delimiters?.length) {
  16572. const values = val.split(new RegExp(`(?:${props.delimiters.join('|')})+`));
  16573. if (values.length > 1) {
  16574. values.forEach(v => {
  16575. v = v.trim();
  16576. if (v) select(transformItem$3(props, v));
  16577. });
  16578. _search.value = '';
  16579. }
  16580. }
  16581. if (!val) selectionIndex.value = -1;
  16582. isPristine.value = !val;
  16583. }
  16584. });
  16585. const counterValue = vue.computed(() => {
  16586. return typeof props.counterValue === 'function' ? props.counterValue(model.value) : typeof props.counterValue === 'number' ? props.counterValue : props.multiple ? model.value.length : search.value.length;
  16587. });
  16588. vue.watch(_search, value => {
  16589. if (cleared) {
  16590. // wait for clear to finish, VTextField sets _search to null
  16591. // then search computed triggers and updates _search to ''
  16592. vue.nextTick(() => cleared = false);
  16593. } else if (isFocused.value && !menu.value) {
  16594. menu.value = true;
  16595. }
  16596. emit('update:search', value);
  16597. });
  16598. vue.watch(model, value => {
  16599. if (!props.multiple && !hasSelectionSlot.value) {
  16600. _search.value = value[0]?.title ?? '';
  16601. }
  16602. });
  16603. const {
  16604. filteredItems,
  16605. getMatches
  16606. } = useFilter(props, items, () => isPristine.value ? '' : search.value);
  16607. const displayItems = vue.computed(() => {
  16608. if (props.hideSelected) {
  16609. return filteredItems.value.filter(filteredItem => !model.value.some(s => s.value === filteredItem.value));
  16610. }
  16611. return filteredItems.value;
  16612. });
  16613. const selectedValues = vue.computed(() => model.value.map(selection => selection.value));
  16614. const highlightFirst = vue.computed(() => {
  16615. const selectFirst = props.autoSelectFirst === true || props.autoSelectFirst === 'exact' && search.value === displayItems.value[0]?.title;
  16616. return selectFirst && displayItems.value.length > 0 && !isPristine.value && !listHasFocus.value;
  16617. });
  16618. const menuDisabled = vue.computed(() => props.hideNoData && !displayItems.value.length || form.isReadonly.value || form.isDisabled.value);
  16619. const listRef = vue.ref();
  16620. const listEvents = useScrolling(listRef, vTextFieldRef);
  16621. function onClear(e) {
  16622. cleared = true;
  16623. if (props.openOnClear) {
  16624. menu.value = true;
  16625. }
  16626. }
  16627. function onMousedownControl() {
  16628. if (menuDisabled.value) return;
  16629. menu.value = true;
  16630. }
  16631. function onMousedownMenuIcon(e) {
  16632. if (menuDisabled.value) return;
  16633. if (isFocused.value) {
  16634. e.preventDefault();
  16635. e.stopPropagation();
  16636. }
  16637. menu.value = !menu.value;
  16638. }
  16639. function onListKeydown(e) {
  16640. if (checkPrintable(e)) {
  16641. vTextFieldRef.value?.focus();
  16642. }
  16643. }
  16644. // eslint-disable-next-line complexity
  16645. function onKeydown(e) {
  16646. if (isComposingIgnoreKey(e) || form.isReadonly.value) return;
  16647. const selectionStart = vTextFieldRef.value.selectionStart;
  16648. const length = model.value.length;
  16649. if (selectionIndex.value > -1 || ['Enter', 'ArrowDown', 'ArrowUp'].includes(e.key)) {
  16650. e.preventDefault();
  16651. }
  16652. if (['Enter', 'ArrowDown'].includes(e.key)) {
  16653. menu.value = true;
  16654. }
  16655. if (['Escape'].includes(e.key)) {
  16656. menu.value = false;
  16657. }
  16658. if (['Enter', 'Escape', 'Tab'].includes(e.key)) {
  16659. if (highlightFirst.value && ['Enter', 'Tab'].includes(e.key) && !model.value.some(_ref2 => {
  16660. let {
  16661. value
  16662. } = _ref2;
  16663. return value === displayItems.value[0].value;
  16664. })) {
  16665. select(filteredItems.value[0]);
  16666. }
  16667. isPristine.value = true;
  16668. }
  16669. if (e.key === 'ArrowDown' && highlightFirst.value) {
  16670. listRef.value?.focus('next');
  16671. }
  16672. if (e.key === 'Enter' && search.value) {
  16673. select(transformItem$3(props, search.value));
  16674. if (hasSelectionSlot.value) _search.value = '';
  16675. }
  16676. if (['Backspace', 'Delete'].includes(e.key)) {
  16677. if (!props.multiple && hasSelectionSlot.value && model.value.length > 0 && !search.value) return select(model.value[0], false);
  16678. if (~selectionIndex.value) {
  16679. const originalSelectionIndex = selectionIndex.value;
  16680. select(model.value[selectionIndex.value], false);
  16681. selectionIndex.value = originalSelectionIndex >= length - 1 ? length - 2 : originalSelectionIndex;
  16682. } else if (e.key === 'Backspace' && !search.value) {
  16683. selectionIndex.value = length - 1;
  16684. }
  16685. }
  16686. if (!props.multiple) return;
  16687. if (e.key === 'ArrowLeft') {
  16688. if (selectionIndex.value < 0 && selectionStart > 0) return;
  16689. const prev = selectionIndex.value > -1 ? selectionIndex.value - 1 : length - 1;
  16690. if (model.value[prev]) {
  16691. selectionIndex.value = prev;
  16692. } else {
  16693. selectionIndex.value = -1;
  16694. vTextFieldRef.value.setSelectionRange(search.value.length, search.value.length);
  16695. }
  16696. }
  16697. if (e.key === 'ArrowRight') {
  16698. if (selectionIndex.value < 0) return;
  16699. const next = selectionIndex.value + 1;
  16700. if (model.value[next]) {
  16701. selectionIndex.value = next;
  16702. } else {
  16703. selectionIndex.value = -1;
  16704. vTextFieldRef.value.setSelectionRange(0, 0);
  16705. }
  16706. }
  16707. }
  16708. function onAfterEnter() {
  16709. if (props.eager) {
  16710. vVirtualScrollRef.value?.calculateVisibleItems();
  16711. }
  16712. }
  16713. function onAfterLeave() {
  16714. if (isFocused.value) {
  16715. isPristine.value = true;
  16716. vTextFieldRef.value?.focus();
  16717. }
  16718. }
  16719. /** @param set - null means toggle */
  16720. function select(item) {
  16721. let set = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : true;
  16722. if (!item || item.props.disabled) return;
  16723. if (props.multiple) {
  16724. const index = model.value.findIndex(selection => props.valueComparator(selection.value, item.value));
  16725. const add = set == null ? !~index : set;
  16726. if (~index) {
  16727. const value = add ? [...model.value, item] : [...model.value];
  16728. value.splice(index, 1);
  16729. model.value = value;
  16730. } else if (add) {
  16731. model.value = [...model.value, item];
  16732. }
  16733. if (props.clearOnSelect) {
  16734. search.value = '';
  16735. }
  16736. } else {
  16737. const add = set !== false;
  16738. model.value = add ? [item] : [];
  16739. _search.value = add && !hasSelectionSlot.value ? item.title : '';
  16740. // watch for search watcher to trigger
  16741. vue.nextTick(() => {
  16742. menu.value = false;
  16743. isPristine.value = true;
  16744. });
  16745. }
  16746. }
  16747. function onFocusin(e) {
  16748. isFocused.value = true;
  16749. setTimeout(() => {
  16750. listHasFocus.value = true;
  16751. });
  16752. }
  16753. function onFocusout(e) {
  16754. listHasFocus.value = false;
  16755. }
  16756. function onUpdateModelValue(v) {
  16757. if (v == null || v === '' && !props.multiple && !hasSelectionSlot.value) model.value = [];
  16758. }
  16759. vue.watch(isFocused, (val, oldVal) => {
  16760. if (val || val === oldVal) return;
  16761. selectionIndex.value = -1;
  16762. menu.value = false;
  16763. if (search.value) {
  16764. if (props.multiple) {
  16765. select(transformItem$3(props, search.value));
  16766. return;
  16767. }
  16768. if (!hasSelectionSlot.value) return;
  16769. if (model.value.some(_ref3 => {
  16770. let {
  16771. title
  16772. } = _ref3;
  16773. return title === search.value;
  16774. })) {
  16775. _search.value = '';
  16776. } else {
  16777. select(transformItem$3(props, search.value));
  16778. }
  16779. }
  16780. });
  16781. vue.watch(menu, () => {
  16782. if (!props.hideSelected && menu.value && model.value.length) {
  16783. const index = displayItems.value.findIndex(item => model.value.some(s => props.valueComparator(s.value, item.value)));
  16784. IN_BROWSER && window.requestAnimationFrame(() => {
  16785. index >= 0 && vVirtualScrollRef.value?.scrollToIndex(index);
  16786. });
  16787. }
  16788. });
  16789. vue.watch(() => props.items, (newVal, oldVal) => {
  16790. if (menu.value) return;
  16791. if (isFocused.value && !oldVal.length && newVal.length) {
  16792. menu.value = true;
  16793. }
  16794. });
  16795. useRender(() => {
  16796. const hasList = !!(!props.hideNoData || displayItems.value.length || slots['prepend-item'] || slots['append-item'] || slots['no-data']);
  16797. const isDirty = model.value.length > 0;
  16798. const textFieldProps = VTextField.filterProps(props);
  16799. return vue.createVNode(VTextField, vue.mergeProps({
  16800. "ref": vTextFieldRef
  16801. }, textFieldProps, {
  16802. "modelValue": search.value,
  16803. "onUpdate:modelValue": [$event => search.value = $event, onUpdateModelValue],
  16804. "focused": isFocused.value,
  16805. "onUpdate:focused": $event => isFocused.value = $event,
  16806. "validationValue": model.externalValue,
  16807. "counterValue": counterValue.value,
  16808. "dirty": isDirty,
  16809. "class": ['v-combobox', {
  16810. 'v-combobox--active-menu': menu.value,
  16811. 'v-combobox--chips': !!props.chips,
  16812. 'v-combobox--selection-slot': !!hasSelectionSlot.value,
  16813. 'v-combobox--selecting-index': selectionIndex.value > -1,
  16814. [`v-combobox--${props.multiple ? 'multiple' : 'single'}`]: true
  16815. }, props.class],
  16816. "style": props.style,
  16817. "readonly": form.isReadonly.value,
  16818. "placeholder": isDirty ? undefined : props.placeholder,
  16819. "onClick:clear": onClear,
  16820. "onMousedown:control": onMousedownControl,
  16821. "onKeydown": onKeydown
  16822. }), {
  16823. ...slots,
  16824. default: () => vue.createVNode(vue.Fragment, null, [vue.createVNode(VMenu, vue.mergeProps({
  16825. "ref": vMenuRef,
  16826. "modelValue": menu.value,
  16827. "onUpdate:modelValue": $event => menu.value = $event,
  16828. "activator": "parent",
  16829. "contentClass": "v-combobox__content",
  16830. "disabled": menuDisabled.value,
  16831. "eager": props.eager,
  16832. "maxHeight": 310,
  16833. "openOnClick": false,
  16834. "closeOnContentClick": false,
  16835. "transition": props.transition,
  16836. "onAfterEnter": onAfterEnter,
  16837. "onAfterLeave": onAfterLeave
  16838. }, props.menuProps), {
  16839. default: () => [hasList && vue.createVNode(VList, vue.mergeProps({
  16840. "ref": listRef,
  16841. "selected": selectedValues.value,
  16842. "selectStrategy": props.multiple ? 'independent' : 'single-independent',
  16843. "onMousedown": e => e.preventDefault(),
  16844. "onKeydown": onListKeydown,
  16845. "onFocusin": onFocusin,
  16846. "onFocusout": onFocusout,
  16847. "tabindex": "-1",
  16848. "aria-live": "polite",
  16849. "color": props.itemColor ?? props.color
  16850. }, listEvents, props.listProps), {
  16851. default: () => [slots['prepend-item']?.(), !displayItems.value.length && !props.hideNoData && (slots['no-data']?.() ?? vue.createVNode(VListItem, {
  16852. "key": "no-data",
  16853. "title": t(props.noDataText)
  16854. }, null)), vue.createVNode(VVirtualScroll, {
  16855. "ref": vVirtualScrollRef,
  16856. "renderless": true,
  16857. "items": displayItems.value
  16858. }, {
  16859. default: _ref4 => {
  16860. let {
  16861. item,
  16862. index,
  16863. itemRef
  16864. } = _ref4;
  16865. const itemProps = vue.mergeProps(item.props, {
  16866. ref: itemRef,
  16867. key: item.value,
  16868. active: highlightFirst.value && index === 0 ? true : undefined,
  16869. onClick: () => select(item, null)
  16870. });
  16871. return slots.item?.({
  16872. item,
  16873. index,
  16874. props: itemProps
  16875. }) ?? vue.createVNode(VListItem, vue.mergeProps(itemProps, {
  16876. "role": "option"
  16877. }), {
  16878. prepend: _ref5 => {
  16879. let {
  16880. isSelected
  16881. } = _ref5;
  16882. return vue.createVNode(vue.Fragment, null, [props.multiple && !props.hideSelected ? vue.createVNode(VCheckboxBtn, {
  16883. "key": item.value,
  16884. "modelValue": isSelected,
  16885. "ripple": false,
  16886. "tabindex": "-1"
  16887. }, null) : undefined, item.props.prependAvatar && vue.createVNode(VAvatar, {
  16888. "image": item.props.prependAvatar
  16889. }, null), item.props.prependIcon && vue.createVNode(VIcon, {
  16890. "icon": item.props.prependIcon
  16891. }, null)]);
  16892. },
  16893. title: () => {
  16894. return isPristine.value ? item.title : highlightResult(item.title, getMatches(item)?.title, search.value?.length ?? 0);
  16895. }
  16896. });
  16897. }
  16898. }), slots['append-item']?.()]
  16899. })]
  16900. }), model.value.map((item, index) => {
  16901. function onChipClose(e) {
  16902. e.stopPropagation();
  16903. e.preventDefault();
  16904. select(item, false);
  16905. }
  16906. const slotProps = {
  16907. 'onClick:close': onChipClose,
  16908. onKeydown(e) {
  16909. if (e.key !== 'Enter' && e.key !== ' ') return;
  16910. e.preventDefault();
  16911. e.stopPropagation();
  16912. onChipClose(e);
  16913. },
  16914. onMousedown(e) {
  16915. e.preventDefault();
  16916. e.stopPropagation();
  16917. },
  16918. modelValue: true,
  16919. 'onUpdate:modelValue': undefined
  16920. };
  16921. const hasSlot = hasChips.value ? !!slots.chip : !!slots.selection;
  16922. const slotContent = hasSlot ? ensureValidVNode(hasChips.value ? slots.chip({
  16923. item,
  16924. index,
  16925. props: slotProps
  16926. }) : slots.selection({
  16927. item,
  16928. index
  16929. })) : undefined;
  16930. if (hasSlot && !slotContent) return undefined;
  16931. return vue.createVNode("div", {
  16932. "key": item.value,
  16933. "class": ['v-combobox__selection', index === selectionIndex.value && ['v-combobox__selection--selected', textColorClasses.value]],
  16934. "style": index === selectionIndex.value ? textColorStyles.value : {}
  16935. }, [hasChips.value ? !slots.chip ? vue.createVNode(VChip, vue.mergeProps({
  16936. "key": "chip",
  16937. "closable": props.closableChips,
  16938. "size": "small",
  16939. "text": item.title,
  16940. "disabled": item.props.disabled
  16941. }, slotProps), null) : vue.createVNode(VDefaultsProvider, {
  16942. "key": "chip-defaults",
  16943. "defaults": {
  16944. VChip: {
  16945. closable: props.closableChips,
  16946. size: 'small',
  16947. text: item.title
  16948. }
  16949. }
  16950. }, {
  16951. default: () => [slotContent]
  16952. }) : slotContent ?? vue.createVNode("span", {
  16953. "class": "v-combobox__selection-text"
  16954. }, [item.title, props.multiple && index < model.value.length - 1 && vue.createVNode("span", {
  16955. "class": "v-combobox__selection-comma"
  16956. }, [vue.createTextVNode(",")])])]);
  16957. })]),
  16958. 'append-inner': function () {
  16959. for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) {
  16960. args[_key] = arguments[_key];
  16961. }
  16962. return vue.createVNode(vue.Fragment, null, [slots['append-inner']?.(...args), (!props.hideNoData || props.items.length) && props.menuIcon ? vue.createVNode(VIcon, {
  16963. "class": "v-combobox__menu-icon",
  16964. "icon": props.menuIcon,
  16965. "onMousedown": onMousedownMenuIcon,
  16966. "onClick": noop,
  16967. "aria-label": t(label.value),
  16968. "title": t(label.value),
  16969. "tabindex": "-1"
  16970. }, null) : undefined]);
  16971. }
  16972. });
  16973. });
  16974. return forwardRefs({
  16975. isFocused,
  16976. isPristine,
  16977. menu,
  16978. search,
  16979. selectionIndex,
  16980. filteredItems,
  16981. select
  16982. }, vTextFieldRef);
  16983. }
  16984. });
  16985. // Utilities
  16986. // Types
  16987. const firstDay = {
  16988. '001': 1,
  16989. AD: 1,
  16990. AE: 6,
  16991. AF: 6,
  16992. AG: 0,
  16993. AI: 1,
  16994. AL: 1,
  16995. AM: 1,
  16996. AN: 1,
  16997. AR: 1,
  16998. AS: 0,
  16999. AT: 1,
  17000. AU: 1,
  17001. AX: 1,
  17002. AZ: 1,
  17003. BA: 1,
  17004. BD: 0,
  17005. BE: 1,
  17006. BG: 1,
  17007. BH: 6,
  17008. BM: 1,
  17009. BN: 1,
  17010. BR: 0,
  17011. BS: 0,
  17012. BT: 0,
  17013. BW: 0,
  17014. BY: 1,
  17015. BZ: 0,
  17016. CA: 0,
  17017. CH: 1,
  17018. CL: 1,
  17019. CM: 1,
  17020. CN: 1,
  17021. CO: 0,
  17022. CR: 1,
  17023. CY: 1,
  17024. CZ: 1,
  17025. DE: 1,
  17026. DJ: 6,
  17027. DK: 1,
  17028. DM: 0,
  17029. DO: 0,
  17030. DZ: 6,
  17031. EC: 1,
  17032. EE: 1,
  17033. EG: 6,
  17034. ES: 1,
  17035. ET: 0,
  17036. FI: 1,
  17037. FJ: 1,
  17038. FO: 1,
  17039. FR: 1,
  17040. GB: 1,
  17041. 'GB-alt-variant': 0,
  17042. GE: 1,
  17043. GF: 1,
  17044. GP: 1,
  17045. GR: 1,
  17046. GT: 0,
  17047. GU: 0,
  17048. HK: 0,
  17049. HN: 0,
  17050. HR: 1,
  17051. HU: 1,
  17052. ID: 0,
  17053. IE: 1,
  17054. IL: 0,
  17055. IN: 0,
  17056. IQ: 6,
  17057. IR: 6,
  17058. IS: 1,
  17059. IT: 1,
  17060. JM: 0,
  17061. JO: 6,
  17062. JP: 0,
  17063. KE: 0,
  17064. KG: 1,
  17065. KH: 0,
  17066. KR: 0,
  17067. KW: 6,
  17068. KZ: 1,
  17069. LA: 0,
  17070. LB: 1,
  17071. LI: 1,
  17072. LK: 1,
  17073. LT: 1,
  17074. LU: 1,
  17075. LV: 1,
  17076. LY: 6,
  17077. MC: 1,
  17078. MD: 1,
  17079. ME: 1,
  17080. MH: 0,
  17081. MK: 1,
  17082. MM: 0,
  17083. MN: 1,
  17084. MO: 0,
  17085. MQ: 1,
  17086. MT: 0,
  17087. MV: 5,
  17088. MX: 0,
  17089. MY: 1,
  17090. MZ: 0,
  17091. NI: 0,
  17092. NL: 1,
  17093. NO: 1,
  17094. NP: 0,
  17095. NZ: 1,
  17096. OM: 6,
  17097. PA: 0,
  17098. PE: 0,
  17099. PH: 0,
  17100. PK: 0,
  17101. PL: 1,
  17102. PR: 0,
  17103. PT: 0,
  17104. PY: 0,
  17105. QA: 6,
  17106. RE: 1,
  17107. RO: 1,
  17108. RS: 1,
  17109. RU: 1,
  17110. SA: 0,
  17111. SD: 6,
  17112. SE: 1,
  17113. SG: 0,
  17114. SI: 1,
  17115. SK: 1,
  17116. SM: 1,
  17117. SV: 0,
  17118. SY: 6,
  17119. TH: 0,
  17120. TJ: 1,
  17121. TM: 1,
  17122. TR: 1,
  17123. TT: 0,
  17124. TW: 0,
  17125. UA: 1,
  17126. UM: 0,
  17127. US: 0,
  17128. UY: 1,
  17129. UZ: 1,
  17130. VA: 1,
  17131. VE: 0,
  17132. VI: 0,
  17133. VN: 1,
  17134. WS: 0,
  17135. XK: 1,
  17136. YE: 0,
  17137. ZA: 0,
  17138. ZW: 0
  17139. };
  17140. function getWeekArray(date, locale, firstDayOfWeek) {
  17141. const weeks = [];
  17142. let currentWeek = [];
  17143. const firstDayOfMonth = startOfMonth(date);
  17144. const lastDayOfMonth = endOfMonth(date);
  17145. const first = firstDayOfWeek ?? firstDay[locale.slice(-2).toUpperCase()] ?? 0;
  17146. const firstDayWeekIndex = (firstDayOfMonth.getDay() - first + 7) % 7;
  17147. const lastDayWeekIndex = (lastDayOfMonth.getDay() - first + 7) % 7;
  17148. for (let i = 0; i < firstDayWeekIndex; i++) {
  17149. const adjacentDay = new Date(firstDayOfMonth);
  17150. adjacentDay.setDate(adjacentDay.getDate() - (firstDayWeekIndex - i));
  17151. currentWeek.push(adjacentDay);
  17152. }
  17153. for (let i = 1; i <= lastDayOfMonth.getDate(); i++) {
  17154. const day = new Date(date.getFullYear(), date.getMonth(), i);
  17155. // Add the day to the current week
  17156. currentWeek.push(day);
  17157. // If the current week has 7 days, add it to the weeks array and start a new week
  17158. if (currentWeek.length === 7) {
  17159. weeks.push(currentWeek);
  17160. currentWeek = [];
  17161. }
  17162. }
  17163. for (let i = 1; i < 7 - lastDayWeekIndex; i++) {
  17164. const adjacentDay = new Date(lastDayOfMonth);
  17165. adjacentDay.setDate(adjacentDay.getDate() + i);
  17166. currentWeek.push(adjacentDay);
  17167. }
  17168. if (currentWeek.length > 0) {
  17169. weeks.push(currentWeek);
  17170. }
  17171. return weeks;
  17172. }
  17173. function startOfWeek(date, locale, firstDayOfWeek) {
  17174. const day = firstDayOfWeek ?? firstDay[locale.slice(-2).toUpperCase()] ?? 0;
  17175. const d = new Date(date);
  17176. while (d.getDay() !== day) {
  17177. d.setDate(d.getDate() - 1);
  17178. }
  17179. return d;
  17180. }
  17181. function endOfWeek(date, locale) {
  17182. const d = new Date(date);
  17183. const lastDay = ((firstDay[locale.slice(-2).toUpperCase()] ?? 0) + 6) % 7;
  17184. while (d.getDay() !== lastDay) {
  17185. d.setDate(d.getDate() + 1);
  17186. }
  17187. return d;
  17188. }
  17189. function startOfMonth(date) {
  17190. return new Date(date.getFullYear(), date.getMonth(), 1);
  17191. }
  17192. function endOfMonth(date) {
  17193. return new Date(date.getFullYear(), date.getMonth() + 1, 0);
  17194. }
  17195. function parseLocalDate(value) {
  17196. const parts = value.split('-').map(Number);
  17197. // new Date() uses local time zone when passing individual date component values
  17198. return new Date(parts[0], parts[1] - 1, parts[2]);
  17199. }
  17200. const _YYYMMDD = /^([12]\d{3}-([1-9]|0[1-9]|1[0-2])-([1-9]|0[1-9]|[12]\d|3[01]))$/;
  17201. function date(value) {
  17202. if (value == null) return new Date();
  17203. if (value instanceof Date) return value;
  17204. if (typeof value === 'string') {
  17205. let parsed;
  17206. if (_YYYMMDD.test(value)) {
  17207. return parseLocalDate(value);
  17208. } else {
  17209. parsed = Date.parse(value);
  17210. }
  17211. if (!isNaN(parsed)) return new Date(parsed);
  17212. }
  17213. return null;
  17214. }
  17215. const sundayJanuarySecond2000 = new Date(2000, 0, 2);
  17216. function getWeekdays(locale, firstDayOfWeek) {
  17217. const daysFromSunday = firstDayOfWeek ?? firstDay[locale.slice(-2).toUpperCase()] ?? 0;
  17218. return createRange(7).map(i => {
  17219. const weekday = new Date(sundayJanuarySecond2000);
  17220. weekday.setDate(sundayJanuarySecond2000.getDate() + daysFromSunday + i);
  17221. return new Intl.DateTimeFormat(locale, {
  17222. weekday: 'narrow'
  17223. }).format(weekday);
  17224. });
  17225. }
  17226. function format(value, formatString, locale, formats) {
  17227. const newDate = date(value) ?? new Date();
  17228. const customFormat = formats?.[formatString];
  17229. if (typeof customFormat === 'function') {
  17230. return customFormat(newDate, formatString, locale);
  17231. }
  17232. let options = {};
  17233. switch (formatString) {
  17234. case 'fullDate':
  17235. options = {
  17236. year: 'numeric',
  17237. month: 'long',
  17238. day: 'numeric'
  17239. };
  17240. break;
  17241. case 'fullDateWithWeekday':
  17242. options = {
  17243. weekday: 'long',
  17244. year: 'numeric',
  17245. month: 'long',
  17246. day: 'numeric'
  17247. };
  17248. break;
  17249. case 'normalDate':
  17250. const day = newDate.getDate();
  17251. const month = new Intl.DateTimeFormat(locale, {
  17252. month: 'long'
  17253. }).format(newDate);
  17254. return `${day} ${month}`;
  17255. case 'normalDateWithWeekday':
  17256. options = {
  17257. weekday: 'short',
  17258. day: 'numeric',
  17259. month: 'short'
  17260. };
  17261. break;
  17262. case 'shortDate':
  17263. options = {
  17264. month: 'short',
  17265. day: 'numeric'
  17266. };
  17267. break;
  17268. case 'year':
  17269. options = {
  17270. year: 'numeric'
  17271. };
  17272. break;
  17273. case 'month':
  17274. options = {
  17275. month: 'long'
  17276. };
  17277. break;
  17278. case 'monthShort':
  17279. options = {
  17280. month: 'short'
  17281. };
  17282. break;
  17283. case 'monthAndYear':
  17284. options = {
  17285. month: 'long',
  17286. year: 'numeric'
  17287. };
  17288. break;
  17289. case 'monthAndDate':
  17290. options = {
  17291. month: 'long',
  17292. day: 'numeric'
  17293. };
  17294. break;
  17295. case 'weekday':
  17296. options = {
  17297. weekday: 'long'
  17298. };
  17299. break;
  17300. case 'weekdayShort':
  17301. options = {
  17302. weekday: 'short'
  17303. };
  17304. break;
  17305. case 'dayOfMonth':
  17306. return new Intl.NumberFormat(locale).format(newDate.getDate());
  17307. case 'hours12h':
  17308. options = {
  17309. hour: 'numeric',
  17310. hour12: true
  17311. };
  17312. break;
  17313. case 'hours24h':
  17314. options = {
  17315. hour: 'numeric',
  17316. hour12: false
  17317. };
  17318. break;
  17319. case 'minutes':
  17320. options = {
  17321. minute: 'numeric'
  17322. };
  17323. break;
  17324. case 'seconds':
  17325. options = {
  17326. second: 'numeric'
  17327. };
  17328. break;
  17329. case 'fullTime':
  17330. options = {
  17331. hour: 'numeric',
  17332. minute: 'numeric',
  17333. second: 'numeric',
  17334. hour12: true
  17335. };
  17336. break;
  17337. case 'fullTime12h':
  17338. options = {
  17339. hour: 'numeric',
  17340. minute: 'numeric',
  17341. second: 'numeric',
  17342. hour12: true
  17343. };
  17344. break;
  17345. case 'fullTime24h':
  17346. options = {
  17347. hour: 'numeric',
  17348. minute: 'numeric',
  17349. second: 'numeric',
  17350. hour12: false
  17351. };
  17352. break;
  17353. case 'fullDateTime':
  17354. options = {
  17355. year: 'numeric',
  17356. month: 'long',
  17357. day: 'numeric',
  17358. hour: 'numeric',
  17359. minute: 'numeric',
  17360. second: 'numeric',
  17361. hour12: true
  17362. };
  17363. break;
  17364. case 'fullDateTime12h':
  17365. options = {
  17366. year: 'numeric',
  17367. month: 'long',
  17368. day: 'numeric',
  17369. hour: 'numeric',
  17370. minute: 'numeric',
  17371. second: 'numeric',
  17372. hour12: true
  17373. };
  17374. break;
  17375. case 'fullDateTime24h':
  17376. options = {
  17377. year: 'numeric',
  17378. month: 'long',
  17379. day: 'numeric',
  17380. hour: 'numeric',
  17381. minute: 'numeric',
  17382. second: 'numeric',
  17383. hour12: false
  17384. };
  17385. break;
  17386. case 'keyboardDate':
  17387. options = {
  17388. year: 'numeric',
  17389. month: '2-digit',
  17390. day: '2-digit'
  17391. };
  17392. break;
  17393. case 'keyboardDateTime':
  17394. options = {
  17395. year: 'numeric',
  17396. month: '2-digit',
  17397. day: '2-digit',
  17398. hour: 'numeric',
  17399. minute: 'numeric',
  17400. second: 'numeric',
  17401. hour12: false
  17402. };
  17403. break;
  17404. case 'keyboardDateTime12h':
  17405. options = {
  17406. year: 'numeric',
  17407. month: '2-digit',
  17408. day: '2-digit',
  17409. hour: 'numeric',
  17410. minute: 'numeric',
  17411. second: 'numeric',
  17412. hour12: true
  17413. };
  17414. break;
  17415. case 'keyboardDateTime24h':
  17416. options = {
  17417. year: 'numeric',
  17418. month: '2-digit',
  17419. day: '2-digit',
  17420. hour: 'numeric',
  17421. minute: 'numeric',
  17422. second: 'numeric',
  17423. hour12: false
  17424. };
  17425. break;
  17426. default:
  17427. options = customFormat ?? {
  17428. timeZone: 'UTC',
  17429. timeZoneName: 'short'
  17430. };
  17431. }
  17432. return new Intl.DateTimeFormat(locale, options).format(newDate);
  17433. }
  17434. function toISO(adapter, value) {
  17435. const date = adapter.toJsDate(value);
  17436. const year = date.getFullYear();
  17437. const month = padStart(String(date.getMonth() + 1), 2, '0');
  17438. const day = padStart(String(date.getDate()), 2, '0');
  17439. return `${year}-${month}-${day}`;
  17440. }
  17441. function parseISO(value) {
  17442. const [year, month, day] = value.split('-').map(Number);
  17443. return new Date(year, month - 1, day);
  17444. }
  17445. function addMinutes(date, amount) {
  17446. const d = new Date(date);
  17447. d.setMinutes(d.getMinutes() + amount);
  17448. return d;
  17449. }
  17450. function addHours(date, amount) {
  17451. const d = new Date(date);
  17452. d.setHours(d.getHours() + amount);
  17453. return d;
  17454. }
  17455. function addDays(date, amount) {
  17456. const d = new Date(date);
  17457. d.setDate(d.getDate() + amount);
  17458. return d;
  17459. }
  17460. function addWeeks(date, amount) {
  17461. const d = new Date(date);
  17462. d.setDate(d.getDate() + amount * 7);
  17463. return d;
  17464. }
  17465. function addMonths(date, amount) {
  17466. const d = new Date(date);
  17467. d.setDate(1);
  17468. d.setMonth(d.getMonth() + amount);
  17469. return d;
  17470. }
  17471. function getYear(date) {
  17472. return date.getFullYear();
  17473. }
  17474. function getMonth(date) {
  17475. return date.getMonth();
  17476. }
  17477. function getDate(date) {
  17478. return date.getDate();
  17479. }
  17480. function getNextMonth(date) {
  17481. return new Date(date.getFullYear(), date.getMonth() + 1, 1);
  17482. }
  17483. function getPreviousMonth(date) {
  17484. return new Date(date.getFullYear(), date.getMonth() - 1, 1);
  17485. }
  17486. function getHours(date) {
  17487. return date.getHours();
  17488. }
  17489. function getMinutes(date) {
  17490. return date.getMinutes();
  17491. }
  17492. function startOfYear(date) {
  17493. return new Date(date.getFullYear(), 0, 1);
  17494. }
  17495. function endOfYear(date) {
  17496. return new Date(date.getFullYear(), 11, 31);
  17497. }
  17498. function isWithinRange(date, range) {
  17499. return isAfter(date, range[0]) && isBefore(date, range[1]);
  17500. }
  17501. function isValid(date) {
  17502. const d = new Date(date);
  17503. return d instanceof Date && !isNaN(d.getTime());
  17504. }
  17505. function isAfter(date, comparing) {
  17506. return date.getTime() > comparing.getTime();
  17507. }
  17508. function isAfterDay(date, comparing) {
  17509. return isAfter(startOfDay(date), startOfDay(comparing));
  17510. }
  17511. function isBefore(date, comparing) {
  17512. return date.getTime() < comparing.getTime();
  17513. }
  17514. function isEqual(date, comparing) {
  17515. return date.getTime() === comparing.getTime();
  17516. }
  17517. function isSameDay(date, comparing) {
  17518. return date.getDate() === comparing.getDate() && date.getMonth() === comparing.getMonth() && date.getFullYear() === comparing.getFullYear();
  17519. }
  17520. function isSameMonth(date, comparing) {
  17521. return date.getMonth() === comparing.getMonth() && date.getFullYear() === comparing.getFullYear();
  17522. }
  17523. function isSameYear(date, comparing) {
  17524. return date.getFullYear() === comparing.getFullYear();
  17525. }
  17526. function getDiff(date, comparing, unit) {
  17527. const d = new Date(date);
  17528. const c = new Date(comparing);
  17529. switch (unit) {
  17530. case 'years':
  17531. return d.getFullYear() - c.getFullYear();
  17532. case 'quarters':
  17533. return Math.floor((d.getMonth() - c.getMonth() + (d.getFullYear() - c.getFullYear()) * 12) / 4);
  17534. case 'months':
  17535. return d.getMonth() - c.getMonth() + (d.getFullYear() - c.getFullYear()) * 12;
  17536. case 'weeks':
  17537. return Math.floor((d.getTime() - c.getTime()) / (1000 * 60 * 60 * 24 * 7));
  17538. case 'days':
  17539. return Math.floor((d.getTime() - c.getTime()) / (1000 * 60 * 60 * 24));
  17540. case 'hours':
  17541. return Math.floor((d.getTime() - c.getTime()) / (1000 * 60 * 60));
  17542. case 'minutes':
  17543. return Math.floor((d.getTime() - c.getTime()) / (1000 * 60));
  17544. case 'seconds':
  17545. return Math.floor((d.getTime() - c.getTime()) / 1000);
  17546. default:
  17547. {
  17548. return d.getTime() - c.getTime();
  17549. }
  17550. }
  17551. }
  17552. function setHours(date, count) {
  17553. const d = new Date(date);
  17554. d.setHours(count);
  17555. return d;
  17556. }
  17557. function setMinutes(date, count) {
  17558. const d = new Date(date);
  17559. d.setMinutes(count);
  17560. return d;
  17561. }
  17562. function setMonth(date, count) {
  17563. const d = new Date(date);
  17564. d.setMonth(count);
  17565. return d;
  17566. }
  17567. function setDate(date, day) {
  17568. const d = new Date(date);
  17569. d.setDate(day);
  17570. return d;
  17571. }
  17572. function setYear(date, year) {
  17573. const d = new Date(date);
  17574. d.setFullYear(year);
  17575. return d;
  17576. }
  17577. function startOfDay(date) {
  17578. return new Date(date.getFullYear(), date.getMonth(), date.getDate(), 0, 0, 0, 0);
  17579. }
  17580. function endOfDay(date) {
  17581. return new Date(date.getFullYear(), date.getMonth(), date.getDate(), 23, 59, 59, 999);
  17582. }
  17583. class VuetifyDateAdapter {
  17584. constructor(options) {
  17585. this.locale = options.locale;
  17586. this.formats = options.formats;
  17587. }
  17588. date(value) {
  17589. return date(value);
  17590. }
  17591. toJsDate(date) {
  17592. return date;
  17593. }
  17594. toISO(date) {
  17595. return toISO(this, date);
  17596. }
  17597. parseISO(date) {
  17598. return parseISO(date);
  17599. }
  17600. addMinutes(date, amount) {
  17601. return addMinutes(date, amount);
  17602. }
  17603. addHours(date, amount) {
  17604. return addHours(date, amount);
  17605. }
  17606. addDays(date, amount) {
  17607. return addDays(date, amount);
  17608. }
  17609. addWeeks(date, amount) {
  17610. return addWeeks(date, amount);
  17611. }
  17612. addMonths(date, amount) {
  17613. return addMonths(date, amount);
  17614. }
  17615. getWeekArray(date, firstDayOfWeek) {
  17616. return getWeekArray(date, this.locale, firstDayOfWeek ? Number(firstDayOfWeek) : undefined);
  17617. }
  17618. startOfWeek(date, firstDayOfWeek) {
  17619. return startOfWeek(date, this.locale, firstDayOfWeek ? Number(firstDayOfWeek) : undefined);
  17620. }
  17621. endOfWeek(date) {
  17622. return endOfWeek(date, this.locale);
  17623. }
  17624. startOfMonth(date) {
  17625. return startOfMonth(date);
  17626. }
  17627. endOfMonth(date) {
  17628. return endOfMonth(date);
  17629. }
  17630. format(date, formatString) {
  17631. return format(date, formatString, this.locale, this.formats);
  17632. }
  17633. isEqual(date, comparing) {
  17634. return isEqual(date, comparing);
  17635. }
  17636. isValid(date) {
  17637. return isValid(date);
  17638. }
  17639. isWithinRange(date, range) {
  17640. return isWithinRange(date, range);
  17641. }
  17642. isAfter(date, comparing) {
  17643. return isAfter(date, comparing);
  17644. }
  17645. isAfterDay(date, comparing) {
  17646. return isAfterDay(date, comparing);
  17647. }
  17648. isBefore(date, comparing) {
  17649. return !isAfter(date, comparing) && !isEqual(date, comparing);
  17650. }
  17651. isSameDay(date, comparing) {
  17652. return isSameDay(date, comparing);
  17653. }
  17654. isSameMonth(date, comparing) {
  17655. return isSameMonth(date, comparing);
  17656. }
  17657. isSameYear(date, comparing) {
  17658. return isSameYear(date, comparing);
  17659. }
  17660. setMinutes(date, count) {
  17661. return setMinutes(date, count);
  17662. }
  17663. setHours(date, count) {
  17664. return setHours(date, count);
  17665. }
  17666. setMonth(date, count) {
  17667. return setMonth(date, count);
  17668. }
  17669. setDate(date, day) {
  17670. return setDate(date, day);
  17671. }
  17672. setYear(date, year) {
  17673. return setYear(date, year);
  17674. }
  17675. getDiff(date, comparing, unit) {
  17676. return getDiff(date, comparing, unit);
  17677. }
  17678. getWeekdays(firstDayOfWeek) {
  17679. return getWeekdays(this.locale, firstDayOfWeek ? Number(firstDayOfWeek) : undefined);
  17680. }
  17681. getYear(date) {
  17682. return getYear(date);
  17683. }
  17684. getMonth(date) {
  17685. return getMonth(date);
  17686. }
  17687. getDate(date) {
  17688. return getDate(date);
  17689. }
  17690. getNextMonth(date) {
  17691. return getNextMonth(date);
  17692. }
  17693. getPreviousMonth(date) {
  17694. return getPreviousMonth(date);
  17695. }
  17696. getHours(date) {
  17697. return getHours(date);
  17698. }
  17699. getMinutes(date) {
  17700. return getMinutes(date);
  17701. }
  17702. startOfDay(date) {
  17703. return startOfDay(date);
  17704. }
  17705. endOfDay(date) {
  17706. return endOfDay(date);
  17707. }
  17708. startOfYear(date) {
  17709. return startOfYear(date);
  17710. }
  17711. endOfYear(date) {
  17712. return endOfYear(date);
  17713. }
  17714. }
  17715. // Composables
  17716. const DateOptionsSymbol = Symbol.for('vuetify:date-options');
  17717. const DateAdapterSymbol = Symbol.for('vuetify:date-adapter');
  17718. function createDate(options, locale) {
  17719. const _options = mergeDeep({
  17720. adapter: VuetifyDateAdapter,
  17721. locale: {
  17722. af: 'af-ZA',
  17723. // ar: '', # not the same value for all variants
  17724. bg: 'bg-BG',
  17725. ca: 'ca-ES',
  17726. ckb: '',
  17727. cs: 'cs-CZ',
  17728. de: 'de-DE',
  17729. el: 'el-GR',
  17730. en: 'en-US',
  17731. // es: '', # not the same value for all variants
  17732. et: 'et-EE',
  17733. fa: 'fa-IR',
  17734. fi: 'fi-FI',
  17735. // fr: '', #not the same value for all variants
  17736. hr: 'hr-HR',
  17737. hu: 'hu-HU',
  17738. he: 'he-IL',
  17739. id: 'id-ID',
  17740. it: 'it-IT',
  17741. ja: 'ja-JP',
  17742. ko: 'ko-KR',
  17743. lv: 'lv-LV',
  17744. lt: 'lt-LT',
  17745. nl: 'nl-NL',
  17746. no: 'no-NO',
  17747. pl: 'pl-PL',
  17748. pt: 'pt-PT',
  17749. ro: 'ro-RO',
  17750. ru: 'ru-RU',
  17751. sk: 'sk-SK',
  17752. sl: 'sl-SI',
  17753. srCyrl: 'sr-SP',
  17754. srLatn: 'sr-SP',
  17755. sv: 'sv-SE',
  17756. th: 'th-TH',
  17757. tr: 'tr-TR',
  17758. az: 'az-AZ',
  17759. uk: 'uk-UA',
  17760. vi: 'vi-VN',
  17761. zhHans: 'zh-CN',
  17762. zhHant: 'zh-TW'
  17763. }
  17764. }, options);
  17765. return {
  17766. options: _options,
  17767. instance: createInstance(_options, locale)
  17768. };
  17769. }
  17770. function createInstance(options, locale) {
  17771. const instance = vue.reactive(typeof options.adapter === 'function'
  17772. // eslint-disable-next-line new-cap
  17773. ? new options.adapter({
  17774. locale: options.locale[locale.current.value] ?? locale.current.value,
  17775. formats: options.formats
  17776. }) : options.adapter);
  17777. vue.watch(locale.current, value => {
  17778. instance.locale = options.locale[value] ?? value ?? instance.locale;
  17779. });
  17780. return instance;
  17781. }
  17782. function useDate() {
  17783. const options = vue.inject(DateOptionsSymbol);
  17784. if (!options) throw new Error('[Vuetify] Could not find injected date options');
  17785. const locale = useLocale();
  17786. return createInstance(options, locale);
  17787. }
  17788. // https://stackoverflow.com/questions/274861/how-do-i-calculate-the-week-number-given-a-date/275024#275024
  17789. function getWeek(adapter, value) {
  17790. const date = adapter.toJsDate(value);
  17791. let year = date.getFullYear();
  17792. let d1w1 = new Date(year, 0, 1);
  17793. if (date < d1w1) {
  17794. year = year - 1;
  17795. d1w1 = new Date(year, 0, 1);
  17796. } else {
  17797. const tv = new Date(year + 1, 0, 1);
  17798. if (date >= tv) {
  17799. year = year + 1;
  17800. d1w1 = tv;
  17801. }
  17802. }
  17803. const diffTime = Math.abs(date.getTime() - d1w1.getTime());
  17804. const diffDays = Math.ceil(diffTime / (1000 * 60 * 60 * 24));
  17805. return Math.floor(diffDays / 7) + 1;
  17806. }
  17807. // Types
  17808. const makeVConfirmEditProps = propsFactory({
  17809. modelValue: null,
  17810. color: String,
  17811. cancelText: {
  17812. type: String,
  17813. default: '$vuetify.confirmEdit.cancel'
  17814. },
  17815. okText: {
  17816. type: String,
  17817. default: '$vuetify.confirmEdit.ok'
  17818. }
  17819. }, 'VConfirmEdit');
  17820. const VConfirmEdit = genericComponent()({
  17821. name: 'VConfirmEdit',
  17822. props: makeVConfirmEditProps(),
  17823. emits: {
  17824. cancel: () => true,
  17825. save: value => true,
  17826. 'update:modelValue': value => true
  17827. },
  17828. setup(props, _ref) {
  17829. let {
  17830. emit,
  17831. slots
  17832. } = _ref;
  17833. const model = useProxiedModel(props, 'modelValue');
  17834. const internalModel = vue.ref();
  17835. vue.watchEffect(() => {
  17836. internalModel.value = structuredClone(vue.toRaw(model.value));
  17837. });
  17838. const {
  17839. t
  17840. } = useLocale();
  17841. const isPristine = vue.computed(() => {
  17842. return deepEqual(model.value, internalModel.value);
  17843. });
  17844. function save() {
  17845. model.value = internalModel.value;
  17846. emit('save', internalModel.value);
  17847. }
  17848. function cancel() {
  17849. internalModel.value = structuredClone(vue.toRaw(model.value));
  17850. emit('cancel');
  17851. }
  17852. function actions(actionsProps) {
  17853. return vue.createVNode(vue.Fragment, null, [vue.createVNode(VBtn, vue.mergeProps({
  17854. "disabled": isPristine.value,
  17855. "variant": "text",
  17856. "color": props.color,
  17857. "onClick": cancel,
  17858. "text": t(props.cancelText)
  17859. }, actionsProps), null), vue.createVNode(VBtn, vue.mergeProps({
  17860. "disabled": isPristine.value,
  17861. "variant": "text",
  17862. "color": props.color,
  17863. "onClick": save,
  17864. "text": t(props.okText)
  17865. }, actionsProps), null)]);
  17866. }
  17867. let actionsUsed = false;
  17868. useRender(() => {
  17869. return vue.createVNode(vue.Fragment, null, [slots.default?.({
  17870. model: internalModel,
  17871. save,
  17872. cancel,
  17873. isPristine: isPristine.value,
  17874. get actions() {
  17875. actionsUsed = true;
  17876. return actions;
  17877. }
  17878. }), !actionsUsed && actions()]);
  17879. });
  17880. return {
  17881. save,
  17882. cancel,
  17883. isPristine
  17884. };
  17885. }
  17886. });
  17887. // Composables
  17888. // Types
  17889. const makeDataTableExpandProps = propsFactory({
  17890. expandOnClick: Boolean,
  17891. showExpand: Boolean,
  17892. expanded: {
  17893. type: Array,
  17894. default: () => []
  17895. }
  17896. }, 'DataTable-expand');
  17897. const VDataTableExpandedKey = Symbol.for('vuetify:datatable:expanded');
  17898. function provideExpanded(props) {
  17899. const expandOnClick = vue.toRef(props, 'expandOnClick');
  17900. const expanded = useProxiedModel(props, 'expanded', props.expanded, v => {
  17901. return new Set(v);
  17902. }, v => {
  17903. return [...v.values()];
  17904. });
  17905. function expand(item, value) {
  17906. const newExpanded = new Set(expanded.value);
  17907. if (!value) {
  17908. newExpanded.delete(item.value);
  17909. } else {
  17910. newExpanded.add(item.value);
  17911. }
  17912. expanded.value = newExpanded;
  17913. }
  17914. function isExpanded(item) {
  17915. return expanded.value.has(item.value);
  17916. }
  17917. function toggleExpand(item) {
  17918. expand(item, !isExpanded(item));
  17919. }
  17920. const data = {
  17921. expand,
  17922. expanded,
  17923. expandOnClick,
  17924. isExpanded,
  17925. toggleExpand
  17926. };
  17927. vue.provide(VDataTableExpandedKey, data);
  17928. return data;
  17929. }
  17930. function useExpanded() {
  17931. const data = vue.inject(VDataTableExpandedKey);
  17932. if (!data) throw new Error('foo');
  17933. return data;
  17934. }
  17935. // Composables
  17936. // Types
  17937. const makeDataTableGroupProps = propsFactory({
  17938. groupBy: {
  17939. type: Array,
  17940. default: () => []
  17941. }
  17942. }, 'DataTable-group');
  17943. const VDataTableGroupSymbol = Symbol.for('vuetify:data-table-group');
  17944. function createGroupBy(props) {
  17945. const groupBy = useProxiedModel(props, 'groupBy');
  17946. return {
  17947. groupBy
  17948. };
  17949. }
  17950. function provideGroupBy(options) {
  17951. const {
  17952. disableSort,
  17953. groupBy,
  17954. sortBy
  17955. } = options;
  17956. const opened = vue.ref(new Set());
  17957. const sortByWithGroups = vue.computed(() => {
  17958. return groupBy.value.map(val => ({
  17959. ...val,
  17960. order: val.order ?? false
  17961. })).concat(disableSort?.value ? [] : sortBy.value);
  17962. });
  17963. function isGroupOpen(group) {
  17964. return opened.value.has(group.id);
  17965. }
  17966. function toggleGroup(group) {
  17967. const newOpened = new Set(opened.value);
  17968. if (!isGroupOpen(group)) newOpened.add(group.id);else newOpened.delete(group.id);
  17969. opened.value = newOpened;
  17970. }
  17971. function extractRows(items) {
  17972. function dive(group) {
  17973. const arr = [];
  17974. for (const item of group.items) {
  17975. if ('type' in item && item.type === 'group') {
  17976. arr.push(...dive(item));
  17977. } else {
  17978. arr.push(item);
  17979. }
  17980. }
  17981. return arr;
  17982. }
  17983. return dive({
  17984. type: 'group',
  17985. items,
  17986. id: 'dummy',
  17987. key: 'dummy',
  17988. value: 'dummy',
  17989. depth: 0
  17990. });
  17991. }
  17992. // onBeforeMount(() => {
  17993. // for (const key of groupedItems.value.keys()) {
  17994. // opened.value.add(key)
  17995. // }
  17996. // })
  17997. const data = {
  17998. sortByWithGroups,
  17999. toggleGroup,
  18000. opened,
  18001. groupBy,
  18002. extractRows,
  18003. isGroupOpen
  18004. };
  18005. vue.provide(VDataTableGroupSymbol, data);
  18006. return data;
  18007. }
  18008. function useGroupBy() {
  18009. const data = vue.inject(VDataTableGroupSymbol);
  18010. if (!data) throw new Error('Missing group!');
  18011. return data;
  18012. }
  18013. function groupItemsByProperty(items, groupBy) {
  18014. if (!items.length) return [];
  18015. const groups = new Map();
  18016. for (const item of items) {
  18017. const value = getObjectValueByPath(item.raw, groupBy);
  18018. if (!groups.has(value)) {
  18019. groups.set(value, []);
  18020. }
  18021. groups.get(value).push(item);
  18022. }
  18023. return groups;
  18024. }
  18025. function groupItems(items, groupBy) {
  18026. let depth = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : 0;
  18027. let prefix = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : 'root';
  18028. if (!groupBy.length) return [];
  18029. const groupedItems = groupItemsByProperty(items, groupBy[0]);
  18030. const groups = [];
  18031. const rest = groupBy.slice(1);
  18032. groupedItems.forEach((items, value) => {
  18033. const key = groupBy[0];
  18034. const id = `${prefix}_${key}_${value}`;
  18035. groups.push({
  18036. depth,
  18037. id,
  18038. key,
  18039. value,
  18040. items: rest.length ? groupItems(items, rest, depth + 1, id) : items,
  18041. type: 'group'
  18042. });
  18043. });
  18044. return groups;
  18045. }
  18046. function flattenItems(items, opened) {
  18047. const flatItems = [];
  18048. for (const item of items) {
  18049. // TODO: make this better
  18050. if ('type' in item && item.type === 'group') {
  18051. if (item.value != null) {
  18052. flatItems.push(item);
  18053. }
  18054. if (opened.has(item.id) || item.value == null) {
  18055. flatItems.push(...flattenItems(item.items, opened));
  18056. }
  18057. } else {
  18058. flatItems.push(item);
  18059. }
  18060. }
  18061. return flatItems;
  18062. }
  18063. function useGroupedItems(items, groupBy, opened) {
  18064. const flatItems = vue.computed(() => {
  18065. if (!groupBy.value.length) return items.value;
  18066. const groupedItems = groupItems(items.value, groupBy.value.map(item => item.key));
  18067. return flattenItems(groupedItems, opened.value);
  18068. });
  18069. return {
  18070. flatItems
  18071. };
  18072. }
  18073. // Utilities
  18074. // Types
  18075. function useOptions(_ref) {
  18076. let {
  18077. page,
  18078. itemsPerPage,
  18079. sortBy,
  18080. groupBy,
  18081. search
  18082. } = _ref;
  18083. const vm = getCurrentInstance('VDataTable');
  18084. const options = vue.computed(() => ({
  18085. page: page.value,
  18086. itemsPerPage: itemsPerPage.value,
  18087. sortBy: sortBy.value,
  18088. groupBy: groupBy.value,
  18089. search: search.value
  18090. }));
  18091. let oldOptions = null;
  18092. vue.watch(options, () => {
  18093. if (deepEqual(oldOptions, options.value)) return;
  18094. // Reset page when searching
  18095. if (oldOptions && oldOptions.search !== options.value.search) {
  18096. page.value = 1;
  18097. }
  18098. vm.emit('update:options', options.value);
  18099. oldOptions = options.value;
  18100. }, {
  18101. deep: true,
  18102. immediate: true
  18103. });
  18104. }
  18105. // Composables
  18106. // Types
  18107. const makeDataTablePaginateProps = propsFactory({
  18108. page: {
  18109. type: [Number, String],
  18110. default: 1
  18111. },
  18112. itemsPerPage: {
  18113. type: [Number, String],
  18114. default: 10
  18115. }
  18116. }, 'DataTable-paginate');
  18117. const VDataTablePaginationSymbol = Symbol.for('vuetify:data-table-pagination');
  18118. function createPagination(props) {
  18119. const page = useProxiedModel(props, 'page', undefined, value => +(value ?? 1));
  18120. const itemsPerPage = useProxiedModel(props, 'itemsPerPage', undefined, value => +(value ?? 10));
  18121. return {
  18122. page,
  18123. itemsPerPage
  18124. };
  18125. }
  18126. function providePagination(options) {
  18127. const {
  18128. page,
  18129. itemsPerPage,
  18130. itemsLength
  18131. } = options;
  18132. const startIndex = vue.computed(() => {
  18133. if (itemsPerPage.value === -1) return 0;
  18134. return itemsPerPage.value * (page.value - 1);
  18135. });
  18136. const stopIndex = vue.computed(() => {
  18137. if (itemsPerPage.value === -1) return itemsLength.value;
  18138. return Math.min(itemsLength.value, startIndex.value + itemsPerPage.value);
  18139. });
  18140. const pageCount = vue.computed(() => {
  18141. if (itemsPerPage.value === -1 || itemsLength.value === 0) return 1;
  18142. return Math.ceil(itemsLength.value / itemsPerPage.value);
  18143. });
  18144. // Don't run immediately, items may not have been loaded yet: #17966
  18145. vue.watch([page, pageCount], () => {
  18146. if (page.value > pageCount.value) {
  18147. page.value = pageCount.value;
  18148. }
  18149. });
  18150. function setItemsPerPage(value) {
  18151. itemsPerPage.value = value;
  18152. page.value = 1;
  18153. }
  18154. function nextPage() {
  18155. page.value = clamp(page.value + 1, 1, pageCount.value);
  18156. }
  18157. function prevPage() {
  18158. page.value = clamp(page.value - 1, 1, pageCount.value);
  18159. }
  18160. function setPage(value) {
  18161. page.value = clamp(value, 1, pageCount.value);
  18162. }
  18163. const data = {
  18164. page,
  18165. itemsPerPage,
  18166. startIndex,
  18167. stopIndex,
  18168. pageCount,
  18169. itemsLength,
  18170. nextPage,
  18171. prevPage,
  18172. setPage,
  18173. setItemsPerPage
  18174. };
  18175. vue.provide(VDataTablePaginationSymbol, data);
  18176. return data;
  18177. }
  18178. function usePagination() {
  18179. const data = vue.inject(VDataTablePaginationSymbol);
  18180. if (!data) throw new Error('Missing pagination!');
  18181. return data;
  18182. }
  18183. function usePaginatedItems(options) {
  18184. const vm = getCurrentInstance('usePaginatedItems');
  18185. const {
  18186. items,
  18187. startIndex,
  18188. stopIndex,
  18189. itemsPerPage
  18190. } = options;
  18191. const paginatedItems = vue.computed(() => {
  18192. if (itemsPerPage.value <= 0) return items.value;
  18193. return items.value.slice(startIndex.value, stopIndex.value);
  18194. });
  18195. vue.watch(paginatedItems, val => {
  18196. vm.emit('update:currentItems', val);
  18197. });
  18198. return {
  18199. paginatedItems
  18200. };
  18201. }
  18202. // Composables
  18203. // Types
  18204. const singleSelectStrategy = {
  18205. showSelectAll: false,
  18206. allSelected: () => [],
  18207. select: _ref => {
  18208. let {
  18209. items,
  18210. value
  18211. } = _ref;
  18212. return new Set(value ? [items[0]?.value] : []);
  18213. },
  18214. selectAll: _ref2 => {
  18215. let {
  18216. selected
  18217. } = _ref2;
  18218. return selected;
  18219. }
  18220. };
  18221. const pageSelectStrategy = {
  18222. showSelectAll: true,
  18223. allSelected: _ref3 => {
  18224. let {
  18225. currentPage
  18226. } = _ref3;
  18227. return currentPage;
  18228. },
  18229. select: _ref4 => {
  18230. let {
  18231. items,
  18232. value,
  18233. selected
  18234. } = _ref4;
  18235. for (const item of items) {
  18236. if (value) selected.add(item.value);else selected.delete(item.value);
  18237. }
  18238. return selected;
  18239. },
  18240. selectAll: _ref5 => {
  18241. let {
  18242. value,
  18243. currentPage,
  18244. selected
  18245. } = _ref5;
  18246. return pageSelectStrategy.select({
  18247. items: currentPage,
  18248. value,
  18249. selected
  18250. });
  18251. }
  18252. };
  18253. const allSelectStrategy = {
  18254. showSelectAll: true,
  18255. allSelected: _ref6 => {
  18256. let {
  18257. allItems
  18258. } = _ref6;
  18259. return allItems;
  18260. },
  18261. select: _ref7 => {
  18262. let {
  18263. items,
  18264. value,
  18265. selected
  18266. } = _ref7;
  18267. for (const item of items) {
  18268. if (value) selected.add(item.value);else selected.delete(item.value);
  18269. }
  18270. return selected;
  18271. },
  18272. selectAll: _ref8 => {
  18273. let {
  18274. value,
  18275. allItems,
  18276. selected
  18277. } = _ref8;
  18278. return allSelectStrategy.select({
  18279. items: allItems,
  18280. value,
  18281. selected
  18282. });
  18283. }
  18284. };
  18285. const makeDataTableSelectProps = propsFactory({
  18286. showSelect: Boolean,
  18287. selectStrategy: {
  18288. type: [String, Object],
  18289. default: 'page'
  18290. },
  18291. modelValue: {
  18292. type: Array,
  18293. default: () => []
  18294. },
  18295. valueComparator: {
  18296. type: Function,
  18297. default: deepEqual
  18298. }
  18299. }, 'DataTable-select');
  18300. const VDataTableSelectionSymbol = Symbol.for('vuetify:data-table-selection');
  18301. function provideSelection(props, _ref9) {
  18302. let {
  18303. allItems,
  18304. currentPage
  18305. } = _ref9;
  18306. const selected = useProxiedModel(props, 'modelValue', props.modelValue, v => {
  18307. return new Set(wrapInArray(v).map(v => {
  18308. return allItems.value.find(item => props.valueComparator(v, item.value))?.value ?? v;
  18309. }));
  18310. }, v => {
  18311. return [...v.values()];
  18312. });
  18313. const allSelectable = vue.computed(() => allItems.value.filter(item => item.selectable));
  18314. const currentPageSelectable = vue.computed(() => currentPage.value.filter(item => item.selectable));
  18315. const selectStrategy = vue.computed(() => {
  18316. if (typeof props.selectStrategy === 'object') return props.selectStrategy;
  18317. switch (props.selectStrategy) {
  18318. case 'single':
  18319. return singleSelectStrategy;
  18320. case 'all':
  18321. return allSelectStrategy;
  18322. case 'page':
  18323. default:
  18324. return pageSelectStrategy;
  18325. }
  18326. });
  18327. function isSelected(items) {
  18328. return wrapInArray(items).every(item => selected.value.has(item.value));
  18329. }
  18330. function isSomeSelected(items) {
  18331. return wrapInArray(items).some(item => selected.value.has(item.value));
  18332. }
  18333. function select(items, value) {
  18334. const newSelected = selectStrategy.value.select({
  18335. items,
  18336. value,
  18337. selected: new Set(selected.value)
  18338. });
  18339. selected.value = newSelected;
  18340. }
  18341. function toggleSelect(item) {
  18342. select([item], !isSelected([item]));
  18343. }
  18344. function selectAll(value) {
  18345. const newSelected = selectStrategy.value.selectAll({
  18346. value,
  18347. allItems: allSelectable.value,
  18348. currentPage: currentPageSelectable.value,
  18349. selected: new Set(selected.value)
  18350. });
  18351. selected.value = newSelected;
  18352. }
  18353. const someSelected = vue.computed(() => selected.value.size > 0);
  18354. const allSelected = vue.computed(() => {
  18355. const items = selectStrategy.value.allSelected({
  18356. allItems: allSelectable.value,
  18357. currentPage: currentPageSelectable.value
  18358. });
  18359. return !!items.length && isSelected(items);
  18360. });
  18361. const showSelectAll = vue.computed(() => selectStrategy.value.showSelectAll);
  18362. const data = {
  18363. toggleSelect,
  18364. select,
  18365. selectAll,
  18366. isSelected,
  18367. isSomeSelected,
  18368. someSelected,
  18369. allSelected,
  18370. showSelectAll
  18371. };
  18372. vue.provide(VDataTableSelectionSymbol, data);
  18373. return data;
  18374. }
  18375. function useSelection() {
  18376. const data = vue.inject(VDataTableSelectionSymbol);
  18377. if (!data) throw new Error('Missing selection!');
  18378. return data;
  18379. }
  18380. // Composables
  18381. // Types
  18382. const makeDataTableSortProps = propsFactory({
  18383. sortBy: {
  18384. type: Array,
  18385. default: () => []
  18386. },
  18387. customKeySort: Object,
  18388. multiSort: Boolean,
  18389. mustSort: Boolean
  18390. }, 'DataTable-sort');
  18391. const VDataTableSortSymbol = Symbol.for('vuetify:data-table-sort');
  18392. function createSort(props) {
  18393. const sortBy = useProxiedModel(props, 'sortBy');
  18394. const mustSort = vue.toRef(props, 'mustSort');
  18395. const multiSort = vue.toRef(props, 'multiSort');
  18396. return {
  18397. sortBy,
  18398. mustSort,
  18399. multiSort
  18400. };
  18401. }
  18402. function provideSort(options) {
  18403. const {
  18404. sortBy,
  18405. mustSort,
  18406. multiSort,
  18407. page
  18408. } = options;
  18409. const toggleSort = column => {
  18410. if (column.key == null) return;
  18411. let newSortBy = sortBy.value.map(x => ({
  18412. ...x
  18413. })) ?? [];
  18414. const item = newSortBy.find(x => x.key === column.key);
  18415. if (!item) {
  18416. if (multiSort.value) newSortBy = [...newSortBy, {
  18417. key: column.key,
  18418. order: 'asc'
  18419. }];else newSortBy = [{
  18420. key: column.key,
  18421. order: 'asc'
  18422. }];
  18423. } else if (item.order === 'desc') {
  18424. if (mustSort.value) {
  18425. item.order = 'asc';
  18426. } else {
  18427. newSortBy = newSortBy.filter(x => x.key !== column.key);
  18428. }
  18429. } else {
  18430. item.order = 'desc';
  18431. }
  18432. sortBy.value = newSortBy;
  18433. if (page) page.value = 1;
  18434. };
  18435. function isSorted(column) {
  18436. return !!sortBy.value.find(item => item.key === column.key);
  18437. }
  18438. const data = {
  18439. sortBy,
  18440. toggleSort,
  18441. isSorted
  18442. };
  18443. vue.provide(VDataTableSortSymbol, data);
  18444. return data;
  18445. }
  18446. function useSort() {
  18447. const data = vue.inject(VDataTableSortSymbol);
  18448. if (!data) throw new Error('Missing sort!');
  18449. return data;
  18450. }
  18451. // TODO: abstract into project composable
  18452. function useSortedItems(props, items, sortBy, options) {
  18453. const locale = useLocale();
  18454. const sortedItems = vue.computed(() => {
  18455. if (!sortBy.value.length) return items.value;
  18456. return sortItems(items.value, sortBy.value, locale.current.value, {
  18457. transform: options?.transform,
  18458. sortFunctions: {
  18459. ...props.customKeySort,
  18460. ...options?.sortFunctions?.value
  18461. },
  18462. sortRawFunctions: options?.sortRawFunctions?.value
  18463. });
  18464. });
  18465. return {
  18466. sortedItems
  18467. };
  18468. }
  18469. function sortItems(items, sortByItems, locale, options) {
  18470. const stringCollator = new Intl.Collator(locale, {
  18471. sensitivity: 'accent',
  18472. usage: 'sort'
  18473. });
  18474. const transformedItems = items.map(item => [item, options?.transform ? options.transform(item) : item]);
  18475. return transformedItems.sort((a, b) => {
  18476. for (let i = 0; i < sortByItems.length; i++) {
  18477. let hasCustomResult = false;
  18478. const sortKey = sortByItems[i].key;
  18479. const sortOrder = sortByItems[i].order ?? 'asc';
  18480. if (sortOrder === false) continue;
  18481. let sortA = getObjectValueByPath(a[1], sortKey);
  18482. let sortB = getObjectValueByPath(b[1], sortKey);
  18483. let sortARaw = a[0].raw;
  18484. let sortBRaw = b[0].raw;
  18485. if (sortOrder === 'desc') {
  18486. [sortA, sortB] = [sortB, sortA];
  18487. [sortARaw, sortBRaw] = [sortBRaw, sortARaw];
  18488. }
  18489. if (options?.sortRawFunctions?.[sortKey]) {
  18490. const customResult = options.sortRawFunctions[sortKey](sortARaw, sortBRaw);
  18491. if (customResult == null) continue;
  18492. hasCustomResult = true;
  18493. if (customResult) return customResult;
  18494. }
  18495. if (options?.sortFunctions?.[sortKey]) {
  18496. const customResult = options.sortFunctions[sortKey](sortA, sortB);
  18497. if (customResult == null) continue;
  18498. hasCustomResult = true;
  18499. if (customResult) return customResult;
  18500. }
  18501. if (hasCustomResult) continue;
  18502. // Dates should be compared numerically
  18503. if (sortA instanceof Date && sortB instanceof Date) {
  18504. return sortA.getTime() - sortB.getTime();
  18505. }
  18506. [sortA, sortB] = [sortA, sortB].map(s => s != null ? s.toString().toLocaleLowerCase() : s);
  18507. if (sortA !== sortB) {
  18508. if (isEmpty(sortA) && isEmpty(sortB)) return 0;
  18509. if (isEmpty(sortA)) return -1;
  18510. if (isEmpty(sortB)) return 1;
  18511. if (!isNaN(sortA) && !isNaN(sortB)) return Number(sortA) - Number(sortB);
  18512. return stringCollator.compare(sortA, sortB);
  18513. }
  18514. }
  18515. return 0;
  18516. }).map(_ref => {
  18517. let [item] = _ref;
  18518. return item;
  18519. });
  18520. }
  18521. // Utilities
  18522. // Types
  18523. // Composables
  18524. const makeDataIteratorItemsProps = propsFactory({
  18525. items: {
  18526. type: Array,
  18527. default: () => []
  18528. },
  18529. itemValue: {
  18530. type: [String, Array, Function],
  18531. default: 'id'
  18532. },
  18533. itemSelectable: {
  18534. type: [String, Array, Function],
  18535. default: null
  18536. },
  18537. returnObject: Boolean
  18538. }, 'DataIterator-items');
  18539. function transformItem$1(props, item) {
  18540. const value = props.returnObject ? item : getPropertyFromItem(item, props.itemValue);
  18541. const selectable = getPropertyFromItem(item, props.itemSelectable, true);
  18542. return {
  18543. type: 'item',
  18544. value,
  18545. selectable,
  18546. raw: item
  18547. };
  18548. }
  18549. function transformItems$1(props, items) {
  18550. const array = [];
  18551. for (const item of items) {
  18552. array.push(transformItem$1(props, item));
  18553. }
  18554. return array;
  18555. }
  18556. function useDataIteratorItems(props) {
  18557. const items = vue.computed(() => transformItems$1(props, props.items));
  18558. return {
  18559. items
  18560. };
  18561. }
  18562. // Types
  18563. const makeVDataIteratorProps = propsFactory({
  18564. search: String,
  18565. loading: Boolean,
  18566. ...makeComponentProps(),
  18567. ...makeDataIteratorItemsProps(),
  18568. ...makeDataTableSelectProps(),
  18569. ...makeDataTableSortProps(),
  18570. ...makeDataTablePaginateProps({
  18571. itemsPerPage: 5
  18572. }),
  18573. ...makeDataTableExpandProps(),
  18574. ...makeDataTableGroupProps(),
  18575. ...makeFilterProps(),
  18576. ...makeTagProps(),
  18577. ...makeTransitionProps({
  18578. transition: {
  18579. component: VFadeTransition,
  18580. hideOnLeave: true
  18581. }
  18582. })
  18583. }, 'VDataIterator');
  18584. const VDataIterator = genericComponent()({
  18585. name: 'VDataIterator',
  18586. props: makeVDataIteratorProps(),
  18587. emits: {
  18588. 'update:modelValue': value => true,
  18589. 'update:groupBy': value => true,
  18590. 'update:page': value => true,
  18591. 'update:itemsPerPage': value => true,
  18592. 'update:sortBy': value => true,
  18593. 'update:options': value => true,
  18594. 'update:expanded': value => true,
  18595. 'update:currentItems': value => true
  18596. },
  18597. setup(props, _ref) {
  18598. let {
  18599. slots
  18600. } = _ref;
  18601. const groupBy = useProxiedModel(props, 'groupBy');
  18602. const search = vue.toRef(props, 'search');
  18603. const {
  18604. items
  18605. } = useDataIteratorItems(props);
  18606. const {
  18607. filteredItems
  18608. } = useFilter(props, items, search, {
  18609. transform: item => item.raw
  18610. });
  18611. const {
  18612. sortBy,
  18613. multiSort,
  18614. mustSort
  18615. } = createSort(props);
  18616. const {
  18617. page,
  18618. itemsPerPage
  18619. } = createPagination(props);
  18620. const {
  18621. toggleSort
  18622. } = provideSort({
  18623. sortBy,
  18624. multiSort,
  18625. mustSort,
  18626. page
  18627. });
  18628. const {
  18629. sortByWithGroups,
  18630. opened,
  18631. extractRows,
  18632. isGroupOpen,
  18633. toggleGroup
  18634. } = provideGroupBy({
  18635. groupBy,
  18636. sortBy
  18637. });
  18638. const {
  18639. sortedItems
  18640. } = useSortedItems(props, filteredItems, sortByWithGroups, {
  18641. transform: item => item.raw
  18642. });
  18643. const {
  18644. flatItems
  18645. } = useGroupedItems(sortedItems, groupBy, opened);
  18646. const itemsLength = vue.computed(() => flatItems.value.length);
  18647. const {
  18648. startIndex,
  18649. stopIndex,
  18650. pageCount,
  18651. prevPage,
  18652. nextPage,
  18653. setItemsPerPage,
  18654. setPage
  18655. } = providePagination({
  18656. page,
  18657. itemsPerPage,
  18658. itemsLength
  18659. });
  18660. const {
  18661. paginatedItems
  18662. } = usePaginatedItems({
  18663. items: flatItems,
  18664. startIndex,
  18665. stopIndex,
  18666. itemsPerPage
  18667. });
  18668. const paginatedItemsWithoutGroups = vue.computed(() => extractRows(paginatedItems.value));
  18669. const {
  18670. isSelected,
  18671. select,
  18672. selectAll,
  18673. toggleSelect
  18674. } = provideSelection(props, {
  18675. allItems: items,
  18676. currentPage: paginatedItemsWithoutGroups
  18677. });
  18678. const {
  18679. isExpanded,
  18680. toggleExpand
  18681. } = provideExpanded(props);
  18682. useOptions({
  18683. page,
  18684. itemsPerPage,
  18685. sortBy,
  18686. groupBy,
  18687. search
  18688. });
  18689. const slotProps = vue.computed(() => ({
  18690. page: page.value,
  18691. itemsPerPage: itemsPerPage.value,
  18692. sortBy: sortBy.value,
  18693. pageCount: pageCount.value,
  18694. toggleSort,
  18695. prevPage,
  18696. nextPage,
  18697. setPage,
  18698. setItemsPerPage,
  18699. isSelected,
  18700. select,
  18701. selectAll,
  18702. toggleSelect,
  18703. isExpanded,
  18704. toggleExpand,
  18705. isGroupOpen,
  18706. toggleGroup,
  18707. items: paginatedItemsWithoutGroups.value,
  18708. groupedItems: paginatedItems.value
  18709. }));
  18710. useRender(() => vue.createVNode(props.tag, {
  18711. "class": ['v-data-iterator', {
  18712. 'v-data-iterator--loading': props.loading
  18713. }, props.class],
  18714. "style": props.style
  18715. }, {
  18716. default: () => [slots.header?.(slotProps.value), vue.createVNode(MaybeTransition, {
  18717. "transition": props.transition
  18718. }, {
  18719. default: () => [props.loading ? vue.createVNode(LoaderSlot, {
  18720. "key": "loader",
  18721. "name": "v-data-iterator",
  18722. "active": true
  18723. }, {
  18724. default: slotProps => slots.loader?.(slotProps)
  18725. }) : vue.createVNode("div", {
  18726. "key": "items"
  18727. }, [!paginatedItems.value.length ? slots['no-data']?.() : slots.default?.(slotProps.value)])]
  18728. }), slots.footer?.(slotProps.value)]
  18729. }));
  18730. return {};
  18731. }
  18732. });
  18733. // Utilities
  18734. // Types
  18735. function useRefs() {
  18736. const refs = vue.ref([]);
  18737. vue.onBeforeUpdate(() => refs.value = []);
  18738. function updateRef(e, i) {
  18739. refs.value[i] = e;
  18740. }
  18741. return {
  18742. refs,
  18743. updateRef
  18744. };
  18745. }
  18746. // Types
  18747. const makeVPaginationProps = propsFactory({
  18748. activeColor: String,
  18749. start: {
  18750. type: [Number, String],
  18751. default: 1
  18752. },
  18753. modelValue: {
  18754. type: Number,
  18755. default: props => props.start
  18756. },
  18757. disabled: Boolean,
  18758. length: {
  18759. type: [Number, String],
  18760. default: 1,
  18761. validator: val => val % 1 === 0
  18762. },
  18763. totalVisible: [Number, String],
  18764. firstIcon: {
  18765. type: IconValue,
  18766. default: '$first'
  18767. },
  18768. prevIcon: {
  18769. type: IconValue,
  18770. default: '$prev'
  18771. },
  18772. nextIcon: {
  18773. type: IconValue,
  18774. default: '$next'
  18775. },
  18776. lastIcon: {
  18777. type: IconValue,
  18778. default: '$last'
  18779. },
  18780. ariaLabel: {
  18781. type: String,
  18782. default: '$vuetify.pagination.ariaLabel.root'
  18783. },
  18784. pageAriaLabel: {
  18785. type: String,
  18786. default: '$vuetify.pagination.ariaLabel.page'
  18787. },
  18788. currentPageAriaLabel: {
  18789. type: String,
  18790. default: '$vuetify.pagination.ariaLabel.currentPage'
  18791. },
  18792. firstAriaLabel: {
  18793. type: String,
  18794. default: '$vuetify.pagination.ariaLabel.first'
  18795. },
  18796. previousAriaLabel: {
  18797. type: String,
  18798. default: '$vuetify.pagination.ariaLabel.previous'
  18799. },
  18800. nextAriaLabel: {
  18801. type: String,
  18802. default: '$vuetify.pagination.ariaLabel.next'
  18803. },
  18804. lastAriaLabel: {
  18805. type: String,
  18806. default: '$vuetify.pagination.ariaLabel.last'
  18807. },
  18808. ellipsis: {
  18809. type: String,
  18810. default: '...'
  18811. },
  18812. showFirstLastPage: Boolean,
  18813. ...makeBorderProps(),
  18814. ...makeComponentProps(),
  18815. ...makeDensityProps(),
  18816. ...makeElevationProps(),
  18817. ...makeRoundedProps(),
  18818. ...makeSizeProps(),
  18819. ...makeTagProps({
  18820. tag: 'nav'
  18821. }),
  18822. ...makeThemeProps(),
  18823. ...makeVariantProps({
  18824. variant: 'text'
  18825. })
  18826. }, 'VPagination');
  18827. const VPagination = genericComponent()({
  18828. name: 'VPagination',
  18829. props: makeVPaginationProps(),
  18830. emits: {
  18831. 'update:modelValue': value => true,
  18832. first: value => true,
  18833. prev: value => true,
  18834. next: value => true,
  18835. last: value => true
  18836. },
  18837. setup(props, _ref) {
  18838. let {
  18839. slots,
  18840. emit
  18841. } = _ref;
  18842. const page = useProxiedModel(props, 'modelValue');
  18843. const {
  18844. t,
  18845. n
  18846. } = useLocale();
  18847. const {
  18848. isRtl
  18849. } = useRtl();
  18850. const {
  18851. themeClasses
  18852. } = provideTheme(props);
  18853. const {
  18854. width
  18855. } = useDisplay();
  18856. const maxButtons = vue.shallowRef(-1);
  18857. provideDefaults(undefined, {
  18858. scoped: true
  18859. });
  18860. const {
  18861. resizeRef
  18862. } = useResizeObserver(entries => {
  18863. if (!entries.length) return;
  18864. const {
  18865. target,
  18866. contentRect
  18867. } = entries[0];
  18868. const firstItem = target.querySelector('.v-pagination__list > *');
  18869. if (!firstItem) return;
  18870. const totalWidth = contentRect.width;
  18871. const itemWidth = firstItem.offsetWidth + parseFloat(getComputedStyle(firstItem).marginRight) * 2;
  18872. maxButtons.value = getMax(totalWidth, itemWidth);
  18873. });
  18874. const length = vue.computed(() => parseInt(props.length, 10));
  18875. const start = vue.computed(() => parseInt(props.start, 10));
  18876. const totalVisible = vue.computed(() => {
  18877. if (props.totalVisible != null) return parseInt(props.totalVisible, 10);else if (maxButtons.value >= 0) return maxButtons.value;
  18878. return getMax(width.value, 58);
  18879. });
  18880. function getMax(totalWidth, itemWidth) {
  18881. const minButtons = props.showFirstLastPage ? 5 : 3;
  18882. return Math.max(0, Math.floor(
  18883. // Round to two decimal places to avoid floating point errors
  18884. +((totalWidth - itemWidth * minButtons) / itemWidth).toFixed(2)));
  18885. }
  18886. const range = vue.computed(() => {
  18887. if (length.value <= 0 || isNaN(length.value) || length.value > Number.MAX_SAFE_INTEGER) return [];
  18888. if (totalVisible.value <= 0) return [];else if (totalVisible.value === 1) return [page.value];
  18889. if (length.value <= totalVisible.value) {
  18890. return createRange(length.value, start.value);
  18891. }
  18892. const even = totalVisible.value % 2 === 0;
  18893. const middle = even ? totalVisible.value / 2 : Math.floor(totalVisible.value / 2);
  18894. const left = even ? middle : middle + 1;
  18895. const right = length.value - middle;
  18896. if (left - page.value >= 0) {
  18897. return [...createRange(Math.max(1, totalVisible.value - 1), start.value), props.ellipsis, length.value];
  18898. } else if (page.value - right >= (even ? 1 : 0)) {
  18899. const rangeLength = totalVisible.value - 1;
  18900. const rangeStart = length.value - rangeLength + start.value;
  18901. return [start.value, props.ellipsis, ...createRange(rangeLength, rangeStart)];
  18902. } else {
  18903. const rangeLength = Math.max(1, totalVisible.value - 3);
  18904. const rangeStart = rangeLength === 1 ? page.value : page.value - Math.ceil(rangeLength / 2) + start.value;
  18905. return [start.value, props.ellipsis, ...createRange(rangeLength, rangeStart), props.ellipsis, length.value];
  18906. }
  18907. });
  18908. // TODO: 'first' | 'prev' | 'next' | 'last' does not work here?
  18909. function setValue(e, value, event) {
  18910. e.preventDefault();
  18911. page.value = value;
  18912. event && emit(event, value);
  18913. }
  18914. const {
  18915. refs,
  18916. updateRef
  18917. } = useRefs();
  18918. provideDefaults({
  18919. VPaginationBtn: {
  18920. color: vue.toRef(props, 'color'),
  18921. border: vue.toRef(props, 'border'),
  18922. density: vue.toRef(props, 'density'),
  18923. size: vue.toRef(props, 'size'),
  18924. variant: vue.toRef(props, 'variant'),
  18925. rounded: vue.toRef(props, 'rounded'),
  18926. elevation: vue.toRef(props, 'elevation')
  18927. }
  18928. });
  18929. const items = vue.computed(() => {
  18930. return range.value.map((item, index) => {
  18931. const ref = e => updateRef(e, index);
  18932. if (typeof item === 'string') {
  18933. return {
  18934. isActive: false,
  18935. key: `ellipsis-${index}`,
  18936. page: item,
  18937. props: {
  18938. ref,
  18939. ellipsis: true,
  18940. icon: true,
  18941. disabled: true
  18942. }
  18943. };
  18944. } else {
  18945. const isActive = item === page.value;
  18946. return {
  18947. isActive,
  18948. key: item,
  18949. page: n(item),
  18950. props: {
  18951. ref,
  18952. ellipsis: false,
  18953. icon: true,
  18954. disabled: !!props.disabled || +props.length < 2,
  18955. color: isActive ? props.activeColor : props.color,
  18956. 'aria-current': isActive,
  18957. 'aria-label': t(isActive ? props.currentPageAriaLabel : props.pageAriaLabel, item),
  18958. onClick: e => setValue(e, item)
  18959. }
  18960. };
  18961. }
  18962. });
  18963. });
  18964. const controls = vue.computed(() => {
  18965. const prevDisabled = !!props.disabled || page.value <= start.value;
  18966. const nextDisabled = !!props.disabled || page.value >= start.value + length.value - 1;
  18967. return {
  18968. first: props.showFirstLastPage ? {
  18969. icon: isRtl.value ? props.lastIcon : props.firstIcon,
  18970. onClick: e => setValue(e, start.value, 'first'),
  18971. disabled: prevDisabled,
  18972. 'aria-label': t(props.firstAriaLabel),
  18973. 'aria-disabled': prevDisabled
  18974. } : undefined,
  18975. prev: {
  18976. icon: isRtl.value ? props.nextIcon : props.prevIcon,
  18977. onClick: e => setValue(e, page.value - 1, 'prev'),
  18978. disabled: prevDisabled,
  18979. 'aria-label': t(props.previousAriaLabel),
  18980. 'aria-disabled': prevDisabled
  18981. },
  18982. next: {
  18983. icon: isRtl.value ? props.prevIcon : props.nextIcon,
  18984. onClick: e => setValue(e, page.value + 1, 'next'),
  18985. disabled: nextDisabled,
  18986. 'aria-label': t(props.nextAriaLabel),
  18987. 'aria-disabled': nextDisabled
  18988. },
  18989. last: props.showFirstLastPage ? {
  18990. icon: isRtl.value ? props.firstIcon : props.lastIcon,
  18991. onClick: e => setValue(e, start.value + length.value - 1, 'last'),
  18992. disabled: nextDisabled,
  18993. 'aria-label': t(props.lastAriaLabel),
  18994. 'aria-disabled': nextDisabled
  18995. } : undefined
  18996. };
  18997. });
  18998. function updateFocus() {
  18999. const currentIndex = page.value - start.value;
  19000. refs.value[currentIndex]?.$el.focus();
  19001. }
  19002. function onKeydown(e) {
  19003. if (e.key === keyValues.left && !props.disabled && page.value > +props.start) {
  19004. page.value = page.value - 1;
  19005. vue.nextTick(updateFocus);
  19006. } else if (e.key === keyValues.right && !props.disabled && page.value < start.value + length.value - 1) {
  19007. page.value = page.value + 1;
  19008. vue.nextTick(updateFocus);
  19009. }
  19010. }
  19011. useRender(() => vue.createVNode(props.tag, {
  19012. "ref": resizeRef,
  19013. "class": ['v-pagination', themeClasses.value, props.class],
  19014. "style": props.style,
  19015. "role": "navigation",
  19016. "aria-label": t(props.ariaLabel),
  19017. "onKeydown": onKeydown,
  19018. "data-test": "v-pagination-root"
  19019. }, {
  19020. default: () => [vue.createVNode("ul", {
  19021. "class": "v-pagination__list"
  19022. }, [props.showFirstLastPage && vue.createVNode("li", {
  19023. "key": "first",
  19024. "class": "v-pagination__first",
  19025. "data-test": "v-pagination-first"
  19026. }, [slots.first ? slots.first(controls.value.first) : vue.createVNode(VBtn, vue.mergeProps({
  19027. "_as": "VPaginationBtn"
  19028. }, controls.value.first), null)]), vue.createVNode("li", {
  19029. "key": "prev",
  19030. "class": "v-pagination__prev",
  19031. "data-test": "v-pagination-prev"
  19032. }, [slots.prev ? slots.prev(controls.value.prev) : vue.createVNode(VBtn, vue.mergeProps({
  19033. "_as": "VPaginationBtn"
  19034. }, controls.value.prev), null)]), items.value.map((item, index) => vue.createVNode("li", {
  19035. "key": item.key,
  19036. "class": ['v-pagination__item', {
  19037. 'v-pagination__item--is-active': item.isActive
  19038. }],
  19039. "data-test": "v-pagination-item"
  19040. }, [slots.item ? slots.item(item) : vue.createVNode(VBtn, vue.mergeProps({
  19041. "_as": "VPaginationBtn"
  19042. }, item.props), {
  19043. default: () => [item.page]
  19044. })])), vue.createVNode("li", {
  19045. "key": "next",
  19046. "class": "v-pagination__next",
  19047. "data-test": "v-pagination-next"
  19048. }, [slots.next ? slots.next(controls.value.next) : vue.createVNode(VBtn, vue.mergeProps({
  19049. "_as": "VPaginationBtn"
  19050. }, controls.value.next), null)]), props.showFirstLastPage && vue.createVNode("li", {
  19051. "key": "last",
  19052. "class": "v-pagination__last",
  19053. "data-test": "v-pagination-last"
  19054. }, [slots.last ? slots.last(controls.value.last) : vue.createVNode(VBtn, vue.mergeProps({
  19055. "_as": "VPaginationBtn"
  19056. }, controls.value.last), null)])])]
  19057. }));
  19058. return {};
  19059. }
  19060. });
  19061. // Types
  19062. const makeVDataTableFooterProps = propsFactory({
  19063. prevIcon: {
  19064. type: IconValue,
  19065. default: '$prev'
  19066. },
  19067. nextIcon: {
  19068. type: IconValue,
  19069. default: '$next'
  19070. },
  19071. firstIcon: {
  19072. type: IconValue,
  19073. default: '$first'
  19074. },
  19075. lastIcon: {
  19076. type: IconValue,
  19077. default: '$last'
  19078. },
  19079. itemsPerPageText: {
  19080. type: String,
  19081. default: '$vuetify.dataFooter.itemsPerPageText'
  19082. },
  19083. pageText: {
  19084. type: String,
  19085. default: '$vuetify.dataFooter.pageText'
  19086. },
  19087. firstPageLabel: {
  19088. type: String,
  19089. default: '$vuetify.dataFooter.firstPage'
  19090. },
  19091. prevPageLabel: {
  19092. type: String,
  19093. default: '$vuetify.dataFooter.prevPage'
  19094. },
  19095. nextPageLabel: {
  19096. type: String,
  19097. default: '$vuetify.dataFooter.nextPage'
  19098. },
  19099. lastPageLabel: {
  19100. type: String,
  19101. default: '$vuetify.dataFooter.lastPage'
  19102. },
  19103. itemsPerPageOptions: {
  19104. type: Array,
  19105. default: () => [{
  19106. value: 10,
  19107. title: '10'
  19108. }, {
  19109. value: 25,
  19110. title: '25'
  19111. }, {
  19112. value: 50,
  19113. title: '50'
  19114. }, {
  19115. value: 100,
  19116. title: '100'
  19117. }, {
  19118. value: -1,
  19119. title: '$vuetify.dataFooter.itemsPerPageAll'
  19120. }]
  19121. },
  19122. showCurrentPage: Boolean
  19123. }, 'VDataTableFooter');
  19124. const VDataTableFooter = genericComponent()({
  19125. name: 'VDataTableFooter',
  19126. props: makeVDataTableFooterProps(),
  19127. setup(props, _ref) {
  19128. let {
  19129. slots
  19130. } = _ref;
  19131. const {
  19132. t
  19133. } = useLocale();
  19134. const {
  19135. page,
  19136. pageCount,
  19137. startIndex,
  19138. stopIndex,
  19139. itemsLength,
  19140. itemsPerPage,
  19141. setItemsPerPage
  19142. } = usePagination();
  19143. const itemsPerPageOptions = vue.computed(() => props.itemsPerPageOptions.map(option => {
  19144. if (typeof option === 'number') {
  19145. return {
  19146. value: option,
  19147. title: option === -1 ? t('$vuetify.dataFooter.itemsPerPageAll') : String(option)
  19148. };
  19149. }
  19150. return {
  19151. ...option,
  19152. title: !isNaN(Number(option.title)) ? option.title : t(option.title)
  19153. };
  19154. }));
  19155. useRender(() => {
  19156. const paginationProps = VPagination.filterProps(props);
  19157. return vue.createVNode("div", {
  19158. "class": "v-data-table-footer"
  19159. }, [slots.prepend?.(), vue.createVNode("div", {
  19160. "class": "v-data-table-footer__items-per-page"
  19161. }, [vue.createVNode("span", null, [t(props.itemsPerPageText)]), vue.createVNode(VSelect, {
  19162. "items": itemsPerPageOptions.value,
  19163. "modelValue": itemsPerPage.value,
  19164. "onUpdate:modelValue": v => setItemsPerPage(Number(v)),
  19165. "density": "compact",
  19166. "variant": "outlined",
  19167. "hide-details": true
  19168. }, null)]), vue.createVNode("div", {
  19169. "class": "v-data-table-footer__info"
  19170. }, [vue.createVNode("div", null, [t(props.pageText, !itemsLength.value ? 0 : startIndex.value + 1, stopIndex.value, itemsLength.value)])]), vue.createVNode("div", {
  19171. "class": "v-data-table-footer__pagination"
  19172. }, [vue.createVNode(VPagination, vue.mergeProps({
  19173. "modelValue": page.value,
  19174. "onUpdate:modelValue": $event => page.value = $event,
  19175. "density": "comfortable",
  19176. "first-aria-label": props.firstPageLabel,
  19177. "last-aria-label": props.lastPageLabel,
  19178. "length": pageCount.value,
  19179. "next-aria-label": props.nextPageLabel,
  19180. "previous-aria-label": props.prevPageLabel,
  19181. "rounded": true,
  19182. "show-first-last-page": true,
  19183. "total-visible": props.showCurrentPage ? 1 : 0,
  19184. "variant": "plain"
  19185. }, paginationProps), null)])]);
  19186. });
  19187. return {};
  19188. }
  19189. });
  19190. // Types
  19191. const VDataTableColumn = defineFunctionalComponent({
  19192. align: {
  19193. type: String,
  19194. default: 'start'
  19195. },
  19196. fixed: Boolean,
  19197. fixedOffset: [Number, String],
  19198. height: [Number, String],
  19199. lastFixed: Boolean,
  19200. noPadding: Boolean,
  19201. tag: String,
  19202. width: [Number, String],
  19203. maxWidth: [Number, String],
  19204. nowrap: Boolean
  19205. }, (props, _ref) => {
  19206. let {
  19207. slots
  19208. } = _ref;
  19209. const Tag = props.tag ?? 'td';
  19210. return vue.createVNode(Tag, {
  19211. "class": ['v-data-table__td', {
  19212. 'v-data-table-column--fixed': props.fixed,
  19213. 'v-data-table-column--last-fixed': props.lastFixed,
  19214. 'v-data-table-column--no-padding': props.noPadding,
  19215. 'v-data-table-column--nowrap': props.nowrap
  19216. }, `v-data-table-column--align-${props.align}`],
  19217. "style": {
  19218. height: convertToUnit(props.height),
  19219. width: convertToUnit(props.width),
  19220. maxWidth: convertToUnit(props.maxWidth),
  19221. left: convertToUnit(props.fixedOffset || null)
  19222. }
  19223. }, {
  19224. default: () => [slots.default?.()]
  19225. });
  19226. });
  19227. // Utilities
  19228. // Types
  19229. const makeDataTableHeaderProps = propsFactory({
  19230. headers: Array
  19231. }, 'DataTable-header');
  19232. const VDataTableHeadersSymbol = Symbol.for('vuetify:data-table-headers');
  19233. const defaultHeader = {
  19234. title: '',
  19235. sortable: false
  19236. };
  19237. const defaultActionHeader = {
  19238. ...defaultHeader,
  19239. width: 48
  19240. };
  19241. function priorityQueue() {
  19242. let arr = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : [];
  19243. const queue = arr.map(element => ({
  19244. element,
  19245. priority: 0
  19246. }));
  19247. return {
  19248. enqueue: (element, priority) => {
  19249. let added = false;
  19250. for (let i = 0; i < queue.length; i++) {
  19251. const item = queue[i];
  19252. if (item.priority > priority) {
  19253. queue.splice(i, 0, {
  19254. element,
  19255. priority
  19256. });
  19257. added = true;
  19258. break;
  19259. }
  19260. }
  19261. if (!added) queue.push({
  19262. element,
  19263. priority
  19264. });
  19265. },
  19266. size: () => queue.length,
  19267. count: () => {
  19268. let count = 0;
  19269. if (!queue.length) return 0;
  19270. const whole = Math.floor(queue[0].priority);
  19271. for (let i = 0; i < queue.length; i++) {
  19272. if (Math.floor(queue[i].priority) === whole) count += 1;
  19273. }
  19274. return count;
  19275. },
  19276. dequeue: () => {
  19277. return queue.shift();
  19278. }
  19279. };
  19280. }
  19281. function extractLeaves(item) {
  19282. let columns = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : [];
  19283. if (!item.children) {
  19284. columns.push(item);
  19285. } else {
  19286. for (const child of item.children) {
  19287. extractLeaves(child, columns);
  19288. }
  19289. }
  19290. return columns;
  19291. }
  19292. function extractKeys(headers) {
  19293. let keys = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : new Set();
  19294. for (const item of headers) {
  19295. if (item.key) keys.add(item.key);
  19296. if (item.children) {
  19297. extractKeys(item.children, keys);
  19298. }
  19299. }
  19300. return keys;
  19301. }
  19302. function getDefaultItem(item) {
  19303. if (!item.key) return undefined;
  19304. if (item.key === 'data-table-group') return defaultHeader;
  19305. if (['data-table-expand', 'data-table-select'].includes(item.key)) return defaultActionHeader;
  19306. return undefined;
  19307. }
  19308. function getDepth(item) {
  19309. let depth = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 0;
  19310. if (!item.children) return depth;
  19311. return Math.max(depth, ...item.children.map(child => getDepth(child, depth + 1)));
  19312. }
  19313. function parseFixedColumns(items) {
  19314. let seenFixed = false;
  19315. function setFixed(item) {
  19316. let parentFixed = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : false;
  19317. if (!item) return;
  19318. if (parentFixed) {
  19319. item.fixed = true;
  19320. }
  19321. if (item.fixed) {
  19322. if (item.children) {
  19323. for (let i = item.children.length - 1; i >= 0; i--) {
  19324. setFixed(item.children[i], true);
  19325. }
  19326. } else {
  19327. if (!seenFixed) {
  19328. item.lastFixed = true;
  19329. } else if (isNaN(+item.width)) {
  19330. consoleError(`Multiple fixed columns should have a static width (key: ${item.key})`);
  19331. }
  19332. seenFixed = true;
  19333. }
  19334. } else {
  19335. if (item.children) {
  19336. for (let i = item.children.length - 1; i >= 0; i--) {
  19337. setFixed(item.children[i]);
  19338. }
  19339. } else {
  19340. seenFixed = false;
  19341. }
  19342. }
  19343. }
  19344. for (let i = items.length - 1; i >= 0; i--) {
  19345. setFixed(items[i]);
  19346. }
  19347. function setFixedOffset(item) {
  19348. let fixedOffset = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 0;
  19349. if (!item) return fixedOffset;
  19350. if (item.children) {
  19351. item.fixedOffset = fixedOffset;
  19352. for (const child of item.children) {
  19353. fixedOffset = setFixedOffset(child, fixedOffset);
  19354. }
  19355. } else if (item.fixed) {
  19356. item.fixedOffset = fixedOffset;
  19357. fixedOffset += parseFloat(item.width || '0') || 0;
  19358. }
  19359. return fixedOffset;
  19360. }
  19361. let fixedOffset = 0;
  19362. for (const item of items) {
  19363. fixedOffset = setFixedOffset(item, fixedOffset);
  19364. }
  19365. }
  19366. function parse(items, maxDepth) {
  19367. const headers = [];
  19368. let currentDepth = 0;
  19369. const queue = priorityQueue(items);
  19370. while (queue.size() > 0) {
  19371. let rowSize = queue.count();
  19372. const row = [];
  19373. let fraction = 1;
  19374. while (rowSize > 0) {
  19375. const {
  19376. element: item,
  19377. priority
  19378. } = queue.dequeue();
  19379. const diff = maxDepth - currentDepth - getDepth(item);
  19380. row.push({
  19381. ...item,
  19382. rowspan: diff ?? 1,
  19383. colspan: item.children ? extractLeaves(item).length : 1
  19384. });
  19385. if (item.children) {
  19386. for (const child of item.children) {
  19387. // This internally sorts items that are on the same priority "row"
  19388. const sort = priority % 1 + fraction / Math.pow(10, currentDepth + 2);
  19389. queue.enqueue(child, currentDepth + diff + sort);
  19390. }
  19391. }
  19392. fraction += 1;
  19393. rowSize -= 1;
  19394. }
  19395. currentDepth += 1;
  19396. headers.push(row);
  19397. }
  19398. const columns = items.map(item => extractLeaves(item)).flat();
  19399. return {
  19400. columns,
  19401. headers
  19402. };
  19403. }
  19404. function convertToInternalHeaders(items) {
  19405. const internalHeaders = [];
  19406. for (const item of items) {
  19407. const defaultItem = {
  19408. ...getDefaultItem(item),
  19409. ...item
  19410. };
  19411. const key = defaultItem.key ?? (typeof defaultItem.value === 'string' ? defaultItem.value : null);
  19412. const value = defaultItem.value ?? key ?? null;
  19413. const internalItem = {
  19414. ...defaultItem,
  19415. key,
  19416. value,
  19417. sortable: defaultItem.sortable ?? (defaultItem.key != null || !!defaultItem.sort),
  19418. children: defaultItem.children ? convertToInternalHeaders(defaultItem.children) : undefined
  19419. };
  19420. internalHeaders.push(internalItem);
  19421. }
  19422. return internalHeaders;
  19423. }
  19424. function createHeaders(props, options) {
  19425. const headers = vue.ref([]);
  19426. const columns = vue.ref([]);
  19427. const sortFunctions = vue.ref({});
  19428. const sortRawFunctions = vue.ref({});
  19429. const filterFunctions = vue.ref({});
  19430. vue.watchEffect(() => {
  19431. const _headers = props.headers || Object.keys(props.items[0] ?? {}).map(key => ({
  19432. key,
  19433. title: vue.capitalize(key)
  19434. }));
  19435. const items = _headers.slice();
  19436. const keys = extractKeys(items);
  19437. if (options?.groupBy?.value.length && !keys.has('data-table-group')) {
  19438. items.unshift({
  19439. key: 'data-table-group',
  19440. title: 'Group'
  19441. });
  19442. }
  19443. if (options?.showSelect?.value && !keys.has('data-table-select')) {
  19444. items.unshift({
  19445. key: 'data-table-select'
  19446. });
  19447. }
  19448. if (options?.showExpand?.value && !keys.has('data-table-expand')) {
  19449. items.push({
  19450. key: 'data-table-expand'
  19451. });
  19452. }
  19453. const internalHeaders = convertToInternalHeaders(items);
  19454. parseFixedColumns(internalHeaders);
  19455. const maxDepth = Math.max(...internalHeaders.map(item => getDepth(item))) + 1;
  19456. const parsed = parse(internalHeaders, maxDepth);
  19457. headers.value = parsed.headers;
  19458. columns.value = parsed.columns;
  19459. const flatHeaders = parsed.headers.flat(1);
  19460. for (const header of flatHeaders) {
  19461. if (!header.key) continue;
  19462. if (header.sortable) {
  19463. if (header.sort) {
  19464. sortFunctions.value[header.key] = header.sort;
  19465. }
  19466. if (header.sortRaw) {
  19467. sortRawFunctions.value[header.key] = header.sortRaw;
  19468. }
  19469. }
  19470. if (header.filter) {
  19471. filterFunctions.value[header.key] = header.filter;
  19472. }
  19473. }
  19474. });
  19475. const data = {
  19476. headers,
  19477. columns,
  19478. sortFunctions,
  19479. sortRawFunctions,
  19480. filterFunctions
  19481. };
  19482. vue.provide(VDataTableHeadersSymbol, data);
  19483. return data;
  19484. }
  19485. function useHeaders() {
  19486. const data = vue.inject(VDataTableHeadersSymbol);
  19487. if (!data) throw new Error('Missing headers!');
  19488. return data;
  19489. }
  19490. // Types
  19491. const makeVDataTableHeadersProps = propsFactory({
  19492. color: String,
  19493. sticky: Boolean,
  19494. disableSort: Boolean,
  19495. multiSort: Boolean,
  19496. sortAscIcon: {
  19497. type: IconValue,
  19498. default: '$sortAsc'
  19499. },
  19500. sortDescIcon: {
  19501. type: IconValue,
  19502. default: '$sortDesc'
  19503. },
  19504. headerProps: {
  19505. type: Object
  19506. },
  19507. ...makeDisplayProps(),
  19508. ...makeLoaderProps()
  19509. }, 'VDataTableHeaders');
  19510. const VDataTableHeaders = genericComponent()({
  19511. name: 'VDataTableHeaders',
  19512. props: makeVDataTableHeadersProps(),
  19513. setup(props, _ref) {
  19514. let {
  19515. slots
  19516. } = _ref;
  19517. const {
  19518. t
  19519. } = useLocale();
  19520. const {
  19521. toggleSort,
  19522. sortBy,
  19523. isSorted
  19524. } = useSort();
  19525. const {
  19526. someSelected,
  19527. allSelected,
  19528. selectAll,
  19529. showSelectAll
  19530. } = useSelection();
  19531. const {
  19532. columns,
  19533. headers
  19534. } = useHeaders();
  19535. const {
  19536. loaderClasses
  19537. } = useLoader(props);
  19538. function getFixedStyles(column, y) {
  19539. if (!props.sticky && !column.fixed) return undefined;
  19540. return {
  19541. position: 'sticky',
  19542. left: column.fixed ? convertToUnit(column.fixedOffset) : undefined,
  19543. top: props.sticky ? `calc(var(--v-table-header-height) * ${y})` : undefined
  19544. };
  19545. }
  19546. function getSortIcon(column) {
  19547. const item = sortBy.value.find(item => item.key === column.key);
  19548. if (!item) return props.sortAscIcon;
  19549. return item.order === 'asc' ? props.sortAscIcon : props.sortDescIcon;
  19550. }
  19551. const {
  19552. backgroundColorClasses,
  19553. backgroundColorStyles
  19554. } = useBackgroundColor(props, 'color');
  19555. const {
  19556. displayClasses,
  19557. mobile
  19558. } = useDisplay(props);
  19559. const slotProps = vue.computed(() => ({
  19560. headers: headers.value,
  19561. columns: columns.value,
  19562. toggleSort,
  19563. isSorted,
  19564. sortBy: sortBy.value,
  19565. someSelected: someSelected.value,
  19566. allSelected: allSelected.value,
  19567. selectAll,
  19568. getSortIcon
  19569. }));
  19570. const headerCellClasses = vue.computed(() => ['v-data-table__th', {
  19571. 'v-data-table__th--sticky': props.sticky
  19572. }, displayClasses.value, loaderClasses.value]);
  19573. const VDataTableHeaderCell = _ref2 => {
  19574. let {
  19575. column,
  19576. x,
  19577. y
  19578. } = _ref2;
  19579. const noPadding = column.key === 'data-table-select' || column.key === 'data-table-expand';
  19580. const headerProps = vue.mergeProps(props.headerProps ?? {}, column.headerProps ?? {});
  19581. return vue.createVNode(VDataTableColumn, vue.mergeProps({
  19582. "tag": "th",
  19583. "align": column.align,
  19584. "class": [{
  19585. 'v-data-table__th--sortable': column.sortable && !props.disableSort,
  19586. 'v-data-table__th--sorted': isSorted(column),
  19587. 'v-data-table__th--fixed': column.fixed
  19588. }, ...headerCellClasses.value],
  19589. "style": {
  19590. width: convertToUnit(column.width),
  19591. minWidth: convertToUnit(column.minWidth),
  19592. maxWidth: convertToUnit(column.maxWidth),
  19593. ...getFixedStyles(column, y)
  19594. },
  19595. "colspan": column.colspan,
  19596. "rowspan": column.rowspan,
  19597. "onClick": column.sortable ? () => toggleSort(column) : undefined,
  19598. "fixed": column.fixed,
  19599. "nowrap": column.nowrap,
  19600. "lastFixed": column.lastFixed,
  19601. "noPadding": noPadding
  19602. }, headerProps), {
  19603. default: () => {
  19604. const columnSlotName = `header.${column.key}`;
  19605. const columnSlotProps = {
  19606. column,
  19607. selectAll,
  19608. isSorted,
  19609. toggleSort,
  19610. sortBy: sortBy.value,
  19611. someSelected: someSelected.value,
  19612. allSelected: allSelected.value,
  19613. getSortIcon
  19614. };
  19615. if (slots[columnSlotName]) return slots[columnSlotName](columnSlotProps);
  19616. if (column.key === 'data-table-select') {
  19617. return slots['header.data-table-select']?.(columnSlotProps) ?? (showSelectAll.value && vue.createVNode(VCheckboxBtn, {
  19618. "modelValue": allSelected.value,
  19619. "indeterminate": someSelected.value && !allSelected.value,
  19620. "onUpdate:modelValue": selectAll
  19621. }, null));
  19622. }
  19623. return vue.createVNode("div", {
  19624. "class": "v-data-table-header__content"
  19625. }, [vue.createVNode("span", null, [column.title]), column.sortable && !props.disableSort && vue.createVNode(VIcon, {
  19626. "key": "icon",
  19627. "class": "v-data-table-header__sort-icon",
  19628. "icon": getSortIcon(column)
  19629. }, null), props.multiSort && isSorted(column) && vue.createVNode("div", {
  19630. "key": "badge",
  19631. "class": ['v-data-table-header__sort-badge', ...backgroundColorClasses.value],
  19632. "style": backgroundColorStyles.value
  19633. }, [sortBy.value.findIndex(x => x.key === column.key) + 1])]);
  19634. }
  19635. });
  19636. };
  19637. const VDataTableMobileHeaderCell = () => {
  19638. const headerProps = vue.mergeProps(props.headerProps ?? {} ?? {});
  19639. const displayItems = vue.computed(() => {
  19640. return columns.value.filter(column => column?.sortable && !props.disableSort);
  19641. });
  19642. const appendIcon = vue.computed(() => {
  19643. const showSelectColumn = columns.value.find(column => column.key === 'data-table-select');
  19644. if (showSelectColumn == null) return;
  19645. return allSelected.value ? '$checkboxOn' : someSelected.value ? '$checkboxIndeterminate' : '$checkboxOff';
  19646. });
  19647. return vue.createVNode(VDataTableColumn, vue.mergeProps({
  19648. "tag": "th",
  19649. "class": [...headerCellClasses.value],
  19650. "colspan": headers.value.length + 1
  19651. }, headerProps), {
  19652. default: () => [vue.createVNode("div", {
  19653. "class": "v-data-table-header__content"
  19654. }, [vue.createVNode(VSelect, {
  19655. "chips": true,
  19656. "class": "v-data-table__td-sort-select",
  19657. "clearable": true,
  19658. "density": "default",
  19659. "items": displayItems.value,
  19660. "label": t('$vuetify.dataTable.sortBy'),
  19661. "multiple": props.multiSort,
  19662. "variant": "underlined",
  19663. "onClick:clear": () => sortBy.value = [],
  19664. "appendIcon": appendIcon.value,
  19665. "onClick:append": () => selectAll(!allSelected.value)
  19666. }, {
  19667. ...slots,
  19668. chip: props => vue.createVNode(VChip, {
  19669. "onClick": props.item.raw?.sortable ? () => toggleSort(props.item.raw) : undefined,
  19670. "onMousedown": e => {
  19671. e.preventDefault();
  19672. e.stopPropagation();
  19673. }
  19674. }, {
  19675. default: () => [props.item.title, vue.createVNode(VIcon, {
  19676. "class": ['v-data-table__td-sort-icon', isSorted(props.item.raw) && 'v-data-table__td-sort-icon-active'],
  19677. "icon": getSortIcon(props.item.raw),
  19678. "size": "small"
  19679. }, null)]
  19680. })
  19681. })])]
  19682. });
  19683. };
  19684. useRender(() => {
  19685. return mobile.value ? vue.createVNode("tr", null, [vue.createVNode(VDataTableMobileHeaderCell, null, null)]) : vue.createVNode(vue.Fragment, null, [slots.headers ? slots.headers(slotProps.value) : headers.value.map((row, y) => vue.createVNode("tr", null, [row.map((column, x) => vue.createVNode(VDataTableHeaderCell, {
  19686. "column": column,
  19687. "x": x,
  19688. "y": y
  19689. }, null))])), props.loading && vue.createVNode("tr", {
  19690. "class": "v-data-table-progress"
  19691. }, [vue.createVNode("th", {
  19692. "colspan": columns.value.length
  19693. }, [vue.createVNode(LoaderSlot, {
  19694. "name": "v-data-table-progress",
  19695. "absolute": true,
  19696. "active": true,
  19697. "color": typeof props.loading === 'boolean' ? undefined : props.loading,
  19698. "indeterminate": true
  19699. }, {
  19700. default: slots.loader
  19701. })])])]);
  19702. });
  19703. }
  19704. });
  19705. // Types
  19706. const makeVDataTableGroupHeaderRowProps = propsFactory({
  19707. item: {
  19708. type: Object,
  19709. required: true
  19710. }
  19711. }, 'VDataTableGroupHeaderRow');
  19712. const VDataTableGroupHeaderRow = genericComponent()({
  19713. name: 'VDataTableGroupHeaderRow',
  19714. props: makeVDataTableGroupHeaderRowProps(),
  19715. setup(props, _ref) {
  19716. let {
  19717. slots
  19718. } = _ref;
  19719. const {
  19720. isGroupOpen,
  19721. toggleGroup,
  19722. extractRows
  19723. } = useGroupBy();
  19724. const {
  19725. isSelected,
  19726. isSomeSelected,
  19727. select
  19728. } = useSelection();
  19729. const {
  19730. columns
  19731. } = useHeaders();
  19732. const rows = vue.computed(() => {
  19733. return extractRows([props.item]);
  19734. });
  19735. return () => vue.createVNode("tr", {
  19736. "class": "v-data-table-group-header-row",
  19737. "style": {
  19738. '--v-data-table-group-header-row-depth': props.item.depth
  19739. }
  19740. }, [columns.value.map(column => {
  19741. if (column.key === 'data-table-group') {
  19742. const icon = isGroupOpen(props.item) ? '$expand' : '$next';
  19743. const onClick = () => toggleGroup(props.item);
  19744. return slots['data-table-group']?.({
  19745. item: props.item,
  19746. count: rows.value.length,
  19747. props: {
  19748. icon,
  19749. onClick
  19750. }
  19751. }) ?? vue.createVNode(VDataTableColumn, {
  19752. "class": "v-data-table-group-header-row__column"
  19753. }, {
  19754. default: () => [vue.createVNode(VBtn, {
  19755. "size": "small",
  19756. "variant": "text",
  19757. "icon": icon,
  19758. "onClick": onClick
  19759. }, null), vue.createVNode("span", null, [props.item.value]), vue.createVNode("span", null, [vue.createTextVNode("("), rows.value.length, vue.createTextVNode(")")])]
  19760. });
  19761. }
  19762. if (column.key === 'data-table-select') {
  19763. const modelValue = isSelected(rows.value);
  19764. const indeterminate = isSomeSelected(rows.value) && !modelValue;
  19765. const selectGroup = v => select(rows.value, v);
  19766. return slots['data-table-select']?.({
  19767. props: {
  19768. modelValue,
  19769. indeterminate,
  19770. 'onUpdate:modelValue': selectGroup
  19771. }
  19772. }) ?? vue.createVNode("td", null, [vue.createVNode(VCheckboxBtn, {
  19773. "modelValue": modelValue,
  19774. "indeterminate": indeterminate,
  19775. "onUpdate:modelValue": selectGroup
  19776. }, null)]);
  19777. }
  19778. return vue.createVNode("td", null, null);
  19779. })]);
  19780. }
  19781. });
  19782. // Types
  19783. const makeVDataTableRowProps = propsFactory({
  19784. index: Number,
  19785. item: Object,
  19786. cellProps: [Object, Function],
  19787. onClick: EventProp(),
  19788. onContextmenu: EventProp(),
  19789. onDblclick: EventProp(),
  19790. ...makeDisplayProps()
  19791. }, 'VDataTableRow');
  19792. const VDataTableRow = genericComponent()({
  19793. name: 'VDataTableRow',
  19794. props: makeVDataTableRowProps(),
  19795. setup(props, _ref) {
  19796. let {
  19797. slots
  19798. } = _ref;
  19799. const {
  19800. displayClasses,
  19801. mobile
  19802. } = useDisplay(props, 'v-data-table__tr');
  19803. const {
  19804. isSelected,
  19805. toggleSelect,
  19806. someSelected,
  19807. allSelected,
  19808. selectAll
  19809. } = useSelection();
  19810. const {
  19811. isExpanded,
  19812. toggleExpand
  19813. } = useExpanded();
  19814. const {
  19815. toggleSort,
  19816. sortBy,
  19817. isSorted
  19818. } = useSort();
  19819. const {
  19820. columns
  19821. } = useHeaders();
  19822. useRender(() => vue.createVNode("tr", {
  19823. "class": ['v-data-table__tr', {
  19824. 'v-data-table__tr--clickable': !!(props.onClick || props.onContextmenu || props.onDblclick)
  19825. }, displayClasses.value],
  19826. "onClick": props.onClick,
  19827. "onContextmenu": props.onContextmenu,
  19828. "onDblclick": props.onDblclick
  19829. }, [props.item && columns.value.map((column, i) => {
  19830. const item = props.item;
  19831. const slotName = `item.${column.key}`;
  19832. const headerSlotName = `header.${column.key}`;
  19833. const slotProps = {
  19834. index: props.index,
  19835. item: item.raw,
  19836. internalItem: item,
  19837. value: getObjectValueByPath(item.columns, column.key),
  19838. column,
  19839. isSelected,
  19840. toggleSelect,
  19841. isExpanded,
  19842. toggleExpand
  19843. };
  19844. const columnSlotProps = {
  19845. column,
  19846. selectAll,
  19847. isSorted,
  19848. toggleSort,
  19849. sortBy: sortBy.value,
  19850. someSelected: someSelected.value,
  19851. allSelected: allSelected.value,
  19852. getSortIcon: () => ''
  19853. };
  19854. const cellProps = typeof props.cellProps === 'function' ? props.cellProps({
  19855. index: slotProps.index,
  19856. item: slotProps.item,
  19857. internalItem: slotProps.internalItem,
  19858. value: slotProps.value,
  19859. column
  19860. }) : props.cellProps;
  19861. const columnCellProps = typeof column.cellProps === 'function' ? column.cellProps({
  19862. index: slotProps.index,
  19863. item: slotProps.item,
  19864. internalItem: slotProps.internalItem,
  19865. value: slotProps.value
  19866. }) : column.cellProps;
  19867. return vue.createVNode(VDataTableColumn, vue.mergeProps({
  19868. "align": column.align,
  19869. "class": {
  19870. 'v-data-table__td--expanded-row': column.key === 'data-table-expand',
  19871. 'v-data-table__td--select-row': column.key === 'data-table-select'
  19872. },
  19873. "fixed": column.fixed,
  19874. "fixedOffset": column.fixedOffset,
  19875. "lastFixed": column.lastFixed,
  19876. "maxWidth": !mobile.value ? column.maxWidth : undefined,
  19877. "noPadding": column.key === 'data-table-select' || column.key === 'data-table-expand',
  19878. "nowrap": column.nowrap,
  19879. "width": !mobile.value ? column.width : undefined
  19880. }, cellProps, columnCellProps), {
  19881. default: () => {
  19882. if (slots[slotName] && !mobile.value) return slots[slotName]?.(slotProps);
  19883. if (column.key === 'data-table-select') {
  19884. return slots['item.data-table-select']?.(slotProps) ?? vue.createVNode(VCheckboxBtn, {
  19885. "disabled": !item.selectable,
  19886. "modelValue": isSelected([item]),
  19887. "onClick": vue.withModifiers(() => toggleSelect(item), ['stop'])
  19888. }, null);
  19889. }
  19890. if (column.key === 'data-table-expand') {
  19891. return slots['item.data-table-expand']?.(slotProps) ?? vue.createVNode(VBtn, {
  19892. "icon": isExpanded(item) ? '$collapse' : '$expand',
  19893. "size": "small",
  19894. "variant": "text",
  19895. "onClick": vue.withModifiers(() => toggleExpand(item), ['stop'])
  19896. }, null);
  19897. }
  19898. const displayValue = vue.toDisplayString(slotProps.value);
  19899. return !mobile.value ? displayValue : vue.createVNode(vue.Fragment, null, [vue.createVNode("div", {
  19900. "class": "v-data-table__td-title"
  19901. }, [slots[headerSlotName]?.(columnSlotProps) ?? column.title]), vue.createVNode("div", {
  19902. "class": "v-data-table__td-value"
  19903. }, [slots[slotName]?.(slotProps) ?? displayValue])]);
  19904. }
  19905. });
  19906. })]));
  19907. }
  19908. });
  19909. // Types
  19910. const makeVDataTableRowsProps = propsFactory({
  19911. loading: [Boolean, String],
  19912. loadingText: {
  19913. type: String,
  19914. default: '$vuetify.dataIterator.loadingText'
  19915. },
  19916. hideNoData: Boolean,
  19917. items: {
  19918. type: Array,
  19919. default: () => []
  19920. },
  19921. noDataText: {
  19922. type: String,
  19923. default: '$vuetify.noDataText'
  19924. },
  19925. rowProps: [Object, Function],
  19926. cellProps: [Object, Function],
  19927. ...makeDisplayProps()
  19928. }, 'VDataTableRows');
  19929. const VDataTableRows = genericComponent()({
  19930. name: 'VDataTableRows',
  19931. inheritAttrs: false,
  19932. props: makeVDataTableRowsProps(),
  19933. setup(props, _ref) {
  19934. let {
  19935. attrs,
  19936. slots
  19937. } = _ref;
  19938. const {
  19939. columns
  19940. } = useHeaders();
  19941. const {
  19942. expandOnClick,
  19943. toggleExpand,
  19944. isExpanded
  19945. } = useExpanded();
  19946. const {
  19947. isSelected,
  19948. toggleSelect
  19949. } = useSelection();
  19950. const {
  19951. toggleGroup,
  19952. isGroupOpen
  19953. } = useGroupBy();
  19954. const {
  19955. t
  19956. } = useLocale();
  19957. const {
  19958. mobile
  19959. } = useDisplay(props);
  19960. useRender(() => {
  19961. if (props.loading && (!props.items.length || slots.loading)) {
  19962. return vue.createVNode("tr", {
  19963. "class": "v-data-table-rows-loading",
  19964. "key": "loading"
  19965. }, [vue.createVNode("td", {
  19966. "colspan": columns.value.length
  19967. }, [slots.loading?.() ?? t(props.loadingText)])]);
  19968. }
  19969. if (!props.loading && !props.items.length && !props.hideNoData) {
  19970. return vue.createVNode("tr", {
  19971. "class": "v-data-table-rows-no-data",
  19972. "key": "no-data"
  19973. }, [vue.createVNode("td", {
  19974. "colspan": columns.value.length
  19975. }, [slots['no-data']?.() ?? t(props.noDataText)])]);
  19976. }
  19977. return vue.createVNode(vue.Fragment, null, [props.items.map((item, index) => {
  19978. if (item.type === 'group') {
  19979. const slotProps = {
  19980. index,
  19981. item,
  19982. columns: columns.value,
  19983. isExpanded,
  19984. toggleExpand,
  19985. isSelected,
  19986. toggleSelect,
  19987. toggleGroup,
  19988. isGroupOpen
  19989. };
  19990. return slots['group-header'] ? slots['group-header'](slotProps) : vue.createVNode(VDataTableGroupHeaderRow, vue.mergeProps({
  19991. "key": `group-header_${item.id}`,
  19992. "item": item
  19993. }, getPrefixedEventHandlers(attrs, ':group-header', () => slotProps)), slots);
  19994. }
  19995. const slotProps = {
  19996. index,
  19997. item: item.raw,
  19998. internalItem: item,
  19999. columns: columns.value,
  20000. isExpanded,
  20001. toggleExpand,
  20002. isSelected,
  20003. toggleSelect
  20004. };
  20005. const itemSlotProps = {
  20006. ...slotProps,
  20007. props: vue.mergeProps({
  20008. key: `item_${item.key ?? item.index}`,
  20009. onClick: expandOnClick.value ? () => {
  20010. toggleExpand(item);
  20011. } : undefined,
  20012. index,
  20013. item,
  20014. cellProps: props.cellProps,
  20015. mobile: mobile.value
  20016. }, getPrefixedEventHandlers(attrs, ':row', () => slotProps), typeof props.rowProps === 'function' ? props.rowProps({
  20017. item: slotProps.item,
  20018. index: slotProps.index,
  20019. internalItem: slotProps.internalItem
  20020. }) : props.rowProps)
  20021. };
  20022. return vue.createVNode(vue.Fragment, {
  20023. "key": itemSlotProps.props.key
  20024. }, [slots.item ? slots.item(itemSlotProps) : vue.createVNode(VDataTableRow, itemSlotProps.props, slots), isExpanded(item) && slots['expanded-row']?.(slotProps)]);
  20025. })]);
  20026. });
  20027. return {};
  20028. }
  20029. });
  20030. const makeVTableProps = propsFactory({
  20031. fixedHeader: Boolean,
  20032. fixedFooter: Boolean,
  20033. height: [Number, String],
  20034. hover: Boolean,
  20035. ...makeComponentProps(),
  20036. ...makeDensityProps(),
  20037. ...makeTagProps(),
  20038. ...makeThemeProps()
  20039. }, 'VTable');
  20040. const VTable = genericComponent()({
  20041. name: 'VTable',
  20042. props: makeVTableProps(),
  20043. setup(props, _ref) {
  20044. let {
  20045. slots,
  20046. emit
  20047. } = _ref;
  20048. const {
  20049. themeClasses
  20050. } = provideTheme(props);
  20051. const {
  20052. densityClasses
  20053. } = useDensity(props);
  20054. useRender(() => vue.createVNode(props.tag, {
  20055. "class": ['v-table', {
  20056. 'v-table--fixed-height': !!props.height,
  20057. 'v-table--fixed-header': props.fixedHeader,
  20058. 'v-table--fixed-footer': props.fixedFooter,
  20059. 'v-table--has-top': !!slots.top,
  20060. 'v-table--has-bottom': !!slots.bottom,
  20061. 'v-table--hover': props.hover
  20062. }, themeClasses.value, densityClasses.value, props.class],
  20063. "style": props.style
  20064. }, {
  20065. default: () => [slots.top?.(), slots.default ? vue.createVNode("div", {
  20066. "class": "v-table__wrapper",
  20067. "style": {
  20068. height: convertToUnit(props.height)
  20069. }
  20070. }, [vue.createVNode("table", null, [slots.default()])]) : slots.wrapper?.(), slots.bottom?.()]
  20071. }));
  20072. return {};
  20073. }
  20074. });
  20075. // Utilities
  20076. // Types
  20077. // Composables
  20078. const makeDataTableItemsProps = propsFactory({
  20079. items: {
  20080. type: Array,
  20081. default: () => []
  20082. },
  20083. itemValue: {
  20084. type: [String, Array, Function],
  20085. default: 'id'
  20086. },
  20087. itemSelectable: {
  20088. type: [String, Array, Function],
  20089. default: null
  20090. },
  20091. rowProps: [Object, Function],
  20092. cellProps: [Object, Function],
  20093. returnObject: Boolean
  20094. }, 'DataTable-items');
  20095. function transformItem(props, item, index, columns) {
  20096. const value = props.returnObject ? item : getPropertyFromItem(item, props.itemValue);
  20097. const selectable = getPropertyFromItem(item, props.itemSelectable, true);
  20098. const itemColumns = columns.reduce((obj, column) => {
  20099. if (column.key != null) obj[column.key] = getPropertyFromItem(item, column.value);
  20100. return obj;
  20101. }, {});
  20102. return {
  20103. type: 'item',
  20104. key: props.returnObject ? getPropertyFromItem(item, props.itemValue) : value,
  20105. index,
  20106. value,
  20107. selectable,
  20108. columns: itemColumns,
  20109. raw: item
  20110. };
  20111. }
  20112. function transformItems(props, items, columns) {
  20113. return items.map((item, index) => transformItem(props, item, index, columns));
  20114. }
  20115. function useDataTableItems(props, columns) {
  20116. const items = vue.computed(() => transformItems(props, props.items, columns.value));
  20117. return {
  20118. items
  20119. };
  20120. }
  20121. // Types
  20122. const makeDataTableProps = propsFactory({
  20123. ...makeVDataTableRowsProps(),
  20124. hideDefaultBody: Boolean,
  20125. hideDefaultFooter: Boolean,
  20126. hideDefaultHeader: Boolean,
  20127. width: [String, Number],
  20128. search: String,
  20129. ...makeDataTableExpandProps(),
  20130. ...makeDataTableGroupProps(),
  20131. ...makeDataTableHeaderProps(),
  20132. ...makeDataTableItemsProps(),
  20133. ...makeDataTableSelectProps(),
  20134. ...makeDataTableSortProps(),
  20135. ...makeVDataTableHeadersProps(),
  20136. ...makeVTableProps()
  20137. }, 'DataTable');
  20138. const makeVDataTableProps = propsFactory({
  20139. ...makeDataTablePaginateProps(),
  20140. ...makeDataTableProps(),
  20141. ...makeFilterProps(),
  20142. ...makeVDataTableFooterProps()
  20143. }, 'VDataTable');
  20144. const VDataTable = genericComponent()({
  20145. name: 'VDataTable',
  20146. props: makeVDataTableProps(),
  20147. emits: {
  20148. 'update:modelValue': value => true,
  20149. 'update:page': value => true,
  20150. 'update:itemsPerPage': value => true,
  20151. 'update:sortBy': value => true,
  20152. 'update:options': value => true,
  20153. 'update:groupBy': value => true,
  20154. 'update:expanded': value => true,
  20155. 'update:currentItems': value => true
  20156. },
  20157. setup(props, _ref) {
  20158. let {
  20159. attrs,
  20160. slots
  20161. } = _ref;
  20162. const {
  20163. groupBy
  20164. } = createGroupBy(props);
  20165. const {
  20166. sortBy,
  20167. multiSort,
  20168. mustSort
  20169. } = createSort(props);
  20170. const {
  20171. page,
  20172. itemsPerPage
  20173. } = createPagination(props);
  20174. const {
  20175. disableSort
  20176. } = vue.toRefs(props);
  20177. const {
  20178. columns,
  20179. headers,
  20180. sortFunctions,
  20181. sortRawFunctions,
  20182. filterFunctions
  20183. } = createHeaders(props, {
  20184. groupBy,
  20185. showSelect: vue.toRef(props, 'showSelect'),
  20186. showExpand: vue.toRef(props, 'showExpand')
  20187. });
  20188. const {
  20189. items
  20190. } = useDataTableItems(props, columns);
  20191. const search = vue.toRef(props, 'search');
  20192. const {
  20193. filteredItems
  20194. } = useFilter(props, items, search, {
  20195. transform: item => item.columns,
  20196. customKeyFilter: filterFunctions
  20197. });
  20198. const {
  20199. toggleSort
  20200. } = provideSort({
  20201. sortBy,
  20202. multiSort,
  20203. mustSort,
  20204. page
  20205. });
  20206. const {
  20207. sortByWithGroups,
  20208. opened,
  20209. extractRows,
  20210. isGroupOpen,
  20211. toggleGroup
  20212. } = provideGroupBy({
  20213. groupBy,
  20214. sortBy,
  20215. disableSort
  20216. });
  20217. const {
  20218. sortedItems
  20219. } = useSortedItems(props, filteredItems, sortByWithGroups, {
  20220. transform: item => ({
  20221. ...item.raw,
  20222. ...item.columns
  20223. }),
  20224. sortFunctions,
  20225. sortRawFunctions
  20226. });
  20227. const {
  20228. flatItems
  20229. } = useGroupedItems(sortedItems, groupBy, opened);
  20230. const itemsLength = vue.computed(() => flatItems.value.length);
  20231. const {
  20232. startIndex,
  20233. stopIndex,
  20234. pageCount,
  20235. setItemsPerPage
  20236. } = providePagination({
  20237. page,
  20238. itemsPerPage,
  20239. itemsLength
  20240. });
  20241. const {
  20242. paginatedItems
  20243. } = usePaginatedItems({
  20244. items: flatItems,
  20245. startIndex,
  20246. stopIndex,
  20247. itemsPerPage
  20248. });
  20249. const paginatedItemsWithoutGroups = vue.computed(() => extractRows(paginatedItems.value));
  20250. const {
  20251. isSelected,
  20252. select,
  20253. selectAll,
  20254. toggleSelect,
  20255. someSelected,
  20256. allSelected
  20257. } = provideSelection(props, {
  20258. allItems: items,
  20259. currentPage: paginatedItemsWithoutGroups
  20260. });
  20261. const {
  20262. isExpanded,
  20263. toggleExpand
  20264. } = provideExpanded(props);
  20265. useOptions({
  20266. page,
  20267. itemsPerPage,
  20268. sortBy,
  20269. groupBy,
  20270. search
  20271. });
  20272. provideDefaults({
  20273. VDataTableRows: {
  20274. hideNoData: vue.toRef(props, 'hideNoData'),
  20275. noDataText: vue.toRef(props, 'noDataText'),
  20276. loading: vue.toRef(props, 'loading'),
  20277. loadingText: vue.toRef(props, 'loadingText')
  20278. }
  20279. });
  20280. const slotProps = vue.computed(() => ({
  20281. page: page.value,
  20282. itemsPerPage: itemsPerPage.value,
  20283. sortBy: sortBy.value,
  20284. pageCount: pageCount.value,
  20285. toggleSort,
  20286. setItemsPerPage,
  20287. someSelected: someSelected.value,
  20288. allSelected: allSelected.value,
  20289. isSelected,
  20290. select,
  20291. selectAll,
  20292. toggleSelect,
  20293. isExpanded,
  20294. toggleExpand,
  20295. isGroupOpen,
  20296. toggleGroup,
  20297. items: paginatedItemsWithoutGroups.value.map(item => item.raw),
  20298. internalItems: paginatedItemsWithoutGroups.value,
  20299. groupedItems: paginatedItems.value,
  20300. columns: columns.value,
  20301. headers: headers.value
  20302. }));
  20303. useRender(() => {
  20304. const dataTableFooterProps = VDataTableFooter.filterProps(props);
  20305. const dataTableHeadersProps = VDataTableHeaders.filterProps(props);
  20306. const dataTableRowsProps = VDataTableRows.filterProps(props);
  20307. const tableProps = VTable.filterProps(props);
  20308. return vue.createVNode(VTable, vue.mergeProps({
  20309. "class": ['v-data-table', {
  20310. 'v-data-table--show-select': props.showSelect,
  20311. 'v-data-table--loading': props.loading
  20312. }, props.class],
  20313. "style": props.style
  20314. }, tableProps), {
  20315. top: () => slots.top?.(slotProps.value),
  20316. default: () => slots.default ? slots.default(slotProps.value) : vue.createVNode(vue.Fragment, null, [slots.colgroup?.(slotProps.value), !props.hideDefaultHeader && vue.createVNode("thead", {
  20317. "key": "thead"
  20318. }, [vue.createVNode(VDataTableHeaders, dataTableHeadersProps, slots)]), slots.thead?.(slotProps.value), !props.hideDefaultBody && vue.createVNode("tbody", null, [slots['body.prepend']?.(slotProps.value), slots.body ? slots.body(slotProps.value) : vue.createVNode(VDataTableRows, vue.mergeProps(attrs, dataTableRowsProps, {
  20319. "items": paginatedItems.value
  20320. }), slots), slots['body.append']?.(slotProps.value)]), slots.tbody?.(slotProps.value), slots.tfoot?.(slotProps.value)]),
  20321. bottom: () => slots.bottom ? slots.bottom(slotProps.value) : !props.hideDefaultFooter && vue.createVNode(vue.Fragment, null, [vue.createVNode(VDivider, null, null), vue.createVNode(VDataTableFooter, dataTableFooterProps, {
  20322. prepend: slots['footer.prepend']
  20323. })])
  20324. });
  20325. });
  20326. return {};
  20327. }
  20328. });
  20329. // Types
  20330. const makeVDataTableVirtualProps = propsFactory({
  20331. ...makeDataTableProps(),
  20332. ...makeDataTableGroupProps(),
  20333. ...makeVirtualProps(),
  20334. ...makeFilterProps()
  20335. }, 'VDataTableVirtual');
  20336. const VDataTableVirtual = genericComponent()({
  20337. name: 'VDataTableVirtual',
  20338. props: makeVDataTableVirtualProps(),
  20339. emits: {
  20340. 'update:modelValue': value => true,
  20341. 'update:sortBy': value => true,
  20342. 'update:options': value => true,
  20343. 'update:groupBy': value => true,
  20344. 'update:expanded': value => true
  20345. },
  20346. setup(props, _ref) {
  20347. let {
  20348. attrs,
  20349. slots
  20350. } = _ref;
  20351. const {
  20352. groupBy
  20353. } = createGroupBy(props);
  20354. const {
  20355. sortBy,
  20356. multiSort,
  20357. mustSort
  20358. } = createSort(props);
  20359. const {
  20360. disableSort
  20361. } = vue.toRefs(props);
  20362. const {
  20363. columns,
  20364. headers,
  20365. filterFunctions,
  20366. sortFunctions,
  20367. sortRawFunctions
  20368. } = createHeaders(props, {
  20369. groupBy,
  20370. showSelect: vue.toRef(props, 'showSelect'),
  20371. showExpand: vue.toRef(props, 'showExpand')
  20372. });
  20373. const {
  20374. items
  20375. } = useDataTableItems(props, columns);
  20376. const search = vue.toRef(props, 'search');
  20377. const {
  20378. filteredItems
  20379. } = useFilter(props, items, search, {
  20380. transform: item => item.columns,
  20381. customKeyFilter: filterFunctions
  20382. });
  20383. const {
  20384. toggleSort
  20385. } = provideSort({
  20386. sortBy,
  20387. multiSort,
  20388. mustSort
  20389. });
  20390. const {
  20391. sortByWithGroups,
  20392. opened,
  20393. extractRows,
  20394. isGroupOpen,
  20395. toggleGroup
  20396. } = provideGroupBy({
  20397. groupBy,
  20398. sortBy,
  20399. disableSort
  20400. });
  20401. const {
  20402. sortedItems
  20403. } = useSortedItems(props, filteredItems, sortByWithGroups, {
  20404. transform: item => ({
  20405. ...item.raw,
  20406. ...item.columns
  20407. }),
  20408. sortFunctions,
  20409. sortRawFunctions
  20410. });
  20411. const {
  20412. flatItems
  20413. } = useGroupedItems(sortedItems, groupBy, opened);
  20414. const allItems = vue.computed(() => extractRows(flatItems.value));
  20415. const {
  20416. isSelected,
  20417. select,
  20418. selectAll,
  20419. toggleSelect,
  20420. someSelected,
  20421. allSelected
  20422. } = provideSelection(props, {
  20423. allItems,
  20424. currentPage: allItems
  20425. });
  20426. const {
  20427. isExpanded,
  20428. toggleExpand
  20429. } = provideExpanded(props);
  20430. const {
  20431. containerRef,
  20432. markerRef,
  20433. paddingTop,
  20434. paddingBottom,
  20435. computedItems,
  20436. handleItemResize,
  20437. handleScroll,
  20438. handleScrollend
  20439. } = useVirtual(props, flatItems);
  20440. const displayItems = vue.computed(() => computedItems.value.map(item => item.raw));
  20441. useOptions({
  20442. sortBy,
  20443. page: vue.shallowRef(1),
  20444. itemsPerPage: vue.shallowRef(-1),
  20445. groupBy,
  20446. search
  20447. });
  20448. provideDefaults({
  20449. VDataTableRows: {
  20450. hideNoData: vue.toRef(props, 'hideNoData'),
  20451. noDataText: vue.toRef(props, 'noDataText'),
  20452. loading: vue.toRef(props, 'loading'),
  20453. loadingText: vue.toRef(props, 'loadingText')
  20454. }
  20455. });
  20456. const slotProps = vue.computed(() => ({
  20457. sortBy: sortBy.value,
  20458. toggleSort,
  20459. someSelected: someSelected.value,
  20460. allSelected: allSelected.value,
  20461. isSelected,
  20462. select,
  20463. selectAll,
  20464. toggleSelect,
  20465. isExpanded,
  20466. toggleExpand,
  20467. isGroupOpen,
  20468. toggleGroup,
  20469. items: allItems.value.map(item => item.raw),
  20470. internalItems: allItems.value,
  20471. groupedItems: flatItems.value,
  20472. columns: columns.value,
  20473. headers: headers.value
  20474. }));
  20475. useRender(() => {
  20476. const dataTableHeadersProps = VDataTableHeaders.filterProps(props);
  20477. const dataTableRowsProps = VDataTableRows.filterProps(props);
  20478. const tableProps = VTable.filterProps(props);
  20479. return vue.createVNode(VTable, vue.mergeProps({
  20480. "class": ['v-data-table', {
  20481. 'v-data-table--loading': props.loading
  20482. }, props.class],
  20483. "style": props.style
  20484. }, tableProps), {
  20485. top: () => slots.top?.(slotProps.value),
  20486. wrapper: () => vue.createVNode("div", {
  20487. "ref": containerRef,
  20488. "onScrollPassive": handleScroll,
  20489. "onScrollend": handleScrollend,
  20490. "class": "v-table__wrapper",
  20491. "style": {
  20492. height: convertToUnit(props.height)
  20493. }
  20494. }, [vue.createVNode("table", null, [slots.colgroup?.(slotProps.value), !props.hideDefaultHeader && vue.createVNode("thead", {
  20495. "key": "thead"
  20496. }, [vue.createVNode(VDataTableHeaders, vue.mergeProps(dataTableHeadersProps, {
  20497. "sticky": props.fixedHeader
  20498. }), slots)]), !props.hideDefaultBody && vue.createVNode("tbody", null, [vue.createVNode("tr", {
  20499. "ref": markerRef,
  20500. "style": {
  20501. height: convertToUnit(paddingTop.value),
  20502. border: 0
  20503. }
  20504. }, [vue.createVNode("td", {
  20505. "colspan": columns.value.length,
  20506. "style": {
  20507. height: 0,
  20508. border: 0
  20509. }
  20510. }, null)]), slots['body.prepend']?.(slotProps.value), vue.createVNode(VDataTableRows, vue.mergeProps(attrs, dataTableRowsProps, {
  20511. "items": displayItems.value
  20512. }), {
  20513. ...slots,
  20514. item: itemSlotProps => vue.createVNode(VVirtualScrollItem, {
  20515. "key": itemSlotProps.internalItem.index,
  20516. "renderless": true,
  20517. "onUpdate:height": height => handleItemResize(itemSlotProps.internalItem.index, height)
  20518. }, {
  20519. default: _ref2 => {
  20520. let {
  20521. itemRef
  20522. } = _ref2;
  20523. return slots.item?.({
  20524. ...itemSlotProps,
  20525. itemRef
  20526. }) ?? vue.createVNode(VDataTableRow, vue.mergeProps(itemSlotProps.props, {
  20527. "ref": itemRef,
  20528. "key": itemSlotProps.internalItem.index,
  20529. "index": itemSlotProps.internalItem.index
  20530. }), slots);
  20531. }
  20532. })
  20533. }), slots['body.append']?.(slotProps.value), vue.createVNode("tr", {
  20534. "style": {
  20535. height: convertToUnit(paddingBottom.value),
  20536. border: 0
  20537. }
  20538. }, [vue.createVNode("td", {
  20539. "colspan": columns.value.length,
  20540. "style": {
  20541. height: 0,
  20542. border: 0
  20543. }
  20544. }, null)])])])]),
  20545. bottom: () => slots.bottom?.(slotProps.value)
  20546. });
  20547. });
  20548. }
  20549. });
  20550. // Types
  20551. const makeVDataTableServerProps = propsFactory({
  20552. itemsLength: {
  20553. type: [Number, String],
  20554. required: true
  20555. },
  20556. ...makeDataTablePaginateProps(),
  20557. ...makeDataTableProps(),
  20558. ...makeVDataTableFooterProps()
  20559. }, 'VDataTableServer');
  20560. const VDataTableServer = genericComponent()({
  20561. name: 'VDataTableServer',
  20562. props: makeVDataTableServerProps(),
  20563. emits: {
  20564. 'update:modelValue': value => true,
  20565. 'update:page': page => true,
  20566. 'update:itemsPerPage': page => true,
  20567. 'update:sortBy': sortBy => true,
  20568. 'update:options': options => true,
  20569. 'update:expanded': options => true,
  20570. 'update:groupBy': value => true
  20571. },
  20572. setup(props, _ref) {
  20573. let {
  20574. attrs,
  20575. slots
  20576. } = _ref;
  20577. const {
  20578. groupBy
  20579. } = createGroupBy(props);
  20580. const {
  20581. sortBy,
  20582. multiSort,
  20583. mustSort
  20584. } = createSort(props);
  20585. const {
  20586. page,
  20587. itemsPerPage
  20588. } = createPagination(props);
  20589. const {
  20590. disableSort
  20591. } = vue.toRefs(props);
  20592. const itemsLength = vue.computed(() => parseInt(props.itemsLength, 10));
  20593. const {
  20594. columns,
  20595. headers
  20596. } = createHeaders(props, {
  20597. groupBy,
  20598. showSelect: vue.toRef(props, 'showSelect'),
  20599. showExpand: vue.toRef(props, 'showExpand')
  20600. });
  20601. const {
  20602. items
  20603. } = useDataTableItems(props, columns);
  20604. const {
  20605. toggleSort
  20606. } = provideSort({
  20607. sortBy,
  20608. multiSort,
  20609. mustSort,
  20610. page
  20611. });
  20612. const {
  20613. opened,
  20614. isGroupOpen,
  20615. toggleGroup,
  20616. extractRows
  20617. } = provideGroupBy({
  20618. groupBy,
  20619. sortBy,
  20620. disableSort
  20621. });
  20622. const {
  20623. pageCount,
  20624. setItemsPerPage
  20625. } = providePagination({
  20626. page,
  20627. itemsPerPage,
  20628. itemsLength
  20629. });
  20630. const {
  20631. flatItems
  20632. } = useGroupedItems(items, groupBy, opened);
  20633. const {
  20634. isSelected,
  20635. select,
  20636. selectAll,
  20637. toggleSelect,
  20638. someSelected,
  20639. allSelected
  20640. } = provideSelection(props, {
  20641. allItems: items,
  20642. currentPage: items
  20643. });
  20644. const {
  20645. isExpanded,
  20646. toggleExpand
  20647. } = provideExpanded(props);
  20648. const itemsWithoutGroups = vue.computed(() => extractRows(items.value));
  20649. useOptions({
  20650. page,
  20651. itemsPerPage,
  20652. sortBy,
  20653. groupBy,
  20654. search: vue.toRef(props, 'search')
  20655. });
  20656. vue.provide('v-data-table', {
  20657. toggleSort,
  20658. sortBy
  20659. });
  20660. provideDefaults({
  20661. VDataTableRows: {
  20662. hideNoData: vue.toRef(props, 'hideNoData'),
  20663. noDataText: vue.toRef(props, 'noDataText'),
  20664. loading: vue.toRef(props, 'loading'),
  20665. loadingText: vue.toRef(props, 'loadingText')
  20666. }
  20667. });
  20668. const slotProps = vue.computed(() => ({
  20669. page: page.value,
  20670. itemsPerPage: itemsPerPage.value,
  20671. sortBy: sortBy.value,
  20672. pageCount: pageCount.value,
  20673. toggleSort,
  20674. setItemsPerPage,
  20675. someSelected: someSelected.value,
  20676. allSelected: allSelected.value,
  20677. isSelected,
  20678. select,
  20679. selectAll,
  20680. toggleSelect,
  20681. isExpanded,
  20682. toggleExpand,
  20683. isGroupOpen,
  20684. toggleGroup,
  20685. items: itemsWithoutGroups.value.map(item => item.raw),
  20686. internalItems: itemsWithoutGroups.value,
  20687. groupedItems: flatItems.value,
  20688. columns: columns.value,
  20689. headers: headers.value
  20690. }));
  20691. useRender(() => {
  20692. const dataTableFooterProps = VDataTableFooter.filterProps(props);
  20693. const dataTableHeadersProps = VDataTableHeaders.filterProps(props);
  20694. const dataTableRowsProps = VDataTableRows.filterProps(props);
  20695. const tableProps = VTable.filterProps(props);
  20696. return vue.createVNode(VTable, vue.mergeProps({
  20697. "class": ['v-data-table', {
  20698. 'v-data-table--loading': props.loading
  20699. }, props.class],
  20700. "style": props.style
  20701. }, tableProps), {
  20702. top: () => slots.top?.(slotProps.value),
  20703. default: () => slots.default ? slots.default(slotProps.value) : vue.createVNode(vue.Fragment, null, [slots.colgroup?.(slotProps.value), !props.hideDefaultHeader && vue.createVNode("thead", {
  20704. "key": "thead",
  20705. "class": "v-data-table__thead",
  20706. "role": "rowgroup"
  20707. }, [vue.createVNode(VDataTableHeaders, vue.mergeProps(dataTableHeadersProps, {
  20708. "sticky": props.fixedHeader
  20709. }), slots)]), slots.thead?.(slotProps.value), !props.hideDefaultBody && vue.createVNode("tbody", {
  20710. "class": "v-data-table__tbody",
  20711. "role": "rowgroup"
  20712. }, [slots['body.prepend']?.(slotProps.value), slots.body ? slots.body(slotProps.value) : vue.createVNode(VDataTableRows, vue.mergeProps(attrs, dataTableRowsProps, {
  20713. "items": flatItems.value
  20714. }), slots), slots['body.append']?.(slotProps.value)]), slots.tbody?.(slotProps.value), slots.tfoot?.(slotProps.value)]),
  20715. bottom: () => slots.bottom ? slots.bottom(slotProps.value) : !props.hideDefaultFooter && vue.createVNode(vue.Fragment, null, [vue.createVNode(VDivider, null, null), vue.createVNode(VDataTableFooter, dataTableFooterProps, {
  20716. prepend: slots['footer.prepend']
  20717. })])
  20718. });
  20719. });
  20720. }
  20721. });
  20722. const makeVContainerProps = propsFactory({
  20723. fluid: {
  20724. type: Boolean,
  20725. default: false
  20726. },
  20727. ...makeComponentProps(),
  20728. ...makeDimensionProps(),
  20729. ...makeTagProps()
  20730. }, 'VContainer');
  20731. const VContainer = genericComponent()({
  20732. name: 'VContainer',
  20733. props: makeVContainerProps(),
  20734. setup(props, _ref) {
  20735. let {
  20736. slots
  20737. } = _ref;
  20738. const {
  20739. rtlClasses
  20740. } = useRtl();
  20741. const {
  20742. dimensionStyles
  20743. } = useDimension(props);
  20744. useRender(() => vue.createVNode(props.tag, {
  20745. "class": ['v-container', {
  20746. 'v-container--fluid': props.fluid
  20747. }, rtlClasses.value, props.class],
  20748. "style": [dimensionStyles.value, props.style]
  20749. }, slots));
  20750. return {};
  20751. }
  20752. });
  20753. // Styles
  20754. // Types
  20755. const breakpointProps = (() => {
  20756. return breakpoints.reduce((props, val) => {
  20757. props[val] = {
  20758. type: [Boolean, String, Number],
  20759. default: false
  20760. };
  20761. return props;
  20762. }, {});
  20763. })();
  20764. const offsetProps = (() => {
  20765. return breakpoints.reduce((props, val) => {
  20766. const offsetKey = 'offset' + vue.capitalize(val);
  20767. props[offsetKey] = {
  20768. type: [String, Number],
  20769. default: null
  20770. };
  20771. return props;
  20772. }, {});
  20773. })();
  20774. const orderProps = (() => {
  20775. return breakpoints.reduce((props, val) => {
  20776. const orderKey = 'order' + vue.capitalize(val);
  20777. props[orderKey] = {
  20778. type: [String, Number],
  20779. default: null
  20780. };
  20781. return props;
  20782. }, {});
  20783. })();
  20784. const propMap$1 = {
  20785. col: Object.keys(breakpointProps),
  20786. offset: Object.keys(offsetProps),
  20787. order: Object.keys(orderProps)
  20788. };
  20789. function breakpointClass$1(type, prop, val) {
  20790. let className = type;
  20791. if (val == null || val === false) {
  20792. return undefined;
  20793. }
  20794. if (prop) {
  20795. const breakpoint = prop.replace(type, '');
  20796. className += `-${breakpoint}`;
  20797. }
  20798. if (type === 'col') {
  20799. className = 'v-' + className;
  20800. }
  20801. // Handling the boolean style prop when accepting [Boolean, String, Number]
  20802. // means Vue will not convert <v-col sm></v-col> to sm: true for us.
  20803. // Since the default is false, an empty string indicates the prop's presence.
  20804. if (type === 'col' && (val === '' || val === true)) {
  20805. // .v-col-md
  20806. return className.toLowerCase();
  20807. }
  20808. // .order-md-6
  20809. className += `-${val}`;
  20810. return className.toLowerCase();
  20811. }
  20812. const ALIGN_SELF_VALUES = ['auto', 'start', 'end', 'center', 'baseline', 'stretch'];
  20813. const makeVColProps = propsFactory({
  20814. cols: {
  20815. type: [Boolean, String, Number],
  20816. default: false
  20817. },
  20818. ...breakpointProps,
  20819. offset: {
  20820. type: [String, Number],
  20821. default: null
  20822. },
  20823. ...offsetProps,
  20824. order: {
  20825. type: [String, Number],
  20826. default: null
  20827. },
  20828. ...orderProps,
  20829. alignSelf: {
  20830. type: String,
  20831. default: null,
  20832. validator: str => ALIGN_SELF_VALUES.includes(str)
  20833. },
  20834. ...makeComponentProps(),
  20835. ...makeTagProps()
  20836. }, 'VCol');
  20837. const VCol = genericComponent()({
  20838. name: 'VCol',
  20839. props: makeVColProps(),
  20840. setup(props, _ref) {
  20841. let {
  20842. slots
  20843. } = _ref;
  20844. const classes = vue.computed(() => {
  20845. const classList = [];
  20846. // Loop through `col`, `offset`, `order` breakpoint props
  20847. let type;
  20848. for (type in propMap$1) {
  20849. propMap$1[type].forEach(prop => {
  20850. const value = props[prop];
  20851. const className = breakpointClass$1(type, prop, value);
  20852. if (className) classList.push(className);
  20853. });
  20854. }
  20855. const hasColClasses = classList.some(className => className.startsWith('v-col-'));
  20856. classList.push({
  20857. // Default to .v-col if no other col-{bp}-* classes generated nor `cols` specified.
  20858. 'v-col': !hasColClasses || !props.cols,
  20859. [`v-col-${props.cols}`]: props.cols,
  20860. [`offset-${props.offset}`]: props.offset,
  20861. [`order-${props.order}`]: props.order,
  20862. [`align-self-${props.alignSelf}`]: props.alignSelf
  20863. });
  20864. return classList;
  20865. });
  20866. return () => vue.h(props.tag, {
  20867. class: [classes.value, props.class],
  20868. style: props.style
  20869. }, slots.default?.());
  20870. }
  20871. });
  20872. // Styles
  20873. // Types
  20874. const ALIGNMENT = ['start', 'end', 'center'];
  20875. const SPACE = ['space-between', 'space-around', 'space-evenly'];
  20876. function makeRowProps(prefix, def) {
  20877. return breakpoints.reduce((props, val) => {
  20878. const prefixKey = prefix + vue.capitalize(val);
  20879. props[prefixKey] = def();
  20880. return props;
  20881. }, {});
  20882. }
  20883. const ALIGN_VALUES = [...ALIGNMENT, 'baseline', 'stretch'];
  20884. const alignValidator = str => ALIGN_VALUES.includes(str);
  20885. const alignProps = makeRowProps('align', () => ({
  20886. type: String,
  20887. default: null,
  20888. validator: alignValidator
  20889. }));
  20890. const JUSTIFY_VALUES = [...ALIGNMENT, ...SPACE];
  20891. const justifyValidator = str => JUSTIFY_VALUES.includes(str);
  20892. const justifyProps = makeRowProps('justify', () => ({
  20893. type: String,
  20894. default: null,
  20895. validator: justifyValidator
  20896. }));
  20897. const ALIGN_CONTENT_VALUES = [...ALIGNMENT, ...SPACE, 'stretch'];
  20898. const alignContentValidator = str => ALIGN_CONTENT_VALUES.includes(str);
  20899. const alignContentProps = makeRowProps('alignContent', () => ({
  20900. type: String,
  20901. default: null,
  20902. validator: alignContentValidator
  20903. }));
  20904. const propMap = {
  20905. align: Object.keys(alignProps),
  20906. justify: Object.keys(justifyProps),
  20907. alignContent: Object.keys(alignContentProps)
  20908. };
  20909. const classMap = {
  20910. align: 'align',
  20911. justify: 'justify',
  20912. alignContent: 'align-content'
  20913. };
  20914. function breakpointClass(type, prop, val) {
  20915. let className = classMap[type];
  20916. if (val == null) {
  20917. return undefined;
  20918. }
  20919. if (prop) {
  20920. // alignSm -> Sm
  20921. const breakpoint = prop.replace(type, '');
  20922. className += `-${breakpoint}`;
  20923. }
  20924. // .align-items-sm-center
  20925. className += `-${val}`;
  20926. return className.toLowerCase();
  20927. }
  20928. const makeVRowProps = propsFactory({
  20929. dense: Boolean,
  20930. noGutters: Boolean,
  20931. align: {
  20932. type: String,
  20933. default: null,
  20934. validator: alignValidator
  20935. },
  20936. ...alignProps,
  20937. justify: {
  20938. type: String,
  20939. default: null,
  20940. validator: justifyValidator
  20941. },
  20942. ...justifyProps,
  20943. alignContent: {
  20944. type: String,
  20945. default: null,
  20946. validator: alignContentValidator
  20947. },
  20948. ...alignContentProps,
  20949. ...makeComponentProps(),
  20950. ...makeTagProps()
  20951. }, 'VRow');
  20952. const VRow = genericComponent()({
  20953. name: 'VRow',
  20954. props: makeVRowProps(),
  20955. setup(props, _ref) {
  20956. let {
  20957. slots
  20958. } = _ref;
  20959. const classes = vue.computed(() => {
  20960. const classList = [];
  20961. // Loop through `align`, `justify`, `alignContent` breakpoint props
  20962. let type;
  20963. for (type in propMap) {
  20964. propMap[type].forEach(prop => {
  20965. const value = props[prop];
  20966. const className = breakpointClass(type, prop, value);
  20967. if (className) classList.push(className);
  20968. });
  20969. }
  20970. classList.push({
  20971. 'v-row--no-gutters': props.noGutters,
  20972. 'v-row--dense': props.dense,
  20973. [`align-${props.align}`]: props.align,
  20974. [`justify-${props.justify}`]: props.justify,
  20975. [`align-content-${props.alignContent}`]: props.alignContent
  20976. });
  20977. return classList;
  20978. });
  20979. return () => vue.h(props.tag, {
  20980. class: ['v-row', classes.value, props.class],
  20981. style: props.style
  20982. }, slots.default?.());
  20983. }
  20984. });
  20985. // Styles
  20986. const VSpacer = createSimpleFunctional('v-spacer', 'div', 'VSpacer');
  20987. // Types
  20988. const makeVDatePickerControlsProps = propsFactory({
  20989. active: {
  20990. type: [String, Array],
  20991. default: undefined
  20992. },
  20993. disabled: {
  20994. type: [Boolean, String, Array],
  20995. default: false
  20996. },
  20997. nextIcon: {
  20998. type: IconValue,
  20999. default: '$next'
  21000. },
  21001. prevIcon: {
  21002. type: IconValue,
  21003. default: '$prev'
  21004. },
  21005. modeIcon: {
  21006. type: IconValue,
  21007. default: '$subgroup'
  21008. },
  21009. text: String,
  21010. viewMode: {
  21011. type: String,
  21012. default: 'month'
  21013. }
  21014. }, 'VDatePickerControls');
  21015. const VDatePickerControls = genericComponent()({
  21016. name: 'VDatePickerControls',
  21017. props: makeVDatePickerControlsProps(),
  21018. emits: {
  21019. 'click:year': () => true,
  21020. 'click:month': () => true,
  21021. 'click:prev': () => true,
  21022. 'click:next': () => true,
  21023. 'click:text': () => true
  21024. },
  21025. setup(props, _ref) {
  21026. let {
  21027. emit
  21028. } = _ref;
  21029. const disableMonth = vue.computed(() => {
  21030. return Array.isArray(props.disabled) ? props.disabled.includes('text') : !!props.disabled;
  21031. });
  21032. const disableYear = vue.computed(() => {
  21033. return Array.isArray(props.disabled) ? props.disabled.includes('mode') : !!props.disabled;
  21034. });
  21035. const disablePrev = vue.computed(() => {
  21036. return Array.isArray(props.disabled) ? props.disabled.includes('prev') : !!props.disabled;
  21037. });
  21038. const disableNext = vue.computed(() => {
  21039. return Array.isArray(props.disabled) ? props.disabled.includes('next') : !!props.disabled;
  21040. });
  21041. function onClickPrev() {
  21042. emit('click:prev');
  21043. }
  21044. function onClickNext() {
  21045. emit('click:next');
  21046. }
  21047. function onClickYear() {
  21048. emit('click:year');
  21049. }
  21050. function onClickMonth() {
  21051. emit('click:month');
  21052. }
  21053. useRender(() => {
  21054. // TODO: add slot support and scope defaults
  21055. return vue.createVNode("div", {
  21056. "class": ['v-date-picker-controls']
  21057. }, [vue.createVNode(VBtn, {
  21058. "class": "v-date-picker-controls__month-btn",
  21059. "disabled": disableMonth.value,
  21060. "text": props.text,
  21061. "variant": "text",
  21062. "rounded": true,
  21063. "onClick": onClickMonth
  21064. }, null), vue.createVNode(VBtn, {
  21065. "key": "mode-btn",
  21066. "class": "v-date-picker-controls__mode-btn",
  21067. "disabled": disableYear.value,
  21068. "density": "comfortable",
  21069. "icon": props.modeIcon,
  21070. "variant": "text",
  21071. "onClick": onClickYear
  21072. }, null), vue.createVNode(VSpacer, {
  21073. "key": "mode-spacer"
  21074. }, null), vue.createVNode("div", {
  21075. "key": "month-buttons",
  21076. "class": "v-date-picker-controls__month"
  21077. }, [vue.createVNode(VBtn, {
  21078. "disabled": disablePrev.value,
  21079. "icon": props.prevIcon,
  21080. "variant": "text",
  21081. "onClick": onClickPrev
  21082. }, null), vue.createVNode(VBtn, {
  21083. "disabled": disableNext.value,
  21084. "icon": props.nextIcon,
  21085. "variant": "text",
  21086. "onClick": onClickNext
  21087. }, null)])]);
  21088. });
  21089. return {};
  21090. }
  21091. });
  21092. // Types
  21093. const makeVDatePickerHeaderProps = propsFactory({
  21094. appendIcon: IconValue,
  21095. color: String,
  21096. header: String,
  21097. transition: String,
  21098. onClick: EventProp()
  21099. }, 'VDatePickerHeader');
  21100. const VDatePickerHeader = genericComponent()({
  21101. name: 'VDatePickerHeader',
  21102. props: makeVDatePickerHeaderProps(),
  21103. emits: {
  21104. click: () => true,
  21105. 'click:append': () => true
  21106. },
  21107. setup(props, _ref) {
  21108. let {
  21109. emit,
  21110. slots
  21111. } = _ref;
  21112. const {
  21113. backgroundColorClasses,
  21114. backgroundColorStyles
  21115. } = useBackgroundColor(props, 'color');
  21116. function onClick() {
  21117. emit('click');
  21118. }
  21119. function onClickAppend() {
  21120. emit('click:append');
  21121. }
  21122. useRender(() => {
  21123. const hasContent = !!(slots.default || props.header);
  21124. const hasAppend = !!(slots.append || props.appendIcon);
  21125. return vue.createVNode("div", {
  21126. "class": ['v-date-picker-header', {
  21127. 'v-date-picker-header--clickable': !!props.onClick
  21128. }, backgroundColorClasses.value],
  21129. "style": backgroundColorStyles.value,
  21130. "onClick": onClick
  21131. }, [slots.prepend && vue.createVNode("div", {
  21132. "key": "prepend",
  21133. "class": "v-date-picker-header__prepend"
  21134. }, [slots.prepend()]), hasContent && vue.createVNode(MaybeTransition, {
  21135. "key": "content",
  21136. "name": props.transition
  21137. }, {
  21138. default: () => [vue.createVNode("div", {
  21139. "key": props.header,
  21140. "class": "v-date-picker-header__content"
  21141. }, [slots.default?.() ?? props.header])]
  21142. }), hasAppend && vue.createVNode("div", {
  21143. "class": "v-date-picker-header__append"
  21144. }, [!slots.append ? vue.createVNode(VBtn, {
  21145. "key": "append-btn",
  21146. "icon": props.appendIcon,
  21147. "variant": "text",
  21148. "onClick": onClickAppend
  21149. }, null) : vue.createVNode(VDefaultsProvider, {
  21150. "key": "append-defaults",
  21151. "disabled": !props.appendIcon,
  21152. "defaults": {
  21153. VBtn: {
  21154. icon: props.appendIcon,
  21155. variant: 'text'
  21156. }
  21157. }
  21158. }, {
  21159. default: () => [slots.append?.()]
  21160. })])]);
  21161. });
  21162. return {};
  21163. }
  21164. });
  21165. // Composables
  21166. // Types
  21167. // Types
  21168. // Composables
  21169. const makeCalendarProps = propsFactory({
  21170. allowedDates: [Array, Function],
  21171. disabled: Boolean,
  21172. displayValue: null,
  21173. modelValue: Array,
  21174. month: [Number, String],
  21175. max: null,
  21176. min: null,
  21177. showAdjacentMonths: Boolean,
  21178. year: [Number, String],
  21179. weekdays: {
  21180. type: Array,
  21181. default: () => [0, 1, 2, 3, 4, 5, 6]
  21182. },
  21183. weeksInMonth: {
  21184. type: String,
  21185. default: 'dynamic'
  21186. },
  21187. firstDayOfWeek: [Number, String]
  21188. }, 'calendar');
  21189. function useCalendar(props) {
  21190. const adapter = useDate();
  21191. const model = useProxiedModel(props, 'modelValue', [], v => wrapInArray(v));
  21192. const displayValue = vue.computed(() => {
  21193. if (props.displayValue) return adapter.date(props.displayValue);
  21194. if (model.value.length > 0) return adapter.date(model.value[0]);
  21195. if (props.min) return adapter.date(props.min);
  21196. if (Array.isArray(props.allowedDates)) return adapter.date(props.allowedDates[0]);
  21197. return adapter.date();
  21198. });
  21199. const year = useProxiedModel(props, 'year', undefined, v => {
  21200. const value = v != null ? Number(v) : adapter.getYear(displayValue.value);
  21201. return adapter.startOfYear(adapter.setYear(adapter.date(), value));
  21202. }, v => adapter.getYear(v));
  21203. const month = useProxiedModel(props, 'month', undefined, v => {
  21204. const value = v != null ? Number(v) : adapter.getMonth(displayValue.value);
  21205. const date = adapter.setYear(adapter.startOfMonth(adapter.date()), adapter.getYear(year.value));
  21206. return adapter.setMonth(date, value);
  21207. }, v => adapter.getMonth(v));
  21208. const weekDays = vue.computed(() => {
  21209. const firstDayOfWeek = Number(props.firstDayOfWeek ?? 0);
  21210. return props.weekdays.map(day => (day + firstDayOfWeek) % 7);
  21211. });
  21212. const weeksInMonth = vue.computed(() => {
  21213. const weeks = adapter.getWeekArray(month.value, props.firstDayOfWeek);
  21214. const days = weeks.flat();
  21215. // Make sure there's always 6 weeks in month (6 * 7 days)
  21216. // if weeksInMonth is 'static'
  21217. const daysInMonth = 6 * 7;
  21218. if (props.weeksInMonth === 'static' && days.length < daysInMonth) {
  21219. const lastDay = days[days.length - 1];
  21220. let week = [];
  21221. for (let day = 1; day <= daysInMonth - days.length; day++) {
  21222. week.push(adapter.addDays(lastDay, day));
  21223. if (day % 7 === 0) {
  21224. weeks.push(week);
  21225. week = [];
  21226. }
  21227. }
  21228. }
  21229. return weeks;
  21230. });
  21231. function genDays(days, today) {
  21232. return days.filter(date => {
  21233. return weekDays.value.includes(adapter.toJsDate(date).getDay());
  21234. }).map((date, index) => {
  21235. const isoDate = adapter.toISO(date);
  21236. const isAdjacent = !adapter.isSameMonth(date, month.value);
  21237. const isStart = adapter.isSameDay(date, adapter.startOfMonth(month.value));
  21238. const isEnd = adapter.isSameDay(date, adapter.endOfMonth(month.value));
  21239. const isSame = adapter.isSameDay(date, month.value);
  21240. return {
  21241. date,
  21242. isoDate,
  21243. formatted: adapter.format(date, 'keyboardDate'),
  21244. year: adapter.getYear(date),
  21245. month: adapter.getMonth(date),
  21246. isDisabled: isDisabled(date),
  21247. isWeekStart: index % 7 === 0,
  21248. isWeekEnd: index % 7 === 6,
  21249. isToday: adapter.isSameDay(date, today),
  21250. isAdjacent,
  21251. isHidden: isAdjacent && !props.showAdjacentMonths,
  21252. isStart,
  21253. isSelected: model.value.some(value => adapter.isSameDay(date, value)),
  21254. isEnd,
  21255. isSame,
  21256. localized: adapter.format(date, 'dayOfMonth')
  21257. };
  21258. });
  21259. }
  21260. const daysInWeek = vue.computed(() => {
  21261. const lastDay = adapter.startOfWeek(displayValue.value, props.firstDayOfWeek);
  21262. const week = [];
  21263. for (let day = 0; day <= 6; day++) {
  21264. week.push(adapter.addDays(lastDay, day));
  21265. }
  21266. const today = adapter.date();
  21267. return genDays(week, today);
  21268. });
  21269. const daysInMonth = vue.computed(() => {
  21270. const days = weeksInMonth.value.flat();
  21271. const today = adapter.date();
  21272. return genDays(days, today);
  21273. });
  21274. const weekNumbers = vue.computed(() => {
  21275. return weeksInMonth.value.map(week => {
  21276. return week.length ? getWeek(adapter, week[0]) : null;
  21277. });
  21278. });
  21279. function isDisabled(value) {
  21280. if (props.disabled) return true;
  21281. const date = adapter.date(value);
  21282. if (props.min && adapter.isAfter(adapter.date(props.min), date)) return true;
  21283. if (props.max && adapter.isAfter(date, adapter.date(props.max))) return true;
  21284. if (Array.isArray(props.allowedDates) && props.allowedDates.length > 0) {
  21285. return !props.allowedDates.some(d => adapter.isSameDay(adapter.date(d), date));
  21286. }
  21287. if (typeof props.allowedDates === 'function') {
  21288. return !props.allowedDates(date);
  21289. }
  21290. return false;
  21291. }
  21292. return {
  21293. displayValue,
  21294. daysInMonth,
  21295. daysInWeek,
  21296. genDays,
  21297. model,
  21298. weeksInMonth,
  21299. weekDays,
  21300. weekNumbers
  21301. };
  21302. }
  21303. // Types
  21304. const makeVDatePickerMonthProps = propsFactory({
  21305. color: String,
  21306. hideWeekdays: Boolean,
  21307. multiple: [Boolean, Number, String],
  21308. showWeek: Boolean,
  21309. transition: {
  21310. type: String,
  21311. default: 'picker-transition'
  21312. },
  21313. reverseTransition: {
  21314. type: String,
  21315. default: 'picker-reverse-transition'
  21316. },
  21317. ...makeCalendarProps()
  21318. }, 'VDatePickerMonth');
  21319. const VDatePickerMonth = genericComponent()({
  21320. name: 'VDatePickerMonth',
  21321. props: makeVDatePickerMonthProps(),
  21322. emits: {
  21323. 'update:modelValue': date => true,
  21324. 'update:month': date => true,
  21325. 'update:year': date => true
  21326. },
  21327. setup(props, _ref) {
  21328. let {
  21329. emit,
  21330. slots
  21331. } = _ref;
  21332. const daysRef = vue.ref();
  21333. const {
  21334. daysInMonth,
  21335. model,
  21336. weekNumbers
  21337. } = useCalendar(props);
  21338. const adapter = useDate();
  21339. const rangeStart = vue.shallowRef();
  21340. const rangeStop = vue.shallowRef();
  21341. const isReverse = vue.shallowRef(false);
  21342. const transition = vue.computed(() => {
  21343. return !isReverse.value ? props.transition : props.reverseTransition;
  21344. });
  21345. if (props.multiple === 'range' && model.value.length > 0) {
  21346. rangeStart.value = model.value[0];
  21347. if (model.value.length > 1) {
  21348. rangeStop.value = model.value[model.value.length - 1];
  21349. }
  21350. }
  21351. const atMax = vue.computed(() => {
  21352. const max = ['number', 'string'].includes(typeof props.multiple) ? Number(props.multiple) : Infinity;
  21353. return model.value.length >= max;
  21354. });
  21355. vue.watch(daysInMonth, (val, oldVal) => {
  21356. if (!oldVal) return;
  21357. isReverse.value = adapter.isBefore(val[0].date, oldVal[0].date);
  21358. });
  21359. function onRangeClick(value) {
  21360. const _value = adapter.startOfDay(value);
  21361. if (model.value.length === 0) {
  21362. rangeStart.value = undefined;
  21363. } else if (model.value.length === 1) {
  21364. rangeStart.value = model.value[0];
  21365. rangeStop.value = undefined;
  21366. }
  21367. if (!rangeStart.value) {
  21368. rangeStart.value = _value;
  21369. model.value = [rangeStart.value];
  21370. } else if (!rangeStop.value) {
  21371. if (adapter.isSameDay(_value, rangeStart.value)) {
  21372. rangeStart.value = undefined;
  21373. model.value = [];
  21374. return;
  21375. } else if (adapter.isBefore(_value, rangeStart.value)) {
  21376. rangeStop.value = adapter.endOfDay(rangeStart.value);
  21377. rangeStart.value = _value;
  21378. } else {
  21379. rangeStop.value = adapter.endOfDay(_value);
  21380. }
  21381. const diff = adapter.getDiff(rangeStop.value, rangeStart.value, 'days');
  21382. const datesInRange = [rangeStart.value];
  21383. for (let i = 1; i < diff; i++) {
  21384. const nextDate = adapter.addDays(rangeStart.value, i);
  21385. datesInRange.push(nextDate);
  21386. }
  21387. datesInRange.push(rangeStop.value);
  21388. model.value = datesInRange;
  21389. } else {
  21390. rangeStart.value = value;
  21391. rangeStop.value = undefined;
  21392. model.value = [rangeStart.value];
  21393. }
  21394. }
  21395. function onMultipleClick(value) {
  21396. const index = model.value.findIndex(selection => adapter.isSameDay(selection, value));
  21397. if (index === -1) {
  21398. model.value = [...model.value, value];
  21399. } else {
  21400. const value = [...model.value];
  21401. value.splice(index, 1);
  21402. model.value = value;
  21403. }
  21404. }
  21405. function onClick(value) {
  21406. if (props.multiple === 'range') {
  21407. onRangeClick(value);
  21408. } else if (props.multiple) {
  21409. onMultipleClick(value);
  21410. } else {
  21411. model.value = [value];
  21412. }
  21413. }
  21414. return () => vue.createVNode("div", {
  21415. "class": "v-date-picker-month"
  21416. }, [props.showWeek && vue.createVNode("div", {
  21417. "key": "weeks",
  21418. "class": "v-date-picker-month__weeks"
  21419. }, [!props.hideWeekdays && vue.createVNode("div", {
  21420. "key": "hide-week-days",
  21421. "class": "v-date-picker-month__day"
  21422. }, [vue.createTextVNode("\xA0")]), weekNumbers.value.map(week => vue.createVNode("div", {
  21423. "class": ['v-date-picker-month__day', 'v-date-picker-month__day--adjacent']
  21424. }, [week]))]), vue.createVNode(MaybeTransition, {
  21425. "name": transition.value
  21426. }, {
  21427. default: () => [vue.createVNode("div", {
  21428. "ref": daysRef,
  21429. "key": daysInMonth.value[0].date?.toString(),
  21430. "class": "v-date-picker-month__days"
  21431. }, [!props.hideWeekdays && adapter.getWeekdays(props.firstDayOfWeek).map(weekDay => vue.createVNode("div", {
  21432. "class": ['v-date-picker-month__day', 'v-date-picker-month__weekday']
  21433. }, [weekDay])), daysInMonth.value.map((item, i) => {
  21434. const slotProps = {
  21435. props: {
  21436. onClick: () => onClick(item.date)
  21437. },
  21438. item,
  21439. i
  21440. };
  21441. if (atMax.value && !item.isSelected) {
  21442. item.isDisabled = true;
  21443. }
  21444. return vue.createVNode("div", {
  21445. "class": ['v-date-picker-month__day', {
  21446. 'v-date-picker-month__day--adjacent': item.isAdjacent,
  21447. 'v-date-picker-month__day--hide-adjacent': item.isHidden,
  21448. 'v-date-picker-month__day--selected': item.isSelected,
  21449. 'v-date-picker-month__day--week-end': item.isWeekEnd,
  21450. 'v-date-picker-month__day--week-start': item.isWeekStart
  21451. }],
  21452. "data-v-date": !item.isDisabled ? item.isoDate : undefined
  21453. }, [(props.showAdjacentMonths || !item.isAdjacent) && vue.createVNode(VDefaultsProvider, {
  21454. "defaults": {
  21455. VBtn: {
  21456. class: 'v-date-picker-month__day-btn',
  21457. color: (item.isSelected || item.isToday) && !item.isDisabled ? props.color : undefined,
  21458. disabled: item.isDisabled,
  21459. icon: true,
  21460. ripple: false,
  21461. text: item.localized,
  21462. variant: item.isDisabled ? item.isToday ? 'outlined' : 'text' : item.isToday && !item.isSelected ? 'outlined' : 'flat',
  21463. onClick: () => onClick(item.date)
  21464. }
  21465. }
  21466. }, {
  21467. default: () => [slots.day?.(slotProps) ?? vue.createVNode(VBtn, slotProps.props, null)]
  21468. })]);
  21469. })])]
  21470. })]);
  21471. }
  21472. });
  21473. // Types
  21474. const makeVDatePickerMonthsProps = propsFactory({
  21475. color: String,
  21476. height: [String, Number],
  21477. min: null,
  21478. max: null,
  21479. modelValue: Number,
  21480. year: Number
  21481. }, 'VDatePickerMonths');
  21482. const VDatePickerMonths = genericComponent()({
  21483. name: 'VDatePickerMonths',
  21484. props: makeVDatePickerMonthsProps(),
  21485. emits: {
  21486. 'update:modelValue': date => true
  21487. },
  21488. setup(props, _ref) {
  21489. let {
  21490. emit,
  21491. slots
  21492. } = _ref;
  21493. const adapter = useDate();
  21494. const model = useProxiedModel(props, 'modelValue');
  21495. const months = vue.computed(() => {
  21496. let date = adapter.startOfYear(adapter.date());
  21497. if (props.year) {
  21498. date = adapter.setYear(date, props.year);
  21499. }
  21500. return createRange(12).map(i => {
  21501. const text = adapter.format(date, 'monthShort');
  21502. const isDisabled = !!(props.min && adapter.isAfter(adapter.startOfMonth(adapter.date(props.min)), date) || props.max && adapter.isAfter(date, adapter.startOfMonth(adapter.date(props.max))));
  21503. date = adapter.getNextMonth(date);
  21504. return {
  21505. isDisabled,
  21506. text,
  21507. value: i
  21508. };
  21509. });
  21510. });
  21511. vue.watchEffect(() => {
  21512. model.value = model.value ?? adapter.getMonth(adapter.date());
  21513. });
  21514. useRender(() => vue.createVNode("div", {
  21515. "class": "v-date-picker-months",
  21516. "style": {
  21517. height: convertToUnit(props.height)
  21518. }
  21519. }, [vue.createVNode("div", {
  21520. "class": "v-date-picker-months__content"
  21521. }, [months.value.map((month, i) => {
  21522. const btnProps = {
  21523. active: model.value === i,
  21524. color: model.value === i ? props.color : undefined,
  21525. disabled: month.isDisabled,
  21526. rounded: true,
  21527. text: month.text,
  21528. variant: model.value === month.value ? 'flat' : 'text',
  21529. onClick: () => onClick(i)
  21530. };
  21531. function onClick(i) {
  21532. if (model.value === i) {
  21533. emit('update:modelValue', model.value);
  21534. return;
  21535. }
  21536. model.value = i;
  21537. }
  21538. return slots.month?.({
  21539. month,
  21540. i,
  21541. props: btnProps
  21542. }) ?? vue.createVNode(VBtn, vue.mergeProps({
  21543. "key": "month"
  21544. }, btnProps), null);
  21545. })])]));
  21546. return {};
  21547. }
  21548. });
  21549. // Types
  21550. // Types
  21551. const makeVDatePickerYearsProps = propsFactory({
  21552. color: String,
  21553. height: [String, Number],
  21554. min: null,
  21555. max: null,
  21556. modelValue: Number
  21557. }, 'VDatePickerYears');
  21558. const VDatePickerYears = genericComponent()({
  21559. name: 'VDatePickerYears',
  21560. props: makeVDatePickerYearsProps(),
  21561. emits: {
  21562. 'update:modelValue': year => true
  21563. },
  21564. setup(props, _ref) {
  21565. let {
  21566. emit,
  21567. slots
  21568. } = _ref;
  21569. const adapter = useDate();
  21570. const model = useProxiedModel(props, 'modelValue');
  21571. const years = vue.computed(() => {
  21572. const year = adapter.getYear(adapter.date());
  21573. let min = year - 100;
  21574. let max = year + 52;
  21575. if (props.min) {
  21576. min = adapter.getYear(adapter.date(props.min));
  21577. }
  21578. if (props.max) {
  21579. max = adapter.getYear(adapter.date(props.max));
  21580. }
  21581. let date = adapter.startOfYear(adapter.date());
  21582. date = adapter.setYear(date, min);
  21583. return createRange(max - min + 1, min).map(i => {
  21584. const text = adapter.format(date, 'year');
  21585. date = adapter.setYear(date, adapter.getYear(date) + 1);
  21586. return {
  21587. text,
  21588. value: i
  21589. };
  21590. });
  21591. });
  21592. vue.watchEffect(() => {
  21593. model.value = model.value ?? adapter.getYear(adapter.date());
  21594. });
  21595. const yearRef = templateRef();
  21596. vue.onMounted(async () => {
  21597. await vue.nextTick();
  21598. yearRef.el?.scrollIntoView({
  21599. block: 'center'
  21600. });
  21601. });
  21602. useRender(() => vue.createVNode("div", {
  21603. "class": "v-date-picker-years",
  21604. "style": {
  21605. height: convertToUnit(props.height)
  21606. }
  21607. }, [vue.createVNode("div", {
  21608. "class": "v-date-picker-years__content"
  21609. }, [years.value.map((year, i) => {
  21610. const btnProps = {
  21611. ref: model.value === year.value ? yearRef : undefined,
  21612. active: model.value === year.value,
  21613. color: model.value === year.value ? props.color : undefined,
  21614. rounded: true,
  21615. text: year.text,
  21616. variant: model.value === year.value ? 'flat' : 'text',
  21617. onClick: () => {
  21618. if (model.value === year.value) {
  21619. emit('update:modelValue', model.value);
  21620. return;
  21621. }
  21622. model.value = year.value;
  21623. }
  21624. };
  21625. return slots.year?.({
  21626. year,
  21627. i,
  21628. props: btnProps
  21629. }) ?? vue.createVNode(VBtn, vue.mergeProps({
  21630. "key": "month"
  21631. }, btnProps), null);
  21632. })])]));
  21633. return {};
  21634. }
  21635. });
  21636. // Utilities
  21637. const VPickerTitle = createSimpleFunctional('v-picker-title');
  21638. // Types
  21639. const makeVPickerProps = propsFactory({
  21640. bgColor: String,
  21641. landscape: Boolean,
  21642. title: String,
  21643. hideHeader: Boolean,
  21644. ...makeVSheetProps()
  21645. }, 'VPicker');
  21646. const VPicker = genericComponent()({
  21647. name: 'VPicker',
  21648. props: makeVPickerProps(),
  21649. setup(props, _ref) {
  21650. let {
  21651. slots
  21652. } = _ref;
  21653. const {
  21654. backgroundColorClasses,
  21655. backgroundColorStyles
  21656. } = useBackgroundColor(vue.toRef(props, 'color'));
  21657. useRender(() => {
  21658. const sheetProps = VSheet.filterProps(props);
  21659. const hasTitle = !!(props.title || slots.title);
  21660. return vue.createVNode(VSheet, vue.mergeProps(sheetProps, {
  21661. "color": props.bgColor,
  21662. "class": ['v-picker', {
  21663. 'v-picker--landscape': props.landscape,
  21664. 'v-picker--with-actions': !!slots.actions
  21665. }, props.class],
  21666. "style": props.style
  21667. }), {
  21668. default: () => [!props.hideHeader && vue.createVNode("div", {
  21669. "key": "header",
  21670. "class": [backgroundColorClasses.value],
  21671. "style": [backgroundColorStyles.value]
  21672. }, [hasTitle && vue.createVNode(VPickerTitle, {
  21673. "key": "picker-title"
  21674. }, {
  21675. default: () => [slots.title?.() ?? props.title]
  21676. }), slots.header && vue.createVNode("div", {
  21677. "class": "v-picker__header"
  21678. }, [slots.header()])]), vue.createVNode("div", {
  21679. "class": "v-picker__body"
  21680. }, [slots.default?.()]), slots.actions && vue.createVNode(VDefaultsProvider, {
  21681. "defaults": {
  21682. VBtn: {
  21683. slim: true,
  21684. variant: 'text'
  21685. }
  21686. }
  21687. }, {
  21688. default: () => [vue.createVNode("div", {
  21689. "class": "v-picker__actions"
  21690. }, [slots.actions()])]
  21691. })]
  21692. });
  21693. });
  21694. return {};
  21695. }
  21696. });
  21697. // Types
  21698. // Types
  21699. const makeVDatePickerProps = propsFactory({
  21700. // TODO: implement in v3.5
  21701. // calendarIcon: {
  21702. // type: String,
  21703. // default: '$calendar',
  21704. // },
  21705. // keyboardIcon: {
  21706. // type: String,
  21707. // default: '$edit',
  21708. // },
  21709. // inputMode: {
  21710. // type: String as PropType<'calendar' | 'keyboard'>,
  21711. // default: 'calendar',
  21712. // },
  21713. // inputText: {
  21714. // type: String,
  21715. // default: '$vuetify.datePicker.input.placeholder',
  21716. // },
  21717. // inputPlaceholder: {
  21718. // type: String,
  21719. // default: 'dd/mm/yyyy',
  21720. // },
  21721. header: {
  21722. type: String,
  21723. default: '$vuetify.datePicker.header'
  21724. },
  21725. ...makeVDatePickerControlsProps(),
  21726. ...makeVDatePickerMonthProps({
  21727. weeksInMonth: 'static'
  21728. }),
  21729. ...omit(makeVDatePickerMonthsProps(), ['modelValue']),
  21730. ...omit(makeVDatePickerYearsProps(), ['modelValue']),
  21731. ...makeVPickerProps({
  21732. title: '$vuetify.datePicker.title'
  21733. }),
  21734. modelValue: null
  21735. }, 'VDatePicker');
  21736. const VDatePicker = genericComponent()({
  21737. name: 'VDatePicker',
  21738. props: makeVDatePickerProps(),
  21739. emits: {
  21740. 'update:modelValue': date => true,
  21741. 'update:month': date => true,
  21742. 'update:year': date => true,
  21743. // 'update:inputMode': (date: any) => true,
  21744. 'update:viewMode': date => true
  21745. },
  21746. setup(props, _ref) {
  21747. let {
  21748. emit,
  21749. slots
  21750. } = _ref;
  21751. const adapter = useDate();
  21752. const {
  21753. t
  21754. } = useLocale();
  21755. const model = useProxiedModel(props, 'modelValue', undefined, v => wrapInArray(v), v => props.multiple ? v : v[0]);
  21756. const viewMode = useProxiedModel(props, 'viewMode');
  21757. // const inputMode = useProxiedModel(props, 'inputMode')
  21758. const internal = vue.computed(() => {
  21759. const value = adapter.date(model.value?.[0]);
  21760. return value && adapter.isValid(value) ? value : adapter.date();
  21761. });
  21762. const month = vue.ref(Number(props.month ?? adapter.getMonth(adapter.startOfMonth(internal.value))));
  21763. const year = vue.ref(Number(props.year ?? adapter.getYear(adapter.startOfYear(adapter.setMonth(internal.value, month.value)))));
  21764. const isReversing = vue.shallowRef(false);
  21765. const header = vue.computed(() => {
  21766. if (props.multiple && model.value.length > 1) {
  21767. return t('$vuetify.datePicker.itemsSelected', model.value.length);
  21768. }
  21769. return model.value[0] && adapter.isValid(model.value[0]) ? adapter.format(adapter.date(model.value[0]), 'normalDateWithWeekday') : t(props.header);
  21770. });
  21771. const text = vue.computed(() => {
  21772. let date = adapter.date();
  21773. date = adapter.setDate(date, 1);
  21774. date = adapter.setMonth(date, month.value);
  21775. date = adapter.setYear(date, year.value);
  21776. return adapter.format(date, 'monthAndYear');
  21777. });
  21778. // const headerIcon = computed(() => props.inputMode === 'calendar' ? props.keyboardIcon : props.calendarIcon)
  21779. const headerTransition = vue.computed(() => `date-picker-header${isReversing.value ? '-reverse' : ''}-transition`);
  21780. const minDate = vue.computed(() => {
  21781. const date = adapter.date(props.min);
  21782. return props.min && adapter.isValid(date) ? date : null;
  21783. });
  21784. const maxDate = vue.computed(() => {
  21785. const date = adapter.date(props.max);
  21786. return props.max && adapter.isValid(date) ? date : null;
  21787. });
  21788. const disabled = vue.computed(() => {
  21789. if (props.disabled) return true;
  21790. const targets = [];
  21791. if (viewMode.value !== 'month') {
  21792. targets.push(...['prev', 'next']);
  21793. } else {
  21794. let _date = adapter.date();
  21795. _date = adapter.setYear(_date, year.value);
  21796. _date = adapter.setMonth(_date, month.value);
  21797. if (minDate.value) {
  21798. const date = adapter.addDays(adapter.startOfMonth(_date), -1);
  21799. adapter.isAfter(minDate.value, date) && targets.push('prev');
  21800. }
  21801. if (maxDate.value) {
  21802. const date = adapter.addDays(adapter.endOfMonth(_date), 1);
  21803. adapter.isAfter(date, maxDate.value) && targets.push('next');
  21804. }
  21805. }
  21806. return targets;
  21807. });
  21808. // function onClickAppend () {
  21809. // inputMode.value = inputMode.value === 'calendar' ? 'keyboard' : 'calendar'
  21810. // }
  21811. function onClickNext() {
  21812. if (month.value < 11) {
  21813. month.value++;
  21814. } else {
  21815. year.value++;
  21816. month.value = 0;
  21817. onUpdateYear(year.value);
  21818. }
  21819. onUpdateMonth(month.value);
  21820. }
  21821. function onClickPrev() {
  21822. if (month.value > 0) {
  21823. month.value--;
  21824. } else {
  21825. year.value--;
  21826. month.value = 11;
  21827. onUpdateYear(year.value);
  21828. }
  21829. onUpdateMonth(month.value);
  21830. }
  21831. function onClickDate() {
  21832. viewMode.value = 'month';
  21833. }
  21834. function onClickMonth() {
  21835. viewMode.value = viewMode.value === 'months' ? 'month' : 'months';
  21836. }
  21837. function onClickYear() {
  21838. viewMode.value = viewMode.value === 'year' ? 'month' : 'year';
  21839. }
  21840. function onUpdateMonth(value) {
  21841. if (viewMode.value === 'months') onClickMonth();
  21842. emit('update:month', value);
  21843. }
  21844. function onUpdateYear(value) {
  21845. if (viewMode.value === 'year') onClickYear();
  21846. emit('update:year', value);
  21847. }
  21848. vue.watch(model, (val, oldVal) => {
  21849. const arrBefore = wrapInArray(oldVal);
  21850. const arrAfter = wrapInArray(val);
  21851. if (!arrAfter.length) return;
  21852. const before = adapter.date(arrBefore[arrBefore.length - 1]);
  21853. const after = adapter.date(arrAfter[arrAfter.length - 1]);
  21854. const newMonth = adapter.getMonth(after);
  21855. const newYear = adapter.getYear(after);
  21856. if (newMonth !== month.value) {
  21857. month.value = newMonth;
  21858. onUpdateMonth(month.value);
  21859. }
  21860. if (newYear !== year.value) {
  21861. year.value = newYear;
  21862. onUpdateYear(year.value);
  21863. }
  21864. isReversing.value = adapter.isBefore(before, after);
  21865. });
  21866. useRender(() => {
  21867. const pickerProps = VPicker.filterProps(props);
  21868. const datePickerControlsProps = VDatePickerControls.filterProps(props);
  21869. const datePickerHeaderProps = VDatePickerHeader.filterProps(props);
  21870. const datePickerMonthProps = VDatePickerMonth.filterProps(props);
  21871. const datePickerMonthsProps = omit(VDatePickerMonths.filterProps(props), ['modelValue']);
  21872. const datePickerYearsProps = omit(VDatePickerYears.filterProps(props), ['modelValue']);
  21873. const headerProps = {
  21874. header: header.value,
  21875. transition: headerTransition.value
  21876. };
  21877. return vue.createVNode(VPicker, vue.mergeProps(pickerProps, {
  21878. "class": ['v-date-picker', `v-date-picker--${viewMode.value}`, {
  21879. 'v-date-picker--show-week': props.showWeek
  21880. }, props.class],
  21881. "style": props.style
  21882. }), {
  21883. title: () => slots.title?.() ?? vue.createVNode("div", {
  21884. "class": "v-date-picker__title"
  21885. }, [t(props.title)]),
  21886. header: () => slots.header ? vue.createVNode(VDefaultsProvider, {
  21887. "defaults": {
  21888. VDatePickerHeader: {
  21889. ...headerProps
  21890. }
  21891. }
  21892. }, {
  21893. default: () => [slots.header?.(headerProps)]
  21894. }) : vue.createVNode(VDatePickerHeader, vue.mergeProps({
  21895. "key": "header"
  21896. }, datePickerHeaderProps, headerProps, {
  21897. "onClick": viewMode.value !== 'month' ? onClickDate : undefined
  21898. }), {
  21899. ...slots,
  21900. default: undefined
  21901. }),
  21902. default: () => vue.createVNode(vue.Fragment, null, [vue.createVNode(VDatePickerControls, vue.mergeProps(datePickerControlsProps, {
  21903. "disabled": disabled.value,
  21904. "text": text.value,
  21905. "onClick:next": onClickNext,
  21906. "onClick:prev": onClickPrev,
  21907. "onClick:month": onClickMonth,
  21908. "onClick:year": onClickYear
  21909. }), null), vue.createVNode(VFadeTransition, {
  21910. "hideOnLeave": true
  21911. }, {
  21912. default: () => [viewMode.value === 'months' ? vue.createVNode(VDatePickerMonths, vue.mergeProps({
  21913. "key": "date-picker-months"
  21914. }, datePickerMonthsProps, {
  21915. "modelValue": month.value,
  21916. "onUpdate:modelValue": [$event => month.value = $event, onUpdateMonth],
  21917. "min": minDate.value,
  21918. "max": maxDate.value,
  21919. "year": year.value
  21920. }), null) : viewMode.value === 'year' ? vue.createVNode(VDatePickerYears, vue.mergeProps({
  21921. "key": "date-picker-years"
  21922. }, datePickerYearsProps, {
  21923. "modelValue": year.value,
  21924. "onUpdate:modelValue": [$event => year.value = $event, onUpdateYear],
  21925. "min": minDate.value,
  21926. "max": maxDate.value
  21927. }), null) : vue.createVNode(VDatePickerMonth, vue.mergeProps({
  21928. "key": "date-picker-month"
  21929. }, datePickerMonthProps, {
  21930. "modelValue": model.value,
  21931. "onUpdate:modelValue": $event => model.value = $event,
  21932. "month": month.value,
  21933. "onUpdate:month": [$event => month.value = $event, onUpdateMonth],
  21934. "year": year.value,
  21935. "onUpdate:year": [$event => year.value = $event, onUpdateYear],
  21936. "min": minDate.value,
  21937. "max": maxDate.value
  21938. }), null)]
  21939. })]),
  21940. actions: slots.actions
  21941. });
  21942. });
  21943. return {};
  21944. }
  21945. });
  21946. // Types
  21947. // Types
  21948. const makeVEmptyStateProps = propsFactory({
  21949. actionText: String,
  21950. bgColor: String,
  21951. color: String,
  21952. icon: IconValue,
  21953. image: String,
  21954. justify: {
  21955. type: String,
  21956. default: 'center'
  21957. },
  21958. headline: String,
  21959. title: String,
  21960. text: String,
  21961. textWidth: {
  21962. type: [Number, String],
  21963. default: 500
  21964. },
  21965. href: String,
  21966. to: String,
  21967. ...makeComponentProps(),
  21968. ...makeDimensionProps(),
  21969. ...makeSizeProps({
  21970. size: undefined
  21971. }),
  21972. ...makeThemeProps()
  21973. }, 'VEmptyState');
  21974. const VEmptyState = genericComponent()({
  21975. name: 'VEmptyState',
  21976. props: makeVEmptyStateProps(),
  21977. emits: {
  21978. 'click:action': e => true
  21979. },
  21980. setup(props, _ref) {
  21981. let {
  21982. emit,
  21983. slots
  21984. } = _ref;
  21985. const {
  21986. themeClasses
  21987. } = provideTheme(props);
  21988. const {
  21989. backgroundColorClasses,
  21990. backgroundColorStyles
  21991. } = useBackgroundColor(vue.toRef(props, 'bgColor'));
  21992. const {
  21993. dimensionStyles
  21994. } = useDimension(props);
  21995. const {
  21996. displayClasses
  21997. } = useDisplay();
  21998. function onClickAction(e) {
  21999. emit('click:action', e);
  22000. }
  22001. useRender(() => {
  22002. const hasActions = !!(slots.actions || props.actionText);
  22003. const hasHeadline = !!(slots.headline || props.headline);
  22004. const hasTitle = !!(slots.title || props.title);
  22005. const hasText = !!(slots.text || props.text);
  22006. const hasMedia = !!(slots.media || props.image || props.icon);
  22007. const size = props.size || (props.image ? 200 : 96);
  22008. return vue.createVNode("div", {
  22009. "class": ['v-empty-state', {
  22010. [`v-empty-state--${props.justify}`]: true
  22011. }, themeClasses.value, backgroundColorClasses.value, displayClasses.value, props.class],
  22012. "style": [backgroundColorStyles.value, dimensionStyles.value, props.style]
  22013. }, [hasMedia && vue.createVNode("div", {
  22014. "key": "media",
  22015. "class": "v-empty-state__media"
  22016. }, [!slots.media ? vue.createVNode(vue.Fragment, null, [props.image ? vue.createVNode(VImg, {
  22017. "key": "image",
  22018. "src": props.image,
  22019. "height": size
  22020. }, null) : props.icon ? vue.createVNode(VIcon, {
  22021. "key": "icon",
  22022. "color": props.color,
  22023. "size": size,
  22024. "icon": props.icon
  22025. }, null) : undefined]) : vue.createVNode(VDefaultsProvider, {
  22026. "key": "media-defaults",
  22027. "defaults": {
  22028. VImg: {
  22029. src: props.image,
  22030. height: size
  22031. },
  22032. VIcon: {
  22033. size,
  22034. icon: props.icon
  22035. }
  22036. }
  22037. }, {
  22038. default: () => [slots.media()]
  22039. })]), hasHeadline && vue.createVNode("div", {
  22040. "key": "headline",
  22041. "class": "v-empty-state__headline"
  22042. }, [slots.headline?.() ?? props.headline]), hasTitle && vue.createVNode("div", {
  22043. "key": "title",
  22044. "class": "v-empty-state__title"
  22045. }, [slots.title?.() ?? props.title]), hasText && vue.createVNode("div", {
  22046. "key": "text",
  22047. "class": "v-empty-state__text",
  22048. "style": {
  22049. maxWidth: convertToUnit(props.textWidth)
  22050. }
  22051. }, [slots.text?.() ?? props.text]), slots.default && vue.createVNode("div", {
  22052. "key": "content",
  22053. "class": "v-empty-state__content"
  22054. }, [slots.default()]), hasActions && vue.createVNode("div", {
  22055. "key": "actions",
  22056. "class": "v-empty-state__actions"
  22057. }, [vue.createVNode(VDefaultsProvider, {
  22058. "defaults": {
  22059. VBtn: {
  22060. class: 'v-empty-state__action-btn',
  22061. color: props.color ?? 'surface-variant',
  22062. text: props.actionText
  22063. }
  22064. }
  22065. }, {
  22066. default: () => [slots.actions?.({
  22067. props: {
  22068. onClick: onClickAction
  22069. }
  22070. }) ?? vue.createVNode(VBtn, {
  22071. "onClick": onClickAction
  22072. }, null)]
  22073. })])]);
  22074. });
  22075. return {};
  22076. }
  22077. });
  22078. // Types
  22079. const VExpansionPanelSymbol = Symbol.for('vuetify:v-expansion-panel');
  22080. const makeVExpansionPanelTextProps = propsFactory({
  22081. ...makeComponentProps(),
  22082. ...makeLazyProps()
  22083. }, 'VExpansionPanelText');
  22084. const VExpansionPanelText = genericComponent()({
  22085. name: 'VExpansionPanelText',
  22086. props: makeVExpansionPanelTextProps(),
  22087. setup(props, _ref) {
  22088. let {
  22089. slots
  22090. } = _ref;
  22091. const expansionPanel = vue.inject(VExpansionPanelSymbol);
  22092. if (!expansionPanel) throw new Error('[Vuetify] v-expansion-panel-text needs to be placed inside v-expansion-panel');
  22093. const {
  22094. hasContent,
  22095. onAfterLeave
  22096. } = useLazy(props, expansionPanel.isSelected);
  22097. useRender(() => vue.createVNode(VExpandTransition, {
  22098. "onAfterLeave": onAfterLeave
  22099. }, {
  22100. default: () => [vue.withDirectives(vue.createVNode("div", {
  22101. "class": ['v-expansion-panel-text', props.class],
  22102. "style": props.style
  22103. }, [slots.default && hasContent.value && vue.createVNode("div", {
  22104. "class": "v-expansion-panel-text__wrapper"
  22105. }, [slots.default?.()])]), [[vue.vShow, expansionPanel.isSelected.value]])]
  22106. }));
  22107. return {};
  22108. }
  22109. });
  22110. // Types
  22111. const makeVExpansionPanelTitleProps = propsFactory({
  22112. color: String,
  22113. expandIcon: {
  22114. type: IconValue,
  22115. default: '$expand'
  22116. },
  22117. collapseIcon: {
  22118. type: IconValue,
  22119. default: '$collapse'
  22120. },
  22121. hideActions: Boolean,
  22122. focusable: Boolean,
  22123. static: Boolean,
  22124. ripple: {
  22125. type: [Boolean, Object],
  22126. default: false
  22127. },
  22128. readonly: Boolean,
  22129. ...makeComponentProps(),
  22130. ...makeDimensionProps()
  22131. }, 'VExpansionPanelTitle');
  22132. const VExpansionPanelTitle = genericComponent()({
  22133. name: 'VExpansionPanelTitle',
  22134. directives: {
  22135. Ripple
  22136. },
  22137. props: makeVExpansionPanelTitleProps(),
  22138. setup(props, _ref) {
  22139. let {
  22140. slots
  22141. } = _ref;
  22142. const expansionPanel = vue.inject(VExpansionPanelSymbol);
  22143. if (!expansionPanel) throw new Error('[Vuetify] v-expansion-panel-title needs to be placed inside v-expansion-panel');
  22144. const {
  22145. backgroundColorClasses,
  22146. backgroundColorStyles
  22147. } = useBackgroundColor(props, 'color');
  22148. const {
  22149. dimensionStyles
  22150. } = useDimension(props);
  22151. const slotProps = vue.computed(() => ({
  22152. collapseIcon: props.collapseIcon,
  22153. disabled: expansionPanel.disabled.value,
  22154. expanded: expansionPanel.isSelected.value,
  22155. expandIcon: props.expandIcon,
  22156. readonly: props.readonly
  22157. }));
  22158. const icon = vue.computed(() => expansionPanel.isSelected.value ? props.collapseIcon : props.expandIcon);
  22159. useRender(() => vue.withDirectives(vue.createVNode("button", {
  22160. "class": ['v-expansion-panel-title', {
  22161. 'v-expansion-panel-title--active': expansionPanel.isSelected.value,
  22162. 'v-expansion-panel-title--focusable': props.focusable,
  22163. 'v-expansion-panel-title--static': props.static
  22164. }, backgroundColorClasses.value, props.class],
  22165. "style": [backgroundColorStyles.value, dimensionStyles.value, props.style],
  22166. "type": "button",
  22167. "tabindex": expansionPanel.disabled.value ? -1 : undefined,
  22168. "disabled": expansionPanel.disabled.value,
  22169. "aria-expanded": expansionPanel.isSelected.value,
  22170. "onClick": !props.readonly ? expansionPanel.toggle : undefined
  22171. }, [vue.createVNode("span", {
  22172. "class": "v-expansion-panel-title__overlay"
  22173. }, null), slots.default?.(slotProps.value), !props.hideActions && vue.createVNode(VDefaultsProvider, {
  22174. "defaults": {
  22175. VIcon: {
  22176. icon: icon.value
  22177. }
  22178. }
  22179. }, {
  22180. default: () => [vue.createVNode("span", {
  22181. "class": "v-expansion-panel-title__icon"
  22182. }, [slots.actions?.(slotProps.value) ?? vue.createVNode(VIcon, null, null)])]
  22183. })]), [[vue.resolveDirective("ripple"), props.ripple]]));
  22184. return {};
  22185. }
  22186. });
  22187. const makeVExpansionPanelProps = propsFactory({
  22188. title: String,
  22189. text: String,
  22190. bgColor: String,
  22191. ...makeElevationProps(),
  22192. ...makeGroupItemProps(),
  22193. ...makeRoundedProps(),
  22194. ...makeTagProps(),
  22195. ...makeVExpansionPanelTitleProps(),
  22196. ...makeVExpansionPanelTextProps()
  22197. }, 'VExpansionPanel');
  22198. const VExpansionPanel = genericComponent()({
  22199. name: 'VExpansionPanel',
  22200. props: makeVExpansionPanelProps(),
  22201. emits: {
  22202. 'group:selected': val => true
  22203. },
  22204. setup(props, _ref) {
  22205. let {
  22206. slots
  22207. } = _ref;
  22208. const groupItem = useGroupItem(props, VExpansionPanelSymbol);
  22209. const {
  22210. backgroundColorClasses,
  22211. backgroundColorStyles
  22212. } = useBackgroundColor(props, 'bgColor');
  22213. const {
  22214. elevationClasses
  22215. } = useElevation(props);
  22216. const {
  22217. roundedClasses
  22218. } = useRounded(props);
  22219. const isDisabled = vue.computed(() => groupItem?.disabled.value || props.disabled);
  22220. const selectedIndices = vue.computed(() => groupItem.group.items.value.reduce((arr, item, index) => {
  22221. if (groupItem.group.selected.value.includes(item.id)) arr.push(index);
  22222. return arr;
  22223. }, []));
  22224. const isBeforeSelected = vue.computed(() => {
  22225. const index = groupItem.group.items.value.findIndex(item => item.id === groupItem.id);
  22226. return !groupItem.isSelected.value && selectedIndices.value.some(selectedIndex => selectedIndex - index === 1);
  22227. });
  22228. const isAfterSelected = vue.computed(() => {
  22229. const index = groupItem.group.items.value.findIndex(item => item.id === groupItem.id);
  22230. return !groupItem.isSelected.value && selectedIndices.value.some(selectedIndex => selectedIndex - index === -1);
  22231. });
  22232. vue.provide(VExpansionPanelSymbol, groupItem);
  22233. useRender(() => {
  22234. const hasText = !!(slots.text || props.text);
  22235. const hasTitle = !!(slots.title || props.title);
  22236. const expansionPanelTitleProps = VExpansionPanelTitle.filterProps(props);
  22237. const expansionPanelTextProps = VExpansionPanelText.filterProps(props);
  22238. return vue.createVNode(props.tag, {
  22239. "class": ['v-expansion-panel', {
  22240. 'v-expansion-panel--active': groupItem.isSelected.value,
  22241. 'v-expansion-panel--before-active': isBeforeSelected.value,
  22242. 'v-expansion-panel--after-active': isAfterSelected.value,
  22243. 'v-expansion-panel--disabled': isDisabled.value
  22244. }, roundedClasses.value, backgroundColorClasses.value, props.class],
  22245. "style": [backgroundColorStyles.value, props.style]
  22246. }, {
  22247. default: () => [vue.createVNode("div", {
  22248. "class": ['v-expansion-panel__shadow', ...elevationClasses.value]
  22249. }, null), vue.createVNode(VDefaultsProvider, {
  22250. "defaults": {
  22251. VExpansionPanelTitle: {
  22252. ...expansionPanelTitleProps
  22253. },
  22254. VExpansionPanelText: {
  22255. ...expansionPanelTextProps
  22256. }
  22257. }
  22258. }, {
  22259. default: () => [hasTitle && vue.createVNode(VExpansionPanelTitle, {
  22260. "key": "title"
  22261. }, {
  22262. default: () => [slots.title ? slots.title() : props.title]
  22263. }), hasText && vue.createVNode(VExpansionPanelText, {
  22264. "key": "text"
  22265. }, {
  22266. default: () => [slots.text ? slots.text() : props.text]
  22267. }), slots.default?.()]
  22268. })]
  22269. });
  22270. });
  22271. return {
  22272. groupItem
  22273. };
  22274. }
  22275. });
  22276. // Types
  22277. const allowedVariants = ['default', 'accordion', 'inset', 'popout'];
  22278. const makeVExpansionPanelsProps = propsFactory({
  22279. flat: Boolean,
  22280. ...makeGroupProps(),
  22281. ...pick(makeVExpansionPanelProps(), ['bgColor', 'collapseIcon', 'color', 'eager', 'elevation', 'expandIcon', 'focusable', 'hideActions', 'readonly', 'ripple', 'rounded', 'tile', 'static']),
  22282. ...makeThemeProps(),
  22283. ...makeComponentProps(),
  22284. ...makeTagProps(),
  22285. variant: {
  22286. type: String,
  22287. default: 'default',
  22288. validator: v => allowedVariants.includes(v)
  22289. }
  22290. }, 'VExpansionPanels');
  22291. const VExpansionPanels = genericComponent()({
  22292. name: 'VExpansionPanels',
  22293. props: makeVExpansionPanelsProps(),
  22294. emits: {
  22295. 'update:modelValue': val => true
  22296. },
  22297. setup(props, _ref) {
  22298. let {
  22299. slots
  22300. } = _ref;
  22301. const {
  22302. next,
  22303. prev
  22304. } = useGroup(props, VExpansionPanelSymbol);
  22305. const {
  22306. themeClasses
  22307. } = provideTheme(props);
  22308. const variantClass = vue.computed(() => props.variant && `v-expansion-panels--variant-${props.variant}`);
  22309. provideDefaults({
  22310. VExpansionPanel: {
  22311. bgColor: vue.toRef(props, 'bgColor'),
  22312. collapseIcon: vue.toRef(props, 'collapseIcon'),
  22313. color: vue.toRef(props, 'color'),
  22314. eager: vue.toRef(props, 'eager'),
  22315. elevation: vue.toRef(props, 'elevation'),
  22316. expandIcon: vue.toRef(props, 'expandIcon'),
  22317. focusable: vue.toRef(props, 'focusable'),
  22318. hideActions: vue.toRef(props, 'hideActions'),
  22319. readonly: vue.toRef(props, 'readonly'),
  22320. ripple: vue.toRef(props, 'ripple'),
  22321. rounded: vue.toRef(props, 'rounded'),
  22322. static: vue.toRef(props, 'static')
  22323. }
  22324. });
  22325. useRender(() => vue.createVNode(props.tag, {
  22326. "class": ['v-expansion-panels', {
  22327. 'v-expansion-panels--flat': props.flat,
  22328. 'v-expansion-panels--tile': props.tile
  22329. }, themeClasses.value, variantClass.value, props.class],
  22330. "style": props.style
  22331. }, {
  22332. default: () => [slots.default?.({
  22333. prev,
  22334. next
  22335. })]
  22336. }));
  22337. return {
  22338. next,
  22339. prev
  22340. };
  22341. }
  22342. });
  22343. // Types
  22344. const makeVFabProps = propsFactory({
  22345. app: Boolean,
  22346. appear: Boolean,
  22347. extended: Boolean,
  22348. layout: Boolean,
  22349. offset: Boolean,
  22350. modelValue: {
  22351. type: Boolean,
  22352. default: true
  22353. },
  22354. ...omit(makeVBtnProps({
  22355. active: true
  22356. }), ['location']),
  22357. ...makeLayoutItemProps(),
  22358. ...makeLocationProps(),
  22359. ...makeTransitionProps({
  22360. transition: 'fab-transition'
  22361. })
  22362. }, 'VFab');
  22363. const VFab = genericComponent()({
  22364. name: 'VFab',
  22365. props: makeVFabProps(),
  22366. emits: {
  22367. 'update:modelValue': value => true
  22368. },
  22369. setup(props, _ref) {
  22370. let {
  22371. slots
  22372. } = _ref;
  22373. const model = useProxiedModel(props, 'modelValue');
  22374. const height = vue.shallowRef(56);
  22375. const layoutItemStyles = vue.ref();
  22376. const {
  22377. resizeRef
  22378. } = useResizeObserver(entries => {
  22379. if (!entries.length) return;
  22380. height.value = entries[0].target.clientHeight;
  22381. });
  22382. const hasPosition = vue.computed(() => props.app || props.absolute);
  22383. const position = vue.computed(() => {
  22384. if (!hasPosition.value) return false;
  22385. return props.location?.split(' ').shift() ?? 'bottom';
  22386. });
  22387. const orientation = vue.computed(() => {
  22388. if (!hasPosition.value) return false;
  22389. return props.location?.split(' ')[1] ?? 'end';
  22390. });
  22391. useToggleScope(() => props.app, () => {
  22392. const layout = useLayoutItem({
  22393. id: props.name,
  22394. order: vue.computed(() => parseInt(props.order, 10)),
  22395. position,
  22396. layoutSize: vue.computed(() => props.layout ? height.value + 24 : 0),
  22397. elementSize: vue.computed(() => height.value + 24),
  22398. active: vue.computed(() => props.app && model.value),
  22399. absolute: vue.toRef(props, 'absolute')
  22400. });
  22401. vue.watchEffect(() => {
  22402. layoutItemStyles.value = layout.layoutItemStyles.value;
  22403. });
  22404. });
  22405. const vFabRef = vue.ref();
  22406. useRender(() => {
  22407. const btnProps = VBtn.filterProps(props);
  22408. return vue.createVNode("div", {
  22409. "ref": vFabRef,
  22410. "class": ['v-fab', {
  22411. 'v-fab--absolute': props.absolute,
  22412. 'v-fab--app': !!props.app,
  22413. 'v-fab--extended': props.extended,
  22414. 'v-fab--offset': props.offset,
  22415. [`v-fab--${position.value}`]: hasPosition.value,
  22416. [`v-fab--${orientation.value}`]: hasPosition.value
  22417. }, props.class],
  22418. "style": [props.app ? {
  22419. ...layoutItemStyles.value
  22420. } : {
  22421. height: 'inherit',
  22422. width: undefined
  22423. }, props.style]
  22424. }, [vue.createVNode("div", {
  22425. "class": "v-fab__container"
  22426. }, [vue.createVNode(MaybeTransition, {
  22427. "appear": props.appear,
  22428. "transition": props.transition
  22429. }, {
  22430. default: () => [vue.withDirectives(vue.createVNode(VBtn, vue.mergeProps({
  22431. "ref": resizeRef
  22432. }, btnProps, {
  22433. "active": undefined,
  22434. "location": undefined
  22435. }), slots), [[vue.vShow, props.active]])]
  22436. })])]);
  22437. });
  22438. return {};
  22439. }
  22440. });
  22441. // Types
  22442. const makeVFileInputProps = propsFactory({
  22443. chips: Boolean,
  22444. counter: Boolean,
  22445. counterSizeString: {
  22446. type: String,
  22447. default: '$vuetify.fileInput.counterSize'
  22448. },
  22449. counterString: {
  22450. type: String,
  22451. default: '$vuetify.fileInput.counter'
  22452. },
  22453. hideInput: Boolean,
  22454. multiple: Boolean,
  22455. showSize: {
  22456. type: [Boolean, Number, String],
  22457. default: false,
  22458. validator: v => {
  22459. return typeof v === 'boolean' || [1000, 1024].includes(Number(v));
  22460. }
  22461. },
  22462. ...makeVInputProps({
  22463. prependIcon: '$file'
  22464. }),
  22465. modelValue: {
  22466. type: [Array, Object],
  22467. default: props => props.multiple ? [] : null,
  22468. validator: val => {
  22469. return wrapInArray(val).every(v => v != null && typeof v === 'object');
  22470. }
  22471. },
  22472. ...makeVFieldProps({
  22473. clearable: true
  22474. })
  22475. }, 'VFileInput');
  22476. const VFileInput = genericComponent()({
  22477. name: 'VFileInput',
  22478. inheritAttrs: false,
  22479. props: makeVFileInputProps(),
  22480. emits: {
  22481. 'click:control': e => true,
  22482. 'mousedown:control': e => true,
  22483. 'update:focused': focused => true,
  22484. 'update:modelValue': files => true
  22485. },
  22486. setup(props, _ref) {
  22487. let {
  22488. attrs,
  22489. emit,
  22490. slots
  22491. } = _ref;
  22492. const {
  22493. t
  22494. } = useLocale();
  22495. const model = useProxiedModel(props, 'modelValue', props.modelValue, val => wrapInArray(val), val => !props.multiple && Array.isArray(val) ? val[0] : val);
  22496. const {
  22497. isFocused,
  22498. focus,
  22499. blur
  22500. } = useFocus(props);
  22501. const base = vue.computed(() => typeof props.showSize !== 'boolean' ? props.showSize : undefined);
  22502. const totalBytes = vue.computed(() => (model.value ?? []).reduce((bytes, _ref2) => {
  22503. let {
  22504. size = 0
  22505. } = _ref2;
  22506. return bytes + size;
  22507. }, 0));
  22508. const totalBytesReadable = vue.computed(() => humanReadableFileSize(totalBytes.value, base.value));
  22509. const fileNames = vue.computed(() => (model.value ?? []).map(file => {
  22510. const {
  22511. name = '',
  22512. size = 0
  22513. } = file;
  22514. return !props.showSize ? name : `${name} (${humanReadableFileSize(size, base.value)})`;
  22515. }));
  22516. const counterValue = vue.computed(() => {
  22517. const fileCount = model.value?.length ?? 0;
  22518. if (props.showSize) return t(props.counterSizeString, fileCount, totalBytesReadable.value);else return t(props.counterString, fileCount);
  22519. });
  22520. const vInputRef = vue.ref();
  22521. const vFieldRef = vue.ref();
  22522. const inputRef = vue.ref();
  22523. const isActive = vue.computed(() => isFocused.value || props.active);
  22524. const isPlainOrUnderlined = vue.computed(() => ['plain', 'underlined'].includes(props.variant));
  22525. function onFocus() {
  22526. if (inputRef.value !== document.activeElement) {
  22527. inputRef.value?.focus();
  22528. }
  22529. if (!isFocused.value) focus();
  22530. }
  22531. function onClickPrepend(e) {
  22532. inputRef.value?.click();
  22533. }
  22534. function onControlMousedown(e) {
  22535. emit('mousedown:control', e);
  22536. }
  22537. function onControlClick(e) {
  22538. inputRef.value?.click();
  22539. emit('click:control', e);
  22540. }
  22541. function onClear(e) {
  22542. e.stopPropagation();
  22543. onFocus();
  22544. vue.nextTick(() => {
  22545. model.value = [];
  22546. callEvent(props['onClick:clear'], e);
  22547. });
  22548. }
  22549. vue.watch(model, newValue => {
  22550. const hasModelReset = !Array.isArray(newValue) || !newValue.length;
  22551. if (hasModelReset && inputRef.value) {
  22552. inputRef.value.value = '';
  22553. }
  22554. });
  22555. useRender(() => {
  22556. const hasCounter = !!(slots.counter || props.counter);
  22557. const hasDetails = !!(hasCounter || slots.details);
  22558. const [rootAttrs, inputAttrs] = filterInputAttrs(attrs);
  22559. const {
  22560. modelValue: _,
  22561. ...inputProps
  22562. } = VInput.filterProps(props);
  22563. const fieldProps = filterFieldProps(props);
  22564. return vue.createVNode(VInput, vue.mergeProps({
  22565. "ref": vInputRef,
  22566. "modelValue": model.value,
  22567. "onUpdate:modelValue": $event => model.value = $event,
  22568. "class": ['v-file-input', {
  22569. 'v-file-input--chips': !!props.chips,
  22570. 'v-file-input--hide': props.hideInput,
  22571. 'v-input--plain-underlined': isPlainOrUnderlined.value
  22572. }, props.class],
  22573. "style": props.style,
  22574. "onClick:prepend": onClickPrepend
  22575. }, rootAttrs, inputProps, {
  22576. "centerAffix": !isPlainOrUnderlined.value,
  22577. "focused": isFocused.value
  22578. }), {
  22579. ...slots,
  22580. default: _ref3 => {
  22581. let {
  22582. id,
  22583. isDisabled,
  22584. isDirty,
  22585. isReadonly,
  22586. isValid
  22587. } = _ref3;
  22588. return vue.createVNode(VField, vue.mergeProps({
  22589. "ref": vFieldRef,
  22590. "prepend-icon": props.prependIcon,
  22591. "onMousedown": onControlMousedown,
  22592. "onClick": onControlClick,
  22593. "onClick:clear": onClear,
  22594. "onClick:prependInner": props['onClick:prependInner'],
  22595. "onClick:appendInner": props['onClick:appendInner']
  22596. }, fieldProps, {
  22597. "id": id.value,
  22598. "active": isActive.value || isDirty.value,
  22599. "dirty": isDirty.value || props.dirty,
  22600. "disabled": isDisabled.value,
  22601. "focused": isFocused.value,
  22602. "error": isValid.value === false
  22603. }), {
  22604. ...slots,
  22605. default: _ref4 => {
  22606. let {
  22607. props: {
  22608. class: fieldClass,
  22609. ...slotProps
  22610. }
  22611. } = _ref4;
  22612. return vue.createVNode(vue.Fragment, null, [vue.createVNode("input", vue.mergeProps({
  22613. "ref": inputRef,
  22614. "type": "file",
  22615. "readonly": isReadonly.value,
  22616. "disabled": isDisabled.value,
  22617. "multiple": props.multiple,
  22618. "name": props.name,
  22619. "onClick": e => {
  22620. e.stopPropagation();
  22621. if (isReadonly.value) e.preventDefault();
  22622. onFocus();
  22623. },
  22624. "onChange": e => {
  22625. if (!e.target) return;
  22626. const target = e.target;
  22627. model.value = [...(target.files ?? [])];
  22628. },
  22629. "onFocus": onFocus,
  22630. "onBlur": blur
  22631. }, slotProps, inputAttrs), null), vue.createVNode("div", {
  22632. "class": fieldClass
  22633. }, [!!model.value?.length && !props.hideInput && (slots.selection ? slots.selection({
  22634. fileNames: fileNames.value,
  22635. totalBytes: totalBytes.value,
  22636. totalBytesReadable: totalBytesReadable.value
  22637. }) : props.chips ? fileNames.value.map(text => vue.createVNode(VChip, {
  22638. "key": text,
  22639. "size": "small",
  22640. "text": text
  22641. }, null)) : fileNames.value.join(', '))])]);
  22642. }
  22643. });
  22644. },
  22645. details: hasDetails ? slotProps => vue.createVNode(vue.Fragment, null, [slots.details?.(slotProps), hasCounter && vue.createVNode(vue.Fragment, null, [vue.createVNode("span", null, null), vue.createVNode(VCounter, {
  22646. "active": !!model.value?.length,
  22647. "value": counterValue.value,
  22648. "disabled": props.disabled
  22649. }, slots.counter)])]) : undefined
  22650. });
  22651. });
  22652. return forwardRefs({}, vInputRef, vFieldRef, inputRef);
  22653. }
  22654. });
  22655. const makeVFooterProps = propsFactory({
  22656. app: Boolean,
  22657. color: String,
  22658. height: {
  22659. type: [Number, String],
  22660. default: 'auto'
  22661. },
  22662. ...makeBorderProps(),
  22663. ...makeComponentProps(),
  22664. ...makeElevationProps(),
  22665. ...makeLayoutItemProps(),
  22666. ...makeRoundedProps(),
  22667. ...makeTagProps({
  22668. tag: 'footer'
  22669. }),
  22670. ...makeThemeProps()
  22671. }, 'VFooter');
  22672. const VFooter = genericComponent()({
  22673. name: 'VFooter',
  22674. props: makeVFooterProps(),
  22675. setup(props, _ref) {
  22676. let {
  22677. slots
  22678. } = _ref;
  22679. const layoutItemStyles = vue.ref();
  22680. const {
  22681. themeClasses
  22682. } = provideTheme(props);
  22683. const {
  22684. backgroundColorClasses,
  22685. backgroundColorStyles
  22686. } = useBackgroundColor(vue.toRef(props, 'color'));
  22687. const {
  22688. borderClasses
  22689. } = useBorder(props);
  22690. const {
  22691. elevationClasses
  22692. } = useElevation(props);
  22693. const {
  22694. roundedClasses
  22695. } = useRounded(props);
  22696. const autoHeight = vue.shallowRef(32);
  22697. const {
  22698. resizeRef
  22699. } = useResizeObserver(entries => {
  22700. if (!entries.length) return;
  22701. autoHeight.value = entries[0].target.clientHeight;
  22702. });
  22703. const height = vue.computed(() => props.height === 'auto' ? autoHeight.value : parseInt(props.height, 10));
  22704. useToggleScope(() => props.app, () => {
  22705. const layout = useLayoutItem({
  22706. id: props.name,
  22707. order: vue.computed(() => parseInt(props.order, 10)),
  22708. position: vue.computed(() => 'bottom'),
  22709. layoutSize: height,
  22710. elementSize: vue.computed(() => props.height === 'auto' ? undefined : height.value),
  22711. active: vue.computed(() => props.app),
  22712. absolute: vue.toRef(props, 'absolute')
  22713. });
  22714. vue.watchEffect(() => {
  22715. layoutItemStyles.value = layout.layoutItemStyles.value;
  22716. });
  22717. });
  22718. useRender(() => vue.createVNode(props.tag, {
  22719. "ref": resizeRef,
  22720. "class": ['v-footer', themeClasses.value, backgroundColorClasses.value, borderClasses.value, elevationClasses.value, roundedClasses.value, props.class],
  22721. "style": [backgroundColorStyles.value, props.app ? layoutItemStyles.value : {
  22722. height: convertToUnit(props.height)
  22723. }, props.style]
  22724. }, slots));
  22725. return {};
  22726. }
  22727. });
  22728. // Types
  22729. const makeVFormProps = propsFactory({
  22730. ...makeComponentProps(),
  22731. ...makeFormProps()
  22732. }, 'VForm');
  22733. const VForm = genericComponent()({
  22734. name: 'VForm',
  22735. props: makeVFormProps(),
  22736. emits: {
  22737. 'update:modelValue': val => true,
  22738. submit: e => true
  22739. },
  22740. setup(props, _ref) {
  22741. let {
  22742. slots,
  22743. emit
  22744. } = _ref;
  22745. const form = createForm(props);
  22746. const formRef = vue.ref();
  22747. function onReset(e) {
  22748. e.preventDefault();
  22749. form.reset();
  22750. }
  22751. function onSubmit(_e) {
  22752. const e = _e;
  22753. const ready = form.validate();
  22754. e.then = ready.then.bind(ready);
  22755. e.catch = ready.catch.bind(ready);
  22756. e.finally = ready.finally.bind(ready);
  22757. emit('submit', e);
  22758. if (!e.defaultPrevented) {
  22759. ready.then(_ref2 => {
  22760. let {
  22761. valid
  22762. } = _ref2;
  22763. if (valid) {
  22764. formRef.value?.submit();
  22765. }
  22766. });
  22767. }
  22768. e.preventDefault();
  22769. }
  22770. useRender(() => vue.createVNode("form", {
  22771. "ref": formRef,
  22772. "class": ['v-form', props.class],
  22773. "style": props.style,
  22774. "novalidate": true,
  22775. "onReset": onReset,
  22776. "onSubmit": onSubmit
  22777. }, [slots.default?.(form)]));
  22778. return forwardRefs(form, formRef);
  22779. }
  22780. });
  22781. // Composables
  22782. const makeVHoverProps = propsFactory({
  22783. disabled: Boolean,
  22784. modelValue: {
  22785. type: Boolean,
  22786. default: null
  22787. },
  22788. ...makeDelayProps()
  22789. }, 'VHover');
  22790. const VHover = genericComponent()({
  22791. name: 'VHover',
  22792. props: makeVHoverProps(),
  22793. emits: {
  22794. 'update:modelValue': value => true
  22795. },
  22796. setup(props, _ref) {
  22797. let {
  22798. slots
  22799. } = _ref;
  22800. const isHovering = useProxiedModel(props, 'modelValue');
  22801. const {
  22802. runOpenDelay,
  22803. runCloseDelay
  22804. } = useDelay(props, value => !props.disabled && (isHovering.value = value));
  22805. return () => slots.default?.({
  22806. isHovering: isHovering.value,
  22807. props: {
  22808. onMouseenter: runOpenDelay,
  22809. onMouseleave: runCloseDelay
  22810. }
  22811. });
  22812. }
  22813. });
  22814. // Types
  22815. const makeVInfiniteScrollProps = propsFactory({
  22816. color: String,
  22817. direction: {
  22818. type: String,
  22819. default: 'vertical',
  22820. validator: v => ['vertical', 'horizontal'].includes(v)
  22821. },
  22822. side: {
  22823. type: String,
  22824. default: 'end',
  22825. validator: v => ['start', 'end', 'both'].includes(v)
  22826. },
  22827. mode: {
  22828. type: String,
  22829. default: 'intersect',
  22830. validator: v => ['intersect', 'manual'].includes(v)
  22831. },
  22832. margin: [Number, String],
  22833. loadMoreText: {
  22834. type: String,
  22835. default: '$vuetify.infiniteScroll.loadMore'
  22836. },
  22837. emptyText: {
  22838. type: String,
  22839. default: '$vuetify.infiniteScroll.empty'
  22840. },
  22841. ...makeDimensionProps(),
  22842. ...makeTagProps()
  22843. }, 'VInfiniteScroll');
  22844. const VInfiniteScrollIntersect = defineComponent({
  22845. name: 'VInfiniteScrollIntersect',
  22846. props: {
  22847. side: {
  22848. type: String,
  22849. required: true
  22850. },
  22851. rootMargin: String
  22852. },
  22853. emits: {
  22854. intersect: (side, isIntersecting) => true
  22855. },
  22856. setup(props, _ref) {
  22857. let {
  22858. emit
  22859. } = _ref;
  22860. const {
  22861. intersectionRef,
  22862. isIntersecting
  22863. } = useIntersectionObserver();
  22864. vue.watch(isIntersecting, async val => {
  22865. emit('intersect', props.side, val);
  22866. });
  22867. useRender(() => vue.createVNode("div", {
  22868. "class": "v-infinite-scroll-intersect",
  22869. "style": {
  22870. '--v-infinite-margin-size': props.rootMargin
  22871. },
  22872. "ref": intersectionRef
  22873. }, [vue.createTextVNode("\xA0")]));
  22874. return {};
  22875. }
  22876. });
  22877. const VInfiniteScroll = genericComponent()({
  22878. name: 'VInfiniteScroll',
  22879. props: makeVInfiniteScrollProps(),
  22880. emits: {
  22881. load: options => true
  22882. },
  22883. setup(props, _ref2) {
  22884. let {
  22885. slots,
  22886. emit
  22887. } = _ref2;
  22888. const rootEl = vue.ref();
  22889. const startStatus = vue.shallowRef('ok');
  22890. const endStatus = vue.shallowRef('ok');
  22891. const margin = vue.computed(() => convertToUnit(props.margin));
  22892. const isIntersecting = vue.shallowRef(false);
  22893. function setScrollAmount(amount) {
  22894. if (!rootEl.value) return;
  22895. const property = props.direction === 'vertical' ? 'scrollTop' : 'scrollLeft';
  22896. rootEl.value[property] = amount;
  22897. }
  22898. function getScrollAmount() {
  22899. if (!rootEl.value) return 0;
  22900. const property = props.direction === 'vertical' ? 'scrollTop' : 'scrollLeft';
  22901. return rootEl.value[property];
  22902. }
  22903. function getScrollSize() {
  22904. if (!rootEl.value) return 0;
  22905. const property = props.direction === 'vertical' ? 'scrollHeight' : 'scrollWidth';
  22906. return rootEl.value[property];
  22907. }
  22908. function getContainerSize() {
  22909. if (!rootEl.value) return 0;
  22910. const property = props.direction === 'vertical' ? 'clientHeight' : 'clientWidth';
  22911. return rootEl.value[property];
  22912. }
  22913. vue.onMounted(() => {
  22914. if (!rootEl.value) return;
  22915. if (props.side === 'start') {
  22916. setScrollAmount(getScrollSize());
  22917. } else if (props.side === 'both') {
  22918. setScrollAmount(getScrollSize() / 2 - getContainerSize() / 2);
  22919. }
  22920. });
  22921. function setStatus(side, status) {
  22922. if (side === 'start') {
  22923. startStatus.value = status;
  22924. } else if (side === 'end') {
  22925. endStatus.value = status;
  22926. }
  22927. }
  22928. function getStatus(side) {
  22929. return side === 'start' ? startStatus.value : endStatus.value;
  22930. }
  22931. let previousScrollSize = 0;
  22932. function handleIntersect(side, _isIntersecting) {
  22933. isIntersecting.value = _isIntersecting;
  22934. if (isIntersecting.value) {
  22935. intersecting(side);
  22936. }
  22937. }
  22938. function intersecting(side) {
  22939. if (props.mode !== 'manual' && !isIntersecting.value) return;
  22940. const status = getStatus(side);
  22941. if (!rootEl.value || ['empty', 'loading'].includes(status)) return;
  22942. previousScrollSize = getScrollSize();
  22943. setStatus(side, 'loading');
  22944. function done(status) {
  22945. setStatus(side, status);
  22946. vue.nextTick(() => {
  22947. if (status === 'empty' || status === 'error') return;
  22948. if (status === 'ok' && side === 'start') {
  22949. setScrollAmount(getScrollSize() - previousScrollSize + getScrollAmount());
  22950. }
  22951. if (props.mode !== 'manual') {
  22952. vue.nextTick(() => {
  22953. window.requestAnimationFrame(() => {
  22954. window.requestAnimationFrame(() => {
  22955. window.requestAnimationFrame(() => {
  22956. intersecting(side);
  22957. });
  22958. });
  22959. });
  22960. });
  22961. }
  22962. });
  22963. }
  22964. emit('load', {
  22965. side,
  22966. done
  22967. });
  22968. }
  22969. const {
  22970. t
  22971. } = useLocale();
  22972. function renderSide(side, status) {
  22973. if (props.side !== side && props.side !== 'both') return;
  22974. const onClick = () => intersecting(side);
  22975. const slotProps = {
  22976. side,
  22977. props: {
  22978. onClick,
  22979. color: props.color
  22980. }
  22981. };
  22982. if (status === 'error') return slots.error?.(slotProps);
  22983. if (status === 'empty') return slots.empty?.(slotProps) ?? vue.createVNode("div", null, [t(props.emptyText)]);
  22984. if (props.mode === 'manual') {
  22985. if (status === 'loading') {
  22986. return slots.loading?.(slotProps) ?? vue.createVNode(VProgressCircular, {
  22987. "indeterminate": true,
  22988. "color": props.color
  22989. }, null);
  22990. }
  22991. return slots['load-more']?.(slotProps) ?? vue.createVNode(VBtn, {
  22992. "variant": "outlined",
  22993. "color": props.color,
  22994. "onClick": onClick
  22995. }, {
  22996. default: () => [t(props.loadMoreText)]
  22997. });
  22998. }
  22999. return slots.loading?.(slotProps) ?? vue.createVNode(VProgressCircular, {
  23000. "indeterminate": true,
  23001. "color": props.color
  23002. }, null);
  23003. }
  23004. const {
  23005. dimensionStyles
  23006. } = useDimension(props);
  23007. useRender(() => {
  23008. const Tag = props.tag;
  23009. const hasStartIntersect = props.side === 'start' || props.side === 'both';
  23010. const hasEndIntersect = props.side === 'end' || props.side === 'both';
  23011. const intersectMode = props.mode === 'intersect';
  23012. return vue.createVNode(Tag, {
  23013. "ref": rootEl,
  23014. "class": ['v-infinite-scroll', `v-infinite-scroll--${props.direction}`, {
  23015. 'v-infinite-scroll--start': hasStartIntersect,
  23016. 'v-infinite-scroll--end': hasEndIntersect
  23017. }],
  23018. "style": dimensionStyles.value
  23019. }, {
  23020. default: () => [vue.createVNode("div", {
  23021. "class": "v-infinite-scroll__side"
  23022. }, [renderSide('start', startStatus.value)]), hasStartIntersect && intersectMode && vue.createVNode(VInfiniteScrollIntersect, {
  23023. "key": "start",
  23024. "side": "start",
  23025. "onIntersect": handleIntersect,
  23026. "rootMargin": margin.value
  23027. }, null), slots.default?.(), hasEndIntersect && intersectMode && vue.createVNode(VInfiniteScrollIntersect, {
  23028. "key": "end",
  23029. "side": "end",
  23030. "onIntersect": handleIntersect,
  23031. "rootMargin": margin.value
  23032. }, null), vue.createVNode("div", {
  23033. "class": "v-infinite-scroll__side"
  23034. }, [renderSide('end', endStatus.value)])]
  23035. });
  23036. });
  23037. }
  23038. });
  23039. // Types
  23040. const VItemGroupSymbol = Symbol.for('vuetify:v-item-group');
  23041. const makeVItemGroupProps = propsFactory({
  23042. ...makeComponentProps(),
  23043. ...makeGroupProps({
  23044. selectedClass: 'v-item--selected'
  23045. }),
  23046. ...makeTagProps(),
  23047. ...makeThemeProps()
  23048. }, 'VItemGroup');
  23049. const VItemGroup = genericComponent()({
  23050. name: 'VItemGroup',
  23051. props: makeVItemGroupProps(),
  23052. emits: {
  23053. 'update:modelValue': value => true
  23054. },
  23055. setup(props, _ref) {
  23056. let {
  23057. slots
  23058. } = _ref;
  23059. const {
  23060. themeClasses
  23061. } = provideTheme(props);
  23062. const {
  23063. isSelected,
  23064. select,
  23065. next,
  23066. prev,
  23067. selected
  23068. } = useGroup(props, VItemGroupSymbol);
  23069. return () => vue.createVNode(props.tag, {
  23070. "class": ['v-item-group', themeClasses.value, props.class],
  23071. "style": props.style
  23072. }, {
  23073. default: () => [slots.default?.({
  23074. isSelected,
  23075. select,
  23076. next,
  23077. prev,
  23078. selected: selected.value
  23079. })]
  23080. });
  23081. }
  23082. });
  23083. // Composables
  23084. const VItem = genericComponent()({
  23085. name: 'VItem',
  23086. props: makeGroupItemProps(),
  23087. emits: {
  23088. 'group:selected': val => true
  23089. },
  23090. setup(props, _ref) {
  23091. let {
  23092. slots
  23093. } = _ref;
  23094. const {
  23095. isSelected,
  23096. select,
  23097. toggle,
  23098. selectedClass,
  23099. value,
  23100. disabled
  23101. } = useGroupItem(props, VItemGroupSymbol);
  23102. return () => slots.default?.({
  23103. isSelected: isSelected.value,
  23104. selectedClass: selectedClass.value,
  23105. select,
  23106. toggle,
  23107. value: value.value,
  23108. disabled: disabled.value
  23109. });
  23110. }
  23111. });
  23112. // Styles
  23113. const VKbd = createSimpleFunctional('v-kbd', 'kbd');
  23114. const makeVLayoutProps = propsFactory({
  23115. ...makeComponentProps(),
  23116. ...makeDimensionProps(),
  23117. ...makeLayoutProps()
  23118. }, 'VLayout');
  23119. const VLayout = genericComponent()({
  23120. name: 'VLayout',
  23121. props: makeVLayoutProps(),
  23122. setup(props, _ref) {
  23123. let {
  23124. slots
  23125. } = _ref;
  23126. const {
  23127. layoutClasses,
  23128. layoutStyles,
  23129. getLayoutItem,
  23130. items,
  23131. layoutRef
  23132. } = createLayout(props);
  23133. const {
  23134. dimensionStyles
  23135. } = useDimension(props);
  23136. useRender(() => vue.createVNode("div", {
  23137. "ref": layoutRef,
  23138. "class": [layoutClasses.value, props.class],
  23139. "style": [dimensionStyles.value, layoutStyles.value, props.style]
  23140. }, [slots.default?.()]));
  23141. return {
  23142. getLayoutItem,
  23143. items
  23144. };
  23145. }
  23146. });
  23147. // Types
  23148. const makeVLayoutItemProps = propsFactory({
  23149. position: {
  23150. type: String,
  23151. required: true
  23152. },
  23153. size: {
  23154. type: [Number, String],
  23155. default: 300
  23156. },
  23157. modelValue: Boolean,
  23158. ...makeComponentProps(),
  23159. ...makeLayoutItemProps()
  23160. }, 'VLayoutItem');
  23161. const VLayoutItem = genericComponent()({
  23162. name: 'VLayoutItem',
  23163. props: makeVLayoutItemProps(),
  23164. setup(props, _ref) {
  23165. let {
  23166. slots
  23167. } = _ref;
  23168. const {
  23169. layoutItemStyles
  23170. } = useLayoutItem({
  23171. id: props.name,
  23172. order: vue.computed(() => parseInt(props.order, 10)),
  23173. position: vue.toRef(props, 'position'),
  23174. elementSize: vue.toRef(props, 'size'),
  23175. layoutSize: vue.toRef(props, 'size'),
  23176. active: vue.toRef(props, 'modelValue'),
  23177. absolute: vue.toRef(props, 'absolute')
  23178. });
  23179. return () => vue.createVNode("div", {
  23180. "class": ['v-layout-item', props.class],
  23181. "style": [layoutItemStyles.value, props.style]
  23182. }, [slots.default?.()]);
  23183. }
  23184. });
  23185. // Types
  23186. const makeVLazyProps = propsFactory({
  23187. modelValue: Boolean,
  23188. options: {
  23189. type: Object,
  23190. // For more information on types, navigate to:
  23191. // https://developer.mozilla.org/en-US/docs/Web/API/Intersection_Observer_API
  23192. default: () => ({
  23193. root: undefined,
  23194. rootMargin: undefined,
  23195. threshold: undefined
  23196. })
  23197. },
  23198. ...makeComponentProps(),
  23199. ...makeDimensionProps(),
  23200. ...makeTagProps(),
  23201. ...makeTransitionProps({
  23202. transition: 'fade-transition'
  23203. })
  23204. }, 'VLazy');
  23205. const VLazy = genericComponent()({
  23206. name: 'VLazy',
  23207. directives: {
  23208. intersect: Intersect
  23209. },
  23210. props: makeVLazyProps(),
  23211. emits: {
  23212. 'update:modelValue': value => true
  23213. },
  23214. setup(props, _ref) {
  23215. let {
  23216. slots
  23217. } = _ref;
  23218. const {
  23219. dimensionStyles
  23220. } = useDimension(props);
  23221. const isActive = useProxiedModel(props, 'modelValue');
  23222. function onIntersect(isIntersecting) {
  23223. if (isActive.value) return;
  23224. isActive.value = isIntersecting;
  23225. }
  23226. useRender(() => vue.withDirectives(vue.createVNode(props.tag, {
  23227. "class": ['v-lazy', props.class],
  23228. "style": [dimensionStyles.value, props.style]
  23229. }, {
  23230. default: () => [isActive.value && vue.createVNode(MaybeTransition, {
  23231. "transition": props.transition,
  23232. "appear": true
  23233. }, {
  23234. default: () => [slots.default?.()]
  23235. })]
  23236. }), [[vue.resolveDirective("intersect"), {
  23237. handler: onIntersect,
  23238. options: props.options
  23239. }, null]]));
  23240. return {};
  23241. }
  23242. });
  23243. const makeVLocaleProviderProps = propsFactory({
  23244. locale: String,
  23245. fallbackLocale: String,
  23246. messages: Object,
  23247. rtl: {
  23248. type: Boolean,
  23249. default: undefined
  23250. },
  23251. ...makeComponentProps()
  23252. }, 'VLocaleProvider');
  23253. const VLocaleProvider = genericComponent()({
  23254. name: 'VLocaleProvider',
  23255. props: makeVLocaleProviderProps(),
  23256. setup(props, _ref) {
  23257. let {
  23258. slots
  23259. } = _ref;
  23260. const {
  23261. rtlClasses
  23262. } = provideLocale(props);
  23263. useRender(() => vue.createVNode("div", {
  23264. "class": ['v-locale-provider', rtlClasses.value, props.class],
  23265. "style": props.style
  23266. }, [slots.default?.()]));
  23267. return {};
  23268. }
  23269. });
  23270. const makeVMainProps = propsFactory({
  23271. scrollable: Boolean,
  23272. ...makeComponentProps(),
  23273. ...makeDimensionProps(),
  23274. ...makeTagProps({
  23275. tag: 'main'
  23276. })
  23277. }, 'VMain');
  23278. const VMain = genericComponent()({
  23279. name: 'VMain',
  23280. props: makeVMainProps(),
  23281. setup(props, _ref) {
  23282. let {
  23283. slots
  23284. } = _ref;
  23285. const {
  23286. dimensionStyles
  23287. } = useDimension(props);
  23288. const {
  23289. mainStyles
  23290. } = useLayout();
  23291. const {
  23292. ssrBootStyles
  23293. } = useSsrBoot();
  23294. useRender(() => vue.createVNode(props.tag, {
  23295. "class": ['v-main', {
  23296. 'v-main--scrollable': props.scrollable
  23297. }, props.class],
  23298. "style": [mainStyles.value, ssrBootStyles.value, dimensionStyles.value, props.style]
  23299. }, {
  23300. default: () => [props.scrollable ? vue.createVNode("div", {
  23301. "class": "v-main__scroller"
  23302. }, [slots.default?.()]) : slots.default?.()]
  23303. }));
  23304. return {};
  23305. }
  23306. });
  23307. // Utilities
  23308. // Types
  23309. function useSticky(_ref) {
  23310. let {
  23311. rootEl,
  23312. isSticky,
  23313. layoutItemStyles
  23314. } = _ref;
  23315. const isStuck = vue.shallowRef(false);
  23316. const stuckPosition = vue.shallowRef(0);
  23317. const stickyStyles = vue.computed(() => {
  23318. const side = typeof isStuck.value === 'boolean' ? 'top' : isStuck.value;
  23319. return [isSticky.value ? {
  23320. top: 'auto',
  23321. bottom: 'auto',
  23322. height: undefined
  23323. } : undefined, isStuck.value ? {
  23324. [side]: convertToUnit(stuckPosition.value)
  23325. } : {
  23326. top: layoutItemStyles.value.top
  23327. }];
  23328. });
  23329. vue.onMounted(() => {
  23330. vue.watch(isSticky, val => {
  23331. if (val) {
  23332. window.addEventListener('scroll', onScroll, {
  23333. passive: true
  23334. });
  23335. } else {
  23336. window.removeEventListener('scroll', onScroll);
  23337. }
  23338. }, {
  23339. immediate: true
  23340. });
  23341. });
  23342. vue.onBeforeUnmount(() => {
  23343. window.removeEventListener('scroll', onScroll);
  23344. });
  23345. let lastScrollTop = 0;
  23346. function onScroll() {
  23347. const direction = lastScrollTop > window.scrollY ? 'up' : 'down';
  23348. const rect = rootEl.value.getBoundingClientRect();
  23349. const layoutTop = parseFloat(layoutItemStyles.value.top ?? 0);
  23350. const top = window.scrollY - Math.max(0, stuckPosition.value - layoutTop);
  23351. const bottom = rect.height + Math.max(stuckPosition.value, layoutTop) - window.scrollY - window.innerHeight;
  23352. const bodyScroll = parseFloat(getComputedStyle(rootEl.value).getPropertyValue('--v-body-scroll-y')) || 0;
  23353. if (rect.height < window.innerHeight - layoutTop) {
  23354. isStuck.value = 'top';
  23355. stuckPosition.value = layoutTop;
  23356. } else if (direction === 'up' && isStuck.value === 'bottom' || direction === 'down' && isStuck.value === 'top') {
  23357. stuckPosition.value = window.scrollY + rect.top - bodyScroll;
  23358. isStuck.value = true;
  23359. } else if (direction === 'down' && bottom <= 0) {
  23360. stuckPosition.value = 0;
  23361. isStuck.value = 'bottom';
  23362. } else if (direction === 'up' && top <= 0) {
  23363. if (!bodyScroll) {
  23364. stuckPosition.value = rect.top + top;
  23365. isStuck.value = 'top';
  23366. } else if (isStuck.value !== 'top') {
  23367. stuckPosition.value = -top + bodyScroll + layoutTop;
  23368. isStuck.value = 'top';
  23369. }
  23370. }
  23371. lastScrollTop = window.scrollY;
  23372. }
  23373. return {
  23374. isStuck,
  23375. stickyStyles
  23376. };
  23377. }
  23378. // Utilities
  23379. const HORIZON = 100; // ms
  23380. const HISTORY = 20; // number of samples to keep
  23381. /** @see https://android.googlesource.com/platform/frameworks/native/+/master/libs/input/VelocityTracker.cpp */
  23382. function kineticEnergyToVelocity(work) {
  23383. const sqrt2 = 1.41421356237;
  23384. return (work < 0 ? -1.0 : 1.0) * Math.sqrt(Math.abs(work)) * sqrt2;
  23385. }
  23386. /**
  23387. * Returns pointer velocity in px/s
  23388. */
  23389. function calculateImpulseVelocity(samples) {
  23390. // The input should be in reversed time order (most recent sample at index i=0)
  23391. if (samples.length < 2) {
  23392. // if 0 or 1 points, velocity is zero
  23393. return 0;
  23394. }
  23395. // if (samples[1].t > samples[0].t) {
  23396. // // Algorithm will still work, but not perfectly
  23397. // consoleWarn('Samples provided to calculateImpulseVelocity in the wrong order')
  23398. // }
  23399. if (samples.length === 2) {
  23400. // if 2 points, basic linear calculation
  23401. if (samples[1].t === samples[0].t) {
  23402. // consoleWarn(`Events have identical time stamps t=${samples[0].t}, setting velocity = 0`)
  23403. return 0;
  23404. }
  23405. return (samples[1].d - samples[0].d) / (samples[1].t - samples[0].t);
  23406. }
  23407. // Guaranteed to have at least 3 points here
  23408. // start with the oldest sample and go forward in time
  23409. let work = 0;
  23410. for (let i = samples.length - 1; i > 0; i--) {
  23411. if (samples[i].t === samples[i - 1].t) {
  23412. // consoleWarn(`Events have identical time stamps t=${samples[i].t}, skipping sample`)
  23413. continue;
  23414. }
  23415. const vprev = kineticEnergyToVelocity(work); // v[i-1]
  23416. const vcurr = (samples[i].d - samples[i - 1].d) / (samples[i].t - samples[i - 1].t); // v[i]
  23417. work += (vcurr - vprev) * Math.abs(vcurr);
  23418. if (i === samples.length - 1) {
  23419. work *= 0.5;
  23420. }
  23421. }
  23422. return kineticEnergyToVelocity(work) * 1000;
  23423. }
  23424. function useVelocity() {
  23425. const touches = {};
  23426. function addMovement(e) {
  23427. Array.from(e.changedTouches).forEach(touch => {
  23428. const samples = touches[touch.identifier] ?? (touches[touch.identifier] = new CircularBuffer(HISTORY));
  23429. samples.push([e.timeStamp, touch]);
  23430. });
  23431. }
  23432. function endTouch(e) {
  23433. Array.from(e.changedTouches).forEach(touch => {
  23434. delete touches[touch.identifier];
  23435. });
  23436. }
  23437. function getVelocity(id) {
  23438. const samples = touches[id]?.values().reverse();
  23439. if (!samples) {
  23440. throw new Error(`No samples for touch id ${id}`);
  23441. }
  23442. const newest = samples[0];
  23443. const x = [];
  23444. const y = [];
  23445. for (const val of samples) {
  23446. if (newest[0] - val[0] > HORIZON) break;
  23447. x.push({
  23448. t: val[0],
  23449. d: val[1].clientX
  23450. });
  23451. y.push({
  23452. t: val[0],
  23453. d: val[1].clientY
  23454. });
  23455. }
  23456. return {
  23457. x: calculateImpulseVelocity(x),
  23458. y: calculateImpulseVelocity(y),
  23459. get direction() {
  23460. const {
  23461. x,
  23462. y
  23463. } = this;
  23464. const [absX, absY] = [Math.abs(x), Math.abs(y)];
  23465. return absX > absY && x >= 0 ? 'right' : absX > absY && x <= 0 ? 'left' : absY > absX && y >= 0 ? 'down' : absY > absX && y <= 0 ? 'up' : oops$1();
  23466. }
  23467. };
  23468. }
  23469. return {
  23470. addMovement,
  23471. endTouch,
  23472. getVelocity
  23473. };
  23474. }
  23475. function oops$1() {
  23476. throw new Error();
  23477. }
  23478. // Composables
  23479. // Types
  23480. function useTouch(_ref) {
  23481. let {
  23482. el,
  23483. isActive,
  23484. isTemporary,
  23485. width,
  23486. touchless,
  23487. position
  23488. } = _ref;
  23489. vue.onMounted(() => {
  23490. window.addEventListener('touchstart', onTouchstart, {
  23491. passive: true
  23492. });
  23493. window.addEventListener('touchmove', onTouchmove, {
  23494. passive: false
  23495. });
  23496. window.addEventListener('touchend', onTouchend, {
  23497. passive: true
  23498. });
  23499. });
  23500. vue.onBeforeUnmount(() => {
  23501. window.removeEventListener('touchstart', onTouchstart);
  23502. window.removeEventListener('touchmove', onTouchmove);
  23503. window.removeEventListener('touchend', onTouchend);
  23504. });
  23505. const isHorizontal = vue.computed(() => ['left', 'right'].includes(position.value));
  23506. const {
  23507. addMovement,
  23508. endTouch,
  23509. getVelocity
  23510. } = useVelocity();
  23511. let maybeDragging = false;
  23512. const isDragging = vue.shallowRef(false);
  23513. const dragProgress = vue.shallowRef(0);
  23514. const offset = vue.shallowRef(0);
  23515. let start;
  23516. function getOffset(pos, active) {
  23517. 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);
  23518. }
  23519. function getProgress(pos) {
  23520. let limit = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : true;
  23521. 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();
  23522. return limit ? Math.max(0, Math.min(1, progress)) : progress;
  23523. }
  23524. function onTouchstart(e) {
  23525. if (touchless.value) return;
  23526. const touchX = e.changedTouches[0].clientX;
  23527. const touchY = e.changedTouches[0].clientY;
  23528. const touchZone = 25;
  23529. 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();
  23530. 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());
  23531. if (inTouchZone || inElement || isActive.value && isTemporary.value) {
  23532. start = [touchX, touchY];
  23533. offset.value = getOffset(isHorizontal.value ? touchX : touchY, isActive.value);
  23534. dragProgress.value = getProgress(isHorizontal.value ? touchX : touchY);
  23535. maybeDragging = offset.value > -20 && offset.value < 80;
  23536. endTouch(e);
  23537. addMovement(e);
  23538. }
  23539. }
  23540. function onTouchmove(e) {
  23541. const touchX = e.changedTouches[0].clientX;
  23542. const touchY = e.changedTouches[0].clientY;
  23543. if (maybeDragging) {
  23544. if (!e.cancelable) {
  23545. maybeDragging = false;
  23546. return;
  23547. }
  23548. const dx = Math.abs(touchX - start[0]);
  23549. const dy = Math.abs(touchY - start[1]);
  23550. const thresholdMet = isHorizontal.value ? dx > dy && dx > 3 : dy > dx && dy > 3;
  23551. if (thresholdMet) {
  23552. isDragging.value = true;
  23553. maybeDragging = false;
  23554. } else if ((isHorizontal.value ? dy : dx) > 3) {
  23555. maybeDragging = false;
  23556. }
  23557. }
  23558. if (!isDragging.value) return;
  23559. e.preventDefault();
  23560. addMovement(e);
  23561. const progress = getProgress(isHorizontal.value ? touchX : touchY, false);
  23562. dragProgress.value = Math.max(0, Math.min(1, progress));
  23563. if (progress > 1) {
  23564. offset.value = getOffset(isHorizontal.value ? touchX : touchY, true);
  23565. } else if (progress < 0) {
  23566. offset.value = getOffset(isHorizontal.value ? touchX : touchY, false);
  23567. }
  23568. }
  23569. function onTouchend(e) {
  23570. maybeDragging = false;
  23571. if (!isDragging.value) return;
  23572. addMovement(e);
  23573. isDragging.value = false;
  23574. const velocity = getVelocity(e.changedTouches[0].identifier);
  23575. const vx = Math.abs(velocity.x);
  23576. const vy = Math.abs(velocity.y);
  23577. const thresholdMet = isHorizontal.value ? vx > vy && vx > 400 : vy > vx && vy > 3;
  23578. if (thresholdMet) {
  23579. isActive.value = velocity.direction === ({
  23580. left: 'right',
  23581. right: 'left',
  23582. top: 'down',
  23583. bottom: 'up'
  23584. }[position.value] || oops());
  23585. } else {
  23586. isActive.value = dragProgress.value > 0.5;
  23587. }
  23588. }
  23589. const dragStyles = vue.computed(() => {
  23590. return isDragging.value ? {
  23591. 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(),
  23592. transition: 'none'
  23593. } : undefined;
  23594. });
  23595. useToggleScope(isDragging, () => {
  23596. const transform = el.value?.style.transform ?? null;
  23597. const transition = el.value?.style.transition ?? null;
  23598. vue.watchEffect(() => {
  23599. el.value?.style.setProperty('transform', dragStyles.value?.transform || 'none');
  23600. el.value?.style.setProperty('transition', dragStyles.value?.transition || null);
  23601. });
  23602. vue.onScopeDispose(() => {
  23603. el.value?.style.setProperty('transform', transform);
  23604. el.value?.style.setProperty('transition', transition);
  23605. });
  23606. });
  23607. return {
  23608. isDragging,
  23609. dragProgress,
  23610. dragStyles
  23611. };
  23612. }
  23613. function oops() {
  23614. throw new Error();
  23615. }
  23616. // Types
  23617. const locations = ['start', 'end', 'left', 'right', 'top', 'bottom'];
  23618. const makeVNavigationDrawerProps = propsFactory({
  23619. color: String,
  23620. disableResizeWatcher: Boolean,
  23621. disableRouteWatcher: Boolean,
  23622. expandOnHover: Boolean,
  23623. floating: Boolean,
  23624. modelValue: {
  23625. type: Boolean,
  23626. default: null
  23627. },
  23628. permanent: Boolean,
  23629. rail: {
  23630. type: Boolean,
  23631. default: null
  23632. },
  23633. railWidth: {
  23634. type: [Number, String],
  23635. default: 56
  23636. },
  23637. scrim: {
  23638. type: [Boolean, String],
  23639. default: true
  23640. },
  23641. image: String,
  23642. temporary: Boolean,
  23643. persistent: Boolean,
  23644. touchless: Boolean,
  23645. width: {
  23646. type: [Number, String],
  23647. default: 256
  23648. },
  23649. location: {
  23650. type: String,
  23651. default: 'start',
  23652. validator: value => locations.includes(value)
  23653. },
  23654. sticky: Boolean,
  23655. ...makeBorderProps(),
  23656. ...makeComponentProps(),
  23657. ...makeDelayProps(),
  23658. ...makeDisplayProps({
  23659. mobile: null
  23660. }),
  23661. ...makeElevationProps(),
  23662. ...makeLayoutItemProps(),
  23663. ...makeRoundedProps(),
  23664. ...makeTagProps({
  23665. tag: 'nav'
  23666. }),
  23667. ...makeThemeProps()
  23668. }, 'VNavigationDrawer');
  23669. const VNavigationDrawer = genericComponent()({
  23670. name: 'VNavigationDrawer',
  23671. props: makeVNavigationDrawerProps(),
  23672. emits: {
  23673. 'update:modelValue': val => true,
  23674. 'update:rail': val => true
  23675. },
  23676. setup(props, _ref) {
  23677. let {
  23678. attrs,
  23679. emit,
  23680. slots
  23681. } = _ref;
  23682. const {
  23683. isRtl
  23684. } = useRtl();
  23685. const {
  23686. themeClasses
  23687. } = provideTheme(props);
  23688. const {
  23689. borderClasses
  23690. } = useBorder(props);
  23691. const {
  23692. backgroundColorClasses,
  23693. backgroundColorStyles
  23694. } = useBackgroundColor(vue.toRef(props, 'color'));
  23695. const {
  23696. elevationClasses
  23697. } = useElevation(props);
  23698. const {
  23699. displayClasses,
  23700. mobile
  23701. } = useDisplay(props);
  23702. const {
  23703. roundedClasses
  23704. } = useRounded(props);
  23705. const router = useRouter();
  23706. const isActive = useProxiedModel(props, 'modelValue', null, v => !!v);
  23707. const {
  23708. ssrBootStyles
  23709. } = useSsrBoot();
  23710. const {
  23711. scopeId
  23712. } = useScopeId();
  23713. const rootEl = vue.ref();
  23714. const isHovering = vue.shallowRef(false);
  23715. const {
  23716. runOpenDelay,
  23717. runCloseDelay
  23718. } = useDelay(props, value => {
  23719. isHovering.value = value;
  23720. });
  23721. const width = vue.computed(() => {
  23722. return props.rail && props.expandOnHover && isHovering.value ? Number(props.width) : Number(props.rail ? props.railWidth : props.width);
  23723. });
  23724. const location = vue.computed(() => {
  23725. return toPhysical(props.location, isRtl.value);
  23726. });
  23727. const isPersistent = vue.computed(() => props.persistent);
  23728. const isTemporary = vue.computed(() => !props.permanent && (mobile.value || props.temporary));
  23729. const isSticky = vue.computed(() => props.sticky && !isTemporary.value && location.value !== 'bottom');
  23730. useToggleScope(() => props.expandOnHover && props.rail != null, () => {
  23731. vue.watch(isHovering, val => emit('update:rail', !val));
  23732. });
  23733. useToggleScope(() => !props.disableResizeWatcher, () => {
  23734. vue.watch(isTemporary, val => !props.permanent && vue.nextTick(() => isActive.value = !val));
  23735. });
  23736. useToggleScope(() => !props.disableRouteWatcher && !!router, () => {
  23737. vue.watch(router.currentRoute, () => isTemporary.value && (isActive.value = false));
  23738. });
  23739. vue.watch(() => props.permanent, val => {
  23740. if (val) isActive.value = true;
  23741. });
  23742. if (props.modelValue == null && !isTemporary.value) {
  23743. isActive.value = props.permanent || !mobile.value;
  23744. }
  23745. const {
  23746. isDragging,
  23747. dragProgress
  23748. } = useTouch({
  23749. el: rootEl,
  23750. isActive,
  23751. isTemporary,
  23752. width,
  23753. touchless: vue.toRef(props, 'touchless'),
  23754. position: location
  23755. });
  23756. const layoutSize = vue.computed(() => {
  23757. const size = isTemporary.value ? 0 : props.rail && props.expandOnHover ? Number(props.railWidth) : width.value;
  23758. return isDragging.value ? size * dragProgress.value : size;
  23759. });
  23760. const elementSize = vue.computed(() => ['top', 'bottom'].includes(props.location) ? 0 : width.value);
  23761. const {
  23762. layoutItemStyles,
  23763. layoutItemScrimStyles
  23764. } = useLayoutItem({
  23765. id: props.name,
  23766. order: vue.computed(() => parseInt(props.order, 10)),
  23767. position: location,
  23768. layoutSize,
  23769. elementSize,
  23770. active: vue.computed(() => isActive.value || isDragging.value),
  23771. disableTransitions: vue.computed(() => isDragging.value),
  23772. absolute: vue.computed(() =>
  23773. // eslint-disable-next-line @typescript-eslint/no-use-before-define
  23774. props.absolute || isSticky.value && typeof isStuck.value !== 'string')
  23775. });
  23776. const {
  23777. isStuck,
  23778. stickyStyles
  23779. } = useSticky({
  23780. rootEl,
  23781. isSticky,
  23782. layoutItemStyles
  23783. });
  23784. const scrimColor = useBackgroundColor(vue.computed(() => {
  23785. return typeof props.scrim === 'string' ? props.scrim : null;
  23786. }));
  23787. const scrimStyles = vue.computed(() => ({
  23788. ...(isDragging.value ? {
  23789. opacity: dragProgress.value * 0.2,
  23790. transition: 'none'
  23791. } : undefined),
  23792. ...layoutItemScrimStyles.value
  23793. }));
  23794. provideDefaults({
  23795. VList: {
  23796. bgColor: 'transparent'
  23797. }
  23798. });
  23799. useRender(() => {
  23800. const hasImage = slots.image || props.image;
  23801. return vue.createVNode(vue.Fragment, null, [vue.createVNode(props.tag, vue.mergeProps({
  23802. "ref": rootEl,
  23803. "onMouseenter": runOpenDelay,
  23804. "onMouseleave": runCloseDelay,
  23805. "class": ['v-navigation-drawer', `v-navigation-drawer--${location.value}`, {
  23806. 'v-navigation-drawer--expand-on-hover': props.expandOnHover,
  23807. 'v-navigation-drawer--floating': props.floating,
  23808. 'v-navigation-drawer--is-hovering': isHovering.value,
  23809. 'v-navigation-drawer--rail': props.rail,
  23810. 'v-navigation-drawer--temporary': isTemporary.value,
  23811. 'v-navigation-drawer--persistent': isPersistent.value,
  23812. 'v-navigation-drawer--active': isActive.value,
  23813. 'v-navigation-drawer--sticky': isSticky.value
  23814. }, themeClasses.value, backgroundColorClasses.value, borderClasses.value, displayClasses.value, elevationClasses.value, roundedClasses.value, props.class],
  23815. "style": [backgroundColorStyles.value, layoutItemStyles.value, ssrBootStyles.value, stickyStyles.value, props.style, ['top', 'bottom'].includes(location.value) ? {
  23816. height: 'auto'
  23817. } : {}]
  23818. }, scopeId, attrs), {
  23819. default: () => [hasImage && vue.createVNode("div", {
  23820. "key": "image",
  23821. "class": "v-navigation-drawer__img"
  23822. }, [!slots.image ? vue.createVNode(VImg, {
  23823. "key": "image-img",
  23824. "alt": "",
  23825. "cover": true,
  23826. "height": "inherit",
  23827. "src": props.image
  23828. }, null) : vue.createVNode(VDefaultsProvider, {
  23829. "key": "image-defaults",
  23830. "disabled": !props.image,
  23831. "defaults": {
  23832. VImg: {
  23833. alt: '',
  23834. cover: true,
  23835. height: 'inherit',
  23836. src: props.image
  23837. }
  23838. }
  23839. }, slots.image)]), slots.prepend && vue.createVNode("div", {
  23840. "class": "v-navigation-drawer__prepend"
  23841. }, [slots.prepend?.()]), vue.createVNode("div", {
  23842. "class": "v-navigation-drawer__content"
  23843. }, [slots.default?.()]), slots.append && vue.createVNode("div", {
  23844. "class": "v-navigation-drawer__append"
  23845. }, [slots.append?.()])]
  23846. }), vue.createVNode(vue.Transition, {
  23847. "name": "fade-transition"
  23848. }, {
  23849. default: () => [isTemporary.value && (isDragging.value || isActive.value) && !!props.scrim && vue.createVNode("div", vue.mergeProps({
  23850. "class": ['v-navigation-drawer__scrim', scrimColor.backgroundColorClasses.value],
  23851. "style": [scrimStyles.value, scrimColor.backgroundColorStyles.value],
  23852. "onClick": () => {
  23853. if (isPersistent.value) return;
  23854. isActive.value = false;
  23855. }
  23856. }, scopeId), null)]
  23857. })]);
  23858. });
  23859. return {
  23860. isStuck
  23861. };
  23862. }
  23863. });
  23864. // Composables
  23865. const VNoSsr = defineComponent({
  23866. name: 'VNoSsr',
  23867. setup(_, _ref) {
  23868. let {
  23869. slots
  23870. } = _ref;
  23871. const show = useHydration();
  23872. return () => show.value && slots.default?.();
  23873. }
  23874. });
  23875. // Types
  23876. // Types
  23877. const makeVOtpInputProps = propsFactory({
  23878. autofocus: Boolean,
  23879. divider: String,
  23880. focusAll: Boolean,
  23881. label: {
  23882. type: String,
  23883. default: '$vuetify.input.otp'
  23884. },
  23885. length: {
  23886. type: [Number, String],
  23887. default: 6
  23888. },
  23889. modelValue: {
  23890. type: [Number, String],
  23891. default: undefined
  23892. },
  23893. placeholder: String,
  23894. type: {
  23895. type: String,
  23896. default: 'number'
  23897. },
  23898. ...makeDimensionProps(),
  23899. ...makeFocusProps(),
  23900. ...only(makeVFieldProps({
  23901. variant: 'outlined'
  23902. }), ['baseColor', 'bgColor', 'class', 'color', 'disabled', 'error', 'loading', 'rounded', 'style', 'theme', 'variant'])
  23903. }, 'VOtpInput');
  23904. const VOtpInput = genericComponent()({
  23905. name: 'VOtpInput',
  23906. props: makeVOtpInputProps(),
  23907. emits: {
  23908. finish: val => true,
  23909. 'update:focused': val => true,
  23910. 'update:modelValue': val => true
  23911. },
  23912. setup(props, _ref) {
  23913. let {
  23914. attrs,
  23915. emit,
  23916. slots
  23917. } = _ref;
  23918. const {
  23919. dimensionStyles
  23920. } = useDimension(props);
  23921. const {
  23922. isFocused,
  23923. focus,
  23924. blur
  23925. } = useFocus(props);
  23926. const model = useProxiedModel(props, 'modelValue', '', val => val == null ? [] : String(val).split(''), val => val.join(''));
  23927. const {
  23928. t
  23929. } = useLocale();
  23930. const length = vue.computed(() => Number(props.length));
  23931. const fields = vue.computed(() => Array(length.value).fill(0));
  23932. const focusIndex = vue.ref(-1);
  23933. const contentRef = vue.ref();
  23934. const inputRef = vue.ref([]);
  23935. const current = vue.computed(() => inputRef.value[focusIndex.value]);
  23936. function onInput() {
  23937. // The maxlength attribute doesn't work for the number type input, so the text type is used.
  23938. // The following logic simulates the behavior of a number input.
  23939. if (isValidNumber(current.value.value)) {
  23940. current.value.value = '';
  23941. return;
  23942. }
  23943. const array = model.value.slice();
  23944. const value = current.value.value;
  23945. array[focusIndex.value] = value;
  23946. let target = null;
  23947. if (focusIndex.value > model.value.length) {
  23948. target = model.value.length + 1;
  23949. } else if (focusIndex.value + 1 !== length.value) {
  23950. target = 'next';
  23951. }
  23952. model.value = array;
  23953. if (target) focusChild(contentRef.value, target);
  23954. }
  23955. function onKeydown(e) {
  23956. const array = model.value.slice();
  23957. const index = focusIndex.value;
  23958. let target = null;
  23959. if (!['ArrowLeft', 'ArrowRight', 'Backspace', 'Delete'].includes(e.key)) return;
  23960. e.preventDefault();
  23961. if (e.key === 'ArrowLeft') {
  23962. target = 'prev';
  23963. } else if (e.key === 'ArrowRight') {
  23964. target = 'next';
  23965. } else if (['Backspace', 'Delete'].includes(e.key)) {
  23966. array[focusIndex.value] = '';
  23967. model.value = array;
  23968. if (focusIndex.value > 0 && e.key === 'Backspace') {
  23969. target = 'prev';
  23970. } else {
  23971. requestAnimationFrame(() => {
  23972. inputRef.value[index]?.select();
  23973. });
  23974. }
  23975. }
  23976. requestAnimationFrame(() => {
  23977. if (target != null) {
  23978. focusChild(contentRef.value, target);
  23979. }
  23980. });
  23981. }
  23982. function onPaste(index, e) {
  23983. e.preventDefault();
  23984. e.stopPropagation();
  23985. const clipboardText = e?.clipboardData?.getData('Text').slice(0, length.value) ?? '';
  23986. if (isValidNumber(clipboardText)) return;
  23987. model.value = clipboardText.split('');
  23988. inputRef.value?.[index].blur();
  23989. }
  23990. function reset() {
  23991. model.value = [];
  23992. }
  23993. function onFocus(e, index) {
  23994. focus();
  23995. focusIndex.value = index;
  23996. }
  23997. function onBlur() {
  23998. blur();
  23999. focusIndex.value = -1;
  24000. }
  24001. function isValidNumber(value) {
  24002. return props.type === 'number' && /[^0-9]/g.test(value);
  24003. }
  24004. provideDefaults({
  24005. VField: {
  24006. color: vue.computed(() => props.color),
  24007. bgColor: vue.computed(() => props.color),
  24008. baseColor: vue.computed(() => props.baseColor),
  24009. disabled: vue.computed(() => props.disabled),
  24010. error: vue.computed(() => props.error),
  24011. variant: vue.computed(() => props.variant)
  24012. }
  24013. }, {
  24014. scoped: true
  24015. });
  24016. vue.watch(model, val => {
  24017. if (val.length === length.value) emit('finish', val.join(''));
  24018. }, {
  24019. deep: true
  24020. });
  24021. vue.watch(focusIndex, val => {
  24022. if (val < 0) return;
  24023. vue.nextTick(() => {
  24024. inputRef.value[val]?.select();
  24025. });
  24026. });
  24027. useRender(() => {
  24028. const [rootAttrs, inputAttrs] = filterInputAttrs(attrs);
  24029. return vue.createVNode("div", vue.mergeProps({
  24030. "class": ['v-otp-input', {
  24031. 'v-otp-input--divided': !!props.divider
  24032. }, props.class],
  24033. "style": [props.style]
  24034. }, rootAttrs), [vue.createVNode("div", {
  24035. "ref": contentRef,
  24036. "class": "v-otp-input__content",
  24037. "style": [dimensionStyles.value]
  24038. }, [fields.value.map((_, i) => vue.createVNode(vue.Fragment, null, [props.divider && i !== 0 && vue.createVNode("span", {
  24039. "class": "v-otp-input__divider"
  24040. }, [props.divider]), vue.createVNode(VField, {
  24041. "focused": isFocused.value && props.focusAll || focusIndex.value === i,
  24042. "key": i
  24043. }, {
  24044. ...slots,
  24045. loader: undefined,
  24046. default: () => {
  24047. return vue.createVNode("input", {
  24048. "ref": val => inputRef.value[i] = val,
  24049. "aria-label": t(props.label, i + 1),
  24050. "autofocus": i === 0 && props.autofocus,
  24051. "autocomplete": "one-time-code",
  24052. "class": ['v-otp-input__field'],
  24053. "disabled": props.disabled,
  24054. "inputmode": props.type === 'number' ? 'numeric' : 'text',
  24055. "min": props.type === 'number' ? 0 : undefined,
  24056. "maxlength": "1",
  24057. "placeholder": props.placeholder,
  24058. "type": props.type === 'number' ? 'text' : props.type,
  24059. "value": model.value[i],
  24060. "onInput": onInput,
  24061. "onFocus": e => onFocus(e, i),
  24062. "onBlur": onBlur,
  24063. "onKeydown": onKeydown,
  24064. "onPaste": event => onPaste(i, event)
  24065. }, null);
  24066. }
  24067. })])), vue.createVNode("input", vue.mergeProps({
  24068. "class": "v-otp-input-input",
  24069. "type": "hidden"
  24070. }, inputAttrs, {
  24071. "value": model.value.join('')
  24072. }), null), vue.createVNode(VOverlay, {
  24073. "contained": true,
  24074. "content-class": "v-otp-input__loader",
  24075. "model-value": !!props.loading,
  24076. "persistent": true
  24077. }, {
  24078. default: () => [slots.loader?.() ?? vue.createVNode(VProgressCircular, {
  24079. "color": typeof props.loading === 'boolean' ? undefined : props.loading,
  24080. "indeterminate": true,
  24081. "size": "24",
  24082. "width": "2"
  24083. }, null)]
  24084. }), slots.default?.()])]);
  24085. });
  24086. return {
  24087. blur: () => {
  24088. inputRef.value?.some(input => input.blur());
  24089. },
  24090. focus: () => {
  24091. inputRef.value?.[0].focus();
  24092. },
  24093. reset,
  24094. isFocused
  24095. };
  24096. }
  24097. });
  24098. // Types
  24099. function floor(val) {
  24100. return Math.floor(Math.abs(val)) * Math.sign(val);
  24101. }
  24102. const makeVParallaxProps = propsFactory({
  24103. scale: {
  24104. type: [Number, String],
  24105. default: 0.5
  24106. },
  24107. ...makeComponentProps()
  24108. }, 'VParallax');
  24109. const VParallax = genericComponent()({
  24110. name: 'VParallax',
  24111. props: makeVParallaxProps(),
  24112. setup(props, _ref) {
  24113. let {
  24114. slots
  24115. } = _ref;
  24116. const {
  24117. intersectionRef,
  24118. isIntersecting
  24119. } = useIntersectionObserver();
  24120. const {
  24121. resizeRef,
  24122. contentRect
  24123. } = useResizeObserver();
  24124. const {
  24125. height: displayHeight
  24126. } = useDisplay();
  24127. const root = vue.ref();
  24128. vue.watchEffect(() => {
  24129. intersectionRef.value = resizeRef.value = root.value?.$el;
  24130. });
  24131. let scrollParent;
  24132. vue.watch(isIntersecting, val => {
  24133. if (val) {
  24134. scrollParent = getScrollParent(intersectionRef.value);
  24135. scrollParent = scrollParent === document.scrollingElement ? document : scrollParent;
  24136. scrollParent.addEventListener('scroll', onScroll, {
  24137. passive: true
  24138. });
  24139. onScroll();
  24140. } else {
  24141. scrollParent.removeEventListener('scroll', onScroll);
  24142. }
  24143. });
  24144. vue.onBeforeUnmount(() => {
  24145. scrollParent?.removeEventListener('scroll', onScroll);
  24146. });
  24147. vue.watch(displayHeight, onScroll);
  24148. vue.watch(() => contentRect.value?.height, onScroll);
  24149. const scale = vue.computed(() => {
  24150. return 1 - clamp(+props.scale);
  24151. });
  24152. let frame = -1;
  24153. function onScroll() {
  24154. if (!isIntersecting.value) return;
  24155. cancelAnimationFrame(frame);
  24156. frame = requestAnimationFrame(() => {
  24157. const el = (root.value?.$el).querySelector('.v-img__img');
  24158. if (!el) return;
  24159. const scrollHeight = scrollParent instanceof Document ? document.documentElement.clientHeight : scrollParent.clientHeight;
  24160. const scrollPos = scrollParent instanceof Document ? window.scrollY : scrollParent.scrollTop;
  24161. const top = intersectionRef.value.getBoundingClientRect().top + scrollPos;
  24162. const height = contentRect.value.height;
  24163. const center = top + (height - scrollHeight) / 2;
  24164. const translate = floor((scrollPos - center) * scale.value);
  24165. const sizeScale = Math.max(1, (scale.value * (scrollHeight - height) + height) / height);
  24166. el.style.setProperty('transform', `translateY(${translate}px) scale(${sizeScale})`);
  24167. });
  24168. }
  24169. useRender(() => vue.createVNode(VImg, {
  24170. "class": ['v-parallax', {
  24171. 'v-parallax--active': isIntersecting.value
  24172. }, props.class],
  24173. "style": props.style,
  24174. "ref": root,
  24175. "cover": true,
  24176. "onLoadstart": onScroll,
  24177. "onLoad": onScroll
  24178. }, slots));
  24179. return {};
  24180. }
  24181. });
  24182. // Types
  24183. const makeVRadioProps = propsFactory({
  24184. ...makeVSelectionControlProps({
  24185. falseIcon: '$radioOff',
  24186. trueIcon: '$radioOn'
  24187. })
  24188. }, 'VRadio');
  24189. const VRadio = genericComponent()({
  24190. name: 'VRadio',
  24191. props: makeVRadioProps(),
  24192. setup(props, _ref) {
  24193. let {
  24194. slots
  24195. } = _ref;
  24196. useRender(() => {
  24197. const controlProps = VSelectionControl.filterProps(props);
  24198. return vue.createVNode(VSelectionControl, vue.mergeProps(controlProps, {
  24199. "class": ['v-radio', props.class],
  24200. "style": props.style,
  24201. "type": "radio"
  24202. }), slots);
  24203. });
  24204. return {};
  24205. }
  24206. });
  24207. // Types
  24208. const makeVRadioGroupProps = propsFactory({
  24209. height: {
  24210. type: [Number, String],
  24211. default: 'auto'
  24212. },
  24213. ...makeVInputProps(),
  24214. ...omit(makeSelectionControlGroupProps(), ['multiple']),
  24215. trueIcon: {
  24216. type: IconValue,
  24217. default: '$radioOn'
  24218. },
  24219. falseIcon: {
  24220. type: IconValue,
  24221. default: '$radioOff'
  24222. },
  24223. type: {
  24224. type: String,
  24225. default: 'radio'
  24226. }
  24227. }, 'VRadioGroup');
  24228. const VRadioGroup = genericComponent()({
  24229. name: 'VRadioGroup',
  24230. inheritAttrs: false,
  24231. props: makeVRadioGroupProps(),
  24232. emits: {
  24233. 'update:modelValue': value => true
  24234. },
  24235. setup(props, _ref) {
  24236. let {
  24237. attrs,
  24238. slots
  24239. } = _ref;
  24240. const uid = getUid();
  24241. const id = vue.computed(() => props.id || `radio-group-${uid}`);
  24242. const model = useProxiedModel(props, 'modelValue');
  24243. useRender(() => {
  24244. const [rootAttrs, controlAttrs] = filterInputAttrs(attrs);
  24245. const inputProps = VInput.filterProps(props);
  24246. const controlProps = VSelectionControl.filterProps(props);
  24247. const label = slots.label ? slots.label({
  24248. label: props.label,
  24249. props: {
  24250. for: id.value
  24251. }
  24252. }) : props.label;
  24253. return vue.createVNode(VInput, vue.mergeProps({
  24254. "class": ['v-radio-group', props.class],
  24255. "style": props.style
  24256. }, rootAttrs, inputProps, {
  24257. "modelValue": model.value,
  24258. "onUpdate:modelValue": $event => model.value = $event,
  24259. "id": id.value
  24260. }), {
  24261. ...slots,
  24262. default: _ref2 => {
  24263. let {
  24264. id,
  24265. messagesId,
  24266. isDisabled,
  24267. isReadonly
  24268. } = _ref2;
  24269. return vue.createVNode(vue.Fragment, null, [label && vue.createVNode(VLabel, {
  24270. "id": id.value
  24271. }, {
  24272. default: () => [label]
  24273. }), vue.createVNode(VSelectionControlGroup, vue.mergeProps(controlProps, {
  24274. "id": id.value,
  24275. "aria-describedby": messagesId.value,
  24276. "defaultsTarget": "VRadio",
  24277. "trueIcon": props.trueIcon,
  24278. "falseIcon": props.falseIcon,
  24279. "type": props.type,
  24280. "disabled": isDisabled.value,
  24281. "readonly": isReadonly.value,
  24282. "aria-labelledby": label ? id.value : undefined,
  24283. "multiple": false
  24284. }, controlAttrs, {
  24285. "modelValue": model.value,
  24286. "onUpdate:modelValue": $event => model.value = $event
  24287. }), slots)]);
  24288. }
  24289. });
  24290. });
  24291. return {};
  24292. }
  24293. });
  24294. // Types
  24295. const makeVRangeSliderProps = propsFactory({
  24296. ...makeFocusProps(),
  24297. ...makeVInputProps(),
  24298. ...makeSliderProps(),
  24299. strict: Boolean,
  24300. modelValue: {
  24301. type: Array,
  24302. default: () => [0, 0]
  24303. }
  24304. }, 'VRangeSlider');
  24305. const VRangeSlider = genericComponent()({
  24306. name: 'VRangeSlider',
  24307. props: makeVRangeSliderProps(),
  24308. emits: {
  24309. 'update:focused': value => true,
  24310. 'update:modelValue': value => true,
  24311. end: value => true,
  24312. start: value => true
  24313. },
  24314. setup(props, _ref) {
  24315. let {
  24316. slots,
  24317. emit
  24318. } = _ref;
  24319. const startThumbRef = vue.ref();
  24320. const stopThumbRef = vue.ref();
  24321. const inputRef = vue.ref();
  24322. const {
  24323. rtlClasses
  24324. } = useRtl();
  24325. function getActiveThumb(e) {
  24326. if (!startThumbRef.value || !stopThumbRef.value) return;
  24327. const startOffset = getOffset(e, startThumbRef.value.$el, props.direction);
  24328. const stopOffset = getOffset(e, stopThumbRef.value.$el, props.direction);
  24329. const a = Math.abs(startOffset);
  24330. const b = Math.abs(stopOffset);
  24331. return a < b || a === b && startOffset < 0 ? startThumbRef.value.$el : stopThumbRef.value.$el;
  24332. }
  24333. const steps = useSteps(props);
  24334. const model = useProxiedModel(props, 'modelValue', undefined, arr => {
  24335. if (!arr?.length) return [0, 0];
  24336. return arr.map(value => steps.roundValue(value));
  24337. });
  24338. const {
  24339. activeThumbRef,
  24340. hasLabels,
  24341. max,
  24342. min,
  24343. mousePressed,
  24344. onSliderMousedown,
  24345. onSliderTouchstart,
  24346. position,
  24347. trackContainerRef,
  24348. readonly
  24349. } = useSlider({
  24350. props,
  24351. steps,
  24352. onSliderStart: () => {
  24353. emit('start', model.value);
  24354. },
  24355. onSliderEnd: _ref2 => {
  24356. let {
  24357. value
  24358. } = _ref2;
  24359. const newValue = activeThumbRef.value === startThumbRef.value?.$el ? [value, model.value[1]] : [model.value[0], value];
  24360. if (!props.strict && newValue[0] < newValue[1]) {
  24361. model.value = newValue;
  24362. }
  24363. emit('end', model.value);
  24364. },
  24365. onSliderMove: _ref3 => {
  24366. let {
  24367. value
  24368. } = _ref3;
  24369. const [start, stop] = model.value;
  24370. if (!props.strict && start === stop && start !== min.value) {
  24371. activeThumbRef.value = value > start ? stopThumbRef.value?.$el : startThumbRef.value?.$el;
  24372. activeThumbRef.value?.focus();
  24373. }
  24374. if (activeThumbRef.value === startThumbRef.value?.$el) {
  24375. model.value = [Math.min(value, stop), stop];
  24376. } else {
  24377. model.value = [start, Math.max(start, value)];
  24378. }
  24379. },
  24380. getActiveThumb
  24381. });
  24382. const {
  24383. isFocused,
  24384. focus,
  24385. blur
  24386. } = useFocus(props);
  24387. const trackStart = vue.computed(() => position(model.value[0]));
  24388. const trackStop = vue.computed(() => position(model.value[1]));
  24389. useRender(() => {
  24390. const inputProps = VInput.filterProps(props);
  24391. const hasPrepend = !!(props.label || slots.label || slots.prepend);
  24392. return vue.createVNode(VInput, vue.mergeProps({
  24393. "class": ['v-slider', 'v-range-slider', {
  24394. 'v-slider--has-labels': !!slots['tick-label'] || hasLabels.value,
  24395. 'v-slider--focused': isFocused.value,
  24396. 'v-slider--pressed': mousePressed.value,
  24397. 'v-slider--disabled': props.disabled
  24398. }, rtlClasses.value, props.class],
  24399. "style": props.style,
  24400. "ref": inputRef
  24401. }, inputProps, {
  24402. "focused": isFocused.value
  24403. }), {
  24404. ...slots,
  24405. prepend: hasPrepend ? slotProps => vue.createVNode(vue.Fragment, null, [slots.label?.(slotProps) ?? (props.label ? vue.createVNode(VLabel, {
  24406. "class": "v-slider__label",
  24407. "text": props.label
  24408. }, null) : undefined), slots.prepend?.(slotProps)]) : undefined,
  24409. default: _ref4 => {
  24410. let {
  24411. id,
  24412. messagesId
  24413. } = _ref4;
  24414. return vue.createVNode("div", {
  24415. "class": "v-slider__container",
  24416. "onMousedown": !readonly.value ? onSliderMousedown : undefined,
  24417. "onTouchstartPassive": !readonly.value ? onSliderTouchstart : undefined
  24418. }, [vue.createVNode("input", {
  24419. "id": `${id.value}_start`,
  24420. "name": props.name || id.value,
  24421. "disabled": !!props.disabled,
  24422. "readonly": !!props.readonly,
  24423. "tabindex": "-1",
  24424. "value": model.value[0]
  24425. }, null), vue.createVNode("input", {
  24426. "id": `${id.value}_stop`,
  24427. "name": props.name || id.value,
  24428. "disabled": !!props.disabled,
  24429. "readonly": !!props.readonly,
  24430. "tabindex": "-1",
  24431. "value": model.value[1]
  24432. }, null), vue.createVNode(VSliderTrack, {
  24433. "ref": trackContainerRef,
  24434. "start": trackStart.value,
  24435. "stop": trackStop.value
  24436. }, {
  24437. 'tick-label': slots['tick-label']
  24438. }), vue.createVNode(VSliderThumb, {
  24439. "ref": startThumbRef,
  24440. "aria-describedby": messagesId.value,
  24441. "focused": isFocused && activeThumbRef.value === startThumbRef.value?.$el,
  24442. "modelValue": model.value[0],
  24443. "onUpdate:modelValue": v => model.value = [v, model.value[1]],
  24444. "onFocus": e => {
  24445. focus();
  24446. activeThumbRef.value = startThumbRef.value?.$el;
  24447. // Make sure second thumb is focused if
  24448. // the thumbs are on top of each other
  24449. // and they are both at minimum value
  24450. // but only if focused from outside.
  24451. if (max.value !== min.value && model.value[0] === model.value[1] && model.value[1] === min.value && e.relatedTarget !== stopThumbRef.value?.$el) {
  24452. startThumbRef.value?.$el.blur();
  24453. stopThumbRef.value?.$el.focus();
  24454. }
  24455. },
  24456. "onBlur": () => {
  24457. blur();
  24458. activeThumbRef.value = undefined;
  24459. },
  24460. "min": min.value,
  24461. "max": model.value[1],
  24462. "position": trackStart.value,
  24463. "ripple": props.ripple
  24464. }, {
  24465. 'thumb-label': slots['thumb-label']
  24466. }), vue.createVNode(VSliderThumb, {
  24467. "ref": stopThumbRef,
  24468. "aria-describedby": messagesId.value,
  24469. "focused": isFocused && activeThumbRef.value === stopThumbRef.value?.$el,
  24470. "modelValue": model.value[1],
  24471. "onUpdate:modelValue": v => model.value = [model.value[0], v],
  24472. "onFocus": e => {
  24473. focus();
  24474. activeThumbRef.value = stopThumbRef.value?.$el;
  24475. // Make sure first thumb is focused if
  24476. // the thumbs are on top of each other
  24477. // and they are both at maximum value
  24478. // but only if focused from outside.
  24479. if (max.value !== min.value && model.value[0] === model.value[1] && model.value[0] === max.value && e.relatedTarget !== startThumbRef.value?.$el) {
  24480. stopThumbRef.value?.$el.blur();
  24481. startThumbRef.value?.$el.focus();
  24482. }
  24483. },
  24484. "onBlur": () => {
  24485. blur();
  24486. activeThumbRef.value = undefined;
  24487. },
  24488. "min": model.value[0],
  24489. "max": max.value,
  24490. "position": trackStop.value,
  24491. "ripple": props.ripple
  24492. }, {
  24493. 'thumb-label': slots['thumb-label']
  24494. })]);
  24495. }
  24496. });
  24497. });
  24498. return {};
  24499. }
  24500. });
  24501. // Types
  24502. const makeVRatingProps = propsFactory({
  24503. name: String,
  24504. itemAriaLabel: {
  24505. type: String,
  24506. default: '$vuetify.rating.ariaLabel.item'
  24507. },
  24508. activeColor: String,
  24509. color: String,
  24510. clearable: Boolean,
  24511. disabled: Boolean,
  24512. emptyIcon: {
  24513. type: IconValue,
  24514. default: '$ratingEmpty'
  24515. },
  24516. fullIcon: {
  24517. type: IconValue,
  24518. default: '$ratingFull'
  24519. },
  24520. halfIncrements: Boolean,
  24521. hover: Boolean,
  24522. length: {
  24523. type: [Number, String],
  24524. default: 5
  24525. },
  24526. readonly: Boolean,
  24527. modelValue: {
  24528. type: [Number, String],
  24529. default: 0
  24530. },
  24531. itemLabels: Array,
  24532. itemLabelPosition: {
  24533. type: String,
  24534. default: 'top',
  24535. validator: v => ['top', 'bottom'].includes(v)
  24536. },
  24537. ripple: Boolean,
  24538. ...makeComponentProps(),
  24539. ...makeDensityProps(),
  24540. ...makeSizeProps(),
  24541. ...makeTagProps(),
  24542. ...makeThemeProps()
  24543. }, 'VRating');
  24544. const VRating = genericComponent()({
  24545. name: 'VRating',
  24546. props: makeVRatingProps(),
  24547. emits: {
  24548. 'update:modelValue': value => true
  24549. },
  24550. setup(props, _ref) {
  24551. let {
  24552. slots
  24553. } = _ref;
  24554. const {
  24555. t
  24556. } = useLocale();
  24557. const {
  24558. themeClasses
  24559. } = provideTheme(props);
  24560. const rating = useProxiedModel(props, 'modelValue');
  24561. const normalizedValue = vue.computed(() => clamp(parseFloat(rating.value), 0, +props.length));
  24562. const range = vue.computed(() => createRange(Number(props.length), 1));
  24563. const increments = vue.computed(() => range.value.flatMap(v => props.halfIncrements ? [v - 0.5, v] : [v]));
  24564. const hoverIndex = vue.shallowRef(-1);
  24565. const itemState = vue.computed(() => increments.value.map(value => {
  24566. const isHovering = props.hover && hoverIndex.value > -1;
  24567. const isFilled = normalizedValue.value >= value;
  24568. const isHovered = hoverIndex.value >= value;
  24569. const isFullIcon = isHovering ? isHovered : isFilled;
  24570. const icon = isFullIcon ? props.fullIcon : props.emptyIcon;
  24571. const activeColor = props.activeColor ?? props.color;
  24572. const color = isFilled || isHovered ? activeColor : props.color;
  24573. return {
  24574. isFilled,
  24575. isHovered,
  24576. icon,
  24577. color
  24578. };
  24579. }));
  24580. const eventState = vue.computed(() => [0, ...increments.value].map(value => {
  24581. function onMouseenter() {
  24582. hoverIndex.value = value;
  24583. }
  24584. function onMouseleave() {
  24585. hoverIndex.value = -1;
  24586. }
  24587. function onClick() {
  24588. if (props.disabled || props.readonly) return;
  24589. rating.value = normalizedValue.value === value && props.clearable ? 0 : value;
  24590. }
  24591. return {
  24592. onMouseenter: props.hover ? onMouseenter : undefined,
  24593. onMouseleave: props.hover ? onMouseleave : undefined,
  24594. onClick
  24595. };
  24596. }));
  24597. const name = vue.computed(() => props.name ?? `v-rating-${getUid()}`);
  24598. function VRatingItem(_ref2) {
  24599. let {
  24600. value,
  24601. index,
  24602. showStar = true
  24603. } = _ref2;
  24604. const {
  24605. onMouseenter,
  24606. onMouseleave,
  24607. onClick
  24608. } = eventState.value[index + 1];
  24609. const id = `${name.value}-${String(value).replace('.', '-')}`;
  24610. const btnProps = {
  24611. color: itemState.value[index]?.color,
  24612. density: props.density,
  24613. disabled: props.disabled,
  24614. icon: itemState.value[index]?.icon,
  24615. ripple: props.ripple,
  24616. size: props.size,
  24617. variant: 'plain'
  24618. };
  24619. return vue.createVNode(vue.Fragment, null, [vue.createVNode("label", {
  24620. "for": id,
  24621. "class": {
  24622. 'v-rating__item--half': props.halfIncrements && value % 1 > 0,
  24623. 'v-rating__item--full': props.halfIncrements && value % 1 === 0
  24624. },
  24625. "onMouseenter": onMouseenter,
  24626. "onMouseleave": onMouseleave,
  24627. "onClick": onClick
  24628. }, [vue.createVNode("span", {
  24629. "class": "v-rating__hidden"
  24630. }, [t(props.itemAriaLabel, value, props.length)]), !showStar ? undefined : slots.item ? slots.item({
  24631. ...itemState.value[index],
  24632. props: btnProps,
  24633. value,
  24634. index,
  24635. rating: normalizedValue.value
  24636. }) : vue.createVNode(VBtn, vue.mergeProps({
  24637. "aria-label": t(props.itemAriaLabel, value, props.length)
  24638. }, btnProps), null)]), vue.createVNode("input", {
  24639. "class": "v-rating__hidden",
  24640. "name": name.value,
  24641. "id": id,
  24642. "type": "radio",
  24643. "value": value,
  24644. "checked": normalizedValue.value === value,
  24645. "tabindex": -1,
  24646. "readonly": props.readonly,
  24647. "disabled": props.disabled
  24648. }, null)]);
  24649. }
  24650. function createLabel(labelProps) {
  24651. if (slots['item-label']) return slots['item-label'](labelProps);
  24652. if (labelProps.label) return vue.createVNode("span", null, [labelProps.label]);
  24653. return vue.createVNode("span", null, [vue.createTextVNode("\xA0")]);
  24654. }
  24655. useRender(() => {
  24656. const hasLabels = !!props.itemLabels?.length || slots['item-label'];
  24657. return vue.createVNode(props.tag, {
  24658. "class": ['v-rating', {
  24659. 'v-rating--hover': props.hover,
  24660. 'v-rating--readonly': props.readonly
  24661. }, themeClasses.value, props.class],
  24662. "style": props.style
  24663. }, {
  24664. default: () => [vue.createVNode(VRatingItem, {
  24665. "value": 0,
  24666. "index": -1,
  24667. "showStar": false
  24668. }, null), range.value.map((value, i) => vue.createVNode("div", {
  24669. "class": "v-rating__wrapper"
  24670. }, [hasLabels && props.itemLabelPosition === 'top' ? createLabel({
  24671. value,
  24672. index: i,
  24673. label: props.itemLabels?.[i]
  24674. }) : undefined, vue.createVNode("div", {
  24675. "class": "v-rating__item"
  24676. }, [props.halfIncrements ? vue.createVNode(vue.Fragment, null, [vue.createVNode(VRatingItem, {
  24677. "value": value - 0.5,
  24678. "index": i * 2
  24679. }, null), vue.createVNode(VRatingItem, {
  24680. "value": value,
  24681. "index": i * 2 + 1
  24682. }, null)]) : vue.createVNode(VRatingItem, {
  24683. "value": value,
  24684. "index": i
  24685. }, null)]), hasLabels && props.itemLabelPosition === 'bottom' ? createLabel({
  24686. value,
  24687. index: i,
  24688. label: props.itemLabels?.[i]
  24689. }) : undefined]))]
  24690. });
  24691. });
  24692. return {};
  24693. }
  24694. });
  24695. // Types
  24696. const rootTypes = {
  24697. actions: 'button@2',
  24698. article: 'heading, paragraph',
  24699. avatar: 'avatar',
  24700. button: 'button',
  24701. card: 'image, heading',
  24702. 'card-avatar': 'image, list-item-avatar',
  24703. chip: 'chip',
  24704. 'date-picker': 'list-item, heading, divider, date-picker-options, date-picker-days, actions',
  24705. 'date-picker-options': 'text, avatar@2',
  24706. 'date-picker-days': 'avatar@28',
  24707. divider: 'divider',
  24708. heading: 'heading',
  24709. image: 'image',
  24710. 'list-item': 'text',
  24711. 'list-item-avatar': 'avatar, text',
  24712. 'list-item-two-line': 'sentences',
  24713. 'list-item-avatar-two-line': 'avatar, sentences',
  24714. 'list-item-three-line': 'paragraph',
  24715. 'list-item-avatar-three-line': 'avatar, paragraph',
  24716. ossein: 'ossein',
  24717. paragraph: 'text@3',
  24718. sentences: 'text@2',
  24719. subtitle: 'text',
  24720. table: 'table-heading, table-thead, table-tbody, table-tfoot',
  24721. 'table-heading': 'chip, text',
  24722. 'table-thead': 'heading@6',
  24723. 'table-tbody': 'table-row-divider@6',
  24724. 'table-row-divider': 'table-row, divider',
  24725. 'table-row': 'text@6',
  24726. 'table-tfoot': 'text@2, avatar@2',
  24727. text: 'text'
  24728. };
  24729. function genBone(type) {
  24730. let children = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : [];
  24731. return vue.createVNode("div", {
  24732. "class": ['v-skeleton-loader__bone', `v-skeleton-loader__${type}`]
  24733. }, [children]);
  24734. }
  24735. function genBones(bone) {
  24736. // e.g. 'text@3'
  24737. const [type, length] = bone.split('@');
  24738. // Generate a length array based upon
  24739. // value after @ in the bone string
  24740. return Array.from({
  24741. length
  24742. }).map(() => genStructure(type));
  24743. }
  24744. function genStructure(type) {
  24745. let children = [];
  24746. if (!type) return children;
  24747. // TODO: figure out a better way to type this
  24748. const bone = rootTypes[type];
  24749. // End of recursion, do nothing
  24750. /* eslint-disable-next-line no-empty, brace-style */
  24751. if (type === bone) ;
  24752. // Array of values - e.g. 'heading, paragraph, text@2'
  24753. else if (type.includes(',')) return mapBones(type);
  24754. // Array of values - e.g. 'paragraph@4'
  24755. else if (type.includes('@')) return genBones(type);
  24756. // Array of values - e.g. 'card@2'
  24757. else if (bone.includes(',')) children = mapBones(bone);
  24758. // Array of values - e.g. 'list-item@2'
  24759. else if (bone.includes('@')) children = genBones(bone);
  24760. // Single value - e.g. 'card-heading'
  24761. else if (bone) children.push(genStructure(bone));
  24762. return [genBone(type, children)];
  24763. }
  24764. function mapBones(bones) {
  24765. // Remove spaces and return array of structures
  24766. return bones.replace(/\s/g, '').split(',').map(genStructure);
  24767. }
  24768. const makeVSkeletonLoaderProps = propsFactory({
  24769. boilerplate: Boolean,
  24770. color: String,
  24771. loading: Boolean,
  24772. loadingText: {
  24773. type: String,
  24774. default: '$vuetify.loading'
  24775. },
  24776. type: {
  24777. type: [String, Array],
  24778. default: 'ossein'
  24779. },
  24780. ...makeDimensionProps(),
  24781. ...makeElevationProps(),
  24782. ...makeThemeProps()
  24783. }, 'VSkeletonLoader');
  24784. const VSkeletonLoader = genericComponent()({
  24785. name: 'VSkeletonLoader',
  24786. props: makeVSkeletonLoaderProps(),
  24787. setup(props, _ref) {
  24788. let {
  24789. slots
  24790. } = _ref;
  24791. const {
  24792. backgroundColorClasses,
  24793. backgroundColorStyles
  24794. } = useBackgroundColor(vue.toRef(props, 'color'));
  24795. const {
  24796. dimensionStyles
  24797. } = useDimension(props);
  24798. const {
  24799. elevationClasses
  24800. } = useElevation(props);
  24801. const {
  24802. themeClasses
  24803. } = provideTheme(props);
  24804. const {
  24805. t
  24806. } = useLocale();
  24807. const items = vue.computed(() => genStructure(wrapInArray(props.type).join(',')));
  24808. useRender(() => {
  24809. const isLoading = !slots.default || props.loading;
  24810. const loadingProps = props.boilerplate || !isLoading ? {} : {
  24811. ariaLive: 'polite',
  24812. ariaLabel: t(props.loadingText),
  24813. role: 'alert'
  24814. };
  24815. return vue.createVNode("div", vue.mergeProps({
  24816. "class": ['v-skeleton-loader', {
  24817. 'v-skeleton-loader--boilerplate': props.boilerplate
  24818. }, themeClasses.value, backgroundColorClasses.value, elevationClasses.value],
  24819. "style": [backgroundColorStyles.value, isLoading ? dimensionStyles.value : {}]
  24820. }, loadingProps), [isLoading ? items.value : slots.default?.()]);
  24821. });
  24822. return {};
  24823. }
  24824. });
  24825. // Composables
  24826. // Types
  24827. const VSlideGroupItem = genericComponent()({
  24828. name: 'VSlideGroupItem',
  24829. props: makeGroupItemProps(),
  24830. emits: {
  24831. 'group:selected': val => true
  24832. },
  24833. setup(props, _ref) {
  24834. let {
  24835. slots
  24836. } = _ref;
  24837. const slideGroupItem = useGroupItem(props, VSlideGroupSymbol);
  24838. return () => slots.default?.({
  24839. isSelected: slideGroupItem.isSelected.value,
  24840. select: slideGroupItem.select,
  24841. toggle: slideGroupItem.toggle,
  24842. selectedClass: slideGroupItem.selectedClass.value
  24843. });
  24844. }
  24845. });
  24846. // Types
  24847. function useCountdown(milliseconds) {
  24848. const time = vue.shallowRef(milliseconds());
  24849. let timer = -1;
  24850. function clear() {
  24851. clearInterval(timer);
  24852. }
  24853. function reset() {
  24854. clear();
  24855. vue.nextTick(() => time.value = milliseconds());
  24856. }
  24857. function start(el) {
  24858. const style = el ? getComputedStyle(el) : {
  24859. transitionDuration: 0.2
  24860. };
  24861. const interval = parseFloat(style.transitionDuration) * 1000 || 200;
  24862. clear();
  24863. if (time.value <= 0) return;
  24864. const startTime = performance.now();
  24865. timer = window.setInterval(() => {
  24866. const elapsed = performance.now() - startTime + interval;
  24867. time.value = Math.max(milliseconds() - elapsed, 0);
  24868. if (time.value <= 0) clear();
  24869. }, interval);
  24870. }
  24871. vue.onScopeDispose(clear);
  24872. return {
  24873. clear,
  24874. time,
  24875. start,
  24876. reset
  24877. };
  24878. }
  24879. const makeVSnackbarProps = propsFactory({
  24880. multiLine: Boolean,
  24881. text: String,
  24882. timer: [Boolean, String],
  24883. timeout: {
  24884. type: [Number, String],
  24885. default: 5000
  24886. },
  24887. vertical: Boolean,
  24888. ...makeLocationProps({
  24889. location: 'bottom'
  24890. }),
  24891. ...makePositionProps(),
  24892. ...makeRoundedProps(),
  24893. ...makeVariantProps(),
  24894. ...makeThemeProps(),
  24895. ...omit(makeVOverlayProps({
  24896. transition: 'v-snackbar-transition'
  24897. }), ['persistent', 'noClickAnimation', 'scrim', 'scrollStrategy'])
  24898. }, 'VSnackbar');
  24899. const VSnackbar = genericComponent()({
  24900. name: 'VSnackbar',
  24901. props: makeVSnackbarProps(),
  24902. emits: {
  24903. 'update:modelValue': v => true
  24904. },
  24905. setup(props, _ref) {
  24906. let {
  24907. slots
  24908. } = _ref;
  24909. const isActive = useProxiedModel(props, 'modelValue');
  24910. const {
  24911. positionClasses
  24912. } = usePosition(props);
  24913. const {
  24914. scopeId
  24915. } = useScopeId();
  24916. const {
  24917. themeClasses
  24918. } = provideTheme(props);
  24919. const {
  24920. colorClasses,
  24921. colorStyles,
  24922. variantClasses
  24923. } = useVariant(props);
  24924. const {
  24925. roundedClasses
  24926. } = useRounded(props);
  24927. const countdown = useCountdown(() => Number(props.timeout));
  24928. const overlay = vue.ref();
  24929. const timerRef = vue.ref();
  24930. const isHovering = vue.shallowRef(false);
  24931. const startY = vue.shallowRef(0);
  24932. const mainStyles = vue.ref();
  24933. const hasLayout = vue.inject(VuetifyLayoutKey, undefined);
  24934. useToggleScope(() => !!hasLayout, () => {
  24935. const layout = useLayout();
  24936. vue.watchEffect(() => {
  24937. mainStyles.value = layout.mainStyles.value;
  24938. });
  24939. });
  24940. vue.watch(isActive, startTimeout);
  24941. vue.watch(() => props.timeout, startTimeout);
  24942. vue.onMounted(() => {
  24943. if (isActive.value) startTimeout();
  24944. });
  24945. let activeTimeout = -1;
  24946. function startTimeout() {
  24947. countdown.reset();
  24948. window.clearTimeout(activeTimeout);
  24949. const timeout = Number(props.timeout);
  24950. if (!isActive.value || timeout === -1) return;
  24951. const element = refElement(timerRef.value);
  24952. countdown.start(element);
  24953. activeTimeout = window.setTimeout(() => {
  24954. isActive.value = false;
  24955. }, timeout);
  24956. }
  24957. function clearTimeout() {
  24958. countdown.reset();
  24959. window.clearTimeout(activeTimeout);
  24960. }
  24961. function onPointerenter() {
  24962. isHovering.value = true;
  24963. clearTimeout();
  24964. }
  24965. function onPointerleave() {
  24966. isHovering.value = false;
  24967. startTimeout();
  24968. }
  24969. function onTouchstart(event) {
  24970. startY.value = event.touches[0].clientY;
  24971. }
  24972. function onTouchend(event) {
  24973. if (Math.abs(startY.value - event.changedTouches[0].clientY) > 50) {
  24974. isActive.value = false;
  24975. }
  24976. }
  24977. function onAfterLeave() {
  24978. if (isHovering.value) onPointerleave();
  24979. }
  24980. const locationClasses = vue.computed(() => {
  24981. return props.location.split(' ').reduce((acc, loc) => {
  24982. acc[`v-snackbar--${loc}`] = true;
  24983. return acc;
  24984. }, {});
  24985. });
  24986. useRender(() => {
  24987. const overlayProps = VOverlay.filterProps(props);
  24988. const hasContent = !!(slots.default || slots.text || props.text);
  24989. return vue.createVNode(VOverlay, vue.mergeProps({
  24990. "ref": overlay,
  24991. "class": ['v-snackbar', {
  24992. 'v-snackbar--active': isActive.value,
  24993. 'v-snackbar--multi-line': props.multiLine && !props.vertical,
  24994. 'v-snackbar--timer': !!props.timer,
  24995. 'v-snackbar--vertical': props.vertical
  24996. }, locationClasses.value, positionClasses.value, props.class],
  24997. "style": [mainStyles.value, props.style]
  24998. }, overlayProps, {
  24999. "modelValue": isActive.value,
  25000. "onUpdate:modelValue": $event => isActive.value = $event,
  25001. "contentProps": vue.mergeProps({
  25002. class: ['v-snackbar__wrapper', themeClasses.value, colorClasses.value, roundedClasses.value, variantClasses.value],
  25003. style: [colorStyles.value],
  25004. onPointerenter,
  25005. onPointerleave
  25006. }, overlayProps.contentProps),
  25007. "persistent": true,
  25008. "noClickAnimation": true,
  25009. "scrim": false,
  25010. "scrollStrategy": "none",
  25011. "_disableGlobalStack": true,
  25012. "onTouchstartPassive": onTouchstart,
  25013. "onTouchend": onTouchend,
  25014. "onAfterLeave": onAfterLeave
  25015. }, scopeId), {
  25016. default: () => [genOverlays(false, 'v-snackbar'), props.timer && !isHovering.value && vue.createVNode("div", {
  25017. "key": "timer",
  25018. "class": "v-snackbar__timer"
  25019. }, [vue.createVNode(VProgressLinear, {
  25020. "ref": timerRef,
  25021. "color": typeof props.timer === 'string' ? props.timer : 'info',
  25022. "max": props.timeout,
  25023. "model-value": countdown.time.value
  25024. }, null)]), hasContent && vue.createVNode("div", {
  25025. "key": "content",
  25026. "class": "v-snackbar__content",
  25027. "role": "status",
  25028. "aria-live": "polite"
  25029. }, [slots.text?.() ?? props.text, slots.default?.()]), slots.actions && vue.createVNode(VDefaultsProvider, {
  25030. "defaults": {
  25031. VBtn: {
  25032. variant: 'text',
  25033. ripple: false,
  25034. slim: true
  25035. }
  25036. }
  25037. }, {
  25038. default: () => [vue.createVNode("div", {
  25039. "class": "v-snackbar__actions"
  25040. }, [slots.actions({
  25041. isActive
  25042. })])]
  25043. })],
  25044. activator: slots.activator
  25045. });
  25046. });
  25047. return forwardRefs({}, overlay);
  25048. }
  25049. });
  25050. // Utilities
  25051. // Types
  25052. const makeLineProps = propsFactory({
  25053. autoDraw: Boolean,
  25054. autoDrawDuration: [Number, String],
  25055. autoDrawEasing: {
  25056. type: String,
  25057. default: 'ease'
  25058. },
  25059. color: String,
  25060. gradient: {
  25061. type: Array,
  25062. default: () => []
  25063. },
  25064. gradientDirection: {
  25065. type: String,
  25066. validator: val => ['top', 'bottom', 'left', 'right'].includes(val),
  25067. default: 'top'
  25068. },
  25069. height: {
  25070. type: [String, Number],
  25071. default: 75
  25072. },
  25073. labels: {
  25074. type: Array,
  25075. default: () => []
  25076. },
  25077. labelSize: {
  25078. type: [Number, String],
  25079. default: 7
  25080. },
  25081. lineWidth: {
  25082. type: [String, Number],
  25083. default: 4
  25084. },
  25085. id: String,
  25086. itemValue: {
  25087. type: String,
  25088. default: 'value'
  25089. },
  25090. modelValue: {
  25091. type: Array,
  25092. default: () => []
  25093. },
  25094. min: [String, Number],
  25095. max: [String, Number],
  25096. padding: {
  25097. type: [String, Number],
  25098. default: 8
  25099. },
  25100. showLabels: Boolean,
  25101. smooth: Boolean,
  25102. width: {
  25103. type: [Number, String],
  25104. default: 300
  25105. }
  25106. }, 'Line');
  25107. // Types
  25108. const makeVBarlineProps = propsFactory({
  25109. autoLineWidth: Boolean,
  25110. ...makeLineProps()
  25111. }, 'VBarline');
  25112. const VBarline = genericComponent()({
  25113. name: 'VBarline',
  25114. props: makeVBarlineProps(),
  25115. setup(props, _ref) {
  25116. let {
  25117. slots
  25118. } = _ref;
  25119. const uid = getUid();
  25120. const id = vue.computed(() => props.id || `barline-${uid}`);
  25121. const autoDrawDuration = vue.computed(() => Number(props.autoDrawDuration) || 500);
  25122. const hasLabels = vue.computed(() => {
  25123. return Boolean(props.showLabels || props.labels.length > 0 || !!slots?.label);
  25124. });
  25125. const lineWidth = vue.computed(() => parseFloat(props.lineWidth) || 4);
  25126. const totalWidth = vue.computed(() => Math.max(props.modelValue.length * lineWidth.value, Number(props.width)));
  25127. const boundary = vue.computed(() => {
  25128. return {
  25129. minX: 0,
  25130. maxX: totalWidth.value,
  25131. minY: 0,
  25132. maxY: parseInt(props.height, 10)
  25133. };
  25134. });
  25135. const items = vue.computed(() => props.modelValue.map(item => getPropertyFromItem(item, props.itemValue, item)));
  25136. function genBars(values, boundary) {
  25137. const {
  25138. minX,
  25139. maxX,
  25140. minY,
  25141. maxY
  25142. } = boundary;
  25143. const totalValues = values.length;
  25144. let maxValue = props.max != null ? Number(props.max) : Math.max(...values);
  25145. let minValue = props.min != null ? Number(props.min) : Math.min(...values);
  25146. if (minValue > 0 && props.min == null) minValue = 0;
  25147. if (maxValue < 0 && props.max == null) maxValue = 0;
  25148. const gridX = maxX / totalValues;
  25149. const gridY = (maxY - minY) / (maxValue - minValue || 1);
  25150. const horizonY = maxY - Math.abs(minValue * gridY);
  25151. return values.map((value, index) => {
  25152. const height = Math.abs(gridY * value);
  25153. return {
  25154. x: minX + index * gridX,
  25155. y: horizonY - height + +(value < 0) * height,
  25156. height,
  25157. value
  25158. };
  25159. });
  25160. }
  25161. const parsedLabels = vue.computed(() => {
  25162. const labels = [];
  25163. const points = genBars(items.value, boundary.value);
  25164. const len = points.length;
  25165. for (let i = 0; labels.length < len; i++) {
  25166. const item = points[i];
  25167. let value = props.labels[i];
  25168. if (!value) {
  25169. value = typeof item === 'object' ? item.value : item;
  25170. }
  25171. labels.push({
  25172. x: item.x,
  25173. value: String(value)
  25174. });
  25175. }
  25176. return labels;
  25177. });
  25178. const bars = vue.computed(() => genBars(items.value, boundary.value));
  25179. const offsetX = vue.computed(() => (Math.abs(bars.value[0].x - bars.value[1].x) - lineWidth.value) / 2);
  25180. useRender(() => {
  25181. const gradientData = !props.gradient.slice().length ? [''] : props.gradient.slice().reverse();
  25182. return vue.createVNode("svg", {
  25183. "display": "block"
  25184. }, [vue.createVNode("defs", null, [vue.createVNode("linearGradient", {
  25185. "id": id.value,
  25186. "gradientUnits": "userSpaceOnUse",
  25187. "x1": props.gradientDirection === 'left' ? '100%' : '0',
  25188. "y1": props.gradientDirection === 'top' ? '100%' : '0',
  25189. "x2": props.gradientDirection === 'right' ? '100%' : '0',
  25190. "y2": props.gradientDirection === 'bottom' ? '100%' : '0'
  25191. }, [gradientData.map((color, index) => vue.createVNode("stop", {
  25192. "offset": index / Math.max(gradientData.length - 1, 1),
  25193. "stop-color": color || 'currentColor'
  25194. }, null))])]), vue.createVNode("clipPath", {
  25195. "id": `${id.value}-clip`
  25196. }, [bars.value.map(item => vue.createVNode("rect", {
  25197. "x": item.x + offsetX.value,
  25198. "y": item.y,
  25199. "width": lineWidth.value,
  25200. "height": item.height,
  25201. "rx": typeof props.smooth === 'number' ? props.smooth : props.smooth ? 2 : 0,
  25202. "ry": typeof props.smooth === 'number' ? props.smooth : props.smooth ? 2 : 0
  25203. }, [props.autoDraw && vue.createVNode(vue.Fragment, null, [vue.createVNode("animate", {
  25204. "attributeName": "y",
  25205. "from": item.y + item.height,
  25206. "to": item.y,
  25207. "dur": `${autoDrawDuration.value}ms`,
  25208. "fill": "freeze"
  25209. }, null), vue.createVNode("animate", {
  25210. "attributeName": "height",
  25211. "from": "0",
  25212. "to": item.height,
  25213. "dur": `${autoDrawDuration.value}ms`,
  25214. "fill": "freeze"
  25215. }, null)])]))]), hasLabels.value && vue.createVNode("g", {
  25216. "key": "labels",
  25217. "style": {
  25218. textAnchor: 'middle',
  25219. dominantBaseline: 'mathematical',
  25220. fill: 'currentColor'
  25221. }
  25222. }, [parsedLabels.value.map((item, i) => vue.createVNode("text", {
  25223. "x": item.x + offsetX.value + lineWidth.value / 2,
  25224. "y": parseInt(props.height, 10) - 2 + (parseInt(props.labelSize, 10) || 7 * 0.75),
  25225. "font-size": Number(props.labelSize) || 7
  25226. }, [slots.label?.({
  25227. index: i,
  25228. value: item.value
  25229. }) ?? item.value]))]), vue.createVNode("g", {
  25230. "clip-path": `url(#${id.value}-clip)`,
  25231. "fill": `url(#${id.value})`
  25232. }, [vue.createVNode("rect", {
  25233. "x": 0,
  25234. "y": 0,
  25235. "width": Math.max(props.modelValue.length * lineWidth.value, Number(props.width)),
  25236. "height": props.height
  25237. }, null)])]);
  25238. });
  25239. }
  25240. });
  25241. // @ts-nocheck
  25242. /* eslint-disable */
  25243. // import { checkCollinear, getDistance, moveTo } from './math'
  25244. /**
  25245. * From https://github.com/unsplash/react-trend/blob/master/src/helpers/DOM.helpers.js#L18
  25246. */
  25247. function genPath(points, radius) {
  25248. let fill = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : false;
  25249. let height = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : 75;
  25250. if (points.length === 0) return '';
  25251. const start = points.shift();
  25252. const end = points[points.length - 1];
  25253. return (fill ? `M${start.x} ${height - start.x + 2} L${start.x} ${start.y}` : `M${start.x} ${start.y}`) + points.map((point, index) => {
  25254. const next = points[index + 1];
  25255. const prev = points[index - 1] || start;
  25256. const isCollinear = next && checkCollinear(next, point, prev);
  25257. if (!next || isCollinear) {
  25258. return `L${point.x} ${point.y}`;
  25259. }
  25260. const threshold = Math.min(getDistance(prev, point), getDistance(next, point));
  25261. const isTooCloseForRadius = threshold / 2 < radius;
  25262. const radiusForPoint = isTooCloseForRadius ? threshold / 2 : radius;
  25263. const before = moveTo(prev, point, radiusForPoint);
  25264. const after = moveTo(next, point, radiusForPoint);
  25265. return `L${before.x} ${before.y}S${point.x} ${point.y} ${after.x} ${after.y}`;
  25266. }).join('') + (fill ? `L${end.x} ${height - start.x + 2} Z` : '');
  25267. }
  25268. function int(value) {
  25269. return parseInt(value, 10);
  25270. }
  25271. /**
  25272. * https://en.wikipedia.org/wiki/Collinearity
  25273. * x=(x1+x2)/2
  25274. * y=(y1+y2)/2
  25275. */
  25276. function checkCollinear(p0, p1, p2) {
  25277. return int(p0.x + p2.x) === int(2 * p1.x) && int(p0.y + p2.y) === int(2 * p1.y);
  25278. }
  25279. function getDistance(p1, p2) {
  25280. return Math.sqrt(Math.pow(p2.x - p1.x, 2) + Math.pow(p2.y - p1.y, 2));
  25281. }
  25282. function moveTo(to, from, radius) {
  25283. const vector = {
  25284. x: to.x - from.x,
  25285. y: to.y - from.y
  25286. };
  25287. const length = Math.sqrt(vector.x * vector.x + vector.y * vector.y);
  25288. const unitVector = {
  25289. x: vector.x / length,
  25290. y: vector.y / length
  25291. };
  25292. return {
  25293. x: from.x + unitVector.x * radius,
  25294. y: from.y + unitVector.y * radius
  25295. };
  25296. }
  25297. // Types
  25298. const makeVTrendlineProps = propsFactory({
  25299. fill: Boolean,
  25300. ...makeLineProps()
  25301. }, 'VTrendline');
  25302. const VTrendline = genericComponent()({
  25303. name: 'VTrendline',
  25304. props: makeVTrendlineProps(),
  25305. setup(props, _ref) {
  25306. let {
  25307. slots
  25308. } = _ref;
  25309. const uid = getUid();
  25310. const id = vue.computed(() => props.id || `trendline-${uid}`);
  25311. const autoDrawDuration = vue.computed(() => Number(props.autoDrawDuration) || (props.fill ? 500 : 2000));
  25312. const lastLength = vue.ref(0);
  25313. const path = vue.ref(null);
  25314. function genPoints(values, boundary) {
  25315. const {
  25316. minX,
  25317. maxX,
  25318. minY,
  25319. maxY
  25320. } = boundary;
  25321. const totalValues = values.length;
  25322. const maxValue = props.max != null ? Number(props.max) : Math.max(...values);
  25323. const minValue = props.min != null ? Number(props.min) : Math.min(...values);
  25324. const gridX = (maxX - minX) / (totalValues - 1);
  25325. const gridY = (maxY - minY) / (maxValue - minValue || 1);
  25326. return values.map((value, index) => {
  25327. return {
  25328. x: minX + index * gridX,
  25329. y: maxY - (value - minValue) * gridY,
  25330. value
  25331. };
  25332. });
  25333. }
  25334. const hasLabels = vue.computed(() => {
  25335. return Boolean(props.showLabels || props.labels.length > 0 || !!slots?.label);
  25336. });
  25337. const lineWidth = vue.computed(() => {
  25338. return parseFloat(props.lineWidth) || 4;
  25339. });
  25340. const totalWidth = vue.computed(() => Number(props.width));
  25341. const boundary = vue.computed(() => {
  25342. const padding = Number(props.padding);
  25343. return {
  25344. minX: padding,
  25345. maxX: totalWidth.value - padding,
  25346. minY: padding,
  25347. maxY: parseInt(props.height, 10) - padding
  25348. };
  25349. });
  25350. const items = vue.computed(() => props.modelValue.map(item => getPropertyFromItem(item, props.itemValue, item)));
  25351. const parsedLabels = vue.computed(() => {
  25352. const labels = [];
  25353. const points = genPoints(items.value, boundary.value);
  25354. const len = points.length;
  25355. for (let i = 0; labels.length < len; i++) {
  25356. const item = points[i];
  25357. let value = props.labels[i];
  25358. if (!value) {
  25359. value = typeof item === 'object' ? item.value : item;
  25360. }
  25361. labels.push({
  25362. x: item.x,
  25363. value: String(value)
  25364. });
  25365. }
  25366. return labels;
  25367. });
  25368. vue.watch(() => props.modelValue, async () => {
  25369. await vue.nextTick();
  25370. if (!props.autoDraw || !path.value) return;
  25371. const pathRef = path.value;
  25372. const length = pathRef.getTotalLength();
  25373. if (!props.fill) {
  25374. // Initial setup to "hide" the line by using the stroke dash array
  25375. pathRef.style.strokeDasharray = `${length}`;
  25376. pathRef.style.strokeDashoffset = `${length}`;
  25377. // Force reflow to ensure the transition starts from this state
  25378. pathRef.getBoundingClientRect();
  25379. // Animate the stroke dash offset to "draw" the line
  25380. pathRef.style.transition = `stroke-dashoffset ${autoDrawDuration.value}ms ${props.autoDrawEasing}`;
  25381. pathRef.style.strokeDashoffset = '0';
  25382. } else {
  25383. // Your existing logic for filled paths remains the same
  25384. pathRef.style.transformOrigin = 'bottom center';
  25385. pathRef.style.transition = 'none';
  25386. pathRef.style.transform = `scaleY(0)`;
  25387. pathRef.getBoundingClientRect();
  25388. pathRef.style.transition = `transform ${autoDrawDuration.value}ms ${props.autoDrawEasing}`;
  25389. pathRef.style.transform = `scaleY(1)`;
  25390. }
  25391. lastLength.value = length;
  25392. }, {
  25393. immediate: true
  25394. });
  25395. function genPath$1(fill) {
  25396. return genPath(genPoints(items.value, boundary.value), props.smooth ? 8 : Number(props.smooth), fill, parseInt(props.height, 10));
  25397. }
  25398. useRender(() => {
  25399. const gradientData = !props.gradient.slice().length ? [''] : props.gradient.slice().reverse();
  25400. return vue.createVNode("svg", {
  25401. "display": "block",
  25402. "stroke-width": parseFloat(props.lineWidth) ?? 4
  25403. }, [vue.createVNode("defs", null, [vue.createVNode("linearGradient", {
  25404. "id": id.value,
  25405. "gradientUnits": "userSpaceOnUse",
  25406. "x1": props.gradientDirection === 'left' ? '100%' : '0',
  25407. "y1": props.gradientDirection === 'top' ? '100%' : '0',
  25408. "x2": props.gradientDirection === 'right' ? '100%' : '0',
  25409. "y2": props.gradientDirection === 'bottom' ? '100%' : '0'
  25410. }, [gradientData.map((color, index) => vue.createVNode("stop", {
  25411. "offset": index / Math.max(gradientData.length - 1, 1),
  25412. "stop-color": color || 'currentColor'
  25413. }, null))])]), hasLabels.value && vue.createVNode("g", {
  25414. "key": "labels",
  25415. "style": {
  25416. textAnchor: 'middle',
  25417. dominantBaseline: 'mathematical',
  25418. fill: 'currentColor'
  25419. }
  25420. }, [parsedLabels.value.map((item, i) => vue.createVNode("text", {
  25421. "x": item.x + lineWidth.value / 2 + lineWidth.value / 2,
  25422. "y": parseInt(props.height, 10) - 4 + (parseInt(props.labelSize, 10) || 7 * 0.75),
  25423. "font-size": Number(props.labelSize) || 7
  25424. }, [slots.label?.({
  25425. index: i,
  25426. value: item.value
  25427. }) ?? item.value]))]), vue.createVNode("path", {
  25428. "ref": path,
  25429. "d": genPath$1(props.fill),
  25430. "fill": props.fill ? `url(#${id.value})` : 'none',
  25431. "stroke": props.fill ? 'none' : `url(#${id.value})`
  25432. }, null), props.fill && vue.createVNode("path", {
  25433. "d": genPath$1(false),
  25434. "fill": "none",
  25435. "stroke": props.color ?? props.gradient?.[0]
  25436. }, null)]);
  25437. });
  25438. }
  25439. });
  25440. // Types
  25441. // Types
  25442. const makeVSparklineProps = propsFactory({
  25443. type: {
  25444. type: String,
  25445. default: 'trend'
  25446. },
  25447. ...makeVBarlineProps(),
  25448. ...makeVTrendlineProps()
  25449. }, 'VSparkline');
  25450. const VSparkline = genericComponent()({
  25451. name: 'VSparkline',
  25452. props: makeVSparklineProps(),
  25453. setup(props, _ref) {
  25454. let {
  25455. slots
  25456. } = _ref;
  25457. const {
  25458. textColorClasses,
  25459. textColorStyles
  25460. } = useTextColor(vue.toRef(props, 'color'));
  25461. const hasLabels = vue.computed(() => {
  25462. return Boolean(props.showLabels || props.labels.length > 0 || !!slots?.label);
  25463. });
  25464. const totalHeight = vue.computed(() => {
  25465. let height = parseInt(props.height, 10);
  25466. if (hasLabels.value) height += parseInt(props.labelSize, 10) * 1.5;
  25467. return height;
  25468. });
  25469. useRender(() => {
  25470. const Tag = props.type === 'trend' ? VTrendline : VBarline;
  25471. const lineProps = props.type === 'trend' ? VTrendline.filterProps(props) : VBarline.filterProps(props);
  25472. return vue.createVNode(Tag, vue.mergeProps({
  25473. "key": props.type,
  25474. "class": textColorClasses.value,
  25475. "style": textColorStyles.value,
  25476. "viewBox": `0 0 ${props.width} ${parseInt(totalHeight.value, 10)}`
  25477. }, lineProps), slots);
  25478. });
  25479. }
  25480. });
  25481. // Types
  25482. const makeVSpeedDialProps = propsFactory({
  25483. ...makeComponentProps(),
  25484. ...makeVMenuProps({
  25485. offset: 8,
  25486. minWidth: 0,
  25487. openDelay: 0,
  25488. closeDelay: 100,
  25489. location: 'top center',
  25490. transition: 'scale-transition'
  25491. })
  25492. }, 'VSpeedDial');
  25493. const VSpeedDial = genericComponent()({
  25494. name: 'VSpeedDial',
  25495. props: makeVSpeedDialProps(),
  25496. emits: {
  25497. 'update:modelValue': value => true
  25498. },
  25499. setup(props, _ref) {
  25500. let {
  25501. slots
  25502. } = _ref;
  25503. const model = useProxiedModel(props, 'modelValue');
  25504. const menuRef = vue.ref();
  25505. const location = vue.computed(() => {
  25506. const [y, x = 'center'] = props.location?.split(' ') ?? [];
  25507. return `${y} ${x}`;
  25508. });
  25509. const locationClasses = vue.computed(() => ({
  25510. [`v-speed-dial__content--${location.value.replace(' ', '-')}`]: true
  25511. }));
  25512. useRender(() => {
  25513. const menuProps = VMenu.filterProps(props);
  25514. return vue.createVNode(VMenu, vue.mergeProps(menuProps, {
  25515. "modelValue": model.value,
  25516. "onUpdate:modelValue": $event => model.value = $event,
  25517. "class": props.class,
  25518. "style": props.style,
  25519. "contentClass": ['v-speed-dial__content', locationClasses.value, props.contentClass],
  25520. "location": location.value,
  25521. "ref": menuRef,
  25522. "transition": "fade-transition"
  25523. }), {
  25524. ...slots,
  25525. default: slotProps => vue.createVNode(VDefaultsProvider, {
  25526. "defaults": {
  25527. VBtn: {
  25528. size: 'small'
  25529. }
  25530. }
  25531. }, {
  25532. default: () => [vue.createVNode(MaybeTransition, {
  25533. "appear": true,
  25534. "group": true,
  25535. "transition": props.transition
  25536. }, {
  25537. default: () => [slots.default?.(slotProps)]
  25538. })]
  25539. })
  25540. });
  25541. });
  25542. return {};
  25543. }
  25544. });
  25545. // Types
  25546. const VStepperSymbol = Symbol.for('vuetify:v-stepper');
  25547. // Types
  25548. const makeVStepperActionsProps = propsFactory({
  25549. color: String,
  25550. disabled: {
  25551. type: [Boolean, String],
  25552. default: false
  25553. },
  25554. prevText: {
  25555. type: String,
  25556. default: '$vuetify.stepper.prev'
  25557. },
  25558. nextText: {
  25559. type: String,
  25560. default: '$vuetify.stepper.next'
  25561. }
  25562. }, 'VStepperActions');
  25563. const VStepperActions = genericComponent()({
  25564. name: 'VStepperActions',
  25565. props: makeVStepperActionsProps(),
  25566. emits: {
  25567. 'click:prev': () => true,
  25568. 'click:next': () => true
  25569. },
  25570. setup(props, _ref) {
  25571. let {
  25572. emit,
  25573. slots
  25574. } = _ref;
  25575. const {
  25576. t
  25577. } = useLocale();
  25578. function onClickPrev() {
  25579. emit('click:prev');
  25580. }
  25581. function onClickNext() {
  25582. emit('click:next');
  25583. }
  25584. useRender(() => {
  25585. const prevSlotProps = {
  25586. onClick: onClickPrev
  25587. };
  25588. const nextSlotProps = {
  25589. onClick: onClickNext
  25590. };
  25591. return vue.createVNode("div", {
  25592. "class": "v-stepper-actions"
  25593. }, [vue.createVNode(VDefaultsProvider, {
  25594. "defaults": {
  25595. VBtn: {
  25596. disabled: ['prev', true].includes(props.disabled),
  25597. text: t(props.prevText),
  25598. variant: 'text'
  25599. }
  25600. }
  25601. }, {
  25602. default: () => [slots.prev?.({
  25603. props: prevSlotProps
  25604. }) ?? vue.createVNode(VBtn, prevSlotProps, null)]
  25605. }), vue.createVNode(VDefaultsProvider, {
  25606. "defaults": {
  25607. VBtn: {
  25608. color: props.color,
  25609. disabled: ['next', true].includes(props.disabled),
  25610. text: t(props.nextText),
  25611. variant: 'tonal'
  25612. }
  25613. }
  25614. }, {
  25615. default: () => [slots.next?.({
  25616. props: nextSlotProps
  25617. }) ?? vue.createVNode(VBtn, nextSlotProps, null)]
  25618. })]);
  25619. });
  25620. return {};
  25621. }
  25622. });
  25623. // Utilities
  25624. const VStepperHeader = createSimpleFunctional('v-stepper-header');
  25625. // Types
  25626. const makeStepperItemProps = propsFactory({
  25627. color: String,
  25628. title: String,
  25629. subtitle: String,
  25630. complete: Boolean,
  25631. completeIcon: {
  25632. type: IconValue,
  25633. default: '$complete'
  25634. },
  25635. editable: Boolean,
  25636. editIcon: {
  25637. type: IconValue,
  25638. default: '$edit'
  25639. },
  25640. error: Boolean,
  25641. errorIcon: {
  25642. type: IconValue,
  25643. default: '$error'
  25644. },
  25645. icon: IconValue,
  25646. ripple: {
  25647. type: [Boolean, Object],
  25648. default: true
  25649. },
  25650. rules: {
  25651. type: Array,
  25652. default: () => []
  25653. }
  25654. }, 'StepperItem');
  25655. const makeVStepperItemProps = propsFactory({
  25656. ...makeStepperItemProps(),
  25657. ...makeGroupItemProps()
  25658. }, 'VStepperItem');
  25659. const VStepperItem = genericComponent()({
  25660. name: 'VStepperItem',
  25661. directives: {
  25662. Ripple
  25663. },
  25664. props: makeVStepperItemProps(),
  25665. emits: {
  25666. 'group:selected': val => true
  25667. },
  25668. setup(props, _ref) {
  25669. let {
  25670. slots
  25671. } = _ref;
  25672. const group = useGroupItem(props, VStepperSymbol, true);
  25673. const step = vue.computed(() => group?.value.value ?? props.value);
  25674. const isValid = vue.computed(() => props.rules.every(handler => handler() === true));
  25675. const isClickable = vue.computed(() => !props.disabled && props.editable);
  25676. const canEdit = vue.computed(() => !props.disabled && props.editable);
  25677. const hasError = vue.computed(() => props.error || !isValid.value);
  25678. const hasCompleted = vue.computed(() => props.complete || props.rules.length > 0 && isValid.value);
  25679. const icon = vue.computed(() => {
  25680. if (hasError.value) return props.errorIcon;
  25681. if (hasCompleted.value) return props.completeIcon;
  25682. if (group.isSelected.value && props.editable) return props.editIcon;
  25683. return props.icon;
  25684. });
  25685. const slotProps = vue.computed(() => ({
  25686. canEdit: canEdit.value,
  25687. hasError: hasError.value,
  25688. hasCompleted: hasCompleted.value,
  25689. title: props.title,
  25690. subtitle: props.subtitle,
  25691. step: step.value,
  25692. value: props.value
  25693. }));
  25694. useRender(() => {
  25695. const hasColor = (!group || group.isSelected.value || hasCompleted.value || canEdit.value) && !hasError.value && !props.disabled;
  25696. const hasTitle = !!(props.title != null || slots.title);
  25697. const hasSubtitle = !!(props.subtitle != null || slots.subtitle);
  25698. function onClick() {
  25699. group?.toggle();
  25700. }
  25701. return vue.withDirectives(vue.createVNode("button", {
  25702. "class": ['v-stepper-item', {
  25703. 'v-stepper-item--complete': hasCompleted.value,
  25704. 'v-stepper-item--disabled': props.disabled,
  25705. 'v-stepper-item--error': hasError.value
  25706. }, group?.selectedClass.value],
  25707. "disabled": !props.editable,
  25708. "onClick": onClick
  25709. }, [isClickable.value && genOverlays(true, 'v-stepper-item'), vue.createVNode(VAvatar, {
  25710. "key": "stepper-avatar",
  25711. "class": "v-stepper-item__avatar",
  25712. "color": hasColor ? props.color : undefined,
  25713. "size": 24
  25714. }, {
  25715. default: () => [slots.icon?.(slotProps.value) ?? (icon.value ? vue.createVNode(VIcon, {
  25716. "icon": icon.value
  25717. }, null) : step.value)]
  25718. }), vue.createVNode("div", {
  25719. "class": "v-stepper-item__content"
  25720. }, [hasTitle && vue.createVNode("div", {
  25721. "key": "title",
  25722. "class": "v-stepper-item__title"
  25723. }, [slots.title?.(slotProps.value) ?? props.title]), hasSubtitle && vue.createVNode("div", {
  25724. "key": "subtitle",
  25725. "class": "v-stepper-item__subtitle"
  25726. }, [slots.subtitle?.(slotProps.value) ?? props.subtitle]), slots.default?.(slotProps.value)])]), [[vue.resolveDirective("ripple"), props.ripple && props.editable, null]]);
  25727. });
  25728. return {};
  25729. }
  25730. });
  25731. const makeVStepperWindowProps = propsFactory({
  25732. ...omit(makeVWindowProps(), ['continuous', 'nextIcon', 'prevIcon', 'showArrows', 'touch', 'mandatory'])
  25733. }, 'VStepperWindow');
  25734. const VStepperWindow = genericComponent()({
  25735. name: 'VStepperWindow',
  25736. props: makeVStepperWindowProps(),
  25737. emits: {
  25738. 'update:modelValue': v => true
  25739. },
  25740. setup(props, _ref) {
  25741. let {
  25742. slots
  25743. } = _ref;
  25744. const group = vue.inject(VStepperSymbol, null);
  25745. const _model = useProxiedModel(props, 'modelValue');
  25746. const model = vue.computed({
  25747. get() {
  25748. // Always return modelValue if defined
  25749. // or if not within a VStepper group
  25750. if (_model.value != null || !group) return _model.value;
  25751. // If inside of a VStepper, find the currently selected
  25752. // item by id. Item value may be assigned by its index
  25753. return group.items.value.find(item => group.selected.value.includes(item.id))?.value;
  25754. },
  25755. set(val) {
  25756. _model.value = val;
  25757. }
  25758. });
  25759. useRender(() => {
  25760. const windowProps = VWindow.filterProps(props);
  25761. return vue.createVNode(VWindow, vue.mergeProps({
  25762. "_as": "VStepperWindow"
  25763. }, windowProps, {
  25764. "modelValue": model.value,
  25765. "onUpdate:modelValue": $event => model.value = $event,
  25766. "class": ['v-stepper-window', props.class],
  25767. "style": props.style,
  25768. "mandatory": false,
  25769. "touch": false
  25770. }), slots);
  25771. });
  25772. return {};
  25773. }
  25774. });
  25775. const makeVStepperWindowItemProps = propsFactory({
  25776. ...makeVWindowItemProps()
  25777. }, 'VStepperWindowItem');
  25778. const VStepperWindowItem = genericComponent()({
  25779. name: 'VStepperWindowItem',
  25780. props: makeVStepperWindowItemProps(),
  25781. setup(props, _ref) {
  25782. let {
  25783. slots
  25784. } = _ref;
  25785. useRender(() => {
  25786. const windowItemProps = VWindowItem.filterProps(props);
  25787. return vue.createVNode(VWindowItem, vue.mergeProps({
  25788. "_as": "VStepperWindowItem"
  25789. }, windowItemProps, {
  25790. "class": ['v-stepper-window-item', props.class],
  25791. "style": props.style
  25792. }), slots);
  25793. });
  25794. return {};
  25795. }
  25796. });
  25797. // Types
  25798. const makeStepperProps = propsFactory({
  25799. altLabels: Boolean,
  25800. bgColor: String,
  25801. completeIcon: IconValue,
  25802. editIcon: IconValue,
  25803. editable: Boolean,
  25804. errorIcon: IconValue,
  25805. hideActions: Boolean,
  25806. items: {
  25807. type: Array,
  25808. default: () => []
  25809. },
  25810. itemTitle: {
  25811. type: String,
  25812. default: 'title'
  25813. },
  25814. itemValue: {
  25815. type: String,
  25816. default: 'value'
  25817. },
  25818. nonLinear: Boolean,
  25819. flat: Boolean,
  25820. ...makeDisplayProps()
  25821. }, 'Stepper');
  25822. const makeVStepperProps = propsFactory({
  25823. ...makeStepperProps(),
  25824. ...makeGroupProps({
  25825. mandatory: 'force',
  25826. selectedClass: 'v-stepper-item--selected'
  25827. }),
  25828. ...makeVSheetProps(),
  25829. ...only(makeVStepperActionsProps(), ['prevText', 'nextText'])
  25830. }, 'VStepper');
  25831. const VStepper = genericComponent()({
  25832. name: 'VStepper',
  25833. props: makeVStepperProps(),
  25834. emits: {
  25835. 'update:modelValue': v => true
  25836. },
  25837. setup(props, _ref) {
  25838. let {
  25839. slots
  25840. } = _ref;
  25841. const {
  25842. items: _items,
  25843. next,
  25844. prev,
  25845. selected
  25846. } = useGroup(props, VStepperSymbol);
  25847. const {
  25848. displayClasses,
  25849. mobile
  25850. } = useDisplay(props);
  25851. const {
  25852. completeIcon,
  25853. editIcon,
  25854. errorIcon,
  25855. color,
  25856. editable,
  25857. prevText,
  25858. nextText
  25859. } = vue.toRefs(props);
  25860. const items = vue.computed(() => props.items.map((item, index) => {
  25861. const title = getPropertyFromItem(item, props.itemTitle, item);
  25862. const value = getPropertyFromItem(item, props.itemValue, index + 1);
  25863. return {
  25864. title,
  25865. value,
  25866. raw: item
  25867. };
  25868. }));
  25869. const activeIndex = vue.computed(() => {
  25870. return _items.value.findIndex(item => selected.value.includes(item.id));
  25871. });
  25872. const disabled = vue.computed(() => {
  25873. if (props.disabled) return props.disabled;
  25874. if (activeIndex.value === 0) return 'prev';
  25875. if (activeIndex.value === _items.value.length - 1) return 'next';
  25876. return false;
  25877. });
  25878. provideDefaults({
  25879. VStepperItem: {
  25880. editable,
  25881. errorIcon,
  25882. completeIcon,
  25883. editIcon,
  25884. prevText,
  25885. nextText
  25886. },
  25887. VStepperActions: {
  25888. color,
  25889. disabled,
  25890. prevText,
  25891. nextText
  25892. }
  25893. });
  25894. useRender(() => {
  25895. const sheetProps = VSheet.filterProps(props);
  25896. const hasHeader = !!(slots.header || props.items.length);
  25897. const hasWindow = props.items.length > 0;
  25898. const hasActions = !props.hideActions && !!(hasWindow || slots.actions);
  25899. return vue.createVNode(VSheet, vue.mergeProps(sheetProps, {
  25900. "color": props.bgColor,
  25901. "class": ['v-stepper', {
  25902. 'v-stepper--alt-labels': props.altLabels,
  25903. 'v-stepper--flat': props.flat,
  25904. 'v-stepper--non-linear': props.nonLinear,
  25905. 'v-stepper--mobile': mobile.value
  25906. }, displayClasses.value, props.class],
  25907. "style": props.style
  25908. }), {
  25909. default: () => [hasHeader && vue.createVNode(VStepperHeader, {
  25910. "key": "stepper-header"
  25911. }, {
  25912. default: () => [items.value.map((_ref2, index) => {
  25913. let {
  25914. raw,
  25915. ...item
  25916. } = _ref2;
  25917. return vue.createVNode(vue.Fragment, null, [!!index && vue.createVNode(VDivider, null, null), vue.createVNode(VStepperItem, item, {
  25918. default: slots[`header-item.${item.value}`] ?? slots.header,
  25919. icon: slots.icon,
  25920. title: slots.title,
  25921. subtitle: slots.subtitle
  25922. })]);
  25923. })]
  25924. }), hasWindow && vue.createVNode(VStepperWindow, {
  25925. "key": "stepper-window"
  25926. }, {
  25927. default: () => [items.value.map(item => vue.createVNode(VStepperWindowItem, {
  25928. "value": item.value
  25929. }, {
  25930. default: () => slots[`item.${item.value}`]?.(item) ?? slots.item?.(item)
  25931. }))]
  25932. }), slots.default?.({
  25933. prev,
  25934. next
  25935. }), hasActions && (slots.actions?.({
  25936. next,
  25937. prev
  25938. }) ?? vue.createVNode(VStepperActions, {
  25939. "key": "stepper-actions",
  25940. "onClick:prev": prev,
  25941. "onClick:next": next
  25942. }, slots))]
  25943. });
  25944. });
  25945. return {
  25946. prev,
  25947. next
  25948. };
  25949. }
  25950. });
  25951. // Types
  25952. const makeVSwitchProps = propsFactory({
  25953. indeterminate: Boolean,
  25954. inset: Boolean,
  25955. flat: Boolean,
  25956. loading: {
  25957. type: [Boolean, String],
  25958. default: false
  25959. },
  25960. ...makeVInputProps(),
  25961. ...makeVSelectionControlProps()
  25962. }, 'VSwitch');
  25963. const VSwitch = genericComponent()({
  25964. name: 'VSwitch',
  25965. inheritAttrs: false,
  25966. props: makeVSwitchProps(),
  25967. emits: {
  25968. 'update:focused': focused => true,
  25969. 'update:modelValue': value => true,
  25970. 'update:indeterminate': value => true
  25971. },
  25972. setup(props, _ref) {
  25973. let {
  25974. attrs,
  25975. slots
  25976. } = _ref;
  25977. const indeterminate = useProxiedModel(props, 'indeterminate');
  25978. const model = useProxiedModel(props, 'modelValue');
  25979. const {
  25980. loaderClasses
  25981. } = useLoader(props);
  25982. const {
  25983. isFocused,
  25984. focus,
  25985. blur
  25986. } = useFocus(props);
  25987. const control = vue.ref();
  25988. const isForcedColorsModeActive = IN_BROWSER && window.matchMedia('(forced-colors: active)').matches;
  25989. const loaderColor = vue.computed(() => {
  25990. return typeof props.loading === 'string' && props.loading !== '' ? props.loading : props.color;
  25991. });
  25992. const uid = getUid();
  25993. const id = vue.computed(() => props.id || `switch-${uid}`);
  25994. function onChange() {
  25995. if (indeterminate.value) {
  25996. indeterminate.value = false;
  25997. }
  25998. }
  25999. function onTrackClick(e) {
  26000. e.stopPropagation();
  26001. e.preventDefault();
  26002. control.value?.input?.click();
  26003. }
  26004. useRender(() => {
  26005. const [rootAttrs, controlAttrs] = filterInputAttrs(attrs);
  26006. const inputProps = VInput.filterProps(props);
  26007. const controlProps = VSelectionControl.filterProps(props);
  26008. return vue.createVNode(VInput, vue.mergeProps({
  26009. "class": ['v-switch', {
  26010. 'v-switch--flat': props.flat
  26011. }, {
  26012. 'v-switch--inset': props.inset
  26013. }, {
  26014. 'v-switch--indeterminate': indeterminate.value
  26015. }, loaderClasses.value, props.class]
  26016. }, rootAttrs, inputProps, {
  26017. "modelValue": model.value,
  26018. "onUpdate:modelValue": $event => model.value = $event,
  26019. "id": id.value,
  26020. "focused": isFocused.value,
  26021. "style": props.style
  26022. }), {
  26023. ...slots,
  26024. default: _ref2 => {
  26025. let {
  26026. id,
  26027. messagesId,
  26028. isDisabled,
  26029. isReadonly,
  26030. isValid
  26031. } = _ref2;
  26032. const slotProps = {
  26033. model,
  26034. isValid
  26035. };
  26036. return vue.createVNode(VSelectionControl, vue.mergeProps({
  26037. "ref": control
  26038. }, controlProps, {
  26039. "modelValue": model.value,
  26040. "onUpdate:modelValue": [$event => model.value = $event, onChange],
  26041. "id": id.value,
  26042. "aria-describedby": messagesId.value,
  26043. "type": "checkbox",
  26044. "aria-checked": indeterminate.value ? 'mixed' : undefined,
  26045. "disabled": isDisabled.value,
  26046. "readonly": isReadonly.value,
  26047. "onFocus": focus,
  26048. "onBlur": blur
  26049. }, controlAttrs), {
  26050. ...slots,
  26051. default: _ref3 => {
  26052. let {
  26053. backgroundColorClasses,
  26054. backgroundColorStyles
  26055. } = _ref3;
  26056. return vue.createVNode("div", {
  26057. "class": ['v-switch__track', !isForcedColorsModeActive ? backgroundColorClasses.value : undefined],
  26058. "style": backgroundColorStyles.value,
  26059. "onClick": onTrackClick
  26060. }, [slots['track-true'] && vue.createVNode("div", {
  26061. "key": "prepend",
  26062. "class": "v-switch__track-true"
  26063. }, [slots['track-true'](slotProps)]), slots['track-false'] && vue.createVNode("div", {
  26064. "key": "append",
  26065. "class": "v-switch__track-false"
  26066. }, [slots['track-false'](slotProps)])]);
  26067. },
  26068. input: _ref4 => {
  26069. let {
  26070. inputNode,
  26071. icon,
  26072. backgroundColorClasses,
  26073. backgroundColorStyles
  26074. } = _ref4;
  26075. return vue.createVNode(vue.Fragment, null, [inputNode, vue.createVNode("div", {
  26076. "class": ['v-switch__thumb', {
  26077. 'v-switch__thumb--filled': icon || props.loading
  26078. }, props.inset || isForcedColorsModeActive ? undefined : backgroundColorClasses.value],
  26079. "style": props.inset ? undefined : backgroundColorStyles.value
  26080. }, [slots.thumb ? vue.createVNode(VDefaultsProvider, {
  26081. "defaults": {
  26082. VIcon: {
  26083. icon,
  26084. size: 'x-small'
  26085. }
  26086. }
  26087. }, {
  26088. default: () => [slots.thumb({
  26089. ...slotProps,
  26090. icon
  26091. })]
  26092. }) : vue.createVNode(VScaleTransition, null, {
  26093. default: () => [!props.loading ? icon && vue.createVNode(VIcon, {
  26094. "key": String(icon),
  26095. "icon": icon,
  26096. "size": "x-small"
  26097. }, null) : vue.createVNode(LoaderSlot, {
  26098. "name": "v-switch",
  26099. "active": true,
  26100. "color": isValid.value === false ? undefined : loaderColor.value
  26101. }, {
  26102. default: slotProps => slots.loader ? slots.loader(slotProps) : vue.createVNode(VProgressCircular, {
  26103. "active": slotProps.isActive,
  26104. "color": slotProps.color,
  26105. "indeterminate": true,
  26106. "size": "16",
  26107. "width": "2"
  26108. }, null)
  26109. })]
  26110. })])]);
  26111. }
  26112. });
  26113. }
  26114. });
  26115. });
  26116. return {};
  26117. }
  26118. });
  26119. const makeVSystemBarProps = propsFactory({
  26120. color: String,
  26121. height: [Number, String],
  26122. window: Boolean,
  26123. ...makeComponentProps(),
  26124. ...makeElevationProps(),
  26125. ...makeLayoutItemProps(),
  26126. ...makeRoundedProps(),
  26127. ...makeTagProps(),
  26128. ...makeThemeProps()
  26129. }, 'VSystemBar');
  26130. const VSystemBar = genericComponent()({
  26131. name: 'VSystemBar',
  26132. props: makeVSystemBarProps(),
  26133. setup(props, _ref) {
  26134. let {
  26135. slots
  26136. } = _ref;
  26137. const {
  26138. themeClasses
  26139. } = provideTheme(props);
  26140. const {
  26141. backgroundColorClasses,
  26142. backgroundColorStyles
  26143. } = useBackgroundColor(vue.toRef(props, 'color'));
  26144. const {
  26145. elevationClasses
  26146. } = useElevation(props);
  26147. const {
  26148. roundedClasses
  26149. } = useRounded(props);
  26150. const {
  26151. ssrBootStyles
  26152. } = useSsrBoot();
  26153. const height = vue.computed(() => props.height ?? (props.window ? 32 : 24));
  26154. const {
  26155. layoutItemStyles
  26156. } = useLayoutItem({
  26157. id: props.name,
  26158. order: vue.computed(() => parseInt(props.order, 10)),
  26159. position: vue.shallowRef('top'),
  26160. layoutSize: height,
  26161. elementSize: height,
  26162. active: vue.computed(() => true),
  26163. absolute: vue.toRef(props, 'absolute')
  26164. });
  26165. useRender(() => vue.createVNode(props.tag, {
  26166. "class": ['v-system-bar', {
  26167. 'v-system-bar--window': props.window
  26168. }, themeClasses.value, backgroundColorClasses.value, elevationClasses.value, roundedClasses.value, props.class],
  26169. "style": [backgroundColorStyles.value, layoutItemStyles.value, ssrBootStyles.value, props.style]
  26170. }, slots));
  26171. return {};
  26172. }
  26173. });
  26174. // Types
  26175. const VTabsSymbol = Symbol.for('vuetify:v-tabs');
  26176. // Types
  26177. const makeVTabProps = propsFactory({
  26178. fixed: Boolean,
  26179. sliderColor: String,
  26180. hideSlider: Boolean,
  26181. direction: {
  26182. type: String,
  26183. default: 'horizontal'
  26184. },
  26185. ...omit(makeVBtnProps({
  26186. selectedClass: 'v-tab--selected',
  26187. variant: 'text'
  26188. }), ['active', 'block', 'flat', 'location', 'position', 'symbol'])
  26189. }, 'VTab');
  26190. const VTab = genericComponent()({
  26191. name: 'VTab',
  26192. props: makeVTabProps(),
  26193. setup(props, _ref) {
  26194. let {
  26195. slots,
  26196. attrs
  26197. } = _ref;
  26198. const {
  26199. textColorClasses: sliderColorClasses,
  26200. textColorStyles: sliderColorStyles
  26201. } = useTextColor(props, 'sliderColor');
  26202. const rootEl = vue.ref();
  26203. const sliderEl = vue.ref();
  26204. const isHorizontal = vue.computed(() => props.direction === 'horizontal');
  26205. const isSelected = vue.computed(() => rootEl.value?.group?.isSelected.value ?? false);
  26206. function updateSlider(_ref2) {
  26207. let {
  26208. value
  26209. } = _ref2;
  26210. if (value) {
  26211. const prevEl = rootEl.value?.$el.parentElement?.querySelector('.v-tab--selected .v-tab__slider');
  26212. const nextEl = sliderEl.value;
  26213. if (!prevEl || !nextEl) return;
  26214. const color = getComputedStyle(prevEl).color;
  26215. const prevBox = prevEl.getBoundingClientRect();
  26216. const nextBox = nextEl.getBoundingClientRect();
  26217. const xy = isHorizontal.value ? 'x' : 'y';
  26218. const XY = isHorizontal.value ? 'X' : 'Y';
  26219. const rightBottom = isHorizontal.value ? 'right' : 'bottom';
  26220. const widthHeight = isHorizontal.value ? 'width' : 'height';
  26221. const prevPos = prevBox[xy];
  26222. const nextPos = nextBox[xy];
  26223. const delta = prevPos > nextPos ? prevBox[rightBottom] - nextBox[rightBottom] : prevBox[xy] - nextBox[xy];
  26224. const origin = Math.sign(delta) > 0 ? isHorizontal.value ? 'right' : 'bottom' : Math.sign(delta) < 0 ? isHorizontal.value ? 'left' : 'top' : 'center';
  26225. const size = Math.abs(delta) + (Math.sign(delta) < 0 ? prevBox[widthHeight] : nextBox[widthHeight]);
  26226. const scale = size / Math.max(prevBox[widthHeight], nextBox[widthHeight]) || 0;
  26227. const initialScale = prevBox[widthHeight] / nextBox[widthHeight] || 0;
  26228. const sigma = 1.5;
  26229. animate(nextEl, {
  26230. backgroundColor: [color, 'currentcolor'],
  26231. transform: [`translate${XY}(${delta}px) scale${XY}(${initialScale})`, `translate${XY}(${delta / sigma}px) scale${XY}(${(scale - 1) / sigma + 1})`, 'none'],
  26232. transformOrigin: Array(3).fill(origin)
  26233. }, {
  26234. duration: 225,
  26235. easing: standardEasing
  26236. });
  26237. }
  26238. }
  26239. useRender(() => {
  26240. const btnProps = VBtn.filterProps(props);
  26241. return vue.createVNode(VBtn, vue.mergeProps({
  26242. "symbol": VTabsSymbol,
  26243. "ref": rootEl,
  26244. "class": ['v-tab', props.class],
  26245. "style": props.style,
  26246. "tabindex": isSelected.value ? 0 : -1,
  26247. "role": "tab",
  26248. "aria-selected": String(isSelected.value),
  26249. "active": false
  26250. }, btnProps, attrs, {
  26251. "block": props.fixed,
  26252. "maxWidth": props.fixed ? 300 : undefined,
  26253. "onGroup:selected": updateSlider
  26254. }), {
  26255. ...slots,
  26256. default: () => vue.createVNode(vue.Fragment, null, [slots.default?.() ?? props.text, !props.hideSlider && vue.createVNode("div", {
  26257. "ref": sliderEl,
  26258. "class": ['v-tab__slider', sliderColorClasses.value],
  26259. "style": sliderColorStyles.value
  26260. }, null)])
  26261. });
  26262. });
  26263. return forwardRefs({}, rootEl);
  26264. }
  26265. });
  26266. const makeVTabsWindowProps = propsFactory({
  26267. ...omit(makeVWindowProps(), ['continuous', 'nextIcon', 'prevIcon', 'showArrows', 'touch', 'mandatory'])
  26268. }, 'VTabsWindow');
  26269. const VTabsWindow = genericComponent()({
  26270. name: 'VTabsWindow',
  26271. props: makeVTabsWindowProps(),
  26272. emits: {
  26273. 'update:modelValue': v => true
  26274. },
  26275. setup(props, _ref) {
  26276. let {
  26277. slots
  26278. } = _ref;
  26279. const group = vue.inject(VTabsSymbol, null);
  26280. const _model = useProxiedModel(props, 'modelValue');
  26281. const model = vue.computed({
  26282. get() {
  26283. // Always return modelValue if defined
  26284. // or if not within a VTabs group
  26285. if (_model.value != null || !group) return _model.value;
  26286. // If inside of a VTabs, find the currently selected
  26287. // item by id. Item value may be assigned by its index
  26288. return group.items.value.find(item => group.selected.value.includes(item.id))?.value;
  26289. },
  26290. set(val) {
  26291. _model.value = val;
  26292. }
  26293. });
  26294. useRender(() => {
  26295. const windowProps = VWindow.filterProps(props);
  26296. return vue.createVNode(VWindow, vue.mergeProps({
  26297. "_as": "VTabsWindow"
  26298. }, windowProps, {
  26299. "modelValue": model.value,
  26300. "onUpdate:modelValue": $event => model.value = $event,
  26301. "class": ['v-tabs-window', props.class],
  26302. "style": props.style,
  26303. "mandatory": false,
  26304. "touch": false
  26305. }), slots);
  26306. });
  26307. return {};
  26308. }
  26309. });
  26310. const makeVTabsWindowItemProps = propsFactory({
  26311. ...makeVWindowItemProps()
  26312. }, 'VTabsWindowItem');
  26313. const VTabsWindowItem = genericComponent()({
  26314. name: 'VTabsWindowItem',
  26315. props: makeVTabsWindowItemProps(),
  26316. setup(props, _ref) {
  26317. let {
  26318. slots
  26319. } = _ref;
  26320. useRender(() => {
  26321. const windowItemProps = VWindowItem.filterProps(props);
  26322. return vue.createVNode(VWindowItem, vue.mergeProps({
  26323. "_as": "VTabsWindowItem"
  26324. }, windowItemProps, {
  26325. "class": ['v-tabs-window-item', props.class],
  26326. "style": props.style
  26327. }), slots);
  26328. });
  26329. return {};
  26330. }
  26331. });
  26332. function parseItems(items) {
  26333. if (!items) return [];
  26334. return items.map(item => {
  26335. if (!isObject(item)) return {
  26336. text: item,
  26337. value: item
  26338. };
  26339. return item;
  26340. });
  26341. }
  26342. const makeVTabsProps = propsFactory({
  26343. alignTabs: {
  26344. type: String,
  26345. default: 'start'
  26346. },
  26347. color: String,
  26348. fixedTabs: Boolean,
  26349. items: {
  26350. type: Array,
  26351. default: () => []
  26352. },
  26353. stacked: Boolean,
  26354. bgColor: String,
  26355. grow: Boolean,
  26356. height: {
  26357. type: [Number, String],
  26358. default: undefined
  26359. },
  26360. hideSlider: Boolean,
  26361. sliderColor: String,
  26362. ...makeVSlideGroupProps({
  26363. mandatory: 'force',
  26364. selectedClass: 'v-tab-item--selected'
  26365. }),
  26366. ...makeDensityProps(),
  26367. ...makeTagProps()
  26368. }, 'VTabs');
  26369. const VTabs = genericComponent()({
  26370. name: 'VTabs',
  26371. props: makeVTabsProps(),
  26372. emits: {
  26373. 'update:modelValue': v => true
  26374. },
  26375. setup(props, _ref) {
  26376. let {
  26377. attrs,
  26378. slots
  26379. } = _ref;
  26380. const model = useProxiedModel(props, 'modelValue');
  26381. const items = vue.computed(() => parseItems(props.items));
  26382. const {
  26383. densityClasses
  26384. } = useDensity(props);
  26385. const {
  26386. backgroundColorClasses,
  26387. backgroundColorStyles
  26388. } = useBackgroundColor(vue.toRef(props, 'bgColor'));
  26389. const {
  26390. scopeId
  26391. } = useScopeId();
  26392. provideDefaults({
  26393. VTab: {
  26394. color: vue.toRef(props, 'color'),
  26395. direction: vue.toRef(props, 'direction'),
  26396. stacked: vue.toRef(props, 'stacked'),
  26397. fixed: vue.toRef(props, 'fixedTabs'),
  26398. sliderColor: vue.toRef(props, 'sliderColor'),
  26399. hideSlider: vue.toRef(props, 'hideSlider')
  26400. }
  26401. });
  26402. useRender(() => {
  26403. const slideGroupProps = VSlideGroup.filterProps(props);
  26404. const hasWindow = !!(slots.window || props.items.length > 0);
  26405. return vue.createVNode(vue.Fragment, null, [vue.createVNode(VSlideGroup, vue.mergeProps(slideGroupProps, {
  26406. "modelValue": model.value,
  26407. "onUpdate:modelValue": $event => model.value = $event,
  26408. "class": ['v-tabs', `v-tabs--${props.direction}`, `v-tabs--align-tabs-${props.alignTabs}`, {
  26409. 'v-tabs--fixed-tabs': props.fixedTabs,
  26410. 'v-tabs--grow': props.grow,
  26411. 'v-tabs--stacked': props.stacked
  26412. }, densityClasses.value, backgroundColorClasses.value, props.class],
  26413. "style": [{
  26414. '--v-tabs-height': convertToUnit(props.height)
  26415. }, backgroundColorStyles.value, props.style],
  26416. "role": "tablist",
  26417. "symbol": VTabsSymbol
  26418. }, scopeId, attrs), {
  26419. default: () => [slots.default?.() ?? items.value.map(item => slots.tab?.({
  26420. item
  26421. }) ?? vue.createVNode(VTab, vue.mergeProps(item, {
  26422. "key": item.text,
  26423. "value": item.value
  26424. }), {
  26425. default: slots[`tab.${item.value}`] ? () => slots[`tab.${item.value}`]?.({
  26426. item
  26427. }) : undefined
  26428. }))]
  26429. }), hasWindow && vue.createVNode(VTabsWindow, vue.mergeProps({
  26430. "modelValue": model.value,
  26431. "onUpdate:modelValue": $event => model.value = $event,
  26432. "key": "tabs-window"
  26433. }, scopeId), {
  26434. default: () => [items.value.map(item => slots.item?.({
  26435. item
  26436. }) ?? vue.createVNode(VTabsWindowItem, {
  26437. "value": item.value
  26438. }, {
  26439. default: () => slots[`item.${item.value}`]?.({
  26440. item
  26441. })
  26442. })), slots.window?.()]
  26443. })]);
  26444. });
  26445. return {};
  26446. }
  26447. });
  26448. // Types
  26449. const makeVTextareaProps = propsFactory({
  26450. autoGrow: Boolean,
  26451. autofocus: Boolean,
  26452. counter: [Boolean, Number, String],
  26453. counterValue: Function,
  26454. prefix: String,
  26455. placeholder: String,
  26456. persistentPlaceholder: Boolean,
  26457. persistentCounter: Boolean,
  26458. noResize: Boolean,
  26459. rows: {
  26460. type: [Number, String],
  26461. default: 5,
  26462. validator: v => !isNaN(parseFloat(v))
  26463. },
  26464. maxRows: {
  26465. type: [Number, String],
  26466. validator: v => !isNaN(parseFloat(v))
  26467. },
  26468. suffix: String,
  26469. modelModifiers: Object,
  26470. ...makeVInputProps(),
  26471. ...makeVFieldProps()
  26472. }, 'VTextarea');
  26473. const VTextarea = genericComponent()({
  26474. name: 'VTextarea',
  26475. directives: {
  26476. Intersect
  26477. },
  26478. inheritAttrs: false,
  26479. props: makeVTextareaProps(),
  26480. emits: {
  26481. 'click:control': e => true,
  26482. 'mousedown:control': e => true,
  26483. 'update:focused': focused => true,
  26484. 'update:modelValue': val => true
  26485. },
  26486. setup(props, _ref) {
  26487. let {
  26488. attrs,
  26489. emit,
  26490. slots
  26491. } = _ref;
  26492. const model = useProxiedModel(props, 'modelValue');
  26493. const {
  26494. isFocused,
  26495. focus,
  26496. blur
  26497. } = useFocus(props);
  26498. const counterValue = vue.computed(() => {
  26499. return typeof props.counterValue === 'function' ? props.counterValue(model.value) : (model.value || '').toString().length;
  26500. });
  26501. const max = vue.computed(() => {
  26502. if (attrs.maxlength) return attrs.maxlength;
  26503. if (!props.counter || typeof props.counter !== 'number' && typeof props.counter !== 'string') return undefined;
  26504. return props.counter;
  26505. });
  26506. function onIntersect(isIntersecting, entries) {
  26507. if (!props.autofocus || !isIntersecting) return;
  26508. entries[0].target?.focus?.();
  26509. }
  26510. const vInputRef = vue.ref();
  26511. const vFieldRef = vue.ref();
  26512. const controlHeight = vue.shallowRef('');
  26513. const textareaRef = vue.ref();
  26514. const isActive = vue.computed(() => props.persistentPlaceholder || isFocused.value || props.active);
  26515. function onFocus() {
  26516. if (textareaRef.value !== document.activeElement) {
  26517. textareaRef.value?.focus();
  26518. }
  26519. if (!isFocused.value) focus();
  26520. }
  26521. function onControlClick(e) {
  26522. onFocus();
  26523. emit('click:control', e);
  26524. }
  26525. function onControlMousedown(e) {
  26526. emit('mousedown:control', e);
  26527. }
  26528. function onClear(e) {
  26529. e.stopPropagation();
  26530. onFocus();
  26531. vue.nextTick(() => {
  26532. model.value = '';
  26533. callEvent(props['onClick:clear'], e);
  26534. });
  26535. }
  26536. function onInput(e) {
  26537. const el = e.target;
  26538. model.value = el.value;
  26539. if (props.modelModifiers?.trim) {
  26540. const caretPosition = [el.selectionStart, el.selectionEnd];
  26541. vue.nextTick(() => {
  26542. el.selectionStart = caretPosition[0];
  26543. el.selectionEnd = caretPosition[1];
  26544. });
  26545. }
  26546. }
  26547. const sizerRef = vue.ref();
  26548. const rows = vue.ref(+props.rows);
  26549. const isPlainOrUnderlined = vue.computed(() => ['plain', 'underlined'].includes(props.variant));
  26550. vue.watchEffect(() => {
  26551. if (!props.autoGrow) rows.value = +props.rows;
  26552. });
  26553. function calculateInputHeight() {
  26554. if (!props.autoGrow) return;
  26555. vue.nextTick(() => {
  26556. if (!sizerRef.value || !vFieldRef.value) return;
  26557. const style = getComputedStyle(sizerRef.value);
  26558. const fieldStyle = getComputedStyle(vFieldRef.value.$el);
  26559. const padding = parseFloat(style.getPropertyValue('--v-field-padding-top')) + parseFloat(style.getPropertyValue('--v-input-padding-top')) + parseFloat(style.getPropertyValue('--v-field-padding-bottom'));
  26560. const height = sizerRef.value.scrollHeight;
  26561. const lineHeight = parseFloat(style.lineHeight);
  26562. const minHeight = Math.max(parseFloat(props.rows) * lineHeight + padding, parseFloat(fieldStyle.getPropertyValue('--v-input-control-height')));
  26563. const maxHeight = parseFloat(props.maxRows) * lineHeight + padding || Infinity;
  26564. const newHeight = clamp(height ?? 0, minHeight, maxHeight);
  26565. rows.value = Math.floor((newHeight - padding) / lineHeight);
  26566. controlHeight.value = convertToUnit(newHeight);
  26567. });
  26568. }
  26569. vue.onMounted(calculateInputHeight);
  26570. vue.watch(model, calculateInputHeight);
  26571. vue.watch(() => props.rows, calculateInputHeight);
  26572. vue.watch(() => props.maxRows, calculateInputHeight);
  26573. vue.watch(() => props.density, calculateInputHeight);
  26574. let observer;
  26575. vue.watch(sizerRef, val => {
  26576. if (val) {
  26577. observer = new ResizeObserver(calculateInputHeight);
  26578. observer.observe(sizerRef.value);
  26579. } else {
  26580. observer?.disconnect();
  26581. }
  26582. });
  26583. vue.onBeforeUnmount(() => {
  26584. observer?.disconnect();
  26585. });
  26586. useRender(() => {
  26587. const hasCounter = !!(slots.counter || props.counter || props.counterValue);
  26588. const hasDetails = !!(hasCounter || slots.details);
  26589. const [rootAttrs, inputAttrs] = filterInputAttrs(attrs);
  26590. const {
  26591. modelValue: _,
  26592. ...inputProps
  26593. } = VInput.filterProps(props);
  26594. const fieldProps = filterFieldProps(props);
  26595. return vue.createVNode(VInput, vue.mergeProps({
  26596. "ref": vInputRef,
  26597. "modelValue": model.value,
  26598. "onUpdate:modelValue": $event => model.value = $event,
  26599. "class": ['v-textarea v-text-field', {
  26600. 'v-textarea--prefixed': props.prefix,
  26601. 'v-textarea--suffixed': props.suffix,
  26602. 'v-text-field--prefixed': props.prefix,
  26603. 'v-text-field--suffixed': props.suffix,
  26604. 'v-textarea--auto-grow': props.autoGrow,
  26605. 'v-textarea--no-resize': props.noResize || props.autoGrow,
  26606. 'v-input--plain-underlined': isPlainOrUnderlined.value
  26607. }, props.class],
  26608. "style": props.style
  26609. }, rootAttrs, inputProps, {
  26610. "centerAffix": rows.value === 1 && !isPlainOrUnderlined.value,
  26611. "focused": isFocused.value
  26612. }), {
  26613. ...slots,
  26614. default: _ref2 => {
  26615. let {
  26616. id,
  26617. isDisabled,
  26618. isDirty,
  26619. isReadonly,
  26620. isValid
  26621. } = _ref2;
  26622. return vue.createVNode(VField, vue.mergeProps({
  26623. "ref": vFieldRef,
  26624. "style": {
  26625. '--v-textarea-control-height': controlHeight.value
  26626. },
  26627. "onClick": onControlClick,
  26628. "onMousedown": onControlMousedown,
  26629. "onClick:clear": onClear,
  26630. "onClick:prependInner": props['onClick:prependInner'],
  26631. "onClick:appendInner": props['onClick:appendInner']
  26632. }, fieldProps, {
  26633. "id": id.value,
  26634. "active": isActive.value || isDirty.value,
  26635. "centerAffix": rows.value === 1 && !isPlainOrUnderlined.value,
  26636. "dirty": isDirty.value || props.dirty,
  26637. "disabled": isDisabled.value,
  26638. "focused": isFocused.value,
  26639. "error": isValid.value === false
  26640. }), {
  26641. ...slots,
  26642. default: _ref3 => {
  26643. let {
  26644. props: {
  26645. class: fieldClass,
  26646. ...slotProps
  26647. }
  26648. } = _ref3;
  26649. return vue.createVNode(vue.Fragment, null, [props.prefix && vue.createVNode("span", {
  26650. "class": "v-text-field__prefix"
  26651. }, [props.prefix]), vue.withDirectives(vue.createVNode("textarea", vue.mergeProps({
  26652. "ref": textareaRef,
  26653. "class": fieldClass,
  26654. "value": model.value,
  26655. "onInput": onInput,
  26656. "autofocus": props.autofocus,
  26657. "readonly": isReadonly.value,
  26658. "disabled": isDisabled.value,
  26659. "placeholder": props.placeholder,
  26660. "rows": props.rows,
  26661. "name": props.name,
  26662. "onFocus": onFocus,
  26663. "onBlur": blur
  26664. }, slotProps, inputAttrs), null), [[vue.resolveDirective("intersect"), {
  26665. handler: onIntersect
  26666. }, null, {
  26667. once: true
  26668. }]]), props.autoGrow && vue.withDirectives(vue.createVNode("textarea", {
  26669. "class": [fieldClass, 'v-textarea__sizer'],
  26670. "id": `${slotProps.id}-sizer`,
  26671. "onUpdate:modelValue": $event => model.value = $event,
  26672. "ref": sizerRef,
  26673. "readonly": true,
  26674. "aria-hidden": "true"
  26675. }, null), [[vue.vModelText, model.value]]), props.suffix && vue.createVNode("span", {
  26676. "class": "v-text-field__suffix"
  26677. }, [props.suffix])]);
  26678. }
  26679. });
  26680. },
  26681. details: hasDetails ? slotProps => vue.createVNode(vue.Fragment, null, [slots.details?.(slotProps), hasCounter && vue.createVNode(vue.Fragment, null, [vue.createVNode("span", null, null), vue.createVNode(VCounter, {
  26682. "active": props.persistentCounter || isFocused.value,
  26683. "value": counterValue.value,
  26684. "max": max.value,
  26685. "disabled": props.disabled
  26686. }, slots.counter)])]) : undefined
  26687. });
  26688. });
  26689. return forwardRefs({}, vInputRef, vFieldRef, textareaRef);
  26690. }
  26691. });
  26692. const makeVThemeProviderProps = propsFactory({
  26693. withBackground: Boolean,
  26694. ...makeComponentProps(),
  26695. ...makeThemeProps(),
  26696. ...makeTagProps()
  26697. }, 'VThemeProvider');
  26698. const VThemeProvider = genericComponent()({
  26699. name: 'VThemeProvider',
  26700. props: makeVThemeProviderProps(),
  26701. setup(props, _ref) {
  26702. let {
  26703. slots
  26704. } = _ref;
  26705. const {
  26706. themeClasses
  26707. } = provideTheme(props);
  26708. return () => {
  26709. if (!props.withBackground) return slots.default?.();
  26710. return vue.createVNode(props.tag, {
  26711. "class": ['v-theme-provider', themeClasses.value, props.class],
  26712. "style": props.style
  26713. }, {
  26714. default: () => [slots.default?.()]
  26715. });
  26716. };
  26717. }
  26718. });
  26719. const makeVTimelineDividerProps = propsFactory({
  26720. dotColor: String,
  26721. fillDot: Boolean,
  26722. hideDot: Boolean,
  26723. icon: IconValue,
  26724. iconColor: String,
  26725. lineColor: String,
  26726. ...makeComponentProps(),
  26727. ...makeRoundedProps(),
  26728. ...makeSizeProps(),
  26729. ...makeElevationProps()
  26730. }, 'VTimelineDivider');
  26731. const VTimelineDivider = genericComponent()({
  26732. name: 'VTimelineDivider',
  26733. props: makeVTimelineDividerProps(),
  26734. setup(props, _ref) {
  26735. let {
  26736. slots
  26737. } = _ref;
  26738. const {
  26739. sizeClasses,
  26740. sizeStyles
  26741. } = useSize(props, 'v-timeline-divider__dot');
  26742. const {
  26743. backgroundColorStyles,
  26744. backgroundColorClasses
  26745. } = useBackgroundColor(vue.toRef(props, 'dotColor'));
  26746. const {
  26747. roundedClasses
  26748. } = useRounded(props, 'v-timeline-divider__dot');
  26749. const {
  26750. elevationClasses
  26751. } = useElevation(props);
  26752. const {
  26753. backgroundColorClasses: lineColorClasses,
  26754. backgroundColorStyles: lineColorStyles
  26755. } = useBackgroundColor(vue.toRef(props, 'lineColor'));
  26756. useRender(() => vue.createVNode("div", {
  26757. "class": ['v-timeline-divider', {
  26758. 'v-timeline-divider--fill-dot': props.fillDot
  26759. }, props.class],
  26760. "style": props.style
  26761. }, [vue.createVNode("div", {
  26762. "class": ['v-timeline-divider__before', lineColorClasses.value],
  26763. "style": lineColorStyles.value
  26764. }, null), !props.hideDot && vue.createVNode("div", {
  26765. "key": "dot",
  26766. "class": ['v-timeline-divider__dot', elevationClasses.value, roundedClasses.value, sizeClasses.value],
  26767. "style": sizeStyles.value
  26768. }, [vue.createVNode("div", {
  26769. "class": ['v-timeline-divider__inner-dot', backgroundColorClasses.value, roundedClasses.value],
  26770. "style": backgroundColorStyles.value
  26771. }, [!slots.default ? vue.createVNode(VIcon, {
  26772. "key": "icon",
  26773. "color": props.iconColor,
  26774. "icon": props.icon,
  26775. "size": props.size
  26776. }, null) : vue.createVNode(VDefaultsProvider, {
  26777. "key": "icon-defaults",
  26778. "disabled": !props.icon,
  26779. "defaults": {
  26780. VIcon: {
  26781. color: props.iconColor,
  26782. icon: props.icon,
  26783. size: props.size
  26784. }
  26785. }
  26786. }, slots.default)])]), vue.createVNode("div", {
  26787. "class": ['v-timeline-divider__after', lineColorClasses.value],
  26788. "style": lineColorStyles.value
  26789. }, null)]));
  26790. return {};
  26791. }
  26792. });
  26793. // Types
  26794. // Types
  26795. const makeVTimelineItemProps = propsFactory({
  26796. density: String,
  26797. dotColor: String,
  26798. fillDot: Boolean,
  26799. hideDot: Boolean,
  26800. hideOpposite: {
  26801. type: Boolean,
  26802. default: undefined
  26803. },
  26804. icon: IconValue,
  26805. iconColor: String,
  26806. lineInset: [Number, String],
  26807. ...makeComponentProps(),
  26808. ...makeDimensionProps(),
  26809. ...makeElevationProps(),
  26810. ...makeRoundedProps(),
  26811. ...makeSizeProps(),
  26812. ...makeTagProps()
  26813. }, 'VTimelineItem');
  26814. const VTimelineItem = genericComponent()({
  26815. name: 'VTimelineItem',
  26816. props: makeVTimelineItemProps(),
  26817. setup(props, _ref) {
  26818. let {
  26819. slots
  26820. } = _ref;
  26821. const {
  26822. dimensionStyles
  26823. } = useDimension(props);
  26824. const dotSize = vue.shallowRef(0);
  26825. const dotRef = vue.ref();
  26826. vue.watch(dotRef, newValue => {
  26827. if (!newValue) return;
  26828. dotSize.value = newValue.$el.querySelector('.v-timeline-divider__dot')?.getBoundingClientRect().width ?? 0;
  26829. }, {
  26830. flush: 'post'
  26831. });
  26832. useRender(() => vue.createVNode("div", {
  26833. "class": ['v-timeline-item', {
  26834. 'v-timeline-item--fill-dot': props.fillDot
  26835. }, props.class],
  26836. "style": [{
  26837. '--v-timeline-dot-size': convertToUnit(dotSize.value),
  26838. '--v-timeline-line-inset': props.lineInset ? `calc(var(--v-timeline-dot-size) / 2 + ${convertToUnit(props.lineInset)})` : convertToUnit(0)
  26839. }, props.style]
  26840. }, [vue.createVNode("div", {
  26841. "class": "v-timeline-item__body",
  26842. "style": dimensionStyles.value
  26843. }, [slots.default?.()]), vue.createVNode(VTimelineDivider, {
  26844. "ref": dotRef,
  26845. "hideDot": props.hideDot,
  26846. "icon": props.icon,
  26847. "iconColor": props.iconColor,
  26848. "size": props.size,
  26849. "elevation": props.elevation,
  26850. "dotColor": props.dotColor,
  26851. "fillDot": props.fillDot,
  26852. "rounded": props.rounded
  26853. }, {
  26854. default: slots.icon
  26855. }), props.density !== 'compact' && vue.createVNode("div", {
  26856. "class": "v-timeline-item__opposite"
  26857. }, [!props.hideOpposite && slots.opposite?.()])]));
  26858. return {};
  26859. }
  26860. });
  26861. const makeVTimelineProps = propsFactory({
  26862. align: {
  26863. type: String,
  26864. default: 'center',
  26865. validator: v => ['center', 'start'].includes(v)
  26866. },
  26867. direction: {
  26868. type: String,
  26869. default: 'vertical',
  26870. validator: v => ['vertical', 'horizontal'].includes(v)
  26871. },
  26872. justify: {
  26873. type: String,
  26874. default: 'auto',
  26875. validator: v => ['auto', 'center'].includes(v)
  26876. },
  26877. side: {
  26878. type: String,
  26879. validator: v => v == null || ['start', 'end'].includes(v)
  26880. },
  26881. lineThickness: {
  26882. type: [String, Number],
  26883. default: 2
  26884. },
  26885. lineColor: String,
  26886. truncateLine: {
  26887. type: String,
  26888. validator: v => ['start', 'end', 'both'].includes(v)
  26889. },
  26890. ...only(makeVTimelineItemProps({
  26891. lineInset: 0
  26892. }), ['dotColor', 'fillDot', 'hideOpposite', 'iconColor', 'lineInset', 'size']),
  26893. ...makeComponentProps(),
  26894. ...makeDensityProps(),
  26895. ...makeTagProps(),
  26896. ...makeThemeProps()
  26897. }, 'VTimeline');
  26898. const VTimeline = genericComponent()({
  26899. name: 'VTimeline',
  26900. props: makeVTimelineProps(),
  26901. setup(props, _ref) {
  26902. let {
  26903. slots
  26904. } = _ref;
  26905. const {
  26906. themeClasses
  26907. } = provideTheme(props);
  26908. const {
  26909. densityClasses
  26910. } = useDensity(props);
  26911. const {
  26912. rtlClasses
  26913. } = useRtl();
  26914. provideDefaults({
  26915. VTimelineDivider: {
  26916. lineColor: vue.toRef(props, 'lineColor')
  26917. },
  26918. VTimelineItem: {
  26919. density: vue.toRef(props, 'density'),
  26920. dotColor: vue.toRef(props, 'dotColor'),
  26921. fillDot: vue.toRef(props, 'fillDot'),
  26922. hideOpposite: vue.toRef(props, 'hideOpposite'),
  26923. iconColor: vue.toRef(props, 'iconColor'),
  26924. lineColor: vue.toRef(props, 'lineColor'),
  26925. lineInset: vue.toRef(props, 'lineInset'),
  26926. size: vue.toRef(props, 'size')
  26927. }
  26928. });
  26929. const sideClasses = vue.computed(() => {
  26930. const side = props.side ? props.side : props.density !== 'default' ? 'end' : null;
  26931. return side && `v-timeline--side-${side}`;
  26932. });
  26933. const truncateClasses = vue.computed(() => {
  26934. const classes = ['v-timeline--truncate-line-start', 'v-timeline--truncate-line-end'];
  26935. switch (props.truncateLine) {
  26936. case 'both':
  26937. return classes;
  26938. case 'start':
  26939. return classes[0];
  26940. case 'end':
  26941. return classes[1];
  26942. default:
  26943. return null;
  26944. }
  26945. });
  26946. useRender(() => vue.createVNode(props.tag, {
  26947. "class": ['v-timeline', `v-timeline--${props.direction}`, `v-timeline--align-${props.align}`, `v-timeline--justify-${props.justify}`, truncateClasses.value, {
  26948. 'v-timeline--inset-line': !!props.lineInset
  26949. }, themeClasses.value, densityClasses.value, sideClasses.value, rtlClasses.value, props.class],
  26950. "style": [{
  26951. '--v-timeline-line-thickness': convertToUnit(props.lineThickness)
  26952. }, props.style]
  26953. }, slots));
  26954. return {};
  26955. }
  26956. });
  26957. const makeVToolbarItemsProps = propsFactory({
  26958. ...makeComponentProps(),
  26959. ...makeVariantProps({
  26960. variant: 'text'
  26961. })
  26962. }, 'VToolbarItems');
  26963. const VToolbarItems = genericComponent()({
  26964. name: 'VToolbarItems',
  26965. props: makeVToolbarItemsProps(),
  26966. setup(props, _ref) {
  26967. let {
  26968. slots
  26969. } = _ref;
  26970. provideDefaults({
  26971. VBtn: {
  26972. color: vue.toRef(props, 'color'),
  26973. height: 'inherit',
  26974. variant: vue.toRef(props, 'variant')
  26975. }
  26976. });
  26977. useRender(() => vue.createVNode("div", {
  26978. "class": ['v-toolbar-items', props.class],
  26979. "style": props.style
  26980. }, [slots.default?.()]));
  26981. return {};
  26982. }
  26983. });
  26984. // Types
  26985. const makeVTooltipProps = propsFactory({
  26986. id: String,
  26987. text: String,
  26988. ...omit(makeVOverlayProps({
  26989. closeOnBack: false,
  26990. location: 'end',
  26991. locationStrategy: 'connected',
  26992. eager: true,
  26993. minWidth: 0,
  26994. offset: 10,
  26995. openOnClick: false,
  26996. openOnHover: true,
  26997. origin: 'auto',
  26998. scrim: false,
  26999. scrollStrategy: 'reposition',
  27000. transition: false
  27001. }), ['absolute', 'persistent'])
  27002. }, 'VTooltip');
  27003. const VTooltip = genericComponent()({
  27004. name: 'VTooltip',
  27005. props: makeVTooltipProps(),
  27006. emits: {
  27007. 'update:modelValue': value => true
  27008. },
  27009. setup(props, _ref) {
  27010. let {
  27011. slots
  27012. } = _ref;
  27013. const isActive = useProxiedModel(props, 'modelValue');
  27014. const {
  27015. scopeId
  27016. } = useScopeId();
  27017. const uid = getUid();
  27018. const id = vue.computed(() => props.id || `v-tooltip-${uid}`);
  27019. const overlay = vue.ref();
  27020. const location = vue.computed(() => {
  27021. return props.location.split(' ').length > 1 ? props.location : props.location + ' center';
  27022. });
  27023. const origin = vue.computed(() => {
  27024. return props.origin === 'auto' || props.origin === 'overlap' || props.origin.split(' ').length > 1 || props.location.split(' ').length > 1 ? props.origin : props.origin + ' center';
  27025. });
  27026. const transition = vue.computed(() => {
  27027. if (props.transition) return props.transition;
  27028. return isActive.value ? 'scale-transition' : 'fade-transition';
  27029. });
  27030. const activatorProps = vue.computed(() => vue.mergeProps({
  27031. 'aria-describedby': id.value
  27032. }, props.activatorProps));
  27033. useRender(() => {
  27034. const overlayProps = VOverlay.filterProps(props);
  27035. return vue.createVNode(VOverlay, vue.mergeProps({
  27036. "ref": overlay,
  27037. "class": ['v-tooltip', props.class],
  27038. "style": props.style,
  27039. "id": id.value
  27040. }, overlayProps, {
  27041. "modelValue": isActive.value,
  27042. "onUpdate:modelValue": $event => isActive.value = $event,
  27043. "transition": transition.value,
  27044. "absolute": true,
  27045. "location": location.value,
  27046. "origin": origin.value,
  27047. "persistent": true,
  27048. "role": "tooltip",
  27049. "activatorProps": activatorProps.value,
  27050. "_disableGlobalStack": true
  27051. }, scopeId), {
  27052. activator: slots.activator,
  27053. default: function () {
  27054. for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) {
  27055. args[_key] = arguments[_key];
  27056. }
  27057. return slots.default?.(...args) ?? props.text;
  27058. }
  27059. });
  27060. });
  27061. return forwardRefs({}, overlay);
  27062. }
  27063. });
  27064. // Composables
  27065. // Types
  27066. const VValidation = genericComponent()({
  27067. name: 'VValidation',
  27068. props: makeValidationProps(),
  27069. emits: {
  27070. 'update:modelValue': value => true
  27071. },
  27072. setup(props, _ref) {
  27073. let {
  27074. slots
  27075. } = _ref;
  27076. const validation = useValidation(props, 'validation');
  27077. return () => slots.default?.(validation);
  27078. }
  27079. });
  27080. var components = /*#__PURE__*/Object.freeze({
  27081. __proto__: null,
  27082. VAlert: VAlert,
  27083. VAlertTitle: VAlertTitle,
  27084. VApp: VApp,
  27085. VAppBar: VAppBar,
  27086. VAppBarNavIcon: VAppBarNavIcon,
  27087. VAppBarTitle: VAppBarTitle,
  27088. VAutocomplete: VAutocomplete,
  27089. VAvatar: VAvatar,
  27090. VBadge: VBadge,
  27091. VBanner: VBanner,
  27092. VBannerActions: VBannerActions,
  27093. VBannerText: VBannerText,
  27094. VBottomNavigation: VBottomNavigation,
  27095. VBottomSheet: VBottomSheet,
  27096. VBreadcrumbs: VBreadcrumbs,
  27097. VBreadcrumbsDivider: VBreadcrumbsDivider,
  27098. VBreadcrumbsItem: VBreadcrumbsItem,
  27099. VBtn: VBtn,
  27100. VBtnGroup: VBtnGroup,
  27101. VBtnToggle: VBtnToggle,
  27102. VCard: VCard,
  27103. VCardActions: VCardActions,
  27104. VCardItem: VCardItem,
  27105. VCardSubtitle: VCardSubtitle,
  27106. VCardText: VCardText,
  27107. VCardTitle: VCardTitle,
  27108. VCarousel: VCarousel,
  27109. VCarouselItem: VCarouselItem,
  27110. VCheckbox: VCheckbox,
  27111. VCheckboxBtn: VCheckboxBtn,
  27112. VChip: VChip,
  27113. VChipGroup: VChipGroup,
  27114. VClassIcon: VClassIcon,
  27115. VCode: VCode,
  27116. VCol: VCol,
  27117. VColorPicker: VColorPicker,
  27118. VCombobox: VCombobox,
  27119. VComponentIcon: VComponentIcon,
  27120. VConfirmEdit: VConfirmEdit,
  27121. VContainer: VContainer,
  27122. VCounter: VCounter,
  27123. VDataIterator: VDataIterator,
  27124. VDataTable: VDataTable,
  27125. VDataTableFooter: VDataTableFooter,
  27126. VDataTableHeaders: VDataTableHeaders,
  27127. VDataTableRow: VDataTableRow,
  27128. VDataTableRows: VDataTableRows,
  27129. VDataTableServer: VDataTableServer,
  27130. VDataTableVirtual: VDataTableVirtual,
  27131. VDatePicker: VDatePicker,
  27132. VDatePickerControls: VDatePickerControls,
  27133. VDatePickerHeader: VDatePickerHeader,
  27134. VDatePickerMonth: VDatePickerMonth,
  27135. VDatePickerMonths: VDatePickerMonths,
  27136. VDatePickerYears: VDatePickerYears,
  27137. VDefaultsProvider: VDefaultsProvider,
  27138. VDialog: VDialog,
  27139. VDialogBottomTransition: VDialogBottomTransition,
  27140. VDialogTopTransition: VDialogTopTransition,
  27141. VDialogTransition: VDialogTransition,
  27142. VDivider: VDivider,
  27143. VEmptyState: VEmptyState,
  27144. VExpandTransition: VExpandTransition,
  27145. VExpandXTransition: VExpandXTransition,
  27146. VExpansionPanel: VExpansionPanel,
  27147. VExpansionPanelText: VExpansionPanelText,
  27148. VExpansionPanelTitle: VExpansionPanelTitle,
  27149. VExpansionPanels: VExpansionPanels,
  27150. VFab: VFab,
  27151. VFabTransition: VFabTransition,
  27152. VFadeTransition: VFadeTransition,
  27153. VField: VField,
  27154. VFieldLabel: VFieldLabel,
  27155. VFileInput: VFileInput,
  27156. VFooter: VFooter,
  27157. VForm: VForm,
  27158. VHover: VHover,
  27159. VIcon: VIcon,
  27160. VImg: VImg,
  27161. VInfiniteScroll: VInfiniteScroll,
  27162. VInput: VInput,
  27163. VItem: VItem,
  27164. VItemGroup: VItemGroup,
  27165. VKbd: VKbd,
  27166. VLabel: VLabel,
  27167. VLayout: VLayout,
  27168. VLayoutItem: VLayoutItem,
  27169. VLazy: VLazy,
  27170. VLigatureIcon: VLigatureIcon,
  27171. VList: VList,
  27172. VListGroup: VListGroup,
  27173. VListImg: VListImg,
  27174. VListItem: VListItem,
  27175. VListItemAction: VListItemAction,
  27176. VListItemMedia: VListItemMedia,
  27177. VListItemSubtitle: VListItemSubtitle,
  27178. VListItemTitle: VListItemTitle,
  27179. VListSubheader: VListSubheader,
  27180. VLocaleProvider: VLocaleProvider,
  27181. VMain: VMain,
  27182. VMenu: VMenu,
  27183. VMessages: VMessages,
  27184. VNavigationDrawer: VNavigationDrawer,
  27185. VNoSsr: VNoSsr,
  27186. VOtpInput: VOtpInput,
  27187. VOverlay: VOverlay,
  27188. VPagination: VPagination,
  27189. VParallax: VParallax,
  27190. VProgressCircular: VProgressCircular,
  27191. VProgressLinear: VProgressLinear,
  27192. VRadio: VRadio,
  27193. VRadioGroup: VRadioGroup,
  27194. VRangeSlider: VRangeSlider,
  27195. VRating: VRating,
  27196. VResponsive: VResponsive,
  27197. VRow: VRow,
  27198. VScaleTransition: VScaleTransition,
  27199. VScrollXReverseTransition: VScrollXReverseTransition,
  27200. VScrollXTransition: VScrollXTransition,
  27201. VScrollYReverseTransition: VScrollYReverseTransition,
  27202. VScrollYTransition: VScrollYTransition,
  27203. VSelect: VSelect,
  27204. VSelectionControl: VSelectionControl,
  27205. VSelectionControlGroup: VSelectionControlGroup,
  27206. VSheet: VSheet,
  27207. VSkeletonLoader: VSkeletonLoader,
  27208. VSlideGroup: VSlideGroup,
  27209. VSlideGroupItem: VSlideGroupItem,
  27210. VSlideXReverseTransition: VSlideXReverseTransition,
  27211. VSlideXTransition: VSlideXTransition,
  27212. VSlideYReverseTransition: VSlideYReverseTransition,
  27213. VSlideYTransition: VSlideYTransition,
  27214. VSlider: VSlider,
  27215. VSnackbar: VSnackbar,
  27216. VSpacer: VSpacer,
  27217. VSparkline: VSparkline,
  27218. VSpeedDial: VSpeedDial,
  27219. VStepper: VStepper,
  27220. VStepperActions: VStepperActions,
  27221. VStepperHeader: VStepperHeader,
  27222. VStepperItem: VStepperItem,
  27223. VStepperWindow: VStepperWindow,
  27224. VStepperWindowItem: VStepperWindowItem,
  27225. VSvgIcon: VSvgIcon,
  27226. VSwitch: VSwitch,
  27227. VSystemBar: VSystemBar,
  27228. VTab: VTab,
  27229. VTable: VTable,
  27230. VTabs: VTabs,
  27231. VTabsWindow: VTabsWindow,
  27232. VTabsWindowItem: VTabsWindowItem,
  27233. VTextField: VTextField,
  27234. VTextarea: VTextarea,
  27235. VThemeProvider: VThemeProvider,
  27236. VTimeline: VTimeline,
  27237. VTimelineItem: VTimelineItem,
  27238. VToolbar: VToolbar,
  27239. VToolbarItems: VToolbarItems,
  27240. VToolbarTitle: VToolbarTitle,
  27241. VTooltip: VTooltip,
  27242. VValidation: VValidation,
  27243. VVirtualScroll: VVirtualScroll,
  27244. VWindow: VWindow,
  27245. VWindowItem: VWindowItem
  27246. });
  27247. // Types
  27248. function mounted$2(el, binding) {
  27249. const modifiers = binding.modifiers || {};
  27250. const value = binding.value;
  27251. const {
  27252. once,
  27253. immediate,
  27254. ...modifierKeys
  27255. } = modifiers;
  27256. const defaultValue = !Object.keys(modifierKeys).length;
  27257. const {
  27258. handler,
  27259. options
  27260. } = typeof value === 'object' ? value : {
  27261. handler: value,
  27262. options: {
  27263. attributes: modifierKeys?.attr ?? defaultValue,
  27264. characterData: modifierKeys?.char ?? defaultValue,
  27265. childList: modifierKeys?.child ?? defaultValue,
  27266. subtree: modifierKeys?.sub ?? defaultValue
  27267. }
  27268. };
  27269. const observer = new MutationObserver(function () {
  27270. let mutations = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : [];
  27271. let observer = arguments.length > 1 ? arguments[1] : undefined;
  27272. handler?.(mutations, observer);
  27273. if (once) unmounted$2(el, binding);
  27274. });
  27275. if (immediate) handler?.([], observer);
  27276. el._mutate = Object(el._mutate);
  27277. el._mutate[binding.instance.$.uid] = {
  27278. observer
  27279. };
  27280. observer.observe(el, options);
  27281. }
  27282. function unmounted$2(el, binding) {
  27283. if (!el._mutate?.[binding.instance.$.uid]) return;
  27284. el._mutate[binding.instance.$.uid].observer.disconnect();
  27285. delete el._mutate[binding.instance.$.uid];
  27286. }
  27287. const Mutate = {
  27288. mounted: mounted$2,
  27289. unmounted: unmounted$2
  27290. };
  27291. // Types
  27292. function mounted$1(el, binding) {
  27293. const handler = binding.value;
  27294. const options = {
  27295. passive: !binding.modifiers?.active
  27296. };
  27297. window.addEventListener('resize', handler, options);
  27298. el._onResize = Object(el._onResize);
  27299. el._onResize[binding.instance.$.uid] = {
  27300. handler,
  27301. options
  27302. };
  27303. if (!binding.modifiers?.quiet) {
  27304. handler();
  27305. }
  27306. }
  27307. function unmounted$1(el, binding) {
  27308. if (!el._onResize?.[binding.instance.$.uid]) return;
  27309. const {
  27310. handler,
  27311. options
  27312. } = el._onResize[binding.instance.$.uid];
  27313. window.removeEventListener('resize', handler, options);
  27314. delete el._onResize[binding.instance.$.uid];
  27315. }
  27316. const Resize = {
  27317. mounted: mounted$1,
  27318. unmounted: unmounted$1
  27319. };
  27320. // Types
  27321. function mounted(el, binding) {
  27322. const {
  27323. self = false
  27324. } = binding.modifiers ?? {};
  27325. const value = binding.value;
  27326. const options = typeof value === 'object' && value.options || {
  27327. passive: true
  27328. };
  27329. const handler = typeof value === 'function' || 'handleEvent' in value ? value : value.handler;
  27330. const target = self ? el : binding.arg ? document.querySelector(binding.arg) : window;
  27331. if (!target) return;
  27332. target.addEventListener('scroll', handler, options);
  27333. el._onScroll = Object(el._onScroll);
  27334. el._onScroll[binding.instance.$.uid] = {
  27335. handler,
  27336. options,
  27337. // Don't reference self
  27338. target: self ? undefined : target
  27339. };
  27340. }
  27341. function unmounted(el, binding) {
  27342. if (!el._onScroll?.[binding.instance.$.uid]) return;
  27343. const {
  27344. handler,
  27345. options,
  27346. target = el
  27347. } = el._onScroll[binding.instance.$.uid];
  27348. target.removeEventListener('scroll', handler, options);
  27349. delete el._onScroll[binding.instance.$.uid];
  27350. }
  27351. function updated(el, binding) {
  27352. if (binding.value === binding.oldValue) return;
  27353. unmounted(el, binding);
  27354. mounted(el, binding);
  27355. }
  27356. const Scroll = {
  27357. mounted,
  27358. unmounted,
  27359. updated
  27360. };
  27361. // Utilities
  27362. // Types
  27363. function useDirectiveComponent(component, props) {
  27364. const concreteComponent = typeof component === 'string' ? vue.resolveComponent(component) : component;
  27365. const hook = mountComponent(concreteComponent, props);
  27366. return {
  27367. mounted: hook,
  27368. updated: hook,
  27369. unmounted(el) {
  27370. vue.render(null, el);
  27371. }
  27372. };
  27373. }
  27374. function mountComponent(component, props) {
  27375. return function (el, binding, vnode) {
  27376. const _props = typeof props === 'function' ? props(binding) : props;
  27377. const text = binding.value?.text ?? binding.value ?? _props?.text;
  27378. const value = isObject(binding.value) ? binding.value : {};
  27379. // Get the children from the props or directive value, or the element's children
  27380. const children = () => text ?? el.textContent;
  27381. // If vnode.ctx is the same as the instance, then we're bound to a plain element
  27382. // and need to find the nearest parent component instance to inherit provides from
  27383. const provides = (vnode.ctx === binding.instance.$ ? findComponentParent(vnode, binding.instance.$)?.provides : vnode.ctx?.provides) ?? binding.instance.$.provides;
  27384. const node = vue.h(component, vue.mergeProps(_props, value), children);
  27385. node.appContext = Object.assign(Object.create(null), binding.instance.$.appContext, {
  27386. provides
  27387. });
  27388. vue.render(node, el);
  27389. };
  27390. }
  27391. function findComponentParent(vnode, root) {
  27392. // Walk the tree from root until we find the child vnode
  27393. const stack = new Set();
  27394. const walk = children => {
  27395. for (const child of children) {
  27396. if (!child) continue;
  27397. if (child === vnode || child.el && vnode.el && child.el === vnode.el) {
  27398. return true;
  27399. }
  27400. stack.add(child);
  27401. let result;
  27402. if (child.suspense) {
  27403. result = walk([child.ssContent]);
  27404. } else if (Array.isArray(child.children)) {
  27405. result = walk(child.children);
  27406. } else if (child.component?.vnode) {
  27407. result = walk([child.component?.subTree]);
  27408. }
  27409. if (result) {
  27410. return result;
  27411. }
  27412. stack.delete(child);
  27413. }
  27414. return false;
  27415. };
  27416. if (!walk([root.subTree])) {
  27417. consoleError('Could not find original vnode, component will not inherit provides');
  27418. return root;
  27419. }
  27420. // Return the first component parent
  27421. const result = Array.from(stack).reverse();
  27422. for (const child of result) {
  27423. if (child.component) {
  27424. return child.component;
  27425. }
  27426. }
  27427. return root;
  27428. }
  27429. // Components
  27430. // Types
  27431. const Tooltip = useDirectiveComponent(VTooltip, binding => {
  27432. return {
  27433. activator: 'parent',
  27434. location: binding.arg?.replace('-', ' '),
  27435. text: typeof binding.value === 'boolean' ? undefined : binding.value
  27436. };
  27437. });
  27438. var directives = /*#__PURE__*/Object.freeze({
  27439. __proto__: null,
  27440. ClickOutside: ClickOutside,
  27441. Intersect: Intersect,
  27442. Mutate: Mutate,
  27443. Resize: Resize,
  27444. Ripple: Ripple,
  27445. Scroll: Scroll,
  27446. Tooltip: Tooltip,
  27447. Touch: Touch
  27448. });
  27449. // Composables
  27450. function createVuetify$1() {
  27451. let vuetify = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
  27452. const {
  27453. blueprint,
  27454. ...rest
  27455. } = vuetify;
  27456. const options = mergeDeep(blueprint, rest);
  27457. const {
  27458. aliases = {},
  27459. components = {},
  27460. directives = {}
  27461. } = options;
  27462. const defaults = createDefaults(options.defaults);
  27463. const display = createDisplay(options.display, options.ssr);
  27464. const theme = createTheme(options.theme);
  27465. const icons = createIcons(options.icons);
  27466. const locale = createLocale(options.locale);
  27467. const date = createDate(options.date, locale);
  27468. const goTo = createGoTo(options.goTo, locale);
  27469. const install = app => {
  27470. for (const key in directives) {
  27471. app.directive(key, directives[key]);
  27472. }
  27473. for (const key in components) {
  27474. app.component(key, components[key]);
  27475. }
  27476. for (const key in aliases) {
  27477. app.component(key, defineComponent({
  27478. ...aliases[key],
  27479. name: key,
  27480. aliasName: aliases[key].name
  27481. }));
  27482. }
  27483. theme.install(app);
  27484. app.provide(DefaultsSymbol, defaults);
  27485. app.provide(DisplaySymbol, display);
  27486. app.provide(ThemeSymbol, theme);
  27487. app.provide(IconSymbol, icons);
  27488. app.provide(LocaleSymbol, locale);
  27489. app.provide(DateOptionsSymbol, date.options);
  27490. app.provide(DateAdapterSymbol, date.instance);
  27491. app.provide(GoToSymbol, goTo);
  27492. if (IN_BROWSER && options.ssr) {
  27493. if (app.$nuxt) {
  27494. app.$nuxt.hook('app:suspense:resolve', () => {
  27495. display.update();
  27496. });
  27497. } else {
  27498. const {
  27499. mount
  27500. } = app;
  27501. app.mount = function () {
  27502. const vm = mount(...arguments);
  27503. vue.nextTick(() => display.update());
  27504. app.mount = mount;
  27505. return vm;
  27506. };
  27507. }
  27508. }
  27509. getUid.reset();
  27510. if (typeof __VUE_OPTIONS_API__ !== 'boolean' || __VUE_OPTIONS_API__) {
  27511. app.mixin({
  27512. computed: {
  27513. $vuetify() {
  27514. return vue.reactive({
  27515. defaults: inject.call(this, DefaultsSymbol),
  27516. display: inject.call(this, DisplaySymbol),
  27517. theme: inject.call(this, ThemeSymbol),
  27518. icons: inject.call(this, IconSymbol),
  27519. locale: inject.call(this, LocaleSymbol),
  27520. date: inject.call(this, DateAdapterSymbol)
  27521. });
  27522. }
  27523. }
  27524. });
  27525. }
  27526. };
  27527. return {
  27528. install,
  27529. defaults,
  27530. display,
  27531. theme,
  27532. icons,
  27533. locale,
  27534. date,
  27535. goTo
  27536. };
  27537. }
  27538. const version$1 = "3.7.6";
  27539. createVuetify$1.version = version$1;
  27540. // Vue's inject() can only be used in setup
  27541. function inject(key) {
  27542. const vm = this.$;
  27543. const provides = vm.parent?.provides ?? vm.vnode.appContext?.provides;
  27544. if (provides && key in provides) {
  27545. return provides[key];
  27546. }
  27547. }
  27548. /* eslint-disable local-rules/sort-imports */
  27549. // Types
  27550. const createVuetify = function () {
  27551. let options = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
  27552. return createVuetify$1({
  27553. components,
  27554. directives,
  27555. ...options
  27556. });
  27557. };
  27558. const version = "3.7.6";
  27559. createVuetify.version = version;
  27560. exports.blueprints = index;
  27561. exports.components = components;
  27562. exports.createVuetify = createVuetify;
  27563. exports.directives = directives;
  27564. exports.useDate = useDate;
  27565. exports.useDefaults = useDefaults;
  27566. exports.useDisplay = useDisplay;
  27567. exports.useGoTo = useGoTo;
  27568. exports.useLayout = useLayout;
  27569. exports.useLocale = useLocale;
  27570. exports.useRtl = useRtl;
  27571. exports.useTheme = useTheme;
  27572. exports.version = version;
  27573. }));
  27574. //# sourceMappingURL=vuetify.js.map