vuetify.js 630 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538253925402541254225432544254525462547254825492550255125522553255425552556255725582559256025612562256325642565256625672568256925702571257225732574257525762577257825792580258125822583258425852586258725882589259025912592259325942595259625972598259926002601260226032604260526062607260826092610261126122613261426152616261726182619262026212622262326242625262626272628262926302631263226332634263526362637263826392640264126422643264426452646264726482649265026512652265326542655265626572658265926602661266226632664266526662667266826692670267126722673267426752676267726782679268026812682268326842685268626872688268926902691269226932694269526962697269826992700270127022703270427052706270727082709271027112712271327142715271627172718271927202721272227232724272527262727272827292730273127322733273427352736273727382739274027412742274327442745274627472748274927502751275227532754275527562757275827592760276127622763276427652766276727682769277027712772277327742775277627772778277927802781278227832784278527862787278827892790279127922793279427952796279727982799280028012802280328042805280628072808280928102811281228132814281528162817281828192820282128222823282428252826282728282829283028312832283328342835283628372838283928402841284228432844284528462847284828492850285128522853285428552856285728582859286028612862286328642865286628672868286928702871287228732874287528762877287828792880288128822883288428852886288728882889289028912892289328942895289628972898289929002901290229032904290529062907290829092910291129122913291429152916291729182919292029212922292329242925292629272928292929302931293229332934293529362937293829392940294129422943294429452946294729482949295029512952295329542955295629572958295929602961296229632964296529662967296829692970297129722973297429752976297729782979298029812982298329842985298629872988298929902991299229932994299529962997299829993000300130023003300430053006300730083009301030113012301330143015301630173018301930203021302230233024302530263027302830293030303130323033303430353036303730383039304030413042304330443045304630473048304930503051305230533054305530563057305830593060306130623063306430653066306730683069307030713072307330743075307630773078307930803081308230833084308530863087308830893090309130923093309430953096309730983099310031013102310331043105310631073108310931103111311231133114311531163117311831193120312131223123312431253126312731283129313031313132313331343135313631373138313931403141314231433144314531463147314831493150315131523153315431553156315731583159316031613162316331643165316631673168316931703171317231733174317531763177317831793180318131823183318431853186318731883189319031913192319331943195319631973198319932003201320232033204320532063207320832093210321132123213321432153216321732183219322032213222322332243225322632273228322932303231323232333234323532363237323832393240324132423243324432453246324732483249325032513252325332543255325632573258325932603261326232633264326532663267326832693270327132723273327432753276327732783279328032813282328332843285328632873288328932903291329232933294329532963297329832993300330133023303330433053306330733083309331033113312331333143315331633173318331933203321332233233324332533263327332833293330333133323333333433353336333733383339334033413342334333443345334633473348334933503351335233533354335533563357335833593360336133623363336433653366336733683369337033713372337333743375337633773378337933803381338233833384338533863387338833893390339133923393339433953396339733983399340034013402340334043405340634073408340934103411341234133414341534163417341834193420342134223423342434253426342734283429343034313432343334343435343634373438343934403441344234433444344534463447344834493450345134523453345434553456345734583459346034613462346334643465346634673468346934703471347234733474347534763477347834793480348134823483348434853486348734883489349034913492349334943495349634973498349935003501350235033504350535063507350835093510351135123513351435153516351735183519352035213522352335243525352635273528352935303531353235333534353535363537353835393540354135423543354435453546354735483549355035513552355335543555355635573558355935603561356235633564356535663567356835693570357135723573357435753576357735783579358035813582358335843585358635873588358935903591359235933594359535963597359835993600360136023603360436053606360736083609361036113612361336143615361636173618361936203621362236233624362536263627362836293630363136323633363436353636363736383639364036413642364336443645364636473648364936503651365236533654365536563657365836593660366136623663366436653666366736683669367036713672367336743675367636773678367936803681368236833684368536863687368836893690369136923693369436953696369736983699370037013702370337043705370637073708370937103711371237133714371537163717371837193720372137223723372437253726372737283729373037313732373337343735373637373738373937403741374237433744374537463747374837493750375137523753375437553756375737583759376037613762376337643765376637673768376937703771377237733774377537763777377837793780378137823783378437853786378737883789379037913792379337943795379637973798379938003801380238033804380538063807380838093810381138123813381438153816381738183819382038213822382338243825382638273828382938303831383238333834383538363837383838393840384138423843384438453846384738483849385038513852385338543855385638573858385938603861386238633864386538663867386838693870387138723873387438753876387738783879388038813882388338843885388638873888388938903891389238933894389538963897389838993900390139023903390439053906390739083909391039113912391339143915391639173918391939203921392239233924392539263927392839293930393139323933393439353936393739383939394039413942394339443945394639473948394939503951395239533954395539563957395839593960396139623963396439653966396739683969397039713972397339743975397639773978397939803981398239833984398539863987398839893990399139923993399439953996399739983999400040014002400340044005400640074008400940104011401240134014401540164017401840194020402140224023402440254026402740284029403040314032403340344035403640374038403940404041404240434044404540464047404840494050405140524053405440554056405740584059406040614062406340644065406640674068406940704071407240734074407540764077407840794080408140824083408440854086408740884089409040914092409340944095409640974098409941004101410241034104410541064107410841094110411141124113411441154116411741184119412041214122412341244125412641274128412941304131413241334134413541364137413841394140414141424143414441454146414741484149415041514152415341544155415641574158415941604161416241634164416541664167416841694170417141724173417441754176417741784179418041814182418341844185418641874188418941904191419241934194419541964197419841994200420142024203420442054206420742084209421042114212421342144215421642174218421942204221422242234224422542264227422842294230423142324233423442354236423742384239424042414242424342444245424642474248424942504251425242534254425542564257425842594260426142624263426442654266426742684269427042714272427342744275427642774278427942804281428242834284428542864287428842894290429142924293429442954296429742984299430043014302430343044305430643074308430943104311431243134314431543164317431843194320432143224323432443254326432743284329433043314332433343344335433643374338433943404341434243434344434543464347434843494350435143524353435443554356435743584359436043614362436343644365436643674368436943704371437243734374437543764377437843794380438143824383438443854386438743884389439043914392439343944395439643974398439944004401440244034404440544064407440844094410441144124413441444154416441744184419442044214422442344244425442644274428442944304431443244334434443544364437443844394440444144424443444444454446444744484449445044514452445344544455445644574458445944604461446244634464446544664467446844694470447144724473447444754476447744784479448044814482448344844485448644874488448944904491449244934494449544964497449844994500450145024503450445054506450745084509451045114512451345144515451645174518451945204521452245234524452545264527452845294530453145324533453445354536453745384539454045414542454345444545454645474548454945504551455245534554455545564557455845594560456145624563456445654566456745684569457045714572457345744575457645774578457945804581458245834584458545864587458845894590459145924593459445954596459745984599460046014602460346044605460646074608460946104611461246134614461546164617461846194620462146224623462446254626462746284629463046314632463346344635463646374638463946404641464246434644464546464647464846494650465146524653465446554656465746584659466046614662466346644665466646674668466946704671467246734674467546764677467846794680468146824683468446854686468746884689469046914692469346944695469646974698469947004701470247034704470547064707470847094710471147124713471447154716471747184719472047214722472347244725472647274728472947304731473247334734473547364737473847394740474147424743474447454746474747484749475047514752475347544755475647574758475947604761476247634764476547664767476847694770477147724773477447754776477747784779478047814782478347844785478647874788478947904791479247934794479547964797479847994800480148024803480448054806480748084809481048114812481348144815481648174818481948204821482248234824482548264827482848294830483148324833483448354836483748384839484048414842484348444845484648474848484948504851485248534854485548564857485848594860486148624863486448654866486748684869487048714872487348744875487648774878487948804881488248834884488548864887488848894890489148924893489448954896489748984899490049014902490349044905490649074908490949104911491249134914491549164917491849194920492149224923492449254926492749284929493049314932493349344935493649374938493949404941494249434944494549464947494849494950495149524953495449554956495749584959496049614962496349644965496649674968496949704971497249734974497549764977497849794980498149824983498449854986498749884989499049914992499349944995499649974998499950005001500250035004500550065007500850095010501150125013501450155016501750185019502050215022502350245025502650275028502950305031503250335034503550365037503850395040504150425043504450455046504750485049505050515052505350545055505650575058505950605061506250635064506550665067506850695070507150725073507450755076507750785079508050815082508350845085508650875088508950905091509250935094509550965097509850995100510151025103510451055106510751085109511051115112511351145115511651175118511951205121512251235124512551265127512851295130513151325133513451355136513751385139514051415142514351445145514651475148514951505151515251535154515551565157515851595160516151625163516451655166516751685169517051715172517351745175517651775178517951805181518251835184518551865187518851895190519151925193519451955196519751985199520052015202520352045205520652075208520952105211521252135214521552165217521852195220522152225223522452255226522752285229523052315232523352345235523652375238523952405241524252435244524552465247524852495250525152525253525452555256525752585259526052615262526352645265526652675268526952705271527252735274527552765277527852795280528152825283528452855286528752885289529052915292529352945295529652975298529953005301530253035304530553065307530853095310531153125313531453155316531753185319532053215322532353245325532653275328532953305331533253335334533553365337533853395340534153425343534453455346534753485349535053515352535353545355535653575358535953605361536253635364536553665367536853695370537153725373537453755376537753785379538053815382538353845385538653875388538953905391539253935394539553965397539853995400540154025403540454055406540754085409541054115412541354145415541654175418541954205421542254235424542554265427542854295430543154325433543454355436543754385439544054415442544354445445544654475448544954505451545254535454545554565457545854595460546154625463546454655466546754685469547054715472547354745475547654775478547954805481548254835484548554865487548854895490549154925493549454955496549754985499550055015502550355045505550655075508550955105511551255135514551555165517551855195520552155225523552455255526552755285529553055315532553355345535553655375538553955405541554255435544554555465547554855495550555155525553555455555556555755585559556055615562556355645565556655675568556955705571557255735574557555765577557855795580558155825583558455855586558755885589559055915592559355945595559655975598559956005601560256035604560556065607560856095610561156125613561456155616561756185619562056215622562356245625562656275628562956305631563256335634563556365637563856395640564156425643564456455646564756485649565056515652565356545655565656575658565956605661566256635664566556665667566856695670567156725673567456755676567756785679568056815682568356845685568656875688568956905691569256935694569556965697569856995700570157025703570457055706570757085709571057115712571357145715571657175718571957205721572257235724572557265727572857295730573157325733573457355736573757385739574057415742574357445745574657475748574957505751575257535754575557565757575857595760576157625763576457655766576757685769577057715772577357745775577657775778577957805781578257835784578557865787578857895790579157925793579457955796579757985799580058015802580358045805580658075808580958105811581258135814581558165817581858195820582158225823582458255826582758285829583058315832583358345835583658375838583958405841584258435844584558465847584858495850585158525853585458555856585758585859586058615862586358645865586658675868586958705871587258735874587558765877587858795880588158825883588458855886588758885889589058915892589358945895589658975898589959005901590259035904590559065907590859095910591159125913591459155916591759185919592059215922592359245925592659275928592959305931593259335934593559365937593859395940594159425943594459455946594759485949595059515952595359545955595659575958595959605961596259635964596559665967596859695970597159725973597459755976597759785979598059815982598359845985598659875988598959905991599259935994599559965997599859996000600160026003600460056006600760086009601060116012601360146015601660176018601960206021602260236024602560266027602860296030603160326033603460356036603760386039604060416042604360446045604660476048604960506051605260536054605560566057605860596060606160626063606460656066606760686069607060716072607360746075607660776078607960806081608260836084608560866087608860896090609160926093609460956096609760986099610061016102610361046105610661076108610961106111611261136114611561166117611861196120612161226123612461256126612761286129613061316132613361346135613661376138613961406141614261436144614561466147614861496150615161526153615461556156615761586159616061616162616361646165616661676168616961706171617261736174617561766177617861796180618161826183618461856186618761886189619061916192619361946195619661976198619962006201620262036204620562066207620862096210621162126213621462156216621762186219622062216222622362246225622662276228622962306231623262336234623562366237623862396240624162426243624462456246624762486249625062516252625362546255625662576258625962606261626262636264626562666267626862696270627162726273627462756276627762786279628062816282628362846285628662876288628962906291629262936294629562966297629862996300630163026303630463056306630763086309631063116312631363146315631663176318631963206321632263236324632563266327632863296330633163326333633463356336633763386339634063416342634363446345634663476348634963506351635263536354635563566357635863596360636163626363636463656366636763686369637063716372637363746375637663776378637963806381638263836384638563866387638863896390639163926393639463956396639763986399640064016402640364046405640664076408640964106411641264136414641564166417641864196420642164226423642464256426642764286429643064316432643364346435643664376438643964406441644264436444644564466447644864496450645164526453645464556456645764586459646064616462646364646465646664676468646964706471647264736474647564766477647864796480648164826483648464856486648764886489649064916492649364946495649664976498649965006501650265036504650565066507650865096510651165126513651465156516651765186519652065216522652365246525652665276528652965306531653265336534653565366537653865396540654165426543654465456546654765486549655065516552655365546555655665576558655965606561656265636564656565666567656865696570657165726573657465756576657765786579658065816582658365846585658665876588658965906591659265936594659565966597659865996600660166026603660466056606660766086609661066116612661366146615661666176618661966206621662266236624662566266627662866296630663166326633663466356636663766386639664066416642664366446645664666476648664966506651665266536654665566566657665866596660666166626663666466656666666766686669667066716672667366746675667666776678667966806681668266836684668566866687668866896690669166926693669466956696669766986699670067016702670367046705670667076708670967106711671267136714671567166717671867196720672167226723672467256726672767286729673067316732673367346735673667376738673967406741674267436744674567466747674867496750675167526753675467556756675767586759676067616762676367646765676667676768676967706771677267736774677567766777677867796780678167826783678467856786678767886789679067916792679367946795679667976798679968006801680268036804680568066807680868096810681168126813681468156816681768186819682068216822682368246825682668276828682968306831683268336834683568366837683868396840684168426843684468456846684768486849685068516852685368546855685668576858685968606861686268636864686568666867686868696870687168726873687468756876687768786879688068816882688368846885688668876888688968906891689268936894689568966897689868996900690169026903690469056906690769086909691069116912691369146915691669176918691969206921692269236924692569266927692869296930693169326933693469356936693769386939694069416942694369446945694669476948694969506951695269536954695569566957695869596960696169626963696469656966696769686969697069716972697369746975697669776978697969806981698269836984698569866987698869896990699169926993699469956996699769986999700070017002700370047005700670077008700970107011701270137014701570167017701870197020702170227023702470257026702770287029703070317032703370347035703670377038703970407041704270437044704570467047704870497050705170527053705470557056705770587059706070617062706370647065706670677068706970707071707270737074707570767077707870797080708170827083708470857086708770887089709070917092709370947095709670977098709971007101710271037104710571067107710871097110711171127113711471157116711771187119712071217122712371247125712671277128712971307131713271337134713571367137713871397140714171427143714471457146714771487149715071517152715371547155715671577158715971607161716271637164716571667167716871697170717171727173717471757176717771787179718071817182718371847185718671877188718971907191719271937194719571967197719871997200720172027203720472057206720772087209721072117212721372147215721672177218721972207221722272237224722572267227722872297230723172327233723472357236723772387239724072417242724372447245724672477248724972507251725272537254725572567257725872597260726172627263726472657266726772687269727072717272727372747275727672777278727972807281728272837284728572867287728872897290729172927293729472957296729772987299730073017302730373047305730673077308730973107311731273137314731573167317731873197320732173227323732473257326732773287329733073317332733373347335733673377338733973407341734273437344734573467347734873497350735173527353735473557356735773587359736073617362736373647365736673677368736973707371737273737374737573767377737873797380738173827383738473857386738773887389739073917392739373947395739673977398739974007401740274037404740574067407740874097410741174127413741474157416741774187419742074217422742374247425742674277428742974307431743274337434743574367437743874397440744174427443744474457446744774487449745074517452745374547455745674577458745974607461746274637464746574667467746874697470747174727473747474757476747774787479748074817482748374847485748674877488748974907491749274937494749574967497749874997500750175027503750475057506750775087509751075117512751375147515751675177518751975207521752275237524752575267527752875297530753175327533753475357536753775387539754075417542754375447545754675477548754975507551755275537554755575567557755875597560756175627563756475657566756775687569757075717572757375747575757675777578757975807581758275837584758575867587758875897590759175927593759475957596759775987599760076017602760376047605760676077608760976107611761276137614761576167617761876197620762176227623762476257626762776287629763076317632763376347635763676377638763976407641764276437644764576467647764876497650765176527653765476557656765776587659766076617662766376647665766676677668766976707671767276737674767576767677767876797680768176827683768476857686768776887689769076917692769376947695769676977698769977007701770277037704770577067707770877097710771177127713771477157716771777187719772077217722772377247725772677277728772977307731773277337734773577367737773877397740774177427743774477457746774777487749775077517752775377547755775677577758775977607761776277637764776577667767776877697770777177727773777477757776777777787779778077817782778377847785778677877788778977907791779277937794779577967797779877997800780178027803780478057806780778087809781078117812781378147815781678177818781978207821782278237824782578267827782878297830783178327833783478357836783778387839784078417842784378447845784678477848784978507851785278537854785578567857785878597860786178627863786478657866786778687869787078717872787378747875787678777878787978807881788278837884788578867887788878897890789178927893789478957896789778987899790079017902790379047905790679077908790979107911791279137914791579167917791879197920792179227923792479257926792779287929793079317932793379347935793679377938793979407941794279437944794579467947794879497950795179527953795479557956795779587959796079617962796379647965796679677968796979707971797279737974797579767977797879797980798179827983798479857986798779887989799079917992799379947995799679977998799980008001800280038004800580068007800880098010801180128013801480158016801780188019802080218022802380248025802680278028802980308031803280338034803580368037803880398040804180428043804480458046804780488049805080518052805380548055805680578058805980608061806280638064806580668067806880698070807180728073807480758076807780788079808080818082808380848085808680878088808980908091809280938094809580968097809880998100810181028103810481058106810781088109811081118112811381148115811681178118811981208121812281238124812581268127812881298130813181328133813481358136813781388139814081418142814381448145814681478148814981508151815281538154815581568157815881598160816181628163816481658166816781688169817081718172817381748175817681778178817981808181818281838184818581868187818881898190819181928193819481958196819781988199820082018202820382048205820682078208820982108211821282138214821582168217821882198220822182228223822482258226822782288229823082318232823382348235823682378238823982408241824282438244824582468247824882498250825182528253825482558256825782588259826082618262826382648265826682678268826982708271827282738274827582768277827882798280828182828283828482858286828782888289829082918292829382948295829682978298829983008301830283038304830583068307830883098310831183128313831483158316831783188319832083218322832383248325832683278328832983308331833283338334833583368337833883398340834183428343834483458346834783488349835083518352835383548355835683578358835983608361836283638364836583668367836883698370837183728373837483758376837783788379838083818382838383848385838683878388838983908391839283938394839583968397839883998400840184028403840484058406840784088409841084118412841384148415841684178418841984208421842284238424842584268427842884298430843184328433843484358436843784388439844084418442844384448445844684478448844984508451845284538454845584568457845884598460846184628463846484658466846784688469847084718472847384748475847684778478847984808481848284838484848584868487848884898490849184928493849484958496849784988499850085018502850385048505850685078508850985108511851285138514851585168517851885198520852185228523852485258526852785288529853085318532853385348535853685378538853985408541854285438544854585468547854885498550855185528553855485558556855785588559856085618562856385648565856685678568856985708571857285738574857585768577857885798580858185828583858485858586858785888589859085918592859385948595859685978598859986008601860286038604860586068607860886098610861186128613861486158616861786188619862086218622862386248625862686278628862986308631863286338634863586368637863886398640864186428643864486458646864786488649865086518652865386548655865686578658865986608661866286638664866586668667866886698670867186728673867486758676867786788679868086818682868386848685868686878688868986908691869286938694869586968697869886998700870187028703870487058706870787088709871087118712871387148715871687178718871987208721872287238724872587268727872887298730873187328733873487358736873787388739874087418742874387448745874687478748874987508751875287538754875587568757875887598760876187628763876487658766876787688769877087718772877387748775877687778778877987808781878287838784878587868787878887898790879187928793879487958796879787988799880088018802880388048805880688078808880988108811881288138814881588168817881888198820882188228823882488258826882788288829883088318832883388348835883688378838883988408841884288438844884588468847884888498850885188528853885488558856885788588859886088618862886388648865886688678868886988708871887288738874887588768877887888798880888188828883888488858886888788888889889088918892889388948895889688978898889989008901890289038904890589068907890889098910891189128913891489158916891789188919892089218922892389248925892689278928892989308931893289338934893589368937893889398940894189428943894489458946894789488949895089518952895389548955895689578958895989608961896289638964896589668967896889698970897189728973897489758976897789788979898089818982898389848985898689878988898989908991899289938994899589968997899889999000900190029003900490059006900790089009901090119012901390149015901690179018901990209021902290239024902590269027902890299030903190329033903490359036903790389039904090419042904390449045904690479048904990509051905290539054905590569057905890599060906190629063906490659066906790689069907090719072907390749075907690779078907990809081908290839084908590869087908890899090909190929093909490959096909790989099910091019102910391049105910691079108910991109111911291139114911591169117911891199120912191229123912491259126912791289129913091319132913391349135913691379138913991409141914291439144914591469147914891499150915191529153915491559156915791589159916091619162916391649165916691679168916991709171917291739174917591769177917891799180918191829183918491859186918791889189919091919192919391949195919691979198919992009201920292039204920592069207920892099210921192129213921492159216921792189219922092219222922392249225922692279228922992309231923292339234923592369237923892399240924192429243924492459246924792489249925092519252925392549255925692579258925992609261926292639264926592669267926892699270927192729273927492759276927792789279928092819282928392849285928692879288928992909291929292939294929592969297929892999300930193029303930493059306930793089309931093119312931393149315931693179318931993209321932293239324932593269327932893299330933193329333933493359336933793389339934093419342934393449345934693479348934993509351935293539354935593569357935893599360936193629363936493659366936793689369937093719372937393749375937693779378937993809381938293839384938593869387938893899390939193929393939493959396939793989399940094019402940394049405940694079408940994109411941294139414941594169417941894199420942194229423942494259426942794289429943094319432943394349435943694379438943994409441944294439444944594469447944894499450945194529453945494559456945794589459946094619462946394649465946694679468946994709471947294739474947594769477947894799480948194829483948494859486948794889489949094919492949394949495949694979498949995009501950295039504950595069507950895099510951195129513951495159516951795189519952095219522952395249525952695279528952995309531953295339534953595369537953895399540954195429543954495459546954795489549955095519552955395549555955695579558955995609561956295639564956595669567956895699570957195729573957495759576957795789579958095819582958395849585958695879588958995909591959295939594959595969597959895999600960196029603960496059606960796089609961096119612961396149615961696179618961996209621962296239624962596269627962896299630963196329633963496359636963796389639964096419642964396449645964696479648964996509651965296539654965596569657965896599660966196629663966496659666966796689669967096719672967396749675967696779678967996809681968296839684968596869687968896899690969196929693969496959696969796989699970097019702970397049705970697079708970997109711971297139714971597169717971897199720972197229723972497259726972797289729973097319732973397349735973697379738973997409741974297439744974597469747974897499750975197529753975497559756975797589759976097619762976397649765976697679768976997709771977297739774977597769777977897799780978197829783978497859786978797889789979097919792979397949795979697979798979998009801980298039804980598069807980898099810981198129813981498159816981798189819982098219822982398249825982698279828982998309831983298339834983598369837983898399840984198429843984498459846984798489849985098519852985398549855985698579858985998609861986298639864986598669867986898699870987198729873987498759876987798789879988098819882988398849885988698879888988998909891989298939894989598969897989898999900990199029903990499059906990799089909991099119912991399149915991699179918991999209921992299239924992599269927992899299930993199329933993499359936993799389939994099419942994399449945994699479948994999509951995299539954995599569957995899599960996199629963996499659966996799689969997099719972997399749975997699779978997999809981998299839984998599869987998899899990999199929993999499959996999799989999100001000110002100031000410005100061000710008100091001010011100121001310014100151001610017100181001910020100211002210023100241002510026100271002810029100301003110032100331003410035100361003710038100391004010041100421004310044100451004610047100481004910050100511005210053100541005510056100571005810059100601006110062100631006410065100661006710068100691007010071100721007310074100751007610077100781007910080100811008210083100841008510086100871008810089100901009110092100931009410095100961009710098100991010010101101021010310104101051010610107101081010910110101111011210113101141011510116101171011810119101201012110122101231012410125101261012710128101291013010131101321013310134101351013610137101381013910140101411014210143101441014510146101471014810149101501015110152101531015410155101561015710158101591016010161101621016310164101651016610167101681016910170101711017210173101741017510176101771017810179101801018110182101831018410185101861018710188101891019010191101921019310194101951019610197101981019910200102011020210203102041020510206102071020810209102101021110212102131021410215102161021710218102191022010221102221022310224102251022610227102281022910230102311023210233102341023510236102371023810239102401024110242102431024410245102461024710248102491025010251102521025310254102551025610257102581025910260102611026210263102641026510266102671026810269102701027110272102731027410275102761027710278102791028010281102821028310284102851028610287102881028910290102911029210293102941029510296102971029810299103001030110302103031030410305103061030710308103091031010311103121031310314103151031610317103181031910320103211032210323103241032510326103271032810329103301033110332103331033410335103361033710338103391034010341103421034310344103451034610347103481034910350103511035210353103541035510356103571035810359103601036110362103631036410365103661036710368103691037010371103721037310374103751037610377103781037910380103811038210383103841038510386103871038810389103901039110392103931039410395103961039710398103991040010401104021040310404104051040610407104081040910410104111041210413104141041510416104171041810419104201042110422104231042410425104261042710428104291043010431104321043310434104351043610437104381043910440104411044210443104441044510446104471044810449104501045110452104531045410455104561045710458104591046010461104621046310464104651046610467104681046910470104711047210473104741047510476104771047810479104801048110482104831048410485104861048710488104891049010491104921049310494104951049610497104981049910500105011050210503105041050510506105071050810509105101051110512105131051410515105161051710518105191052010521105221052310524105251052610527105281052910530105311053210533105341053510536105371053810539105401054110542105431054410545105461054710548105491055010551105521055310554105551055610557105581055910560105611056210563105641056510566105671056810569105701057110572105731057410575105761057710578105791058010581105821058310584105851058610587105881058910590105911059210593105941059510596105971059810599106001060110602106031060410605106061060710608106091061010611106121061310614106151061610617106181061910620106211062210623106241062510626106271062810629106301063110632106331063410635106361063710638106391064010641106421064310644106451064610647106481064910650106511065210653106541065510656106571065810659106601066110662106631066410665106661066710668106691067010671106721067310674106751067610677106781067910680106811068210683106841068510686106871068810689106901069110692106931069410695106961069710698106991070010701107021070310704107051070610707107081070910710107111071210713107141071510716107171071810719107201072110722107231072410725107261072710728107291073010731107321073310734107351073610737107381073910740107411074210743107441074510746107471074810749107501075110752107531075410755107561075710758107591076010761107621076310764107651076610767107681076910770107711077210773107741077510776107771077810779107801078110782107831078410785107861078710788107891079010791107921079310794107951079610797107981079910800108011080210803108041080510806108071080810809108101081110812108131081410815108161081710818108191082010821108221082310824108251082610827108281082910830108311083210833108341083510836108371083810839108401084110842108431084410845108461084710848108491085010851108521085310854108551085610857108581085910860108611086210863108641086510866108671086810869108701087110872108731087410875108761087710878108791088010881108821088310884108851088610887108881088910890108911089210893108941089510896108971089810899109001090110902109031090410905109061090710908109091091010911109121091310914109151091610917109181091910920109211092210923109241092510926109271092810929109301093110932109331093410935109361093710938109391094010941109421094310944109451094610947109481094910950109511095210953109541095510956109571095810959109601096110962109631096410965109661096710968109691097010971109721097310974109751097610977109781097910980109811098210983109841098510986109871098810989109901099110992109931099410995109961099710998109991100011001110021100311004110051100611007110081100911010110111101211013110141101511016110171101811019110201102111022110231102411025110261102711028110291103011031110321103311034110351103611037110381103911040110411104211043110441104511046110471104811049110501105111052110531105411055110561105711058110591106011061110621106311064110651106611067110681106911070110711107211073110741107511076110771107811079110801108111082110831108411085110861108711088110891109011091110921109311094110951109611097110981109911100111011110211103111041110511106111071110811109111101111111112111131111411115111161111711118111191112011121111221112311124111251112611127111281112911130111311113211133111341113511136111371113811139111401114111142111431114411145111461114711148111491115011151111521115311154111551115611157111581115911160111611116211163111641116511166111671116811169111701117111172111731117411175111761117711178111791118011181111821118311184111851118611187111881118911190111911119211193111941119511196111971119811199112001120111202112031120411205112061120711208112091121011211112121121311214112151121611217112181121911220112211122211223112241122511226112271122811229112301123111232112331123411235112361123711238112391124011241112421124311244112451124611247112481124911250112511125211253112541125511256112571125811259112601126111262112631126411265112661126711268112691127011271112721127311274112751127611277112781127911280112811128211283112841128511286112871128811289112901129111292112931129411295112961129711298112991130011301113021130311304113051130611307113081130911310113111131211313113141131511316113171131811319113201132111322113231132411325113261132711328113291133011331113321133311334113351133611337113381133911340113411134211343113441134511346113471134811349113501135111352113531135411355113561135711358113591136011361113621136311364113651136611367113681136911370113711137211373113741137511376113771137811379113801138111382113831138411385113861138711388113891139011391113921139311394113951139611397113981139911400114011140211403114041140511406114071140811409114101141111412114131141411415114161141711418114191142011421114221142311424114251142611427114281142911430114311143211433114341143511436114371143811439114401144111442114431144411445114461144711448114491145011451114521145311454114551145611457114581145911460114611146211463114641146511466114671146811469114701147111472114731147411475114761147711478114791148011481114821148311484114851148611487114881148911490114911149211493114941149511496114971149811499115001150111502115031150411505115061150711508115091151011511115121151311514115151151611517115181151911520115211152211523115241152511526115271152811529115301153111532115331153411535115361153711538115391154011541115421154311544115451154611547115481154911550115511155211553115541155511556115571155811559115601156111562115631156411565115661156711568115691157011571115721157311574115751157611577115781157911580115811158211583115841158511586115871158811589115901159111592115931159411595115961159711598115991160011601116021160311604116051160611607116081160911610116111161211613116141161511616116171161811619116201162111622116231162411625116261162711628116291163011631116321163311634116351163611637116381163911640116411164211643116441164511646116471164811649116501165111652116531165411655116561165711658116591166011661116621166311664116651166611667116681166911670116711167211673116741167511676116771167811679116801168111682116831168411685116861168711688116891169011691116921169311694116951169611697116981169911700117011170211703117041170511706117071170811709117101171111712117131171411715117161171711718117191172011721117221172311724117251172611727117281172911730117311173211733117341173511736117371173811739117401174111742117431174411745117461174711748117491175011751117521175311754117551175611757117581175911760117611176211763117641176511766117671176811769117701177111772117731177411775117761177711778117791178011781117821178311784117851178611787117881178911790117911179211793117941179511796117971179811799118001180111802118031180411805118061180711808118091181011811118121181311814118151181611817118181181911820118211182211823118241182511826118271182811829118301183111832118331183411835118361183711838118391184011841118421184311844118451184611847118481184911850118511185211853118541185511856118571185811859118601186111862118631186411865118661186711868118691187011871118721187311874118751187611877118781187911880118811188211883118841188511886118871188811889118901189111892118931189411895118961189711898118991190011901119021190311904119051190611907119081190911910119111191211913119141191511916119171191811919119201192111922119231192411925119261192711928119291193011931119321193311934119351193611937119381193911940119411194211943119441194511946119471194811949119501195111952119531195411955119561195711958119591196011961119621196311964119651196611967119681196911970119711197211973119741197511976119771197811979119801198111982119831198411985119861198711988119891199011991119921199311994119951199611997119981199912000120011200212003120041200512006120071200812009120101201112012120131201412015120161201712018120191202012021120221202312024120251202612027120281202912030120311203212033120341203512036120371203812039120401204112042120431204412045120461204712048120491205012051120521205312054120551205612057120581205912060120611206212063120641206512066120671206812069120701207112072120731207412075120761207712078120791208012081120821208312084120851208612087120881208912090120911209212093120941209512096120971209812099121001210112102121031210412105121061210712108121091211012111121121211312114121151211612117121181211912120121211212212123121241212512126121271212812129121301213112132121331213412135121361213712138121391214012141121421214312144121451214612147121481214912150121511215212153121541215512156121571215812159121601216112162121631216412165121661216712168121691217012171121721217312174121751217612177121781217912180121811218212183121841218512186121871218812189121901219112192121931219412195121961219712198121991220012201122021220312204122051220612207122081220912210122111221212213122141221512216122171221812219122201222112222122231222412225122261222712228122291223012231122321223312234122351223612237122381223912240122411224212243122441224512246122471224812249122501225112252122531225412255122561225712258122591226012261122621226312264122651226612267122681226912270122711227212273122741227512276122771227812279122801228112282122831228412285122861228712288122891229012291122921229312294122951229612297122981229912300123011230212303123041230512306123071230812309123101231112312123131231412315123161231712318123191232012321123221232312324123251232612327123281232912330123311233212333123341233512336123371233812339123401234112342123431234412345123461234712348123491235012351123521235312354123551235612357123581235912360123611236212363123641236512366123671236812369123701237112372123731237412375123761237712378123791238012381123821238312384123851238612387123881238912390123911239212393123941239512396123971239812399124001240112402124031240412405124061240712408124091241012411124121241312414124151241612417124181241912420124211242212423124241242512426124271242812429124301243112432124331243412435124361243712438124391244012441124421244312444124451244612447124481244912450124511245212453124541245512456124571245812459124601246112462124631246412465124661246712468124691247012471124721247312474124751247612477124781247912480124811248212483124841248512486124871248812489124901249112492124931249412495124961249712498124991250012501125021250312504125051250612507125081250912510125111251212513125141251512516125171251812519125201252112522125231252412525125261252712528125291253012531125321253312534125351253612537125381253912540125411254212543125441254512546125471254812549125501255112552125531255412555125561255712558125591256012561125621256312564125651256612567125681256912570125711257212573125741257512576125771257812579125801258112582125831258412585125861258712588125891259012591125921259312594125951259612597125981259912600126011260212603126041260512606126071260812609126101261112612126131261412615126161261712618126191262012621126221262312624126251262612627126281262912630126311263212633126341263512636126371263812639126401264112642126431264412645126461264712648126491265012651126521265312654126551265612657126581265912660126611266212663126641266512666126671266812669126701267112672126731267412675126761267712678126791268012681126821268312684126851268612687126881268912690126911269212693126941269512696126971269812699127001270112702127031270412705127061270712708127091271012711127121271312714127151271612717127181271912720127211272212723127241272512726127271272812729127301273112732127331273412735127361273712738127391274012741127421274312744127451274612747127481274912750127511275212753127541275512756127571275812759127601276112762127631276412765127661276712768127691277012771127721277312774127751277612777127781277912780127811278212783127841278512786127871278812789127901279112792127931279412795127961279712798127991280012801128021280312804128051280612807128081280912810128111281212813128141281512816128171281812819128201282112822128231282412825128261282712828128291283012831128321283312834128351283612837128381283912840128411284212843128441284512846128471284812849128501285112852128531285412855128561285712858128591286012861128621286312864128651286612867128681286912870128711287212873128741287512876128771287812879128801288112882128831288412885128861288712888128891289012891128921289312894128951289612897128981289912900129011290212903129041290512906129071290812909129101291112912129131291412915129161291712918129191292012921129221292312924129251292612927129281292912930129311293212933129341293512936129371293812939129401294112942129431294412945129461294712948129491295012951129521295312954129551295612957129581295912960129611296212963129641296512966129671296812969129701297112972129731297412975129761297712978129791298012981129821298312984129851298612987129881298912990129911299212993129941299512996129971299812999130001300113002130031300413005130061300713008130091301013011130121301313014130151301613017130181301913020130211302213023130241302513026130271302813029130301303113032130331303413035130361303713038130391304013041130421304313044130451304613047130481304913050130511305213053130541305513056130571305813059130601306113062130631306413065130661306713068130691307013071130721307313074130751307613077130781307913080130811308213083130841308513086130871308813089130901309113092130931309413095130961309713098130991310013101131021310313104131051310613107131081310913110131111311213113131141311513116131171311813119131201312113122131231312413125131261312713128131291313013131131321313313134131351313613137131381313913140131411314213143131441314513146131471314813149131501315113152131531315413155131561315713158131591316013161131621316313164131651316613167131681316913170131711317213173131741317513176131771317813179131801318113182131831318413185131861318713188131891319013191131921319313194131951319613197131981319913200132011320213203132041320513206132071320813209132101321113212132131321413215132161321713218132191322013221132221322313224132251322613227132281322913230132311323213233132341323513236132371323813239132401324113242132431324413245132461324713248132491325013251132521325313254132551325613257132581325913260132611326213263132641326513266132671326813269132701327113272132731327413275132761327713278132791328013281132821328313284132851328613287132881328913290132911329213293132941329513296132971329813299133001330113302133031330413305133061330713308133091331013311133121331313314133151331613317133181331913320133211332213323133241332513326133271332813329133301333113332133331333413335133361333713338133391334013341133421334313344133451334613347133481334913350133511335213353133541335513356133571335813359133601336113362133631336413365133661336713368133691337013371133721337313374133751337613377133781337913380133811338213383133841338513386133871338813389133901339113392133931339413395133961339713398133991340013401134021340313404134051340613407134081340913410134111341213413134141341513416134171341813419134201342113422134231342413425134261342713428134291343013431134321343313434134351343613437134381343913440134411344213443134441344513446134471344813449134501345113452134531345413455134561345713458134591346013461134621346313464134651346613467134681346913470134711347213473134741347513476134771347813479134801348113482134831348413485134861348713488134891349013491134921349313494134951349613497134981349913500135011350213503135041350513506135071350813509135101351113512135131351413515135161351713518135191352013521135221352313524135251352613527135281352913530135311353213533135341353513536135371353813539135401354113542135431354413545135461354713548135491355013551135521355313554135551355613557135581355913560135611356213563135641356513566135671356813569135701357113572135731357413575135761357713578135791358013581135821358313584135851358613587135881358913590135911359213593135941359513596135971359813599136001360113602136031360413605136061360713608136091361013611136121361313614136151361613617136181361913620136211362213623136241362513626136271362813629136301363113632136331363413635136361363713638136391364013641136421364313644136451364613647136481364913650136511365213653136541365513656136571365813659136601366113662136631366413665136661366713668136691367013671136721367313674136751367613677136781367913680136811368213683136841368513686136871368813689136901369113692136931369413695136961369713698136991370013701137021370313704137051370613707137081370913710137111371213713137141371513716137171371813719137201372113722137231372413725137261372713728137291373013731137321373313734137351373613737137381373913740137411374213743137441374513746137471374813749137501375113752137531375413755137561375713758137591376013761137621376313764137651376613767137681376913770137711377213773137741377513776137771377813779137801378113782137831378413785137861378713788137891379013791137921379313794137951379613797137981379913800138011380213803138041380513806138071380813809138101381113812138131381413815138161381713818138191382013821138221382313824138251382613827138281382913830138311383213833138341383513836138371383813839138401384113842138431384413845138461384713848138491385013851138521385313854138551385613857138581385913860138611386213863138641386513866138671386813869138701387113872138731387413875138761387713878138791388013881138821388313884138851388613887138881388913890138911389213893138941389513896138971389813899139001390113902139031390413905139061390713908139091391013911139121391313914139151391613917139181391913920139211392213923139241392513926139271392813929139301393113932139331393413935139361393713938139391394013941139421394313944139451394613947139481394913950139511395213953139541395513956139571395813959139601396113962139631396413965139661396713968139691397013971139721397313974139751397613977139781397913980139811398213983139841398513986139871398813989139901399113992139931399413995139961399713998139991400014001140021400314004140051400614007140081400914010140111401214013140141401514016140171401814019140201402114022140231402414025140261402714028140291403014031140321403314034140351403614037140381403914040140411404214043140441404514046140471404814049140501405114052140531405414055140561405714058140591406014061140621406314064140651406614067140681406914070140711407214073140741407514076140771407814079140801408114082140831408414085140861408714088140891409014091140921409314094140951409614097140981409914100141011410214103141041410514106141071410814109141101411114112141131411414115141161411714118141191412014121141221412314124141251412614127141281412914130141311413214133141341413514136141371413814139141401414114142141431414414145141461414714148141491415014151141521415314154141551415614157141581415914160141611416214163141641416514166141671416814169141701417114172141731417414175141761417714178141791418014181141821418314184141851418614187141881418914190141911419214193141941419514196141971419814199142001420114202142031420414205142061420714208142091421014211142121421314214142151421614217142181421914220142211422214223142241422514226142271422814229142301423114232142331423414235142361423714238142391424014241142421424314244142451424614247142481424914250142511425214253142541425514256142571425814259142601426114262142631426414265142661426714268142691427014271142721427314274142751427614277142781427914280142811428214283142841428514286142871428814289142901429114292142931429414295142961429714298142991430014301143021430314304143051430614307143081430914310143111431214313143141431514316143171431814319143201432114322143231432414325143261432714328143291433014331143321433314334143351433614337143381433914340143411434214343143441434514346143471434814349143501435114352143531435414355143561435714358143591436014361143621436314364143651436614367143681436914370143711437214373143741437514376143771437814379143801438114382143831438414385143861438714388143891439014391143921439314394143951439614397143981439914400144011440214403144041440514406144071440814409144101441114412144131441414415144161441714418144191442014421144221442314424144251442614427144281442914430144311443214433144341443514436144371443814439144401444114442144431444414445144461444714448144491445014451144521445314454144551445614457144581445914460144611446214463144641446514466144671446814469144701447114472144731447414475144761447714478144791448014481144821448314484144851448614487144881448914490144911449214493144941449514496144971449814499145001450114502145031450414505145061450714508145091451014511145121451314514145151451614517145181451914520145211452214523145241452514526145271452814529145301453114532145331453414535145361453714538145391454014541145421454314544145451454614547145481454914550145511455214553145541455514556145571455814559145601456114562145631456414565145661456714568145691457014571145721457314574145751457614577145781457914580145811458214583145841458514586145871458814589145901459114592145931459414595145961459714598145991460014601146021460314604146051460614607146081460914610146111461214613146141461514616146171461814619146201462114622146231462414625146261462714628146291463014631146321463314634146351463614637146381463914640146411464214643146441464514646146471464814649146501465114652146531465414655146561465714658146591466014661146621466314664146651466614667146681466914670146711467214673146741467514676146771467814679146801468114682146831468414685146861468714688146891469014691146921469314694146951469614697146981469914700147011470214703147041470514706147071470814709147101471114712147131471414715147161471714718147191472014721147221472314724147251472614727147281472914730147311473214733147341473514736147371473814739147401474114742147431474414745147461474714748147491475014751147521475314754147551475614757147581475914760147611476214763147641476514766147671476814769147701477114772147731477414775147761477714778147791478014781147821478314784147851478614787147881478914790147911479214793147941479514796147971479814799148001480114802148031480414805148061480714808148091481014811148121481314814148151481614817148181481914820148211482214823148241482514826148271482814829148301483114832148331483414835148361483714838148391484014841148421484314844148451484614847148481484914850148511485214853148541485514856148571485814859148601486114862148631486414865148661486714868148691487014871148721487314874148751487614877148781487914880148811488214883148841488514886148871488814889148901489114892148931489414895148961489714898148991490014901149021490314904149051490614907149081490914910149111491214913149141491514916149171491814919149201492114922149231492414925149261492714928149291493014931149321493314934149351493614937149381493914940149411494214943149441494514946149471494814949149501495114952149531495414955149561495714958149591496014961149621496314964149651496614967149681496914970149711497214973149741497514976149771497814979149801498114982149831498414985149861498714988149891499014991149921499314994149951499614997149981499915000150011500215003150041500515006150071500815009150101501115012150131501415015150161501715018150191502015021150221502315024150251502615027150281502915030150311503215033150341503515036150371503815039150401504115042150431504415045150461504715048150491505015051150521505315054150551505615057150581505915060150611506215063150641506515066150671506815069150701507115072150731507415075150761507715078150791508015081150821508315084150851508615087150881508915090150911509215093150941509515096150971509815099151001510115102151031510415105151061510715108151091511015111151121511315114151151511615117151181511915120151211512215123151241512515126151271512815129151301513115132151331513415135151361513715138151391514015141151421514315144151451514615147151481514915150151511515215153151541515515156151571515815159151601516115162151631516415165151661516715168151691517015171151721517315174151751517615177151781517915180151811518215183151841518515186151871518815189151901519115192151931519415195151961519715198151991520015201152021520315204152051520615207152081520915210152111521215213152141521515216152171521815219152201522115222152231522415225152261522715228152291523015231152321523315234152351523615237152381523915240152411524215243152441524515246152471524815249152501525115252152531525415255152561525715258152591526015261152621526315264152651526615267152681526915270152711527215273152741527515276152771527815279152801528115282152831528415285152861528715288152891529015291152921529315294152951529615297152981529915300153011530215303153041530515306153071530815309153101531115312153131531415315153161531715318153191532015321153221532315324153251532615327153281532915330153311533215333153341533515336153371533815339153401534115342153431534415345153461534715348153491535015351153521535315354153551535615357153581535915360153611536215363153641536515366153671536815369153701537115372153731537415375153761537715378153791538015381153821538315384153851538615387153881538915390153911539215393153941539515396153971539815399154001540115402154031540415405154061540715408154091541015411154121541315414154151541615417154181541915420154211542215423154241542515426154271542815429154301543115432154331543415435154361543715438154391544015441154421544315444154451544615447154481544915450154511545215453154541545515456154571545815459154601546115462154631546415465154661546715468154691547015471154721547315474154751547615477154781547915480154811548215483154841548515486154871548815489154901549115492154931549415495154961549715498154991550015501155021550315504155051550615507155081550915510155111551215513155141551515516155171551815519155201552115522155231552415525155261552715528155291553015531155321553315534155351553615537155381553915540155411554215543155441554515546155471554815549155501555115552155531555415555155561555715558155591556015561155621556315564155651556615567155681556915570155711557215573155741557515576155771557815579155801558115582155831558415585155861558715588155891559015591155921559315594155951559615597155981559915600156011560215603156041560515606156071560815609156101561115612156131561415615156161561715618156191562015621156221562315624156251562615627156281562915630156311563215633156341563515636156371563815639156401564115642156431564415645156461564715648156491565015651156521565315654156551565615657156581565915660156611566215663156641566515666156671566815669156701567115672156731567415675156761567715678156791568015681156821568315684156851568615687156881568915690156911569215693156941569515696156971569815699157001570115702157031570415705157061570715708157091571015711157121571315714157151571615717157181571915720157211572215723157241572515726157271572815729157301573115732157331573415735157361573715738157391574015741157421574315744157451574615747157481574915750157511575215753157541575515756157571575815759157601576115762157631576415765157661576715768157691577015771157721577315774157751577615777157781577915780157811578215783157841578515786157871578815789157901579115792157931579415795157961579715798157991580015801158021580315804158051580615807158081580915810158111581215813158141581515816158171581815819158201582115822158231582415825158261582715828158291583015831158321583315834158351583615837158381583915840158411584215843158441584515846158471584815849158501585115852158531585415855158561585715858158591586015861158621586315864158651586615867158681586915870158711587215873158741587515876158771587815879158801588115882158831588415885158861588715888158891589015891158921589315894158951589615897158981589915900159011590215903159041590515906159071590815909159101591115912159131591415915159161591715918159191592015921159221592315924159251592615927159281592915930159311593215933159341593515936159371593815939159401594115942159431594415945159461594715948159491595015951159521595315954159551595615957159581595915960159611596215963159641596515966159671596815969159701597115972159731597415975159761597715978159791598015981159821598315984159851598615987159881598915990159911599215993159941599515996159971599815999160001600116002160031600416005160061600716008160091601016011160121601316014160151601616017160181601916020160211602216023160241602516026160271602816029160301603116032160331603416035160361603716038160391604016041160421604316044160451604616047160481604916050160511605216053160541605516056160571605816059160601606116062160631606416065160661606716068160691607016071160721607316074160751607616077160781607916080160811608216083160841608516086160871608816089160901609116092160931609416095160961609716098160991610016101161021610316104161051610616107161081610916110161111611216113161141611516116161171611816119161201612116122161231612416125161261612716128161291613016131161321613316134161351613616137161381613916140161411614216143161441614516146161471614816149161501615116152161531615416155161561615716158161591616016161161621616316164161651616616167161681616916170161711617216173161741617516176161771617816179161801618116182161831618416185161861618716188161891619016191161921619316194161951619616197161981619916200162011620216203162041620516206162071620816209162101621116212162131621416215162161621716218162191622016221162221622316224162251622616227162281622916230162311623216233162341623516236162371623816239162401624116242162431624416245162461624716248162491625016251162521625316254162551625616257162581625916260162611626216263162641626516266162671626816269162701627116272162731627416275162761627716278162791628016281162821628316284162851628616287162881628916290162911629216293162941629516296162971629816299163001630116302163031630416305163061630716308163091631016311163121631316314163151631616317163181631916320163211632216323163241632516326163271632816329163301633116332163331633416335163361633716338163391634016341163421634316344163451634616347163481634916350163511635216353163541635516356163571635816359163601636116362163631636416365163661636716368163691637016371163721637316374163751637616377163781637916380163811638216383163841638516386163871638816389163901639116392163931639416395163961639716398163991640016401164021640316404164051640616407164081640916410164111641216413164141641516416164171641816419164201642116422164231642416425164261642716428164291643016431164321643316434164351643616437164381643916440164411644216443164441644516446164471644816449164501645116452164531645416455164561645716458164591646016461164621646316464164651646616467164681646916470164711647216473164741647516476164771647816479164801648116482164831648416485164861648716488164891649016491164921649316494164951649616497164981649916500165011650216503165041650516506165071650816509165101651116512165131651416515165161651716518165191652016521165221652316524165251652616527165281652916530165311653216533165341653516536165371653816539165401654116542165431654416545165461654716548165491655016551165521655316554165551655616557165581655916560165611656216563165641656516566165671656816569165701657116572165731657416575165761657716578165791658016581165821658316584165851658616587165881658916590165911659216593165941659516596165971659816599166001660116602166031660416605166061660716608166091661016611166121661316614166151661616617166181661916620166211662216623166241662516626166271662816629166301663116632166331663416635166361663716638166391664016641166421664316644166451664616647166481664916650166511665216653166541665516656166571665816659166601666116662166631666416665166661666716668166691667016671166721667316674166751667616677166781667916680166811668216683166841668516686166871668816689166901669116692166931669416695166961669716698166991670016701167021670316704167051670616707167081670916710167111671216713167141671516716167171671816719167201672116722167231672416725167261672716728167291673016731167321673316734167351673616737167381673916740167411674216743167441674516746167471674816749167501675116752167531675416755167561675716758167591676016761167621676316764167651676616767167681676916770167711677216773167741677516776167771677816779167801678116782167831678416785167861678716788167891679016791167921679316794167951679616797167981679916800168011680216803168041680516806168071680816809168101681116812168131681416815168161681716818168191682016821168221682316824168251682616827168281682916830168311683216833168341683516836168371683816839168401684116842168431684416845168461684716848168491685016851168521685316854168551685616857168581685916860168611686216863168641686516866168671686816869168701687116872168731687416875168761687716878168791688016881168821688316884168851688616887168881688916890168911689216893168941689516896168971689816899169001690116902169031690416905169061690716908169091691016911169121691316914169151691616917169181691916920169211692216923169241692516926169271692816929169301693116932169331693416935169361693716938169391694016941169421694316944169451694616947169481694916950169511695216953169541695516956169571695816959169601696116962169631696416965169661696716968169691697016971169721697316974169751697616977169781697916980169811698216983169841698516986169871698816989169901699116992169931699416995169961699716998169991700017001170021700317004170051700617007170081700917010170111701217013170141701517016170171701817019170201702117022170231702417025170261702717028170291703017031170321703317034170351703617037170381703917040170411704217043170441704517046170471704817049170501705117052170531705417055170561705717058170591706017061170621706317064170651706617067170681706917070170711707217073170741707517076170771707817079170801708117082170831708417085170861708717088170891709017091170921709317094170951709617097170981709917100171011710217103171041710517106171071710817109171101711117112171131711417115171161711717118171191712017121171221712317124171251712617127171281712917130171311713217133171341713517136171371713817139171401714117142171431714417145171461714717148171491715017151171521715317154171551715617157171581715917160171611716217163171641716517166171671716817169171701717117172171731717417175171761717717178171791718017181171821718317184171851718617187171881718917190171911719217193171941719517196171971719817199172001720117202172031720417205172061720717208172091721017211172121721317214172151721617217172181721917220172211722217223172241722517226172271722817229172301723117232172331723417235172361723717238172391724017241172421724317244172451724617247172481724917250172511725217253172541725517256172571725817259172601726117262172631726417265172661726717268172691727017271172721727317274172751727617277172781727917280172811728217283172841728517286172871728817289172901729117292172931729417295172961729717298172991730017301173021730317304173051730617307173081730917310173111731217313173141731517316173171731817319173201732117322173231732417325173261732717328173291733017331173321733317334173351733617337173381733917340173411734217343173441734517346173471734817349173501735117352173531735417355173561735717358173591736017361173621736317364173651736617367173681736917370173711737217373173741737517376173771737817379173801738117382173831738417385173861738717388173891739017391173921739317394173951739617397173981739917400174011740217403174041740517406174071740817409174101741117412174131741417415174161741717418174191742017421174221742317424174251742617427174281742917430174311743217433174341743517436174371743817439174401744117442174431744417445174461744717448174491745017451174521745317454174551745617457174581745917460174611746217463174641746517466174671746817469174701747117472174731747417475174761747717478174791748017481174821748317484174851748617487174881748917490174911749217493174941749517496174971749817499175001750117502175031750417505175061750717508175091751017511175121751317514175151751617517175181751917520175211752217523175241752517526175271752817529175301753117532175331753417535175361753717538175391754017541175421754317544175451754617547175481754917550175511755217553175541755517556175571755817559175601756117562175631756417565175661756717568175691757017571175721757317574175751757617577175781757917580175811758217583175841758517586175871758817589175901759117592175931759417595175961759717598175991760017601176021760317604176051760617607176081760917610176111761217613176141761517616176171761817619176201762117622176231762417625176261762717628176291763017631176321763317634176351763617637176381763917640176411764217643176441764517646176471764817649176501765117652176531765417655176561765717658176591766017661176621766317664176651766617667176681766917670176711767217673176741767517676176771767817679176801768117682176831768417685176861768717688176891769017691176921769317694176951769617697176981769917700177011770217703177041770517706177071770817709177101771117712177131771417715177161771717718177191772017721177221772317724177251772617727177281772917730177311773217733177341773517736177371773817739177401774117742177431774417745177461774717748177491775017751177521775317754177551775617757177581775917760177611776217763177641776517766177671776817769177701777117772177731777417775177761777717778177791778017781177821778317784177851778617787177881778917790177911779217793177941779517796177971779817799178001780117802178031780417805178061780717808178091781017811178121781317814178151781617817178181781917820178211782217823178241782517826178271782817829178301783117832178331783417835178361783717838178391784017841178421784317844178451784617847178481784917850178511785217853178541785517856178571785817859178601786117862178631786417865178661786717868178691787017871178721787317874178751787617877178781787917880178811788217883178841788517886178871788817889178901789117892178931789417895178961789717898178991790017901179021790317904179051790617907179081790917910179111791217913179141791517916179171791817919179201792117922179231792417925179261792717928179291793017931179321793317934179351793617937179381793917940179411794217943179441794517946179471794817949179501795117952179531795417955179561795717958179591796017961179621796317964179651796617967179681796917970179711797217973179741797517976179771797817979179801798117982179831798417985179861798717988179891799017991179921799317994179951799617997179981799918000180011800218003180041800518006180071800818009180101801118012180131801418015180161801718018180191802018021180221802318024180251802618027180281802918030180311803218033180341803518036180371803818039180401804118042180431804418045180461804718048180491805018051180521805318054180551805618057180581805918060180611806218063180641806518066180671806818069180701807118072180731807418075180761807718078180791808018081180821808318084180851808618087180881808918090180911809218093180941809518096180971809818099181001810118102181031810418105181061810718108181091811018111181121811318114181151811618117181181811918120181211812218123181241812518126181271812818129181301813118132181331813418135181361813718138181391814018141181421814318144181451814618147181481814918150181511815218153181541815518156181571815818159181601816118162181631816418165181661816718168181691817018171181721817318174181751817618177181781817918180181811818218183181841818518186181871818818189181901819118192181931819418195181961819718198181991820018201182021820318204182051820618207182081820918210182111821218213182141821518216182171821818219182201822118222182231822418225182261822718228182291823018231182321823318234182351823618237182381823918240182411824218243182441824518246182471824818249182501825118252182531825418255182561825718258182591826018261182621826318264182651826618267182681826918270182711827218273182741827518276182771827818279182801828118282182831828418285182861828718288182891829018291182921829318294182951829618297182981829918300183011830218303183041830518306183071830818309183101831118312183131831418315183161831718318183191832018321183221832318324183251832618327183281832918330183311833218333183341833518336183371833818339183401834118342183431834418345183461834718348183491835018351183521835318354183551835618357183581835918360183611836218363183641836518366183671836818369183701837118372183731837418375183761837718378183791838018381183821838318384183851838618387183881838918390183911839218393183941839518396183971839818399184001840118402184031840418405184061840718408184091841018411184121841318414184151841618417184181841918420184211842218423184241842518426184271842818429184301843118432184331843418435184361843718438184391844018441184421844318444184451844618447184481844918450184511845218453184541845518456184571845818459184601846118462184631846418465184661846718468184691847018471184721847318474184751847618477184781847918480184811848218483184841848518486184871848818489184901849118492184931849418495184961849718498184991850018501185021850318504185051850618507185081850918510185111851218513185141851518516185171851818519185201852118522185231852418525185261852718528185291853018531185321853318534185351853618537185381853918540185411854218543185441854518546185471854818549185501855118552185531855418555185561855718558185591856018561185621856318564185651856618567185681856918570185711857218573185741857518576185771857818579185801858118582185831858418585185861858718588185891859018591185921859318594185951859618597185981859918600186011860218603186041860518606186071860818609186101861118612186131861418615186161861718618186191862018621186221862318624186251862618627186281862918630186311863218633186341863518636186371863818639186401864118642186431864418645186461864718648186491865018651186521865318654186551865618657186581865918660186611866218663186641866518666186671866818669186701867118672186731867418675186761867718678186791868018681186821868318684186851868618687186881868918690186911869218693186941869518696186971869818699187001870118702187031870418705187061870718708187091871018711187121871318714187151871618717187181871918720187211872218723187241872518726187271872818729187301873118732187331873418735187361873718738187391874018741187421874318744187451874618747187481874918750187511875218753187541875518756187571875818759187601876118762187631876418765187661876718768187691877018771187721877318774187751877618777187781877918780187811878218783187841878518786187871878818789187901879118792187931879418795187961879718798187991880018801188021880318804188051880618807188081880918810188111881218813188141881518816188171881818819188201882118822188231882418825188261882718828188291883018831188321883318834188351883618837188381883918840188411884218843188441884518846188471884818849188501885118852188531885418855188561885718858188591886018861188621886318864188651886618867188681886918870188711887218873188741887518876188771887818879188801888118882188831888418885188861888718888188891889018891188921889318894188951889618897188981889918900189011890218903189041890518906189071890818909189101891118912189131891418915189161891718918189191892018921189221892318924189251892618927189281892918930189311893218933189341893518936189371893818939189401894118942189431894418945189461894718948189491895018951189521895318954189551895618957189581895918960189611896218963189641896518966189671896818969189701897118972189731897418975189761897718978189791898018981189821898318984189851898618987189881898918990189911899218993189941899518996189971899818999190001900119002190031900419005190061900719008190091901019011190121901319014190151901619017190181901919020190211902219023190241902519026190271902819029190301903119032190331903419035190361903719038190391904019041190421904319044190451904619047190481904919050190511905219053190541905519056190571905819059190601906119062190631906419065190661906719068190691907019071190721907319074190751907619077190781907919080190811908219083190841908519086190871908819089190901909119092190931909419095190961909719098190991910019101191021910319104191051910619107191081910919110191111911219113191141911519116191171911819119191201912119122191231912419125191261912719128191291913019131191321913319134191351913619137191381913919140191411914219143191441914519146191471914819149191501915119152191531915419155191561915719158191591916019161191621916319164191651916619167191681916919170191711917219173191741917519176191771917819179191801918119182191831918419185191861918719188191891919019191191921919319194191951919619197191981919919200192011920219203192041920519206192071920819209192101921119212192131921419215192161921719218192191922019221192221922319224192251922619227192281922919230192311923219233192341923519236192371923819239192401924119242192431924419245192461924719248192491925019251192521925319254192551925619257192581925919260192611926219263192641926519266192671926819269192701927119272192731927419275192761927719278192791928019281192821928319284192851928619287192881928919290192911929219293192941929519296192971929819299193001930119302193031930419305193061930719308193091931019311193121931319314193151931619317193181931919320193211932219323193241932519326193271932819329193301933119332193331933419335193361933719338193391934019341193421934319344193451934619347193481934919350193511935219353193541935519356193571935819359193601936119362193631936419365193661936719368193691937019371193721937319374193751937619377193781937919380193811938219383193841938519386193871938819389193901939119392193931939419395193961939719398193991940019401194021940319404194051940619407194081940919410194111941219413194141941519416194171941819419194201942119422194231942419425194261942719428194291943019431194321943319434194351943619437194381943919440194411944219443194441944519446194471944819449194501945119452194531945419455194561945719458194591946019461194621946319464194651946619467194681946919470194711947219473194741947519476194771947819479194801948119482194831948419485194861948719488194891949019491194921949319494194951949619497194981949919500195011950219503195041950519506195071950819509195101951119512195131951419515195161951719518195191952019521195221952319524195251952619527195281952919530195311953219533195341953519536195371953819539195401954119542195431954419545195461954719548195491955019551195521955319554195551955619557195581955919560195611956219563195641956519566195671956819569195701957119572195731957419575195761957719578195791958019581195821958319584195851958619587195881958919590195911959219593195941959519596195971959819599196001960119602196031960419605196061960719608196091961019611196121961319614196151961619617196181961919620196211962219623196241962519626196271962819629196301963119632196331963419635196361963719638196391964019641196421964319644196451964619647196481964919650196511965219653196541965519656196571965819659196601966119662196631966419665196661966719668196691967019671196721967319674196751967619677196781967919680196811968219683196841968519686196871968819689196901969119692196931969419695196961969719698196991970019701197021970319704197051970619707197081970919710197111971219713197141971519716197171971819719197201972119722197231972419725197261972719728197291973019731197321973319734197351973619737197381973919740197411974219743197441974519746197471974819749197501975119752197531975419755197561975719758197591976019761197621976319764197651976619767197681976919770197711977219773197741977519776197771977819779197801978119782197831978419785197861978719788197891979019791197921979319794197951979619797197981979919800198011980219803198041980519806198071980819809198101981119812198131981419815198161981719818198191982019821198221982319824198251982619827198281982919830198311983219833198341983519836198371983819839198401984119842198431984419845198461984719848198491985019851198521985319854198551985619857198581985919860198611986219863198641986519866198671986819869198701987119872198731987419875198761987719878198791988019881198821988319884198851988619887198881988919890198911989219893198941989519896198971989819899199001990119902199031990419905199061990719908199091991019911199121991319914199151991619917199181991919920199211992219923199241992519926199271992819929199301993119932199331993419935199361993719938199391994019941199421994319944199451994619947199481994919950199511995219953199541995519956199571995819959199601996119962199631996419965199661996719968199691997019971199721997319974199751997619977199781997919980199811998219983199841998519986199871998819989199901999119992199931999419995199961999719998199992000020001200022000320004200052000620007200082000920010200112001220013200142001520016200172001820019200202002120022200232002420025200262002720028200292003020031200322003320034200352003620037200382003920040200412004220043200442004520046200472004820049200502005120052200532005420055200562005720058200592006020061200622006320064200652006620067200682006920070200712007220073200742007520076200772007820079200802008120082200832008420085200862008720088200892009020091200922009320094200952009620097200982009920100201012010220103201042010520106201072010820109201102011120112201132011420115201162011720118201192012020121201222012320124201252012620127201282012920130201312013220133201342013520136201372013820139201402014120142201432014420145201462014720148201492015020151201522015320154201552015620157201582015920160201612016220163201642016520166201672016820169201702017120172201732017420175201762017720178201792018020181201822018320184201852018620187201882018920190201912019220193201942019520196201972019820199202002020120202202032020420205202062020720208202092021020211202122021320214202152021620217202182021920220202212022220223202242022520226202272022820229202302023120232202332023420235202362023720238202392024020241202422024320244202452024620247202482024920250202512025220253202542025520256202572025820259202602026120262202632026420265202662026720268202692027020271202722027320274202752027620277202782027920280202812028220283202842028520286202872028820289202902029120292202932029420295202962029720298202992030020301203022030320304203052030620307203082030920310203112031220313203142031520316203172031820319203202032120322203232032420325203262032720328203292033020331203322033320334
  1. /*!
  2. * Vuetify v3.3.11
  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. // Types
  12. // eslint-disable-line vue/prefer-import-from-vue
  13. /**
  14. * Creates a factory function for props definitions.
  15. * This is used to define props in a composable then override
  16. * default values in an implementing component.
  17. *
  18. * @example Simplified signature
  19. * (props: Props) => (defaults?: Record<keyof props, any>) => Props
  20. *
  21. * @example Usage
  22. * const makeProps = propsFactory({
  23. * foo: String,
  24. * })
  25. *
  26. * defineComponent({
  27. * props: {
  28. * ...makeProps({
  29. * foo: 'a',
  30. * }),
  31. * },
  32. * setup (props) {
  33. * // would be "string | undefined", now "string" because a default has been provided
  34. * props.foo
  35. * },
  36. * }
  37. */
  38. function propsFactory(props, source) {
  39. return defaults => {
  40. return Object.keys(props).reduce((obj, prop) => {
  41. const isObjectDefinition = typeof props[prop] === 'object' && props[prop] != null && !Array.isArray(props[prop]);
  42. const definition = isObjectDefinition ? props[prop] : {
  43. type: props[prop]
  44. };
  45. if (defaults && prop in defaults) {
  46. obj[prop] = {
  47. ...definition,
  48. default: defaults[prop]
  49. };
  50. } else {
  51. obj[prop] = definition;
  52. }
  53. if (source && !obj[prop].source) {
  54. obj[prop].source = source;
  55. }
  56. return obj;
  57. }, {});
  58. };
  59. }
  60. // Utilities
  61. // Types
  62. // Composables
  63. const makeComponentProps = propsFactory({
  64. class: [String, Array],
  65. style: {
  66. type: [String, Array, Object],
  67. default: null
  68. }
  69. }, 'component');
  70. const IN_BROWSER = typeof window !== 'undefined';
  71. const SUPPORTS_INTERSECTION = IN_BROWSER && 'IntersectionObserver' in window;
  72. const SUPPORTS_TOUCH = IN_BROWSER && ('ontouchstart' in window || window.navigator.maxTouchPoints > 0);
  73. function _classPrivateFieldInitSpec(obj, privateMap, value) { _checkPrivateRedeclaration(obj, privateMap); privateMap.set(obj, value); }
  74. function _checkPrivateRedeclaration(obj, privateCollection) { if (privateCollection.has(obj)) { throw new TypeError("Cannot initialize the same private elements twice on an object"); } }
  75. function _classPrivateFieldSet(receiver, privateMap, value) { var descriptor = _classExtractFieldDescriptor(receiver, privateMap, "set"); _classApplyDescriptorSet(receiver, descriptor, value); return value; }
  76. function _classApplyDescriptorSet(receiver, descriptor, value) { if (descriptor.set) { descriptor.set.call(receiver, value); } else { if (!descriptor.writable) { throw new TypeError("attempted to set read only private field"); } descriptor.value = value; } }
  77. function _classPrivateFieldGet(receiver, privateMap) { var descriptor = _classExtractFieldDescriptor(receiver, privateMap, "get"); return _classApplyDescriptorGet(receiver, descriptor); }
  78. function _classExtractFieldDescriptor(receiver, privateMap, action) { if (!privateMap.has(receiver)) { throw new TypeError("attempted to " + action + " private field on non-instance"); } return privateMap.get(receiver); }
  79. function _classApplyDescriptorGet(receiver, descriptor) { if (descriptor.get) { return descriptor.get.call(receiver); } return descriptor.value; }
  80. // Types
  81. function getNestedValue(obj, path, fallback) {
  82. const last = path.length - 1;
  83. if (last < 0) return obj === undefined ? fallback : obj;
  84. for (let i = 0; i < last; i++) {
  85. if (obj == null) {
  86. return fallback;
  87. }
  88. obj = obj[path[i]];
  89. }
  90. if (obj == null) return fallback;
  91. return obj[path[last]] === undefined ? fallback : obj[path[last]];
  92. }
  93. function deepEqual(a, b) {
  94. if (a === b) return true;
  95. if (a instanceof Date && b instanceof Date && a.getTime() !== b.getTime()) {
  96. // If the values are Date, compare them as timestamps
  97. return false;
  98. }
  99. if (a !== Object(a) || b !== Object(b)) {
  100. // If the values aren't objects, they were already checked for equality
  101. return false;
  102. }
  103. const props = Object.keys(a);
  104. if (props.length !== Object.keys(b).length) {
  105. // Different number of props, don't bother to check
  106. return false;
  107. }
  108. return props.every(p => deepEqual(a[p], b[p]));
  109. }
  110. function getObjectValueByPath(obj, path, fallback) {
  111. // credit: http://stackoverflow.com/questions/6491463/accessing-nested-javascript-objects-with-string-key#comment55278413_6491621
  112. if (obj == null || !path || typeof path !== 'string') return fallback;
  113. if (obj[path] !== undefined) return obj[path];
  114. path = path.replace(/\[(\w+)\]/g, '.$1'); // convert indexes to properties
  115. path = path.replace(/^\./, ''); // strip a leading dot
  116. return getNestedValue(obj, path.split('.'), fallback);
  117. }
  118. function getPropertyFromItem(item, property, fallback) {
  119. if (property == null) return item === undefined ? fallback : item;
  120. if (item !== Object(item)) {
  121. if (typeof property !== 'function') return fallback;
  122. const value = property(item, fallback);
  123. return typeof value === 'undefined' ? fallback : value;
  124. }
  125. if (typeof property === 'string') return getObjectValueByPath(item, property, fallback);
  126. if (Array.isArray(property)) return getNestedValue(item, property, fallback);
  127. if (typeof property !== 'function') return fallback;
  128. const value = property(item, fallback);
  129. return typeof value === 'undefined' ? fallback : value;
  130. }
  131. function createRange(length) {
  132. let start = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 0;
  133. return Array.from({
  134. length
  135. }, (v, k) => start + k);
  136. }
  137. function convertToUnit(str) {
  138. let unit = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 'px';
  139. if (str == null || str === '') {
  140. return undefined;
  141. } else if (isNaN(+str)) {
  142. return String(str);
  143. } else if (!isFinite(+str)) {
  144. return undefined;
  145. } else {
  146. return `${Number(str)}${unit}`;
  147. }
  148. }
  149. function isObject(obj) {
  150. return obj !== null && typeof obj === 'object' && !Array.isArray(obj);
  151. }
  152. function refElement(obj) {
  153. return obj && '$el' in obj ? obj.$el : obj;
  154. }
  155. // KeyboardEvent.keyCode aliases
  156. const keyCodes = Object.freeze({
  157. enter: 13,
  158. tab: 9,
  159. delete: 46,
  160. esc: 27,
  161. space: 32,
  162. up: 38,
  163. down: 40,
  164. left: 37,
  165. right: 39,
  166. end: 35,
  167. home: 36,
  168. del: 46,
  169. backspace: 8,
  170. insert: 45,
  171. pageup: 33,
  172. pagedown: 34,
  173. shift: 16
  174. });
  175. const keyValues = Object.freeze({
  176. enter: 'Enter',
  177. tab: 'Tab',
  178. delete: 'Delete',
  179. esc: 'Escape',
  180. space: 'Space',
  181. up: 'ArrowUp',
  182. down: 'ArrowDown',
  183. left: 'ArrowLeft',
  184. right: 'ArrowRight',
  185. end: 'End',
  186. home: 'Home',
  187. del: 'Delete',
  188. backspace: 'Backspace',
  189. insert: 'Insert',
  190. pageup: 'PageUp',
  191. pagedown: 'PageDown',
  192. shift: 'Shift'
  193. });
  194. function keys(o) {
  195. return Object.keys(o);
  196. }
  197. function has(obj, key) {
  198. return key.every(k => obj.hasOwnProperty(k));
  199. }
  200. function pick(obj, paths, exclude) {
  201. const found = Object.create(null);
  202. const rest = Object.create(null);
  203. for (const key in obj) {
  204. if (paths.some(path => path instanceof RegExp ? path.test(key) : path === key) && !exclude?.some(path => path === key)) {
  205. found[key] = obj[key];
  206. } else {
  207. rest[key] = obj[key];
  208. }
  209. }
  210. return [found, rest];
  211. }
  212. function omit(obj, exclude) {
  213. const clone = {
  214. ...obj
  215. };
  216. exclude.forEach(prop => delete clone[prop]);
  217. return clone;
  218. }
  219. /**
  220. * Filter attributes that should be applied to
  221. * the root element of a an input component. Remaining
  222. * attributes should be passed to the <input> element inside.
  223. */
  224. function filterInputAttrs(attrs) {
  225. return pick(attrs, ['class', 'style', 'id', /^data-/]);
  226. }
  227. function wrapInArray(v) {
  228. return v == null ? [] : Array.isArray(v) ? v : [v];
  229. }
  230. function clamp(value) {
  231. let min = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 0;
  232. let max = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : 1;
  233. return Math.max(min, Math.min(max, value));
  234. }
  235. function getDecimals(value) {
  236. const trimmedStr = value.toString().trim();
  237. return trimmedStr.includes('.') ? trimmedStr.length - trimmedStr.indexOf('.') - 1 : 0;
  238. }
  239. function padEnd(str, length) {
  240. let char = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : '0';
  241. return str + char.repeat(Math.max(0, length - str.length));
  242. }
  243. function chunk(str) {
  244. let size = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 1;
  245. const chunked = [];
  246. let index = 0;
  247. while (index < str.length) {
  248. chunked.push(str.substr(index, size));
  249. index += size;
  250. }
  251. return chunked;
  252. }
  253. function humanReadableFileSize(bytes) {
  254. let base = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 1000;
  255. if (bytes < base) {
  256. return `${bytes} B`;
  257. }
  258. const prefix = base === 1024 ? ['Ki', 'Mi', 'Gi'] : ['k', 'M', 'G'];
  259. let unit = -1;
  260. while (Math.abs(bytes) >= base && unit < prefix.length - 1) {
  261. bytes /= base;
  262. ++unit;
  263. }
  264. return `${bytes.toFixed(1)} ${prefix[unit]}B`;
  265. }
  266. function mergeDeep() {
  267. let source = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
  268. let target = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
  269. let arrayFn = arguments.length > 2 ? arguments[2] : undefined;
  270. const out = {};
  271. for (const key in source) {
  272. out[key] = source[key];
  273. }
  274. for (const key in target) {
  275. const sourceProperty = source[key];
  276. const targetProperty = target[key];
  277. // Only continue deep merging if
  278. // both properties are objects
  279. if (isObject(sourceProperty) && isObject(targetProperty)) {
  280. out[key] = mergeDeep(sourceProperty, targetProperty, arrayFn);
  281. continue;
  282. }
  283. if (Array.isArray(sourceProperty) && Array.isArray(targetProperty) && arrayFn) {
  284. out[key] = arrayFn(sourceProperty, targetProperty);
  285. continue;
  286. }
  287. out[key] = targetProperty;
  288. }
  289. return out;
  290. }
  291. function flattenFragments(nodes) {
  292. return nodes.map(node => {
  293. if (node.type === vue.Fragment) {
  294. return flattenFragments(node.children);
  295. } else {
  296. return node;
  297. }
  298. }).flat();
  299. }
  300. function toKebabCase() {
  301. let str = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : '';
  302. if (toKebabCase.cache.has(str)) return toKebabCase.cache.get(str);
  303. const kebab = str.replace(/[^a-z]/gi, '-').replace(/\B([A-Z])/g, '-$1').toLowerCase();
  304. toKebabCase.cache.set(str, kebab);
  305. return kebab;
  306. }
  307. toKebabCase.cache = new Map();
  308. function findChildrenWithProvide(key, vnode) {
  309. if (!vnode || typeof vnode !== 'object') return [];
  310. if (Array.isArray(vnode)) {
  311. return vnode.map(child => findChildrenWithProvide(key, child)).flat(1);
  312. } else if (Array.isArray(vnode.children)) {
  313. return vnode.children.map(child => findChildrenWithProvide(key, child)).flat(1);
  314. } else if (vnode.component) {
  315. if (Object.getOwnPropertySymbols(vnode.component.provides).includes(key)) {
  316. return [vnode.component];
  317. } else if (vnode.component.subTree) {
  318. return findChildrenWithProvide(key, vnode.component.subTree).flat(1);
  319. }
  320. }
  321. return [];
  322. }
  323. var _arr = /*#__PURE__*/new WeakMap();
  324. var _pointer = /*#__PURE__*/new WeakMap();
  325. class CircularBuffer {
  326. constructor(size) {
  327. _classPrivateFieldInitSpec(this, _arr, {
  328. writable: true,
  329. value: []
  330. });
  331. _classPrivateFieldInitSpec(this, _pointer, {
  332. writable: true,
  333. value: 0
  334. });
  335. this.size = size;
  336. }
  337. push(val) {
  338. _classPrivateFieldGet(this, _arr)[_classPrivateFieldGet(this, _pointer)] = val;
  339. _classPrivateFieldSet(this, _pointer, (_classPrivateFieldGet(this, _pointer) + 1) % this.size);
  340. }
  341. values() {
  342. return _classPrivateFieldGet(this, _arr).slice(_classPrivateFieldGet(this, _pointer)).concat(_classPrivateFieldGet(this, _arr).slice(0, _classPrivateFieldGet(this, _pointer)));
  343. }
  344. }
  345. function getEventCoordinates(e) {
  346. if ('touches' in e) {
  347. return {
  348. clientX: e.touches[0].clientX,
  349. clientY: e.touches[0].clientY
  350. };
  351. }
  352. return {
  353. clientX: e.clientX,
  354. clientY: e.clientY
  355. };
  356. }
  357. // Only allow a single return type
  358. function destructComputed(getter) {
  359. const refs = vue.reactive({});
  360. const base = vue.computed(getter);
  361. vue.watchEffect(() => {
  362. for (const key in base.value) {
  363. refs[key] = base.value[key];
  364. }
  365. }, {
  366. flush: 'sync'
  367. });
  368. return vue.toRefs(refs);
  369. }
  370. /** Array.includes but value can be any type */
  371. function includes(arr, val) {
  372. return arr.includes(val);
  373. }
  374. const onRE = /^on[^a-z]/;
  375. const isOn = key => onRE.test(key);
  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 noop() {}
  429. /** Returns null if the selector is not supported or we can't check */
  430. function matchesSelector(el, selector) {
  431. const supportsSelector = IN_BROWSER && typeof CSS !== 'undefined' && typeof CSS.supports !== 'undefined' && CSS.supports(`selector(${selector})`);
  432. if (!supportsSelector) return null;
  433. try {
  434. return !!el && el.matches(selector);
  435. } catch (err) {
  436. return null;
  437. }
  438. }
  439. // Utilities
  440. const block = ['top', 'bottom'];
  441. const inline = ['start', 'end', 'left', 'right'];
  442. /** Parse a raw anchor string into an object */
  443. function parseAnchor(anchor, isRtl) {
  444. let [side, align] = anchor.split(' ');
  445. if (!align) {
  446. align = includes(block, side) ? 'start' : includes(inline, side) ? 'top' : 'center';
  447. }
  448. return {
  449. side: toPhysical(side, isRtl),
  450. align: toPhysical(align, isRtl)
  451. };
  452. }
  453. function toPhysical(str, isRtl) {
  454. if (str === 'start') return isRtl ? 'right' : 'left';
  455. if (str === 'end') return isRtl ? 'left' : 'right';
  456. return str;
  457. }
  458. function flipSide(anchor) {
  459. return {
  460. side: {
  461. center: 'center',
  462. top: 'bottom',
  463. bottom: 'top',
  464. left: 'right',
  465. right: 'left'
  466. }[anchor.side],
  467. align: anchor.align
  468. };
  469. }
  470. function flipAlign(anchor) {
  471. return {
  472. side: anchor.side,
  473. align: {
  474. center: 'center',
  475. top: 'bottom',
  476. bottom: 'top',
  477. left: 'right',
  478. right: 'left'
  479. }[anchor.align]
  480. };
  481. }
  482. function flipCorner(anchor) {
  483. return {
  484. side: anchor.align,
  485. align: anchor.side
  486. };
  487. }
  488. function getAxis(anchor) {
  489. return includes(block, anchor.side) ? 'y' : 'x';
  490. }
  491. class Box {
  492. constructor(_ref) {
  493. let {
  494. x,
  495. y,
  496. width,
  497. height
  498. } = _ref;
  499. this.x = x;
  500. this.y = y;
  501. this.width = width;
  502. this.height = height;
  503. }
  504. get top() {
  505. return this.y;
  506. }
  507. get bottom() {
  508. return this.y + this.height;
  509. }
  510. get left() {
  511. return this.x;
  512. }
  513. get right() {
  514. return this.x + this.width;
  515. }
  516. }
  517. function getOverflow(a, b) {
  518. return {
  519. x: {
  520. before: Math.max(0, b.left - a.left),
  521. after: Math.max(0, a.right - b.right)
  522. },
  523. y: {
  524. before: Math.max(0, b.top - a.top),
  525. after: Math.max(0, a.bottom - b.bottom)
  526. }
  527. };
  528. }
  529. // Utilities
  530. /** @see https://stackoverflow.com/a/57876601/2074736 */
  531. function nullifyTransforms(el) {
  532. const rect = el.getBoundingClientRect();
  533. const style = getComputedStyle(el);
  534. const tx = style.transform;
  535. if (tx) {
  536. let ta, sx, sy, dx, dy;
  537. if (tx.startsWith('matrix3d(')) {
  538. ta = tx.slice(9, -1).split(/, /);
  539. sx = +ta[0];
  540. sy = +ta[5];
  541. dx = +ta[12];
  542. dy = +ta[13];
  543. } else if (tx.startsWith('matrix(')) {
  544. ta = tx.slice(7, -1).split(/, /);
  545. sx = +ta[0];
  546. sy = +ta[3];
  547. dx = +ta[4];
  548. dy = +ta[5];
  549. } else {
  550. return new Box(rect);
  551. }
  552. const to = style.transformOrigin;
  553. const x = rect.x - dx - (1 - sx) * parseFloat(to);
  554. const y = rect.y - dy - (1 - sy) * parseFloat(to.slice(to.indexOf(' ') + 1));
  555. const w = sx ? rect.width / sx : el.offsetWidth + 1;
  556. const h = sy ? rect.height / sy : el.offsetHeight + 1;
  557. return new Box({
  558. x,
  559. y,
  560. width: w,
  561. height: h
  562. });
  563. } else {
  564. return new Box(rect);
  565. }
  566. }
  567. function animate(el, keyframes, options) {
  568. if (typeof el.animate === 'undefined') return {
  569. finished: Promise.resolve()
  570. };
  571. let animation;
  572. try {
  573. animation = el.animate(keyframes, options);
  574. } catch (err) {
  575. return {
  576. finished: Promise.resolve()
  577. };
  578. }
  579. if (typeof animation.finished === 'undefined') {
  580. animation.finished = new Promise(resolve => {
  581. animation.onfinish = () => {
  582. resolve(animation);
  583. };
  584. });
  585. }
  586. return animation;
  587. }
  588. // Utilities
  589. const handlers = new WeakMap();
  590. function bindProps(el, props) {
  591. Object.keys(props).forEach(k => {
  592. if (isOn(k)) {
  593. const name = eventName(k);
  594. const handler = handlers.get(el);
  595. if (props[k] == null) {
  596. handler?.forEach(v => {
  597. const [n, fn] = v;
  598. if (n === name) {
  599. el.removeEventListener(name, fn);
  600. handler.delete(v);
  601. }
  602. });
  603. } else if (!handler || ![...handler]?.some(v => v[0] === name && v[1] === props[k])) {
  604. el.addEventListener(name, props[k]);
  605. const _handler = handler || new Set();
  606. _handler.add([name, props[k]]);
  607. if (!handlers.has(el)) handlers.set(el, _handler);
  608. }
  609. } else {
  610. if (props[k] == null) {
  611. el.removeAttribute(k);
  612. } else {
  613. el.setAttribute(k, props[k]);
  614. }
  615. }
  616. });
  617. }
  618. function unbindProps(el, props) {
  619. Object.keys(props).forEach(k => {
  620. if (isOn(k)) {
  621. const name = eventName(k);
  622. const handler = handlers.get(el);
  623. handler?.forEach(v => {
  624. const [n, fn] = v;
  625. if (n === name) {
  626. el.removeEventListener(name, fn);
  627. handler.delete(v);
  628. }
  629. });
  630. } else {
  631. el.removeAttribute(k);
  632. }
  633. });
  634. }
  635. /* eslint-disable no-console */
  636. function consoleWarn(message) {
  637. vue.warn(`Vuetify: ${message}`);
  638. }
  639. function consoleError(message) {
  640. vue.warn(`Vuetify error: ${message}`);
  641. }
  642. function deprecate(original, replacement) {
  643. replacement = Array.isArray(replacement) ? replacement.slice(0, -1).map(s => `'${s}'`).join(', ') + ` or '${replacement.at(-1)}'` : `'${replacement}'`;
  644. vue.warn(`[Vuetify UPGRADE] '${original}' is deprecated, use ${replacement} instead.`);
  645. }
  646. // Types
  647. const delta = 0.20689655172413793; // 6÷29
  648. const cielabForwardTransform = t => t > delta ** 3 ? Math.cbrt(t) : t / (3 * delta ** 2) + 4 / 29;
  649. const cielabReverseTransform = t => t > delta ? t ** 3 : 3 * delta ** 2 * (t - 4 / 29);
  650. function fromXYZ$1(xyz) {
  651. const transform = cielabForwardTransform;
  652. const transformedY = transform(xyz[1]);
  653. return [116 * transformedY - 16, 500 * (transform(xyz[0] / 0.95047) - transformedY), 200 * (transformedY - transform(xyz[2] / 1.08883))];
  654. }
  655. function toXYZ$1(lab) {
  656. const transform = cielabReverseTransform;
  657. const Ln = (lab[0] + 16) / 116;
  658. return [transform(Ln + lab[1] / 500) * 0.95047, transform(Ln), transform(Ln - lab[2] / 200) * 1.08883];
  659. }
  660. // Utilities
  661. // Types
  662. // For converting XYZ to sRGB
  663. const srgbForwardMatrix = [[3.2406, -1.5372, -0.4986], [-0.9689, 1.8758, 0.0415], [0.0557, -0.2040, 1.0570]];
  664. // Forward gamma adjust
  665. const srgbForwardTransform = C => C <= 0.0031308 ? C * 12.92 : 1.055 * C ** (1 / 2.4) - 0.055;
  666. // For converting sRGB to XYZ
  667. const srgbReverseMatrix = [[0.4124, 0.3576, 0.1805], [0.2126, 0.7152, 0.0722], [0.0193, 0.1192, 0.9505]];
  668. // Reverse gamma adjust
  669. const srgbReverseTransform = C => C <= 0.04045 ? C / 12.92 : ((C + 0.055) / 1.055) ** 2.4;
  670. function fromXYZ(xyz) {
  671. const rgb = Array(3);
  672. const transform = srgbForwardTransform;
  673. const matrix = srgbForwardMatrix;
  674. // Matrix transform, then gamma adjustment
  675. for (let i = 0; i < 3; ++i) {
  676. // Rescale back to [0, 255]
  677. rgb[i] = Math.round(clamp(transform(matrix[i][0] * xyz[0] + matrix[i][1] * xyz[1] + matrix[i][2] * xyz[2])) * 255);
  678. }
  679. return {
  680. r: rgb[0],
  681. g: rgb[1],
  682. b: rgb[2]
  683. };
  684. }
  685. function toXYZ(_ref) {
  686. let {
  687. r,
  688. g,
  689. b
  690. } = _ref;
  691. const xyz = [0, 0, 0];
  692. const transform = srgbReverseTransform;
  693. const matrix = srgbReverseMatrix;
  694. // Rescale from [0, 255] to [0, 1] then adjust sRGB gamma to linear RGB
  695. r = transform(r / 255);
  696. g = transform(g / 255);
  697. b = transform(b / 255);
  698. // Matrix color space transform
  699. for (let i = 0; i < 3; ++i) {
  700. xyz[i] = matrix[i][0] * r + matrix[i][1] * g + matrix[i][2] * b;
  701. }
  702. return xyz;
  703. }
  704. // Utilities
  705. // Types
  706. function isCssColor(color) {
  707. return !!color && /^(#|var\(--|(rgb|hsl)a?\()/.test(color);
  708. }
  709. const cssColorRe = /^(?<fn>(?:rgb|hsl)a?)\((?<values>.+)\)/;
  710. const mappers = {
  711. rgb: (r, g, b, a) => ({
  712. r,
  713. g,
  714. b,
  715. a
  716. }),
  717. rgba: (r, g, b, a) => ({
  718. r,
  719. g,
  720. b,
  721. a
  722. }),
  723. hsl: (h, s, l, a) => HSLtoRGB({
  724. h,
  725. s,
  726. l,
  727. a
  728. }),
  729. hsla: (h, s, l, a) => HSLtoRGB({
  730. h,
  731. s,
  732. l,
  733. a
  734. }),
  735. hsv: (h, s, v, a) => HSVtoRGB({
  736. h,
  737. s,
  738. v,
  739. a
  740. }),
  741. hsva: (h, s, v, a) => HSVtoRGB({
  742. h,
  743. s,
  744. v,
  745. a
  746. })
  747. };
  748. function parseColor(color) {
  749. if (typeof color === 'number') {
  750. if (isNaN(color) || color < 0 || color > 0xFFFFFF) {
  751. // int can't have opacity
  752. consoleWarn(`'${color}' is not a valid hex color`);
  753. }
  754. return {
  755. r: (color & 0xFF0000) >> 16,
  756. g: (color & 0xFF00) >> 8,
  757. b: color & 0xFF
  758. };
  759. } else if (typeof color === 'string' && cssColorRe.test(color)) {
  760. const {
  761. groups
  762. } = color.match(cssColorRe);
  763. const {
  764. fn,
  765. values
  766. } = groups;
  767. const realValues = values.split(/,\s*/).map(v => {
  768. if (v.endsWith('%') && ['hsl', 'hsla', 'hsv', 'hsva'].includes(fn)) {
  769. return parseFloat(v) / 100;
  770. } else {
  771. return parseFloat(v);
  772. }
  773. });
  774. return mappers[fn](...realValues);
  775. } else if (typeof color === 'string') {
  776. let hex = color.startsWith('#') ? color.slice(1) : color;
  777. if ([3, 4].includes(hex.length)) {
  778. hex = hex.split('').map(char => char + char).join('');
  779. } else if (![6, 8].includes(hex.length)) {
  780. consoleWarn(`'${color}' is not a valid hex(a) color`);
  781. }
  782. const int = parseInt(hex, 16);
  783. if (isNaN(int) || int < 0 || int > 0xFFFFFFFF) {
  784. consoleWarn(`'${color}' is not a valid hex(a) color`);
  785. }
  786. return HexToRGB(hex);
  787. } else if (typeof color === 'object') {
  788. if (has(color, ['r', 'g', 'b'])) {
  789. return color;
  790. } else if (has(color, ['h', 's', 'l'])) {
  791. return HSVtoRGB(HSLtoHSV(color));
  792. } else if (has(color, ['h', 's', 'v'])) {
  793. return HSVtoRGB(color);
  794. }
  795. }
  796. throw new TypeError(`Invalid color: ${color == null ? color : String(color) || color.constructor.name}\nExpected #hex, #hexa, rgb(), rgba(), hsl(), hsla(), object or number`);
  797. }
  798. /** Converts HSVA to RGBA. Based on formula from https://en.wikipedia.org/wiki/HSL_and_HSV */
  799. function HSVtoRGB(hsva) {
  800. const {
  801. h,
  802. s,
  803. v,
  804. a
  805. } = hsva;
  806. const f = n => {
  807. const k = (n + h / 60) % 6;
  808. return v - v * s * Math.max(Math.min(k, 4 - k, 1), 0);
  809. };
  810. const rgb = [f(5), f(3), f(1)].map(v => Math.round(v * 255));
  811. return {
  812. r: rgb[0],
  813. g: rgb[1],
  814. b: rgb[2],
  815. a
  816. };
  817. }
  818. function HSLtoRGB(hsla) {
  819. return HSVtoRGB(HSLtoHSV(hsla));
  820. }
  821. /** Converts RGBA to HSVA. Based on formula from https://en.wikipedia.org/wiki/HSL_and_HSV */
  822. function RGBtoHSV(rgba) {
  823. if (!rgba) return {
  824. h: 0,
  825. s: 1,
  826. v: 1,
  827. a: 1
  828. };
  829. const r = rgba.r / 255;
  830. const g = rgba.g / 255;
  831. const b = rgba.b / 255;
  832. const max = Math.max(r, g, b);
  833. const min = Math.min(r, g, b);
  834. let h = 0;
  835. if (max !== min) {
  836. if (max === r) {
  837. h = 60 * (0 + (g - b) / (max - min));
  838. } else if (max === g) {
  839. h = 60 * (2 + (b - r) / (max - min));
  840. } else if (max === b) {
  841. h = 60 * (4 + (r - g) / (max - min));
  842. }
  843. }
  844. if (h < 0) h = h + 360;
  845. const s = max === 0 ? 0 : (max - min) / max;
  846. const hsv = [h, s, max];
  847. return {
  848. h: hsv[0],
  849. s: hsv[1],
  850. v: hsv[2],
  851. a: rgba.a
  852. };
  853. }
  854. function HSVtoHSL(hsva) {
  855. const {
  856. h,
  857. s,
  858. v,
  859. a
  860. } = hsva;
  861. const l = v - v * s / 2;
  862. const sprime = l === 1 || l === 0 ? 0 : (v - l) / Math.min(l, 1 - l);
  863. return {
  864. h,
  865. s: sprime,
  866. l,
  867. a
  868. };
  869. }
  870. function HSLtoHSV(hsl) {
  871. const {
  872. h,
  873. s,
  874. l,
  875. a
  876. } = hsl;
  877. const v = l + s * Math.min(l, 1 - l);
  878. const sprime = v === 0 ? 0 : 2 - 2 * l / v;
  879. return {
  880. h,
  881. s: sprime,
  882. v,
  883. a
  884. };
  885. }
  886. function RGBtoCSS(_ref) {
  887. let {
  888. r,
  889. g,
  890. b,
  891. a
  892. } = _ref;
  893. return a === undefined ? `rgb(${r}, ${g}, ${b})` : `rgba(${r}, ${g}, ${b}, ${a})`;
  894. }
  895. function HSVtoCSS(hsva) {
  896. return RGBtoCSS(HSVtoRGB(hsva));
  897. }
  898. function toHex(v) {
  899. const h = Math.round(v).toString(16);
  900. return ('00'.substr(0, 2 - h.length) + h).toUpperCase();
  901. }
  902. function RGBtoHex(_ref2) {
  903. let {
  904. r,
  905. g,
  906. b,
  907. a
  908. } = _ref2;
  909. return `#${[toHex(r), toHex(g), toHex(b), a !== undefined ? toHex(Math.round(a * 255)) : ''].join('')}`;
  910. }
  911. function HexToRGB(hex) {
  912. hex = parseHex(hex);
  913. let [r, g, b, a] = chunk(hex, 2).map(c => parseInt(c, 16));
  914. a = a === undefined ? a : a / 255;
  915. return {
  916. r,
  917. g,
  918. b,
  919. a
  920. };
  921. }
  922. function HexToHSV(hex) {
  923. const rgb = HexToRGB(hex);
  924. return RGBtoHSV(rgb);
  925. }
  926. function HSVtoHex(hsva) {
  927. return RGBtoHex(HSVtoRGB(hsva));
  928. }
  929. function parseHex(hex) {
  930. if (hex.startsWith('#')) {
  931. hex = hex.slice(1);
  932. }
  933. hex = hex.replace(/([^0-9a-f])/gi, 'F');
  934. if (hex.length === 3 || hex.length === 4) {
  935. hex = hex.split('').map(x => x + x).join('');
  936. }
  937. if (hex.length !== 6) {
  938. hex = padEnd(padEnd(hex, 6), 8, 'F');
  939. }
  940. return hex;
  941. }
  942. function lighten(value, amount) {
  943. const lab = fromXYZ$1(toXYZ(value));
  944. lab[0] = lab[0] + amount * 10;
  945. return fromXYZ(toXYZ$1(lab));
  946. }
  947. function darken(value, amount) {
  948. const lab = fromXYZ$1(toXYZ(value));
  949. lab[0] = lab[0] - amount * 10;
  950. return fromXYZ(toXYZ$1(lab));
  951. }
  952. /**
  953. * Calculate the relative luminance of a given color
  954. * @see https://www.w3.org/TR/WCAG20/#relativeluminancedef
  955. */
  956. function getLuma(color) {
  957. const rgb = parseColor(color);
  958. return toXYZ(rgb)[1];
  959. }
  960. /**
  961. * Returns the contrast ratio (1-21) between two colors.
  962. * @see https://www.w3.org/TR/WCAG20/#contrast-ratiodef
  963. */
  964. function getContrast(first, second) {
  965. const l1 = getLuma(first);
  966. const l2 = getLuma(second);
  967. const light = Math.max(l1, l2);
  968. const dark = Math.min(l1, l2);
  969. return (light + 0.05) / (dark + 0.05);
  970. }
  971. // Utilities
  972. // Types
  973. function useToggleScope(source, fn) {
  974. let scope;
  975. function start() {
  976. scope = vue.effectScope();
  977. scope.run(() => fn.length ? fn(() => {
  978. scope?.stop();
  979. start();
  980. }) : fn());
  981. }
  982. vue.watch(source, active => {
  983. if (active && !scope) {
  984. start();
  985. } else if (!active) {
  986. scope?.stop();
  987. scope = undefined;
  988. }
  989. }, {
  990. immediate: true
  991. });
  992. vue.onScopeDispose(() => {
  993. scope?.stop();
  994. });
  995. }
  996. // Composables
  997. // Types
  998. const DefaultsSymbol = Symbol.for('vuetify:defaults');
  999. function createDefaults(options) {
  1000. return vue.ref(options);
  1001. }
  1002. function injectDefaults() {
  1003. const defaults = vue.inject(DefaultsSymbol);
  1004. if (!defaults) throw new Error('[Vuetify] Could not find defaults instance');
  1005. return defaults;
  1006. }
  1007. function provideDefaults(defaults, options) {
  1008. const injectedDefaults = injectDefaults();
  1009. const providedDefaults = vue.ref(defaults);
  1010. const newDefaults = vue.computed(() => {
  1011. const disabled = vue.unref(options?.disabled);
  1012. if (disabled) return injectedDefaults.value;
  1013. const scoped = vue.unref(options?.scoped);
  1014. const reset = vue.unref(options?.reset);
  1015. const root = vue.unref(options?.root);
  1016. let properties = mergeDeep(providedDefaults.value, {
  1017. prev: injectedDefaults.value
  1018. });
  1019. if (scoped) return properties;
  1020. if (reset || root) {
  1021. const len = Number(reset || Infinity);
  1022. for (let i = 0; i <= len; i++) {
  1023. if (!properties || !('prev' in properties)) {
  1024. break;
  1025. }
  1026. properties = properties.prev;
  1027. }
  1028. if (properties && typeof root === 'string' && root in properties) {
  1029. properties = mergeDeep(mergeDeep(properties, {
  1030. prev: properties
  1031. }), properties[root]);
  1032. }
  1033. return properties;
  1034. }
  1035. return properties.prev ? mergeDeep(properties.prev, properties) : properties;
  1036. });
  1037. vue.provide(DefaultsSymbol, newDefaults);
  1038. return newDefaults;
  1039. }
  1040. function propIsDefined(vnode, prop) {
  1041. return typeof vnode.props?.[prop] !== 'undefined' || typeof vnode.props?.[toKebabCase(prop)] !== 'undefined';
  1042. }
  1043. function internalUseDefaults() {
  1044. let props = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
  1045. let name = arguments.length > 1 ? arguments[1] : undefined;
  1046. let defaults = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : injectDefaults();
  1047. const vm = getCurrentInstance('useDefaults');
  1048. name = name ?? vm.type.name ?? vm.type.__name;
  1049. if (!name) {
  1050. throw new Error('[Vuetify] Could not determine component name');
  1051. }
  1052. const componentDefaults = vue.computed(() => defaults.value?.[props._as ?? name]);
  1053. const _props = new Proxy(props, {
  1054. get(target, prop) {
  1055. const propValue = Reflect.get(target, prop);
  1056. if (prop === 'class' || prop === 'style') {
  1057. return [componentDefaults.value?.[prop], propValue].filter(v => v != null);
  1058. } else if (typeof prop === 'string' && !propIsDefined(vm.vnode, prop)) {
  1059. return componentDefaults.value?.[prop] ?? defaults.value?.global?.[prop] ?? propValue;
  1060. }
  1061. return propValue;
  1062. }
  1063. });
  1064. const _subcomponentDefaults = vue.shallowRef();
  1065. vue.watchEffect(() => {
  1066. if (componentDefaults.value) {
  1067. const subComponents = Object.entries(componentDefaults.value).filter(_ref => {
  1068. let [key] = _ref;
  1069. return key.startsWith(key[0].toUpperCase());
  1070. });
  1071. if (subComponents.length) _subcomponentDefaults.value = Object.fromEntries(subComponents);
  1072. }
  1073. });
  1074. function provideSubDefaults() {
  1075. // If subcomponent defaults are provided, override any
  1076. // subcomponents provided by the component's setup function.
  1077. // This uses injectSelf so must be done after the original setup to work.
  1078. useToggleScope(_subcomponentDefaults, () => {
  1079. provideDefaults(mergeDeep(injectSelf(DefaultsSymbol)?.value ?? {}, _subcomponentDefaults.value));
  1080. });
  1081. }
  1082. return {
  1083. props: _props,
  1084. provideSubDefaults
  1085. };
  1086. }
  1087. function useDefaults() {
  1088. let props = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
  1089. let name = arguments.length > 1 ? arguments[1] : undefined;
  1090. const {
  1091. props: _props,
  1092. provideSubDefaults
  1093. } = internalUseDefaults(props, name);
  1094. provideSubDefaults();
  1095. return _props;
  1096. }
  1097. // Composables
  1098. // Types
  1099. // Implementation
  1100. function defineComponent(options) {
  1101. options._setup = options._setup ?? options.setup;
  1102. if (!options.name) {
  1103. consoleWarn('The component is missing an explicit name, unable to generate default prop value');
  1104. return options;
  1105. }
  1106. if (options._setup) {
  1107. options.props = propsFactory(options.props ?? {}, options.name)();
  1108. const propKeys = Object.keys(options.props);
  1109. options.filterProps = function filterProps(props) {
  1110. return pick(props, propKeys, ['class', 'style']);
  1111. };
  1112. options.props._as = String;
  1113. options.setup = function setup(props, ctx) {
  1114. const defaults = injectDefaults();
  1115. // Skip props proxy if defaults are not provided
  1116. if (!defaults.value) return options._setup(props, ctx);
  1117. const {
  1118. props: _props,
  1119. provideSubDefaults
  1120. } = internalUseDefaults(props, props._as ?? options.name, defaults);
  1121. const setupBindings = options._setup(_props, ctx);
  1122. provideSubDefaults();
  1123. return setupBindings;
  1124. };
  1125. }
  1126. return options;
  1127. }
  1128. // Implementation
  1129. function genericComponent() {
  1130. let exposeDefaults = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : true;
  1131. return options => (exposeDefaults ? defineComponent : vue.defineComponent)(options);
  1132. }
  1133. // Composables
  1134. function createSimpleFunctional(klass) {
  1135. let tag = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 'div';
  1136. let name = arguments.length > 2 ? arguments[2] : undefined;
  1137. return genericComponent()({
  1138. name: name ?? vue.capitalize(vue.camelize(klass.replace(/__/g, '-'))),
  1139. props: {
  1140. tag: {
  1141. type: String,
  1142. default: tag
  1143. },
  1144. ...makeComponentProps()
  1145. },
  1146. setup(props, _ref) {
  1147. let {
  1148. slots
  1149. } = _ref;
  1150. return () => {
  1151. return vue.h(props.tag, {
  1152. class: [klass, props.class],
  1153. style: props.style
  1154. }, slots.default?.());
  1155. };
  1156. }
  1157. });
  1158. }
  1159. /**
  1160. * Returns:
  1161. * - 'null' if the node is not attached to the DOM
  1162. * - the root node (HTMLDocument | ShadowRoot) otherwise
  1163. */
  1164. function attachedRoot(node) {
  1165. /* istanbul ignore next */
  1166. if (typeof node.getRootNode !== 'function') {
  1167. // Shadow DOM not supported (IE11), lets find the root of this node
  1168. while (node.parentNode) node = node.parentNode;
  1169. // The root parent is the document if the node is attached to the DOM
  1170. if (node !== document) return null;
  1171. return document;
  1172. }
  1173. const root = node.getRootNode();
  1174. // The composed root node is the document if the node is attached to the DOM
  1175. if (root !== document && root.getRootNode({
  1176. composed: true
  1177. }) !== document) return null;
  1178. return root;
  1179. }
  1180. const standardEasing = 'cubic-bezier(0.4, 0, 0.2, 1)';
  1181. const deceleratedEasing = 'cubic-bezier(0.0, 0, 0.2, 1)'; // Entering
  1182. const acceleratedEasing = 'cubic-bezier(0.4, 0, 1, 1)'; // Leaving
  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. function getScrollParent(el) {
  1212. let includeHidden = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : false;
  1213. while (el) {
  1214. if (includeHidden ? isPotentiallyScrollable(el) : hasScrollbar(el)) return el;
  1215. el = el.parentElement;
  1216. }
  1217. return document.scrollingElement;
  1218. }
  1219. function getScrollParents(el, stopAt) {
  1220. const elements = [];
  1221. if (stopAt && el && !stopAt.contains(el)) return elements;
  1222. while (el) {
  1223. if (hasScrollbar(el)) elements.push(el);
  1224. if (el === stopAt) break;
  1225. el = el.parentElement;
  1226. }
  1227. return elements;
  1228. }
  1229. function hasScrollbar(el) {
  1230. if (!el || el.nodeType !== Node.ELEMENT_NODE) return false;
  1231. const style = window.getComputedStyle(el);
  1232. return style.overflowY === 'scroll' || style.overflowY === 'auto' && el.scrollHeight > el.clientHeight;
  1233. }
  1234. function isPotentiallyScrollable(el) {
  1235. if (!el || el.nodeType !== Node.ELEMENT_NODE) return false;
  1236. const style = window.getComputedStyle(el);
  1237. return ['scroll', 'auto'].includes(style.overflowY);
  1238. }
  1239. // Utilities
  1240. // Types
  1241. function injectSelf(key) {
  1242. const {
  1243. provides
  1244. } = getCurrentInstance('injectSelf');
  1245. if (provides && key in provides) {
  1246. // TS doesn't allow symbol as index type
  1247. return provides[key];
  1248. }
  1249. return undefined;
  1250. }
  1251. function isFixedPosition(el) {
  1252. while (el) {
  1253. if (window.getComputedStyle(el).position === 'fixed') {
  1254. return true;
  1255. }
  1256. el = el.offsetParent;
  1257. }
  1258. return false;
  1259. }
  1260. // Utilities
  1261. // Types
  1262. function useRender(render) {
  1263. const vm = getCurrentInstance('useRender');
  1264. vm.render = render;
  1265. }
  1266. // Utilities
  1267. // Types
  1268. function useResizeObserver(callback) {
  1269. let box = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 'content';
  1270. const resizeRef = vue.ref();
  1271. const contentRect = vue.ref();
  1272. if (IN_BROWSER) {
  1273. const observer = new ResizeObserver(entries => {
  1274. callback?.(entries, observer);
  1275. if (!entries.length) return;
  1276. if (box === 'content') {
  1277. contentRect.value = entries[0].contentRect;
  1278. } else {
  1279. contentRect.value = entries[0].target.getBoundingClientRect();
  1280. }
  1281. });
  1282. vue.onBeforeUnmount(() => {
  1283. observer.disconnect();
  1284. });
  1285. vue.watch(resizeRef, (newValue, oldValue) => {
  1286. if (oldValue) {
  1287. observer.unobserve(refElement(oldValue));
  1288. contentRect.value = undefined;
  1289. }
  1290. if (newValue) observer.observe(refElement(newValue));
  1291. }, {
  1292. flush: 'post'
  1293. });
  1294. }
  1295. return {
  1296. resizeRef,
  1297. contentRect: vue.readonly(contentRect)
  1298. };
  1299. }
  1300. // Composables
  1301. // Types
  1302. const VuetifyLayoutKey = Symbol.for('vuetify:layout');
  1303. const VuetifyLayoutItemKey = Symbol.for('vuetify:layout-item');
  1304. const ROOT_ZINDEX = 1000;
  1305. const makeLayoutProps = propsFactory({
  1306. overlaps: {
  1307. type: Array,
  1308. default: () => []
  1309. },
  1310. fullHeight: Boolean
  1311. }, 'layout');
  1312. // Composables
  1313. const makeLayoutItemProps = propsFactory({
  1314. name: {
  1315. type: String
  1316. },
  1317. order: {
  1318. type: [Number, String],
  1319. default: 0
  1320. },
  1321. absolute: Boolean
  1322. }, 'layout-item');
  1323. function useLayout() {
  1324. const layout = vue.inject(VuetifyLayoutKey);
  1325. if (!layout) throw new Error('[Vuetify] Could not find injected layout');
  1326. return {
  1327. getLayoutItem: layout.getLayoutItem,
  1328. mainRect: layout.mainRect,
  1329. mainStyles: layout.mainStyles
  1330. };
  1331. }
  1332. function useLayoutItem(options) {
  1333. const layout = vue.inject(VuetifyLayoutKey);
  1334. if (!layout) throw new Error('[Vuetify] Could not find injected layout');
  1335. const id = options.id ?? `layout-item-${getUid()}`;
  1336. const vm = getCurrentInstance('useLayoutItem');
  1337. vue.provide(VuetifyLayoutItemKey, {
  1338. id
  1339. });
  1340. const isKeptAlive = vue.shallowRef(false);
  1341. vue.onDeactivated(() => isKeptAlive.value = true);
  1342. vue.onActivated(() => isKeptAlive.value = false);
  1343. const {
  1344. layoutItemStyles,
  1345. layoutItemScrimStyles
  1346. } = layout.register(vm, {
  1347. ...options,
  1348. active: vue.computed(() => isKeptAlive.value ? false : options.active.value),
  1349. id
  1350. });
  1351. vue.onBeforeUnmount(() => layout.unregister(id));
  1352. return {
  1353. layoutItemStyles,
  1354. layoutRect: layout.layoutRect,
  1355. layoutItemScrimStyles
  1356. };
  1357. }
  1358. const generateLayers = (layout, positions, layoutSizes, activeItems) => {
  1359. let previousLayer = {
  1360. top: 0,
  1361. left: 0,
  1362. right: 0,
  1363. bottom: 0
  1364. };
  1365. const layers = [{
  1366. id: '',
  1367. layer: {
  1368. ...previousLayer
  1369. }
  1370. }];
  1371. for (const id of layout) {
  1372. const position = positions.get(id);
  1373. const amount = layoutSizes.get(id);
  1374. const active = activeItems.get(id);
  1375. if (!position || !amount || !active) continue;
  1376. const layer = {
  1377. ...previousLayer,
  1378. [position.value]: parseInt(previousLayer[position.value], 10) + (active.value ? parseInt(amount.value, 10) : 0)
  1379. };
  1380. layers.push({
  1381. id,
  1382. layer
  1383. });
  1384. previousLayer = layer;
  1385. }
  1386. return layers;
  1387. };
  1388. function createLayout(props) {
  1389. const parentLayout = vue.inject(VuetifyLayoutKey, null);
  1390. const rootZIndex = vue.computed(() => parentLayout ? parentLayout.rootZIndex.value - 100 : ROOT_ZINDEX);
  1391. const registered = vue.ref([]);
  1392. const positions = vue.reactive(new Map());
  1393. const layoutSizes = vue.reactive(new Map());
  1394. const priorities = vue.reactive(new Map());
  1395. const activeItems = vue.reactive(new Map());
  1396. const disabledTransitions = vue.reactive(new Map());
  1397. const {
  1398. resizeRef,
  1399. contentRect: layoutRect
  1400. } = useResizeObserver();
  1401. const computedOverlaps = vue.computed(() => {
  1402. const map = new Map();
  1403. const overlaps = props.overlaps ?? [];
  1404. for (const overlap of overlaps.filter(item => item.includes(':'))) {
  1405. const [top, bottom] = overlap.split(':');
  1406. if (!registered.value.includes(top) || !registered.value.includes(bottom)) continue;
  1407. const topPosition = positions.get(top);
  1408. const bottomPosition = positions.get(bottom);
  1409. const topAmount = layoutSizes.get(top);
  1410. const bottomAmount = layoutSizes.get(bottom);
  1411. if (!topPosition || !bottomPosition || !topAmount || !bottomAmount) continue;
  1412. map.set(bottom, {
  1413. position: topPosition.value,
  1414. amount: parseInt(topAmount.value, 10)
  1415. });
  1416. map.set(top, {
  1417. position: bottomPosition.value,
  1418. amount: -parseInt(bottomAmount.value, 10)
  1419. });
  1420. }
  1421. return map;
  1422. });
  1423. const layers = vue.computed(() => {
  1424. const uniquePriorities = [...new Set([...priorities.values()].map(p => p.value))].sort((a, b) => a - b);
  1425. const layout = [];
  1426. for (const p of uniquePriorities) {
  1427. const items = registered.value.filter(id => priorities.get(id)?.value === p);
  1428. layout.push(...items);
  1429. }
  1430. return generateLayers(layout, positions, layoutSizes, activeItems);
  1431. });
  1432. const transitionsEnabled = vue.computed(() => {
  1433. return !Array.from(disabledTransitions.values()).some(ref => ref.value);
  1434. });
  1435. const mainRect = vue.computed(() => {
  1436. return layers.value[layers.value.length - 1].layer;
  1437. });
  1438. const mainStyles = vue.computed(() => {
  1439. return {
  1440. '--v-layout-left': convertToUnit(mainRect.value.left),
  1441. '--v-layout-right': convertToUnit(mainRect.value.right),
  1442. '--v-layout-top': convertToUnit(mainRect.value.top),
  1443. '--v-layout-bottom': convertToUnit(mainRect.value.bottom),
  1444. ...(transitionsEnabled.value ? undefined : {
  1445. transition: 'none'
  1446. })
  1447. };
  1448. });
  1449. const items = vue.computed(() => {
  1450. return layers.value.slice(1).map((_ref, index) => {
  1451. let {
  1452. id
  1453. } = _ref;
  1454. const {
  1455. layer
  1456. } = layers.value[index];
  1457. const size = layoutSizes.get(id);
  1458. const position = positions.get(id);
  1459. return {
  1460. id,
  1461. ...layer,
  1462. size: Number(size.value),
  1463. position: position.value
  1464. };
  1465. });
  1466. });
  1467. const getLayoutItem = id => {
  1468. return items.value.find(item => item.id === id);
  1469. };
  1470. const rootVm = getCurrentInstance('createLayout');
  1471. const isMounted = vue.shallowRef(false);
  1472. vue.onMounted(() => {
  1473. isMounted.value = true;
  1474. });
  1475. vue.provide(VuetifyLayoutKey, {
  1476. register: (vm, _ref2) => {
  1477. let {
  1478. id,
  1479. order,
  1480. position,
  1481. layoutSize,
  1482. elementSize,
  1483. active,
  1484. disableTransitions,
  1485. absolute
  1486. } = _ref2;
  1487. priorities.set(id, order);
  1488. positions.set(id, position);
  1489. layoutSizes.set(id, layoutSize);
  1490. activeItems.set(id, active);
  1491. disableTransitions && disabledTransitions.set(id, disableTransitions);
  1492. const instances = findChildrenWithProvide(VuetifyLayoutItemKey, rootVm?.vnode);
  1493. const instanceIndex = instances.indexOf(vm);
  1494. if (instanceIndex > -1) registered.value.splice(instanceIndex, 0, id);else registered.value.push(id);
  1495. const index = vue.computed(() => items.value.findIndex(i => i.id === id));
  1496. const zIndex = vue.computed(() => rootZIndex.value + layers.value.length * 2 - index.value * 2);
  1497. const layoutItemStyles = vue.computed(() => {
  1498. const isHorizontal = position.value === 'left' || position.value === 'right';
  1499. const isOppositeHorizontal = position.value === 'right';
  1500. const isOppositeVertical = position.value === 'bottom';
  1501. const styles = {
  1502. [position.value]: 0,
  1503. zIndex: zIndex.value,
  1504. transform: `translate${isHorizontal ? 'X' : 'Y'}(${(active.value ? 0 : -110) * (isOppositeHorizontal || isOppositeVertical ? -1 : 1)}%)`,
  1505. position: absolute.value || rootZIndex.value !== ROOT_ZINDEX ? 'absolute' : 'fixed',
  1506. ...(transitionsEnabled.value ? undefined : {
  1507. transition: 'none'
  1508. })
  1509. };
  1510. if (!isMounted.value) return styles;
  1511. const item = items.value[index.value];
  1512. if (!item) throw new Error(`[Vuetify] Could not find layout item "${id}"`);
  1513. const overlap = computedOverlaps.value.get(id);
  1514. if (overlap) {
  1515. item[overlap.position] += overlap.amount;
  1516. }
  1517. return {
  1518. ...styles,
  1519. height: isHorizontal ? `calc(100% - ${item.top}px - ${item.bottom}px)` : elementSize.value ? `${elementSize.value}px` : undefined,
  1520. left: isOppositeHorizontal ? undefined : `${item.left}px`,
  1521. right: isOppositeHorizontal ? `${item.right}px` : undefined,
  1522. top: position.value !== 'bottom' ? `${item.top}px` : undefined,
  1523. bottom: position.value !== 'top' ? `${item.bottom}px` : undefined,
  1524. width: !isHorizontal ? `calc(100% - ${item.left}px - ${item.right}px)` : elementSize.value ? `${elementSize.value}px` : undefined
  1525. };
  1526. });
  1527. const layoutItemScrimStyles = vue.computed(() => ({
  1528. zIndex: zIndex.value - 1
  1529. }));
  1530. return {
  1531. layoutItemStyles,
  1532. layoutItemScrimStyles,
  1533. zIndex
  1534. };
  1535. },
  1536. unregister: id => {
  1537. priorities.delete(id);
  1538. positions.delete(id);
  1539. layoutSizes.delete(id);
  1540. activeItems.delete(id);
  1541. disabledTransitions.delete(id);
  1542. registered.value = registered.value.filter(v => v !== id);
  1543. },
  1544. mainRect,
  1545. mainStyles,
  1546. getLayoutItem,
  1547. items,
  1548. layoutRect,
  1549. rootZIndex
  1550. });
  1551. const layoutClasses = vue.computed(() => ['v-layout', {
  1552. 'v-layout--full-height': props.fullHeight
  1553. }]);
  1554. const layoutStyles = vue.computed(() => ({
  1555. zIndex: rootZIndex.value,
  1556. position: parentLayout ? 'relative' : undefined,
  1557. overflow: parentLayout ? 'hidden' : undefined
  1558. }));
  1559. return {
  1560. layoutClasses,
  1561. layoutStyles,
  1562. getLayoutItem,
  1563. items,
  1564. layoutRect,
  1565. layoutRef: resizeRef
  1566. };
  1567. }
  1568. var en = {
  1569. badge: 'Badge',
  1570. close: 'Close',
  1571. dataIterator: {
  1572. noResultsText: 'No matching records found',
  1573. loadingText: 'Loading items...'
  1574. },
  1575. dataTable: {
  1576. itemsPerPageText: 'Rows per page:',
  1577. ariaLabel: {
  1578. sortDescending: 'Sorted descending.',
  1579. sortAscending: 'Sorted ascending.',
  1580. sortNone: 'Not sorted.',
  1581. activateNone: 'Activate to remove sorting.',
  1582. activateDescending: 'Activate to sort descending.',
  1583. activateAscending: 'Activate to sort ascending.'
  1584. },
  1585. sortBy: 'Sort by'
  1586. },
  1587. dataFooter: {
  1588. itemsPerPageText: 'Items per page:',
  1589. itemsPerPageAll: 'All',
  1590. nextPage: 'Next page',
  1591. prevPage: 'Previous page',
  1592. firstPage: 'First page',
  1593. lastPage: 'Last page',
  1594. pageText: '{0}-{1} of {2}'
  1595. },
  1596. dateRangeInput: {
  1597. divider: 'to'
  1598. },
  1599. datePicker: {
  1600. ok: 'OK',
  1601. cancel: 'Cancel',
  1602. range: {
  1603. title: 'Select dates',
  1604. header: 'Enter dates'
  1605. },
  1606. title: 'Select date',
  1607. header: 'Enter date',
  1608. input: {
  1609. placeholder: 'Enter date'
  1610. }
  1611. },
  1612. noDataText: 'No data available',
  1613. carousel: {
  1614. prev: 'Previous visual',
  1615. next: 'Next visual',
  1616. ariaLabel: {
  1617. delimiter: 'Carousel slide {0} of {1}'
  1618. }
  1619. },
  1620. calendar: {
  1621. moreEvents: '{0} more'
  1622. },
  1623. input: {
  1624. clear: 'Clear {0}',
  1625. prependAction: '{0} prepended action',
  1626. appendAction: '{0} appended action',
  1627. otp: 'Please enter OTP character {0}'
  1628. },
  1629. fileInput: {
  1630. counter: '{0} files',
  1631. counterSize: '{0} files ({1} in total)'
  1632. },
  1633. timePicker: {
  1634. am: 'AM',
  1635. pm: 'PM'
  1636. },
  1637. pagination: {
  1638. ariaLabel: {
  1639. root: 'Pagination Navigation',
  1640. next: 'Next page',
  1641. previous: 'Previous page',
  1642. page: 'Go to page {0}',
  1643. currentPage: 'Page {0}, Current page',
  1644. first: 'First page',
  1645. last: 'Last page'
  1646. }
  1647. },
  1648. stepper: {
  1649. next: 'Next',
  1650. prev: 'Previous'
  1651. },
  1652. rating: {
  1653. ariaLabel: {
  1654. item: 'Rating {0} of {1}'
  1655. }
  1656. },
  1657. loading: 'Loading...',
  1658. infiniteScroll: {
  1659. loadMore: 'Load more',
  1660. empty: 'No more'
  1661. }
  1662. };
  1663. const defaultRtl = {
  1664. af: false,
  1665. ar: true,
  1666. bg: false,
  1667. ca: false,
  1668. ckb: false,
  1669. cs: false,
  1670. de: false,
  1671. el: false,
  1672. en: false,
  1673. es: false,
  1674. et: false,
  1675. fa: true,
  1676. fi: false,
  1677. fr: false,
  1678. hr: false,
  1679. hu: false,
  1680. he: true,
  1681. id: false,
  1682. it: false,
  1683. ja: false,
  1684. ko: false,
  1685. lv: false,
  1686. lt: false,
  1687. nl: false,
  1688. no: false,
  1689. pl: false,
  1690. pt: false,
  1691. ro: false,
  1692. ru: false,
  1693. sk: false,
  1694. sl: false,
  1695. srCyrl: false,
  1696. srLatn: false,
  1697. sv: false,
  1698. th: false,
  1699. tr: false,
  1700. az: false,
  1701. uk: false,
  1702. vi: false,
  1703. zhHans: false,
  1704. zhHant: false
  1705. };
  1706. // Composables
  1707. // Types
  1708. // Composables
  1709. function useProxiedModel(props, prop, defaultValue) {
  1710. let transformIn = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : v => v;
  1711. let transformOut = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : v => v;
  1712. const vm = getCurrentInstance('useProxiedModel');
  1713. const internal = vue.ref(props[prop] !== undefined ? props[prop] : defaultValue);
  1714. const kebabProp = toKebabCase(prop);
  1715. const checkKebab = kebabProp !== prop;
  1716. const isControlled = checkKebab ? vue.computed(() => {
  1717. void props[prop];
  1718. return !!((vm.vnode.props?.hasOwnProperty(prop) || vm.vnode.props?.hasOwnProperty(kebabProp)) && (vm.vnode.props?.hasOwnProperty(`onUpdate:${prop}`) || vm.vnode.props?.hasOwnProperty(`onUpdate:${kebabProp}`)));
  1719. }) : vue.computed(() => {
  1720. void props[prop];
  1721. return !!(vm.vnode.props?.hasOwnProperty(prop) && vm.vnode.props?.hasOwnProperty(`onUpdate:${prop}`));
  1722. });
  1723. useToggleScope(() => !isControlled.value, () => {
  1724. vue.watch(() => props[prop], val => {
  1725. internal.value = val;
  1726. });
  1727. });
  1728. const model = vue.computed({
  1729. get() {
  1730. const externalValue = props[prop];
  1731. return transformIn(isControlled.value ? externalValue : internal.value);
  1732. },
  1733. set(internalValue) {
  1734. const newValue = transformOut(internalValue);
  1735. const value = vue.toRaw(isControlled.value ? props[prop] : internal.value);
  1736. if (value === newValue || transformIn(value) === internalValue) {
  1737. return;
  1738. }
  1739. internal.value = newValue;
  1740. vm?.emit(`update:${prop}`, newValue);
  1741. }
  1742. });
  1743. Object.defineProperty(model, 'externalValue', {
  1744. get: () => isControlled.value ? props[prop] : internal.value
  1745. });
  1746. return model;
  1747. }
  1748. // Composables
  1749. // Types
  1750. const LANG_PREFIX = '$vuetify.';
  1751. const replace = (str, params) => {
  1752. return str.replace(/\{(\d+)\}/g, (match, index) => {
  1753. return String(params[+index]);
  1754. });
  1755. };
  1756. const createTranslateFunction = (current, fallback, messages) => {
  1757. return function (key) {
  1758. for (var _len = arguments.length, params = new Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) {
  1759. params[_key - 1] = arguments[_key];
  1760. }
  1761. if (!key.startsWith(LANG_PREFIX)) {
  1762. return replace(key, params);
  1763. }
  1764. const shortKey = key.replace(LANG_PREFIX, '');
  1765. const currentLocale = current.value && messages.value[current.value];
  1766. const fallbackLocale = fallback.value && messages.value[fallback.value];
  1767. let str = getObjectValueByPath(currentLocale, shortKey, null);
  1768. if (!str) {
  1769. consoleWarn(`Translation key "${key}" not found in "${current.value}", trying fallback locale`);
  1770. str = getObjectValueByPath(fallbackLocale, shortKey, null);
  1771. }
  1772. if (!str) {
  1773. consoleError(`Translation key "${key}" not found in fallback`);
  1774. str = key;
  1775. }
  1776. if (typeof str !== 'string') {
  1777. consoleError(`Translation key "${key}" has a non-string value`);
  1778. str = key;
  1779. }
  1780. return replace(str, params);
  1781. };
  1782. };
  1783. function createNumberFunction(current, fallback) {
  1784. return (value, options) => {
  1785. const numberFormat = new Intl.NumberFormat([current.value, fallback.value], options);
  1786. return numberFormat.format(value);
  1787. };
  1788. }
  1789. function useProvided(props, prop, provided) {
  1790. const internal = useProxiedModel(props, prop, props[prop] ?? provided.value);
  1791. // TODO: Remove when defaultValue works
  1792. internal.value = props[prop] ?? provided.value;
  1793. vue.watch(provided, v => {
  1794. if (props[prop] == null) {
  1795. internal.value = provided.value;
  1796. }
  1797. });
  1798. return internal;
  1799. }
  1800. function createProvideFunction(state) {
  1801. return props => {
  1802. const current = useProvided(props, 'locale', state.current);
  1803. const fallback = useProvided(props, 'fallback', state.fallback);
  1804. const messages = useProvided(props, 'messages', state.messages);
  1805. return {
  1806. name: 'vuetify',
  1807. current,
  1808. fallback,
  1809. messages,
  1810. t: createTranslateFunction(current, fallback, messages),
  1811. n: createNumberFunction(current, fallback),
  1812. provide: createProvideFunction({
  1813. current,
  1814. fallback,
  1815. messages
  1816. })
  1817. };
  1818. };
  1819. }
  1820. function createVuetifyAdapter(options) {
  1821. const current = vue.shallowRef(options?.locale ?? 'en');
  1822. const fallback = vue.shallowRef(options?.fallback ?? 'en');
  1823. const messages = vue.ref({
  1824. en,
  1825. ...options?.messages
  1826. });
  1827. return {
  1828. name: 'vuetify',
  1829. current,
  1830. fallback,
  1831. messages,
  1832. t: createTranslateFunction(current, fallback, messages),
  1833. n: createNumberFunction(current, fallback),
  1834. provide: createProvideFunction({
  1835. current,
  1836. fallback,
  1837. messages
  1838. })
  1839. };
  1840. }
  1841. // Utilities
  1842. // Types
  1843. const LocaleSymbol = Symbol.for('vuetify:locale');
  1844. function isLocaleInstance(obj) {
  1845. return obj.name != null;
  1846. }
  1847. function createLocale(options) {
  1848. const i18n = options?.adapter && isLocaleInstance(options?.adapter) ? options?.adapter : createVuetifyAdapter(options);
  1849. const rtl = createRtl(i18n, options);
  1850. return {
  1851. ...i18n,
  1852. ...rtl
  1853. };
  1854. }
  1855. function useLocale() {
  1856. const locale = vue.inject(LocaleSymbol);
  1857. if (!locale) throw new Error('[Vuetify] Could not find injected locale instance');
  1858. return locale;
  1859. }
  1860. function provideLocale(props) {
  1861. const locale = vue.inject(LocaleSymbol);
  1862. if (!locale) throw new Error('[Vuetify] Could not find injected locale instance');
  1863. const i18n = locale.provide(props);
  1864. const rtl = provideRtl(i18n, locale.rtl, props);
  1865. const data = {
  1866. ...i18n,
  1867. ...rtl
  1868. };
  1869. vue.provide(LocaleSymbol, data);
  1870. return data;
  1871. }
  1872. function createRtl(i18n, options) {
  1873. const rtl = vue.ref(options?.rtl ?? defaultRtl);
  1874. const isRtl = vue.computed(() => rtl.value[i18n.current.value] ?? false);
  1875. return {
  1876. isRtl,
  1877. rtl,
  1878. rtlClasses: vue.computed(() => `v-locale--is-${isRtl.value ? 'rtl' : 'ltr'}`)
  1879. };
  1880. }
  1881. function provideRtl(locale, rtl, props) {
  1882. const isRtl = vue.computed(() => props.rtl ?? rtl.value[locale.current.value] ?? false);
  1883. return {
  1884. isRtl,
  1885. rtl,
  1886. rtlClasses: vue.computed(() => `v-locale--is-${isRtl.value ? 'rtl' : 'ltr'}`)
  1887. };
  1888. }
  1889. function useRtl() {
  1890. const locale = vue.inject(LocaleSymbol);
  1891. if (!locale) throw new Error('[Vuetify] Could not find injected rtl instance');
  1892. return {
  1893. isRtl: locale.isRtl,
  1894. rtlClasses: locale.rtlClasses
  1895. };
  1896. }
  1897. /**
  1898. * WCAG 3.0 APCA perceptual contrast algorithm from https://github.com/Myndex/SAPC-APCA
  1899. * @licence https://www.w3.org/Consortium/Legal/2015/copyright-software-and-document
  1900. * @see https://www.w3.org/WAI/GL/task-forces/silver/wiki/Visual_Contrast_of_Text_Subgroup
  1901. */
  1902. // Types
  1903. // MAGICAL NUMBERS
  1904. // sRGB Conversion to Relative Luminance (Y)
  1905. // Transfer Curve (aka "Gamma") for sRGB linearization
  1906. // Simple power curve vs piecewise described in docs
  1907. // Essentially, 2.4 best models actual display
  1908. // characteristics in combination with the total method
  1909. const mainTRC = 2.4;
  1910. const Rco = 0.2126729; // sRGB Red Coefficient (from matrix)
  1911. const Gco = 0.7151522; // sRGB Green Coefficient (from matrix)
  1912. const Bco = 0.0721750; // sRGB Blue Coefficient (from matrix)
  1913. // For Finding Raw SAPC Contrast from Relative Luminance (Y)
  1914. // Constants for SAPC Power Curve Exponents
  1915. // One pair for normal text, and one for reverse
  1916. // These are the "beating heart" of SAPC
  1917. const normBG = 0.55;
  1918. const normTXT = 0.58;
  1919. const revTXT = 0.57;
  1920. const revBG = 0.62;
  1921. // For Clamping and Scaling Values
  1922. const blkThrs = 0.03; // Level that triggers the soft black clamp
  1923. const blkClmp = 1.45; // Exponent for the soft black clamp curve
  1924. const deltaYmin = 0.0005; // Lint trap
  1925. const scaleBoW = 1.25; // Scaling for dark text on light
  1926. const scaleWoB = 1.25; // Scaling for light text on dark
  1927. const loConThresh = 0.078; // Threshold for new simple offset scale
  1928. const loConFactor = 12.82051282051282; // = 1/0.078,
  1929. const loConOffset = 0.06; // The simple offset
  1930. const loClip = 0.001; // Output clip (lint trap #2)
  1931. function APCAcontrast(text, background) {
  1932. // Linearize sRGB
  1933. const Rtxt = (text.r / 255) ** mainTRC;
  1934. const Gtxt = (text.g / 255) ** mainTRC;
  1935. const Btxt = (text.b / 255) ** mainTRC;
  1936. const Rbg = (background.r / 255) ** mainTRC;
  1937. const Gbg = (background.g / 255) ** mainTRC;
  1938. const Bbg = (background.b / 255) ** mainTRC;
  1939. // Apply the standard coefficients and sum to Y
  1940. let Ytxt = Rtxt * Rco + Gtxt * Gco + Btxt * Bco;
  1941. let Ybg = Rbg * Rco + Gbg * Gco + Bbg * Bco;
  1942. // Soft clamp Y when near black.
  1943. // Now clamping all colors to prevent crossover errors
  1944. if (Ytxt <= blkThrs) Ytxt += (blkThrs - Ytxt) ** blkClmp;
  1945. if (Ybg <= blkThrs) Ybg += (blkThrs - Ybg) ** blkClmp;
  1946. // Return 0 Early for extremely low ∆Y (lint trap #1)
  1947. if (Math.abs(Ybg - Ytxt) < deltaYmin) return 0.0;
  1948. // SAPC CONTRAST
  1949. let outputContrast; // For weighted final values
  1950. if (Ybg > Ytxt) {
  1951. // For normal polarity, black text on white
  1952. // Calculate the SAPC contrast value and scale
  1953. const SAPC = (Ybg ** normBG - Ytxt ** normTXT) * scaleBoW;
  1954. // NEW! SAPC SmoothScale™
  1955. // Low Contrast Smooth Scale Rollout to prevent polarity reversal
  1956. // and also a low clip for very low contrasts (lint trap #2)
  1957. // much of this is for very low contrasts, less than 10
  1958. // therefore for most reversing needs, only loConOffset is important
  1959. outputContrast = SAPC < loClip ? 0.0 : SAPC < loConThresh ? SAPC - SAPC * loConFactor * loConOffset : SAPC - loConOffset;
  1960. } else {
  1961. // For reverse polarity, light text on dark
  1962. // WoB should always return negative value.
  1963. const SAPC = (Ybg ** revBG - Ytxt ** revTXT) * scaleWoB;
  1964. outputContrast = SAPC > -loClip ? 0.0 : SAPC > -loConThresh ? SAPC - SAPC * loConFactor * loConOffset : SAPC + loConOffset;
  1965. }
  1966. return outputContrast * 100;
  1967. }
  1968. // Utilities
  1969. // Types
  1970. const ThemeSymbol = Symbol.for('vuetify:theme');
  1971. const makeThemeProps = propsFactory({
  1972. theme: String
  1973. }, 'theme');
  1974. const defaultThemeOptions = {
  1975. defaultTheme: 'light',
  1976. variations: {
  1977. colors: [],
  1978. lighten: 0,
  1979. darken: 0
  1980. },
  1981. themes: {
  1982. light: {
  1983. dark: false,
  1984. colors: {
  1985. background: '#FFFFFF',
  1986. surface: '#FFFFFF',
  1987. 'surface-variant': '#424242',
  1988. 'on-surface-variant': '#EEEEEE',
  1989. primary: '#6200EE',
  1990. 'primary-darken-1': '#3700B3',
  1991. secondary: '#03DAC6',
  1992. 'secondary-darken-1': '#018786',
  1993. error: '#B00020',
  1994. info: '#2196F3',
  1995. success: '#4CAF50',
  1996. warning: '#FB8C00'
  1997. },
  1998. variables: {
  1999. 'border-color': '#000000',
  2000. 'border-opacity': 0.12,
  2001. 'high-emphasis-opacity': 0.87,
  2002. 'medium-emphasis-opacity': 0.60,
  2003. 'disabled-opacity': 0.38,
  2004. 'idle-opacity': 0.04,
  2005. 'hover-opacity': 0.04,
  2006. 'focus-opacity': 0.12,
  2007. 'selected-opacity': 0.08,
  2008. 'activated-opacity': 0.12,
  2009. 'pressed-opacity': 0.12,
  2010. 'dragged-opacity': 0.08,
  2011. 'theme-kbd': '#212529',
  2012. 'theme-on-kbd': '#FFFFFF',
  2013. 'theme-code': '#F5F5F5',
  2014. 'theme-on-code': '#000000'
  2015. }
  2016. },
  2017. dark: {
  2018. dark: true,
  2019. colors: {
  2020. background: '#121212',
  2021. surface: '#212121',
  2022. 'surface-variant': '#BDBDBD',
  2023. 'on-surface-variant': '#424242',
  2024. primary: '#BB86FC',
  2025. 'primary-darken-1': '#3700B3',
  2026. secondary: '#03DAC5',
  2027. 'secondary-darken-1': '#03DAC5',
  2028. error: '#CF6679',
  2029. info: '#2196F3',
  2030. success: '#4CAF50',
  2031. warning: '#FB8C00'
  2032. },
  2033. variables: {
  2034. 'border-color': '#FFFFFF',
  2035. 'border-opacity': 0.12,
  2036. 'high-emphasis-opacity': 1,
  2037. 'medium-emphasis-opacity': 0.70,
  2038. 'disabled-opacity': 0.50,
  2039. 'idle-opacity': 0.10,
  2040. 'hover-opacity': 0.04,
  2041. 'focus-opacity': 0.12,
  2042. 'selected-opacity': 0.08,
  2043. 'activated-opacity': 0.12,
  2044. 'pressed-opacity': 0.16,
  2045. 'dragged-opacity': 0.08,
  2046. 'theme-kbd': '#212529',
  2047. 'theme-on-kbd': '#FFFFFF',
  2048. 'theme-code': '#343434',
  2049. 'theme-on-code': '#CCCCCC'
  2050. }
  2051. }
  2052. }
  2053. };
  2054. function parseThemeOptions() {
  2055. let options = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : defaultThemeOptions;
  2056. if (!options) return {
  2057. ...defaultThemeOptions,
  2058. isDisabled: true
  2059. };
  2060. const themes = {};
  2061. for (const [key, theme] of Object.entries(options.themes ?? {})) {
  2062. const defaultTheme = theme.dark || key === 'dark' ? defaultThemeOptions.themes?.dark : defaultThemeOptions.themes?.light;
  2063. themes[key] = mergeDeep(defaultTheme, theme);
  2064. }
  2065. return mergeDeep(defaultThemeOptions, {
  2066. ...options,
  2067. themes
  2068. });
  2069. }
  2070. // Composables
  2071. function createTheme(options) {
  2072. const parsedOptions = parseThemeOptions(options);
  2073. const name = vue.ref(parsedOptions.defaultTheme);
  2074. const themes = vue.ref(parsedOptions.themes);
  2075. const computedThemes = vue.computed(() => {
  2076. const acc = {};
  2077. for (const [name, original] of Object.entries(themes.value)) {
  2078. const theme = acc[name] = {
  2079. ...original,
  2080. colors: {
  2081. ...original.colors
  2082. }
  2083. };
  2084. if (parsedOptions.variations) {
  2085. for (const name of parsedOptions.variations.colors) {
  2086. const color = theme.colors[name];
  2087. if (!color) continue;
  2088. for (const variation of ['lighten', 'darken']) {
  2089. const fn = variation === 'lighten' ? lighten : darken;
  2090. for (const amount of createRange(parsedOptions.variations[variation], 1)) {
  2091. theme.colors[`${name}-${variation}-${amount}`] = RGBtoHex(fn(parseColor(color), amount));
  2092. }
  2093. }
  2094. }
  2095. }
  2096. for (const color of Object.keys(theme.colors)) {
  2097. if (/^on-[a-z]/.test(color) || theme.colors[`on-${color}`]) continue;
  2098. const onColor = `on-${color}`;
  2099. const colorVal = parseColor(theme.colors[color]);
  2100. const blackContrast = Math.abs(APCAcontrast(parseColor(0), colorVal));
  2101. const whiteContrast = Math.abs(APCAcontrast(parseColor(0xffffff), colorVal));
  2102. // TODO: warn about poor color selections
  2103. // const contrastAsText = Math.abs(APCAcontrast(colorVal, colorToInt(theme.colors.background)))
  2104. // const minContrast = Math.max(blackContrast, whiteContrast)
  2105. // if (minContrast < 60) {
  2106. // consoleInfo(`${key} theme color ${color} has poor contrast (${minContrast.toFixed()}%)`)
  2107. // } else if (contrastAsText < 60 && !['background', 'surface'].includes(color)) {
  2108. // consoleInfo(`${key} theme color ${color} has poor contrast as text (${contrastAsText.toFixed()}%)`)
  2109. // }
  2110. // Prefer white text if both have an acceptable contrast ratio
  2111. theme.colors[onColor] = whiteContrast > Math.min(blackContrast, 50) ? '#fff' : '#000';
  2112. }
  2113. }
  2114. return acc;
  2115. });
  2116. const current = vue.computed(() => computedThemes.value[name.value]);
  2117. const styles = vue.computed(() => {
  2118. const lines = [];
  2119. if (current.value.dark) {
  2120. createCssClass(lines, ':root', ['color-scheme: dark']);
  2121. }
  2122. createCssClass(lines, ':root', genCssVariables(current.value));
  2123. for (const [themeName, theme] of Object.entries(computedThemes.value)) {
  2124. createCssClass(lines, `.v-theme--${themeName}`, [`color-scheme: ${theme.dark ? 'dark' : 'normal'}`, ...genCssVariables(theme)]);
  2125. }
  2126. const bgLines = [];
  2127. const fgLines = [];
  2128. const colors = new Set(Object.values(computedThemes.value).flatMap(theme => Object.keys(theme.colors)));
  2129. for (const key of colors) {
  2130. if (/^on-[a-z]/.test(key)) {
  2131. createCssClass(fgLines, `.${key}`, [`color: rgb(var(--v-theme-${key})) !important`]);
  2132. } else {
  2133. 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`]);
  2134. createCssClass(fgLines, `.text-${key}`, [`color: rgb(var(--v-theme-${key})) !important`]);
  2135. createCssClass(fgLines, `.border-${key}`, [`--v-border-color: var(--v-theme-${key})`]);
  2136. }
  2137. }
  2138. lines.push(...bgLines, ...fgLines);
  2139. return lines.map((str, i) => i === 0 ? str : ` ${str}`).join('');
  2140. });
  2141. function getHead() {
  2142. return {
  2143. style: [{
  2144. children: styles.value,
  2145. id: 'vuetify-theme-stylesheet',
  2146. nonce: parsedOptions.cspNonce || false
  2147. }]
  2148. };
  2149. }
  2150. function install(app) {
  2151. if (parsedOptions.isDisabled) return;
  2152. const head = app._context.provides.usehead;
  2153. if (head) {
  2154. if (head.push) {
  2155. const entry = head.push(getHead);
  2156. if (IN_BROWSER) {
  2157. vue.watch(styles, () => {
  2158. entry.patch(getHead);
  2159. });
  2160. }
  2161. } else {
  2162. if (IN_BROWSER) {
  2163. head.addHeadObjs(vue.computed(getHead));
  2164. vue.watchEffect(() => head.updateDOM());
  2165. } else {
  2166. head.addHeadObjs(getHead());
  2167. }
  2168. }
  2169. } else {
  2170. let styleEl = IN_BROWSER ? document.getElementById('vuetify-theme-stylesheet') : null;
  2171. if (IN_BROWSER) {
  2172. vue.watch(styles, updateStyles, {
  2173. immediate: true
  2174. });
  2175. } else {
  2176. updateStyles();
  2177. }
  2178. function updateStyles() {
  2179. if (typeof document !== 'undefined' && !styleEl) {
  2180. const el = document.createElement('style');
  2181. el.type = 'text/css';
  2182. el.id = 'vuetify-theme-stylesheet';
  2183. if (parsedOptions.cspNonce) el.setAttribute('nonce', parsedOptions.cspNonce);
  2184. styleEl = el;
  2185. document.head.appendChild(styleEl);
  2186. }
  2187. if (styleEl) styleEl.innerHTML = styles.value;
  2188. }
  2189. }
  2190. }
  2191. const themeClasses = vue.computed(() => parsedOptions.isDisabled ? undefined : `v-theme--${name.value}`);
  2192. return {
  2193. install,
  2194. isDisabled: parsedOptions.isDisabled,
  2195. name,
  2196. themes,
  2197. current,
  2198. computedThemes,
  2199. themeClasses,
  2200. styles,
  2201. global: {
  2202. name,
  2203. current
  2204. }
  2205. };
  2206. }
  2207. function provideTheme(props) {
  2208. getCurrentInstance('provideTheme');
  2209. const theme = vue.inject(ThemeSymbol, null);
  2210. if (!theme) throw new Error('Could not find Vuetify theme injection');
  2211. const name = vue.computed(() => {
  2212. return props.theme ?? theme?.name.value;
  2213. });
  2214. const themeClasses = vue.computed(() => theme.isDisabled ? undefined : `v-theme--${name.value}`);
  2215. const newTheme = {
  2216. ...theme,
  2217. name,
  2218. themeClasses
  2219. };
  2220. vue.provide(ThemeSymbol, newTheme);
  2221. return newTheme;
  2222. }
  2223. function useTheme() {
  2224. getCurrentInstance('useTheme');
  2225. const theme = vue.inject(ThemeSymbol, null);
  2226. if (!theme) throw new Error('Could not find Vuetify theme injection');
  2227. return theme;
  2228. }
  2229. function createCssClass(lines, selector, content) {
  2230. lines.push(`${selector} {\n`, ...content.map(line => ` ${line};\n`), '}\n');
  2231. }
  2232. function genCssVariables(theme) {
  2233. const lightOverlay = theme.dark ? 2 : 1;
  2234. const darkOverlay = theme.dark ? 1 : 2;
  2235. const variables = [];
  2236. for (const [key, value] of Object.entries(theme.colors)) {
  2237. const rgb = parseColor(value);
  2238. variables.push(`--v-theme-${key}: ${rgb.r},${rgb.g},${rgb.b}`);
  2239. if (!key.startsWith('on-')) {
  2240. variables.push(`--v-theme-${key}-overlay-multiplier: ${getLuma(value) > 0.18 ? lightOverlay : darkOverlay}`);
  2241. }
  2242. }
  2243. for (const [key, value] of Object.entries(theme.variables)) {
  2244. const color = typeof value === 'string' && value.startsWith('#') ? parseColor(value) : undefined;
  2245. const rgb = color ? `${color.r}, ${color.g}, ${color.b}` : undefined;
  2246. variables.push(`--v-${key}: ${rgb ?? value}`);
  2247. }
  2248. return variables;
  2249. }
  2250. const makeVAppProps = propsFactory({
  2251. ...makeComponentProps(),
  2252. ...makeLayoutProps({
  2253. fullHeight: true
  2254. }),
  2255. ...makeThemeProps()
  2256. }, 'VApp');
  2257. const VApp = genericComponent()({
  2258. name: 'VApp',
  2259. props: makeVAppProps(),
  2260. setup(props, _ref) {
  2261. let {
  2262. slots
  2263. } = _ref;
  2264. const theme = provideTheme(props);
  2265. const {
  2266. layoutClasses,
  2267. layoutStyles,
  2268. getLayoutItem,
  2269. items,
  2270. layoutRef
  2271. } = createLayout(props);
  2272. const {
  2273. rtlClasses
  2274. } = useRtl();
  2275. useRender(() => vue.createVNode("div", {
  2276. "ref": layoutRef,
  2277. "class": ['v-application', theme.themeClasses.value, layoutClasses.value, rtlClasses.value, props.class],
  2278. "style": [layoutStyles.value, props.style]
  2279. }, [vue.createVNode("div", {
  2280. "class": "v-application__wrap"
  2281. }, [slots.default?.()])]));
  2282. return {
  2283. getLayoutItem,
  2284. items,
  2285. theme
  2286. };
  2287. }
  2288. });
  2289. // Utilities
  2290. // Types
  2291. // Composables
  2292. const makeTagProps = propsFactory({
  2293. tag: {
  2294. type: String,
  2295. default: 'div'
  2296. }
  2297. }, 'tag');
  2298. const makeVToolbarTitleProps = propsFactory({
  2299. text: String,
  2300. ...makeComponentProps(),
  2301. ...makeTagProps()
  2302. }, 'VToolbarTitle');
  2303. const VToolbarTitle = genericComponent()({
  2304. name: 'VToolbarTitle',
  2305. props: makeVToolbarTitleProps(),
  2306. setup(props, _ref) {
  2307. let {
  2308. slots
  2309. } = _ref;
  2310. useRender(() => {
  2311. const hasText = !!(slots.default || slots.text || props.text);
  2312. return vue.createVNode(props.tag, {
  2313. "class": ['v-toolbar-title', props.class],
  2314. "style": props.style
  2315. }, {
  2316. default: () => [hasText && vue.createVNode("div", {
  2317. "class": "v-toolbar-title__placeholder"
  2318. }, [slots.text ? slots.text() : props.text, slots.default?.()])]
  2319. });
  2320. });
  2321. return {};
  2322. }
  2323. });
  2324. // Utilities
  2325. // Types
  2326. const makeTransitionProps$1 = propsFactory({
  2327. disabled: Boolean,
  2328. group: Boolean,
  2329. hideOnLeave: Boolean,
  2330. leaveAbsolute: Boolean,
  2331. mode: String,
  2332. origin: String
  2333. }, 'transition');
  2334. function createCssTransition(name, origin, mode) {
  2335. return genericComponent()({
  2336. name,
  2337. props: makeTransitionProps$1({
  2338. mode,
  2339. origin
  2340. }),
  2341. setup(props, _ref) {
  2342. let {
  2343. slots
  2344. } = _ref;
  2345. const functions = {
  2346. onBeforeEnter(el) {
  2347. if (props.origin) {
  2348. el.style.transformOrigin = props.origin;
  2349. }
  2350. },
  2351. onLeave(el) {
  2352. if (props.leaveAbsolute) {
  2353. const {
  2354. offsetTop,
  2355. offsetLeft,
  2356. offsetWidth,
  2357. offsetHeight
  2358. } = el;
  2359. el._transitionInitialStyles = {
  2360. position: el.style.position,
  2361. top: el.style.top,
  2362. left: el.style.left,
  2363. width: el.style.width,
  2364. height: el.style.height
  2365. };
  2366. el.style.position = 'absolute';
  2367. el.style.top = `${offsetTop}px`;
  2368. el.style.left = `${offsetLeft}px`;
  2369. el.style.width = `${offsetWidth}px`;
  2370. el.style.height = `${offsetHeight}px`;
  2371. }
  2372. if (props.hideOnLeave) {
  2373. el.style.setProperty('display', 'none', 'important');
  2374. }
  2375. },
  2376. onAfterLeave(el) {
  2377. if (props.leaveAbsolute && el?._transitionInitialStyles) {
  2378. const {
  2379. position,
  2380. top,
  2381. left,
  2382. width,
  2383. height
  2384. } = el._transitionInitialStyles;
  2385. delete el._transitionInitialStyles;
  2386. el.style.position = position || '';
  2387. el.style.top = top || '';
  2388. el.style.left = left || '';
  2389. el.style.width = width || '';
  2390. el.style.height = height || '';
  2391. }
  2392. }
  2393. };
  2394. return () => {
  2395. const tag = props.group ? vue.TransitionGroup : vue.Transition;
  2396. return vue.h(tag, {
  2397. name: props.disabled ? '' : name,
  2398. css: !props.disabled,
  2399. ...(props.group ? undefined : {
  2400. mode: props.mode
  2401. }),
  2402. ...(props.disabled ? {} : functions)
  2403. }, slots.default);
  2404. };
  2405. }
  2406. });
  2407. }
  2408. function createJavascriptTransition(name, functions) {
  2409. let mode = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : 'in-out';
  2410. return genericComponent()({
  2411. name,
  2412. props: {
  2413. mode: {
  2414. type: String,
  2415. default: mode
  2416. },
  2417. disabled: Boolean
  2418. },
  2419. setup(props, _ref2) {
  2420. let {
  2421. slots
  2422. } = _ref2;
  2423. return () => {
  2424. return vue.h(vue.Transition, {
  2425. name: props.disabled ? '' : name,
  2426. css: !props.disabled,
  2427. // mode: props.mode, // TODO: vuejs/vue-next#3104
  2428. ...(props.disabled ? {} : functions)
  2429. }, slots.default);
  2430. };
  2431. }
  2432. });
  2433. }
  2434. // Utilities
  2435. function ExpandTransitionGenerator () {
  2436. let expandedParentClass = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : '';
  2437. let x = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : false;
  2438. const sizeProperty = x ? 'width' : 'height';
  2439. const offsetProperty = vue.camelize(`offset-${sizeProperty}`);
  2440. return {
  2441. onBeforeEnter(el) {
  2442. el._parent = el.parentNode;
  2443. el._initialStyle = {
  2444. transition: el.style.transition,
  2445. overflow: el.style.overflow,
  2446. [sizeProperty]: el.style[sizeProperty]
  2447. };
  2448. },
  2449. onEnter(el) {
  2450. const initialStyle = el._initialStyle;
  2451. el.style.setProperty('transition', 'none', 'important');
  2452. // Hide overflow to account for collapsed margins in the calculated height
  2453. el.style.overflow = 'hidden';
  2454. const offset = `${el[offsetProperty]}px`;
  2455. el.style[sizeProperty] = '0';
  2456. void el.offsetHeight; // force reflow
  2457. el.style.transition = initialStyle.transition;
  2458. if (expandedParentClass && el._parent) {
  2459. el._parent.classList.add(expandedParentClass);
  2460. }
  2461. requestAnimationFrame(() => {
  2462. el.style[sizeProperty] = offset;
  2463. });
  2464. },
  2465. onAfterEnter: resetStyles,
  2466. onEnterCancelled: resetStyles,
  2467. onLeave(el) {
  2468. el._initialStyle = {
  2469. transition: '',
  2470. overflow: el.style.overflow,
  2471. [sizeProperty]: el.style[sizeProperty]
  2472. };
  2473. el.style.overflow = 'hidden';
  2474. el.style[sizeProperty] = `${el[offsetProperty]}px`;
  2475. void el.offsetHeight; // force reflow
  2476. requestAnimationFrame(() => el.style[sizeProperty] = '0');
  2477. },
  2478. onAfterLeave,
  2479. onLeaveCancelled: onAfterLeave
  2480. };
  2481. function onAfterLeave(el) {
  2482. if (expandedParentClass && el._parent) {
  2483. el._parent.classList.remove(expandedParentClass);
  2484. }
  2485. resetStyles(el);
  2486. }
  2487. function resetStyles(el) {
  2488. const size = el._initialStyle[sizeProperty];
  2489. el.style.overflow = el._initialStyle.overflow;
  2490. if (size != null) el.style[sizeProperty] = size;
  2491. delete el._initialStyle;
  2492. }
  2493. }
  2494. // Types
  2495. const makeVDialogTransitionProps = propsFactory({
  2496. target: Object
  2497. }, 'v-dialog-transition');
  2498. const VDialogTransition = genericComponent()({
  2499. name: 'VDialogTransition',
  2500. props: makeVDialogTransitionProps(),
  2501. setup(props, _ref) {
  2502. let {
  2503. slots
  2504. } = _ref;
  2505. const functions = {
  2506. onBeforeEnter(el) {
  2507. el.style.pointerEvents = 'none';
  2508. el.style.visibility = 'hidden';
  2509. },
  2510. async onEnter(el, done) {
  2511. await new Promise(resolve => requestAnimationFrame(resolve));
  2512. await new Promise(resolve => requestAnimationFrame(resolve));
  2513. el.style.visibility = '';
  2514. const {
  2515. x,
  2516. y,
  2517. sx,
  2518. sy,
  2519. speed
  2520. } = getDimensions(props.target, el);
  2521. const animation = animate(el, [{
  2522. transform: `translate(${x}px, ${y}px) scale(${sx}, ${sy})`,
  2523. opacity: 0
  2524. }, {}], {
  2525. duration: 225 * speed,
  2526. easing: deceleratedEasing
  2527. });
  2528. getChildren(el)?.forEach(el => {
  2529. animate(el, [{
  2530. opacity: 0
  2531. }, {
  2532. opacity: 0,
  2533. offset: 0.33
  2534. }, {}], {
  2535. duration: 225 * 2 * speed,
  2536. easing: standardEasing
  2537. });
  2538. });
  2539. animation.finished.then(() => done());
  2540. },
  2541. onAfterEnter(el) {
  2542. el.style.removeProperty('pointer-events');
  2543. },
  2544. onBeforeLeave(el) {
  2545. el.style.pointerEvents = 'none';
  2546. },
  2547. async onLeave(el, done) {
  2548. await new Promise(resolve => requestAnimationFrame(resolve));
  2549. const {
  2550. x,
  2551. y,
  2552. sx,
  2553. sy,
  2554. speed
  2555. } = getDimensions(props.target, el);
  2556. const animation = animate(el, [{}, {
  2557. transform: `translate(${x}px, ${y}px) scale(${sx}, ${sy})`,
  2558. opacity: 0
  2559. }], {
  2560. duration: 125 * speed,
  2561. easing: acceleratedEasing
  2562. });
  2563. animation.finished.then(() => done());
  2564. getChildren(el)?.forEach(el => {
  2565. animate(el, [{}, {
  2566. opacity: 0,
  2567. offset: 0.2
  2568. }, {
  2569. opacity: 0
  2570. }], {
  2571. duration: 125 * 2 * speed,
  2572. easing: standardEasing
  2573. });
  2574. });
  2575. },
  2576. onAfterLeave(el) {
  2577. el.style.removeProperty('pointer-events');
  2578. }
  2579. };
  2580. return () => {
  2581. return props.target ? vue.createVNode(vue.Transition, vue.mergeProps({
  2582. "name": "dialog-transition"
  2583. }, functions, {
  2584. "css": false
  2585. }), slots) : vue.createVNode(vue.Transition, {
  2586. "name": "dialog-transition"
  2587. }, slots);
  2588. };
  2589. }
  2590. });
  2591. /** Animatable children (card, sheet, list) */
  2592. function getChildren(el) {
  2593. const els = el.querySelector(':scope > .v-card, :scope > .v-sheet, :scope > .v-list')?.children;
  2594. return els && [...els];
  2595. }
  2596. function getDimensions(target, el) {
  2597. const targetBox = target.getBoundingClientRect();
  2598. const elBox = nullifyTransforms(el);
  2599. const [originX, originY] = getComputedStyle(el).transformOrigin.split(' ').map(v => parseFloat(v));
  2600. const [anchorSide, anchorOffset] = getComputedStyle(el).getPropertyValue('--v-overlay-anchor-origin').split(' ');
  2601. let offsetX = targetBox.left + targetBox.width / 2;
  2602. if (anchorSide === 'left' || anchorOffset === 'left') {
  2603. offsetX -= targetBox.width / 2;
  2604. } else if (anchorSide === 'right' || anchorOffset === 'right') {
  2605. offsetX += targetBox.width / 2;
  2606. }
  2607. let offsetY = targetBox.top + targetBox.height / 2;
  2608. if (anchorSide === 'top' || anchorOffset === 'top') {
  2609. offsetY -= targetBox.height / 2;
  2610. } else if (anchorSide === 'bottom' || anchorOffset === 'bottom') {
  2611. offsetY += targetBox.height / 2;
  2612. }
  2613. const tsx = targetBox.width / elBox.width;
  2614. const tsy = targetBox.height / elBox.height;
  2615. const maxs = Math.max(1, tsx, tsy);
  2616. const sx = tsx / maxs || 0;
  2617. const sy = tsy / maxs || 0;
  2618. // Animate elements larger than 12% of the screen area up to 1.5x slower
  2619. const asa = elBox.width * elBox.height / (window.innerWidth * window.innerHeight);
  2620. const speed = asa > 0.12 ? Math.min(1.5, (asa - 0.12) * 10 + 1) : 1;
  2621. return {
  2622. x: offsetX - (originX + elBox.left),
  2623. y: offsetY - (originY + elBox.top),
  2624. sx,
  2625. sy,
  2626. speed
  2627. };
  2628. }
  2629. // Component specific transitions
  2630. const VFabTransition = createCssTransition('fab-transition', 'center center', 'out-in');
  2631. // Generic transitions
  2632. const VDialogBottomTransition = createCssTransition('dialog-bottom-transition');
  2633. const VDialogTopTransition = createCssTransition('dialog-top-transition');
  2634. const VFadeTransition = createCssTransition('fade-transition');
  2635. const VScaleTransition = createCssTransition('scale-transition');
  2636. const VScrollXTransition = createCssTransition('scroll-x-transition');
  2637. const VScrollXReverseTransition = createCssTransition('scroll-x-reverse-transition');
  2638. const VScrollYTransition = createCssTransition('scroll-y-transition');
  2639. const VScrollYReverseTransition = createCssTransition('scroll-y-reverse-transition');
  2640. const VSlideXTransition = createCssTransition('slide-x-transition');
  2641. const VSlideXReverseTransition = createCssTransition('slide-x-reverse-transition');
  2642. const VSlideYTransition = createCssTransition('slide-y-transition');
  2643. const VSlideYReverseTransition = createCssTransition('slide-y-reverse-transition');
  2644. // Javascript transitions
  2645. const VExpandTransition = createJavascriptTransition('expand-transition', ExpandTransitionGenerator());
  2646. const VExpandXTransition = createJavascriptTransition('expand-x-transition', ExpandTransitionGenerator('', true));
  2647. // Composables
  2648. // Types
  2649. const makeVDefaultsProviderProps = propsFactory({
  2650. defaults: Object,
  2651. disabled: Boolean,
  2652. reset: [Number, String],
  2653. root: [Boolean, String],
  2654. scoped: Boolean
  2655. }, 'VDefaultsProvider');
  2656. const VDefaultsProvider = genericComponent(false)({
  2657. name: 'VDefaultsProvider',
  2658. props: makeVDefaultsProviderProps(),
  2659. setup(props, _ref) {
  2660. let {
  2661. slots
  2662. } = _ref;
  2663. const {
  2664. defaults,
  2665. disabled,
  2666. reset,
  2667. root,
  2668. scoped
  2669. } = vue.toRefs(props);
  2670. provideDefaults(defaults, {
  2671. reset,
  2672. root,
  2673. scoped,
  2674. disabled
  2675. });
  2676. return () => slots.default?.();
  2677. }
  2678. });
  2679. // Utilities
  2680. // Types
  2681. // Composables
  2682. const makeDimensionProps = propsFactory({
  2683. height: [Number, String],
  2684. maxHeight: [Number, String],
  2685. maxWidth: [Number, String],
  2686. minHeight: [Number, String],
  2687. minWidth: [Number, String],
  2688. width: [Number, String]
  2689. }, 'dimension');
  2690. function useDimension(props) {
  2691. const dimensionStyles = vue.computed(() => ({
  2692. height: convertToUnit(props.height),
  2693. maxHeight: convertToUnit(props.maxHeight),
  2694. maxWidth: convertToUnit(props.maxWidth),
  2695. minHeight: convertToUnit(props.minHeight),
  2696. minWidth: convertToUnit(props.minWidth),
  2697. width: convertToUnit(props.width)
  2698. }));
  2699. return {
  2700. dimensionStyles
  2701. };
  2702. }
  2703. function useAspectStyles(props) {
  2704. return {
  2705. aspectStyles: vue.computed(() => {
  2706. const ratio = Number(props.aspectRatio);
  2707. return ratio ? {
  2708. paddingBottom: String(1 / ratio * 100) + '%'
  2709. } : undefined;
  2710. })
  2711. };
  2712. }
  2713. const makeVResponsiveProps = propsFactory({
  2714. aspectRatio: [String, Number],
  2715. contentClass: String,
  2716. inline: Boolean,
  2717. ...makeComponentProps(),
  2718. ...makeDimensionProps()
  2719. }, 'VResponsive');
  2720. const VResponsive = genericComponent()({
  2721. name: 'VResponsive',
  2722. props: makeVResponsiveProps(),
  2723. setup(props, _ref) {
  2724. let {
  2725. slots
  2726. } = _ref;
  2727. const {
  2728. aspectStyles
  2729. } = useAspectStyles(props);
  2730. const {
  2731. dimensionStyles
  2732. } = useDimension(props);
  2733. useRender(() => vue.createVNode("div", {
  2734. "class": ['v-responsive', {
  2735. 'v-responsive--inline': props.inline
  2736. }, props.class],
  2737. "style": [dimensionStyles.value, props.style]
  2738. }, [vue.createVNode("div", {
  2739. "class": "v-responsive__sizer",
  2740. "style": aspectStyles.value
  2741. }, null), slots.additional?.(), slots.default && vue.createVNode("div", {
  2742. "class": ['v-responsive__content', props.contentClass]
  2743. }, [slots.default()])]));
  2744. return {};
  2745. }
  2746. });
  2747. // Utilities
  2748. // Types
  2749. const makeTransitionProps = propsFactory({
  2750. transition: {
  2751. type: [Boolean, String, Object],
  2752. default: 'fade-transition',
  2753. validator: val => val !== true
  2754. }
  2755. }, 'transition');
  2756. const MaybeTransition = (props, _ref) => {
  2757. let {
  2758. slots
  2759. } = _ref;
  2760. const {
  2761. transition,
  2762. disabled,
  2763. ...rest
  2764. } = props;
  2765. const {
  2766. component = vue.Transition,
  2767. ...customProps
  2768. } = typeof transition === 'object' ? transition : {};
  2769. return vue.h(component, vue.mergeProps(typeof transition === 'string' ? {
  2770. name: disabled ? '' : transition
  2771. } : customProps, rest, {
  2772. disabled
  2773. }), slots);
  2774. };
  2775. // Utilities
  2776. // Types
  2777. function mounted$5(el, binding) {
  2778. if (!SUPPORTS_INTERSECTION) return;
  2779. const modifiers = binding.modifiers || {};
  2780. const value = binding.value;
  2781. const {
  2782. handler,
  2783. options
  2784. } = typeof value === 'object' ? value : {
  2785. handler: value,
  2786. options: {}
  2787. };
  2788. const observer = new IntersectionObserver(function () {
  2789. let entries = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : [];
  2790. let observer = arguments.length > 1 ? arguments[1] : undefined;
  2791. const _observe = el._observe?.[binding.instance.$.uid];
  2792. if (!_observe) return; // Just in case, should never fire
  2793. const isIntersecting = entries.some(entry => entry.isIntersecting);
  2794. // If is not quiet or has already been
  2795. // initted, invoke the user callback
  2796. if (handler && (!modifiers.quiet || _observe.init) && (!modifiers.once || isIntersecting || _observe.init)) {
  2797. handler(isIntersecting, entries, observer);
  2798. }
  2799. if (isIntersecting && modifiers.once) unmounted$5(el, binding);else _observe.init = true;
  2800. }, options);
  2801. el._observe = Object(el._observe);
  2802. el._observe[binding.instance.$.uid] = {
  2803. init: false,
  2804. observer
  2805. };
  2806. observer.observe(el);
  2807. }
  2808. function unmounted$5(el, binding) {
  2809. const observe = el._observe?.[binding.instance.$.uid];
  2810. if (!observe) return;
  2811. observe.observer.unobserve(el);
  2812. delete el._observe[binding.instance.$.uid];
  2813. }
  2814. const Intersect = {
  2815. mounted: mounted$5,
  2816. unmounted: unmounted$5
  2817. };
  2818. // Types
  2819. const makeVImgProps = propsFactory({
  2820. alt: String,
  2821. cover: Boolean,
  2822. eager: Boolean,
  2823. gradient: String,
  2824. lazySrc: String,
  2825. options: {
  2826. type: Object,
  2827. // For more information on types, navigate to:
  2828. // https://developer.mozilla.org/en-US/docs/Web/API/Intersection_Observer_API
  2829. default: () => ({
  2830. root: undefined,
  2831. rootMargin: undefined,
  2832. threshold: undefined
  2833. })
  2834. },
  2835. sizes: String,
  2836. src: {
  2837. type: [String, Object],
  2838. default: ''
  2839. },
  2840. srcset: String,
  2841. ...makeVResponsiveProps(),
  2842. ...makeComponentProps(),
  2843. ...makeTransitionProps()
  2844. }, 'VImg');
  2845. const VImg = genericComponent()({
  2846. name: 'VImg',
  2847. directives: {
  2848. intersect: Intersect
  2849. },
  2850. props: makeVImgProps(),
  2851. emits: {
  2852. loadstart: value => true,
  2853. load: value => true,
  2854. error: value => true
  2855. },
  2856. setup(props, _ref) {
  2857. let {
  2858. emit,
  2859. slots
  2860. } = _ref;
  2861. const currentSrc = vue.shallowRef(''); // Set from srcset
  2862. const image = vue.ref();
  2863. const state = vue.shallowRef(props.eager ? 'loading' : 'idle');
  2864. const naturalWidth = vue.shallowRef();
  2865. const naturalHeight = vue.shallowRef();
  2866. const normalisedSrc = vue.computed(() => {
  2867. return props.src && typeof props.src === 'object' ? {
  2868. src: props.src.src,
  2869. srcset: props.srcset || props.src.srcset,
  2870. lazySrc: props.lazySrc || props.src.lazySrc,
  2871. aspect: Number(props.aspectRatio || props.src.aspect || 0)
  2872. } : {
  2873. src: props.src,
  2874. srcset: props.srcset,
  2875. lazySrc: props.lazySrc,
  2876. aspect: Number(props.aspectRatio || 0)
  2877. };
  2878. });
  2879. const aspectRatio = vue.computed(() => {
  2880. return normalisedSrc.value.aspect || naturalWidth.value / naturalHeight.value || 0;
  2881. });
  2882. vue.watch(() => props.src, () => {
  2883. init(state.value !== 'idle');
  2884. });
  2885. vue.watch(aspectRatio, (val, oldVal) => {
  2886. if (!val && oldVal && image.value) {
  2887. pollForSize(image.value);
  2888. }
  2889. });
  2890. // TODO: getSrc when window width changes
  2891. vue.onBeforeMount(() => init());
  2892. function init(isIntersecting) {
  2893. if (props.eager && isIntersecting) return;
  2894. if (SUPPORTS_INTERSECTION && !isIntersecting && !props.eager) return;
  2895. state.value = 'loading';
  2896. if (normalisedSrc.value.lazySrc) {
  2897. const lazyImg = new Image();
  2898. lazyImg.src = normalisedSrc.value.lazySrc;
  2899. pollForSize(lazyImg, null);
  2900. }
  2901. if (!normalisedSrc.value.src) return;
  2902. vue.nextTick(() => {
  2903. emit('loadstart', image.value?.currentSrc || normalisedSrc.value.src);
  2904. if (image.value?.complete) {
  2905. if (!image.value.naturalWidth) {
  2906. onError();
  2907. }
  2908. if (state.value === 'error') return;
  2909. if (!aspectRatio.value) pollForSize(image.value, null);
  2910. onLoad();
  2911. } else {
  2912. if (!aspectRatio.value) pollForSize(image.value);
  2913. getSrc();
  2914. }
  2915. });
  2916. }
  2917. function onLoad() {
  2918. getSrc();
  2919. state.value = 'loaded';
  2920. emit('load', image.value?.currentSrc || normalisedSrc.value.src);
  2921. }
  2922. function onError() {
  2923. state.value = 'error';
  2924. emit('error', image.value?.currentSrc || normalisedSrc.value.src);
  2925. }
  2926. function getSrc() {
  2927. const img = image.value;
  2928. if (img) currentSrc.value = img.currentSrc || img.src;
  2929. }
  2930. let timer = -1;
  2931. function pollForSize(img) {
  2932. let timeout = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 100;
  2933. const poll = () => {
  2934. clearTimeout(timer);
  2935. const {
  2936. naturalHeight: imgHeight,
  2937. naturalWidth: imgWidth
  2938. } = img;
  2939. if (imgHeight || imgWidth) {
  2940. naturalWidth.value = imgWidth;
  2941. naturalHeight.value = imgHeight;
  2942. } else if (!img.complete && state.value === 'loading' && timeout != null) {
  2943. timer = window.setTimeout(poll, timeout);
  2944. } else if (img.currentSrc.endsWith('.svg') || img.currentSrc.startsWith('data:image/svg+xml')) {
  2945. naturalWidth.value = 1;
  2946. naturalHeight.value = 1;
  2947. }
  2948. };
  2949. poll();
  2950. }
  2951. const containClasses = vue.computed(() => ({
  2952. 'v-img__img--cover': props.cover,
  2953. 'v-img__img--contain': !props.cover
  2954. }));
  2955. const __image = () => {
  2956. if (!normalisedSrc.value.src || state.value === 'idle') return null;
  2957. const img = vue.createVNode("img", {
  2958. "class": ['v-img__img', containClasses.value],
  2959. "src": normalisedSrc.value.src,
  2960. "srcset": normalisedSrc.value.srcset,
  2961. "alt": props.alt,
  2962. "sizes": props.sizes,
  2963. "ref": image,
  2964. "onLoad": onLoad,
  2965. "onError": onError
  2966. }, null);
  2967. const sources = slots.sources?.();
  2968. return vue.createVNode(MaybeTransition, {
  2969. "transition": props.transition,
  2970. "appear": true
  2971. }, {
  2972. default: () => [vue.withDirectives(sources ? vue.createVNode("picture", {
  2973. "class": "v-img__picture"
  2974. }, [sources, img]) : img, [[vue.vShow, state.value === 'loaded']])]
  2975. });
  2976. };
  2977. const __preloadImage = () => vue.createVNode(MaybeTransition, {
  2978. "transition": props.transition
  2979. }, {
  2980. default: () => [normalisedSrc.value.lazySrc && state.value !== 'loaded' && vue.createVNode("img", {
  2981. "class": ['v-img__img', 'v-img__img--preload', containClasses.value],
  2982. "src": normalisedSrc.value.lazySrc,
  2983. "alt": props.alt
  2984. }, null)]
  2985. });
  2986. const __placeholder = () => {
  2987. if (!slots.placeholder) return null;
  2988. return vue.createVNode(MaybeTransition, {
  2989. "transition": props.transition,
  2990. "appear": true
  2991. }, {
  2992. default: () => [(state.value === 'loading' || state.value === 'error' && !slots.error) && vue.createVNode("div", {
  2993. "class": "v-img__placeholder"
  2994. }, [slots.placeholder()])]
  2995. });
  2996. };
  2997. const __error = () => {
  2998. if (!slots.error) return null;
  2999. return vue.createVNode(MaybeTransition, {
  3000. "transition": props.transition,
  3001. "appear": true
  3002. }, {
  3003. default: () => [state.value === 'error' && vue.createVNode("div", {
  3004. "class": "v-img__error"
  3005. }, [slots.error()])]
  3006. });
  3007. };
  3008. const __gradient = () => {
  3009. if (!props.gradient) return null;
  3010. return vue.createVNode("div", {
  3011. "class": "v-img__gradient",
  3012. "style": {
  3013. backgroundImage: `linear-gradient(${props.gradient})`
  3014. }
  3015. }, null);
  3016. };
  3017. const isBooted = vue.shallowRef(false);
  3018. {
  3019. const stop = vue.watch(aspectRatio, val => {
  3020. if (val) {
  3021. // Doesn't work with nextTick, idk why
  3022. requestAnimationFrame(() => {
  3023. requestAnimationFrame(() => {
  3024. isBooted.value = true;
  3025. });
  3026. });
  3027. stop();
  3028. }
  3029. });
  3030. }
  3031. useRender(() => {
  3032. const [responsiveProps] = VResponsive.filterProps(props);
  3033. return vue.withDirectives(vue.createVNode(VResponsive, vue.mergeProps({
  3034. "class": ['v-img', {
  3035. 'v-img--booting': !isBooted.value
  3036. }, props.class],
  3037. "style": [{
  3038. width: convertToUnit(props.width === 'auto' ? naturalWidth.value : props.width)
  3039. }, props.style]
  3040. }, responsiveProps, {
  3041. "aspectRatio": aspectRatio.value,
  3042. "aria-label": props.alt,
  3043. "role": props.alt ? 'img' : undefined
  3044. }), {
  3045. 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)]),
  3046. default: slots.default
  3047. }), [[vue.resolveDirective("intersect"), {
  3048. handler: init,
  3049. options: props.options
  3050. }, null, {
  3051. once: true
  3052. }]]);
  3053. });
  3054. return {
  3055. currentSrc,
  3056. image,
  3057. state,
  3058. naturalWidth,
  3059. naturalHeight
  3060. };
  3061. }
  3062. });
  3063. // Utilities
  3064. // Types
  3065. // Composables
  3066. const makeBorderProps = propsFactory({
  3067. border: [Boolean, Number, String]
  3068. }, 'border');
  3069. function useBorder(props) {
  3070. let name = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : getCurrentInstanceName();
  3071. const borderClasses = vue.computed(() => {
  3072. const border = vue.isRef(props) ? props.value : props.border;
  3073. const classes = [];
  3074. if (border === true || border === '') {
  3075. classes.push(`${name}--border`);
  3076. } else if (typeof border === 'string' || border === 0) {
  3077. for (const value of String(border).split(' ')) {
  3078. classes.push(`border-${value}`);
  3079. }
  3080. }
  3081. return classes;
  3082. });
  3083. return {
  3084. borderClasses
  3085. };
  3086. }
  3087. // Utilities
  3088. // Types
  3089. // Composables
  3090. function useColor(colors) {
  3091. return destructComputed(() => {
  3092. const classes = [];
  3093. const styles = {};
  3094. if (colors.value.background) {
  3095. if (isCssColor(colors.value.background)) {
  3096. styles.backgroundColor = colors.value.background;
  3097. } else {
  3098. classes.push(`bg-${colors.value.background}`);
  3099. }
  3100. }
  3101. if (colors.value.text) {
  3102. if (isCssColor(colors.value.text)) {
  3103. styles.color = colors.value.text;
  3104. styles.caretColor = colors.value.text;
  3105. } else {
  3106. classes.push(`text-${colors.value.text}`);
  3107. }
  3108. }
  3109. return {
  3110. colorClasses: classes,
  3111. colorStyles: styles
  3112. };
  3113. });
  3114. }
  3115. function useTextColor(props, name) {
  3116. const colors = vue.computed(() => ({
  3117. text: vue.isRef(props) ? props.value : name ? props[name] : null
  3118. }));
  3119. const {
  3120. colorClasses: textColorClasses,
  3121. colorStyles: textColorStyles
  3122. } = useColor(colors);
  3123. return {
  3124. textColorClasses,
  3125. textColorStyles
  3126. };
  3127. }
  3128. function useBackgroundColor(props, name) {
  3129. const colors = vue.computed(() => ({
  3130. background: vue.isRef(props) ? props.value : name ? props[name] : null
  3131. }));
  3132. const {
  3133. colorClasses: backgroundColorClasses,
  3134. colorStyles: backgroundColorStyles
  3135. } = useColor(colors);
  3136. return {
  3137. backgroundColorClasses,
  3138. backgroundColorStyles
  3139. };
  3140. }
  3141. // Utilities
  3142. // Types
  3143. // Composables
  3144. const makeElevationProps = propsFactory({
  3145. elevation: {
  3146. type: [Number, String],
  3147. validator(v) {
  3148. const value = parseInt(v);
  3149. return !isNaN(value) && value >= 0 &&
  3150. // Material Design has a maximum elevation of 24
  3151. // https://material.io/design/environment/elevation.html#default-elevations
  3152. value <= 24;
  3153. }
  3154. }
  3155. }, 'elevation');
  3156. function useElevation(props) {
  3157. const elevationClasses = vue.computed(() => {
  3158. const elevation = vue.isRef(props) ? props.value : props.elevation;
  3159. const classes = [];
  3160. if (elevation == null) return classes;
  3161. classes.push(`elevation-${elevation}`);
  3162. return classes;
  3163. });
  3164. return {
  3165. elevationClasses
  3166. };
  3167. }
  3168. // Utilities
  3169. // Types
  3170. // Composables
  3171. const makeRoundedProps = propsFactory({
  3172. rounded: {
  3173. type: [Boolean, Number, String],
  3174. default: undefined
  3175. }
  3176. }, 'rounded');
  3177. function useRounded(props) {
  3178. let name = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : getCurrentInstanceName();
  3179. const roundedClasses = vue.computed(() => {
  3180. const rounded = vue.isRef(props) ? props.value : props.rounded;
  3181. const classes = [];
  3182. if (rounded === true || rounded === '') {
  3183. classes.push(`${name}--rounded`);
  3184. } else if (typeof rounded === 'string' || rounded === 0) {
  3185. for (const value of String(rounded).split(' ')) {
  3186. classes.push(`rounded-${value}`);
  3187. }
  3188. }
  3189. return classes;
  3190. });
  3191. return {
  3192. roundedClasses
  3193. };
  3194. }
  3195. // Types
  3196. const allowedDensities$1 = [null, 'prominent', 'default', 'comfortable', 'compact'];
  3197. const makeVToolbarProps = propsFactory({
  3198. absolute: Boolean,
  3199. collapse: Boolean,
  3200. color: String,
  3201. density: {
  3202. type: String,
  3203. default: 'default',
  3204. validator: v => allowedDensities$1.includes(v)
  3205. },
  3206. extended: Boolean,
  3207. extensionHeight: {
  3208. type: [Number, String],
  3209. default: 48
  3210. },
  3211. flat: Boolean,
  3212. floating: Boolean,
  3213. height: {
  3214. type: [Number, String],
  3215. default: 64
  3216. },
  3217. image: String,
  3218. title: String,
  3219. ...makeBorderProps(),
  3220. ...makeComponentProps(),
  3221. ...makeElevationProps(),
  3222. ...makeRoundedProps(),
  3223. ...makeTagProps({
  3224. tag: 'header'
  3225. }),
  3226. ...makeThemeProps()
  3227. }, 'VToolbar');
  3228. const VToolbar = genericComponent()({
  3229. name: 'VToolbar',
  3230. props: makeVToolbarProps(),
  3231. setup(props, _ref) {
  3232. let {
  3233. slots
  3234. } = _ref;
  3235. const {
  3236. backgroundColorClasses,
  3237. backgroundColorStyles
  3238. } = useBackgroundColor(vue.toRef(props, 'color'));
  3239. const {
  3240. borderClasses
  3241. } = useBorder(props);
  3242. const {
  3243. elevationClasses
  3244. } = useElevation(props);
  3245. const {
  3246. roundedClasses
  3247. } = useRounded(props);
  3248. const {
  3249. themeClasses
  3250. } = provideTheme(props);
  3251. const {
  3252. rtlClasses
  3253. } = useRtl();
  3254. const isExtended = vue.shallowRef(!!(props.extended || slots.extension?.()));
  3255. 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));
  3256. 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);
  3257. provideDefaults({
  3258. VBtn: {
  3259. variant: 'text'
  3260. }
  3261. });
  3262. useRender(() => {
  3263. const hasTitle = !!(props.title || slots.title);
  3264. const hasImage = !!(slots.image || props.image);
  3265. const extension = slots.extension?.();
  3266. isExtended.value = !!(props.extended || extension);
  3267. return vue.createVNode(props.tag, {
  3268. "class": ['v-toolbar', {
  3269. 'v-toolbar--absolute': props.absolute,
  3270. 'v-toolbar--collapse': props.collapse,
  3271. 'v-toolbar--flat': props.flat,
  3272. 'v-toolbar--floating': props.floating,
  3273. [`v-toolbar--density-${props.density}`]: true
  3274. }, backgroundColorClasses.value, borderClasses.value, elevationClasses.value, roundedClasses.value, themeClasses.value, rtlClasses.value, props.class],
  3275. "style": [backgroundColorStyles.value, props.style]
  3276. }, {
  3277. default: () => [hasImage && vue.createVNode("div", {
  3278. "key": "image",
  3279. "class": "v-toolbar__image"
  3280. }, [!slots.image ? vue.createVNode(VImg, {
  3281. "key": "image-img",
  3282. "cover": true,
  3283. "src": props.image
  3284. }, null) : vue.createVNode(VDefaultsProvider, {
  3285. "key": "image-defaults",
  3286. "disabled": !props.image,
  3287. "defaults": {
  3288. VImg: {
  3289. cover: true,
  3290. src: props.image
  3291. }
  3292. }
  3293. }, slots.image)]), vue.createVNode(VDefaultsProvider, {
  3294. "defaults": {
  3295. VTabs: {
  3296. height: convertToUnit(contentHeight.value)
  3297. }
  3298. }
  3299. }, {
  3300. default: () => [vue.createVNode("div", {
  3301. "class": "v-toolbar__content",
  3302. "style": {
  3303. height: convertToUnit(contentHeight.value)
  3304. }
  3305. }, [slots.prepend && vue.createVNode("div", {
  3306. "class": "v-toolbar__prepend"
  3307. }, [slots.prepend?.()]), hasTitle && vue.createVNode(VToolbarTitle, {
  3308. "key": "title",
  3309. "text": props.title
  3310. }, {
  3311. text: slots.title
  3312. }), slots.default?.(), slots.append && vue.createVNode("div", {
  3313. "class": "v-toolbar__append"
  3314. }, [slots.append?.()])])]
  3315. }), vue.createVNode(VDefaultsProvider, {
  3316. "defaults": {
  3317. VTabs: {
  3318. height: convertToUnit(extensionHeight.value)
  3319. }
  3320. }
  3321. }, {
  3322. default: () => [vue.createVNode(VExpandTransition, null, {
  3323. default: () => [isExtended.value && vue.createVNode("div", {
  3324. "class": "v-toolbar__extension",
  3325. "style": {
  3326. height: convertToUnit(extensionHeight.value)
  3327. }
  3328. }, [extension])]
  3329. })]
  3330. })]
  3331. });
  3332. });
  3333. return {
  3334. contentHeight,
  3335. extensionHeight
  3336. };
  3337. }
  3338. });
  3339. // Utilities
  3340. // Types
  3341. // Composables
  3342. const makeScrollProps = propsFactory({
  3343. scrollTarget: {
  3344. type: String
  3345. },
  3346. scrollThreshold: {
  3347. type: [String, Number],
  3348. default: 300
  3349. }
  3350. }, 'scroll');
  3351. function useScroll(props) {
  3352. let args = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
  3353. const {
  3354. canScroll
  3355. } = args;
  3356. let previousScroll = 0;
  3357. const target = vue.ref(null);
  3358. const currentScroll = vue.shallowRef(0);
  3359. const savedScroll = vue.shallowRef(0);
  3360. const currentThreshold = vue.shallowRef(0);
  3361. const isScrollActive = vue.shallowRef(false);
  3362. const isScrollingUp = vue.shallowRef(false);
  3363. const scrollThreshold = vue.computed(() => {
  3364. return Number(props.scrollThreshold);
  3365. });
  3366. /**
  3367. * 1: at top
  3368. * 0: at threshold
  3369. */
  3370. const scrollRatio = vue.computed(() => {
  3371. return clamp((scrollThreshold.value - currentScroll.value) / scrollThreshold.value || 0);
  3372. });
  3373. const onScroll = () => {
  3374. const targetEl = target.value;
  3375. if (!targetEl || canScroll && !canScroll.value) return;
  3376. previousScroll = currentScroll.value;
  3377. currentScroll.value = 'window' in targetEl ? targetEl.pageYOffset : targetEl.scrollTop;
  3378. isScrollingUp.value = currentScroll.value < previousScroll;
  3379. currentThreshold.value = Math.abs(currentScroll.value - scrollThreshold.value);
  3380. };
  3381. vue.watch(isScrollingUp, () => {
  3382. savedScroll.value = savedScroll.value || currentScroll.value;
  3383. });
  3384. vue.watch(isScrollActive, () => {
  3385. savedScroll.value = 0;
  3386. });
  3387. vue.onMounted(() => {
  3388. vue.watch(() => props.scrollTarget, scrollTarget => {
  3389. const newTarget = scrollTarget ? document.querySelector(scrollTarget) : window;
  3390. if (!newTarget) {
  3391. consoleWarn(`Unable to locate element with identifier ${scrollTarget}`);
  3392. return;
  3393. }
  3394. if (newTarget === target.value) return;
  3395. target.value?.removeEventListener('scroll', onScroll);
  3396. target.value = newTarget;
  3397. target.value.addEventListener('scroll', onScroll, {
  3398. passive: true
  3399. });
  3400. }, {
  3401. immediate: true
  3402. });
  3403. });
  3404. vue.onBeforeUnmount(() => {
  3405. target.value?.removeEventListener('scroll', onScroll);
  3406. });
  3407. // Do we need this? If yes - seems that
  3408. // there's no need to expose onScroll
  3409. canScroll && vue.watch(canScroll, onScroll, {
  3410. immediate: true
  3411. });
  3412. return {
  3413. scrollThreshold,
  3414. currentScroll,
  3415. currentThreshold,
  3416. isScrollActive,
  3417. scrollRatio,
  3418. // required only for testing
  3419. // probably can be removed
  3420. // later (2 chars chlng)
  3421. isScrollingUp,
  3422. savedScroll
  3423. };
  3424. }
  3425. // Utilities
  3426. // Composables
  3427. function useSsrBoot() {
  3428. const isBooted = vue.shallowRef(false);
  3429. vue.onMounted(() => {
  3430. window.requestAnimationFrame(() => {
  3431. isBooted.value = true;
  3432. });
  3433. });
  3434. const ssrBootStyles = vue.computed(() => !isBooted.value ? {
  3435. transition: 'none !important'
  3436. } : undefined);
  3437. return {
  3438. ssrBootStyles,
  3439. isBooted: vue.readonly(isBooted)
  3440. };
  3441. }
  3442. // Types
  3443. const makeVAppBarProps = propsFactory({
  3444. scrollBehavior: String,
  3445. modelValue: {
  3446. type: Boolean,
  3447. default: true
  3448. },
  3449. location: {
  3450. type: String,
  3451. default: 'top',
  3452. validator: value => ['top', 'bottom'].includes(value)
  3453. },
  3454. ...makeVToolbarProps(),
  3455. ...makeLayoutItemProps(),
  3456. ...makeScrollProps(),
  3457. height: {
  3458. type: [Number, String],
  3459. default: 64
  3460. }
  3461. }, 'VAppBar');
  3462. const VAppBar = genericComponent()({
  3463. name: 'VAppBar',
  3464. props: makeVAppBarProps(),
  3465. emits: {
  3466. 'update:modelValue': value => true
  3467. },
  3468. setup(props, _ref) {
  3469. let {
  3470. slots
  3471. } = _ref;
  3472. const vToolbarRef = vue.ref();
  3473. const isActive = useProxiedModel(props, 'modelValue');
  3474. const scrollBehavior = vue.computed(() => {
  3475. const behavior = new Set(props.scrollBehavior?.split(' ') ?? []);
  3476. return {
  3477. hide: behavior.has('hide'),
  3478. // fullyHide: behavior.has('fully-hide'),
  3479. inverted: behavior.has('inverted'),
  3480. collapse: behavior.has('collapse'),
  3481. elevate: behavior.has('elevate'),
  3482. fadeImage: behavior.has('fade-image')
  3483. // shrink: behavior.has('shrink'),
  3484. };
  3485. });
  3486. const canScroll = vue.computed(() => {
  3487. const behavior = scrollBehavior.value;
  3488. return behavior.hide ||
  3489. // behavior.fullyHide ||
  3490. behavior.inverted || behavior.collapse || behavior.elevate || behavior.fadeImage ||
  3491. // behavior.shrink ||
  3492. !isActive.value;
  3493. });
  3494. const {
  3495. currentScroll,
  3496. scrollThreshold,
  3497. isScrollingUp,
  3498. scrollRatio
  3499. } = useScroll(props, {
  3500. canScroll
  3501. });
  3502. const isCollapsed = vue.computed(() => props.collapse || scrollBehavior.value.collapse && (scrollBehavior.value.inverted ? scrollRatio.value > 0 : scrollRatio.value === 0));
  3503. const isFlat = vue.computed(() => props.flat || scrollBehavior.value.elevate && (scrollBehavior.value.inverted ? currentScroll.value > 0 : currentScroll.value === 0));
  3504. const opacity = vue.computed(() => scrollBehavior.value.fadeImage ? scrollBehavior.value.inverted ? 1 - scrollRatio.value : scrollRatio.value : undefined);
  3505. const height = vue.computed(() => {
  3506. if (scrollBehavior.value.hide && scrollBehavior.value.inverted) return 0;
  3507. const height = vToolbarRef.value?.contentHeight ?? 0;
  3508. const extensionHeight = vToolbarRef.value?.extensionHeight ?? 0;
  3509. return height + extensionHeight;
  3510. });
  3511. useToggleScope(vue.computed(() => !!props.scrollBehavior), () => {
  3512. vue.watchEffect(() => {
  3513. if (scrollBehavior.value.hide) {
  3514. if (scrollBehavior.value.inverted) {
  3515. isActive.value = currentScroll.value > scrollThreshold.value;
  3516. } else {
  3517. isActive.value = isScrollingUp.value || currentScroll.value < scrollThreshold.value;
  3518. }
  3519. } else {
  3520. isActive.value = true;
  3521. }
  3522. });
  3523. });
  3524. const {
  3525. ssrBootStyles
  3526. } = useSsrBoot();
  3527. const {
  3528. layoutItemStyles
  3529. } = useLayoutItem({
  3530. id: props.name,
  3531. order: vue.computed(() => parseInt(props.order, 10)),
  3532. position: vue.toRef(props, 'location'),
  3533. layoutSize: height,
  3534. elementSize: vue.shallowRef(undefined),
  3535. active: isActive,
  3536. absolute: vue.toRef(props, 'absolute')
  3537. });
  3538. useRender(() => {
  3539. const [toolbarProps] = VToolbar.filterProps(props);
  3540. return vue.createVNode(VToolbar, vue.mergeProps({
  3541. "ref": vToolbarRef,
  3542. "class": ['v-app-bar', {
  3543. 'v-app-bar--bottom': props.location === 'bottom'
  3544. }, props.class],
  3545. "style": [{
  3546. ...layoutItemStyles.value,
  3547. '--v-toolbar-image-opacity': opacity.value,
  3548. height: undefined,
  3549. ...ssrBootStyles.value
  3550. }, props.style]
  3551. }, toolbarProps, {
  3552. "collapse": isCollapsed.value,
  3553. "flat": isFlat.value
  3554. }), slots);
  3555. });
  3556. return {};
  3557. }
  3558. });
  3559. // Utilities
  3560. // Types
  3561. const allowedDensities = [null, 'default', 'comfortable', 'compact'];
  3562. // typeof allowedDensities[number] evalutes to any
  3563. // when generating api types for whatever reason.
  3564. // Composables
  3565. const makeDensityProps = propsFactory({
  3566. density: {
  3567. type: String,
  3568. default: 'default',
  3569. validator: v => allowedDensities.includes(v)
  3570. }
  3571. }, 'density');
  3572. function useDensity(props) {
  3573. let name = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : getCurrentInstanceName();
  3574. const densityClasses = vue.computed(() => {
  3575. return `${name}--density-${props.density}`;
  3576. });
  3577. return {
  3578. densityClasses
  3579. };
  3580. }
  3581. // Types
  3582. const allowedVariants$2 = ['elevated', 'flat', 'tonal', 'outlined', 'text', 'plain'];
  3583. function genOverlays(isClickable, name) {
  3584. return vue.createVNode(vue.Fragment, null, [isClickable && vue.createVNode("span", {
  3585. "key": "overlay",
  3586. "class": `${name}__overlay`
  3587. }, null), vue.createVNode("span", {
  3588. "key": "underlay",
  3589. "class": `${name}__underlay`
  3590. }, null)]);
  3591. }
  3592. const makeVariantProps = propsFactory({
  3593. color: String,
  3594. variant: {
  3595. type: String,
  3596. default: 'elevated',
  3597. validator: v => allowedVariants$2.includes(v)
  3598. }
  3599. }, 'variant');
  3600. function useVariant(props) {
  3601. let name = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : getCurrentInstanceName();
  3602. const variantClasses = vue.computed(() => {
  3603. const {
  3604. variant
  3605. } = vue.unref(props);
  3606. return `${name}--variant-${variant}`;
  3607. });
  3608. const {
  3609. colorClasses,
  3610. colorStyles
  3611. } = useColor(vue.computed(() => {
  3612. const {
  3613. variant,
  3614. color
  3615. } = vue.unref(props);
  3616. return {
  3617. [['elevated', 'flat'].includes(variant) ? 'background' : 'text']: color
  3618. };
  3619. }));
  3620. return {
  3621. colorClasses,
  3622. colorStyles,
  3623. variantClasses
  3624. };
  3625. }
  3626. const makeVBtnGroupProps = propsFactory({
  3627. divided: Boolean,
  3628. ...makeBorderProps(),
  3629. ...makeComponentProps(),
  3630. ...makeDensityProps(),
  3631. ...makeElevationProps(),
  3632. ...makeRoundedProps(),
  3633. ...makeTagProps(),
  3634. ...makeThemeProps(),
  3635. ...makeVariantProps()
  3636. }, 'VBtnGroup');
  3637. const VBtnGroup = genericComponent()({
  3638. name: 'VBtnGroup',
  3639. props: makeVBtnGroupProps(),
  3640. setup(props, _ref) {
  3641. let {
  3642. slots
  3643. } = _ref;
  3644. const {
  3645. themeClasses
  3646. } = provideTheme(props);
  3647. const {
  3648. densityClasses
  3649. } = useDensity(props);
  3650. const {
  3651. borderClasses
  3652. } = useBorder(props);
  3653. const {
  3654. elevationClasses
  3655. } = useElevation(props);
  3656. const {
  3657. roundedClasses
  3658. } = useRounded(props);
  3659. provideDefaults({
  3660. VBtn: {
  3661. height: 'auto',
  3662. color: vue.toRef(props, 'color'),
  3663. density: vue.toRef(props, 'density'),
  3664. flat: true,
  3665. variant: vue.toRef(props, 'variant')
  3666. }
  3667. });
  3668. useRender(() => {
  3669. return vue.createVNode(props.tag, {
  3670. "class": ['v-btn-group', {
  3671. 'v-btn-group--divided': props.divided
  3672. }, themeClasses.value, borderClasses.value, densityClasses.value, elevationClasses.value, roundedClasses.value, props.class],
  3673. "style": props.style
  3674. }, slots);
  3675. });
  3676. }
  3677. });
  3678. // Composables
  3679. // Types
  3680. const makeGroupProps = propsFactory({
  3681. modelValue: {
  3682. type: null,
  3683. default: undefined
  3684. },
  3685. multiple: Boolean,
  3686. mandatory: [Boolean, String],
  3687. max: Number,
  3688. selectedClass: String,
  3689. disabled: Boolean
  3690. }, 'group');
  3691. const makeGroupItemProps = propsFactory({
  3692. value: null,
  3693. disabled: Boolean,
  3694. selectedClass: String
  3695. }, 'group-item');
  3696. function useGroupItem(props, injectKey) {
  3697. let required = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : true;
  3698. const vm = getCurrentInstance('useGroupItem');
  3699. if (!vm) {
  3700. throw new Error('[Vuetify] useGroupItem composable must be used inside a component setup function');
  3701. }
  3702. const id = getUid();
  3703. vue.provide(Symbol.for(`${injectKey.description}:id`), id);
  3704. const group = vue.inject(injectKey, null);
  3705. if (!group) {
  3706. if (!required) return group;
  3707. throw new Error(`[Vuetify] Could not find useGroup injection with symbol ${injectKey.description}`);
  3708. }
  3709. const value = vue.toRef(props, 'value');
  3710. const disabled = vue.computed(() => !!(group.disabled.value || props.disabled));
  3711. group.register({
  3712. id,
  3713. value,
  3714. disabled
  3715. }, vm);
  3716. vue.onBeforeUnmount(() => {
  3717. group.unregister(id);
  3718. });
  3719. const isSelected = vue.computed(() => {
  3720. return group.isSelected(id);
  3721. });
  3722. const selectedClass = vue.computed(() => isSelected.value && [group.selectedClass.value, props.selectedClass]);
  3723. vue.watch(isSelected, value => {
  3724. vm.emit('group:selected', {
  3725. value
  3726. });
  3727. });
  3728. return {
  3729. id,
  3730. isSelected,
  3731. toggle: () => group.select(id, !isSelected.value),
  3732. select: value => group.select(id, value),
  3733. selectedClass,
  3734. value,
  3735. disabled,
  3736. group
  3737. };
  3738. }
  3739. function useGroup(props, injectKey) {
  3740. let isUnmounted = false;
  3741. const items = vue.reactive([]);
  3742. const selected = useProxiedModel(props, 'modelValue', [], v => {
  3743. if (v == null) return [];
  3744. return getIds(items, wrapInArray(v));
  3745. }, v => {
  3746. const arr = getValues(items, v);
  3747. return props.multiple ? arr : arr[0];
  3748. });
  3749. const groupVm = getCurrentInstance('useGroup');
  3750. function register(item, vm) {
  3751. // Is there a better way to fix this typing?
  3752. const unwrapped = item;
  3753. const key = Symbol.for(`${injectKey.description}:id`);
  3754. const children = findChildrenWithProvide(key, groupVm?.vnode);
  3755. const index = children.indexOf(vm);
  3756. if (index > -1) {
  3757. items.splice(index, 0, unwrapped);
  3758. } else {
  3759. items.push(unwrapped);
  3760. }
  3761. }
  3762. function unregister(id) {
  3763. if (isUnmounted) return;
  3764. // TODO: re-evaluate this line's importance in the future
  3765. // should we only modify the model if mandatory is set.
  3766. // selected.value = selected.value.filter(v => v !== id)
  3767. forceMandatoryValue();
  3768. const index = items.findIndex(item => item.id === id);
  3769. items.splice(index, 1);
  3770. }
  3771. // If mandatory and nothing is selected, then select first non-disabled item
  3772. function forceMandatoryValue() {
  3773. const item = items.find(item => !item.disabled);
  3774. if (item && props.mandatory === 'force' && !selected.value.length) {
  3775. selected.value = [item.id];
  3776. }
  3777. }
  3778. vue.onMounted(() => {
  3779. forceMandatoryValue();
  3780. });
  3781. vue.onBeforeUnmount(() => {
  3782. isUnmounted = true;
  3783. });
  3784. function select(id, value) {
  3785. const item = items.find(item => item.id === id);
  3786. if (value && item?.disabled) return;
  3787. if (props.multiple) {
  3788. const internalValue = selected.value.slice();
  3789. const index = internalValue.findIndex(v => v === id);
  3790. const isSelected = ~index;
  3791. value = value ?? !isSelected;
  3792. // We can't remove value if group is
  3793. // mandatory, value already exists,
  3794. // and it is the only value
  3795. if (isSelected && props.mandatory && internalValue.length <= 1) return;
  3796. // We can't add value if it would
  3797. // cause max limit to be exceeded
  3798. if (!isSelected && props.max != null && internalValue.length + 1 > props.max) return;
  3799. if (index < 0 && value) internalValue.push(id);else if (index >= 0 && !value) internalValue.splice(index, 1);
  3800. selected.value = internalValue;
  3801. } else {
  3802. const isSelected = selected.value.includes(id);
  3803. if (props.mandatory && isSelected) return;
  3804. selected.value = value ?? !isSelected ? [id] : [];
  3805. }
  3806. }
  3807. function step(offset) {
  3808. // getting an offset from selected value obviously won't work with multiple values
  3809. if (props.multiple) consoleWarn('This method is not supported when using "multiple" prop');
  3810. if (!selected.value.length) {
  3811. const item = items.find(item => !item.disabled);
  3812. item && (selected.value = [item.id]);
  3813. } else {
  3814. const currentId = selected.value[0];
  3815. const currentIndex = items.findIndex(i => i.id === currentId);
  3816. let newIndex = (currentIndex + offset) % items.length;
  3817. let newItem = items[newIndex];
  3818. while (newItem.disabled && newIndex !== currentIndex) {
  3819. newIndex = (newIndex + offset) % items.length;
  3820. newItem = items[newIndex];
  3821. }
  3822. if (newItem.disabled) return;
  3823. selected.value = [items[newIndex].id];
  3824. }
  3825. }
  3826. const state = {
  3827. register,
  3828. unregister,
  3829. selected,
  3830. select,
  3831. disabled: vue.toRef(props, 'disabled'),
  3832. prev: () => step(items.length - 1),
  3833. next: () => step(1),
  3834. isSelected: id => selected.value.includes(id),
  3835. selectedClass: vue.computed(() => props.selectedClass),
  3836. items: vue.computed(() => items),
  3837. getItemIndex: value => getItemIndex(items, value)
  3838. };
  3839. vue.provide(injectKey, state);
  3840. return state;
  3841. }
  3842. function getItemIndex(items, value) {
  3843. const ids = getIds(items, [value]);
  3844. if (!ids.length) return -1;
  3845. return items.findIndex(item => item.id === ids[0]);
  3846. }
  3847. function getIds(items, modelValue) {
  3848. const ids = [];
  3849. modelValue.forEach(value => {
  3850. const item = items.find(item => deepEqual(value, item.value));
  3851. const itemByIndex = items[value];
  3852. if (item?.value != null) {
  3853. ids.push(item.id);
  3854. } else if (itemByIndex != null) {
  3855. ids.push(itemByIndex.id);
  3856. }
  3857. });
  3858. return ids;
  3859. }
  3860. function getValues(items, ids) {
  3861. const values = [];
  3862. ids.forEach(id => {
  3863. const itemIndex = items.findIndex(item => item.id === id);
  3864. if (~itemIndex) {
  3865. const item = items[itemIndex];
  3866. values.push(item.value != null ? item.value : itemIndex);
  3867. }
  3868. });
  3869. return values;
  3870. }
  3871. // Types
  3872. const VBtnToggleSymbol = Symbol.for('vuetify:v-btn-toggle');
  3873. const makeVBtnToggleProps = propsFactory({
  3874. ...makeVBtnGroupProps(),
  3875. ...makeGroupProps()
  3876. }, 'VBtnToggle');
  3877. const VBtnToggle = genericComponent()({
  3878. name: 'VBtnToggle',
  3879. props: makeVBtnToggleProps(),
  3880. emits: {
  3881. 'update:modelValue': value => true
  3882. },
  3883. setup(props, _ref) {
  3884. let {
  3885. slots
  3886. } = _ref;
  3887. const {
  3888. isSelected,
  3889. next,
  3890. prev,
  3891. select,
  3892. selected
  3893. } = useGroup(props, VBtnToggleSymbol);
  3894. useRender(() => {
  3895. const [btnGroupProps] = VBtnGroup.filterProps(props);
  3896. return vue.createVNode(VBtnGroup, vue.mergeProps({
  3897. "class": ['v-btn-toggle', props.class]
  3898. }, btnGroupProps, {
  3899. "style": props.style
  3900. }), {
  3901. default: () => [slots.default?.({
  3902. isSelected,
  3903. next,
  3904. prev,
  3905. select,
  3906. selected
  3907. })]
  3908. });
  3909. });
  3910. return {
  3911. next,
  3912. prev,
  3913. select
  3914. };
  3915. }
  3916. });
  3917. // Composables
  3918. // Types
  3919. const aliases = {
  3920. collapse: 'mdi-chevron-up',
  3921. complete: 'mdi-check',
  3922. cancel: 'mdi-close-circle',
  3923. close: 'mdi-close',
  3924. delete: 'mdi-close-circle',
  3925. // delete (e.g. v-chip close)
  3926. clear: 'mdi-close-circle',
  3927. success: 'mdi-check-circle',
  3928. info: 'mdi-information',
  3929. warning: 'mdi-alert-circle',
  3930. error: 'mdi-close-circle',
  3931. prev: 'mdi-chevron-left',
  3932. next: 'mdi-chevron-right',
  3933. checkboxOn: 'mdi-checkbox-marked',
  3934. checkboxOff: 'mdi-checkbox-blank-outline',
  3935. checkboxIndeterminate: 'mdi-minus-box',
  3936. delimiter: 'mdi-circle',
  3937. // for carousel
  3938. sortAsc: 'mdi-arrow-up',
  3939. sortDesc: 'mdi-arrow-down',
  3940. expand: 'mdi-chevron-down',
  3941. menu: 'mdi-menu',
  3942. subgroup: 'mdi-menu-down',
  3943. dropdown: 'mdi-menu-down',
  3944. radioOn: 'mdi-radiobox-marked',
  3945. radioOff: 'mdi-radiobox-blank',
  3946. edit: 'mdi-pencil',
  3947. ratingEmpty: 'mdi-star-outline',
  3948. ratingFull: 'mdi-star',
  3949. ratingHalf: 'mdi-star-half-full',
  3950. loading: 'mdi-cached',
  3951. first: 'mdi-page-first',
  3952. last: 'mdi-page-last',
  3953. unfold: 'mdi-unfold-more-horizontal',
  3954. file: 'mdi-paperclip',
  3955. plus: 'mdi-plus',
  3956. minus: 'mdi-minus',
  3957. calendar: 'mdi-calendar'
  3958. };
  3959. const mdi = {
  3960. // Not using mergeProps here, functional components merge props by default (?)
  3961. component: props => vue.h(VClassIcon, {
  3962. ...props,
  3963. class: 'mdi'
  3964. })
  3965. };
  3966. // Types
  3967. const IconValue = [String, Function, Object, Array];
  3968. const IconSymbol = Symbol.for('vuetify:icons');
  3969. const makeIconProps = propsFactory({
  3970. icon: {
  3971. type: IconValue
  3972. },
  3973. // Could not remove this and use makeTagProps, types complained because it is not required
  3974. tag: {
  3975. type: String,
  3976. required: true
  3977. }
  3978. }, 'icon');
  3979. const VComponentIcon = genericComponent()({
  3980. name: 'VComponentIcon',
  3981. props: makeIconProps(),
  3982. setup(props, _ref) {
  3983. let {
  3984. slots
  3985. } = _ref;
  3986. return () => {
  3987. const Icon = props.icon;
  3988. return vue.createVNode(props.tag, null, {
  3989. default: () => [props.icon ? vue.createVNode(Icon, null, null) : slots.default?.()]
  3990. });
  3991. };
  3992. }
  3993. });
  3994. const VSvgIcon = defineComponent({
  3995. name: 'VSvgIcon',
  3996. inheritAttrs: false,
  3997. props: makeIconProps(),
  3998. setup(props, _ref2) {
  3999. let {
  4000. attrs
  4001. } = _ref2;
  4002. return () => {
  4003. return vue.createVNode(props.tag, vue.mergeProps(attrs, {
  4004. "style": null
  4005. }), {
  4006. default: () => [vue.createVNode("svg", {
  4007. "class": "v-icon__svg",
  4008. "xmlns": "http://www.w3.org/2000/svg",
  4009. "viewBox": "0 0 24 24",
  4010. "role": "img",
  4011. "aria-hidden": "true"
  4012. }, [Array.isArray(props.icon) ? props.icon.map(path => Array.isArray(path) ? vue.createVNode("path", {
  4013. "d": path[0],
  4014. "fill-opacity": path[1]
  4015. }, null) : vue.createVNode("path", {
  4016. "d": path
  4017. }, null)) : vue.createVNode("path", {
  4018. "d": props.icon
  4019. }, null)])]
  4020. });
  4021. };
  4022. }
  4023. });
  4024. const VLigatureIcon = defineComponent({
  4025. name: 'VLigatureIcon',
  4026. props: makeIconProps(),
  4027. setup(props) {
  4028. return () => {
  4029. return vue.createVNode(props.tag, null, {
  4030. default: () => [props.icon]
  4031. });
  4032. };
  4033. }
  4034. });
  4035. const VClassIcon = defineComponent({
  4036. name: 'VClassIcon',
  4037. props: makeIconProps(),
  4038. setup(props) {
  4039. return () => {
  4040. return vue.createVNode(props.tag, {
  4041. "class": props.icon
  4042. }, null);
  4043. };
  4044. }
  4045. });
  4046. const defaultSets = {
  4047. svg: {
  4048. component: VSvgIcon
  4049. },
  4050. class: {
  4051. component: VClassIcon
  4052. }
  4053. };
  4054. // Composables
  4055. function createIcons(options) {
  4056. return mergeDeep({
  4057. defaultSet: 'mdi',
  4058. sets: {
  4059. ...defaultSets,
  4060. mdi
  4061. },
  4062. aliases: {
  4063. ...aliases,
  4064. /* eslint-disable max-len */
  4065. 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]],
  4066. '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'
  4067. /* eslint-enable max-len */
  4068. }
  4069. }, options);
  4070. }
  4071. const useIcon = props => {
  4072. const icons = vue.inject(IconSymbol);
  4073. if (!icons) throw new Error('Missing Vuetify Icons provide!');
  4074. const iconData = vue.computed(() => {
  4075. const iconAlias = vue.unref(props);
  4076. if (!iconAlias) return {
  4077. component: VComponentIcon
  4078. };
  4079. let icon = iconAlias;
  4080. if (typeof icon === 'string') {
  4081. icon = icon.trim();
  4082. if (icon.startsWith('$')) {
  4083. icon = icons.aliases?.[icon.slice(1)];
  4084. }
  4085. }
  4086. if (!icon) throw new Error(`Could not find aliased icon "${iconAlias}"`);
  4087. if (Array.isArray(icon)) {
  4088. return {
  4089. component: VSvgIcon,
  4090. icon
  4091. };
  4092. } else if (typeof icon !== 'string') {
  4093. return {
  4094. component: VComponentIcon,
  4095. icon
  4096. };
  4097. }
  4098. const iconSetName = Object.keys(icons.sets).find(setName => typeof icon === 'string' && icon.startsWith(`${setName}:`));
  4099. const iconName = iconSetName ? icon.slice(iconSetName.length + 1) : icon;
  4100. const iconSet = icons.sets[iconSetName ?? icons.defaultSet];
  4101. return {
  4102. component: iconSet.component,
  4103. icon: iconName
  4104. };
  4105. });
  4106. return {
  4107. iconData
  4108. };
  4109. };
  4110. // Utilities
  4111. // Types
  4112. const predefinedSizes = ['x-small', 'small', 'default', 'large', 'x-large'];
  4113. // Composables
  4114. const makeSizeProps = propsFactory({
  4115. size: {
  4116. type: [String, Number],
  4117. default: 'default'
  4118. }
  4119. }, 'size');
  4120. function useSize(props) {
  4121. let name = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : getCurrentInstanceName();
  4122. return destructComputed(() => {
  4123. let sizeClasses;
  4124. let sizeStyles;
  4125. if (includes(predefinedSizes, props.size)) {
  4126. sizeClasses = `${name}--size-${props.size}`;
  4127. } else if (props.size) {
  4128. sizeStyles = {
  4129. width: convertToUnit(props.size),
  4130. height: convertToUnit(props.size)
  4131. };
  4132. }
  4133. return {
  4134. sizeClasses,
  4135. sizeStyles
  4136. };
  4137. });
  4138. }
  4139. const makeVIconProps = propsFactory({
  4140. color: String,
  4141. start: Boolean,
  4142. end: Boolean,
  4143. icon: IconValue,
  4144. ...makeComponentProps(),
  4145. ...makeSizeProps(),
  4146. ...makeTagProps({
  4147. tag: 'i'
  4148. }),
  4149. ...makeThemeProps()
  4150. }, 'VIcon');
  4151. const VIcon = genericComponent()({
  4152. name: 'VIcon',
  4153. props: makeVIconProps(),
  4154. setup(props, _ref) {
  4155. let {
  4156. attrs,
  4157. slots
  4158. } = _ref;
  4159. const slotIcon = vue.ref();
  4160. const {
  4161. themeClasses
  4162. } = provideTheme(props);
  4163. const {
  4164. iconData
  4165. } = useIcon(vue.computed(() => slotIcon.value || props.icon));
  4166. const {
  4167. sizeClasses
  4168. } = useSize(props);
  4169. const {
  4170. textColorClasses,
  4171. textColorStyles
  4172. } = useTextColor(vue.toRef(props, 'color'));
  4173. useRender(() => {
  4174. const slotValue = slots.default?.();
  4175. if (slotValue) {
  4176. slotIcon.value = flattenFragments(slotValue).filter(node => node.type === vue.Text && node.children && typeof node.children === 'string')[0]?.children;
  4177. }
  4178. return vue.createVNode(iconData.value.component, {
  4179. "tag": props.tag,
  4180. "icon": iconData.value.icon,
  4181. "class": ['v-icon', 'notranslate', themeClasses.value, sizeClasses.value, textColorClasses.value, {
  4182. 'v-icon--clickable': !!attrs.onClick,
  4183. 'v-icon--start': props.start,
  4184. 'v-icon--end': props.end
  4185. }, props.class],
  4186. "style": [!sizeClasses.value ? {
  4187. fontSize: convertToUnit(props.size),
  4188. height: convertToUnit(props.size),
  4189. width: convertToUnit(props.size)
  4190. } : undefined, textColorStyles.value, props.style],
  4191. "role": attrs.onClick ? 'button' : undefined,
  4192. "aria-hidden": !attrs.onClick
  4193. }, {
  4194. default: () => [slotValue]
  4195. });
  4196. });
  4197. return {};
  4198. }
  4199. });
  4200. // Utilities
  4201. function useIntersectionObserver(callback, options) {
  4202. const intersectionRef = vue.ref();
  4203. const isIntersecting = vue.shallowRef(false);
  4204. if (SUPPORTS_INTERSECTION) {
  4205. const observer = new IntersectionObserver(entries => {
  4206. callback?.(entries, observer);
  4207. isIntersecting.value = !!entries.find(entry => entry.isIntersecting);
  4208. }, options);
  4209. vue.onBeforeUnmount(() => {
  4210. observer.disconnect();
  4211. });
  4212. vue.watch(intersectionRef, (newValue, oldValue) => {
  4213. if (oldValue) {
  4214. observer.unobserve(oldValue);
  4215. isIntersecting.value = false;
  4216. }
  4217. if (newValue) observer.observe(newValue);
  4218. }, {
  4219. flush: 'post'
  4220. });
  4221. }
  4222. return {
  4223. intersectionRef,
  4224. isIntersecting
  4225. };
  4226. }
  4227. // Types
  4228. const makeVProgressCircularProps = propsFactory({
  4229. bgColor: String,
  4230. color: String,
  4231. indeterminate: [Boolean, String],
  4232. modelValue: {
  4233. type: [Number, String],
  4234. default: 0
  4235. },
  4236. rotate: {
  4237. type: [Number, String],
  4238. default: 0
  4239. },
  4240. width: {
  4241. type: [Number, String],
  4242. default: 4
  4243. },
  4244. ...makeComponentProps(),
  4245. ...makeSizeProps(),
  4246. ...makeTagProps({
  4247. tag: 'div'
  4248. }),
  4249. ...makeThemeProps()
  4250. }, 'VProgressCircular');
  4251. const VProgressCircular = genericComponent()({
  4252. name: 'VProgressCircular',
  4253. props: makeVProgressCircularProps(),
  4254. setup(props, _ref) {
  4255. let {
  4256. slots
  4257. } = _ref;
  4258. const MAGIC_RADIUS_CONSTANT = 20;
  4259. const CIRCUMFERENCE = 2 * Math.PI * MAGIC_RADIUS_CONSTANT;
  4260. const root = vue.ref();
  4261. const {
  4262. themeClasses
  4263. } = provideTheme(props);
  4264. const {
  4265. sizeClasses,
  4266. sizeStyles
  4267. } = useSize(props);
  4268. const {
  4269. textColorClasses,
  4270. textColorStyles
  4271. } = useTextColor(vue.toRef(props, 'color'));
  4272. const {
  4273. textColorClasses: underlayColorClasses,
  4274. textColorStyles: underlayColorStyles
  4275. } = useTextColor(vue.toRef(props, 'bgColor'));
  4276. const {
  4277. intersectionRef,
  4278. isIntersecting
  4279. } = useIntersectionObserver();
  4280. const {
  4281. resizeRef,
  4282. contentRect
  4283. } = useResizeObserver();
  4284. const normalizedValue = vue.computed(() => Math.max(0, Math.min(100, parseFloat(props.modelValue))));
  4285. const width = vue.computed(() => Number(props.width));
  4286. const size = vue.computed(() => {
  4287. // Get size from element if size prop value is small, large etc
  4288. return sizeStyles.value ? Number(props.size) : contentRect.value ? contentRect.value.width : Math.max(width.value, 32);
  4289. });
  4290. const diameter = vue.computed(() => MAGIC_RADIUS_CONSTANT / (1 - width.value / size.value) * 2);
  4291. const strokeWidth = vue.computed(() => width.value / size.value * diameter.value);
  4292. const strokeDashOffset = vue.computed(() => convertToUnit((100 - normalizedValue.value) / 100 * CIRCUMFERENCE));
  4293. vue.watchEffect(() => {
  4294. intersectionRef.value = root.value;
  4295. resizeRef.value = root.value;
  4296. });
  4297. useRender(() => vue.createVNode(props.tag, {
  4298. "ref": root,
  4299. "class": ['v-progress-circular', {
  4300. 'v-progress-circular--indeterminate': !!props.indeterminate,
  4301. 'v-progress-circular--visible': isIntersecting.value,
  4302. 'v-progress-circular--disable-shrink': props.indeterminate === 'disable-shrink'
  4303. }, themeClasses.value, sizeClasses.value, textColorClasses.value, props.class],
  4304. "style": [sizeStyles.value, textColorStyles.value, props.style],
  4305. "role": "progressbar",
  4306. "aria-valuemin": "0",
  4307. "aria-valuemax": "100",
  4308. "aria-valuenow": props.indeterminate ? undefined : normalizedValue.value
  4309. }, {
  4310. default: () => [vue.createVNode("svg", {
  4311. "style": {
  4312. transform: `rotate(calc(-90deg + ${Number(props.rotate)}deg))`
  4313. },
  4314. "xmlns": "http://www.w3.org/2000/svg",
  4315. "viewBox": `0 0 ${diameter.value} ${diameter.value}`
  4316. }, [vue.createVNode("circle", {
  4317. "class": ['v-progress-circular__underlay', underlayColorClasses.value],
  4318. "style": underlayColorStyles.value,
  4319. "fill": "transparent",
  4320. "cx": "50%",
  4321. "cy": "50%",
  4322. "r": MAGIC_RADIUS_CONSTANT,
  4323. "stroke-width": strokeWidth.value,
  4324. "stroke-dasharray": CIRCUMFERENCE,
  4325. "stroke-dashoffset": 0
  4326. }, null), vue.createVNode("circle", {
  4327. "class": "v-progress-circular__overlay",
  4328. "fill": "transparent",
  4329. "cx": "50%",
  4330. "cy": "50%",
  4331. "r": MAGIC_RADIUS_CONSTANT,
  4332. "stroke-width": strokeWidth.value,
  4333. "stroke-dasharray": CIRCUMFERENCE,
  4334. "stroke-dashoffset": strokeDashOffset.value
  4335. }, null)]), slots.default && vue.createVNode("div", {
  4336. "class": "v-progress-circular__content"
  4337. }, [slots.default({
  4338. value: normalizedValue.value
  4339. })])]
  4340. }));
  4341. return {};
  4342. }
  4343. });
  4344. // Composables
  4345. // Types
  4346. const oppositeMap = {
  4347. center: 'center',
  4348. top: 'bottom',
  4349. bottom: 'top',
  4350. left: 'right',
  4351. right: 'left'
  4352. };
  4353. const makeLocationProps = propsFactory({
  4354. location: String
  4355. }, 'location');
  4356. function useLocation(props) {
  4357. let opposite = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : false;
  4358. let offset = arguments.length > 2 ? arguments[2] : undefined;
  4359. const {
  4360. isRtl
  4361. } = useRtl();
  4362. const locationStyles = vue.computed(() => {
  4363. if (!props.location) return {};
  4364. const {
  4365. side,
  4366. align
  4367. } = parseAnchor(props.location.split(' ').length > 1 ? props.location : `${props.location} center`, isRtl.value);
  4368. function getOffset(side) {
  4369. return offset ? offset(side) : 0;
  4370. }
  4371. const styles = {};
  4372. if (side !== 'center') {
  4373. if (opposite) styles[oppositeMap[side]] = `calc(100% - ${getOffset(side)}px)`;else styles[side] = 0;
  4374. }
  4375. if (align !== 'center') {
  4376. if (opposite) styles[oppositeMap[align]] = `calc(100% - ${getOffset(align)}px)`;else styles[align] = 0;
  4377. } else {
  4378. if (side === 'center') styles.top = styles.left = '50%';else {
  4379. styles[{
  4380. top: 'left',
  4381. bottom: 'left',
  4382. left: 'top',
  4383. right: 'top'
  4384. }[side]] = '50%';
  4385. }
  4386. styles.transform = {
  4387. top: 'translateX(-50%)',
  4388. bottom: 'translateX(-50%)',
  4389. left: 'translateY(-50%)',
  4390. right: 'translateY(-50%)',
  4391. center: 'translate(-50%, -50%)'
  4392. }[side];
  4393. }
  4394. return styles;
  4395. });
  4396. return {
  4397. locationStyles
  4398. };
  4399. }
  4400. const makeVProgressLinearProps = propsFactory({
  4401. absolute: Boolean,
  4402. active: {
  4403. type: Boolean,
  4404. default: true
  4405. },
  4406. bgColor: String,
  4407. bgOpacity: [Number, String],
  4408. bufferValue: {
  4409. type: [Number, String],
  4410. default: 0
  4411. },
  4412. clickable: Boolean,
  4413. color: String,
  4414. height: {
  4415. type: [Number, String],
  4416. default: 4
  4417. },
  4418. indeterminate: Boolean,
  4419. max: {
  4420. type: [Number, String],
  4421. default: 100
  4422. },
  4423. modelValue: {
  4424. type: [Number, String],
  4425. default: 0
  4426. },
  4427. reverse: Boolean,
  4428. stream: Boolean,
  4429. striped: Boolean,
  4430. roundedBar: Boolean,
  4431. ...makeComponentProps(),
  4432. ...makeLocationProps({
  4433. location: 'top'
  4434. }),
  4435. ...makeRoundedProps(),
  4436. ...makeTagProps(),
  4437. ...makeThemeProps()
  4438. }, 'VProgressLinear');
  4439. const VProgressLinear = genericComponent()({
  4440. name: 'VProgressLinear',
  4441. props: makeVProgressLinearProps(),
  4442. emits: {
  4443. 'update:modelValue': value => true
  4444. },
  4445. setup(props, _ref) {
  4446. let {
  4447. slots
  4448. } = _ref;
  4449. const progress = useProxiedModel(props, 'modelValue');
  4450. const {
  4451. isRtl,
  4452. rtlClasses
  4453. } = useRtl();
  4454. const {
  4455. themeClasses
  4456. } = provideTheme(props);
  4457. const {
  4458. locationStyles
  4459. } = useLocation(props);
  4460. const {
  4461. textColorClasses,
  4462. textColorStyles
  4463. } = useTextColor(props, 'color');
  4464. const {
  4465. backgroundColorClasses,
  4466. backgroundColorStyles
  4467. } = useBackgroundColor(vue.computed(() => props.bgColor || props.color));
  4468. const {
  4469. backgroundColorClasses: barColorClasses,
  4470. backgroundColorStyles: barColorStyles
  4471. } = useBackgroundColor(props, 'color');
  4472. const {
  4473. roundedClasses
  4474. } = useRounded(props);
  4475. const {
  4476. intersectionRef,
  4477. isIntersecting
  4478. } = useIntersectionObserver();
  4479. const max = vue.computed(() => parseInt(props.max, 10));
  4480. const height = vue.computed(() => parseInt(props.height, 10));
  4481. const normalizedBuffer = vue.computed(() => parseFloat(props.bufferValue) / max.value * 100);
  4482. const normalizedValue = vue.computed(() => parseFloat(progress.value) / max.value * 100);
  4483. const isReversed = vue.computed(() => isRtl.value !== props.reverse);
  4484. const transition = vue.computed(() => props.indeterminate ? 'fade-transition' : 'slide-x-transition');
  4485. const opacity = vue.computed(() => {
  4486. return props.bgOpacity == null ? props.bgOpacity : parseFloat(props.bgOpacity);
  4487. });
  4488. function handleClick(e) {
  4489. if (!intersectionRef.value) return;
  4490. const {
  4491. left,
  4492. right,
  4493. width
  4494. } = intersectionRef.value.getBoundingClientRect();
  4495. const value = isReversed.value ? width - e.clientX + (right - width) : e.clientX - left;
  4496. progress.value = Math.round(value / width * max.value);
  4497. }
  4498. useRender(() => vue.createVNode(props.tag, {
  4499. "ref": intersectionRef,
  4500. "class": ['v-progress-linear', {
  4501. 'v-progress-linear--absolute': props.absolute,
  4502. 'v-progress-linear--active': props.active && isIntersecting.value,
  4503. 'v-progress-linear--reverse': isReversed.value,
  4504. 'v-progress-linear--rounded': props.rounded,
  4505. 'v-progress-linear--rounded-bar': props.roundedBar,
  4506. 'v-progress-linear--striped': props.striped
  4507. }, roundedClasses.value, themeClasses.value, rtlClasses.value, props.class],
  4508. "style": [{
  4509. bottom: props.location === 'bottom' ? 0 : undefined,
  4510. top: props.location === 'top' ? 0 : undefined,
  4511. height: props.active ? convertToUnit(height.value) : 0,
  4512. '--v-progress-linear-height': convertToUnit(height.value),
  4513. ...locationStyles.value
  4514. }, props.style],
  4515. "role": "progressbar",
  4516. "aria-hidden": props.active ? 'false' : 'true',
  4517. "aria-valuemin": "0",
  4518. "aria-valuemax": props.max,
  4519. "aria-valuenow": props.indeterminate ? undefined : normalizedValue.value,
  4520. "onClick": props.clickable && handleClick
  4521. }, {
  4522. default: () => [props.stream && vue.createVNode("div", {
  4523. "key": "stream",
  4524. "class": ['v-progress-linear__stream', textColorClasses.value],
  4525. "style": {
  4526. ...textColorStyles.value,
  4527. [isReversed.value ? 'left' : 'right']: convertToUnit(-height.value),
  4528. borderTop: `${convertToUnit(height.value / 2)} dotted`,
  4529. opacity: opacity.value,
  4530. top: `calc(50% - ${convertToUnit(height.value / 4)})`,
  4531. width: convertToUnit(100 - normalizedBuffer.value, '%'),
  4532. '--v-progress-linear-stream-to': convertToUnit(height.value * (isReversed.value ? 1 : -1))
  4533. }
  4534. }, null), vue.createVNode("div", {
  4535. "class": ['v-progress-linear__background', backgroundColorClasses.value],
  4536. "style": [backgroundColorStyles.value, {
  4537. opacity: opacity.value,
  4538. width: convertToUnit(!props.stream ? 100 : normalizedBuffer.value, '%')
  4539. }]
  4540. }, null), vue.createVNode(vue.Transition, {
  4541. "name": transition.value
  4542. }, {
  4543. default: () => [!props.indeterminate ? vue.createVNode("div", {
  4544. "class": ['v-progress-linear__determinate', barColorClasses.value],
  4545. "style": [barColorStyles.value, {
  4546. width: convertToUnit(normalizedValue.value, '%')
  4547. }]
  4548. }, null) : vue.createVNode("div", {
  4549. "class": "v-progress-linear__indeterminate"
  4550. }, [['long', 'short'].map(bar => vue.createVNode("div", {
  4551. "key": bar,
  4552. "class": ['v-progress-linear__indeterminate', bar, barColorClasses.value],
  4553. "style": barColorStyles.value
  4554. }, null))])]
  4555. }), slots.default && vue.createVNode("div", {
  4556. "class": "v-progress-linear__content"
  4557. }, [slots.default({
  4558. value: normalizedValue.value,
  4559. buffer: normalizedBuffer.value
  4560. })])]
  4561. }));
  4562. return {};
  4563. }
  4564. });
  4565. // Types
  4566. // Composables
  4567. const makeLoaderProps = propsFactory({
  4568. loading: [Boolean, String]
  4569. }, 'loader');
  4570. function useLoader(props) {
  4571. let name = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : getCurrentInstanceName();
  4572. const loaderClasses = vue.computed(() => ({
  4573. [`${name}--loading`]: props.loading
  4574. }));
  4575. return {
  4576. loaderClasses
  4577. };
  4578. }
  4579. function LoaderSlot(props, _ref) {
  4580. let {
  4581. slots
  4582. } = _ref;
  4583. return vue.createVNode("div", {
  4584. "class": `${props.name}__loader`
  4585. }, [slots.default?.({
  4586. color: props.color,
  4587. isActive: props.active
  4588. }) || vue.createVNode(VProgressLinear, {
  4589. "active": props.active,
  4590. "color": props.color,
  4591. "height": "2",
  4592. "indeterminate": true
  4593. }, null)]);
  4594. }
  4595. // Utilities
  4596. // Types
  4597. const positionValues = ['static', 'relative', 'fixed', 'absolute', 'sticky'];
  4598. // Composables
  4599. const makePositionProps = propsFactory({
  4600. position: {
  4601. type: String,
  4602. validator: /* istanbul ignore next */v => positionValues.includes(v)
  4603. }
  4604. }, 'position');
  4605. function usePosition(props) {
  4606. let name = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : getCurrentInstanceName();
  4607. const positionClasses = vue.computed(() => {
  4608. return props.position ? `${name}--${props.position}` : undefined;
  4609. });
  4610. return {
  4611. positionClasses
  4612. };
  4613. }
  4614. // Utilities
  4615. function useRouter() {
  4616. return getCurrentInstance('useRouter')?.proxy?.$router;
  4617. }
  4618. function useLink(props, attrs) {
  4619. const RouterLink = vue.resolveDynamicComponent('RouterLink');
  4620. const isLink = vue.computed(() => !!(props.href || props.to));
  4621. const isClickable = vue.computed(() => {
  4622. return isLink?.value || hasEvent(attrs, 'click') || hasEvent(props, 'click');
  4623. });
  4624. if (typeof RouterLink === 'string') {
  4625. return {
  4626. isLink,
  4627. isClickable,
  4628. href: vue.toRef(props, 'href')
  4629. };
  4630. }
  4631. const link = props.to ? RouterLink.useLink(props) : undefined;
  4632. return {
  4633. isLink,
  4634. isClickable,
  4635. route: link?.route,
  4636. navigate: link?.navigate,
  4637. isActive: link && vue.computed(() => props.exact ? link.isExactActive?.value : link.isActive?.value),
  4638. href: vue.computed(() => props.to ? link?.route.value.href : props.href)
  4639. };
  4640. }
  4641. const makeRouterProps = propsFactory({
  4642. href: String,
  4643. replace: Boolean,
  4644. to: [String, Object],
  4645. exact: Boolean
  4646. }, 'router');
  4647. let inTransition = false;
  4648. function useBackButton(router, cb) {
  4649. let popped = false;
  4650. let removeBefore;
  4651. let removeAfter;
  4652. if (IN_BROWSER) {
  4653. vue.nextTick(() => {
  4654. window.addEventListener('popstate', onPopstate);
  4655. removeBefore = router?.beforeEach((to, from, next) => {
  4656. if (!inTransition) {
  4657. setTimeout(() => popped ? cb(next) : next());
  4658. } else {
  4659. popped ? cb(next) : next();
  4660. }
  4661. inTransition = true;
  4662. });
  4663. removeAfter = router?.afterEach(() => {
  4664. inTransition = false;
  4665. });
  4666. });
  4667. vue.onScopeDispose(() => {
  4668. window.removeEventListener('popstate', onPopstate);
  4669. removeBefore?.();
  4670. removeAfter?.();
  4671. });
  4672. }
  4673. function onPopstate(e) {
  4674. if (e.state?.replaced) return;
  4675. popped = true;
  4676. setTimeout(() => popped = false);
  4677. }
  4678. }
  4679. // Utilities
  4680. // Types
  4681. function useSelectLink(link, select) {
  4682. vue.watch(() => link.isActive?.value, isActive => {
  4683. if (link.isLink.value && isActive && select) {
  4684. vue.nextTick(() => {
  4685. select(true);
  4686. });
  4687. }
  4688. }, {
  4689. immediate: true
  4690. });
  4691. }
  4692. // Styles
  4693. // Types
  4694. const stopSymbol = Symbol('rippleStop');
  4695. const DELAY_RIPPLE = 80;
  4696. function transform(el, value) {
  4697. el.style.transform = value;
  4698. el.style.webkitTransform = value;
  4699. }
  4700. function isTouchEvent(e) {
  4701. return e.constructor.name === 'TouchEvent';
  4702. }
  4703. function isKeyboardEvent(e) {
  4704. return e.constructor.name === 'KeyboardEvent';
  4705. }
  4706. const calculate = function (e, el) {
  4707. let value = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {};
  4708. let localX = 0;
  4709. let localY = 0;
  4710. if (!isKeyboardEvent(e)) {
  4711. const offset = el.getBoundingClientRect();
  4712. const target = isTouchEvent(e) ? e.touches[e.touches.length - 1] : e;
  4713. localX = target.clientX - offset.left;
  4714. localY = target.clientY - offset.top;
  4715. }
  4716. let radius = 0;
  4717. let scale = 0.3;
  4718. if (el._ripple?.circle) {
  4719. scale = 0.15;
  4720. radius = el.clientWidth / 2;
  4721. radius = value.center ? radius : radius + Math.sqrt((localX - radius) ** 2 + (localY - radius) ** 2) / 4;
  4722. } else {
  4723. radius = Math.sqrt(el.clientWidth ** 2 + el.clientHeight ** 2) / 2;
  4724. }
  4725. const centerX = `${(el.clientWidth - radius * 2) / 2}px`;
  4726. const centerY = `${(el.clientHeight - radius * 2) / 2}px`;
  4727. const x = value.center ? centerX : `${localX - radius}px`;
  4728. const y = value.center ? centerY : `${localY - radius}px`;
  4729. return {
  4730. radius,
  4731. scale,
  4732. x,
  4733. y,
  4734. centerX,
  4735. centerY
  4736. };
  4737. };
  4738. const ripples = {
  4739. /* eslint-disable max-statements */
  4740. show(e, el) {
  4741. let value = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {};
  4742. if (!el?._ripple?.enabled) {
  4743. return;
  4744. }
  4745. const container = document.createElement('span');
  4746. const animation = document.createElement('span');
  4747. container.appendChild(animation);
  4748. container.className = 'v-ripple__container';
  4749. if (value.class) {
  4750. container.className += ` ${value.class}`;
  4751. }
  4752. const {
  4753. radius,
  4754. scale,
  4755. x,
  4756. y,
  4757. centerX,
  4758. centerY
  4759. } = calculate(e, el, value);
  4760. const size = `${radius * 2}px`;
  4761. animation.className = 'v-ripple__animation';
  4762. animation.style.width = size;
  4763. animation.style.height = size;
  4764. el.appendChild(container);
  4765. const computed = window.getComputedStyle(el);
  4766. if (computed && computed.position === 'static') {
  4767. el.style.position = 'relative';
  4768. el.dataset.previousPosition = 'static';
  4769. }
  4770. animation.classList.add('v-ripple__animation--enter');
  4771. animation.classList.add('v-ripple__animation--visible');
  4772. transform(animation, `translate(${x}, ${y}) scale3d(${scale},${scale},${scale})`);
  4773. animation.dataset.activated = String(performance.now());
  4774. setTimeout(() => {
  4775. animation.classList.remove('v-ripple__animation--enter');
  4776. animation.classList.add('v-ripple__animation--in');
  4777. transform(animation, `translate(${centerX}, ${centerY}) scale3d(1,1,1)`);
  4778. }, 0);
  4779. },
  4780. hide(el) {
  4781. if (!el?._ripple?.enabled) return;
  4782. const ripples = el.getElementsByClassName('v-ripple__animation');
  4783. if (ripples.length === 0) return;
  4784. const animation = ripples[ripples.length - 1];
  4785. if (animation.dataset.isHiding) return;else animation.dataset.isHiding = 'true';
  4786. const diff = performance.now() - Number(animation.dataset.activated);
  4787. const delay = Math.max(250 - diff, 0);
  4788. setTimeout(() => {
  4789. animation.classList.remove('v-ripple__animation--in');
  4790. animation.classList.add('v-ripple__animation--out');
  4791. setTimeout(() => {
  4792. const ripples = el.getElementsByClassName('v-ripple__animation');
  4793. if (ripples.length === 1 && el.dataset.previousPosition) {
  4794. el.style.position = el.dataset.previousPosition;
  4795. delete el.dataset.previousPosition;
  4796. }
  4797. if (animation.parentNode?.parentNode === el) el.removeChild(animation.parentNode);
  4798. }, 300);
  4799. }, delay);
  4800. }
  4801. };
  4802. function isRippleEnabled(value) {
  4803. return typeof value === 'undefined' || !!value;
  4804. }
  4805. function rippleShow(e) {
  4806. const value = {};
  4807. const element = e.currentTarget;
  4808. if (!element?._ripple || element._ripple.touched || e[stopSymbol]) return;
  4809. // Don't allow the event to trigger ripples on any other elements
  4810. e[stopSymbol] = true;
  4811. if (isTouchEvent(e)) {
  4812. element._ripple.touched = true;
  4813. element._ripple.isTouch = true;
  4814. } else {
  4815. // It's possible for touch events to fire
  4816. // as mouse events on Android/iOS, this
  4817. // will skip the event call if it has
  4818. // already been registered as touch
  4819. if (element._ripple.isTouch) return;
  4820. }
  4821. value.center = element._ripple.centered || isKeyboardEvent(e);
  4822. if (element._ripple.class) {
  4823. value.class = element._ripple.class;
  4824. }
  4825. if (isTouchEvent(e)) {
  4826. // already queued that shows or hides the ripple
  4827. if (element._ripple.showTimerCommit) return;
  4828. element._ripple.showTimerCommit = () => {
  4829. ripples.show(e, element, value);
  4830. };
  4831. element._ripple.showTimer = window.setTimeout(() => {
  4832. if (element?._ripple?.showTimerCommit) {
  4833. element._ripple.showTimerCommit();
  4834. element._ripple.showTimerCommit = null;
  4835. }
  4836. }, DELAY_RIPPLE);
  4837. } else {
  4838. ripples.show(e, element, value);
  4839. }
  4840. }
  4841. function rippleStop(e) {
  4842. e[stopSymbol] = true;
  4843. }
  4844. function rippleHide(e) {
  4845. const element = e.currentTarget;
  4846. if (!element?._ripple) return;
  4847. window.clearTimeout(element._ripple.showTimer);
  4848. // The touch interaction occurs before the show timer is triggered.
  4849. // We still want to show ripple effect.
  4850. if (e.type === 'touchend' && element._ripple.showTimerCommit) {
  4851. element._ripple.showTimerCommit();
  4852. element._ripple.showTimerCommit = null;
  4853. // re-queue ripple hiding
  4854. element._ripple.showTimer = window.setTimeout(() => {
  4855. rippleHide(e);
  4856. });
  4857. return;
  4858. }
  4859. window.setTimeout(() => {
  4860. if (element._ripple) {
  4861. element._ripple.touched = false;
  4862. }
  4863. });
  4864. ripples.hide(element);
  4865. }
  4866. function rippleCancelShow(e) {
  4867. const element = e.currentTarget;
  4868. if (!element?._ripple) return;
  4869. if (element._ripple.showTimerCommit) {
  4870. element._ripple.showTimerCommit = null;
  4871. }
  4872. window.clearTimeout(element._ripple.showTimer);
  4873. }
  4874. let keyboardRipple = false;
  4875. function keyboardRippleShow(e) {
  4876. if (!keyboardRipple && (e.keyCode === keyCodes.enter || e.keyCode === keyCodes.space)) {
  4877. keyboardRipple = true;
  4878. rippleShow(e);
  4879. }
  4880. }
  4881. function keyboardRippleHide(e) {
  4882. keyboardRipple = false;
  4883. rippleHide(e);
  4884. }
  4885. function focusRippleHide(e) {
  4886. if (keyboardRipple) {
  4887. keyboardRipple = false;
  4888. rippleHide(e);
  4889. }
  4890. }
  4891. function updateRipple(el, binding, wasEnabled) {
  4892. const {
  4893. value,
  4894. modifiers
  4895. } = binding;
  4896. const enabled = isRippleEnabled(value);
  4897. if (!enabled) {
  4898. ripples.hide(el);
  4899. }
  4900. el._ripple = el._ripple ?? {};
  4901. el._ripple.enabled = enabled;
  4902. el._ripple.centered = modifiers.center;
  4903. el._ripple.circle = modifiers.circle;
  4904. if (isObject(value) && value.class) {
  4905. el._ripple.class = value.class;
  4906. }
  4907. if (enabled && !wasEnabled) {
  4908. if (modifiers.stop) {
  4909. el.addEventListener('touchstart', rippleStop, {
  4910. passive: true
  4911. });
  4912. el.addEventListener('mousedown', rippleStop);
  4913. return;
  4914. }
  4915. el.addEventListener('touchstart', rippleShow, {
  4916. passive: true
  4917. });
  4918. el.addEventListener('touchend', rippleHide, {
  4919. passive: true
  4920. });
  4921. el.addEventListener('touchmove', rippleCancelShow, {
  4922. passive: true
  4923. });
  4924. el.addEventListener('touchcancel', rippleHide);
  4925. el.addEventListener('mousedown', rippleShow);
  4926. el.addEventListener('mouseup', rippleHide);
  4927. el.addEventListener('mouseleave', rippleHide);
  4928. el.addEventListener('keydown', keyboardRippleShow);
  4929. el.addEventListener('keyup', keyboardRippleHide);
  4930. el.addEventListener('blur', focusRippleHide);
  4931. // Anchor tags can be dragged, causes other hides to fail - #1537
  4932. el.addEventListener('dragstart', rippleHide, {
  4933. passive: true
  4934. });
  4935. } else if (!enabled && wasEnabled) {
  4936. removeListeners(el);
  4937. }
  4938. }
  4939. function removeListeners(el) {
  4940. el.removeEventListener('mousedown', rippleShow);
  4941. el.removeEventListener('touchstart', rippleShow);
  4942. el.removeEventListener('touchend', rippleHide);
  4943. el.removeEventListener('touchmove', rippleCancelShow);
  4944. el.removeEventListener('touchcancel', rippleHide);
  4945. el.removeEventListener('mouseup', rippleHide);
  4946. el.removeEventListener('mouseleave', rippleHide);
  4947. el.removeEventListener('keydown', keyboardRippleShow);
  4948. el.removeEventListener('keyup', keyboardRippleHide);
  4949. el.removeEventListener('dragstart', rippleHide);
  4950. el.removeEventListener('blur', focusRippleHide);
  4951. }
  4952. function mounted$4(el, binding) {
  4953. updateRipple(el, binding, false);
  4954. }
  4955. function unmounted$4(el) {
  4956. delete el._ripple;
  4957. removeListeners(el);
  4958. }
  4959. function updated$1(el, binding) {
  4960. if (binding.value === binding.oldValue) {
  4961. return;
  4962. }
  4963. const wasEnabled = isRippleEnabled(binding.oldValue);
  4964. updateRipple(el, binding, wasEnabled);
  4965. }
  4966. const Ripple = {
  4967. mounted: mounted$4,
  4968. unmounted: unmounted$4,
  4969. updated: updated$1
  4970. };
  4971. // Types
  4972. const makeVBtnProps = propsFactory({
  4973. active: {
  4974. type: Boolean,
  4975. default: undefined
  4976. },
  4977. symbol: {
  4978. type: null,
  4979. default: VBtnToggleSymbol
  4980. },
  4981. flat: Boolean,
  4982. icon: [Boolean, String, Function, Object],
  4983. prependIcon: IconValue,
  4984. appendIcon: IconValue,
  4985. block: Boolean,
  4986. stacked: Boolean,
  4987. ripple: {
  4988. type: [Boolean, Object],
  4989. default: true
  4990. },
  4991. text: String,
  4992. ...makeBorderProps(),
  4993. ...makeComponentProps(),
  4994. ...makeDensityProps(),
  4995. ...makeDimensionProps(),
  4996. ...makeElevationProps(),
  4997. ...makeGroupItemProps(),
  4998. ...makeLoaderProps(),
  4999. ...makeLocationProps(),
  5000. ...makePositionProps(),
  5001. ...makeRoundedProps(),
  5002. ...makeRouterProps(),
  5003. ...makeSizeProps(),
  5004. ...makeTagProps({
  5005. tag: 'button'
  5006. }),
  5007. ...makeThemeProps(),
  5008. ...makeVariantProps({
  5009. variant: 'elevated'
  5010. })
  5011. }, 'VBtn');
  5012. const VBtn = genericComponent()({
  5013. name: 'VBtn',
  5014. directives: {
  5015. Ripple
  5016. },
  5017. props: makeVBtnProps(),
  5018. emits: {
  5019. 'group:selected': val => true
  5020. },
  5021. setup(props, _ref) {
  5022. let {
  5023. attrs,
  5024. slots
  5025. } = _ref;
  5026. const {
  5027. themeClasses
  5028. } = provideTheme(props);
  5029. const {
  5030. borderClasses
  5031. } = useBorder(props);
  5032. const {
  5033. colorClasses,
  5034. colorStyles,
  5035. variantClasses
  5036. } = useVariant(props);
  5037. const {
  5038. densityClasses
  5039. } = useDensity(props);
  5040. const {
  5041. dimensionStyles
  5042. } = useDimension(props);
  5043. const {
  5044. elevationClasses
  5045. } = useElevation(props);
  5046. const {
  5047. loaderClasses
  5048. } = useLoader(props);
  5049. const {
  5050. locationStyles
  5051. } = useLocation(props);
  5052. const {
  5053. positionClasses
  5054. } = usePosition(props);
  5055. const {
  5056. roundedClasses
  5057. } = useRounded(props);
  5058. const {
  5059. sizeClasses,
  5060. sizeStyles
  5061. } = useSize(props);
  5062. const group = useGroupItem(props, props.symbol, false);
  5063. const link = useLink(props, attrs);
  5064. const isActive = vue.computed(() => {
  5065. if (props.active !== undefined) {
  5066. return props.active;
  5067. }
  5068. if (link.isLink.value) {
  5069. return link.isActive?.value;
  5070. }
  5071. return group?.isSelected.value;
  5072. });
  5073. const isDisabled = vue.computed(() => group?.disabled.value || props.disabled);
  5074. const isElevated = vue.computed(() => {
  5075. return props.variant === 'elevated' && !(props.disabled || props.flat || props.border);
  5076. });
  5077. const valueAttr = vue.computed(() => {
  5078. if (props.value === undefined) return undefined;
  5079. return Object(props.value) === props.value ? JSON.stringify(props.value, null, 0) : props.value;
  5080. });
  5081. function onClick(e) {
  5082. if (isDisabled.value || link.isLink.value && (e.metaKey || e.ctrlKey || e.shiftKey || e.button !== 0 || attrs.target === '_blank')) return;
  5083. link.navigate?.(e);
  5084. group?.toggle();
  5085. }
  5086. useSelectLink(link, group?.select);
  5087. useRender(() => {
  5088. const Tag = link.isLink.value ? 'a' : props.tag;
  5089. const hasPrepend = !!(props.prependIcon || slots.prepend);
  5090. const hasAppend = !!(props.appendIcon || slots.append);
  5091. const hasIcon = !!(props.icon && props.icon !== true);
  5092. const hasColor = group?.isSelected.value && (!link.isLink.value || link.isActive?.value) || !group || link.isActive?.value;
  5093. return vue.withDirectives(vue.createVNode(Tag, {
  5094. "type": Tag === 'a' ? undefined : 'button',
  5095. "class": ['v-btn', group?.selectedClass.value, {
  5096. 'v-btn--active': isActive.value,
  5097. 'v-btn--block': props.block,
  5098. 'v-btn--disabled': isDisabled.value,
  5099. 'v-btn--elevated': isElevated.value,
  5100. 'v-btn--flat': props.flat,
  5101. 'v-btn--icon': !!props.icon,
  5102. 'v-btn--loading': props.loading,
  5103. 'v-btn--stacked': props.stacked
  5104. }, themeClasses.value, borderClasses.value, hasColor ? colorClasses.value : undefined, densityClasses.value, elevationClasses.value, loaderClasses.value, positionClasses.value, roundedClasses.value, sizeClasses.value, variantClasses.value, props.class],
  5105. "style": [hasColor ? colorStyles.value : undefined, dimensionStyles.value, locationStyles.value, sizeStyles.value, props.style],
  5106. "disabled": isDisabled.value || undefined,
  5107. "href": link.href.value,
  5108. "onClick": onClick,
  5109. "value": valueAttr.value
  5110. }, {
  5111. default: () => [genOverlays(true, 'v-btn'), !props.icon && hasPrepend && vue.createVNode("span", {
  5112. "key": "prepend",
  5113. "class": "v-btn__prepend"
  5114. }, [!slots.prepend ? vue.createVNode(VIcon, {
  5115. "key": "prepend-icon",
  5116. "icon": props.prependIcon
  5117. }, null) : vue.createVNode(VDefaultsProvider, {
  5118. "key": "prepend-defaults",
  5119. "disabled": !props.prependIcon,
  5120. "defaults": {
  5121. VIcon: {
  5122. icon: props.prependIcon
  5123. }
  5124. }
  5125. }, slots.prepend)]), vue.createVNode("span", {
  5126. "class": "v-btn__content",
  5127. "data-no-activator": ""
  5128. }, [!slots.default && hasIcon ? vue.createVNode(VIcon, {
  5129. "key": "content-icon",
  5130. "icon": props.icon
  5131. }, null) : vue.createVNode(VDefaultsProvider, {
  5132. "key": "content-defaults",
  5133. "disabled": !hasIcon,
  5134. "defaults": {
  5135. VIcon: {
  5136. icon: props.icon
  5137. }
  5138. }
  5139. }, {
  5140. default: () => [slots.default?.() ?? props.text]
  5141. })]), !props.icon && hasAppend && vue.createVNode("span", {
  5142. "key": "append",
  5143. "class": "v-btn__append"
  5144. }, [!slots.append ? vue.createVNode(VIcon, {
  5145. "key": "append-icon",
  5146. "icon": props.appendIcon
  5147. }, null) : vue.createVNode(VDefaultsProvider, {
  5148. "key": "append-defaults",
  5149. "disabled": !props.appendIcon,
  5150. "defaults": {
  5151. VIcon: {
  5152. icon: props.appendIcon
  5153. }
  5154. }
  5155. }, slots.append)]), !!props.loading && vue.createVNode("span", {
  5156. "key": "loader",
  5157. "class": "v-btn__loader"
  5158. }, [slots.loader?.() ?? vue.createVNode(VProgressCircular, {
  5159. "color": typeof props.loading === 'boolean' ? undefined : props.loading,
  5160. "indeterminate": true,
  5161. "size": "23",
  5162. "width": "2"
  5163. }, null)])]
  5164. }), [[vue.resolveDirective("ripple"), !isDisabled.value && props.ripple, null]]);
  5165. });
  5166. return {};
  5167. }
  5168. });
  5169. // Types
  5170. const makeVAppBarNavIconProps = propsFactory({
  5171. ...makeVBtnProps({
  5172. icon: '$menu',
  5173. variant: 'text'
  5174. })
  5175. }, 'VAppBarNavIcon');
  5176. const VAppBarNavIcon = genericComponent()({
  5177. name: 'VAppBarNavIcon',
  5178. props: makeVAppBarNavIconProps(),
  5179. setup(props, _ref) {
  5180. let {
  5181. slots
  5182. } = _ref;
  5183. useRender(() => vue.createVNode(VBtn, vue.mergeProps(props, {
  5184. "class": ['v-app-bar-nav-icon']
  5185. }), slots));
  5186. return {};
  5187. }
  5188. });
  5189. // Types
  5190. const VAppBarTitle = genericComponent()({
  5191. name: 'VAppBarTitle',
  5192. props: makeVToolbarTitleProps(),
  5193. setup(props, _ref) {
  5194. let {
  5195. slots
  5196. } = _ref;
  5197. useRender(() => vue.createVNode(VToolbarTitle, vue.mergeProps(props, {
  5198. "class": "v-app-bar-title"
  5199. }), slots));
  5200. return {};
  5201. }
  5202. });
  5203. // Utilities
  5204. const VAlertTitle = createSimpleFunctional('v-alert-title');
  5205. // Types
  5206. const allowedTypes = ['success', 'info', 'warning', 'error'];
  5207. const makeVAlertProps = propsFactory({
  5208. border: {
  5209. type: [Boolean, String],
  5210. validator: val => {
  5211. return typeof val === 'boolean' || ['top', 'end', 'bottom', 'start'].includes(val);
  5212. }
  5213. },
  5214. borderColor: String,
  5215. closable: Boolean,
  5216. closeIcon: {
  5217. type: IconValue,
  5218. default: '$close'
  5219. },
  5220. closeLabel: {
  5221. type: String,
  5222. default: '$vuetify.close'
  5223. },
  5224. icon: {
  5225. type: [Boolean, String, Function, Object],
  5226. default: null
  5227. },
  5228. modelValue: {
  5229. type: Boolean,
  5230. default: true
  5231. },
  5232. prominent: Boolean,
  5233. title: String,
  5234. text: String,
  5235. type: {
  5236. type: String,
  5237. validator: val => allowedTypes.includes(val)
  5238. },
  5239. ...makeComponentProps(),
  5240. ...makeDensityProps(),
  5241. ...makeDimensionProps(),
  5242. ...makeElevationProps(),
  5243. ...makeLocationProps(),
  5244. ...makePositionProps(),
  5245. ...makeRoundedProps(),
  5246. ...makeTagProps(),
  5247. ...makeThemeProps(),
  5248. ...makeVariantProps({
  5249. variant: 'flat'
  5250. })
  5251. }, 'VAlert');
  5252. const VAlert = genericComponent()({
  5253. name: 'VAlert',
  5254. props: makeVAlertProps(),
  5255. emits: {
  5256. 'click:close': e => true,
  5257. 'update:modelValue': value => true
  5258. },
  5259. setup(props, _ref) {
  5260. let {
  5261. emit,
  5262. slots
  5263. } = _ref;
  5264. const isActive = useProxiedModel(props, 'modelValue');
  5265. const icon = vue.computed(() => {
  5266. if (props.icon === false) return undefined;
  5267. if (!props.type) return props.icon;
  5268. return props.icon ?? `$${props.type}`;
  5269. });
  5270. const variantProps = vue.computed(() => ({
  5271. color: props.color ?? props.type,
  5272. variant: props.variant
  5273. }));
  5274. const {
  5275. themeClasses
  5276. } = provideTheme(props);
  5277. const {
  5278. colorClasses,
  5279. colorStyles,
  5280. variantClasses
  5281. } = useVariant(variantProps);
  5282. const {
  5283. densityClasses
  5284. } = useDensity(props);
  5285. const {
  5286. dimensionStyles
  5287. } = useDimension(props);
  5288. const {
  5289. elevationClasses
  5290. } = useElevation(props);
  5291. const {
  5292. locationStyles
  5293. } = useLocation(props);
  5294. const {
  5295. positionClasses
  5296. } = usePosition(props);
  5297. const {
  5298. roundedClasses
  5299. } = useRounded(props);
  5300. const {
  5301. textColorClasses,
  5302. textColorStyles
  5303. } = useTextColor(vue.toRef(props, 'borderColor'));
  5304. const {
  5305. t
  5306. } = useLocale();
  5307. const closeProps = vue.computed(() => ({
  5308. 'aria-label': t(props.closeLabel),
  5309. onClick(e) {
  5310. isActive.value = false;
  5311. emit('click:close', e);
  5312. }
  5313. }));
  5314. return () => {
  5315. const hasPrepend = !!(slots.prepend || icon.value);
  5316. const hasTitle = !!(slots.title || props.title);
  5317. const hasClose = !!(slots.close || props.closable);
  5318. return isActive.value && vue.createVNode(props.tag, {
  5319. "class": ['v-alert', props.border && {
  5320. 'v-alert--border': !!props.border,
  5321. [`v-alert--border-${props.border === true ? 'start' : props.border}`]: true
  5322. }, {
  5323. 'v-alert--prominent': props.prominent
  5324. }, themeClasses.value, colorClasses.value, densityClasses.value, elevationClasses.value, positionClasses.value, roundedClasses.value, variantClasses.value, props.class],
  5325. "style": [colorStyles.value, dimensionStyles.value, locationStyles.value, props.style],
  5326. "role": "alert"
  5327. }, {
  5328. default: () => [genOverlays(false, 'v-alert'), props.border && vue.createVNode("div", {
  5329. "key": "border",
  5330. "class": ['v-alert__border', textColorClasses.value],
  5331. "style": textColorStyles.value
  5332. }, null), hasPrepend && vue.createVNode("div", {
  5333. "key": "prepend",
  5334. "class": "v-alert__prepend"
  5335. }, [!slots.prepend ? vue.createVNode(VIcon, {
  5336. "key": "prepend-icon",
  5337. "density": props.density,
  5338. "icon": icon.value,
  5339. "size": props.prominent ? 44 : 28
  5340. }, null) : vue.createVNode(VDefaultsProvider, {
  5341. "key": "prepend-defaults",
  5342. "disabled": !icon.value,
  5343. "defaults": {
  5344. VIcon: {
  5345. density: props.density,
  5346. icon: icon.value,
  5347. size: props.prominent ? 44 : 28
  5348. }
  5349. }
  5350. }, slots.prepend)]), vue.createVNode("div", {
  5351. "class": "v-alert__content"
  5352. }, [hasTitle && vue.createVNode(VAlertTitle, {
  5353. "key": "title"
  5354. }, {
  5355. default: () => [slots.title?.() ?? props.title]
  5356. }), slots.text?.() ?? props.text, slots.default?.()]), slots.append && vue.createVNode("div", {
  5357. "key": "append",
  5358. "class": "v-alert__append"
  5359. }, [slots.append()]), hasClose && vue.createVNode("div", {
  5360. "key": "close",
  5361. "class": "v-alert__close"
  5362. }, [!slots.close ? vue.createVNode(VBtn, vue.mergeProps({
  5363. "key": "close-btn",
  5364. "icon": props.closeIcon,
  5365. "size": "x-small",
  5366. "variant": "text"
  5367. }, closeProps.value), null) : vue.createVNode(VDefaultsProvider, {
  5368. "key": "close-defaults",
  5369. "defaults": {
  5370. VBtn: {
  5371. icon: props.closeIcon,
  5372. size: 'x-small',
  5373. variant: 'text'
  5374. }
  5375. }
  5376. }, {
  5377. default: () => [slots.close?.({
  5378. props: closeProps.value
  5379. })]
  5380. })])]
  5381. });
  5382. };
  5383. }
  5384. });
  5385. const makeVLabelProps = propsFactory({
  5386. text: String,
  5387. clickable: Boolean,
  5388. ...makeComponentProps(),
  5389. ...makeThemeProps()
  5390. }, 'VLabel');
  5391. const VLabel = genericComponent()({
  5392. name: 'VLabel',
  5393. props: makeVLabelProps(),
  5394. setup(props, _ref) {
  5395. let {
  5396. slots
  5397. } = _ref;
  5398. useRender(() => vue.createVNode("label", {
  5399. "class": ['v-label', {
  5400. 'v-label--clickable': props.clickable
  5401. }, props.class],
  5402. "style": props.style
  5403. }, [props.text, slots.default?.()]));
  5404. return {};
  5405. }
  5406. });
  5407. // Types
  5408. const VSelectionControlGroupSymbol = Symbol.for('vuetify:selection-control-group');
  5409. const makeSelectionControlGroupProps = propsFactory({
  5410. color: String,
  5411. disabled: {
  5412. type: Boolean,
  5413. default: null
  5414. },
  5415. defaultsTarget: String,
  5416. error: Boolean,
  5417. id: String,
  5418. inline: Boolean,
  5419. falseIcon: IconValue,
  5420. trueIcon: IconValue,
  5421. ripple: {
  5422. type: Boolean,
  5423. default: true
  5424. },
  5425. multiple: {
  5426. type: Boolean,
  5427. default: null
  5428. },
  5429. name: String,
  5430. readonly: Boolean,
  5431. modelValue: null,
  5432. type: String,
  5433. valueComparator: {
  5434. type: Function,
  5435. default: deepEqual
  5436. },
  5437. ...makeComponentProps(),
  5438. ...makeDensityProps(),
  5439. ...makeThemeProps()
  5440. }, 'SelectionControlGroup');
  5441. const makeVSelectionControlGroupProps = propsFactory({
  5442. ...makeSelectionControlGroupProps({
  5443. defaultsTarget: 'VSelectionControl'
  5444. })
  5445. }, 'VSelectionControlGroup');
  5446. const VSelectionControlGroup = genericComponent()({
  5447. name: 'VSelectionControlGroup',
  5448. props: makeVSelectionControlGroupProps(),
  5449. emits: {
  5450. 'update:modelValue': val => true
  5451. },
  5452. setup(props, _ref) {
  5453. let {
  5454. slots
  5455. } = _ref;
  5456. const modelValue = useProxiedModel(props, 'modelValue');
  5457. const uid = getUid();
  5458. const id = vue.computed(() => props.id || `v-selection-control-group-${uid}`);
  5459. const name = vue.computed(() => props.name || id.value);
  5460. const updateHandlers = new Set();
  5461. vue.provide(VSelectionControlGroupSymbol, {
  5462. modelValue,
  5463. forceUpdate: () => {
  5464. updateHandlers.forEach(fn => fn());
  5465. },
  5466. onForceUpdate: cb => {
  5467. updateHandlers.add(cb);
  5468. vue.onScopeDispose(() => {
  5469. updateHandlers.delete(cb);
  5470. });
  5471. }
  5472. });
  5473. provideDefaults({
  5474. [props.defaultsTarget]: {
  5475. color: vue.toRef(props, 'color'),
  5476. disabled: vue.toRef(props, 'disabled'),
  5477. density: vue.toRef(props, 'density'),
  5478. error: vue.toRef(props, 'error'),
  5479. inline: vue.toRef(props, 'inline'),
  5480. modelValue,
  5481. multiple: vue.computed(() => !!props.multiple || props.multiple == null && Array.isArray(modelValue.value)),
  5482. name,
  5483. falseIcon: vue.toRef(props, 'falseIcon'),
  5484. trueIcon: vue.toRef(props, 'trueIcon'),
  5485. readonly: vue.toRef(props, 'readonly'),
  5486. ripple: vue.toRef(props, 'ripple'),
  5487. type: vue.toRef(props, 'type'),
  5488. valueComparator: vue.toRef(props, 'valueComparator')
  5489. }
  5490. });
  5491. useRender(() => vue.createVNode("div", {
  5492. "class": ['v-selection-control-group', {
  5493. 'v-selection-control-group--inline': props.inline
  5494. }, props.class],
  5495. "style": props.style,
  5496. "role": props.type === 'radio' ? 'radiogroup' : undefined
  5497. }, [slots.default?.()]));
  5498. return {};
  5499. }
  5500. });
  5501. // Types
  5502. const makeVSelectionControlProps = propsFactory({
  5503. label: String,
  5504. trueValue: null,
  5505. falseValue: null,
  5506. value: null,
  5507. ...makeComponentProps(),
  5508. ...makeSelectionControlGroupProps()
  5509. }, 'VSelectionControl');
  5510. function useSelectionControl(props) {
  5511. const group = vue.inject(VSelectionControlGroupSymbol, undefined);
  5512. const {
  5513. densityClasses
  5514. } = useDensity(props);
  5515. const modelValue = useProxiedModel(props, 'modelValue');
  5516. const trueValue = vue.computed(() => props.trueValue !== undefined ? props.trueValue : props.value !== undefined ? props.value : true);
  5517. const falseValue = vue.computed(() => props.falseValue !== undefined ? props.falseValue : false);
  5518. const isMultiple = vue.computed(() => !!props.multiple || props.multiple == null && Array.isArray(modelValue.value));
  5519. const model = vue.computed({
  5520. get() {
  5521. const val = group ? group.modelValue.value : modelValue.value;
  5522. return isMultiple.value ? val.some(v => props.valueComparator(v, trueValue.value)) : props.valueComparator(val, trueValue.value);
  5523. },
  5524. set(val) {
  5525. if (props.readonly) return;
  5526. const currentValue = val ? trueValue.value : falseValue.value;
  5527. let newVal = currentValue;
  5528. if (isMultiple.value) {
  5529. newVal = val ? [...wrapInArray(modelValue.value), currentValue] : wrapInArray(modelValue.value).filter(item => !props.valueComparator(item, trueValue.value));
  5530. }
  5531. if (group) {
  5532. group.modelValue.value = newVal;
  5533. } else {
  5534. modelValue.value = newVal;
  5535. }
  5536. }
  5537. });
  5538. const {
  5539. textColorClasses,
  5540. textColorStyles
  5541. } = useTextColor(vue.computed(() => {
  5542. return model.value && !props.error && !props.disabled ? props.color : undefined;
  5543. }));
  5544. const icon = vue.computed(() => model.value ? props.trueIcon : props.falseIcon);
  5545. return {
  5546. group,
  5547. densityClasses,
  5548. trueValue,
  5549. falseValue,
  5550. model,
  5551. textColorClasses,
  5552. textColorStyles,
  5553. icon
  5554. };
  5555. }
  5556. const VSelectionControl = genericComponent()({
  5557. name: 'VSelectionControl',
  5558. directives: {
  5559. Ripple
  5560. },
  5561. inheritAttrs: false,
  5562. props: makeVSelectionControlProps(),
  5563. emits: {
  5564. 'update:modelValue': val => true
  5565. },
  5566. setup(props, _ref) {
  5567. let {
  5568. attrs,
  5569. slots
  5570. } = _ref;
  5571. const {
  5572. group,
  5573. densityClasses,
  5574. icon,
  5575. model,
  5576. textColorClasses,
  5577. textColorStyles,
  5578. trueValue
  5579. } = useSelectionControl(props);
  5580. const uid = getUid();
  5581. const id = vue.computed(() => props.id || `input-${uid}`);
  5582. const isFocused = vue.shallowRef(false);
  5583. const isFocusVisible = vue.shallowRef(false);
  5584. const input = vue.ref();
  5585. group?.onForceUpdate(() => {
  5586. if (input.value) {
  5587. input.value.checked = model.value;
  5588. }
  5589. });
  5590. function onFocus(e) {
  5591. isFocused.value = true;
  5592. if (matchesSelector(e.target, ':focus-visible') !== false) {
  5593. isFocusVisible.value = true;
  5594. }
  5595. }
  5596. function onBlur() {
  5597. isFocused.value = false;
  5598. isFocusVisible.value = false;
  5599. }
  5600. function onInput(e) {
  5601. if (props.readonly && group) {
  5602. vue.nextTick(() => group.forceUpdate());
  5603. }
  5604. model.value = e.target.checked;
  5605. }
  5606. useRender(() => {
  5607. const label = slots.label ? slots.label({
  5608. label: props.label,
  5609. props: {
  5610. for: id.value
  5611. }
  5612. }) : props.label;
  5613. const [rootAttrs, inputAttrs] = filterInputAttrs(attrs);
  5614. return vue.createVNode("div", vue.mergeProps({
  5615. "class": ['v-selection-control', {
  5616. 'v-selection-control--dirty': model.value,
  5617. 'v-selection-control--disabled': props.disabled,
  5618. 'v-selection-control--error': props.error,
  5619. 'v-selection-control--focused': isFocused.value,
  5620. 'v-selection-control--focus-visible': isFocusVisible.value,
  5621. 'v-selection-control--inline': props.inline
  5622. }, densityClasses.value, props.class]
  5623. }, rootAttrs, {
  5624. "style": props.style
  5625. }), [vue.createVNode("div", {
  5626. "class": ['v-selection-control__wrapper', textColorClasses.value],
  5627. "style": textColorStyles.value
  5628. }, [slots.default?.(), vue.withDirectives(vue.createVNode("div", {
  5629. "class": ['v-selection-control__input']
  5630. }, [icon.value && vue.createVNode(VIcon, {
  5631. "key": "icon",
  5632. "icon": icon.value
  5633. }, null), vue.createVNode("input", vue.mergeProps({
  5634. "ref": input,
  5635. "checked": model.value,
  5636. "disabled": !!(props.readonly || props.disabled),
  5637. "id": id.value,
  5638. "onBlur": onBlur,
  5639. "onFocus": onFocus,
  5640. "onInput": onInput,
  5641. "aria-disabled": !!(props.readonly || props.disabled),
  5642. "type": props.type,
  5643. "value": trueValue.value,
  5644. "name": props.name,
  5645. "aria-checked": props.type === 'checkbox' ? model.value : undefined
  5646. }, inputAttrs), null), slots.input?.({
  5647. model,
  5648. textColorClasses,
  5649. textColorStyles,
  5650. props: {
  5651. onFocus,
  5652. onBlur,
  5653. id: id.value
  5654. }
  5655. })]), [[vue.resolveDirective("ripple"), props.ripple && [!props.disabled && !props.readonly, null, ['center', 'circle']]]])]), label && vue.createVNode(VLabel, {
  5656. "for": id.value,
  5657. "clickable": true
  5658. }, {
  5659. default: () => [label]
  5660. })]);
  5661. });
  5662. return {
  5663. isFocused,
  5664. input
  5665. };
  5666. }
  5667. });
  5668. // Types
  5669. const makeVCheckboxBtnProps = propsFactory({
  5670. indeterminate: Boolean,
  5671. indeterminateIcon: {
  5672. type: IconValue,
  5673. default: '$checkboxIndeterminate'
  5674. },
  5675. ...makeVSelectionControlProps({
  5676. falseIcon: '$checkboxOff',
  5677. trueIcon: '$checkboxOn'
  5678. })
  5679. }, 'VCheckboxBtn');
  5680. const VCheckboxBtn = genericComponent()({
  5681. name: 'VCheckboxBtn',
  5682. props: makeVCheckboxBtnProps(),
  5683. emits: {
  5684. 'update:modelValue': value => true,
  5685. 'update:indeterminate': val => true
  5686. },
  5687. setup(props, _ref) {
  5688. let {
  5689. slots
  5690. } = _ref;
  5691. const indeterminate = useProxiedModel(props, 'indeterminate');
  5692. const model = useProxiedModel(props, 'modelValue');
  5693. function onChange(v) {
  5694. if (indeterminate.value) {
  5695. indeterminate.value = false;
  5696. }
  5697. }
  5698. const falseIcon = vue.computed(() => {
  5699. return indeterminate.value ? props.indeterminateIcon : props.falseIcon;
  5700. });
  5701. const trueIcon = vue.computed(() => {
  5702. return indeterminate.value ? props.indeterminateIcon : props.trueIcon;
  5703. });
  5704. useRender(() => vue.createVNode(VSelectionControl, vue.mergeProps(props, {
  5705. "modelValue": model.value,
  5706. "onUpdate:modelValue": [$event => model.value = $event, onChange],
  5707. "class": ['v-checkbox-btn', props.class],
  5708. "style": props.style,
  5709. "type": "checkbox",
  5710. "falseIcon": falseIcon.value,
  5711. "trueIcon": trueIcon.value,
  5712. "aria-checked": indeterminate.value ? 'mixed' : undefined
  5713. }), slots));
  5714. return {};
  5715. }
  5716. });
  5717. // Types
  5718. function useInputIcon(props) {
  5719. const {
  5720. t
  5721. } = useLocale();
  5722. function InputIcon(_ref) {
  5723. let {
  5724. name
  5725. } = _ref;
  5726. const localeKey = {
  5727. prepend: 'prependAction',
  5728. prependInner: 'prependAction',
  5729. append: 'appendAction',
  5730. appendInner: 'appendAction',
  5731. clear: 'clear'
  5732. }[name];
  5733. const listener = props[`onClick:${name}`];
  5734. const label = listener && localeKey ? t(`$vuetify.input.${localeKey}`, props.label ?? '') : undefined;
  5735. return vue.createVNode(VIcon, {
  5736. "icon": props[`${name}Icon`],
  5737. "aria-label": label,
  5738. "onClick": listener
  5739. }, null);
  5740. }
  5741. return {
  5742. InputIcon
  5743. };
  5744. }
  5745. // Types
  5746. const makeVMessagesProps = propsFactory({
  5747. active: Boolean,
  5748. color: String,
  5749. messages: {
  5750. type: [Array, String],
  5751. default: () => []
  5752. },
  5753. ...makeComponentProps(),
  5754. ...makeTransitionProps({
  5755. transition: {
  5756. component: VSlideYTransition,
  5757. leaveAbsolute: true,
  5758. group: true
  5759. }
  5760. })
  5761. }, 'VMessages');
  5762. const VMessages = genericComponent()({
  5763. name: 'VMessages',
  5764. props: makeVMessagesProps(),
  5765. setup(props, _ref) {
  5766. let {
  5767. slots
  5768. } = _ref;
  5769. const messages = vue.computed(() => wrapInArray(props.messages));
  5770. const {
  5771. textColorClasses,
  5772. textColorStyles
  5773. } = useTextColor(vue.computed(() => props.color));
  5774. useRender(() => vue.createVNode(MaybeTransition, {
  5775. "transition": props.transition,
  5776. "tag": "div",
  5777. "class": ['v-messages', textColorClasses.value, props.class],
  5778. "style": [textColorStyles.value, props.style],
  5779. "role": "alert",
  5780. "aria-live": "polite"
  5781. }, {
  5782. default: () => [props.active && messages.value.map((message, i) => vue.createVNode("div", {
  5783. "class": "v-messages__message",
  5784. "key": `${i}-${messages.value}`
  5785. }, [slots.message ? slots.message({
  5786. message
  5787. }) : message]))]
  5788. }));
  5789. return {};
  5790. }
  5791. });
  5792. // Composables
  5793. // Types
  5794. // Composables
  5795. const makeFocusProps = propsFactory({
  5796. focused: Boolean,
  5797. 'onUpdate:focused': EventProp()
  5798. }, 'focus');
  5799. function useFocus(props) {
  5800. let name = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : getCurrentInstanceName();
  5801. const isFocused = useProxiedModel(props, 'focused');
  5802. const focusClasses = vue.computed(() => {
  5803. return {
  5804. [`${name}--focused`]: isFocused.value
  5805. };
  5806. });
  5807. function focus() {
  5808. isFocused.value = true;
  5809. }
  5810. function blur() {
  5811. isFocused.value = false;
  5812. }
  5813. return {
  5814. focusClasses,
  5815. isFocused,
  5816. focus,
  5817. blur
  5818. };
  5819. }
  5820. // Composables
  5821. // Types
  5822. const FormKey = Symbol.for('vuetify:form');
  5823. const makeFormProps = propsFactory({
  5824. disabled: Boolean,
  5825. fastFail: Boolean,
  5826. readonly: Boolean,
  5827. modelValue: {
  5828. type: Boolean,
  5829. default: null
  5830. },
  5831. validateOn: {
  5832. type: String,
  5833. default: 'input'
  5834. }
  5835. }, 'form');
  5836. function createForm(props) {
  5837. const model = useProxiedModel(props, 'modelValue');
  5838. const isDisabled = vue.computed(() => props.disabled);
  5839. const isReadonly = vue.computed(() => props.readonly);
  5840. const isValidating = vue.shallowRef(false);
  5841. const items = vue.ref([]);
  5842. const errors = vue.ref([]);
  5843. async function validate() {
  5844. const results = [];
  5845. let valid = true;
  5846. errors.value = [];
  5847. isValidating.value = true;
  5848. for (const item of items.value) {
  5849. const itemErrorMessages = await item.validate();
  5850. if (itemErrorMessages.length > 0) {
  5851. valid = false;
  5852. results.push({
  5853. id: item.id,
  5854. errorMessages: itemErrorMessages
  5855. });
  5856. }
  5857. if (!valid && props.fastFail) break;
  5858. }
  5859. errors.value = results;
  5860. isValidating.value = false;
  5861. return {
  5862. valid,
  5863. errors: errors.value
  5864. };
  5865. }
  5866. function reset() {
  5867. items.value.forEach(item => item.reset());
  5868. }
  5869. function resetValidation() {
  5870. items.value.forEach(item => item.resetValidation());
  5871. }
  5872. vue.watch(items, () => {
  5873. let valid = 0;
  5874. let invalid = 0;
  5875. const results = [];
  5876. for (const item of items.value) {
  5877. if (item.isValid === false) {
  5878. invalid++;
  5879. results.push({
  5880. id: item.id,
  5881. errorMessages: item.errorMessages
  5882. });
  5883. } else if (item.isValid === true) valid++;
  5884. }
  5885. errors.value = results;
  5886. model.value = invalid > 0 ? false : valid === items.value.length ? true : null;
  5887. }, {
  5888. deep: true
  5889. });
  5890. vue.provide(FormKey, {
  5891. register: _ref => {
  5892. let {
  5893. id,
  5894. validate,
  5895. reset,
  5896. resetValidation
  5897. } = _ref;
  5898. if (items.value.some(item => item.id === id)) {
  5899. consoleWarn(`Duplicate input name "${id}"`);
  5900. }
  5901. items.value.push({
  5902. id,
  5903. validate,
  5904. reset,
  5905. resetValidation,
  5906. isValid: null,
  5907. errorMessages: []
  5908. });
  5909. },
  5910. unregister: id => {
  5911. items.value = items.value.filter(item => {
  5912. return item.id !== id;
  5913. });
  5914. },
  5915. update: (id, isValid, errorMessages) => {
  5916. const found = items.value.find(item => item.id === id);
  5917. if (!found) return;
  5918. found.isValid = isValid;
  5919. found.errorMessages = errorMessages;
  5920. },
  5921. isDisabled,
  5922. isReadonly,
  5923. isValidating,
  5924. isValid: model,
  5925. items,
  5926. validateOn: vue.toRef(props, 'validateOn')
  5927. });
  5928. return {
  5929. errors,
  5930. isDisabled,
  5931. isReadonly,
  5932. isValidating,
  5933. isValid: model,
  5934. items,
  5935. validate,
  5936. reset,
  5937. resetValidation
  5938. };
  5939. }
  5940. function useForm() {
  5941. return vue.inject(FormKey, null);
  5942. }
  5943. // Composables
  5944. // Types
  5945. const makeValidationProps = propsFactory({
  5946. disabled: {
  5947. type: Boolean,
  5948. default: null
  5949. },
  5950. error: Boolean,
  5951. errorMessages: {
  5952. type: [Array, String],
  5953. default: () => []
  5954. },
  5955. maxErrors: {
  5956. type: [Number, String],
  5957. default: 1
  5958. },
  5959. name: String,
  5960. label: String,
  5961. readonly: {
  5962. type: Boolean,
  5963. default: null
  5964. },
  5965. rules: {
  5966. type: Array,
  5967. default: () => []
  5968. },
  5969. modelValue: null,
  5970. validateOn: String,
  5971. validationValue: null,
  5972. ...makeFocusProps()
  5973. }, 'validation');
  5974. function useValidation(props) {
  5975. let name = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : getCurrentInstanceName();
  5976. let id = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : getUid();
  5977. const model = useProxiedModel(props, 'modelValue');
  5978. const validationModel = vue.computed(() => props.validationValue === undefined ? model.value : props.validationValue);
  5979. const form = useForm();
  5980. const internalErrorMessages = vue.ref([]);
  5981. const isPristine = vue.shallowRef(true);
  5982. const isDirty = vue.computed(() => !!(wrapInArray(model.value === '' ? null : model.value).length || wrapInArray(validationModel.value === '' ? null : validationModel.value).length));
  5983. const isDisabled = vue.computed(() => !!(props.disabled ?? form?.isDisabled.value));
  5984. const isReadonly = vue.computed(() => !!(props.readonly ?? form?.isReadonly.value));
  5985. const errorMessages = vue.computed(() => {
  5986. return props.errorMessages.length ? wrapInArray(props.errorMessages).slice(0, Math.max(0, +props.maxErrors)) : internalErrorMessages.value;
  5987. });
  5988. const validateOn = vue.computed(() => {
  5989. let value = (props.validateOn ?? form?.validateOn.value) || 'input';
  5990. if (value === 'lazy') value = 'input lazy';
  5991. const set = new Set(value?.split(' ') ?? []);
  5992. return {
  5993. blur: set.has('blur') || set.has('input'),
  5994. input: set.has('input'),
  5995. submit: set.has('submit'),
  5996. lazy: set.has('lazy')
  5997. };
  5998. });
  5999. const isValid = vue.computed(() => {
  6000. if (props.error || props.errorMessages.length) return false;
  6001. if (!props.rules.length) return true;
  6002. if (isPristine.value) {
  6003. return internalErrorMessages.value.length || validateOn.value.lazy ? null : true;
  6004. } else {
  6005. return !internalErrorMessages.value.length;
  6006. }
  6007. });
  6008. const isValidating = vue.shallowRef(false);
  6009. const validationClasses = vue.computed(() => {
  6010. return {
  6011. [`${name}--error`]: isValid.value === false,
  6012. [`${name}--dirty`]: isDirty.value,
  6013. [`${name}--disabled`]: isDisabled.value,
  6014. [`${name}--readonly`]: isReadonly.value
  6015. };
  6016. });
  6017. const uid = vue.computed(() => props.name ?? vue.unref(id));
  6018. vue.onBeforeMount(() => {
  6019. form?.register({
  6020. id: uid.value,
  6021. validate,
  6022. reset,
  6023. resetValidation
  6024. });
  6025. });
  6026. vue.onBeforeUnmount(() => {
  6027. form?.unregister(uid.value);
  6028. });
  6029. vue.onMounted(async () => {
  6030. if (!validateOn.value.lazy) {
  6031. await validate(true);
  6032. }
  6033. form?.update(uid.value, isValid.value, errorMessages.value);
  6034. });
  6035. useToggleScope(() => validateOn.value.input, () => {
  6036. vue.watch(validationModel, () => {
  6037. if (validationModel.value != null) {
  6038. validate();
  6039. } else if (props.focused) {
  6040. const unwatch = vue.watch(() => props.focused, val => {
  6041. if (!val) validate();
  6042. unwatch();
  6043. });
  6044. }
  6045. });
  6046. });
  6047. useToggleScope(() => validateOn.value.blur, () => {
  6048. vue.watch(() => props.focused, val => {
  6049. if (!val) validate();
  6050. });
  6051. });
  6052. vue.watch(isValid, () => {
  6053. form?.update(uid.value, isValid.value, errorMessages.value);
  6054. });
  6055. function reset() {
  6056. model.value = null;
  6057. vue.nextTick(resetValidation);
  6058. }
  6059. function resetValidation() {
  6060. isPristine.value = true;
  6061. if (!validateOn.value.lazy) {
  6062. validate(true);
  6063. } else {
  6064. internalErrorMessages.value = [];
  6065. }
  6066. }
  6067. async function validate() {
  6068. let silent = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : false;
  6069. const results = [];
  6070. isValidating.value = true;
  6071. for (const rule of props.rules) {
  6072. if (results.length >= +(props.maxErrors ?? 1)) {
  6073. break;
  6074. }
  6075. const handler = typeof rule === 'function' ? rule : () => rule;
  6076. const result = await handler(validationModel.value);
  6077. if (result === true) continue;
  6078. if (result !== false && typeof result !== 'string') {
  6079. // eslint-disable-next-line no-console
  6080. console.warn(`${result} is not a valid value. Rule functions must return boolean true or a string.`);
  6081. continue;
  6082. }
  6083. results.push(result || '');
  6084. }
  6085. internalErrorMessages.value = results;
  6086. isValidating.value = false;
  6087. isPristine.value = silent;
  6088. return internalErrorMessages.value;
  6089. }
  6090. return {
  6091. errorMessages,
  6092. isDirty,
  6093. isDisabled,
  6094. isReadonly,
  6095. isPristine,
  6096. isValid,
  6097. isValidating,
  6098. reset,
  6099. resetValidation,
  6100. validate,
  6101. validationClasses
  6102. };
  6103. }
  6104. // Types
  6105. const makeVInputProps = propsFactory({
  6106. id: String,
  6107. appendIcon: IconValue,
  6108. centerAffix: {
  6109. type: Boolean,
  6110. default: true
  6111. },
  6112. prependIcon: IconValue,
  6113. hideDetails: [Boolean, String],
  6114. hint: String,
  6115. persistentHint: Boolean,
  6116. messages: {
  6117. type: [Array, String],
  6118. default: () => []
  6119. },
  6120. direction: {
  6121. type: String,
  6122. default: 'horizontal',
  6123. validator: v => ['horizontal', 'vertical'].includes(v)
  6124. },
  6125. 'onClick:prepend': EventProp(),
  6126. 'onClick:append': EventProp(),
  6127. ...makeComponentProps(),
  6128. ...makeDensityProps(),
  6129. ...makeValidationProps()
  6130. }, 'VInput');
  6131. const VInput = genericComponent()({
  6132. name: 'VInput',
  6133. props: {
  6134. ...makeVInputProps()
  6135. },
  6136. emits: {
  6137. 'update:modelValue': val => true
  6138. },
  6139. setup(props, _ref) {
  6140. let {
  6141. attrs,
  6142. slots,
  6143. emit
  6144. } = _ref;
  6145. const {
  6146. densityClasses
  6147. } = useDensity(props);
  6148. const {
  6149. rtlClasses
  6150. } = useRtl();
  6151. const {
  6152. InputIcon
  6153. } = useInputIcon(props);
  6154. const uid = getUid();
  6155. const id = vue.computed(() => props.id || `input-${uid}`);
  6156. const messagesId = vue.computed(() => `${id.value}-messages`);
  6157. const {
  6158. errorMessages,
  6159. isDirty,
  6160. isDisabled,
  6161. isReadonly,
  6162. isPristine,
  6163. isValid,
  6164. isValidating,
  6165. reset,
  6166. resetValidation,
  6167. validate,
  6168. validationClasses
  6169. } = useValidation(props, 'v-input', id);
  6170. const slotProps = vue.computed(() => ({
  6171. id,
  6172. messagesId,
  6173. isDirty,
  6174. isDisabled,
  6175. isReadonly,
  6176. isPristine,
  6177. isValid,
  6178. isValidating,
  6179. reset,
  6180. resetValidation,
  6181. validate
  6182. }));
  6183. const messages = vue.computed(() => {
  6184. if (props.errorMessages?.length || !isPristine.value && errorMessages.value.length) {
  6185. return errorMessages.value;
  6186. } else if (props.hint && (props.persistentHint || props.focused)) {
  6187. return props.hint;
  6188. } else {
  6189. return props.messages;
  6190. }
  6191. });
  6192. useRender(() => {
  6193. const hasPrepend = !!(slots.prepend || props.prependIcon);
  6194. const hasAppend = !!(slots.append || props.appendIcon);
  6195. const hasMessages = messages.value.length > 0;
  6196. const hasDetails = !props.hideDetails || props.hideDetails === 'auto' && (hasMessages || !!slots.details);
  6197. return vue.createVNode("div", {
  6198. "class": ['v-input', `v-input--${props.direction}`, {
  6199. 'v-input--center-affix': props.centerAffix
  6200. }, densityClasses.value, rtlClasses.value, validationClasses.value, props.class],
  6201. "style": props.style
  6202. }, [hasPrepend && vue.createVNode("div", {
  6203. "key": "prepend",
  6204. "class": "v-input__prepend"
  6205. }, [slots.prepend?.(slotProps.value), props.prependIcon && vue.createVNode(InputIcon, {
  6206. "key": "prepend-icon",
  6207. "name": "prepend"
  6208. }, null)]), slots.default && vue.createVNode("div", {
  6209. "class": "v-input__control"
  6210. }, [slots.default?.(slotProps.value)]), hasAppend && vue.createVNode("div", {
  6211. "key": "append",
  6212. "class": "v-input__append"
  6213. }, [props.appendIcon && vue.createVNode(InputIcon, {
  6214. "key": "append-icon",
  6215. "name": "append"
  6216. }, null), slots.append?.(slotProps.value)]), hasDetails && vue.createVNode("div", {
  6217. "class": "v-input__details"
  6218. }, [vue.createVNode(VMessages, {
  6219. "id": messagesId.value,
  6220. "active": hasMessages,
  6221. "messages": messages.value
  6222. }, {
  6223. message: slots.message
  6224. }), slots.details?.(slotProps.value)])]);
  6225. });
  6226. return {
  6227. reset,
  6228. resetValidation,
  6229. validate
  6230. };
  6231. }
  6232. });
  6233. // Types
  6234. const makeVCheckboxProps = propsFactory({
  6235. ...makeVInputProps(),
  6236. ...omit(makeVCheckboxBtnProps(), ['inline'])
  6237. }, 'VCheckbox');
  6238. const VCheckbox = genericComponent()({
  6239. name: 'VCheckbox',
  6240. inheritAttrs: false,
  6241. props: makeVCheckboxProps(),
  6242. emits: {
  6243. 'update:modelValue': value => true,
  6244. 'update:focused': focused => true
  6245. },
  6246. setup(props, _ref) {
  6247. let {
  6248. attrs,
  6249. slots
  6250. } = _ref;
  6251. const model = useProxiedModel(props, 'modelValue');
  6252. const {
  6253. isFocused,
  6254. focus,
  6255. blur
  6256. } = useFocus(props);
  6257. const uid = getUid();
  6258. const id = vue.computed(() => props.id || `checkbox-${uid}`);
  6259. useRender(() => {
  6260. const [inputAttrs, controlAttrs] = filterInputAttrs(attrs);
  6261. const [inputProps, _1] = VInput.filterProps(props);
  6262. const [checkboxProps, _2] = VCheckboxBtn.filterProps(props);
  6263. return vue.createVNode(VInput, vue.mergeProps({
  6264. "class": ['v-checkbox', props.class]
  6265. }, inputAttrs, inputProps, {
  6266. "modelValue": model.value,
  6267. "onUpdate:modelValue": $event => model.value = $event,
  6268. "id": id.value,
  6269. "focused": isFocused.value,
  6270. "style": props.style
  6271. }), {
  6272. ...slots,
  6273. default: _ref2 => {
  6274. let {
  6275. id,
  6276. messagesId,
  6277. isDisabled,
  6278. isReadonly
  6279. } = _ref2;
  6280. return vue.createVNode(VCheckboxBtn, vue.mergeProps(checkboxProps, {
  6281. "id": id.value,
  6282. "aria-describedby": messagesId.value,
  6283. "disabled": isDisabled.value,
  6284. "readonly": isReadonly.value
  6285. }, controlAttrs, {
  6286. "modelValue": model.value,
  6287. "onUpdate:modelValue": $event => model.value = $event,
  6288. "onFocus": focus,
  6289. "onBlur": blur
  6290. }), slots);
  6291. }
  6292. });
  6293. });
  6294. return {};
  6295. }
  6296. });
  6297. const makeVAvatarProps = propsFactory({
  6298. start: Boolean,
  6299. end: Boolean,
  6300. icon: IconValue,
  6301. image: String,
  6302. ...makeComponentProps(),
  6303. ...makeDensityProps(),
  6304. ...makeRoundedProps(),
  6305. ...makeSizeProps(),
  6306. ...makeTagProps(),
  6307. ...makeThemeProps(),
  6308. ...makeVariantProps({
  6309. variant: 'flat'
  6310. })
  6311. }, 'VAvatar');
  6312. const VAvatar = genericComponent()({
  6313. name: 'VAvatar',
  6314. props: makeVAvatarProps(),
  6315. setup(props, _ref) {
  6316. let {
  6317. slots
  6318. } = _ref;
  6319. const {
  6320. themeClasses
  6321. } = provideTheme(props);
  6322. const {
  6323. colorClasses,
  6324. colorStyles,
  6325. variantClasses
  6326. } = useVariant(props);
  6327. const {
  6328. densityClasses
  6329. } = useDensity(props);
  6330. const {
  6331. roundedClasses
  6332. } = useRounded(props);
  6333. const {
  6334. sizeClasses,
  6335. sizeStyles
  6336. } = useSize(props);
  6337. useRender(() => vue.createVNode(props.tag, {
  6338. "class": ['v-avatar', {
  6339. 'v-avatar--start': props.start,
  6340. 'v-avatar--end': props.end
  6341. }, themeClasses.value, colorClasses.value, densityClasses.value, roundedClasses.value, sizeClasses.value, variantClasses.value, props.class],
  6342. "style": [colorStyles.value, sizeStyles.value, props.style]
  6343. }, {
  6344. default: () => [props.image ? vue.createVNode(VImg, {
  6345. "key": "image",
  6346. "src": props.image,
  6347. "alt": "",
  6348. "cover": true
  6349. }, null) : props.icon ? vue.createVNode(VIcon, {
  6350. "key": "icon",
  6351. "icon": props.icon
  6352. }, null) : slots.default?.(), genOverlays(false, 'v-avatar')]
  6353. }));
  6354. return {};
  6355. }
  6356. });
  6357. // Types
  6358. const VChipGroupSymbol = Symbol.for('vuetify:v-chip-group');
  6359. const makeVChipGroupProps = propsFactory({
  6360. column: Boolean,
  6361. filter: Boolean,
  6362. valueComparator: {
  6363. type: Function,
  6364. default: deepEqual
  6365. },
  6366. ...makeComponentProps(),
  6367. ...makeGroupProps({
  6368. selectedClass: 'v-chip--selected'
  6369. }),
  6370. ...makeTagProps(),
  6371. ...makeThemeProps(),
  6372. ...makeVariantProps({
  6373. variant: 'tonal'
  6374. })
  6375. }, 'VChipGroup');
  6376. const VChipGroup = genericComponent()({
  6377. name: 'VChipGroup',
  6378. props: makeVChipGroupProps(),
  6379. emits: {
  6380. 'update:modelValue': value => true
  6381. },
  6382. setup(props, _ref) {
  6383. let {
  6384. slots
  6385. } = _ref;
  6386. const {
  6387. themeClasses
  6388. } = provideTheme(props);
  6389. const {
  6390. isSelected,
  6391. select,
  6392. next,
  6393. prev,
  6394. selected
  6395. } = useGroup(props, VChipGroupSymbol);
  6396. provideDefaults({
  6397. VChip: {
  6398. color: vue.toRef(props, 'color'),
  6399. disabled: vue.toRef(props, 'disabled'),
  6400. filter: vue.toRef(props, 'filter'),
  6401. variant: vue.toRef(props, 'variant')
  6402. }
  6403. });
  6404. useRender(() => vue.createVNode(props.tag, {
  6405. "class": ['v-chip-group', {
  6406. 'v-chip-group--column': props.column
  6407. }, themeClasses.value, props.class],
  6408. "style": props.style
  6409. }, {
  6410. default: () => [slots.default?.({
  6411. isSelected,
  6412. select,
  6413. next,
  6414. prev,
  6415. selected: selected.value
  6416. })]
  6417. }));
  6418. return {};
  6419. }
  6420. });
  6421. // Types
  6422. const makeVChipProps = propsFactory({
  6423. activeClass: String,
  6424. appendAvatar: String,
  6425. appendIcon: IconValue,
  6426. closable: Boolean,
  6427. closeIcon: {
  6428. type: IconValue,
  6429. default: '$delete'
  6430. },
  6431. closeLabel: {
  6432. type: String,
  6433. default: '$vuetify.close'
  6434. },
  6435. draggable: Boolean,
  6436. filter: Boolean,
  6437. filterIcon: {
  6438. type: String,
  6439. default: '$complete'
  6440. },
  6441. label: Boolean,
  6442. link: {
  6443. type: Boolean,
  6444. default: undefined
  6445. },
  6446. pill: Boolean,
  6447. prependAvatar: String,
  6448. prependIcon: IconValue,
  6449. ripple: {
  6450. type: [Boolean, Object],
  6451. default: true
  6452. },
  6453. text: String,
  6454. modelValue: {
  6455. type: Boolean,
  6456. default: true
  6457. },
  6458. onClick: EventProp(),
  6459. onClickOnce: EventProp(),
  6460. ...makeBorderProps(),
  6461. ...makeComponentProps(),
  6462. ...makeDensityProps(),
  6463. ...makeElevationProps(),
  6464. ...makeGroupItemProps(),
  6465. ...makeRoundedProps(),
  6466. ...makeRouterProps(),
  6467. ...makeSizeProps(),
  6468. ...makeTagProps({
  6469. tag: 'span'
  6470. }),
  6471. ...makeThemeProps(),
  6472. ...makeVariantProps({
  6473. variant: 'tonal'
  6474. })
  6475. }, 'VChip');
  6476. const VChip = genericComponent()({
  6477. name: 'VChip',
  6478. directives: {
  6479. Ripple
  6480. },
  6481. props: makeVChipProps(),
  6482. emits: {
  6483. 'click:close': e => true,
  6484. 'update:modelValue': value => true,
  6485. 'group:selected': val => true,
  6486. click: e => true
  6487. },
  6488. setup(props, _ref) {
  6489. let {
  6490. attrs,
  6491. emit,
  6492. slots
  6493. } = _ref;
  6494. const {
  6495. t
  6496. } = useLocale();
  6497. const {
  6498. borderClasses
  6499. } = useBorder(props);
  6500. const {
  6501. colorClasses,
  6502. colorStyles,
  6503. variantClasses
  6504. } = useVariant(props);
  6505. const {
  6506. densityClasses
  6507. } = useDensity(props);
  6508. const {
  6509. elevationClasses
  6510. } = useElevation(props);
  6511. const {
  6512. roundedClasses
  6513. } = useRounded(props);
  6514. const {
  6515. sizeClasses
  6516. } = useSize(props);
  6517. const {
  6518. themeClasses
  6519. } = provideTheme(props);
  6520. const isActive = useProxiedModel(props, 'modelValue');
  6521. const group = useGroupItem(props, VChipGroupSymbol, false);
  6522. const link = useLink(props, attrs);
  6523. const isLink = vue.computed(() => props.link !== false && link.isLink.value);
  6524. const isClickable = vue.computed(() => !props.disabled && props.link !== false && (!!group || props.link || link.isClickable.value));
  6525. const closeProps = vue.computed(() => ({
  6526. 'aria-label': t(props.closeLabel),
  6527. onClick(e) {
  6528. isActive.value = false;
  6529. emit('click:close', e);
  6530. }
  6531. }));
  6532. function onClick(e) {
  6533. emit('click', e);
  6534. if (!isClickable.value) return;
  6535. link.navigate?.(e);
  6536. group?.toggle();
  6537. }
  6538. function onKeyDown(e) {
  6539. if (e.key === 'Enter' || e.key === ' ') {
  6540. e.preventDefault();
  6541. onClick(e);
  6542. }
  6543. }
  6544. return () => {
  6545. const Tag = link.isLink.value ? 'a' : props.tag;
  6546. const hasAppendMedia = !!(props.appendIcon || props.appendAvatar);
  6547. const hasAppend = !!(hasAppendMedia || slots.append);
  6548. const hasClose = !!(slots.close || props.closable);
  6549. const hasFilter = !!(slots.filter || props.filter) && group;
  6550. const hasPrependMedia = !!(props.prependIcon || props.prependAvatar);
  6551. const hasPrepend = !!(hasPrependMedia || slots.prepend);
  6552. const hasColor = !group || group.isSelected.value;
  6553. return isActive.value && vue.withDirectives(vue.createVNode(Tag, {
  6554. "class": ['v-chip', {
  6555. 'v-chip--disabled': props.disabled,
  6556. 'v-chip--label': props.label,
  6557. 'v-chip--link': isClickable.value,
  6558. 'v-chip--filter': hasFilter,
  6559. 'v-chip--pill': props.pill
  6560. }, themeClasses.value, borderClasses.value, hasColor ? colorClasses.value : undefined, densityClasses.value, elevationClasses.value, roundedClasses.value, sizeClasses.value, variantClasses.value, group?.selectedClass.value, props.class],
  6561. "style": [hasColor ? colorStyles.value : undefined, props.style],
  6562. "disabled": props.disabled || undefined,
  6563. "draggable": props.draggable,
  6564. "href": link.href.value,
  6565. "tabindex": isClickable.value ? 0 : undefined,
  6566. "onClick": onClick,
  6567. "onKeydown": isClickable.value && !isLink.value && onKeyDown
  6568. }, {
  6569. default: () => [genOverlays(isClickable.value, 'v-chip'), hasFilter && vue.createVNode(VExpandXTransition, {
  6570. "key": "filter"
  6571. }, {
  6572. default: () => [vue.withDirectives(vue.createVNode("div", {
  6573. "class": "v-chip__filter"
  6574. }, [!slots.filter ? vue.createVNode(VIcon, {
  6575. "key": "filter-icon",
  6576. "icon": props.filterIcon
  6577. }, null) : vue.createVNode(VDefaultsProvider, {
  6578. "key": "filter-defaults",
  6579. "disabled": !props.filterIcon,
  6580. "defaults": {
  6581. VIcon: {
  6582. icon: props.filterIcon
  6583. }
  6584. }
  6585. }, slots.filter)]), [[vue.vShow, group.isSelected.value]])]
  6586. }), hasPrepend && vue.createVNode("div", {
  6587. "key": "prepend",
  6588. "class": "v-chip__prepend"
  6589. }, [!slots.prepend ? vue.createVNode(vue.Fragment, null, [props.prependIcon && vue.createVNode(VIcon, {
  6590. "key": "prepend-icon",
  6591. "icon": props.prependIcon,
  6592. "start": true
  6593. }, null), props.prependAvatar && vue.createVNode(VAvatar, {
  6594. "key": "prepend-avatar",
  6595. "image": props.prependAvatar,
  6596. "start": true
  6597. }, null)]) : vue.createVNode(VDefaultsProvider, {
  6598. "key": "prepend-defaults",
  6599. "disabled": !hasPrependMedia,
  6600. "defaults": {
  6601. VAvatar: {
  6602. image: props.prependAvatar,
  6603. start: true
  6604. },
  6605. VIcon: {
  6606. icon: props.prependIcon,
  6607. start: true
  6608. }
  6609. }
  6610. }, slots.prepend)]), vue.createVNode("div", {
  6611. "class": "v-chip__content"
  6612. }, [slots.default?.({
  6613. isSelected: group?.isSelected.value,
  6614. selectedClass: group?.selectedClass.value,
  6615. select: group?.select,
  6616. toggle: group?.toggle,
  6617. value: group?.value.value,
  6618. disabled: props.disabled
  6619. }) ?? props.text]), hasAppend && vue.createVNode("div", {
  6620. "key": "append",
  6621. "class": "v-chip__append"
  6622. }, [!slots.append ? vue.createVNode(vue.Fragment, null, [props.appendIcon && vue.createVNode(VIcon, {
  6623. "key": "append-icon",
  6624. "end": true,
  6625. "icon": props.appendIcon
  6626. }, null), props.appendAvatar && vue.createVNode(VAvatar, {
  6627. "key": "append-avatar",
  6628. "end": true,
  6629. "image": props.appendAvatar
  6630. }, null)]) : vue.createVNode(VDefaultsProvider, {
  6631. "key": "append-defaults",
  6632. "disabled": !hasAppendMedia,
  6633. "defaults": {
  6634. VAvatar: {
  6635. end: true,
  6636. image: props.appendAvatar
  6637. },
  6638. VIcon: {
  6639. end: true,
  6640. icon: props.appendIcon
  6641. }
  6642. }
  6643. }, slots.append)]), hasClose && vue.createVNode("div", vue.mergeProps({
  6644. "key": "close",
  6645. "class": "v-chip__close"
  6646. }, closeProps.value), [!slots.close ? vue.createVNode(VIcon, {
  6647. "key": "close-icon",
  6648. "icon": props.closeIcon,
  6649. "size": "x-small"
  6650. }, null) : vue.createVNode(VDefaultsProvider, {
  6651. "key": "close-defaults",
  6652. "defaults": {
  6653. VIcon: {
  6654. icon: props.closeIcon,
  6655. size: 'x-small'
  6656. }
  6657. }
  6658. }, slots.close)])]
  6659. }), [[vue.resolveDirective("ripple"), isClickable.value && props.ripple, null]]);
  6660. };
  6661. }
  6662. });
  6663. // Utilities
  6664. // List
  6665. const ListKey = Symbol.for('vuetify:list');
  6666. function createList() {
  6667. const parent = vue.inject(ListKey, {
  6668. hasPrepend: vue.shallowRef(false),
  6669. updateHasPrepend: () => null
  6670. });
  6671. const data = {
  6672. hasPrepend: vue.shallowRef(false),
  6673. updateHasPrepend: value => {
  6674. if (value) data.hasPrepend.value = value;
  6675. }
  6676. };
  6677. vue.provide(ListKey, data);
  6678. return parent;
  6679. }
  6680. function useList() {
  6681. return vue.inject(ListKey, null);
  6682. }
  6683. const singleOpenStrategy = {
  6684. open: _ref => {
  6685. let {
  6686. id,
  6687. value,
  6688. opened,
  6689. parents
  6690. } = _ref;
  6691. if (value) {
  6692. const newOpened = new Set();
  6693. newOpened.add(id);
  6694. let parent = parents.get(id);
  6695. while (parent != null) {
  6696. newOpened.add(parent);
  6697. parent = parents.get(parent);
  6698. }
  6699. return newOpened;
  6700. } else {
  6701. opened.delete(id);
  6702. return opened;
  6703. }
  6704. },
  6705. select: () => null
  6706. };
  6707. const multipleOpenStrategy = {
  6708. open: _ref2 => {
  6709. let {
  6710. id,
  6711. value,
  6712. opened,
  6713. parents
  6714. } = _ref2;
  6715. if (value) {
  6716. let parent = parents.get(id);
  6717. opened.add(id);
  6718. while (parent != null && parent !== id) {
  6719. opened.add(parent);
  6720. parent = parents.get(parent);
  6721. }
  6722. return opened;
  6723. } else {
  6724. opened.delete(id);
  6725. }
  6726. return opened;
  6727. },
  6728. select: () => null
  6729. };
  6730. const listOpenStrategy = {
  6731. open: multipleOpenStrategy.open,
  6732. select: _ref3 => {
  6733. let {
  6734. id,
  6735. value,
  6736. opened,
  6737. parents
  6738. } = _ref3;
  6739. if (!value) return opened;
  6740. const path = [];
  6741. let parent = parents.get(id);
  6742. while (parent != null) {
  6743. path.push(parent);
  6744. parent = parents.get(parent);
  6745. }
  6746. return new Set(path);
  6747. }
  6748. };
  6749. /* eslint-disable sonarjs/no-identical-functions */
  6750. // Utilities
  6751. const independentSelectStrategy = mandatory => {
  6752. const strategy = {
  6753. select: _ref => {
  6754. let {
  6755. id,
  6756. value,
  6757. selected
  6758. } = _ref;
  6759. id = vue.toRaw(id);
  6760. // When mandatory and we're trying to deselect when id
  6761. // is the only currently selected item then do nothing
  6762. if (mandatory && !value) {
  6763. const on = Array.from(selected.entries()).reduce((arr, _ref2) => {
  6764. let [key, value] = _ref2;
  6765. return value === 'on' ? [...arr, key] : arr;
  6766. }, []);
  6767. if (on.length === 1 && on[0] === id) return selected;
  6768. }
  6769. selected.set(id, value ? 'on' : 'off');
  6770. return selected;
  6771. },
  6772. in: (v, children, parents) => {
  6773. let map = new Map();
  6774. for (const id of v || []) {
  6775. map = strategy.select({
  6776. id,
  6777. value: true,
  6778. selected: new Map(map),
  6779. children,
  6780. parents
  6781. });
  6782. }
  6783. return map;
  6784. },
  6785. out: v => {
  6786. const arr = [];
  6787. for (const [key, value] of v.entries()) {
  6788. if (value === 'on') arr.push(key);
  6789. }
  6790. return arr;
  6791. }
  6792. };
  6793. return strategy;
  6794. };
  6795. const independentSingleSelectStrategy = mandatory => {
  6796. const parentStrategy = independentSelectStrategy(mandatory);
  6797. const strategy = {
  6798. select: _ref3 => {
  6799. let {
  6800. selected,
  6801. id,
  6802. ...rest
  6803. } = _ref3;
  6804. id = vue.toRaw(id);
  6805. const singleSelected = selected.has(id) ? new Map([[id, selected.get(id)]]) : new Map();
  6806. return parentStrategy.select({
  6807. ...rest,
  6808. id,
  6809. selected: singleSelected
  6810. });
  6811. },
  6812. in: (v, children, parents) => {
  6813. let map = new Map();
  6814. if (v?.length) {
  6815. map = parentStrategy.in(v.slice(0, 1), children, parents);
  6816. }
  6817. return map;
  6818. },
  6819. out: (v, children, parents) => {
  6820. return parentStrategy.out(v, children, parents);
  6821. }
  6822. };
  6823. return strategy;
  6824. };
  6825. const leafSelectStrategy = mandatory => {
  6826. const parentStrategy = independentSelectStrategy(mandatory);
  6827. const strategy = {
  6828. select: _ref4 => {
  6829. let {
  6830. id,
  6831. selected,
  6832. children,
  6833. ...rest
  6834. } = _ref4;
  6835. id = vue.toRaw(id);
  6836. if (children.has(id)) return selected;
  6837. return parentStrategy.select({
  6838. id,
  6839. selected,
  6840. children,
  6841. ...rest
  6842. });
  6843. },
  6844. in: parentStrategy.in,
  6845. out: parentStrategy.out
  6846. };
  6847. return strategy;
  6848. };
  6849. const leafSingleSelectStrategy = mandatory => {
  6850. const parentStrategy = independentSingleSelectStrategy(mandatory);
  6851. const strategy = {
  6852. select: _ref5 => {
  6853. let {
  6854. id,
  6855. selected,
  6856. children,
  6857. ...rest
  6858. } = _ref5;
  6859. id = vue.toRaw(id);
  6860. if (children.has(id)) return selected;
  6861. return parentStrategy.select({
  6862. id,
  6863. selected,
  6864. children,
  6865. ...rest
  6866. });
  6867. },
  6868. in: parentStrategy.in,
  6869. out: parentStrategy.out
  6870. };
  6871. return strategy;
  6872. };
  6873. const classicSelectStrategy = mandatory => {
  6874. const strategy = {
  6875. select: _ref6 => {
  6876. let {
  6877. id,
  6878. value,
  6879. selected,
  6880. children,
  6881. parents
  6882. } = _ref6;
  6883. id = vue.toRaw(id);
  6884. const original = new Map(selected);
  6885. const items = [id];
  6886. while (items.length) {
  6887. const item = items.shift();
  6888. selected.set(item, value ? 'on' : 'off');
  6889. if (children.has(item)) {
  6890. items.push(...children.get(item));
  6891. }
  6892. }
  6893. let parent = parents.get(id);
  6894. while (parent) {
  6895. const childrenIds = children.get(parent);
  6896. const everySelected = childrenIds.every(cid => selected.get(cid) === 'on');
  6897. const noneSelected = childrenIds.every(cid => !selected.has(cid) || selected.get(cid) === 'off');
  6898. selected.set(parent, everySelected ? 'on' : noneSelected ? 'off' : 'indeterminate');
  6899. parent = parents.get(parent);
  6900. }
  6901. // If mandatory and planned deselect results in no selected
  6902. // items then we can't do it, so return original state
  6903. if (mandatory && !value) {
  6904. const on = Array.from(selected.entries()).reduce((arr, _ref7) => {
  6905. let [key, value] = _ref7;
  6906. return value === 'on' ? [...arr, key] : arr;
  6907. }, []);
  6908. if (on.length === 0) return original;
  6909. }
  6910. return selected;
  6911. },
  6912. in: (v, children, parents) => {
  6913. let map = new Map();
  6914. for (const id of v || []) {
  6915. map = strategy.select({
  6916. id,
  6917. value: true,
  6918. selected: new Map(map),
  6919. children,
  6920. parents
  6921. });
  6922. }
  6923. return map;
  6924. },
  6925. out: (v, children) => {
  6926. const arr = [];
  6927. for (const [key, value] of v.entries()) {
  6928. if (value === 'on' && !children.has(key)) arr.push(key);
  6929. }
  6930. return arr;
  6931. }
  6932. };
  6933. return strategy;
  6934. };
  6935. // Composables
  6936. // Types
  6937. const VNestedSymbol = Symbol.for('vuetify:nested');
  6938. const emptyNested = {
  6939. id: vue.shallowRef(),
  6940. root: {
  6941. register: () => null,
  6942. unregister: () => null,
  6943. parents: vue.ref(new Map()),
  6944. children: vue.ref(new Map()),
  6945. open: () => null,
  6946. openOnSelect: () => null,
  6947. select: () => null,
  6948. opened: vue.ref(new Set()),
  6949. selected: vue.ref(new Map()),
  6950. selectedValues: vue.ref([])
  6951. }
  6952. };
  6953. const makeNestedProps = propsFactory({
  6954. selectStrategy: [String, Function],
  6955. openStrategy: [String, Object],
  6956. opened: Array,
  6957. selected: Array,
  6958. mandatory: Boolean
  6959. }, 'nested');
  6960. const useNested = props => {
  6961. let isUnmounted = false;
  6962. const children = vue.ref(new Map());
  6963. const parents = vue.ref(new Map());
  6964. const opened = useProxiedModel(props, 'opened', props.opened, v => new Set(v), v => [...v.values()]);
  6965. const selectStrategy = vue.computed(() => {
  6966. if (typeof props.selectStrategy === 'object') return props.selectStrategy;
  6967. switch (props.selectStrategy) {
  6968. case 'single-leaf':
  6969. return leafSingleSelectStrategy(props.mandatory);
  6970. case 'leaf':
  6971. return leafSelectStrategy(props.mandatory);
  6972. case 'independent':
  6973. return independentSelectStrategy(props.mandatory);
  6974. case 'single-independent':
  6975. return independentSingleSelectStrategy(props.mandatory);
  6976. case 'classic':
  6977. default:
  6978. return classicSelectStrategy(props.mandatory);
  6979. }
  6980. });
  6981. const openStrategy = vue.computed(() => {
  6982. if (typeof props.openStrategy === 'object') return props.openStrategy;
  6983. switch (props.openStrategy) {
  6984. case 'list':
  6985. return listOpenStrategy;
  6986. case 'single':
  6987. return singleOpenStrategy;
  6988. case 'multiple':
  6989. default:
  6990. return multipleOpenStrategy;
  6991. }
  6992. });
  6993. 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));
  6994. vue.onBeforeUnmount(() => {
  6995. isUnmounted = true;
  6996. });
  6997. function getPath(id) {
  6998. const path = [];
  6999. let parent = id;
  7000. while (parent != null) {
  7001. path.unshift(parent);
  7002. parent = parents.value.get(parent);
  7003. }
  7004. return path;
  7005. }
  7006. const vm = getCurrentInstance('nested');
  7007. const nested = {
  7008. id: vue.shallowRef(),
  7009. root: {
  7010. opened,
  7011. selected,
  7012. selectedValues: vue.computed(() => {
  7013. const arr = [];
  7014. for (const [key, value] of selected.value.entries()) {
  7015. if (value === 'on') arr.push(key);
  7016. }
  7017. return arr;
  7018. }),
  7019. register: (id, parentId, isGroup) => {
  7020. parentId && id !== parentId && parents.value.set(id, parentId);
  7021. isGroup && children.value.set(id, []);
  7022. if (parentId != null) {
  7023. children.value.set(parentId, [...(children.value.get(parentId) || []), id]);
  7024. }
  7025. },
  7026. unregister: id => {
  7027. if (isUnmounted) return;
  7028. children.value.delete(id);
  7029. const parent = parents.value.get(id);
  7030. if (parent) {
  7031. const list = children.value.get(parent) ?? [];
  7032. children.value.set(parent, list.filter(child => child !== id));
  7033. }
  7034. parents.value.delete(id);
  7035. opened.value.delete(id);
  7036. },
  7037. open: (id, value, event) => {
  7038. vm.emit('click:open', {
  7039. id,
  7040. value,
  7041. path: getPath(id),
  7042. event
  7043. });
  7044. const newOpened = openStrategy.value.open({
  7045. id,
  7046. value,
  7047. opened: new Set(opened.value),
  7048. children: children.value,
  7049. parents: parents.value,
  7050. event
  7051. });
  7052. newOpened && (opened.value = newOpened);
  7053. },
  7054. openOnSelect: (id, value, event) => {
  7055. const newOpened = openStrategy.value.select({
  7056. id,
  7057. value,
  7058. selected: new Map(selected.value),
  7059. opened: new Set(opened.value),
  7060. children: children.value,
  7061. parents: parents.value,
  7062. event
  7063. });
  7064. newOpened && (opened.value = newOpened);
  7065. },
  7066. select: (id, value, event) => {
  7067. vm.emit('click:select', {
  7068. id,
  7069. value,
  7070. path: getPath(id),
  7071. event
  7072. });
  7073. const newSelected = selectStrategy.value.select({
  7074. id,
  7075. value,
  7076. selected: new Map(selected.value),
  7077. children: children.value,
  7078. parents: parents.value,
  7079. event
  7080. });
  7081. newSelected && (selected.value = newSelected);
  7082. nested.root.openOnSelect(id, value, event);
  7083. },
  7084. children,
  7085. parents
  7086. }
  7087. };
  7088. vue.provide(VNestedSymbol, nested);
  7089. return nested.root;
  7090. };
  7091. const useNestedItem = (id, isGroup) => {
  7092. const parent = vue.inject(VNestedSymbol, emptyNested);
  7093. const uidSymbol = Symbol(getUid());
  7094. const computedId = vue.computed(() => id.value !== undefined ? id.value : uidSymbol);
  7095. const item = {
  7096. ...parent,
  7097. id: computedId,
  7098. open: (open, e) => parent.root.open(computedId.value, open, e),
  7099. openOnSelect: (open, e) => parent.root.openOnSelect(computedId.value, open, e),
  7100. isOpen: vue.computed(() => parent.root.opened.value.has(computedId.value)),
  7101. parent: vue.computed(() => parent.root.parents.value.get(computedId.value)),
  7102. select: (selected, e) => parent.root.select(computedId.value, selected, e),
  7103. isSelected: vue.computed(() => parent.root.selected.value.get(vue.toRaw(computedId.value)) === 'on'),
  7104. isIndeterminate: vue.computed(() => parent.root.selected.value.get(computedId.value) === 'indeterminate'),
  7105. isLeaf: vue.computed(() => !parent.root.children.value.get(computedId.value)),
  7106. isGroupActivator: parent.isGroupActivator
  7107. };
  7108. !parent.isGroupActivator && parent.root.register(computedId.value, parent.id.value, isGroup);
  7109. vue.onBeforeUnmount(() => {
  7110. !parent.isGroupActivator && parent.root.unregister(computedId.value);
  7111. });
  7112. isGroup && vue.provide(VNestedSymbol, item);
  7113. return item;
  7114. };
  7115. const useNestedGroupActivator = () => {
  7116. const parent = vue.inject(VNestedSymbol, emptyNested);
  7117. vue.provide(VNestedSymbol, {
  7118. ...parent,
  7119. isGroupActivator: true
  7120. });
  7121. };
  7122. const VListGroupActivator = defineComponent({
  7123. name: 'VListGroupActivator',
  7124. setup(_, _ref) {
  7125. let {
  7126. slots
  7127. } = _ref;
  7128. useNestedGroupActivator();
  7129. return () => slots.default?.();
  7130. }
  7131. });
  7132. const makeVListGroupProps = propsFactory({
  7133. /* @deprecated */
  7134. activeColor: String,
  7135. baseColor: String,
  7136. color: String,
  7137. collapseIcon: {
  7138. type: IconValue,
  7139. default: '$collapse'
  7140. },
  7141. expandIcon: {
  7142. type: IconValue,
  7143. default: '$expand'
  7144. },
  7145. prependIcon: IconValue,
  7146. appendIcon: IconValue,
  7147. fluid: Boolean,
  7148. subgroup: Boolean,
  7149. title: String,
  7150. value: null,
  7151. ...makeComponentProps(),
  7152. ...makeTagProps()
  7153. }, 'VListGroup');
  7154. const VListGroup = genericComponent()({
  7155. name: 'VListGroup',
  7156. props: makeVListGroupProps(),
  7157. setup(props, _ref2) {
  7158. let {
  7159. slots
  7160. } = _ref2;
  7161. const {
  7162. isOpen,
  7163. open,
  7164. id: _id
  7165. } = useNestedItem(vue.toRef(props, 'value'), true);
  7166. const id = vue.computed(() => `v-list-group--id-${String(_id.value)}`);
  7167. const list = useList();
  7168. const {
  7169. isBooted
  7170. } = useSsrBoot();
  7171. function onClick(e) {
  7172. open(!isOpen.value, e);
  7173. }
  7174. const activatorProps = vue.computed(() => ({
  7175. onClick,
  7176. class: 'v-list-group__header',
  7177. id: id.value
  7178. }));
  7179. const toggleIcon = vue.computed(() => isOpen.value ? props.collapseIcon : props.expandIcon);
  7180. const activatorDefaults = vue.computed(() => ({
  7181. VListItem: {
  7182. active: isOpen.value,
  7183. activeColor: props.activeColor,
  7184. baseColor: props.baseColor,
  7185. color: props.color,
  7186. prependIcon: props.prependIcon || props.subgroup && toggleIcon.value,
  7187. appendIcon: props.appendIcon || !props.subgroup && toggleIcon.value,
  7188. title: props.title,
  7189. value: props.value
  7190. }
  7191. }));
  7192. useRender(() => vue.createVNode(props.tag, {
  7193. "class": ['v-list-group', {
  7194. 'v-list-group--prepend': list?.hasPrepend.value,
  7195. 'v-list-group--fluid': props.fluid,
  7196. 'v-list-group--subgroup': props.subgroup,
  7197. 'v-list-group--open': isOpen.value
  7198. }, props.class],
  7199. "style": props.style
  7200. }, {
  7201. default: () => [slots.activator && vue.createVNode(VDefaultsProvider, {
  7202. "defaults": activatorDefaults.value
  7203. }, {
  7204. default: () => [vue.createVNode(VListGroupActivator, null, {
  7205. default: () => [slots.activator({
  7206. props: activatorProps.value,
  7207. isOpen: isOpen.value
  7208. })]
  7209. })]
  7210. }), vue.createVNode(MaybeTransition, {
  7211. "transition": {
  7212. component: VExpandTransition
  7213. },
  7214. "disabled": !isBooted.value
  7215. }, {
  7216. default: () => [vue.withDirectives(vue.createVNode("div", {
  7217. "class": "v-list-group__items",
  7218. "role": "group",
  7219. "aria-labelledby": id.value
  7220. }, [slots.default?.()]), [[vue.vShow, isOpen.value]])]
  7221. })]
  7222. }));
  7223. return {};
  7224. }
  7225. });
  7226. // Utilities
  7227. const VListItemSubtitle = createSimpleFunctional('v-list-item-subtitle');
  7228. // Utilities
  7229. const VListItemTitle = createSimpleFunctional('v-list-item-title');
  7230. // Types
  7231. const makeVListItemProps = propsFactory({
  7232. active: {
  7233. type: Boolean,
  7234. default: undefined
  7235. },
  7236. activeClass: String,
  7237. /* @deprecated */
  7238. activeColor: String,
  7239. appendAvatar: String,
  7240. appendIcon: IconValue,
  7241. baseColor: String,
  7242. disabled: Boolean,
  7243. lines: String,
  7244. link: {
  7245. type: Boolean,
  7246. default: undefined
  7247. },
  7248. nav: Boolean,
  7249. prependAvatar: String,
  7250. prependIcon: IconValue,
  7251. ripple: {
  7252. type: [Boolean, Object],
  7253. default: true
  7254. },
  7255. subtitle: [String, Number, Boolean],
  7256. title: [String, Number, Boolean],
  7257. value: null,
  7258. onClick: EventProp(),
  7259. onClickOnce: EventProp(),
  7260. ...makeBorderProps(),
  7261. ...makeComponentProps(),
  7262. ...makeDensityProps(),
  7263. ...makeDimensionProps(),
  7264. ...makeElevationProps(),
  7265. ...makeRoundedProps(),
  7266. ...makeRouterProps(),
  7267. ...makeTagProps(),
  7268. ...makeThemeProps(),
  7269. ...makeVariantProps({
  7270. variant: 'text'
  7271. })
  7272. }, 'VListItem');
  7273. const VListItem = genericComponent()({
  7274. name: 'VListItem',
  7275. directives: {
  7276. Ripple
  7277. },
  7278. props: makeVListItemProps(),
  7279. emits: {
  7280. click: e => true
  7281. },
  7282. setup(props, _ref) {
  7283. let {
  7284. attrs,
  7285. slots,
  7286. emit
  7287. } = _ref;
  7288. const link = useLink(props, attrs);
  7289. const id = vue.computed(() => props.value === undefined ? link.href.value : props.value);
  7290. const {
  7291. select,
  7292. isSelected,
  7293. isIndeterminate,
  7294. isGroupActivator,
  7295. root,
  7296. parent,
  7297. openOnSelect
  7298. } = useNestedItem(id, false);
  7299. const list = useList();
  7300. const isActive = vue.computed(() => props.active !== false && (props.active || link.isActive?.value || isSelected.value));
  7301. const isLink = vue.computed(() => props.link !== false && link.isLink.value);
  7302. const isClickable = vue.computed(() => !props.disabled && props.link !== false && (props.link || link.isClickable.value || props.value != null && !!list));
  7303. const roundedProps = vue.computed(() => props.rounded || props.nav);
  7304. const color = vue.computed(() => props.color ?? props.activeColor);
  7305. const variantProps = vue.computed(() => ({
  7306. color: isActive.value ? color.value ?? props.baseColor : props.baseColor,
  7307. variant: props.variant
  7308. }));
  7309. vue.watch(() => link.isActive?.value, val => {
  7310. if (val && parent.value != null) {
  7311. root.open(parent.value, true);
  7312. }
  7313. if (val) {
  7314. openOnSelect(val);
  7315. }
  7316. }, {
  7317. immediate: true
  7318. });
  7319. const {
  7320. themeClasses
  7321. } = provideTheme(props);
  7322. const {
  7323. borderClasses
  7324. } = useBorder(props);
  7325. const {
  7326. colorClasses,
  7327. colorStyles,
  7328. variantClasses
  7329. } = useVariant(variantProps);
  7330. const {
  7331. densityClasses
  7332. } = useDensity(props);
  7333. const {
  7334. dimensionStyles
  7335. } = useDimension(props);
  7336. const {
  7337. elevationClasses
  7338. } = useElevation(props);
  7339. const {
  7340. roundedClasses
  7341. } = useRounded(roundedProps);
  7342. const lineClasses = vue.computed(() => props.lines ? `v-list-item--${props.lines}-line` : undefined);
  7343. const slotProps = vue.computed(() => ({
  7344. isActive: isActive.value,
  7345. select,
  7346. isSelected: isSelected.value,
  7347. isIndeterminate: isIndeterminate.value
  7348. }));
  7349. function onClick(e) {
  7350. emit('click', e);
  7351. if (isGroupActivator || !isClickable.value) return;
  7352. link.navigate?.(e);
  7353. props.value != null && select(!isSelected.value, e);
  7354. }
  7355. function onKeyDown(e) {
  7356. if (e.key === 'Enter' || e.key === ' ') {
  7357. e.preventDefault();
  7358. onClick(e);
  7359. }
  7360. }
  7361. useRender(() => {
  7362. const Tag = isLink.value ? 'a' : props.tag;
  7363. const hasTitle = slots.title || props.title;
  7364. const hasSubtitle = slots.subtitle || props.subtitle;
  7365. const hasAppendMedia = !!(props.appendAvatar || props.appendIcon);
  7366. const hasAppend = !!(hasAppendMedia || slots.append);
  7367. const hasPrependMedia = !!(props.prependAvatar || props.prependIcon);
  7368. const hasPrepend = !!(hasPrependMedia || slots.prepend);
  7369. list?.updateHasPrepend(hasPrepend);
  7370. if (props.activeColor) {
  7371. deprecate('active-color', ['color', 'base-color']);
  7372. }
  7373. return vue.withDirectives(vue.createVNode(Tag, {
  7374. "class": ['v-list-item', {
  7375. 'v-list-item--active': isActive.value,
  7376. 'v-list-item--disabled': props.disabled,
  7377. 'v-list-item--link': isClickable.value,
  7378. 'v-list-item--nav': props.nav,
  7379. 'v-list-item--prepend': !hasPrepend && list?.hasPrepend.value,
  7380. [`${props.activeClass}`]: props.activeClass && isActive.value
  7381. }, themeClasses.value, borderClasses.value, colorClasses.value, densityClasses.value, elevationClasses.value, lineClasses.value, roundedClasses.value, variantClasses.value, props.class],
  7382. "style": [colorStyles.value, dimensionStyles.value, props.style],
  7383. "href": link.href.value,
  7384. "tabindex": isClickable.value ? list ? -2 : 0 : undefined,
  7385. "onClick": onClick,
  7386. "onKeydown": isClickable.value && !isLink.value && onKeyDown
  7387. }, {
  7388. default: () => [genOverlays(isClickable.value || isActive.value, 'v-list-item'), hasPrepend && vue.createVNode("div", {
  7389. "key": "prepend",
  7390. "class": "v-list-item__prepend"
  7391. }, [!slots.prepend ? vue.createVNode(vue.Fragment, null, [props.prependAvatar && vue.createVNode(VAvatar, {
  7392. "key": "prepend-avatar",
  7393. "density": props.density,
  7394. "image": props.prependAvatar
  7395. }, null), props.prependIcon && vue.createVNode(VIcon, {
  7396. "key": "prepend-icon",
  7397. "density": props.density,
  7398. "icon": props.prependIcon
  7399. }, null)]) : vue.createVNode(VDefaultsProvider, {
  7400. "key": "prepend-defaults",
  7401. "disabled": !hasPrependMedia,
  7402. "defaults": {
  7403. VAvatar: {
  7404. density: props.density,
  7405. image: props.prependAvatar
  7406. },
  7407. VIcon: {
  7408. density: props.density,
  7409. icon: props.prependIcon
  7410. },
  7411. VListItemAction: {
  7412. start: true
  7413. }
  7414. }
  7415. }, {
  7416. default: () => [slots.prepend?.(slotProps.value)]
  7417. })]), vue.createVNode("div", {
  7418. "class": "v-list-item__content",
  7419. "data-no-activator": ""
  7420. }, [hasTitle && vue.createVNode(VListItemTitle, {
  7421. "key": "title"
  7422. }, {
  7423. default: () => [slots.title?.({
  7424. title: props.title
  7425. }) ?? props.title]
  7426. }), hasSubtitle && vue.createVNode(VListItemSubtitle, {
  7427. "key": "subtitle"
  7428. }, {
  7429. default: () => [slots.subtitle?.({
  7430. subtitle: props.subtitle
  7431. }) ?? props.subtitle]
  7432. }), slots.default?.(slotProps.value)]), hasAppend && vue.createVNode("div", {
  7433. "key": "append",
  7434. "class": "v-list-item__append"
  7435. }, [!slots.append ? vue.createVNode(vue.Fragment, null, [props.appendIcon && vue.createVNode(VIcon, {
  7436. "key": "append-icon",
  7437. "density": props.density,
  7438. "icon": props.appendIcon
  7439. }, null), props.appendAvatar && vue.createVNode(VAvatar, {
  7440. "key": "append-avatar",
  7441. "density": props.density,
  7442. "image": props.appendAvatar
  7443. }, null)]) : vue.createVNode(VDefaultsProvider, {
  7444. "key": "append-defaults",
  7445. "disabled": !hasAppendMedia,
  7446. "defaults": {
  7447. VAvatar: {
  7448. density: props.density,
  7449. image: props.appendAvatar
  7450. },
  7451. VIcon: {
  7452. density: props.density,
  7453. icon: props.appendIcon
  7454. },
  7455. VListItemAction: {
  7456. end: true
  7457. }
  7458. }
  7459. }, {
  7460. default: () => [slots.append?.(slotProps.value)]
  7461. })])]
  7462. }), [[vue.resolveDirective("ripple"), isClickable.value && props.ripple]]);
  7463. });
  7464. return {};
  7465. }
  7466. });
  7467. const makeVListSubheaderProps = propsFactory({
  7468. color: String,
  7469. inset: Boolean,
  7470. sticky: Boolean,
  7471. title: String,
  7472. ...makeComponentProps(),
  7473. ...makeTagProps()
  7474. }, 'VListSubheader');
  7475. const VListSubheader = genericComponent()({
  7476. name: 'VListSubheader',
  7477. props: makeVListSubheaderProps(),
  7478. setup(props, _ref) {
  7479. let {
  7480. slots
  7481. } = _ref;
  7482. const {
  7483. textColorClasses,
  7484. textColorStyles
  7485. } = useTextColor(vue.toRef(props, 'color'));
  7486. useRender(() => {
  7487. const hasText = !!(slots.default || props.title);
  7488. return vue.createVNode(props.tag, {
  7489. "class": ['v-list-subheader', {
  7490. 'v-list-subheader--inset': props.inset,
  7491. 'v-list-subheader--sticky': props.sticky
  7492. }, textColorClasses.value, props.class],
  7493. "style": [{
  7494. textColorStyles
  7495. }, props.style]
  7496. }, {
  7497. default: () => [hasText && vue.createVNode("div", {
  7498. "class": "v-list-subheader__text"
  7499. }, [slots.default?.() ?? props.title])]
  7500. });
  7501. });
  7502. return {};
  7503. }
  7504. });
  7505. const makeVDividerProps = propsFactory({
  7506. color: String,
  7507. inset: Boolean,
  7508. length: [Number, String],
  7509. thickness: [Number, String],
  7510. vertical: Boolean,
  7511. ...makeComponentProps(),
  7512. ...makeThemeProps()
  7513. }, 'VDivider');
  7514. const VDivider = genericComponent()({
  7515. name: 'VDivider',
  7516. props: makeVDividerProps(),
  7517. setup(props, _ref) {
  7518. let {
  7519. attrs
  7520. } = _ref;
  7521. const {
  7522. themeClasses
  7523. } = provideTheme(props);
  7524. const {
  7525. textColorClasses,
  7526. textColorStyles
  7527. } = useTextColor(vue.toRef(props, 'color'));
  7528. const dividerStyles = vue.computed(() => {
  7529. const styles = {};
  7530. if (props.length) {
  7531. styles[props.vertical ? 'maxHeight' : 'maxWidth'] = convertToUnit(props.length);
  7532. }
  7533. if (props.thickness) {
  7534. styles[props.vertical ? 'borderRightWidth' : 'borderTopWidth'] = convertToUnit(props.thickness);
  7535. }
  7536. return styles;
  7537. });
  7538. useRender(() => vue.createVNode("hr", {
  7539. "class": [{
  7540. 'v-divider': true,
  7541. 'v-divider--inset': props.inset,
  7542. 'v-divider--vertical': props.vertical
  7543. }, themeClasses.value, textColorClasses.value, props.class],
  7544. "style": [dividerStyles.value, textColorStyles.value, props.style],
  7545. "aria-orientation": !attrs.role || attrs.role === 'separator' ? props.vertical ? 'vertical' : 'horizontal' : undefined,
  7546. "role": `${attrs.role || 'separator'}`
  7547. }, null));
  7548. return {};
  7549. }
  7550. });
  7551. // Types
  7552. const makeVListChildrenProps = propsFactory({
  7553. items: Array
  7554. }, 'VListChildren');
  7555. const VListChildren = genericComponent()({
  7556. name: 'VListChildren',
  7557. props: makeVListChildrenProps(),
  7558. setup(props, _ref) {
  7559. let {
  7560. slots
  7561. } = _ref;
  7562. createList();
  7563. return () => slots.default?.() ?? props.items?.map(_ref2 => {
  7564. let {
  7565. children,
  7566. props: itemProps,
  7567. type,
  7568. raw: item
  7569. } = _ref2;
  7570. if (type === 'divider') {
  7571. return slots.divider?.({
  7572. props: itemProps
  7573. }) ?? vue.createVNode(VDivider, itemProps, null);
  7574. }
  7575. if (type === 'subheader') {
  7576. return slots.subheader?.({
  7577. props: itemProps
  7578. }) ?? vue.createVNode(VListSubheader, itemProps, null);
  7579. }
  7580. const slotsWithItem = {
  7581. subtitle: slots.subtitle ? slotProps => slots.subtitle?.({
  7582. ...slotProps,
  7583. item
  7584. }) : undefined,
  7585. prepend: slots.prepend ? slotProps => slots.prepend?.({
  7586. ...slotProps,
  7587. item
  7588. }) : undefined,
  7589. append: slots.append ? slotProps => slots.append?.({
  7590. ...slotProps,
  7591. item
  7592. }) : undefined,
  7593. title: slots.title ? slotProps => slots.title?.({
  7594. ...slotProps,
  7595. item
  7596. }) : undefined
  7597. };
  7598. const [listGroupProps, _1] = VListGroup.filterProps(itemProps);
  7599. return children ? vue.createVNode(VListGroup, vue.mergeProps({
  7600. "value": itemProps?.value
  7601. }, listGroupProps), {
  7602. activator: _ref3 => {
  7603. let {
  7604. props: activatorProps
  7605. } = _ref3;
  7606. return slots.header ? slots.header({
  7607. props: {
  7608. ...itemProps,
  7609. ...activatorProps
  7610. }
  7611. }) : vue.createVNode(VListItem, vue.mergeProps(itemProps, activatorProps), slotsWithItem);
  7612. },
  7613. default: () => vue.createVNode(VListChildren, {
  7614. "items": children
  7615. }, slots)
  7616. }) : slots.item ? slots.item({
  7617. props: itemProps
  7618. }) : vue.createVNode(VListItem, itemProps, slotsWithItem);
  7619. });
  7620. }
  7621. });
  7622. // Utilities
  7623. // Types
  7624. // Composables
  7625. const makeItemsProps = propsFactory({
  7626. items: {
  7627. type: Array,
  7628. default: () => []
  7629. },
  7630. itemTitle: {
  7631. type: [String, Array, Function],
  7632. default: 'title'
  7633. },
  7634. itemValue: {
  7635. type: [String, Array, Function],
  7636. default: 'value'
  7637. },
  7638. itemChildren: {
  7639. type: [Boolean, String, Array, Function],
  7640. default: 'children'
  7641. },
  7642. itemProps: {
  7643. type: [Boolean, String, Array, Function],
  7644. default: 'props'
  7645. },
  7646. returnObject: Boolean
  7647. }, 'list-items');
  7648. function transformItem$1(props, item) {
  7649. const title = getPropertyFromItem(item, props.itemTitle, item);
  7650. const value = props.returnObject ? item : getPropertyFromItem(item, props.itemValue, title);
  7651. const children = getPropertyFromItem(item, props.itemChildren);
  7652. const itemProps = props.itemProps === true ? typeof item === 'object' && item != null && !Array.isArray(item) ? 'children' in item ? pick(item, ['children'])[1] : item : undefined : getPropertyFromItem(item, props.itemProps);
  7653. const _props = {
  7654. title,
  7655. value,
  7656. ...itemProps
  7657. };
  7658. return {
  7659. title: String(_props.title ?? ''),
  7660. value: _props.value,
  7661. props: _props,
  7662. children: Array.isArray(children) ? transformItems$1(props, children) : undefined,
  7663. raw: item
  7664. };
  7665. }
  7666. function transformItems$1(props, items) {
  7667. const array = [];
  7668. for (const item of items) {
  7669. array.push(transformItem$1(props, item));
  7670. }
  7671. return array;
  7672. }
  7673. function useItems(props) {
  7674. const items = vue.computed(() => transformItems$1(props, props.items));
  7675. return useTransformItems(items, value => transformItem$1(props, value));
  7676. }
  7677. function useTransformItems(items, transform) {
  7678. function transformIn(value) {
  7679. return value
  7680. // When the model value is null, returns an InternalItem based on null
  7681. // only if null is one of the items
  7682. .filter(v => v !== null || items.value.some(item => item.value === null)).map(v => {
  7683. const existingItem = items.value.find(item => deepEqual(v, item.value));
  7684. // Nullish existingItem means value is a custom input value from combobox
  7685. // In this case, use transformItem to create an InternalItem based on value
  7686. return existingItem ?? transform(v);
  7687. });
  7688. }
  7689. function transformOut(value) {
  7690. return value.map(_ref => {
  7691. let {
  7692. value
  7693. } = _ref;
  7694. return value;
  7695. });
  7696. }
  7697. return {
  7698. items,
  7699. transformIn,
  7700. transformOut
  7701. };
  7702. }
  7703. // Types
  7704. function isPrimitive(value) {
  7705. return typeof value === 'string' || typeof value === 'number' || typeof value === 'boolean';
  7706. }
  7707. function transformItem(props, item) {
  7708. const type = getPropertyFromItem(item, props.itemType, 'item');
  7709. const title = isPrimitive(item) ? item : getPropertyFromItem(item, props.itemTitle);
  7710. const value = getPropertyFromItem(item, props.itemValue, undefined);
  7711. const children = getPropertyFromItem(item, props.itemChildren);
  7712. const itemProps = props.itemProps === true ? pick(item, ['children'])[1] : getPropertyFromItem(item, props.itemProps);
  7713. const _props = {
  7714. title,
  7715. value,
  7716. ...itemProps
  7717. };
  7718. return {
  7719. type,
  7720. title: _props.title,
  7721. value: _props.value,
  7722. props: _props,
  7723. children: type === 'item' && children ? transformItems(props, children) : undefined,
  7724. raw: item
  7725. };
  7726. }
  7727. function transformItems(props, items) {
  7728. const array = [];
  7729. for (const item of items) {
  7730. array.push(transformItem(props, item));
  7731. }
  7732. return array;
  7733. }
  7734. function useListItems(props) {
  7735. const items = vue.computed(() => transformItems(props, props.items));
  7736. return {
  7737. items
  7738. };
  7739. }
  7740. const makeVListProps = propsFactory({
  7741. baseColor: String,
  7742. /* @deprecated */
  7743. activeColor: String,
  7744. activeClass: String,
  7745. bgColor: String,
  7746. disabled: Boolean,
  7747. lines: {
  7748. type: [Boolean, String],
  7749. default: 'one'
  7750. },
  7751. nav: Boolean,
  7752. ...makeNestedProps({
  7753. selectStrategy: 'single-leaf',
  7754. openStrategy: 'list'
  7755. }),
  7756. ...makeBorderProps(),
  7757. ...makeComponentProps(),
  7758. ...makeDensityProps(),
  7759. ...makeDimensionProps(),
  7760. ...makeElevationProps(),
  7761. itemType: {
  7762. type: String,
  7763. default: 'type'
  7764. },
  7765. ...makeItemsProps(),
  7766. ...makeRoundedProps(),
  7767. ...makeTagProps(),
  7768. ...makeThemeProps(),
  7769. ...makeVariantProps({
  7770. variant: 'text'
  7771. })
  7772. }, 'VList');
  7773. const VList = genericComponent()({
  7774. name: 'VList',
  7775. props: makeVListProps(),
  7776. emits: {
  7777. 'update:selected': val => true,
  7778. 'update:opened': val => true,
  7779. 'click:open': value => true,
  7780. 'click:select': value => true
  7781. },
  7782. setup(props, _ref) {
  7783. let {
  7784. slots
  7785. } = _ref;
  7786. const {
  7787. items
  7788. } = useListItems(props);
  7789. const {
  7790. themeClasses
  7791. } = provideTheme(props);
  7792. const {
  7793. backgroundColorClasses,
  7794. backgroundColorStyles
  7795. } = useBackgroundColor(vue.toRef(props, 'bgColor'));
  7796. const {
  7797. borderClasses
  7798. } = useBorder(props);
  7799. const {
  7800. densityClasses
  7801. } = useDensity(props);
  7802. const {
  7803. dimensionStyles
  7804. } = useDimension(props);
  7805. const {
  7806. elevationClasses
  7807. } = useElevation(props);
  7808. const {
  7809. roundedClasses
  7810. } = useRounded(props);
  7811. const {
  7812. open,
  7813. select
  7814. } = useNested(props);
  7815. const lineClasses = vue.computed(() => props.lines ? `v-list--${props.lines}-line` : undefined);
  7816. const activeColor = vue.toRef(props, 'activeColor');
  7817. const baseColor = vue.toRef(props, 'baseColor');
  7818. const color = vue.toRef(props, 'color');
  7819. createList();
  7820. provideDefaults({
  7821. VListGroup: {
  7822. activeColor,
  7823. baseColor,
  7824. color
  7825. },
  7826. VListItem: {
  7827. activeClass: vue.toRef(props, 'activeClass'),
  7828. activeColor,
  7829. baseColor,
  7830. color,
  7831. density: vue.toRef(props, 'density'),
  7832. disabled: vue.toRef(props, 'disabled'),
  7833. lines: vue.toRef(props, 'lines'),
  7834. nav: vue.toRef(props, 'nav'),
  7835. variant: vue.toRef(props, 'variant')
  7836. }
  7837. });
  7838. const isFocused = vue.shallowRef(false);
  7839. const contentRef = vue.ref();
  7840. function onFocusin(e) {
  7841. isFocused.value = true;
  7842. }
  7843. function onFocusout(e) {
  7844. isFocused.value = false;
  7845. }
  7846. function onFocus(e) {
  7847. if (!isFocused.value && !(e.relatedTarget && contentRef.value?.contains(e.relatedTarget))) focus();
  7848. }
  7849. function onKeydown(e) {
  7850. if (!contentRef.value) return;
  7851. if (e.key === 'ArrowDown') {
  7852. focus('next');
  7853. } else if (e.key === 'ArrowUp') {
  7854. focus('prev');
  7855. } else if (e.key === 'Home') {
  7856. focus('first');
  7857. } else if (e.key === 'End') {
  7858. focus('last');
  7859. } else {
  7860. return;
  7861. }
  7862. e.preventDefault();
  7863. }
  7864. function focus(location) {
  7865. if (contentRef.value) {
  7866. return focusChild(contentRef.value, location);
  7867. }
  7868. }
  7869. useRender(() => {
  7870. return vue.createVNode(props.tag, {
  7871. "ref": contentRef,
  7872. "class": ['v-list', {
  7873. 'v-list--disabled': props.disabled,
  7874. 'v-list--nav': props.nav
  7875. }, themeClasses.value, backgroundColorClasses.value, borderClasses.value, densityClasses.value, elevationClasses.value, lineClasses.value, roundedClasses.value, props.class],
  7876. "style": [backgroundColorStyles.value, dimensionStyles.value, props.style],
  7877. "tabindex": props.disabled || isFocused.value ? -1 : 0,
  7878. "role": "listbox",
  7879. "aria-activedescendant": undefined,
  7880. "onFocusin": onFocusin,
  7881. "onFocusout": onFocusout,
  7882. "onFocus": onFocus,
  7883. "onKeydown": onKeydown
  7884. }, {
  7885. default: () => [vue.createVNode(VListChildren, {
  7886. "items": items.value
  7887. }, slots)]
  7888. });
  7889. });
  7890. return {
  7891. open,
  7892. select,
  7893. focus
  7894. };
  7895. }
  7896. });
  7897. // Utilities
  7898. const VListImg = createSimpleFunctional('v-list-img');
  7899. const makeVListItemActionProps = propsFactory({
  7900. start: Boolean,
  7901. end: Boolean,
  7902. ...makeComponentProps(),
  7903. ...makeTagProps()
  7904. }, 'VListItemAction');
  7905. const VListItemAction = genericComponent()({
  7906. name: 'VListItemAction',
  7907. props: makeVListItemActionProps(),
  7908. setup(props, _ref) {
  7909. let {
  7910. slots
  7911. } = _ref;
  7912. useRender(() => vue.createVNode(props.tag, {
  7913. "class": ['v-list-item-action', {
  7914. 'v-list-item-action--start': props.start,
  7915. 'v-list-item-action--end': props.end
  7916. }, props.class],
  7917. "style": props.style
  7918. }, slots));
  7919. return {};
  7920. }
  7921. });
  7922. const makeVListItemMediaProps = propsFactory({
  7923. start: Boolean,
  7924. end: Boolean,
  7925. ...makeComponentProps(),
  7926. ...makeTagProps()
  7927. }, 'VListItemMedia');
  7928. const VListItemMedia = genericComponent()({
  7929. name: 'VListItemMedia',
  7930. props: makeVListItemMediaProps(),
  7931. setup(props, _ref) {
  7932. let {
  7933. slots
  7934. } = _ref;
  7935. useRender(() => {
  7936. return vue.createVNode(props.tag, {
  7937. "class": ['v-list-item-media', {
  7938. 'v-list-item-media--start': props.start,
  7939. 'v-list-item-media--end': props.end
  7940. }, props.class],
  7941. "style": props.style
  7942. }, slots);
  7943. });
  7944. return {};
  7945. }
  7946. });
  7947. // Types
  7948. /** Convert a point in local space to viewport space */
  7949. function elementToViewport(point, offset) {
  7950. return {
  7951. x: point.x + offset.x,
  7952. y: point.y + offset.y
  7953. };
  7954. }
  7955. /** Get the difference between two points */
  7956. function getOffset$1(a, b) {
  7957. return {
  7958. x: a.x - b.x,
  7959. y: a.y - b.y
  7960. };
  7961. }
  7962. /** Convert an anchor object to a point in local space */
  7963. function anchorToPoint(anchor, box) {
  7964. if (anchor.side === 'top' || anchor.side === 'bottom') {
  7965. const {
  7966. side,
  7967. align
  7968. } = anchor;
  7969. const x = align === 'left' ? 0 : align === 'center' ? box.width / 2 : align === 'right' ? box.width : align;
  7970. const y = side === 'top' ? 0 : side === 'bottom' ? box.height : side;
  7971. return elementToViewport({
  7972. x,
  7973. y
  7974. }, box);
  7975. } else if (anchor.side === 'left' || anchor.side === 'right') {
  7976. const {
  7977. side,
  7978. align
  7979. } = anchor;
  7980. const x = side === 'left' ? 0 : side === 'right' ? box.width : side;
  7981. const y = align === 'top' ? 0 : align === 'center' ? box.height / 2 : align === 'bottom' ? box.height : align;
  7982. return elementToViewport({
  7983. x,
  7984. y
  7985. }, box);
  7986. }
  7987. return elementToViewport({
  7988. x: box.width / 2,
  7989. y: box.height / 2
  7990. }, box);
  7991. }
  7992. // Composables
  7993. // Types
  7994. const locationStrategies = {
  7995. static: staticLocationStrategy,
  7996. // specific viewport position, usually centered
  7997. connected: connectedLocationStrategy // connected to a certain element
  7998. };
  7999. const makeLocationStrategyProps = propsFactory({
  8000. locationStrategy: {
  8001. type: [String, Function],
  8002. default: 'static',
  8003. validator: val => typeof val === 'function' || val in locationStrategies
  8004. },
  8005. location: {
  8006. type: String,
  8007. default: 'bottom'
  8008. },
  8009. origin: {
  8010. type: String,
  8011. default: 'auto'
  8012. },
  8013. offset: [Number, String, Array]
  8014. }, 'VOverlay-location-strategies');
  8015. function useLocationStrategies(props, data) {
  8016. const contentStyles = vue.ref({});
  8017. const updateLocation = vue.ref();
  8018. if (IN_BROWSER) {
  8019. useToggleScope(() => !!(data.isActive.value && props.locationStrategy), reset => {
  8020. vue.watch(() => props.locationStrategy, reset);
  8021. vue.onScopeDispose(() => {
  8022. updateLocation.value = undefined;
  8023. });
  8024. if (typeof props.locationStrategy === 'function') {
  8025. updateLocation.value = props.locationStrategy(data, props, contentStyles)?.updateLocation;
  8026. } else {
  8027. updateLocation.value = locationStrategies[props.locationStrategy](data, props, contentStyles)?.updateLocation;
  8028. }
  8029. });
  8030. window.addEventListener('resize', onResize, {
  8031. passive: true
  8032. });
  8033. vue.onScopeDispose(() => {
  8034. window.removeEventListener('resize', onResize);
  8035. updateLocation.value = undefined;
  8036. });
  8037. }
  8038. function onResize(e) {
  8039. updateLocation.value?.(e);
  8040. }
  8041. return {
  8042. contentStyles,
  8043. updateLocation
  8044. };
  8045. }
  8046. function staticLocationStrategy() {
  8047. // TODO
  8048. }
  8049. /** Get size of element ignoring max-width/max-height */
  8050. function getIntrinsicSize(el, isRtl) {
  8051. // const scrollables = new Map<Element, [number, number]>()
  8052. // el.querySelectorAll('*').forEach(el => {
  8053. // const x = el.scrollLeft
  8054. // const y = el.scrollTop
  8055. // if (x || y) {
  8056. // scrollables.set(el, [x, y])
  8057. // }
  8058. // })
  8059. // const initialMaxWidth = el.style.maxWidth
  8060. // const initialMaxHeight = el.style.maxHeight
  8061. // el.style.removeProperty('max-width')
  8062. // el.style.removeProperty('max-height')
  8063. if (isRtl) {
  8064. el.style.removeProperty('left');
  8065. } else {
  8066. el.style.removeProperty('right');
  8067. }
  8068. /* eslint-disable-next-line sonarjs/prefer-immediate-return */
  8069. const contentBox = nullifyTransforms(el);
  8070. if (isRtl) {
  8071. contentBox.x += parseFloat(el.style.right || 0);
  8072. } else {
  8073. contentBox.x -= parseFloat(el.style.left || 0);
  8074. }
  8075. contentBox.y -= parseFloat(el.style.top || 0);
  8076. // el.style.maxWidth = initialMaxWidth
  8077. // el.style.maxHeight = initialMaxHeight
  8078. // scrollables.forEach((position, el) => {
  8079. // el.scrollTo(...position)
  8080. // })
  8081. return contentBox;
  8082. }
  8083. function connectedLocationStrategy(data, props, contentStyles) {
  8084. const activatorFixed = isFixedPosition(data.activatorEl.value);
  8085. if (activatorFixed) {
  8086. Object.assign(contentStyles.value, {
  8087. position: 'fixed',
  8088. top: 0,
  8089. [data.isRtl.value ? 'right' : 'left']: 0
  8090. });
  8091. }
  8092. const {
  8093. preferredAnchor,
  8094. preferredOrigin
  8095. } = destructComputed(() => {
  8096. const parsedAnchor = parseAnchor(props.location, data.isRtl.value);
  8097. const parsedOrigin = props.origin === 'overlap' ? parsedAnchor : props.origin === 'auto' ? flipSide(parsedAnchor) : parseAnchor(props.origin, data.isRtl.value);
  8098. // Some combinations of props may produce an invalid origin
  8099. if (parsedAnchor.side === parsedOrigin.side && parsedAnchor.align === flipAlign(parsedOrigin).align) {
  8100. return {
  8101. preferredAnchor: flipCorner(parsedAnchor),
  8102. preferredOrigin: flipCorner(parsedOrigin)
  8103. };
  8104. } else {
  8105. return {
  8106. preferredAnchor: parsedAnchor,
  8107. preferredOrigin: parsedOrigin
  8108. };
  8109. }
  8110. });
  8111. const [minWidth, minHeight, maxWidth, maxHeight] = ['minWidth', 'minHeight', 'maxWidth', 'maxHeight'].map(key => {
  8112. return vue.computed(() => {
  8113. const val = parseFloat(props[key]);
  8114. return isNaN(val) ? Infinity : val;
  8115. });
  8116. });
  8117. const offset = vue.computed(() => {
  8118. if (Array.isArray(props.offset)) {
  8119. return props.offset;
  8120. }
  8121. if (typeof props.offset === 'string') {
  8122. const offset = props.offset.split(' ').map(parseFloat);
  8123. if (offset.length < 2) offset.push(0);
  8124. return offset;
  8125. }
  8126. return typeof props.offset === 'number' ? [props.offset, 0] : [0, 0];
  8127. });
  8128. let observe = false;
  8129. const observer = new ResizeObserver(() => {
  8130. if (observe) updateLocation();
  8131. });
  8132. vue.watch([data.activatorEl, data.contentEl], (_ref, _ref2) => {
  8133. let [newActivatorEl, newContentEl] = _ref;
  8134. let [oldActivatorEl, oldContentEl] = _ref2;
  8135. if (oldActivatorEl) observer.unobserve(oldActivatorEl);
  8136. if (newActivatorEl) observer.observe(newActivatorEl);
  8137. if (oldContentEl) observer.unobserve(oldContentEl);
  8138. if (newContentEl) observer.observe(newContentEl);
  8139. }, {
  8140. immediate: true
  8141. });
  8142. vue.onScopeDispose(() => {
  8143. observer.disconnect();
  8144. });
  8145. // eslint-disable-next-line max-statements
  8146. function updateLocation() {
  8147. observe = false;
  8148. requestAnimationFrame(() => {
  8149. requestAnimationFrame(() => observe = true);
  8150. });
  8151. if (!data.activatorEl.value || !data.contentEl.value) return;
  8152. const targetBox = data.activatorEl.value.getBoundingClientRect();
  8153. const contentBox = getIntrinsicSize(data.contentEl.value, data.isRtl.value);
  8154. const scrollParents = getScrollParents(data.contentEl.value);
  8155. const viewportMargin = 12;
  8156. if (!scrollParents.length) {
  8157. scrollParents.push(document.documentElement);
  8158. if (!(data.contentEl.value.style.top && data.contentEl.value.style.left)) {
  8159. contentBox.x -= parseFloat(document.documentElement.style.getPropertyValue('--v-body-scroll-x') || 0);
  8160. contentBox.y -= parseFloat(document.documentElement.style.getPropertyValue('--v-body-scroll-y') || 0);
  8161. }
  8162. }
  8163. const viewport = scrollParents.reduce((box, el) => {
  8164. const rect = el.getBoundingClientRect();
  8165. const scrollBox = new Box({
  8166. x: el === document.documentElement ? 0 : rect.x,
  8167. y: el === document.documentElement ? 0 : rect.y,
  8168. width: el.clientWidth,
  8169. height: el.clientHeight
  8170. });
  8171. if (box) {
  8172. return new Box({
  8173. x: Math.max(box.left, scrollBox.left),
  8174. y: Math.max(box.top, scrollBox.top),
  8175. width: Math.min(box.right, scrollBox.right) - Math.max(box.left, scrollBox.left),
  8176. height: Math.min(box.bottom, scrollBox.bottom) - Math.max(box.top, scrollBox.top)
  8177. });
  8178. }
  8179. return scrollBox;
  8180. }, undefined);
  8181. viewport.x += viewportMargin;
  8182. viewport.y += viewportMargin;
  8183. viewport.width -= viewportMargin * 2;
  8184. viewport.height -= viewportMargin * 2;
  8185. let placement = {
  8186. anchor: preferredAnchor.value,
  8187. origin: preferredOrigin.value
  8188. };
  8189. function checkOverflow(_placement) {
  8190. const box = new Box(contentBox);
  8191. const targetPoint = anchorToPoint(_placement.anchor, targetBox);
  8192. const contentPoint = anchorToPoint(_placement.origin, box);
  8193. let {
  8194. x,
  8195. y
  8196. } = getOffset$1(targetPoint, contentPoint);
  8197. switch (_placement.anchor.side) {
  8198. case 'top':
  8199. y -= offset.value[0];
  8200. break;
  8201. case 'bottom':
  8202. y += offset.value[0];
  8203. break;
  8204. case 'left':
  8205. x -= offset.value[0];
  8206. break;
  8207. case 'right':
  8208. x += offset.value[0];
  8209. break;
  8210. }
  8211. switch (_placement.anchor.align) {
  8212. case 'top':
  8213. y -= offset.value[1];
  8214. break;
  8215. case 'bottom':
  8216. y += offset.value[1];
  8217. break;
  8218. case 'left':
  8219. x -= offset.value[1];
  8220. break;
  8221. case 'right':
  8222. x += offset.value[1];
  8223. break;
  8224. }
  8225. box.x += x;
  8226. box.y += y;
  8227. box.width = Math.min(box.width, maxWidth.value);
  8228. box.height = Math.min(box.height, maxHeight.value);
  8229. const overflows = getOverflow(box, viewport);
  8230. return {
  8231. overflows,
  8232. x,
  8233. y
  8234. };
  8235. }
  8236. let x = 0;
  8237. let y = 0;
  8238. const available = {
  8239. x: 0,
  8240. y: 0
  8241. };
  8242. const flipped = {
  8243. x: false,
  8244. y: false
  8245. };
  8246. let resets = -1;
  8247. while (true) {
  8248. if (resets++ > 10) {
  8249. consoleError('Infinite loop detected in connectedLocationStrategy');
  8250. break;
  8251. }
  8252. const {
  8253. x: _x,
  8254. y: _y,
  8255. overflows
  8256. } = checkOverflow(placement);
  8257. x += _x;
  8258. y += _y;
  8259. contentBox.x += _x;
  8260. contentBox.y += _y;
  8261. // flip
  8262. {
  8263. const axis = getAxis(placement.anchor);
  8264. const hasOverflowX = overflows.x.before || overflows.x.after;
  8265. const hasOverflowY = overflows.y.before || overflows.y.after;
  8266. let reset = false;
  8267. ['x', 'y'].forEach(key => {
  8268. if (key === 'x' && hasOverflowX && !flipped.x || key === 'y' && hasOverflowY && !flipped.y) {
  8269. const newPlacement = {
  8270. anchor: {
  8271. ...placement.anchor
  8272. },
  8273. origin: {
  8274. ...placement.origin
  8275. }
  8276. };
  8277. const flip = key === 'x' ? axis === 'y' ? flipAlign : flipSide : axis === 'y' ? flipSide : flipAlign;
  8278. newPlacement.anchor = flip(newPlacement.anchor);
  8279. newPlacement.origin = flip(newPlacement.origin);
  8280. const {
  8281. overflows: newOverflows
  8282. } = checkOverflow(newPlacement);
  8283. 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) {
  8284. placement = newPlacement;
  8285. reset = flipped[key] = true;
  8286. }
  8287. }
  8288. });
  8289. if (reset) continue;
  8290. }
  8291. // shift
  8292. if (overflows.x.before) {
  8293. x += overflows.x.before;
  8294. contentBox.x += overflows.x.before;
  8295. }
  8296. if (overflows.x.after) {
  8297. x -= overflows.x.after;
  8298. contentBox.x -= overflows.x.after;
  8299. }
  8300. if (overflows.y.before) {
  8301. y += overflows.y.before;
  8302. contentBox.y += overflows.y.before;
  8303. }
  8304. if (overflows.y.after) {
  8305. y -= overflows.y.after;
  8306. contentBox.y -= overflows.y.after;
  8307. }
  8308. // size
  8309. {
  8310. const overflows = getOverflow(contentBox, viewport);
  8311. available.x = viewport.width - overflows.x.before - overflows.x.after;
  8312. available.y = viewport.height - overflows.y.before - overflows.y.after;
  8313. x += overflows.x.before;
  8314. contentBox.x += overflows.x.before;
  8315. y += overflows.y.before;
  8316. contentBox.y += overflows.y.before;
  8317. }
  8318. break;
  8319. }
  8320. const axis = getAxis(placement.anchor);
  8321. Object.assign(contentStyles.value, {
  8322. '--v-overlay-anchor-origin': `${placement.anchor.side} ${placement.anchor.align}`,
  8323. transformOrigin: `${placement.origin.side} ${placement.origin.align}`,
  8324. // transform: `translate(${pixelRound(x)}px, ${pixelRound(y)}px)`,
  8325. top: convertToUnit(pixelRound(y)),
  8326. left: data.isRtl.value ? undefined : convertToUnit(pixelRound(x)),
  8327. right: data.isRtl.value ? convertToUnit(pixelRound(-x)) : undefined,
  8328. minWidth: convertToUnit(axis === 'y' ? Math.min(minWidth.value, targetBox.width) : minWidth.value),
  8329. maxWidth: convertToUnit(pixelCeil(clamp(available.x, minWidth.value === Infinity ? 0 : minWidth.value, maxWidth.value))),
  8330. maxHeight: convertToUnit(pixelCeil(clamp(available.y, minHeight.value === Infinity ? 0 : minHeight.value, maxHeight.value)))
  8331. });
  8332. return {
  8333. available,
  8334. contentBox
  8335. };
  8336. }
  8337. vue.watch(() => [preferredAnchor.value, preferredOrigin.value, props.offset, props.minWidth, props.minHeight, props.maxWidth, props.maxHeight], () => updateLocation());
  8338. vue.nextTick(() => {
  8339. const result = updateLocation();
  8340. // TODO: overflowing content should only require a single updateLocation call
  8341. // Icky hack to make sure the content is positioned consistently
  8342. if (!result) return;
  8343. const {
  8344. available,
  8345. contentBox
  8346. } = result;
  8347. if (contentBox.height > available.y) {
  8348. requestAnimationFrame(() => {
  8349. updateLocation();
  8350. requestAnimationFrame(() => {
  8351. updateLocation();
  8352. });
  8353. });
  8354. }
  8355. });
  8356. return {
  8357. updateLocation
  8358. };
  8359. }
  8360. function pixelRound(val) {
  8361. return Math.round(val * devicePixelRatio) / devicePixelRatio;
  8362. }
  8363. function pixelCeil(val) {
  8364. return Math.ceil(val * devicePixelRatio) / devicePixelRatio;
  8365. }
  8366. let clean = true;
  8367. const frames = [];
  8368. /**
  8369. * Schedule a task to run in an animation frame on its own
  8370. * This is useful for heavy tasks that may cause jank if all ran together
  8371. */
  8372. function requestNewFrame(cb) {
  8373. if (!clean || frames.length) {
  8374. frames.push(cb);
  8375. run();
  8376. } else {
  8377. clean = false;
  8378. cb();
  8379. run();
  8380. }
  8381. }
  8382. let raf = -1;
  8383. function run() {
  8384. cancelAnimationFrame(raf);
  8385. raf = requestAnimationFrame(() => {
  8386. const frame = frames.shift();
  8387. if (frame) frame();
  8388. if (frames.length) run();else clean = true;
  8389. });
  8390. }
  8391. // Utilities
  8392. // Types
  8393. const scrollStrategies = {
  8394. none: null,
  8395. close: closeScrollStrategy,
  8396. block: blockScrollStrategy,
  8397. reposition: repositionScrollStrategy
  8398. };
  8399. const makeScrollStrategyProps = propsFactory({
  8400. scrollStrategy: {
  8401. type: [String, Function],
  8402. default: 'block',
  8403. validator: val => typeof val === 'function' || val in scrollStrategies
  8404. }
  8405. }, 'VOverlay-scroll-strategies');
  8406. function useScrollStrategies(props, data) {
  8407. if (!IN_BROWSER) return;
  8408. let scope;
  8409. vue.watchEffect(async () => {
  8410. scope?.stop();
  8411. if (!(data.isActive.value && props.scrollStrategy)) return;
  8412. scope = vue.effectScope();
  8413. await vue.nextTick();
  8414. scope.active && scope.run(() => {
  8415. if (typeof props.scrollStrategy === 'function') {
  8416. props.scrollStrategy(data, props, scope);
  8417. } else {
  8418. scrollStrategies[props.scrollStrategy]?.(data, props, scope);
  8419. }
  8420. });
  8421. });
  8422. vue.onScopeDispose(() => {
  8423. scope?.stop();
  8424. });
  8425. }
  8426. function closeScrollStrategy(data) {
  8427. function onScroll(e) {
  8428. data.isActive.value = false;
  8429. }
  8430. bindScroll(data.activatorEl.value ?? data.contentEl.value, onScroll);
  8431. }
  8432. function blockScrollStrategy(data, props) {
  8433. const offsetParent = data.root.value?.offsetParent;
  8434. const scrollElements = [...new Set([...getScrollParents(data.activatorEl.value, props.contained ? offsetParent : undefined), ...getScrollParents(data.contentEl.value, props.contained ? offsetParent : undefined)])].filter(el => !el.classList.contains('v-overlay-scroll-blocked'));
  8435. const scrollbarWidth = window.innerWidth - document.documentElement.offsetWidth;
  8436. const scrollableParent = (el => hasScrollbar(el) && el)(offsetParent || document.documentElement);
  8437. if (scrollableParent) {
  8438. data.root.value.classList.add('v-overlay--scroll-blocked');
  8439. }
  8440. scrollElements.forEach((el, i) => {
  8441. el.style.setProperty('--v-body-scroll-x', convertToUnit(-el.scrollLeft));
  8442. el.style.setProperty('--v-body-scroll-y', convertToUnit(-el.scrollTop));
  8443. if (el !== document.documentElement) {
  8444. el.style.setProperty('--v-scrollbar-offset', convertToUnit(scrollbarWidth));
  8445. }
  8446. el.classList.add('v-overlay-scroll-blocked');
  8447. });
  8448. vue.onScopeDispose(() => {
  8449. scrollElements.forEach((el, i) => {
  8450. const x = parseFloat(el.style.getPropertyValue('--v-body-scroll-x'));
  8451. const y = parseFloat(el.style.getPropertyValue('--v-body-scroll-y'));
  8452. el.style.removeProperty('--v-body-scroll-x');
  8453. el.style.removeProperty('--v-body-scroll-y');
  8454. el.style.removeProperty('--v-scrollbar-offset');
  8455. el.classList.remove('v-overlay-scroll-blocked');
  8456. el.scrollLeft = -x;
  8457. el.scrollTop = -y;
  8458. });
  8459. if (scrollableParent) {
  8460. data.root.value.classList.remove('v-overlay--scroll-blocked');
  8461. }
  8462. });
  8463. }
  8464. function repositionScrollStrategy(data, props, scope) {
  8465. let slow = false;
  8466. let raf = -1;
  8467. let ric = -1;
  8468. function update(e) {
  8469. requestNewFrame(() => {
  8470. const start = performance.now();
  8471. data.updateLocation.value?.(e);
  8472. const time = performance.now() - start;
  8473. slow = time / (1000 / 60) > 2;
  8474. });
  8475. }
  8476. ric = (typeof requestIdleCallback === 'undefined' ? cb => cb() : requestIdleCallback)(() => {
  8477. scope.run(() => {
  8478. bindScroll(data.activatorEl.value ?? data.contentEl.value, e => {
  8479. if (slow) {
  8480. // If the position calculation is slow,
  8481. // defer updates until scrolling is finished.
  8482. // Browsers usually fire one scroll event per frame so
  8483. // we just wait until we've got two frames without an event
  8484. cancelAnimationFrame(raf);
  8485. raf = requestAnimationFrame(() => {
  8486. raf = requestAnimationFrame(() => {
  8487. update(e);
  8488. });
  8489. });
  8490. } else {
  8491. update(e);
  8492. }
  8493. });
  8494. });
  8495. });
  8496. vue.onScopeDispose(() => {
  8497. typeof cancelIdleCallback !== 'undefined' && cancelIdleCallback(ric);
  8498. cancelAnimationFrame(raf);
  8499. });
  8500. }
  8501. /** @private */
  8502. function bindScroll(el, onScroll) {
  8503. const scrollElements = [document, ...getScrollParents(el)];
  8504. scrollElements.forEach(el => {
  8505. el.addEventListener('scroll', onScroll, {
  8506. passive: true
  8507. });
  8508. });
  8509. vue.onScopeDispose(() => {
  8510. scrollElements.forEach(el => {
  8511. el.removeEventListener('scroll', onScroll);
  8512. });
  8513. });
  8514. }
  8515. // Types
  8516. const VMenuSymbol = Symbol.for('vuetify:v-menu');
  8517. // Utilities
  8518. // Types
  8519. // Composables
  8520. const makeDelayProps = propsFactory({
  8521. closeDelay: [Number, String],
  8522. openDelay: [Number, String]
  8523. }, 'delay');
  8524. function useDelay(props, cb) {
  8525. const delays = {};
  8526. const runDelayFactory = prop => () => {
  8527. // istanbul ignore next
  8528. if (!IN_BROWSER) return Promise.resolve(true);
  8529. const active = prop === 'openDelay';
  8530. delays.closeDelay && window.clearTimeout(delays.closeDelay);
  8531. delete delays.closeDelay;
  8532. delays.openDelay && window.clearTimeout(delays.openDelay);
  8533. delete delays.openDelay;
  8534. return new Promise(resolve => {
  8535. const delay = parseInt(props[prop] ?? 0, 10);
  8536. delays[prop] = window.setTimeout(() => {
  8537. cb?.(active);
  8538. resolve(active);
  8539. }, delay);
  8540. });
  8541. };
  8542. return {
  8543. runCloseDelay: runDelayFactory('closeDelay'),
  8544. runOpenDelay: runDelayFactory('openDelay')
  8545. };
  8546. }
  8547. // Components
  8548. // Types
  8549. const makeActivatorProps = propsFactory({
  8550. activator: [String, Object],
  8551. activatorProps: {
  8552. type: Object,
  8553. default: () => ({})
  8554. },
  8555. openOnClick: {
  8556. type: Boolean,
  8557. default: undefined
  8558. },
  8559. openOnHover: Boolean,
  8560. openOnFocus: {
  8561. type: Boolean,
  8562. default: undefined
  8563. },
  8564. closeOnContentClick: Boolean,
  8565. ...makeDelayProps()
  8566. }, 'VOverlay-activator');
  8567. function useActivator(props, _ref) {
  8568. let {
  8569. isActive,
  8570. isTop
  8571. } = _ref;
  8572. const activatorEl = vue.ref();
  8573. let isHovered = false;
  8574. let isFocused = false;
  8575. let firstEnter = true;
  8576. const openOnFocus = vue.computed(() => props.openOnFocus || props.openOnFocus == null && props.openOnHover);
  8577. const openOnClick = vue.computed(() => props.openOnClick || props.openOnClick == null && !props.openOnHover && !openOnFocus.value);
  8578. const {
  8579. runOpenDelay,
  8580. runCloseDelay
  8581. } = useDelay(props, value => {
  8582. if (value === (props.openOnHover && isHovered || openOnFocus.value && isFocused) && !(props.openOnHover && isActive.value && !isTop.value)) {
  8583. if (isActive.value !== value) {
  8584. firstEnter = true;
  8585. }
  8586. isActive.value = value;
  8587. }
  8588. });
  8589. const availableEvents = {
  8590. onClick: e => {
  8591. e.stopPropagation();
  8592. activatorEl.value = e.currentTarget || e.target;
  8593. isActive.value = !isActive.value;
  8594. },
  8595. onMouseenter: e => {
  8596. if (e.sourceCapabilities?.firesTouchEvents) return;
  8597. isHovered = true;
  8598. activatorEl.value = e.currentTarget || e.target;
  8599. runOpenDelay();
  8600. },
  8601. onMouseleave: e => {
  8602. isHovered = false;
  8603. runCloseDelay();
  8604. },
  8605. onFocus: e => {
  8606. if (matchesSelector(e.target, ':focus-visible') === false) return;
  8607. isFocused = true;
  8608. e.stopPropagation();
  8609. activatorEl.value = e.currentTarget || e.target;
  8610. runOpenDelay();
  8611. },
  8612. onBlur: e => {
  8613. isFocused = false;
  8614. e.stopPropagation();
  8615. runCloseDelay();
  8616. }
  8617. };
  8618. const activatorEvents = vue.computed(() => {
  8619. const events = {};
  8620. if (openOnClick.value) {
  8621. events.onClick = availableEvents.onClick;
  8622. }
  8623. if (props.openOnHover) {
  8624. events.onMouseenter = availableEvents.onMouseenter;
  8625. events.onMouseleave = availableEvents.onMouseleave;
  8626. }
  8627. if (openOnFocus.value) {
  8628. events.onFocus = availableEvents.onFocus;
  8629. events.onBlur = availableEvents.onBlur;
  8630. }
  8631. return events;
  8632. });
  8633. const contentEvents = vue.computed(() => {
  8634. const events = {};
  8635. if (props.openOnHover) {
  8636. events.onMouseenter = () => {
  8637. isHovered = true;
  8638. runOpenDelay();
  8639. };
  8640. events.onMouseleave = () => {
  8641. isHovered = false;
  8642. runCloseDelay();
  8643. };
  8644. }
  8645. if (openOnFocus.value) {
  8646. events.onFocusin = () => {
  8647. isFocused = true;
  8648. runOpenDelay();
  8649. };
  8650. events.onFocusout = () => {
  8651. isFocused = false;
  8652. runCloseDelay();
  8653. };
  8654. }
  8655. if (props.closeOnContentClick) {
  8656. const menu = vue.inject(VMenuSymbol, null);
  8657. events.onClick = () => {
  8658. isActive.value = false;
  8659. menu?.closeParents();
  8660. };
  8661. }
  8662. return events;
  8663. });
  8664. const scrimEvents = vue.computed(() => {
  8665. const events = {};
  8666. if (props.openOnHover) {
  8667. events.onMouseenter = () => {
  8668. if (firstEnter) {
  8669. isHovered = true;
  8670. firstEnter = false;
  8671. runOpenDelay();
  8672. }
  8673. };
  8674. events.onMouseleave = () => {
  8675. isHovered = false;
  8676. runCloseDelay();
  8677. };
  8678. }
  8679. return events;
  8680. });
  8681. vue.watch(isTop, val => {
  8682. if (val && (props.openOnHover && !isHovered && (!openOnFocus.value || !isFocused) || openOnFocus.value && !isFocused && (!props.openOnHover || !isHovered))) {
  8683. isActive.value = false;
  8684. }
  8685. });
  8686. const activatorRef = vue.ref();
  8687. vue.watchEffect(() => {
  8688. if (!activatorRef.value) return;
  8689. vue.nextTick(() => {
  8690. activatorEl.value = refElement(activatorRef.value);
  8691. });
  8692. });
  8693. const vm = getCurrentInstance('useActivator');
  8694. let scope;
  8695. vue.watch(() => !!props.activator, val => {
  8696. if (val && IN_BROWSER) {
  8697. scope = vue.effectScope();
  8698. scope.run(() => {
  8699. _useActivator(props, vm, {
  8700. activatorEl,
  8701. activatorEvents
  8702. });
  8703. });
  8704. } else if (scope) {
  8705. scope.stop();
  8706. }
  8707. }, {
  8708. flush: 'post',
  8709. immediate: true
  8710. });
  8711. vue.onScopeDispose(() => {
  8712. scope?.stop();
  8713. });
  8714. return {
  8715. activatorEl,
  8716. activatorRef,
  8717. activatorEvents,
  8718. contentEvents,
  8719. scrimEvents
  8720. };
  8721. }
  8722. function _useActivator(props, vm, _ref2) {
  8723. let {
  8724. activatorEl,
  8725. activatorEvents
  8726. } = _ref2;
  8727. vue.watch(() => props.activator, (val, oldVal) => {
  8728. if (oldVal && val !== oldVal) {
  8729. const activator = getActivator(oldVal);
  8730. activator && unbindActivatorProps(activator);
  8731. }
  8732. if (val) {
  8733. vue.nextTick(() => bindActivatorProps());
  8734. }
  8735. }, {
  8736. immediate: true
  8737. });
  8738. vue.watch(() => props.activatorProps, () => {
  8739. bindActivatorProps();
  8740. });
  8741. vue.onScopeDispose(() => {
  8742. unbindActivatorProps();
  8743. });
  8744. function bindActivatorProps() {
  8745. let el = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : getActivator();
  8746. let _props = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : props.activatorProps;
  8747. if (!el) return;
  8748. bindProps(el, vue.mergeProps(activatorEvents.value, _props));
  8749. }
  8750. function unbindActivatorProps() {
  8751. let el = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : getActivator();
  8752. let _props = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : props.activatorProps;
  8753. if (!el) return;
  8754. unbindProps(el, vue.mergeProps(activatorEvents.value, _props));
  8755. }
  8756. function getActivator() {
  8757. let selector = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : props.activator;
  8758. let activator;
  8759. if (selector) {
  8760. if (selector === 'parent') {
  8761. let el = vm?.proxy?.$el?.parentNode;
  8762. while (el.hasAttribute('data-no-activator')) {
  8763. el = el.parentNode;
  8764. }
  8765. activator = el;
  8766. } else if (typeof selector === 'string') {
  8767. // Selector
  8768. activator = document.querySelector(selector);
  8769. } else if ('$el' in selector) {
  8770. // Component (ref)
  8771. activator = selector.$el;
  8772. } else {
  8773. // HTMLElement | Element
  8774. activator = selector;
  8775. }
  8776. }
  8777. // The activator should only be a valid element (Ignore comments and text nodes)
  8778. activatorEl.value = activator?.nodeType === Node.ELEMENT_NODE ? activator : null;
  8779. return activatorEl.value;
  8780. }
  8781. }
  8782. // Utilities
  8783. // Types
  8784. const breakpoints = ['sm', 'md', 'lg', 'xl', 'xxl']; // no xs
  8785. const DisplaySymbol = Symbol.for('vuetify:display');
  8786. const defaultDisplayOptions = {
  8787. mobileBreakpoint: 'lg',
  8788. thresholds: {
  8789. xs: 0,
  8790. sm: 600,
  8791. md: 960,
  8792. lg: 1280,
  8793. xl: 1920,
  8794. xxl: 2560
  8795. }
  8796. };
  8797. const parseDisplayOptions = function () {
  8798. let options = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : defaultDisplayOptions;
  8799. return mergeDeep(defaultDisplayOptions, options);
  8800. };
  8801. function getClientWidth(ssr) {
  8802. return IN_BROWSER && !ssr ? window.innerWidth : typeof ssr === 'object' && ssr.clientWidth || 0;
  8803. }
  8804. function getClientHeight(ssr) {
  8805. return IN_BROWSER && !ssr ? window.innerHeight : typeof ssr === 'object' && ssr.clientHeight || 0;
  8806. }
  8807. function getPlatform(ssr) {
  8808. const userAgent = IN_BROWSER && !ssr ? window.navigator.userAgent : 'ssr';
  8809. function match(regexp) {
  8810. return Boolean(userAgent.match(regexp));
  8811. }
  8812. const android = match(/android/i);
  8813. const ios = match(/iphone|ipad|ipod/i);
  8814. const cordova = match(/cordova/i);
  8815. const electron = match(/electron/i);
  8816. const chrome = match(/chrome/i);
  8817. const edge = match(/edge/i);
  8818. const firefox = match(/firefox/i);
  8819. const opera = match(/opera/i);
  8820. const win = match(/win/i);
  8821. const mac = match(/mac/i);
  8822. const linux = match(/linux/i);
  8823. return {
  8824. android,
  8825. ios,
  8826. cordova,
  8827. electron,
  8828. chrome,
  8829. edge,
  8830. firefox,
  8831. opera,
  8832. win,
  8833. mac,
  8834. linux,
  8835. touch: SUPPORTS_TOUCH,
  8836. ssr: userAgent === 'ssr'
  8837. };
  8838. }
  8839. function createDisplay(options, ssr) {
  8840. const {
  8841. thresholds,
  8842. mobileBreakpoint
  8843. } = parseDisplayOptions(options);
  8844. const height = vue.shallowRef(getClientHeight(ssr));
  8845. const platform = vue.shallowRef(getPlatform(ssr));
  8846. const state = vue.reactive({});
  8847. const width = vue.shallowRef(getClientWidth(ssr));
  8848. function updateSize() {
  8849. height.value = getClientHeight();
  8850. width.value = getClientWidth();
  8851. }
  8852. function update() {
  8853. updateSize();
  8854. platform.value = getPlatform();
  8855. }
  8856. // eslint-disable-next-line max-statements
  8857. vue.watchEffect(() => {
  8858. const xs = width.value < thresholds.sm;
  8859. const sm = width.value < thresholds.md && !xs;
  8860. const md = width.value < thresholds.lg && !(sm || xs);
  8861. const lg = width.value < thresholds.xl && !(md || sm || xs);
  8862. const xl = width.value < thresholds.xxl && !(lg || md || sm || xs);
  8863. const xxl = width.value >= thresholds.xxl;
  8864. const name = xs ? 'xs' : sm ? 'sm' : md ? 'md' : lg ? 'lg' : xl ? 'xl' : 'xxl';
  8865. const breakpointValue = typeof mobileBreakpoint === 'number' ? mobileBreakpoint : thresholds[mobileBreakpoint];
  8866. const mobile = width.value < breakpointValue;
  8867. state.xs = xs;
  8868. state.sm = sm;
  8869. state.md = md;
  8870. state.lg = lg;
  8871. state.xl = xl;
  8872. state.xxl = xxl;
  8873. state.smAndUp = !xs;
  8874. state.mdAndUp = !(xs || sm);
  8875. state.lgAndUp = !(xs || sm || md);
  8876. state.xlAndUp = !(xs || sm || md || lg);
  8877. state.smAndDown = !(md || lg || xl || xxl);
  8878. state.mdAndDown = !(lg || xl || xxl);
  8879. state.lgAndDown = !(xl || xxl);
  8880. state.xlAndDown = !xxl;
  8881. state.name = name;
  8882. state.height = height.value;
  8883. state.width = width.value;
  8884. state.mobile = mobile;
  8885. state.mobileBreakpoint = mobileBreakpoint;
  8886. state.platform = platform.value;
  8887. state.thresholds = thresholds;
  8888. });
  8889. if (IN_BROWSER) {
  8890. window.addEventListener('resize', updateSize, {
  8891. passive: true
  8892. });
  8893. }
  8894. return {
  8895. ...vue.toRefs(state),
  8896. update,
  8897. ssr: !!ssr
  8898. };
  8899. }
  8900. function useDisplay() {
  8901. const display = vue.inject(DisplaySymbol);
  8902. if (!display) throw new Error('Could not find Vuetify display injection');
  8903. return display;
  8904. }
  8905. // Composables
  8906. function useHydration() {
  8907. if (!IN_BROWSER) return vue.shallowRef(false);
  8908. const {
  8909. ssr
  8910. } = useDisplay();
  8911. if (ssr) {
  8912. const isMounted = vue.shallowRef(false);
  8913. vue.onMounted(() => {
  8914. isMounted.value = true;
  8915. });
  8916. return isMounted;
  8917. } else {
  8918. return vue.shallowRef(true);
  8919. }
  8920. }
  8921. // Utilities
  8922. // Types
  8923. const makeLazyProps = propsFactory({
  8924. eager: Boolean
  8925. }, 'lazy');
  8926. function useLazy(props, active) {
  8927. const isBooted = vue.shallowRef(false);
  8928. const hasContent = vue.computed(() => isBooted.value || props.eager || active.value);
  8929. vue.watch(active, () => isBooted.value = true);
  8930. function onAfterLeave() {
  8931. if (!props.eager) isBooted.value = false;
  8932. }
  8933. return {
  8934. isBooted,
  8935. hasContent,
  8936. onAfterLeave
  8937. };
  8938. }
  8939. // Utilities
  8940. function useScopeId() {
  8941. const vm = getCurrentInstance('useScopeId');
  8942. const scopeId = vm.vnode.scopeId;
  8943. return {
  8944. scopeId: scopeId ? {
  8945. [scopeId]: ''
  8946. } : undefined
  8947. };
  8948. }
  8949. // Composables
  8950. // Types
  8951. const StackSymbol = Symbol.for('vuetify:stack');
  8952. const globalStack = vue.reactive([]);
  8953. function useStack(isActive, zIndex, disableGlobalStack) {
  8954. const vm = getCurrentInstance('useStack');
  8955. const createStackEntry = !disableGlobalStack;
  8956. const parent = vue.inject(StackSymbol, undefined);
  8957. const stack = vue.reactive({
  8958. activeChildren: new Set()
  8959. });
  8960. vue.provide(StackSymbol, stack);
  8961. const _zIndex = vue.shallowRef(+zIndex.value);
  8962. useToggleScope(isActive, () => {
  8963. const lastZIndex = globalStack.at(-1)?.[1];
  8964. _zIndex.value = lastZIndex ? lastZIndex + 10 : +zIndex.value;
  8965. if (createStackEntry) {
  8966. globalStack.push([vm.uid, _zIndex.value]);
  8967. }
  8968. parent?.activeChildren.add(vm.uid);
  8969. vue.onScopeDispose(() => {
  8970. if (createStackEntry) {
  8971. const idx = vue.toRaw(globalStack).findIndex(v => v[0] === vm.uid);
  8972. globalStack.splice(idx, 1);
  8973. }
  8974. parent?.activeChildren.delete(vm.uid);
  8975. });
  8976. });
  8977. const globalTop = vue.shallowRef(true);
  8978. if (createStackEntry) {
  8979. vue.watchEffect(() => {
  8980. const _isTop = globalStack.at(-1)?.[0] === vm.uid;
  8981. setTimeout(() => globalTop.value = _isTop);
  8982. });
  8983. }
  8984. const localTop = vue.computed(() => !stack.activeChildren.size);
  8985. return {
  8986. globalTop: vue.readonly(globalTop),
  8987. localTop,
  8988. stackStyles: vue.computed(() => ({
  8989. zIndex: _zIndex.value
  8990. }))
  8991. };
  8992. }
  8993. // Utilities
  8994. // Types
  8995. function useTeleport(target) {
  8996. const teleportTarget = vue.computed(() => {
  8997. const _target = target.value;
  8998. if (_target === true || !IN_BROWSER) return undefined;
  8999. const targetElement = _target === false ? document.body : typeof _target === 'string' ? document.querySelector(_target) : _target;
  9000. if (targetElement == null) {
  9001. vue.warn(`Unable to locate target ${_target}`);
  9002. return undefined;
  9003. }
  9004. let container = targetElement.querySelector(':scope > .v-overlay-container');
  9005. if (!container) {
  9006. container = document.createElement('div');
  9007. container.className = 'v-overlay-container';
  9008. targetElement.appendChild(container);
  9009. }
  9010. return container;
  9011. });
  9012. return {
  9013. teleportTarget
  9014. };
  9015. }
  9016. // Utilities
  9017. // Types
  9018. function defaultConditional() {
  9019. return true;
  9020. }
  9021. function checkEvent(e, el, binding) {
  9022. // The include element callbacks below can be expensive
  9023. // so we should avoid calling them when we're not active.
  9024. // Explicitly check for false to allow fallback compatibility
  9025. // with non-toggleable components
  9026. if (!e || checkIsActive(e, binding) === false) return false;
  9027. // If we're clicking inside the shadowroot, then the app root doesn't get the same
  9028. // level of introspection as to _what_ we're clicking. We want to check to see if
  9029. // our target is the shadowroot parent container, and if it is, ignore.
  9030. const root = attachedRoot(el);
  9031. if (typeof ShadowRoot !== 'undefined' && root instanceof ShadowRoot && root.host === e.target) return false;
  9032. // Check if additional elements were passed to be included in check
  9033. // (click must be outside all included elements, if any)
  9034. const elements = (typeof binding.value === 'object' && binding.value.include || (() => []))();
  9035. // Add the root element for the component this directive was defined on
  9036. elements.push(el);
  9037. // Check if it's a click outside our elements, and then if our callback returns true.
  9038. // Non-toggleable components should take action in their callback and return falsy.
  9039. // Toggleable can return true if it wants to deactivate.
  9040. // Note that, because we're in the capture phase, this callback will occur before
  9041. // the bubbling click event on any outside elements.
  9042. return !elements.some(el => el?.contains(e.target));
  9043. }
  9044. function checkIsActive(e, binding) {
  9045. const isActive = typeof binding.value === 'object' && binding.value.closeConditional || defaultConditional;
  9046. return isActive(e);
  9047. }
  9048. function directive(e, el, binding) {
  9049. const handler = typeof binding.value === 'function' ? binding.value : binding.value.handler;
  9050. el._clickOutside.lastMousedownWasOutside && checkEvent(e, el, binding) && setTimeout(() => {
  9051. checkIsActive(e, binding) && handler && handler(e);
  9052. }, 0);
  9053. }
  9054. function handleShadow(el, callback) {
  9055. const root = attachedRoot(el);
  9056. callback(document);
  9057. if (typeof ShadowRoot !== 'undefined' && root instanceof ShadowRoot) {
  9058. callback(root);
  9059. }
  9060. }
  9061. const ClickOutside = {
  9062. // [data-app] may not be found
  9063. // if using bind, inserted makes
  9064. // sure that the root element is
  9065. // available, iOS does not support
  9066. // clicks on body
  9067. mounted(el, binding) {
  9068. const onClick = e => directive(e, el, binding);
  9069. const onMousedown = e => {
  9070. el._clickOutside.lastMousedownWasOutside = checkEvent(e, el, binding);
  9071. };
  9072. handleShadow(el, app => {
  9073. app.addEventListener('click', onClick, true);
  9074. app.addEventListener('mousedown', onMousedown, true);
  9075. });
  9076. if (!el._clickOutside) {
  9077. el._clickOutside = {
  9078. lastMousedownWasOutside: false
  9079. };
  9080. }
  9081. el._clickOutside[binding.instance.$.uid] = {
  9082. onClick,
  9083. onMousedown
  9084. };
  9085. },
  9086. unmounted(el, binding) {
  9087. if (!el._clickOutside) return;
  9088. handleShadow(el, app => {
  9089. if (!app || !el._clickOutside?.[binding.instance.$.uid]) return;
  9090. const {
  9091. onClick,
  9092. onMousedown
  9093. } = el._clickOutside[binding.instance.$.uid];
  9094. app.removeEventListener('click', onClick, true);
  9095. app.removeEventListener('mousedown', onMousedown, true);
  9096. });
  9097. delete el._clickOutside[binding.instance.$.uid];
  9098. }
  9099. };
  9100. // Types
  9101. function Scrim(props) {
  9102. const {
  9103. modelValue,
  9104. color,
  9105. ...rest
  9106. } = props;
  9107. return vue.createVNode(vue.Transition, {
  9108. "name": "fade-transition",
  9109. "appear": true
  9110. }, {
  9111. default: () => [props.modelValue && vue.createVNode("div", vue.mergeProps({
  9112. "class": ['v-overlay__scrim', props.color.backgroundColorClasses.value],
  9113. "style": props.color.backgroundColorStyles.value
  9114. }, rest), null)]
  9115. });
  9116. }
  9117. const makeVOverlayProps = propsFactory({
  9118. absolute: Boolean,
  9119. attach: [Boolean, String, Object],
  9120. closeOnBack: {
  9121. type: Boolean,
  9122. default: true
  9123. },
  9124. contained: Boolean,
  9125. contentClass: null,
  9126. contentProps: null,
  9127. disabled: Boolean,
  9128. noClickAnimation: Boolean,
  9129. modelValue: Boolean,
  9130. persistent: Boolean,
  9131. scrim: {
  9132. type: [Boolean, String],
  9133. default: true
  9134. },
  9135. zIndex: {
  9136. type: [Number, String],
  9137. default: 2000
  9138. },
  9139. ...makeActivatorProps(),
  9140. ...makeComponentProps(),
  9141. ...makeDimensionProps(),
  9142. ...makeLazyProps(),
  9143. ...makeLocationStrategyProps(),
  9144. ...makeScrollStrategyProps(),
  9145. ...makeThemeProps(),
  9146. ...makeTransitionProps()
  9147. }, 'VOverlay');
  9148. const VOverlay = genericComponent()({
  9149. name: 'VOverlay',
  9150. directives: {
  9151. ClickOutside
  9152. },
  9153. inheritAttrs: false,
  9154. props: {
  9155. _disableGlobalStack: Boolean,
  9156. ...makeVOverlayProps()
  9157. },
  9158. emits: {
  9159. 'click:outside': e => true,
  9160. 'update:modelValue': value => true,
  9161. afterLeave: () => true
  9162. },
  9163. setup(props, _ref) {
  9164. let {
  9165. slots,
  9166. attrs,
  9167. emit
  9168. } = _ref;
  9169. const model = useProxiedModel(props, 'modelValue');
  9170. const isActive = vue.computed({
  9171. get: () => model.value,
  9172. set: v => {
  9173. if (!(v && props.disabled)) model.value = v;
  9174. }
  9175. });
  9176. const {
  9177. teleportTarget
  9178. } = useTeleport(vue.computed(() => props.attach || props.contained));
  9179. const {
  9180. themeClasses
  9181. } = provideTheme(props);
  9182. const {
  9183. rtlClasses,
  9184. isRtl
  9185. } = useRtl();
  9186. const {
  9187. hasContent,
  9188. onAfterLeave
  9189. } = useLazy(props, isActive);
  9190. const scrimColor = useBackgroundColor(vue.computed(() => {
  9191. return typeof props.scrim === 'string' ? props.scrim : null;
  9192. }));
  9193. const {
  9194. globalTop,
  9195. localTop,
  9196. stackStyles
  9197. } = useStack(isActive, vue.toRef(props, 'zIndex'), props._disableGlobalStack);
  9198. const {
  9199. activatorEl,
  9200. activatorRef,
  9201. activatorEvents,
  9202. contentEvents,
  9203. scrimEvents
  9204. } = useActivator(props, {
  9205. isActive,
  9206. isTop: localTop
  9207. });
  9208. const {
  9209. dimensionStyles
  9210. } = useDimension(props);
  9211. const isMounted = useHydration();
  9212. const {
  9213. scopeId
  9214. } = useScopeId();
  9215. vue.watch(() => props.disabled, v => {
  9216. if (v) isActive.value = false;
  9217. });
  9218. const root = vue.ref();
  9219. const contentEl = vue.ref();
  9220. const {
  9221. contentStyles,
  9222. updateLocation
  9223. } = useLocationStrategies(props, {
  9224. isRtl,
  9225. contentEl,
  9226. activatorEl,
  9227. isActive
  9228. });
  9229. useScrollStrategies(props, {
  9230. root,
  9231. contentEl,
  9232. activatorEl,
  9233. isActive,
  9234. updateLocation
  9235. });
  9236. function onClickOutside(e) {
  9237. emit('click:outside', e);
  9238. if (!props.persistent) isActive.value = false;else animateClick();
  9239. }
  9240. function closeConditional() {
  9241. return isActive.value && globalTop.value;
  9242. }
  9243. IN_BROWSER && vue.watch(isActive, val => {
  9244. if (val) {
  9245. window.addEventListener('keydown', onKeydown);
  9246. } else {
  9247. window.removeEventListener('keydown', onKeydown);
  9248. }
  9249. }, {
  9250. immediate: true
  9251. });
  9252. function onKeydown(e) {
  9253. if (e.key === 'Escape' && globalTop.value) {
  9254. if (!props.persistent) {
  9255. isActive.value = false;
  9256. if (contentEl.value?.contains(document.activeElement)) {
  9257. activatorEl.value?.focus();
  9258. }
  9259. } else animateClick();
  9260. }
  9261. }
  9262. const router = useRouter();
  9263. useToggleScope(() => props.closeOnBack, () => {
  9264. useBackButton(router, next => {
  9265. if (globalTop.value && isActive.value) {
  9266. next(false);
  9267. if (!props.persistent) isActive.value = false;else animateClick();
  9268. } else {
  9269. next();
  9270. }
  9271. });
  9272. });
  9273. const top = vue.ref();
  9274. vue.watch(() => isActive.value && (props.absolute || props.contained) && teleportTarget.value == null, val => {
  9275. if (val) {
  9276. const scrollParent = getScrollParent(root.value);
  9277. if (scrollParent && scrollParent !== document.scrollingElement) {
  9278. top.value = scrollParent.scrollTop;
  9279. }
  9280. }
  9281. });
  9282. // Add a quick "bounce" animation to the content
  9283. function animateClick() {
  9284. if (props.noClickAnimation) return;
  9285. contentEl.value && animate(contentEl.value, [{
  9286. transformOrigin: 'center'
  9287. }, {
  9288. transform: 'scale(1.03)'
  9289. }, {
  9290. transformOrigin: 'center'
  9291. }], {
  9292. duration: 150,
  9293. easing: standardEasing
  9294. });
  9295. }
  9296. useRender(() => vue.createVNode(vue.Fragment, null, [slots.activator?.({
  9297. isActive: isActive.value,
  9298. props: vue.mergeProps({
  9299. ref: activatorRef
  9300. }, activatorEvents.value, props.activatorProps)
  9301. }), isMounted.value && hasContent.value && vue.createVNode(vue.Teleport, {
  9302. "disabled": !teleportTarget.value,
  9303. "to": teleportTarget.value
  9304. }, {
  9305. default: () => [vue.createVNode("div", vue.mergeProps({
  9306. "class": ['v-overlay', {
  9307. 'v-overlay--absolute': props.absolute || props.contained,
  9308. 'v-overlay--active': isActive.value,
  9309. 'v-overlay--contained': props.contained
  9310. }, themeClasses.value, rtlClasses.value, props.class],
  9311. "style": [stackStyles.value, {
  9312. top: convertToUnit(top.value)
  9313. }, props.style],
  9314. "ref": root
  9315. }, scopeId, attrs), [vue.createVNode(Scrim, vue.mergeProps({
  9316. "color": scrimColor,
  9317. "modelValue": isActive.value && !!props.scrim
  9318. }, scrimEvents.value), null), vue.createVNode(MaybeTransition, {
  9319. "appear": true,
  9320. "persisted": true,
  9321. "transition": props.transition,
  9322. "target": activatorEl.value,
  9323. "onAfterLeave": () => {
  9324. onAfterLeave();
  9325. emit('afterLeave');
  9326. }
  9327. }, {
  9328. default: () => [vue.withDirectives(vue.createVNode("div", vue.mergeProps({
  9329. "ref": contentEl,
  9330. "class": ['v-overlay__content', props.contentClass],
  9331. "style": [dimensionStyles.value, contentStyles.value]
  9332. }, contentEvents.value, props.contentProps), [slots.default?.({
  9333. isActive
  9334. })]), [[vue.vShow, isActive.value], [vue.resolveDirective("click-outside"), {
  9335. handler: onClickOutside,
  9336. closeConditional,
  9337. include: () => [activatorEl.value]
  9338. }]])]
  9339. })])]
  9340. })]));
  9341. return {
  9342. activatorEl,
  9343. animateClick,
  9344. contentEl,
  9345. globalTop,
  9346. localTop,
  9347. updateLocation
  9348. };
  9349. }
  9350. });
  9351. // Types
  9352. const Refs = Symbol('Forwarded refs');
  9353. /** Omit properties starting with P */
  9354. function getDescriptor(obj, key) {
  9355. let currentObj = obj;
  9356. while (currentObj) {
  9357. const descriptor = Reflect.getOwnPropertyDescriptor(currentObj, key);
  9358. if (descriptor) return descriptor;
  9359. currentObj = Object.getPrototypeOf(currentObj);
  9360. }
  9361. return undefined;
  9362. }
  9363. function forwardRefs(target) {
  9364. for (var _len = arguments.length, refs = new Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) {
  9365. refs[_key - 1] = arguments[_key];
  9366. }
  9367. target[Refs] = refs;
  9368. return new Proxy(target, {
  9369. get(target, key) {
  9370. if (Reflect.has(target, key)) {
  9371. return Reflect.get(target, key);
  9372. }
  9373. // Skip internal properties
  9374. if (typeof key === 'symbol' || key.startsWith('__')) return;
  9375. for (const ref of refs) {
  9376. if (ref.value && Reflect.has(ref.value, key)) {
  9377. const val = Reflect.get(ref.value, key);
  9378. return typeof val === 'function' ? val.bind(ref.value) : val;
  9379. }
  9380. }
  9381. },
  9382. has(target, key) {
  9383. if (Reflect.has(target, key)) {
  9384. return true;
  9385. }
  9386. // Skip internal properties
  9387. if (typeof key === 'symbol' || key.startsWith('__')) return false;
  9388. for (const ref of refs) {
  9389. if (ref.value && Reflect.has(ref.value, key)) {
  9390. return true;
  9391. }
  9392. }
  9393. return false;
  9394. },
  9395. set(target, key, value) {
  9396. if (Reflect.has(target, key)) {
  9397. return Reflect.set(target, key, value);
  9398. }
  9399. // Skip internal properties
  9400. if (typeof key === 'symbol' || key.startsWith('__')) return false;
  9401. for (const ref of refs) {
  9402. if (ref.value && Reflect.has(ref.value, key)) {
  9403. return Reflect.set(ref.value, key, value);
  9404. }
  9405. }
  9406. return false;
  9407. },
  9408. getOwnPropertyDescriptor(target, key) {
  9409. const descriptor = Reflect.getOwnPropertyDescriptor(target, key);
  9410. if (descriptor) return descriptor;
  9411. // Skip internal properties
  9412. if (typeof key === 'symbol' || key.startsWith('__')) return;
  9413. // Check each ref's own properties
  9414. for (const ref of refs) {
  9415. if (!ref.value) continue;
  9416. const descriptor = getDescriptor(ref.value, key) ?? ('_' in ref.value ? getDescriptor(ref.value._?.setupState, key) : undefined);
  9417. if (descriptor) return descriptor;
  9418. }
  9419. // Recursive search up each ref's prototype
  9420. for (const ref of refs) {
  9421. const childRefs = ref.value && ref.value[Refs];
  9422. if (!childRefs) continue;
  9423. const queue = childRefs.slice();
  9424. while (queue.length) {
  9425. const ref = queue.shift();
  9426. const descriptor = getDescriptor(ref.value, key);
  9427. if (descriptor) return descriptor;
  9428. const childRefs = ref.value && ref.value[Refs];
  9429. if (childRefs) queue.push(...childRefs);
  9430. }
  9431. }
  9432. return undefined;
  9433. }
  9434. });
  9435. }
  9436. // Types
  9437. const makeVMenuProps = propsFactory({
  9438. // TODO
  9439. // disableKeys: Boolean,
  9440. id: String,
  9441. ...omit(makeVOverlayProps({
  9442. closeDelay: 250,
  9443. closeOnContentClick: true,
  9444. locationStrategy: 'connected',
  9445. openDelay: 300,
  9446. scrim: false,
  9447. scrollStrategy: 'reposition',
  9448. transition: {
  9449. component: VDialogTransition
  9450. }
  9451. }), ['absolute'])
  9452. }, 'VMenu');
  9453. const VMenu = genericComponent()({
  9454. name: 'VMenu',
  9455. props: makeVMenuProps(),
  9456. emits: {
  9457. 'update:modelValue': value => true
  9458. },
  9459. setup(props, _ref) {
  9460. let {
  9461. slots
  9462. } = _ref;
  9463. const isActive = useProxiedModel(props, 'modelValue');
  9464. const {
  9465. scopeId
  9466. } = useScopeId();
  9467. const uid = getUid();
  9468. const id = vue.computed(() => props.id || `v-menu-${uid}`);
  9469. const overlay = vue.ref();
  9470. const parent = vue.inject(VMenuSymbol, null);
  9471. const openChildren = vue.shallowRef(0);
  9472. vue.provide(VMenuSymbol, {
  9473. register() {
  9474. ++openChildren.value;
  9475. },
  9476. unregister() {
  9477. --openChildren.value;
  9478. },
  9479. closeParents() {
  9480. setTimeout(() => {
  9481. if (!openChildren.value) {
  9482. isActive.value = false;
  9483. parent?.closeParents();
  9484. }
  9485. }, 40);
  9486. }
  9487. });
  9488. function onFocusIn(e) {
  9489. const before = e.relatedTarget;
  9490. const after = e.target;
  9491. if (before !== after && overlay.value?.contentEl &&
  9492. // We're the topmost menu
  9493. overlay.value?.globalTop &&
  9494. // It isn't the document or the menu body
  9495. ![document, overlay.value.contentEl].includes(after) &&
  9496. // It isn't inside the menu body
  9497. !overlay.value.contentEl.contains(after)) {
  9498. const focusable = focusableChildren(overlay.value.contentEl);
  9499. focusable[0]?.focus();
  9500. }
  9501. }
  9502. vue.watch(isActive, val => {
  9503. if (val) {
  9504. parent?.register();
  9505. document.addEventListener('focusin', onFocusIn, {
  9506. once: true
  9507. });
  9508. } else {
  9509. parent?.unregister();
  9510. document.removeEventListener('focusin', onFocusIn);
  9511. }
  9512. });
  9513. function onClickOutside() {
  9514. parent?.closeParents();
  9515. }
  9516. function onKeydown(e) {
  9517. if (props.disabled) return;
  9518. if (e.key === 'Tab') {
  9519. const nextElement = getNextElement(focusableChildren(overlay.value?.contentEl, false), e.shiftKey ? 'prev' : 'next', el => el.tabIndex >= 0);
  9520. if (!nextElement) {
  9521. isActive.value = false;
  9522. overlay.value?.activatorEl?.focus();
  9523. }
  9524. }
  9525. }
  9526. function onActivatorKeydown(e) {
  9527. if (props.disabled) return;
  9528. const el = overlay.value?.contentEl;
  9529. if (el && isActive.value) {
  9530. if (e.key === 'ArrowDown') {
  9531. e.preventDefault();
  9532. focusChild(el, 'next');
  9533. } else if (e.key === 'ArrowUp') {
  9534. e.preventDefault();
  9535. focusChild(el, 'prev');
  9536. }
  9537. } else if (['ArrowDown', 'ArrowUp'].includes(e.key)) {
  9538. isActive.value = true;
  9539. e.preventDefault();
  9540. setTimeout(() => setTimeout(() => onActivatorKeydown(e)));
  9541. }
  9542. }
  9543. const activatorProps = vue.computed(() => vue.mergeProps({
  9544. 'aria-haspopup': 'menu',
  9545. 'aria-expanded': String(isActive.value),
  9546. 'aria-owns': id.value,
  9547. onKeydown: onActivatorKeydown
  9548. }, props.activatorProps));
  9549. useRender(() => {
  9550. const [overlayProps] = VOverlay.filterProps(props);
  9551. return vue.createVNode(VOverlay, vue.mergeProps({
  9552. "ref": overlay,
  9553. "class": ['v-menu', props.class],
  9554. "style": props.style
  9555. }, overlayProps, {
  9556. "modelValue": isActive.value,
  9557. "onUpdate:modelValue": $event => isActive.value = $event,
  9558. "absolute": true,
  9559. "activatorProps": activatorProps.value,
  9560. "onClick:outside": onClickOutside,
  9561. "onKeydown": onKeydown
  9562. }, scopeId), {
  9563. activator: slots.activator,
  9564. default: function () {
  9565. for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) {
  9566. args[_key] = arguments[_key];
  9567. }
  9568. return vue.createVNode(VDefaultsProvider, {
  9569. "root": "VMenu"
  9570. }, {
  9571. default: () => [slots.default?.(...args)]
  9572. });
  9573. }
  9574. });
  9575. });
  9576. return forwardRefs({
  9577. id,
  9578. ΨopenChildren: openChildren
  9579. }, overlay);
  9580. }
  9581. });
  9582. // Types
  9583. const makeVCounterProps = propsFactory({
  9584. active: Boolean,
  9585. max: [Number, String],
  9586. value: {
  9587. type: [Number, String],
  9588. default: 0
  9589. },
  9590. ...makeComponentProps(),
  9591. ...makeTransitionProps({
  9592. transition: {
  9593. component: VSlideYTransition
  9594. }
  9595. })
  9596. }, 'VCounter');
  9597. const VCounter = genericComponent()({
  9598. name: 'VCounter',
  9599. functional: true,
  9600. props: makeVCounterProps(),
  9601. setup(props, _ref) {
  9602. let {
  9603. slots
  9604. } = _ref;
  9605. const counter = vue.computed(() => {
  9606. return props.max ? `${props.value} / ${props.max}` : String(props.value);
  9607. });
  9608. useRender(() => vue.createVNode(MaybeTransition, {
  9609. "transition": props.transition
  9610. }, {
  9611. default: () => [vue.withDirectives(vue.createVNode("div", {
  9612. "class": ['v-counter', props.class],
  9613. "style": props.style
  9614. }, [slots.default ? slots.default({
  9615. counter: counter.value,
  9616. max: props.max,
  9617. value: props.value
  9618. }) : counter.value]), [[vue.vShow, props.active]])]
  9619. }));
  9620. return {};
  9621. }
  9622. });
  9623. const makeVFieldLabelProps = propsFactory({
  9624. floating: Boolean,
  9625. ...makeComponentProps()
  9626. }, 'VFieldLabel');
  9627. const VFieldLabel = genericComponent()({
  9628. name: 'VFieldLabel',
  9629. props: makeVFieldLabelProps(),
  9630. setup(props, _ref) {
  9631. let {
  9632. slots
  9633. } = _ref;
  9634. useRender(() => vue.createVNode(VLabel, {
  9635. "class": ['v-field-label', {
  9636. 'v-field-label--floating': props.floating
  9637. }, props.class],
  9638. "style": props.style,
  9639. "aria-hidden": props.floating || undefined
  9640. }, slots));
  9641. return {};
  9642. }
  9643. });
  9644. // Types
  9645. const allowedVariants$1 = ['underlined', 'outlined', 'filled', 'solo', 'solo-inverted', 'solo-filled', 'plain'];
  9646. const makeVFieldProps = propsFactory({
  9647. appendInnerIcon: IconValue,
  9648. bgColor: String,
  9649. clearable: Boolean,
  9650. clearIcon: {
  9651. type: IconValue,
  9652. default: '$clear'
  9653. },
  9654. active: Boolean,
  9655. centerAffix: {
  9656. type: Boolean,
  9657. default: undefined
  9658. },
  9659. color: String,
  9660. baseColor: String,
  9661. dirty: Boolean,
  9662. disabled: {
  9663. type: Boolean,
  9664. default: null
  9665. },
  9666. error: Boolean,
  9667. flat: Boolean,
  9668. label: String,
  9669. persistentClear: Boolean,
  9670. prependInnerIcon: IconValue,
  9671. reverse: Boolean,
  9672. singleLine: Boolean,
  9673. variant: {
  9674. type: String,
  9675. default: 'filled',
  9676. validator: v => allowedVariants$1.includes(v)
  9677. },
  9678. 'onClick:clear': EventProp(),
  9679. 'onClick:appendInner': EventProp(),
  9680. 'onClick:prependInner': EventProp(),
  9681. ...makeComponentProps(),
  9682. ...makeLoaderProps(),
  9683. ...makeRoundedProps(),
  9684. ...makeThemeProps()
  9685. }, 'VField');
  9686. const VField = genericComponent()({
  9687. name: 'VField',
  9688. inheritAttrs: false,
  9689. props: {
  9690. id: String,
  9691. ...makeFocusProps(),
  9692. ...makeVFieldProps()
  9693. },
  9694. emits: {
  9695. 'update:focused': focused => true,
  9696. 'update:modelValue': val => true
  9697. },
  9698. setup(props, _ref) {
  9699. let {
  9700. attrs,
  9701. emit,
  9702. slots
  9703. } = _ref;
  9704. const {
  9705. themeClasses
  9706. } = provideTheme(props);
  9707. const {
  9708. loaderClasses
  9709. } = useLoader(props);
  9710. const {
  9711. focusClasses,
  9712. isFocused,
  9713. focus,
  9714. blur
  9715. } = useFocus(props);
  9716. const {
  9717. InputIcon
  9718. } = useInputIcon(props);
  9719. const {
  9720. roundedClasses
  9721. } = useRounded(props);
  9722. const {
  9723. rtlClasses
  9724. } = useRtl();
  9725. const isActive = vue.computed(() => props.dirty || props.active);
  9726. const hasLabel = vue.computed(() => !props.singleLine && !!(props.label || slots.label));
  9727. const uid = getUid();
  9728. const id = vue.computed(() => props.id || `input-${uid}`);
  9729. const messagesId = vue.computed(() => `${id.value}-messages`);
  9730. const labelRef = vue.ref();
  9731. const floatingLabelRef = vue.ref();
  9732. const controlRef = vue.ref();
  9733. const isPlainOrUnderlined = vue.computed(() => ['plain', 'underlined'].includes(props.variant));
  9734. const {
  9735. backgroundColorClasses,
  9736. backgroundColorStyles
  9737. } = useBackgroundColor(vue.toRef(props, 'bgColor'));
  9738. const {
  9739. textColorClasses,
  9740. textColorStyles
  9741. } = useTextColor(vue.computed(() => {
  9742. return props.error || props.disabled ? undefined : isActive.value && isFocused.value ? props.color : props.baseColor;
  9743. }));
  9744. vue.watch(isActive, val => {
  9745. if (hasLabel.value) {
  9746. const el = labelRef.value.$el;
  9747. const targetEl = floatingLabelRef.value.$el;
  9748. requestAnimationFrame(() => {
  9749. const rect = nullifyTransforms(el);
  9750. const targetRect = targetEl.getBoundingClientRect();
  9751. const x = targetRect.x - rect.x;
  9752. const y = targetRect.y - rect.y - (rect.height / 2 - targetRect.height / 2);
  9753. const targetWidth = targetRect.width / 0.75;
  9754. const width = Math.abs(targetWidth - rect.width) > 1 ? {
  9755. maxWidth: convertToUnit(targetWidth)
  9756. } : undefined;
  9757. const style = getComputedStyle(el);
  9758. const targetStyle = getComputedStyle(targetEl);
  9759. const duration = parseFloat(style.transitionDuration) * 1000 || 150;
  9760. const scale = parseFloat(targetStyle.getPropertyValue('--v-field-label-scale'));
  9761. const color = targetStyle.getPropertyValue('color');
  9762. el.style.visibility = 'visible';
  9763. targetEl.style.visibility = 'hidden';
  9764. animate(el, {
  9765. transform: `translate(${x}px, ${y}px) scale(${scale})`,
  9766. color,
  9767. ...width
  9768. }, {
  9769. duration,
  9770. easing: standardEasing,
  9771. direction: val ? 'normal' : 'reverse'
  9772. }).finished.then(() => {
  9773. el.style.removeProperty('visibility');
  9774. targetEl.style.removeProperty('visibility');
  9775. });
  9776. });
  9777. }
  9778. }, {
  9779. flush: 'post'
  9780. });
  9781. const slotProps = vue.computed(() => ({
  9782. isActive,
  9783. isFocused,
  9784. controlRef,
  9785. blur,
  9786. focus
  9787. }));
  9788. function onClick(e) {
  9789. if (e.target !== document.activeElement) {
  9790. e.preventDefault();
  9791. }
  9792. }
  9793. useRender(() => {
  9794. const isOutlined = props.variant === 'outlined';
  9795. const hasPrepend = slots['prepend-inner'] || props.prependInnerIcon;
  9796. const hasClear = !!(props.clearable || slots.clear);
  9797. const hasAppend = !!(slots['append-inner'] || props.appendInnerIcon || hasClear);
  9798. const label = slots.label ? slots.label({
  9799. ...slotProps.value,
  9800. label: props.label,
  9801. props: {
  9802. for: id.value
  9803. }
  9804. }) : props.label;
  9805. return vue.createVNode("div", vue.mergeProps({
  9806. "class": ['v-field', {
  9807. 'v-field--active': isActive.value,
  9808. 'v-field--appended': hasAppend,
  9809. 'v-field--center-affix': props.centerAffix ?? !isPlainOrUnderlined.value,
  9810. 'v-field--disabled': props.disabled,
  9811. 'v-field--dirty': props.dirty,
  9812. 'v-field--error': props.error,
  9813. 'v-field--flat': props.flat,
  9814. 'v-field--has-background': !!props.bgColor,
  9815. 'v-field--persistent-clear': props.persistentClear,
  9816. 'v-field--prepended': hasPrepend,
  9817. 'v-field--reverse': props.reverse,
  9818. 'v-field--single-line': props.singleLine,
  9819. 'v-field--no-label': !label,
  9820. [`v-field--variant-${props.variant}`]: true
  9821. }, themeClasses.value, backgroundColorClasses.value, focusClasses.value, loaderClasses.value, roundedClasses.value, rtlClasses.value, props.class],
  9822. "style": [backgroundColorStyles.value, textColorStyles.value, props.style],
  9823. "onClick": onClick
  9824. }, attrs), [vue.createVNode("div", {
  9825. "class": "v-field__overlay"
  9826. }, null), vue.createVNode(LoaderSlot, {
  9827. "name": "v-field",
  9828. "active": !!props.loading,
  9829. "color": props.error ? 'error' : typeof props.loading === 'string' ? props.loading : props.color
  9830. }, {
  9831. default: slots.loader
  9832. }), hasPrepend && vue.createVNode("div", {
  9833. "key": "prepend",
  9834. "class": "v-field__prepend-inner"
  9835. }, [props.prependInnerIcon && vue.createVNode(InputIcon, {
  9836. "key": "prepend-icon",
  9837. "name": "prependInner"
  9838. }, null), slots['prepend-inner']?.(slotProps.value)]), vue.createVNode("div", {
  9839. "class": "v-field__field",
  9840. "data-no-activator": ""
  9841. }, [['filled', 'solo', 'solo-inverted', 'solo-filled'].includes(props.variant) && hasLabel.value && vue.createVNode(VFieldLabel, {
  9842. "key": "floating-label",
  9843. "ref": floatingLabelRef,
  9844. "class": [textColorClasses.value],
  9845. "floating": true,
  9846. "for": id.value
  9847. }, {
  9848. default: () => [label]
  9849. }), vue.createVNode(VFieldLabel, {
  9850. "ref": labelRef,
  9851. "for": id.value
  9852. }, {
  9853. default: () => [label]
  9854. }), slots.default?.({
  9855. ...slotProps.value,
  9856. props: {
  9857. id: id.value,
  9858. class: 'v-field__input',
  9859. 'aria-describedby': messagesId.value
  9860. },
  9861. focus,
  9862. blur
  9863. })]), hasClear && vue.createVNode(VExpandXTransition, {
  9864. "key": "clear"
  9865. }, {
  9866. default: () => [vue.withDirectives(vue.createVNode("div", {
  9867. "class": "v-field__clearable",
  9868. "onMousedown": e => {
  9869. e.preventDefault();
  9870. e.stopPropagation();
  9871. }
  9872. }, [slots.clear ? slots.clear() : vue.createVNode(InputIcon, {
  9873. "name": "clear"
  9874. }, null)]), [[vue.vShow, props.dirty]])]
  9875. }), hasAppend && vue.createVNode("div", {
  9876. "key": "append",
  9877. "class": "v-field__append-inner"
  9878. }, [slots['append-inner']?.(slotProps.value), props.appendInnerIcon && vue.createVNode(InputIcon, {
  9879. "key": "append-icon",
  9880. "name": "appendInner"
  9881. }, null)]), vue.createVNode("div", {
  9882. "class": ['v-field__outline', textColorClasses.value]
  9883. }, [isOutlined && vue.createVNode(vue.Fragment, null, [vue.createVNode("div", {
  9884. "class": "v-field__outline__start"
  9885. }, null), hasLabel.value && vue.createVNode("div", {
  9886. "class": "v-field__outline__notch"
  9887. }, [vue.createVNode(VFieldLabel, {
  9888. "ref": floatingLabelRef,
  9889. "floating": true,
  9890. "for": id.value
  9891. }, {
  9892. default: () => [label]
  9893. })]), vue.createVNode("div", {
  9894. "class": "v-field__outline__end"
  9895. }, null)]), isPlainOrUnderlined.value && hasLabel.value && vue.createVNode(VFieldLabel, {
  9896. "ref": floatingLabelRef,
  9897. "floating": true,
  9898. "for": id.value
  9899. }, {
  9900. default: () => [label]
  9901. })])]);
  9902. });
  9903. return {
  9904. controlRef
  9905. };
  9906. }
  9907. });
  9908. // TODO: this is kinda slow, might be better to implicitly inherit props instead
  9909. function filterFieldProps(attrs) {
  9910. const keys = Object.keys(VField.props).filter(k => !isOn(k) && k !== 'class' && k !== 'style');
  9911. return pick(attrs, keys);
  9912. }
  9913. // Types
  9914. const activeTypes = ['color', 'file', 'time', 'date', 'datetime-local', 'week', 'month'];
  9915. const makeVTextFieldProps = propsFactory({
  9916. autofocus: Boolean,
  9917. counter: [Boolean, Number, String],
  9918. counterValue: Function,
  9919. prefix: String,
  9920. placeholder: String,
  9921. persistentPlaceholder: Boolean,
  9922. persistentCounter: Boolean,
  9923. suffix: String,
  9924. type: {
  9925. type: String,
  9926. default: 'text'
  9927. },
  9928. modelModifiers: Object,
  9929. ...makeVInputProps(),
  9930. ...makeVFieldProps()
  9931. }, 'VTextField');
  9932. const VTextField = genericComponent()({
  9933. name: 'VTextField',
  9934. directives: {
  9935. Intersect
  9936. },
  9937. inheritAttrs: false,
  9938. props: makeVTextFieldProps(),
  9939. emits: {
  9940. 'click:control': e => true,
  9941. 'mousedown:control': e => true,
  9942. 'update:focused': focused => true,
  9943. 'update:modelValue': val => true
  9944. },
  9945. setup(props, _ref) {
  9946. let {
  9947. attrs,
  9948. emit,
  9949. slots
  9950. } = _ref;
  9951. const model = useProxiedModel(props, 'modelValue');
  9952. const {
  9953. isFocused,
  9954. focus,
  9955. blur
  9956. } = useFocus(props);
  9957. const counterValue = vue.computed(() => {
  9958. return typeof props.counterValue === 'function' ? props.counterValue(model.value) : (model.value ?? '').toString().length;
  9959. });
  9960. const max = vue.computed(() => {
  9961. if (attrs.maxlength) return attrs.maxlength;
  9962. if (!props.counter || typeof props.counter !== 'number' && typeof props.counter !== 'string') return undefined;
  9963. return props.counter;
  9964. });
  9965. const isPlainOrUnderlined = vue.computed(() => ['plain', 'underlined'].includes(props.variant));
  9966. function onIntersect(isIntersecting, entries) {
  9967. if (!props.autofocus || !isIntersecting) return;
  9968. entries[0].target?.focus?.();
  9969. }
  9970. const vInputRef = vue.ref();
  9971. const vFieldRef = vue.ref();
  9972. const inputRef = vue.ref();
  9973. const isActive = vue.computed(() => activeTypes.includes(props.type) || props.persistentPlaceholder || isFocused.value || props.active);
  9974. function onFocus() {
  9975. if (inputRef.value !== document.activeElement) {
  9976. inputRef.value?.focus();
  9977. }
  9978. if (!isFocused.value) focus();
  9979. }
  9980. function onControlMousedown(e) {
  9981. emit('mousedown:control', e);
  9982. if (e.target === inputRef.value) return;
  9983. onFocus();
  9984. e.preventDefault();
  9985. }
  9986. function onControlClick(e) {
  9987. onFocus();
  9988. emit('click:control', e);
  9989. }
  9990. function onClear(e) {
  9991. e.stopPropagation();
  9992. onFocus();
  9993. vue.nextTick(() => {
  9994. model.value = null;
  9995. callEvent(props['onClick:clear'], e);
  9996. });
  9997. }
  9998. function onInput(e) {
  9999. const el = e.target;
  10000. model.value = el.value;
  10001. if (props.modelModifiers?.trim && ['text', 'search', 'password', 'tel', 'url'].includes(props.type)) {
  10002. const caretPosition = [el.selectionStart, el.selectionEnd];
  10003. vue.nextTick(() => {
  10004. el.selectionStart = caretPosition[0];
  10005. el.selectionEnd = caretPosition[1];
  10006. });
  10007. }
  10008. }
  10009. useRender(() => {
  10010. const hasCounter = !!(slots.counter || props.counter || props.counterValue);
  10011. const hasDetails = !!(hasCounter || slots.details);
  10012. const [rootAttrs, inputAttrs] = filterInputAttrs(attrs);
  10013. const [{
  10014. modelValue: _,
  10015. ...inputProps
  10016. }] = VInput.filterProps(props);
  10017. const [fieldProps] = filterFieldProps(props);
  10018. return vue.createVNode(VInput, vue.mergeProps({
  10019. "ref": vInputRef,
  10020. "modelValue": model.value,
  10021. "onUpdate:modelValue": $event => model.value = $event,
  10022. "class": ['v-text-field', {
  10023. 'v-text-field--prefixed': props.prefix,
  10024. 'v-text-field--suffixed': props.suffix,
  10025. 'v-text-field--plain-underlined': ['plain', 'underlined'].includes(props.variant)
  10026. }, props.class],
  10027. "style": props.style
  10028. }, rootAttrs, inputProps, {
  10029. "centerAffix": !isPlainOrUnderlined.value,
  10030. "focused": isFocused.value
  10031. }), {
  10032. ...slots,
  10033. default: _ref2 => {
  10034. let {
  10035. id,
  10036. isDisabled,
  10037. isDirty,
  10038. isReadonly,
  10039. isValid
  10040. } = _ref2;
  10041. return vue.createVNode(VField, vue.mergeProps({
  10042. "ref": vFieldRef,
  10043. "onMousedown": onControlMousedown,
  10044. "onClick": onControlClick,
  10045. "onClick:clear": onClear,
  10046. "onClick:prependInner": props['onClick:prependInner'],
  10047. "onClick:appendInner": props['onClick:appendInner'],
  10048. "role": "textbox"
  10049. }, fieldProps, {
  10050. "id": id.value,
  10051. "active": isActive.value || isDirty.value,
  10052. "dirty": isDirty.value || props.dirty,
  10053. "disabled": isDisabled.value,
  10054. "focused": isFocused.value,
  10055. "error": isValid.value === false
  10056. }), {
  10057. ...slots,
  10058. default: _ref3 => {
  10059. let {
  10060. props: {
  10061. class: fieldClass,
  10062. ...slotProps
  10063. }
  10064. } = _ref3;
  10065. const inputNode = vue.withDirectives(vue.createVNode("input", vue.mergeProps({
  10066. "ref": inputRef,
  10067. "value": model.value,
  10068. "onInput": onInput,
  10069. "autofocus": props.autofocus,
  10070. "readonly": isReadonly.value,
  10071. "disabled": isDisabled.value,
  10072. "name": props.name,
  10073. "placeholder": props.placeholder,
  10074. "size": 1,
  10075. "type": props.type,
  10076. "onFocus": onFocus,
  10077. "onBlur": blur
  10078. }, slotProps, inputAttrs), null), [[vue.resolveDirective("intersect"), {
  10079. handler: onIntersect
  10080. }, null, {
  10081. once: true
  10082. }]]);
  10083. return vue.createVNode(vue.Fragment, null, [props.prefix && vue.createVNode("span", {
  10084. "class": "v-text-field__prefix"
  10085. }, [vue.createVNode("span", {
  10086. "class": "v-text-field__prefix__text"
  10087. }, [props.prefix])]), vue.createVNode("div", {
  10088. "class": fieldClass,
  10089. "data-no-activator": ""
  10090. }, [slots.default ? vue.createVNode(vue.Fragment, null, [slots.default(), inputNode]) : vue.cloneVNode(inputNode)]), props.suffix && vue.createVNode("span", {
  10091. "class": "v-text-field__suffix"
  10092. }, [vue.createVNode("span", {
  10093. "class": "v-text-field__suffix__text"
  10094. }, [props.suffix])])]);
  10095. }
  10096. });
  10097. },
  10098. 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, {
  10099. "active": props.persistentCounter || isFocused.value,
  10100. "value": counterValue.value,
  10101. "max": max.value
  10102. }, slots.counter)])]) : undefined
  10103. });
  10104. });
  10105. return forwardRefs({}, vInputRef, vFieldRef, inputRef);
  10106. }
  10107. });
  10108. // Types
  10109. const makeVVirtualScrollItemProps = propsFactory({
  10110. renderless: Boolean,
  10111. ...makeComponentProps()
  10112. }, 'VVirtualScrollItem');
  10113. const VVirtualScrollItem = genericComponent()({
  10114. name: 'VVirtualScrollItem',
  10115. inheritAttrs: false,
  10116. props: makeVVirtualScrollItemProps(),
  10117. emits: {
  10118. 'update:height': height => true
  10119. },
  10120. setup(props, _ref) {
  10121. let {
  10122. attrs,
  10123. emit,
  10124. slots
  10125. } = _ref;
  10126. const {
  10127. resizeRef,
  10128. contentRect
  10129. } = useResizeObserver(undefined, 'border');
  10130. vue.watch(() => contentRect.value?.height, height => {
  10131. if (height != null) emit('update:height', height);
  10132. });
  10133. useRender(() => props.renderless ? vue.createVNode(vue.Fragment, null, [slots.default?.({
  10134. itemRef: resizeRef
  10135. })]) : vue.createVNode("div", vue.mergeProps({
  10136. "ref": resizeRef,
  10137. "class": ['v-virtual-scroll__item', props.class],
  10138. "style": props.style
  10139. }, attrs), [slots.default?.()]));
  10140. }
  10141. });
  10142. // Composables
  10143. // Types
  10144. const UP = -1;
  10145. const DOWN = 1;
  10146. const makeVirtualProps = propsFactory({
  10147. itemHeight: {
  10148. type: [Number, String],
  10149. default: 48
  10150. }
  10151. }, 'virtual');
  10152. function useVirtual(props, items, offset) {
  10153. const first = vue.shallowRef(0);
  10154. const baseItemHeight = vue.shallowRef(props.itemHeight);
  10155. const itemHeight = vue.computed({
  10156. get: () => parseInt(baseItemHeight.value ?? 0, 10),
  10157. set(val) {
  10158. baseItemHeight.value = val;
  10159. }
  10160. });
  10161. const containerRef = vue.ref();
  10162. const {
  10163. resizeRef,
  10164. contentRect
  10165. } = useResizeObserver();
  10166. vue.watchEffect(() => {
  10167. resizeRef.value = containerRef.value;
  10168. });
  10169. const display = useDisplay();
  10170. const sizeMap = new Map();
  10171. let sizes = Array.from({
  10172. length: items.value.length
  10173. });
  10174. const visibleItems = vue.computed(() => {
  10175. const height = (!contentRect.value || containerRef.value === document.documentElement ? display.height.value : contentRect.value.height) - (offset?.value ?? 0);
  10176. return Math.ceil(height / itemHeight.value * 1.7 + 1);
  10177. });
  10178. function handleItemResize(index, height) {
  10179. itemHeight.value = Math.max(itemHeight.value, height);
  10180. sizes[index] = height;
  10181. sizeMap.set(items.value[index], height);
  10182. }
  10183. function calculateOffset(index) {
  10184. return sizes.slice(0, index).reduce((acc, val) => acc + (val || itemHeight.value), 0);
  10185. }
  10186. function calculateMidPointIndex(scrollTop) {
  10187. const end = items.value.length;
  10188. let middle = 0;
  10189. let middleOffset = 0;
  10190. while (middleOffset < scrollTop && middle < end) {
  10191. middleOffset += sizes[middle++] || itemHeight.value;
  10192. }
  10193. return middle - 1;
  10194. }
  10195. let lastScrollTop = 0;
  10196. function handleScroll() {
  10197. if (!containerRef.value || !contentRect.value) return;
  10198. const height = contentRect.value.height - 56;
  10199. const scrollTop = containerRef.value.scrollTop;
  10200. const direction = scrollTop < lastScrollTop ? UP : DOWN;
  10201. const midPointIndex = calculateMidPointIndex(scrollTop + height / 2);
  10202. const buffer = Math.round(visibleItems.value / 3);
  10203. const firstIndex = midPointIndex - buffer;
  10204. const lastIndex = first.value + buffer * 2 - 1;
  10205. if (direction === UP && midPointIndex <= lastIndex) {
  10206. first.value = clamp(firstIndex, 0, items.value.length);
  10207. } else if (direction === DOWN && midPointIndex >= lastIndex) {
  10208. first.value = clamp(firstIndex, 0, items.value.length - visibleItems.value);
  10209. }
  10210. lastScrollTop = scrollTop;
  10211. }
  10212. function scrollToIndex(index) {
  10213. if (!containerRef.value) return;
  10214. const offset = calculateOffset(index);
  10215. containerRef.value.scrollTop = offset;
  10216. }
  10217. const last = vue.computed(() => Math.min(items.value.length, first.value + visibleItems.value));
  10218. const computedItems = vue.computed(() => {
  10219. return items.value.slice(first.value, last.value).map((item, index) => ({
  10220. raw: item,
  10221. index: index + first.value
  10222. }));
  10223. });
  10224. const paddingTop = vue.computed(() => calculateOffset(first.value));
  10225. const paddingBottom = vue.computed(() => calculateOffset(items.value.length) - calculateOffset(last.value));
  10226. vue.watch(() => items.value.length, () => {
  10227. sizes = createRange(items.value.length).map(() => itemHeight.value);
  10228. sizeMap.forEach((height, item) => {
  10229. const index = items.value.indexOf(item);
  10230. if (index === -1) {
  10231. sizeMap.delete(item);
  10232. } else {
  10233. sizes[index] = height;
  10234. }
  10235. });
  10236. });
  10237. return {
  10238. containerRef,
  10239. computedItems,
  10240. itemHeight,
  10241. paddingTop,
  10242. paddingBottom,
  10243. scrollToIndex,
  10244. handleScroll,
  10245. handleItemResize
  10246. };
  10247. }
  10248. // Types
  10249. const makeVVirtualScrollProps = propsFactory({
  10250. items: {
  10251. type: Array,
  10252. default: () => []
  10253. },
  10254. renderless: Boolean,
  10255. ...makeVirtualProps(),
  10256. ...makeComponentProps(),
  10257. ...makeDimensionProps()
  10258. }, 'VVirtualScroll');
  10259. const VVirtualScroll = genericComponent()({
  10260. name: 'VVirtualScroll',
  10261. props: makeVVirtualScrollProps(),
  10262. setup(props, _ref) {
  10263. let {
  10264. slots
  10265. } = _ref;
  10266. const vm = getCurrentInstance('VVirtualScroll');
  10267. const {
  10268. dimensionStyles
  10269. } = useDimension(props);
  10270. const {
  10271. containerRef,
  10272. handleScroll,
  10273. handleItemResize,
  10274. scrollToIndex,
  10275. paddingTop,
  10276. paddingBottom,
  10277. computedItems
  10278. } = useVirtual(props, vue.toRef(props, 'items'));
  10279. useToggleScope(() => props.renderless, () => {
  10280. vue.onMounted(() => {
  10281. containerRef.value = getScrollParent(vm.vnode.el, true);
  10282. containerRef.value?.addEventListener('scroll', handleScroll);
  10283. });
  10284. vue.onScopeDispose(() => {
  10285. containerRef.value?.removeEventListener('scroll', handleScroll);
  10286. });
  10287. });
  10288. useRender(() => {
  10289. const children = computedItems.value.map(item => vue.createVNode(VVirtualScrollItem, {
  10290. "key": item.index,
  10291. "renderless": props.renderless,
  10292. "onUpdate:height": height => handleItemResize(item.index, height)
  10293. }, {
  10294. default: slotProps => slots.default?.({
  10295. item: item.raw,
  10296. index: item.index,
  10297. ...slotProps
  10298. })
  10299. }));
  10300. return props.renderless ? vue.createVNode(vue.Fragment, null, [vue.createVNode("div", {
  10301. "class": "v-virtual-scroll__spacer",
  10302. "style": {
  10303. paddingTop: convertToUnit(paddingTop.value)
  10304. }
  10305. }, null), children, vue.createVNode("div", {
  10306. "class": "v-virtual-scroll__spacer",
  10307. "style": {
  10308. paddingBottom: convertToUnit(paddingBottom.value)
  10309. }
  10310. }, null)]) : vue.createVNode("div", {
  10311. "ref": containerRef,
  10312. "class": ['v-virtual-scroll', props.class],
  10313. "onScroll": handleScroll,
  10314. "style": [dimensionStyles.value, props.style]
  10315. }, [vue.createVNode("div", {
  10316. "class": "v-virtual-scroll__container",
  10317. "style": {
  10318. paddingTop: convertToUnit(paddingTop.value),
  10319. paddingBottom: convertToUnit(paddingBottom.value)
  10320. }
  10321. }, [children])]);
  10322. });
  10323. return {
  10324. scrollToIndex
  10325. };
  10326. }
  10327. });
  10328. // Utilities
  10329. // Types
  10330. function useScrolling(listRef, textFieldRef) {
  10331. const isScrolling = vue.shallowRef(false);
  10332. let scrollTimeout;
  10333. function onListScroll(e) {
  10334. cancelAnimationFrame(scrollTimeout);
  10335. isScrolling.value = true;
  10336. scrollTimeout = requestAnimationFrame(() => {
  10337. scrollTimeout = requestAnimationFrame(() => {
  10338. isScrolling.value = false;
  10339. });
  10340. });
  10341. }
  10342. async function finishScrolling() {
  10343. await new Promise(resolve => requestAnimationFrame(resolve));
  10344. await new Promise(resolve => requestAnimationFrame(resolve));
  10345. await new Promise(resolve => requestAnimationFrame(resolve));
  10346. await new Promise(resolve => {
  10347. if (isScrolling.value) {
  10348. const stop = vue.watch(isScrolling, () => {
  10349. stop();
  10350. resolve();
  10351. });
  10352. } else resolve();
  10353. });
  10354. }
  10355. async function onListKeydown(e) {
  10356. if (e.key === 'Tab') {
  10357. textFieldRef.value?.focus();
  10358. }
  10359. if (!['PageDown', 'PageUp', 'Home', 'End'].includes(e.key)) return;
  10360. const el = listRef.value?.$el;
  10361. if (!el) return;
  10362. if (e.key === 'Home' || e.key === 'End') {
  10363. el.scrollTo({
  10364. top: e.key === 'Home' ? 0 : el.scrollHeight,
  10365. behavior: 'smooth'
  10366. });
  10367. }
  10368. await finishScrolling();
  10369. const children = el.querySelectorAll(':scope > :not(.v-virtual-scroll__spacer)');
  10370. if (e.key === 'PageDown' || e.key === 'Home') {
  10371. const top = el.getBoundingClientRect().top;
  10372. for (const child of children) {
  10373. if (child.getBoundingClientRect().top >= top) {
  10374. child.focus();
  10375. break;
  10376. }
  10377. }
  10378. } else {
  10379. const bottom = el.getBoundingClientRect().bottom;
  10380. for (const child of [...children].reverse()) {
  10381. if (child.getBoundingClientRect().bottom <= bottom) {
  10382. child.focus();
  10383. break;
  10384. }
  10385. }
  10386. }
  10387. }
  10388. return {
  10389. onListScroll,
  10390. onListKeydown
  10391. };
  10392. }
  10393. // Types
  10394. const makeSelectProps = propsFactory({
  10395. chips: Boolean,
  10396. closableChips: Boolean,
  10397. eager: Boolean,
  10398. hideNoData: Boolean,
  10399. hideSelected: Boolean,
  10400. menu: Boolean,
  10401. menuIcon: {
  10402. type: IconValue,
  10403. default: '$dropdown'
  10404. },
  10405. menuProps: {
  10406. type: Object
  10407. },
  10408. multiple: Boolean,
  10409. noDataText: {
  10410. type: String,
  10411. default: '$vuetify.noDataText'
  10412. },
  10413. openOnClear: Boolean,
  10414. valueComparator: {
  10415. type: Function,
  10416. default: deepEqual
  10417. },
  10418. itemColor: String,
  10419. ...makeItemsProps({
  10420. itemChildren: false
  10421. })
  10422. }, 'Select');
  10423. const makeVSelectProps = propsFactory({
  10424. ...makeSelectProps(),
  10425. ...omit(makeVTextFieldProps({
  10426. modelValue: null
  10427. }), ['validationValue', 'dirty', 'appendInnerIcon']),
  10428. ...makeTransitionProps({
  10429. transition: {
  10430. component: VDialogTransition
  10431. }
  10432. })
  10433. }, 'VSelect');
  10434. const VSelect = genericComponent()({
  10435. name: 'VSelect',
  10436. props: makeVSelectProps(),
  10437. emits: {
  10438. 'update:focused': focused => true,
  10439. 'update:modelValue': val => true,
  10440. 'update:menu': val => true
  10441. },
  10442. setup(props, _ref) {
  10443. let {
  10444. slots
  10445. } = _ref;
  10446. const {
  10447. t
  10448. } = useLocale();
  10449. const vTextFieldRef = vue.ref();
  10450. const vMenuRef = vue.ref();
  10451. const _menu = useProxiedModel(props, 'menu');
  10452. const menu = vue.computed({
  10453. get: () => _menu.value,
  10454. set: v => {
  10455. if (_menu.value && !v && vMenuRef.value?.ΨopenChildren) return;
  10456. _menu.value = v;
  10457. }
  10458. });
  10459. const {
  10460. items,
  10461. transformIn,
  10462. transformOut
  10463. } = useItems(props);
  10464. const model = useProxiedModel(props, 'modelValue', [], v => transformIn(v === null ? [null] : wrapInArray(v)), v => {
  10465. const transformed = transformOut(v);
  10466. return props.multiple ? transformed : transformed[0] ?? null;
  10467. });
  10468. const form = useForm();
  10469. const selections = vue.computed(() => {
  10470. return model.value.map(v => {
  10471. return items.value.find(item => {
  10472. const itemRawValue = getPropertyFromItem(item.raw, props.itemValue);
  10473. const modelRawValue = getPropertyFromItem(v.raw, props.itemValue);
  10474. if (itemRawValue === undefined || modelRawValue === undefined) return false;
  10475. return props.returnObject ? props.valueComparator(itemRawValue, modelRawValue) : props.valueComparator(item.value, v.value);
  10476. }) || v;
  10477. });
  10478. });
  10479. const selected = vue.computed(() => selections.value.map(selection => selection.props.value));
  10480. const isFocused = vue.shallowRef(false);
  10481. let keyboardLookupPrefix = '';
  10482. let keyboardLookupLastTime;
  10483. const displayItems = vue.computed(() => {
  10484. if (props.hideSelected) {
  10485. return items.value.filter(item => !selections.value.some(s => s === item));
  10486. }
  10487. return items.value;
  10488. });
  10489. const menuDisabled = vue.computed(() => props.hideNoData && !items.value.length || props.readonly || form?.isReadonly.value);
  10490. const listRef = vue.ref();
  10491. const {
  10492. onListScroll,
  10493. onListKeydown
  10494. } = useScrolling(listRef, vTextFieldRef);
  10495. function onClear(e) {
  10496. if (props.openOnClear) {
  10497. menu.value = true;
  10498. }
  10499. }
  10500. function onMousedownControl() {
  10501. if (menuDisabled.value) return;
  10502. menu.value = !menu.value;
  10503. }
  10504. function onKeydown(e) {
  10505. if (!e.key || props.readonly || form?.isReadonly.value) return;
  10506. if (['Enter', ' ', 'ArrowDown', 'ArrowUp', 'Home', 'End'].includes(e.key)) {
  10507. e.preventDefault();
  10508. }
  10509. if (['Enter', 'ArrowDown', ' '].includes(e.key)) {
  10510. menu.value = true;
  10511. }
  10512. if (['Escape', 'Tab'].includes(e.key)) {
  10513. menu.value = false;
  10514. }
  10515. if (e.key === 'Home') {
  10516. listRef.value?.focus('first');
  10517. } else if (e.key === 'End') {
  10518. listRef.value?.focus('last');
  10519. }
  10520. // html select hotkeys
  10521. const KEYBOARD_LOOKUP_THRESHOLD = 1000; // milliseconds
  10522. function checkPrintable(e) {
  10523. const isPrintableChar = e.key.length === 1;
  10524. const noModifier = !e.ctrlKey && !e.metaKey && !e.altKey;
  10525. return isPrintableChar && noModifier;
  10526. }
  10527. if (props.multiple || !checkPrintable(e)) return;
  10528. const now = performance.now();
  10529. if (now - keyboardLookupLastTime > KEYBOARD_LOOKUP_THRESHOLD) {
  10530. keyboardLookupPrefix = '';
  10531. }
  10532. keyboardLookupPrefix += e.key.toLowerCase();
  10533. keyboardLookupLastTime = now;
  10534. const item = items.value.find(item => item.title.toLowerCase().startsWith(keyboardLookupPrefix));
  10535. if (item !== undefined) {
  10536. model.value = [item];
  10537. }
  10538. }
  10539. function select(item) {
  10540. if (props.multiple) {
  10541. const index = selected.value.findIndex(selection => props.valueComparator(selection, item.value));
  10542. if (index === -1) {
  10543. model.value = [...model.value, item];
  10544. } else {
  10545. const value = [...model.value];
  10546. value.splice(index, 1);
  10547. model.value = value;
  10548. }
  10549. } else {
  10550. model.value = [item];
  10551. menu.value = false;
  10552. }
  10553. }
  10554. function onBlur(e) {
  10555. if (!listRef.value?.$el.contains(e.relatedTarget)) {
  10556. menu.value = false;
  10557. }
  10558. }
  10559. function onAfterLeave() {
  10560. if (isFocused.value) {
  10561. vTextFieldRef.value?.focus();
  10562. }
  10563. }
  10564. function onFocusin(e) {
  10565. isFocused.value = true;
  10566. }
  10567. function onModelUpdate(v) {
  10568. if (v == null) model.value = [];else if (matchesSelector(vTextFieldRef.value, ':autofill') || matchesSelector(vTextFieldRef.value, ':-webkit-autofill')) {
  10569. const item = items.value.find(item => item.title === v);
  10570. if (item) {
  10571. select(item);
  10572. }
  10573. } else if (vTextFieldRef.value) {
  10574. vTextFieldRef.value.value = '';
  10575. }
  10576. }
  10577. useRender(() => {
  10578. const hasChips = !!(props.chips || slots.chip);
  10579. const hasList = !!(!props.hideNoData || displayItems.value.length || slots['prepend-item'] || slots['append-item'] || slots['no-data']);
  10580. const isDirty = model.value.length > 0;
  10581. const [textFieldProps] = VTextField.filterProps(props);
  10582. const placeholder = isDirty || !isFocused.value && props.label && !props.persistentPlaceholder ? undefined : props.placeholder;
  10583. return vue.createVNode(VTextField, vue.mergeProps({
  10584. "ref": vTextFieldRef
  10585. }, textFieldProps, {
  10586. "modelValue": model.value.map(v => v.props.value).join(', '),
  10587. "onUpdate:modelValue": onModelUpdate,
  10588. "focused": isFocused.value,
  10589. "onUpdate:focused": $event => isFocused.value = $event,
  10590. "validationValue": model.externalValue,
  10591. "dirty": isDirty,
  10592. "class": ['v-select', {
  10593. 'v-select--active-menu': menu.value,
  10594. 'v-select--chips': !!props.chips,
  10595. [`v-select--${props.multiple ? 'multiple' : 'single'}`]: true,
  10596. 'v-select--selected': model.value.length,
  10597. 'v-select--selection-slot': !!slots.selection
  10598. }, props.class],
  10599. "style": props.style,
  10600. "inputmode": "none",
  10601. "placeholder": placeholder,
  10602. "onClick:clear": onClear,
  10603. "onMousedown:control": onMousedownControl,
  10604. "onBlur": onBlur,
  10605. "onKeydown": onKeydown
  10606. }), {
  10607. ...slots,
  10608. default: () => vue.createVNode(vue.Fragment, null, [vue.createVNode(VMenu, vue.mergeProps({
  10609. "ref": vMenuRef,
  10610. "modelValue": menu.value,
  10611. "onUpdate:modelValue": $event => menu.value = $event,
  10612. "activator": "parent",
  10613. "contentClass": "v-select__content",
  10614. "disabled": menuDisabled.value,
  10615. "eager": props.eager,
  10616. "maxHeight": 310,
  10617. "openOnClick": false,
  10618. "closeOnContentClick": false,
  10619. "transition": props.transition,
  10620. "onAfterLeave": onAfterLeave
  10621. }, props.menuProps), {
  10622. default: () => [hasList && vue.createVNode(VList, {
  10623. "ref": listRef,
  10624. "selected": selected.value,
  10625. "selectStrategy": props.multiple ? 'independent' : 'single-independent',
  10626. "onMousedown": e => e.preventDefault(),
  10627. "onKeydown": onListKeydown,
  10628. "onFocusin": onFocusin,
  10629. "onScrollPassive": onListScroll,
  10630. "tabindex": "-1",
  10631. "color": props.itemColor ?? props.color
  10632. }, {
  10633. default: () => [slots['prepend-item']?.(), !displayItems.value.length && !props.hideNoData && (slots['no-data']?.() ?? vue.createVNode(VListItem, {
  10634. "title": t(props.noDataText)
  10635. }, null)), vue.createVNode(VVirtualScroll, {
  10636. "renderless": true,
  10637. "items": displayItems.value
  10638. }, {
  10639. default: _ref2 => {
  10640. let {
  10641. item,
  10642. index,
  10643. itemRef
  10644. } = _ref2;
  10645. const itemProps = vue.mergeProps(item.props, {
  10646. ref: itemRef,
  10647. key: index,
  10648. onClick: () => select(item)
  10649. });
  10650. return slots.item?.({
  10651. item,
  10652. index,
  10653. props: itemProps
  10654. }) ?? vue.createVNode(VListItem, itemProps, {
  10655. prepend: _ref3 => {
  10656. let {
  10657. isSelected
  10658. } = _ref3;
  10659. return vue.createVNode(vue.Fragment, null, [props.multiple && !props.hideSelected ? vue.createVNode(VCheckboxBtn, {
  10660. "key": item.value,
  10661. "modelValue": isSelected,
  10662. "ripple": false,
  10663. "tabindex": "-1"
  10664. }, null) : undefined, item.props.prependIcon && vue.createVNode(VIcon, {
  10665. "icon": item.props.prependIcon
  10666. }, null)]);
  10667. }
  10668. });
  10669. }
  10670. }), slots['append-item']?.()]
  10671. })]
  10672. }), selections.value.map((item, index) => {
  10673. function onChipClose(e) {
  10674. e.stopPropagation();
  10675. e.preventDefault();
  10676. select(item);
  10677. }
  10678. const slotProps = {
  10679. 'onClick:close': onChipClose,
  10680. onMousedown(e) {
  10681. e.preventDefault();
  10682. e.stopPropagation();
  10683. },
  10684. modelValue: true,
  10685. 'onUpdate:modelValue': undefined
  10686. };
  10687. return vue.createVNode("div", {
  10688. "key": item.value,
  10689. "class": "v-select__selection"
  10690. }, [hasChips ? !slots.chip ? vue.createVNode(VChip, vue.mergeProps({
  10691. "key": "chip",
  10692. "closable": props.closableChips,
  10693. "size": "small",
  10694. "text": item.title
  10695. }, slotProps), null) : vue.createVNode(VDefaultsProvider, {
  10696. "key": "chip-defaults",
  10697. "defaults": {
  10698. VChip: {
  10699. closable: props.closableChips,
  10700. size: 'small',
  10701. text: item.title
  10702. }
  10703. }
  10704. }, {
  10705. default: () => [slots.chip?.({
  10706. item,
  10707. index,
  10708. props: slotProps
  10709. })]
  10710. }) : slots.selection?.({
  10711. item,
  10712. index
  10713. }) ?? vue.createVNode("span", {
  10714. "class": "v-select__selection-text"
  10715. }, [item.title, props.multiple && index < selections.value.length - 1 && vue.createVNode("span", {
  10716. "class": "v-select__selection-comma"
  10717. }, [vue.createTextVNode(",")])])]);
  10718. })]),
  10719. 'append-inner': function () {
  10720. for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) {
  10721. args[_key] = arguments[_key];
  10722. }
  10723. return vue.createVNode(vue.Fragment, null, [slots['append-inner']?.(...args), props.menuIcon ? vue.createVNode(VIcon, {
  10724. "class": "v-select__menu-icon",
  10725. "icon": props.menuIcon
  10726. }, null) : undefined]);
  10727. }
  10728. });
  10729. });
  10730. return forwardRefs({
  10731. isFocused,
  10732. menu,
  10733. select
  10734. }, vTextFieldRef);
  10735. }
  10736. });
  10737. /* eslint-disable max-statements */
  10738. /* eslint-disable no-labels */
  10739. // Types
  10740. // Composables
  10741. const defaultFilter = (value, query, item) => {
  10742. if (value == null || query == null) return -1;
  10743. return value.toString().toLocaleLowerCase().indexOf(query.toString().toLocaleLowerCase());
  10744. };
  10745. const makeFilterProps = propsFactory({
  10746. customFilter: Function,
  10747. customKeyFilter: Object,
  10748. filterKeys: [Array, String],
  10749. filterMode: {
  10750. type: String,
  10751. default: 'intersection'
  10752. },
  10753. noFilter: Boolean
  10754. }, 'filter');
  10755. function filterItems(items, query, options) {
  10756. const array = [];
  10757. // always ensure we fall back to a functioning filter
  10758. const filter = options?.default ?? defaultFilter;
  10759. const keys = options?.filterKeys ? wrapInArray(options.filterKeys) : false;
  10760. const customFiltersLength = Object.keys(options?.customKeyFilter ?? {}).length;
  10761. if (!items?.length) return array;
  10762. loop: for (let i = 0; i < items.length; i++) {
  10763. const item = items[i];
  10764. const customMatches = {};
  10765. const defaultMatches = {};
  10766. let match = -1;
  10767. if (query && !options?.noFilter) {
  10768. if (typeof item === 'object') {
  10769. const filterKeys = keys || Object.keys(item);
  10770. for (const key of filterKeys) {
  10771. const value = getPropertyFromItem(item, key, item);
  10772. const keyFilter = options?.customKeyFilter?.[key];
  10773. match = keyFilter ? keyFilter(value, query, item) : filter(value, query, item);
  10774. if (match !== -1 && match !== false) {
  10775. if (keyFilter) customMatches[key] = match;else defaultMatches[key] = match;
  10776. } else if (options?.filterMode === 'every') {
  10777. continue loop;
  10778. }
  10779. }
  10780. } else {
  10781. match = filter(item, query, item);
  10782. if (match !== -1 && match !== false) {
  10783. defaultMatches.title = match;
  10784. }
  10785. }
  10786. const defaultMatchesLength = Object.keys(defaultMatches).length;
  10787. const customMatchesLength = Object.keys(customMatches).length;
  10788. if (!defaultMatchesLength && !customMatchesLength) continue;
  10789. if (options?.filterMode === 'union' && customMatchesLength !== customFiltersLength && !defaultMatchesLength) continue;
  10790. if (options?.filterMode === 'intersection' && (customMatchesLength !== customFiltersLength || !defaultMatchesLength)) continue;
  10791. }
  10792. array.push({
  10793. index: i,
  10794. matches: {
  10795. ...defaultMatches,
  10796. ...customMatches
  10797. }
  10798. });
  10799. }
  10800. return array;
  10801. }
  10802. function useFilter(props, items, query, options) {
  10803. const filteredItems = vue.ref([]);
  10804. const filteredMatches = vue.ref(new Map());
  10805. const transformedItems = vue.computed(() => options?.transform ? vue.unref(items).map(options?.transform) : vue.unref(items));
  10806. vue.watchEffect(() => {
  10807. const _query = typeof query === 'function' ? query() : vue.unref(query);
  10808. const strQuery = typeof _query !== 'string' && typeof _query !== 'number' ? '' : String(_query);
  10809. const results = filterItems(transformedItems.value, strQuery, {
  10810. customKeyFilter: props.customKeyFilter,
  10811. default: props.customFilter,
  10812. filterKeys: props.filterKeys,
  10813. filterMode: props.filterMode,
  10814. noFilter: props.noFilter
  10815. });
  10816. const originalItems = vue.unref(items);
  10817. const _filteredItems = [];
  10818. const _filteredMatches = new Map();
  10819. results.forEach(_ref => {
  10820. let {
  10821. index,
  10822. matches
  10823. } = _ref;
  10824. const item = originalItems[index];
  10825. _filteredItems.push(item);
  10826. _filteredMatches.set(item.value, matches);
  10827. });
  10828. filteredItems.value = _filteredItems;
  10829. filteredMatches.value = _filteredMatches;
  10830. });
  10831. function getMatches(item) {
  10832. return filteredMatches.value.get(item.value);
  10833. }
  10834. return {
  10835. filteredItems,
  10836. filteredMatches,
  10837. getMatches
  10838. };
  10839. }
  10840. // Types
  10841. function highlightResult$1(text, matches, length) {
  10842. if (matches == null) return text;
  10843. if (Array.isArray(matches)) throw new Error('Multiple matches is not implemented');
  10844. return typeof matches === 'number' && ~matches ? vue.createVNode(vue.Fragment, null, [vue.createVNode("span", {
  10845. "class": "v-autocomplete__unmask"
  10846. }, [text.substr(0, matches)]), vue.createVNode("span", {
  10847. "class": "v-autocomplete__mask"
  10848. }, [text.substr(matches, length)]), vue.createVNode("span", {
  10849. "class": "v-autocomplete__unmask"
  10850. }, [text.substr(matches + length)])]) : text;
  10851. }
  10852. const makeVAutocompleteProps = propsFactory({
  10853. autoSelectFirst: {
  10854. type: [Boolean, String]
  10855. },
  10856. search: String,
  10857. ...makeFilterProps({
  10858. filterKeys: ['title']
  10859. }),
  10860. ...makeSelectProps(),
  10861. ...omit(makeVTextFieldProps({
  10862. modelValue: null
  10863. }), ['validationValue', 'dirty', 'appendInnerIcon']),
  10864. ...makeTransitionProps({
  10865. transition: false
  10866. })
  10867. }, 'VAutocomplete');
  10868. const VAutocomplete = genericComponent()({
  10869. name: 'VAutocomplete',
  10870. props: makeVAutocompleteProps(),
  10871. emits: {
  10872. 'update:focused': focused => true,
  10873. 'update:search': val => true,
  10874. 'update:modelValue': val => true,
  10875. 'update:menu': val => true
  10876. },
  10877. setup(props, _ref) {
  10878. let {
  10879. slots
  10880. } = _ref;
  10881. const {
  10882. t
  10883. } = useLocale();
  10884. const vTextFieldRef = vue.ref();
  10885. const isFocused = vue.shallowRef(false);
  10886. const isPristine = vue.shallowRef(true);
  10887. const listHasFocus = vue.shallowRef(false);
  10888. const vMenuRef = vue.ref();
  10889. const _menu = useProxiedModel(props, 'menu');
  10890. const menu = vue.computed({
  10891. get: () => _menu.value,
  10892. set: v => {
  10893. if (_menu.value && !v && vMenuRef.value?.ΨopenChildren) return;
  10894. _menu.value = v;
  10895. }
  10896. });
  10897. const selectionIndex = vue.shallowRef(-1);
  10898. const color = vue.computed(() => vTextFieldRef.value?.color);
  10899. const {
  10900. items,
  10901. transformIn,
  10902. transformOut
  10903. } = useItems(props);
  10904. const {
  10905. textColorClasses,
  10906. textColorStyles
  10907. } = useTextColor(color);
  10908. const search = useProxiedModel(props, 'search', '');
  10909. const model = useProxiedModel(props, 'modelValue', [], v => transformIn(v === null ? [null] : wrapInArray(v)), v => {
  10910. const transformed = transformOut(v);
  10911. return props.multiple ? transformed : transformed[0] ?? null;
  10912. });
  10913. const form = useForm();
  10914. const {
  10915. filteredItems,
  10916. getMatches
  10917. } = useFilter(props, items, () => isPristine.value ? '' : search.value);
  10918. const selections = vue.computed(() => {
  10919. return model.value.map(v => {
  10920. return items.value.find(item => {
  10921. const itemRawValue = getPropertyFromItem(item.raw, props.itemValue);
  10922. const modelRawValue = getPropertyFromItem(v.raw, props.itemValue);
  10923. if (itemRawValue === undefined || modelRawValue === undefined) return false;
  10924. return props.returnObject ? props.valueComparator(itemRawValue, modelRawValue) : props.valueComparator(item.value, v.value);
  10925. }) || v;
  10926. });
  10927. });
  10928. const displayItems = vue.computed(() => {
  10929. if (props.hideSelected) {
  10930. return filteredItems.value.filter(filteredItem => !selections.value.some(s => s.value === filteredItem.value));
  10931. }
  10932. return filteredItems.value;
  10933. });
  10934. const selected = vue.computed(() => selections.value.map(selection => selection.props.value));
  10935. const selection = vue.computed(() => selections.value[selectionIndex.value]);
  10936. const highlightFirst = vue.computed(() => {
  10937. const selectFirst = props.autoSelectFirst === true || props.autoSelectFirst === 'exact' && search.value === displayItems.value[0]?.title;
  10938. return selectFirst && displayItems.value.length > 0 && !isPristine.value && !listHasFocus.value;
  10939. });
  10940. const menuDisabled = vue.computed(() => props.hideNoData && !items.value.length || props.readonly || form?.isReadonly.value);
  10941. const listRef = vue.ref();
  10942. const {
  10943. onListScroll,
  10944. onListKeydown
  10945. } = useScrolling(listRef, vTextFieldRef);
  10946. function onClear(e) {
  10947. if (props.openOnClear) {
  10948. menu.value = true;
  10949. }
  10950. search.value = '';
  10951. }
  10952. function onMousedownControl() {
  10953. if (menuDisabled.value) return;
  10954. menu.value = true;
  10955. }
  10956. function onMousedownMenuIcon(e) {
  10957. if (menuDisabled.value) return;
  10958. if (isFocused.value) {
  10959. e.preventDefault();
  10960. e.stopPropagation();
  10961. }
  10962. menu.value = !menu.value;
  10963. }
  10964. function onKeydown(e) {
  10965. if (props.readonly || form?.isReadonly.value) return;
  10966. const selectionStart = vTextFieldRef.value.selectionStart;
  10967. const length = selected.value.length;
  10968. if (selectionIndex.value > -1 || ['Enter', 'ArrowDown', 'ArrowUp'].includes(e.key)) {
  10969. e.preventDefault();
  10970. }
  10971. if (['Enter', 'ArrowDown'].includes(e.key)) {
  10972. menu.value = true;
  10973. }
  10974. if (['Escape'].includes(e.key)) {
  10975. menu.value = false;
  10976. }
  10977. if (highlightFirst.value && ['Enter', 'Tab'].includes(e.key)) {
  10978. select(filteredItems.value[0]);
  10979. }
  10980. if (e.key === 'ArrowDown' && highlightFirst.value) {
  10981. listRef.value?.focus('next');
  10982. }
  10983. if (!props.multiple) return;
  10984. if (['Backspace', 'Delete'].includes(e.key)) {
  10985. if (selectionIndex.value < 0) {
  10986. if (e.key === 'Backspace' && !search.value) {
  10987. selectionIndex.value = length - 1;
  10988. }
  10989. return;
  10990. }
  10991. const originalSelectionIndex = selectionIndex.value;
  10992. if (selection.value) select(selection.value);
  10993. selectionIndex.value = originalSelectionIndex >= length - 1 ? length - 2 : originalSelectionIndex;
  10994. }
  10995. if (e.key === 'ArrowLeft') {
  10996. if (selectionIndex.value < 0 && selectionStart > 0) return;
  10997. const prev = selectionIndex.value > -1 ? selectionIndex.value - 1 : length - 1;
  10998. if (selections.value[prev]) {
  10999. selectionIndex.value = prev;
  11000. } else {
  11001. selectionIndex.value = -1;
  11002. vTextFieldRef.value.setSelectionRange(search.value?.length, search.value?.length);
  11003. }
  11004. }
  11005. if (e.key === 'ArrowRight') {
  11006. if (selectionIndex.value < 0) return;
  11007. const next = selectionIndex.value + 1;
  11008. if (selections.value[next]) {
  11009. selectionIndex.value = next;
  11010. } else {
  11011. selectionIndex.value = -1;
  11012. vTextFieldRef.value.setSelectionRange(0, 0);
  11013. }
  11014. }
  11015. }
  11016. function onInput(e) {
  11017. search.value = e.target.value;
  11018. }
  11019. function onChange(e) {
  11020. if (matchesSelector(vTextFieldRef.value, ':autofill') || matchesSelector(vTextFieldRef.value, ':-webkit-autofill')) {
  11021. const item = items.value.find(item => item.title === e.target.value);
  11022. if (item) {
  11023. select(item);
  11024. }
  11025. }
  11026. }
  11027. function onAfterLeave() {
  11028. if (isFocused.value) {
  11029. isPristine.value = true;
  11030. vTextFieldRef.value?.focus();
  11031. }
  11032. }
  11033. function onFocusin(e) {
  11034. isFocused.value = true;
  11035. setTimeout(() => {
  11036. listHasFocus.value = true;
  11037. });
  11038. }
  11039. function onFocusout(e) {
  11040. listHasFocus.value = false;
  11041. }
  11042. function onUpdateModelValue(v) {
  11043. if (v == null || v === '' && !props.multiple) model.value = [];
  11044. }
  11045. const isSelecting = vue.shallowRef(false);
  11046. function select(item) {
  11047. if (props.multiple) {
  11048. const index = selected.value.findIndex(selection => props.valueComparator(selection, item.value));
  11049. if (index === -1) {
  11050. model.value = [...model.value, item];
  11051. } else {
  11052. const value = [...model.value];
  11053. value.splice(index, 1);
  11054. model.value = value;
  11055. }
  11056. } else {
  11057. model.value = [item];
  11058. isSelecting.value = true;
  11059. search.value = item.title;
  11060. menu.value = false;
  11061. isPristine.value = true;
  11062. vue.nextTick(() => isSelecting.value = false);
  11063. }
  11064. }
  11065. vue.watch(isFocused, (val, oldVal) => {
  11066. if (val === oldVal) return;
  11067. if (val) {
  11068. isSelecting.value = true;
  11069. search.value = props.multiple ? '' : String(selections.value.at(-1)?.props.title ?? '');
  11070. isPristine.value = true;
  11071. vue.nextTick(() => isSelecting.value = false);
  11072. } else {
  11073. if (!props.multiple && !search.value) model.value = [];else if (highlightFirst.value && !listHasFocus.value && !selections.value.some(_ref2 => {
  11074. let {
  11075. value
  11076. } = _ref2;
  11077. return value === displayItems.value[0].value;
  11078. })) {
  11079. select(displayItems.value[0]);
  11080. }
  11081. menu.value = false;
  11082. search.value = '';
  11083. selectionIndex.value = -1;
  11084. }
  11085. });
  11086. vue.watch(search, val => {
  11087. if (!isFocused.value || isSelecting.value) return;
  11088. if (val) menu.value = true;
  11089. isPristine.value = !val;
  11090. });
  11091. useRender(() => {
  11092. const hasChips = !!(props.chips || slots.chip);
  11093. const hasList = !!(!props.hideNoData || displayItems.value.length || slots['prepend-item'] || slots['append-item'] || slots['no-data']);
  11094. const isDirty = model.value.length > 0;
  11095. const [textFieldProps] = VTextField.filterProps(props);
  11096. return vue.createVNode(VTextField, vue.mergeProps({
  11097. "ref": vTextFieldRef
  11098. }, textFieldProps, {
  11099. "modelValue": search.value,
  11100. "onUpdate:modelValue": onUpdateModelValue,
  11101. "focused": isFocused.value,
  11102. "onUpdate:focused": $event => isFocused.value = $event,
  11103. "validationValue": model.externalValue,
  11104. "dirty": isDirty,
  11105. "onInput": onInput,
  11106. "onChange": onChange,
  11107. "class": ['v-autocomplete', `v-autocomplete--${props.multiple ? 'multiple' : 'single'}`, {
  11108. 'v-autocomplete--active-menu': menu.value,
  11109. 'v-autocomplete--chips': !!props.chips,
  11110. 'v-autocomplete--selection-slot': !!slots.selection,
  11111. 'v-autocomplete--selecting-index': selectionIndex.value > -1
  11112. }, props.class],
  11113. "style": props.style,
  11114. "readonly": props.readonly,
  11115. "placeholder": isDirty ? undefined : props.placeholder,
  11116. "onClick:clear": onClear,
  11117. "onMousedown:control": onMousedownControl,
  11118. "onKeydown": onKeydown
  11119. }), {
  11120. ...slots,
  11121. default: () => vue.createVNode(vue.Fragment, null, [vue.createVNode(VMenu, vue.mergeProps({
  11122. "ref": vMenuRef,
  11123. "modelValue": menu.value,
  11124. "onUpdate:modelValue": $event => menu.value = $event,
  11125. "activator": "parent",
  11126. "contentClass": "v-autocomplete__content",
  11127. "disabled": menuDisabled.value,
  11128. "eager": props.eager,
  11129. "maxHeight": 310,
  11130. "openOnClick": false,
  11131. "closeOnContentClick": false,
  11132. "transition": props.transition,
  11133. "onAfterLeave": onAfterLeave
  11134. }, props.menuProps), {
  11135. default: () => [hasList && vue.createVNode(VList, {
  11136. "ref": listRef,
  11137. "selected": selected.value,
  11138. "selectStrategy": props.multiple ? 'independent' : 'single-independent',
  11139. "onMousedown": e => e.preventDefault(),
  11140. "onKeydown": onListKeydown,
  11141. "onFocusin": onFocusin,
  11142. "onFocusout": onFocusout,
  11143. "onScrollPassive": onListScroll,
  11144. "tabindex": "-1",
  11145. "color": props.itemColor ?? props.color
  11146. }, {
  11147. default: () => [slots['prepend-item']?.(), !displayItems.value.length && !props.hideNoData && (slots['no-data']?.() ?? vue.createVNode(VListItem, {
  11148. "title": t(props.noDataText)
  11149. }, null)), vue.createVNode(VVirtualScroll, {
  11150. "renderless": true,
  11151. "items": displayItems.value
  11152. }, {
  11153. default: _ref3 => {
  11154. let {
  11155. item,
  11156. index,
  11157. itemRef
  11158. } = _ref3;
  11159. const itemProps = vue.mergeProps(item.props, {
  11160. ref: itemRef,
  11161. key: index,
  11162. active: highlightFirst.value && index === 0 ? true : undefined,
  11163. onClick: () => select(item)
  11164. });
  11165. return slots.item?.({
  11166. item,
  11167. index,
  11168. props: itemProps
  11169. }) ?? vue.createVNode(VListItem, itemProps, {
  11170. prepend: _ref4 => {
  11171. let {
  11172. isSelected
  11173. } = _ref4;
  11174. return vue.createVNode(vue.Fragment, null, [props.multiple && !props.hideSelected ? vue.createVNode(VCheckboxBtn, {
  11175. "key": item.value,
  11176. "modelValue": isSelected,
  11177. "ripple": false,
  11178. "tabindex": "-1"
  11179. }, null) : undefined, item.props.prependIcon && vue.createVNode(VIcon, {
  11180. "icon": item.props.prependIcon
  11181. }, null)]);
  11182. },
  11183. title: () => {
  11184. return isPristine.value ? item.title : highlightResult$1(item.title, getMatches(item)?.title, search.value?.length ?? 0);
  11185. }
  11186. });
  11187. }
  11188. }), slots['append-item']?.()]
  11189. })]
  11190. }), selections.value.map((item, index) => {
  11191. function onChipClose(e) {
  11192. e.stopPropagation();
  11193. e.preventDefault();
  11194. select(item);
  11195. }
  11196. const slotProps = {
  11197. 'onClick:close': onChipClose,
  11198. onMousedown(e) {
  11199. e.preventDefault();
  11200. e.stopPropagation();
  11201. },
  11202. modelValue: true,
  11203. 'onUpdate:modelValue': undefined
  11204. };
  11205. return vue.createVNode("div", {
  11206. "key": item.value,
  11207. "class": ['v-autocomplete__selection', index === selectionIndex.value && ['v-autocomplete__selection--selected', textColorClasses.value]],
  11208. "style": index === selectionIndex.value ? textColorStyles.value : {}
  11209. }, [hasChips ? !slots.chip ? vue.createVNode(VChip, vue.mergeProps({
  11210. "key": "chip",
  11211. "closable": props.closableChips,
  11212. "size": "small",
  11213. "text": item.title
  11214. }, slotProps), null) : vue.createVNode(VDefaultsProvider, {
  11215. "key": "chip-defaults",
  11216. "defaults": {
  11217. VChip: {
  11218. closable: props.closableChips,
  11219. size: 'small',
  11220. text: item.title
  11221. }
  11222. }
  11223. }, {
  11224. default: () => [slots.chip?.({
  11225. item,
  11226. index,
  11227. props: slotProps
  11228. })]
  11229. }) : slots.selection?.({
  11230. item,
  11231. index
  11232. }) ?? vue.createVNode("span", {
  11233. "class": "v-autocomplete__selection-text"
  11234. }, [item.title, props.multiple && index < selections.value.length - 1 && vue.createVNode("span", {
  11235. "class": "v-autocomplete__selection-comma"
  11236. }, [vue.createTextVNode(",")])])]);
  11237. })]),
  11238. 'append-inner': function () {
  11239. for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) {
  11240. args[_key] = arguments[_key];
  11241. }
  11242. return vue.createVNode(vue.Fragment, null, [slots['append-inner']?.(...args), props.menuIcon ? vue.createVNode(VIcon, {
  11243. "class": "v-autocomplete__menu-icon",
  11244. "icon": props.menuIcon,
  11245. "onMousedown": onMousedownMenuIcon,
  11246. "onClick": noop
  11247. }, null) : undefined]);
  11248. }
  11249. });
  11250. });
  11251. return forwardRefs({
  11252. isFocused,
  11253. isPristine,
  11254. menu,
  11255. search,
  11256. filteredItems,
  11257. select
  11258. }, vTextFieldRef);
  11259. }
  11260. });
  11261. const makeVBadgeProps = propsFactory({
  11262. bordered: Boolean,
  11263. color: String,
  11264. content: [Number, String],
  11265. dot: Boolean,
  11266. floating: Boolean,
  11267. icon: IconValue,
  11268. inline: Boolean,
  11269. label: {
  11270. type: String,
  11271. default: '$vuetify.badge'
  11272. },
  11273. max: [Number, String],
  11274. modelValue: {
  11275. type: Boolean,
  11276. default: true
  11277. },
  11278. offsetX: [Number, String],
  11279. offsetY: [Number, String],
  11280. textColor: String,
  11281. ...makeComponentProps(),
  11282. ...makeLocationProps({
  11283. location: 'top end'
  11284. }),
  11285. ...makeRoundedProps(),
  11286. ...makeTagProps(),
  11287. ...makeThemeProps(),
  11288. ...makeTransitionProps({
  11289. transition: 'scale-rotate-transition'
  11290. })
  11291. }, 'VBadge');
  11292. const VBadge = genericComponent()({
  11293. name: 'VBadge',
  11294. inheritAttrs: false,
  11295. props: makeVBadgeProps(),
  11296. setup(props, ctx) {
  11297. const {
  11298. backgroundColorClasses,
  11299. backgroundColorStyles
  11300. } = useBackgroundColor(vue.toRef(props, 'color'));
  11301. const {
  11302. roundedClasses
  11303. } = useRounded(props);
  11304. const {
  11305. t
  11306. } = useLocale();
  11307. const {
  11308. textColorClasses,
  11309. textColorStyles
  11310. } = useTextColor(vue.toRef(props, 'textColor'));
  11311. const {
  11312. themeClasses
  11313. } = useTheme();
  11314. const {
  11315. locationStyles
  11316. } = useLocation(props, true, side => {
  11317. const base = props.floating ? props.dot ? 2 : 4 : props.dot ? 8 : 12;
  11318. return base + (['top', 'bottom'].includes(side) ? +(props.offsetY ?? 0) : ['left', 'right'].includes(side) ? +(props.offsetX ?? 0) : 0);
  11319. });
  11320. useRender(() => {
  11321. const value = Number(props.content);
  11322. const content = !props.max || isNaN(value) ? props.content : value <= +props.max ? value : `${props.max}+`;
  11323. const [badgeAttrs, attrs] = pick(ctx.attrs, ['aria-atomic', 'aria-label', 'aria-live', 'role', 'title']);
  11324. return vue.createVNode(props.tag, vue.mergeProps({
  11325. "class": ['v-badge', {
  11326. 'v-badge--bordered': props.bordered,
  11327. 'v-badge--dot': props.dot,
  11328. 'v-badge--floating': props.floating,
  11329. 'v-badge--inline': props.inline
  11330. }, props.class]
  11331. }, attrs, {
  11332. "style": props.style
  11333. }), {
  11334. default: () => [vue.createVNode("div", {
  11335. "class": "v-badge__wrapper"
  11336. }, [ctx.slots.default?.(), vue.createVNode(MaybeTransition, {
  11337. "transition": props.transition
  11338. }, {
  11339. default: () => [vue.withDirectives(vue.createVNode("span", vue.mergeProps({
  11340. "class": ['v-badge__badge', themeClasses.value, backgroundColorClasses.value, roundedClasses.value, textColorClasses.value],
  11341. "style": [backgroundColorStyles.value, textColorStyles.value, props.inline ? {} : locationStyles.value],
  11342. "aria-atomic": "true",
  11343. "aria-label": t(props.label, value),
  11344. "aria-live": "polite",
  11345. "role": "status"
  11346. }, badgeAttrs), [props.dot ? undefined : ctx.slots.badge ? ctx.slots.badge?.() : props.icon ? vue.createVNode(VIcon, {
  11347. "icon": props.icon
  11348. }, null) : content]), [[vue.vShow, props.modelValue]])]
  11349. })])]
  11350. });
  11351. });
  11352. return {};
  11353. }
  11354. });
  11355. const makeVBannerActionsProps = propsFactory({
  11356. color: String,
  11357. density: String,
  11358. ...makeComponentProps()
  11359. }, 'VBannerActions');
  11360. const VBannerActions = genericComponent()({
  11361. name: 'VBannerActions',
  11362. props: makeVBannerActionsProps(),
  11363. setup(props, _ref) {
  11364. let {
  11365. slots
  11366. } = _ref;
  11367. provideDefaults({
  11368. VBtn: {
  11369. color: props.color,
  11370. density: props.density,
  11371. variant: 'text'
  11372. }
  11373. });
  11374. useRender(() => vue.createVNode("div", {
  11375. "class": ['v-banner-actions', props.class],
  11376. "style": props.style
  11377. }, [slots.default?.()]));
  11378. return {};
  11379. }
  11380. });
  11381. // Utilities
  11382. const VBannerText = createSimpleFunctional('v-banner-text');
  11383. // Types
  11384. const makeVBannerProps = propsFactory({
  11385. avatar: String,
  11386. color: String,
  11387. icon: IconValue,
  11388. lines: String,
  11389. stacked: Boolean,
  11390. sticky: Boolean,
  11391. text: String,
  11392. ...makeBorderProps(),
  11393. ...makeComponentProps(),
  11394. ...makeDensityProps(),
  11395. ...makeDimensionProps(),
  11396. ...makeElevationProps(),
  11397. ...makeLocationProps(),
  11398. ...makePositionProps(),
  11399. ...makeRoundedProps(),
  11400. ...makeTagProps(),
  11401. ...makeThemeProps()
  11402. }, 'VBanner');
  11403. const VBanner = genericComponent()({
  11404. name: 'VBanner',
  11405. props: makeVBannerProps(),
  11406. setup(props, _ref) {
  11407. let {
  11408. slots
  11409. } = _ref;
  11410. const {
  11411. borderClasses
  11412. } = useBorder(props);
  11413. const {
  11414. densityClasses
  11415. } = useDensity(props);
  11416. const {
  11417. mobile
  11418. } = useDisplay();
  11419. const {
  11420. dimensionStyles
  11421. } = useDimension(props);
  11422. const {
  11423. elevationClasses
  11424. } = useElevation(props);
  11425. const {
  11426. locationStyles
  11427. } = useLocation(props);
  11428. const {
  11429. positionClasses
  11430. } = usePosition(props);
  11431. const {
  11432. roundedClasses
  11433. } = useRounded(props);
  11434. const {
  11435. themeClasses
  11436. } = provideTheme(props);
  11437. const color = vue.toRef(props, 'color');
  11438. const density = vue.toRef(props, 'density');
  11439. provideDefaults({
  11440. VBannerActions: {
  11441. color,
  11442. density
  11443. }
  11444. });
  11445. useRender(() => {
  11446. const hasText = !!(props.text || slots.text);
  11447. const hasPrependMedia = !!(props.avatar || props.icon);
  11448. const hasPrepend = !!(hasPrependMedia || slots.prepend);
  11449. return vue.createVNode(props.tag, {
  11450. "class": ['v-banner', {
  11451. 'v-banner--stacked': props.stacked || mobile.value,
  11452. 'v-banner--sticky': props.sticky,
  11453. [`v-banner--${props.lines}-line`]: !!props.lines
  11454. }, borderClasses.value, densityClasses.value, elevationClasses.value, positionClasses.value, roundedClasses.value, themeClasses.value, props.class],
  11455. "style": [dimensionStyles.value, locationStyles.value, props.style],
  11456. "role": "banner"
  11457. }, {
  11458. default: () => [hasPrepend && vue.createVNode("div", {
  11459. "key": "prepend",
  11460. "class": "v-banner__prepend"
  11461. }, [!slots.prepend ? vue.createVNode(VAvatar, {
  11462. "key": "prepend-avatar",
  11463. "color": color.value,
  11464. "density": density.value,
  11465. "icon": props.icon,
  11466. "image": props.avatar
  11467. }, null) : vue.createVNode(VDefaultsProvider, {
  11468. "key": "prepend-defaults",
  11469. "disabled": !hasPrependMedia,
  11470. "defaults": {
  11471. VAvatar: {
  11472. color: color.value,
  11473. density: density.value,
  11474. icon: props.icon,
  11475. image: props.avatar
  11476. }
  11477. }
  11478. }, slots.prepend)]), vue.createVNode("div", {
  11479. "class": "v-banner__content"
  11480. }, [hasText && vue.createVNode(VBannerText, {
  11481. "key": "text"
  11482. }, {
  11483. default: () => [slots.text?.() ?? props.text]
  11484. }), slots.default?.()]), slots.actions && vue.createVNode(VBannerActions, {
  11485. "key": "actions"
  11486. }, slots.actions)]
  11487. });
  11488. });
  11489. }
  11490. });
  11491. const makeVBottomNavigationProps = propsFactory({
  11492. bgColor: String,
  11493. color: String,
  11494. grow: Boolean,
  11495. mode: {
  11496. type: String,
  11497. validator: v => !v || ['horizontal', 'shift'].includes(v)
  11498. },
  11499. height: {
  11500. type: [Number, String],
  11501. default: 56
  11502. },
  11503. active: {
  11504. type: Boolean,
  11505. default: true
  11506. },
  11507. ...makeBorderProps(),
  11508. ...makeComponentProps(),
  11509. ...makeDensityProps(),
  11510. ...makeElevationProps(),
  11511. ...makeRoundedProps(),
  11512. ...makeLayoutItemProps({
  11513. name: 'bottom-navigation'
  11514. }),
  11515. ...makeTagProps({
  11516. tag: 'header'
  11517. }),
  11518. ...makeGroupProps({
  11519. modelValue: true,
  11520. selectedClass: 'v-btn--selected'
  11521. }),
  11522. ...makeThemeProps()
  11523. }, 'VBottomNavigation');
  11524. const VBottomNavigation = genericComponent()({
  11525. name: 'VBottomNavigation',
  11526. props: makeVBottomNavigationProps(),
  11527. emits: {
  11528. 'update:modelValue': value => true
  11529. },
  11530. setup(props, _ref) {
  11531. let {
  11532. slots
  11533. } = _ref;
  11534. const {
  11535. themeClasses
  11536. } = useTheme();
  11537. const {
  11538. borderClasses
  11539. } = useBorder(props);
  11540. const {
  11541. backgroundColorClasses,
  11542. backgroundColorStyles
  11543. } = useBackgroundColor(vue.toRef(props, 'bgColor'));
  11544. const {
  11545. densityClasses
  11546. } = useDensity(props);
  11547. const {
  11548. elevationClasses
  11549. } = useElevation(props);
  11550. const {
  11551. roundedClasses
  11552. } = useRounded(props);
  11553. const {
  11554. ssrBootStyles
  11555. } = useSsrBoot();
  11556. const height = vue.computed(() => Number(props.height) - (props.density === 'comfortable' ? 8 : 0) - (props.density === 'compact' ? 16 : 0));
  11557. const isActive = vue.toRef(props, 'active');
  11558. const {
  11559. layoutItemStyles
  11560. } = useLayoutItem({
  11561. id: props.name,
  11562. order: vue.computed(() => parseInt(props.order, 10)),
  11563. position: vue.computed(() => 'bottom'),
  11564. layoutSize: vue.computed(() => isActive.value ? height.value : 0),
  11565. elementSize: height,
  11566. active: isActive,
  11567. absolute: vue.toRef(props, 'absolute')
  11568. });
  11569. useGroup(props, VBtnToggleSymbol);
  11570. provideDefaults({
  11571. VBtn: {
  11572. color: vue.toRef(props, 'color'),
  11573. density: vue.toRef(props, 'density'),
  11574. stacked: vue.computed(() => props.mode !== 'horizontal'),
  11575. variant: 'text'
  11576. }
  11577. }, {
  11578. scoped: true
  11579. });
  11580. useRender(() => {
  11581. return vue.createVNode(props.tag, {
  11582. "class": ['v-bottom-navigation', {
  11583. 'v-bottom-navigation--active': isActive.value,
  11584. 'v-bottom-navigation--grow': props.grow,
  11585. 'v-bottom-navigation--shift': props.mode === 'shift'
  11586. }, themeClasses.value, backgroundColorClasses.value, borderClasses.value, densityClasses.value, elevationClasses.value, roundedClasses.value, props.class],
  11587. "style": [backgroundColorStyles.value, layoutItemStyles.value, {
  11588. height: convertToUnit(height.value),
  11589. transform: `translateY(${convertToUnit(!isActive.value ? 100 : 0, '%')})`
  11590. }, ssrBootStyles.value, props.style]
  11591. }, {
  11592. default: () => [slots.default && vue.createVNode("div", {
  11593. "class": "v-bottom-navigation__content"
  11594. }, [slots.default()])]
  11595. });
  11596. });
  11597. return {};
  11598. }
  11599. });
  11600. const makeVBreadcrumbsDividerProps = propsFactory({
  11601. divider: [Number, String],
  11602. ...makeComponentProps()
  11603. }, 'VBreadcrumbsDivider');
  11604. const VBreadcrumbsDivider = genericComponent()({
  11605. name: 'VBreadcrumbsDivider',
  11606. props: makeVBreadcrumbsDividerProps(),
  11607. setup(props, _ref) {
  11608. let {
  11609. slots
  11610. } = _ref;
  11611. useRender(() => vue.createVNode("li", {
  11612. "class": ['v-breadcrumbs-divider', props.class],
  11613. "style": props.style
  11614. }, [slots?.default?.() ?? props.divider]));
  11615. return {};
  11616. }
  11617. });
  11618. const makeVBreadcrumbsItemProps = propsFactory({
  11619. active: Boolean,
  11620. activeClass: String,
  11621. activeColor: String,
  11622. color: String,
  11623. disabled: Boolean,
  11624. title: String,
  11625. ...makeComponentProps(),
  11626. ...makeRouterProps(),
  11627. ...makeTagProps({
  11628. tag: 'li'
  11629. })
  11630. }, 'VBreadcrumbsItem');
  11631. const VBreadcrumbsItem = genericComponent()({
  11632. name: 'VBreadcrumbsItem',
  11633. props: makeVBreadcrumbsItemProps(),
  11634. setup(props, _ref) {
  11635. let {
  11636. slots,
  11637. attrs
  11638. } = _ref;
  11639. const link = useLink(props, attrs);
  11640. const isActive = vue.computed(() => props.active || link.isActive?.value);
  11641. const color = vue.computed(() => isActive.value ? props.activeColor : props.color);
  11642. const {
  11643. textColorClasses,
  11644. textColorStyles
  11645. } = useTextColor(color);
  11646. useRender(() => {
  11647. return vue.createVNode(props.tag, {
  11648. "class": ['v-breadcrumbs-item', {
  11649. 'v-breadcrumbs-item--active': isActive.value,
  11650. 'v-breadcrumbs-item--disabled': props.disabled,
  11651. [`${props.activeClass}`]: isActive.value && props.activeClass
  11652. }, textColorClasses.value, props.class],
  11653. "style": [textColorStyles.value, props.style],
  11654. "aria-current": isActive.value ? 'page' : undefined
  11655. }, {
  11656. default: () => [!link.isLink.value ? slots.default?.() ?? props.title : vue.createVNode("a", {
  11657. "class": "v-breadcrumbs-item--link",
  11658. "href": link.href.value,
  11659. "aria-current": isActive.value ? 'page' : undefined,
  11660. "onClick": link.navigate
  11661. }, [slots.default?.() ?? props.title])]
  11662. });
  11663. });
  11664. return {};
  11665. }
  11666. });
  11667. // Types
  11668. const makeVBreadcrumbsProps = propsFactory({
  11669. activeClass: String,
  11670. activeColor: String,
  11671. bgColor: String,
  11672. color: String,
  11673. disabled: Boolean,
  11674. divider: {
  11675. type: String,
  11676. default: '/'
  11677. },
  11678. icon: IconValue,
  11679. items: {
  11680. type: Array,
  11681. default: () => []
  11682. },
  11683. ...makeComponentProps(),
  11684. ...makeDensityProps(),
  11685. ...makeRoundedProps(),
  11686. ...makeTagProps({
  11687. tag: 'ul'
  11688. })
  11689. }, 'VBreadcrumbs');
  11690. const VBreadcrumbs = genericComponent()({
  11691. name: 'VBreadcrumbs',
  11692. props: makeVBreadcrumbsProps(),
  11693. setup(props, _ref) {
  11694. let {
  11695. slots
  11696. } = _ref;
  11697. const {
  11698. backgroundColorClasses,
  11699. backgroundColorStyles
  11700. } = useBackgroundColor(vue.toRef(props, 'bgColor'));
  11701. const {
  11702. densityClasses
  11703. } = useDensity(props);
  11704. const {
  11705. roundedClasses
  11706. } = useRounded(props);
  11707. provideDefaults({
  11708. VBreadcrumbsDivider: {
  11709. divider: vue.toRef(props, 'divider')
  11710. },
  11711. VBreadcrumbsItem: {
  11712. activeClass: vue.toRef(props, 'activeClass'),
  11713. activeColor: vue.toRef(props, 'activeColor'),
  11714. color: vue.toRef(props, 'color'),
  11715. disabled: vue.toRef(props, 'disabled')
  11716. }
  11717. });
  11718. const items = vue.computed(() => props.items.map(item => {
  11719. return typeof item === 'string' ? {
  11720. item: {
  11721. title: item
  11722. },
  11723. raw: item
  11724. } : {
  11725. item,
  11726. raw: item
  11727. };
  11728. }));
  11729. useRender(() => {
  11730. const hasPrepend = !!(slots.prepend || props.icon);
  11731. return vue.createVNode(props.tag, {
  11732. "class": ['v-breadcrumbs', backgroundColorClasses.value, densityClasses.value, roundedClasses.value, props.class],
  11733. "style": [backgroundColorStyles.value, props.style]
  11734. }, {
  11735. default: () => [hasPrepend && vue.createVNode("li", {
  11736. "key": "prepend",
  11737. "class": "v-breadcrumbs__prepend"
  11738. }, [!slots.prepend ? vue.createVNode(VIcon, {
  11739. "key": "prepend-icon",
  11740. "start": true,
  11741. "icon": props.icon
  11742. }, null) : vue.createVNode(VDefaultsProvider, {
  11743. "key": "prepend-defaults",
  11744. "disabled": !props.icon,
  11745. "defaults": {
  11746. VIcon: {
  11747. icon: props.icon,
  11748. start: true
  11749. }
  11750. }
  11751. }, slots.prepend)]), items.value.map((_ref2, index, array) => {
  11752. let {
  11753. item,
  11754. raw
  11755. } = _ref2;
  11756. return vue.createVNode(vue.Fragment, null, [vue.createVNode(VBreadcrumbsItem, vue.mergeProps({
  11757. "key": item.title,
  11758. "disabled": index >= array.length - 1
  11759. }, item), {
  11760. default: slots.title ? () => slots.title?.({
  11761. item: raw,
  11762. index
  11763. }) : undefined
  11764. }), index < array.length - 1 && vue.createVNode(VBreadcrumbsDivider, null, {
  11765. default: slots.divider ? () => slots.divider?.({
  11766. item: raw,
  11767. index
  11768. }) : undefined
  11769. })]);
  11770. }), slots.default?.()]
  11771. });
  11772. });
  11773. return {};
  11774. }
  11775. });
  11776. const VCardActions = genericComponent()({
  11777. name: 'VCardActions',
  11778. props: makeComponentProps(),
  11779. setup(props, _ref) {
  11780. let {
  11781. slots
  11782. } = _ref;
  11783. provideDefaults({
  11784. VBtn: {
  11785. variant: 'text'
  11786. }
  11787. });
  11788. useRender(() => vue.createVNode("div", {
  11789. "class": ['v-card-actions', props.class],
  11790. "style": props.style
  11791. }, [slots.default?.()]));
  11792. return {};
  11793. }
  11794. });
  11795. // Utilities
  11796. const VCardSubtitle = createSimpleFunctional('v-card-subtitle');
  11797. // Utilities
  11798. const VCardTitle = createSimpleFunctional('v-card-title');
  11799. const makeCardItemProps = propsFactory({
  11800. appendAvatar: String,
  11801. appendIcon: IconValue,
  11802. prependAvatar: String,
  11803. prependIcon: IconValue,
  11804. subtitle: String,
  11805. title: String,
  11806. ...makeComponentProps(),
  11807. ...makeDensityProps()
  11808. }, 'VCardItem');
  11809. const VCardItem = genericComponent()({
  11810. name: 'VCardItem',
  11811. props: makeCardItemProps(),
  11812. setup(props, _ref) {
  11813. let {
  11814. slots
  11815. } = _ref;
  11816. useRender(() => {
  11817. const hasPrependMedia = !!(props.prependAvatar || props.prependIcon);
  11818. const hasPrepend = !!(hasPrependMedia || slots.prepend);
  11819. const hasAppendMedia = !!(props.appendAvatar || props.appendIcon);
  11820. const hasAppend = !!(hasAppendMedia || slots.append);
  11821. const hasTitle = !!(props.title || slots.title);
  11822. const hasSubtitle = !!(props.subtitle || slots.subtitle);
  11823. return vue.createVNode("div", {
  11824. "class": ['v-card-item', props.class],
  11825. "style": props.style
  11826. }, [hasPrepend && vue.createVNode("div", {
  11827. "key": "prepend",
  11828. "class": "v-card-item__prepend"
  11829. }, [!slots.prepend ? hasPrependMedia && vue.createVNode(VAvatar, {
  11830. "key": "prepend-avatar",
  11831. "density": props.density,
  11832. "icon": props.prependIcon,
  11833. "image": props.prependAvatar
  11834. }, null) : vue.createVNode(VDefaultsProvider, {
  11835. "key": "prepend-defaults",
  11836. "disabled": !hasPrependMedia,
  11837. "defaults": {
  11838. VAvatar: {
  11839. density: props.density,
  11840. icon: props.prependIcon,
  11841. image: props.prependAvatar
  11842. }
  11843. }
  11844. }, slots.prepend)]), vue.createVNode("div", {
  11845. "class": "v-card-item__content"
  11846. }, [hasTitle && vue.createVNode(VCardTitle, {
  11847. "key": "title"
  11848. }, {
  11849. default: () => [slots.title?.() ?? props.title]
  11850. }), hasSubtitle && vue.createVNode(VCardSubtitle, {
  11851. "key": "subtitle"
  11852. }, {
  11853. default: () => [slots.subtitle?.() ?? props.subtitle]
  11854. }), slots.default?.()]), hasAppend && vue.createVNode("div", {
  11855. "key": "append",
  11856. "class": "v-card-item__append"
  11857. }, [!slots.append ? hasAppendMedia && vue.createVNode(VAvatar, {
  11858. "key": "append-avatar",
  11859. "density": props.density,
  11860. "icon": props.appendIcon,
  11861. "image": props.appendAvatar
  11862. }, null) : vue.createVNode(VDefaultsProvider, {
  11863. "key": "append-defaults",
  11864. "disabled": !hasAppendMedia,
  11865. "defaults": {
  11866. VAvatar: {
  11867. density: props.density,
  11868. icon: props.appendIcon,
  11869. image: props.appendAvatar
  11870. }
  11871. }
  11872. }, slots.append)])]);
  11873. });
  11874. return {};
  11875. }
  11876. });
  11877. // Utilities
  11878. const VCardText = createSimpleFunctional('v-card-text');
  11879. // Types
  11880. const makeVCardProps = propsFactory({
  11881. appendAvatar: String,
  11882. appendIcon: IconValue,
  11883. disabled: Boolean,
  11884. flat: Boolean,
  11885. hover: Boolean,
  11886. image: String,
  11887. link: {
  11888. type: Boolean,
  11889. default: undefined
  11890. },
  11891. prependAvatar: String,
  11892. prependIcon: IconValue,
  11893. ripple: {
  11894. type: [Boolean, Object],
  11895. default: true
  11896. },
  11897. subtitle: String,
  11898. text: String,
  11899. title: String,
  11900. ...makeBorderProps(),
  11901. ...makeComponentProps(),
  11902. ...makeDensityProps(),
  11903. ...makeDimensionProps(),
  11904. ...makeElevationProps(),
  11905. ...makeLoaderProps(),
  11906. ...makeLocationProps(),
  11907. ...makePositionProps(),
  11908. ...makeRoundedProps(),
  11909. ...makeRouterProps(),
  11910. ...makeTagProps(),
  11911. ...makeThemeProps(),
  11912. ...makeVariantProps({
  11913. variant: 'elevated'
  11914. })
  11915. }, 'VCard');
  11916. const VCard = genericComponent()({
  11917. name: 'VCard',
  11918. directives: {
  11919. Ripple
  11920. },
  11921. props: makeVCardProps(),
  11922. setup(props, _ref) {
  11923. let {
  11924. attrs,
  11925. slots
  11926. } = _ref;
  11927. const {
  11928. themeClasses
  11929. } = provideTheme(props);
  11930. const {
  11931. borderClasses
  11932. } = useBorder(props);
  11933. const {
  11934. colorClasses,
  11935. colorStyles,
  11936. variantClasses
  11937. } = useVariant(props);
  11938. const {
  11939. densityClasses
  11940. } = useDensity(props);
  11941. const {
  11942. dimensionStyles
  11943. } = useDimension(props);
  11944. const {
  11945. elevationClasses
  11946. } = useElevation(props);
  11947. const {
  11948. loaderClasses
  11949. } = useLoader(props);
  11950. const {
  11951. locationStyles
  11952. } = useLocation(props);
  11953. const {
  11954. positionClasses
  11955. } = usePosition(props);
  11956. const {
  11957. roundedClasses
  11958. } = useRounded(props);
  11959. const link = useLink(props, attrs);
  11960. const isLink = vue.computed(() => props.link !== false && link.isLink.value);
  11961. const isClickable = vue.computed(() => !props.disabled && props.link !== false && (props.link || link.isClickable.value));
  11962. useRender(() => {
  11963. const Tag = isLink.value ? 'a' : props.tag;
  11964. const hasTitle = !!(slots.title || props.title);
  11965. const hasSubtitle = !!(slots.subtitle || props.subtitle);
  11966. const hasHeader = hasTitle || hasSubtitle;
  11967. const hasAppend = !!(slots.append || props.appendAvatar || props.appendIcon);
  11968. const hasPrepend = !!(slots.prepend || props.prependAvatar || props.prependIcon);
  11969. const hasImage = !!(slots.image || props.image);
  11970. const hasCardItem = hasHeader || hasPrepend || hasAppend;
  11971. const hasText = !!(slots.text || props.text);
  11972. return vue.withDirectives(vue.createVNode(Tag, {
  11973. "class": ['v-card', {
  11974. 'v-card--disabled': props.disabled,
  11975. 'v-card--flat': props.flat,
  11976. 'v-card--hover': props.hover && !(props.disabled || props.flat),
  11977. 'v-card--link': isClickable.value
  11978. }, themeClasses.value, borderClasses.value, colorClasses.value, densityClasses.value, elevationClasses.value, loaderClasses.value, positionClasses.value, roundedClasses.value, variantClasses.value, props.class],
  11979. "style": [colorStyles.value, dimensionStyles.value, locationStyles.value, props.style],
  11980. "href": link.href.value,
  11981. "onClick": isClickable.value && link.navigate,
  11982. "tabindex": props.disabled ? -1 : undefined
  11983. }, {
  11984. default: () => [hasImage && vue.createVNode("div", {
  11985. "key": "image",
  11986. "class": "v-card__image"
  11987. }, [!slots.image ? vue.createVNode(VImg, {
  11988. "key": "image-img",
  11989. "cover": true,
  11990. "src": props.image
  11991. }, null) : vue.createVNode(VDefaultsProvider, {
  11992. "key": "image-defaults",
  11993. "disabled": !props.image,
  11994. "defaults": {
  11995. VImg: {
  11996. cover: true,
  11997. src: props.image
  11998. }
  11999. }
  12000. }, slots.image)]), vue.createVNode(LoaderSlot, {
  12001. "name": "v-card",
  12002. "active": !!props.loading,
  12003. "color": typeof props.loading === 'boolean' ? undefined : props.loading
  12004. }, {
  12005. default: slots.loader
  12006. }), hasCardItem && vue.createVNode(VCardItem, {
  12007. "key": "item",
  12008. "prependAvatar": props.prependAvatar,
  12009. "prependIcon": props.prependIcon,
  12010. "title": props.title,
  12011. "subtitle": props.subtitle,
  12012. "appendAvatar": props.appendAvatar,
  12013. "appendIcon": props.appendIcon
  12014. }, {
  12015. default: slots.item,
  12016. prepend: slots.prepend,
  12017. title: slots.title,
  12018. subtitle: slots.subtitle,
  12019. append: slots.append
  12020. }), hasText && vue.createVNode(VCardText, {
  12021. "key": "text"
  12022. }, {
  12023. default: () => [slots.text?.() ?? props.text]
  12024. }), slots.default?.(), slots.actions && vue.createVNode(VCardActions, null, {
  12025. default: slots.actions
  12026. }), genOverlays(isClickable.value, 'v-card')]
  12027. }), [[vue.resolveDirective("ripple"), isClickable.value && props.ripple]]);
  12028. });
  12029. return {};
  12030. }
  12031. });
  12032. // Utilities
  12033. // Types
  12034. const handleGesture = wrapper => {
  12035. const {
  12036. touchstartX,
  12037. touchendX,
  12038. touchstartY,
  12039. touchendY
  12040. } = wrapper;
  12041. const dirRatio = 0.5;
  12042. const minDistance = 16;
  12043. wrapper.offsetX = touchendX - touchstartX;
  12044. wrapper.offsetY = touchendY - touchstartY;
  12045. if (Math.abs(wrapper.offsetY) < dirRatio * Math.abs(wrapper.offsetX)) {
  12046. wrapper.left && touchendX < touchstartX - minDistance && wrapper.left(wrapper);
  12047. wrapper.right && touchendX > touchstartX + minDistance && wrapper.right(wrapper);
  12048. }
  12049. if (Math.abs(wrapper.offsetX) < dirRatio * Math.abs(wrapper.offsetY)) {
  12050. wrapper.up && touchendY < touchstartY - minDistance && wrapper.up(wrapper);
  12051. wrapper.down && touchendY > touchstartY + minDistance && wrapper.down(wrapper);
  12052. }
  12053. };
  12054. function touchstart(event, wrapper) {
  12055. const touch = event.changedTouches[0];
  12056. wrapper.touchstartX = touch.clientX;
  12057. wrapper.touchstartY = touch.clientY;
  12058. wrapper.start?.({
  12059. originalEvent: event,
  12060. ...wrapper
  12061. });
  12062. }
  12063. function touchend(event, wrapper) {
  12064. const touch = event.changedTouches[0];
  12065. wrapper.touchendX = touch.clientX;
  12066. wrapper.touchendY = touch.clientY;
  12067. wrapper.end?.({
  12068. originalEvent: event,
  12069. ...wrapper
  12070. });
  12071. handleGesture(wrapper);
  12072. }
  12073. function touchmove(event, wrapper) {
  12074. const touch = event.changedTouches[0];
  12075. wrapper.touchmoveX = touch.clientX;
  12076. wrapper.touchmoveY = touch.clientY;
  12077. wrapper.move?.({
  12078. originalEvent: event,
  12079. ...wrapper
  12080. });
  12081. }
  12082. function createHandlers() {
  12083. let value = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
  12084. const wrapper = {
  12085. touchstartX: 0,
  12086. touchstartY: 0,
  12087. touchendX: 0,
  12088. touchendY: 0,
  12089. touchmoveX: 0,
  12090. touchmoveY: 0,
  12091. offsetX: 0,
  12092. offsetY: 0,
  12093. left: value.left,
  12094. right: value.right,
  12095. up: value.up,
  12096. down: value.down,
  12097. start: value.start,
  12098. move: value.move,
  12099. end: value.end
  12100. };
  12101. return {
  12102. touchstart: e => touchstart(e, wrapper),
  12103. touchend: e => touchend(e, wrapper),
  12104. touchmove: e => touchmove(e, wrapper)
  12105. };
  12106. }
  12107. function mounted$3(el, binding) {
  12108. const value = binding.value;
  12109. const target = value?.parent ? el.parentElement : el;
  12110. const options = value?.options ?? {
  12111. passive: true
  12112. };
  12113. const uid = binding.instance?.$.uid; // TODO: use custom uid generator
  12114. if (!target || !uid) return;
  12115. const handlers = createHandlers(binding.value);
  12116. target._touchHandlers = target._touchHandlers ?? Object.create(null);
  12117. target._touchHandlers[uid] = handlers;
  12118. keys(handlers).forEach(eventName => {
  12119. target.addEventListener(eventName, handlers[eventName], options);
  12120. });
  12121. }
  12122. function unmounted$3(el, binding) {
  12123. const target = binding.value?.parent ? el.parentElement : el;
  12124. const uid = binding.instance?.$.uid;
  12125. if (!target?._touchHandlers || !uid) return;
  12126. const handlers = target._touchHandlers[uid];
  12127. keys(handlers).forEach(eventName => {
  12128. target.removeEventListener(eventName, handlers[eventName]);
  12129. });
  12130. delete target._touchHandlers[uid];
  12131. }
  12132. const Touch = {
  12133. mounted: mounted$3,
  12134. unmounted: unmounted$3
  12135. };
  12136. // Types
  12137. const VWindowSymbol = Symbol.for('vuetify:v-window');
  12138. const VWindowGroupSymbol = Symbol.for('vuetify:v-window-group');
  12139. const makeVWindowProps = propsFactory({
  12140. continuous: Boolean,
  12141. nextIcon: {
  12142. type: [Boolean, String, Function, Object],
  12143. default: '$next'
  12144. },
  12145. prevIcon: {
  12146. type: [Boolean, String, Function, Object],
  12147. default: '$prev'
  12148. },
  12149. reverse: Boolean,
  12150. showArrows: {
  12151. type: [Boolean, String],
  12152. validator: v => typeof v === 'boolean' || v === 'hover'
  12153. },
  12154. touch: {
  12155. type: [Object, Boolean],
  12156. default: undefined
  12157. },
  12158. direction: {
  12159. type: String,
  12160. default: 'horizontal'
  12161. },
  12162. modelValue: null,
  12163. disabled: Boolean,
  12164. selectedClass: {
  12165. type: String,
  12166. default: 'v-window-item--active'
  12167. },
  12168. // TODO: mandatory should probably not be exposed but do this for now
  12169. mandatory: {
  12170. type: [Boolean, String],
  12171. default: 'force'
  12172. },
  12173. ...makeComponentProps(),
  12174. ...makeTagProps(),
  12175. ...makeThemeProps()
  12176. }, 'VWindow');
  12177. const VWindow = genericComponent()({
  12178. name: 'VWindow',
  12179. directives: {
  12180. Touch
  12181. },
  12182. props: makeVWindowProps(),
  12183. emits: {
  12184. 'update:modelValue': v => true
  12185. },
  12186. setup(props, _ref) {
  12187. let {
  12188. slots
  12189. } = _ref;
  12190. const {
  12191. themeClasses
  12192. } = provideTheme(props);
  12193. const {
  12194. isRtl
  12195. } = useRtl();
  12196. const {
  12197. t
  12198. } = useLocale();
  12199. const group = useGroup(props, VWindowGroupSymbol);
  12200. const rootRef = vue.ref();
  12201. const isRtlReverse = vue.computed(() => isRtl.value ? !props.reverse : props.reverse);
  12202. const isReversed = vue.shallowRef(false);
  12203. const transition = vue.computed(() => {
  12204. const axis = props.direction === 'vertical' ? 'y' : 'x';
  12205. const reverse = isRtlReverse.value ? !isReversed.value : isReversed.value;
  12206. const direction = reverse ? '-reverse' : '';
  12207. return `v-window-${axis}${direction}-transition`;
  12208. });
  12209. const transitionCount = vue.shallowRef(0);
  12210. const transitionHeight = vue.ref(undefined);
  12211. const activeIndex = vue.computed(() => {
  12212. return group.items.value.findIndex(item => group.selected.value.includes(item.id));
  12213. });
  12214. vue.watch(activeIndex, (newVal, oldVal) => {
  12215. const itemsLength = group.items.value.length;
  12216. const lastIndex = itemsLength - 1;
  12217. if (itemsLength <= 2) {
  12218. isReversed.value = newVal < oldVal;
  12219. } else if (newVal === lastIndex && oldVal === 0) {
  12220. isReversed.value = true;
  12221. } else if (newVal === 0 && oldVal === lastIndex) {
  12222. isReversed.value = false;
  12223. } else {
  12224. isReversed.value = newVal < oldVal;
  12225. }
  12226. });
  12227. vue.provide(VWindowSymbol, {
  12228. transition,
  12229. isReversed,
  12230. transitionCount,
  12231. transitionHeight,
  12232. rootRef
  12233. });
  12234. const canMoveBack = vue.computed(() => props.continuous || activeIndex.value !== 0);
  12235. const canMoveForward = vue.computed(() => props.continuous || activeIndex.value !== group.items.value.length - 1);
  12236. function prev() {
  12237. canMoveBack.value && group.prev();
  12238. }
  12239. function next() {
  12240. canMoveForward.value && group.next();
  12241. }
  12242. const arrows = vue.computed(() => {
  12243. const arrows = [];
  12244. const prevProps = {
  12245. icon: isRtl.value ? props.nextIcon : props.prevIcon,
  12246. class: `v-window__${isRtlReverse.value ? 'right' : 'left'}`,
  12247. onClick: group.prev,
  12248. ariaLabel: t('$vuetify.carousel.prev')
  12249. };
  12250. arrows.push(canMoveBack.value ? slots.prev ? slots.prev({
  12251. props: prevProps
  12252. }) : vue.createVNode(VBtn, prevProps, null) : vue.createVNode("div", null, null));
  12253. const nextProps = {
  12254. icon: isRtl.value ? props.prevIcon : props.nextIcon,
  12255. class: `v-window__${isRtlReverse.value ? 'left' : 'right'}`,
  12256. onClick: group.next,
  12257. ariaLabel: t('$vuetify.carousel.next')
  12258. };
  12259. arrows.push(canMoveForward.value ? slots.next ? slots.next({
  12260. props: nextProps
  12261. }) : vue.createVNode(VBtn, nextProps, null) : vue.createVNode("div", null, null));
  12262. return arrows;
  12263. });
  12264. const touchOptions = vue.computed(() => {
  12265. if (props.touch === false) return props.touch;
  12266. const options = {
  12267. left: () => {
  12268. isRtlReverse.value ? prev() : next();
  12269. },
  12270. right: () => {
  12271. isRtlReverse.value ? next() : prev();
  12272. },
  12273. start: _ref2 => {
  12274. let {
  12275. originalEvent
  12276. } = _ref2;
  12277. originalEvent.stopPropagation();
  12278. }
  12279. };
  12280. return {
  12281. ...options,
  12282. ...(props.touch === true ? {} : props.touch)
  12283. };
  12284. });
  12285. useRender(() => vue.withDirectives(vue.createVNode(props.tag, {
  12286. "ref": rootRef,
  12287. "class": ['v-window', {
  12288. 'v-window--show-arrows-on-hover': props.showArrows === 'hover'
  12289. }, themeClasses.value, props.class],
  12290. "style": props.style
  12291. }, {
  12292. default: () => [vue.createVNode("div", {
  12293. "class": "v-window__container",
  12294. "style": {
  12295. height: transitionHeight.value
  12296. }
  12297. }, [slots.default?.({
  12298. group
  12299. }), props.showArrows !== false && vue.createVNode("div", {
  12300. "class": "v-window__controls"
  12301. }, [arrows.value])]), slots.additional?.({
  12302. group
  12303. })]
  12304. }), [[vue.resolveDirective("touch"), touchOptions.value]]));
  12305. return {
  12306. group
  12307. };
  12308. }
  12309. });
  12310. // Types
  12311. const makeVCarouselProps = propsFactory({
  12312. color: String,
  12313. cycle: Boolean,
  12314. delimiterIcon: {
  12315. type: IconValue,
  12316. default: '$delimiter'
  12317. },
  12318. height: {
  12319. type: [Number, String],
  12320. default: 500
  12321. },
  12322. hideDelimiters: Boolean,
  12323. hideDelimiterBackground: Boolean,
  12324. interval: {
  12325. type: [Number, String],
  12326. default: 6000,
  12327. validator: value => Number(value) > 0
  12328. },
  12329. progress: [Boolean, String],
  12330. verticalDelimiters: [Boolean, String],
  12331. ...makeVWindowProps({
  12332. continuous: true,
  12333. mandatory: 'force',
  12334. showArrows: true
  12335. })
  12336. }, 'VCarousel');
  12337. const VCarousel = genericComponent()({
  12338. name: 'VCarousel',
  12339. props: makeVCarouselProps(),
  12340. emits: {
  12341. 'update:modelValue': val => true
  12342. },
  12343. setup(props, _ref) {
  12344. let {
  12345. slots
  12346. } = _ref;
  12347. const model = useProxiedModel(props, 'modelValue');
  12348. const {
  12349. t
  12350. } = useLocale();
  12351. const windowRef = vue.ref();
  12352. let slideTimeout = -1;
  12353. vue.watch(model, restartTimeout);
  12354. vue.watch(() => props.interval, restartTimeout);
  12355. vue.watch(() => props.cycle, val => {
  12356. if (val) restartTimeout();else window.clearTimeout(slideTimeout);
  12357. });
  12358. vue.onMounted(startTimeout);
  12359. function startTimeout() {
  12360. if (!props.cycle || !windowRef.value) return;
  12361. slideTimeout = window.setTimeout(windowRef.value.group.next, +props.interval > 0 ? +props.interval : 6000);
  12362. }
  12363. function restartTimeout() {
  12364. window.clearTimeout(slideTimeout);
  12365. window.requestAnimationFrame(startTimeout);
  12366. }
  12367. useRender(() => {
  12368. const [windowProps] = VWindow.filterProps(props);
  12369. return vue.createVNode(VWindow, vue.mergeProps({
  12370. "ref": windowRef
  12371. }, windowProps, {
  12372. "modelValue": model.value,
  12373. "onUpdate:modelValue": $event => model.value = $event,
  12374. "class": ['v-carousel', {
  12375. 'v-carousel--hide-delimiter-background': props.hideDelimiterBackground,
  12376. 'v-carousel--vertical-delimiters': props.verticalDelimiters
  12377. }, props.class],
  12378. "style": [{
  12379. height: convertToUnit(props.height)
  12380. }, props.style]
  12381. }), {
  12382. default: slots.default,
  12383. additional: _ref2 => {
  12384. let {
  12385. group
  12386. } = _ref2;
  12387. return vue.createVNode(vue.Fragment, null, [!props.hideDelimiters && vue.createVNode("div", {
  12388. "class": "v-carousel__controls",
  12389. "style": {
  12390. left: props.verticalDelimiters === 'left' && props.verticalDelimiters ? 0 : 'auto',
  12391. right: props.verticalDelimiters === 'right' ? 0 : 'auto'
  12392. }
  12393. }, [group.items.value.length > 0 && vue.createVNode(VDefaultsProvider, {
  12394. "defaults": {
  12395. VBtn: {
  12396. color: props.color,
  12397. icon: props.delimiterIcon,
  12398. size: 'x-small',
  12399. variant: 'text'
  12400. }
  12401. },
  12402. "scoped": true
  12403. }, {
  12404. default: () => [group.items.value.map((item, index) => {
  12405. const props = {
  12406. id: `carousel-item-${item.id}`,
  12407. 'aria-label': t('$vuetify.carousel.ariaLabel.delimiter', index + 1, group.items.value.length),
  12408. class: [group.isSelected(item.id) && 'v-btn--active'],
  12409. onClick: () => group.select(item.id, true)
  12410. };
  12411. return slots.item ? slots.item({
  12412. props,
  12413. item
  12414. }) : vue.createVNode(VBtn, vue.mergeProps(item, props), null);
  12415. })]
  12416. })]), props.progress && vue.createVNode(VProgressLinear, {
  12417. "class": "v-carousel__progress",
  12418. "color": typeof props.progress === 'string' ? props.progress : undefined,
  12419. "modelValue": (group.getItemIndex(model.value) + 1) / group.items.value.length * 100
  12420. }, null)]);
  12421. },
  12422. prev: slots.prev,
  12423. next: slots.next
  12424. });
  12425. });
  12426. return {};
  12427. }
  12428. });
  12429. const makeVWindowItemProps = propsFactory({
  12430. reverseTransition: {
  12431. type: [Boolean, String],
  12432. default: undefined
  12433. },
  12434. transition: {
  12435. type: [Boolean, String],
  12436. default: undefined
  12437. },
  12438. ...makeComponentProps(),
  12439. ...makeGroupItemProps(),
  12440. ...makeLazyProps()
  12441. }, 'VWindowItem');
  12442. const VWindowItem = genericComponent()({
  12443. name: 'VWindowItem',
  12444. directives: {
  12445. Touch
  12446. },
  12447. props: makeVWindowItemProps(),
  12448. emits: {
  12449. 'group:selected': val => true
  12450. },
  12451. setup(props, _ref) {
  12452. let {
  12453. slots
  12454. } = _ref;
  12455. const window = vue.inject(VWindowSymbol);
  12456. const groupItem = useGroupItem(props, VWindowGroupSymbol);
  12457. const {
  12458. isBooted
  12459. } = useSsrBoot();
  12460. if (!window || !groupItem) throw new Error('[Vuetify] VWindowItem must be used inside VWindow');
  12461. const isTransitioning = vue.shallowRef(false);
  12462. const hasTransition = vue.computed(() => isBooted.value && (window.isReversed.value ? props.reverseTransition !== false : props.transition !== false));
  12463. function onAfterTransition() {
  12464. if (!isTransitioning.value || !window) {
  12465. return;
  12466. }
  12467. // Finalize transition state.
  12468. isTransitioning.value = false;
  12469. if (window.transitionCount.value > 0) {
  12470. window.transitionCount.value -= 1;
  12471. // Remove container height if we are out of transition.
  12472. if (window.transitionCount.value === 0) {
  12473. window.transitionHeight.value = undefined;
  12474. }
  12475. }
  12476. }
  12477. function onBeforeTransition() {
  12478. if (isTransitioning.value || !window) {
  12479. return;
  12480. }
  12481. // Initialize transition state here.
  12482. isTransitioning.value = true;
  12483. if (window.transitionCount.value === 0) {
  12484. // Set initial height for height transition.
  12485. window.transitionHeight.value = convertToUnit(window.rootRef.value?.clientHeight);
  12486. }
  12487. window.transitionCount.value += 1;
  12488. }
  12489. function onTransitionCancelled() {
  12490. onAfterTransition(); // This should have the same path as normal transition end.
  12491. }
  12492. function onEnterTransition(el) {
  12493. if (!isTransitioning.value) {
  12494. return;
  12495. }
  12496. vue.nextTick(() => {
  12497. // Do not set height if no transition or cancelled.
  12498. if (!hasTransition.value || !isTransitioning.value || !window) {
  12499. return;
  12500. }
  12501. // Set transition target height.
  12502. window.transitionHeight.value = convertToUnit(el.clientHeight);
  12503. });
  12504. }
  12505. const transition = vue.computed(() => {
  12506. const name = window.isReversed.value ? props.reverseTransition : props.transition;
  12507. return !hasTransition.value ? false : {
  12508. name: typeof name !== 'string' ? window.transition.value : name,
  12509. onBeforeEnter: onBeforeTransition,
  12510. onAfterEnter: onAfterTransition,
  12511. onEnterCancelled: onTransitionCancelled,
  12512. onBeforeLeave: onBeforeTransition,
  12513. onAfterLeave: onAfterTransition,
  12514. onLeaveCancelled: onTransitionCancelled,
  12515. onEnter: onEnterTransition
  12516. };
  12517. });
  12518. const {
  12519. hasContent
  12520. } = useLazy(props, groupItem.isSelected);
  12521. useRender(() => vue.createVNode(MaybeTransition, {
  12522. "transition": transition.value,
  12523. "disabled": !isBooted.value
  12524. }, {
  12525. default: () => [vue.withDirectives(vue.createVNode("div", {
  12526. "class": ['v-window-item', groupItem.selectedClass.value, props.class],
  12527. "style": props.style
  12528. }, [hasContent.value && slots.default?.()]), [[vue.vShow, groupItem.isSelected.value]])]
  12529. }));
  12530. return {
  12531. groupItem
  12532. };
  12533. }
  12534. });
  12535. // Types
  12536. const makeVCarouselItemProps = propsFactory({
  12537. ...makeVImgProps(),
  12538. ...makeVWindowItemProps()
  12539. }, 'VCarouselItem');
  12540. const VCarouselItem = genericComponent()({
  12541. name: 'VCarouselItem',
  12542. inheritAttrs: false,
  12543. props: makeVCarouselItemProps(),
  12544. setup(props, _ref) {
  12545. let {
  12546. slots,
  12547. attrs
  12548. } = _ref;
  12549. useRender(() => {
  12550. const [imgProps] = VImg.filterProps(props);
  12551. const [windowItemProps] = VWindowItem.filterProps(props);
  12552. return vue.createVNode(VWindowItem, vue.mergeProps({
  12553. "class": "v-carousel-item"
  12554. }, windowItemProps), {
  12555. default: () => [vue.createVNode(VImg, vue.mergeProps(attrs, imgProps), slots)]
  12556. });
  12557. });
  12558. }
  12559. });
  12560. // Styles
  12561. const VCode = createSimpleFunctional('v-code');
  12562. // Types
  12563. const makeVColorPickerCanvasProps = propsFactory({
  12564. color: {
  12565. type: Object
  12566. },
  12567. disabled: Boolean,
  12568. dotSize: {
  12569. type: [Number, String],
  12570. default: 10
  12571. },
  12572. height: {
  12573. type: [Number, String],
  12574. default: 150
  12575. },
  12576. width: {
  12577. type: [Number, String],
  12578. default: 300
  12579. },
  12580. ...makeComponentProps()
  12581. }, 'VColorPickerCanvas');
  12582. const VColorPickerCanvas = defineComponent({
  12583. name: 'VColorPickerCanvas',
  12584. props: makeVColorPickerCanvasProps(),
  12585. emits: {
  12586. 'update:color': color => true,
  12587. 'update:position': hue => true
  12588. },
  12589. setup(props, _ref) {
  12590. let {
  12591. emit
  12592. } = _ref;
  12593. const isInteracting = vue.shallowRef(false);
  12594. const isOutsideUpdate = vue.shallowRef(false);
  12595. const dotPosition = vue.ref({
  12596. x: 0,
  12597. y: 0
  12598. });
  12599. const dotStyles = vue.computed(() => {
  12600. const {
  12601. x,
  12602. y
  12603. } = dotPosition.value;
  12604. const radius = parseInt(props.dotSize, 10) / 2;
  12605. return {
  12606. width: convertToUnit(props.dotSize),
  12607. height: convertToUnit(props.dotSize),
  12608. transform: `translate(${convertToUnit(x - radius)}, ${convertToUnit(y - radius)})`
  12609. };
  12610. });
  12611. const canvasRef = vue.ref();
  12612. const canvasWidth = vue.shallowRef(parseFloat(props.width));
  12613. const canvasHeight = vue.shallowRef(parseFloat(props.height));
  12614. const {
  12615. resizeRef
  12616. } = useResizeObserver(entries => {
  12617. if (!resizeRef.value?.offsetParent) return;
  12618. const {
  12619. width,
  12620. height
  12621. } = entries[0].contentRect;
  12622. canvasWidth.value = width;
  12623. canvasHeight.value = height;
  12624. });
  12625. function updateDotPosition(x, y, rect) {
  12626. const {
  12627. left,
  12628. top,
  12629. width,
  12630. height
  12631. } = rect;
  12632. dotPosition.value = {
  12633. x: clamp(x - left, 0, width),
  12634. y: clamp(y - top, 0, height)
  12635. };
  12636. }
  12637. function handleClick(e) {
  12638. if (props.disabled || !canvasRef.value) return;
  12639. updateDotPosition(e.clientX, e.clientY, canvasRef.value.getBoundingClientRect());
  12640. }
  12641. function handleMouseDown(e) {
  12642. // To prevent selection while moving cursor
  12643. e.preventDefault();
  12644. if (props.disabled) return;
  12645. isInteracting.value = true;
  12646. window.addEventListener('mousemove', handleMouseMove);
  12647. window.addEventListener('mouseup', handleMouseUp);
  12648. window.addEventListener('touchmove', handleMouseMove);
  12649. window.addEventListener('touchend', handleMouseUp);
  12650. }
  12651. function handleMouseMove(e) {
  12652. if (props.disabled || !canvasRef.value) return;
  12653. isInteracting.value = true;
  12654. const coords = getEventCoordinates(e);
  12655. updateDotPosition(coords.clientX, coords.clientY, canvasRef.value.getBoundingClientRect());
  12656. }
  12657. function handleMouseUp() {
  12658. window.removeEventListener('mousemove', handleMouseMove);
  12659. window.removeEventListener('mouseup', handleMouseUp);
  12660. window.removeEventListener('touchmove', handleMouseMove);
  12661. window.removeEventListener('touchend', handleMouseUp);
  12662. }
  12663. vue.watch(dotPosition, () => {
  12664. if (isOutsideUpdate.value) {
  12665. isOutsideUpdate.value = false;
  12666. return;
  12667. }
  12668. if (!canvasRef.value) return;
  12669. const {
  12670. x,
  12671. y
  12672. } = dotPosition.value;
  12673. emit('update:color', {
  12674. h: props.color?.h ?? 0,
  12675. s: clamp(x, 0, canvasWidth.value) / canvasWidth.value,
  12676. v: 1 - clamp(y, 0, canvasHeight.value) / canvasHeight.value,
  12677. a: props.color?.a ?? 1
  12678. });
  12679. });
  12680. function updateCanvas() {
  12681. if (!canvasRef.value) return;
  12682. const canvas = canvasRef.value;
  12683. const ctx = canvas.getContext('2d');
  12684. if (!ctx) return;
  12685. const saturationGradient = ctx.createLinearGradient(0, 0, canvas.width, 0);
  12686. saturationGradient.addColorStop(0, 'hsla(0, 0%, 100%, 1)'); // white
  12687. saturationGradient.addColorStop(1, `hsla(${props.color?.h ?? 0}, 100%, 50%, 1)`);
  12688. ctx.fillStyle = saturationGradient;
  12689. ctx.fillRect(0, 0, canvas.width, canvas.height);
  12690. const valueGradient = ctx.createLinearGradient(0, 0, 0, canvas.height);
  12691. valueGradient.addColorStop(0, 'hsla(0, 0%, 100%, 0)'); // transparent
  12692. valueGradient.addColorStop(1, 'hsla(0, 0%, 0%, 1)'); // black
  12693. ctx.fillStyle = valueGradient;
  12694. ctx.fillRect(0, 0, canvas.width, canvas.height);
  12695. }
  12696. vue.watch(() => props.color?.h, updateCanvas, {
  12697. immediate: true
  12698. });
  12699. vue.watch(() => [canvasWidth.value, canvasHeight.value], (newVal, oldVal) => {
  12700. updateCanvas();
  12701. dotPosition.value = {
  12702. x: dotPosition.value.x * newVal[0] / oldVal[0],
  12703. y: dotPosition.value.y * newVal[1] / oldVal[1]
  12704. };
  12705. }, {
  12706. flush: 'post'
  12707. });
  12708. vue.watch(() => props.color, () => {
  12709. if (isInteracting.value) {
  12710. isInteracting.value = false;
  12711. return;
  12712. }
  12713. isOutsideUpdate.value = true;
  12714. dotPosition.value = props.color ? {
  12715. x: props.color.s * canvasWidth.value,
  12716. y: (1 - props.color.v) * canvasHeight.value
  12717. } : {
  12718. x: 0,
  12719. y: 0
  12720. };
  12721. }, {
  12722. deep: true,
  12723. immediate: true
  12724. });
  12725. vue.onMounted(() => updateCanvas());
  12726. useRender(() => vue.createVNode("div", {
  12727. "ref": resizeRef,
  12728. "class": ['v-color-picker-canvas', props.class],
  12729. "style": props.style,
  12730. "onClick": handleClick,
  12731. "onMousedown": handleMouseDown,
  12732. "onTouchstart": handleMouseDown
  12733. }, [vue.createVNode("canvas", {
  12734. "ref": canvasRef,
  12735. "width": canvasWidth.value,
  12736. "height": canvasHeight.value
  12737. }, null), props.color && vue.createVNode("div", {
  12738. "class": ['v-color-picker-canvas__dot', {
  12739. 'v-color-picker-canvas__dot--disabled': props.disabled
  12740. }],
  12741. "style": dotStyles.value
  12742. }, null)]));
  12743. return {};
  12744. }
  12745. });
  12746. // Utilities
  12747. // Types
  12748. function stripAlpha(color, stripAlpha) {
  12749. if (stripAlpha) {
  12750. const {
  12751. a,
  12752. ...rest
  12753. } = color;
  12754. return rest;
  12755. }
  12756. return color;
  12757. }
  12758. function extractColor(color, input) {
  12759. if (input == null || typeof input === 'string') {
  12760. const hex = HSVtoHex(color);
  12761. if (color.a === 1) return hex.slice(0, 7);else return hex;
  12762. }
  12763. if (typeof input === 'object') {
  12764. let converted;
  12765. 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;
  12766. return stripAlpha(converted, !has(input, ['a']) && color.a === 1);
  12767. }
  12768. return color;
  12769. }
  12770. const nullColor = {
  12771. h: 0,
  12772. s: 0,
  12773. v: 1,
  12774. a: 1
  12775. };
  12776. const rgba = {
  12777. inputProps: {
  12778. type: 'number',
  12779. min: 0
  12780. },
  12781. inputs: [{
  12782. label: 'R',
  12783. max: 255,
  12784. step: 1,
  12785. getValue: c => Math.round(c.r),
  12786. getColor: (c, v) => ({
  12787. ...c,
  12788. r: Number(v)
  12789. })
  12790. }, {
  12791. label: 'G',
  12792. max: 255,
  12793. step: 1,
  12794. getValue: c => Math.round(c.g),
  12795. getColor: (c, v) => ({
  12796. ...c,
  12797. g: Number(v)
  12798. })
  12799. }, {
  12800. label: 'B',
  12801. max: 255,
  12802. step: 1,
  12803. getValue: c => Math.round(c.b),
  12804. getColor: (c, v) => ({
  12805. ...c,
  12806. b: Number(v)
  12807. })
  12808. }, {
  12809. label: 'A',
  12810. max: 1,
  12811. step: 0.01,
  12812. getValue: _ref => {
  12813. let {
  12814. a
  12815. } = _ref;
  12816. return a != null ? Math.round(a * 100) / 100 : 1;
  12817. },
  12818. getColor: (c, v) => ({
  12819. ...c,
  12820. a: Number(v)
  12821. })
  12822. }],
  12823. to: HSVtoRGB,
  12824. from: RGBtoHSV
  12825. };
  12826. const rgb = {
  12827. ...rgba,
  12828. inputs: rgba.inputs?.slice(0, 3)
  12829. };
  12830. const hsla = {
  12831. inputProps: {
  12832. type: 'number',
  12833. min: 0
  12834. },
  12835. inputs: [{
  12836. label: 'H',
  12837. max: 360,
  12838. step: 1,
  12839. getValue: c => Math.round(c.h),
  12840. getColor: (c, v) => ({
  12841. ...c,
  12842. h: Number(v)
  12843. })
  12844. }, {
  12845. label: 'S',
  12846. max: 1,
  12847. step: 0.01,
  12848. getValue: c => Math.round(c.s * 100) / 100,
  12849. getColor: (c, v) => ({
  12850. ...c,
  12851. s: Number(v)
  12852. })
  12853. }, {
  12854. label: 'L',
  12855. max: 1,
  12856. step: 0.01,
  12857. getValue: c => Math.round(c.l * 100) / 100,
  12858. getColor: (c, v) => ({
  12859. ...c,
  12860. l: Number(v)
  12861. })
  12862. }, {
  12863. label: 'A',
  12864. max: 1,
  12865. step: 0.01,
  12866. getValue: _ref2 => {
  12867. let {
  12868. a
  12869. } = _ref2;
  12870. return a != null ? Math.round(a * 100) / 100 : 1;
  12871. },
  12872. getColor: (c, v) => ({
  12873. ...c,
  12874. a: Number(v)
  12875. })
  12876. }],
  12877. to: HSVtoHSL,
  12878. from: HSLtoHSV
  12879. };
  12880. const hsl = {
  12881. ...hsla,
  12882. inputs: hsla.inputs.slice(0, 3)
  12883. };
  12884. const hexa = {
  12885. inputProps: {
  12886. type: 'text'
  12887. },
  12888. inputs: [{
  12889. label: 'HEXA',
  12890. getValue: c => c,
  12891. getColor: (c, v) => v
  12892. }],
  12893. to: HSVtoHex,
  12894. from: HexToHSV
  12895. };
  12896. const hex = {
  12897. ...hexa,
  12898. inputs: [{
  12899. label: 'HEX',
  12900. getValue: c => c.slice(0, 7),
  12901. getColor: (c, v) => v
  12902. }]
  12903. };
  12904. const modes = {
  12905. rgb,
  12906. rgba,
  12907. hsl,
  12908. hsla,
  12909. hex,
  12910. hexa
  12911. };
  12912. // Types
  12913. const VColorPickerInput = _ref => {
  12914. let {
  12915. label,
  12916. ...rest
  12917. } = _ref;
  12918. return vue.createVNode("div", {
  12919. "class": "v-color-picker-edit__input"
  12920. }, [vue.createVNode("input", rest, null), vue.createVNode("span", null, [label])]);
  12921. };
  12922. const makeVColorPickerEditProps = propsFactory({
  12923. color: Object,
  12924. disabled: Boolean,
  12925. mode: {
  12926. type: String,
  12927. default: 'rgba',
  12928. validator: v => Object.keys(modes).includes(v)
  12929. },
  12930. modes: {
  12931. type: Array,
  12932. default: () => Object.keys(modes),
  12933. validator: v => Array.isArray(v) && v.every(m => Object.keys(modes).includes(m))
  12934. },
  12935. ...makeComponentProps()
  12936. }, 'VColorPickerEdit');
  12937. const VColorPickerEdit = defineComponent({
  12938. name: 'VColorPickerEdit',
  12939. props: makeVColorPickerEditProps(),
  12940. emits: {
  12941. 'update:color': color => true,
  12942. 'update:mode': mode => true
  12943. },
  12944. setup(props, _ref2) {
  12945. let {
  12946. emit
  12947. } = _ref2;
  12948. const enabledModes = vue.computed(() => {
  12949. return props.modes.map(key => ({
  12950. ...modes[key],
  12951. name: key
  12952. }));
  12953. });
  12954. const inputs = vue.computed(() => {
  12955. const mode = enabledModes.value.find(m => m.name === props.mode);
  12956. if (!mode) return [];
  12957. const color = props.color ? mode.to(props.color) : null;
  12958. return mode.inputs?.map(_ref3 => {
  12959. let {
  12960. getValue,
  12961. getColor,
  12962. ...inputProps
  12963. } = _ref3;
  12964. return {
  12965. ...mode.inputProps,
  12966. ...inputProps,
  12967. disabled: props.disabled,
  12968. value: color && getValue(color),
  12969. onChange: e => {
  12970. const target = e.target;
  12971. if (!target) return;
  12972. emit('update:color', mode.from(getColor(color ?? nullColor, target.value)));
  12973. }
  12974. };
  12975. });
  12976. });
  12977. useRender(() => vue.createVNode("div", {
  12978. "class": ['v-color-picker-edit', props.class],
  12979. "style": props.style
  12980. }, [inputs.value?.map(props => vue.createVNode(VColorPickerInput, props, null)), enabledModes.value.length > 1 && vue.createVNode(VBtn, {
  12981. "icon": "$unfold",
  12982. "size": "x-small",
  12983. "variant": "plain",
  12984. "onClick": () => {
  12985. const mi = enabledModes.value.findIndex(m => m.name === props.mode);
  12986. emit('update:mode', enabledModes.value[(mi + 1) % enabledModes.value.length].name);
  12987. }
  12988. }, null)]));
  12989. return {};
  12990. }
  12991. });
  12992. /* eslint-disable max-statements */
  12993. // Composables
  12994. // Types
  12995. const VSliderSymbol = Symbol.for('vuetify:v-slider');
  12996. function getOffset(e, el, direction) {
  12997. const vertical = direction === 'vertical';
  12998. const rect = el.getBoundingClientRect();
  12999. const touch = 'touches' in e ? e.touches[0] : e;
  13000. return vertical ? touch.clientY - (rect.top + rect.height / 2) : touch.clientX - (rect.left + rect.width / 2);
  13001. }
  13002. function getPosition(e, position) {
  13003. 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];
  13004. }
  13005. const makeSliderProps = propsFactory({
  13006. disabled: {
  13007. type: Boolean,
  13008. default: null
  13009. },
  13010. error: Boolean,
  13011. readonly: {
  13012. type: Boolean,
  13013. default: null
  13014. },
  13015. max: {
  13016. type: [Number, String],
  13017. default: 100
  13018. },
  13019. min: {
  13020. type: [Number, String],
  13021. default: 0
  13022. },
  13023. step: {
  13024. type: [Number, String],
  13025. default: 0
  13026. },
  13027. thumbColor: String,
  13028. thumbLabel: {
  13029. type: [Boolean, String],
  13030. default: undefined,
  13031. validator: v => typeof v === 'boolean' || v === 'always'
  13032. },
  13033. thumbSize: {
  13034. type: [Number, String],
  13035. default: 20
  13036. },
  13037. showTicks: {
  13038. type: [Boolean, String],
  13039. default: false,
  13040. validator: v => typeof v === 'boolean' || v === 'always'
  13041. },
  13042. ticks: {
  13043. type: [Array, Object]
  13044. },
  13045. tickSize: {
  13046. type: [Number, String],
  13047. default: 2
  13048. },
  13049. color: String,
  13050. trackColor: String,
  13051. trackFillColor: String,
  13052. trackSize: {
  13053. type: [Number, String],
  13054. default: 4
  13055. },
  13056. direction: {
  13057. type: String,
  13058. default: 'horizontal',
  13059. validator: v => ['vertical', 'horizontal'].includes(v)
  13060. },
  13061. reverse: Boolean,
  13062. ...makeRoundedProps(),
  13063. ...makeElevationProps({
  13064. elevation: 2
  13065. })
  13066. }, 'Slider');
  13067. const useSteps = props => {
  13068. const min = vue.computed(() => parseFloat(props.min));
  13069. const max = vue.computed(() => parseFloat(props.max));
  13070. const step = vue.computed(() => +props.step > 0 ? parseFloat(props.step) : 0);
  13071. const decimals = vue.computed(() => Math.max(getDecimals(step.value), getDecimals(min.value)));
  13072. function roundValue(value) {
  13073. value = parseFloat(value);
  13074. if (step.value <= 0) return value;
  13075. const clamped = clamp(value, min.value, max.value);
  13076. const offset = min.value % step.value;
  13077. const newValue = Math.round((clamped - offset) / step.value) * step.value + offset;
  13078. return parseFloat(Math.min(newValue, max.value).toFixed(decimals.value));
  13079. }
  13080. return {
  13081. min,
  13082. max,
  13083. step,
  13084. decimals,
  13085. roundValue
  13086. };
  13087. };
  13088. const useSlider = _ref => {
  13089. let {
  13090. props,
  13091. steps,
  13092. onSliderStart,
  13093. onSliderMove,
  13094. onSliderEnd,
  13095. getActiveThumb
  13096. } = _ref;
  13097. const {
  13098. isRtl
  13099. } = useRtl();
  13100. const isReversed = vue.toRef(props, 'reverse');
  13101. const horizontalDirection = vue.computed(() => {
  13102. let hd = isRtl.value ? 'rtl' : 'ltr';
  13103. if (props.reverse) {
  13104. hd = hd === 'rtl' ? 'ltr' : 'rtl';
  13105. }
  13106. return hd;
  13107. });
  13108. const {
  13109. min,
  13110. max,
  13111. step,
  13112. decimals,
  13113. roundValue
  13114. } = steps;
  13115. const thumbSize = vue.computed(() => parseInt(props.thumbSize, 10));
  13116. const tickSize = vue.computed(() => parseInt(props.tickSize, 10));
  13117. const trackSize = vue.computed(() => parseInt(props.trackSize, 10));
  13118. const numTicks = vue.computed(() => (max.value - min.value) / step.value);
  13119. const disabled = vue.toRef(props, 'disabled');
  13120. const vertical = vue.computed(() => props.direction === 'vertical');
  13121. const thumbColor = vue.computed(() => props.error || props.disabled ? undefined : props.thumbColor ?? props.color);
  13122. const trackColor = vue.computed(() => props.error || props.disabled ? undefined : props.trackColor ?? props.color);
  13123. const trackFillColor = vue.computed(() => props.error || props.disabled ? undefined : props.trackFillColor ?? props.color);
  13124. const mousePressed = vue.shallowRef(false);
  13125. const startOffset = vue.shallowRef(0);
  13126. const trackContainerRef = vue.ref();
  13127. const activeThumbRef = vue.ref();
  13128. function parseMouseMove(e) {
  13129. const vertical = props.direction === 'vertical';
  13130. const start = vertical ? 'top' : 'left';
  13131. const length = vertical ? 'height' : 'width';
  13132. const position = vertical ? 'clientY' : 'clientX';
  13133. const {
  13134. [start]: trackStart,
  13135. [length]: trackLength
  13136. } = trackContainerRef.value?.$el.getBoundingClientRect();
  13137. const clickOffset = getPosition(e, position);
  13138. // It is possible for left to be NaN, force to number
  13139. let clickPos = Math.min(Math.max((clickOffset - trackStart - startOffset.value) / trackLength, 0), 1) || 0;
  13140. if (vertical || horizontalDirection.value === 'rtl') clickPos = 1 - clickPos;
  13141. return roundValue(min.value + clickPos * (max.value - min.value));
  13142. }
  13143. const handleStop = e => {
  13144. onSliderEnd({
  13145. value: parseMouseMove(e)
  13146. });
  13147. mousePressed.value = false;
  13148. startOffset.value = 0;
  13149. };
  13150. const handleStart = e => {
  13151. activeThumbRef.value = getActiveThumb(e);
  13152. if (!activeThumbRef.value) return;
  13153. activeThumbRef.value.focus();
  13154. mousePressed.value = true;
  13155. if (activeThumbRef.value.contains(e.target)) {
  13156. startOffset.value = getOffset(e, activeThumbRef.value, props.direction);
  13157. } else {
  13158. startOffset.value = 0;
  13159. onSliderMove({
  13160. value: parseMouseMove(e)
  13161. });
  13162. }
  13163. onSliderStart({
  13164. value: parseMouseMove(e)
  13165. });
  13166. };
  13167. const moveListenerOptions = {
  13168. passive: true,
  13169. capture: true
  13170. };
  13171. function onMouseMove(e) {
  13172. onSliderMove({
  13173. value: parseMouseMove(e)
  13174. });
  13175. }
  13176. function onSliderMouseUp(e) {
  13177. e.stopPropagation();
  13178. e.preventDefault();
  13179. handleStop(e);
  13180. window.removeEventListener('mousemove', onMouseMove, moveListenerOptions);
  13181. window.removeEventListener('mouseup', onSliderMouseUp);
  13182. }
  13183. function onSliderTouchend(e) {
  13184. handleStop(e);
  13185. window.removeEventListener('touchmove', onMouseMove, moveListenerOptions);
  13186. e.target?.removeEventListener('touchend', onSliderTouchend);
  13187. }
  13188. function onSliderTouchstart(e) {
  13189. handleStart(e);
  13190. window.addEventListener('touchmove', onMouseMove, moveListenerOptions);
  13191. e.target?.addEventListener('touchend', onSliderTouchend, {
  13192. passive: false
  13193. });
  13194. }
  13195. function onSliderMousedown(e) {
  13196. e.preventDefault();
  13197. handleStart(e);
  13198. window.addEventListener('mousemove', onMouseMove, moveListenerOptions);
  13199. window.addEventListener('mouseup', onSliderMouseUp, {
  13200. passive: false
  13201. });
  13202. }
  13203. const position = val => {
  13204. const percentage = (val - min.value) / (max.value - min.value) * 100;
  13205. return clamp(isNaN(percentage) ? 0 : percentage, 0, 100);
  13206. };
  13207. const showTicks = vue.toRef(props, 'showTicks');
  13208. const parsedTicks = vue.computed(() => {
  13209. if (!showTicks.value) return [];
  13210. if (!props.ticks) {
  13211. return numTicks.value !== Infinity ? createRange(numTicks.value + 1).map(t => {
  13212. const value = min.value + t * step.value;
  13213. return {
  13214. value,
  13215. position: position(value)
  13216. };
  13217. }) : [];
  13218. }
  13219. if (Array.isArray(props.ticks)) return props.ticks.map(t => ({
  13220. value: t,
  13221. position: position(t),
  13222. label: t.toString()
  13223. }));
  13224. return Object.keys(props.ticks).map(key => ({
  13225. value: parseFloat(key),
  13226. position: position(parseFloat(key)),
  13227. label: props.ticks[key]
  13228. }));
  13229. });
  13230. const hasLabels = vue.computed(() => parsedTicks.value.some(_ref2 => {
  13231. let {
  13232. label
  13233. } = _ref2;
  13234. return !!label;
  13235. }));
  13236. const data = {
  13237. activeThumbRef,
  13238. color: vue.toRef(props, 'color'),
  13239. decimals,
  13240. disabled,
  13241. direction: vue.toRef(props, 'direction'),
  13242. elevation: vue.toRef(props, 'elevation'),
  13243. hasLabels,
  13244. horizontalDirection,
  13245. isReversed,
  13246. min,
  13247. max,
  13248. mousePressed,
  13249. numTicks,
  13250. onSliderMousedown,
  13251. onSliderTouchstart,
  13252. parsedTicks,
  13253. parseMouseMove,
  13254. position,
  13255. readonly: vue.toRef(props, 'readonly'),
  13256. rounded: vue.toRef(props, 'rounded'),
  13257. roundValue,
  13258. showTicks,
  13259. startOffset,
  13260. step,
  13261. thumbSize,
  13262. thumbColor,
  13263. thumbLabel: vue.toRef(props, 'thumbLabel'),
  13264. ticks: vue.toRef(props, 'ticks'),
  13265. tickSize,
  13266. trackColor,
  13267. trackContainerRef,
  13268. trackFillColor,
  13269. trackSize,
  13270. vertical
  13271. };
  13272. vue.provide(VSliderSymbol, data);
  13273. return data;
  13274. };
  13275. // Types
  13276. const makeVSliderThumbProps = propsFactory({
  13277. focused: Boolean,
  13278. max: {
  13279. type: Number,
  13280. required: true
  13281. },
  13282. min: {
  13283. type: Number,
  13284. required: true
  13285. },
  13286. modelValue: {
  13287. type: Number,
  13288. required: true
  13289. },
  13290. position: {
  13291. type: Number,
  13292. required: true
  13293. },
  13294. ripple: {
  13295. type: [Boolean, Object],
  13296. default: true
  13297. },
  13298. ...makeComponentProps()
  13299. }, 'VSliderThumb');
  13300. const VSliderThumb = genericComponent()({
  13301. name: 'VSliderThumb',
  13302. directives: {
  13303. Ripple
  13304. },
  13305. props: makeVSliderThumbProps(),
  13306. emits: {
  13307. 'update:modelValue': v => true
  13308. },
  13309. setup(props, _ref) {
  13310. let {
  13311. slots,
  13312. emit
  13313. } = _ref;
  13314. const slider = vue.inject(VSliderSymbol);
  13315. const {
  13316. rtlClasses
  13317. } = useRtl();
  13318. if (!slider) throw new Error('[Vuetify] v-slider-thumb must be used inside v-slider or v-range-slider');
  13319. const {
  13320. thumbColor,
  13321. step,
  13322. vertical,
  13323. disabled,
  13324. thumbSize,
  13325. thumbLabel,
  13326. direction,
  13327. readonly,
  13328. elevation,
  13329. isReversed,
  13330. horizontalDirection,
  13331. mousePressed,
  13332. decimals
  13333. } = slider;
  13334. const {
  13335. textColorClasses,
  13336. textColorStyles
  13337. } = useTextColor(thumbColor);
  13338. const {
  13339. pageup,
  13340. pagedown,
  13341. end,
  13342. home,
  13343. left,
  13344. right,
  13345. down,
  13346. up
  13347. } = keyValues;
  13348. const relevantKeys = [pageup, pagedown, end, home, left, right, down, up];
  13349. const multipliers = vue.computed(() => {
  13350. if (step.value) return [1, 2, 3];else return [1, 5, 10];
  13351. });
  13352. function parseKeydown(e, value) {
  13353. if (!relevantKeys.includes(e.key)) return;
  13354. e.preventDefault();
  13355. const _step = step.value || 0.1;
  13356. const steps = (props.max - props.min) / _step;
  13357. if ([left, right, down, up].includes(e.key)) {
  13358. const increase = horizontalDirection.value === 'rtl' ? [left, up] : [right, up];
  13359. const direction = increase.includes(e.key) ? 1 : -1;
  13360. const multiplier = e.shiftKey ? 2 : e.ctrlKey ? 1 : 0;
  13361. value = value + direction * _step * multipliers.value[multiplier];
  13362. } else if (e.key === home) {
  13363. value = props.min;
  13364. } else if (e.key === end) {
  13365. value = props.max;
  13366. } else {
  13367. const direction = e.key === pagedown ? 1 : -1;
  13368. value = value - direction * _step * (steps > 100 ? steps / 10 : 10);
  13369. }
  13370. return Math.max(props.min, Math.min(props.max, value));
  13371. }
  13372. function onKeydown(e) {
  13373. const newValue = parseKeydown(e, props.modelValue);
  13374. newValue != null && emit('update:modelValue', newValue);
  13375. }
  13376. useRender(() => {
  13377. const positionPercentage = convertToUnit(vertical.value || isReversed.value ? 100 - props.position : props.position, '%');
  13378. const {
  13379. elevationClasses
  13380. } = useElevation(vue.computed(() => !disabled.value ? elevation.value : undefined));
  13381. return vue.createVNode("div", {
  13382. "class": ['v-slider-thumb', {
  13383. 'v-slider-thumb--focused': props.focused,
  13384. 'v-slider-thumb--pressed': props.focused && mousePressed.value
  13385. }, props.class, rtlClasses.value],
  13386. "style": [{
  13387. '--v-slider-thumb-position': positionPercentage,
  13388. '--v-slider-thumb-size': convertToUnit(thumbSize.value)
  13389. }, props.style],
  13390. "role": "slider",
  13391. "tabindex": disabled.value ? -1 : 0,
  13392. "aria-valuemin": props.min,
  13393. "aria-valuemax": props.max,
  13394. "aria-valuenow": props.modelValue,
  13395. "aria-readonly": !!readonly.value,
  13396. "aria-orientation": direction.value,
  13397. "onKeydown": !readonly.value ? onKeydown : undefined
  13398. }, [vue.createVNode("div", {
  13399. "class": ['v-slider-thumb__surface', textColorClasses.value, elevationClasses.value],
  13400. "style": {
  13401. ...textColorStyles.value
  13402. }
  13403. }, null), vue.withDirectives(vue.createVNode("div", {
  13404. "class": ['v-slider-thumb__ripple', textColorClasses.value],
  13405. "style": textColorStyles.value
  13406. }, null), [[vue.resolveDirective("ripple"), props.ripple, null, {
  13407. circle: true,
  13408. center: true
  13409. }]]), vue.createVNode(VScaleTransition, {
  13410. "origin": "bottom center"
  13411. }, {
  13412. default: () => [vue.withDirectives(vue.createVNode("div", {
  13413. "class": "v-slider-thumb__label-container"
  13414. }, [vue.createVNode("div", {
  13415. "class": ['v-slider-thumb__label']
  13416. }, [vue.createVNode("div", null, [slots['thumb-label']?.({
  13417. modelValue: props.modelValue
  13418. }) ?? props.modelValue.toFixed(step.value ? decimals.value : 1)])])]), [[vue.vShow, thumbLabel.value && props.focused || thumbLabel.value === 'always']])]
  13419. })]);
  13420. });
  13421. return {};
  13422. }
  13423. });
  13424. // Types
  13425. const makeVSliderTrackProps = propsFactory({
  13426. start: {
  13427. type: Number,
  13428. required: true
  13429. },
  13430. stop: {
  13431. type: Number,
  13432. required: true
  13433. },
  13434. ...makeComponentProps()
  13435. }, 'VSliderTrack');
  13436. const VSliderTrack = genericComponent()({
  13437. name: 'VSliderTrack',
  13438. props: makeVSliderTrackProps(),
  13439. emits: {},
  13440. setup(props, _ref) {
  13441. let {
  13442. slots
  13443. } = _ref;
  13444. const slider = vue.inject(VSliderSymbol);
  13445. if (!slider) throw new Error('[Vuetify] v-slider-track must be inside v-slider or v-range-slider');
  13446. const {
  13447. color,
  13448. horizontalDirection,
  13449. parsedTicks,
  13450. rounded,
  13451. showTicks,
  13452. tickSize,
  13453. trackColor,
  13454. trackFillColor,
  13455. trackSize,
  13456. vertical,
  13457. min,
  13458. max
  13459. } = slider;
  13460. const {
  13461. roundedClasses
  13462. } = useRounded(rounded);
  13463. const {
  13464. backgroundColorClasses: trackFillColorClasses,
  13465. backgroundColorStyles: trackFillColorStyles
  13466. } = useBackgroundColor(trackFillColor);
  13467. const {
  13468. backgroundColorClasses: trackColorClasses,
  13469. backgroundColorStyles: trackColorStyles
  13470. } = useBackgroundColor(trackColor);
  13471. const startDir = vue.computed(() => `inset-${vertical.value ? 'block-end' : 'inline-start'}`);
  13472. const endDir = vue.computed(() => vertical.value ? 'height' : 'width');
  13473. const backgroundStyles = vue.computed(() => {
  13474. return {
  13475. [startDir.value]: '0%',
  13476. [endDir.value]: '100%'
  13477. };
  13478. });
  13479. const trackFillWidth = vue.computed(() => props.stop - props.start);
  13480. const trackFillStyles = vue.computed(() => {
  13481. return {
  13482. [startDir.value]: convertToUnit(props.start, '%'),
  13483. [endDir.value]: convertToUnit(trackFillWidth.value, '%')
  13484. };
  13485. });
  13486. const computedTicks = vue.computed(() => {
  13487. if (!showTicks.value) return [];
  13488. const ticks = vertical.value ? parsedTicks.value.slice().reverse() : parsedTicks.value;
  13489. return ticks.map((tick, index) => {
  13490. const directionProperty = vertical.value ? 'bottom' : 'margin-inline-start';
  13491. const directionValue = tick.value !== min.value && tick.value !== max.value ? convertToUnit(tick.position, '%') : undefined;
  13492. return vue.createVNode("div", {
  13493. "key": tick.value,
  13494. "class": ['v-slider-track__tick', {
  13495. 'v-slider-track__tick--filled': tick.position >= props.start && tick.position <= props.stop,
  13496. 'v-slider-track__tick--first': tick.value === min.value,
  13497. 'v-slider-track__tick--last': tick.value === max.value
  13498. }],
  13499. "style": {
  13500. [directionProperty]: directionValue
  13501. }
  13502. }, [(tick.label || slots['tick-label']) && vue.createVNode("div", {
  13503. "class": "v-slider-track__tick-label"
  13504. }, [slots['tick-label']?.({
  13505. tick,
  13506. index
  13507. }) ?? tick.label])]);
  13508. });
  13509. });
  13510. useRender(() => {
  13511. return vue.createVNode("div", {
  13512. "class": ['v-slider-track', roundedClasses.value, props.class],
  13513. "style": [{
  13514. '--v-slider-track-size': convertToUnit(trackSize.value),
  13515. '--v-slider-tick-size': convertToUnit(tickSize.value),
  13516. direction: !vertical.value ? horizontalDirection.value : undefined
  13517. }, props.style]
  13518. }, [vue.createVNode("div", {
  13519. "class": ['v-slider-track__background', trackColorClasses.value, {
  13520. 'v-slider-track__background--opacity': !!color.value || !trackFillColor.value
  13521. }],
  13522. "style": {
  13523. ...backgroundStyles.value,
  13524. ...trackColorStyles.value
  13525. }
  13526. }, null), vue.createVNode("div", {
  13527. "class": ['v-slider-track__fill', trackFillColorClasses.value],
  13528. "style": {
  13529. ...trackFillStyles.value,
  13530. ...trackFillColorStyles.value
  13531. }
  13532. }, null), showTicks.value && vue.createVNode("div", {
  13533. "class": ['v-slider-track__ticks', {
  13534. 'v-slider-track__ticks--always-show': showTicks.value === 'always'
  13535. }]
  13536. }, [computedTicks.value])]);
  13537. });
  13538. return {};
  13539. }
  13540. });
  13541. // Types
  13542. const makeVSliderProps = propsFactory({
  13543. ...makeFocusProps(),
  13544. ...makeSliderProps(),
  13545. ...makeVInputProps(),
  13546. modelValue: {
  13547. type: [Number, String],
  13548. default: 0
  13549. }
  13550. }, 'VSlider');
  13551. const VSlider = genericComponent()({
  13552. name: 'VSlider',
  13553. props: makeVSliderProps(),
  13554. emits: {
  13555. 'update:focused': value => true,
  13556. 'update:modelValue': v => true,
  13557. start: value => true,
  13558. end: value => true
  13559. },
  13560. setup(props, _ref) {
  13561. let {
  13562. slots,
  13563. emit
  13564. } = _ref;
  13565. const thumbContainerRef = vue.ref();
  13566. const {
  13567. rtlClasses
  13568. } = useRtl();
  13569. const steps = useSteps(props);
  13570. const model = useProxiedModel(props, 'modelValue', undefined, value => {
  13571. return steps.roundValue(value == null ? steps.min.value : value);
  13572. });
  13573. const {
  13574. min,
  13575. max,
  13576. mousePressed,
  13577. roundValue,
  13578. onSliderMousedown,
  13579. onSliderTouchstart,
  13580. trackContainerRef,
  13581. position,
  13582. hasLabels,
  13583. readonly
  13584. } = useSlider({
  13585. props,
  13586. steps,
  13587. onSliderStart: () => {
  13588. emit('start', model.value);
  13589. },
  13590. onSliderEnd: _ref2 => {
  13591. let {
  13592. value
  13593. } = _ref2;
  13594. const roundedValue = roundValue(value);
  13595. model.value = roundedValue;
  13596. emit('end', roundedValue);
  13597. },
  13598. onSliderMove: _ref3 => {
  13599. let {
  13600. value
  13601. } = _ref3;
  13602. return model.value = roundValue(value);
  13603. },
  13604. getActiveThumb: () => thumbContainerRef.value?.$el
  13605. });
  13606. const {
  13607. isFocused,
  13608. focus,
  13609. blur
  13610. } = useFocus(props);
  13611. const trackStop = vue.computed(() => position(model.value));
  13612. useRender(() => {
  13613. const [inputProps, _] = VInput.filterProps(props);
  13614. const hasPrepend = !!(props.label || slots.label || slots.prepend);
  13615. return vue.createVNode(VInput, vue.mergeProps({
  13616. "class": ['v-slider', {
  13617. 'v-slider--has-labels': !!slots['tick-label'] || hasLabels.value,
  13618. 'v-slider--focused': isFocused.value,
  13619. 'v-slider--pressed': mousePressed.value,
  13620. 'v-slider--disabled': props.disabled
  13621. }, rtlClasses.value, props.class],
  13622. "style": props.style
  13623. }, inputProps, {
  13624. "focused": isFocused.value
  13625. }), {
  13626. ...slots,
  13627. prepend: hasPrepend ? slotProps => vue.createVNode(vue.Fragment, null, [slots.label?.(slotProps) ?? props.label ? vue.createVNode(VLabel, {
  13628. "id": slotProps.id.value,
  13629. "class": "v-slider__label",
  13630. "text": props.label
  13631. }, null) : undefined, slots.prepend?.(slotProps)]) : undefined,
  13632. default: _ref4 => {
  13633. let {
  13634. id,
  13635. messagesId
  13636. } = _ref4;
  13637. return vue.createVNode("div", {
  13638. "class": "v-slider__container",
  13639. "onMousedown": !readonly.value ? onSliderMousedown : undefined,
  13640. "onTouchstartPassive": !readonly.value ? onSliderTouchstart : undefined
  13641. }, [vue.createVNode("input", {
  13642. "id": id.value,
  13643. "name": props.name || id.value,
  13644. "disabled": !!props.disabled,
  13645. "readonly": !!props.readonly,
  13646. "tabindex": "-1",
  13647. "value": model.value
  13648. }, null), vue.createVNode(VSliderTrack, {
  13649. "ref": trackContainerRef,
  13650. "start": 0,
  13651. "stop": trackStop.value
  13652. }, {
  13653. 'tick-label': slots['tick-label']
  13654. }), vue.createVNode(VSliderThumb, {
  13655. "ref": thumbContainerRef,
  13656. "aria-describedby": messagesId.value,
  13657. "focused": isFocused.value,
  13658. "min": min.value,
  13659. "max": max.value,
  13660. "modelValue": model.value,
  13661. "onUpdate:modelValue": v => model.value = v,
  13662. "position": trackStop.value,
  13663. "elevation": props.elevation,
  13664. "onFocus": focus,
  13665. "onBlur": blur
  13666. }, {
  13667. 'thumb-label': slots['thumb-label']
  13668. })]);
  13669. }
  13670. });
  13671. });
  13672. return {};
  13673. }
  13674. });
  13675. // Types
  13676. const makeVColorPickerPreviewProps = propsFactory({
  13677. color: {
  13678. type: Object
  13679. },
  13680. disabled: Boolean,
  13681. hideAlpha: Boolean,
  13682. ...makeComponentProps()
  13683. }, 'VColorPickerPreview');
  13684. const VColorPickerPreview = defineComponent({
  13685. name: 'VColorPickerPreview',
  13686. props: makeVColorPickerPreviewProps(),
  13687. emits: {
  13688. 'update:color': color => true
  13689. },
  13690. setup(props, _ref) {
  13691. let {
  13692. emit
  13693. } = _ref;
  13694. useRender(() => vue.createVNode("div", {
  13695. "class": ['v-color-picker-preview', {
  13696. 'v-color-picker-preview--hide-alpha': props.hideAlpha
  13697. }, props.class],
  13698. "style": props.style
  13699. }, [vue.createVNode("div", {
  13700. "class": "v-color-picker-preview__dot"
  13701. }, [vue.createVNode("div", {
  13702. "style": {
  13703. background: HSVtoCSS(props.color ?? nullColor)
  13704. }
  13705. }, null)]), vue.createVNode("div", {
  13706. "class": "v-color-picker-preview__sliders"
  13707. }, [vue.createVNode(VSlider, {
  13708. "class": "v-color-picker-preview__track v-color-picker-preview__hue",
  13709. "modelValue": props.color?.h,
  13710. "onUpdate:modelValue": h => emit('update:color', {
  13711. ...(props.color ?? nullColor),
  13712. h
  13713. }),
  13714. "step": 0,
  13715. "min": 0,
  13716. "max": 360,
  13717. "disabled": props.disabled,
  13718. "thumbSize": 14,
  13719. "trackSize": 8,
  13720. "trackFillColor": "white",
  13721. "hideDetails": true
  13722. }, null), !props.hideAlpha && vue.createVNode(VSlider, {
  13723. "class": "v-color-picker-preview__track v-color-picker-preview__alpha",
  13724. "modelValue": props.color?.a ?? 1,
  13725. "onUpdate:modelValue": a => emit('update:color', {
  13726. ...(props.color ?? nullColor),
  13727. a
  13728. }),
  13729. "step": 1 / 256,
  13730. "min": 0,
  13731. "max": 1,
  13732. "disabled": props.disabled,
  13733. "thumbSize": 14,
  13734. "trackSize": 8,
  13735. "trackFillColor": "white",
  13736. "hideDetails": true
  13737. }, null)])]));
  13738. return {};
  13739. }
  13740. });
  13741. const red = Object.freeze({
  13742. base: '#f44336',
  13743. lighten5: '#ffebee',
  13744. lighten4: '#ffcdd2',
  13745. lighten3: '#ef9a9a',
  13746. lighten2: '#e57373',
  13747. lighten1: '#ef5350',
  13748. darken1: '#e53935',
  13749. darken2: '#d32f2f',
  13750. darken3: '#c62828',
  13751. darken4: '#b71c1c',
  13752. accent1: '#ff8a80',
  13753. accent2: '#ff5252',
  13754. accent3: '#ff1744',
  13755. accent4: '#d50000'
  13756. });
  13757. const pink = Object.freeze({
  13758. base: '#e91e63',
  13759. lighten5: '#fce4ec',
  13760. lighten4: '#f8bbd0',
  13761. lighten3: '#f48fb1',
  13762. lighten2: '#f06292',
  13763. lighten1: '#ec407a',
  13764. darken1: '#d81b60',
  13765. darken2: '#c2185b',
  13766. darken3: '#ad1457',
  13767. darken4: '#880e4f',
  13768. accent1: '#ff80ab',
  13769. accent2: '#ff4081',
  13770. accent3: '#f50057',
  13771. accent4: '#c51162'
  13772. });
  13773. const purple = Object.freeze({
  13774. base: '#9c27b0',
  13775. lighten5: '#f3e5f5',
  13776. lighten4: '#e1bee7',
  13777. lighten3: '#ce93d8',
  13778. lighten2: '#ba68c8',
  13779. lighten1: '#ab47bc',
  13780. darken1: '#8e24aa',
  13781. darken2: '#7b1fa2',
  13782. darken3: '#6a1b9a',
  13783. darken4: '#4a148c',
  13784. accent1: '#ea80fc',
  13785. accent2: '#e040fb',
  13786. accent3: '#d500f9',
  13787. accent4: '#aa00ff'
  13788. });
  13789. const deepPurple = Object.freeze({
  13790. base: '#673ab7',
  13791. lighten5: '#ede7f6',
  13792. lighten4: '#d1c4e9',
  13793. lighten3: '#b39ddb',
  13794. lighten2: '#9575cd',
  13795. lighten1: '#7e57c2',
  13796. darken1: '#5e35b1',
  13797. darken2: '#512da8',
  13798. darken3: '#4527a0',
  13799. darken4: '#311b92',
  13800. accent1: '#b388ff',
  13801. accent2: '#7c4dff',
  13802. accent3: '#651fff',
  13803. accent4: '#6200ea'
  13804. });
  13805. const indigo = Object.freeze({
  13806. base: '#3f51b5',
  13807. lighten5: '#e8eaf6',
  13808. lighten4: '#c5cae9',
  13809. lighten3: '#9fa8da',
  13810. lighten2: '#7986cb',
  13811. lighten1: '#5c6bc0',
  13812. darken1: '#3949ab',
  13813. darken2: '#303f9f',
  13814. darken3: '#283593',
  13815. darken4: '#1a237e',
  13816. accent1: '#8c9eff',
  13817. accent2: '#536dfe',
  13818. accent3: '#3d5afe',
  13819. accent4: '#304ffe'
  13820. });
  13821. const blue = Object.freeze({
  13822. base: '#2196f3',
  13823. lighten5: '#e3f2fd',
  13824. lighten4: '#bbdefb',
  13825. lighten3: '#90caf9',
  13826. lighten2: '#64b5f6',
  13827. lighten1: '#42a5f5',
  13828. darken1: '#1e88e5',
  13829. darken2: '#1976d2',
  13830. darken3: '#1565c0',
  13831. darken4: '#0d47a1',
  13832. accent1: '#82b1ff',
  13833. accent2: '#448aff',
  13834. accent3: '#2979ff',
  13835. accent4: '#2962ff'
  13836. });
  13837. const lightBlue = Object.freeze({
  13838. base: '#03a9f4',
  13839. lighten5: '#e1f5fe',
  13840. lighten4: '#b3e5fc',
  13841. lighten3: '#81d4fa',
  13842. lighten2: '#4fc3f7',
  13843. lighten1: '#29b6f6',
  13844. darken1: '#039be5',
  13845. darken2: '#0288d1',
  13846. darken3: '#0277bd',
  13847. darken4: '#01579b',
  13848. accent1: '#80d8ff',
  13849. accent2: '#40c4ff',
  13850. accent3: '#00b0ff',
  13851. accent4: '#0091ea'
  13852. });
  13853. const cyan = Object.freeze({
  13854. base: '#00bcd4',
  13855. lighten5: '#e0f7fa',
  13856. lighten4: '#b2ebf2',
  13857. lighten3: '#80deea',
  13858. lighten2: '#4dd0e1',
  13859. lighten1: '#26c6da',
  13860. darken1: '#00acc1',
  13861. darken2: '#0097a7',
  13862. darken3: '#00838f',
  13863. darken4: '#006064',
  13864. accent1: '#84ffff',
  13865. accent2: '#18ffff',
  13866. accent3: '#00e5ff',
  13867. accent4: '#00b8d4'
  13868. });
  13869. const teal = Object.freeze({
  13870. base: '#009688',
  13871. lighten5: '#e0f2f1',
  13872. lighten4: '#b2dfdb',
  13873. lighten3: '#80cbc4',
  13874. lighten2: '#4db6ac',
  13875. lighten1: '#26a69a',
  13876. darken1: '#00897b',
  13877. darken2: '#00796b',
  13878. darken3: '#00695c',
  13879. darken4: '#004d40',
  13880. accent1: '#a7ffeb',
  13881. accent2: '#64ffda',
  13882. accent3: '#1de9b6',
  13883. accent4: '#00bfa5'
  13884. });
  13885. const green = Object.freeze({
  13886. base: '#4caf50',
  13887. lighten5: '#e8f5e9',
  13888. lighten4: '#c8e6c9',
  13889. lighten3: '#a5d6a7',
  13890. lighten2: '#81c784',
  13891. lighten1: '#66bb6a',
  13892. darken1: '#43a047',
  13893. darken2: '#388e3c',
  13894. darken3: '#2e7d32',
  13895. darken4: '#1b5e20',
  13896. accent1: '#b9f6ca',
  13897. accent2: '#69f0ae',
  13898. accent3: '#00e676',
  13899. accent4: '#00c853'
  13900. });
  13901. const lightGreen = Object.freeze({
  13902. base: '#8bc34a',
  13903. lighten5: '#f1f8e9',
  13904. lighten4: '#dcedc8',
  13905. lighten3: '#c5e1a5',
  13906. lighten2: '#aed581',
  13907. lighten1: '#9ccc65',
  13908. darken1: '#7cb342',
  13909. darken2: '#689f38',
  13910. darken3: '#558b2f',
  13911. darken4: '#33691e',
  13912. accent1: '#ccff90',
  13913. accent2: '#b2ff59',
  13914. accent3: '#76ff03',
  13915. accent4: '#64dd17'
  13916. });
  13917. const lime = Object.freeze({
  13918. base: '#cddc39',
  13919. lighten5: '#f9fbe7',
  13920. lighten4: '#f0f4c3',
  13921. lighten3: '#e6ee9c',
  13922. lighten2: '#dce775',
  13923. lighten1: '#d4e157',
  13924. darken1: '#c0ca33',
  13925. darken2: '#afb42b',
  13926. darken3: '#9e9d24',
  13927. darken4: '#827717',
  13928. accent1: '#f4ff81',
  13929. accent2: '#eeff41',
  13930. accent3: '#c6ff00',
  13931. accent4: '#aeea00'
  13932. });
  13933. const yellow = Object.freeze({
  13934. base: '#ffeb3b',
  13935. lighten5: '#fffde7',
  13936. lighten4: '#fff9c4',
  13937. lighten3: '#fff59d',
  13938. lighten2: '#fff176',
  13939. lighten1: '#ffee58',
  13940. darken1: '#fdd835',
  13941. darken2: '#fbc02d',
  13942. darken3: '#f9a825',
  13943. darken4: '#f57f17',
  13944. accent1: '#ffff8d',
  13945. accent2: '#ffff00',
  13946. accent3: '#ffea00',
  13947. accent4: '#ffd600'
  13948. });
  13949. const amber = Object.freeze({
  13950. base: '#ffc107',
  13951. lighten5: '#fff8e1',
  13952. lighten4: '#ffecb3',
  13953. lighten3: '#ffe082',
  13954. lighten2: '#ffd54f',
  13955. lighten1: '#ffca28',
  13956. darken1: '#ffb300',
  13957. darken2: '#ffa000',
  13958. darken3: '#ff8f00',
  13959. darken4: '#ff6f00',
  13960. accent1: '#ffe57f',
  13961. accent2: '#ffd740',
  13962. accent3: '#ffc400',
  13963. accent4: '#ffab00'
  13964. });
  13965. const orange = Object.freeze({
  13966. base: '#ff9800',
  13967. lighten5: '#fff3e0',
  13968. lighten4: '#ffe0b2',
  13969. lighten3: '#ffcc80',
  13970. lighten2: '#ffb74d',
  13971. lighten1: '#ffa726',
  13972. darken1: '#fb8c00',
  13973. darken2: '#f57c00',
  13974. darken3: '#ef6c00',
  13975. darken4: '#e65100',
  13976. accent1: '#ffd180',
  13977. accent2: '#ffab40',
  13978. accent3: '#ff9100',
  13979. accent4: '#ff6d00'
  13980. });
  13981. const deepOrange = Object.freeze({
  13982. base: '#ff5722',
  13983. lighten5: '#fbe9e7',
  13984. lighten4: '#ffccbc',
  13985. lighten3: '#ffab91',
  13986. lighten2: '#ff8a65',
  13987. lighten1: '#ff7043',
  13988. darken1: '#f4511e',
  13989. darken2: '#e64a19',
  13990. darken3: '#d84315',
  13991. darken4: '#bf360c',
  13992. accent1: '#ff9e80',
  13993. accent2: '#ff6e40',
  13994. accent3: '#ff3d00',
  13995. accent4: '#dd2c00'
  13996. });
  13997. const brown = Object.freeze({
  13998. base: '#795548',
  13999. lighten5: '#efebe9',
  14000. lighten4: '#d7ccc8',
  14001. lighten3: '#bcaaa4',
  14002. lighten2: '#a1887f',
  14003. lighten1: '#8d6e63',
  14004. darken1: '#6d4c41',
  14005. darken2: '#5d4037',
  14006. darken3: '#4e342e',
  14007. darken4: '#3e2723'
  14008. });
  14009. const blueGrey = Object.freeze({
  14010. base: '#607d8b',
  14011. lighten5: '#eceff1',
  14012. lighten4: '#cfd8dc',
  14013. lighten3: '#b0bec5',
  14014. lighten2: '#90a4ae',
  14015. lighten1: '#78909c',
  14016. darken1: '#546e7a',
  14017. darken2: '#455a64',
  14018. darken3: '#37474f',
  14019. darken4: '#263238'
  14020. });
  14021. const grey = Object.freeze({
  14022. base: '#9e9e9e',
  14023. lighten5: '#fafafa',
  14024. lighten4: '#f5f5f5',
  14025. lighten3: '#eeeeee',
  14026. lighten2: '#e0e0e0',
  14027. lighten1: '#bdbdbd',
  14028. darken1: '#757575',
  14029. darken2: '#616161',
  14030. darken3: '#424242',
  14031. darken4: '#212121'
  14032. });
  14033. const shades = Object.freeze({
  14034. black: '#000000',
  14035. white: '#ffffff',
  14036. transparent: '#ffffff00'
  14037. });
  14038. var colors = Object.freeze({
  14039. red,
  14040. pink,
  14041. purple,
  14042. deepPurple,
  14043. indigo,
  14044. blue,
  14045. lightBlue,
  14046. cyan,
  14047. teal,
  14048. green,
  14049. lightGreen,
  14050. lime,
  14051. yellow,
  14052. amber,
  14053. orange,
  14054. deepOrange,
  14055. brown,
  14056. blueGrey,
  14057. grey,
  14058. shades
  14059. });
  14060. // Types
  14061. const makeVColorPickerSwatchesProps = propsFactory({
  14062. swatches: {
  14063. type: Array,
  14064. default: () => parseDefaultColors(colors)
  14065. },
  14066. disabled: Boolean,
  14067. color: Object,
  14068. maxHeight: [Number, String],
  14069. ...makeComponentProps()
  14070. }, 'VColorPickerSwatches');
  14071. function parseDefaultColors(colors) {
  14072. return Object.keys(colors).map(key => {
  14073. const color = colors[key];
  14074. 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];
  14075. });
  14076. }
  14077. const VColorPickerSwatches = defineComponent({
  14078. name: 'VColorPickerSwatches',
  14079. props: makeVColorPickerSwatchesProps(),
  14080. emits: {
  14081. 'update:color': color => true
  14082. },
  14083. setup(props, _ref) {
  14084. let {
  14085. emit
  14086. } = _ref;
  14087. useRender(() => vue.createVNode("div", {
  14088. "class": ['v-color-picker-swatches', props.class],
  14089. "style": [{
  14090. maxHeight: convertToUnit(props.maxHeight)
  14091. }, props.style]
  14092. }, [vue.createVNode("div", null, [props.swatches.map(swatch => vue.createVNode("div", {
  14093. "class": "v-color-picker-swatches__swatch"
  14094. }, [swatch.map(color => {
  14095. const rgba = parseColor(color);
  14096. const hsva = RGBtoHSV(rgba);
  14097. const background = RGBtoCSS(rgba);
  14098. return vue.createVNode("div", {
  14099. "class": "v-color-picker-swatches__color",
  14100. "onClick": () => hsva && emit('update:color', hsva)
  14101. }, [vue.createVNode("div", {
  14102. "style": {
  14103. background
  14104. }
  14105. }, [props.color && deepEqual(props.color, hsva) ? vue.createVNode(VIcon, {
  14106. "size": "x-small",
  14107. "icon": "$success",
  14108. "color": getContrast(color, '#FFFFFF') > 2 ? 'white' : 'black'
  14109. }, null) : undefined])]);
  14110. })]))])]));
  14111. return {};
  14112. }
  14113. });
  14114. const makeVSheetProps = propsFactory({
  14115. color: String,
  14116. ...makeBorderProps(),
  14117. ...makeComponentProps(),
  14118. ...makeDimensionProps(),
  14119. ...makeElevationProps(),
  14120. ...makeLocationProps(),
  14121. ...makePositionProps(),
  14122. ...makeRoundedProps(),
  14123. ...makeTagProps(),
  14124. ...makeThemeProps()
  14125. }, 'VSheet');
  14126. const VSheet = genericComponent()({
  14127. name: 'VSheet',
  14128. props: makeVSheetProps(),
  14129. setup(props, _ref) {
  14130. let {
  14131. slots
  14132. } = _ref;
  14133. const {
  14134. themeClasses
  14135. } = provideTheme(props);
  14136. const {
  14137. backgroundColorClasses,
  14138. backgroundColorStyles
  14139. } = useBackgroundColor(vue.toRef(props, 'color'));
  14140. const {
  14141. borderClasses
  14142. } = useBorder(props);
  14143. const {
  14144. dimensionStyles
  14145. } = useDimension(props);
  14146. const {
  14147. elevationClasses
  14148. } = useElevation(props);
  14149. const {
  14150. locationStyles
  14151. } = useLocation(props);
  14152. const {
  14153. positionClasses
  14154. } = usePosition(props);
  14155. const {
  14156. roundedClasses
  14157. } = useRounded(props);
  14158. useRender(() => vue.createVNode(props.tag, {
  14159. "class": ['v-sheet', themeClasses.value, backgroundColorClasses.value, borderClasses.value, elevationClasses.value, positionClasses.value, roundedClasses.value, props.class],
  14160. "style": [backgroundColorStyles.value, dimensionStyles.value, locationStyles.value, props.style]
  14161. }, slots));
  14162. return {};
  14163. }
  14164. });
  14165. // Types
  14166. const makeVColorPickerProps = propsFactory({
  14167. canvasHeight: {
  14168. type: [String, Number],
  14169. default: 150
  14170. },
  14171. disabled: Boolean,
  14172. dotSize: {
  14173. type: [Number, String],
  14174. default: 10
  14175. },
  14176. hideCanvas: Boolean,
  14177. hideSliders: Boolean,
  14178. hideInputs: Boolean,
  14179. mode: {
  14180. type: String,
  14181. default: 'rgba',
  14182. validator: v => Object.keys(modes).includes(v)
  14183. },
  14184. modes: {
  14185. type: Array,
  14186. default: () => Object.keys(modes),
  14187. validator: v => Array.isArray(v) && v.every(m => Object.keys(modes).includes(m))
  14188. },
  14189. showSwatches: Boolean,
  14190. swatches: Array,
  14191. swatchesMaxHeight: {
  14192. type: [Number, String],
  14193. default: 150
  14194. },
  14195. modelValue: {
  14196. type: [Object, String]
  14197. },
  14198. ...omit(makeVSheetProps({
  14199. width: 300
  14200. }), ['height', 'location', 'minHeight', 'maxHeight', 'minWidth', 'maxWidth'])
  14201. }, 'VColorPicker');
  14202. const VColorPicker = defineComponent({
  14203. name: 'VColorPicker',
  14204. props: makeVColorPickerProps(),
  14205. emits: {
  14206. 'update:modelValue': color => true,
  14207. 'update:mode': mode => true
  14208. },
  14209. setup(props) {
  14210. const mode = useProxiedModel(props, 'mode');
  14211. const lastPickedColor = vue.ref(null);
  14212. const currentColor = useProxiedModel(props, 'modelValue', undefined, v => {
  14213. if (v == null || v === '') return null;
  14214. let c;
  14215. try {
  14216. c = RGBtoHSV(parseColor(v));
  14217. } catch (err) {
  14218. consoleWarn(err);
  14219. return null;
  14220. }
  14221. if (lastPickedColor.value) {
  14222. c = {
  14223. ...c,
  14224. h: lastPickedColor.value.h
  14225. };
  14226. lastPickedColor.value = null;
  14227. }
  14228. return c;
  14229. }, v => {
  14230. if (!v) return null;
  14231. return extractColor(v, props.modelValue);
  14232. });
  14233. const {
  14234. rtlClasses
  14235. } = useRtl();
  14236. const updateColor = hsva => {
  14237. currentColor.value = hsva;
  14238. lastPickedColor.value = hsva;
  14239. };
  14240. vue.onMounted(() => {
  14241. if (!props.modes.includes(mode.value)) mode.value = props.modes[0];
  14242. });
  14243. provideDefaults({
  14244. VSlider: {
  14245. color: undefined,
  14246. trackColor: undefined,
  14247. trackFillColor: undefined
  14248. }
  14249. });
  14250. useRender(() => {
  14251. const [sheetProps] = VSheet.filterProps(props);
  14252. return vue.createVNode(VSheet, vue.mergeProps({
  14253. "rounded": props.rounded,
  14254. "elevation": props.elevation,
  14255. "theme": props.theme,
  14256. "class": ['v-color-picker', rtlClasses.value, props.class],
  14257. "style": [{
  14258. '--v-color-picker-color-hsv': HSVtoCSS({
  14259. ...(currentColor.value ?? nullColor),
  14260. a: 1
  14261. })
  14262. }, props.style]
  14263. }, sheetProps, {
  14264. "maxWidth": props.width
  14265. }), {
  14266. default: () => [!props.hideCanvas && vue.createVNode(VColorPickerCanvas, {
  14267. "key": "canvas",
  14268. "color": currentColor.value,
  14269. "onUpdate:color": updateColor,
  14270. "disabled": props.disabled,
  14271. "dotSize": props.dotSize,
  14272. "width": props.width,
  14273. "height": props.canvasHeight
  14274. }, null), (!props.hideSliders || !props.hideInputs) && vue.createVNode("div", {
  14275. "key": "controls",
  14276. "class": "v-color-picker__controls"
  14277. }, [!props.hideSliders && vue.createVNode(VColorPickerPreview, {
  14278. "key": "preview",
  14279. "color": currentColor.value,
  14280. "onUpdate:color": updateColor,
  14281. "hideAlpha": !mode.value.endsWith('a'),
  14282. "disabled": props.disabled
  14283. }, null), !props.hideInputs && vue.createVNode(VColorPickerEdit, {
  14284. "key": "edit",
  14285. "modes": props.modes,
  14286. "mode": mode.value,
  14287. "onUpdate:mode": m => mode.value = m,
  14288. "color": currentColor.value,
  14289. "onUpdate:color": updateColor,
  14290. "disabled": props.disabled
  14291. }, null)]), props.showSwatches && vue.createVNode(VColorPickerSwatches, {
  14292. "key": "swatches",
  14293. "color": currentColor.value,
  14294. "onUpdate:color": updateColor,
  14295. "maxHeight": props.swatchesMaxHeight,
  14296. "swatches": props.swatches,
  14297. "disabled": props.disabled
  14298. }, null)]
  14299. });
  14300. });
  14301. return {};
  14302. }
  14303. });
  14304. // Types
  14305. function highlightResult(text, matches, length) {
  14306. if (matches == null) return text;
  14307. if (Array.isArray(matches)) throw new Error('Multiple matches is not implemented');
  14308. return typeof matches === 'number' && ~matches ? vue.createVNode(vue.Fragment, null, [vue.createVNode("span", {
  14309. "class": "v-combobox__unmask"
  14310. }, [text.substr(0, matches)]), vue.createVNode("span", {
  14311. "class": "v-combobox__mask"
  14312. }, [text.substr(matches, length)]), vue.createVNode("span", {
  14313. "class": "v-combobox__unmask"
  14314. }, [text.substr(matches + length)])]) : text;
  14315. }
  14316. const makeVComboboxProps = propsFactory({
  14317. autoSelectFirst: {
  14318. type: [Boolean, String]
  14319. },
  14320. delimiters: Array,
  14321. ...makeFilterProps({
  14322. filterKeys: ['title']
  14323. }),
  14324. ...makeSelectProps({
  14325. hideNoData: true,
  14326. returnObject: true
  14327. }),
  14328. ...omit(makeVTextFieldProps({
  14329. modelValue: null
  14330. }), ['validationValue', 'dirty', 'appendInnerIcon']),
  14331. ...makeTransitionProps({
  14332. transition: false
  14333. })
  14334. }, 'VCombobox');
  14335. const VCombobox = genericComponent()({
  14336. name: 'VCombobox',
  14337. props: makeVComboboxProps(),
  14338. emits: {
  14339. 'update:focused': focused => true,
  14340. 'update:modelValue': val => true,
  14341. 'update:search': val => true,
  14342. 'update:menu': val => true
  14343. },
  14344. setup(props, _ref) {
  14345. let {
  14346. emit,
  14347. slots
  14348. } = _ref;
  14349. const {
  14350. t
  14351. } = useLocale();
  14352. const vTextFieldRef = vue.ref();
  14353. const isFocused = vue.shallowRef(false);
  14354. const isPristine = vue.shallowRef(true);
  14355. const listHasFocus = vue.shallowRef(false);
  14356. const vMenuRef = vue.ref();
  14357. const _menu = useProxiedModel(props, 'menu');
  14358. const menu = vue.computed({
  14359. get: () => _menu.value,
  14360. set: v => {
  14361. if (_menu.value && !v && vMenuRef.value?.ΨopenChildren) return;
  14362. _menu.value = v;
  14363. }
  14364. });
  14365. const selectionIndex = vue.shallowRef(-1);
  14366. let cleared = false;
  14367. const color = vue.computed(() => vTextFieldRef.value?.color);
  14368. const {
  14369. items,
  14370. transformIn,
  14371. transformOut
  14372. } = useItems(props);
  14373. const {
  14374. textColorClasses,
  14375. textColorStyles
  14376. } = useTextColor(color);
  14377. const model = useProxiedModel(props, 'modelValue', [], v => transformIn(wrapInArray(v)), v => {
  14378. const transformed = transformOut(v);
  14379. return props.multiple ? transformed : transformed[0] ?? null;
  14380. });
  14381. const form = useForm();
  14382. const _search = vue.shallowRef(!props.multiple ? model.value[0]?.title ?? '' : '');
  14383. const search = vue.computed({
  14384. get: () => {
  14385. return _search.value;
  14386. },
  14387. set: val => {
  14388. _search.value = val;
  14389. if (!props.multiple) {
  14390. model.value = [transformItem$1(props, val)];
  14391. }
  14392. if (val && props.multiple && props.delimiters?.length) {
  14393. const values = val.split(new RegExp(`(?:${props.delimiters.join('|')})+`));
  14394. if (values.length > 1) {
  14395. values.forEach(v => {
  14396. v = v.trim();
  14397. if (v) select(transformItem$1(props, v));
  14398. });
  14399. _search.value = '';
  14400. }
  14401. }
  14402. if (!val) selectionIndex.value = -1;
  14403. isPristine.value = !val;
  14404. }
  14405. });
  14406. vue.watch(_search, value => {
  14407. if (cleared) {
  14408. // wait for clear to finish, VTextField sets _search to null
  14409. // then search computed triggers and updates _search to ''
  14410. vue.nextTick(() => cleared = false);
  14411. } else if (isFocused.value && !menu.value) {
  14412. menu.value = true;
  14413. }
  14414. emit('update:search', value);
  14415. });
  14416. vue.watch(model, value => {
  14417. if (!props.multiple) {
  14418. _search.value = value[0]?.title ?? '';
  14419. }
  14420. });
  14421. const {
  14422. filteredItems,
  14423. getMatches
  14424. } = useFilter(props, items, () => isPristine.value ? '' : search.value);
  14425. const selections = vue.computed(() => {
  14426. return model.value.map(v => {
  14427. return items.value.find(item => {
  14428. const itemRawValue = getPropertyFromItem(item.raw, props.itemValue);
  14429. const modelRawValue = getPropertyFromItem(v.raw, props.itemValue);
  14430. if (itemRawValue === undefined || modelRawValue === undefined) return false;
  14431. return props.returnObject ? props.valueComparator(itemRawValue, modelRawValue) : props.valueComparator(item.value, v.value);
  14432. }) || v;
  14433. });
  14434. });
  14435. const displayItems = vue.computed(() => {
  14436. if (props.hideSelected) {
  14437. return filteredItems.value.filter(filteredItem => !selections.value.some(s => s.value === filteredItem.value));
  14438. }
  14439. return filteredItems.value;
  14440. });
  14441. const selected = vue.computed(() => selections.value.map(selection => selection.props.value));
  14442. const selection = vue.computed(() => selections.value[selectionIndex.value]);
  14443. const highlightFirst = vue.computed(() => {
  14444. const selectFirst = props.autoSelectFirst === true || props.autoSelectFirst === 'exact' && search.value === displayItems.value[0]?.title;
  14445. return selectFirst && displayItems.value.length > 0 && !isPristine.value && !listHasFocus.value;
  14446. });
  14447. const menuDisabled = vue.computed(() => props.hideNoData && !items.value.length || props.readonly || form?.isReadonly.value);
  14448. const listRef = vue.ref();
  14449. const {
  14450. onListScroll,
  14451. onListKeydown
  14452. } = useScrolling(listRef, vTextFieldRef);
  14453. function onClear(e) {
  14454. cleared = true;
  14455. if (props.openOnClear) {
  14456. menu.value = true;
  14457. }
  14458. }
  14459. function onMousedownControl() {
  14460. if (menuDisabled.value) return;
  14461. menu.value = true;
  14462. }
  14463. function onMousedownMenuIcon(e) {
  14464. if (menuDisabled.value) return;
  14465. if (isFocused.value) {
  14466. e.preventDefault();
  14467. e.stopPropagation();
  14468. }
  14469. menu.value = !menu.value;
  14470. }
  14471. function onKeydown(e) {
  14472. if (props.readonly || form?.isReadonly.value) return;
  14473. const selectionStart = vTextFieldRef.value.selectionStart;
  14474. const length = selected.value.length;
  14475. if (selectionIndex.value > -1 || ['Enter', 'ArrowDown', 'ArrowUp'].includes(e.key)) {
  14476. e.preventDefault();
  14477. }
  14478. if (['Enter', 'ArrowDown'].includes(e.key)) {
  14479. menu.value = true;
  14480. }
  14481. if (['Escape'].includes(e.key)) {
  14482. menu.value = false;
  14483. }
  14484. if (['Enter', 'Escape', 'Tab'].includes(e.key)) {
  14485. if (highlightFirst.value && ['Enter', 'Tab'].includes(e.key)) {
  14486. select(filteredItems.value[0]);
  14487. }
  14488. isPristine.value = true;
  14489. }
  14490. if (e.key === 'ArrowDown' && highlightFirst.value) {
  14491. listRef.value?.focus('next');
  14492. }
  14493. if (!props.multiple) return;
  14494. if (['Backspace', 'Delete'].includes(e.key)) {
  14495. if (selectionIndex.value < 0) {
  14496. if (e.key === 'Backspace' && !search.value) {
  14497. selectionIndex.value = length - 1;
  14498. }
  14499. return;
  14500. }
  14501. const originalSelectionIndex = selectionIndex.value;
  14502. if (selection.value) select(selection.value);
  14503. selectionIndex.value = originalSelectionIndex >= length - 1 ? length - 2 : originalSelectionIndex;
  14504. }
  14505. if (e.key === 'ArrowLeft') {
  14506. if (selectionIndex.value < 0 && selectionStart > 0) return;
  14507. const prev = selectionIndex.value > -1 ? selectionIndex.value - 1 : length - 1;
  14508. if (selections.value[prev]) {
  14509. selectionIndex.value = prev;
  14510. } else {
  14511. selectionIndex.value = -1;
  14512. vTextFieldRef.value.setSelectionRange(search.value.length, search.value.length);
  14513. }
  14514. }
  14515. if (e.key === 'ArrowRight') {
  14516. if (selectionIndex.value < 0) return;
  14517. const next = selectionIndex.value + 1;
  14518. if (selections.value[next]) {
  14519. selectionIndex.value = next;
  14520. } else {
  14521. selectionIndex.value = -1;
  14522. vTextFieldRef.value.setSelectionRange(0, 0);
  14523. }
  14524. }
  14525. if (e.key === 'Enter' && search.value) {
  14526. select(transformItem$1(props, search.value));
  14527. search.value = '';
  14528. }
  14529. }
  14530. function onAfterLeave() {
  14531. if (isFocused.value) {
  14532. isPristine.value = true;
  14533. vTextFieldRef.value?.focus();
  14534. }
  14535. }
  14536. function select(item) {
  14537. if (props.multiple) {
  14538. const index = selected.value.findIndex(selection => props.valueComparator(selection, item.value));
  14539. if (index === -1) {
  14540. model.value = [...model.value, item];
  14541. } else {
  14542. const value = [...model.value];
  14543. value.splice(index, 1);
  14544. model.value = value;
  14545. }
  14546. search.value = '';
  14547. } else {
  14548. model.value = [item];
  14549. _search.value = item.title;
  14550. // watch for search watcher to trigger
  14551. vue.nextTick(() => {
  14552. menu.value = false;
  14553. isPristine.value = true;
  14554. });
  14555. }
  14556. }
  14557. function onFocusin(e) {
  14558. isFocused.value = true;
  14559. setTimeout(() => {
  14560. listHasFocus.value = true;
  14561. });
  14562. }
  14563. function onFocusout(e) {
  14564. listHasFocus.value = false;
  14565. }
  14566. function onUpdateModelValue(v) {
  14567. if (v == null || v === '' && !props.multiple) model.value = [];
  14568. }
  14569. vue.watch(filteredItems, val => {
  14570. if (!val.length && props.hideNoData) menu.value = false;
  14571. });
  14572. vue.watch(isFocused, (val, oldVal) => {
  14573. if (val || val === oldVal) return;
  14574. selectionIndex.value = -1;
  14575. menu.value = false;
  14576. if (highlightFirst.value && !listHasFocus.value && !selections.value.some(_ref2 => {
  14577. let {
  14578. value
  14579. } = _ref2;
  14580. return value === displayItems.value[0].value;
  14581. })) {
  14582. select(displayItems.value[0]);
  14583. } else if (props.multiple && search.value) {
  14584. model.value = [...model.value, transformItem$1(props, search.value)];
  14585. search.value = '';
  14586. }
  14587. });
  14588. useRender(() => {
  14589. const hasChips = !!(props.chips || slots.chip);
  14590. const hasList = !!(!props.hideNoData || displayItems.value.length || slots['prepend-item'] || slots['append-item'] || slots['no-data']);
  14591. const isDirty = model.value.length > 0;
  14592. const [textFieldProps] = VTextField.filterProps(props);
  14593. return vue.createVNode(VTextField, vue.mergeProps({
  14594. "ref": vTextFieldRef
  14595. }, textFieldProps, {
  14596. "modelValue": search.value,
  14597. "onUpdate:modelValue": [$event => search.value = $event, onUpdateModelValue],
  14598. "focused": isFocused.value,
  14599. "onUpdate:focused": $event => isFocused.value = $event,
  14600. "validationValue": model.externalValue,
  14601. "dirty": isDirty,
  14602. "class": ['v-combobox', {
  14603. 'v-combobox--active-menu': menu.value,
  14604. 'v-combobox--chips': !!props.chips,
  14605. 'v-combobox--selection-slot': !!slots.selection,
  14606. 'v-combobox--selecting-index': selectionIndex.value > -1,
  14607. [`v-combobox--${props.multiple ? 'multiple' : 'single'}`]: true
  14608. }, props.class],
  14609. "style": props.style,
  14610. "readonly": props.readonly,
  14611. "placeholder": isDirty ? undefined : props.placeholder,
  14612. "onClick:clear": onClear,
  14613. "onMousedown:control": onMousedownControl,
  14614. "onKeydown": onKeydown
  14615. }), {
  14616. ...slots,
  14617. default: () => vue.createVNode(vue.Fragment, null, [vue.createVNode(VMenu, vue.mergeProps({
  14618. "ref": vMenuRef,
  14619. "modelValue": menu.value,
  14620. "onUpdate:modelValue": $event => menu.value = $event,
  14621. "activator": "parent",
  14622. "contentClass": "v-combobox__content",
  14623. "disabled": menuDisabled.value,
  14624. "eager": props.eager,
  14625. "maxHeight": 310,
  14626. "openOnClick": false,
  14627. "closeOnContentClick": false,
  14628. "transition": props.transition,
  14629. "onAfterLeave": onAfterLeave
  14630. }, props.menuProps), {
  14631. default: () => [hasList && vue.createVNode(VList, {
  14632. "ref": listRef,
  14633. "selected": selected.value,
  14634. "selectStrategy": props.multiple ? 'independent' : 'single-independent',
  14635. "onMousedown": e => e.preventDefault(),
  14636. "onKeydown": onListKeydown,
  14637. "onFocusin": onFocusin,
  14638. "onFocusout": onFocusout,
  14639. "onScrollPassive": onListScroll,
  14640. "tabindex": "-1",
  14641. "color": props.itemColor ?? props.color
  14642. }, {
  14643. default: () => [slots['prepend-item']?.(), !displayItems.value.length && !props.hideNoData && (slots['no-data']?.() ?? vue.createVNode(VListItem, {
  14644. "title": t(props.noDataText)
  14645. }, null)), vue.createVNode(VVirtualScroll, {
  14646. "renderless": true,
  14647. "items": displayItems.value
  14648. }, {
  14649. default: _ref3 => {
  14650. let {
  14651. item,
  14652. index,
  14653. itemRef
  14654. } = _ref3;
  14655. const itemProps = vue.mergeProps(item.props, {
  14656. ref: itemRef,
  14657. key: index,
  14658. active: highlightFirst.value && index === 0 ? true : undefined,
  14659. onClick: () => select(item)
  14660. });
  14661. return slots.item?.({
  14662. item,
  14663. index,
  14664. props: itemProps
  14665. }) ?? vue.createVNode(VListItem, itemProps, {
  14666. prepend: _ref4 => {
  14667. let {
  14668. isSelected
  14669. } = _ref4;
  14670. return vue.createVNode(vue.Fragment, null, [props.multiple && !props.hideSelected ? vue.createVNode(VCheckboxBtn, {
  14671. "key": item.value,
  14672. "modelValue": isSelected,
  14673. "ripple": false,
  14674. "tabindex": "-1"
  14675. }, null) : undefined, item.props.prependIcon && vue.createVNode(VIcon, {
  14676. "icon": item.props.prependIcon
  14677. }, null)]);
  14678. },
  14679. title: () => {
  14680. return isPristine.value ? item.title : highlightResult(item.title, getMatches(item)?.title, search.value?.length ?? 0);
  14681. }
  14682. });
  14683. }
  14684. }), slots['append-item']?.()]
  14685. })]
  14686. }), selections.value.map((item, index) => {
  14687. function onChipClose(e) {
  14688. e.stopPropagation();
  14689. e.preventDefault();
  14690. select(item);
  14691. }
  14692. const slotProps = {
  14693. 'onClick:close': onChipClose,
  14694. onMousedown(e) {
  14695. e.preventDefault();
  14696. e.stopPropagation();
  14697. },
  14698. modelValue: true,
  14699. 'onUpdate:modelValue': undefined
  14700. };
  14701. return vue.createVNode("div", {
  14702. "key": item.value,
  14703. "class": ['v-combobox__selection', index === selectionIndex.value && ['v-combobox__selection--selected', textColorClasses.value]],
  14704. "style": index === selectionIndex.value ? textColorStyles.value : {}
  14705. }, [hasChips ? !slots.chip ? vue.createVNode(VChip, vue.mergeProps({
  14706. "key": "chip",
  14707. "closable": props.closableChips,
  14708. "size": "small",
  14709. "text": item.title
  14710. }, slotProps), null) : vue.createVNode(VDefaultsProvider, {
  14711. "key": "chip-defaults",
  14712. "defaults": {
  14713. VChip: {
  14714. closable: props.closableChips,
  14715. size: 'small',
  14716. text: item.title
  14717. }
  14718. }
  14719. }, {
  14720. default: () => [slots.chip?.({
  14721. item,
  14722. index,
  14723. props: slotProps
  14724. })]
  14725. }) : slots.selection?.({
  14726. item,
  14727. index
  14728. }) ?? vue.createVNode("span", {
  14729. "class": "v-combobox__selection-text"
  14730. }, [item.title, props.multiple && index < selections.value.length - 1 && vue.createVNode("span", {
  14731. "class": "v-combobox__selection-comma"
  14732. }, [vue.createTextVNode(",")])])]);
  14733. })]),
  14734. 'append-inner': function () {
  14735. for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) {
  14736. args[_key] = arguments[_key];
  14737. }
  14738. return vue.createVNode(vue.Fragment, null, [slots['append-inner']?.(...args), (!props.hideNoData || props.items.length) && props.menuIcon ? vue.createVNode(VIcon, {
  14739. "class": "v-combobox__menu-icon",
  14740. "icon": props.menuIcon,
  14741. "onMousedown": onMousedownMenuIcon,
  14742. "onClick": noop
  14743. }, null) : undefined]);
  14744. }
  14745. });
  14746. });
  14747. return forwardRefs({
  14748. isFocused,
  14749. isPristine,
  14750. menu,
  14751. search,
  14752. selectionIndex,
  14753. filteredItems,
  14754. select
  14755. }, vTextFieldRef);
  14756. }
  14757. });
  14758. // Types
  14759. const makeVDialogProps = propsFactory({
  14760. fullscreen: Boolean,
  14761. retainFocus: {
  14762. type: Boolean,
  14763. default: true
  14764. },
  14765. scrollable: Boolean,
  14766. ...makeVOverlayProps({
  14767. origin: 'center center',
  14768. scrollStrategy: 'block',
  14769. transition: {
  14770. component: VDialogTransition
  14771. },
  14772. zIndex: 2400
  14773. })
  14774. }, 'VDialog');
  14775. const VDialog = genericComponent()({
  14776. name: 'VDialog',
  14777. props: makeVDialogProps(),
  14778. emits: {
  14779. 'update:modelValue': value => true
  14780. },
  14781. setup(props, _ref) {
  14782. let {
  14783. slots
  14784. } = _ref;
  14785. const isActive = useProxiedModel(props, 'modelValue');
  14786. const {
  14787. scopeId
  14788. } = useScopeId();
  14789. const overlay = vue.ref();
  14790. function onFocusin(e) {
  14791. const before = e.relatedTarget;
  14792. const after = e.target;
  14793. if (before !== after && overlay.value?.contentEl &&
  14794. // We're the topmost dialog
  14795. overlay.value?.globalTop &&
  14796. // It isn't the document or the dialog body
  14797. ![document, overlay.value.contentEl].includes(after) &&
  14798. // It isn't inside the dialog body
  14799. !overlay.value.contentEl.contains(after)) {
  14800. const focusable = focusableChildren(overlay.value.contentEl);
  14801. if (!focusable.length) return;
  14802. const firstElement = focusable[0];
  14803. const lastElement = focusable[focusable.length - 1];
  14804. if (before === firstElement) {
  14805. lastElement.focus();
  14806. } else {
  14807. firstElement.focus();
  14808. }
  14809. }
  14810. }
  14811. if (IN_BROWSER) {
  14812. vue.watch(() => isActive.value && props.retainFocus, val => {
  14813. val ? document.addEventListener('focusin', onFocusin) : document.removeEventListener('focusin', onFocusin);
  14814. }, {
  14815. immediate: true
  14816. });
  14817. }
  14818. vue.watch(isActive, async val => {
  14819. await vue.nextTick();
  14820. if (val) {
  14821. overlay.value.contentEl?.focus({
  14822. preventScroll: true
  14823. });
  14824. } else {
  14825. overlay.value.activatorEl?.focus({
  14826. preventScroll: true
  14827. });
  14828. }
  14829. });
  14830. const activatorProps = vue.computed(() => vue.mergeProps({
  14831. 'aria-haspopup': 'dialog',
  14832. 'aria-expanded': String(isActive.value)
  14833. }, props.activatorProps));
  14834. useRender(() => {
  14835. const [overlayProps] = VOverlay.filterProps(props);
  14836. return vue.createVNode(VOverlay, vue.mergeProps({
  14837. "ref": overlay,
  14838. "class": ['v-dialog', {
  14839. 'v-dialog--fullscreen': props.fullscreen,
  14840. 'v-dialog--scrollable': props.scrollable
  14841. }, props.class],
  14842. "style": props.style
  14843. }, overlayProps, {
  14844. "modelValue": isActive.value,
  14845. "onUpdate:modelValue": $event => isActive.value = $event,
  14846. "aria-modal": "true",
  14847. "activatorProps": activatorProps.value,
  14848. "role": "dialog"
  14849. }, scopeId), {
  14850. activator: slots.activator,
  14851. default: function () {
  14852. for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) {
  14853. args[_key] = arguments[_key];
  14854. }
  14855. return vue.createVNode(VDefaultsProvider, {
  14856. "root": "VDialog"
  14857. }, {
  14858. default: () => [slots.default?.(...args)]
  14859. });
  14860. }
  14861. });
  14862. });
  14863. return forwardRefs({}, overlay);
  14864. }
  14865. });
  14866. // Types
  14867. const VExpansionPanelSymbol = Symbol.for('vuetify:v-expansion-panel');
  14868. const allowedVariants = ['default', 'accordion', 'inset', 'popout'];
  14869. const makeVExpansionPanelsProps = propsFactory({
  14870. color: String,
  14871. variant: {
  14872. type: String,
  14873. default: 'default',
  14874. validator: v => allowedVariants.includes(v)
  14875. },
  14876. readonly: Boolean,
  14877. ...makeComponentProps(),
  14878. ...makeGroupProps(),
  14879. ...makeTagProps(),
  14880. ...makeThemeProps()
  14881. }, 'VExpansionPanels');
  14882. const VExpansionPanels = genericComponent()({
  14883. name: 'VExpansionPanels',
  14884. props: makeVExpansionPanelsProps(),
  14885. emits: {
  14886. 'update:modelValue': val => true
  14887. },
  14888. setup(props, _ref) {
  14889. let {
  14890. slots
  14891. } = _ref;
  14892. useGroup(props, VExpansionPanelSymbol);
  14893. const {
  14894. themeClasses
  14895. } = provideTheme(props);
  14896. const variantClass = vue.computed(() => props.variant && `v-expansion-panels--variant-${props.variant}`);
  14897. provideDefaults({
  14898. VExpansionPanel: {
  14899. color: vue.toRef(props, 'color')
  14900. },
  14901. VExpansionPanelTitle: {
  14902. readonly: vue.toRef(props, 'readonly')
  14903. }
  14904. });
  14905. useRender(() => vue.createVNode(props.tag, {
  14906. "class": ['v-expansion-panels', themeClasses.value, variantClass.value, props.class],
  14907. "style": props.style
  14908. }, slots));
  14909. return {};
  14910. }
  14911. });
  14912. const makeVExpansionPanelTextProps = propsFactory({
  14913. ...makeComponentProps(),
  14914. ...makeLazyProps()
  14915. }, 'VExpansionPanelText');
  14916. const VExpansionPanelText = genericComponent()({
  14917. name: 'VExpansionPanelText',
  14918. props: makeVExpansionPanelTextProps(),
  14919. setup(props, _ref) {
  14920. let {
  14921. slots
  14922. } = _ref;
  14923. const expansionPanel = vue.inject(VExpansionPanelSymbol);
  14924. if (!expansionPanel) throw new Error('[Vuetify] v-expansion-panel-text needs to be placed inside v-expansion-panel');
  14925. const {
  14926. hasContent,
  14927. onAfterLeave
  14928. } = useLazy(props, expansionPanel.isSelected);
  14929. useRender(() => vue.createVNode(VExpandTransition, {
  14930. "onAfterLeave": onAfterLeave
  14931. }, {
  14932. default: () => [vue.withDirectives(vue.createVNode("div", {
  14933. "class": ['v-expansion-panel-text', props.class],
  14934. "style": props.style
  14935. }, [slots.default && hasContent.value && vue.createVNode("div", {
  14936. "class": "v-expansion-panel-text__wrapper"
  14937. }, [slots.default?.()])]), [[vue.vShow, expansionPanel.isSelected.value]])]
  14938. }));
  14939. return {};
  14940. }
  14941. });
  14942. // Types
  14943. const makeVExpansionPanelTitleProps = propsFactory({
  14944. color: String,
  14945. expandIcon: {
  14946. type: IconValue,
  14947. default: '$expand'
  14948. },
  14949. collapseIcon: {
  14950. type: IconValue,
  14951. default: '$collapse'
  14952. },
  14953. hideActions: Boolean,
  14954. ripple: {
  14955. type: [Boolean, Object],
  14956. default: false
  14957. },
  14958. readonly: Boolean,
  14959. ...makeComponentProps()
  14960. }, 'VExpansionPanelTitle');
  14961. const VExpansionPanelTitle = genericComponent()({
  14962. name: 'VExpansionPanelTitle',
  14963. directives: {
  14964. Ripple
  14965. },
  14966. props: makeVExpansionPanelTitleProps(),
  14967. setup(props, _ref) {
  14968. let {
  14969. slots
  14970. } = _ref;
  14971. const expansionPanel = vue.inject(VExpansionPanelSymbol);
  14972. if (!expansionPanel) throw new Error('[Vuetify] v-expansion-panel-title needs to be placed inside v-expansion-panel');
  14973. const {
  14974. backgroundColorClasses,
  14975. backgroundColorStyles
  14976. } = useBackgroundColor(props, 'color');
  14977. const slotProps = vue.computed(() => ({
  14978. collapseIcon: props.collapseIcon,
  14979. disabled: expansionPanel.disabled.value,
  14980. expanded: expansionPanel.isSelected.value,
  14981. expandIcon: props.expandIcon,
  14982. readonly: props.readonly
  14983. }));
  14984. useRender(() => vue.withDirectives(vue.createVNode("button", {
  14985. "class": ['v-expansion-panel-title', {
  14986. 'v-expansion-panel-title--active': expansionPanel.isSelected.value
  14987. }, backgroundColorClasses.value, props.class],
  14988. "style": [backgroundColorStyles.value, props.style],
  14989. "type": "button",
  14990. "tabindex": expansionPanel.disabled.value ? -1 : undefined,
  14991. "disabled": expansionPanel.disabled.value,
  14992. "aria-expanded": expansionPanel.isSelected.value,
  14993. "onClick": !props.readonly ? expansionPanel.toggle : undefined
  14994. }, [vue.createVNode("span", {
  14995. "class": "v-expansion-panel-title__overlay"
  14996. }, null), slots.default?.(slotProps.value), !props.hideActions && vue.createVNode("span", {
  14997. "class": "v-expansion-panel-title__icon"
  14998. }, [slots.actions ? slots.actions(slotProps.value) : vue.createVNode(VIcon, {
  14999. "icon": expansionPanel.isSelected.value ? props.collapseIcon : props.expandIcon
  15000. }, null)])]), [[vue.resolveDirective("ripple"), props.ripple]]));
  15001. return {};
  15002. }
  15003. });
  15004. const makeVExpansionPanelProps = propsFactory({
  15005. title: String,
  15006. text: String,
  15007. bgColor: String,
  15008. ...makeComponentProps(),
  15009. ...makeElevationProps(),
  15010. ...makeGroupItemProps(),
  15011. ...makeLazyProps(),
  15012. ...makeRoundedProps(),
  15013. ...makeTagProps(),
  15014. ...makeVExpansionPanelTitleProps()
  15015. }, 'VExpansionPanel');
  15016. const VExpansionPanel = genericComponent()({
  15017. name: 'VExpansionPanel',
  15018. props: makeVExpansionPanelProps(),
  15019. emits: {
  15020. 'group:selected': val => true
  15021. },
  15022. setup(props, _ref) {
  15023. let {
  15024. slots
  15025. } = _ref;
  15026. const groupItem = useGroupItem(props, VExpansionPanelSymbol);
  15027. const {
  15028. backgroundColorClasses,
  15029. backgroundColorStyles
  15030. } = useBackgroundColor(props, 'bgColor');
  15031. const {
  15032. elevationClasses
  15033. } = useElevation(props);
  15034. const {
  15035. roundedClasses
  15036. } = useRounded(props);
  15037. const isDisabled = vue.computed(() => groupItem?.disabled.value || props.disabled);
  15038. const selectedIndices = vue.computed(() => groupItem.group.items.value.reduce((arr, item, index) => {
  15039. if (groupItem.group.selected.value.includes(item.id)) arr.push(index);
  15040. return arr;
  15041. }, []));
  15042. const isBeforeSelected = vue.computed(() => {
  15043. const index = groupItem.group.items.value.findIndex(item => item.id === groupItem.id);
  15044. return !groupItem.isSelected.value && selectedIndices.value.some(selectedIndex => selectedIndex - index === 1);
  15045. });
  15046. const isAfterSelected = vue.computed(() => {
  15047. const index = groupItem.group.items.value.findIndex(item => item.id === groupItem.id);
  15048. return !groupItem.isSelected.value && selectedIndices.value.some(selectedIndex => selectedIndex - index === -1);
  15049. });
  15050. vue.provide(VExpansionPanelSymbol, groupItem);
  15051. provideDefaults({
  15052. VExpansionPanelText: {
  15053. eager: vue.toRef(props, 'eager')
  15054. }
  15055. });
  15056. useRender(() => {
  15057. const hasText = !!(slots.text || props.text);
  15058. const hasTitle = !!(slots.title || props.title);
  15059. return vue.createVNode(props.tag, {
  15060. "class": ['v-expansion-panel', {
  15061. 'v-expansion-panel--active': groupItem.isSelected.value,
  15062. 'v-expansion-panel--before-active': isBeforeSelected.value,
  15063. 'v-expansion-panel--after-active': isAfterSelected.value,
  15064. 'v-expansion-panel--disabled': isDisabled.value
  15065. }, roundedClasses.value, backgroundColorClasses.value, props.class],
  15066. "style": [backgroundColorStyles.value, props.style]
  15067. }, {
  15068. default: () => [vue.createVNode("div", {
  15069. "class": ['v-expansion-panel__shadow', ...elevationClasses.value]
  15070. }, null), hasTitle && vue.createVNode(VExpansionPanelTitle, {
  15071. "key": "title",
  15072. "collapseIcon": props.collapseIcon,
  15073. "color": props.color,
  15074. "expandIcon": props.expandIcon,
  15075. "hideActions": props.hideActions,
  15076. "ripple": props.ripple
  15077. }, {
  15078. default: () => [slots.title ? slots.title() : props.title]
  15079. }), hasText && vue.createVNode(VExpansionPanelText, {
  15080. "key": "text"
  15081. }, {
  15082. default: () => [slots.text ? slots.text() : props.text]
  15083. }), slots.default?.()]
  15084. });
  15085. });
  15086. return {};
  15087. }
  15088. });
  15089. // Types
  15090. const makeVFileInputProps = propsFactory({
  15091. chips: Boolean,
  15092. counter: Boolean,
  15093. counterSizeString: {
  15094. type: String,
  15095. default: '$vuetify.fileInput.counterSize'
  15096. },
  15097. counterString: {
  15098. type: String,
  15099. default: '$vuetify.fileInput.counter'
  15100. },
  15101. multiple: Boolean,
  15102. showSize: {
  15103. type: [Boolean, Number],
  15104. default: false,
  15105. validator: v => {
  15106. return typeof v === 'boolean' || [1000, 1024].includes(v);
  15107. }
  15108. },
  15109. ...makeVInputProps({
  15110. prependIcon: '$file'
  15111. }),
  15112. modelValue: {
  15113. type: Array,
  15114. default: () => [],
  15115. validator: val => {
  15116. return wrapInArray(val).every(v => v != null && typeof v === 'object');
  15117. }
  15118. },
  15119. ...makeVFieldProps({
  15120. clearable: true
  15121. })
  15122. }, 'VFileInput');
  15123. const VFileInput = genericComponent()({
  15124. name: 'VFileInput',
  15125. inheritAttrs: false,
  15126. props: makeVFileInputProps(),
  15127. emits: {
  15128. 'click:control': e => true,
  15129. 'mousedown:control': e => true,
  15130. 'update:focused': focused => true,
  15131. 'update:modelValue': files => true
  15132. },
  15133. setup(props, _ref) {
  15134. let {
  15135. attrs,
  15136. emit,
  15137. slots
  15138. } = _ref;
  15139. const {
  15140. t
  15141. } = useLocale();
  15142. const model = useProxiedModel(props, 'modelValue');
  15143. const {
  15144. isFocused,
  15145. focus,
  15146. blur
  15147. } = useFocus(props);
  15148. const base = vue.computed(() => typeof props.showSize !== 'boolean' ? props.showSize : undefined);
  15149. const totalBytes = vue.computed(() => (model.value ?? []).reduce((bytes, _ref2) => {
  15150. let {
  15151. size = 0
  15152. } = _ref2;
  15153. return bytes + size;
  15154. }, 0));
  15155. const totalBytesReadable = vue.computed(() => humanReadableFileSize(totalBytes.value, base.value));
  15156. const fileNames = vue.computed(() => (model.value ?? []).map(file => {
  15157. const {
  15158. name = '',
  15159. size = 0
  15160. } = file;
  15161. return !props.showSize ? name : `${name} (${humanReadableFileSize(size, base.value)})`;
  15162. }));
  15163. const counterValue = vue.computed(() => {
  15164. const fileCount = model.value?.length ?? 0;
  15165. if (props.showSize) return t(props.counterSizeString, fileCount, totalBytesReadable.value);else return t(props.counterString, fileCount);
  15166. });
  15167. const vInputRef = vue.ref();
  15168. const vFieldRef = vue.ref();
  15169. const inputRef = vue.ref();
  15170. const isActive = vue.computed(() => isFocused.value || props.active);
  15171. const isPlainOrUnderlined = vue.computed(() => ['plain', 'underlined'].includes(props.variant));
  15172. function onFocus() {
  15173. if (inputRef.value !== document.activeElement) {
  15174. inputRef.value?.focus();
  15175. }
  15176. if (!isFocused.value) focus();
  15177. }
  15178. function onClickPrepend(e) {
  15179. onControlClick(e);
  15180. }
  15181. function onControlMousedown(e) {
  15182. emit('mousedown:control', e);
  15183. }
  15184. function onControlClick(e) {
  15185. inputRef.value?.click();
  15186. emit('click:control', e);
  15187. }
  15188. function onClear(e) {
  15189. e.stopPropagation();
  15190. onFocus();
  15191. vue.nextTick(() => {
  15192. model.value = [];
  15193. callEvent(props['onClick:clear'], e);
  15194. });
  15195. }
  15196. vue.watch(model, newValue => {
  15197. const hasModelReset = !Array.isArray(newValue) || !newValue.length;
  15198. if (hasModelReset && inputRef.value) {
  15199. inputRef.value.value = '';
  15200. }
  15201. });
  15202. useRender(() => {
  15203. const hasCounter = !!(slots.counter || props.counter);
  15204. const hasDetails = !!(hasCounter || slots.details);
  15205. const [rootAttrs, inputAttrs] = filterInputAttrs(attrs);
  15206. const [{
  15207. modelValue: _,
  15208. ...inputProps
  15209. }] = VInput.filterProps(props);
  15210. const [fieldProps] = filterFieldProps(props);
  15211. return vue.createVNode(VInput, vue.mergeProps({
  15212. "ref": vInputRef,
  15213. "modelValue": model.value,
  15214. "onUpdate:modelValue": $event => model.value = $event,
  15215. "class": ['v-file-input', {
  15216. 'v-text-field--plain-underlined': isPlainOrUnderlined.value
  15217. }, props.class],
  15218. "style": props.style,
  15219. "onClick:prepend": onClickPrepend
  15220. }, rootAttrs, inputProps, {
  15221. "centerAffix": !isPlainOrUnderlined.value,
  15222. "focused": isFocused.value
  15223. }), {
  15224. ...slots,
  15225. default: _ref3 => {
  15226. let {
  15227. id,
  15228. isDisabled,
  15229. isDirty,
  15230. isReadonly,
  15231. isValid
  15232. } = _ref3;
  15233. return vue.createVNode(VField, vue.mergeProps({
  15234. "ref": vFieldRef,
  15235. "prepend-icon": props.prependIcon,
  15236. "onMousedown": onControlMousedown,
  15237. "onClick": onControlClick,
  15238. "onClick:clear": onClear,
  15239. "onClick:prependInner": props['onClick:prependInner'],
  15240. "onClick:appendInner": props['onClick:appendInner']
  15241. }, fieldProps, {
  15242. "id": id.value,
  15243. "active": isActive.value || isDirty.value,
  15244. "dirty": isDirty.value,
  15245. "disabled": isDisabled.value,
  15246. "focused": isFocused.value,
  15247. "error": isValid.value === false
  15248. }), {
  15249. ...slots,
  15250. default: _ref4 => {
  15251. let {
  15252. props: {
  15253. class: fieldClass,
  15254. ...slotProps
  15255. }
  15256. } = _ref4;
  15257. return vue.createVNode(vue.Fragment, null, [vue.createVNode("input", vue.mergeProps({
  15258. "ref": inputRef,
  15259. "type": "file",
  15260. "readonly": isReadonly.value,
  15261. "disabled": isDisabled.value,
  15262. "multiple": props.multiple,
  15263. "name": props.name,
  15264. "onClick": e => {
  15265. e.stopPropagation();
  15266. if (isReadonly.value) e.preventDefault();
  15267. onFocus();
  15268. },
  15269. "onChange": e => {
  15270. if (!e.target) return;
  15271. const target = e.target;
  15272. model.value = [...(target.files ?? [])];
  15273. },
  15274. "onFocus": onFocus,
  15275. "onBlur": blur
  15276. }, slotProps, inputAttrs), null), vue.createVNode("div", {
  15277. "class": fieldClass
  15278. }, [!!model.value?.length && (slots.selection ? slots.selection({
  15279. fileNames: fileNames.value,
  15280. totalBytes: totalBytes.value,
  15281. totalBytesReadable: totalBytesReadable.value
  15282. }) : props.chips ? fileNames.value.map(text => vue.createVNode(VChip, {
  15283. "key": text,
  15284. "size": "small",
  15285. "color": props.color
  15286. }, {
  15287. default: () => [text]
  15288. })) : fileNames.value.join(', '))])]);
  15289. }
  15290. });
  15291. },
  15292. 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, {
  15293. "active": !!model.value?.length,
  15294. "value": counterValue.value
  15295. }, slots.counter)])]) : undefined
  15296. });
  15297. });
  15298. return forwardRefs({}, vInputRef, vFieldRef, inputRef);
  15299. }
  15300. });
  15301. const makeVFooterProps = propsFactory({
  15302. app: Boolean,
  15303. color: String,
  15304. height: {
  15305. type: [Number, String],
  15306. default: 'auto'
  15307. },
  15308. ...makeBorderProps(),
  15309. ...makeComponentProps(),
  15310. ...makeElevationProps(),
  15311. ...makeLayoutItemProps(),
  15312. ...makeRoundedProps(),
  15313. ...makeTagProps({
  15314. tag: 'footer'
  15315. }),
  15316. ...makeThemeProps()
  15317. }, 'VFooter');
  15318. const VFooter = genericComponent()({
  15319. name: 'VFooter',
  15320. props: makeVFooterProps(),
  15321. setup(props, _ref) {
  15322. let {
  15323. slots
  15324. } = _ref;
  15325. const {
  15326. themeClasses
  15327. } = provideTheme(props);
  15328. const {
  15329. backgroundColorClasses,
  15330. backgroundColorStyles
  15331. } = useBackgroundColor(vue.toRef(props, 'color'));
  15332. const {
  15333. borderClasses
  15334. } = useBorder(props);
  15335. const {
  15336. elevationClasses
  15337. } = useElevation(props);
  15338. const {
  15339. roundedClasses
  15340. } = useRounded(props);
  15341. const autoHeight = vue.shallowRef(32);
  15342. const {
  15343. resizeRef
  15344. } = useResizeObserver(entries => {
  15345. if (!entries.length) return;
  15346. autoHeight.value = entries[0].target.clientHeight;
  15347. });
  15348. const height = vue.computed(() => props.height === 'auto' ? autoHeight.value : parseInt(props.height, 10));
  15349. const {
  15350. layoutItemStyles
  15351. } = useLayoutItem({
  15352. id: props.name,
  15353. order: vue.computed(() => parseInt(props.order, 10)),
  15354. position: vue.computed(() => 'bottom'),
  15355. layoutSize: height,
  15356. elementSize: vue.computed(() => props.height === 'auto' ? undefined : height.value),
  15357. active: vue.computed(() => props.app),
  15358. absolute: vue.toRef(props, 'absolute')
  15359. });
  15360. useRender(() => vue.createVNode(props.tag, {
  15361. "ref": resizeRef,
  15362. "class": ['v-footer', themeClasses.value, backgroundColorClasses.value, borderClasses.value, elevationClasses.value, roundedClasses.value, props.class],
  15363. "style": [backgroundColorStyles.value, props.app ? layoutItemStyles.value : {
  15364. height: convertToUnit(props.height)
  15365. }, props.style]
  15366. }, slots));
  15367. return {};
  15368. }
  15369. });
  15370. // Types
  15371. const makeVFormProps = propsFactory({
  15372. ...makeComponentProps(),
  15373. ...makeFormProps()
  15374. }, 'VForm');
  15375. const VForm = genericComponent()({
  15376. name: 'VForm',
  15377. props: makeVFormProps(),
  15378. emits: {
  15379. 'update:modelValue': val => true,
  15380. submit: e => true
  15381. },
  15382. setup(props, _ref) {
  15383. let {
  15384. slots,
  15385. emit
  15386. } = _ref;
  15387. const form = createForm(props);
  15388. const formRef = vue.ref();
  15389. function onReset(e) {
  15390. e.preventDefault();
  15391. form.reset();
  15392. }
  15393. function onSubmit(_e) {
  15394. const e = _e;
  15395. const ready = form.validate();
  15396. e.then = ready.then.bind(ready);
  15397. e.catch = ready.catch.bind(ready);
  15398. e.finally = ready.finally.bind(ready);
  15399. emit('submit', e);
  15400. if (!e.defaultPrevented) {
  15401. ready.then(_ref2 => {
  15402. let {
  15403. valid
  15404. } = _ref2;
  15405. if (valid) {
  15406. formRef.value?.submit();
  15407. }
  15408. });
  15409. }
  15410. e.preventDefault();
  15411. }
  15412. useRender(() => vue.createVNode("form", {
  15413. "ref": formRef,
  15414. "class": ['v-form', props.class],
  15415. "style": props.style,
  15416. "novalidate": true,
  15417. "onReset": onReset,
  15418. "onSubmit": onSubmit
  15419. }, [slots.default?.(form)]));
  15420. return forwardRefs(form, formRef);
  15421. }
  15422. });
  15423. const makeVContainerProps = propsFactory({
  15424. fluid: {
  15425. type: Boolean,
  15426. default: false
  15427. },
  15428. ...makeComponentProps(),
  15429. ...makeTagProps()
  15430. }, 'VContainer');
  15431. const VContainer = genericComponent()({
  15432. name: 'VContainer',
  15433. props: makeVContainerProps(),
  15434. setup(props, _ref) {
  15435. let {
  15436. slots
  15437. } = _ref;
  15438. const {
  15439. rtlClasses
  15440. } = useRtl();
  15441. useRender(() => vue.createVNode(props.tag, {
  15442. "class": ['v-container', {
  15443. 'v-container--fluid': props.fluid
  15444. }, rtlClasses.value, props.class],
  15445. "style": props.style
  15446. }, slots));
  15447. return {};
  15448. }
  15449. });
  15450. // Styles
  15451. // Types
  15452. const breakpointProps = (() => {
  15453. return breakpoints.reduce((props, val) => {
  15454. props[val] = {
  15455. type: [Boolean, String, Number],
  15456. default: false
  15457. };
  15458. return props;
  15459. }, {});
  15460. })();
  15461. const offsetProps = (() => {
  15462. return breakpoints.reduce((props, val) => {
  15463. const offsetKey = 'offset' + vue.capitalize(val);
  15464. props[offsetKey] = {
  15465. type: [String, Number],
  15466. default: null
  15467. };
  15468. return props;
  15469. }, {});
  15470. })();
  15471. const orderProps = (() => {
  15472. return breakpoints.reduce((props, val) => {
  15473. const orderKey = 'order' + vue.capitalize(val);
  15474. props[orderKey] = {
  15475. type: [String, Number],
  15476. default: null
  15477. };
  15478. return props;
  15479. }, {});
  15480. })();
  15481. const propMap$1 = {
  15482. col: Object.keys(breakpointProps),
  15483. offset: Object.keys(offsetProps),
  15484. order: Object.keys(orderProps)
  15485. };
  15486. function breakpointClass$1(type, prop, val) {
  15487. let className = type;
  15488. if (val == null || val === false) {
  15489. return undefined;
  15490. }
  15491. if (prop) {
  15492. const breakpoint = prop.replace(type, '');
  15493. className += `-${breakpoint}`;
  15494. }
  15495. if (type === 'col') {
  15496. className = 'v-' + className;
  15497. }
  15498. // Handling the boolean style prop when accepting [Boolean, String, Number]
  15499. // means Vue will not convert <v-col sm></v-col> to sm: true for us.
  15500. // Since the default is false, an empty string indicates the prop's presence.
  15501. if (type === 'col' && (val === '' || val === true)) {
  15502. // .v-col-md
  15503. return className.toLowerCase();
  15504. }
  15505. // .order-md-6
  15506. className += `-${val}`;
  15507. return className.toLowerCase();
  15508. }
  15509. const ALIGN_SELF_VALUES = ['auto', 'start', 'end', 'center', 'baseline', 'stretch'];
  15510. const makeVColProps = propsFactory({
  15511. cols: {
  15512. type: [Boolean, String, Number],
  15513. default: false
  15514. },
  15515. ...breakpointProps,
  15516. offset: {
  15517. type: [String, Number],
  15518. default: null
  15519. },
  15520. ...offsetProps,
  15521. order: {
  15522. type: [String, Number],
  15523. default: null
  15524. },
  15525. ...orderProps,
  15526. alignSelf: {
  15527. type: String,
  15528. default: null,
  15529. validator: str => ALIGN_SELF_VALUES.includes(str)
  15530. },
  15531. ...makeComponentProps(),
  15532. ...makeTagProps()
  15533. }, 'VCol');
  15534. const VCol = genericComponent()({
  15535. name: 'VCol',
  15536. props: makeVColProps(),
  15537. setup(props, _ref) {
  15538. let {
  15539. slots
  15540. } = _ref;
  15541. const classes = vue.computed(() => {
  15542. const classList = [];
  15543. // Loop through `col`, `offset`, `order` breakpoint props
  15544. let type;
  15545. for (type in propMap$1) {
  15546. propMap$1[type].forEach(prop => {
  15547. const value = props[prop];
  15548. const className = breakpointClass$1(type, prop, value);
  15549. if (className) classList.push(className);
  15550. });
  15551. }
  15552. const hasColClasses = classList.some(className => className.startsWith('v-col-'));
  15553. classList.push({
  15554. // Default to .v-col if no other col-{bp}-* classes generated nor `cols` specified.
  15555. 'v-col': !hasColClasses || !props.cols,
  15556. [`v-col-${props.cols}`]: props.cols,
  15557. [`offset-${props.offset}`]: props.offset,
  15558. [`order-${props.order}`]: props.order,
  15559. [`align-self-${props.alignSelf}`]: props.alignSelf
  15560. });
  15561. return classList;
  15562. });
  15563. return () => vue.h(props.tag, {
  15564. class: [classes.value, props.class],
  15565. style: props.style
  15566. }, slots.default?.());
  15567. }
  15568. });
  15569. // Styles
  15570. // Types
  15571. const ALIGNMENT = ['start', 'end', 'center'];
  15572. const SPACE = ['space-between', 'space-around', 'space-evenly'];
  15573. function makeRowProps(prefix, def) {
  15574. return breakpoints.reduce((props, val) => {
  15575. const prefixKey = prefix + vue.capitalize(val);
  15576. props[prefixKey] = def();
  15577. return props;
  15578. }, {});
  15579. }
  15580. const ALIGN_VALUES = [...ALIGNMENT, 'baseline', 'stretch'];
  15581. const alignValidator = str => ALIGN_VALUES.includes(str);
  15582. const alignProps = makeRowProps('align', () => ({
  15583. type: String,
  15584. default: null,
  15585. validator: alignValidator
  15586. }));
  15587. const JUSTIFY_VALUES = [...ALIGNMENT, ...SPACE];
  15588. const justifyValidator = str => JUSTIFY_VALUES.includes(str);
  15589. const justifyProps = makeRowProps('justify', () => ({
  15590. type: String,
  15591. default: null,
  15592. validator: justifyValidator
  15593. }));
  15594. const ALIGN_CONTENT_VALUES = [...ALIGNMENT, ...SPACE, 'stretch'];
  15595. const alignContentValidator = str => ALIGN_CONTENT_VALUES.includes(str);
  15596. const alignContentProps = makeRowProps('alignContent', () => ({
  15597. type: String,
  15598. default: null,
  15599. validator: alignContentValidator
  15600. }));
  15601. const propMap = {
  15602. align: Object.keys(alignProps),
  15603. justify: Object.keys(justifyProps),
  15604. alignContent: Object.keys(alignContentProps)
  15605. };
  15606. const classMap = {
  15607. align: 'align',
  15608. justify: 'justify',
  15609. alignContent: 'align-content'
  15610. };
  15611. function breakpointClass(type, prop, val) {
  15612. let className = classMap[type];
  15613. if (val == null) {
  15614. return undefined;
  15615. }
  15616. if (prop) {
  15617. // alignSm -> Sm
  15618. const breakpoint = prop.replace(type, '');
  15619. className += `-${breakpoint}`;
  15620. }
  15621. // .align-items-sm-center
  15622. className += `-${val}`;
  15623. return className.toLowerCase();
  15624. }
  15625. const makeVRowProps = propsFactory({
  15626. dense: Boolean,
  15627. noGutters: Boolean,
  15628. align: {
  15629. type: String,
  15630. default: null,
  15631. validator: alignValidator
  15632. },
  15633. ...alignProps,
  15634. justify: {
  15635. type: String,
  15636. default: null,
  15637. validator: justifyValidator
  15638. },
  15639. ...justifyProps,
  15640. alignContent: {
  15641. type: String,
  15642. default: null,
  15643. validator: alignContentValidator
  15644. },
  15645. ...alignContentProps,
  15646. ...makeComponentProps(),
  15647. ...makeTagProps()
  15648. }, 'VRow');
  15649. const VRow = genericComponent()({
  15650. name: 'VRow',
  15651. props: makeVRowProps(),
  15652. setup(props, _ref) {
  15653. let {
  15654. slots
  15655. } = _ref;
  15656. const classes = vue.computed(() => {
  15657. const classList = [];
  15658. // Loop through `align`, `justify`, `alignContent` breakpoint props
  15659. let type;
  15660. for (type in propMap) {
  15661. propMap[type].forEach(prop => {
  15662. const value = props[prop];
  15663. const className = breakpointClass(type, prop, value);
  15664. if (className) classList.push(className);
  15665. });
  15666. }
  15667. classList.push({
  15668. 'v-row--no-gutters': props.noGutters,
  15669. 'v-row--dense': props.dense,
  15670. [`align-${props.align}`]: props.align,
  15671. [`justify-${props.justify}`]: props.justify,
  15672. [`align-content-${props.alignContent}`]: props.alignContent
  15673. });
  15674. return classList;
  15675. });
  15676. return () => vue.h(props.tag, {
  15677. class: ['v-row', classes.value, props.class],
  15678. style: props.style
  15679. }, slots.default?.());
  15680. }
  15681. });
  15682. // Utilities
  15683. const VSpacer = createSimpleFunctional('flex-grow-1', 'div', 'VSpacer');
  15684. // Composables
  15685. const makeVHoverProps = propsFactory({
  15686. disabled: Boolean,
  15687. modelValue: {
  15688. type: Boolean,
  15689. default: undefined
  15690. },
  15691. ...makeDelayProps()
  15692. }, 'VHover');
  15693. const VHover = genericComponent()({
  15694. name: 'VHover',
  15695. props: makeVHoverProps(),
  15696. emits: {
  15697. 'update:modelValue': value => true
  15698. },
  15699. setup(props, _ref) {
  15700. let {
  15701. slots
  15702. } = _ref;
  15703. const isHovering = useProxiedModel(props, 'modelValue');
  15704. const {
  15705. runOpenDelay,
  15706. runCloseDelay
  15707. } = useDelay(props, value => !props.disabled && (isHovering.value = value));
  15708. return () => slots.default?.({
  15709. isHovering: isHovering.value,
  15710. props: {
  15711. onMouseenter: runOpenDelay,
  15712. onMouseleave: runCloseDelay
  15713. }
  15714. });
  15715. }
  15716. });
  15717. const VItemGroupSymbol = Symbol.for('vuetify:v-item-group');
  15718. const makeVItemGroupProps = propsFactory({
  15719. ...makeComponentProps(),
  15720. ...makeGroupProps({
  15721. selectedClass: 'v-item--selected'
  15722. }),
  15723. ...makeTagProps(),
  15724. ...makeThemeProps()
  15725. }, 'VItemGroup');
  15726. const VItemGroup = genericComponent()({
  15727. name: 'VItemGroup',
  15728. props: makeVItemGroupProps(),
  15729. emits: {
  15730. 'update:modelValue': value => true
  15731. },
  15732. setup(props, _ref) {
  15733. let {
  15734. slots
  15735. } = _ref;
  15736. const {
  15737. themeClasses
  15738. } = provideTheme(props);
  15739. const {
  15740. isSelected,
  15741. select,
  15742. next,
  15743. prev,
  15744. selected
  15745. } = useGroup(props, VItemGroupSymbol);
  15746. return () => vue.createVNode(props.tag, {
  15747. "class": ['v-item-group', themeClasses.value, props.class],
  15748. "style": props.style
  15749. }, {
  15750. default: () => [slots.default?.({
  15751. isSelected,
  15752. select,
  15753. next,
  15754. prev,
  15755. selected: selected.value
  15756. })]
  15757. });
  15758. }
  15759. });
  15760. // Composables
  15761. const VItem = genericComponent()({
  15762. name: 'VItem',
  15763. props: makeGroupItemProps(),
  15764. emits: {
  15765. 'group:selected': val => true
  15766. },
  15767. setup(props, _ref) {
  15768. let {
  15769. slots
  15770. } = _ref;
  15771. const {
  15772. isSelected,
  15773. select,
  15774. toggle,
  15775. selectedClass,
  15776. value,
  15777. disabled
  15778. } = useGroupItem(props, VItemGroupSymbol);
  15779. return () => slots.default?.({
  15780. isSelected: isSelected.value,
  15781. selectedClass: selectedClass.value,
  15782. select,
  15783. toggle,
  15784. value: value.value,
  15785. disabled: disabled.value
  15786. });
  15787. }
  15788. });
  15789. // Styles
  15790. const VKbd = createSimpleFunctional('v-kbd');
  15791. const makeVLayoutProps = propsFactory({
  15792. ...makeComponentProps(),
  15793. ...makeLayoutProps()
  15794. }, 'VLayout');
  15795. const VLayout = genericComponent()({
  15796. name: 'VLayout',
  15797. props: makeVLayoutProps(),
  15798. setup(props, _ref) {
  15799. let {
  15800. slots
  15801. } = _ref;
  15802. const {
  15803. layoutClasses,
  15804. layoutStyles,
  15805. getLayoutItem,
  15806. items,
  15807. layoutRef
  15808. } = createLayout(props);
  15809. useRender(() => vue.createVNode("div", {
  15810. "ref": layoutRef,
  15811. "class": [layoutClasses.value, props.class],
  15812. "style": [layoutStyles.value, props.style]
  15813. }, [slots.default?.()]));
  15814. return {
  15815. getLayoutItem,
  15816. items
  15817. };
  15818. }
  15819. });
  15820. // Types
  15821. const makeVLayoutItemProps = propsFactory({
  15822. position: {
  15823. type: String,
  15824. required: true
  15825. },
  15826. size: {
  15827. type: [Number, String],
  15828. default: 300
  15829. },
  15830. modelValue: Boolean,
  15831. ...makeComponentProps(),
  15832. ...makeLayoutItemProps()
  15833. }, 'VLayoutItem');
  15834. const VLayoutItem = genericComponent()({
  15835. name: 'VLayoutItem',
  15836. props: makeVLayoutItemProps(),
  15837. setup(props, _ref) {
  15838. let {
  15839. slots
  15840. } = _ref;
  15841. const {
  15842. layoutItemStyles
  15843. } = useLayoutItem({
  15844. id: props.name,
  15845. order: vue.computed(() => parseInt(props.order, 10)),
  15846. position: vue.toRef(props, 'position'),
  15847. elementSize: vue.toRef(props, 'size'),
  15848. layoutSize: vue.toRef(props, 'size'),
  15849. active: vue.toRef(props, 'modelValue'),
  15850. absolute: vue.toRef(props, 'absolute')
  15851. });
  15852. return () => vue.createVNode("div", {
  15853. "class": ['v-layout-item', props.class],
  15854. "style": [layoutItemStyles.value, props.style]
  15855. }, [slots.default?.()]);
  15856. }
  15857. });
  15858. // Types
  15859. const makeVLazyProps = propsFactory({
  15860. modelValue: Boolean,
  15861. options: {
  15862. type: Object,
  15863. // For more information on types, navigate to:
  15864. // https://developer.mozilla.org/en-US/docs/Web/API/Intersection_Observer_API
  15865. default: () => ({
  15866. root: undefined,
  15867. rootMargin: undefined,
  15868. threshold: undefined
  15869. })
  15870. },
  15871. ...makeComponentProps(),
  15872. ...makeDimensionProps(),
  15873. ...makeTagProps(),
  15874. ...makeTransitionProps({
  15875. transition: 'fade-transition'
  15876. })
  15877. }, 'VLazy');
  15878. const VLazy = genericComponent()({
  15879. name: 'VLazy',
  15880. directives: {
  15881. intersect: Intersect
  15882. },
  15883. props: makeVLazyProps(),
  15884. emits: {
  15885. 'update:modelValue': value => true
  15886. },
  15887. setup(props, _ref) {
  15888. let {
  15889. slots
  15890. } = _ref;
  15891. const {
  15892. dimensionStyles
  15893. } = useDimension(props);
  15894. const isActive = useProxiedModel(props, 'modelValue');
  15895. function onIntersect(isIntersecting) {
  15896. if (isActive.value) return;
  15897. isActive.value = isIntersecting;
  15898. }
  15899. useRender(() => vue.withDirectives(vue.createVNode(props.tag, {
  15900. "class": ['v-lazy', props.class],
  15901. "style": [dimensionStyles.value, props.style]
  15902. }, {
  15903. default: () => [isActive.value && vue.createVNode(MaybeTransition, {
  15904. "transition": props.transition,
  15905. "appear": true
  15906. }, {
  15907. default: () => [slots.default?.()]
  15908. })]
  15909. }), [[vue.resolveDirective("intersect"), {
  15910. handler: onIntersect,
  15911. options: props.options
  15912. }, null]]));
  15913. return {};
  15914. }
  15915. });
  15916. const makeVLocaleProviderProps = propsFactory({
  15917. locale: String,
  15918. fallbackLocale: String,
  15919. messages: Object,
  15920. rtl: {
  15921. type: Boolean,
  15922. default: undefined
  15923. },
  15924. ...makeComponentProps()
  15925. }, 'VLocaleProvider');
  15926. const VLocaleProvider = genericComponent()({
  15927. name: 'VLocaleProvider',
  15928. props: makeVLocaleProviderProps(),
  15929. setup(props, _ref) {
  15930. let {
  15931. slots
  15932. } = _ref;
  15933. const {
  15934. rtlClasses
  15935. } = provideLocale(props);
  15936. useRender(() => vue.createVNode("div", {
  15937. "class": ['v-locale-provider', rtlClasses.value, props.class],
  15938. "style": props.style
  15939. }, [slots.default?.()]));
  15940. return {};
  15941. }
  15942. });
  15943. const makeVMainProps = propsFactory({
  15944. scrollable: Boolean,
  15945. ...makeComponentProps(),
  15946. ...makeTagProps({
  15947. tag: 'main'
  15948. })
  15949. }, 'VMain');
  15950. const VMain = genericComponent()({
  15951. name: 'VMain',
  15952. props: makeVMainProps(),
  15953. setup(props, _ref) {
  15954. let {
  15955. slots
  15956. } = _ref;
  15957. const {
  15958. mainStyles
  15959. } = useLayout();
  15960. const {
  15961. ssrBootStyles
  15962. } = useSsrBoot();
  15963. useRender(() => vue.createVNode(props.tag, {
  15964. "class": ['v-main', {
  15965. 'v-main--scrollable': props.scrollable
  15966. }, props.class],
  15967. "style": [mainStyles.value, ssrBootStyles.value, props.style]
  15968. }, {
  15969. default: () => [props.scrollable ? vue.createVNode("div", {
  15970. "class": "v-main__scroller"
  15971. }, [slots.default?.()]) : slots.default?.()]
  15972. }));
  15973. return {};
  15974. }
  15975. });
  15976. // Utilities
  15977. // Types
  15978. function useSticky(_ref) {
  15979. let {
  15980. rootEl,
  15981. isSticky,
  15982. layoutItemStyles
  15983. } = _ref;
  15984. const isStuck = vue.shallowRef(false);
  15985. const stuckPosition = vue.shallowRef(0);
  15986. const stickyStyles = vue.computed(() => {
  15987. const side = typeof isStuck.value === 'boolean' ? 'top' : isStuck.value;
  15988. return [isSticky.value ? {
  15989. top: 'auto',
  15990. bottom: 'auto',
  15991. height: undefined
  15992. } : undefined, isStuck.value ? {
  15993. [side]: convertToUnit(stuckPosition.value)
  15994. } : {
  15995. top: layoutItemStyles.value.top
  15996. }];
  15997. });
  15998. vue.onMounted(() => {
  15999. vue.watch(isSticky, val => {
  16000. if (val) {
  16001. window.addEventListener('scroll', onScroll, {
  16002. passive: true
  16003. });
  16004. } else {
  16005. window.removeEventListener('scroll', onScroll);
  16006. }
  16007. }, {
  16008. immediate: true
  16009. });
  16010. });
  16011. vue.onBeforeUnmount(() => {
  16012. window.removeEventListener('scroll', onScroll);
  16013. });
  16014. let lastScrollTop = 0;
  16015. function onScroll() {
  16016. const direction = lastScrollTop > window.scrollY ? 'up' : 'down';
  16017. const rect = rootEl.value.getBoundingClientRect();
  16018. const layoutTop = parseFloat(layoutItemStyles.value.top ?? 0);
  16019. const top = window.scrollY - Math.max(0, stuckPosition.value - layoutTop);
  16020. const bottom = rect.height + Math.max(stuckPosition.value, layoutTop) - window.scrollY - window.innerHeight;
  16021. const bodyScroll = parseFloat(getComputedStyle(rootEl.value).getPropertyValue('--v-body-scroll-y')) || 0;
  16022. if (rect.height < window.innerHeight - layoutTop) {
  16023. isStuck.value = 'top';
  16024. stuckPosition.value = layoutTop;
  16025. } else if (direction === 'up' && isStuck.value === 'bottom' || direction === 'down' && isStuck.value === 'top') {
  16026. stuckPosition.value = window.scrollY + rect.top - bodyScroll;
  16027. isStuck.value = true;
  16028. } else if (direction === 'down' && bottom <= 0) {
  16029. stuckPosition.value = 0;
  16030. isStuck.value = 'bottom';
  16031. } else if (direction === 'up' && top <= 0) {
  16032. if (!bodyScroll) {
  16033. stuckPosition.value = rect.top + top;
  16034. isStuck.value = 'top';
  16035. } else if (isStuck.value !== 'top') {
  16036. stuckPosition.value = -top + bodyScroll + layoutTop;
  16037. isStuck.value = 'top';
  16038. }
  16039. }
  16040. lastScrollTop = window.scrollY;
  16041. }
  16042. return {
  16043. isStuck,
  16044. stickyStyles
  16045. };
  16046. }
  16047. // Utilities
  16048. const HORIZON = 100; // ms
  16049. const HISTORY = 20; // number of samples to keep
  16050. /** @see https://android.googlesource.com/platform/frameworks/native/+/master/libs/input/VelocityTracker.cpp */
  16051. function kineticEnergyToVelocity(work) {
  16052. const sqrt2 = 1.41421356237;
  16053. return (work < 0 ? -1.0 : 1.0) * Math.sqrt(Math.abs(work)) * sqrt2;
  16054. }
  16055. /**
  16056. * Returns pointer velocity in px/s
  16057. */
  16058. function calculateImpulseVelocity(samples) {
  16059. // The input should be in reversed time order (most recent sample at index i=0)
  16060. if (samples.length < 2) {
  16061. // if 0 or 1 points, velocity is zero
  16062. return 0;
  16063. }
  16064. // if (samples[1].t > samples[0].t) {
  16065. // // Algorithm will still work, but not perfectly
  16066. // consoleWarn('Samples provided to calculateImpulseVelocity in the wrong order')
  16067. // }
  16068. if (samples.length === 2) {
  16069. // if 2 points, basic linear calculation
  16070. if (samples[1].t === samples[0].t) {
  16071. // consoleWarn(`Events have identical time stamps t=${samples[0].t}, setting velocity = 0`)
  16072. return 0;
  16073. }
  16074. return (samples[1].d - samples[0].d) / (samples[1].t - samples[0].t);
  16075. }
  16076. // Guaranteed to have at least 3 points here
  16077. // start with the oldest sample and go forward in time
  16078. let work = 0;
  16079. for (let i = samples.length - 1; i > 0; i--) {
  16080. if (samples[i].t === samples[i - 1].t) {
  16081. // consoleWarn(`Events have identical time stamps t=${samples[i].t}, skipping sample`)
  16082. continue;
  16083. }
  16084. const vprev = kineticEnergyToVelocity(work); // v[i-1]
  16085. const vcurr = (samples[i].d - samples[i - 1].d) / (samples[i].t - samples[i - 1].t); // v[i]
  16086. work += (vcurr - vprev) * Math.abs(vcurr);
  16087. if (i === samples.length - 1) {
  16088. work *= 0.5;
  16089. }
  16090. }
  16091. return kineticEnergyToVelocity(work) * 1000;
  16092. }
  16093. function useVelocity() {
  16094. const touches = {};
  16095. function addMovement(e) {
  16096. Array.from(e.changedTouches).forEach(touch => {
  16097. const samples = touches[touch.identifier] ?? (touches[touch.identifier] = new CircularBuffer(HISTORY));
  16098. samples.push([e.timeStamp, touch]);
  16099. });
  16100. }
  16101. function endTouch(e) {
  16102. Array.from(e.changedTouches).forEach(touch => {
  16103. delete touches[touch.identifier];
  16104. });
  16105. }
  16106. function getVelocity(id) {
  16107. const samples = touches[id]?.values().reverse();
  16108. if (!samples) {
  16109. throw new Error(`No samples for touch id ${id}`);
  16110. }
  16111. const newest = samples[0];
  16112. const x = [];
  16113. const y = [];
  16114. for (const val of samples) {
  16115. if (newest[0] - val[0] > HORIZON) break;
  16116. x.push({
  16117. t: val[0],
  16118. d: val[1].clientX
  16119. });
  16120. y.push({
  16121. t: val[0],
  16122. d: val[1].clientY
  16123. });
  16124. }
  16125. return {
  16126. x: calculateImpulseVelocity(x),
  16127. y: calculateImpulseVelocity(y),
  16128. get direction() {
  16129. const {
  16130. x,
  16131. y
  16132. } = this;
  16133. const [absX, absY] = [Math.abs(x), Math.abs(y)];
  16134. return absX > absY && x >= 0 ? 'right' : absX > absY && x <= 0 ? 'left' : absY > absX && y >= 0 ? 'down' : absY > absX && y <= 0 ? 'up' : oops$1();
  16135. }
  16136. };
  16137. }
  16138. return {
  16139. addMovement,
  16140. endTouch,
  16141. getVelocity
  16142. };
  16143. }
  16144. function oops$1() {
  16145. throw new Error();
  16146. }
  16147. // Composables
  16148. // Types
  16149. function useTouch(_ref) {
  16150. let {
  16151. isActive,
  16152. isTemporary,
  16153. width,
  16154. touchless,
  16155. position
  16156. } = _ref;
  16157. vue.onMounted(() => {
  16158. window.addEventListener('touchstart', onTouchstart, {
  16159. passive: true
  16160. });
  16161. window.addEventListener('touchmove', onTouchmove, {
  16162. passive: false
  16163. });
  16164. window.addEventListener('touchend', onTouchend, {
  16165. passive: true
  16166. });
  16167. });
  16168. vue.onBeforeUnmount(() => {
  16169. window.removeEventListener('touchstart', onTouchstart);
  16170. window.removeEventListener('touchmove', onTouchmove);
  16171. window.removeEventListener('touchend', onTouchend);
  16172. });
  16173. const isHorizontal = vue.computed(() => ['left', 'right'].includes(position.value));
  16174. const {
  16175. addMovement,
  16176. endTouch,
  16177. getVelocity
  16178. } = useVelocity();
  16179. let maybeDragging = false;
  16180. const isDragging = vue.shallowRef(false);
  16181. const dragProgress = vue.shallowRef(0);
  16182. const offset = vue.shallowRef(0);
  16183. let start;
  16184. function getOffset(pos, active) {
  16185. 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);
  16186. }
  16187. function getProgress(pos) {
  16188. let limit = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : true;
  16189. 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();
  16190. return limit ? Math.max(0, Math.min(1, progress)) : progress;
  16191. }
  16192. function onTouchstart(e) {
  16193. if (touchless.value) return;
  16194. const touchX = e.changedTouches[0].clientX;
  16195. const touchY = e.changedTouches[0].clientY;
  16196. const touchZone = 25;
  16197. 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();
  16198. 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());
  16199. if (inTouchZone || inElement || isActive.value && isTemporary.value) {
  16200. maybeDragging = true;
  16201. start = [touchX, touchY];
  16202. offset.value = getOffset(isHorizontal.value ? touchX : touchY, isActive.value);
  16203. dragProgress.value = getProgress(isHorizontal.value ? touchX : touchY);
  16204. endTouch(e);
  16205. addMovement(e);
  16206. }
  16207. }
  16208. function onTouchmove(e) {
  16209. const touchX = e.changedTouches[0].clientX;
  16210. const touchY = e.changedTouches[0].clientY;
  16211. if (maybeDragging) {
  16212. if (!e.cancelable) {
  16213. maybeDragging = false;
  16214. return;
  16215. }
  16216. const dx = Math.abs(touchX - start[0]);
  16217. const dy = Math.abs(touchY - start[1]);
  16218. const thresholdMet = isHorizontal.value ? dx > dy && dx > 3 : dy > dx && dy > 3;
  16219. if (thresholdMet) {
  16220. isDragging.value = true;
  16221. maybeDragging = false;
  16222. } else if ((isHorizontal.value ? dy : dx) > 3) {
  16223. maybeDragging = false;
  16224. }
  16225. }
  16226. if (!isDragging.value) return;
  16227. e.preventDefault();
  16228. addMovement(e);
  16229. const progress = getProgress(isHorizontal.value ? touchX : touchY, false);
  16230. dragProgress.value = Math.max(0, Math.min(1, progress));
  16231. if (progress > 1) {
  16232. offset.value = getOffset(isHorizontal.value ? touchX : touchY, true);
  16233. } else if (progress < 0) {
  16234. offset.value = getOffset(isHorizontal.value ? touchX : touchY, false);
  16235. }
  16236. }
  16237. function onTouchend(e) {
  16238. maybeDragging = false;
  16239. if (!isDragging.value) return;
  16240. addMovement(e);
  16241. isDragging.value = false;
  16242. const velocity = getVelocity(e.changedTouches[0].identifier);
  16243. const vx = Math.abs(velocity.x);
  16244. const vy = Math.abs(velocity.y);
  16245. const thresholdMet = isHorizontal.value ? vx > vy && vx > 400 : vy > vx && vy > 3;
  16246. if (thresholdMet) {
  16247. isActive.value = velocity.direction === ({
  16248. left: 'right',
  16249. right: 'left',
  16250. top: 'down',
  16251. bottom: 'up'
  16252. }[position.value] || oops());
  16253. } else {
  16254. isActive.value = dragProgress.value > 0.5;
  16255. }
  16256. }
  16257. const dragStyles = vue.computed(() => {
  16258. return isDragging.value ? {
  16259. 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(),
  16260. transition: 'none'
  16261. } : undefined;
  16262. });
  16263. return {
  16264. isDragging,
  16265. dragProgress,
  16266. dragStyles
  16267. };
  16268. }
  16269. function oops() {
  16270. throw new Error();
  16271. }
  16272. // Types
  16273. const locations = ['start', 'end', 'left', 'right', 'top', 'bottom'];
  16274. const makeVNavigationDrawerProps = propsFactory({
  16275. color: String,
  16276. disableResizeWatcher: Boolean,
  16277. disableRouteWatcher: Boolean,
  16278. expandOnHover: Boolean,
  16279. floating: Boolean,
  16280. modelValue: {
  16281. type: Boolean,
  16282. default: null
  16283. },
  16284. permanent: Boolean,
  16285. rail: {
  16286. type: Boolean,
  16287. default: null
  16288. },
  16289. railWidth: {
  16290. type: [Number, String],
  16291. default: 56
  16292. },
  16293. scrim: {
  16294. type: [Boolean, String],
  16295. default: true
  16296. },
  16297. image: String,
  16298. temporary: Boolean,
  16299. touchless: Boolean,
  16300. width: {
  16301. type: [Number, String],
  16302. default: 256
  16303. },
  16304. location: {
  16305. type: String,
  16306. default: 'start',
  16307. validator: value => locations.includes(value)
  16308. },
  16309. sticky: Boolean,
  16310. ...makeBorderProps(),
  16311. ...makeComponentProps(),
  16312. ...makeElevationProps(),
  16313. ...makeLayoutItemProps(),
  16314. ...makeRoundedProps(),
  16315. ...makeTagProps({
  16316. tag: 'nav'
  16317. }),
  16318. ...makeThemeProps()
  16319. }, 'VNavigationDrawer');
  16320. const VNavigationDrawer = genericComponent()({
  16321. name: 'VNavigationDrawer',
  16322. props: makeVNavigationDrawerProps(),
  16323. emits: {
  16324. 'update:modelValue': val => true,
  16325. 'update:rail': val => true
  16326. },
  16327. setup(props, _ref) {
  16328. let {
  16329. attrs,
  16330. emit,
  16331. slots
  16332. } = _ref;
  16333. const {
  16334. isRtl
  16335. } = useRtl();
  16336. const {
  16337. themeClasses
  16338. } = provideTheme(props);
  16339. const {
  16340. borderClasses
  16341. } = useBorder(props);
  16342. const {
  16343. backgroundColorClasses,
  16344. backgroundColorStyles
  16345. } = useBackgroundColor(vue.toRef(props, 'color'));
  16346. const {
  16347. elevationClasses
  16348. } = useElevation(props);
  16349. const {
  16350. mobile
  16351. } = useDisplay();
  16352. const {
  16353. roundedClasses
  16354. } = useRounded(props);
  16355. const router = useRouter();
  16356. const isActive = useProxiedModel(props, 'modelValue', null, v => !!v);
  16357. const {
  16358. ssrBootStyles
  16359. } = useSsrBoot();
  16360. const {
  16361. scopeId
  16362. } = useScopeId();
  16363. const rootEl = vue.ref();
  16364. const isHovering = vue.shallowRef(false);
  16365. const width = vue.computed(() => {
  16366. return props.rail && props.expandOnHover && isHovering.value ? Number(props.width) : Number(props.rail ? props.railWidth : props.width);
  16367. });
  16368. const location = vue.computed(() => {
  16369. return toPhysical(props.location, isRtl.value);
  16370. });
  16371. const isTemporary = vue.computed(() => !props.permanent && (mobile.value || props.temporary));
  16372. const isSticky = vue.computed(() => props.sticky && !isTemporary.value && location.value !== 'bottom');
  16373. if (props.expandOnHover && props.rail != null) {
  16374. vue.watch(isHovering, val => emit('update:rail', !val));
  16375. }
  16376. if (!props.disableResizeWatcher) {
  16377. vue.watch(isTemporary, val => !props.permanent && vue.nextTick(() => isActive.value = !val));
  16378. }
  16379. if (!props.disableRouteWatcher && router) {
  16380. vue.watch(router.currentRoute, () => isTemporary.value && (isActive.value = false));
  16381. }
  16382. vue.watch(() => props.permanent, val => {
  16383. if (val) isActive.value = true;
  16384. });
  16385. vue.onBeforeMount(() => {
  16386. if (props.modelValue != null || isTemporary.value) return;
  16387. isActive.value = props.permanent || !mobile.value;
  16388. });
  16389. const {
  16390. isDragging,
  16391. dragProgress,
  16392. dragStyles
  16393. } = useTouch({
  16394. isActive,
  16395. isTemporary,
  16396. width,
  16397. touchless: vue.toRef(props, 'touchless'),
  16398. position: location
  16399. });
  16400. const layoutSize = vue.computed(() => {
  16401. const size = isTemporary.value ? 0 : props.rail && props.expandOnHover ? Number(props.railWidth) : width.value;
  16402. return isDragging.value ? size * dragProgress.value : size;
  16403. });
  16404. const {
  16405. layoutItemStyles,
  16406. layoutItemScrimStyles
  16407. } = useLayoutItem({
  16408. id: props.name,
  16409. order: vue.computed(() => parseInt(props.order, 10)),
  16410. position: location,
  16411. layoutSize,
  16412. elementSize: width,
  16413. active: vue.computed(() => isActive.value || isDragging.value),
  16414. disableTransitions: vue.computed(() => isDragging.value),
  16415. absolute: vue.computed(() =>
  16416. // eslint-disable-next-line @typescript-eslint/no-use-before-define
  16417. props.absolute || isSticky.value && typeof isStuck.value !== 'string')
  16418. });
  16419. const {
  16420. isStuck,
  16421. stickyStyles
  16422. } = useSticky({
  16423. rootEl,
  16424. isSticky,
  16425. layoutItemStyles
  16426. });
  16427. const scrimColor = useBackgroundColor(vue.computed(() => {
  16428. return typeof props.scrim === 'string' ? props.scrim : null;
  16429. }));
  16430. const scrimStyles = vue.computed(() => ({
  16431. ...(isDragging.value ? {
  16432. opacity: dragProgress.value * 0.2,
  16433. transition: 'none'
  16434. } : undefined),
  16435. ...layoutItemScrimStyles.value
  16436. }));
  16437. provideDefaults({
  16438. VList: {
  16439. bgColor: 'transparent'
  16440. }
  16441. });
  16442. function onMouseenter() {
  16443. isHovering.value = true;
  16444. }
  16445. function onMouseleave() {
  16446. isHovering.value = false;
  16447. }
  16448. useRender(() => {
  16449. const hasImage = slots.image || props.image;
  16450. return vue.createVNode(vue.Fragment, null, [vue.createVNode(props.tag, vue.mergeProps({
  16451. "ref": rootEl,
  16452. "onMouseenter": onMouseenter,
  16453. "onMouseleave": onMouseleave,
  16454. "class": ['v-navigation-drawer', `v-navigation-drawer--${location.value}`, {
  16455. 'v-navigation-drawer--expand-on-hover': props.expandOnHover,
  16456. 'v-navigation-drawer--floating': props.floating,
  16457. 'v-navigation-drawer--is-hovering': isHovering.value,
  16458. 'v-navigation-drawer--rail': props.rail,
  16459. 'v-navigation-drawer--temporary': isTemporary.value,
  16460. 'v-navigation-drawer--active': isActive.value,
  16461. 'v-navigation-drawer--sticky': isSticky.value
  16462. }, themeClasses.value, backgroundColorClasses.value, borderClasses.value, elevationClasses.value, roundedClasses.value, props.class],
  16463. "style": [backgroundColorStyles.value, layoutItemStyles.value, dragStyles.value, ssrBootStyles.value, stickyStyles.value, props.style]
  16464. }, scopeId, attrs), {
  16465. default: () => [hasImage && vue.createVNode("div", {
  16466. "key": "image",
  16467. "class": "v-navigation-drawer__img"
  16468. }, [slots.image ? slots.image?.({
  16469. image: props.image
  16470. }) : vue.createVNode("img", {
  16471. "src": props.image,
  16472. "alt": ""
  16473. }, null)]), slots.prepend && vue.createVNode("div", {
  16474. "class": "v-navigation-drawer__prepend"
  16475. }, [slots.prepend?.()]), vue.createVNode("div", {
  16476. "class": "v-navigation-drawer__content"
  16477. }, [slots.default?.()]), slots.append && vue.createVNode("div", {
  16478. "class": "v-navigation-drawer__append"
  16479. }, [slots.append?.()])]
  16480. }), vue.createVNode(vue.Transition, {
  16481. "name": "fade-transition"
  16482. }, {
  16483. default: () => [isTemporary.value && (isDragging.value || isActive.value) && !!props.scrim && vue.createVNode("div", vue.mergeProps({
  16484. "class": ['v-navigation-drawer__scrim', scrimColor.backgroundColorClasses.value],
  16485. "style": [scrimStyles.value, scrimColor.backgroundColorStyles.value],
  16486. "onClick": () => isActive.value = false
  16487. }, scopeId), null)]
  16488. })]);
  16489. });
  16490. return {
  16491. isStuck
  16492. };
  16493. }
  16494. });
  16495. // Composables
  16496. const VNoSsr = defineComponent({
  16497. name: 'VNoSsr',
  16498. setup(_, _ref) {
  16499. let {
  16500. slots
  16501. } = _ref;
  16502. const show = useHydration();
  16503. return () => show.value && slots.default?.();
  16504. }
  16505. });
  16506. // Utilities
  16507. // Types
  16508. function useRefs() {
  16509. const refs = vue.ref([]);
  16510. vue.onBeforeUpdate(() => refs.value = []);
  16511. function updateRef(e, i) {
  16512. refs.value[i] = e;
  16513. }
  16514. return {
  16515. refs,
  16516. updateRef
  16517. };
  16518. }
  16519. // Types
  16520. const makeVPaginationProps = propsFactory({
  16521. activeColor: String,
  16522. start: {
  16523. type: [Number, String],
  16524. default: 1
  16525. },
  16526. modelValue: {
  16527. type: Number,
  16528. default: props => props.start
  16529. },
  16530. disabled: Boolean,
  16531. length: {
  16532. type: [Number, String],
  16533. default: 1,
  16534. validator: val => val % 1 === 0
  16535. },
  16536. totalVisible: [Number, String],
  16537. firstIcon: {
  16538. type: IconValue,
  16539. default: '$first'
  16540. },
  16541. prevIcon: {
  16542. type: IconValue,
  16543. default: '$prev'
  16544. },
  16545. nextIcon: {
  16546. type: IconValue,
  16547. default: '$next'
  16548. },
  16549. lastIcon: {
  16550. type: IconValue,
  16551. default: '$last'
  16552. },
  16553. ariaLabel: {
  16554. type: String,
  16555. default: '$vuetify.pagination.ariaLabel.root'
  16556. },
  16557. pageAriaLabel: {
  16558. type: String,
  16559. default: '$vuetify.pagination.ariaLabel.page'
  16560. },
  16561. currentPageAriaLabel: {
  16562. type: String,
  16563. default: '$vuetify.pagination.ariaLabel.currentPage'
  16564. },
  16565. firstAriaLabel: {
  16566. type: String,
  16567. default: '$vuetify.pagination.ariaLabel.first'
  16568. },
  16569. previousAriaLabel: {
  16570. type: String,
  16571. default: '$vuetify.pagination.ariaLabel.previous'
  16572. },
  16573. nextAriaLabel: {
  16574. type: String,
  16575. default: '$vuetify.pagination.ariaLabel.next'
  16576. },
  16577. lastAriaLabel: {
  16578. type: String,
  16579. default: '$vuetify.pagination.ariaLabel.last'
  16580. },
  16581. ellipsis: {
  16582. type: String,
  16583. default: '...'
  16584. },
  16585. showFirstLastPage: Boolean,
  16586. ...makeBorderProps(),
  16587. ...makeComponentProps(),
  16588. ...makeDensityProps(),
  16589. ...makeElevationProps(),
  16590. ...makeRoundedProps(),
  16591. ...makeSizeProps(),
  16592. ...makeTagProps({
  16593. tag: 'nav'
  16594. }),
  16595. ...makeThemeProps(),
  16596. ...makeVariantProps({
  16597. variant: 'text'
  16598. })
  16599. }, 'VPagination');
  16600. const VPagination = genericComponent()({
  16601. name: 'VPagination',
  16602. props: makeVPaginationProps(),
  16603. emits: {
  16604. 'update:modelValue': value => true,
  16605. first: value => true,
  16606. prev: value => true,
  16607. next: value => true,
  16608. last: value => true
  16609. },
  16610. setup(props, _ref) {
  16611. let {
  16612. slots,
  16613. emit
  16614. } = _ref;
  16615. const page = useProxiedModel(props, 'modelValue');
  16616. const {
  16617. t,
  16618. n
  16619. } = useLocale();
  16620. const {
  16621. isRtl
  16622. } = useRtl();
  16623. const {
  16624. themeClasses
  16625. } = provideTheme(props);
  16626. const {
  16627. width
  16628. } = useDisplay();
  16629. const maxButtons = vue.shallowRef(-1);
  16630. provideDefaults(undefined, {
  16631. scoped: true
  16632. });
  16633. const {
  16634. resizeRef
  16635. } = useResizeObserver(entries => {
  16636. if (!entries.length) return;
  16637. const {
  16638. target,
  16639. contentRect
  16640. } = entries[0];
  16641. const firstItem = target.querySelector('.v-pagination__list > *');
  16642. if (!firstItem) return;
  16643. const totalWidth = contentRect.width;
  16644. const itemWidth = firstItem.offsetWidth + parseFloat(getComputedStyle(firstItem).marginRight) * 2;
  16645. maxButtons.value = getMax(totalWidth, itemWidth);
  16646. });
  16647. const length = vue.computed(() => parseInt(props.length, 10));
  16648. const start = vue.computed(() => parseInt(props.start, 10));
  16649. const totalVisible = vue.computed(() => {
  16650. if (props.totalVisible) return parseInt(props.totalVisible, 10);else if (maxButtons.value >= 0) return maxButtons.value;
  16651. return getMax(width.value, 58);
  16652. });
  16653. function getMax(totalWidth, itemWidth) {
  16654. const minButtons = props.showFirstLastPage ? 5 : 3;
  16655. return Math.max(0, Math.floor(
  16656. // Round to two decimal places to avoid floating point errors
  16657. +((totalWidth - itemWidth * minButtons) / itemWidth).toFixed(2)));
  16658. }
  16659. const range = vue.computed(() => {
  16660. if (length.value <= 0 || isNaN(length.value) || length.value > Number.MAX_SAFE_INTEGER) return [];
  16661. if (totalVisible.value <= 1) return [page.value];
  16662. if (length.value <= totalVisible.value) {
  16663. return createRange(length.value, start.value);
  16664. }
  16665. const even = totalVisible.value % 2 === 0;
  16666. const middle = even ? totalVisible.value / 2 : Math.floor(totalVisible.value / 2);
  16667. const left = even ? middle : middle + 1;
  16668. const right = length.value - middle;
  16669. if (left - page.value >= 0) {
  16670. return [...createRange(Math.max(1, totalVisible.value - 1), start.value), props.ellipsis, length.value];
  16671. } else if (page.value - right >= (even ? 1 : 0)) {
  16672. const rangeLength = totalVisible.value - 1;
  16673. const rangeStart = length.value - rangeLength + start.value;
  16674. return [start.value, props.ellipsis, ...createRange(rangeLength, rangeStart)];
  16675. } else {
  16676. const rangeLength = Math.max(1, totalVisible.value - 3);
  16677. const rangeStart = rangeLength === 1 ? page.value : page.value - Math.ceil(rangeLength / 2) + start.value;
  16678. return [start.value, props.ellipsis, ...createRange(rangeLength, rangeStart), props.ellipsis, length.value];
  16679. }
  16680. });
  16681. // TODO: 'first' | 'prev' | 'next' | 'last' does not work here?
  16682. function setValue(e, value, event) {
  16683. e.preventDefault();
  16684. page.value = value;
  16685. event && emit(event, value);
  16686. }
  16687. const {
  16688. refs,
  16689. updateRef
  16690. } = useRefs();
  16691. provideDefaults({
  16692. VPaginationBtn: {
  16693. color: vue.toRef(props, 'color'),
  16694. border: vue.toRef(props, 'border'),
  16695. density: vue.toRef(props, 'density'),
  16696. size: vue.toRef(props, 'size'),
  16697. variant: vue.toRef(props, 'variant'),
  16698. rounded: vue.toRef(props, 'rounded'),
  16699. elevation: vue.toRef(props, 'elevation')
  16700. }
  16701. });
  16702. const items = vue.computed(() => {
  16703. return range.value.map((item, index) => {
  16704. const ref = e => updateRef(e, index);
  16705. if (typeof item === 'string') {
  16706. return {
  16707. isActive: false,
  16708. key: `ellipsis-${index}`,
  16709. page: item,
  16710. props: {
  16711. ref,
  16712. ellipsis: true,
  16713. icon: true,
  16714. disabled: true
  16715. }
  16716. };
  16717. } else {
  16718. const isActive = item === page.value;
  16719. return {
  16720. isActive,
  16721. key: item,
  16722. page: n(item),
  16723. props: {
  16724. ref,
  16725. ellipsis: false,
  16726. icon: true,
  16727. disabled: !!props.disabled || +props.length < 2,
  16728. color: isActive ? props.activeColor : props.color,
  16729. ariaCurrent: isActive,
  16730. ariaLabel: t(isActive ? props.currentPageAriaLabel : props.pageAriaLabel, item),
  16731. onClick: e => setValue(e, item)
  16732. }
  16733. };
  16734. }
  16735. });
  16736. });
  16737. const controls = vue.computed(() => {
  16738. const prevDisabled = !!props.disabled || page.value <= start.value;
  16739. const nextDisabled = !!props.disabled || page.value >= start.value + length.value - 1;
  16740. return {
  16741. first: props.showFirstLastPage ? {
  16742. icon: isRtl.value ? props.lastIcon : props.firstIcon,
  16743. onClick: e => setValue(e, start.value, 'first'),
  16744. disabled: prevDisabled,
  16745. ariaLabel: t(props.firstAriaLabel),
  16746. ariaDisabled: prevDisabled
  16747. } : undefined,
  16748. prev: {
  16749. icon: isRtl.value ? props.nextIcon : props.prevIcon,
  16750. onClick: e => setValue(e, page.value - 1, 'prev'),
  16751. disabled: prevDisabled,
  16752. ariaLabel: t(props.previousAriaLabel),
  16753. ariaDisabled: prevDisabled
  16754. },
  16755. next: {
  16756. icon: isRtl.value ? props.prevIcon : props.nextIcon,
  16757. onClick: e => setValue(e, page.value + 1, 'next'),
  16758. disabled: nextDisabled,
  16759. ariaLabel: t(props.nextAriaLabel),
  16760. ariaDisabled: nextDisabled
  16761. },
  16762. last: props.showFirstLastPage ? {
  16763. icon: isRtl.value ? props.firstIcon : props.lastIcon,
  16764. onClick: e => setValue(e, start.value + length.value - 1, 'last'),
  16765. disabled: nextDisabled,
  16766. ariaLabel: t(props.lastAriaLabel),
  16767. ariaDisabled: nextDisabled
  16768. } : undefined
  16769. };
  16770. });
  16771. function updateFocus() {
  16772. const currentIndex = page.value - start.value;
  16773. refs.value[currentIndex]?.$el.focus();
  16774. }
  16775. function onKeydown(e) {
  16776. if (e.key === keyValues.left && !props.disabled && page.value > +props.start) {
  16777. page.value = page.value - 1;
  16778. vue.nextTick(updateFocus);
  16779. } else if (e.key === keyValues.right && !props.disabled && page.value < start.value + length.value - 1) {
  16780. page.value = page.value + 1;
  16781. vue.nextTick(updateFocus);
  16782. }
  16783. }
  16784. useRender(() => vue.createVNode(props.tag, {
  16785. "ref": resizeRef,
  16786. "class": ['v-pagination', themeClasses.value, props.class],
  16787. "style": props.style,
  16788. "role": "navigation",
  16789. "aria-label": t(props.ariaLabel),
  16790. "onKeydown": onKeydown,
  16791. "data-test": "v-pagination-root"
  16792. }, {
  16793. default: () => [vue.createVNode("ul", {
  16794. "class": "v-pagination__list"
  16795. }, [props.showFirstLastPage && vue.createVNode("li", {
  16796. "key": "first",
  16797. "class": "v-pagination__first",
  16798. "data-test": "v-pagination-first"
  16799. }, [slots.first ? slots.first(controls.value.first) : vue.createVNode(VBtn, vue.mergeProps({
  16800. "_as": "VPaginationBtn"
  16801. }, controls.value.first), null)]), vue.createVNode("li", {
  16802. "key": "prev",
  16803. "class": "v-pagination__prev",
  16804. "data-test": "v-pagination-prev"
  16805. }, [slots.prev ? slots.prev(controls.value.prev) : vue.createVNode(VBtn, vue.mergeProps({
  16806. "_as": "VPaginationBtn"
  16807. }, controls.value.prev), null)]), items.value.map((item, index) => vue.createVNode("li", {
  16808. "key": item.key,
  16809. "class": ['v-pagination__item', {
  16810. 'v-pagination__item--is-active': item.isActive
  16811. }],
  16812. "data-test": "v-pagination-item"
  16813. }, [slots.item ? slots.item(item) : vue.createVNode(VBtn, vue.mergeProps({
  16814. "_as": "VPaginationBtn"
  16815. }, item.props), {
  16816. default: () => [item.page]
  16817. })])), vue.createVNode("li", {
  16818. "key": "next",
  16819. "class": "v-pagination__next",
  16820. "data-test": "v-pagination-next"
  16821. }, [slots.next ? slots.next(controls.value.next) : vue.createVNode(VBtn, vue.mergeProps({
  16822. "_as": "VPaginationBtn"
  16823. }, controls.value.next), null)]), props.showFirstLastPage && vue.createVNode("li", {
  16824. "key": "last",
  16825. "class": "v-pagination__last",
  16826. "data-test": "v-pagination-last"
  16827. }, [slots.last ? slots.last(controls.value.last) : vue.createVNode(VBtn, vue.mergeProps({
  16828. "_as": "VPaginationBtn"
  16829. }, controls.value.last), null)])])]
  16830. }));
  16831. return {};
  16832. }
  16833. });
  16834. // Types
  16835. function floor(val) {
  16836. return Math.floor(Math.abs(val)) * Math.sign(val);
  16837. }
  16838. const makeVParallaxProps = propsFactory({
  16839. scale: {
  16840. type: [Number, String],
  16841. default: 0.5
  16842. },
  16843. ...makeComponentProps()
  16844. }, 'VParallax');
  16845. const VParallax = genericComponent()({
  16846. name: 'VParallax',
  16847. props: makeVParallaxProps(),
  16848. setup(props, _ref) {
  16849. let {
  16850. slots
  16851. } = _ref;
  16852. const {
  16853. intersectionRef,
  16854. isIntersecting
  16855. } = useIntersectionObserver();
  16856. const {
  16857. resizeRef,
  16858. contentRect
  16859. } = useResizeObserver();
  16860. const {
  16861. height: displayHeight
  16862. } = useDisplay();
  16863. const root = vue.ref();
  16864. vue.watchEffect(() => {
  16865. intersectionRef.value = resizeRef.value = root.value?.$el;
  16866. });
  16867. let scrollParent;
  16868. vue.watch(isIntersecting, val => {
  16869. if (val) {
  16870. scrollParent = getScrollParent(intersectionRef.value);
  16871. scrollParent = scrollParent === document.scrollingElement ? document : scrollParent;
  16872. scrollParent.addEventListener('scroll', onScroll, {
  16873. passive: true
  16874. });
  16875. onScroll();
  16876. } else {
  16877. scrollParent.removeEventListener('scroll', onScroll);
  16878. }
  16879. });
  16880. vue.onBeforeUnmount(() => {
  16881. scrollParent?.removeEventListener('scroll', onScroll);
  16882. });
  16883. vue.watch(displayHeight, onScroll);
  16884. vue.watch(() => contentRect.value?.height, onScroll);
  16885. const scale = vue.computed(() => {
  16886. return 1 - clamp(+props.scale);
  16887. });
  16888. let frame = -1;
  16889. function onScroll() {
  16890. if (!isIntersecting.value) return;
  16891. cancelAnimationFrame(frame);
  16892. frame = requestAnimationFrame(() => {
  16893. const el = (root.value?.$el).querySelector('.v-img__img');
  16894. if (!el) return;
  16895. const scrollHeight = scrollParent instanceof Document ? document.documentElement.clientHeight : scrollParent.clientHeight;
  16896. const scrollPos = scrollParent instanceof Document ? window.scrollY : scrollParent.scrollTop;
  16897. const top = intersectionRef.value.getBoundingClientRect().top + scrollPos;
  16898. const height = contentRect.value.height;
  16899. const center = top + (height - scrollHeight) / 2;
  16900. const translate = floor((scrollPos - center) * scale.value);
  16901. const sizeScale = Math.max(1, (scale.value * (scrollHeight - height) + height) / height);
  16902. el.style.setProperty('transform', `translateY(${translate}px) scale(${sizeScale})`);
  16903. });
  16904. }
  16905. useRender(() => vue.createVNode(VImg, {
  16906. "class": ['v-parallax', {
  16907. 'v-parallax--active': isIntersecting.value
  16908. }, props.class],
  16909. "style": props.style,
  16910. "ref": root,
  16911. "cover": true,
  16912. "onLoadstart": onScroll,
  16913. "onLoad": onScroll
  16914. }, slots));
  16915. return {};
  16916. }
  16917. });
  16918. // Types
  16919. const makeVRadioProps = propsFactory({
  16920. ...makeVSelectionControlProps({
  16921. falseIcon: '$radioOff',
  16922. trueIcon: '$radioOn'
  16923. })
  16924. }, 'VRadio');
  16925. const VRadio = genericComponent()({
  16926. name: 'VRadio',
  16927. props: makeVRadioProps(),
  16928. setup(props, _ref) {
  16929. let {
  16930. slots
  16931. } = _ref;
  16932. useRender(() => vue.createVNode(VSelectionControl, vue.mergeProps(props, {
  16933. "class": ['v-radio', props.class],
  16934. "style": props.style,
  16935. "type": "radio"
  16936. }), slots));
  16937. return {};
  16938. }
  16939. });
  16940. // Types
  16941. const makeVRadioGroupProps = propsFactory({
  16942. height: {
  16943. type: [Number, String],
  16944. default: 'auto'
  16945. },
  16946. ...makeVInputProps(),
  16947. ...omit(makeSelectionControlGroupProps(), ['multiple']),
  16948. trueIcon: {
  16949. type: IconValue,
  16950. default: '$radioOn'
  16951. },
  16952. falseIcon: {
  16953. type: IconValue,
  16954. default: '$radioOff'
  16955. },
  16956. type: {
  16957. type: String,
  16958. default: 'radio'
  16959. }
  16960. }, 'VRadioGroup');
  16961. const VRadioGroup = genericComponent()({
  16962. name: 'VRadioGroup',
  16963. inheritAttrs: false,
  16964. props: makeVRadioGroupProps(),
  16965. emits: {
  16966. 'update:modelValue': val => true
  16967. },
  16968. setup(props, _ref) {
  16969. let {
  16970. attrs,
  16971. slots
  16972. } = _ref;
  16973. const uid = getUid();
  16974. const id = vue.computed(() => props.id || `radio-group-${uid}`);
  16975. const model = useProxiedModel(props, 'modelValue');
  16976. useRender(() => {
  16977. const [inputAttrs, controlAttrs] = filterInputAttrs(attrs);
  16978. const [inputProps, _1] = VInput.filterProps(props);
  16979. const [controlProps, _2] = VSelectionControl.filterProps(props);
  16980. const label = slots.label ? slots.label({
  16981. label: props.label,
  16982. props: {
  16983. for: id.value
  16984. }
  16985. }) : props.label;
  16986. return vue.createVNode(VInput, vue.mergeProps({
  16987. "class": ['v-radio-group', props.class],
  16988. "style": props.style
  16989. }, inputAttrs, inputProps, {
  16990. "modelValue": model.value,
  16991. "onUpdate:modelValue": $event => model.value = $event,
  16992. "id": id.value
  16993. }), {
  16994. ...slots,
  16995. default: _ref2 => {
  16996. let {
  16997. id,
  16998. messagesId,
  16999. isDisabled,
  17000. isReadonly
  17001. } = _ref2;
  17002. return vue.createVNode(vue.Fragment, null, [label && vue.createVNode(VLabel, {
  17003. "id": id.value
  17004. }, {
  17005. default: () => [label]
  17006. }), vue.createVNode(VSelectionControlGroup, vue.mergeProps(controlProps, {
  17007. "id": id.value,
  17008. "aria-describedby": messagesId.value,
  17009. "defaultsTarget": "VRadio",
  17010. "trueIcon": props.trueIcon,
  17011. "falseIcon": props.falseIcon,
  17012. "type": props.type,
  17013. "disabled": isDisabled.value,
  17014. "readonly": isReadonly.value,
  17015. "aria-labelledby": label ? id.value : undefined,
  17016. "multiple": false
  17017. }, controlAttrs, {
  17018. "modelValue": model.value,
  17019. "onUpdate:modelValue": $event => model.value = $event
  17020. }), slots)]);
  17021. }
  17022. });
  17023. });
  17024. return {};
  17025. }
  17026. });
  17027. // Types
  17028. const makeVRangeSliderProps = propsFactory({
  17029. ...makeFocusProps(),
  17030. ...makeVInputProps(),
  17031. ...makeSliderProps(),
  17032. strict: Boolean,
  17033. modelValue: {
  17034. type: Array,
  17035. default: () => [0, 0]
  17036. }
  17037. }, 'VRangeSlider');
  17038. const VRangeSlider = genericComponent()({
  17039. name: 'VRangeSlider',
  17040. props: makeVRangeSliderProps(),
  17041. emits: {
  17042. 'update:focused': value => true,
  17043. 'update:modelValue': value => true,
  17044. end: value => true,
  17045. start: value => true
  17046. },
  17047. setup(props, _ref) {
  17048. let {
  17049. slots,
  17050. emit
  17051. } = _ref;
  17052. const startThumbRef = vue.ref();
  17053. const stopThumbRef = vue.ref();
  17054. const inputRef = vue.ref();
  17055. const {
  17056. rtlClasses
  17057. } = useRtl();
  17058. function getActiveThumb(e) {
  17059. if (!startThumbRef.value || !stopThumbRef.value) return;
  17060. const startOffset = getOffset(e, startThumbRef.value.$el, props.direction);
  17061. const stopOffset = getOffset(e, stopThumbRef.value.$el, props.direction);
  17062. const a = Math.abs(startOffset);
  17063. const b = Math.abs(stopOffset);
  17064. return a < b || a === b && startOffset < 0 ? startThumbRef.value.$el : stopThumbRef.value.$el;
  17065. }
  17066. const steps = useSteps(props);
  17067. const model = useProxiedModel(props, 'modelValue', undefined, arr => {
  17068. if (!arr?.length) return [0, 0];
  17069. return arr.map(value => steps.roundValue(value));
  17070. });
  17071. const {
  17072. activeThumbRef,
  17073. hasLabels,
  17074. max,
  17075. min,
  17076. mousePressed,
  17077. onSliderMousedown,
  17078. onSliderTouchstart,
  17079. position,
  17080. trackContainerRef
  17081. } = useSlider({
  17082. props,
  17083. steps,
  17084. onSliderStart: () => {
  17085. emit('start', model.value);
  17086. },
  17087. onSliderEnd: _ref2 => {
  17088. let {
  17089. value
  17090. } = _ref2;
  17091. const newValue = activeThumbRef.value === startThumbRef.value?.$el ? [value, model.value[1]] : [model.value[0], value];
  17092. if (!props.strict && newValue[0] < newValue[1]) {
  17093. model.value = newValue;
  17094. }
  17095. emit('end', model.value);
  17096. },
  17097. onSliderMove: _ref3 => {
  17098. let {
  17099. value
  17100. } = _ref3;
  17101. const [start, stop] = model.value;
  17102. if (!props.strict && start === stop && start !== min.value) {
  17103. activeThumbRef.value = value > start ? stopThumbRef.value?.$el : startThumbRef.value?.$el;
  17104. activeThumbRef.value?.focus();
  17105. }
  17106. if (activeThumbRef.value === startThumbRef.value?.$el) {
  17107. model.value = [Math.min(value, stop), stop];
  17108. } else {
  17109. model.value = [start, Math.max(start, value)];
  17110. }
  17111. },
  17112. getActiveThumb
  17113. });
  17114. const {
  17115. isFocused,
  17116. focus,
  17117. blur
  17118. } = useFocus(props);
  17119. const trackStart = vue.computed(() => position(model.value[0]));
  17120. const trackStop = vue.computed(() => position(model.value[1]));
  17121. useRender(() => {
  17122. const [inputProps, _] = VInput.filterProps(props);
  17123. const hasPrepend = !!(props.label || slots.label || slots.prepend);
  17124. return vue.createVNode(VInput, vue.mergeProps({
  17125. "class": ['v-slider', 'v-range-slider', {
  17126. 'v-slider--has-labels': !!slots['tick-label'] || hasLabels.value,
  17127. 'v-slider--focused': isFocused.value,
  17128. 'v-slider--pressed': mousePressed.value,
  17129. 'v-slider--disabled': props.disabled
  17130. }, rtlClasses.value, props.class],
  17131. "style": props.style,
  17132. "ref": inputRef
  17133. }, inputProps, {
  17134. "focused": isFocused.value
  17135. }), {
  17136. ...slots,
  17137. prepend: hasPrepend ? slotProps => vue.createVNode(vue.Fragment, null, [slots.label?.(slotProps) ?? props.label ? vue.createVNode(VLabel, {
  17138. "class": "v-slider__label",
  17139. "text": props.label
  17140. }, null) : undefined, slots.prepend?.(slotProps)]) : undefined,
  17141. default: _ref4 => {
  17142. let {
  17143. id,
  17144. messagesId
  17145. } = _ref4;
  17146. return vue.createVNode("div", {
  17147. "class": "v-slider__container",
  17148. "onMousedown": onSliderMousedown,
  17149. "onTouchstartPassive": onSliderTouchstart
  17150. }, [vue.createVNode("input", {
  17151. "id": `${id.value}_start`,
  17152. "name": props.name || id.value,
  17153. "disabled": !!props.disabled,
  17154. "readonly": !!props.readonly,
  17155. "tabindex": "-1",
  17156. "value": model.value[0]
  17157. }, null), vue.createVNode("input", {
  17158. "id": `${id.value}_stop`,
  17159. "name": props.name || id.value,
  17160. "disabled": !!props.disabled,
  17161. "readonly": !!props.readonly,
  17162. "tabindex": "-1",
  17163. "value": model.value[1]
  17164. }, null), vue.createVNode(VSliderTrack, {
  17165. "ref": trackContainerRef,
  17166. "start": trackStart.value,
  17167. "stop": trackStop.value
  17168. }, {
  17169. 'tick-label': slots['tick-label']
  17170. }), vue.createVNode(VSliderThumb, {
  17171. "ref": startThumbRef,
  17172. "aria-describedby": messagesId.value,
  17173. "focused": isFocused && activeThumbRef.value === startThumbRef.value?.$el,
  17174. "modelValue": model.value[0],
  17175. "onUpdate:modelValue": v => model.value = [v, model.value[1]],
  17176. "onFocus": e => {
  17177. focus();
  17178. activeThumbRef.value = startThumbRef.value?.$el;
  17179. // Make sure second thumb is focused if
  17180. // the thumbs are on top of each other
  17181. // and they are both at minimum value
  17182. // but only if focused from outside.
  17183. if (model.value[0] === model.value[1] && model.value[1] === min.value && e.relatedTarget !== stopThumbRef.value?.$el) {
  17184. startThumbRef.value?.$el.blur();
  17185. stopThumbRef.value?.$el.focus();
  17186. }
  17187. },
  17188. "onBlur": () => {
  17189. blur();
  17190. activeThumbRef.value = undefined;
  17191. },
  17192. "min": min.value,
  17193. "max": model.value[1],
  17194. "position": trackStart.value
  17195. }, {
  17196. 'thumb-label': slots['thumb-label']
  17197. }), vue.createVNode(VSliderThumb, {
  17198. "ref": stopThumbRef,
  17199. "aria-describedby": messagesId.value,
  17200. "focused": isFocused && activeThumbRef.value === stopThumbRef.value?.$el,
  17201. "modelValue": model.value[1],
  17202. "onUpdate:modelValue": v => model.value = [model.value[0], v],
  17203. "onFocus": e => {
  17204. focus();
  17205. activeThumbRef.value = stopThumbRef.value?.$el;
  17206. // Make sure first thumb is focused if
  17207. // the thumbs are on top of each other
  17208. // and they are both at maximum value
  17209. // but only if focused from outside.
  17210. if (model.value[0] === model.value[1] && model.value[0] === max.value && e.relatedTarget !== startThumbRef.value?.$el) {
  17211. stopThumbRef.value?.$el.blur();
  17212. startThumbRef.value?.$el.focus();
  17213. }
  17214. },
  17215. "onBlur": () => {
  17216. blur();
  17217. activeThumbRef.value = undefined;
  17218. },
  17219. "min": model.value[0],
  17220. "max": max.value,
  17221. "position": trackStop.value
  17222. }, {
  17223. 'thumb-label': slots['thumb-label']
  17224. })]);
  17225. }
  17226. });
  17227. });
  17228. return {};
  17229. }
  17230. });
  17231. // Types
  17232. const makeVRatingProps = propsFactory({
  17233. name: String,
  17234. itemAriaLabel: {
  17235. type: String,
  17236. default: '$vuetify.rating.ariaLabel.item'
  17237. },
  17238. activeColor: String,
  17239. color: String,
  17240. clearable: Boolean,
  17241. disabled: Boolean,
  17242. emptyIcon: {
  17243. type: IconValue,
  17244. default: '$ratingEmpty'
  17245. },
  17246. fullIcon: {
  17247. type: IconValue,
  17248. default: '$ratingFull'
  17249. },
  17250. halfIncrements: Boolean,
  17251. hover: Boolean,
  17252. length: {
  17253. type: [Number, String],
  17254. default: 5
  17255. },
  17256. readonly: Boolean,
  17257. modelValue: {
  17258. type: [Number, String],
  17259. default: 0
  17260. },
  17261. itemLabels: Array,
  17262. itemLabelPosition: {
  17263. type: String,
  17264. default: 'top',
  17265. validator: v => ['top', 'bottom'].includes(v)
  17266. },
  17267. ripple: Boolean,
  17268. ...makeComponentProps(),
  17269. ...makeDensityProps(),
  17270. ...makeSizeProps(),
  17271. ...makeTagProps(),
  17272. ...makeThemeProps()
  17273. }, 'VRating');
  17274. const VRating = genericComponent()({
  17275. name: 'VRating',
  17276. props: makeVRatingProps(),
  17277. emits: {
  17278. 'update:modelValue': value => true
  17279. },
  17280. setup(props, _ref) {
  17281. let {
  17282. slots
  17283. } = _ref;
  17284. const {
  17285. t
  17286. } = useLocale();
  17287. const {
  17288. themeClasses
  17289. } = provideTheme(props);
  17290. const rating = useProxiedModel(props, 'modelValue');
  17291. const normalizedValue = vue.computed(() => clamp(parseFloat(rating.value), 0, +props.length));
  17292. const range = vue.computed(() => createRange(Number(props.length), 1));
  17293. const increments = vue.computed(() => range.value.flatMap(v => props.halfIncrements ? [v - 0.5, v] : [v]));
  17294. const hoverIndex = vue.shallowRef(-1);
  17295. const itemState = vue.computed(() => increments.value.map(value => {
  17296. const isHovering = props.hover && hoverIndex.value > -1;
  17297. const isFilled = normalizedValue.value >= value;
  17298. const isHovered = hoverIndex.value >= value;
  17299. const isFullIcon = isHovering ? isHovered : isFilled;
  17300. const icon = isFullIcon ? props.fullIcon : props.emptyIcon;
  17301. const activeColor = props.activeColor ?? props.color;
  17302. const color = isFilled || isHovered ? activeColor : props.color;
  17303. return {
  17304. isFilled,
  17305. isHovered,
  17306. icon,
  17307. color
  17308. };
  17309. }));
  17310. const eventState = vue.computed(() => [0, ...increments.value].map(value => {
  17311. function onMouseenter() {
  17312. hoverIndex.value = value;
  17313. }
  17314. function onMouseleave() {
  17315. hoverIndex.value = -1;
  17316. }
  17317. function onClick() {
  17318. if (props.disabled || props.readonly) return;
  17319. rating.value = normalizedValue.value === value && props.clearable ? 0 : value;
  17320. }
  17321. return {
  17322. onMouseenter: props.hover ? onMouseenter : undefined,
  17323. onMouseleave: props.hover ? onMouseleave : undefined,
  17324. onClick
  17325. };
  17326. }));
  17327. const name = vue.computed(() => props.name ?? `v-rating-${getUid()}`);
  17328. function VRatingItem(_ref2) {
  17329. let {
  17330. value,
  17331. index,
  17332. showStar = true
  17333. } = _ref2;
  17334. const {
  17335. onMouseenter,
  17336. onMouseleave,
  17337. onClick
  17338. } = eventState.value[index + 1];
  17339. const id = `${name.value}-${String(value).replace('.', '-')}`;
  17340. const btnProps = {
  17341. color: itemState.value[index]?.color,
  17342. density: props.density,
  17343. disabled: props.disabled,
  17344. icon: itemState.value[index]?.icon,
  17345. ripple: props.ripple,
  17346. size: props.size,
  17347. variant: 'plain'
  17348. };
  17349. return vue.createVNode(vue.Fragment, null, [vue.createVNode("label", {
  17350. "for": id,
  17351. "class": {
  17352. 'v-rating__item--half': props.halfIncrements && value % 1 > 0,
  17353. 'v-rating__item--full': props.halfIncrements && value % 1 === 0
  17354. },
  17355. "onMouseenter": onMouseenter,
  17356. "onMouseleave": onMouseleave,
  17357. "onClick": onClick
  17358. }, [vue.createVNode("span", {
  17359. "class": "v-rating__hidden"
  17360. }, [t(props.itemAriaLabel, value, props.length)]), !showStar ? undefined : slots.item ? slots.item({
  17361. ...itemState.value[index],
  17362. props: btnProps,
  17363. value,
  17364. index,
  17365. rating: normalizedValue.value
  17366. }) : vue.createVNode(VBtn, vue.mergeProps({
  17367. "aria-label": t(props.itemAriaLabel, value, props.length)
  17368. }, btnProps), null)]), vue.createVNode("input", {
  17369. "class": "v-rating__hidden",
  17370. "name": name.value,
  17371. "id": id,
  17372. "type": "radio",
  17373. "value": value,
  17374. "checked": normalizedValue.value === value,
  17375. "tabindex": -1,
  17376. "readonly": props.readonly,
  17377. "disabled": props.disabled
  17378. }, null)]);
  17379. }
  17380. function createLabel(labelProps) {
  17381. if (slots['item-label']) return slots['item-label'](labelProps);
  17382. if (labelProps.label) return vue.createVNode("span", null, [labelProps.label]);
  17383. return vue.createVNode("span", null, [vue.createTextVNode("\xA0")]);
  17384. }
  17385. useRender(() => {
  17386. const hasLabels = !!props.itemLabels?.length || slots['item-label'];
  17387. return vue.createVNode(props.tag, {
  17388. "class": ['v-rating', {
  17389. 'v-rating--hover': props.hover,
  17390. 'v-rating--readonly': props.readonly
  17391. }, themeClasses.value, props.class],
  17392. "style": props.style
  17393. }, {
  17394. default: () => [vue.createVNode(VRatingItem, {
  17395. "value": 0,
  17396. "index": -1,
  17397. "showStar": false
  17398. }, null), range.value.map((value, i) => vue.createVNode("div", {
  17399. "class": "v-rating__wrapper"
  17400. }, [hasLabels && props.itemLabelPosition === 'top' ? createLabel({
  17401. value,
  17402. index: i,
  17403. label: props.itemLabels?.[i]
  17404. }) : undefined, vue.createVNode("div", {
  17405. "class": "v-rating__item"
  17406. }, [props.halfIncrements ? vue.createVNode(vue.Fragment, null, [vue.createVNode(VRatingItem, {
  17407. "value": value - 0.5,
  17408. "index": i * 2
  17409. }, null), vue.createVNode(VRatingItem, {
  17410. "value": value,
  17411. "index": i * 2 + 1
  17412. }, null)]) : vue.createVNode(VRatingItem, {
  17413. "value": value,
  17414. "index": i
  17415. }, null)]), hasLabels && props.itemLabelPosition === 'bottom' ? createLabel({
  17416. value,
  17417. index: i,
  17418. label: props.itemLabels?.[i]
  17419. }) : undefined]))]
  17420. });
  17421. });
  17422. return {};
  17423. }
  17424. });
  17425. function bias(val) {
  17426. const c = 0.501;
  17427. const x = Math.abs(val);
  17428. return Math.sign(val) * (x / ((1 / c - 2) * (1 - x) + 1));
  17429. }
  17430. function calculateUpdatedOffset(_ref) {
  17431. let {
  17432. selectedElement,
  17433. containerSize,
  17434. contentSize,
  17435. isRtl,
  17436. currentScrollOffset,
  17437. isHorizontal
  17438. } = _ref;
  17439. const clientSize = isHorizontal ? selectedElement.clientWidth : selectedElement.clientHeight;
  17440. const offsetStart = isHorizontal ? selectedElement.offsetLeft : selectedElement.offsetTop;
  17441. const adjustedOffsetStart = isRtl && isHorizontal ? contentSize - offsetStart - clientSize : offsetStart;
  17442. const totalSize = containerSize + currentScrollOffset;
  17443. const itemOffset = clientSize + adjustedOffsetStart;
  17444. const additionalOffset = clientSize * 0.4;
  17445. if (adjustedOffsetStart <= currentScrollOffset) {
  17446. currentScrollOffset = Math.max(adjustedOffsetStart - additionalOffset, 0);
  17447. } else if (totalSize <= itemOffset) {
  17448. currentScrollOffset = Math.min(currentScrollOffset - (totalSize - itemOffset - additionalOffset), contentSize - containerSize);
  17449. }
  17450. return currentScrollOffset;
  17451. }
  17452. function calculateCenteredOffset(_ref2) {
  17453. let {
  17454. selectedElement,
  17455. containerSize,
  17456. contentSize,
  17457. isRtl,
  17458. isHorizontal
  17459. } = _ref2;
  17460. const clientSize = isHorizontal ? selectedElement.clientWidth : selectedElement.clientHeight;
  17461. const offsetStart = isHorizontal ? selectedElement.offsetLeft : selectedElement.offsetTop;
  17462. const offsetCentered = isRtl && isHorizontal ? contentSize - offsetStart - clientSize / 2 - containerSize / 2 : offsetStart + clientSize / 2 - containerSize / 2;
  17463. return Math.min(contentSize - containerSize, Math.max(0, offsetCentered));
  17464. }
  17465. // Types
  17466. const VSlideGroupSymbol = Symbol.for('vuetify:v-slide-group');
  17467. const makeVSlideGroupProps = propsFactory({
  17468. centerActive: Boolean,
  17469. direction: {
  17470. type: String,
  17471. default: 'horizontal'
  17472. },
  17473. symbol: {
  17474. type: null,
  17475. default: VSlideGroupSymbol
  17476. },
  17477. nextIcon: {
  17478. type: IconValue,
  17479. default: '$next'
  17480. },
  17481. prevIcon: {
  17482. type: IconValue,
  17483. default: '$prev'
  17484. },
  17485. showArrows: {
  17486. type: [Boolean, String],
  17487. validator: v => typeof v === 'boolean' || ['always', 'desktop', 'mobile'].includes(v)
  17488. },
  17489. ...makeComponentProps(),
  17490. ...makeTagProps(),
  17491. ...makeGroupProps({
  17492. selectedClass: 'v-slide-group-item--active'
  17493. })
  17494. }, 'VSlideGroup');
  17495. const VSlideGroup = genericComponent()({
  17496. name: 'VSlideGroup',
  17497. props: makeVSlideGroupProps(),
  17498. emits: {
  17499. 'update:modelValue': value => true
  17500. },
  17501. setup(props, _ref) {
  17502. let {
  17503. slots
  17504. } = _ref;
  17505. const {
  17506. isRtl
  17507. } = useRtl();
  17508. const {
  17509. mobile
  17510. } = useDisplay();
  17511. const group = useGroup(props, props.symbol);
  17512. const isOverflowing = vue.shallowRef(false);
  17513. const scrollOffset = vue.shallowRef(0);
  17514. const containerSize = vue.shallowRef(0);
  17515. const contentSize = vue.shallowRef(0);
  17516. const isHorizontal = vue.computed(() => props.direction === 'horizontal');
  17517. const {
  17518. resizeRef: containerRef,
  17519. contentRect: containerRect
  17520. } = useResizeObserver();
  17521. const {
  17522. resizeRef: contentRef,
  17523. contentRect
  17524. } = useResizeObserver();
  17525. const firstSelectedIndex = vue.computed(() => {
  17526. if (!group.selected.value.length) return -1;
  17527. return group.items.value.findIndex(item => item.id === group.selected.value[0]);
  17528. });
  17529. const lastSelectedIndex = vue.computed(() => {
  17530. if (!group.selected.value.length) return -1;
  17531. return group.items.value.findIndex(item => item.id === group.selected.value[group.selected.value.length - 1]);
  17532. });
  17533. if (IN_BROWSER) {
  17534. let frame = -1;
  17535. vue.watch(() => [group.selected.value, containerRect.value, contentRect.value, isHorizontal.value], () => {
  17536. cancelAnimationFrame(frame);
  17537. frame = requestAnimationFrame(() => {
  17538. if (containerRect.value && contentRect.value) {
  17539. const sizeProperty = isHorizontal.value ? 'width' : 'height';
  17540. containerSize.value = containerRect.value[sizeProperty];
  17541. contentSize.value = contentRect.value[sizeProperty];
  17542. isOverflowing.value = containerSize.value + 1 < contentSize.value;
  17543. }
  17544. if (firstSelectedIndex.value >= 0 && contentRef.value) {
  17545. // TODO: Is this too naive? Should we store element references in group composable?
  17546. const selectedElement = contentRef.value.children[lastSelectedIndex.value];
  17547. if (firstSelectedIndex.value === 0 || !isOverflowing.value) {
  17548. scrollOffset.value = 0;
  17549. } else if (props.centerActive) {
  17550. scrollOffset.value = calculateCenteredOffset({
  17551. selectedElement,
  17552. containerSize: containerSize.value,
  17553. contentSize: contentSize.value,
  17554. isRtl: isRtl.value,
  17555. isHorizontal: isHorizontal.value
  17556. });
  17557. } else if (isOverflowing.value) {
  17558. scrollOffset.value = calculateUpdatedOffset({
  17559. selectedElement,
  17560. containerSize: containerSize.value,
  17561. contentSize: contentSize.value,
  17562. isRtl: isRtl.value,
  17563. currentScrollOffset: scrollOffset.value,
  17564. isHorizontal: isHorizontal.value
  17565. });
  17566. }
  17567. }
  17568. });
  17569. });
  17570. }
  17571. const disableTransition = vue.shallowRef(false);
  17572. let startTouch = 0;
  17573. let startOffset = 0;
  17574. function onTouchstart(e) {
  17575. const sizeProperty = isHorizontal.value ? 'clientX' : 'clientY';
  17576. const sign = isRtl.value && isHorizontal.value ? -1 : 1;
  17577. startOffset = sign * scrollOffset.value;
  17578. startTouch = e.touches[0][sizeProperty];
  17579. disableTransition.value = true;
  17580. }
  17581. function onTouchmove(e) {
  17582. if (!isOverflowing.value) return;
  17583. const sizeProperty = isHorizontal.value ? 'clientX' : 'clientY';
  17584. const sign = isRtl.value && isHorizontal.value ? -1 : 1;
  17585. scrollOffset.value = sign * (startOffset + startTouch - e.touches[0][sizeProperty]);
  17586. }
  17587. function onTouchend(e) {
  17588. const maxScrollOffset = contentSize.value - containerSize.value;
  17589. if (scrollOffset.value < 0 || !isOverflowing.value) {
  17590. scrollOffset.value = 0;
  17591. } else if (scrollOffset.value >= maxScrollOffset) {
  17592. scrollOffset.value = maxScrollOffset;
  17593. }
  17594. disableTransition.value = false;
  17595. }
  17596. function onScroll() {
  17597. if (!containerRef.value) return;
  17598. containerRef.value[isHorizontal.value ? 'scrollLeft' : 'scrollTop'] = 0;
  17599. }
  17600. const isFocused = vue.shallowRef(false);
  17601. function onFocusin(e) {
  17602. isFocused.value = true;
  17603. if (!isOverflowing.value || !contentRef.value) return;
  17604. // Focused element is likely to be the root of an item, so a
  17605. // breadth-first search will probably find it in the first iteration
  17606. for (const el of e.composedPath()) {
  17607. for (const item of contentRef.value.children) {
  17608. if (item === el) {
  17609. scrollOffset.value = calculateUpdatedOffset({
  17610. selectedElement: item,
  17611. containerSize: containerSize.value,
  17612. contentSize: contentSize.value,
  17613. isRtl: isRtl.value,
  17614. currentScrollOffset: scrollOffset.value,
  17615. isHorizontal: isHorizontal.value
  17616. });
  17617. return;
  17618. }
  17619. }
  17620. }
  17621. }
  17622. function onFocusout(e) {
  17623. isFocused.value = false;
  17624. }
  17625. function onFocus(e) {
  17626. if (!isFocused.value && !(e.relatedTarget && contentRef.value?.contains(e.relatedTarget))) focus();
  17627. }
  17628. function onKeydown(e) {
  17629. if (!contentRef.value) return;
  17630. if (isHorizontal.value) {
  17631. if (e.key === 'ArrowRight') {
  17632. focus(isRtl.value ? 'prev' : 'next');
  17633. } else if (e.key === 'ArrowLeft') {
  17634. focus(isRtl.value ? 'next' : 'prev');
  17635. }
  17636. } else {
  17637. if (e.key === 'ArrowDown') {
  17638. focus('next');
  17639. } else if (e.key === 'ArrowUp') {
  17640. focus('prev');
  17641. }
  17642. }
  17643. if (e.key === 'Home') {
  17644. focus('first');
  17645. } else if (e.key === 'End') {
  17646. focus('last');
  17647. }
  17648. }
  17649. function focus(location) {
  17650. if (!contentRef.value) return;
  17651. if (!location) {
  17652. const focusable = focusableChildren(contentRef.value);
  17653. focusable[0]?.focus();
  17654. } else if (location === 'next') {
  17655. const el = contentRef.value.querySelector(':focus')?.nextElementSibling;
  17656. if (el) el.focus();else focus('first');
  17657. } else if (location === 'prev') {
  17658. const el = contentRef.value.querySelector(':focus')?.previousElementSibling;
  17659. if (el) el.focus();else focus('last');
  17660. } else if (location === 'first') {
  17661. contentRef.value.firstElementChild?.focus();
  17662. } else if (location === 'last') {
  17663. contentRef.value.lastElementChild?.focus();
  17664. }
  17665. }
  17666. function scrollTo(location) {
  17667. const newAbsoluteOffset = scrollOffset.value + (location === 'prev' ? -1 : 1) * containerSize.value;
  17668. scrollOffset.value = clamp(newAbsoluteOffset, 0, contentSize.value - containerSize.value);
  17669. }
  17670. const contentStyles = vue.computed(() => {
  17671. // This adds friction when scrolling the 'wrong' way when at max offset
  17672. let scrollAmount = scrollOffset.value > contentSize.value - containerSize.value ? -(contentSize.value - containerSize.value) + bias(contentSize.value - containerSize.value - scrollOffset.value) : -scrollOffset.value;
  17673. // This adds friction when scrolling the 'wrong' way when at min offset
  17674. if (scrollOffset.value <= 0) {
  17675. scrollAmount = bias(-scrollOffset.value);
  17676. }
  17677. const sign = isRtl.value && isHorizontal.value ? -1 : 1;
  17678. return {
  17679. transform: `translate${isHorizontal.value ? 'X' : 'Y'}(${sign * scrollAmount}px)`,
  17680. transition: disableTransition.value ? 'none' : '',
  17681. willChange: disableTransition.value ? 'transform' : ''
  17682. };
  17683. });
  17684. const slotProps = vue.computed(() => ({
  17685. next: group.next,
  17686. prev: group.prev,
  17687. select: group.select,
  17688. isSelected: group.isSelected
  17689. }));
  17690. const hasAffixes = vue.computed(() => {
  17691. switch (props.showArrows) {
  17692. // Always show arrows on desktop & mobile
  17693. case 'always':
  17694. return true;
  17695. // Always show arrows on desktop
  17696. case 'desktop':
  17697. return !mobile.value;
  17698. // Show arrows on mobile when overflowing.
  17699. // This matches the default 2.2 behavior
  17700. case true:
  17701. return isOverflowing.value || Math.abs(scrollOffset.value) > 0;
  17702. // Always show on mobile
  17703. case 'mobile':
  17704. return mobile.value || isOverflowing.value || Math.abs(scrollOffset.value) > 0;
  17705. // https://material.io/components/tabs#scrollable-tabs
  17706. // Always show arrows when
  17707. // overflowed on desktop
  17708. default:
  17709. return !mobile.value && (isOverflowing.value || Math.abs(scrollOffset.value) > 0);
  17710. }
  17711. });
  17712. const hasPrev = vue.computed(() => {
  17713. return Math.abs(scrollOffset.value) > 0;
  17714. });
  17715. const hasNext = vue.computed(() => {
  17716. // Check one scroll ahead to know the width of right-most item
  17717. return contentSize.value > Math.abs(scrollOffset.value) + containerSize.value;
  17718. });
  17719. useRender(() => vue.createVNode(props.tag, {
  17720. "class": ['v-slide-group', {
  17721. 'v-slide-group--vertical': !isHorizontal.value,
  17722. 'v-slide-group--has-affixes': hasAffixes.value,
  17723. 'v-slide-group--is-overflowing': isOverflowing.value
  17724. }, props.class],
  17725. "style": props.style,
  17726. "tabindex": isFocused.value || group.selected.value.length ? -1 : 0,
  17727. "onFocus": onFocus
  17728. }, {
  17729. default: () => [hasAffixes.value && vue.createVNode("div", {
  17730. "key": "prev",
  17731. "class": ['v-slide-group__prev', {
  17732. 'v-slide-group__prev--disabled': !hasPrev.value
  17733. }],
  17734. "onClick": () => scrollTo('prev')
  17735. }, [slots.prev?.(slotProps.value) ?? vue.createVNode(VFadeTransition, null, {
  17736. default: () => [vue.createVNode(VIcon, {
  17737. "icon": isRtl.value ? props.nextIcon : props.prevIcon
  17738. }, null)]
  17739. })]), vue.createVNode("div", {
  17740. "key": "container",
  17741. "ref": containerRef,
  17742. "class": "v-slide-group__container",
  17743. "onScroll": onScroll
  17744. }, [vue.createVNode("div", {
  17745. "ref": contentRef,
  17746. "class": "v-slide-group__content",
  17747. "style": contentStyles.value,
  17748. "onTouchstartPassive": onTouchstart,
  17749. "onTouchmovePassive": onTouchmove,
  17750. "onTouchendPassive": onTouchend,
  17751. "onFocusin": onFocusin,
  17752. "onFocusout": onFocusout,
  17753. "onKeydown": onKeydown
  17754. }, [slots.default?.(slotProps.value)])]), hasAffixes.value && vue.createVNode("div", {
  17755. "key": "next",
  17756. "class": ['v-slide-group__next', {
  17757. 'v-slide-group__next--disabled': !hasNext.value
  17758. }],
  17759. "onClick": () => scrollTo('next')
  17760. }, [slots.next?.(slotProps.value) ?? vue.createVNode(VFadeTransition, null, {
  17761. default: () => [vue.createVNode(VIcon, {
  17762. "icon": isRtl.value ? props.prevIcon : props.nextIcon
  17763. }, null)]
  17764. })])]
  17765. }));
  17766. return {
  17767. selected: group.selected,
  17768. scrollTo,
  17769. scrollOffset,
  17770. focus
  17771. };
  17772. }
  17773. });
  17774. // Composables
  17775. // Types
  17776. const VSlideGroupItem = genericComponent()({
  17777. name: 'VSlideGroupItem',
  17778. props: makeGroupItemProps(),
  17779. emits: {
  17780. 'group:selected': val => true
  17781. },
  17782. setup(props, _ref) {
  17783. let {
  17784. slots
  17785. } = _ref;
  17786. const slideGroupItem = useGroupItem(props, VSlideGroupSymbol);
  17787. return () => slots.default?.({
  17788. isSelected: slideGroupItem.isSelected.value,
  17789. select: slideGroupItem.select,
  17790. toggle: slideGroupItem.toggle,
  17791. selectedClass: slideGroupItem.selectedClass.value
  17792. });
  17793. }
  17794. });
  17795. const makeVSnackbarProps = propsFactory({
  17796. multiLine: Boolean,
  17797. timeout: {
  17798. type: [Number, String],
  17799. default: 5000
  17800. },
  17801. vertical: Boolean,
  17802. ...makeLocationProps({
  17803. location: 'bottom'
  17804. }),
  17805. ...makePositionProps(),
  17806. ...makeRoundedProps(),
  17807. ...makeVariantProps(),
  17808. ...makeThemeProps(),
  17809. ...omit(makeVOverlayProps({
  17810. transition: 'v-snackbar-transition'
  17811. }), ['persistent', 'noClickAnimation', 'scrim', 'scrollStrategy'])
  17812. }, 'VSnackbar');
  17813. const VSnackbar = genericComponent()({
  17814. name: 'VSnackbar',
  17815. props: makeVSnackbarProps(),
  17816. emits: {
  17817. 'update:modelValue': v => true
  17818. },
  17819. setup(props, _ref) {
  17820. let {
  17821. slots
  17822. } = _ref;
  17823. const isActive = useProxiedModel(props, 'modelValue');
  17824. const {
  17825. locationStyles
  17826. } = useLocation(props);
  17827. const {
  17828. positionClasses
  17829. } = usePosition(props);
  17830. const {
  17831. scopeId
  17832. } = useScopeId();
  17833. const {
  17834. themeClasses
  17835. } = provideTheme(props);
  17836. const {
  17837. colorClasses,
  17838. colorStyles,
  17839. variantClasses
  17840. } = useVariant(props);
  17841. const {
  17842. roundedClasses
  17843. } = useRounded(props);
  17844. const overlay = vue.ref();
  17845. vue.watch(isActive, startTimeout);
  17846. vue.watch(() => props.timeout, startTimeout);
  17847. vue.onMounted(() => {
  17848. if (isActive.value) startTimeout();
  17849. });
  17850. let activeTimeout = -1;
  17851. function startTimeout() {
  17852. window.clearTimeout(activeTimeout);
  17853. const timeout = Number(props.timeout);
  17854. if (!isActive.value || timeout === -1) return;
  17855. activeTimeout = window.setTimeout(() => {
  17856. isActive.value = false;
  17857. }, timeout);
  17858. }
  17859. function onPointerenter() {
  17860. window.clearTimeout(activeTimeout);
  17861. }
  17862. useRender(() => {
  17863. const [overlayProps] = VOverlay.filterProps(props);
  17864. return vue.createVNode(VOverlay, vue.mergeProps({
  17865. "ref": overlay,
  17866. "class": ['v-snackbar', {
  17867. 'v-snackbar--active': isActive.value,
  17868. 'v-snackbar--multi-line': props.multiLine && !props.vertical,
  17869. 'v-snackbar--vertical': props.vertical
  17870. }, positionClasses.value, props.class],
  17871. "style": props.style
  17872. }, overlayProps, {
  17873. "modelValue": isActive.value,
  17874. "onUpdate:modelValue": $event => isActive.value = $event,
  17875. "contentProps": vue.mergeProps({
  17876. class: ['v-snackbar__wrapper', themeClasses.value, colorClasses.value, roundedClasses.value, variantClasses.value],
  17877. style: [locationStyles.value, colorStyles.value],
  17878. onPointerenter,
  17879. onPointerleave: startTimeout
  17880. }, overlayProps.contentProps),
  17881. "persistent": true,
  17882. "noClickAnimation": true,
  17883. "scrim": false,
  17884. "scrollStrategy": "none",
  17885. "_disableGlobalStack": true
  17886. }, scopeId), {
  17887. default: () => [genOverlays(false, 'v-snackbar'), slots.default && vue.createVNode("div", {
  17888. "class": "v-snackbar__content",
  17889. "role": "status",
  17890. "aria-live": "polite"
  17891. }, [slots.default()]), slots.actions && vue.createVNode(VDefaultsProvider, {
  17892. "defaults": {
  17893. VBtn: {
  17894. variant: 'text',
  17895. ripple: false
  17896. }
  17897. }
  17898. }, {
  17899. default: () => [vue.createVNode("div", {
  17900. "class": "v-snackbar__actions"
  17901. }, [slots.actions()])]
  17902. })],
  17903. activator: slots.activator
  17904. });
  17905. });
  17906. return forwardRefs({}, overlay);
  17907. }
  17908. });
  17909. // Types
  17910. const makeVSwitchProps = propsFactory({
  17911. indeterminate: Boolean,
  17912. inset: Boolean,
  17913. flat: Boolean,
  17914. loading: {
  17915. type: [Boolean, String],
  17916. default: false
  17917. },
  17918. ...makeVInputProps(),
  17919. ...makeVSelectionControlProps()
  17920. }, 'VSwitch');
  17921. const VSwitch = genericComponent()({
  17922. name: 'VSwitch',
  17923. inheritAttrs: false,
  17924. props: makeVSwitchProps(),
  17925. emits: {
  17926. 'update:focused': focused => true,
  17927. 'update:modelValue': () => true,
  17928. 'update:indeterminate': val => true
  17929. },
  17930. setup(props, _ref) {
  17931. let {
  17932. attrs,
  17933. slots
  17934. } = _ref;
  17935. const indeterminate = useProxiedModel(props, 'indeterminate');
  17936. const model = useProxiedModel(props, 'modelValue');
  17937. const {
  17938. loaderClasses
  17939. } = useLoader(props);
  17940. const {
  17941. isFocused,
  17942. focus,
  17943. blur
  17944. } = useFocus(props);
  17945. const loaderColor = vue.computed(() => {
  17946. return typeof props.loading === 'string' && props.loading !== '' ? props.loading : props.color;
  17947. });
  17948. const uid = getUid();
  17949. const id = vue.computed(() => props.id || `switch-${uid}`);
  17950. function onChange() {
  17951. if (indeterminate.value) {
  17952. indeterminate.value = false;
  17953. }
  17954. }
  17955. useRender(() => {
  17956. const [inputAttrs, controlAttrs] = filterInputAttrs(attrs);
  17957. const [inputProps, _1] = VInput.filterProps(props);
  17958. const [controlProps, _2] = VSelectionControl.filterProps(props);
  17959. const control = vue.ref();
  17960. function onClick(e) {
  17961. e.stopPropagation();
  17962. e.preventDefault();
  17963. control.value?.input?.click();
  17964. }
  17965. return vue.createVNode(VInput, vue.mergeProps({
  17966. "class": ['v-switch', {
  17967. 'v-switch--inset': props.inset
  17968. }, {
  17969. 'v-switch--indeterminate': indeterminate.value
  17970. }, loaderClasses.value, props.class],
  17971. "style": props.style
  17972. }, inputAttrs, inputProps, {
  17973. "id": id.value,
  17974. "focused": isFocused.value
  17975. }), {
  17976. ...slots,
  17977. default: _ref2 => {
  17978. let {
  17979. id,
  17980. messagesId,
  17981. isDisabled,
  17982. isReadonly,
  17983. isValid
  17984. } = _ref2;
  17985. return vue.createVNode(VSelectionControl, vue.mergeProps({
  17986. "ref": control
  17987. }, controlProps, {
  17988. "modelValue": model.value,
  17989. "onUpdate:modelValue": [$event => model.value = $event, onChange],
  17990. "id": id.value,
  17991. "aria-describedby": messagesId.value,
  17992. "type": "checkbox",
  17993. "aria-checked": indeterminate.value ? 'mixed' : undefined,
  17994. "disabled": isDisabled.value,
  17995. "readonly": isReadonly.value,
  17996. "onFocus": focus,
  17997. "onBlur": blur
  17998. }, controlAttrs), {
  17999. ...slots,
  18000. default: () => vue.createVNode("div", {
  18001. "class": "v-switch__track",
  18002. "onClick": onClick
  18003. }, null),
  18004. input: _ref3 => {
  18005. let {
  18006. textColorClasses,
  18007. textColorStyles
  18008. } = _ref3;
  18009. return vue.createVNode("div", {
  18010. "class": ['v-switch__thumb', textColorClasses.value],
  18011. "style": textColorStyles.value
  18012. }, [props.loading && vue.createVNode(LoaderSlot, {
  18013. "name": "v-switch",
  18014. "active": true,
  18015. "color": isValid.value === false ? undefined : loaderColor.value
  18016. }, {
  18017. default: slotProps => slots.loader ? slots.loader(slotProps) : vue.createVNode(VProgressCircular, {
  18018. "active": slotProps.isActive,
  18019. "color": slotProps.color,
  18020. "indeterminate": true,
  18021. "size": "16",
  18022. "width": "2"
  18023. }, null)
  18024. })]);
  18025. }
  18026. });
  18027. }
  18028. });
  18029. });
  18030. return {};
  18031. }
  18032. });
  18033. const makeVSystemBarProps = propsFactory({
  18034. color: String,
  18035. height: [Number, String],
  18036. window: Boolean,
  18037. ...makeComponentProps(),
  18038. ...makeElevationProps(),
  18039. ...makeLayoutItemProps(),
  18040. ...makeRoundedProps(),
  18041. ...makeTagProps(),
  18042. ...makeThemeProps()
  18043. }, 'VSystemBar');
  18044. const VSystemBar = genericComponent()({
  18045. name: 'VSystemBar',
  18046. props: makeVSystemBarProps(),
  18047. setup(props, _ref) {
  18048. let {
  18049. slots
  18050. } = _ref;
  18051. const {
  18052. themeClasses
  18053. } = provideTheme(props);
  18054. const {
  18055. backgroundColorClasses,
  18056. backgroundColorStyles
  18057. } = useBackgroundColor(vue.toRef(props, 'color'));
  18058. const {
  18059. elevationClasses
  18060. } = useElevation(props);
  18061. const {
  18062. roundedClasses
  18063. } = useRounded(props);
  18064. const {
  18065. ssrBootStyles
  18066. } = useSsrBoot();
  18067. const height = vue.computed(() => props.height ?? (props.window ? 32 : 24));
  18068. const {
  18069. layoutItemStyles
  18070. } = useLayoutItem({
  18071. id: props.name,
  18072. order: vue.computed(() => parseInt(props.order, 10)),
  18073. position: vue.shallowRef('top'),
  18074. layoutSize: height,
  18075. elementSize: height,
  18076. active: vue.computed(() => true),
  18077. absolute: vue.toRef(props, 'absolute')
  18078. });
  18079. useRender(() => vue.createVNode(props.tag, {
  18080. "class": ['v-system-bar', {
  18081. 'v-system-bar--window': props.window
  18082. }, themeClasses.value, backgroundColorClasses.value, elevationClasses.value, roundedClasses.value, props.class],
  18083. "style": [backgroundColorStyles.value, layoutItemStyles.value, ssrBootStyles.value, props.style]
  18084. }, slots));
  18085. return {};
  18086. }
  18087. });
  18088. // Types
  18089. const VTabsSymbol = Symbol.for('vuetify:v-tabs');
  18090. // Types
  18091. const makeVTabProps = propsFactory({
  18092. fixed: Boolean,
  18093. sliderColor: String,
  18094. hideSlider: Boolean,
  18095. direction: {
  18096. type: String,
  18097. default: 'horizontal'
  18098. },
  18099. ...omit(makeVBtnProps({
  18100. selectedClass: 'v-tab--selected',
  18101. variant: 'text'
  18102. }), ['active', 'block', 'flat', 'location', 'position', 'symbol'])
  18103. }, 'VTab');
  18104. const VTab = genericComponent()({
  18105. name: 'VTab',
  18106. props: makeVTabProps(),
  18107. setup(props, _ref) {
  18108. let {
  18109. slots,
  18110. attrs
  18111. } = _ref;
  18112. const {
  18113. textColorClasses: sliderColorClasses,
  18114. textColorStyles: sliderColorStyles
  18115. } = useTextColor(props, 'sliderColor');
  18116. const isHorizontal = vue.computed(() => props.direction === 'horizontal');
  18117. const isSelected = vue.shallowRef(false);
  18118. const rootEl = vue.ref();
  18119. const sliderEl = vue.ref();
  18120. function updateSlider(_ref2) {
  18121. let {
  18122. value
  18123. } = _ref2;
  18124. isSelected.value = value;
  18125. if (value) {
  18126. const prevEl = rootEl.value?.$el.parentElement?.querySelector('.v-tab--selected .v-tab__slider');
  18127. const nextEl = sliderEl.value;
  18128. if (!prevEl || !nextEl) return;
  18129. const color = getComputedStyle(prevEl).color;
  18130. const prevBox = prevEl.getBoundingClientRect();
  18131. const nextBox = nextEl.getBoundingClientRect();
  18132. const xy = isHorizontal.value ? 'x' : 'y';
  18133. const XY = isHorizontal.value ? 'X' : 'Y';
  18134. const rightBottom = isHorizontal.value ? 'right' : 'bottom';
  18135. const widthHeight = isHorizontal.value ? 'width' : 'height';
  18136. const prevPos = prevBox[xy];
  18137. const nextPos = nextBox[xy];
  18138. const delta = prevPos > nextPos ? prevBox[rightBottom] - nextBox[rightBottom] : prevBox[xy] - nextBox[xy];
  18139. const origin = Math.sign(delta) > 0 ? isHorizontal.value ? 'right' : 'bottom' : Math.sign(delta) < 0 ? isHorizontal.value ? 'left' : 'top' : 'center';
  18140. const size = Math.abs(delta) + (Math.sign(delta) < 0 ? prevBox[widthHeight] : nextBox[widthHeight]);
  18141. const scale = size / Math.max(prevBox[widthHeight], nextBox[widthHeight]);
  18142. const initialScale = prevBox[widthHeight] / nextBox[widthHeight];
  18143. const sigma = 1.5;
  18144. animate(nextEl, {
  18145. backgroundColor: [color, 'currentcolor'],
  18146. transform: [`translate${XY}(${delta}px) scale${XY}(${initialScale})`, `translate${XY}(${delta / sigma}px) scale${XY}(${(scale - 1) / sigma + 1})`, 'none'],
  18147. transformOrigin: Array(3).fill(origin)
  18148. }, {
  18149. duration: 225,
  18150. easing: standardEasing
  18151. });
  18152. }
  18153. }
  18154. useRender(() => {
  18155. const [btnProps] = VBtn.filterProps(props);
  18156. return vue.createVNode(VBtn, vue.mergeProps({
  18157. "symbol": VTabsSymbol,
  18158. "ref": rootEl,
  18159. "class": ['v-tab', props.class],
  18160. "style": props.style,
  18161. "tabindex": isSelected.value ? 0 : -1,
  18162. "role": "tab",
  18163. "aria-selected": String(isSelected.value),
  18164. "active": false,
  18165. "block": props.fixed,
  18166. "maxWidth": props.fixed ? 300 : undefined,
  18167. "rounded": 0
  18168. }, btnProps, attrs, {
  18169. "onGroup:selected": updateSlider
  18170. }), {
  18171. default: () => [slots.default?.() ?? props.text, !props.hideSlider && vue.createVNode("div", {
  18172. "ref": sliderEl,
  18173. "class": ['v-tab__slider', sliderColorClasses.value],
  18174. "style": sliderColorStyles.value
  18175. }, null)]
  18176. });
  18177. });
  18178. return {};
  18179. }
  18180. });
  18181. function parseItems(items) {
  18182. if (!items) return [];
  18183. return items.map(item => {
  18184. if (typeof item === 'string') return {
  18185. title: item,
  18186. value: item
  18187. };
  18188. return item;
  18189. });
  18190. }
  18191. const makeVTabsProps = propsFactory({
  18192. alignTabs: {
  18193. type: String,
  18194. default: 'start'
  18195. },
  18196. color: String,
  18197. fixedTabs: Boolean,
  18198. items: {
  18199. type: Array,
  18200. default: () => []
  18201. },
  18202. stacked: Boolean,
  18203. bgColor: String,
  18204. grow: Boolean,
  18205. height: {
  18206. type: [Number, String],
  18207. default: undefined
  18208. },
  18209. hideSlider: Boolean,
  18210. sliderColor: String,
  18211. ...makeVSlideGroupProps({
  18212. mandatory: 'force'
  18213. }),
  18214. ...makeDensityProps(),
  18215. ...makeTagProps()
  18216. }, 'VTabs');
  18217. const VTabs = genericComponent()({
  18218. name: 'VTabs',
  18219. props: makeVTabsProps(),
  18220. emits: {
  18221. 'update:modelValue': v => true
  18222. },
  18223. setup(props, _ref) {
  18224. let {
  18225. slots
  18226. } = _ref;
  18227. const model = useProxiedModel(props, 'modelValue');
  18228. const parsedItems = vue.computed(() => parseItems(props.items));
  18229. const {
  18230. densityClasses
  18231. } = useDensity(props);
  18232. const {
  18233. backgroundColorClasses,
  18234. backgroundColorStyles
  18235. } = useBackgroundColor(vue.toRef(props, 'bgColor'));
  18236. provideDefaults({
  18237. VTab: {
  18238. color: vue.toRef(props, 'color'),
  18239. direction: vue.toRef(props, 'direction'),
  18240. stacked: vue.toRef(props, 'stacked'),
  18241. fixed: vue.toRef(props, 'fixedTabs'),
  18242. sliderColor: vue.toRef(props, 'sliderColor'),
  18243. hideSlider: vue.toRef(props, 'hideSlider')
  18244. }
  18245. });
  18246. useRender(() => {
  18247. const [slideGroupProps] = VSlideGroup.filterProps(props);
  18248. return vue.createVNode(VSlideGroup, vue.mergeProps(slideGroupProps, {
  18249. "modelValue": model.value,
  18250. "onUpdate:modelValue": $event => model.value = $event,
  18251. "class": ['v-tabs', `v-tabs--${props.direction}`, `v-tabs--align-tabs-${props.alignTabs}`, {
  18252. 'v-tabs--fixed-tabs': props.fixedTabs,
  18253. 'v-tabs--grow': props.grow,
  18254. 'v-tabs--stacked': props.stacked
  18255. }, densityClasses.value, backgroundColorClasses.value, props.class],
  18256. "style": [{
  18257. '--v-tabs-height': convertToUnit(props.height)
  18258. }, backgroundColorStyles.value, props.style],
  18259. "role": "tablist",
  18260. "symbol": VTabsSymbol
  18261. }), {
  18262. default: () => [slots.default ? slots.default() : parsedItems.value.map(item => vue.createVNode(VTab, vue.mergeProps(item, {
  18263. "key": item.title
  18264. }), null))]
  18265. });
  18266. });
  18267. return {};
  18268. }
  18269. });
  18270. const makeVTableProps = propsFactory({
  18271. fixedHeader: Boolean,
  18272. fixedFooter: Boolean,
  18273. height: [Number, String],
  18274. hover: Boolean,
  18275. ...makeComponentProps(),
  18276. ...makeDensityProps(),
  18277. ...makeTagProps(),
  18278. ...makeThemeProps()
  18279. }, 'VTable');
  18280. const VTable = genericComponent()({
  18281. name: 'VTable',
  18282. props: makeVTableProps(),
  18283. setup(props, _ref) {
  18284. let {
  18285. slots
  18286. } = _ref;
  18287. const {
  18288. themeClasses
  18289. } = provideTheme(props);
  18290. const {
  18291. densityClasses
  18292. } = useDensity(props);
  18293. useRender(() => vue.createVNode(props.tag, {
  18294. "class": ['v-table', {
  18295. 'v-table--fixed-height': !!props.height,
  18296. 'v-table--fixed-header': props.fixedHeader,
  18297. 'v-table--fixed-footer': props.fixedFooter,
  18298. 'v-table--has-top': !!slots.top,
  18299. 'v-table--has-bottom': !!slots.bottom,
  18300. 'v-table--hover': props.hover
  18301. }, themeClasses.value, densityClasses.value, props.class],
  18302. "style": props.style
  18303. }, {
  18304. default: () => [slots.top?.(), slots.default ? vue.createVNode("div", {
  18305. "class": "v-table__wrapper",
  18306. "style": {
  18307. height: convertToUnit(props.height)
  18308. }
  18309. }, [vue.createVNode("table", null, [slots.default()])]) : slots.wrapper?.(), slots.bottom?.()]
  18310. }));
  18311. return {};
  18312. }
  18313. });
  18314. // Types
  18315. const makeVTextareaProps = propsFactory({
  18316. autoGrow: Boolean,
  18317. autofocus: Boolean,
  18318. counter: [Boolean, Number, String],
  18319. counterValue: Function,
  18320. prefix: String,
  18321. placeholder: String,
  18322. persistentPlaceholder: Boolean,
  18323. persistentCounter: Boolean,
  18324. noResize: Boolean,
  18325. rows: {
  18326. type: [Number, String],
  18327. default: 5,
  18328. validator: v => !isNaN(parseFloat(v))
  18329. },
  18330. maxRows: {
  18331. type: [Number, String],
  18332. validator: v => !isNaN(parseFloat(v))
  18333. },
  18334. suffix: String,
  18335. modelModifiers: Object,
  18336. ...makeVInputProps(),
  18337. ...makeVFieldProps()
  18338. }, 'VTextarea');
  18339. const VTextarea = genericComponent()({
  18340. name: 'VTextarea',
  18341. directives: {
  18342. Intersect
  18343. },
  18344. inheritAttrs: false,
  18345. props: makeVTextareaProps(),
  18346. emits: {
  18347. 'click:control': e => true,
  18348. 'mousedown:control': e => true,
  18349. 'update:focused': focused => true,
  18350. 'update:modelValue': val => true
  18351. },
  18352. setup(props, _ref) {
  18353. let {
  18354. attrs,
  18355. emit,
  18356. slots
  18357. } = _ref;
  18358. const model = useProxiedModel(props, 'modelValue');
  18359. const {
  18360. isFocused,
  18361. focus,
  18362. blur
  18363. } = useFocus(props);
  18364. const counterValue = vue.computed(() => {
  18365. return typeof props.counterValue === 'function' ? props.counterValue(model.value) : (model.value || '').toString().length;
  18366. });
  18367. const max = vue.computed(() => {
  18368. if (attrs.maxlength) return attrs.maxlength;
  18369. if (!props.counter || typeof props.counter !== 'number' && typeof props.counter !== 'string') return undefined;
  18370. return props.counter;
  18371. });
  18372. function onIntersect(isIntersecting, entries) {
  18373. if (!props.autofocus || !isIntersecting) return;
  18374. entries[0].target?.focus?.();
  18375. }
  18376. const vInputRef = vue.ref();
  18377. const vFieldRef = vue.ref();
  18378. const controlHeight = vue.shallowRef('');
  18379. const textareaRef = vue.ref();
  18380. const isActive = vue.computed(() => props.persistentPlaceholder || isFocused.value || props.active);
  18381. function onFocus() {
  18382. if (textareaRef.value !== document.activeElement) {
  18383. textareaRef.value?.focus();
  18384. }
  18385. if (!isFocused.value) focus();
  18386. }
  18387. function onControlClick(e) {
  18388. onFocus();
  18389. emit('click:control', e);
  18390. }
  18391. function onControlMousedown(e) {
  18392. emit('mousedown:control', e);
  18393. }
  18394. function onClear(e) {
  18395. e.stopPropagation();
  18396. onFocus();
  18397. vue.nextTick(() => {
  18398. model.value = '';
  18399. callEvent(props['onClick:clear'], e);
  18400. });
  18401. }
  18402. function onInput(e) {
  18403. const el = e.target;
  18404. model.value = el.value;
  18405. if (props.modelModifiers?.trim) {
  18406. const caretPosition = [el.selectionStart, el.selectionEnd];
  18407. vue.nextTick(() => {
  18408. el.selectionStart = caretPosition[0];
  18409. el.selectionEnd = caretPosition[1];
  18410. });
  18411. }
  18412. }
  18413. const sizerRef = vue.ref();
  18414. const rows = vue.ref(+props.rows);
  18415. const isPlainOrUnderlined = vue.computed(() => ['plain', 'underlined'].includes(props.variant));
  18416. vue.watchEffect(() => {
  18417. if (!props.autoGrow) rows.value = +props.rows;
  18418. });
  18419. function calculateInputHeight() {
  18420. if (!props.autoGrow) return;
  18421. vue.nextTick(() => {
  18422. if (!sizerRef.value || !vFieldRef.value) return;
  18423. const style = getComputedStyle(sizerRef.value);
  18424. const fieldStyle = getComputedStyle(vFieldRef.value.$el);
  18425. const padding = parseFloat(style.getPropertyValue('--v-field-padding-top')) + parseFloat(style.getPropertyValue('--v-input-padding-top')) + parseFloat(style.getPropertyValue('--v-field-padding-bottom'));
  18426. const height = sizerRef.value.scrollHeight;
  18427. const lineHeight = parseFloat(style.lineHeight);
  18428. const minHeight = Math.max(parseFloat(props.rows) * lineHeight + padding, parseFloat(fieldStyle.getPropertyValue('--v-input-control-height')));
  18429. const maxHeight = parseFloat(props.maxRows) * lineHeight + padding || Infinity;
  18430. const newHeight = clamp(height ?? 0, minHeight, maxHeight);
  18431. rows.value = Math.floor((newHeight - padding) / lineHeight);
  18432. controlHeight.value = convertToUnit(newHeight);
  18433. });
  18434. }
  18435. vue.onMounted(calculateInputHeight);
  18436. vue.watch(model, calculateInputHeight);
  18437. vue.watch(() => props.rows, calculateInputHeight);
  18438. vue.watch(() => props.maxRows, calculateInputHeight);
  18439. vue.watch(() => props.density, calculateInputHeight);
  18440. let observer;
  18441. vue.watch(sizerRef, val => {
  18442. if (val) {
  18443. observer = new ResizeObserver(calculateInputHeight);
  18444. observer.observe(sizerRef.value);
  18445. } else {
  18446. observer?.disconnect();
  18447. }
  18448. });
  18449. vue.onBeforeUnmount(() => {
  18450. observer?.disconnect();
  18451. });
  18452. useRender(() => {
  18453. const hasCounter = !!(slots.counter || props.counter || props.counterValue);
  18454. const hasDetails = !!(hasCounter || slots.details);
  18455. const [rootAttrs, inputAttrs] = filterInputAttrs(attrs);
  18456. const [{
  18457. modelValue: _,
  18458. ...inputProps
  18459. }] = VInput.filterProps(props);
  18460. const [fieldProps] = filterFieldProps(props);
  18461. return vue.createVNode(VInput, vue.mergeProps({
  18462. "ref": vInputRef,
  18463. "modelValue": model.value,
  18464. "onUpdate:modelValue": $event => model.value = $event,
  18465. "class": ['v-textarea v-text-field', {
  18466. 'v-textarea--prefixed': props.prefix,
  18467. 'v-textarea--suffixed': props.suffix,
  18468. 'v-text-field--prefixed': props.prefix,
  18469. 'v-text-field--suffixed': props.suffix,
  18470. 'v-textarea--auto-grow': props.autoGrow,
  18471. 'v-textarea--no-resize': props.noResize || props.autoGrow,
  18472. 'v-text-field--plain-underlined': isPlainOrUnderlined.value
  18473. }, props.class],
  18474. "style": props.style
  18475. }, rootAttrs, inputProps, {
  18476. "centerAffix": rows.value === 1 && !isPlainOrUnderlined.value,
  18477. "focused": isFocused.value
  18478. }), {
  18479. ...slots,
  18480. default: _ref2 => {
  18481. let {
  18482. isDisabled,
  18483. isDirty,
  18484. isReadonly,
  18485. isValid
  18486. } = _ref2;
  18487. return vue.createVNode(VField, vue.mergeProps({
  18488. "ref": vFieldRef,
  18489. "style": {
  18490. '--v-textarea-control-height': controlHeight.value
  18491. },
  18492. "onClick": onControlClick,
  18493. "onMousedown": onControlMousedown,
  18494. "onClick:clear": onClear,
  18495. "onClick:prependInner": props['onClick:prependInner'],
  18496. "onClick:appendInner": props['onClick:appendInner'],
  18497. "role": "textbox"
  18498. }, fieldProps, {
  18499. "active": isActive.value || isDirty.value,
  18500. "centerAffix": rows.value === 1 && !isPlainOrUnderlined.value,
  18501. "dirty": isDirty.value || props.dirty,
  18502. "disabled": isDisabled.value,
  18503. "focused": isFocused.value,
  18504. "error": isValid.value === false
  18505. }), {
  18506. ...slots,
  18507. default: _ref3 => {
  18508. let {
  18509. props: {
  18510. class: fieldClass,
  18511. ...slotProps
  18512. }
  18513. } = _ref3;
  18514. return vue.createVNode(vue.Fragment, null, [props.prefix && vue.createVNode("span", {
  18515. "class": "v-text-field__prefix"
  18516. }, [props.prefix]), vue.withDirectives(vue.createVNode("textarea", vue.mergeProps({
  18517. "ref": textareaRef,
  18518. "class": fieldClass,
  18519. "value": model.value,
  18520. "onInput": onInput,
  18521. "autofocus": props.autofocus,
  18522. "readonly": isReadonly.value,
  18523. "disabled": isDisabled.value,
  18524. "placeholder": props.placeholder,
  18525. "rows": props.rows,
  18526. "name": props.name,
  18527. "onFocus": onFocus,
  18528. "onBlur": blur
  18529. }, slotProps, inputAttrs), null), [[vue.resolveDirective("intersect"), {
  18530. handler: onIntersect
  18531. }, null, {
  18532. once: true
  18533. }]]), props.autoGrow && vue.withDirectives(vue.createVNode("textarea", {
  18534. "class": [fieldClass, 'v-textarea__sizer'],
  18535. "onUpdate:modelValue": $event => model.value = $event,
  18536. "ref": sizerRef,
  18537. "readonly": true,
  18538. "aria-hidden": "true"
  18539. }, null), [[vue.vModelText, model.value]]), props.suffix && vue.createVNode("span", {
  18540. "class": "v-text-field__suffix"
  18541. }, [props.suffix])]);
  18542. }
  18543. });
  18544. },
  18545. 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, {
  18546. "active": props.persistentCounter || isFocused.value,
  18547. "value": counterValue.value,
  18548. "max": max.value
  18549. }, slots.counter)])]) : undefined
  18550. });
  18551. });
  18552. return forwardRefs({}, vInputRef, vFieldRef, textareaRef);
  18553. }
  18554. });
  18555. const makeVThemeProviderProps = propsFactory({
  18556. withBackground: Boolean,
  18557. ...makeComponentProps(),
  18558. ...makeThemeProps(),
  18559. ...makeTagProps()
  18560. }, 'VThemeProvider');
  18561. const VThemeProvider = genericComponent()({
  18562. name: 'VThemeProvider',
  18563. props: makeVThemeProviderProps(),
  18564. setup(props, _ref) {
  18565. let {
  18566. slots
  18567. } = _ref;
  18568. const {
  18569. themeClasses
  18570. } = provideTheme(props);
  18571. return () => {
  18572. if (!props.withBackground) return slots.default?.();
  18573. return vue.createVNode(props.tag, {
  18574. "class": ['v-theme-provider', themeClasses.value, props.class],
  18575. "style": props.style
  18576. }, {
  18577. default: () => [slots.default?.()]
  18578. });
  18579. };
  18580. }
  18581. });
  18582. // Types
  18583. const makeVTimelineProps = propsFactory({
  18584. align: {
  18585. type: String,
  18586. default: 'center',
  18587. validator: v => ['center', 'start'].includes(v)
  18588. },
  18589. direction: {
  18590. type: String,
  18591. default: 'vertical',
  18592. validator: v => ['vertical', 'horizontal'].includes(v)
  18593. },
  18594. justify: {
  18595. type: String,
  18596. default: 'auto',
  18597. validator: v => ['auto', 'center'].includes(v)
  18598. },
  18599. side: {
  18600. type: String,
  18601. validator: v => v == null || ['start', 'end'].includes(v)
  18602. },
  18603. lineInset: {
  18604. type: [String, Number],
  18605. default: 0
  18606. },
  18607. lineThickness: {
  18608. type: [String, Number],
  18609. default: 2
  18610. },
  18611. lineColor: String,
  18612. truncateLine: {
  18613. type: String,
  18614. validator: v => ['start', 'end', 'both'].includes(v)
  18615. },
  18616. ...makeComponentProps(),
  18617. ...makeDensityProps(),
  18618. ...makeTagProps(),
  18619. ...makeThemeProps()
  18620. }, 'VTimeline');
  18621. const VTimeline = genericComponent()({
  18622. name: 'VTimeline',
  18623. props: makeVTimelineProps(),
  18624. setup(props, _ref) {
  18625. let {
  18626. slots
  18627. } = _ref;
  18628. const {
  18629. themeClasses
  18630. } = provideTheme(props);
  18631. const {
  18632. densityClasses
  18633. } = useDensity(props);
  18634. const {
  18635. rtlClasses
  18636. } = useRtl();
  18637. provideDefaults({
  18638. VTimelineDivider: {
  18639. lineColor: vue.toRef(props, 'lineColor')
  18640. },
  18641. VTimelineItem: {
  18642. density: vue.toRef(props, 'density'),
  18643. lineInset: vue.toRef(props, 'lineInset')
  18644. }
  18645. });
  18646. const sideClasses = vue.computed(() => {
  18647. const side = props.side ? props.side : props.density !== 'default' ? 'end' : null;
  18648. return side && `v-timeline--side-${side}`;
  18649. });
  18650. const truncateClasses = vue.computed(() => {
  18651. const classes = ['v-timeline--truncate-line-start', 'v-timeline--truncate-line-end'];
  18652. switch (props.truncateLine) {
  18653. case 'both':
  18654. return classes;
  18655. case 'start':
  18656. return classes[0];
  18657. case 'end':
  18658. return classes[1];
  18659. default:
  18660. return null;
  18661. }
  18662. });
  18663. useRender(() => vue.createVNode(props.tag, {
  18664. "class": ['v-timeline', `v-timeline--${props.direction}`, `v-timeline--align-${props.align}`, `v-timeline--justify-${props.justify}`, truncateClasses.value, {
  18665. 'v-timeline--inset-line': !!props.lineInset
  18666. }, themeClasses.value, densityClasses.value, sideClasses.value, rtlClasses.value, props.class],
  18667. "style": [{
  18668. '--v-timeline-line-thickness': convertToUnit(props.lineThickness)
  18669. }, props.style]
  18670. }, slots));
  18671. return {};
  18672. }
  18673. });
  18674. const makeVTimelineDividerProps = propsFactory({
  18675. dotColor: String,
  18676. fillDot: Boolean,
  18677. hideDot: Boolean,
  18678. icon: IconValue,
  18679. iconColor: String,
  18680. lineColor: String,
  18681. ...makeComponentProps(),
  18682. ...makeRoundedProps(),
  18683. ...makeSizeProps(),
  18684. ...makeElevationProps()
  18685. }, 'VTimelineDivider');
  18686. const VTimelineDivider = genericComponent()({
  18687. name: 'VTimelineDivider',
  18688. props: makeVTimelineDividerProps(),
  18689. setup(props, _ref) {
  18690. let {
  18691. slots
  18692. } = _ref;
  18693. const {
  18694. sizeClasses,
  18695. sizeStyles
  18696. } = useSize(props, 'v-timeline-divider__dot');
  18697. const {
  18698. backgroundColorStyles,
  18699. backgroundColorClasses
  18700. } = useBackgroundColor(vue.toRef(props, 'dotColor'));
  18701. const {
  18702. roundedClasses
  18703. } = useRounded(props, 'v-timeline-divider__dot');
  18704. const {
  18705. elevationClasses
  18706. } = useElevation(props);
  18707. const {
  18708. backgroundColorClasses: lineColorClasses,
  18709. backgroundColorStyles: lineColorStyles
  18710. } = useBackgroundColor(vue.toRef(props, 'lineColor'));
  18711. useRender(() => vue.createVNode("div", {
  18712. "class": ['v-timeline-divider', {
  18713. 'v-timeline-divider--fill-dot': props.fillDot
  18714. }, props.class],
  18715. "style": props.style
  18716. }, [vue.createVNode("div", {
  18717. "class": ['v-timeline-divider__before', lineColorClasses.value],
  18718. "style": lineColorStyles.value
  18719. }, null), !props.hideDot && vue.createVNode("div", {
  18720. "key": "dot",
  18721. "class": ['v-timeline-divider__dot', elevationClasses.value, roundedClasses.value, sizeClasses.value],
  18722. "style": sizeStyles.value
  18723. }, [vue.createVNode("div", {
  18724. "class": ['v-timeline-divider__inner-dot', backgroundColorClasses.value, roundedClasses.value],
  18725. "style": backgroundColorStyles.value
  18726. }, [!slots.default ? vue.createVNode(VIcon, {
  18727. "key": "icon",
  18728. "color": props.iconColor,
  18729. "icon": props.icon,
  18730. "size": props.size
  18731. }, null) : vue.createVNode(VDefaultsProvider, {
  18732. "key": "icon-defaults",
  18733. "disabled": !props.icon,
  18734. "defaults": {
  18735. VIcon: {
  18736. color: props.iconColor,
  18737. icon: props.icon,
  18738. size: props.size
  18739. }
  18740. }
  18741. }, slots.default)])]), vue.createVNode("div", {
  18742. "class": ['v-timeline-divider__after', lineColorClasses.value],
  18743. "style": lineColorStyles.value
  18744. }, null)]));
  18745. return {};
  18746. }
  18747. });
  18748. // Types
  18749. const makeVTimelineItemProps = propsFactory({
  18750. density: String,
  18751. dotColor: String,
  18752. fillDot: Boolean,
  18753. hideDot: Boolean,
  18754. hideOpposite: {
  18755. type: Boolean,
  18756. default: undefined
  18757. },
  18758. icon: IconValue,
  18759. iconColor: String,
  18760. lineInset: [Number, String],
  18761. ...makeComponentProps(),
  18762. ...makeDimensionProps(),
  18763. ...makeElevationProps(),
  18764. ...makeRoundedProps(),
  18765. ...makeSizeProps(),
  18766. ...makeTagProps()
  18767. }, 'VTimelineItem');
  18768. const VTimelineItem = genericComponent()({
  18769. name: 'VTimelineItem',
  18770. props: makeVTimelineItemProps(),
  18771. setup(props, _ref) {
  18772. let {
  18773. slots
  18774. } = _ref;
  18775. const {
  18776. dimensionStyles
  18777. } = useDimension(props);
  18778. const dotSize = vue.shallowRef(0);
  18779. const dotRef = vue.ref();
  18780. vue.watch(dotRef, newValue => {
  18781. if (!newValue) return;
  18782. dotSize.value = newValue.$el.querySelector('.v-timeline-divider__dot')?.getBoundingClientRect().width ?? 0;
  18783. }, {
  18784. flush: 'post'
  18785. });
  18786. useRender(() => vue.createVNode("div", {
  18787. "class": ['v-timeline-item', {
  18788. 'v-timeline-item--fill-dot': props.fillDot
  18789. }, props.class],
  18790. "style": [{
  18791. '--v-timeline-dot-size': convertToUnit(dotSize.value),
  18792. '--v-timeline-line-inset': props.lineInset ? `calc(var(--v-timeline-dot-size) / 2 + ${convertToUnit(props.lineInset)})` : convertToUnit(0)
  18793. }, props.style]
  18794. }, [vue.createVNode("div", {
  18795. "class": "v-timeline-item__body",
  18796. "style": dimensionStyles.value
  18797. }, [slots.default?.()]), vue.createVNode(VTimelineDivider, {
  18798. "ref": dotRef,
  18799. "hideDot": props.hideDot,
  18800. "icon": props.icon,
  18801. "iconColor": props.iconColor,
  18802. "size": props.size,
  18803. "elevation": props.elevation,
  18804. "dotColor": props.dotColor,
  18805. "fillDot": props.fillDot,
  18806. "rounded": props.rounded
  18807. }, {
  18808. default: slots.icon
  18809. }), props.density !== 'compact' && vue.createVNode("div", {
  18810. "class": "v-timeline-item__opposite"
  18811. }, [!props.hideOpposite && slots.opposite?.()])]));
  18812. return {};
  18813. }
  18814. });
  18815. const makeVToolbarItemsProps = propsFactory({
  18816. ...makeComponentProps(),
  18817. ...makeVariantProps({
  18818. variant: 'text'
  18819. })
  18820. }, 'VToolbarItems');
  18821. const VToolbarItems = genericComponent()({
  18822. name: 'VToolbarItems',
  18823. props: makeVToolbarItemsProps(),
  18824. setup(props, _ref) {
  18825. let {
  18826. slots
  18827. } = _ref;
  18828. provideDefaults({
  18829. VBtn: {
  18830. color: vue.toRef(props, 'color'),
  18831. height: 'inherit',
  18832. variant: vue.toRef(props, 'variant')
  18833. }
  18834. });
  18835. useRender(() => vue.createVNode("div", {
  18836. "class": ['v-toolbar-items', props.class],
  18837. "style": props.style
  18838. }, [slots.default?.()]));
  18839. return {};
  18840. }
  18841. });
  18842. // Types
  18843. const makeVTooltipProps = propsFactory({
  18844. id: String,
  18845. text: String,
  18846. ...omit(makeVOverlayProps({
  18847. closeOnBack: false,
  18848. location: 'end',
  18849. locationStrategy: 'connected',
  18850. eager: true,
  18851. minWidth: 0,
  18852. offset: 10,
  18853. openOnClick: false,
  18854. openOnHover: true,
  18855. origin: 'auto',
  18856. scrim: false,
  18857. scrollStrategy: 'reposition',
  18858. transition: false
  18859. }), ['absolute', 'persistent'])
  18860. }, 'VTooltip');
  18861. const VTooltip = genericComponent()({
  18862. name: 'VTooltip',
  18863. props: makeVTooltipProps(),
  18864. emits: {
  18865. 'update:modelValue': value => true
  18866. },
  18867. setup(props, _ref) {
  18868. let {
  18869. slots
  18870. } = _ref;
  18871. const isActive = useProxiedModel(props, 'modelValue');
  18872. const {
  18873. scopeId
  18874. } = useScopeId();
  18875. const uid = getUid();
  18876. const id = vue.computed(() => props.id || `v-tooltip-${uid}`);
  18877. const overlay = vue.ref();
  18878. const location = vue.computed(() => {
  18879. return props.location.split(' ').length > 1 ? props.location : props.location + ' center';
  18880. });
  18881. const origin = vue.computed(() => {
  18882. return props.origin === 'auto' || props.origin === 'overlap' || props.origin.split(' ').length > 1 || props.location.split(' ').length > 1 ? props.origin : props.origin + ' center';
  18883. });
  18884. const transition = vue.computed(() => {
  18885. if (props.transition) return props.transition;
  18886. return isActive.value ? 'scale-transition' : 'fade-transition';
  18887. });
  18888. const activatorProps = vue.computed(() => vue.mergeProps({
  18889. 'aria-describedby': id.value
  18890. }, props.activatorProps));
  18891. useRender(() => {
  18892. const [overlayProps] = VOverlay.filterProps(props);
  18893. return vue.createVNode(VOverlay, vue.mergeProps({
  18894. "ref": overlay,
  18895. "class": ['v-tooltip', props.class],
  18896. "style": props.style,
  18897. "id": id.value
  18898. }, overlayProps, {
  18899. "modelValue": isActive.value,
  18900. "onUpdate:modelValue": $event => isActive.value = $event,
  18901. "transition": transition.value,
  18902. "absolute": true,
  18903. "location": location.value,
  18904. "origin": origin.value,
  18905. "persistent": true,
  18906. "role": "tooltip",
  18907. "activatorProps": activatorProps.value,
  18908. "_disableGlobalStack": true
  18909. }, scopeId), {
  18910. activator: slots.activator,
  18911. default: function () {
  18912. for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) {
  18913. args[_key] = arguments[_key];
  18914. }
  18915. return slots.default?.(...args) ?? props.text;
  18916. }
  18917. });
  18918. });
  18919. return forwardRefs({}, overlay);
  18920. }
  18921. });
  18922. // Composables
  18923. const VValidation = genericComponent()({
  18924. name: 'VValidation',
  18925. props: makeValidationProps(),
  18926. emits: {
  18927. 'update:modelValue': val => true
  18928. },
  18929. setup(props, _ref) {
  18930. let {
  18931. slots
  18932. } = _ref;
  18933. const validation = useValidation(props, 'validation');
  18934. return () => slots.default?.(validation);
  18935. }
  18936. });
  18937. var components = /*#__PURE__*/Object.freeze({
  18938. __proto__: null,
  18939. VAlert: VAlert,
  18940. VAlertTitle: VAlertTitle,
  18941. VApp: VApp,
  18942. VAppBar: VAppBar,
  18943. VAppBarNavIcon: VAppBarNavIcon,
  18944. VAppBarTitle: VAppBarTitle,
  18945. VAutocomplete: VAutocomplete,
  18946. VAvatar: VAvatar,
  18947. VBadge: VBadge,
  18948. VBanner: VBanner,
  18949. VBannerActions: VBannerActions,
  18950. VBannerText: VBannerText,
  18951. VBottomNavigation: VBottomNavigation,
  18952. VBreadcrumbs: VBreadcrumbs,
  18953. VBreadcrumbsDivider: VBreadcrumbsDivider,
  18954. VBreadcrumbsItem: VBreadcrumbsItem,
  18955. VBtn: VBtn,
  18956. VBtnGroup: VBtnGroup,
  18957. VBtnToggle: VBtnToggle,
  18958. VCard: VCard,
  18959. VCardActions: VCardActions,
  18960. VCardItem: VCardItem,
  18961. VCardSubtitle: VCardSubtitle,
  18962. VCardText: VCardText,
  18963. VCardTitle: VCardTitle,
  18964. VCarousel: VCarousel,
  18965. VCarouselItem: VCarouselItem,
  18966. VCheckbox: VCheckbox,
  18967. VCheckboxBtn: VCheckboxBtn,
  18968. VChip: VChip,
  18969. VChipGroup: VChipGroup,
  18970. VClassIcon: VClassIcon,
  18971. VCode: VCode,
  18972. VCol: VCol,
  18973. VColorPicker: VColorPicker,
  18974. VCombobox: VCombobox,
  18975. VComponentIcon: VComponentIcon,
  18976. VContainer: VContainer,
  18977. VCounter: VCounter,
  18978. VDefaultsProvider: VDefaultsProvider,
  18979. VDialog: VDialog,
  18980. VDialogBottomTransition: VDialogBottomTransition,
  18981. VDialogTopTransition: VDialogTopTransition,
  18982. VDialogTransition: VDialogTransition,
  18983. VDivider: VDivider,
  18984. VExpandTransition: VExpandTransition,
  18985. VExpandXTransition: VExpandXTransition,
  18986. VExpansionPanel: VExpansionPanel,
  18987. VExpansionPanelText: VExpansionPanelText,
  18988. VExpansionPanelTitle: VExpansionPanelTitle,
  18989. VExpansionPanels: VExpansionPanels,
  18990. VFabTransition: VFabTransition,
  18991. VFadeTransition: VFadeTransition,
  18992. VField: VField,
  18993. VFieldLabel: VFieldLabel,
  18994. VFileInput: VFileInput,
  18995. VFooter: VFooter,
  18996. VForm: VForm,
  18997. VHover: VHover,
  18998. VIcon: VIcon,
  18999. VImg: VImg,
  19000. VInput: VInput,
  19001. VItem: VItem,
  19002. VItemGroup: VItemGroup,
  19003. VKbd: VKbd,
  19004. VLabel: VLabel,
  19005. VLayout: VLayout,
  19006. VLayoutItem: VLayoutItem,
  19007. VLazy: VLazy,
  19008. VLigatureIcon: VLigatureIcon,
  19009. VList: VList,
  19010. VListGroup: VListGroup,
  19011. VListImg: VListImg,
  19012. VListItem: VListItem,
  19013. VListItemAction: VListItemAction,
  19014. VListItemMedia: VListItemMedia,
  19015. VListItemSubtitle: VListItemSubtitle,
  19016. VListItemTitle: VListItemTitle,
  19017. VListSubheader: VListSubheader,
  19018. VLocaleProvider: VLocaleProvider,
  19019. VMain: VMain,
  19020. VMenu: VMenu,
  19021. VMessages: VMessages,
  19022. VNavigationDrawer: VNavigationDrawer,
  19023. VNoSsr: VNoSsr,
  19024. VOverlay: VOverlay,
  19025. VPagination: VPagination,
  19026. VParallax: VParallax,
  19027. VProgressCircular: VProgressCircular,
  19028. VProgressLinear: VProgressLinear,
  19029. VRadio: VRadio,
  19030. VRadioGroup: VRadioGroup,
  19031. VRangeSlider: VRangeSlider,
  19032. VRating: VRating,
  19033. VResponsive: VResponsive,
  19034. VRow: VRow,
  19035. VScaleTransition: VScaleTransition,
  19036. VScrollXReverseTransition: VScrollXReverseTransition,
  19037. VScrollXTransition: VScrollXTransition,
  19038. VScrollYReverseTransition: VScrollYReverseTransition,
  19039. VScrollYTransition: VScrollYTransition,
  19040. VSelect: VSelect,
  19041. VSelectionControl: VSelectionControl,
  19042. VSelectionControlGroup: VSelectionControlGroup,
  19043. VSheet: VSheet,
  19044. VSlideGroup: VSlideGroup,
  19045. VSlideGroupItem: VSlideGroupItem,
  19046. VSlideXReverseTransition: VSlideXReverseTransition,
  19047. VSlideXTransition: VSlideXTransition,
  19048. VSlideYReverseTransition: VSlideYReverseTransition,
  19049. VSlideYTransition: VSlideYTransition,
  19050. VSlider: VSlider,
  19051. VSnackbar: VSnackbar,
  19052. VSpacer: VSpacer,
  19053. VSvgIcon: VSvgIcon,
  19054. VSwitch: VSwitch,
  19055. VSystemBar: VSystemBar,
  19056. VTab: VTab,
  19057. VTable: VTable,
  19058. VTabs: VTabs,
  19059. VTextField: VTextField,
  19060. VTextarea: VTextarea,
  19061. VThemeProvider: VThemeProvider,
  19062. VTimeline: VTimeline,
  19063. VTimelineItem: VTimelineItem,
  19064. VToolbar: VToolbar,
  19065. VToolbarItems: VToolbarItems,
  19066. VToolbarTitle: VToolbarTitle,
  19067. VTooltip: VTooltip,
  19068. VValidation: VValidation,
  19069. VVirtualScroll: VVirtualScroll,
  19070. VWindow: VWindow,
  19071. VWindowItem: VWindowItem
  19072. });
  19073. // Types
  19074. function mounted$2(el, binding) {
  19075. const modifiers = binding.modifiers || {};
  19076. const value = binding.value;
  19077. const {
  19078. once,
  19079. immediate,
  19080. ...modifierKeys
  19081. } = modifiers;
  19082. const defaultValue = !Object.keys(modifierKeys).length;
  19083. const {
  19084. handler,
  19085. options
  19086. } = typeof value === 'object' ? value : {
  19087. handler: value,
  19088. options: {
  19089. attributes: modifierKeys?.attr ?? defaultValue,
  19090. characterData: modifierKeys?.char ?? defaultValue,
  19091. childList: modifierKeys?.child ?? defaultValue,
  19092. subtree: modifierKeys?.sub ?? defaultValue
  19093. }
  19094. };
  19095. const observer = new MutationObserver(function () {
  19096. let mutations = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : [];
  19097. let observer = arguments.length > 1 ? arguments[1] : undefined;
  19098. handler?.(mutations, observer);
  19099. if (once) unmounted$2(el, binding);
  19100. });
  19101. if (immediate) handler?.([], observer);
  19102. el._mutate = Object(el._mutate);
  19103. el._mutate[binding.instance.$.uid] = {
  19104. observer
  19105. };
  19106. observer.observe(el, options);
  19107. }
  19108. function unmounted$2(el, binding) {
  19109. if (!el._mutate?.[binding.instance.$.uid]) return;
  19110. el._mutate[binding.instance.$.uid].observer.disconnect();
  19111. delete el._mutate[binding.instance.$.uid];
  19112. }
  19113. const Mutate = {
  19114. mounted: mounted$2,
  19115. unmounted: unmounted$2
  19116. };
  19117. // Types
  19118. function mounted$1(el, binding) {
  19119. const handler = binding.value;
  19120. const options = {
  19121. passive: !binding.modifiers?.active
  19122. };
  19123. window.addEventListener('resize', handler, options);
  19124. el._onResize = Object(el._onResize);
  19125. el._onResize[binding.instance.$.uid] = {
  19126. handler,
  19127. options
  19128. };
  19129. if (!binding.modifiers?.quiet) {
  19130. handler();
  19131. }
  19132. }
  19133. function unmounted$1(el, binding) {
  19134. if (!el._onResize?.[binding.instance.$.uid]) return;
  19135. const {
  19136. handler,
  19137. options
  19138. } = el._onResize[binding.instance.$.uid];
  19139. window.removeEventListener('resize', handler, options);
  19140. delete el._onResize[binding.instance.$.uid];
  19141. }
  19142. const Resize = {
  19143. mounted: mounted$1,
  19144. unmounted: unmounted$1
  19145. };
  19146. // Types
  19147. function mounted(el, binding) {
  19148. const {
  19149. self = false
  19150. } = binding.modifiers ?? {};
  19151. const value = binding.value;
  19152. const options = typeof value === 'object' && value.options || {
  19153. passive: true
  19154. };
  19155. const handler = typeof value === 'function' || 'handleEvent' in value ? value : value.handler;
  19156. const target = self ? el : binding.arg ? document.querySelector(binding.arg) : window;
  19157. if (!target) return;
  19158. target.addEventListener('scroll', handler, options);
  19159. el._onScroll = Object(el._onScroll);
  19160. el._onScroll[binding.instance.$.uid] = {
  19161. handler,
  19162. options,
  19163. // Don't reference self
  19164. target: self ? undefined : target
  19165. };
  19166. }
  19167. function unmounted(el, binding) {
  19168. if (!el._onScroll?.[binding.instance.$.uid]) return;
  19169. const {
  19170. handler,
  19171. options,
  19172. target = el
  19173. } = el._onScroll[binding.instance.$.uid];
  19174. target.removeEventListener('scroll', handler, options);
  19175. delete el._onScroll[binding.instance.$.uid];
  19176. }
  19177. function updated(el, binding) {
  19178. if (binding.value === binding.oldValue) return;
  19179. unmounted(el, binding);
  19180. mounted(el, binding);
  19181. }
  19182. const Scroll = {
  19183. mounted,
  19184. unmounted,
  19185. updated
  19186. };
  19187. var directives = /*#__PURE__*/Object.freeze({
  19188. __proto__: null,
  19189. ClickOutside: ClickOutside,
  19190. Intersect: Intersect,
  19191. Mutate: Mutate,
  19192. Resize: Resize,
  19193. Ripple: Ripple,
  19194. Scroll: Scroll,
  19195. Touch: Touch
  19196. });
  19197. // Utilities
  19198. // Types
  19199. const firstDay = {
  19200. '001': 1,
  19201. AD: 1,
  19202. AE: 6,
  19203. AF: 6,
  19204. AG: 0,
  19205. AI: 1,
  19206. AL: 1,
  19207. AM: 1,
  19208. AN: 1,
  19209. AR: 1,
  19210. AS: 0,
  19211. AT: 1,
  19212. AU: 1,
  19213. AX: 1,
  19214. AZ: 1,
  19215. BA: 1,
  19216. BD: 0,
  19217. BE: 1,
  19218. BG: 1,
  19219. BH: 6,
  19220. BM: 1,
  19221. BN: 1,
  19222. BR: 0,
  19223. BS: 0,
  19224. BT: 0,
  19225. BW: 0,
  19226. BY: 1,
  19227. BZ: 0,
  19228. CA: 0,
  19229. CH: 1,
  19230. CL: 1,
  19231. CM: 1,
  19232. CN: 1,
  19233. CO: 0,
  19234. CR: 1,
  19235. CY: 1,
  19236. CZ: 1,
  19237. DE: 1,
  19238. DJ: 6,
  19239. DK: 1,
  19240. DM: 0,
  19241. DO: 0,
  19242. DZ: 6,
  19243. EC: 1,
  19244. EE: 1,
  19245. EG: 6,
  19246. ES: 1,
  19247. ET: 0,
  19248. FI: 1,
  19249. FJ: 1,
  19250. FO: 1,
  19251. FR: 1,
  19252. GB: 1,
  19253. 'GB-alt-variant': 0,
  19254. GE: 1,
  19255. GF: 1,
  19256. GP: 1,
  19257. GR: 1,
  19258. GT: 0,
  19259. GU: 0,
  19260. HK: 0,
  19261. HN: 0,
  19262. HR: 1,
  19263. HU: 1,
  19264. ID: 0,
  19265. IE: 1,
  19266. IL: 0,
  19267. IN: 0,
  19268. IQ: 6,
  19269. IR: 6,
  19270. IS: 1,
  19271. IT: 1,
  19272. JM: 0,
  19273. JO: 6,
  19274. JP: 0,
  19275. KE: 0,
  19276. KG: 1,
  19277. KH: 0,
  19278. KR: 0,
  19279. KW: 6,
  19280. KZ: 1,
  19281. LA: 0,
  19282. LB: 1,
  19283. LI: 1,
  19284. LK: 1,
  19285. LT: 1,
  19286. LU: 1,
  19287. LV: 1,
  19288. LY: 6,
  19289. MC: 1,
  19290. MD: 1,
  19291. ME: 1,
  19292. MH: 0,
  19293. MK: 1,
  19294. MM: 0,
  19295. MN: 1,
  19296. MO: 0,
  19297. MQ: 1,
  19298. MT: 0,
  19299. MV: 5,
  19300. MX: 0,
  19301. MY: 1,
  19302. MZ: 0,
  19303. NI: 0,
  19304. NL: 1,
  19305. NO: 1,
  19306. NP: 0,
  19307. NZ: 1,
  19308. OM: 6,
  19309. PA: 0,
  19310. PE: 0,
  19311. PH: 0,
  19312. PK: 0,
  19313. PL: 1,
  19314. PR: 0,
  19315. PT: 0,
  19316. PY: 0,
  19317. QA: 6,
  19318. RE: 1,
  19319. RO: 1,
  19320. RS: 1,
  19321. RU: 1,
  19322. SA: 0,
  19323. SD: 6,
  19324. SE: 1,
  19325. SG: 0,
  19326. SI: 1,
  19327. SK: 1,
  19328. SM: 1,
  19329. SV: 0,
  19330. SY: 6,
  19331. TH: 0,
  19332. TJ: 1,
  19333. TM: 1,
  19334. TR: 1,
  19335. TT: 0,
  19336. TW: 0,
  19337. UA: 1,
  19338. UM: 0,
  19339. US: 0,
  19340. UY: 1,
  19341. UZ: 1,
  19342. VA: 1,
  19343. VE: 0,
  19344. VI: 0,
  19345. VN: 1,
  19346. WS: 0,
  19347. XK: 1,
  19348. YE: 0,
  19349. ZA: 0,
  19350. ZW: 0
  19351. };
  19352. function getWeekArray(date, locale) {
  19353. const weeks = [];
  19354. let currentWeek = [];
  19355. const firstDayOfMonth = startOfMonth(date);
  19356. const lastDayOfMonth = endOfMonth(date);
  19357. const firstDayWeekIndex = firstDayOfMonth.getDay() - firstDay[locale.slice(-2).toUpperCase()];
  19358. const lastDayWeekIndex = lastDayOfMonth.getDay() - firstDay[locale.slice(-2).toUpperCase()];
  19359. for (let i = 0; i < firstDayWeekIndex; i++) {
  19360. const adjacentDay = new Date(firstDayOfMonth);
  19361. adjacentDay.setDate(adjacentDay.getDate() - (firstDayWeekIndex - i));
  19362. currentWeek.push(adjacentDay);
  19363. }
  19364. for (let i = 1; i <= lastDayOfMonth.getDate(); i++) {
  19365. const day = new Date(date.getFullYear(), date.getMonth(), i);
  19366. // Add the day to the current week
  19367. currentWeek.push(day);
  19368. // If the current week has 7 days, add it to the weeks array and start a new week
  19369. if (currentWeek.length === 7) {
  19370. weeks.push(currentWeek);
  19371. currentWeek = [];
  19372. }
  19373. }
  19374. for (let i = 1; i < 7 - lastDayWeekIndex; i++) {
  19375. const adjacentDay = new Date(lastDayOfMonth);
  19376. adjacentDay.setDate(adjacentDay.getDate() + i);
  19377. currentWeek.push(adjacentDay);
  19378. }
  19379. weeks.push(currentWeek);
  19380. return weeks;
  19381. }
  19382. function startOfMonth(date) {
  19383. return new Date(date.getFullYear(), date.getMonth(), 1);
  19384. }
  19385. function endOfMonth(date) {
  19386. return new Date(date.getFullYear(), date.getMonth() + 1, 0);
  19387. }
  19388. function parseLocalDate(value) {
  19389. const parts = value.split('-').map(Number);
  19390. // new Date() uses local time zone when passing individual date component values
  19391. return new Date(parts[0], parts[1] - 1, parts[2]);
  19392. }
  19393. const _YYYMMDD = /([12]\d{3}-([1-9]|0[1-9]|1[0-2])-([1-9]|0[1-9]|[12]\d|3[01]))/;
  19394. function date(value) {
  19395. if (value == null) return new Date();
  19396. if (value instanceof Date) return value;
  19397. if (typeof value === 'string') {
  19398. let parsed;
  19399. if (_YYYMMDD.test(value)) {
  19400. return parseLocalDate(value);
  19401. } else {
  19402. parsed = Date.parse(value);
  19403. }
  19404. if (!isNaN(parsed)) return new Date(parsed);
  19405. }
  19406. return null;
  19407. }
  19408. const sundayJanuarySecond2000 = new Date(2000, 0, 2);
  19409. function getWeekdays(locale) {
  19410. const daysFromSunday = firstDay[locale.slice(-2).toUpperCase()];
  19411. return createRange(7).map(i => {
  19412. const weekday = new Date(sundayJanuarySecond2000);
  19413. weekday.setDate(sundayJanuarySecond2000.getDate() + daysFromSunday + i);
  19414. return new Intl.DateTimeFormat(locale, {
  19415. weekday: 'short'
  19416. }).format(weekday);
  19417. });
  19418. }
  19419. function format(value, formatString, locale) {
  19420. const date = new Date(value);
  19421. let options = {};
  19422. switch (formatString) {
  19423. case 'fullDateWithWeekday':
  19424. options = {
  19425. weekday: 'long',
  19426. day: 'numeric',
  19427. month: 'long',
  19428. year: 'numeric'
  19429. };
  19430. break;
  19431. case 'normalDateWithWeekday':
  19432. options = {
  19433. weekday: 'short',
  19434. day: 'numeric',
  19435. month: 'short'
  19436. };
  19437. break;
  19438. case 'keyboardDate':
  19439. options = {};
  19440. break;
  19441. case 'monthAndDate':
  19442. options = {
  19443. month: 'long',
  19444. day: 'numeric'
  19445. };
  19446. break;
  19447. case 'monthAndYear':
  19448. options = {
  19449. month: 'long',
  19450. year: 'numeric'
  19451. };
  19452. break;
  19453. case 'dayOfMonth':
  19454. options = {
  19455. day: 'numeric'
  19456. };
  19457. break;
  19458. default:
  19459. options = {
  19460. timeZone: 'UTC',
  19461. timeZoneName: 'short'
  19462. };
  19463. }
  19464. return new Intl.DateTimeFormat(locale, options).format(date);
  19465. }
  19466. function addDays(date, amount) {
  19467. const d = new Date(date);
  19468. d.setDate(d.getDate() + amount);
  19469. return d;
  19470. }
  19471. function addMonths(date, amount) {
  19472. const d = new Date(date);
  19473. d.setMonth(d.getMonth() + amount);
  19474. return d;
  19475. }
  19476. function getYear(date) {
  19477. return date.getFullYear();
  19478. }
  19479. function getMonth(date) {
  19480. return date.getMonth();
  19481. }
  19482. function startOfYear(date) {
  19483. return new Date(date.getFullYear(), 0, 1);
  19484. }
  19485. function endOfYear(date) {
  19486. return new Date(date.getFullYear(), 11, 31);
  19487. }
  19488. function isWithinRange(date, range) {
  19489. return isAfter(date, range[0]) && isBefore(date, range[1]);
  19490. }
  19491. function isValid(date) {
  19492. const d = new Date(date);
  19493. return d instanceof Date && !isNaN(d.getTime());
  19494. }
  19495. function isAfter(date, comparing) {
  19496. return date.getTime() > comparing.getTime();
  19497. }
  19498. function isBefore(date, comparing) {
  19499. return date.getTime() < comparing.getTime();
  19500. }
  19501. function isEqual(date, comparing) {
  19502. return date.getTime() === comparing.getTime();
  19503. }
  19504. function isSameDay(date, comparing) {
  19505. return date.getDate() === comparing.getDate() && date.getMonth() === comparing.getMonth() && date.getFullYear() === comparing.getFullYear();
  19506. }
  19507. function isSameMonth(date, comparing) {
  19508. return date.getMonth() === comparing.getMonth() && date.getFullYear() === comparing.getFullYear();
  19509. }
  19510. function getDiff(date, comparing, unit) {
  19511. const d = new Date(date);
  19512. const c = new Date(comparing);
  19513. if (unit === 'month') {
  19514. return d.getMonth() - c.getMonth() + (d.getFullYear() - c.getFullYear()) * 12;
  19515. }
  19516. return Math.floor((d.getTime() - c.getTime()) / (1000 * 60 * 60 * 24));
  19517. }
  19518. function setYear(date, year) {
  19519. const d = new Date(date);
  19520. d.setFullYear(year);
  19521. return d;
  19522. }
  19523. class VuetifyDateAdapter {
  19524. constructor(options) {
  19525. this.locale = options.locale;
  19526. }
  19527. date(value) {
  19528. return date(value);
  19529. }
  19530. toJsDate(date) {
  19531. return date;
  19532. }
  19533. addDays(date, amount) {
  19534. return addDays(date, amount);
  19535. }
  19536. addMonths(date, amount) {
  19537. return addMonths(date, amount);
  19538. }
  19539. getWeekArray(date) {
  19540. return getWeekArray(date, this.locale);
  19541. }
  19542. startOfMonth(date) {
  19543. return startOfMonth(date);
  19544. }
  19545. endOfMonth(date) {
  19546. return endOfMonth(date);
  19547. }
  19548. format(date, formatString) {
  19549. return format(date, formatString, this.locale);
  19550. }
  19551. isEqual(date, comparing) {
  19552. return isEqual(date, comparing);
  19553. }
  19554. isValid(date) {
  19555. return isValid(date);
  19556. }
  19557. isWithinRange(date, range) {
  19558. return isWithinRange(date, range);
  19559. }
  19560. isAfter(date, comparing) {
  19561. return isAfter(date, comparing);
  19562. }
  19563. isBefore(date, comparing) {
  19564. return !isAfter(date, comparing) && !isEqual(date, comparing);
  19565. }
  19566. isSameDay(date, comparing) {
  19567. return isSameDay(date, comparing);
  19568. }
  19569. isSameMonth(date, comparing) {
  19570. return isSameMonth(date, comparing);
  19571. }
  19572. setYear(date, year) {
  19573. return setYear(date, year);
  19574. }
  19575. getDiff(date, comparing, unit) {
  19576. return getDiff(date, comparing, unit);
  19577. }
  19578. getWeekdays() {
  19579. return getWeekdays(this.locale);
  19580. }
  19581. getYear(date) {
  19582. return getYear(date);
  19583. }
  19584. getMonth(date) {
  19585. return getMonth(date);
  19586. }
  19587. startOfYear(date) {
  19588. return startOfYear(date);
  19589. }
  19590. endOfYear(date) {
  19591. return endOfYear(date);
  19592. }
  19593. }
  19594. // Composables
  19595. // Types
  19596. const DateAdapterSymbol = Symbol.for('vuetify:date-adapter');
  19597. function createDate(options) {
  19598. return mergeDeep({
  19599. adapter: VuetifyDateAdapter,
  19600. locale: {
  19601. af: 'af-ZA',
  19602. // ar: '', # not the same value for all variants
  19603. bg: 'bg-BG',
  19604. ca: 'ca-ES',
  19605. ckb: '',
  19606. cs: '',
  19607. de: 'de-DE',
  19608. el: 'el-GR',
  19609. en: 'en-US',
  19610. // es: '', # not the same value for all variants
  19611. et: 'et-EE',
  19612. fa: 'fa-IR',
  19613. fi: 'fi-FI',
  19614. // fr: '', #not the same value for all variants
  19615. hr: 'hr-HR',
  19616. hu: 'hu-HU',
  19617. he: 'he-IL',
  19618. id: 'id-ID',
  19619. it: 'it-IT',
  19620. ja: 'ja-JP',
  19621. ko: 'ko-KR',
  19622. lv: 'lv-LV',
  19623. lt: 'lt-LT',
  19624. nl: 'nl-NL',
  19625. no: 'nn-NO',
  19626. pl: 'pl-PL',
  19627. pt: 'pt-PT',
  19628. ro: 'ro-RO',
  19629. ru: 'ru-RU',
  19630. sk: 'sk-SK',
  19631. sl: 'sl-SI',
  19632. srCyrl: 'sr-SP',
  19633. srLatn: 'sr-SP',
  19634. sv: 'sv-SE',
  19635. th: 'th-TH',
  19636. tr: 'tr-TR',
  19637. az: 'az-AZ',
  19638. uk: 'uk-UA',
  19639. vi: 'vi-VN',
  19640. zhHans: 'zh-CN',
  19641. zhHant: 'zh-TW'
  19642. }
  19643. }, options);
  19644. }
  19645. // Composables
  19646. function createVuetify$1() {
  19647. let vuetify = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
  19648. const {
  19649. blueprint,
  19650. ...rest
  19651. } = vuetify;
  19652. const options = mergeDeep(blueprint, rest);
  19653. const {
  19654. aliases = {},
  19655. components = {},
  19656. directives = {}
  19657. } = options;
  19658. const defaults = createDefaults(options.defaults);
  19659. const display = createDisplay(options.display, options.ssr);
  19660. const theme = createTheme(options.theme);
  19661. const icons = createIcons(options.icons);
  19662. const locale = createLocale(options.locale);
  19663. const date = createDate(options.date);
  19664. const install = app => {
  19665. for (const key in directives) {
  19666. app.directive(key, directives[key]);
  19667. }
  19668. for (const key in components) {
  19669. app.component(key, components[key]);
  19670. }
  19671. for (const key in aliases) {
  19672. app.component(key, defineComponent({
  19673. ...aliases[key],
  19674. name: key,
  19675. aliasName: aliases[key].name
  19676. }));
  19677. }
  19678. theme.install(app);
  19679. app.provide(DefaultsSymbol, defaults);
  19680. app.provide(DisplaySymbol, display);
  19681. app.provide(ThemeSymbol, theme);
  19682. app.provide(IconSymbol, icons);
  19683. app.provide(LocaleSymbol, locale);
  19684. app.provide(DateAdapterSymbol, date);
  19685. if (IN_BROWSER && options.ssr) {
  19686. if (app.$nuxt) {
  19687. app.$nuxt.hook('app:suspense:resolve', () => {
  19688. display.update();
  19689. });
  19690. } else {
  19691. const {
  19692. mount
  19693. } = app;
  19694. app.mount = function () {
  19695. const vm = mount(...arguments);
  19696. vue.nextTick(() => display.update());
  19697. app.mount = mount;
  19698. return vm;
  19699. };
  19700. }
  19701. }
  19702. getUid.reset();
  19703. if (typeof __VUE_OPTIONS_API__ !== 'boolean' || __VUE_OPTIONS_API__) {
  19704. app.mixin({
  19705. computed: {
  19706. $vuetify() {
  19707. return vue.reactive({
  19708. defaults: inject.call(this, DefaultsSymbol),
  19709. display: inject.call(this, DisplaySymbol),
  19710. theme: inject.call(this, ThemeSymbol),
  19711. icons: inject.call(this, IconSymbol),
  19712. locale: inject.call(this, LocaleSymbol),
  19713. date: inject.call(this, DateAdapterSymbol)
  19714. });
  19715. }
  19716. }
  19717. });
  19718. }
  19719. };
  19720. return {
  19721. install,
  19722. defaults,
  19723. display,
  19724. theme,
  19725. icons,
  19726. locale,
  19727. date
  19728. };
  19729. }
  19730. const version$1 = "3.3.11";
  19731. createVuetify$1.version = version$1;
  19732. // Vue's inject() can only be used in setup
  19733. function inject(key) {
  19734. const vm = this.$;
  19735. const provides = vm.parent?.provides ?? vm.vnode.appContext?.provides;
  19736. if (provides && key in provides) {
  19737. return provides[key];
  19738. }
  19739. }
  19740. /* eslint-disable local-rules/sort-imports */
  19741. // Types
  19742. const createVuetify = function () {
  19743. let options = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
  19744. return createVuetify$1({
  19745. components,
  19746. directives,
  19747. ...options
  19748. });
  19749. };
  19750. const version = "3.3.11";
  19751. createVuetify.version = version;
  19752. exports.components = components;
  19753. exports.createVuetify = createVuetify;
  19754. exports.directives = directives;
  19755. exports.useDefaults = useDefaults;
  19756. exports.useDisplay = useDisplay;
  19757. exports.useLayout = useLayout;
  19758. exports.useLocale = useLocale;
  19759. exports.useRtl = useRtl;
  19760. exports.useTheme = useTheme;
  19761. exports.version = version;
  19762. }));
  19763. //# sourceMappingURL=vuetify.js.map