vuetify-labs.js 977 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264226522662267226822692270227122722273227422752276227722782279228022812282228322842285228622872288228922902291229222932294229522962297229822992300230123022303230423052306230723082309231023112312231323142315231623172318231923202321232223232324232523262327232823292330233123322333233423352336233723382339234023412342234323442345234623472348234923502351235223532354235523562357235823592360236123622363236423652366236723682369237023712372237323742375237623772378237923802381238223832384238523862387238823892390239123922393239423952396239723982399240024012402240324042405240624072408240924102411241224132414241524162417241824192420242124222423242424252426242724282429243024312432243324342435243624372438243924402441244224432444244524462447244824492450245124522453245424552456245724582459246024612462246324642465246624672468246924702471247224732474247524762477247824792480248124822483248424852486248724882489249024912492249324942495249624972498249925002501250225032504250525062507250825092510251125122513251425152516251725182519252025212522252325242525252625272528252925302531253225332534253525362537253825392540254125422543254425452546254725482549255025512552255325542555255625572558255925602561256225632564256525662567256825692570257125722573257425752576257725782579258025812582258325842585258625872588258925902591259225932594259525962597259825992600260126022603260426052606260726082609261026112612261326142615261626172618261926202621262226232624262526262627262826292630263126322633263426352636263726382639264026412642264326442645264626472648264926502651265226532654265526562657265826592660266126622663266426652666266726682669267026712672267326742675267626772678267926802681268226832684268526862687268826892690269126922693269426952696269726982699270027012702270327042705270627072708270927102711271227132714271527162717271827192720272127222723272427252726272727282729273027312732273327342735273627372738273927402741274227432744274527462747274827492750275127522753275427552756275727582759276027612762276327642765276627672768276927702771277227732774277527762777277827792780278127822783278427852786278727882789279027912792279327942795279627972798279928002801280228032804280528062807280828092810281128122813281428152816281728182819282028212822282328242825282628272828282928302831283228332834283528362837283828392840284128422843284428452846284728482849285028512852285328542855285628572858285928602861286228632864286528662867286828692870287128722873287428752876287728782879288028812882288328842885288628872888288928902891289228932894289528962897289828992900290129022903290429052906290729082909291029112912291329142915291629172918291929202921292229232924292529262927292829292930293129322933293429352936293729382939294029412942294329442945294629472948294929502951295229532954295529562957295829592960296129622963296429652966296729682969297029712972297329742975297629772978297929802981298229832984298529862987298829892990299129922993299429952996299729982999300030013002300330043005300630073008300930103011301230133014301530163017301830193020302130223023302430253026302730283029303030313032303330343035303630373038303930403041304230433044304530463047304830493050305130523053305430553056305730583059306030613062306330643065306630673068306930703071307230733074307530763077307830793080308130823083308430853086308730883089309030913092309330943095309630973098309931003101310231033104310531063107310831093110311131123113311431153116311731183119312031213122312331243125312631273128312931303131313231333134313531363137313831393140314131423143314431453146314731483149315031513152315331543155315631573158315931603161316231633164316531663167316831693170317131723173317431753176317731783179318031813182318331843185318631873188318931903191319231933194319531963197319831993200320132023203320432053206320732083209321032113212321332143215321632173218321932203221322232233224322532263227322832293230323132323233323432353236323732383239324032413242324332443245324632473248324932503251325232533254325532563257325832593260326132623263326432653266326732683269327032713272327332743275327632773278327932803281328232833284328532863287328832893290329132923293329432953296329732983299330033013302330333043305330633073308330933103311331233133314331533163317331833193320332133223323332433253326332733283329333033313332333333343335333633373338333933403341334233433344334533463347334833493350335133523353335433553356335733583359336033613362336333643365336633673368336933703371337233733374337533763377337833793380338133823383338433853386338733883389339033913392339333943395339633973398339934003401340234033404340534063407340834093410341134123413341434153416341734183419342034213422342334243425342634273428342934303431343234333434343534363437343834393440344134423443344434453446344734483449345034513452345334543455345634573458345934603461346234633464346534663467346834693470347134723473347434753476347734783479348034813482348334843485348634873488348934903491349234933494349534963497349834993500350135023503350435053506350735083509351035113512351335143515351635173518351935203521352235233524352535263527352835293530353135323533353435353536353735383539354035413542354335443545354635473548354935503551355235533554355535563557355835593560356135623563356435653566356735683569357035713572357335743575357635773578357935803581358235833584358535863587358835893590359135923593359435953596359735983599360036013602360336043605360636073608360936103611361236133614361536163617361836193620362136223623362436253626362736283629363036313632363336343635363636373638363936403641364236433644364536463647364836493650365136523653365436553656365736583659366036613662366336643665366636673668366936703671367236733674367536763677367836793680368136823683368436853686368736883689369036913692369336943695369636973698369937003701370237033704370537063707370837093710371137123713371437153716371737183719372037213722372337243725372637273728372937303731373237333734373537363737373837393740374137423743374437453746374737483749375037513752375337543755375637573758375937603761376237633764376537663767376837693770377137723773377437753776377737783779378037813782378337843785378637873788378937903791379237933794379537963797379837993800380138023803380438053806380738083809381038113812381338143815381638173818381938203821382238233824382538263827382838293830383138323833383438353836383738383839384038413842384338443845384638473848384938503851385238533854385538563857385838593860386138623863386438653866386738683869387038713872387338743875387638773878387938803881388238833884388538863887388838893890389138923893389438953896389738983899390039013902390339043905390639073908390939103911391239133914391539163917391839193920392139223923392439253926392739283929393039313932393339343935393639373938393939403941394239433944394539463947394839493950395139523953395439553956395739583959396039613962396339643965396639673968396939703971397239733974397539763977397839793980398139823983398439853986398739883989399039913992399339943995399639973998399940004001400240034004400540064007400840094010401140124013401440154016401740184019402040214022402340244025402640274028402940304031403240334034403540364037403840394040404140424043404440454046404740484049405040514052405340544055405640574058405940604061406240634064406540664067406840694070407140724073407440754076407740784079408040814082408340844085408640874088408940904091409240934094409540964097409840994100410141024103410441054106410741084109411041114112411341144115411641174118411941204121412241234124412541264127412841294130413141324133413441354136413741384139414041414142414341444145414641474148414941504151415241534154415541564157415841594160416141624163416441654166416741684169417041714172417341744175417641774178417941804181418241834184418541864187418841894190419141924193419441954196419741984199420042014202420342044205420642074208420942104211421242134214421542164217421842194220422142224223422442254226422742284229423042314232423342344235423642374238423942404241424242434244424542464247424842494250425142524253425442554256425742584259426042614262426342644265426642674268426942704271427242734274427542764277427842794280428142824283428442854286428742884289429042914292429342944295429642974298429943004301430243034304430543064307430843094310431143124313431443154316431743184319432043214322432343244325432643274328432943304331433243334334433543364337433843394340434143424343434443454346434743484349435043514352435343544355435643574358435943604361436243634364436543664367436843694370437143724373437443754376437743784379438043814382438343844385438643874388438943904391439243934394439543964397439843994400440144024403440444054406440744084409441044114412441344144415441644174418441944204421442244234424442544264427442844294430443144324433443444354436443744384439444044414442444344444445444644474448444944504451445244534454445544564457445844594460446144624463446444654466446744684469447044714472447344744475447644774478447944804481448244834484448544864487448844894490449144924493449444954496449744984499450045014502450345044505450645074508450945104511451245134514451545164517451845194520452145224523452445254526452745284529453045314532453345344535453645374538453945404541454245434544454545464547454845494550455145524553455445554556455745584559456045614562456345644565456645674568456945704571457245734574457545764577457845794580458145824583458445854586458745884589459045914592459345944595459645974598459946004601460246034604460546064607460846094610461146124613461446154616461746184619462046214622462346244625462646274628462946304631463246334634463546364637463846394640464146424643464446454646464746484649465046514652465346544655465646574658465946604661466246634664466546664667466846694670467146724673467446754676467746784679468046814682468346844685468646874688468946904691469246934694469546964697469846994700470147024703470447054706470747084709471047114712471347144715471647174718471947204721472247234724472547264727472847294730473147324733473447354736473747384739474047414742474347444745474647474748474947504751475247534754475547564757475847594760476147624763476447654766476747684769477047714772477347744775477647774778477947804781478247834784478547864787478847894790479147924793479447954796479747984799480048014802480348044805480648074808480948104811481248134814481548164817481848194820482148224823482448254826482748284829483048314832483348344835483648374838483948404841484248434844484548464847484848494850485148524853485448554856485748584859486048614862486348644865486648674868486948704871487248734874487548764877487848794880488148824883488448854886488748884889489048914892489348944895489648974898489949004901490249034904490549064907490849094910491149124913491449154916491749184919492049214922492349244925492649274928492949304931493249334934493549364937493849394940494149424943494449454946494749484949495049514952495349544955495649574958495949604961496249634964496549664967496849694970497149724973497449754976497749784979498049814982498349844985498649874988498949904991499249934994499549964997499849995000500150025003500450055006500750085009501050115012501350145015501650175018501950205021502250235024502550265027502850295030503150325033503450355036503750385039504050415042504350445045504650475048504950505051505250535054505550565057505850595060506150625063506450655066506750685069507050715072507350745075507650775078507950805081508250835084508550865087508850895090509150925093509450955096509750985099510051015102510351045105510651075108510951105111511251135114511551165117511851195120512151225123512451255126512751285129513051315132513351345135513651375138513951405141514251435144514551465147514851495150515151525153515451555156515751585159516051615162516351645165516651675168516951705171517251735174517551765177517851795180518151825183518451855186518751885189519051915192519351945195519651975198519952005201520252035204520552065207520852095210521152125213521452155216521752185219522052215222522352245225522652275228522952305231523252335234523552365237523852395240524152425243524452455246524752485249525052515252525352545255525652575258525952605261526252635264526552665267526852695270527152725273527452755276527752785279528052815282528352845285528652875288528952905291529252935294529552965297529852995300530153025303530453055306530753085309531053115312531353145315531653175318531953205321532253235324532553265327532853295330533153325333533453355336533753385339534053415342534353445345534653475348534953505351535253535354535553565357535853595360536153625363536453655366536753685369537053715372537353745375537653775378537953805381538253835384538553865387538853895390539153925393539453955396539753985399540054015402540354045405540654075408540954105411541254135414541554165417541854195420542154225423542454255426542754285429543054315432543354345435543654375438543954405441544254435444544554465447544854495450545154525453545454555456545754585459546054615462546354645465546654675468546954705471547254735474547554765477547854795480548154825483548454855486548754885489549054915492549354945495549654975498549955005501550255035504550555065507550855095510551155125513551455155516551755185519552055215522552355245525552655275528552955305531553255335534553555365537553855395540554155425543554455455546554755485549555055515552555355545555555655575558555955605561556255635564556555665567556855695570557155725573557455755576557755785579558055815582558355845585558655875588558955905591559255935594559555965597559855995600560156025603560456055606560756085609561056115612561356145615561656175618561956205621562256235624562556265627562856295630563156325633563456355636563756385639564056415642564356445645564656475648564956505651565256535654565556565657565856595660566156625663566456655666566756685669567056715672567356745675567656775678567956805681568256835684568556865687568856895690569156925693569456955696569756985699570057015702570357045705570657075708570957105711571257135714571557165717571857195720572157225723572457255726572757285729573057315732573357345735573657375738573957405741574257435744574557465747574857495750575157525753575457555756575757585759576057615762576357645765576657675768576957705771577257735774577557765777577857795780578157825783578457855786578757885789579057915792579357945795579657975798579958005801580258035804580558065807580858095810581158125813581458155816581758185819582058215822582358245825582658275828582958305831583258335834583558365837583858395840584158425843584458455846584758485849585058515852585358545855585658575858585958605861586258635864586558665867586858695870587158725873587458755876587758785879588058815882588358845885588658875888588958905891589258935894589558965897589858995900590159025903590459055906590759085909591059115912591359145915591659175918591959205921592259235924592559265927592859295930593159325933593459355936593759385939594059415942594359445945594659475948594959505951595259535954595559565957595859595960596159625963596459655966596759685969597059715972597359745975597659775978597959805981598259835984598559865987598859895990599159925993599459955996599759985999600060016002600360046005600660076008600960106011601260136014601560166017601860196020602160226023602460256026602760286029603060316032603360346035603660376038603960406041604260436044604560466047604860496050605160526053605460556056605760586059606060616062606360646065606660676068606960706071607260736074607560766077607860796080608160826083608460856086608760886089609060916092609360946095609660976098609961006101610261036104610561066107610861096110611161126113611461156116611761186119612061216122612361246125612661276128612961306131613261336134613561366137613861396140614161426143614461456146614761486149615061516152615361546155615661576158615961606161616261636164616561666167616861696170617161726173617461756176617761786179618061816182618361846185618661876188618961906191619261936194619561966197619861996200620162026203620462056206620762086209621062116212621362146215621662176218621962206221622262236224622562266227622862296230623162326233623462356236623762386239624062416242624362446245624662476248624962506251625262536254625562566257625862596260626162626263626462656266626762686269627062716272627362746275627662776278627962806281628262836284628562866287628862896290629162926293629462956296629762986299630063016302630363046305630663076308630963106311631263136314631563166317631863196320632163226323632463256326632763286329633063316332633363346335633663376338633963406341634263436344634563466347634863496350635163526353635463556356635763586359636063616362636363646365636663676368636963706371637263736374637563766377637863796380638163826383638463856386638763886389639063916392639363946395639663976398639964006401640264036404640564066407640864096410641164126413641464156416641764186419642064216422642364246425642664276428642964306431643264336434643564366437643864396440644164426443644464456446644764486449645064516452645364546455645664576458645964606461646264636464646564666467646864696470647164726473647464756476647764786479648064816482648364846485648664876488648964906491649264936494649564966497649864996500650165026503650465056506650765086509651065116512651365146515651665176518651965206521652265236524652565266527652865296530653165326533653465356536653765386539654065416542654365446545654665476548654965506551655265536554655565566557655865596560656165626563656465656566656765686569657065716572657365746575657665776578657965806581658265836584658565866587658865896590659165926593659465956596659765986599660066016602660366046605660666076608660966106611661266136614661566166617661866196620662166226623662466256626662766286629663066316632663366346635663666376638663966406641664266436644664566466647664866496650665166526653665466556656665766586659666066616662666366646665666666676668666966706671667266736674667566766677667866796680668166826683668466856686668766886689669066916692669366946695669666976698669967006701670267036704670567066707670867096710671167126713671467156716671767186719672067216722672367246725672667276728672967306731673267336734673567366737673867396740674167426743674467456746674767486749675067516752675367546755675667576758675967606761676267636764676567666767676867696770677167726773677467756776677767786779678067816782678367846785678667876788678967906791679267936794679567966797679867996800680168026803680468056806680768086809681068116812681368146815681668176818681968206821682268236824682568266827682868296830683168326833683468356836683768386839684068416842684368446845684668476848684968506851685268536854685568566857685868596860686168626863686468656866686768686869687068716872687368746875687668776878687968806881688268836884688568866887688868896890689168926893689468956896689768986899690069016902690369046905690669076908690969106911691269136914691569166917691869196920692169226923692469256926692769286929693069316932693369346935693669376938693969406941694269436944694569466947694869496950695169526953695469556956695769586959696069616962696369646965696669676968696969706971697269736974697569766977697869796980698169826983698469856986698769886989699069916992699369946995699669976998699970007001700270037004700570067007700870097010701170127013701470157016701770187019702070217022702370247025702670277028702970307031703270337034703570367037703870397040704170427043704470457046704770487049705070517052705370547055705670577058705970607061706270637064706570667067706870697070707170727073707470757076707770787079708070817082708370847085708670877088708970907091709270937094709570967097709870997100710171027103710471057106710771087109711071117112711371147115711671177118711971207121712271237124712571267127712871297130713171327133713471357136713771387139714071417142714371447145714671477148714971507151715271537154715571567157715871597160716171627163716471657166716771687169717071717172717371747175717671777178717971807181718271837184718571867187718871897190719171927193719471957196719771987199720072017202720372047205720672077208720972107211721272137214721572167217721872197220722172227223722472257226722772287229723072317232723372347235723672377238723972407241724272437244724572467247724872497250725172527253725472557256725772587259726072617262726372647265726672677268726972707271727272737274727572767277727872797280728172827283728472857286728772887289729072917292729372947295729672977298729973007301730273037304730573067307730873097310731173127313731473157316731773187319732073217322732373247325732673277328732973307331733273337334733573367337733873397340734173427343734473457346734773487349735073517352735373547355735673577358735973607361736273637364736573667367736873697370737173727373737473757376737773787379738073817382738373847385738673877388738973907391739273937394739573967397739873997400740174027403740474057406740774087409741074117412741374147415741674177418741974207421742274237424742574267427742874297430743174327433743474357436743774387439744074417442744374447445744674477448744974507451745274537454745574567457745874597460746174627463746474657466746774687469747074717472747374747475747674777478747974807481748274837484748574867487748874897490749174927493749474957496749774987499750075017502750375047505750675077508750975107511751275137514751575167517751875197520752175227523752475257526752775287529753075317532753375347535753675377538753975407541754275437544754575467547754875497550755175527553755475557556755775587559756075617562756375647565756675677568756975707571757275737574757575767577757875797580758175827583758475857586758775887589759075917592759375947595759675977598759976007601760276037604760576067607760876097610761176127613761476157616761776187619762076217622762376247625762676277628762976307631763276337634763576367637763876397640764176427643764476457646764776487649765076517652765376547655765676577658765976607661766276637664766576667667766876697670767176727673767476757676767776787679768076817682768376847685768676877688768976907691769276937694769576967697769876997700770177027703770477057706770777087709771077117712771377147715771677177718771977207721772277237724772577267727772877297730773177327733773477357736773777387739774077417742774377447745774677477748774977507751775277537754775577567757775877597760776177627763776477657766776777687769777077717772777377747775777677777778777977807781778277837784778577867787778877897790779177927793779477957796779777987799780078017802780378047805780678077808780978107811781278137814781578167817781878197820782178227823782478257826782778287829783078317832783378347835783678377838783978407841784278437844784578467847784878497850785178527853785478557856785778587859786078617862786378647865786678677868786978707871787278737874787578767877787878797880788178827883788478857886788778887889789078917892789378947895789678977898789979007901790279037904790579067907790879097910791179127913791479157916791779187919792079217922792379247925792679277928792979307931793279337934793579367937793879397940794179427943794479457946794779487949795079517952795379547955795679577958795979607961796279637964796579667967796879697970797179727973797479757976797779787979798079817982798379847985798679877988798979907991799279937994799579967997799879998000800180028003800480058006800780088009801080118012801380148015801680178018801980208021802280238024802580268027802880298030803180328033803480358036803780388039804080418042804380448045804680478048804980508051805280538054805580568057805880598060806180628063806480658066806780688069807080718072807380748075807680778078807980808081808280838084808580868087808880898090809180928093809480958096809780988099810081018102810381048105810681078108810981108111811281138114811581168117811881198120812181228123812481258126812781288129813081318132813381348135813681378138813981408141814281438144814581468147814881498150815181528153815481558156815781588159816081618162816381648165816681678168816981708171817281738174817581768177817881798180818181828183818481858186818781888189819081918192819381948195819681978198819982008201820282038204820582068207820882098210821182128213821482158216821782188219822082218222822382248225822682278228822982308231823282338234823582368237823882398240824182428243824482458246824782488249825082518252825382548255825682578258825982608261826282638264826582668267826882698270827182728273827482758276827782788279828082818282828382848285828682878288828982908291829282938294829582968297829882998300830183028303830483058306830783088309831083118312831383148315831683178318831983208321832283238324832583268327832883298330833183328333833483358336833783388339834083418342834383448345834683478348834983508351835283538354835583568357835883598360836183628363836483658366836783688369837083718372837383748375837683778378837983808381838283838384838583868387838883898390839183928393839483958396839783988399840084018402840384048405840684078408840984108411841284138414841584168417841884198420842184228423842484258426842784288429843084318432843384348435843684378438843984408441844284438444844584468447844884498450845184528453845484558456845784588459846084618462846384648465846684678468846984708471847284738474847584768477847884798480848184828483848484858486848784888489849084918492849384948495849684978498849985008501850285038504850585068507850885098510851185128513851485158516851785188519852085218522852385248525852685278528852985308531853285338534853585368537853885398540854185428543854485458546854785488549855085518552855385548555855685578558855985608561856285638564856585668567856885698570857185728573857485758576857785788579858085818582858385848585858685878588858985908591859285938594859585968597859885998600860186028603860486058606860786088609861086118612861386148615861686178618861986208621862286238624862586268627862886298630863186328633863486358636863786388639864086418642864386448645864686478648864986508651865286538654865586568657865886598660866186628663866486658666866786688669867086718672867386748675867686778678867986808681868286838684868586868687868886898690869186928693869486958696869786988699870087018702870387048705870687078708870987108711871287138714871587168717871887198720872187228723872487258726872787288729873087318732873387348735873687378738873987408741874287438744874587468747874887498750875187528753875487558756875787588759876087618762876387648765876687678768876987708771877287738774877587768777877887798780878187828783878487858786878787888789879087918792879387948795879687978798879988008801880288038804880588068807880888098810881188128813881488158816881788188819882088218822882388248825882688278828882988308831883288338834883588368837883888398840884188428843884488458846884788488849885088518852885388548855885688578858885988608861886288638864886588668867886888698870887188728873887488758876887788788879888088818882888388848885888688878888888988908891889288938894889588968897889888998900890189028903890489058906890789088909891089118912891389148915891689178918891989208921892289238924892589268927892889298930893189328933893489358936893789388939894089418942894389448945894689478948894989508951895289538954895589568957895889598960896189628963896489658966896789688969897089718972897389748975897689778978897989808981898289838984898589868987898889898990899189928993899489958996899789988999900090019002900390049005900690079008900990109011901290139014901590169017901890199020902190229023902490259026902790289029903090319032903390349035903690379038903990409041904290439044904590469047904890499050905190529053905490559056905790589059906090619062906390649065906690679068906990709071907290739074907590769077907890799080908190829083908490859086908790889089909090919092909390949095909690979098909991009101910291039104910591069107910891099110911191129113911491159116911791189119912091219122912391249125912691279128912991309131913291339134913591369137913891399140914191429143914491459146914791489149915091519152915391549155915691579158915991609161916291639164916591669167916891699170917191729173917491759176917791789179918091819182918391849185918691879188918991909191919291939194919591969197919891999200920192029203920492059206920792089209921092119212921392149215921692179218921992209221922292239224922592269227922892299230923192329233923492359236923792389239924092419242924392449245924692479248924992509251925292539254925592569257925892599260926192629263926492659266926792689269927092719272927392749275927692779278927992809281928292839284928592869287928892899290929192929293929492959296929792989299930093019302930393049305930693079308930993109311931293139314931593169317931893199320932193229323932493259326932793289329933093319332933393349335933693379338933993409341934293439344934593469347934893499350935193529353935493559356935793589359936093619362936393649365936693679368936993709371937293739374937593769377937893799380938193829383938493859386938793889389939093919392939393949395939693979398939994009401940294039404940594069407940894099410941194129413941494159416941794189419942094219422942394249425942694279428942994309431943294339434943594369437943894399440944194429443944494459446944794489449945094519452945394549455945694579458945994609461946294639464946594669467946894699470947194729473947494759476947794789479948094819482948394849485948694879488948994909491949294939494949594969497949894999500950195029503950495059506950795089509951095119512951395149515951695179518951995209521952295239524952595269527952895299530953195329533953495359536953795389539954095419542954395449545954695479548954995509551955295539554955595569557955895599560956195629563956495659566956795689569957095719572957395749575957695779578957995809581958295839584958595869587958895899590959195929593959495959596959795989599960096019602960396049605960696079608960996109611961296139614961596169617961896199620962196229623962496259626962796289629963096319632963396349635963696379638963996409641964296439644964596469647964896499650965196529653965496559656965796589659966096619662966396649665966696679668966996709671967296739674967596769677967896799680968196829683968496859686968796889689969096919692969396949695969696979698969997009701970297039704970597069707970897099710971197129713971497159716971797189719972097219722972397249725972697279728972997309731973297339734973597369737973897399740974197429743974497459746974797489749975097519752975397549755975697579758975997609761976297639764976597669767976897699770977197729773977497759776977797789779978097819782978397849785978697879788978997909791979297939794979597969797979897999800980198029803980498059806980798089809981098119812981398149815981698179818981998209821982298239824982598269827982898299830983198329833983498359836983798389839984098419842984398449845984698479848984998509851985298539854985598569857985898599860986198629863986498659866986798689869987098719872987398749875987698779878987998809881988298839884988598869887988898899890989198929893989498959896989798989899990099019902990399049905990699079908990999109911991299139914991599169917991899199920992199229923992499259926992799289929993099319932993399349935993699379938993999409941994299439944994599469947994899499950995199529953995499559956995799589959996099619962996399649965996699679968996999709971997299739974997599769977997899799980998199829983998499859986998799889989999099919992999399949995999699979998999910000100011000210003100041000510006100071000810009100101001110012100131001410015100161001710018100191002010021100221002310024100251002610027100281002910030100311003210033100341003510036100371003810039100401004110042100431004410045100461004710048100491005010051100521005310054100551005610057100581005910060100611006210063100641006510066100671006810069100701007110072100731007410075100761007710078100791008010081100821008310084100851008610087100881008910090100911009210093100941009510096100971009810099101001010110102101031010410105101061010710108101091011010111101121011310114101151011610117101181011910120101211012210123101241012510126101271012810129101301013110132101331013410135101361013710138101391014010141101421014310144101451014610147101481014910150101511015210153101541015510156101571015810159101601016110162101631016410165101661016710168101691017010171101721017310174101751017610177101781017910180101811018210183101841018510186101871018810189101901019110192101931019410195101961019710198101991020010201102021020310204102051020610207102081020910210102111021210213102141021510216102171021810219102201022110222102231022410225102261022710228102291023010231102321023310234102351023610237102381023910240102411024210243102441024510246102471024810249102501025110252102531025410255102561025710258102591026010261102621026310264102651026610267102681026910270102711027210273102741027510276102771027810279102801028110282102831028410285102861028710288102891029010291102921029310294102951029610297102981029910300103011030210303103041030510306103071030810309103101031110312103131031410315103161031710318103191032010321103221032310324103251032610327103281032910330103311033210333103341033510336103371033810339103401034110342103431034410345103461034710348103491035010351103521035310354103551035610357103581035910360103611036210363103641036510366103671036810369103701037110372103731037410375103761037710378103791038010381103821038310384103851038610387103881038910390103911039210393103941039510396103971039810399104001040110402104031040410405104061040710408104091041010411104121041310414104151041610417104181041910420104211042210423104241042510426104271042810429104301043110432104331043410435104361043710438104391044010441104421044310444104451044610447104481044910450104511045210453104541045510456104571045810459104601046110462104631046410465104661046710468104691047010471104721047310474104751047610477104781047910480104811048210483104841048510486104871048810489104901049110492104931049410495104961049710498104991050010501105021050310504105051050610507105081050910510105111051210513105141051510516105171051810519105201052110522105231052410525105261052710528105291053010531105321053310534105351053610537105381053910540105411054210543105441054510546105471054810549105501055110552105531055410555105561055710558105591056010561105621056310564105651056610567105681056910570105711057210573105741057510576105771057810579105801058110582105831058410585105861058710588105891059010591105921059310594105951059610597105981059910600106011060210603106041060510606106071060810609106101061110612106131061410615106161061710618106191062010621106221062310624106251062610627106281062910630106311063210633106341063510636106371063810639106401064110642106431064410645106461064710648106491065010651106521065310654106551065610657106581065910660106611066210663106641066510666106671066810669106701067110672106731067410675106761067710678106791068010681106821068310684106851068610687106881068910690106911069210693106941069510696106971069810699107001070110702107031070410705107061070710708107091071010711107121071310714107151071610717107181071910720107211072210723107241072510726107271072810729107301073110732107331073410735107361073710738107391074010741107421074310744107451074610747107481074910750107511075210753107541075510756107571075810759107601076110762107631076410765107661076710768107691077010771107721077310774107751077610777107781077910780107811078210783107841078510786107871078810789107901079110792107931079410795107961079710798107991080010801108021080310804108051080610807108081080910810108111081210813108141081510816108171081810819108201082110822108231082410825108261082710828108291083010831108321083310834108351083610837108381083910840108411084210843108441084510846108471084810849108501085110852108531085410855108561085710858108591086010861108621086310864108651086610867108681086910870108711087210873108741087510876108771087810879108801088110882108831088410885108861088710888108891089010891108921089310894108951089610897108981089910900109011090210903109041090510906109071090810909109101091110912109131091410915109161091710918109191092010921109221092310924109251092610927109281092910930109311093210933109341093510936109371093810939109401094110942109431094410945109461094710948109491095010951109521095310954109551095610957109581095910960109611096210963109641096510966109671096810969109701097110972109731097410975109761097710978109791098010981109821098310984109851098610987109881098910990109911099210993109941099510996109971099810999110001100111002110031100411005110061100711008110091101011011110121101311014110151101611017110181101911020110211102211023110241102511026110271102811029110301103111032110331103411035110361103711038110391104011041110421104311044110451104611047110481104911050110511105211053110541105511056110571105811059110601106111062110631106411065110661106711068110691107011071110721107311074110751107611077110781107911080110811108211083110841108511086110871108811089110901109111092110931109411095110961109711098110991110011101111021110311104111051110611107111081110911110111111111211113111141111511116111171111811119111201112111122111231112411125111261112711128111291113011131111321113311134111351113611137111381113911140111411114211143111441114511146111471114811149111501115111152111531115411155111561115711158111591116011161111621116311164111651116611167111681116911170111711117211173111741117511176111771117811179111801118111182111831118411185111861118711188111891119011191111921119311194111951119611197111981119911200112011120211203112041120511206112071120811209112101121111212112131121411215112161121711218112191122011221112221122311224112251122611227112281122911230112311123211233112341123511236112371123811239112401124111242112431124411245112461124711248112491125011251112521125311254112551125611257112581125911260112611126211263112641126511266112671126811269112701127111272112731127411275112761127711278112791128011281112821128311284112851128611287112881128911290112911129211293112941129511296112971129811299113001130111302113031130411305113061130711308113091131011311113121131311314113151131611317113181131911320113211132211323113241132511326113271132811329113301133111332113331133411335113361133711338113391134011341113421134311344113451134611347113481134911350113511135211353113541135511356113571135811359113601136111362113631136411365113661136711368113691137011371113721137311374113751137611377113781137911380113811138211383113841138511386113871138811389113901139111392113931139411395113961139711398113991140011401114021140311404114051140611407114081140911410114111141211413114141141511416114171141811419114201142111422114231142411425114261142711428114291143011431114321143311434114351143611437114381143911440114411144211443114441144511446114471144811449114501145111452114531145411455114561145711458114591146011461114621146311464114651146611467114681146911470114711147211473114741147511476114771147811479114801148111482114831148411485114861148711488114891149011491114921149311494114951149611497114981149911500115011150211503115041150511506115071150811509115101151111512115131151411515115161151711518115191152011521115221152311524115251152611527115281152911530115311153211533115341153511536115371153811539115401154111542115431154411545115461154711548115491155011551115521155311554115551155611557115581155911560115611156211563115641156511566115671156811569115701157111572115731157411575115761157711578115791158011581115821158311584115851158611587115881158911590115911159211593115941159511596115971159811599116001160111602116031160411605116061160711608116091161011611116121161311614116151161611617116181161911620116211162211623116241162511626116271162811629116301163111632116331163411635116361163711638116391164011641116421164311644116451164611647116481164911650116511165211653116541165511656116571165811659116601166111662116631166411665116661166711668116691167011671116721167311674116751167611677116781167911680116811168211683116841168511686116871168811689116901169111692116931169411695116961169711698116991170011701117021170311704117051170611707117081170911710117111171211713117141171511716117171171811719117201172111722117231172411725117261172711728117291173011731117321173311734117351173611737117381173911740117411174211743117441174511746117471174811749117501175111752117531175411755117561175711758117591176011761117621176311764117651176611767117681176911770117711177211773117741177511776117771177811779117801178111782117831178411785117861178711788117891179011791117921179311794117951179611797117981179911800118011180211803118041180511806118071180811809118101181111812118131181411815118161181711818118191182011821118221182311824118251182611827118281182911830118311183211833118341183511836118371183811839118401184111842118431184411845118461184711848118491185011851118521185311854118551185611857118581185911860118611186211863118641186511866118671186811869118701187111872118731187411875118761187711878118791188011881118821188311884118851188611887118881188911890118911189211893118941189511896118971189811899119001190111902119031190411905119061190711908119091191011911119121191311914119151191611917119181191911920119211192211923119241192511926119271192811929119301193111932119331193411935119361193711938119391194011941119421194311944119451194611947119481194911950119511195211953119541195511956119571195811959119601196111962119631196411965119661196711968119691197011971119721197311974119751197611977119781197911980119811198211983119841198511986119871198811989119901199111992119931199411995119961199711998119991200012001120021200312004120051200612007120081200912010120111201212013120141201512016120171201812019120201202112022120231202412025120261202712028120291203012031120321203312034120351203612037120381203912040120411204212043120441204512046120471204812049120501205112052120531205412055120561205712058120591206012061120621206312064120651206612067120681206912070120711207212073120741207512076120771207812079120801208112082120831208412085120861208712088120891209012091120921209312094120951209612097120981209912100121011210212103121041210512106121071210812109121101211112112121131211412115121161211712118121191212012121121221212312124121251212612127121281212912130121311213212133121341213512136121371213812139121401214112142121431214412145121461214712148121491215012151121521215312154121551215612157121581215912160121611216212163121641216512166121671216812169121701217112172121731217412175121761217712178121791218012181121821218312184121851218612187121881218912190121911219212193121941219512196121971219812199122001220112202122031220412205122061220712208122091221012211122121221312214122151221612217122181221912220122211222212223122241222512226122271222812229122301223112232122331223412235122361223712238122391224012241122421224312244122451224612247122481224912250122511225212253122541225512256122571225812259122601226112262122631226412265122661226712268122691227012271122721227312274122751227612277122781227912280122811228212283122841228512286122871228812289122901229112292122931229412295122961229712298122991230012301123021230312304123051230612307123081230912310123111231212313123141231512316123171231812319123201232112322123231232412325123261232712328123291233012331123321233312334123351233612337123381233912340123411234212343123441234512346123471234812349123501235112352123531235412355123561235712358123591236012361123621236312364123651236612367123681236912370123711237212373123741237512376123771237812379123801238112382123831238412385123861238712388123891239012391123921239312394123951239612397123981239912400124011240212403124041240512406124071240812409124101241112412124131241412415124161241712418124191242012421124221242312424124251242612427124281242912430124311243212433124341243512436124371243812439124401244112442124431244412445124461244712448124491245012451124521245312454124551245612457124581245912460124611246212463124641246512466124671246812469124701247112472124731247412475124761247712478124791248012481124821248312484124851248612487124881248912490124911249212493124941249512496124971249812499125001250112502125031250412505125061250712508125091251012511125121251312514125151251612517125181251912520125211252212523125241252512526125271252812529125301253112532125331253412535125361253712538125391254012541125421254312544125451254612547125481254912550125511255212553125541255512556125571255812559125601256112562125631256412565125661256712568125691257012571125721257312574125751257612577125781257912580125811258212583125841258512586125871258812589125901259112592125931259412595125961259712598125991260012601126021260312604126051260612607126081260912610126111261212613126141261512616126171261812619126201262112622126231262412625126261262712628126291263012631126321263312634126351263612637126381263912640126411264212643126441264512646126471264812649126501265112652126531265412655126561265712658126591266012661126621266312664126651266612667126681266912670126711267212673126741267512676126771267812679126801268112682126831268412685126861268712688126891269012691126921269312694126951269612697126981269912700127011270212703127041270512706127071270812709127101271112712127131271412715127161271712718127191272012721127221272312724127251272612727127281272912730127311273212733127341273512736127371273812739127401274112742127431274412745127461274712748127491275012751127521275312754127551275612757127581275912760127611276212763127641276512766127671276812769127701277112772127731277412775127761277712778127791278012781127821278312784127851278612787127881278912790127911279212793127941279512796127971279812799128001280112802128031280412805128061280712808128091281012811128121281312814128151281612817128181281912820128211282212823128241282512826128271282812829128301283112832128331283412835128361283712838128391284012841128421284312844128451284612847128481284912850128511285212853128541285512856128571285812859128601286112862128631286412865128661286712868128691287012871128721287312874128751287612877128781287912880128811288212883128841288512886128871288812889128901289112892128931289412895128961289712898128991290012901129021290312904129051290612907129081290912910129111291212913129141291512916129171291812919129201292112922129231292412925129261292712928129291293012931129321293312934129351293612937129381293912940129411294212943129441294512946129471294812949129501295112952129531295412955129561295712958129591296012961129621296312964129651296612967129681296912970129711297212973129741297512976129771297812979129801298112982129831298412985129861298712988129891299012991129921299312994129951299612997129981299913000130011300213003130041300513006130071300813009130101301113012130131301413015130161301713018130191302013021130221302313024130251302613027130281302913030130311303213033130341303513036130371303813039130401304113042130431304413045130461304713048130491305013051130521305313054130551305613057130581305913060130611306213063130641306513066130671306813069130701307113072130731307413075130761307713078130791308013081130821308313084130851308613087130881308913090130911309213093130941309513096130971309813099131001310113102131031310413105131061310713108131091311013111131121311313114131151311613117131181311913120131211312213123131241312513126131271312813129131301313113132131331313413135131361313713138131391314013141131421314313144131451314613147131481314913150131511315213153131541315513156131571315813159131601316113162131631316413165131661316713168131691317013171131721317313174131751317613177131781317913180131811318213183131841318513186131871318813189131901319113192131931319413195131961319713198131991320013201132021320313204132051320613207132081320913210132111321213213132141321513216132171321813219132201322113222132231322413225132261322713228132291323013231132321323313234132351323613237132381323913240132411324213243132441324513246132471324813249132501325113252132531325413255132561325713258132591326013261132621326313264132651326613267132681326913270132711327213273132741327513276132771327813279132801328113282132831328413285132861328713288132891329013291132921329313294132951329613297132981329913300133011330213303133041330513306133071330813309133101331113312133131331413315133161331713318133191332013321133221332313324133251332613327133281332913330133311333213333133341333513336133371333813339133401334113342133431334413345133461334713348133491335013351133521335313354133551335613357133581335913360133611336213363133641336513366133671336813369133701337113372133731337413375133761337713378133791338013381133821338313384133851338613387133881338913390133911339213393133941339513396133971339813399134001340113402134031340413405134061340713408134091341013411134121341313414134151341613417134181341913420134211342213423134241342513426134271342813429134301343113432134331343413435134361343713438134391344013441134421344313444134451344613447134481344913450134511345213453134541345513456134571345813459134601346113462134631346413465134661346713468134691347013471134721347313474134751347613477134781347913480134811348213483134841348513486134871348813489134901349113492134931349413495134961349713498134991350013501135021350313504135051350613507135081350913510135111351213513135141351513516135171351813519135201352113522135231352413525135261352713528135291353013531135321353313534135351353613537135381353913540135411354213543135441354513546135471354813549135501355113552135531355413555135561355713558135591356013561135621356313564135651356613567135681356913570135711357213573135741357513576135771357813579135801358113582135831358413585135861358713588135891359013591135921359313594135951359613597135981359913600136011360213603136041360513606136071360813609136101361113612136131361413615136161361713618136191362013621136221362313624136251362613627136281362913630136311363213633136341363513636136371363813639136401364113642136431364413645136461364713648136491365013651136521365313654136551365613657136581365913660136611366213663136641366513666136671366813669136701367113672136731367413675136761367713678136791368013681136821368313684136851368613687136881368913690136911369213693136941369513696136971369813699137001370113702137031370413705137061370713708137091371013711137121371313714137151371613717137181371913720137211372213723137241372513726137271372813729137301373113732137331373413735137361373713738137391374013741137421374313744137451374613747137481374913750137511375213753137541375513756137571375813759137601376113762137631376413765137661376713768137691377013771137721377313774137751377613777137781377913780137811378213783137841378513786137871378813789137901379113792137931379413795137961379713798137991380013801138021380313804138051380613807138081380913810138111381213813138141381513816138171381813819138201382113822138231382413825138261382713828138291383013831138321383313834138351383613837138381383913840138411384213843138441384513846138471384813849138501385113852138531385413855138561385713858138591386013861138621386313864138651386613867138681386913870138711387213873138741387513876138771387813879138801388113882138831388413885138861388713888138891389013891138921389313894138951389613897138981389913900139011390213903139041390513906139071390813909139101391113912139131391413915139161391713918139191392013921139221392313924139251392613927139281392913930139311393213933139341393513936139371393813939139401394113942139431394413945139461394713948139491395013951139521395313954139551395613957139581395913960139611396213963139641396513966139671396813969139701397113972139731397413975139761397713978139791398013981139821398313984139851398613987139881398913990139911399213993139941399513996139971399813999140001400114002140031400414005140061400714008140091401014011140121401314014140151401614017140181401914020140211402214023140241402514026140271402814029140301403114032140331403414035140361403714038140391404014041140421404314044140451404614047140481404914050140511405214053140541405514056140571405814059140601406114062140631406414065140661406714068140691407014071140721407314074140751407614077140781407914080140811408214083140841408514086140871408814089140901409114092140931409414095140961409714098140991410014101141021410314104141051410614107141081410914110141111411214113141141411514116141171411814119141201412114122141231412414125141261412714128141291413014131141321413314134141351413614137141381413914140141411414214143141441414514146141471414814149141501415114152141531415414155141561415714158141591416014161141621416314164141651416614167141681416914170141711417214173141741417514176141771417814179141801418114182141831418414185141861418714188141891419014191141921419314194141951419614197141981419914200142011420214203142041420514206142071420814209142101421114212142131421414215142161421714218142191422014221142221422314224142251422614227142281422914230142311423214233142341423514236142371423814239142401424114242142431424414245142461424714248142491425014251142521425314254142551425614257142581425914260142611426214263142641426514266142671426814269142701427114272142731427414275142761427714278142791428014281142821428314284142851428614287142881428914290142911429214293142941429514296142971429814299143001430114302143031430414305143061430714308143091431014311143121431314314143151431614317143181431914320143211432214323143241432514326143271432814329143301433114332143331433414335143361433714338143391434014341143421434314344143451434614347143481434914350143511435214353143541435514356143571435814359143601436114362143631436414365143661436714368143691437014371143721437314374143751437614377143781437914380143811438214383143841438514386143871438814389143901439114392143931439414395143961439714398143991440014401144021440314404144051440614407144081440914410144111441214413144141441514416144171441814419144201442114422144231442414425144261442714428144291443014431144321443314434144351443614437144381443914440144411444214443144441444514446144471444814449144501445114452144531445414455144561445714458144591446014461144621446314464144651446614467144681446914470144711447214473144741447514476144771447814479144801448114482144831448414485144861448714488144891449014491144921449314494144951449614497144981449914500145011450214503145041450514506145071450814509145101451114512145131451414515145161451714518145191452014521145221452314524145251452614527145281452914530145311453214533145341453514536145371453814539145401454114542145431454414545145461454714548145491455014551145521455314554145551455614557145581455914560145611456214563145641456514566145671456814569145701457114572145731457414575145761457714578145791458014581145821458314584145851458614587145881458914590145911459214593145941459514596145971459814599146001460114602146031460414605146061460714608146091461014611146121461314614146151461614617146181461914620146211462214623146241462514626146271462814629146301463114632146331463414635146361463714638146391464014641146421464314644146451464614647146481464914650146511465214653146541465514656146571465814659146601466114662146631466414665146661466714668146691467014671146721467314674146751467614677146781467914680146811468214683146841468514686146871468814689146901469114692146931469414695146961469714698146991470014701147021470314704147051470614707147081470914710147111471214713147141471514716147171471814719147201472114722147231472414725147261472714728147291473014731147321473314734147351473614737147381473914740147411474214743147441474514746147471474814749147501475114752147531475414755147561475714758147591476014761147621476314764147651476614767147681476914770147711477214773147741477514776147771477814779147801478114782147831478414785147861478714788147891479014791147921479314794147951479614797147981479914800148011480214803148041480514806148071480814809148101481114812148131481414815148161481714818148191482014821148221482314824148251482614827148281482914830148311483214833148341483514836148371483814839148401484114842148431484414845148461484714848148491485014851148521485314854148551485614857148581485914860148611486214863148641486514866148671486814869148701487114872148731487414875148761487714878148791488014881148821488314884148851488614887148881488914890148911489214893148941489514896148971489814899149001490114902149031490414905149061490714908149091491014911149121491314914149151491614917149181491914920149211492214923149241492514926149271492814929149301493114932149331493414935149361493714938149391494014941149421494314944149451494614947149481494914950149511495214953149541495514956149571495814959149601496114962149631496414965149661496714968149691497014971149721497314974149751497614977149781497914980149811498214983149841498514986149871498814989149901499114992149931499414995149961499714998149991500015001150021500315004150051500615007150081500915010150111501215013150141501515016150171501815019150201502115022150231502415025150261502715028150291503015031150321503315034150351503615037150381503915040150411504215043150441504515046150471504815049150501505115052150531505415055150561505715058150591506015061150621506315064150651506615067150681506915070150711507215073150741507515076150771507815079150801508115082150831508415085150861508715088150891509015091150921509315094150951509615097150981509915100151011510215103151041510515106151071510815109151101511115112151131511415115151161511715118151191512015121151221512315124151251512615127151281512915130151311513215133151341513515136151371513815139151401514115142151431514415145151461514715148151491515015151151521515315154151551515615157151581515915160151611516215163151641516515166151671516815169151701517115172151731517415175151761517715178151791518015181151821518315184151851518615187151881518915190151911519215193151941519515196151971519815199152001520115202152031520415205152061520715208152091521015211152121521315214152151521615217152181521915220152211522215223152241522515226152271522815229152301523115232152331523415235152361523715238152391524015241152421524315244152451524615247152481524915250152511525215253152541525515256152571525815259152601526115262152631526415265152661526715268152691527015271152721527315274152751527615277152781527915280152811528215283152841528515286152871528815289152901529115292152931529415295152961529715298152991530015301153021530315304153051530615307153081530915310153111531215313153141531515316153171531815319153201532115322153231532415325153261532715328153291533015331153321533315334153351533615337153381533915340153411534215343153441534515346153471534815349153501535115352153531535415355153561535715358153591536015361153621536315364153651536615367153681536915370153711537215373153741537515376153771537815379153801538115382153831538415385153861538715388153891539015391153921539315394153951539615397153981539915400154011540215403154041540515406154071540815409154101541115412154131541415415154161541715418154191542015421154221542315424154251542615427154281542915430154311543215433154341543515436154371543815439154401544115442154431544415445154461544715448154491545015451154521545315454154551545615457154581545915460154611546215463154641546515466154671546815469154701547115472154731547415475154761547715478154791548015481154821548315484154851548615487154881548915490154911549215493154941549515496154971549815499155001550115502155031550415505155061550715508155091551015511155121551315514155151551615517155181551915520155211552215523155241552515526155271552815529155301553115532155331553415535155361553715538155391554015541155421554315544155451554615547155481554915550155511555215553155541555515556155571555815559155601556115562155631556415565155661556715568155691557015571155721557315574155751557615577155781557915580155811558215583155841558515586155871558815589155901559115592155931559415595155961559715598155991560015601156021560315604156051560615607156081560915610156111561215613156141561515616156171561815619156201562115622156231562415625156261562715628156291563015631156321563315634156351563615637156381563915640156411564215643156441564515646156471564815649156501565115652156531565415655156561565715658156591566015661156621566315664156651566615667156681566915670156711567215673156741567515676156771567815679156801568115682156831568415685156861568715688156891569015691156921569315694156951569615697156981569915700157011570215703157041570515706157071570815709157101571115712157131571415715157161571715718157191572015721157221572315724157251572615727157281572915730157311573215733157341573515736157371573815739157401574115742157431574415745157461574715748157491575015751157521575315754157551575615757157581575915760157611576215763157641576515766157671576815769157701577115772157731577415775157761577715778157791578015781157821578315784157851578615787157881578915790157911579215793157941579515796157971579815799158001580115802158031580415805158061580715808158091581015811158121581315814158151581615817158181581915820158211582215823158241582515826158271582815829158301583115832158331583415835158361583715838158391584015841158421584315844158451584615847158481584915850158511585215853158541585515856158571585815859158601586115862158631586415865158661586715868158691587015871158721587315874158751587615877158781587915880158811588215883158841588515886158871588815889158901589115892158931589415895158961589715898158991590015901159021590315904159051590615907159081590915910159111591215913159141591515916159171591815919159201592115922159231592415925159261592715928159291593015931159321593315934159351593615937159381593915940159411594215943159441594515946159471594815949159501595115952159531595415955159561595715958159591596015961159621596315964159651596615967159681596915970159711597215973159741597515976159771597815979159801598115982159831598415985159861598715988159891599015991159921599315994159951599615997159981599916000160011600216003160041600516006160071600816009160101601116012160131601416015160161601716018160191602016021160221602316024160251602616027160281602916030160311603216033160341603516036160371603816039160401604116042160431604416045160461604716048160491605016051160521605316054160551605616057160581605916060160611606216063160641606516066160671606816069160701607116072160731607416075160761607716078160791608016081160821608316084160851608616087160881608916090160911609216093160941609516096160971609816099161001610116102161031610416105161061610716108161091611016111161121611316114161151611616117161181611916120161211612216123161241612516126161271612816129161301613116132161331613416135161361613716138161391614016141161421614316144161451614616147161481614916150161511615216153161541615516156161571615816159161601616116162161631616416165161661616716168161691617016171161721617316174161751617616177161781617916180161811618216183161841618516186161871618816189161901619116192161931619416195161961619716198161991620016201162021620316204162051620616207162081620916210162111621216213162141621516216162171621816219162201622116222162231622416225162261622716228162291623016231162321623316234162351623616237162381623916240162411624216243162441624516246162471624816249162501625116252162531625416255162561625716258162591626016261162621626316264162651626616267162681626916270162711627216273162741627516276162771627816279162801628116282162831628416285162861628716288162891629016291162921629316294162951629616297162981629916300163011630216303163041630516306163071630816309163101631116312163131631416315163161631716318163191632016321163221632316324163251632616327163281632916330163311633216333163341633516336163371633816339163401634116342163431634416345163461634716348163491635016351163521635316354163551635616357163581635916360163611636216363163641636516366163671636816369163701637116372163731637416375163761637716378163791638016381163821638316384163851638616387163881638916390163911639216393163941639516396163971639816399164001640116402164031640416405164061640716408164091641016411164121641316414164151641616417164181641916420164211642216423164241642516426164271642816429164301643116432164331643416435164361643716438164391644016441164421644316444164451644616447164481644916450164511645216453164541645516456164571645816459164601646116462164631646416465164661646716468164691647016471164721647316474164751647616477164781647916480164811648216483164841648516486164871648816489164901649116492164931649416495164961649716498164991650016501165021650316504165051650616507165081650916510165111651216513165141651516516165171651816519165201652116522165231652416525165261652716528165291653016531165321653316534165351653616537165381653916540165411654216543165441654516546165471654816549165501655116552165531655416555165561655716558165591656016561165621656316564165651656616567165681656916570165711657216573165741657516576165771657816579165801658116582165831658416585165861658716588165891659016591165921659316594165951659616597165981659916600166011660216603166041660516606166071660816609166101661116612166131661416615166161661716618166191662016621166221662316624166251662616627166281662916630166311663216633166341663516636166371663816639166401664116642166431664416645166461664716648166491665016651166521665316654166551665616657166581665916660166611666216663166641666516666166671666816669166701667116672166731667416675166761667716678166791668016681166821668316684166851668616687166881668916690166911669216693166941669516696166971669816699167001670116702167031670416705167061670716708167091671016711167121671316714167151671616717167181671916720167211672216723167241672516726167271672816729167301673116732167331673416735167361673716738167391674016741167421674316744167451674616747167481674916750167511675216753167541675516756167571675816759167601676116762167631676416765167661676716768167691677016771167721677316774167751677616777167781677916780167811678216783167841678516786167871678816789167901679116792167931679416795167961679716798167991680016801168021680316804168051680616807168081680916810168111681216813168141681516816168171681816819168201682116822168231682416825168261682716828168291683016831168321683316834168351683616837168381683916840168411684216843168441684516846168471684816849168501685116852168531685416855168561685716858168591686016861168621686316864168651686616867168681686916870168711687216873168741687516876168771687816879168801688116882168831688416885168861688716888168891689016891168921689316894168951689616897168981689916900169011690216903169041690516906169071690816909169101691116912169131691416915169161691716918169191692016921169221692316924169251692616927169281692916930169311693216933169341693516936169371693816939169401694116942169431694416945169461694716948169491695016951169521695316954169551695616957169581695916960169611696216963169641696516966169671696816969169701697116972169731697416975169761697716978169791698016981169821698316984169851698616987169881698916990169911699216993169941699516996169971699816999170001700117002170031700417005170061700717008170091701017011170121701317014170151701617017170181701917020170211702217023170241702517026170271702817029170301703117032170331703417035170361703717038170391704017041170421704317044170451704617047170481704917050170511705217053170541705517056170571705817059170601706117062170631706417065170661706717068170691707017071170721707317074170751707617077170781707917080170811708217083170841708517086170871708817089170901709117092170931709417095170961709717098170991710017101171021710317104171051710617107171081710917110171111711217113171141711517116171171711817119171201712117122171231712417125171261712717128171291713017131171321713317134171351713617137171381713917140171411714217143171441714517146171471714817149171501715117152171531715417155171561715717158171591716017161171621716317164171651716617167171681716917170171711717217173171741717517176171771717817179171801718117182171831718417185171861718717188171891719017191171921719317194171951719617197171981719917200172011720217203172041720517206172071720817209172101721117212172131721417215172161721717218172191722017221172221722317224172251722617227172281722917230172311723217233172341723517236172371723817239172401724117242172431724417245172461724717248172491725017251172521725317254172551725617257172581725917260172611726217263172641726517266172671726817269172701727117272172731727417275172761727717278172791728017281172821728317284172851728617287172881728917290172911729217293172941729517296172971729817299173001730117302173031730417305173061730717308173091731017311173121731317314173151731617317173181731917320173211732217323173241732517326173271732817329173301733117332173331733417335173361733717338173391734017341173421734317344173451734617347173481734917350173511735217353173541735517356173571735817359173601736117362173631736417365173661736717368173691737017371173721737317374173751737617377173781737917380173811738217383173841738517386173871738817389173901739117392173931739417395173961739717398173991740017401174021740317404174051740617407174081740917410174111741217413174141741517416174171741817419174201742117422174231742417425174261742717428174291743017431174321743317434174351743617437174381743917440174411744217443174441744517446174471744817449174501745117452174531745417455174561745717458174591746017461174621746317464174651746617467174681746917470174711747217473174741747517476174771747817479174801748117482174831748417485174861748717488174891749017491174921749317494174951749617497174981749917500175011750217503175041750517506175071750817509175101751117512175131751417515175161751717518175191752017521175221752317524175251752617527175281752917530175311753217533175341753517536175371753817539175401754117542175431754417545175461754717548175491755017551175521755317554175551755617557175581755917560175611756217563175641756517566175671756817569175701757117572175731757417575175761757717578175791758017581175821758317584175851758617587175881758917590175911759217593175941759517596175971759817599176001760117602176031760417605176061760717608176091761017611176121761317614176151761617617176181761917620176211762217623176241762517626176271762817629176301763117632176331763417635176361763717638176391764017641176421764317644176451764617647176481764917650176511765217653176541765517656176571765817659176601766117662176631766417665176661766717668176691767017671176721767317674176751767617677176781767917680176811768217683176841768517686176871768817689176901769117692176931769417695176961769717698176991770017701177021770317704177051770617707177081770917710177111771217713177141771517716177171771817719177201772117722177231772417725177261772717728177291773017731177321773317734177351773617737177381773917740177411774217743177441774517746177471774817749177501775117752177531775417755177561775717758177591776017761177621776317764177651776617767177681776917770177711777217773177741777517776177771777817779177801778117782177831778417785177861778717788177891779017791177921779317794177951779617797177981779917800178011780217803178041780517806178071780817809178101781117812178131781417815178161781717818178191782017821178221782317824178251782617827178281782917830178311783217833178341783517836178371783817839178401784117842178431784417845178461784717848178491785017851178521785317854178551785617857178581785917860178611786217863178641786517866178671786817869178701787117872178731787417875178761787717878178791788017881178821788317884178851788617887178881788917890178911789217893178941789517896178971789817899179001790117902179031790417905179061790717908179091791017911179121791317914179151791617917179181791917920179211792217923179241792517926179271792817929179301793117932179331793417935179361793717938179391794017941179421794317944179451794617947179481794917950179511795217953179541795517956179571795817959179601796117962179631796417965179661796717968179691797017971179721797317974179751797617977179781797917980179811798217983179841798517986179871798817989179901799117992179931799417995179961799717998179991800018001180021800318004180051800618007180081800918010180111801218013180141801518016180171801818019180201802118022180231802418025180261802718028180291803018031180321803318034180351803618037180381803918040180411804218043180441804518046180471804818049180501805118052180531805418055180561805718058180591806018061180621806318064180651806618067180681806918070180711807218073180741807518076180771807818079180801808118082180831808418085180861808718088180891809018091180921809318094180951809618097180981809918100181011810218103181041810518106181071810818109181101811118112181131811418115181161811718118181191812018121181221812318124181251812618127181281812918130181311813218133181341813518136181371813818139181401814118142181431814418145181461814718148181491815018151181521815318154181551815618157181581815918160181611816218163181641816518166181671816818169181701817118172181731817418175181761817718178181791818018181181821818318184181851818618187181881818918190181911819218193181941819518196181971819818199182001820118202182031820418205182061820718208182091821018211182121821318214182151821618217182181821918220182211822218223182241822518226182271822818229182301823118232182331823418235182361823718238182391824018241182421824318244182451824618247182481824918250182511825218253182541825518256182571825818259182601826118262182631826418265182661826718268182691827018271182721827318274182751827618277182781827918280182811828218283182841828518286182871828818289182901829118292182931829418295182961829718298182991830018301183021830318304183051830618307183081830918310183111831218313183141831518316183171831818319183201832118322183231832418325183261832718328183291833018331183321833318334183351833618337183381833918340183411834218343183441834518346183471834818349183501835118352183531835418355183561835718358183591836018361183621836318364183651836618367183681836918370183711837218373183741837518376183771837818379183801838118382183831838418385183861838718388183891839018391183921839318394183951839618397183981839918400184011840218403184041840518406184071840818409184101841118412184131841418415184161841718418184191842018421184221842318424184251842618427184281842918430184311843218433184341843518436184371843818439184401844118442184431844418445184461844718448184491845018451184521845318454184551845618457184581845918460184611846218463184641846518466184671846818469184701847118472184731847418475184761847718478184791848018481184821848318484184851848618487184881848918490184911849218493184941849518496184971849818499185001850118502185031850418505185061850718508185091851018511185121851318514185151851618517185181851918520185211852218523185241852518526185271852818529185301853118532185331853418535185361853718538185391854018541185421854318544185451854618547185481854918550185511855218553185541855518556185571855818559185601856118562185631856418565185661856718568185691857018571185721857318574185751857618577185781857918580185811858218583185841858518586185871858818589185901859118592185931859418595185961859718598185991860018601186021860318604186051860618607186081860918610186111861218613186141861518616186171861818619186201862118622186231862418625186261862718628186291863018631186321863318634186351863618637186381863918640186411864218643186441864518646186471864818649186501865118652186531865418655186561865718658186591866018661186621866318664186651866618667186681866918670186711867218673186741867518676186771867818679186801868118682186831868418685186861868718688186891869018691186921869318694186951869618697186981869918700187011870218703187041870518706187071870818709187101871118712187131871418715187161871718718187191872018721187221872318724187251872618727187281872918730187311873218733187341873518736187371873818739187401874118742187431874418745187461874718748187491875018751187521875318754187551875618757187581875918760187611876218763187641876518766187671876818769187701877118772187731877418775187761877718778187791878018781187821878318784187851878618787187881878918790187911879218793187941879518796187971879818799188001880118802188031880418805188061880718808188091881018811188121881318814188151881618817188181881918820188211882218823188241882518826188271882818829188301883118832188331883418835188361883718838188391884018841188421884318844188451884618847188481884918850188511885218853188541885518856188571885818859188601886118862188631886418865188661886718868188691887018871188721887318874188751887618877188781887918880188811888218883188841888518886188871888818889188901889118892188931889418895188961889718898188991890018901189021890318904189051890618907189081890918910189111891218913189141891518916189171891818919189201892118922189231892418925189261892718928189291893018931189321893318934189351893618937189381893918940189411894218943189441894518946189471894818949189501895118952189531895418955189561895718958189591896018961189621896318964189651896618967189681896918970189711897218973189741897518976189771897818979189801898118982189831898418985189861898718988189891899018991189921899318994189951899618997189981899919000190011900219003190041900519006190071900819009190101901119012190131901419015190161901719018190191902019021190221902319024190251902619027190281902919030190311903219033190341903519036190371903819039190401904119042190431904419045190461904719048190491905019051190521905319054190551905619057190581905919060190611906219063190641906519066190671906819069190701907119072190731907419075190761907719078190791908019081190821908319084190851908619087190881908919090190911909219093190941909519096190971909819099191001910119102191031910419105191061910719108191091911019111191121911319114191151911619117191181911919120191211912219123191241912519126191271912819129191301913119132191331913419135191361913719138191391914019141191421914319144191451914619147191481914919150191511915219153191541915519156191571915819159191601916119162191631916419165191661916719168191691917019171191721917319174191751917619177191781917919180191811918219183191841918519186191871918819189191901919119192191931919419195191961919719198191991920019201192021920319204192051920619207192081920919210192111921219213192141921519216192171921819219192201922119222192231922419225192261922719228192291923019231192321923319234192351923619237192381923919240192411924219243192441924519246192471924819249192501925119252192531925419255192561925719258192591926019261192621926319264192651926619267192681926919270192711927219273192741927519276192771927819279192801928119282192831928419285192861928719288192891929019291192921929319294192951929619297192981929919300193011930219303193041930519306193071930819309193101931119312193131931419315193161931719318193191932019321193221932319324193251932619327193281932919330193311933219333193341933519336193371933819339193401934119342193431934419345193461934719348193491935019351193521935319354193551935619357193581935919360193611936219363193641936519366193671936819369193701937119372193731937419375193761937719378193791938019381193821938319384193851938619387193881938919390193911939219393193941939519396193971939819399194001940119402194031940419405194061940719408194091941019411194121941319414194151941619417194181941919420194211942219423194241942519426194271942819429194301943119432194331943419435194361943719438194391944019441194421944319444194451944619447194481944919450194511945219453194541945519456194571945819459194601946119462194631946419465194661946719468194691947019471194721947319474194751947619477194781947919480194811948219483194841948519486194871948819489194901949119492194931949419495194961949719498194991950019501195021950319504195051950619507195081950919510195111951219513195141951519516195171951819519195201952119522195231952419525195261952719528195291953019531195321953319534195351953619537195381953919540195411954219543195441954519546195471954819549195501955119552195531955419555195561955719558195591956019561195621956319564195651956619567195681956919570195711957219573195741957519576195771957819579195801958119582195831958419585195861958719588195891959019591195921959319594195951959619597195981959919600196011960219603196041960519606196071960819609196101961119612196131961419615196161961719618196191962019621196221962319624196251962619627196281962919630196311963219633196341963519636196371963819639196401964119642196431964419645196461964719648196491965019651196521965319654196551965619657196581965919660196611966219663196641966519666196671966819669196701967119672196731967419675196761967719678196791968019681196821968319684196851968619687196881968919690196911969219693196941969519696196971969819699197001970119702197031970419705197061970719708197091971019711197121971319714197151971619717197181971919720197211972219723197241972519726197271972819729197301973119732197331973419735197361973719738197391974019741197421974319744197451974619747197481974919750197511975219753197541975519756197571975819759197601976119762197631976419765197661976719768197691977019771197721977319774197751977619777197781977919780197811978219783197841978519786197871978819789197901979119792197931979419795197961979719798197991980019801198021980319804198051980619807198081980919810198111981219813198141981519816198171981819819198201982119822198231982419825198261982719828198291983019831198321983319834198351983619837198381983919840198411984219843198441984519846198471984819849198501985119852198531985419855198561985719858198591986019861198621986319864198651986619867198681986919870198711987219873198741987519876198771987819879198801988119882198831988419885198861988719888198891989019891198921989319894198951989619897198981989919900199011990219903199041990519906199071990819909199101991119912199131991419915199161991719918199191992019921199221992319924199251992619927199281992919930199311993219933199341993519936199371993819939199401994119942199431994419945199461994719948199491995019951199521995319954199551995619957199581995919960199611996219963199641996519966199671996819969199701997119972199731997419975199761997719978199791998019981199821998319984199851998619987199881998919990199911999219993199941999519996199971999819999200002000120002200032000420005200062000720008200092001020011200122001320014200152001620017200182001920020200212002220023200242002520026200272002820029200302003120032200332003420035200362003720038200392004020041200422004320044200452004620047200482004920050200512005220053200542005520056200572005820059200602006120062200632006420065200662006720068200692007020071200722007320074200752007620077200782007920080200812008220083200842008520086200872008820089200902009120092200932009420095200962009720098200992010020101201022010320104201052010620107201082010920110201112011220113201142011520116201172011820119201202012120122201232012420125201262012720128201292013020131201322013320134201352013620137201382013920140201412014220143201442014520146201472014820149201502015120152201532015420155201562015720158201592016020161201622016320164201652016620167201682016920170201712017220173201742017520176201772017820179201802018120182201832018420185201862018720188201892019020191201922019320194201952019620197201982019920200202012020220203202042020520206202072020820209202102021120212202132021420215202162021720218202192022020221202222022320224202252022620227202282022920230202312023220233202342023520236202372023820239202402024120242202432024420245202462024720248202492025020251202522025320254202552025620257202582025920260202612026220263202642026520266202672026820269202702027120272202732027420275202762027720278202792028020281202822028320284202852028620287202882028920290202912029220293202942029520296202972029820299203002030120302203032030420305203062030720308203092031020311203122031320314203152031620317203182031920320203212032220323203242032520326203272032820329203302033120332203332033420335203362033720338203392034020341203422034320344203452034620347203482034920350203512035220353203542035520356203572035820359203602036120362203632036420365203662036720368203692037020371203722037320374203752037620377203782037920380203812038220383203842038520386203872038820389203902039120392203932039420395203962039720398203992040020401204022040320404204052040620407204082040920410204112041220413204142041520416204172041820419204202042120422204232042420425204262042720428204292043020431204322043320434204352043620437204382043920440204412044220443204442044520446204472044820449204502045120452204532045420455204562045720458204592046020461204622046320464204652046620467204682046920470204712047220473204742047520476204772047820479204802048120482204832048420485204862048720488204892049020491204922049320494204952049620497204982049920500205012050220503205042050520506205072050820509205102051120512205132051420515205162051720518205192052020521205222052320524205252052620527205282052920530205312053220533205342053520536205372053820539205402054120542205432054420545205462054720548205492055020551205522055320554205552055620557205582055920560205612056220563205642056520566205672056820569205702057120572205732057420575205762057720578205792058020581205822058320584205852058620587205882058920590205912059220593205942059520596205972059820599206002060120602206032060420605206062060720608206092061020611206122061320614206152061620617206182061920620206212062220623206242062520626206272062820629206302063120632206332063420635206362063720638206392064020641206422064320644206452064620647206482064920650206512065220653206542065520656206572065820659206602066120662206632066420665206662066720668206692067020671206722067320674206752067620677206782067920680206812068220683206842068520686206872068820689206902069120692206932069420695206962069720698206992070020701207022070320704207052070620707207082070920710207112071220713207142071520716207172071820719207202072120722207232072420725207262072720728207292073020731207322073320734207352073620737207382073920740207412074220743207442074520746207472074820749207502075120752207532075420755207562075720758207592076020761207622076320764207652076620767207682076920770207712077220773207742077520776207772077820779207802078120782207832078420785207862078720788207892079020791207922079320794207952079620797207982079920800208012080220803208042080520806208072080820809208102081120812208132081420815208162081720818208192082020821208222082320824208252082620827208282082920830208312083220833208342083520836208372083820839208402084120842208432084420845208462084720848208492085020851208522085320854208552085620857208582085920860208612086220863208642086520866208672086820869208702087120872208732087420875208762087720878208792088020881208822088320884208852088620887208882088920890208912089220893208942089520896208972089820899209002090120902209032090420905209062090720908209092091020911209122091320914209152091620917209182091920920209212092220923209242092520926209272092820929209302093120932209332093420935209362093720938209392094020941209422094320944209452094620947209482094920950209512095220953209542095520956209572095820959209602096120962209632096420965209662096720968209692097020971209722097320974209752097620977209782097920980209812098220983209842098520986209872098820989209902099120992209932099420995209962099720998209992100021001210022100321004210052100621007210082100921010210112101221013210142101521016210172101821019210202102121022210232102421025210262102721028210292103021031210322103321034210352103621037210382103921040210412104221043210442104521046210472104821049210502105121052210532105421055210562105721058210592106021061210622106321064210652106621067210682106921070210712107221073210742107521076210772107821079210802108121082210832108421085210862108721088210892109021091210922109321094210952109621097210982109921100211012110221103211042110521106211072110821109211102111121112211132111421115211162111721118211192112021121211222112321124211252112621127211282112921130211312113221133211342113521136211372113821139211402114121142211432114421145211462114721148211492115021151211522115321154211552115621157211582115921160211612116221163211642116521166211672116821169211702117121172211732117421175211762117721178211792118021181211822118321184211852118621187211882118921190211912119221193211942119521196211972119821199212002120121202212032120421205212062120721208212092121021211212122121321214212152121621217212182121921220212212122221223212242122521226212272122821229212302123121232212332123421235212362123721238212392124021241212422124321244212452124621247212482124921250212512125221253212542125521256212572125821259212602126121262212632126421265212662126721268212692127021271212722127321274212752127621277212782127921280212812128221283212842128521286212872128821289212902129121292212932129421295212962129721298212992130021301213022130321304213052130621307213082130921310213112131221313213142131521316213172131821319213202132121322213232132421325213262132721328213292133021331213322133321334213352133621337213382133921340213412134221343213442134521346213472134821349213502135121352213532135421355213562135721358213592136021361213622136321364213652136621367213682136921370213712137221373213742137521376213772137821379213802138121382213832138421385213862138721388213892139021391213922139321394213952139621397213982139921400214012140221403214042140521406214072140821409214102141121412214132141421415214162141721418214192142021421214222142321424214252142621427214282142921430214312143221433214342143521436214372143821439214402144121442214432144421445214462144721448214492145021451214522145321454214552145621457214582145921460214612146221463214642146521466214672146821469214702147121472214732147421475214762147721478214792148021481214822148321484214852148621487214882148921490214912149221493214942149521496214972149821499215002150121502215032150421505215062150721508215092151021511215122151321514215152151621517215182151921520215212152221523215242152521526215272152821529215302153121532215332153421535215362153721538215392154021541215422154321544215452154621547215482154921550215512155221553215542155521556215572155821559215602156121562215632156421565215662156721568215692157021571215722157321574215752157621577215782157921580215812158221583215842158521586215872158821589215902159121592215932159421595215962159721598215992160021601216022160321604216052160621607216082160921610216112161221613216142161521616216172161821619216202162121622216232162421625216262162721628216292163021631216322163321634216352163621637216382163921640216412164221643216442164521646216472164821649216502165121652216532165421655216562165721658216592166021661216622166321664216652166621667216682166921670216712167221673216742167521676216772167821679216802168121682216832168421685216862168721688216892169021691216922169321694216952169621697216982169921700217012170221703217042170521706217072170821709217102171121712217132171421715217162171721718217192172021721217222172321724217252172621727217282172921730217312173221733217342173521736217372173821739217402174121742217432174421745217462174721748217492175021751217522175321754217552175621757217582175921760217612176221763217642176521766217672176821769217702177121772217732177421775217762177721778217792178021781217822178321784217852178621787217882178921790217912179221793217942179521796217972179821799218002180121802218032180421805218062180721808218092181021811218122181321814218152181621817218182181921820218212182221823218242182521826218272182821829218302183121832218332183421835218362183721838218392184021841218422184321844218452184621847218482184921850218512185221853218542185521856218572185821859218602186121862218632186421865218662186721868218692187021871218722187321874218752187621877218782187921880218812188221883218842188521886218872188821889218902189121892218932189421895218962189721898218992190021901219022190321904219052190621907219082190921910219112191221913219142191521916219172191821919219202192121922219232192421925219262192721928219292193021931219322193321934219352193621937219382193921940219412194221943219442194521946219472194821949219502195121952219532195421955219562195721958219592196021961219622196321964219652196621967219682196921970219712197221973219742197521976219772197821979219802198121982219832198421985219862198721988219892199021991219922199321994219952199621997219982199922000220012200222003220042200522006220072200822009220102201122012220132201422015220162201722018220192202022021220222202322024220252202622027220282202922030220312203222033220342203522036220372203822039220402204122042220432204422045220462204722048220492205022051220522205322054220552205622057220582205922060220612206222063220642206522066220672206822069220702207122072220732207422075220762207722078220792208022081220822208322084220852208622087220882208922090220912209222093220942209522096220972209822099221002210122102221032210422105221062210722108221092211022111221122211322114221152211622117221182211922120221212212222123221242212522126221272212822129221302213122132221332213422135221362213722138221392214022141221422214322144221452214622147221482214922150221512215222153221542215522156221572215822159221602216122162221632216422165221662216722168221692217022171221722217322174221752217622177221782217922180221812218222183221842218522186221872218822189221902219122192221932219422195221962219722198221992220022201222022220322204222052220622207222082220922210222112221222213222142221522216222172221822219222202222122222222232222422225222262222722228222292223022231222322223322234222352223622237222382223922240222412224222243222442224522246222472224822249222502225122252222532225422255222562225722258222592226022261222622226322264222652226622267222682226922270222712227222273222742227522276222772227822279222802228122282222832228422285222862228722288222892229022291222922229322294222952229622297222982229922300223012230222303223042230522306223072230822309223102231122312223132231422315223162231722318223192232022321223222232322324223252232622327223282232922330223312233222333223342233522336223372233822339223402234122342223432234422345223462234722348223492235022351223522235322354223552235622357223582235922360223612236222363223642236522366223672236822369223702237122372223732237422375223762237722378223792238022381223822238322384223852238622387223882238922390223912239222393223942239522396223972239822399224002240122402224032240422405224062240722408224092241022411224122241322414224152241622417224182241922420224212242222423224242242522426224272242822429224302243122432224332243422435224362243722438224392244022441224422244322444224452244622447224482244922450224512245222453224542245522456224572245822459224602246122462224632246422465224662246722468224692247022471224722247322474224752247622477224782247922480224812248222483224842248522486224872248822489224902249122492224932249422495224962249722498224992250022501225022250322504225052250622507225082250922510225112251222513225142251522516225172251822519225202252122522225232252422525225262252722528225292253022531225322253322534225352253622537225382253922540225412254222543225442254522546225472254822549225502255122552225532255422555225562255722558225592256022561225622256322564225652256622567225682256922570225712257222573225742257522576225772257822579225802258122582225832258422585225862258722588225892259022591225922259322594225952259622597225982259922600226012260222603226042260522606226072260822609226102261122612226132261422615226162261722618226192262022621226222262322624226252262622627226282262922630226312263222633226342263522636226372263822639226402264122642226432264422645226462264722648226492265022651226522265322654226552265622657226582265922660226612266222663226642266522666226672266822669226702267122672226732267422675226762267722678226792268022681226822268322684226852268622687226882268922690226912269222693226942269522696226972269822699227002270122702227032270422705227062270722708227092271022711227122271322714227152271622717227182271922720227212272222723227242272522726227272272822729227302273122732227332273422735227362273722738227392274022741227422274322744227452274622747227482274922750227512275222753227542275522756227572275822759227602276122762227632276422765227662276722768227692277022771227722277322774227752277622777227782277922780227812278222783227842278522786227872278822789227902279122792227932279422795227962279722798227992280022801228022280322804228052280622807228082280922810228112281222813228142281522816228172281822819228202282122822228232282422825228262282722828228292283022831228322283322834228352283622837228382283922840228412284222843228442284522846228472284822849228502285122852228532285422855228562285722858228592286022861228622286322864228652286622867228682286922870228712287222873228742287522876228772287822879228802288122882228832288422885228862288722888228892289022891228922289322894228952289622897228982289922900229012290222903229042290522906229072290822909229102291122912229132291422915229162291722918229192292022921229222292322924229252292622927229282292922930229312293222933229342293522936229372293822939229402294122942229432294422945229462294722948229492295022951229522295322954229552295622957229582295922960229612296222963229642296522966229672296822969229702297122972229732297422975229762297722978229792298022981229822298322984229852298622987229882298922990229912299222993229942299522996229972299822999230002300123002230032300423005230062300723008230092301023011230122301323014230152301623017230182301923020230212302223023230242302523026230272302823029230302303123032230332303423035230362303723038230392304023041230422304323044230452304623047230482304923050230512305223053230542305523056230572305823059230602306123062230632306423065230662306723068230692307023071230722307323074230752307623077230782307923080230812308223083230842308523086230872308823089230902309123092230932309423095230962309723098230992310023101231022310323104231052310623107231082310923110231112311223113231142311523116231172311823119231202312123122231232312423125231262312723128231292313023131231322313323134231352313623137231382313923140231412314223143231442314523146231472314823149231502315123152231532315423155231562315723158231592316023161231622316323164231652316623167231682316923170231712317223173231742317523176231772317823179231802318123182231832318423185231862318723188231892319023191231922319323194231952319623197231982319923200232012320223203232042320523206232072320823209232102321123212232132321423215232162321723218232192322023221232222322323224232252322623227232282322923230232312323223233232342323523236232372323823239232402324123242232432324423245232462324723248232492325023251232522325323254232552325623257232582325923260232612326223263232642326523266232672326823269232702327123272232732327423275232762327723278232792328023281232822328323284232852328623287232882328923290232912329223293232942329523296232972329823299233002330123302233032330423305233062330723308233092331023311233122331323314233152331623317233182331923320233212332223323233242332523326233272332823329233302333123332233332333423335233362333723338233392334023341233422334323344233452334623347233482334923350233512335223353233542335523356233572335823359233602336123362233632336423365233662336723368233692337023371233722337323374233752337623377233782337923380233812338223383233842338523386233872338823389233902339123392233932339423395233962339723398233992340023401234022340323404234052340623407234082340923410234112341223413234142341523416234172341823419234202342123422234232342423425234262342723428234292343023431234322343323434234352343623437234382343923440234412344223443234442344523446234472344823449234502345123452234532345423455234562345723458234592346023461234622346323464234652346623467234682346923470234712347223473234742347523476234772347823479234802348123482234832348423485234862348723488234892349023491234922349323494234952349623497234982349923500235012350223503235042350523506235072350823509235102351123512235132351423515235162351723518235192352023521235222352323524235252352623527235282352923530235312353223533235342353523536235372353823539235402354123542235432354423545235462354723548235492355023551235522355323554235552355623557235582355923560235612356223563235642356523566235672356823569235702357123572235732357423575235762357723578235792358023581235822358323584235852358623587235882358923590235912359223593235942359523596235972359823599236002360123602236032360423605236062360723608236092361023611236122361323614236152361623617236182361923620236212362223623236242362523626236272362823629236302363123632236332363423635236362363723638236392364023641236422364323644236452364623647236482364923650236512365223653236542365523656236572365823659236602366123662236632366423665236662366723668236692367023671236722367323674236752367623677236782367923680236812368223683236842368523686236872368823689236902369123692236932369423695236962369723698236992370023701237022370323704237052370623707237082370923710237112371223713237142371523716237172371823719237202372123722237232372423725237262372723728237292373023731237322373323734237352373623737237382373923740237412374223743237442374523746237472374823749237502375123752237532375423755237562375723758237592376023761237622376323764237652376623767237682376923770237712377223773237742377523776237772377823779237802378123782237832378423785237862378723788237892379023791237922379323794237952379623797237982379923800238012380223803238042380523806238072380823809238102381123812238132381423815238162381723818238192382023821238222382323824238252382623827238282382923830238312383223833238342383523836238372383823839238402384123842238432384423845238462384723848238492385023851238522385323854238552385623857238582385923860238612386223863238642386523866238672386823869238702387123872238732387423875238762387723878238792388023881238822388323884238852388623887238882388923890238912389223893238942389523896238972389823899239002390123902239032390423905239062390723908239092391023911239122391323914239152391623917239182391923920239212392223923239242392523926239272392823929239302393123932239332393423935239362393723938239392394023941239422394323944239452394623947239482394923950239512395223953239542395523956239572395823959239602396123962239632396423965239662396723968239692397023971239722397323974239752397623977239782397923980239812398223983239842398523986239872398823989239902399123992239932399423995239962399723998239992400024001240022400324004240052400624007240082400924010240112401224013240142401524016240172401824019240202402124022240232402424025240262402724028240292403024031240322403324034240352403624037240382403924040240412404224043240442404524046240472404824049240502405124052240532405424055240562405724058240592406024061240622406324064240652406624067240682406924070240712407224073240742407524076240772407824079240802408124082240832408424085240862408724088240892409024091240922409324094240952409624097240982409924100241012410224103241042410524106241072410824109241102411124112241132411424115241162411724118241192412024121241222412324124241252412624127241282412924130241312413224133241342413524136241372413824139241402414124142241432414424145241462414724148241492415024151241522415324154241552415624157241582415924160241612416224163241642416524166241672416824169241702417124172241732417424175241762417724178241792418024181241822418324184241852418624187241882418924190241912419224193241942419524196241972419824199242002420124202242032420424205242062420724208242092421024211242122421324214242152421624217242182421924220242212422224223242242422524226242272422824229242302423124232242332423424235242362423724238242392424024241242422424324244242452424624247242482424924250242512425224253242542425524256242572425824259242602426124262242632426424265242662426724268242692427024271242722427324274242752427624277242782427924280242812428224283242842428524286242872428824289242902429124292242932429424295242962429724298242992430024301243022430324304243052430624307243082430924310243112431224313243142431524316243172431824319243202432124322243232432424325243262432724328243292433024331243322433324334243352433624337243382433924340243412434224343243442434524346243472434824349243502435124352243532435424355243562435724358243592436024361243622436324364243652436624367243682436924370243712437224373243742437524376243772437824379243802438124382243832438424385243862438724388243892439024391243922439324394243952439624397243982439924400244012440224403244042440524406244072440824409244102441124412244132441424415244162441724418244192442024421244222442324424244252442624427244282442924430244312443224433244342443524436244372443824439244402444124442244432444424445244462444724448244492445024451244522445324454244552445624457244582445924460244612446224463244642446524466244672446824469244702447124472244732447424475244762447724478244792448024481244822448324484244852448624487244882448924490244912449224493244942449524496244972449824499245002450124502245032450424505245062450724508245092451024511245122451324514245152451624517245182451924520245212452224523245242452524526245272452824529245302453124532245332453424535245362453724538245392454024541245422454324544245452454624547245482454924550245512455224553245542455524556245572455824559245602456124562245632456424565245662456724568245692457024571245722457324574245752457624577245782457924580245812458224583245842458524586245872458824589245902459124592245932459424595245962459724598245992460024601246022460324604246052460624607246082460924610246112461224613246142461524616246172461824619246202462124622246232462424625246262462724628246292463024631246322463324634246352463624637246382463924640246412464224643246442464524646246472464824649246502465124652246532465424655246562465724658246592466024661246622466324664246652466624667246682466924670246712467224673246742467524676246772467824679246802468124682246832468424685246862468724688246892469024691246922469324694246952469624697246982469924700247012470224703247042470524706247072470824709247102471124712247132471424715247162471724718247192472024721247222472324724247252472624727247282472924730247312473224733247342473524736247372473824739247402474124742247432474424745247462474724748247492475024751247522475324754247552475624757247582475924760247612476224763247642476524766247672476824769247702477124772247732477424775247762477724778247792478024781247822478324784247852478624787247882478924790247912479224793247942479524796247972479824799248002480124802248032480424805248062480724808248092481024811248122481324814248152481624817248182481924820248212482224823248242482524826248272482824829248302483124832248332483424835248362483724838248392484024841248422484324844248452484624847248482484924850248512485224853248542485524856248572485824859248602486124862248632486424865248662486724868248692487024871248722487324874248752487624877248782487924880248812488224883248842488524886248872488824889248902489124892248932489424895248962489724898248992490024901249022490324904249052490624907249082490924910249112491224913249142491524916249172491824919249202492124922249232492424925249262492724928249292493024931249322493324934249352493624937249382493924940249412494224943249442494524946249472494824949249502495124952249532495424955249562495724958249592496024961249622496324964249652496624967249682496924970249712497224973249742497524976249772497824979249802498124982249832498424985249862498724988249892499024991249922499324994249952499624997249982499925000250012500225003250042500525006250072500825009250102501125012250132501425015250162501725018250192502025021250222502325024250252502625027250282502925030250312503225033250342503525036250372503825039250402504125042250432504425045250462504725048250492505025051250522505325054250552505625057250582505925060250612506225063250642506525066250672506825069250702507125072250732507425075250762507725078250792508025081250822508325084250852508625087250882508925090250912509225093250942509525096250972509825099251002510125102251032510425105251062510725108251092511025111251122511325114251152511625117251182511925120251212512225123251242512525126251272512825129251302513125132251332513425135251362513725138251392514025141251422514325144251452514625147251482514925150251512515225153251542515525156251572515825159251602516125162251632516425165251662516725168251692517025171251722517325174251752517625177251782517925180251812518225183251842518525186251872518825189251902519125192251932519425195251962519725198251992520025201252022520325204252052520625207252082520925210252112521225213252142521525216252172521825219252202522125222252232522425225252262522725228252292523025231252322523325234252352523625237252382523925240252412524225243252442524525246252472524825249252502525125252252532525425255252562525725258252592526025261252622526325264252652526625267252682526925270252712527225273252742527525276252772527825279252802528125282252832528425285252862528725288252892529025291252922529325294252952529625297252982529925300253012530225303253042530525306253072530825309253102531125312253132531425315253162531725318253192532025321253222532325324253252532625327253282532925330253312533225333253342533525336253372533825339253402534125342253432534425345253462534725348253492535025351253522535325354253552535625357253582535925360253612536225363253642536525366253672536825369253702537125372253732537425375253762537725378253792538025381253822538325384253852538625387253882538925390253912539225393253942539525396253972539825399254002540125402254032540425405254062540725408254092541025411254122541325414254152541625417254182541925420254212542225423254242542525426254272542825429254302543125432254332543425435254362543725438254392544025441254422544325444254452544625447254482544925450254512545225453254542545525456254572545825459254602546125462254632546425465254662546725468254692547025471254722547325474254752547625477254782547925480254812548225483254842548525486254872548825489254902549125492254932549425495254962549725498254992550025501255022550325504255052550625507255082550925510255112551225513255142551525516255172551825519255202552125522255232552425525255262552725528255292553025531255322553325534255352553625537255382553925540255412554225543255442554525546255472554825549255502555125552255532555425555255562555725558255592556025561255622556325564255652556625567255682556925570255712557225573255742557525576255772557825579255802558125582255832558425585255862558725588255892559025591255922559325594255952559625597255982559925600256012560225603256042560525606256072560825609256102561125612256132561425615256162561725618256192562025621256222562325624256252562625627256282562925630256312563225633256342563525636256372563825639256402564125642256432564425645256462564725648256492565025651256522565325654256552565625657256582565925660256612566225663256642566525666256672566825669256702567125672256732567425675256762567725678256792568025681256822568325684256852568625687256882568925690256912569225693256942569525696256972569825699257002570125702257032570425705257062570725708257092571025711257122571325714257152571625717257182571925720257212572225723257242572525726257272572825729257302573125732257332573425735257362573725738257392574025741257422574325744257452574625747257482574925750257512575225753257542575525756257572575825759257602576125762257632576425765257662576725768257692577025771257722577325774257752577625777257782577925780257812578225783257842578525786257872578825789257902579125792257932579425795257962579725798257992580025801258022580325804258052580625807258082580925810258112581225813258142581525816258172581825819258202582125822258232582425825258262582725828258292583025831258322583325834258352583625837258382583925840258412584225843258442584525846258472584825849258502585125852258532585425855258562585725858258592586025861258622586325864258652586625867258682586925870258712587225873258742587525876258772587825879258802588125882258832588425885258862588725888258892589025891258922589325894258952589625897258982589925900259012590225903259042590525906259072590825909259102591125912259132591425915259162591725918259192592025921259222592325924259252592625927259282592925930259312593225933259342593525936259372593825939259402594125942259432594425945259462594725948259492595025951259522595325954259552595625957259582595925960259612596225963259642596525966259672596825969259702597125972259732597425975259762597725978259792598025981259822598325984259852598625987259882598925990259912599225993259942599525996259972599825999260002600126002260032600426005260062600726008260092601026011260122601326014260152601626017260182601926020260212602226023260242602526026260272602826029260302603126032260332603426035260362603726038260392604026041260422604326044260452604626047260482604926050260512605226053260542605526056260572605826059260602606126062260632606426065260662606726068260692607026071260722607326074260752607626077260782607926080260812608226083260842608526086260872608826089260902609126092260932609426095260962609726098260992610026101261022610326104261052610626107261082610926110261112611226113261142611526116261172611826119261202612126122261232612426125261262612726128261292613026131261322613326134261352613626137261382613926140261412614226143261442614526146261472614826149261502615126152261532615426155261562615726158261592616026161261622616326164261652616626167261682616926170261712617226173261742617526176261772617826179261802618126182261832618426185261862618726188261892619026191261922619326194261952619626197261982619926200262012620226203262042620526206262072620826209262102621126212262132621426215262162621726218262192622026221262222622326224262252622626227262282622926230262312623226233262342623526236262372623826239262402624126242262432624426245262462624726248262492625026251262522625326254262552625626257262582625926260262612626226263262642626526266262672626826269262702627126272262732627426275262762627726278262792628026281262822628326284262852628626287262882628926290262912629226293262942629526296262972629826299263002630126302263032630426305263062630726308263092631026311263122631326314263152631626317263182631926320263212632226323263242632526326263272632826329263302633126332263332633426335263362633726338263392634026341263422634326344263452634626347263482634926350263512635226353263542635526356263572635826359263602636126362263632636426365263662636726368263692637026371263722637326374263752637626377263782637926380263812638226383263842638526386263872638826389263902639126392263932639426395263962639726398263992640026401264022640326404264052640626407264082640926410264112641226413264142641526416264172641826419264202642126422264232642426425264262642726428264292643026431264322643326434264352643626437264382643926440264412644226443264442644526446264472644826449264502645126452264532645426455264562645726458264592646026461264622646326464264652646626467264682646926470264712647226473264742647526476264772647826479264802648126482264832648426485264862648726488264892649026491264922649326494264952649626497264982649926500265012650226503265042650526506265072650826509265102651126512265132651426515265162651726518265192652026521265222652326524265252652626527265282652926530265312653226533265342653526536265372653826539265402654126542265432654426545265462654726548265492655026551265522655326554265552655626557265582655926560265612656226563265642656526566265672656826569265702657126572265732657426575265762657726578265792658026581265822658326584265852658626587265882658926590265912659226593265942659526596265972659826599266002660126602266032660426605266062660726608266092661026611266122661326614266152661626617266182661926620266212662226623266242662526626266272662826629266302663126632266332663426635266362663726638266392664026641266422664326644266452664626647266482664926650266512665226653266542665526656266572665826659266602666126662266632666426665266662666726668266692667026671266722667326674266752667626677266782667926680266812668226683266842668526686266872668826689266902669126692266932669426695266962669726698266992670026701267022670326704267052670626707267082670926710267112671226713267142671526716267172671826719267202672126722267232672426725267262672726728267292673026731267322673326734267352673626737267382673926740267412674226743267442674526746267472674826749267502675126752267532675426755267562675726758267592676026761267622676326764267652676626767267682676926770267712677226773267742677526776267772677826779267802678126782267832678426785267862678726788267892679026791267922679326794267952679626797267982679926800268012680226803268042680526806268072680826809268102681126812268132681426815268162681726818268192682026821268222682326824268252682626827268282682926830268312683226833268342683526836268372683826839268402684126842268432684426845268462684726848268492685026851268522685326854268552685626857268582685926860268612686226863268642686526866268672686826869268702687126872268732687426875268762687726878268792688026881268822688326884268852688626887268882688926890268912689226893268942689526896268972689826899269002690126902269032690426905269062690726908269092691026911269122691326914269152691626917269182691926920269212692226923269242692526926269272692826929269302693126932269332693426935269362693726938269392694026941269422694326944269452694626947269482694926950269512695226953269542695526956269572695826959269602696126962269632696426965269662696726968269692697026971269722697326974269752697626977269782697926980269812698226983269842698526986269872698826989269902699126992269932699426995269962699726998269992700027001270022700327004270052700627007270082700927010270112701227013270142701527016270172701827019270202702127022270232702427025270262702727028270292703027031270322703327034270352703627037270382703927040270412704227043270442704527046270472704827049270502705127052270532705427055270562705727058270592706027061270622706327064270652706627067270682706927070270712707227073270742707527076270772707827079270802708127082270832708427085270862708727088270892709027091270922709327094270952709627097270982709927100271012710227103271042710527106271072710827109271102711127112271132711427115271162711727118271192712027121271222712327124271252712627127271282712927130271312713227133271342713527136271372713827139271402714127142271432714427145271462714727148271492715027151271522715327154271552715627157271582715927160271612716227163271642716527166271672716827169271702717127172271732717427175271762717727178271792718027181271822718327184271852718627187271882718927190271912719227193271942719527196271972719827199272002720127202272032720427205272062720727208272092721027211272122721327214272152721627217272182721927220272212722227223272242722527226272272722827229272302723127232272332723427235272362723727238272392724027241272422724327244272452724627247272482724927250272512725227253272542725527256272572725827259272602726127262272632726427265272662726727268272692727027271272722727327274272752727627277272782727927280272812728227283272842728527286272872728827289272902729127292272932729427295272962729727298272992730027301273022730327304273052730627307273082730927310273112731227313273142731527316273172731827319273202732127322273232732427325273262732727328273292733027331273322733327334273352733627337273382733927340273412734227343273442734527346273472734827349273502735127352273532735427355273562735727358273592736027361273622736327364273652736627367273682736927370273712737227373273742737527376273772737827379273802738127382273832738427385273862738727388273892739027391273922739327394273952739627397273982739927400274012740227403274042740527406274072740827409274102741127412274132741427415274162741727418274192742027421274222742327424274252742627427274282742927430274312743227433274342743527436274372743827439274402744127442274432744427445274462744727448274492745027451274522745327454274552745627457274582745927460274612746227463274642746527466274672746827469274702747127472274732747427475274762747727478274792748027481274822748327484274852748627487274882748927490274912749227493274942749527496274972749827499275002750127502275032750427505275062750727508275092751027511275122751327514275152751627517275182751927520275212752227523275242752527526275272752827529275302753127532275332753427535275362753727538275392754027541275422754327544275452754627547275482754927550275512755227553275542755527556275572755827559275602756127562275632756427565275662756727568275692757027571275722757327574275752757627577275782757927580275812758227583275842758527586275872758827589275902759127592275932759427595275962759727598275992760027601276022760327604276052760627607276082760927610276112761227613276142761527616276172761827619276202762127622276232762427625276262762727628276292763027631276322763327634276352763627637276382763927640276412764227643276442764527646276472764827649276502765127652276532765427655276562765727658276592766027661276622766327664276652766627667276682766927670276712767227673276742767527676276772767827679276802768127682276832768427685276862768727688276892769027691276922769327694276952769627697276982769927700277012770227703277042770527706277072770827709277102771127712277132771427715277162771727718277192772027721277222772327724277252772627727277282772927730277312773227733277342773527736277372773827739277402774127742277432774427745277462774727748277492775027751277522775327754277552775627757277582775927760277612776227763277642776527766277672776827769277702777127772277732777427775277762777727778277792778027781277822778327784277852778627787277882778927790277912779227793277942779527796277972779827799278002780127802278032780427805278062780727808278092781027811278122781327814278152781627817278182781927820278212782227823278242782527826278272782827829278302783127832278332783427835278362783727838278392784027841278422784327844278452784627847278482784927850278512785227853278542785527856278572785827859278602786127862278632786427865278662786727868278692787027871278722787327874278752787627877278782787927880278812788227883278842788527886278872788827889278902789127892278932789427895278962789727898278992790027901279022790327904279052790627907279082790927910279112791227913279142791527916279172791827919279202792127922279232792427925279262792727928279292793027931279322793327934279352793627937279382793927940279412794227943279442794527946279472794827949279502795127952279532795427955279562795727958279592796027961279622796327964279652796627967279682796927970279712797227973279742797527976279772797827979279802798127982279832798427985279862798727988279892799027991279922799327994279952799627997279982799928000280012800228003280042800528006280072800828009280102801128012280132801428015280162801728018280192802028021280222802328024280252802628027280282802928030280312803228033280342803528036280372803828039280402804128042280432804428045280462804728048280492805028051280522805328054280552805628057280582805928060280612806228063280642806528066280672806828069280702807128072280732807428075280762807728078280792808028081280822808328084280852808628087280882808928090280912809228093280942809528096280972809828099281002810128102281032810428105281062810728108281092811028111281122811328114281152811628117281182811928120281212812228123281242812528126281272812828129281302813128132281332813428135281362813728138281392814028141281422814328144281452814628147281482814928150281512815228153281542815528156281572815828159281602816128162281632816428165281662816728168281692817028171281722817328174281752817628177281782817928180281812818228183281842818528186281872818828189281902819128192281932819428195281962819728198281992820028201282022820328204282052820628207282082820928210282112821228213282142821528216282172821828219282202822128222282232822428225282262822728228282292823028231282322823328234282352823628237282382823928240282412824228243282442824528246282472824828249282502825128252282532825428255282562825728258282592826028261282622826328264282652826628267282682826928270282712827228273282742827528276282772827828279282802828128282282832828428285282862828728288282892829028291282922829328294282952829628297282982829928300283012830228303283042830528306283072830828309283102831128312283132831428315283162831728318283192832028321283222832328324283252832628327283282832928330283312833228333283342833528336283372833828339283402834128342283432834428345283462834728348283492835028351283522835328354283552835628357283582835928360283612836228363283642836528366283672836828369283702837128372283732837428375283762837728378283792838028381283822838328384283852838628387283882838928390283912839228393283942839528396283972839828399284002840128402284032840428405284062840728408284092841028411284122841328414284152841628417284182841928420284212842228423284242842528426284272842828429284302843128432284332843428435284362843728438284392844028441284422844328444284452844628447284482844928450284512845228453284542845528456284572845828459284602846128462284632846428465284662846728468284692847028471284722847328474284752847628477284782847928480284812848228483284842848528486284872848828489284902849128492284932849428495284962849728498284992850028501285022850328504285052850628507285082850928510285112851228513285142851528516285172851828519285202852128522285232852428525285262852728528285292853028531285322853328534285352853628537285382853928540285412854228543285442854528546285472854828549285502855128552285532855428555285562855728558285592856028561285622856328564285652856628567285682856928570285712857228573285742857528576285772857828579285802858128582285832858428585285862858728588285892859028591285922859328594285952859628597285982859928600286012860228603286042860528606286072860828609286102861128612286132861428615286162861728618286192862028621286222862328624286252862628627286282862928630286312863228633286342863528636286372863828639286402864128642286432864428645286462864728648286492865028651286522865328654286552865628657286582865928660286612866228663286642866528666286672866828669286702867128672286732867428675286762867728678286792868028681286822868328684286852868628687286882868928690286912869228693286942869528696286972869828699287002870128702287032870428705287062870728708287092871028711287122871328714287152871628717287182871928720287212872228723287242872528726287272872828729287302873128732287332873428735287362873728738287392874028741287422874328744287452874628747287482874928750287512875228753287542875528756287572875828759287602876128762287632876428765287662876728768287692877028771287722877328774287752877628777287782877928780287812878228783287842878528786287872878828789287902879128792287932879428795287962879728798287992880028801288022880328804288052880628807288082880928810288112881228813288142881528816288172881828819288202882128822288232882428825288262882728828288292883028831288322883328834288352883628837288382883928840288412884228843288442884528846288472884828849288502885128852288532885428855288562885728858288592886028861288622886328864288652886628867288682886928870288712887228873288742887528876288772887828879288802888128882288832888428885288862888728888288892889028891288922889328894288952889628897288982889928900289012890228903289042890528906289072890828909289102891128912289132891428915289162891728918289192892028921289222892328924289252892628927289282892928930289312893228933289342893528936289372893828939289402894128942289432894428945289462894728948289492895028951289522895328954289552895628957289582895928960289612896228963289642896528966289672896828969289702897128972289732897428975289762897728978289792898028981289822898328984289852898628987289882898928990289912899228993289942899528996289972899828999290002900129002290032900429005290062900729008290092901029011290122901329014290152901629017290182901929020290212902229023290242902529026290272902829029290302903129032290332903429035290362903729038290392904029041290422904329044290452904629047290482904929050290512905229053290542905529056290572905829059290602906129062290632906429065290662906729068290692907029071290722907329074290752907629077290782907929080290812908229083290842908529086290872908829089290902909129092290932909429095290962909729098290992910029101291022910329104291052910629107291082910929110291112911229113291142911529116291172911829119291202912129122291232912429125291262912729128291292913029131291322913329134291352913629137291382913929140291412914229143291442914529146291472914829149291502915129152291532915429155291562915729158291592916029161291622916329164291652916629167291682916929170291712917229173291742917529176291772917829179291802918129182291832918429185291862918729188291892919029191291922919329194291952919629197291982919929200292012920229203292042920529206292072920829209292102921129212292132921429215292162921729218292192922029221292222922329224292252922629227292282922929230292312923229233292342923529236292372923829239292402924129242292432924429245292462924729248292492925029251292522925329254292552925629257292582925929260292612926229263292642926529266292672926829269292702927129272292732927429275292762927729278292792928029281292822928329284292852928629287292882928929290292912929229293292942929529296292972929829299293002930129302293032930429305293062930729308293092931029311293122931329314293152931629317293182931929320293212932229323293242932529326293272932829329293302933129332293332933429335293362933729338293392934029341293422934329344293452934629347293482934929350293512935229353293542935529356293572935829359293602936129362293632936429365293662936729368293692937029371293722937329374293752937629377293782937929380293812938229383293842938529386293872938829389293902939129392293932939429395293962939729398293992940029401294022940329404294052940629407294082940929410294112941229413294142941529416294172941829419294202942129422294232942429425294262942729428294292943029431294322943329434294352943629437294382943929440294412944229443294442944529446294472944829449294502945129452294532945429455294562945729458294592946029461294622946329464294652946629467294682946929470294712947229473294742947529476294772947829479294802948129482294832948429485294862948729488294892949029491294922949329494294952949629497294982949929500295012950229503295042950529506295072950829509295102951129512295132951429515295162951729518295192952029521295222952329524295252952629527295282952929530295312953229533295342953529536295372953829539295402954129542295432954429545295462954729548295492955029551295522955329554295552955629557295582955929560295612956229563295642956529566295672956829569295702957129572295732957429575295762957729578295792958029581295822958329584295852958629587295882958929590295912959229593295942959529596295972959829599296002960129602296032960429605296062960729608296092961029611296122961329614296152961629617296182961929620296212962229623296242962529626296272962829629296302963129632296332963429635296362963729638296392964029641296422964329644296452964629647296482964929650296512965229653296542965529656296572965829659296602966129662296632966429665296662966729668296692967029671296722967329674296752967629677296782967929680296812968229683296842968529686296872968829689296902969129692296932969429695296962969729698296992970029701297022970329704297052970629707297082970929710297112971229713297142971529716297172971829719297202972129722297232972429725297262972729728297292973029731297322973329734297352973629737297382973929740297412974229743297442974529746297472974829749297502975129752297532975429755297562975729758297592976029761297622976329764297652976629767297682976929770297712977229773297742977529776297772977829779297802978129782297832978429785297862978729788297892979029791297922979329794297952979629797297982979929800298012980229803298042980529806298072980829809298102981129812298132981429815298162981729818298192982029821298222982329824298252982629827298282982929830298312983229833298342983529836298372983829839298402984129842298432984429845298462984729848298492985029851298522985329854298552985629857298582985929860298612986229863298642986529866298672986829869298702987129872298732987429875298762987729878298792988029881298822988329884298852988629887298882988929890298912989229893298942989529896298972989829899299002990129902299032990429905299062990729908299092991029911299122991329914299152991629917299182991929920299212992229923299242992529926299272992829929299302993129932299332993429935299362993729938299392994029941299422994329944299452994629947299482994929950299512995229953299542995529956299572995829959299602996129962299632996429965299662996729968299692997029971299722997329974299752997629977299782997929980299812998229983299842998529986299872998829989299902999129992299932999429995299962999729998299993000030001300023000330004300053000630007300083000930010300113001230013300143001530016300173001830019300203002130022300233002430025300263002730028300293003030031300323003330034300353003630037300383003930040300413004230043300443004530046300473004830049300503005130052300533005430055300563005730058300593006030061300623006330064300653006630067300683006930070300713007230073300743007530076300773007830079300803008130082300833008430085300863008730088300893009030091300923009330094300953009630097300983009930100301013010230103301043010530106301073010830109301103011130112301133011430115301163011730118301193012030121301223012330124301253012630127301283012930130301313013230133301343013530136301373013830139301403014130142301433014430145301463014730148301493015030151301523015330154301553015630157301583015930160301613016230163301643016530166301673016830169301703017130172301733017430175301763017730178301793018030181301823018330184301853018630187301883018930190301913019230193301943019530196301973019830199302003020130202302033020430205302063020730208302093021030211302123021330214302153021630217302183021930220302213022230223302243022530226302273022830229302303023130232302333023430235302363023730238302393024030241302423024330244302453024630247302483024930250302513025230253302543025530256302573025830259302603026130262302633026430265302663026730268302693027030271302723027330274302753027630277302783027930280302813028230283302843028530286302873028830289302903029130292302933029430295302963029730298302993030030301303023030330304303053030630307303083030930310303113031230313303143031530316303173031830319303203032130322303233032430325303263032730328303293033030331303323033330334303353033630337303383033930340303413034230343303443034530346303473034830349303503035130352303533035430355303563035730358303593036030361303623036330364303653036630367303683036930370303713037230373303743037530376303773037830379303803038130382303833038430385303863038730388303893039030391303923039330394303953039630397303983039930400304013040230403304043040530406304073040830409304103041130412304133041430415304163041730418304193042030421304223042330424304253042630427304283042930430304313043230433304343043530436304373043830439304403044130442304433044430445304463044730448304493045030451304523045330454304553045630457304583045930460304613046230463304643046530466304673046830469304703047130472304733047430475304763047730478304793048030481304823048330484304853048630487304883048930490304913049230493304943049530496304973049830499305003050130502305033050430505305063050730508305093051030511305123051330514305153051630517305183051930520305213052230523305243052530526305273052830529305303053130532305333053430535305363053730538305393054030541305423054330544305453054630547305483054930550305513055230553305543055530556305573055830559305603056130562305633056430565305663056730568305693057030571305723057330574305753057630577305783057930580305813058230583305843058530586305873058830589305903059130592305933059430595305963059730598305993060030601306023060330604306053060630607306083060930610306113061230613306143061530616306173061830619306203062130622306233062430625306263062730628306293063030631306323063330634306353063630637306383063930640306413064230643306443064530646306473064830649306503065130652306533065430655306563065730658306593066030661306623066330664306653066630667306683066930670306713067230673306743067530676306773067830679306803068130682306833068430685306863068730688306893069030691306923069330694306953069630697306983069930700307013070230703307043070530706307073070830709307103071130712307133071430715307163071730718307193072030721307223072330724307253072630727307283072930730307313073230733307343073530736307373073830739307403074130742307433074430745307463074730748307493075030751307523075330754307553075630757307583075930760307613076230763307643076530766307673076830769307703077130772307733077430775307763077730778307793078030781307823078330784307853078630787307883078930790307913079230793307943079530796307973079830799308003080130802308033080430805308063080730808308093081030811308123081330814308153081630817308183081930820308213082230823308243082530826308273082830829308303083130832308333083430835308363083730838308393084030841308423084330844308453084630847308483084930850308513085230853308543085530856308573085830859308603086130862308633086430865308663086730868308693087030871308723087330874308753087630877308783087930880308813088230883308843088530886308873088830889308903089130892308933089430895308963089730898308993090030901309023090330904309053090630907309083090930910309113091230913309143091530916309173091830919309203092130922309233092430925309263092730928309293093030931309323093330934309353093630937309383093930940309413094230943309443094530946309473094830949309503095130952309533095430955309563095730958309593096030961309623096330964309653096630967309683096930970309713097230973309743097530976309773097830979309803098130982309833098430985309863098730988309893099030991309923099330994309953099630997309983099931000310013100231003310043100531006310073100831009310103101131012310133101431015310163101731018310193102031021310223102331024310253102631027310283102931030310313103231033
  1. /*!
  2. * Vuetify v3.7.6
  3. * Forged by John Leider
  4. * Released under the MIT License.
  5. */
  6. (function (global, factory) {
  7. typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports, require('vue')) :
  8. typeof define === 'function' && define.amd ? define(['exports', 'vue'], factory) :
  9. (global = typeof globalThis !== 'undefined' ? globalThis : global || self, factory(global.Vuetify = {}, global.Vue));
  10. })(this, (function (exports, vue) { 'use strict';
  11. // 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. /**
  61. * Like `Partial<T>` but doesn't care what the value is
  62. */
  63. // Copied from Vue
  64. // Utilities
  65. // Types
  66. // Composables
  67. const makeComponentProps = propsFactory({
  68. class: [String, Array, Object],
  69. style: {
  70. type: [String, Array, Object],
  71. default: null
  72. }
  73. }, 'component');
  74. const IN_BROWSER = typeof window !== 'undefined';
  75. const SUPPORTS_INTERSECTION = IN_BROWSER && 'IntersectionObserver' in window;
  76. const SUPPORTS_TOUCH = IN_BROWSER && ('ontouchstart' in window || window.navigator.maxTouchPoints > 0);
  77. const SUPPORTS_EYE_DROPPER = IN_BROWSER && 'EyeDropper' in window;
  78. function _classPrivateFieldInitSpec(e, t, a) { _checkPrivateRedeclaration(e, t), t.set(e, a); }
  79. function _checkPrivateRedeclaration(e, t) { if (t.has(e)) throw new TypeError("Cannot initialize the same private elements twice on an object"); }
  80. function _classPrivateFieldSet(s, a, r) { return s.set(_assertClassBrand(s, a), r), r; }
  81. function _classPrivateFieldGet(s, a) { return s.get(_assertClassBrand(s, a)); }
  82. function _assertClassBrand(e, t, n) { if ("function" == typeof e ? e === t : e.has(t)) return arguments.length < 3 ? t : n; throw new TypeError("Private element is not present on this object"); }
  83. // Types
  84. function getNestedValue(obj, path, fallback) {
  85. const last = path.length - 1;
  86. if (last < 0) return obj === undefined ? fallback : obj;
  87. for (let i = 0; i < last; i++) {
  88. if (obj == null) {
  89. return fallback;
  90. }
  91. obj = obj[path[i]];
  92. }
  93. if (obj == null) return fallback;
  94. return obj[path[last]] === undefined ? fallback : obj[path[last]];
  95. }
  96. function deepEqual(a, b) {
  97. if (a === b) return true;
  98. if (a instanceof Date && b instanceof Date && a.getTime() !== b.getTime()) {
  99. // If the values are Date, compare them as timestamps
  100. return false;
  101. }
  102. if (a !== Object(a) || b !== Object(b)) {
  103. // If the values aren't objects, they were already checked for equality
  104. return false;
  105. }
  106. const props = Object.keys(a);
  107. if (props.length !== Object.keys(b).length) {
  108. // Different number of props, don't bother to check
  109. return false;
  110. }
  111. return props.every(p => deepEqual(a[p], b[p]));
  112. }
  113. function getObjectValueByPath(obj, path, fallback) {
  114. // credit: http://stackoverflow.com/questions/6491463/accessing-nested-javascript-objects-with-string-key#comment55278413_6491621
  115. if (obj == null || !path || typeof path !== 'string') return fallback;
  116. if (obj[path] !== undefined) return obj[path];
  117. path = path.replace(/\[(\w+)\]/g, '.$1'); // convert indexes to properties
  118. path = path.replace(/^\./, ''); // strip a leading dot
  119. return getNestedValue(obj, path.split('.'), fallback);
  120. }
  121. function getPropertyFromItem(item, property, fallback) {
  122. if (property === true) return item === undefined ? fallback : item;
  123. if (property == null || typeof property === 'boolean') return fallback;
  124. if (item !== Object(item)) {
  125. if (typeof property !== 'function') return fallback;
  126. const value = property(item, fallback);
  127. return typeof value === 'undefined' ? fallback : value;
  128. }
  129. if (typeof property === 'string') return getObjectValueByPath(item, property, fallback);
  130. if (Array.isArray(property)) return getNestedValue(item, property, fallback);
  131. if (typeof property !== 'function') return fallback;
  132. const value = property(item, fallback);
  133. return typeof value === 'undefined' ? fallback : value;
  134. }
  135. function createRange(length) {
  136. let start = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 0;
  137. return Array.from({
  138. length
  139. }, (v, k) => start + k);
  140. }
  141. function convertToUnit(str) {
  142. let unit = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 'px';
  143. if (str == null || str === '') {
  144. return undefined;
  145. } else if (isNaN(+str)) {
  146. return String(str);
  147. } else if (!isFinite(+str)) {
  148. return undefined;
  149. } else {
  150. return `${Number(str)}${unit}`;
  151. }
  152. }
  153. function isObject(obj) {
  154. return obj !== null && typeof obj === 'object' && !Array.isArray(obj);
  155. }
  156. function isPlainObject(obj) {
  157. let proto;
  158. return obj !== null && typeof obj === 'object' && ((proto = Object.getPrototypeOf(obj)) === Object.prototype || proto === null);
  159. }
  160. function refElement(obj) {
  161. if (obj && '$el' in obj) {
  162. const el = obj.$el;
  163. if (el?.nodeType === Node.TEXT_NODE) {
  164. // Multi-root component, use the first element
  165. return el.nextElementSibling;
  166. }
  167. return el;
  168. }
  169. return obj;
  170. }
  171. // KeyboardEvent.keyCode aliases
  172. const keyCodes = Object.freeze({
  173. enter: 13,
  174. tab: 9,
  175. delete: 46,
  176. esc: 27,
  177. space: 32,
  178. up: 38,
  179. down: 40,
  180. left: 37,
  181. right: 39,
  182. end: 35,
  183. home: 36,
  184. del: 46,
  185. backspace: 8,
  186. insert: 45,
  187. pageup: 33,
  188. pagedown: 34,
  189. shift: 16
  190. });
  191. const keyValues = Object.freeze({
  192. enter: 'Enter',
  193. tab: 'Tab',
  194. delete: 'Delete',
  195. esc: 'Escape',
  196. space: 'Space',
  197. up: 'ArrowUp',
  198. down: 'ArrowDown',
  199. left: 'ArrowLeft',
  200. right: 'ArrowRight',
  201. end: 'End',
  202. home: 'Home',
  203. del: 'Delete',
  204. backspace: 'Backspace',
  205. insert: 'Insert',
  206. pageup: 'PageUp',
  207. pagedown: 'PageDown',
  208. shift: 'Shift'
  209. });
  210. function keys(o) {
  211. return Object.keys(o);
  212. }
  213. function has(obj, key) {
  214. return key.every(k => obj.hasOwnProperty(k));
  215. }
  216. // Array of keys
  217. function pick(obj, paths) {
  218. const found = {};
  219. const keys = new Set(Object.keys(obj));
  220. for (const path of paths) {
  221. if (keys.has(path)) {
  222. found[path] = obj[path];
  223. }
  224. }
  225. return found;
  226. }
  227. // Array of keys
  228. // Array of keys or RegExp to test keys against
  229. function pickWithRest(obj, paths, exclude) {
  230. const found = Object.create(null);
  231. const rest = Object.create(null);
  232. for (const key in obj) {
  233. if (paths.some(path => path instanceof RegExp ? path.test(key) : path === key) && !exclude?.some(path => path === key)) {
  234. found[key] = obj[key];
  235. } else {
  236. rest[key] = obj[key];
  237. }
  238. }
  239. return [found, rest];
  240. }
  241. function omit(obj, exclude) {
  242. const clone = {
  243. ...obj
  244. };
  245. exclude.forEach(prop => delete clone[prop]);
  246. return clone;
  247. }
  248. function only(obj, include) {
  249. const clone = {};
  250. include.forEach(prop => clone[prop] = obj[prop]);
  251. return clone;
  252. }
  253. const onRE = /^on[^a-z]/;
  254. const isOn = key => onRE.test(key);
  255. const bubblingEvents = ['onAfterscriptexecute', 'onAnimationcancel', 'onAnimationend', 'onAnimationiteration', 'onAnimationstart', 'onAuxclick', 'onBeforeinput', 'onBeforescriptexecute', 'onChange', 'onClick', 'onCompositionend', 'onCompositionstart', 'onCompositionupdate', 'onContextmenu', 'onCopy', 'onCut', 'onDblclick', 'onFocusin', 'onFocusout', 'onFullscreenchange', 'onFullscreenerror', 'onGesturechange', 'onGestureend', 'onGesturestart', 'onGotpointercapture', 'onInput', 'onKeydown', 'onKeypress', 'onKeyup', 'onLostpointercapture', 'onMousedown', 'onMousemove', 'onMouseout', 'onMouseover', 'onMouseup', 'onMousewheel', 'onPaste', 'onPointercancel', 'onPointerdown', 'onPointerenter', 'onPointerleave', 'onPointermove', 'onPointerout', 'onPointerover', 'onPointerup', 'onReset', 'onSelect', 'onSubmit', 'onTouchcancel', 'onTouchend', 'onTouchmove', 'onTouchstart', 'onTransitioncancel', 'onTransitionend', 'onTransitionrun', 'onTransitionstart', 'onWheel'];
  256. const compositionIgnoreKeys = ['ArrowUp', 'ArrowDown', 'ArrowRight', 'ArrowLeft', 'Enter', 'Escape', 'Tab', ' '];
  257. function isComposingIgnoreKey(e) {
  258. return e.isComposing && compositionIgnoreKeys.includes(e.key);
  259. }
  260. /**
  261. * Filter attributes that should be applied to
  262. * the root element of an input component. Remaining
  263. * attributes should be passed to the <input> element inside.
  264. */
  265. function filterInputAttrs(attrs) {
  266. const [events, props] = pickWithRest(attrs, [onRE]);
  267. const inputEvents = omit(events, bubblingEvents);
  268. const [rootAttrs, inputAttrs] = pickWithRest(props, ['class', 'style', 'id', /^data-/]);
  269. Object.assign(rootAttrs, events);
  270. Object.assign(inputAttrs, inputEvents);
  271. return [rootAttrs, inputAttrs];
  272. }
  273. function wrapInArray(v) {
  274. return v == null ? [] : Array.isArray(v) ? v : [v];
  275. }
  276. function debounce(fn, delay) {
  277. let timeoutId = 0;
  278. const wrap = function () {
  279. for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) {
  280. args[_key] = arguments[_key];
  281. }
  282. clearTimeout(timeoutId);
  283. timeoutId = setTimeout(() => fn(...args), vue.unref(delay));
  284. };
  285. wrap.clear = () => {
  286. clearTimeout(timeoutId);
  287. };
  288. wrap.immediate = fn;
  289. return wrap;
  290. }
  291. function clamp(value) {
  292. let min = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 0;
  293. let max = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : 1;
  294. return Math.max(min, Math.min(max, value));
  295. }
  296. function getDecimals(value) {
  297. const trimmedStr = value.toString().trim();
  298. return trimmedStr.includes('.') ? trimmedStr.length - trimmedStr.indexOf('.') - 1 : 0;
  299. }
  300. function padEnd(str, length) {
  301. let char = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : '0';
  302. return str + char.repeat(Math.max(0, length - str.length));
  303. }
  304. function padStart(str, length) {
  305. let char = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : '0';
  306. return char.repeat(Math.max(0, length - str.length)) + str;
  307. }
  308. function chunk(str) {
  309. let size = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 1;
  310. const chunked = [];
  311. let index = 0;
  312. while (index < str.length) {
  313. chunked.push(str.substr(index, size));
  314. index += size;
  315. }
  316. return chunked;
  317. }
  318. function chunkArray(array) {
  319. let size = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 1;
  320. return Array.from({
  321. length: Math.ceil(array.length / size)
  322. }, (v, i) => array.slice(i * size, i * size + size));
  323. }
  324. function humanReadableFileSize(bytes) {
  325. let base = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 1000;
  326. if (bytes < base) {
  327. return `${bytes} B`;
  328. }
  329. const prefix = base === 1024 ? ['Ki', 'Mi', 'Gi'] : ['k', 'M', 'G'];
  330. let unit = -1;
  331. while (Math.abs(bytes) >= base && unit < prefix.length - 1) {
  332. bytes /= base;
  333. ++unit;
  334. }
  335. return `${bytes.toFixed(1)} ${prefix[unit]}B`;
  336. }
  337. function mergeDeep() {
  338. let source = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
  339. let target = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
  340. let arrayFn = arguments.length > 2 ? arguments[2] : undefined;
  341. const out = {};
  342. for (const key in source) {
  343. out[key] = source[key];
  344. }
  345. for (const key in target) {
  346. const sourceProperty = source[key];
  347. const targetProperty = target[key];
  348. // Only continue deep merging if
  349. // both properties are plain objects
  350. if (isPlainObject(sourceProperty) && isPlainObject(targetProperty)) {
  351. out[key] = mergeDeep(sourceProperty, targetProperty, arrayFn);
  352. continue;
  353. }
  354. if (arrayFn && Array.isArray(sourceProperty) && Array.isArray(targetProperty)) {
  355. out[key] = arrayFn(sourceProperty, targetProperty);
  356. continue;
  357. }
  358. out[key] = targetProperty;
  359. }
  360. return out;
  361. }
  362. function flattenFragments(nodes) {
  363. return nodes.map(node => {
  364. if (node.type === vue.Fragment) {
  365. return flattenFragments(node.children);
  366. } else {
  367. return node;
  368. }
  369. }).flat();
  370. }
  371. function toKebabCase() {
  372. let str = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : '';
  373. if (toKebabCase.cache.has(str)) return toKebabCase.cache.get(str);
  374. const kebab = str.replace(/[^a-z]/gi, '-').replace(/\B([A-Z])/g, '-$1').toLowerCase();
  375. toKebabCase.cache.set(str, kebab);
  376. return kebab;
  377. }
  378. toKebabCase.cache = new Map();
  379. function findChildrenWithProvide(key, vnode) {
  380. if (!vnode || typeof vnode !== 'object') return [];
  381. if (Array.isArray(vnode)) {
  382. return vnode.map(child => findChildrenWithProvide(key, child)).flat(1);
  383. } else if (vnode.suspense) {
  384. return findChildrenWithProvide(key, vnode.ssContent);
  385. } else if (Array.isArray(vnode.children)) {
  386. return vnode.children.map(child => findChildrenWithProvide(key, child)).flat(1);
  387. } else if (vnode.component) {
  388. if (Object.getOwnPropertySymbols(vnode.component.provides).includes(key)) {
  389. return [vnode.component];
  390. } else if (vnode.component.subTree) {
  391. return findChildrenWithProvide(key, vnode.component.subTree).flat(1);
  392. }
  393. }
  394. return [];
  395. }
  396. var _arr = /*#__PURE__*/new WeakMap();
  397. var _pointer = /*#__PURE__*/new WeakMap();
  398. class CircularBuffer {
  399. constructor(size) {
  400. _classPrivateFieldInitSpec(this, _arr, []);
  401. _classPrivateFieldInitSpec(this, _pointer, 0);
  402. this.size = size;
  403. }
  404. push(val) {
  405. _classPrivateFieldGet(_arr, this)[_classPrivateFieldGet(_pointer, this)] = val;
  406. _classPrivateFieldSet(_pointer, this, (_classPrivateFieldGet(_pointer, this) + 1) % this.size);
  407. }
  408. values() {
  409. return _classPrivateFieldGet(_arr, this).slice(_classPrivateFieldGet(_pointer, this)).concat(_classPrivateFieldGet(_arr, this).slice(0, _classPrivateFieldGet(_pointer, this)));
  410. }
  411. }
  412. function getEventCoordinates(e) {
  413. if ('touches' in e) {
  414. return {
  415. clientX: e.touches[0].clientX,
  416. clientY: e.touches[0].clientY
  417. };
  418. }
  419. return {
  420. clientX: e.clientX,
  421. clientY: e.clientY
  422. };
  423. }
  424. // Only allow a single return type
  425. /**
  426. * Convert a computed ref to a record of refs.
  427. * The getter function must always return an object with the same keys.
  428. */
  429. function destructComputed(getter) {
  430. const refs = vue.reactive({});
  431. const base = vue.computed(getter);
  432. vue.watchEffect(() => {
  433. for (const key in base.value) {
  434. refs[key] = base.value[key];
  435. }
  436. }, {
  437. flush: 'sync'
  438. });
  439. return vue.toRefs(refs);
  440. }
  441. /** Array.includes but value can be any type */
  442. function includes(arr, val) {
  443. return arr.includes(val);
  444. }
  445. function eventName(propName) {
  446. return propName[2].toLowerCase() + propName.slice(3);
  447. }
  448. const EventProp = () => [Function, Array];
  449. function hasEvent(props, name) {
  450. name = 'on' + vue.capitalize(name);
  451. return !!(props[name] || props[`${name}Once`] || props[`${name}Capture`] || props[`${name}OnceCapture`] || props[`${name}CaptureOnce`]);
  452. }
  453. function callEvent(handler) {
  454. for (var _len2 = arguments.length, args = new Array(_len2 > 1 ? _len2 - 1 : 0), _key2 = 1; _key2 < _len2; _key2++) {
  455. args[_key2 - 1] = arguments[_key2];
  456. }
  457. if (Array.isArray(handler)) {
  458. for (const h of handler) {
  459. h(...args);
  460. }
  461. } else if (typeof handler === 'function') {
  462. handler(...args);
  463. }
  464. }
  465. function focusableChildren(el) {
  466. let filterByTabIndex = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : true;
  467. const targets = ['button', '[href]', 'input:not([type="hidden"])', 'select', 'textarea', '[tabindex]'].map(s => `${s}${filterByTabIndex ? ':not([tabindex="-1"])' : ''}:not([disabled])`).join(', ');
  468. return [...el.querySelectorAll(targets)];
  469. }
  470. function getNextElement(elements, location, condition) {
  471. let _el;
  472. let idx = elements.indexOf(document.activeElement);
  473. const inc = location === 'next' ? 1 : -1;
  474. do {
  475. idx += inc;
  476. _el = elements[idx];
  477. } while ((!_el || _el.offsetParent == null || !(condition?.(_el) ?? true)) && idx < elements.length && idx >= 0);
  478. return _el;
  479. }
  480. function focusChild(el, location) {
  481. const focusable = focusableChildren(el);
  482. if (!location) {
  483. if (el === document.activeElement || !el.contains(document.activeElement)) {
  484. focusable[0]?.focus();
  485. }
  486. } else if (location === 'first') {
  487. focusable[0]?.focus();
  488. } else if (location === 'last') {
  489. focusable.at(-1)?.focus();
  490. } else if (typeof location === 'number') {
  491. focusable[location]?.focus();
  492. } else {
  493. const _el = getNextElement(focusable, location);
  494. if (_el) _el.focus();else focusChild(el, location === 'next' ? 'first' : 'last');
  495. }
  496. }
  497. function isEmpty(val) {
  498. return val === null || val === undefined || typeof val === 'string' && val.trim() === '';
  499. }
  500. function noop() {}
  501. /** Returns null if the selector is not supported or we can't check */
  502. function matchesSelector(el, selector) {
  503. const supportsSelector = IN_BROWSER && typeof CSS !== 'undefined' && typeof CSS.supports !== 'undefined' && CSS.supports(`selector(${selector})`);
  504. if (!supportsSelector) return null;
  505. try {
  506. return !!el && el.matches(selector);
  507. } catch (err) {
  508. return null;
  509. }
  510. }
  511. function ensureValidVNode(vnodes) {
  512. return vnodes.some(child => {
  513. if (!vue.isVNode(child)) return true;
  514. if (child.type === vue.Comment) return false;
  515. return child.type !== vue.Fragment || ensureValidVNode(child.children);
  516. }) ? vnodes : null;
  517. }
  518. function defer(timeout, cb) {
  519. if (!IN_BROWSER || timeout === 0) {
  520. cb();
  521. return () => {};
  522. }
  523. const timeoutId = window.setTimeout(cb, timeout);
  524. return () => window.clearTimeout(timeoutId);
  525. }
  526. function isClickInsideElement(event, targetDiv) {
  527. const mouseX = event.clientX;
  528. const mouseY = event.clientY;
  529. const divRect = targetDiv.getBoundingClientRect();
  530. const divLeft = divRect.left;
  531. const divTop = divRect.top;
  532. const divRight = divRect.right;
  533. const divBottom = divRect.bottom;
  534. return mouseX >= divLeft && mouseX <= divRight && mouseY >= divTop && mouseY <= divBottom;
  535. }
  536. function templateRef() {
  537. const el = vue.shallowRef();
  538. const fn = target => {
  539. el.value = target;
  540. };
  541. Object.defineProperty(fn, 'value', {
  542. enumerable: true,
  543. get: () => el.value,
  544. set: val => el.value = val
  545. });
  546. Object.defineProperty(fn, 'el', {
  547. enumerable: true,
  548. get: () => refElement(el.value)
  549. });
  550. return fn;
  551. }
  552. function checkPrintable(e) {
  553. const isPrintableChar = e.key.length === 1;
  554. const noModifier = !e.ctrlKey && !e.metaKey && !e.altKey;
  555. return isPrintableChar && noModifier;
  556. }
  557. // Utilities
  558. const block = ['top', 'bottom'];
  559. const inline = ['start', 'end', 'left', 'right'];
  560. /** Parse a raw anchor string into an object */
  561. function parseAnchor(anchor, isRtl) {
  562. let [side, align] = anchor.split(' ');
  563. if (!align) {
  564. align = includes(block, side) ? 'start' : includes(inline, side) ? 'top' : 'center';
  565. }
  566. return {
  567. side: toPhysical(side, isRtl),
  568. align: toPhysical(align, isRtl)
  569. };
  570. }
  571. function toPhysical(str, isRtl) {
  572. if (str === 'start') return isRtl ? 'right' : 'left';
  573. if (str === 'end') return isRtl ? 'left' : 'right';
  574. return str;
  575. }
  576. function flipSide(anchor) {
  577. return {
  578. side: {
  579. center: 'center',
  580. top: 'bottom',
  581. bottom: 'top',
  582. left: 'right',
  583. right: 'left'
  584. }[anchor.side],
  585. align: anchor.align
  586. };
  587. }
  588. function flipAlign(anchor) {
  589. return {
  590. side: anchor.side,
  591. align: {
  592. center: 'center',
  593. top: 'bottom',
  594. bottom: 'top',
  595. left: 'right',
  596. right: 'left'
  597. }[anchor.align]
  598. };
  599. }
  600. function flipCorner(anchor) {
  601. return {
  602. side: anchor.align,
  603. align: anchor.side
  604. };
  605. }
  606. function getAxis(anchor) {
  607. return includes(block, anchor.side) ? 'y' : 'x';
  608. }
  609. class Box {
  610. constructor(_ref) {
  611. let {
  612. x,
  613. y,
  614. width,
  615. height
  616. } = _ref;
  617. this.x = x;
  618. this.y = y;
  619. this.width = width;
  620. this.height = height;
  621. }
  622. get top() {
  623. return this.y;
  624. }
  625. get bottom() {
  626. return this.y + this.height;
  627. }
  628. get left() {
  629. return this.x;
  630. }
  631. get right() {
  632. return this.x + this.width;
  633. }
  634. }
  635. function getOverflow(a, b) {
  636. return {
  637. x: {
  638. before: Math.max(0, b.left - a.left),
  639. after: Math.max(0, a.right - b.right)
  640. },
  641. y: {
  642. before: Math.max(0, b.top - a.top),
  643. after: Math.max(0, a.bottom - b.bottom)
  644. }
  645. };
  646. }
  647. function getTargetBox(target) {
  648. if (Array.isArray(target)) {
  649. return new Box({
  650. x: target[0],
  651. y: target[1],
  652. width: 0,
  653. height: 0
  654. });
  655. } else {
  656. return target.getBoundingClientRect();
  657. }
  658. }
  659. // Utilities
  660. /** @see https://stackoverflow.com/a/57876601/2074736 */
  661. function nullifyTransforms(el) {
  662. const rect = el.getBoundingClientRect();
  663. const style = getComputedStyle(el);
  664. const tx = style.transform;
  665. if (tx) {
  666. let ta, sx, sy, dx, dy;
  667. if (tx.startsWith('matrix3d(')) {
  668. ta = tx.slice(9, -1).split(/, /);
  669. sx = +ta[0];
  670. sy = +ta[5];
  671. dx = +ta[12];
  672. dy = +ta[13];
  673. } else if (tx.startsWith('matrix(')) {
  674. ta = tx.slice(7, -1).split(/, /);
  675. sx = +ta[0];
  676. sy = +ta[3];
  677. dx = +ta[4];
  678. dy = +ta[5];
  679. } else {
  680. return new Box(rect);
  681. }
  682. const to = style.transformOrigin;
  683. const x = rect.x - dx - (1 - sx) * parseFloat(to);
  684. const y = rect.y - dy - (1 - sy) * parseFloat(to.slice(to.indexOf(' ') + 1));
  685. const w = sx ? rect.width / sx : el.offsetWidth + 1;
  686. const h = sy ? rect.height / sy : el.offsetHeight + 1;
  687. return new Box({
  688. x,
  689. y,
  690. width: w,
  691. height: h
  692. });
  693. } else {
  694. return new Box(rect);
  695. }
  696. }
  697. function animate(el, keyframes, options) {
  698. if (typeof el.animate === 'undefined') return {
  699. finished: Promise.resolve()
  700. };
  701. let animation;
  702. try {
  703. animation = el.animate(keyframes, options);
  704. } catch (err) {
  705. return {
  706. finished: Promise.resolve()
  707. };
  708. }
  709. if (typeof animation.finished === 'undefined') {
  710. animation.finished = new Promise(resolve => {
  711. animation.onfinish = () => {
  712. resolve(animation);
  713. };
  714. });
  715. }
  716. return animation;
  717. }
  718. // Utilities
  719. const handlers = new WeakMap();
  720. function bindProps(el, props) {
  721. Object.keys(props).forEach(k => {
  722. if (isOn(k)) {
  723. const name = eventName(k);
  724. const handler = handlers.get(el);
  725. if (props[k] == null) {
  726. handler?.forEach(v => {
  727. const [n, fn] = v;
  728. if (n === name) {
  729. el.removeEventListener(name, fn);
  730. handler.delete(v);
  731. }
  732. });
  733. } else if (!handler || ![...handler]?.some(v => v[0] === name && v[1] === props[k])) {
  734. el.addEventListener(name, props[k]);
  735. const _handler = handler || new Set();
  736. _handler.add([name, props[k]]);
  737. if (!handlers.has(el)) handlers.set(el, _handler);
  738. }
  739. } else {
  740. if (props[k] == null) {
  741. el.removeAttribute(k);
  742. } else {
  743. el.setAttribute(k, props[k]);
  744. }
  745. }
  746. });
  747. }
  748. function unbindProps(el, props) {
  749. Object.keys(props).forEach(k => {
  750. if (isOn(k)) {
  751. const name = eventName(k);
  752. const handler = handlers.get(el);
  753. handler?.forEach(v => {
  754. const [n, fn] = v;
  755. if (n === name) {
  756. el.removeEventListener(name, fn);
  757. handler.delete(v);
  758. }
  759. });
  760. } else {
  761. el.removeAttribute(k);
  762. }
  763. });
  764. }
  765. /**
  766. * WCAG 3.0 APCA perceptual contrast algorithm from https://github.com/Myndex/SAPC-APCA
  767. * @licence https://www.w3.org/Consortium/Legal/2015/copyright-software-and-document
  768. * @see https://www.w3.org/WAI/GL/task-forces/silver/wiki/Visual_Contrast_of_Text_Subgroup
  769. */
  770. // Types
  771. // MAGICAL NUMBERS
  772. // sRGB Conversion to Relative Luminance (Y)
  773. // Transfer Curve (aka "Gamma") for sRGB linearization
  774. // Simple power curve vs piecewise described in docs
  775. // Essentially, 2.4 best models actual display
  776. // characteristics in combination with the total method
  777. const mainTRC = 2.4;
  778. const Rco = 0.2126729; // sRGB Red Coefficient (from matrix)
  779. const Gco = 0.7151522; // sRGB Green Coefficient (from matrix)
  780. const Bco = 0.0721750; // sRGB Blue Coefficient (from matrix)
  781. // For Finding Raw SAPC Contrast from Relative Luminance (Y)
  782. // Constants for SAPC Power Curve Exponents
  783. // One pair for normal text, and one for reverse
  784. // These are the "beating heart" of SAPC
  785. const normBG = 0.55;
  786. const normTXT = 0.58;
  787. const revTXT = 0.57;
  788. const revBG = 0.62;
  789. // For Clamping and Scaling Values
  790. const blkThrs = 0.03; // Level that triggers the soft black clamp
  791. const blkClmp = 1.45; // Exponent for the soft black clamp curve
  792. const deltaYmin = 0.0005; // Lint trap
  793. const scaleBoW = 1.25; // Scaling for dark text on light
  794. const scaleWoB = 1.25; // Scaling for light text on dark
  795. const loConThresh = 0.078; // Threshold for new simple offset scale
  796. const loConFactor = 12.82051282051282; // = 1/0.078,
  797. const loConOffset = 0.06; // The simple offset
  798. const loClip = 0.001; // Output clip (lint trap #2)
  799. function APCAcontrast(text, background) {
  800. // Linearize sRGB
  801. const Rtxt = (text.r / 255) ** mainTRC;
  802. const Gtxt = (text.g / 255) ** mainTRC;
  803. const Btxt = (text.b / 255) ** mainTRC;
  804. const Rbg = (background.r / 255) ** mainTRC;
  805. const Gbg = (background.g / 255) ** mainTRC;
  806. const Bbg = (background.b / 255) ** mainTRC;
  807. // Apply the standard coefficients and sum to Y
  808. let Ytxt = Rtxt * Rco + Gtxt * Gco + Btxt * Bco;
  809. let Ybg = Rbg * Rco + Gbg * Gco + Bbg * Bco;
  810. // Soft clamp Y when near black.
  811. // Now clamping all colors to prevent crossover errors
  812. if (Ytxt <= blkThrs) Ytxt += (blkThrs - Ytxt) ** blkClmp;
  813. if (Ybg <= blkThrs) Ybg += (blkThrs - Ybg) ** blkClmp;
  814. // Return 0 Early for extremely low ∆Y (lint trap #1)
  815. if (Math.abs(Ybg - Ytxt) < deltaYmin) return 0.0;
  816. // SAPC CONTRAST
  817. let outputContrast; // For weighted final values
  818. if (Ybg > Ytxt) {
  819. // For normal polarity, black text on white
  820. // Calculate the SAPC contrast value and scale
  821. const SAPC = (Ybg ** normBG - Ytxt ** normTXT) * scaleBoW;
  822. // NEW! SAPC SmoothScale™
  823. // Low Contrast Smooth Scale Rollout to prevent polarity reversal
  824. // and also a low clip for very low contrasts (lint trap #2)
  825. // much of this is for very low contrasts, less than 10
  826. // therefore for most reversing needs, only loConOffset is important
  827. outputContrast = SAPC < loClip ? 0.0 : SAPC < loConThresh ? SAPC - SAPC * loConFactor * loConOffset : SAPC - loConOffset;
  828. } else {
  829. // For reverse polarity, light text on dark
  830. // WoB should always return negative value.
  831. const SAPC = (Ybg ** revBG - Ytxt ** revTXT) * scaleWoB;
  832. outputContrast = SAPC > -loClip ? 0.0 : SAPC > -loConThresh ? SAPC - SAPC * loConFactor * loConOffset : SAPC + loConOffset;
  833. }
  834. return outputContrast * 100;
  835. }
  836. /* eslint-disable no-console */
  837. function consoleWarn(message) {
  838. vue.warn(`Vuetify: ${message}`);
  839. }
  840. function consoleError(message) {
  841. vue.warn(`Vuetify error: ${message}`);
  842. }
  843. function deprecate(original, replacement) {
  844. replacement = Array.isArray(replacement) ? replacement.slice(0, -1).map(s => `'${s}'`).join(', ') + ` or '${replacement.at(-1)}'` : `'${replacement}'`;
  845. vue.warn(`[Vuetify UPGRADE] '${original}' is deprecated, use ${replacement} instead.`);
  846. }
  847. // Types
  848. const delta = 0.20689655172413793; // 6÷29
  849. const cielabForwardTransform = t => t > delta ** 3 ? Math.cbrt(t) : t / (3 * delta ** 2) + 4 / 29;
  850. const cielabReverseTransform = t => t > delta ? t ** 3 : 3 * delta ** 2 * (t - 4 / 29);
  851. function fromXYZ$1(xyz) {
  852. const transform = cielabForwardTransform;
  853. const transformedY = transform(xyz[1]);
  854. return [116 * transformedY - 16, 500 * (transform(xyz[0] / 0.95047) - transformedY), 200 * (transformedY - transform(xyz[2] / 1.08883))];
  855. }
  856. function toXYZ$1(lab) {
  857. const transform = cielabReverseTransform;
  858. const Ln = (lab[0] + 16) / 116;
  859. return [transform(Ln + lab[1] / 500) * 0.95047, transform(Ln), transform(Ln - lab[2] / 200) * 1.08883];
  860. }
  861. // Utilities
  862. // Types
  863. // For converting XYZ to sRGB
  864. const srgbForwardMatrix = [[3.2406, -1.5372, -0.4986], [-0.9689, 1.8758, 0.0415], [0.0557, -0.2040, 1.0570]];
  865. // Forward gamma adjust
  866. const srgbForwardTransform = C => C <= 0.0031308 ? C * 12.92 : 1.055 * C ** (1 / 2.4) - 0.055;
  867. // For converting sRGB to XYZ
  868. const srgbReverseMatrix = [[0.4124, 0.3576, 0.1805], [0.2126, 0.7152, 0.0722], [0.0193, 0.1192, 0.9505]];
  869. // Reverse gamma adjust
  870. const srgbReverseTransform = C => C <= 0.04045 ? C / 12.92 : ((C + 0.055) / 1.055) ** 2.4;
  871. function fromXYZ(xyz) {
  872. const rgb = Array(3);
  873. const transform = srgbForwardTransform;
  874. const matrix = srgbForwardMatrix;
  875. // Matrix transform, then gamma adjustment
  876. for (let i = 0; i < 3; ++i) {
  877. // Rescale back to [0, 255]
  878. rgb[i] = Math.round(clamp(transform(matrix[i][0] * xyz[0] + matrix[i][1] * xyz[1] + matrix[i][2] * xyz[2])) * 255);
  879. }
  880. return {
  881. r: rgb[0],
  882. g: rgb[1],
  883. b: rgb[2]
  884. };
  885. }
  886. function toXYZ(_ref) {
  887. let {
  888. r,
  889. g,
  890. b
  891. } = _ref;
  892. const xyz = [0, 0, 0];
  893. const transform = srgbReverseTransform;
  894. const matrix = srgbReverseMatrix;
  895. // Rescale from [0, 255] to [0, 1] then adjust sRGB gamma to linear RGB
  896. r = transform(r / 255);
  897. g = transform(g / 255);
  898. b = transform(b / 255);
  899. // Matrix color space transform
  900. for (let i = 0; i < 3; ++i) {
  901. xyz[i] = matrix[i][0] * r + matrix[i][1] * g + matrix[i][2] * b;
  902. }
  903. return xyz;
  904. }
  905. // Utilities
  906. // Types
  907. function isCssColor(color) {
  908. return !!color && /^(#|var\(--|(rgb|hsl)a?\()/.test(color);
  909. }
  910. function isParsableColor(color) {
  911. return isCssColor(color) && !/^((rgb|hsl)a?\()?var\(--/.test(color);
  912. }
  913. const cssColorRe = /^(?<fn>(?:rgb|hsl)a?)\((?<values>.+)\)/;
  914. const mappers = {
  915. rgb: (r, g, b, a) => ({
  916. r,
  917. g,
  918. b,
  919. a
  920. }),
  921. rgba: (r, g, b, a) => ({
  922. r,
  923. g,
  924. b,
  925. a
  926. }),
  927. hsl: (h, s, l, a) => HSLtoRGB({
  928. h,
  929. s,
  930. l,
  931. a
  932. }),
  933. hsla: (h, s, l, a) => HSLtoRGB({
  934. h,
  935. s,
  936. l,
  937. a
  938. }),
  939. hsv: (h, s, v, a) => HSVtoRGB({
  940. h,
  941. s,
  942. v,
  943. a
  944. }),
  945. hsva: (h, s, v, a) => HSVtoRGB({
  946. h,
  947. s,
  948. v,
  949. a
  950. })
  951. };
  952. function parseColor(color) {
  953. if (typeof color === 'number') {
  954. if (isNaN(color) || color < 0 || color > 0xFFFFFF) {
  955. // int can't have opacity
  956. consoleWarn(`'${color}' is not a valid hex color`);
  957. }
  958. return {
  959. r: (color & 0xFF0000) >> 16,
  960. g: (color & 0xFF00) >> 8,
  961. b: color & 0xFF
  962. };
  963. } else if (typeof color === 'string' && cssColorRe.test(color)) {
  964. const {
  965. groups
  966. } = color.match(cssColorRe);
  967. const {
  968. fn,
  969. values
  970. } = groups;
  971. const realValues = values.split(/,\s*/).map(v => {
  972. if (v.endsWith('%') && ['hsl', 'hsla', 'hsv', 'hsva'].includes(fn)) {
  973. return parseFloat(v) / 100;
  974. } else {
  975. return parseFloat(v);
  976. }
  977. });
  978. return mappers[fn](...realValues);
  979. } else if (typeof color === 'string') {
  980. let hex = color.startsWith('#') ? color.slice(1) : color;
  981. if ([3, 4].includes(hex.length)) {
  982. hex = hex.split('').map(char => char + char).join('');
  983. } else if (![6, 8].includes(hex.length)) {
  984. consoleWarn(`'${color}' is not a valid hex(a) color`);
  985. }
  986. const int = parseInt(hex, 16);
  987. if (isNaN(int) || int < 0 || int > 0xFFFFFFFF) {
  988. consoleWarn(`'${color}' is not a valid hex(a) color`);
  989. }
  990. return HexToRGB(hex);
  991. } else if (typeof color === 'object') {
  992. if (has(color, ['r', 'g', 'b'])) {
  993. return color;
  994. } else if (has(color, ['h', 's', 'l'])) {
  995. return HSVtoRGB(HSLtoHSV(color));
  996. } else if (has(color, ['h', 's', 'v'])) {
  997. return HSVtoRGB(color);
  998. }
  999. }
  1000. throw new TypeError(`Invalid color: ${color == null ? color : String(color) || color.constructor.name}\nExpected #hex, #hexa, rgb(), rgba(), hsl(), hsla(), object or number`);
  1001. }
  1002. /** Converts HSVA to RGBA. Based on formula from https://en.wikipedia.org/wiki/HSL_and_HSV */
  1003. function HSVtoRGB(hsva) {
  1004. const {
  1005. h,
  1006. s,
  1007. v,
  1008. a
  1009. } = hsva;
  1010. const f = n => {
  1011. const k = (n + h / 60) % 6;
  1012. return v - v * s * Math.max(Math.min(k, 4 - k, 1), 0);
  1013. };
  1014. const rgb = [f(5), f(3), f(1)].map(v => Math.round(v * 255));
  1015. return {
  1016. r: rgb[0],
  1017. g: rgb[1],
  1018. b: rgb[2],
  1019. a
  1020. };
  1021. }
  1022. function HSLtoRGB(hsla) {
  1023. return HSVtoRGB(HSLtoHSV(hsla));
  1024. }
  1025. /** Converts RGBA to HSVA. Based on formula from https://en.wikipedia.org/wiki/HSL_and_HSV */
  1026. function RGBtoHSV(rgba) {
  1027. if (!rgba) return {
  1028. h: 0,
  1029. s: 1,
  1030. v: 1,
  1031. a: 1
  1032. };
  1033. const r = rgba.r / 255;
  1034. const g = rgba.g / 255;
  1035. const b = rgba.b / 255;
  1036. const max = Math.max(r, g, b);
  1037. const min = Math.min(r, g, b);
  1038. let h = 0;
  1039. if (max !== min) {
  1040. if (max === r) {
  1041. h = 60 * (0 + (g - b) / (max - min));
  1042. } else if (max === g) {
  1043. h = 60 * (2 + (b - r) / (max - min));
  1044. } else if (max === b) {
  1045. h = 60 * (4 + (r - g) / (max - min));
  1046. }
  1047. }
  1048. if (h < 0) h = h + 360;
  1049. const s = max === 0 ? 0 : (max - min) / max;
  1050. const hsv = [h, s, max];
  1051. return {
  1052. h: hsv[0],
  1053. s: hsv[1],
  1054. v: hsv[2],
  1055. a: rgba.a
  1056. };
  1057. }
  1058. function HSVtoHSL(hsva) {
  1059. const {
  1060. h,
  1061. s,
  1062. v,
  1063. a
  1064. } = hsva;
  1065. const l = v - v * s / 2;
  1066. const sprime = l === 1 || l === 0 ? 0 : (v - l) / Math.min(l, 1 - l);
  1067. return {
  1068. h,
  1069. s: sprime,
  1070. l,
  1071. a
  1072. };
  1073. }
  1074. function HSLtoHSV(hsl) {
  1075. const {
  1076. h,
  1077. s,
  1078. l,
  1079. a
  1080. } = hsl;
  1081. const v = l + s * Math.min(l, 1 - l);
  1082. const sprime = v === 0 ? 0 : 2 - 2 * l / v;
  1083. return {
  1084. h,
  1085. s: sprime,
  1086. v,
  1087. a
  1088. };
  1089. }
  1090. function RGBtoCSS(_ref) {
  1091. let {
  1092. r,
  1093. g,
  1094. b,
  1095. a
  1096. } = _ref;
  1097. return a === undefined ? `rgb(${r}, ${g}, ${b})` : `rgba(${r}, ${g}, ${b}, ${a})`;
  1098. }
  1099. function HSVtoCSS(hsva) {
  1100. return RGBtoCSS(HSVtoRGB(hsva));
  1101. }
  1102. function toHex(v) {
  1103. const h = Math.round(v).toString(16);
  1104. return ('00'.substr(0, 2 - h.length) + h).toUpperCase();
  1105. }
  1106. function RGBtoHex(_ref2) {
  1107. let {
  1108. r,
  1109. g,
  1110. b,
  1111. a
  1112. } = _ref2;
  1113. return `#${[toHex(r), toHex(g), toHex(b), a !== undefined ? toHex(Math.round(a * 255)) : ''].join('')}`;
  1114. }
  1115. function HexToRGB(hex) {
  1116. hex = parseHex(hex);
  1117. let [r, g, b, a] = chunk(hex, 2).map(c => parseInt(c, 16));
  1118. a = a === undefined ? a : a / 255;
  1119. return {
  1120. r,
  1121. g,
  1122. b,
  1123. a
  1124. };
  1125. }
  1126. function HexToHSV(hex) {
  1127. const rgb = HexToRGB(hex);
  1128. return RGBtoHSV(rgb);
  1129. }
  1130. function HSVtoHex(hsva) {
  1131. return RGBtoHex(HSVtoRGB(hsva));
  1132. }
  1133. function parseHex(hex) {
  1134. if (hex.startsWith('#')) {
  1135. hex = hex.slice(1);
  1136. }
  1137. hex = hex.replace(/([^0-9a-f])/gi, 'F');
  1138. if (hex.length === 3 || hex.length === 4) {
  1139. hex = hex.split('').map(x => x + x).join('');
  1140. }
  1141. if (hex.length !== 6) {
  1142. hex = padEnd(padEnd(hex, 6), 8, 'F');
  1143. }
  1144. return hex;
  1145. }
  1146. function lighten(value, amount) {
  1147. const lab = fromXYZ$1(toXYZ(value));
  1148. lab[0] = lab[0] + amount * 10;
  1149. return fromXYZ(toXYZ$1(lab));
  1150. }
  1151. function darken(value, amount) {
  1152. const lab = fromXYZ$1(toXYZ(value));
  1153. lab[0] = lab[0] - amount * 10;
  1154. return fromXYZ(toXYZ$1(lab));
  1155. }
  1156. /**
  1157. * Calculate the relative luminance of a given color
  1158. * @see https://www.w3.org/TR/WCAG20/#relativeluminancedef
  1159. */
  1160. function getLuma(color) {
  1161. const rgb = parseColor(color);
  1162. return toXYZ(rgb)[1];
  1163. }
  1164. /**
  1165. * Returns the contrast ratio (1-21) between two colors.
  1166. * @see https://www.w3.org/TR/WCAG20/#contrast-ratiodef
  1167. */
  1168. function getContrast(first, second) {
  1169. const l1 = getLuma(first);
  1170. const l2 = getLuma(second);
  1171. const light = Math.max(l1, l2);
  1172. const dark = Math.min(l1, l2);
  1173. return (light + 0.05) / (dark + 0.05);
  1174. }
  1175. function getForeground(color) {
  1176. const blackContrast = Math.abs(APCAcontrast(parseColor(0), parseColor(color)));
  1177. const whiteContrast = Math.abs(APCAcontrast(parseColor(0xffffff), parseColor(color)));
  1178. // TODO: warn about poor color selections
  1179. // const contrastAsText = Math.abs(APCAcontrast(colorVal, colorToInt(theme.colors.background)))
  1180. // const minContrast = Math.max(blackContrast, whiteContrast)
  1181. // if (minContrast < 60) {
  1182. // consoleInfo(`${key} theme color ${color} has poor contrast (${minContrast.toFixed()}%)`)
  1183. // } else if (contrastAsText < 60 && !['background', 'surface'].includes(color)) {
  1184. // consoleInfo(`${key} theme color ${color} has poor contrast as text (${contrastAsText.toFixed()}%)`)
  1185. // }
  1186. // Prefer white text if both have an acceptable contrast ratio
  1187. return whiteContrast > Math.min(blackContrast, 50) ? '#fff' : '#000';
  1188. }
  1189. // Utilities
  1190. // Types
  1191. function getCurrentInstance(name, message) {
  1192. const vm = vue.getCurrentInstance();
  1193. if (!vm) {
  1194. throw new Error(`[Vuetify] ${name} ${message || 'must be called from inside a setup function'}`);
  1195. }
  1196. return vm;
  1197. }
  1198. function getCurrentInstanceName() {
  1199. let name = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 'composables';
  1200. const vm = getCurrentInstance(name).type;
  1201. return toKebabCase(vm?.aliasName || vm?.name);
  1202. }
  1203. let _uid = 0;
  1204. let _map = new WeakMap();
  1205. function getUid() {
  1206. const vm = getCurrentInstance('getUid');
  1207. if (_map.has(vm)) return _map.get(vm);else {
  1208. const uid = _uid++;
  1209. _map.set(vm, uid);
  1210. return uid;
  1211. }
  1212. }
  1213. getUid.reset = () => {
  1214. _uid = 0;
  1215. _map = new WeakMap();
  1216. };
  1217. // Utilities
  1218. // Types
  1219. function injectSelf(key) {
  1220. let vm = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : getCurrentInstance('injectSelf');
  1221. const {
  1222. provides
  1223. } = vm;
  1224. if (provides && key in provides) {
  1225. // TS doesn't allow symbol as index type
  1226. return provides[key];
  1227. }
  1228. return undefined;
  1229. }
  1230. // Utilities
  1231. // Types
  1232. const DefaultsSymbol = Symbol.for('vuetify:defaults');
  1233. function createDefaults(options) {
  1234. return vue.ref(options);
  1235. }
  1236. function injectDefaults() {
  1237. const defaults = vue.inject(DefaultsSymbol);
  1238. if (!defaults) throw new Error('[Vuetify] Could not find defaults instance');
  1239. return defaults;
  1240. }
  1241. function provideDefaults(defaults, options) {
  1242. const injectedDefaults = injectDefaults();
  1243. const providedDefaults = vue.ref(defaults);
  1244. const newDefaults = vue.computed(() => {
  1245. const disabled = vue.unref(options?.disabled);
  1246. if (disabled) return injectedDefaults.value;
  1247. const scoped = vue.unref(options?.scoped);
  1248. const reset = vue.unref(options?.reset);
  1249. const root = vue.unref(options?.root);
  1250. if (providedDefaults.value == null && !(scoped || reset || root)) return injectedDefaults.value;
  1251. let properties = mergeDeep(providedDefaults.value, {
  1252. prev: injectedDefaults.value
  1253. });
  1254. if (scoped) return properties;
  1255. if (reset || root) {
  1256. const len = Number(reset || Infinity);
  1257. for (let i = 0; i <= len; i++) {
  1258. if (!properties || !('prev' in properties)) {
  1259. break;
  1260. }
  1261. properties = properties.prev;
  1262. }
  1263. if (properties && typeof root === 'string' && root in properties) {
  1264. properties = mergeDeep(mergeDeep(properties, {
  1265. prev: properties
  1266. }), properties[root]);
  1267. }
  1268. return properties;
  1269. }
  1270. return properties.prev ? mergeDeep(properties.prev, properties) : properties;
  1271. });
  1272. vue.provide(DefaultsSymbol, newDefaults);
  1273. return newDefaults;
  1274. }
  1275. function propIsDefined(vnode, prop) {
  1276. return typeof vnode.props?.[prop] !== 'undefined' || typeof vnode.props?.[toKebabCase(prop)] !== 'undefined';
  1277. }
  1278. function internalUseDefaults() {
  1279. let props = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
  1280. let name = arguments.length > 1 ? arguments[1] : undefined;
  1281. let defaults = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : injectDefaults();
  1282. const vm = getCurrentInstance('useDefaults');
  1283. name = name ?? vm.type.name ?? vm.type.__name;
  1284. if (!name) {
  1285. throw new Error('[Vuetify] Could not determine component name');
  1286. }
  1287. const componentDefaults = vue.computed(() => defaults.value?.[props._as ?? name]);
  1288. const _props = new Proxy(props, {
  1289. get(target, prop) {
  1290. const propValue = Reflect.get(target, prop);
  1291. if (prop === 'class' || prop === 'style') {
  1292. return [componentDefaults.value?.[prop], propValue].filter(v => v != null);
  1293. } else if (typeof prop === 'string' && !propIsDefined(vm.vnode, prop)) {
  1294. return componentDefaults.value?.[prop] !== undefined ? componentDefaults.value?.[prop] : defaults.value?.global?.[prop] !== undefined ? defaults.value?.global?.[prop] : propValue;
  1295. }
  1296. return propValue;
  1297. }
  1298. });
  1299. const _subcomponentDefaults = vue.shallowRef();
  1300. vue.watchEffect(() => {
  1301. if (componentDefaults.value) {
  1302. const subComponents = Object.entries(componentDefaults.value).filter(_ref => {
  1303. let [key] = _ref;
  1304. return key.startsWith(key[0].toUpperCase());
  1305. });
  1306. _subcomponentDefaults.value = subComponents.length ? Object.fromEntries(subComponents) : undefined;
  1307. } else {
  1308. _subcomponentDefaults.value = undefined;
  1309. }
  1310. });
  1311. function provideSubDefaults() {
  1312. const injected = injectSelf(DefaultsSymbol, vm);
  1313. vue.provide(DefaultsSymbol, vue.computed(() => {
  1314. return _subcomponentDefaults.value ? mergeDeep(injected?.value ?? {}, _subcomponentDefaults.value) : injected?.value;
  1315. }));
  1316. }
  1317. return {
  1318. props: _props,
  1319. provideSubDefaults
  1320. };
  1321. }
  1322. function useDefaults() {
  1323. let props = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
  1324. let name = arguments.length > 1 ? arguments[1] : undefined;
  1325. const {
  1326. props: _props,
  1327. provideSubDefaults
  1328. } = internalUseDefaults(props, name);
  1329. provideSubDefaults();
  1330. return _props;
  1331. }
  1332. // Composables
  1333. // Types
  1334. // No props
  1335. // Object Props
  1336. // Implementation
  1337. function defineComponent(options) {
  1338. options._setup = options._setup ?? options.setup;
  1339. if (!options.name) {
  1340. consoleWarn('The component is missing an explicit name, unable to generate default prop value');
  1341. return options;
  1342. }
  1343. if (options._setup) {
  1344. options.props = propsFactory(options.props ?? {}, options.name)();
  1345. const propKeys = Object.keys(options.props).filter(key => key !== 'class' && key !== 'style');
  1346. options.filterProps = function filterProps(props) {
  1347. return pick(props, propKeys);
  1348. };
  1349. options.props._as = String;
  1350. options.setup = function setup(props, ctx) {
  1351. const defaults = injectDefaults();
  1352. // Skip props proxy if defaults are not provided
  1353. if (!defaults.value) return options._setup(props, ctx);
  1354. const {
  1355. props: _props,
  1356. provideSubDefaults
  1357. } = internalUseDefaults(props, props._as ?? options.name, defaults);
  1358. const setupBindings = options._setup(_props, ctx);
  1359. provideSubDefaults();
  1360. return setupBindings;
  1361. };
  1362. }
  1363. return options;
  1364. }
  1365. // No argument - simple default slot
  1366. // Generic constructor argument - generic props and slots
  1367. // Slots argument - simple slots
  1368. // Implementation
  1369. function genericComponent() {
  1370. let exposeDefaults = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : true;
  1371. return options => (exposeDefaults ? defineComponent : vue.defineComponent)(options);
  1372. }
  1373. function defineFunctionalComponent(props, render) {
  1374. render.props = props;
  1375. return render;
  1376. }
  1377. // Adds a filterProps method to the component options
  1378. // https://github.com/vuejs/core/pull/10557
  1379. // not a vue Component
  1380. // Composables
  1381. function createSimpleFunctional(klass) {
  1382. let tag = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 'div';
  1383. let name = arguments.length > 2 ? arguments[2] : undefined;
  1384. return genericComponent()({
  1385. name: name ?? vue.capitalize(vue.camelize(klass.replace(/__/g, '-'))),
  1386. props: {
  1387. tag: {
  1388. type: String,
  1389. default: tag
  1390. },
  1391. ...makeComponentProps()
  1392. },
  1393. setup(props, _ref) {
  1394. let {
  1395. slots
  1396. } = _ref;
  1397. return () => {
  1398. return vue.h(props.tag, {
  1399. class: [klass, props.class],
  1400. style: props.style
  1401. }, slots.default?.());
  1402. };
  1403. }
  1404. });
  1405. }
  1406. /**
  1407. * Returns:
  1408. * - 'null' if the node is not attached to the DOM
  1409. * - the root node (HTMLDocument | ShadowRoot) otherwise
  1410. */
  1411. function attachedRoot(node) {
  1412. /* istanbul ignore next */
  1413. if (typeof node.getRootNode !== 'function') {
  1414. // Shadow DOM not supported (IE11), lets find the root of this node
  1415. while (node.parentNode) node = node.parentNode;
  1416. // The root parent is the document if the node is attached to the DOM
  1417. if (node !== document) return null;
  1418. return document;
  1419. }
  1420. const root = node.getRootNode();
  1421. // The composed root node is the document if the node is attached to the DOM
  1422. if (root !== document && root.getRootNode({
  1423. composed: true
  1424. }) !== document) return null;
  1425. return root;
  1426. }
  1427. const standardEasing = 'cubic-bezier(0.4, 0, 0.2, 1)';
  1428. const deceleratedEasing = 'cubic-bezier(0.0, 0, 0.2, 1)'; // Entering
  1429. const acceleratedEasing = 'cubic-bezier(0.4, 0, 1, 1)'; // Leaving
  1430. // Utilities
  1431. function getPrefixedEventHandlers(attrs, suffix, getData) {
  1432. return Object.keys(attrs).filter(key => isOn(key) && key.endsWith(suffix)).reduce((acc, key) => {
  1433. acc[key.slice(0, -suffix.length)] = event => attrs[key](event, getData(event));
  1434. return acc;
  1435. }, {});
  1436. }
  1437. function getScrollParent(el) {
  1438. let includeHidden = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : false;
  1439. while (el) {
  1440. if (includeHidden ? isPotentiallyScrollable(el) : hasScrollbar(el)) return el;
  1441. el = el.parentElement;
  1442. }
  1443. return document.scrollingElement;
  1444. }
  1445. function getScrollParents(el, stopAt) {
  1446. const elements = [];
  1447. if (stopAt && el && !stopAt.contains(el)) return elements;
  1448. while (el) {
  1449. if (hasScrollbar(el)) elements.push(el);
  1450. if (el === stopAt) break;
  1451. el = el.parentElement;
  1452. }
  1453. return elements;
  1454. }
  1455. function hasScrollbar(el) {
  1456. if (!el || el.nodeType !== Node.ELEMENT_NODE) return false;
  1457. const style = window.getComputedStyle(el);
  1458. return style.overflowY === 'scroll' || style.overflowY === 'auto' && el.scrollHeight > el.clientHeight;
  1459. }
  1460. function isPotentiallyScrollable(el) {
  1461. if (!el || el.nodeType !== Node.ELEMENT_NODE) return false;
  1462. const style = window.getComputedStyle(el);
  1463. return ['scroll', 'auto'].includes(style.overflowY);
  1464. }
  1465. function isFixedPosition(el) {
  1466. while (el) {
  1467. if (window.getComputedStyle(el).position === 'fixed') {
  1468. return true;
  1469. }
  1470. el = el.offsetParent;
  1471. }
  1472. return false;
  1473. }
  1474. // Utilities
  1475. // Types
  1476. function useRender(render) {
  1477. const vm = getCurrentInstance('useRender');
  1478. vm.render = render;
  1479. }
  1480. // Utilities
  1481. // Types
  1482. function useResizeObserver(callback) {
  1483. let box = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 'content';
  1484. const resizeRef = templateRef();
  1485. const contentRect = vue.ref();
  1486. if (IN_BROWSER) {
  1487. const observer = new ResizeObserver(entries => {
  1488. callback?.(entries, observer);
  1489. if (!entries.length) return;
  1490. if (box === 'content') {
  1491. contentRect.value = entries[0].contentRect;
  1492. } else {
  1493. contentRect.value = entries[0].target.getBoundingClientRect();
  1494. }
  1495. });
  1496. vue.onBeforeUnmount(() => {
  1497. observer.disconnect();
  1498. });
  1499. vue.watch(() => resizeRef.el, (newValue, oldValue) => {
  1500. if (oldValue) {
  1501. observer.unobserve(oldValue);
  1502. contentRect.value = undefined;
  1503. }
  1504. if (newValue) observer.observe(newValue);
  1505. }, {
  1506. flush: 'post'
  1507. });
  1508. }
  1509. return {
  1510. resizeRef,
  1511. contentRect: vue.readonly(contentRect)
  1512. };
  1513. }
  1514. // Composables
  1515. // Types
  1516. const VuetifyLayoutKey = Symbol.for('vuetify:layout');
  1517. const VuetifyLayoutItemKey = Symbol.for('vuetify:layout-item');
  1518. const ROOT_ZINDEX = 1000;
  1519. const makeLayoutProps = propsFactory({
  1520. overlaps: {
  1521. type: Array,
  1522. default: () => []
  1523. },
  1524. fullHeight: Boolean
  1525. }, 'layout');
  1526. // Composables
  1527. const makeLayoutItemProps = propsFactory({
  1528. name: {
  1529. type: String
  1530. },
  1531. order: {
  1532. type: [Number, String],
  1533. default: 0
  1534. },
  1535. absolute: Boolean
  1536. }, 'layout-item');
  1537. function useLayout() {
  1538. const layout = vue.inject(VuetifyLayoutKey);
  1539. if (!layout) throw new Error('[Vuetify] Could not find injected layout');
  1540. return {
  1541. getLayoutItem: layout.getLayoutItem,
  1542. mainRect: layout.mainRect,
  1543. mainStyles: layout.mainStyles
  1544. };
  1545. }
  1546. function useLayoutItem(options) {
  1547. const layout = vue.inject(VuetifyLayoutKey);
  1548. if (!layout) throw new Error('[Vuetify] Could not find injected layout');
  1549. const id = options.id ?? `layout-item-${getUid()}`;
  1550. const vm = getCurrentInstance('useLayoutItem');
  1551. vue.provide(VuetifyLayoutItemKey, {
  1552. id
  1553. });
  1554. const isKeptAlive = vue.shallowRef(false);
  1555. vue.onDeactivated(() => isKeptAlive.value = true);
  1556. vue.onActivated(() => isKeptAlive.value = false);
  1557. const {
  1558. layoutItemStyles,
  1559. layoutItemScrimStyles
  1560. } = layout.register(vm, {
  1561. ...options,
  1562. active: vue.computed(() => isKeptAlive.value ? false : options.active.value),
  1563. id
  1564. });
  1565. vue.onBeforeUnmount(() => layout.unregister(id));
  1566. return {
  1567. layoutItemStyles,
  1568. layoutRect: layout.layoutRect,
  1569. layoutItemScrimStyles
  1570. };
  1571. }
  1572. const generateLayers = (layout, positions, layoutSizes, activeItems) => {
  1573. let previousLayer = {
  1574. top: 0,
  1575. left: 0,
  1576. right: 0,
  1577. bottom: 0
  1578. };
  1579. const layers = [{
  1580. id: '',
  1581. layer: {
  1582. ...previousLayer
  1583. }
  1584. }];
  1585. for (const id of layout) {
  1586. const position = positions.get(id);
  1587. const amount = layoutSizes.get(id);
  1588. const active = activeItems.get(id);
  1589. if (!position || !amount || !active) continue;
  1590. const layer = {
  1591. ...previousLayer,
  1592. [position.value]: parseInt(previousLayer[position.value], 10) + (active.value ? parseInt(amount.value, 10) : 0)
  1593. };
  1594. layers.push({
  1595. id,
  1596. layer
  1597. });
  1598. previousLayer = layer;
  1599. }
  1600. return layers;
  1601. };
  1602. function createLayout(props) {
  1603. const parentLayout = vue.inject(VuetifyLayoutKey, null);
  1604. const rootZIndex = vue.computed(() => parentLayout ? parentLayout.rootZIndex.value - 100 : ROOT_ZINDEX);
  1605. const registered = vue.ref([]);
  1606. const positions = vue.reactive(new Map());
  1607. const layoutSizes = vue.reactive(new Map());
  1608. const priorities = vue.reactive(new Map());
  1609. const activeItems = vue.reactive(new Map());
  1610. const disabledTransitions = vue.reactive(new Map());
  1611. const {
  1612. resizeRef,
  1613. contentRect: layoutRect
  1614. } = useResizeObserver();
  1615. const computedOverlaps = vue.computed(() => {
  1616. const map = new Map();
  1617. const overlaps = props.overlaps ?? [];
  1618. for (const overlap of overlaps.filter(item => item.includes(':'))) {
  1619. const [top, bottom] = overlap.split(':');
  1620. if (!registered.value.includes(top) || !registered.value.includes(bottom)) continue;
  1621. const topPosition = positions.get(top);
  1622. const bottomPosition = positions.get(bottom);
  1623. const topAmount = layoutSizes.get(top);
  1624. const bottomAmount = layoutSizes.get(bottom);
  1625. if (!topPosition || !bottomPosition || !topAmount || !bottomAmount) continue;
  1626. map.set(bottom, {
  1627. position: topPosition.value,
  1628. amount: parseInt(topAmount.value, 10)
  1629. });
  1630. map.set(top, {
  1631. position: bottomPosition.value,
  1632. amount: -parseInt(bottomAmount.value, 10)
  1633. });
  1634. }
  1635. return map;
  1636. });
  1637. const layers = vue.computed(() => {
  1638. const uniquePriorities = [...new Set([...priorities.values()].map(p => p.value))].sort((a, b) => a - b);
  1639. const layout = [];
  1640. for (const p of uniquePriorities) {
  1641. const items = registered.value.filter(id => priorities.get(id)?.value === p);
  1642. layout.push(...items);
  1643. }
  1644. return generateLayers(layout, positions, layoutSizes, activeItems);
  1645. });
  1646. const transitionsEnabled = vue.computed(() => {
  1647. return !Array.from(disabledTransitions.values()).some(ref => ref.value);
  1648. });
  1649. const mainRect = vue.computed(() => {
  1650. return layers.value[layers.value.length - 1].layer;
  1651. });
  1652. const mainStyles = vue.computed(() => {
  1653. return {
  1654. '--v-layout-left': convertToUnit(mainRect.value.left),
  1655. '--v-layout-right': convertToUnit(mainRect.value.right),
  1656. '--v-layout-top': convertToUnit(mainRect.value.top),
  1657. '--v-layout-bottom': convertToUnit(mainRect.value.bottom),
  1658. ...(transitionsEnabled.value ? undefined : {
  1659. transition: 'none'
  1660. })
  1661. };
  1662. });
  1663. const items = vue.computed(() => {
  1664. return layers.value.slice(1).map((_ref, index) => {
  1665. let {
  1666. id
  1667. } = _ref;
  1668. const {
  1669. layer
  1670. } = layers.value[index];
  1671. const size = layoutSizes.get(id);
  1672. const position = positions.get(id);
  1673. return {
  1674. id,
  1675. ...layer,
  1676. size: Number(size.value),
  1677. position: position.value
  1678. };
  1679. });
  1680. });
  1681. const getLayoutItem = id => {
  1682. return items.value.find(item => item.id === id);
  1683. };
  1684. const rootVm = getCurrentInstance('createLayout');
  1685. const isMounted = vue.shallowRef(false);
  1686. vue.onMounted(() => {
  1687. isMounted.value = true;
  1688. });
  1689. vue.provide(VuetifyLayoutKey, {
  1690. register: (vm, _ref2) => {
  1691. let {
  1692. id,
  1693. order,
  1694. position,
  1695. layoutSize,
  1696. elementSize,
  1697. active,
  1698. disableTransitions,
  1699. absolute
  1700. } = _ref2;
  1701. priorities.set(id, order);
  1702. positions.set(id, position);
  1703. layoutSizes.set(id, layoutSize);
  1704. activeItems.set(id, active);
  1705. disableTransitions && disabledTransitions.set(id, disableTransitions);
  1706. const instances = findChildrenWithProvide(VuetifyLayoutItemKey, rootVm?.vnode);
  1707. const instanceIndex = instances.indexOf(vm);
  1708. if (instanceIndex > -1) registered.value.splice(instanceIndex, 0, id);else registered.value.push(id);
  1709. const index = vue.computed(() => items.value.findIndex(i => i.id === id));
  1710. const zIndex = vue.computed(() => rootZIndex.value + layers.value.length * 2 - index.value * 2);
  1711. const layoutItemStyles = vue.computed(() => {
  1712. const isHorizontal = position.value === 'left' || position.value === 'right';
  1713. const isOppositeHorizontal = position.value === 'right';
  1714. const isOppositeVertical = position.value === 'bottom';
  1715. const size = elementSize.value ?? layoutSize.value;
  1716. const unit = size === 0 ? '%' : 'px';
  1717. const styles = {
  1718. [position.value]: 0,
  1719. zIndex: zIndex.value,
  1720. transform: `translate${isHorizontal ? 'X' : 'Y'}(${(active.value ? 0 : -(size === 0 ? 100 : size)) * (isOppositeHorizontal || isOppositeVertical ? -1 : 1)}${unit})`,
  1721. position: absolute.value || rootZIndex.value !== ROOT_ZINDEX ? 'absolute' : 'fixed',
  1722. ...(transitionsEnabled.value ? undefined : {
  1723. transition: 'none'
  1724. })
  1725. };
  1726. if (!isMounted.value) return styles;
  1727. const item = items.value[index.value];
  1728. if (!item) throw new Error(`[Vuetify] Could not find layout item "${id}"`);
  1729. const overlap = computedOverlaps.value.get(id);
  1730. if (overlap) {
  1731. item[overlap.position] += overlap.amount;
  1732. }
  1733. return {
  1734. ...styles,
  1735. height: isHorizontal ? `calc(100% - ${item.top}px - ${item.bottom}px)` : elementSize.value ? `${elementSize.value}px` : undefined,
  1736. left: isOppositeHorizontal ? undefined : `${item.left}px`,
  1737. right: isOppositeHorizontal ? `${item.right}px` : undefined,
  1738. top: position.value !== 'bottom' ? `${item.top}px` : undefined,
  1739. bottom: position.value !== 'top' ? `${item.bottom}px` : undefined,
  1740. width: !isHorizontal ? `calc(100% - ${item.left}px - ${item.right}px)` : elementSize.value ? `${elementSize.value}px` : undefined
  1741. };
  1742. });
  1743. const layoutItemScrimStyles = vue.computed(() => ({
  1744. zIndex: zIndex.value - 1
  1745. }));
  1746. return {
  1747. layoutItemStyles,
  1748. layoutItemScrimStyles,
  1749. zIndex
  1750. };
  1751. },
  1752. unregister: id => {
  1753. priorities.delete(id);
  1754. positions.delete(id);
  1755. layoutSizes.delete(id);
  1756. activeItems.delete(id);
  1757. disabledTransitions.delete(id);
  1758. registered.value = registered.value.filter(v => v !== id);
  1759. },
  1760. mainRect,
  1761. mainStyles,
  1762. getLayoutItem,
  1763. items,
  1764. layoutRect,
  1765. rootZIndex
  1766. });
  1767. const layoutClasses = vue.computed(() => ['v-layout', {
  1768. 'v-layout--full-height': props.fullHeight
  1769. }]);
  1770. const layoutStyles = vue.computed(() => ({
  1771. zIndex: parentLayout ? rootZIndex.value : undefined,
  1772. position: parentLayout ? 'relative' : undefined,
  1773. overflow: parentLayout ? 'hidden' : undefined
  1774. }));
  1775. return {
  1776. layoutClasses,
  1777. layoutStyles,
  1778. getLayoutItem,
  1779. items,
  1780. layoutRect,
  1781. layoutRef: resizeRef
  1782. };
  1783. }
  1784. // Utilities
  1785. // Types
  1786. function useToggleScope(source, fn) {
  1787. let scope;
  1788. function start() {
  1789. scope = vue.effectScope();
  1790. scope.run(() => fn.length ? fn(() => {
  1791. scope?.stop();
  1792. start();
  1793. }) : fn());
  1794. }
  1795. vue.watch(source, active => {
  1796. if (active && !scope) {
  1797. start();
  1798. } else if (!active) {
  1799. scope?.stop();
  1800. scope = undefined;
  1801. }
  1802. }, {
  1803. immediate: true
  1804. });
  1805. vue.onScopeDispose(() => {
  1806. scope?.stop();
  1807. });
  1808. }
  1809. // Composables
  1810. // Types
  1811. // Composables
  1812. function useProxiedModel(props, prop, defaultValue) {
  1813. let transformIn = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : v => v;
  1814. let transformOut = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : v => v;
  1815. const vm = getCurrentInstance('useProxiedModel');
  1816. const internal = vue.ref(props[prop] !== undefined ? props[prop] : defaultValue);
  1817. const kebabProp = toKebabCase(prop);
  1818. const checkKebab = kebabProp !== prop;
  1819. const isControlled = checkKebab ? vue.computed(() => {
  1820. void props[prop];
  1821. return !!((vm.vnode.props?.hasOwnProperty(prop) || vm.vnode.props?.hasOwnProperty(kebabProp)) && (vm.vnode.props?.hasOwnProperty(`onUpdate:${prop}`) || vm.vnode.props?.hasOwnProperty(`onUpdate:${kebabProp}`)));
  1822. }) : vue.computed(() => {
  1823. void props[prop];
  1824. return !!(vm.vnode.props?.hasOwnProperty(prop) && vm.vnode.props?.hasOwnProperty(`onUpdate:${prop}`));
  1825. });
  1826. useToggleScope(() => !isControlled.value, () => {
  1827. vue.watch(() => props[prop], val => {
  1828. internal.value = val;
  1829. });
  1830. });
  1831. const model = vue.computed({
  1832. get() {
  1833. const externalValue = props[prop];
  1834. return transformIn(isControlled.value ? externalValue : internal.value);
  1835. },
  1836. set(internalValue) {
  1837. const newValue = transformOut(internalValue);
  1838. const value = vue.toRaw(isControlled.value ? props[prop] : internal.value);
  1839. if (value === newValue || transformIn(value) === internalValue) {
  1840. return;
  1841. }
  1842. internal.value = newValue;
  1843. vm?.emit(`update:${prop}`, newValue);
  1844. }
  1845. });
  1846. Object.defineProperty(model, 'externalValue', {
  1847. get: () => isControlled.value ? props[prop] : internal.value
  1848. });
  1849. return model;
  1850. }
  1851. var en = {
  1852. badge: 'Badge',
  1853. open: 'Open',
  1854. close: 'Close',
  1855. dismiss: 'Dismiss',
  1856. confirmEdit: {
  1857. ok: 'OK',
  1858. cancel: 'Cancel'
  1859. },
  1860. dataIterator: {
  1861. noResultsText: 'No matching records found',
  1862. loadingText: 'Loading items...'
  1863. },
  1864. dataTable: {
  1865. itemsPerPageText: 'Rows per page:',
  1866. ariaLabel: {
  1867. sortDescending: 'Sorted descending.',
  1868. sortAscending: 'Sorted ascending.',
  1869. sortNone: 'Not sorted.',
  1870. activateNone: 'Activate to remove sorting.',
  1871. activateDescending: 'Activate to sort descending.',
  1872. activateAscending: 'Activate to sort ascending.'
  1873. },
  1874. sortBy: 'Sort by'
  1875. },
  1876. dataFooter: {
  1877. itemsPerPageText: 'Items per page:',
  1878. itemsPerPageAll: 'All',
  1879. nextPage: 'Next page',
  1880. prevPage: 'Previous page',
  1881. firstPage: 'First page',
  1882. lastPage: 'Last page',
  1883. pageText: '{0}-{1} of {2}'
  1884. },
  1885. dateRangeInput: {
  1886. divider: 'to'
  1887. },
  1888. datePicker: {
  1889. itemsSelected: '{0} selected',
  1890. range: {
  1891. title: 'Select dates',
  1892. header: 'Enter dates'
  1893. },
  1894. title: 'Select date',
  1895. header: 'Enter date',
  1896. input: {
  1897. placeholder: 'Enter date'
  1898. }
  1899. },
  1900. noDataText: 'No data available',
  1901. carousel: {
  1902. prev: 'Previous visual',
  1903. next: 'Next visual',
  1904. ariaLabel: {
  1905. delimiter: 'Carousel slide {0} of {1}'
  1906. }
  1907. },
  1908. calendar: {
  1909. moreEvents: '{0} more',
  1910. today: 'Today'
  1911. },
  1912. input: {
  1913. clear: 'Clear {0}',
  1914. prependAction: '{0} prepended action',
  1915. appendAction: '{0} appended action',
  1916. otp: 'Please enter OTP character {0}'
  1917. },
  1918. fileInput: {
  1919. counter: '{0} files',
  1920. counterSize: '{0} files ({1} in total)'
  1921. },
  1922. fileUpload: {
  1923. title: 'Drag and drop files here',
  1924. divider: 'or',
  1925. browse: 'Browse Files'
  1926. },
  1927. timePicker: {
  1928. am: 'AM',
  1929. pm: 'PM',
  1930. title: 'Select Time'
  1931. },
  1932. pagination: {
  1933. ariaLabel: {
  1934. root: 'Pagination Navigation',
  1935. next: 'Next page',
  1936. previous: 'Previous page',
  1937. page: 'Go to page {0}',
  1938. currentPage: 'Page {0}, Current page',
  1939. first: 'First page',
  1940. last: 'Last page'
  1941. }
  1942. },
  1943. stepper: {
  1944. next: 'Next',
  1945. prev: 'Previous'
  1946. },
  1947. rating: {
  1948. ariaLabel: {
  1949. item: 'Rating {0} of {1}'
  1950. }
  1951. },
  1952. loading: 'Loading...',
  1953. infiniteScroll: {
  1954. loadMore: 'Load more',
  1955. empty: 'No more'
  1956. }
  1957. };
  1958. // Composables
  1959. // Types
  1960. const LANG_PREFIX = '$vuetify.';
  1961. const replace = (str, params) => {
  1962. return str.replace(/\{(\d+)\}/g, (match, index) => {
  1963. return String(params[+index]);
  1964. });
  1965. };
  1966. const createTranslateFunction = (current, fallback, messages) => {
  1967. return function (key) {
  1968. for (var _len = arguments.length, params = new Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) {
  1969. params[_key - 1] = arguments[_key];
  1970. }
  1971. if (!key.startsWith(LANG_PREFIX)) {
  1972. return replace(key, params);
  1973. }
  1974. const shortKey = key.replace(LANG_PREFIX, '');
  1975. const currentLocale = current.value && messages.value[current.value];
  1976. const fallbackLocale = fallback.value && messages.value[fallback.value];
  1977. let str = getObjectValueByPath(currentLocale, shortKey, null);
  1978. if (!str) {
  1979. consoleWarn(`Translation key "${key}" not found in "${current.value}", trying fallback locale`);
  1980. str = getObjectValueByPath(fallbackLocale, shortKey, null);
  1981. }
  1982. if (!str) {
  1983. consoleError(`Translation key "${key}" not found in fallback`);
  1984. str = key;
  1985. }
  1986. if (typeof str !== 'string') {
  1987. consoleError(`Translation key "${key}" has a non-string value`);
  1988. str = key;
  1989. }
  1990. return replace(str, params);
  1991. };
  1992. };
  1993. function createNumberFunction(current, fallback) {
  1994. return (value, options) => {
  1995. const numberFormat = new Intl.NumberFormat([current.value, fallback.value], options);
  1996. return numberFormat.format(value);
  1997. };
  1998. }
  1999. function useProvided(props, prop, provided) {
  2000. const internal = useProxiedModel(props, prop, props[prop] ?? provided.value);
  2001. // TODO: Remove when defaultValue works
  2002. internal.value = props[prop] ?? provided.value;
  2003. vue.watch(provided, v => {
  2004. if (props[prop] == null) {
  2005. internal.value = provided.value;
  2006. }
  2007. });
  2008. return internal;
  2009. }
  2010. function createProvideFunction(state) {
  2011. return props => {
  2012. const current = useProvided(props, 'locale', state.current);
  2013. const fallback = useProvided(props, 'fallback', state.fallback);
  2014. const messages = useProvided(props, 'messages', state.messages);
  2015. return {
  2016. name: 'vuetify',
  2017. current,
  2018. fallback,
  2019. messages,
  2020. t: createTranslateFunction(current, fallback, messages),
  2021. n: createNumberFunction(current, fallback),
  2022. provide: createProvideFunction({
  2023. current,
  2024. fallback,
  2025. messages
  2026. })
  2027. };
  2028. };
  2029. }
  2030. function createVuetifyAdapter(options) {
  2031. const current = vue.shallowRef(options?.locale ?? 'en');
  2032. const fallback = vue.shallowRef(options?.fallback ?? 'en');
  2033. const messages = vue.ref({
  2034. en,
  2035. ...options?.messages
  2036. });
  2037. return {
  2038. name: 'vuetify',
  2039. current,
  2040. fallback,
  2041. messages,
  2042. t: createTranslateFunction(current, fallback, messages),
  2043. n: createNumberFunction(current, fallback),
  2044. provide: createProvideFunction({
  2045. current,
  2046. fallback,
  2047. messages
  2048. })
  2049. };
  2050. }
  2051. // Utilities
  2052. // Types
  2053. const LocaleSymbol = Symbol.for('vuetify:locale');
  2054. function isLocaleInstance(obj) {
  2055. return obj.name != null;
  2056. }
  2057. function createLocale(options) {
  2058. const i18n = options?.adapter && isLocaleInstance(options?.adapter) ? options?.adapter : createVuetifyAdapter(options);
  2059. const rtl = createRtl(i18n, options);
  2060. return {
  2061. ...i18n,
  2062. ...rtl
  2063. };
  2064. }
  2065. function useLocale() {
  2066. const locale = vue.inject(LocaleSymbol);
  2067. if (!locale) throw new Error('[Vuetify] Could not find injected locale instance');
  2068. return locale;
  2069. }
  2070. function provideLocale(props) {
  2071. const locale = vue.inject(LocaleSymbol);
  2072. if (!locale) throw new Error('[Vuetify] Could not find injected locale instance');
  2073. const i18n = locale.provide(props);
  2074. const rtl = provideRtl(i18n, locale.rtl, props);
  2075. const data = {
  2076. ...i18n,
  2077. ...rtl
  2078. };
  2079. vue.provide(LocaleSymbol, data);
  2080. return data;
  2081. }
  2082. function genDefaults$3() {
  2083. return {
  2084. af: false,
  2085. ar: true,
  2086. bg: false,
  2087. ca: false,
  2088. ckb: false,
  2089. cs: false,
  2090. de: false,
  2091. el: false,
  2092. en: false,
  2093. es: false,
  2094. et: false,
  2095. fa: true,
  2096. fi: false,
  2097. fr: false,
  2098. hr: false,
  2099. hu: false,
  2100. he: true,
  2101. id: false,
  2102. it: false,
  2103. ja: false,
  2104. km: false,
  2105. ko: false,
  2106. lv: false,
  2107. lt: false,
  2108. nl: false,
  2109. no: false,
  2110. pl: false,
  2111. pt: false,
  2112. ro: false,
  2113. ru: false,
  2114. sk: false,
  2115. sl: false,
  2116. srCyrl: false,
  2117. srLatn: false,
  2118. sv: false,
  2119. th: false,
  2120. tr: false,
  2121. az: false,
  2122. uk: false,
  2123. vi: false,
  2124. zhHans: false,
  2125. zhHant: false
  2126. };
  2127. }
  2128. function createRtl(i18n, options) {
  2129. const rtl = vue.ref(options?.rtl ?? genDefaults$3());
  2130. const isRtl = vue.computed(() => rtl.value[i18n.current.value] ?? false);
  2131. return {
  2132. isRtl,
  2133. rtl,
  2134. rtlClasses: vue.computed(() => `v-locale--is-${isRtl.value ? 'rtl' : 'ltr'}`)
  2135. };
  2136. }
  2137. function provideRtl(locale, rtl, props) {
  2138. const isRtl = vue.computed(() => props.rtl ?? rtl.value[locale.current.value] ?? false);
  2139. return {
  2140. isRtl,
  2141. rtl,
  2142. rtlClasses: vue.computed(() => `v-locale--is-${isRtl.value ? 'rtl' : 'ltr'}`)
  2143. };
  2144. }
  2145. function useRtl() {
  2146. const locale = vue.inject(LocaleSymbol);
  2147. if (!locale) throw new Error('[Vuetify] Could not find injected rtl instance');
  2148. return {
  2149. isRtl: locale.isRtl,
  2150. rtlClasses: locale.rtlClasses
  2151. };
  2152. }
  2153. // Utilities
  2154. // Types
  2155. const ThemeSymbol = Symbol.for('vuetify:theme');
  2156. const makeThemeProps = propsFactory({
  2157. theme: String
  2158. }, 'theme');
  2159. function genDefaults$2() {
  2160. return {
  2161. defaultTheme: 'light',
  2162. variations: {
  2163. colors: [],
  2164. lighten: 0,
  2165. darken: 0
  2166. },
  2167. themes: {
  2168. light: {
  2169. dark: false,
  2170. colors: {
  2171. background: '#FFFFFF',
  2172. surface: '#FFFFFF',
  2173. 'surface-bright': '#FFFFFF',
  2174. 'surface-light': '#EEEEEE',
  2175. 'surface-variant': '#424242',
  2176. 'on-surface-variant': '#EEEEEE',
  2177. primary: '#1867C0',
  2178. 'primary-darken-1': '#1F5592',
  2179. secondary: '#48A9A6',
  2180. 'secondary-darken-1': '#018786',
  2181. error: '#B00020',
  2182. info: '#2196F3',
  2183. success: '#4CAF50',
  2184. warning: '#FB8C00'
  2185. },
  2186. variables: {
  2187. 'border-color': '#000000',
  2188. 'border-opacity': 0.12,
  2189. 'high-emphasis-opacity': 0.87,
  2190. 'medium-emphasis-opacity': 0.60,
  2191. 'disabled-opacity': 0.38,
  2192. 'idle-opacity': 0.04,
  2193. 'hover-opacity': 0.04,
  2194. 'focus-opacity': 0.12,
  2195. 'selected-opacity': 0.08,
  2196. 'activated-opacity': 0.12,
  2197. 'pressed-opacity': 0.12,
  2198. 'dragged-opacity': 0.08,
  2199. 'theme-kbd': '#212529',
  2200. 'theme-on-kbd': '#FFFFFF',
  2201. 'theme-code': '#F5F5F5',
  2202. 'theme-on-code': '#000000'
  2203. }
  2204. },
  2205. dark: {
  2206. dark: true,
  2207. colors: {
  2208. background: '#121212',
  2209. surface: '#212121',
  2210. 'surface-bright': '#ccbfd6',
  2211. 'surface-light': '#424242',
  2212. 'surface-variant': '#a3a3a3',
  2213. 'on-surface-variant': '#424242',
  2214. primary: '#2196F3',
  2215. 'primary-darken-1': '#277CC1',
  2216. secondary: '#54B6B2',
  2217. 'secondary-darken-1': '#48A9A6',
  2218. error: '#CF6679',
  2219. info: '#2196F3',
  2220. success: '#4CAF50',
  2221. warning: '#FB8C00'
  2222. },
  2223. variables: {
  2224. 'border-color': '#FFFFFF',
  2225. 'border-opacity': 0.12,
  2226. 'high-emphasis-opacity': 1,
  2227. 'medium-emphasis-opacity': 0.70,
  2228. 'disabled-opacity': 0.50,
  2229. 'idle-opacity': 0.10,
  2230. 'hover-opacity': 0.04,
  2231. 'focus-opacity': 0.12,
  2232. 'selected-opacity': 0.08,
  2233. 'activated-opacity': 0.12,
  2234. 'pressed-opacity': 0.16,
  2235. 'dragged-opacity': 0.08,
  2236. 'theme-kbd': '#212529',
  2237. 'theme-on-kbd': '#FFFFFF',
  2238. 'theme-code': '#343434',
  2239. 'theme-on-code': '#CCCCCC'
  2240. }
  2241. }
  2242. }
  2243. };
  2244. }
  2245. function parseThemeOptions() {
  2246. let options = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : genDefaults$2();
  2247. const defaults = genDefaults$2();
  2248. if (!options) return {
  2249. ...defaults,
  2250. isDisabled: true
  2251. };
  2252. const themes = {};
  2253. for (const [key, theme] of Object.entries(options.themes ?? {})) {
  2254. const defaultTheme = theme.dark || key === 'dark' ? defaults.themes?.dark : defaults.themes?.light;
  2255. themes[key] = mergeDeep(defaultTheme, theme);
  2256. }
  2257. return mergeDeep(defaults, {
  2258. ...options,
  2259. themes
  2260. });
  2261. }
  2262. // Composables
  2263. function createTheme(options) {
  2264. const parsedOptions = parseThemeOptions(options);
  2265. const name = vue.ref(parsedOptions.defaultTheme);
  2266. const themes = vue.ref(parsedOptions.themes);
  2267. const computedThemes = vue.computed(() => {
  2268. const acc = {};
  2269. for (const [name, original] of Object.entries(themes.value)) {
  2270. const theme = acc[name] = {
  2271. ...original,
  2272. colors: {
  2273. ...original.colors
  2274. }
  2275. };
  2276. if (parsedOptions.variations) {
  2277. for (const name of parsedOptions.variations.colors) {
  2278. const color = theme.colors[name];
  2279. if (!color) continue;
  2280. for (const variation of ['lighten', 'darken']) {
  2281. const fn = variation === 'lighten' ? lighten : darken;
  2282. for (const amount of createRange(parsedOptions.variations[variation], 1)) {
  2283. theme.colors[`${name}-${variation}-${amount}`] = RGBtoHex(fn(parseColor(color), amount));
  2284. }
  2285. }
  2286. }
  2287. }
  2288. for (const color of Object.keys(theme.colors)) {
  2289. if (/^on-[a-z]/.test(color) || theme.colors[`on-${color}`]) continue;
  2290. const onColor = `on-${color}`;
  2291. const colorVal = parseColor(theme.colors[color]);
  2292. theme.colors[onColor] = getForeground(colorVal);
  2293. }
  2294. }
  2295. return acc;
  2296. });
  2297. const current = vue.computed(() => computedThemes.value[name.value]);
  2298. const styles = vue.computed(() => {
  2299. const lines = [];
  2300. if (current.value?.dark) {
  2301. createCssClass(lines, ':root', ['color-scheme: dark']);
  2302. }
  2303. createCssClass(lines, ':root', genCssVariables(current.value));
  2304. for (const [themeName, theme] of Object.entries(computedThemes.value)) {
  2305. createCssClass(lines, `.v-theme--${themeName}`, [`color-scheme: ${theme.dark ? 'dark' : 'normal'}`, ...genCssVariables(theme)]);
  2306. }
  2307. const bgLines = [];
  2308. const fgLines = [];
  2309. const colors = new Set(Object.values(computedThemes.value).flatMap(theme => Object.keys(theme.colors)));
  2310. for (const key of colors) {
  2311. if (/^on-[a-z]/.test(key)) {
  2312. createCssClass(fgLines, `.${key}`, [`color: rgb(var(--v-theme-${key})) !important`]);
  2313. } else {
  2314. 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`]);
  2315. createCssClass(fgLines, `.text-${key}`, [`color: rgb(var(--v-theme-${key})) !important`]);
  2316. createCssClass(fgLines, `.border-${key}`, [`--v-border-color: var(--v-theme-${key})`]);
  2317. }
  2318. }
  2319. lines.push(...bgLines, ...fgLines);
  2320. return lines.map((str, i) => i === 0 ? str : ` ${str}`).join('');
  2321. });
  2322. function getHead() {
  2323. return {
  2324. style: [{
  2325. children: styles.value,
  2326. id: 'vuetify-theme-stylesheet',
  2327. nonce: parsedOptions.cspNonce || false
  2328. }]
  2329. };
  2330. }
  2331. function install(app) {
  2332. if (parsedOptions.isDisabled) return;
  2333. const head = app._context.provides.usehead;
  2334. if (head) {
  2335. if (head.push) {
  2336. const entry = head.push(getHead);
  2337. if (IN_BROWSER) {
  2338. vue.watch(styles, () => {
  2339. entry.patch(getHead);
  2340. });
  2341. }
  2342. } else {
  2343. if (IN_BROWSER) {
  2344. head.addHeadObjs(vue.computed(getHead));
  2345. vue.watchEffect(() => head.updateDOM());
  2346. } else {
  2347. head.addHeadObjs(getHead());
  2348. }
  2349. }
  2350. } else {
  2351. let styleEl = IN_BROWSER ? document.getElementById('vuetify-theme-stylesheet') : null;
  2352. if (IN_BROWSER) {
  2353. vue.watch(styles, updateStyles, {
  2354. immediate: true
  2355. });
  2356. } else {
  2357. updateStyles();
  2358. }
  2359. function updateStyles() {
  2360. if (typeof document !== 'undefined' && !styleEl) {
  2361. const el = document.createElement('style');
  2362. el.type = 'text/css';
  2363. el.id = 'vuetify-theme-stylesheet';
  2364. if (parsedOptions.cspNonce) el.setAttribute('nonce', parsedOptions.cspNonce);
  2365. styleEl = el;
  2366. document.head.appendChild(styleEl);
  2367. }
  2368. if (styleEl) styleEl.innerHTML = styles.value;
  2369. }
  2370. }
  2371. }
  2372. const themeClasses = vue.computed(() => parsedOptions.isDisabled ? undefined : `v-theme--${name.value}`);
  2373. return {
  2374. install,
  2375. isDisabled: parsedOptions.isDisabled,
  2376. name,
  2377. themes,
  2378. current,
  2379. computedThemes,
  2380. themeClasses,
  2381. styles,
  2382. global: {
  2383. name,
  2384. current
  2385. }
  2386. };
  2387. }
  2388. function provideTheme(props) {
  2389. getCurrentInstance('provideTheme');
  2390. const theme = vue.inject(ThemeSymbol, null);
  2391. if (!theme) throw new Error('Could not find Vuetify theme injection');
  2392. const name = vue.computed(() => {
  2393. return props.theme ?? theme.name.value;
  2394. });
  2395. const current = vue.computed(() => theme.themes.value[name.value]);
  2396. const themeClasses = vue.computed(() => theme.isDisabled ? undefined : `v-theme--${name.value}`);
  2397. const newTheme = {
  2398. ...theme,
  2399. name,
  2400. current,
  2401. themeClasses
  2402. };
  2403. vue.provide(ThemeSymbol, newTheme);
  2404. return newTheme;
  2405. }
  2406. function useTheme() {
  2407. getCurrentInstance('useTheme');
  2408. const theme = vue.inject(ThemeSymbol, null);
  2409. if (!theme) throw new Error('Could not find Vuetify theme injection');
  2410. return theme;
  2411. }
  2412. function createCssClass(lines, selector, content) {
  2413. lines.push(`${selector} {\n`, ...content.map(line => ` ${line};\n`), '}\n');
  2414. }
  2415. function genCssVariables(theme) {
  2416. const lightOverlay = theme.dark ? 2 : 1;
  2417. const darkOverlay = theme.dark ? 1 : 2;
  2418. const variables = [];
  2419. for (const [key, value] of Object.entries(theme.colors)) {
  2420. const rgb = parseColor(value);
  2421. variables.push(`--v-theme-${key}: ${rgb.r},${rgb.g},${rgb.b}`);
  2422. if (!key.startsWith('on-')) {
  2423. variables.push(`--v-theme-${key}-overlay-multiplier: ${getLuma(value) > 0.18 ? lightOverlay : darkOverlay}`);
  2424. }
  2425. }
  2426. for (const [key, value] of Object.entries(theme.variables)) {
  2427. const color = typeof value === 'string' && value.startsWith('#') ? parseColor(value) : undefined;
  2428. const rgb = color ? `${color.r}, ${color.g}, ${color.b}` : undefined;
  2429. variables.push(`--v-${key}: ${rgb ?? value}`);
  2430. }
  2431. return variables;
  2432. }
  2433. const makeVAppProps = propsFactory({
  2434. ...makeComponentProps(),
  2435. ...makeLayoutProps({
  2436. fullHeight: true
  2437. }),
  2438. ...makeThemeProps()
  2439. }, 'VApp');
  2440. const VApp = genericComponent()({
  2441. name: 'VApp',
  2442. props: makeVAppProps(),
  2443. setup(props, _ref) {
  2444. let {
  2445. slots
  2446. } = _ref;
  2447. const theme = provideTheme(props);
  2448. const {
  2449. layoutClasses,
  2450. getLayoutItem,
  2451. items,
  2452. layoutRef
  2453. } = createLayout(props);
  2454. const {
  2455. rtlClasses
  2456. } = useRtl();
  2457. useRender(() => vue.createVNode("div", {
  2458. "ref": layoutRef,
  2459. "class": ['v-application', theme.themeClasses.value, layoutClasses.value, rtlClasses.value, props.class],
  2460. "style": [props.style]
  2461. }, [vue.createVNode("div", {
  2462. "class": "v-application__wrap"
  2463. }, [slots.default?.()])]));
  2464. return {
  2465. getLayoutItem,
  2466. items,
  2467. theme
  2468. };
  2469. }
  2470. });
  2471. // Utilities
  2472. // Types
  2473. // Composables
  2474. const makeTagProps = propsFactory({
  2475. tag: {
  2476. type: String,
  2477. default: 'div'
  2478. }
  2479. }, 'tag');
  2480. const makeVToolbarTitleProps = propsFactory({
  2481. text: String,
  2482. ...makeComponentProps(),
  2483. ...makeTagProps()
  2484. }, 'VToolbarTitle');
  2485. const VToolbarTitle = genericComponent()({
  2486. name: 'VToolbarTitle',
  2487. props: makeVToolbarTitleProps(),
  2488. setup(props, _ref) {
  2489. let {
  2490. slots
  2491. } = _ref;
  2492. useRender(() => {
  2493. const hasText = !!(slots.default || slots.text || props.text);
  2494. return vue.createVNode(props.tag, {
  2495. "class": ['v-toolbar-title', props.class],
  2496. "style": props.style
  2497. }, {
  2498. default: () => [hasText && vue.createVNode("div", {
  2499. "class": "v-toolbar-title__placeholder"
  2500. }, [slots.text ? slots.text() : props.text, slots.default?.()])]
  2501. });
  2502. });
  2503. return {};
  2504. }
  2505. });
  2506. // Utilities
  2507. // Types
  2508. const makeTransitionProps$1 = propsFactory({
  2509. disabled: Boolean,
  2510. group: Boolean,
  2511. hideOnLeave: Boolean,
  2512. leaveAbsolute: Boolean,
  2513. mode: String,
  2514. origin: String
  2515. }, 'transition');
  2516. function createCssTransition(name, origin, mode) {
  2517. return genericComponent()({
  2518. name,
  2519. props: makeTransitionProps$1({
  2520. mode,
  2521. origin
  2522. }),
  2523. setup(props, _ref) {
  2524. let {
  2525. slots
  2526. } = _ref;
  2527. const functions = {
  2528. onBeforeEnter(el) {
  2529. if (props.origin) {
  2530. el.style.transformOrigin = props.origin;
  2531. }
  2532. },
  2533. onLeave(el) {
  2534. if (props.leaveAbsolute) {
  2535. const {
  2536. offsetTop,
  2537. offsetLeft,
  2538. offsetWidth,
  2539. offsetHeight
  2540. } = el;
  2541. el._transitionInitialStyles = {
  2542. position: el.style.position,
  2543. top: el.style.top,
  2544. left: el.style.left,
  2545. width: el.style.width,
  2546. height: el.style.height
  2547. };
  2548. el.style.position = 'absolute';
  2549. el.style.top = `${offsetTop}px`;
  2550. el.style.left = `${offsetLeft}px`;
  2551. el.style.width = `${offsetWidth}px`;
  2552. el.style.height = `${offsetHeight}px`;
  2553. }
  2554. if (props.hideOnLeave) {
  2555. el.style.setProperty('display', 'none', 'important');
  2556. }
  2557. },
  2558. onAfterLeave(el) {
  2559. if (props.leaveAbsolute && el?._transitionInitialStyles) {
  2560. const {
  2561. position,
  2562. top,
  2563. left,
  2564. width,
  2565. height
  2566. } = el._transitionInitialStyles;
  2567. delete el._transitionInitialStyles;
  2568. el.style.position = position || '';
  2569. el.style.top = top || '';
  2570. el.style.left = left || '';
  2571. el.style.width = width || '';
  2572. el.style.height = height || '';
  2573. }
  2574. }
  2575. };
  2576. return () => {
  2577. const tag = props.group ? vue.TransitionGroup : vue.Transition;
  2578. return vue.h(tag, {
  2579. name: props.disabled ? '' : name,
  2580. css: !props.disabled,
  2581. ...(props.group ? undefined : {
  2582. mode: props.mode
  2583. }),
  2584. ...(props.disabled ? {} : functions)
  2585. }, slots.default);
  2586. };
  2587. }
  2588. });
  2589. }
  2590. function createJavascriptTransition(name, functions) {
  2591. let mode = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : 'in-out';
  2592. return genericComponent()({
  2593. name,
  2594. props: {
  2595. mode: {
  2596. type: String,
  2597. default: mode
  2598. },
  2599. disabled: Boolean,
  2600. group: Boolean
  2601. },
  2602. setup(props, _ref2) {
  2603. let {
  2604. slots
  2605. } = _ref2;
  2606. const tag = props.group ? vue.TransitionGroup : vue.Transition;
  2607. return () => {
  2608. return vue.h(tag, {
  2609. name: props.disabled ? '' : name,
  2610. css: !props.disabled,
  2611. // mode: props.mode, // TODO: vuejs/vue-next#3104
  2612. ...(props.disabled ? {} : functions)
  2613. }, slots.default);
  2614. };
  2615. }
  2616. });
  2617. }
  2618. // Utilities
  2619. function ExpandTransitionGenerator () {
  2620. let expandedParentClass = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : '';
  2621. let x = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : false;
  2622. const sizeProperty = x ? 'width' : 'height';
  2623. const offsetProperty = vue.camelize(`offset-${sizeProperty}`);
  2624. return {
  2625. onBeforeEnter(el) {
  2626. el._parent = el.parentNode;
  2627. el._initialStyle = {
  2628. transition: el.style.transition,
  2629. overflow: el.style.overflow,
  2630. [sizeProperty]: el.style[sizeProperty]
  2631. };
  2632. },
  2633. onEnter(el) {
  2634. const initialStyle = el._initialStyle;
  2635. el.style.setProperty('transition', 'none', 'important');
  2636. // Hide overflow to account for collapsed margins in the calculated height
  2637. el.style.overflow = 'hidden';
  2638. const offset = `${el[offsetProperty]}px`;
  2639. el.style[sizeProperty] = '0';
  2640. void el.offsetHeight; // force reflow
  2641. el.style.transition = initialStyle.transition;
  2642. if (expandedParentClass && el._parent) {
  2643. el._parent.classList.add(expandedParentClass);
  2644. }
  2645. requestAnimationFrame(() => {
  2646. el.style[sizeProperty] = offset;
  2647. });
  2648. },
  2649. onAfterEnter: resetStyles,
  2650. onEnterCancelled: resetStyles,
  2651. onLeave(el) {
  2652. el._initialStyle = {
  2653. transition: '',
  2654. overflow: el.style.overflow,
  2655. [sizeProperty]: el.style[sizeProperty]
  2656. };
  2657. el.style.overflow = 'hidden';
  2658. el.style[sizeProperty] = `${el[offsetProperty]}px`;
  2659. void el.offsetHeight; // force reflow
  2660. requestAnimationFrame(() => el.style[sizeProperty] = '0');
  2661. },
  2662. onAfterLeave,
  2663. onLeaveCancelled: onAfterLeave
  2664. };
  2665. function onAfterLeave(el) {
  2666. if (expandedParentClass && el._parent) {
  2667. el._parent.classList.remove(expandedParentClass);
  2668. }
  2669. resetStyles(el);
  2670. }
  2671. function resetStyles(el) {
  2672. const size = el._initialStyle[sizeProperty];
  2673. el.style.overflow = el._initialStyle.overflow;
  2674. if (size != null) el.style[sizeProperty] = size;
  2675. delete el._initialStyle;
  2676. }
  2677. }
  2678. // Types
  2679. const makeVDialogTransitionProps = propsFactory({
  2680. target: [Object, Array]
  2681. }, 'v-dialog-transition');
  2682. const VDialogTransition = genericComponent()({
  2683. name: 'VDialogTransition',
  2684. props: makeVDialogTransitionProps(),
  2685. setup(props, _ref) {
  2686. let {
  2687. slots
  2688. } = _ref;
  2689. const functions = {
  2690. onBeforeEnter(el) {
  2691. el.style.pointerEvents = 'none';
  2692. el.style.visibility = 'hidden';
  2693. },
  2694. async onEnter(el, done) {
  2695. await new Promise(resolve => requestAnimationFrame(resolve));
  2696. await new Promise(resolve => requestAnimationFrame(resolve));
  2697. el.style.visibility = '';
  2698. const {
  2699. x,
  2700. y,
  2701. sx,
  2702. sy,
  2703. speed
  2704. } = getDimensions(props.target, el);
  2705. const animation = animate(el, [{
  2706. transform: `translate(${x}px, ${y}px) scale(${sx}, ${sy})`,
  2707. opacity: 0
  2708. }, {}], {
  2709. duration: 225 * speed,
  2710. easing: deceleratedEasing
  2711. });
  2712. getChildren(el)?.forEach(el => {
  2713. animate(el, [{
  2714. opacity: 0
  2715. }, {
  2716. opacity: 0,
  2717. offset: 0.33
  2718. }, {}], {
  2719. duration: 225 * 2 * speed,
  2720. easing: standardEasing
  2721. });
  2722. });
  2723. animation.finished.then(() => done());
  2724. },
  2725. onAfterEnter(el) {
  2726. el.style.removeProperty('pointer-events');
  2727. },
  2728. onBeforeLeave(el) {
  2729. el.style.pointerEvents = 'none';
  2730. },
  2731. async onLeave(el, done) {
  2732. await new Promise(resolve => requestAnimationFrame(resolve));
  2733. const {
  2734. x,
  2735. y,
  2736. sx,
  2737. sy,
  2738. speed
  2739. } = getDimensions(props.target, el);
  2740. const animation = animate(el, [{}, {
  2741. transform: `translate(${x}px, ${y}px) scale(${sx}, ${sy})`,
  2742. opacity: 0
  2743. }], {
  2744. duration: 125 * speed,
  2745. easing: acceleratedEasing
  2746. });
  2747. animation.finished.then(() => done());
  2748. getChildren(el)?.forEach(el => {
  2749. animate(el, [{}, {
  2750. opacity: 0,
  2751. offset: 0.2
  2752. }, {
  2753. opacity: 0
  2754. }], {
  2755. duration: 125 * 2 * speed,
  2756. easing: standardEasing
  2757. });
  2758. });
  2759. },
  2760. onAfterLeave(el) {
  2761. el.style.removeProperty('pointer-events');
  2762. }
  2763. };
  2764. return () => {
  2765. return props.target ? vue.createVNode(vue.Transition, vue.mergeProps({
  2766. "name": "dialog-transition"
  2767. }, functions, {
  2768. "css": false
  2769. }), slots) : vue.createVNode(vue.Transition, {
  2770. "name": "dialog-transition"
  2771. }, slots);
  2772. };
  2773. }
  2774. });
  2775. /** Animatable children (card, sheet, list) */
  2776. function getChildren(el) {
  2777. const els = el.querySelector(':scope > .v-card, :scope > .v-sheet, :scope > .v-list')?.children;
  2778. return els && [...els];
  2779. }
  2780. function getDimensions(target, el) {
  2781. const targetBox = getTargetBox(target);
  2782. const elBox = nullifyTransforms(el);
  2783. const [originX, originY] = getComputedStyle(el).transformOrigin.split(' ').map(v => parseFloat(v));
  2784. const [anchorSide, anchorOffset] = getComputedStyle(el).getPropertyValue('--v-overlay-anchor-origin').split(' ');
  2785. let offsetX = targetBox.left + targetBox.width / 2;
  2786. if (anchorSide === 'left' || anchorOffset === 'left') {
  2787. offsetX -= targetBox.width / 2;
  2788. } else if (anchorSide === 'right' || anchorOffset === 'right') {
  2789. offsetX += targetBox.width / 2;
  2790. }
  2791. let offsetY = targetBox.top + targetBox.height / 2;
  2792. if (anchorSide === 'top' || anchorOffset === 'top') {
  2793. offsetY -= targetBox.height / 2;
  2794. } else if (anchorSide === 'bottom' || anchorOffset === 'bottom') {
  2795. offsetY += targetBox.height / 2;
  2796. }
  2797. const tsx = targetBox.width / elBox.width;
  2798. const tsy = targetBox.height / elBox.height;
  2799. const maxs = Math.max(1, tsx, tsy);
  2800. const sx = tsx / maxs || 0;
  2801. const sy = tsy / maxs || 0;
  2802. // Animate elements larger than 12% of the screen area up to 1.5x slower
  2803. const asa = elBox.width * elBox.height / (window.innerWidth * window.innerHeight);
  2804. const speed = asa > 0.12 ? Math.min(1.5, (asa - 0.12) * 10 + 1) : 1;
  2805. return {
  2806. x: offsetX - (originX + elBox.left),
  2807. y: offsetY - (originY + elBox.top),
  2808. sx,
  2809. sy,
  2810. speed
  2811. };
  2812. }
  2813. // Component specific transitions
  2814. const VFabTransition = createCssTransition('fab-transition', 'center center', 'out-in');
  2815. // Generic transitions
  2816. const VDialogBottomTransition = createCssTransition('dialog-bottom-transition');
  2817. const VDialogTopTransition = createCssTransition('dialog-top-transition');
  2818. const VFadeTransition = createCssTransition('fade-transition');
  2819. const VScaleTransition = createCssTransition('scale-transition');
  2820. const VScrollXTransition = createCssTransition('scroll-x-transition');
  2821. const VScrollXReverseTransition = createCssTransition('scroll-x-reverse-transition');
  2822. const VScrollYTransition = createCssTransition('scroll-y-transition');
  2823. const VScrollYReverseTransition = createCssTransition('scroll-y-reverse-transition');
  2824. const VSlideXTransition = createCssTransition('slide-x-transition');
  2825. const VSlideXReverseTransition = createCssTransition('slide-x-reverse-transition');
  2826. const VSlideYTransition = createCssTransition('slide-y-transition');
  2827. const VSlideYReverseTransition = createCssTransition('slide-y-reverse-transition');
  2828. // Javascript transitions
  2829. const VExpandTransition = createJavascriptTransition('expand-transition', ExpandTransitionGenerator());
  2830. const VExpandXTransition = createJavascriptTransition('expand-x-transition', ExpandTransitionGenerator('', true));
  2831. // Composables
  2832. // Types
  2833. const makeVDefaultsProviderProps = propsFactory({
  2834. defaults: Object,
  2835. disabled: Boolean,
  2836. reset: [Number, String],
  2837. root: [Boolean, String],
  2838. scoped: Boolean
  2839. }, 'VDefaultsProvider');
  2840. const VDefaultsProvider = genericComponent(false)({
  2841. name: 'VDefaultsProvider',
  2842. props: makeVDefaultsProviderProps(),
  2843. setup(props, _ref) {
  2844. let {
  2845. slots
  2846. } = _ref;
  2847. const {
  2848. defaults,
  2849. disabled,
  2850. reset,
  2851. root,
  2852. scoped
  2853. } = vue.toRefs(props);
  2854. provideDefaults(defaults, {
  2855. reset,
  2856. root,
  2857. scoped,
  2858. disabled
  2859. });
  2860. return () => slots.default?.();
  2861. }
  2862. });
  2863. // Utilities
  2864. // Types
  2865. // Composables
  2866. const makeDimensionProps = propsFactory({
  2867. height: [Number, String],
  2868. maxHeight: [Number, String],
  2869. maxWidth: [Number, String],
  2870. minHeight: [Number, String],
  2871. minWidth: [Number, String],
  2872. width: [Number, String]
  2873. }, 'dimension');
  2874. function useDimension(props) {
  2875. const dimensionStyles = vue.computed(() => {
  2876. const styles = {};
  2877. const height = convertToUnit(props.height);
  2878. const maxHeight = convertToUnit(props.maxHeight);
  2879. const maxWidth = convertToUnit(props.maxWidth);
  2880. const minHeight = convertToUnit(props.minHeight);
  2881. const minWidth = convertToUnit(props.minWidth);
  2882. const width = convertToUnit(props.width);
  2883. if (height != null) styles.height = height;
  2884. if (maxHeight != null) styles.maxHeight = maxHeight;
  2885. if (maxWidth != null) styles.maxWidth = maxWidth;
  2886. if (minHeight != null) styles.minHeight = minHeight;
  2887. if (minWidth != null) styles.minWidth = minWidth;
  2888. if (width != null) styles.width = width;
  2889. return styles;
  2890. });
  2891. return {
  2892. dimensionStyles
  2893. };
  2894. }
  2895. function useAspectStyles(props) {
  2896. return {
  2897. aspectStyles: vue.computed(() => {
  2898. const ratio = Number(props.aspectRatio);
  2899. return ratio ? {
  2900. paddingBottom: String(1 / ratio * 100) + '%'
  2901. } : undefined;
  2902. })
  2903. };
  2904. }
  2905. const makeVResponsiveProps = propsFactory({
  2906. aspectRatio: [String, Number],
  2907. contentClass: null,
  2908. inline: Boolean,
  2909. ...makeComponentProps(),
  2910. ...makeDimensionProps()
  2911. }, 'VResponsive');
  2912. const VResponsive = genericComponent()({
  2913. name: 'VResponsive',
  2914. props: makeVResponsiveProps(),
  2915. setup(props, _ref) {
  2916. let {
  2917. slots
  2918. } = _ref;
  2919. const {
  2920. aspectStyles
  2921. } = useAspectStyles(props);
  2922. const {
  2923. dimensionStyles
  2924. } = useDimension(props);
  2925. useRender(() => vue.createVNode("div", {
  2926. "class": ['v-responsive', {
  2927. 'v-responsive--inline': props.inline
  2928. }, props.class],
  2929. "style": [dimensionStyles.value, props.style]
  2930. }, [vue.createVNode("div", {
  2931. "class": "v-responsive__sizer",
  2932. "style": aspectStyles.value
  2933. }, null), slots.additional?.(), slots.default && vue.createVNode("div", {
  2934. "class": ['v-responsive__content', props.contentClass]
  2935. }, [slots.default()])]));
  2936. return {};
  2937. }
  2938. });
  2939. // Utilities
  2940. // Types
  2941. // Composables
  2942. function useColor(colors) {
  2943. return destructComputed(() => {
  2944. const classes = [];
  2945. const styles = {};
  2946. if (colors.value.background) {
  2947. if (isCssColor(colors.value.background)) {
  2948. styles.backgroundColor = colors.value.background;
  2949. if (!colors.value.text && isParsableColor(colors.value.background)) {
  2950. const backgroundColor = parseColor(colors.value.background);
  2951. if (backgroundColor.a == null || backgroundColor.a === 1) {
  2952. const textColor = getForeground(backgroundColor);
  2953. styles.color = textColor;
  2954. styles.caretColor = textColor;
  2955. }
  2956. }
  2957. } else {
  2958. classes.push(`bg-${colors.value.background}`);
  2959. }
  2960. }
  2961. if (colors.value.text) {
  2962. if (isCssColor(colors.value.text)) {
  2963. styles.color = colors.value.text;
  2964. styles.caretColor = colors.value.text;
  2965. } else {
  2966. classes.push(`text-${colors.value.text}`);
  2967. }
  2968. }
  2969. return {
  2970. colorClasses: classes,
  2971. colorStyles: styles
  2972. };
  2973. });
  2974. }
  2975. function useTextColor(props, name) {
  2976. const colors = vue.computed(() => ({
  2977. text: vue.isRef(props) ? props.value : name ? props[name] : null
  2978. }));
  2979. const {
  2980. colorClasses: textColorClasses,
  2981. colorStyles: textColorStyles
  2982. } = useColor(colors);
  2983. return {
  2984. textColorClasses,
  2985. textColorStyles
  2986. };
  2987. }
  2988. function useBackgroundColor(props, name) {
  2989. const colors = vue.computed(() => ({
  2990. background: vue.isRef(props) ? props.value : name ? props[name] : null
  2991. }));
  2992. const {
  2993. colorClasses: backgroundColorClasses,
  2994. colorStyles: backgroundColorStyles
  2995. } = useColor(colors);
  2996. return {
  2997. backgroundColorClasses,
  2998. backgroundColorStyles
  2999. };
  3000. }
  3001. // Utilities
  3002. // Types
  3003. // Composables
  3004. const makeRoundedProps = propsFactory({
  3005. rounded: {
  3006. type: [Boolean, Number, String],
  3007. default: undefined
  3008. },
  3009. tile: Boolean
  3010. }, 'rounded');
  3011. function useRounded(props) {
  3012. let name = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : getCurrentInstanceName();
  3013. const roundedClasses = vue.computed(() => {
  3014. const rounded = vue.isRef(props) ? props.value : props.rounded;
  3015. const tile = vue.isRef(props) ? props.value : props.tile;
  3016. const classes = [];
  3017. if (rounded === true || rounded === '') {
  3018. classes.push(`${name}--rounded`);
  3019. } else if (typeof rounded === 'string' || rounded === 0) {
  3020. for (const value of String(rounded).split(' ')) {
  3021. classes.push(`rounded-${value}`);
  3022. }
  3023. } else if (tile || rounded === false) {
  3024. classes.push('rounded-0');
  3025. }
  3026. return classes;
  3027. });
  3028. return {
  3029. roundedClasses
  3030. };
  3031. }
  3032. // Utilities
  3033. // Types
  3034. const makeTransitionProps = propsFactory({
  3035. transition: {
  3036. type: [Boolean, String, Object],
  3037. default: 'fade-transition',
  3038. validator: val => val !== true
  3039. }
  3040. }, 'transition');
  3041. const MaybeTransition = (props, _ref) => {
  3042. let {
  3043. slots
  3044. } = _ref;
  3045. const {
  3046. transition,
  3047. disabled,
  3048. group,
  3049. ...rest
  3050. } = props;
  3051. const {
  3052. component = group ? vue.TransitionGroup : vue.Transition,
  3053. ...customProps
  3054. } = typeof transition === 'object' ? transition : {};
  3055. return vue.h(component, vue.mergeProps(typeof transition === 'string' ? {
  3056. name: disabled ? '' : transition
  3057. } : customProps, typeof transition === 'string' ? {} : Object.fromEntries(Object.entries({
  3058. disabled,
  3059. group
  3060. }).filter(_ref2 => {
  3061. let [_, v] = _ref2;
  3062. return v !== undefined;
  3063. })), rest), slots);
  3064. };
  3065. // Utilities
  3066. // Types
  3067. function mounted$5(el, binding) {
  3068. if (!SUPPORTS_INTERSECTION) return;
  3069. const modifiers = binding.modifiers || {};
  3070. const value = binding.value;
  3071. const {
  3072. handler,
  3073. options
  3074. } = typeof value === 'object' ? value : {
  3075. handler: value,
  3076. options: {}
  3077. };
  3078. const observer = new IntersectionObserver(function () {
  3079. let entries = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : [];
  3080. let observer = arguments.length > 1 ? arguments[1] : undefined;
  3081. const _observe = el._observe?.[binding.instance.$.uid];
  3082. if (!_observe) return; // Just in case, should never fire
  3083. const isIntersecting = entries.some(entry => entry.isIntersecting);
  3084. // If is not quiet or has already been
  3085. // initted, invoke the user callback
  3086. if (handler && (!modifiers.quiet || _observe.init) && (!modifiers.once || isIntersecting || _observe.init)) {
  3087. handler(isIntersecting, entries, observer);
  3088. }
  3089. if (isIntersecting && modifiers.once) unmounted$5(el, binding);else _observe.init = true;
  3090. }, options);
  3091. el._observe = Object(el._observe);
  3092. el._observe[binding.instance.$.uid] = {
  3093. init: false,
  3094. observer
  3095. };
  3096. observer.observe(el);
  3097. }
  3098. function unmounted$5(el, binding) {
  3099. const observe = el._observe?.[binding.instance.$.uid];
  3100. if (!observe) return;
  3101. observe.observer.unobserve(el);
  3102. delete el._observe[binding.instance.$.uid];
  3103. }
  3104. const Intersect = {
  3105. mounted: mounted$5,
  3106. unmounted: unmounted$5
  3107. };
  3108. // Types
  3109. // not intended for public use, this is passed in by vuetify-loader
  3110. const makeVImgProps = propsFactory({
  3111. absolute: Boolean,
  3112. alt: String,
  3113. cover: Boolean,
  3114. color: String,
  3115. draggable: {
  3116. type: [Boolean, String],
  3117. default: undefined
  3118. },
  3119. eager: Boolean,
  3120. gradient: String,
  3121. lazySrc: String,
  3122. options: {
  3123. type: Object,
  3124. // For more information on types, navigate to:
  3125. // https://developer.mozilla.org/en-US/docs/Web/API/Intersection_Observer_API
  3126. default: () => ({
  3127. root: undefined,
  3128. rootMargin: undefined,
  3129. threshold: undefined
  3130. })
  3131. },
  3132. sizes: String,
  3133. src: {
  3134. type: [String, Object],
  3135. default: ''
  3136. },
  3137. crossorigin: String,
  3138. referrerpolicy: String,
  3139. srcset: String,
  3140. position: String,
  3141. ...makeVResponsiveProps(),
  3142. ...makeComponentProps(),
  3143. ...makeRoundedProps(),
  3144. ...makeTransitionProps()
  3145. }, 'VImg');
  3146. const VImg = genericComponent()({
  3147. name: 'VImg',
  3148. directives: {
  3149. intersect: Intersect
  3150. },
  3151. props: makeVImgProps(),
  3152. emits: {
  3153. loadstart: value => true,
  3154. load: value => true,
  3155. error: value => true
  3156. },
  3157. setup(props, _ref) {
  3158. let {
  3159. emit,
  3160. slots
  3161. } = _ref;
  3162. const {
  3163. backgroundColorClasses,
  3164. backgroundColorStyles
  3165. } = useBackgroundColor(vue.toRef(props, 'color'));
  3166. const {
  3167. roundedClasses
  3168. } = useRounded(props);
  3169. const vm = getCurrentInstance('VImg');
  3170. const currentSrc = vue.shallowRef(''); // Set from srcset
  3171. const image = vue.ref();
  3172. const state = vue.shallowRef(props.eager ? 'loading' : 'idle');
  3173. const naturalWidth = vue.shallowRef();
  3174. const naturalHeight = vue.shallowRef();
  3175. const normalisedSrc = vue.computed(() => {
  3176. return props.src && typeof props.src === 'object' ? {
  3177. src: props.src.src,
  3178. srcset: props.srcset || props.src.srcset,
  3179. lazySrc: props.lazySrc || props.src.lazySrc,
  3180. aspect: Number(props.aspectRatio || props.src.aspect || 0)
  3181. } : {
  3182. src: props.src,
  3183. srcset: props.srcset,
  3184. lazySrc: props.lazySrc,
  3185. aspect: Number(props.aspectRatio || 0)
  3186. };
  3187. });
  3188. const aspectRatio = vue.computed(() => {
  3189. return normalisedSrc.value.aspect || naturalWidth.value / naturalHeight.value || 0;
  3190. });
  3191. vue.watch(() => props.src, () => {
  3192. init(state.value !== 'idle');
  3193. });
  3194. vue.watch(aspectRatio, (val, oldVal) => {
  3195. if (!val && oldVal && image.value) {
  3196. pollForSize(image.value);
  3197. }
  3198. });
  3199. // TODO: getSrc when window width changes
  3200. vue.onBeforeMount(() => init());
  3201. function init(isIntersecting) {
  3202. if (props.eager && isIntersecting) return;
  3203. if (SUPPORTS_INTERSECTION && !isIntersecting && !props.eager) return;
  3204. state.value = 'loading';
  3205. if (normalisedSrc.value.lazySrc) {
  3206. const lazyImg = new Image();
  3207. lazyImg.src = normalisedSrc.value.lazySrc;
  3208. pollForSize(lazyImg, null);
  3209. }
  3210. if (!normalisedSrc.value.src) return;
  3211. vue.nextTick(() => {
  3212. emit('loadstart', image.value?.currentSrc || normalisedSrc.value.src);
  3213. setTimeout(() => {
  3214. if (vm.isUnmounted) return;
  3215. if (image.value?.complete) {
  3216. if (!image.value.naturalWidth) {
  3217. onError();
  3218. }
  3219. if (state.value === 'error') return;
  3220. if (!aspectRatio.value) pollForSize(image.value, null);
  3221. if (state.value === 'loading') onLoad();
  3222. } else {
  3223. if (!aspectRatio.value) pollForSize(image.value);
  3224. getSrc();
  3225. }
  3226. });
  3227. });
  3228. }
  3229. function onLoad() {
  3230. if (vm.isUnmounted) return;
  3231. getSrc();
  3232. pollForSize(image.value);
  3233. state.value = 'loaded';
  3234. emit('load', image.value?.currentSrc || normalisedSrc.value.src);
  3235. }
  3236. function onError() {
  3237. if (vm.isUnmounted) return;
  3238. state.value = 'error';
  3239. emit('error', image.value?.currentSrc || normalisedSrc.value.src);
  3240. }
  3241. function getSrc() {
  3242. const img = image.value;
  3243. if (img) currentSrc.value = img.currentSrc || img.src;
  3244. }
  3245. let timer = -1;
  3246. vue.onBeforeUnmount(() => {
  3247. clearTimeout(timer);
  3248. });
  3249. function pollForSize(img) {
  3250. let timeout = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 100;
  3251. const poll = () => {
  3252. clearTimeout(timer);
  3253. if (vm.isUnmounted) return;
  3254. const {
  3255. naturalHeight: imgHeight,
  3256. naturalWidth: imgWidth
  3257. } = img;
  3258. if (imgHeight || imgWidth) {
  3259. naturalWidth.value = imgWidth;
  3260. naturalHeight.value = imgHeight;
  3261. } else if (!img.complete && state.value === 'loading' && timeout != null) {
  3262. timer = window.setTimeout(poll, timeout);
  3263. } else if (img.currentSrc.endsWith('.svg') || img.currentSrc.startsWith('data:image/svg+xml')) {
  3264. naturalWidth.value = 1;
  3265. naturalHeight.value = 1;
  3266. }
  3267. };
  3268. poll();
  3269. }
  3270. const containClasses = vue.computed(() => ({
  3271. 'v-img__img--cover': props.cover,
  3272. 'v-img__img--contain': !props.cover
  3273. }));
  3274. const __image = () => {
  3275. if (!normalisedSrc.value.src || state.value === 'idle') return null;
  3276. const img = vue.createVNode("img", {
  3277. "class": ['v-img__img', containClasses.value],
  3278. "style": {
  3279. objectPosition: props.position
  3280. },
  3281. "src": normalisedSrc.value.src,
  3282. "srcset": normalisedSrc.value.srcset,
  3283. "alt": props.alt,
  3284. "crossorigin": props.crossorigin,
  3285. "referrerpolicy": props.referrerpolicy,
  3286. "draggable": props.draggable,
  3287. "sizes": props.sizes,
  3288. "ref": image,
  3289. "onLoad": onLoad,
  3290. "onError": onError
  3291. }, null);
  3292. const sources = slots.sources?.();
  3293. return vue.createVNode(MaybeTransition, {
  3294. "transition": props.transition,
  3295. "appear": true
  3296. }, {
  3297. default: () => [vue.withDirectives(sources ? vue.createVNode("picture", {
  3298. "class": "v-img__picture"
  3299. }, [sources, img]) : img, [[vue.vShow, state.value === 'loaded']])]
  3300. });
  3301. };
  3302. const __preloadImage = () => vue.createVNode(MaybeTransition, {
  3303. "transition": props.transition
  3304. }, {
  3305. default: () => [normalisedSrc.value.lazySrc && state.value !== 'loaded' && vue.createVNode("img", {
  3306. "class": ['v-img__img', 'v-img__img--preload', containClasses.value],
  3307. "style": {
  3308. objectPosition: props.position
  3309. },
  3310. "src": normalisedSrc.value.lazySrc,
  3311. "alt": props.alt,
  3312. "crossorigin": props.crossorigin,
  3313. "referrerpolicy": props.referrerpolicy,
  3314. "draggable": props.draggable
  3315. }, null)]
  3316. });
  3317. const __placeholder = () => {
  3318. if (!slots.placeholder) return null;
  3319. return vue.createVNode(MaybeTransition, {
  3320. "transition": props.transition,
  3321. "appear": true
  3322. }, {
  3323. default: () => [(state.value === 'loading' || state.value === 'error' && !slots.error) && vue.createVNode("div", {
  3324. "class": "v-img__placeholder"
  3325. }, [slots.placeholder()])]
  3326. });
  3327. };
  3328. const __error = () => {
  3329. if (!slots.error) return null;
  3330. return vue.createVNode(MaybeTransition, {
  3331. "transition": props.transition,
  3332. "appear": true
  3333. }, {
  3334. default: () => [state.value === 'error' && vue.createVNode("div", {
  3335. "class": "v-img__error"
  3336. }, [slots.error()])]
  3337. });
  3338. };
  3339. const __gradient = () => {
  3340. if (!props.gradient) return null;
  3341. return vue.createVNode("div", {
  3342. "class": "v-img__gradient",
  3343. "style": {
  3344. backgroundImage: `linear-gradient(${props.gradient})`
  3345. }
  3346. }, null);
  3347. };
  3348. const isBooted = vue.shallowRef(false);
  3349. {
  3350. const stop = vue.watch(aspectRatio, val => {
  3351. if (val) {
  3352. // Doesn't work with nextTick, idk why
  3353. requestAnimationFrame(() => {
  3354. requestAnimationFrame(() => {
  3355. isBooted.value = true;
  3356. });
  3357. });
  3358. stop();
  3359. }
  3360. });
  3361. }
  3362. useRender(() => {
  3363. const responsiveProps = VResponsive.filterProps(props);
  3364. return vue.withDirectives(vue.createVNode(VResponsive, vue.mergeProps({
  3365. "class": ['v-img', {
  3366. 'v-img--absolute': props.absolute,
  3367. 'v-img--booting': !isBooted.value
  3368. }, backgroundColorClasses.value, roundedClasses.value, props.class],
  3369. "style": [{
  3370. width: convertToUnit(props.width === 'auto' ? naturalWidth.value : props.width)
  3371. }, backgroundColorStyles.value, props.style]
  3372. }, responsiveProps, {
  3373. "aspectRatio": aspectRatio.value,
  3374. "aria-label": props.alt,
  3375. "role": props.alt ? 'img' : undefined
  3376. }), {
  3377. 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)]),
  3378. default: slots.default
  3379. }), [[vue.resolveDirective("intersect"), {
  3380. handler: init,
  3381. options: props.options
  3382. }, null, {
  3383. once: true
  3384. }]]);
  3385. });
  3386. return {
  3387. currentSrc,
  3388. image,
  3389. state,
  3390. naturalWidth,
  3391. naturalHeight
  3392. };
  3393. }
  3394. });
  3395. // Utilities
  3396. // Types
  3397. // Composables
  3398. const makeBorderProps = propsFactory({
  3399. border: [Boolean, Number, String]
  3400. }, 'border');
  3401. function useBorder(props) {
  3402. let name = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : getCurrentInstanceName();
  3403. const borderClasses = vue.computed(() => {
  3404. const border = vue.isRef(props) ? props.value : props.border;
  3405. const classes = [];
  3406. if (border === true || border === '') {
  3407. classes.push(`${name}--border`);
  3408. } else if (typeof border === 'string' || border === 0) {
  3409. for (const value of String(border).split(' ')) {
  3410. classes.push(`border-${value}`);
  3411. }
  3412. }
  3413. return classes;
  3414. });
  3415. return {
  3416. borderClasses
  3417. };
  3418. }
  3419. // Utilities
  3420. // Types
  3421. // Composables
  3422. const makeElevationProps = propsFactory({
  3423. elevation: {
  3424. type: [Number, String],
  3425. validator(v) {
  3426. const value = parseInt(v);
  3427. return !isNaN(value) && value >= 0 &&
  3428. // Material Design has a maximum elevation of 24
  3429. // https://material.io/design/environment/elevation.html#default-elevations
  3430. value <= 24;
  3431. }
  3432. }
  3433. }, 'elevation');
  3434. function useElevation(props) {
  3435. const elevationClasses = vue.computed(() => {
  3436. const elevation = vue.isRef(props) ? props.value : props.elevation;
  3437. const classes = [];
  3438. if (elevation == null) return classes;
  3439. classes.push(`elevation-${elevation}`);
  3440. return classes;
  3441. });
  3442. return {
  3443. elevationClasses
  3444. };
  3445. }
  3446. // Types
  3447. const allowedDensities$1 = [null, 'prominent', 'default', 'comfortable', 'compact'];
  3448. const makeVToolbarProps = propsFactory({
  3449. absolute: Boolean,
  3450. collapse: Boolean,
  3451. color: String,
  3452. density: {
  3453. type: String,
  3454. default: 'default',
  3455. validator: v => allowedDensities$1.includes(v)
  3456. },
  3457. extended: Boolean,
  3458. extensionHeight: {
  3459. type: [Number, String],
  3460. default: 48
  3461. },
  3462. flat: Boolean,
  3463. floating: Boolean,
  3464. height: {
  3465. type: [Number, String],
  3466. default: 64
  3467. },
  3468. image: String,
  3469. title: String,
  3470. ...makeBorderProps(),
  3471. ...makeComponentProps(),
  3472. ...makeElevationProps(),
  3473. ...makeRoundedProps(),
  3474. ...makeTagProps({
  3475. tag: 'header'
  3476. }),
  3477. ...makeThemeProps()
  3478. }, 'VToolbar');
  3479. const VToolbar = genericComponent()({
  3480. name: 'VToolbar',
  3481. props: makeVToolbarProps(),
  3482. setup(props, _ref) {
  3483. let {
  3484. slots
  3485. } = _ref;
  3486. const {
  3487. backgroundColorClasses,
  3488. backgroundColorStyles
  3489. } = useBackgroundColor(vue.toRef(props, 'color'));
  3490. const {
  3491. borderClasses
  3492. } = useBorder(props);
  3493. const {
  3494. elevationClasses
  3495. } = useElevation(props);
  3496. const {
  3497. roundedClasses
  3498. } = useRounded(props);
  3499. const {
  3500. themeClasses
  3501. } = provideTheme(props);
  3502. const {
  3503. rtlClasses
  3504. } = useRtl();
  3505. const isExtended = vue.shallowRef(!!(props.extended || slots.extension?.()));
  3506. 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));
  3507. 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);
  3508. provideDefaults({
  3509. VBtn: {
  3510. variant: 'text'
  3511. }
  3512. });
  3513. useRender(() => {
  3514. const hasTitle = !!(props.title || slots.title);
  3515. const hasImage = !!(slots.image || props.image);
  3516. const extension = slots.extension?.();
  3517. isExtended.value = !!(props.extended || extension);
  3518. return vue.createVNode(props.tag, {
  3519. "class": ['v-toolbar', {
  3520. 'v-toolbar--absolute': props.absolute,
  3521. 'v-toolbar--collapse': props.collapse,
  3522. 'v-toolbar--flat': props.flat,
  3523. 'v-toolbar--floating': props.floating,
  3524. [`v-toolbar--density-${props.density}`]: true
  3525. }, backgroundColorClasses.value, borderClasses.value, elevationClasses.value, roundedClasses.value, themeClasses.value, rtlClasses.value, props.class],
  3526. "style": [backgroundColorStyles.value, props.style]
  3527. }, {
  3528. default: () => [hasImage && vue.createVNode("div", {
  3529. "key": "image",
  3530. "class": "v-toolbar__image"
  3531. }, [!slots.image ? vue.createVNode(VImg, {
  3532. "key": "image-img",
  3533. "cover": true,
  3534. "src": props.image
  3535. }, null) : vue.createVNode(VDefaultsProvider, {
  3536. "key": "image-defaults",
  3537. "disabled": !props.image,
  3538. "defaults": {
  3539. VImg: {
  3540. cover: true,
  3541. src: props.image
  3542. }
  3543. }
  3544. }, slots.image)]), vue.createVNode(VDefaultsProvider, {
  3545. "defaults": {
  3546. VTabs: {
  3547. height: convertToUnit(contentHeight.value)
  3548. }
  3549. }
  3550. }, {
  3551. default: () => [vue.createVNode("div", {
  3552. "class": "v-toolbar__content",
  3553. "style": {
  3554. height: convertToUnit(contentHeight.value)
  3555. }
  3556. }, [slots.prepend && vue.createVNode("div", {
  3557. "class": "v-toolbar__prepend"
  3558. }, [slots.prepend?.()]), hasTitle && vue.createVNode(VToolbarTitle, {
  3559. "key": "title",
  3560. "text": props.title
  3561. }, {
  3562. text: slots.title
  3563. }), slots.default?.(), slots.append && vue.createVNode("div", {
  3564. "class": "v-toolbar__append"
  3565. }, [slots.append?.()])])]
  3566. }), vue.createVNode(VDefaultsProvider, {
  3567. "defaults": {
  3568. VTabs: {
  3569. height: convertToUnit(extensionHeight.value)
  3570. }
  3571. }
  3572. }, {
  3573. default: () => [vue.createVNode(VExpandTransition, null, {
  3574. default: () => [isExtended.value && vue.createVNode("div", {
  3575. "class": "v-toolbar__extension",
  3576. "style": {
  3577. height: convertToUnit(extensionHeight.value)
  3578. }
  3579. }, [extension])]
  3580. })]
  3581. })]
  3582. });
  3583. });
  3584. return {
  3585. contentHeight,
  3586. extensionHeight
  3587. };
  3588. }
  3589. });
  3590. // Utilities
  3591. // Types
  3592. // Composables
  3593. const makeScrollProps = propsFactory({
  3594. scrollTarget: {
  3595. type: String
  3596. },
  3597. scrollThreshold: {
  3598. type: [String, Number],
  3599. default: 300
  3600. }
  3601. }, 'scroll');
  3602. function useScroll(props) {
  3603. let args = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
  3604. const {
  3605. canScroll
  3606. } = args;
  3607. let previousScroll = 0;
  3608. let previousScrollHeight = 0;
  3609. const target = vue.ref(null);
  3610. const currentScroll = vue.shallowRef(0);
  3611. const savedScroll = vue.shallowRef(0);
  3612. const currentThreshold = vue.shallowRef(0);
  3613. const isScrollActive = vue.shallowRef(false);
  3614. const isScrollingUp = vue.shallowRef(false);
  3615. const scrollThreshold = vue.computed(() => {
  3616. return Number(props.scrollThreshold);
  3617. });
  3618. /**
  3619. * 1: at top
  3620. * 0: at threshold
  3621. */
  3622. const scrollRatio = vue.computed(() => {
  3623. return clamp((scrollThreshold.value - currentScroll.value) / scrollThreshold.value || 0);
  3624. });
  3625. const onScroll = () => {
  3626. const targetEl = target.value;
  3627. if (!targetEl || canScroll && !canScroll.value) return;
  3628. previousScroll = currentScroll.value;
  3629. currentScroll.value = 'window' in targetEl ? targetEl.pageYOffset : targetEl.scrollTop;
  3630. const currentScrollHeight = targetEl instanceof Window ? document.documentElement.scrollHeight : targetEl.scrollHeight;
  3631. if (previousScrollHeight !== currentScrollHeight) {
  3632. previousScrollHeight = currentScrollHeight;
  3633. return;
  3634. }
  3635. isScrollingUp.value = currentScroll.value < previousScroll;
  3636. currentThreshold.value = Math.abs(currentScroll.value - scrollThreshold.value);
  3637. };
  3638. vue.watch(isScrollingUp, () => {
  3639. savedScroll.value = savedScroll.value || currentScroll.value;
  3640. });
  3641. vue.watch(isScrollActive, () => {
  3642. savedScroll.value = 0;
  3643. });
  3644. vue.onMounted(() => {
  3645. vue.watch(() => props.scrollTarget, scrollTarget => {
  3646. const newTarget = scrollTarget ? document.querySelector(scrollTarget) : window;
  3647. if (!newTarget) {
  3648. consoleWarn(`Unable to locate element with identifier ${scrollTarget}`);
  3649. return;
  3650. }
  3651. if (newTarget === target.value) return;
  3652. target.value?.removeEventListener('scroll', onScroll);
  3653. target.value = newTarget;
  3654. target.value.addEventListener('scroll', onScroll, {
  3655. passive: true
  3656. });
  3657. }, {
  3658. immediate: true
  3659. });
  3660. });
  3661. vue.onBeforeUnmount(() => {
  3662. target.value?.removeEventListener('scroll', onScroll);
  3663. });
  3664. // Do we need this? If yes - seems that
  3665. // there's no need to expose onScroll
  3666. canScroll && vue.watch(canScroll, onScroll, {
  3667. immediate: true
  3668. });
  3669. return {
  3670. scrollThreshold,
  3671. currentScroll,
  3672. currentThreshold,
  3673. isScrollActive,
  3674. scrollRatio,
  3675. // required only for testing
  3676. // probably can be removed
  3677. // later (2 chars chlng)
  3678. isScrollingUp,
  3679. savedScroll
  3680. };
  3681. }
  3682. // Utilities
  3683. // Composables
  3684. function useSsrBoot() {
  3685. const isBooted = vue.shallowRef(false);
  3686. vue.onMounted(() => {
  3687. window.requestAnimationFrame(() => {
  3688. isBooted.value = true;
  3689. });
  3690. });
  3691. const ssrBootStyles = vue.computed(() => !isBooted.value ? {
  3692. transition: 'none !important'
  3693. } : undefined);
  3694. return {
  3695. ssrBootStyles,
  3696. isBooted: vue.readonly(isBooted)
  3697. };
  3698. }
  3699. // Types
  3700. const makeVAppBarProps = propsFactory({
  3701. scrollBehavior: String,
  3702. modelValue: {
  3703. type: Boolean,
  3704. default: true
  3705. },
  3706. location: {
  3707. type: String,
  3708. default: 'top',
  3709. validator: value => ['top', 'bottom'].includes(value)
  3710. },
  3711. ...makeVToolbarProps(),
  3712. ...makeLayoutItemProps(),
  3713. ...makeScrollProps(),
  3714. height: {
  3715. type: [Number, String],
  3716. default: 64
  3717. }
  3718. }, 'VAppBar');
  3719. const VAppBar = genericComponent()({
  3720. name: 'VAppBar',
  3721. props: makeVAppBarProps(),
  3722. emits: {
  3723. 'update:modelValue': value => true
  3724. },
  3725. setup(props, _ref) {
  3726. let {
  3727. slots
  3728. } = _ref;
  3729. const vToolbarRef = vue.ref();
  3730. const isActive = useProxiedModel(props, 'modelValue');
  3731. const scrollBehavior = vue.computed(() => {
  3732. const behavior = new Set(props.scrollBehavior?.split(' ') ?? []);
  3733. return {
  3734. hide: behavior.has('hide'),
  3735. fullyHide: behavior.has('fully-hide'),
  3736. inverted: behavior.has('inverted'),
  3737. collapse: behavior.has('collapse'),
  3738. elevate: behavior.has('elevate'),
  3739. fadeImage: behavior.has('fade-image')
  3740. // shrink: behavior.has('shrink'),
  3741. };
  3742. });
  3743. const canScroll = vue.computed(() => {
  3744. const behavior = scrollBehavior.value;
  3745. return behavior.hide || behavior.fullyHide || behavior.inverted || behavior.collapse || behavior.elevate || behavior.fadeImage ||
  3746. // behavior.shrink ||
  3747. !isActive.value;
  3748. });
  3749. const {
  3750. currentScroll,
  3751. scrollThreshold,
  3752. isScrollingUp,
  3753. scrollRatio
  3754. } = useScroll(props, {
  3755. canScroll
  3756. });
  3757. const canHide = vue.computed(() => scrollBehavior.value.hide || scrollBehavior.value.fullyHide);
  3758. const isCollapsed = vue.computed(() => props.collapse || scrollBehavior.value.collapse && (scrollBehavior.value.inverted ? scrollRatio.value > 0 : scrollRatio.value === 0));
  3759. const isFlat = vue.computed(() => props.flat || scrollBehavior.value.fullyHide && !isActive.value || scrollBehavior.value.elevate && (scrollBehavior.value.inverted ? currentScroll.value > 0 : currentScroll.value === 0));
  3760. const opacity = vue.computed(() => scrollBehavior.value.fadeImage ? scrollBehavior.value.inverted ? 1 - scrollRatio.value : scrollRatio.value : undefined);
  3761. const height = vue.computed(() => {
  3762. if (scrollBehavior.value.hide && scrollBehavior.value.inverted) return 0;
  3763. const height = vToolbarRef.value?.contentHeight ?? 0;
  3764. const extensionHeight = vToolbarRef.value?.extensionHeight ?? 0;
  3765. if (!canHide.value) return height + extensionHeight;
  3766. return currentScroll.value < scrollThreshold.value || scrollBehavior.value.fullyHide ? height + extensionHeight : height;
  3767. });
  3768. useToggleScope(vue.computed(() => !!props.scrollBehavior), () => {
  3769. vue.watchEffect(() => {
  3770. if (canHide.value) {
  3771. if (scrollBehavior.value.inverted) {
  3772. isActive.value = currentScroll.value > scrollThreshold.value;
  3773. } else {
  3774. isActive.value = isScrollingUp.value || currentScroll.value < scrollThreshold.value;
  3775. }
  3776. } else {
  3777. isActive.value = true;
  3778. }
  3779. });
  3780. });
  3781. const {
  3782. ssrBootStyles
  3783. } = useSsrBoot();
  3784. const {
  3785. layoutItemStyles
  3786. } = useLayoutItem({
  3787. id: props.name,
  3788. order: vue.computed(() => parseInt(props.order, 10)),
  3789. position: vue.toRef(props, 'location'),
  3790. layoutSize: height,
  3791. elementSize: vue.shallowRef(undefined),
  3792. active: isActive,
  3793. absolute: vue.toRef(props, 'absolute')
  3794. });
  3795. useRender(() => {
  3796. const toolbarProps = VToolbar.filterProps(props);
  3797. return vue.createVNode(VToolbar, vue.mergeProps({
  3798. "ref": vToolbarRef,
  3799. "class": ['v-app-bar', {
  3800. 'v-app-bar--bottom': props.location === 'bottom'
  3801. }, props.class],
  3802. "style": [{
  3803. ...layoutItemStyles.value,
  3804. '--v-toolbar-image-opacity': opacity.value,
  3805. height: undefined,
  3806. ...ssrBootStyles.value
  3807. }, props.style]
  3808. }, toolbarProps, {
  3809. "collapse": isCollapsed.value,
  3810. "flat": isFlat.value
  3811. }), slots);
  3812. });
  3813. return {};
  3814. }
  3815. });
  3816. // Utilities
  3817. // Types
  3818. const allowedDensities = [null, 'default', 'comfortable', 'compact'];
  3819. // typeof allowedDensities[number] evalutes to any
  3820. // when generating api types for whatever reason.
  3821. // Composables
  3822. const makeDensityProps = propsFactory({
  3823. density: {
  3824. type: String,
  3825. default: 'default',
  3826. validator: v => allowedDensities.includes(v)
  3827. }
  3828. }, 'density');
  3829. function useDensity(props) {
  3830. let name = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : getCurrentInstanceName();
  3831. const densityClasses = vue.computed(() => {
  3832. return `${name}--density-${props.density}`;
  3833. });
  3834. return {
  3835. densityClasses
  3836. };
  3837. }
  3838. // Types
  3839. const allowedVariants$2 = ['elevated', 'flat', 'tonal', 'outlined', 'text', 'plain'];
  3840. function genOverlays(isClickable, name) {
  3841. return vue.createVNode(vue.Fragment, null, [isClickable && vue.createVNode("span", {
  3842. "key": "overlay",
  3843. "class": `${name}__overlay`
  3844. }, null), vue.createVNode("span", {
  3845. "key": "underlay",
  3846. "class": `${name}__underlay`
  3847. }, null)]);
  3848. }
  3849. const makeVariantProps = propsFactory({
  3850. color: String,
  3851. variant: {
  3852. type: String,
  3853. default: 'elevated',
  3854. validator: v => allowedVariants$2.includes(v)
  3855. }
  3856. }, 'variant');
  3857. function useVariant(props) {
  3858. let name = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : getCurrentInstanceName();
  3859. const variantClasses = vue.computed(() => {
  3860. const {
  3861. variant
  3862. } = vue.unref(props);
  3863. return `${name}--variant-${variant}`;
  3864. });
  3865. const {
  3866. colorClasses,
  3867. colorStyles
  3868. } = useColor(vue.computed(() => {
  3869. const {
  3870. variant,
  3871. color
  3872. } = vue.unref(props);
  3873. return {
  3874. [['elevated', 'flat'].includes(variant) ? 'background' : 'text']: color
  3875. };
  3876. }));
  3877. return {
  3878. colorClasses,
  3879. colorStyles,
  3880. variantClasses
  3881. };
  3882. }
  3883. const makeVBtnGroupProps = propsFactory({
  3884. baseColor: String,
  3885. divided: Boolean,
  3886. ...makeBorderProps(),
  3887. ...makeComponentProps(),
  3888. ...makeDensityProps(),
  3889. ...makeElevationProps(),
  3890. ...makeRoundedProps(),
  3891. ...makeTagProps(),
  3892. ...makeThemeProps(),
  3893. ...makeVariantProps()
  3894. }, 'VBtnGroup');
  3895. const VBtnGroup = genericComponent()({
  3896. name: 'VBtnGroup',
  3897. props: makeVBtnGroupProps(),
  3898. setup(props, _ref) {
  3899. let {
  3900. slots
  3901. } = _ref;
  3902. const {
  3903. themeClasses
  3904. } = provideTheme(props);
  3905. const {
  3906. densityClasses
  3907. } = useDensity(props);
  3908. const {
  3909. borderClasses
  3910. } = useBorder(props);
  3911. const {
  3912. elevationClasses
  3913. } = useElevation(props);
  3914. const {
  3915. roundedClasses
  3916. } = useRounded(props);
  3917. provideDefaults({
  3918. VBtn: {
  3919. height: 'auto',
  3920. baseColor: vue.toRef(props, 'baseColor'),
  3921. color: vue.toRef(props, 'color'),
  3922. density: vue.toRef(props, 'density'),
  3923. flat: true,
  3924. variant: vue.toRef(props, 'variant')
  3925. }
  3926. });
  3927. useRender(() => {
  3928. return vue.createVNode(props.tag, {
  3929. "class": ['v-btn-group', {
  3930. 'v-btn-group--divided': props.divided
  3931. }, themeClasses.value, borderClasses.value, densityClasses.value, elevationClasses.value, roundedClasses.value, props.class],
  3932. "style": props.style
  3933. }, slots);
  3934. });
  3935. }
  3936. });
  3937. // Composables
  3938. // Types
  3939. const makeGroupProps = propsFactory({
  3940. modelValue: {
  3941. type: null,
  3942. default: undefined
  3943. },
  3944. multiple: Boolean,
  3945. mandatory: [Boolean, String],
  3946. max: Number,
  3947. selectedClass: String,
  3948. disabled: Boolean
  3949. }, 'group');
  3950. const makeGroupItemProps = propsFactory({
  3951. value: null,
  3952. disabled: Boolean,
  3953. selectedClass: String
  3954. }, 'group-item');
  3955. // Composables
  3956. function useGroupItem(props, injectKey) {
  3957. let required = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : true;
  3958. const vm = getCurrentInstance('useGroupItem');
  3959. if (!vm) {
  3960. throw new Error('[Vuetify] useGroupItem composable must be used inside a component setup function');
  3961. }
  3962. const id = getUid();
  3963. vue.provide(Symbol.for(`${injectKey.description}:id`), id);
  3964. const group = vue.inject(injectKey, null);
  3965. if (!group) {
  3966. if (!required) return group;
  3967. throw new Error(`[Vuetify] Could not find useGroup injection with symbol ${injectKey.description}`);
  3968. }
  3969. const value = vue.toRef(props, 'value');
  3970. const disabled = vue.computed(() => !!(group.disabled.value || props.disabled));
  3971. group.register({
  3972. id,
  3973. value,
  3974. disabled
  3975. }, vm);
  3976. vue.onBeforeUnmount(() => {
  3977. group.unregister(id);
  3978. });
  3979. const isSelected = vue.computed(() => {
  3980. return group.isSelected(id);
  3981. });
  3982. const isFirst = vue.computed(() => {
  3983. return group.items.value[0].id === id;
  3984. });
  3985. const isLast = vue.computed(() => {
  3986. return group.items.value[group.items.value.length - 1].id === id;
  3987. });
  3988. const selectedClass = vue.computed(() => isSelected.value && [group.selectedClass.value, props.selectedClass]);
  3989. vue.watch(isSelected, value => {
  3990. vm.emit('group:selected', {
  3991. value
  3992. });
  3993. }, {
  3994. flush: 'sync'
  3995. });
  3996. return {
  3997. id,
  3998. isSelected,
  3999. isFirst,
  4000. isLast,
  4001. toggle: () => group.select(id, !isSelected.value),
  4002. select: value => group.select(id, value),
  4003. selectedClass,
  4004. value,
  4005. disabled,
  4006. group
  4007. };
  4008. }
  4009. function useGroup(props, injectKey) {
  4010. let isUnmounted = false;
  4011. const items = vue.reactive([]);
  4012. const selected = useProxiedModel(props, 'modelValue', [], v => {
  4013. if (v == null) return [];
  4014. return getIds(items, wrapInArray(v));
  4015. }, v => {
  4016. const arr = getValues(items, v);
  4017. return props.multiple ? arr : arr[0];
  4018. });
  4019. const groupVm = getCurrentInstance('useGroup');
  4020. function register(item, vm) {
  4021. // Is there a better way to fix this typing?
  4022. const unwrapped = item;
  4023. const key = Symbol.for(`${injectKey.description}:id`);
  4024. const children = findChildrenWithProvide(key, groupVm?.vnode);
  4025. const index = children.indexOf(vm);
  4026. if (vue.unref(unwrapped.value) == null) {
  4027. unwrapped.value = index;
  4028. unwrapped.useIndexAsValue = true;
  4029. }
  4030. if (index > -1) {
  4031. items.splice(index, 0, unwrapped);
  4032. } else {
  4033. items.push(unwrapped);
  4034. }
  4035. }
  4036. function unregister(id) {
  4037. if (isUnmounted) return;
  4038. // TODO: re-evaluate this line's importance in the future
  4039. // should we only modify the model if mandatory is set.
  4040. // selected.value = selected.value.filter(v => v !== id)
  4041. forceMandatoryValue();
  4042. const index = items.findIndex(item => item.id === id);
  4043. items.splice(index, 1);
  4044. }
  4045. // If mandatory and nothing is selected, then select first non-disabled item
  4046. function forceMandatoryValue() {
  4047. const item = items.find(item => !item.disabled);
  4048. if (item && props.mandatory === 'force' && !selected.value.length) {
  4049. selected.value = [item.id];
  4050. }
  4051. }
  4052. vue.onMounted(() => {
  4053. forceMandatoryValue();
  4054. });
  4055. vue.onBeforeUnmount(() => {
  4056. isUnmounted = true;
  4057. });
  4058. vue.onUpdated(() => {
  4059. // #19655 update the items that use the index as the value.
  4060. for (let i = 0; i < items.length; i++) {
  4061. if (items[i].useIndexAsValue) {
  4062. items[i].value = i;
  4063. }
  4064. }
  4065. });
  4066. function select(id, value) {
  4067. const item = items.find(item => item.id === id);
  4068. if (value && item?.disabled) return;
  4069. if (props.multiple) {
  4070. const internalValue = selected.value.slice();
  4071. const index = internalValue.findIndex(v => v === id);
  4072. const isSelected = ~index;
  4073. value = value ?? !isSelected;
  4074. // We can't remove value if group is
  4075. // mandatory, value already exists,
  4076. // and it is the only value
  4077. if (isSelected && props.mandatory && internalValue.length <= 1) return;
  4078. // We can't add value if it would
  4079. // cause max limit to be exceeded
  4080. if (!isSelected && props.max != null && internalValue.length + 1 > props.max) return;
  4081. if (index < 0 && value) internalValue.push(id);else if (index >= 0 && !value) internalValue.splice(index, 1);
  4082. selected.value = internalValue;
  4083. } else {
  4084. const isSelected = selected.value.includes(id);
  4085. if (props.mandatory && isSelected) return;
  4086. selected.value = value ?? !isSelected ? [id] : [];
  4087. }
  4088. }
  4089. function step(offset) {
  4090. // getting an offset from selected value obviously won't work with multiple values
  4091. if (props.multiple) consoleWarn('This method is not supported when using "multiple" prop');
  4092. if (!selected.value.length) {
  4093. const item = items.find(item => !item.disabled);
  4094. item && (selected.value = [item.id]);
  4095. } else {
  4096. const currentId = selected.value[0];
  4097. const currentIndex = items.findIndex(i => i.id === currentId);
  4098. let newIndex = (currentIndex + offset) % items.length;
  4099. let newItem = items[newIndex];
  4100. while (newItem.disabled && newIndex !== currentIndex) {
  4101. newIndex = (newIndex + offset) % items.length;
  4102. newItem = items[newIndex];
  4103. }
  4104. if (newItem.disabled) return;
  4105. selected.value = [items[newIndex].id];
  4106. }
  4107. }
  4108. const state = {
  4109. register,
  4110. unregister,
  4111. selected,
  4112. select,
  4113. disabled: vue.toRef(props, 'disabled'),
  4114. prev: () => step(items.length - 1),
  4115. next: () => step(1),
  4116. isSelected: id => selected.value.includes(id),
  4117. selectedClass: vue.computed(() => props.selectedClass),
  4118. items: vue.computed(() => items),
  4119. getItemIndex: value => getItemIndex(items, value)
  4120. };
  4121. vue.provide(injectKey, state);
  4122. return state;
  4123. }
  4124. function getItemIndex(items, value) {
  4125. const ids = getIds(items, [value]);
  4126. if (!ids.length) return -1;
  4127. return items.findIndex(item => item.id === ids[0]);
  4128. }
  4129. function getIds(items, modelValue) {
  4130. const ids = [];
  4131. modelValue.forEach(value => {
  4132. const item = items.find(item => deepEqual(value, item.value));
  4133. const itemByIndex = items[value];
  4134. if (item?.value != null) {
  4135. ids.push(item.id);
  4136. } else if (itemByIndex != null) {
  4137. ids.push(itemByIndex.id);
  4138. }
  4139. });
  4140. return ids;
  4141. }
  4142. function getValues(items, ids) {
  4143. const values = [];
  4144. ids.forEach(id => {
  4145. const itemIndex = items.findIndex(item => item.id === id);
  4146. if (~itemIndex) {
  4147. const item = items[itemIndex];
  4148. values.push(item.value != null ? item.value : itemIndex);
  4149. }
  4150. });
  4151. return values;
  4152. }
  4153. // Types
  4154. const VBtnToggleSymbol = Symbol.for('vuetify:v-btn-toggle');
  4155. const makeVBtnToggleProps = propsFactory({
  4156. ...makeVBtnGroupProps(),
  4157. ...makeGroupProps()
  4158. }, 'VBtnToggle');
  4159. const VBtnToggle = genericComponent()({
  4160. name: 'VBtnToggle',
  4161. props: makeVBtnToggleProps(),
  4162. emits: {
  4163. 'update:modelValue': value => true
  4164. },
  4165. setup(props, _ref) {
  4166. let {
  4167. slots
  4168. } = _ref;
  4169. const {
  4170. isSelected,
  4171. next,
  4172. prev,
  4173. select,
  4174. selected
  4175. } = useGroup(props, VBtnToggleSymbol);
  4176. useRender(() => {
  4177. const btnGroupProps = VBtnGroup.filterProps(props);
  4178. return vue.createVNode(VBtnGroup, vue.mergeProps({
  4179. "class": ['v-btn-toggle', props.class]
  4180. }, btnGroupProps, {
  4181. "style": props.style
  4182. }), {
  4183. default: () => [slots.default?.({
  4184. isSelected,
  4185. next,
  4186. prev,
  4187. select,
  4188. selected
  4189. })]
  4190. });
  4191. });
  4192. return {
  4193. next,
  4194. prev,
  4195. select
  4196. };
  4197. }
  4198. });
  4199. // Composables
  4200. // Types
  4201. const aliases = {
  4202. collapse: 'mdi-chevron-up',
  4203. complete: 'mdi-check',
  4204. cancel: 'mdi-close-circle',
  4205. close: 'mdi-close',
  4206. delete: 'mdi-close-circle',
  4207. // delete (e.g. v-chip close)
  4208. clear: 'mdi-close-circle',
  4209. success: 'mdi-check-circle',
  4210. info: 'mdi-information',
  4211. warning: 'mdi-alert-circle',
  4212. error: 'mdi-close-circle',
  4213. prev: 'mdi-chevron-left',
  4214. next: 'mdi-chevron-right',
  4215. checkboxOn: 'mdi-checkbox-marked',
  4216. checkboxOff: 'mdi-checkbox-blank-outline',
  4217. checkboxIndeterminate: 'mdi-minus-box',
  4218. delimiter: 'mdi-circle',
  4219. // for carousel
  4220. sortAsc: 'mdi-arrow-up',
  4221. sortDesc: 'mdi-arrow-down',
  4222. expand: 'mdi-chevron-down',
  4223. menu: 'mdi-menu',
  4224. subgroup: 'mdi-menu-down',
  4225. dropdown: 'mdi-menu-down',
  4226. radioOn: 'mdi-radiobox-marked',
  4227. radioOff: 'mdi-radiobox-blank',
  4228. edit: 'mdi-pencil',
  4229. ratingEmpty: 'mdi-star-outline',
  4230. ratingFull: 'mdi-star',
  4231. ratingHalf: 'mdi-star-half-full',
  4232. loading: 'mdi-cached',
  4233. first: 'mdi-page-first',
  4234. last: 'mdi-page-last',
  4235. unfold: 'mdi-unfold-more-horizontal',
  4236. file: 'mdi-paperclip',
  4237. plus: 'mdi-plus',
  4238. minus: 'mdi-minus',
  4239. calendar: 'mdi-calendar',
  4240. treeviewCollapse: 'mdi-menu-down',
  4241. treeviewExpand: 'mdi-menu-right',
  4242. eyeDropper: 'mdi-eyedropper',
  4243. upload: 'mdi-cloud-upload'
  4244. };
  4245. const mdi = {
  4246. // Not using mergeProps here, functional components merge props by default (?)
  4247. component: props => vue.h(VClassIcon, {
  4248. ...props,
  4249. class: 'mdi'
  4250. })
  4251. };
  4252. // Types
  4253. const IconValue = [String, Function, Object, Array];
  4254. const IconSymbol = Symbol.for('vuetify:icons');
  4255. const makeIconProps = propsFactory({
  4256. icon: {
  4257. type: IconValue
  4258. },
  4259. // Could not remove this and use makeTagProps, types complained because it is not required
  4260. tag: {
  4261. type: String,
  4262. required: true
  4263. }
  4264. }, 'icon');
  4265. const VComponentIcon = genericComponent()({
  4266. name: 'VComponentIcon',
  4267. props: makeIconProps(),
  4268. setup(props, _ref) {
  4269. let {
  4270. slots
  4271. } = _ref;
  4272. return () => {
  4273. const Icon = props.icon;
  4274. return vue.createVNode(props.tag, null, {
  4275. default: () => [props.icon ? vue.createVNode(Icon, null, null) : slots.default?.()]
  4276. });
  4277. };
  4278. }
  4279. });
  4280. const VSvgIcon = defineComponent({
  4281. name: 'VSvgIcon',
  4282. inheritAttrs: false,
  4283. props: makeIconProps(),
  4284. setup(props, _ref2) {
  4285. let {
  4286. attrs
  4287. } = _ref2;
  4288. return () => {
  4289. return vue.createVNode(props.tag, vue.mergeProps(attrs, {
  4290. "style": null
  4291. }), {
  4292. default: () => [vue.createVNode("svg", {
  4293. "class": "v-icon__svg",
  4294. "xmlns": "http://www.w3.org/2000/svg",
  4295. "viewBox": "0 0 24 24",
  4296. "role": "img",
  4297. "aria-hidden": "true"
  4298. }, [Array.isArray(props.icon) ? props.icon.map(path => Array.isArray(path) ? vue.createVNode("path", {
  4299. "d": path[0],
  4300. "fill-opacity": path[1]
  4301. }, null) : vue.createVNode("path", {
  4302. "d": path
  4303. }, null)) : vue.createVNode("path", {
  4304. "d": props.icon
  4305. }, null)])]
  4306. });
  4307. };
  4308. }
  4309. });
  4310. const VLigatureIcon = defineComponent({
  4311. name: 'VLigatureIcon',
  4312. props: makeIconProps(),
  4313. setup(props) {
  4314. return () => {
  4315. return vue.createVNode(props.tag, null, {
  4316. default: () => [props.icon]
  4317. });
  4318. };
  4319. }
  4320. });
  4321. const VClassIcon = defineComponent({
  4322. name: 'VClassIcon',
  4323. props: makeIconProps(),
  4324. setup(props) {
  4325. return () => {
  4326. return vue.createVNode(props.tag, {
  4327. "class": props.icon
  4328. }, null);
  4329. };
  4330. }
  4331. });
  4332. function genDefaults$1() {
  4333. return {
  4334. svg: {
  4335. component: VSvgIcon
  4336. },
  4337. class: {
  4338. component: VClassIcon
  4339. }
  4340. };
  4341. }
  4342. // Composables
  4343. function createIcons(options) {
  4344. const sets = genDefaults$1();
  4345. const defaultSet = options?.defaultSet ?? 'mdi';
  4346. if (defaultSet === 'mdi' && !sets.mdi) {
  4347. sets.mdi = mdi;
  4348. }
  4349. return mergeDeep({
  4350. defaultSet,
  4351. sets,
  4352. aliases: {
  4353. ...aliases,
  4354. /* eslint-disable max-len */
  4355. 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]],
  4356. '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',
  4357. 'vuetify-play': ['m6.376 13.184-4.11-7.192C1.505 4.66 2.467 3 4.003 3h8.532l-.953 1.576-.006.01-.396.677c-.429.732-.214 1.507.194 2.015.404.503 1.092.878 1.869.806a3.72 3.72 0 0 1 1.005.022c.276.053.434.143.523.237.138.146.38.635-.25 2.09-.893 1.63-1.553 1.722-1.847 1.677-.213-.033-.468-.158-.756-.406a4.95 4.95 0 0 1-.8-.927c-.39-.564-1.04-.84-1.66-.846-.625-.006-1.316.27-1.693.921l-.478.826-.911 1.506Z', ['M9.093 11.552c.046-.079.144-.15.32-.148a.53.53 0 0 1 .43.207c.285.414.636.847 1.046 1.2.405.35.914.662 1.516.754 1.334.205 2.502-.698 3.48-2.495l.014-.028.013-.03c.687-1.574.774-2.852-.005-3.675-.37-.391-.861-.586-1.333-.676a5.243 5.243 0 0 0-1.447-.044c-.173.016-.393-.073-.54-.257-.145-.18-.127-.316-.082-.392l.393-.672L14.287 3h5.71c1.536 0 2.499 1.659 1.737 2.992l-7.997 13.996c-.768 1.344-2.706 1.344-3.473 0l-3.037-5.314 1.377-2.278.004-.006.004-.007.481-.831Z', 0.6]]
  4358. /* eslint-enable max-len */
  4359. }
  4360. }, options);
  4361. }
  4362. const useIcon = props => {
  4363. const icons = vue.inject(IconSymbol);
  4364. if (!icons) throw new Error('Missing Vuetify Icons provide!');
  4365. const iconData = vue.computed(() => {
  4366. const iconAlias = vue.unref(props);
  4367. if (!iconAlias) return {
  4368. component: VComponentIcon
  4369. };
  4370. let icon = iconAlias;
  4371. if (typeof icon === 'string') {
  4372. icon = icon.trim();
  4373. if (icon.startsWith('$')) {
  4374. icon = icons.aliases?.[icon.slice(1)];
  4375. }
  4376. }
  4377. if (!icon) consoleWarn(`Could not find aliased icon "${iconAlias}"`);
  4378. if (Array.isArray(icon)) {
  4379. return {
  4380. component: VSvgIcon,
  4381. icon
  4382. };
  4383. } else if (typeof icon !== 'string') {
  4384. return {
  4385. component: VComponentIcon,
  4386. icon
  4387. };
  4388. }
  4389. const iconSetName = Object.keys(icons.sets).find(setName => typeof icon === 'string' && icon.startsWith(`${setName}:`));
  4390. const iconName = iconSetName ? icon.slice(iconSetName.length + 1) : icon;
  4391. const iconSet = icons.sets[iconSetName ?? icons.defaultSet];
  4392. return {
  4393. component: iconSet.component,
  4394. icon: iconName
  4395. };
  4396. });
  4397. return {
  4398. iconData
  4399. };
  4400. };
  4401. // Utilities
  4402. // Types
  4403. const predefinedSizes = ['x-small', 'small', 'default', 'large', 'x-large'];
  4404. // Composables
  4405. const makeSizeProps = propsFactory({
  4406. size: {
  4407. type: [String, Number],
  4408. default: 'default'
  4409. }
  4410. }, 'size');
  4411. function useSize(props) {
  4412. let name = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : getCurrentInstanceName();
  4413. return destructComputed(() => {
  4414. let sizeClasses;
  4415. let sizeStyles;
  4416. if (includes(predefinedSizes, props.size)) {
  4417. sizeClasses = `${name}--size-${props.size}`;
  4418. } else if (props.size) {
  4419. sizeStyles = {
  4420. width: convertToUnit(props.size),
  4421. height: convertToUnit(props.size)
  4422. };
  4423. }
  4424. return {
  4425. sizeClasses,
  4426. sizeStyles
  4427. };
  4428. });
  4429. }
  4430. const makeVIconProps = propsFactory({
  4431. color: String,
  4432. disabled: Boolean,
  4433. start: Boolean,
  4434. end: Boolean,
  4435. icon: IconValue,
  4436. ...makeComponentProps(),
  4437. ...makeSizeProps(),
  4438. ...makeTagProps({
  4439. tag: 'i'
  4440. }),
  4441. ...makeThemeProps()
  4442. }, 'VIcon');
  4443. const VIcon = genericComponent()({
  4444. name: 'VIcon',
  4445. props: makeVIconProps(),
  4446. setup(props, _ref) {
  4447. let {
  4448. attrs,
  4449. slots
  4450. } = _ref;
  4451. const slotIcon = vue.ref();
  4452. const {
  4453. themeClasses
  4454. } = provideTheme(props);
  4455. const {
  4456. iconData
  4457. } = useIcon(vue.computed(() => slotIcon.value || props.icon));
  4458. const {
  4459. sizeClasses
  4460. } = useSize(props);
  4461. const {
  4462. textColorClasses,
  4463. textColorStyles
  4464. } = useTextColor(vue.toRef(props, 'color'));
  4465. useRender(() => {
  4466. const slotValue = slots.default?.();
  4467. if (slotValue) {
  4468. slotIcon.value = flattenFragments(slotValue).filter(node => node.type === vue.Text && node.children && typeof node.children === 'string')[0]?.children;
  4469. }
  4470. const hasClick = !!(attrs.onClick || attrs.onClickOnce);
  4471. return vue.createVNode(iconData.value.component, {
  4472. "tag": props.tag,
  4473. "icon": iconData.value.icon,
  4474. "class": ['v-icon', 'notranslate', themeClasses.value, sizeClasses.value, textColorClasses.value, {
  4475. 'v-icon--clickable': hasClick,
  4476. 'v-icon--disabled': props.disabled,
  4477. 'v-icon--start': props.start,
  4478. 'v-icon--end': props.end
  4479. }, props.class],
  4480. "style": [!sizeClasses.value ? {
  4481. fontSize: convertToUnit(props.size),
  4482. height: convertToUnit(props.size),
  4483. width: convertToUnit(props.size)
  4484. } : undefined, textColorStyles.value, props.style],
  4485. "role": hasClick ? 'button' : undefined,
  4486. "aria-hidden": !hasClick,
  4487. "tabindex": hasClick ? props.disabled ? -1 : 0 : undefined
  4488. }, {
  4489. default: () => [slotValue]
  4490. });
  4491. });
  4492. return {};
  4493. }
  4494. });
  4495. // Utilities
  4496. function useIntersectionObserver(callback, options) {
  4497. const intersectionRef = vue.ref();
  4498. const isIntersecting = vue.shallowRef(false);
  4499. if (SUPPORTS_INTERSECTION) {
  4500. const observer = new IntersectionObserver(entries => {
  4501. callback?.(entries, observer);
  4502. isIntersecting.value = !!entries.find(entry => entry.isIntersecting);
  4503. }, options);
  4504. vue.onBeforeUnmount(() => {
  4505. observer.disconnect();
  4506. });
  4507. vue.watch(intersectionRef, (newValue, oldValue) => {
  4508. if (oldValue) {
  4509. observer.unobserve(oldValue);
  4510. isIntersecting.value = false;
  4511. }
  4512. if (newValue) observer.observe(newValue);
  4513. }, {
  4514. flush: 'post'
  4515. });
  4516. }
  4517. return {
  4518. intersectionRef,
  4519. isIntersecting
  4520. };
  4521. }
  4522. // Types
  4523. const makeVProgressCircularProps = propsFactory({
  4524. bgColor: String,
  4525. color: String,
  4526. indeterminate: [Boolean, String],
  4527. modelValue: {
  4528. type: [Number, String],
  4529. default: 0
  4530. },
  4531. rotate: {
  4532. type: [Number, String],
  4533. default: 0
  4534. },
  4535. width: {
  4536. type: [Number, String],
  4537. default: 4
  4538. },
  4539. ...makeComponentProps(),
  4540. ...makeSizeProps(),
  4541. ...makeTagProps({
  4542. tag: 'div'
  4543. }),
  4544. ...makeThemeProps()
  4545. }, 'VProgressCircular');
  4546. const VProgressCircular = genericComponent()({
  4547. name: 'VProgressCircular',
  4548. props: makeVProgressCircularProps(),
  4549. setup(props, _ref) {
  4550. let {
  4551. slots
  4552. } = _ref;
  4553. const MAGIC_RADIUS_CONSTANT = 20;
  4554. const CIRCUMFERENCE = 2 * Math.PI * MAGIC_RADIUS_CONSTANT;
  4555. const root = vue.ref();
  4556. const {
  4557. themeClasses
  4558. } = provideTheme(props);
  4559. const {
  4560. sizeClasses,
  4561. sizeStyles
  4562. } = useSize(props);
  4563. const {
  4564. textColorClasses,
  4565. textColorStyles
  4566. } = useTextColor(vue.toRef(props, 'color'));
  4567. const {
  4568. textColorClasses: underlayColorClasses,
  4569. textColorStyles: underlayColorStyles
  4570. } = useTextColor(vue.toRef(props, 'bgColor'));
  4571. const {
  4572. intersectionRef,
  4573. isIntersecting
  4574. } = useIntersectionObserver();
  4575. const {
  4576. resizeRef,
  4577. contentRect
  4578. } = useResizeObserver();
  4579. const normalizedValue = vue.computed(() => Math.max(0, Math.min(100, parseFloat(props.modelValue))));
  4580. const width = vue.computed(() => Number(props.width));
  4581. const size = vue.computed(() => {
  4582. // Get size from element if size prop value is small, large etc
  4583. return sizeStyles.value ? Number(props.size) : contentRect.value ? contentRect.value.width : Math.max(width.value, 32);
  4584. });
  4585. const diameter = vue.computed(() => MAGIC_RADIUS_CONSTANT / (1 - width.value / size.value) * 2);
  4586. const strokeWidth = vue.computed(() => width.value / size.value * diameter.value);
  4587. const strokeDashOffset = vue.computed(() => convertToUnit((100 - normalizedValue.value) / 100 * CIRCUMFERENCE));
  4588. vue.watchEffect(() => {
  4589. intersectionRef.value = root.value;
  4590. resizeRef.value = root.value;
  4591. });
  4592. useRender(() => vue.createVNode(props.tag, {
  4593. "ref": root,
  4594. "class": ['v-progress-circular', {
  4595. 'v-progress-circular--indeterminate': !!props.indeterminate,
  4596. 'v-progress-circular--visible': isIntersecting.value,
  4597. 'v-progress-circular--disable-shrink': props.indeterminate === 'disable-shrink'
  4598. }, themeClasses.value, sizeClasses.value, textColorClasses.value, props.class],
  4599. "style": [sizeStyles.value, textColorStyles.value, props.style],
  4600. "role": "progressbar",
  4601. "aria-valuemin": "0",
  4602. "aria-valuemax": "100",
  4603. "aria-valuenow": props.indeterminate ? undefined : normalizedValue.value
  4604. }, {
  4605. default: () => [vue.createVNode("svg", {
  4606. "style": {
  4607. transform: `rotate(calc(-90deg + ${Number(props.rotate)}deg))`
  4608. },
  4609. "xmlns": "http://www.w3.org/2000/svg",
  4610. "viewBox": `0 0 ${diameter.value} ${diameter.value}`
  4611. }, [vue.createVNode("circle", {
  4612. "class": ['v-progress-circular__underlay', underlayColorClasses.value],
  4613. "style": underlayColorStyles.value,
  4614. "fill": "transparent",
  4615. "cx": "50%",
  4616. "cy": "50%",
  4617. "r": MAGIC_RADIUS_CONSTANT,
  4618. "stroke-width": strokeWidth.value,
  4619. "stroke-dasharray": CIRCUMFERENCE,
  4620. "stroke-dashoffset": 0
  4621. }, null), vue.createVNode("circle", {
  4622. "class": "v-progress-circular__overlay",
  4623. "fill": "transparent",
  4624. "cx": "50%",
  4625. "cy": "50%",
  4626. "r": MAGIC_RADIUS_CONSTANT,
  4627. "stroke-width": strokeWidth.value,
  4628. "stroke-dasharray": CIRCUMFERENCE,
  4629. "stroke-dashoffset": strokeDashOffset.value
  4630. }, null)]), slots.default && vue.createVNode("div", {
  4631. "class": "v-progress-circular__content"
  4632. }, [slots.default({
  4633. value: normalizedValue.value
  4634. })])]
  4635. }));
  4636. return {};
  4637. }
  4638. });
  4639. // Composables
  4640. // Types
  4641. const oppositeMap = {
  4642. center: 'center',
  4643. top: 'bottom',
  4644. bottom: 'top',
  4645. left: 'right',
  4646. right: 'left'
  4647. };
  4648. const makeLocationProps = propsFactory({
  4649. location: String
  4650. }, 'location');
  4651. function useLocation(props) {
  4652. let opposite = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : false;
  4653. let offset = arguments.length > 2 ? arguments[2] : undefined;
  4654. const {
  4655. isRtl
  4656. } = useRtl();
  4657. const locationStyles = vue.computed(() => {
  4658. if (!props.location) return {};
  4659. const {
  4660. side,
  4661. align
  4662. } = parseAnchor(props.location.split(' ').length > 1 ? props.location : `${props.location} center`, isRtl.value);
  4663. function getOffset(side) {
  4664. return offset ? offset(side) : 0;
  4665. }
  4666. const styles = {};
  4667. if (side !== 'center') {
  4668. if (opposite) styles[oppositeMap[side]] = `calc(100% - ${getOffset(side)}px)`;else styles[side] = 0;
  4669. }
  4670. if (align !== 'center') {
  4671. if (opposite) styles[oppositeMap[align]] = `calc(100% - ${getOffset(align)}px)`;else styles[align] = 0;
  4672. } else {
  4673. if (side === 'center') styles.top = styles.left = '50%';else {
  4674. styles[{
  4675. top: 'left',
  4676. bottom: 'left',
  4677. left: 'top',
  4678. right: 'top'
  4679. }[side]] = '50%';
  4680. }
  4681. styles.transform = {
  4682. top: 'translateX(-50%)',
  4683. bottom: 'translateX(-50%)',
  4684. left: 'translateY(-50%)',
  4685. right: 'translateY(-50%)',
  4686. center: 'translate(-50%, -50%)'
  4687. }[side];
  4688. }
  4689. return styles;
  4690. });
  4691. return {
  4692. locationStyles
  4693. };
  4694. }
  4695. const makeVProgressLinearProps = propsFactory({
  4696. absolute: Boolean,
  4697. active: {
  4698. type: Boolean,
  4699. default: true
  4700. },
  4701. bgColor: String,
  4702. bgOpacity: [Number, String],
  4703. bufferValue: {
  4704. type: [Number, String],
  4705. default: 0
  4706. },
  4707. bufferColor: String,
  4708. bufferOpacity: [Number, String],
  4709. clickable: Boolean,
  4710. color: String,
  4711. height: {
  4712. type: [Number, String],
  4713. default: 4
  4714. },
  4715. indeterminate: Boolean,
  4716. max: {
  4717. type: [Number, String],
  4718. default: 100
  4719. },
  4720. modelValue: {
  4721. type: [Number, String],
  4722. default: 0
  4723. },
  4724. opacity: [Number, String],
  4725. reverse: Boolean,
  4726. stream: Boolean,
  4727. striped: Boolean,
  4728. roundedBar: Boolean,
  4729. ...makeComponentProps(),
  4730. ...makeLocationProps({
  4731. location: 'top'
  4732. }),
  4733. ...makeRoundedProps(),
  4734. ...makeTagProps(),
  4735. ...makeThemeProps()
  4736. }, 'VProgressLinear');
  4737. const VProgressLinear = genericComponent()({
  4738. name: 'VProgressLinear',
  4739. props: makeVProgressLinearProps(),
  4740. emits: {
  4741. 'update:modelValue': value => true
  4742. },
  4743. setup(props, _ref) {
  4744. let {
  4745. slots
  4746. } = _ref;
  4747. const progress = useProxiedModel(props, 'modelValue');
  4748. const {
  4749. isRtl,
  4750. rtlClasses
  4751. } = useRtl();
  4752. const {
  4753. themeClasses
  4754. } = provideTheme(props);
  4755. const {
  4756. locationStyles
  4757. } = useLocation(props);
  4758. const {
  4759. textColorClasses,
  4760. textColorStyles
  4761. } = useTextColor(props, 'color');
  4762. const {
  4763. backgroundColorClasses,
  4764. backgroundColorStyles
  4765. } = useBackgroundColor(vue.computed(() => props.bgColor || props.color));
  4766. const {
  4767. backgroundColorClasses: bufferColorClasses,
  4768. backgroundColorStyles: bufferColorStyles
  4769. } = useBackgroundColor(vue.computed(() => props.bufferColor || props.bgColor || props.color));
  4770. const {
  4771. backgroundColorClasses: barColorClasses,
  4772. backgroundColorStyles: barColorStyles
  4773. } = useBackgroundColor(props, 'color');
  4774. const {
  4775. roundedClasses
  4776. } = useRounded(props);
  4777. const {
  4778. intersectionRef,
  4779. isIntersecting
  4780. } = useIntersectionObserver();
  4781. const max = vue.computed(() => parseFloat(props.max));
  4782. const height = vue.computed(() => parseFloat(props.height));
  4783. const normalizedBuffer = vue.computed(() => clamp(parseFloat(props.bufferValue) / max.value * 100, 0, 100));
  4784. const normalizedValue = vue.computed(() => clamp(parseFloat(progress.value) / max.value * 100, 0, 100));
  4785. const isReversed = vue.computed(() => isRtl.value !== props.reverse);
  4786. const transition = vue.computed(() => props.indeterminate ? 'fade-transition' : 'slide-x-transition');
  4787. const isForcedColorsModeActive = IN_BROWSER && window.matchMedia?.('(forced-colors: active)').matches;
  4788. function handleClick(e) {
  4789. if (!intersectionRef.value) return;
  4790. const {
  4791. left,
  4792. right,
  4793. width
  4794. } = intersectionRef.value.getBoundingClientRect();
  4795. const value = isReversed.value ? width - e.clientX + (right - width) : e.clientX - left;
  4796. progress.value = Math.round(value / width * max.value);
  4797. }
  4798. useRender(() => vue.createVNode(props.tag, {
  4799. "ref": intersectionRef,
  4800. "class": ['v-progress-linear', {
  4801. 'v-progress-linear--absolute': props.absolute,
  4802. 'v-progress-linear--active': props.active && isIntersecting.value,
  4803. 'v-progress-linear--reverse': isReversed.value,
  4804. 'v-progress-linear--rounded': props.rounded,
  4805. 'v-progress-linear--rounded-bar': props.roundedBar,
  4806. 'v-progress-linear--striped': props.striped
  4807. }, roundedClasses.value, themeClasses.value, rtlClasses.value, props.class],
  4808. "style": [{
  4809. bottom: props.location === 'bottom' ? 0 : undefined,
  4810. top: props.location === 'top' ? 0 : undefined,
  4811. height: props.active ? convertToUnit(height.value) : 0,
  4812. '--v-progress-linear-height': convertToUnit(height.value),
  4813. ...(props.absolute ? locationStyles.value : {})
  4814. }, props.style],
  4815. "role": "progressbar",
  4816. "aria-hidden": props.active ? 'false' : 'true',
  4817. "aria-valuemin": "0",
  4818. "aria-valuemax": props.max,
  4819. "aria-valuenow": props.indeterminate ? undefined : normalizedValue.value,
  4820. "onClick": props.clickable && handleClick
  4821. }, {
  4822. default: () => [props.stream && vue.createVNode("div", {
  4823. "key": "stream",
  4824. "class": ['v-progress-linear__stream', textColorClasses.value],
  4825. "style": {
  4826. ...textColorStyles.value,
  4827. [isReversed.value ? 'left' : 'right']: convertToUnit(-height.value),
  4828. borderTop: `${convertToUnit(height.value / 2)} dotted`,
  4829. opacity: parseFloat(props.bufferOpacity),
  4830. top: `calc(50% - ${convertToUnit(height.value / 4)})`,
  4831. width: convertToUnit(100 - normalizedBuffer.value, '%'),
  4832. '--v-progress-linear-stream-to': convertToUnit(height.value * (isReversed.value ? 1 : -1))
  4833. }
  4834. }, null), vue.createVNode("div", {
  4835. "class": ['v-progress-linear__background', !isForcedColorsModeActive ? backgroundColorClasses.value : undefined],
  4836. "style": [backgroundColorStyles.value, {
  4837. opacity: parseFloat(props.bgOpacity),
  4838. width: props.stream ? 0 : undefined
  4839. }]
  4840. }, null), vue.createVNode("div", {
  4841. "class": ['v-progress-linear__buffer', !isForcedColorsModeActive ? bufferColorClasses.value : undefined],
  4842. "style": [bufferColorStyles.value, {
  4843. opacity: parseFloat(props.bufferOpacity),
  4844. width: convertToUnit(normalizedBuffer.value, '%')
  4845. }]
  4846. }, null), vue.createVNode(vue.Transition, {
  4847. "name": transition.value
  4848. }, {
  4849. default: () => [!props.indeterminate ? vue.createVNode("div", {
  4850. "class": ['v-progress-linear__determinate', !isForcedColorsModeActive ? barColorClasses.value : undefined],
  4851. "style": [barColorStyles.value, {
  4852. width: convertToUnit(normalizedValue.value, '%')
  4853. }]
  4854. }, null) : vue.createVNode("div", {
  4855. "class": "v-progress-linear__indeterminate"
  4856. }, [['long', 'short'].map(bar => vue.createVNode("div", {
  4857. "key": bar,
  4858. "class": ['v-progress-linear__indeterminate', bar, !isForcedColorsModeActive ? barColorClasses.value : undefined],
  4859. "style": barColorStyles.value
  4860. }, null))])]
  4861. }), slots.default && vue.createVNode("div", {
  4862. "class": "v-progress-linear__content"
  4863. }, [slots.default({
  4864. value: normalizedValue.value,
  4865. buffer: normalizedBuffer.value
  4866. })])]
  4867. }));
  4868. return {};
  4869. }
  4870. });
  4871. // Types
  4872. // Composables
  4873. const makeLoaderProps = propsFactory({
  4874. loading: [Boolean, String]
  4875. }, 'loader');
  4876. function useLoader(props) {
  4877. let name = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : getCurrentInstanceName();
  4878. const loaderClasses = vue.computed(() => ({
  4879. [`${name}--loading`]: props.loading
  4880. }));
  4881. return {
  4882. loaderClasses
  4883. };
  4884. }
  4885. function LoaderSlot(props, _ref) {
  4886. let {
  4887. slots
  4888. } = _ref;
  4889. return vue.createVNode("div", {
  4890. "class": `${props.name}__loader`
  4891. }, [slots.default?.({
  4892. color: props.color,
  4893. isActive: props.active
  4894. }) || vue.createVNode(VProgressLinear, {
  4895. "absolute": props.absolute,
  4896. "active": props.active,
  4897. "color": props.color,
  4898. "height": "2",
  4899. "indeterminate": true
  4900. }, null)]);
  4901. }
  4902. // Utilities
  4903. // Types
  4904. const positionValues = ['static', 'relative', 'fixed', 'absolute', 'sticky'];
  4905. // Composables
  4906. const makePositionProps = propsFactory({
  4907. position: {
  4908. type: String,
  4909. validator: /* istanbul ignore next */v => positionValues.includes(v)
  4910. }
  4911. }, 'position');
  4912. function usePosition(props) {
  4913. let name = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : getCurrentInstanceName();
  4914. const positionClasses = vue.computed(() => {
  4915. return props.position ? `${name}--${props.position}` : undefined;
  4916. });
  4917. return {
  4918. positionClasses
  4919. };
  4920. }
  4921. // Utilities
  4922. // Types
  4923. function useRoute() {
  4924. const vm = getCurrentInstance('useRoute');
  4925. return vue.computed(() => vm?.proxy?.$route);
  4926. }
  4927. function useRouter() {
  4928. return getCurrentInstance('useRouter')?.proxy?.$router;
  4929. }
  4930. function useLink(props, attrs) {
  4931. const RouterLink = vue.resolveDynamicComponent('RouterLink');
  4932. const isLink = vue.computed(() => !!(props.href || props.to));
  4933. const isClickable = vue.computed(() => {
  4934. return isLink?.value || hasEvent(attrs, 'click') || hasEvent(props, 'click');
  4935. });
  4936. if (typeof RouterLink === 'string' || !('useLink' in RouterLink)) {
  4937. const href = vue.toRef(props, 'href');
  4938. return {
  4939. isLink,
  4940. isClickable,
  4941. href,
  4942. linkProps: vue.reactive({
  4943. href
  4944. })
  4945. };
  4946. }
  4947. // vue-router useLink `to` prop needs to be reactive and useLink will crash if undefined
  4948. const linkProps = vue.computed(() => ({
  4949. ...props,
  4950. to: vue.toRef(() => props.to || '')
  4951. }));
  4952. const routerLink = RouterLink.useLink(linkProps.value);
  4953. // Actual link needs to be undefined when to prop is not used
  4954. const link = vue.computed(() => props.to ? routerLink : undefined);
  4955. const route = useRoute();
  4956. const isActive = vue.computed(() => {
  4957. if (!link.value) return false;
  4958. if (!props.exact) return link.value.isActive?.value ?? false;
  4959. if (!route.value) return link.value.isExactActive?.value ?? false;
  4960. return link.value.isExactActive?.value && deepEqual(link.value.route.value.query, route.value.query);
  4961. });
  4962. const href = vue.computed(() => props.to ? link.value?.route.value.href : props.href);
  4963. return {
  4964. isLink,
  4965. isClickable,
  4966. isActive,
  4967. route: link.value?.route,
  4968. navigate: link.value?.navigate,
  4969. href,
  4970. linkProps: vue.reactive({
  4971. href,
  4972. 'aria-current': vue.computed(() => isActive.value ? 'page' : undefined)
  4973. })
  4974. };
  4975. }
  4976. const makeRouterProps = propsFactory({
  4977. href: String,
  4978. replace: Boolean,
  4979. to: [String, Object],
  4980. exact: Boolean
  4981. }, 'router');
  4982. let inTransition = false;
  4983. function useBackButton(router, cb) {
  4984. let popped = false;
  4985. let removeBefore;
  4986. let removeAfter;
  4987. if (IN_BROWSER) {
  4988. vue.nextTick(() => {
  4989. window.addEventListener('popstate', onPopstate);
  4990. removeBefore = router?.beforeEach((to, from, next) => {
  4991. if (!inTransition) {
  4992. setTimeout(() => popped ? cb(next) : next());
  4993. } else {
  4994. popped ? cb(next) : next();
  4995. }
  4996. inTransition = true;
  4997. });
  4998. removeAfter = router?.afterEach(() => {
  4999. inTransition = false;
  5000. });
  5001. });
  5002. vue.onScopeDispose(() => {
  5003. window.removeEventListener('popstate', onPopstate);
  5004. removeBefore?.();
  5005. removeAfter?.();
  5006. });
  5007. }
  5008. function onPopstate(e) {
  5009. if (e.state?.replaced) return;
  5010. popped = true;
  5011. setTimeout(() => popped = false);
  5012. }
  5013. }
  5014. // Utilities
  5015. // Types
  5016. function useSelectLink(link, select) {
  5017. vue.watch(() => link.isActive?.value, isActive => {
  5018. if (link.isLink.value && isActive && select) {
  5019. vue.nextTick(() => {
  5020. select(true);
  5021. });
  5022. }
  5023. }, {
  5024. immediate: true
  5025. });
  5026. }
  5027. // Styles
  5028. // Types
  5029. const stopSymbol = Symbol('rippleStop');
  5030. const DELAY_RIPPLE = 80;
  5031. function transform(el, value) {
  5032. el.style.transform = value;
  5033. el.style.webkitTransform = value;
  5034. }
  5035. function isTouchEvent(e) {
  5036. return e.constructor.name === 'TouchEvent';
  5037. }
  5038. function isKeyboardEvent(e) {
  5039. return e.constructor.name === 'KeyboardEvent';
  5040. }
  5041. const calculate = function (e, el) {
  5042. let value = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {};
  5043. let localX = 0;
  5044. let localY = 0;
  5045. if (!isKeyboardEvent(e)) {
  5046. const offset = el.getBoundingClientRect();
  5047. const target = isTouchEvent(e) ? e.touches[e.touches.length - 1] : e;
  5048. localX = target.clientX - offset.left;
  5049. localY = target.clientY - offset.top;
  5050. }
  5051. let radius = 0;
  5052. let scale = 0.3;
  5053. if (el._ripple?.circle) {
  5054. scale = 0.15;
  5055. radius = el.clientWidth / 2;
  5056. radius = value.center ? radius : radius + Math.sqrt((localX - radius) ** 2 + (localY - radius) ** 2) / 4;
  5057. } else {
  5058. radius = Math.sqrt(el.clientWidth ** 2 + el.clientHeight ** 2) / 2;
  5059. }
  5060. const centerX = `${(el.clientWidth - radius * 2) / 2}px`;
  5061. const centerY = `${(el.clientHeight - radius * 2) / 2}px`;
  5062. const x = value.center ? centerX : `${localX - radius}px`;
  5063. const y = value.center ? centerY : `${localY - radius}px`;
  5064. return {
  5065. radius,
  5066. scale,
  5067. x,
  5068. y,
  5069. centerX,
  5070. centerY
  5071. };
  5072. };
  5073. const ripples = {
  5074. /* eslint-disable max-statements */
  5075. show(e, el) {
  5076. let value = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {};
  5077. if (!el?._ripple?.enabled) {
  5078. return;
  5079. }
  5080. const container = document.createElement('span');
  5081. const animation = document.createElement('span');
  5082. container.appendChild(animation);
  5083. container.className = 'v-ripple__container';
  5084. if (value.class) {
  5085. container.className += ` ${value.class}`;
  5086. }
  5087. const {
  5088. radius,
  5089. scale,
  5090. x,
  5091. y,
  5092. centerX,
  5093. centerY
  5094. } = calculate(e, el, value);
  5095. const size = `${radius * 2}px`;
  5096. animation.className = 'v-ripple__animation';
  5097. animation.style.width = size;
  5098. animation.style.height = size;
  5099. el.appendChild(container);
  5100. const computed = window.getComputedStyle(el);
  5101. if (computed && computed.position === 'static') {
  5102. el.style.position = 'relative';
  5103. el.dataset.previousPosition = 'static';
  5104. }
  5105. animation.classList.add('v-ripple__animation--enter');
  5106. animation.classList.add('v-ripple__animation--visible');
  5107. transform(animation, `translate(${x}, ${y}) scale3d(${scale},${scale},${scale})`);
  5108. animation.dataset.activated = String(performance.now());
  5109. setTimeout(() => {
  5110. animation.classList.remove('v-ripple__animation--enter');
  5111. animation.classList.add('v-ripple__animation--in');
  5112. transform(animation, `translate(${centerX}, ${centerY}) scale3d(1,1,1)`);
  5113. }, 0);
  5114. },
  5115. hide(el) {
  5116. if (!el?._ripple?.enabled) return;
  5117. const ripples = el.getElementsByClassName('v-ripple__animation');
  5118. if (ripples.length === 0) return;
  5119. const animation = ripples[ripples.length - 1];
  5120. if (animation.dataset.isHiding) return;else animation.dataset.isHiding = 'true';
  5121. const diff = performance.now() - Number(animation.dataset.activated);
  5122. const delay = Math.max(250 - diff, 0);
  5123. setTimeout(() => {
  5124. animation.classList.remove('v-ripple__animation--in');
  5125. animation.classList.add('v-ripple__animation--out');
  5126. setTimeout(() => {
  5127. const ripples = el.getElementsByClassName('v-ripple__animation');
  5128. if (ripples.length === 1 && el.dataset.previousPosition) {
  5129. el.style.position = el.dataset.previousPosition;
  5130. delete el.dataset.previousPosition;
  5131. }
  5132. if (animation.parentNode?.parentNode === el) el.removeChild(animation.parentNode);
  5133. }, 300);
  5134. }, delay);
  5135. }
  5136. };
  5137. function isRippleEnabled(value) {
  5138. return typeof value === 'undefined' || !!value;
  5139. }
  5140. function rippleShow(e) {
  5141. const value = {};
  5142. const element = e.currentTarget;
  5143. if (!element?._ripple || element._ripple.touched || e[stopSymbol]) return;
  5144. // Don't allow the event to trigger ripples on any other elements
  5145. e[stopSymbol] = true;
  5146. if (isTouchEvent(e)) {
  5147. element._ripple.touched = true;
  5148. element._ripple.isTouch = true;
  5149. } else {
  5150. // It's possible for touch events to fire
  5151. // as mouse events on Android/iOS, this
  5152. // will skip the event call if it has
  5153. // already been registered as touch
  5154. if (element._ripple.isTouch) return;
  5155. }
  5156. value.center = element._ripple.centered || isKeyboardEvent(e);
  5157. if (element._ripple.class) {
  5158. value.class = element._ripple.class;
  5159. }
  5160. if (isTouchEvent(e)) {
  5161. // already queued that shows or hides the ripple
  5162. if (element._ripple.showTimerCommit) return;
  5163. element._ripple.showTimerCommit = () => {
  5164. ripples.show(e, element, value);
  5165. };
  5166. element._ripple.showTimer = window.setTimeout(() => {
  5167. if (element?._ripple?.showTimerCommit) {
  5168. element._ripple.showTimerCommit();
  5169. element._ripple.showTimerCommit = null;
  5170. }
  5171. }, DELAY_RIPPLE);
  5172. } else {
  5173. ripples.show(e, element, value);
  5174. }
  5175. }
  5176. function rippleStop(e) {
  5177. e[stopSymbol] = true;
  5178. }
  5179. function rippleHide(e) {
  5180. const element = e.currentTarget;
  5181. if (!element?._ripple) return;
  5182. window.clearTimeout(element._ripple.showTimer);
  5183. // The touch interaction occurs before the show timer is triggered.
  5184. // We still want to show ripple effect.
  5185. if (e.type === 'touchend' && element._ripple.showTimerCommit) {
  5186. element._ripple.showTimerCommit();
  5187. element._ripple.showTimerCommit = null;
  5188. // re-queue ripple hiding
  5189. element._ripple.showTimer = window.setTimeout(() => {
  5190. rippleHide(e);
  5191. });
  5192. return;
  5193. }
  5194. window.setTimeout(() => {
  5195. if (element._ripple) {
  5196. element._ripple.touched = false;
  5197. }
  5198. });
  5199. ripples.hide(element);
  5200. }
  5201. function rippleCancelShow(e) {
  5202. const element = e.currentTarget;
  5203. if (!element?._ripple) return;
  5204. if (element._ripple.showTimerCommit) {
  5205. element._ripple.showTimerCommit = null;
  5206. }
  5207. window.clearTimeout(element._ripple.showTimer);
  5208. }
  5209. let keyboardRipple = false;
  5210. function keyboardRippleShow(e) {
  5211. if (!keyboardRipple && (e.keyCode === keyCodes.enter || e.keyCode === keyCodes.space)) {
  5212. keyboardRipple = true;
  5213. rippleShow(e);
  5214. }
  5215. }
  5216. function keyboardRippleHide(e) {
  5217. keyboardRipple = false;
  5218. rippleHide(e);
  5219. }
  5220. function focusRippleHide(e) {
  5221. if (keyboardRipple) {
  5222. keyboardRipple = false;
  5223. rippleHide(e);
  5224. }
  5225. }
  5226. function updateRipple(el, binding, wasEnabled) {
  5227. const {
  5228. value,
  5229. modifiers
  5230. } = binding;
  5231. const enabled = isRippleEnabled(value);
  5232. if (!enabled) {
  5233. ripples.hide(el);
  5234. }
  5235. el._ripple = el._ripple ?? {};
  5236. el._ripple.enabled = enabled;
  5237. el._ripple.centered = modifiers.center;
  5238. el._ripple.circle = modifiers.circle;
  5239. if (isObject(value) && value.class) {
  5240. el._ripple.class = value.class;
  5241. }
  5242. if (enabled && !wasEnabled) {
  5243. if (modifiers.stop) {
  5244. el.addEventListener('touchstart', rippleStop, {
  5245. passive: true
  5246. });
  5247. el.addEventListener('mousedown', rippleStop);
  5248. return;
  5249. }
  5250. el.addEventListener('touchstart', rippleShow, {
  5251. passive: true
  5252. });
  5253. el.addEventListener('touchend', rippleHide, {
  5254. passive: true
  5255. });
  5256. el.addEventListener('touchmove', rippleCancelShow, {
  5257. passive: true
  5258. });
  5259. el.addEventListener('touchcancel', rippleHide);
  5260. el.addEventListener('mousedown', rippleShow);
  5261. el.addEventListener('mouseup', rippleHide);
  5262. el.addEventListener('mouseleave', rippleHide);
  5263. el.addEventListener('keydown', keyboardRippleShow);
  5264. el.addEventListener('keyup', keyboardRippleHide);
  5265. el.addEventListener('blur', focusRippleHide);
  5266. // Anchor tags can be dragged, causes other hides to fail - #1537
  5267. el.addEventListener('dragstart', rippleHide, {
  5268. passive: true
  5269. });
  5270. } else if (!enabled && wasEnabled) {
  5271. removeListeners(el);
  5272. }
  5273. }
  5274. function removeListeners(el) {
  5275. el.removeEventListener('mousedown', rippleShow);
  5276. el.removeEventListener('touchstart', rippleShow);
  5277. el.removeEventListener('touchend', rippleHide);
  5278. el.removeEventListener('touchmove', rippleCancelShow);
  5279. el.removeEventListener('touchcancel', rippleHide);
  5280. el.removeEventListener('mouseup', rippleHide);
  5281. el.removeEventListener('mouseleave', rippleHide);
  5282. el.removeEventListener('keydown', keyboardRippleShow);
  5283. el.removeEventListener('keyup', keyboardRippleHide);
  5284. el.removeEventListener('dragstart', rippleHide);
  5285. el.removeEventListener('blur', focusRippleHide);
  5286. }
  5287. function mounted$4(el, binding) {
  5288. updateRipple(el, binding, false);
  5289. }
  5290. function unmounted$4(el) {
  5291. delete el._ripple;
  5292. removeListeners(el);
  5293. }
  5294. function updated$1(el, binding) {
  5295. if (binding.value === binding.oldValue) {
  5296. return;
  5297. }
  5298. const wasEnabled = isRippleEnabled(binding.oldValue);
  5299. updateRipple(el, binding, wasEnabled);
  5300. }
  5301. const Ripple = {
  5302. mounted: mounted$4,
  5303. unmounted: unmounted$4,
  5304. updated: updated$1
  5305. };
  5306. // Types
  5307. const makeVBtnProps = propsFactory({
  5308. active: {
  5309. type: Boolean,
  5310. default: undefined
  5311. },
  5312. activeColor: String,
  5313. baseColor: String,
  5314. symbol: {
  5315. type: null,
  5316. default: VBtnToggleSymbol
  5317. },
  5318. flat: Boolean,
  5319. icon: [Boolean, String, Function, Object],
  5320. prependIcon: IconValue,
  5321. appendIcon: IconValue,
  5322. block: Boolean,
  5323. readonly: Boolean,
  5324. slim: Boolean,
  5325. stacked: Boolean,
  5326. ripple: {
  5327. type: [Boolean, Object],
  5328. default: true
  5329. },
  5330. text: String,
  5331. ...makeBorderProps(),
  5332. ...makeComponentProps(),
  5333. ...makeDensityProps(),
  5334. ...makeDimensionProps(),
  5335. ...makeElevationProps(),
  5336. ...makeGroupItemProps(),
  5337. ...makeLoaderProps(),
  5338. ...makeLocationProps(),
  5339. ...makePositionProps(),
  5340. ...makeRoundedProps(),
  5341. ...makeRouterProps(),
  5342. ...makeSizeProps(),
  5343. ...makeTagProps({
  5344. tag: 'button'
  5345. }),
  5346. ...makeThemeProps(),
  5347. ...makeVariantProps({
  5348. variant: 'elevated'
  5349. })
  5350. }, 'VBtn');
  5351. const VBtn = genericComponent()({
  5352. name: 'VBtn',
  5353. props: makeVBtnProps(),
  5354. emits: {
  5355. 'group:selected': val => true
  5356. },
  5357. setup(props, _ref) {
  5358. let {
  5359. attrs,
  5360. slots
  5361. } = _ref;
  5362. const {
  5363. themeClasses
  5364. } = provideTheme(props);
  5365. const {
  5366. borderClasses
  5367. } = useBorder(props);
  5368. const {
  5369. densityClasses
  5370. } = useDensity(props);
  5371. const {
  5372. dimensionStyles
  5373. } = useDimension(props);
  5374. const {
  5375. elevationClasses
  5376. } = useElevation(props);
  5377. const {
  5378. loaderClasses
  5379. } = useLoader(props);
  5380. const {
  5381. locationStyles
  5382. } = useLocation(props);
  5383. const {
  5384. positionClasses
  5385. } = usePosition(props);
  5386. const {
  5387. roundedClasses
  5388. } = useRounded(props);
  5389. const {
  5390. sizeClasses,
  5391. sizeStyles
  5392. } = useSize(props);
  5393. const group = useGroupItem(props, props.symbol, false);
  5394. const link = useLink(props, attrs);
  5395. const isActive = vue.computed(() => {
  5396. if (props.active !== undefined) {
  5397. return props.active;
  5398. }
  5399. if (link.isLink.value) {
  5400. return link.isActive?.value;
  5401. }
  5402. return group?.isSelected.value;
  5403. });
  5404. const color = vue.computed(() => isActive.value ? props.activeColor ?? props.color : props.color);
  5405. const variantProps = vue.computed(() => {
  5406. const showColor = group?.isSelected.value && (!link.isLink.value || link.isActive?.value) || !group || link.isActive?.value;
  5407. return {
  5408. color: showColor ? color.value ?? props.baseColor : props.baseColor,
  5409. variant: props.variant
  5410. };
  5411. });
  5412. const {
  5413. colorClasses,
  5414. colorStyles,
  5415. variantClasses
  5416. } = useVariant(variantProps);
  5417. const isDisabled = vue.computed(() => group?.disabled.value || props.disabled);
  5418. const isElevated = vue.computed(() => {
  5419. return props.variant === 'elevated' && !(props.disabled || props.flat || props.border);
  5420. });
  5421. const valueAttr = vue.computed(() => {
  5422. if (props.value === undefined || typeof props.value === 'symbol') return undefined;
  5423. return Object(props.value) === props.value ? JSON.stringify(props.value, null, 0) : props.value;
  5424. });
  5425. function onClick(e) {
  5426. if (isDisabled.value || link.isLink.value && (e.metaKey || e.ctrlKey || e.shiftKey || e.button !== 0 || attrs.target === '_blank')) return;
  5427. link.navigate?.(e);
  5428. group?.toggle();
  5429. }
  5430. useSelectLink(link, group?.select);
  5431. useRender(() => {
  5432. const Tag = link.isLink.value ? 'a' : props.tag;
  5433. const hasPrepend = !!(props.prependIcon || slots.prepend);
  5434. const hasAppend = !!(props.appendIcon || slots.append);
  5435. const hasIcon = !!(props.icon && props.icon !== true);
  5436. return vue.withDirectives(vue.createVNode(Tag, vue.mergeProps({
  5437. "type": Tag === 'a' ? undefined : 'button',
  5438. "class": ['v-btn', group?.selectedClass.value, {
  5439. 'v-btn--active': isActive.value,
  5440. 'v-btn--block': props.block,
  5441. 'v-btn--disabled': isDisabled.value,
  5442. 'v-btn--elevated': isElevated.value,
  5443. 'v-btn--flat': props.flat,
  5444. 'v-btn--icon': !!props.icon,
  5445. 'v-btn--loading': props.loading,
  5446. 'v-btn--readonly': props.readonly,
  5447. 'v-btn--slim': props.slim,
  5448. 'v-btn--stacked': props.stacked
  5449. }, themeClasses.value, borderClasses.value, colorClasses.value, densityClasses.value, elevationClasses.value, loaderClasses.value, positionClasses.value, roundedClasses.value, sizeClasses.value, variantClasses.value, props.class],
  5450. "style": [colorStyles.value, dimensionStyles.value, locationStyles.value, sizeStyles.value, props.style],
  5451. "aria-busy": props.loading ? true : undefined,
  5452. "disabled": isDisabled.value || undefined,
  5453. "tabindex": props.loading || props.readonly ? -1 : undefined,
  5454. "onClick": onClick,
  5455. "value": valueAttr.value
  5456. }, link.linkProps), {
  5457. default: () => [genOverlays(true, 'v-btn'), !props.icon && hasPrepend && vue.createVNode("span", {
  5458. "key": "prepend",
  5459. "class": "v-btn__prepend"
  5460. }, [!slots.prepend ? vue.createVNode(VIcon, {
  5461. "key": "prepend-icon",
  5462. "icon": props.prependIcon
  5463. }, null) : vue.createVNode(VDefaultsProvider, {
  5464. "key": "prepend-defaults",
  5465. "disabled": !props.prependIcon,
  5466. "defaults": {
  5467. VIcon: {
  5468. icon: props.prependIcon
  5469. }
  5470. }
  5471. }, slots.prepend)]), vue.createVNode("span", {
  5472. "class": "v-btn__content",
  5473. "data-no-activator": ""
  5474. }, [!slots.default && hasIcon ? vue.createVNode(VIcon, {
  5475. "key": "content-icon",
  5476. "icon": props.icon
  5477. }, null) : vue.createVNode(VDefaultsProvider, {
  5478. "key": "content-defaults",
  5479. "disabled": !hasIcon,
  5480. "defaults": {
  5481. VIcon: {
  5482. icon: props.icon
  5483. }
  5484. }
  5485. }, {
  5486. default: () => [slots.default?.() ?? props.text]
  5487. })]), !props.icon && hasAppend && vue.createVNode("span", {
  5488. "key": "append",
  5489. "class": "v-btn__append"
  5490. }, [!slots.append ? vue.createVNode(VIcon, {
  5491. "key": "append-icon",
  5492. "icon": props.appendIcon
  5493. }, null) : vue.createVNode(VDefaultsProvider, {
  5494. "key": "append-defaults",
  5495. "disabled": !props.appendIcon,
  5496. "defaults": {
  5497. VIcon: {
  5498. icon: props.appendIcon
  5499. }
  5500. }
  5501. }, slots.append)]), !!props.loading && vue.createVNode("span", {
  5502. "key": "loader",
  5503. "class": "v-btn__loader"
  5504. }, [slots.loader?.() ?? vue.createVNode(VProgressCircular, {
  5505. "color": typeof props.loading === 'boolean' ? undefined : props.loading,
  5506. "indeterminate": true,
  5507. "width": "2"
  5508. }, null)])]
  5509. }), [[Ripple, !isDisabled.value && props.ripple, '', {
  5510. center: !!props.icon
  5511. }]]);
  5512. });
  5513. return {
  5514. group
  5515. };
  5516. }
  5517. });
  5518. // Types
  5519. const makeVAppBarNavIconProps = propsFactory({
  5520. ...makeVBtnProps({
  5521. icon: '$menu',
  5522. variant: 'text'
  5523. })
  5524. }, 'VAppBarNavIcon');
  5525. const VAppBarNavIcon = genericComponent()({
  5526. name: 'VAppBarNavIcon',
  5527. props: makeVAppBarNavIconProps(),
  5528. setup(props, _ref) {
  5529. let {
  5530. slots
  5531. } = _ref;
  5532. useRender(() => vue.createVNode(VBtn, vue.mergeProps(props, {
  5533. "class": ['v-app-bar-nav-icon']
  5534. }), slots));
  5535. return {};
  5536. }
  5537. });
  5538. // Types
  5539. const VAppBarTitle = genericComponent()({
  5540. name: 'VAppBarTitle',
  5541. props: makeVToolbarTitleProps(),
  5542. setup(props, _ref) {
  5543. let {
  5544. slots
  5545. } = _ref;
  5546. useRender(() => vue.createVNode(VToolbarTitle, vue.mergeProps(props, {
  5547. "class": "v-app-bar-title"
  5548. }), slots));
  5549. return {};
  5550. }
  5551. });
  5552. // Utilities
  5553. const VAlertTitle = createSimpleFunctional('v-alert-title');
  5554. // Types
  5555. const allowedTypes = ['success', 'info', 'warning', 'error'];
  5556. const makeVAlertProps = propsFactory({
  5557. border: {
  5558. type: [Boolean, String],
  5559. validator: val => {
  5560. return typeof val === 'boolean' || ['top', 'end', 'bottom', 'start'].includes(val);
  5561. }
  5562. },
  5563. borderColor: String,
  5564. closable: Boolean,
  5565. closeIcon: {
  5566. type: IconValue,
  5567. default: '$close'
  5568. },
  5569. closeLabel: {
  5570. type: String,
  5571. default: '$vuetify.close'
  5572. },
  5573. icon: {
  5574. type: [Boolean, String, Function, Object],
  5575. default: null
  5576. },
  5577. modelValue: {
  5578. type: Boolean,
  5579. default: true
  5580. },
  5581. prominent: Boolean,
  5582. title: String,
  5583. text: String,
  5584. type: {
  5585. type: String,
  5586. validator: val => allowedTypes.includes(val)
  5587. },
  5588. ...makeComponentProps(),
  5589. ...makeDensityProps(),
  5590. ...makeDimensionProps(),
  5591. ...makeElevationProps(),
  5592. ...makeLocationProps(),
  5593. ...makePositionProps(),
  5594. ...makeRoundedProps(),
  5595. ...makeTagProps(),
  5596. ...makeThemeProps(),
  5597. ...makeVariantProps({
  5598. variant: 'flat'
  5599. })
  5600. }, 'VAlert');
  5601. const VAlert = genericComponent()({
  5602. name: 'VAlert',
  5603. props: makeVAlertProps(),
  5604. emits: {
  5605. 'click:close': e => true,
  5606. 'update:modelValue': value => true
  5607. },
  5608. setup(props, _ref) {
  5609. let {
  5610. emit,
  5611. slots
  5612. } = _ref;
  5613. const isActive = useProxiedModel(props, 'modelValue');
  5614. const icon = vue.computed(() => {
  5615. if (props.icon === false) return undefined;
  5616. if (!props.type) return props.icon;
  5617. return props.icon ?? `$${props.type}`;
  5618. });
  5619. const variantProps = vue.computed(() => ({
  5620. color: props.color ?? props.type,
  5621. variant: props.variant
  5622. }));
  5623. const {
  5624. themeClasses
  5625. } = provideTheme(props);
  5626. const {
  5627. colorClasses,
  5628. colorStyles,
  5629. variantClasses
  5630. } = useVariant(variantProps);
  5631. const {
  5632. densityClasses
  5633. } = useDensity(props);
  5634. const {
  5635. dimensionStyles
  5636. } = useDimension(props);
  5637. const {
  5638. elevationClasses
  5639. } = useElevation(props);
  5640. const {
  5641. locationStyles
  5642. } = useLocation(props);
  5643. const {
  5644. positionClasses
  5645. } = usePosition(props);
  5646. const {
  5647. roundedClasses
  5648. } = useRounded(props);
  5649. const {
  5650. textColorClasses,
  5651. textColorStyles
  5652. } = useTextColor(vue.toRef(props, 'borderColor'));
  5653. const {
  5654. t
  5655. } = useLocale();
  5656. const closeProps = vue.computed(() => ({
  5657. 'aria-label': t(props.closeLabel),
  5658. onClick(e) {
  5659. isActive.value = false;
  5660. emit('click:close', e);
  5661. }
  5662. }));
  5663. return () => {
  5664. const hasPrepend = !!(slots.prepend || icon.value);
  5665. const hasTitle = !!(slots.title || props.title);
  5666. const hasClose = !!(slots.close || props.closable);
  5667. return isActive.value && vue.createVNode(props.tag, {
  5668. "class": ['v-alert', props.border && {
  5669. 'v-alert--border': !!props.border,
  5670. [`v-alert--border-${props.border === true ? 'start' : props.border}`]: true
  5671. }, {
  5672. 'v-alert--prominent': props.prominent
  5673. }, themeClasses.value, colorClasses.value, densityClasses.value, elevationClasses.value, positionClasses.value, roundedClasses.value, variantClasses.value, props.class],
  5674. "style": [colorStyles.value, dimensionStyles.value, locationStyles.value, props.style],
  5675. "role": "alert"
  5676. }, {
  5677. default: () => [genOverlays(false, 'v-alert'), props.border && vue.createVNode("div", {
  5678. "key": "border",
  5679. "class": ['v-alert__border', textColorClasses.value],
  5680. "style": textColorStyles.value
  5681. }, null), hasPrepend && vue.createVNode("div", {
  5682. "key": "prepend",
  5683. "class": "v-alert__prepend"
  5684. }, [!slots.prepend ? vue.createVNode(VIcon, {
  5685. "key": "prepend-icon",
  5686. "density": props.density,
  5687. "icon": icon.value,
  5688. "size": props.prominent ? 44 : 28
  5689. }, null) : vue.createVNode(VDefaultsProvider, {
  5690. "key": "prepend-defaults",
  5691. "disabled": !icon.value,
  5692. "defaults": {
  5693. VIcon: {
  5694. density: props.density,
  5695. icon: icon.value,
  5696. size: props.prominent ? 44 : 28
  5697. }
  5698. }
  5699. }, slots.prepend)]), vue.createVNode("div", {
  5700. "class": "v-alert__content"
  5701. }, [hasTitle && vue.createVNode(VAlertTitle, {
  5702. "key": "title"
  5703. }, {
  5704. default: () => [slots.title?.() ?? props.title]
  5705. }), slots.text?.() ?? props.text, slots.default?.()]), slots.append && vue.createVNode("div", {
  5706. "key": "append",
  5707. "class": "v-alert__append"
  5708. }, [slots.append()]), hasClose && vue.createVNode("div", {
  5709. "key": "close",
  5710. "class": "v-alert__close"
  5711. }, [!slots.close ? vue.createVNode(VBtn, vue.mergeProps({
  5712. "key": "close-btn",
  5713. "icon": props.closeIcon,
  5714. "size": "x-small",
  5715. "variant": "text"
  5716. }, closeProps.value), null) : vue.createVNode(VDefaultsProvider, {
  5717. "key": "close-defaults",
  5718. "defaults": {
  5719. VBtn: {
  5720. icon: props.closeIcon,
  5721. size: 'x-small',
  5722. variant: 'text'
  5723. }
  5724. }
  5725. }, {
  5726. default: () => [slots.close?.({
  5727. props: closeProps.value
  5728. })]
  5729. })])]
  5730. });
  5731. };
  5732. }
  5733. });
  5734. const makeVAvatarProps = propsFactory({
  5735. start: Boolean,
  5736. end: Boolean,
  5737. icon: IconValue,
  5738. image: String,
  5739. text: String,
  5740. ...makeBorderProps(),
  5741. ...makeComponentProps(),
  5742. ...makeDensityProps(),
  5743. ...makeRoundedProps(),
  5744. ...makeSizeProps(),
  5745. ...makeTagProps(),
  5746. ...makeThemeProps(),
  5747. ...makeVariantProps({
  5748. variant: 'flat'
  5749. })
  5750. }, 'VAvatar');
  5751. const VAvatar = genericComponent()({
  5752. name: 'VAvatar',
  5753. props: makeVAvatarProps(),
  5754. setup(props, _ref) {
  5755. let {
  5756. slots
  5757. } = _ref;
  5758. const {
  5759. themeClasses
  5760. } = provideTheme(props);
  5761. const {
  5762. borderClasses
  5763. } = useBorder(props);
  5764. const {
  5765. colorClasses,
  5766. colorStyles,
  5767. variantClasses
  5768. } = useVariant(props);
  5769. const {
  5770. densityClasses
  5771. } = useDensity(props);
  5772. const {
  5773. roundedClasses
  5774. } = useRounded(props);
  5775. const {
  5776. sizeClasses,
  5777. sizeStyles
  5778. } = useSize(props);
  5779. useRender(() => vue.createVNode(props.tag, {
  5780. "class": ['v-avatar', {
  5781. 'v-avatar--start': props.start,
  5782. 'v-avatar--end': props.end
  5783. }, themeClasses.value, borderClasses.value, colorClasses.value, densityClasses.value, roundedClasses.value, sizeClasses.value, variantClasses.value, props.class],
  5784. "style": [colorStyles.value, sizeStyles.value, props.style]
  5785. }, {
  5786. default: () => [!slots.default ? props.image ? vue.createVNode(VImg, {
  5787. "key": "image",
  5788. "src": props.image,
  5789. "alt": "",
  5790. "cover": true
  5791. }, null) : props.icon ? vue.createVNode(VIcon, {
  5792. "key": "icon",
  5793. "icon": props.icon
  5794. }, null) : props.text : vue.createVNode(VDefaultsProvider, {
  5795. "key": "content-defaults",
  5796. "defaults": {
  5797. VImg: {
  5798. cover: true,
  5799. src: props.image
  5800. },
  5801. VIcon: {
  5802. icon: props.icon
  5803. }
  5804. }
  5805. }, {
  5806. default: () => [slots.default()]
  5807. }), genOverlays(false, 'v-avatar')]
  5808. }));
  5809. return {};
  5810. }
  5811. });
  5812. const makeVLabelProps = propsFactory({
  5813. text: String,
  5814. onClick: EventProp(),
  5815. ...makeComponentProps(),
  5816. ...makeThemeProps()
  5817. }, 'VLabel');
  5818. const VLabel = genericComponent()({
  5819. name: 'VLabel',
  5820. props: makeVLabelProps(),
  5821. setup(props, _ref) {
  5822. let {
  5823. slots
  5824. } = _ref;
  5825. useRender(() => vue.createVNode("label", {
  5826. "class": ['v-label', {
  5827. 'v-label--clickable': !!props.onClick
  5828. }, props.class],
  5829. "style": props.style,
  5830. "onClick": props.onClick
  5831. }, [props.text, slots.default?.()]));
  5832. return {};
  5833. }
  5834. });
  5835. // Types
  5836. const VSelectionControlGroupSymbol = Symbol.for('vuetify:selection-control-group');
  5837. const makeSelectionControlGroupProps = propsFactory({
  5838. color: String,
  5839. disabled: {
  5840. type: Boolean,
  5841. default: null
  5842. },
  5843. defaultsTarget: String,
  5844. error: Boolean,
  5845. id: String,
  5846. inline: Boolean,
  5847. falseIcon: IconValue,
  5848. trueIcon: IconValue,
  5849. ripple: {
  5850. type: [Boolean, Object],
  5851. default: true
  5852. },
  5853. multiple: {
  5854. type: Boolean,
  5855. default: null
  5856. },
  5857. name: String,
  5858. readonly: {
  5859. type: Boolean,
  5860. default: null
  5861. },
  5862. modelValue: null,
  5863. type: String,
  5864. valueComparator: {
  5865. type: Function,
  5866. default: deepEqual
  5867. },
  5868. ...makeComponentProps(),
  5869. ...makeDensityProps(),
  5870. ...makeThemeProps()
  5871. }, 'SelectionControlGroup');
  5872. const makeVSelectionControlGroupProps = propsFactory({
  5873. ...makeSelectionControlGroupProps({
  5874. defaultsTarget: 'VSelectionControl'
  5875. })
  5876. }, 'VSelectionControlGroup');
  5877. const VSelectionControlGroup = genericComponent()({
  5878. name: 'VSelectionControlGroup',
  5879. props: makeVSelectionControlGroupProps(),
  5880. emits: {
  5881. 'update:modelValue': value => true
  5882. },
  5883. setup(props, _ref) {
  5884. let {
  5885. slots
  5886. } = _ref;
  5887. const modelValue = useProxiedModel(props, 'modelValue');
  5888. const uid = getUid();
  5889. const id = vue.computed(() => props.id || `v-selection-control-group-${uid}`);
  5890. const name = vue.computed(() => props.name || id.value);
  5891. const updateHandlers = new Set();
  5892. vue.provide(VSelectionControlGroupSymbol, {
  5893. modelValue,
  5894. forceUpdate: () => {
  5895. updateHandlers.forEach(fn => fn());
  5896. },
  5897. onForceUpdate: cb => {
  5898. updateHandlers.add(cb);
  5899. vue.onScopeDispose(() => {
  5900. updateHandlers.delete(cb);
  5901. });
  5902. }
  5903. });
  5904. provideDefaults({
  5905. [props.defaultsTarget]: {
  5906. color: vue.toRef(props, 'color'),
  5907. disabled: vue.toRef(props, 'disabled'),
  5908. density: vue.toRef(props, 'density'),
  5909. error: vue.toRef(props, 'error'),
  5910. inline: vue.toRef(props, 'inline'),
  5911. modelValue,
  5912. multiple: vue.computed(() => !!props.multiple || props.multiple == null && Array.isArray(modelValue.value)),
  5913. name,
  5914. falseIcon: vue.toRef(props, 'falseIcon'),
  5915. trueIcon: vue.toRef(props, 'trueIcon'),
  5916. readonly: vue.toRef(props, 'readonly'),
  5917. ripple: vue.toRef(props, 'ripple'),
  5918. type: vue.toRef(props, 'type'),
  5919. valueComparator: vue.toRef(props, 'valueComparator')
  5920. }
  5921. });
  5922. useRender(() => vue.createVNode("div", {
  5923. "class": ['v-selection-control-group', {
  5924. 'v-selection-control-group--inline': props.inline
  5925. }, props.class],
  5926. "style": props.style,
  5927. "role": props.type === 'radio' ? 'radiogroup' : undefined
  5928. }, [slots.default?.()]));
  5929. return {};
  5930. }
  5931. });
  5932. // Types
  5933. const makeVSelectionControlProps = propsFactory({
  5934. label: String,
  5935. baseColor: String,
  5936. trueValue: null,
  5937. falseValue: null,
  5938. value: null,
  5939. ...makeComponentProps(),
  5940. ...makeSelectionControlGroupProps()
  5941. }, 'VSelectionControl');
  5942. function useSelectionControl(props) {
  5943. const group = vue.inject(VSelectionControlGroupSymbol, undefined);
  5944. const {
  5945. densityClasses
  5946. } = useDensity(props);
  5947. const modelValue = useProxiedModel(props, 'modelValue');
  5948. const trueValue = vue.computed(() => props.trueValue !== undefined ? props.trueValue : props.value !== undefined ? props.value : true);
  5949. const falseValue = vue.computed(() => props.falseValue !== undefined ? props.falseValue : false);
  5950. const isMultiple = vue.computed(() => !!props.multiple || props.multiple == null && Array.isArray(modelValue.value));
  5951. const model = vue.computed({
  5952. get() {
  5953. const val = group ? group.modelValue.value : modelValue.value;
  5954. return isMultiple.value ? wrapInArray(val).some(v => props.valueComparator(v, trueValue.value)) : props.valueComparator(val, trueValue.value);
  5955. },
  5956. set(val) {
  5957. if (props.readonly) return;
  5958. const currentValue = val ? trueValue.value : falseValue.value;
  5959. let newVal = currentValue;
  5960. if (isMultiple.value) {
  5961. newVal = val ? [...wrapInArray(modelValue.value), currentValue] : wrapInArray(modelValue.value).filter(item => !props.valueComparator(item, trueValue.value));
  5962. }
  5963. if (group) {
  5964. group.modelValue.value = newVal;
  5965. } else {
  5966. modelValue.value = newVal;
  5967. }
  5968. }
  5969. });
  5970. const {
  5971. textColorClasses,
  5972. textColorStyles
  5973. } = useTextColor(vue.computed(() => {
  5974. if (props.error || props.disabled) return undefined;
  5975. return model.value ? props.color : props.baseColor;
  5976. }));
  5977. const {
  5978. backgroundColorClasses,
  5979. backgroundColorStyles
  5980. } = useBackgroundColor(vue.computed(() => {
  5981. return model.value && !props.error && !props.disabled ? props.color : props.baseColor;
  5982. }));
  5983. const icon = vue.computed(() => model.value ? props.trueIcon : props.falseIcon);
  5984. return {
  5985. group,
  5986. densityClasses,
  5987. trueValue,
  5988. falseValue,
  5989. model,
  5990. textColorClasses,
  5991. textColorStyles,
  5992. backgroundColorClasses,
  5993. backgroundColorStyles,
  5994. icon
  5995. };
  5996. }
  5997. const VSelectionControl = genericComponent()({
  5998. name: 'VSelectionControl',
  5999. directives: {
  6000. Ripple
  6001. },
  6002. inheritAttrs: false,
  6003. props: makeVSelectionControlProps(),
  6004. emits: {
  6005. 'update:modelValue': value => true
  6006. },
  6007. setup(props, _ref) {
  6008. let {
  6009. attrs,
  6010. slots
  6011. } = _ref;
  6012. const {
  6013. group,
  6014. densityClasses,
  6015. icon,
  6016. model,
  6017. textColorClasses,
  6018. textColorStyles,
  6019. backgroundColorClasses,
  6020. backgroundColorStyles,
  6021. trueValue
  6022. } = useSelectionControl(props);
  6023. const uid = getUid();
  6024. const isFocused = vue.shallowRef(false);
  6025. const isFocusVisible = vue.shallowRef(false);
  6026. const input = vue.ref();
  6027. const id = vue.computed(() => props.id || `input-${uid}`);
  6028. const isInteractive = vue.computed(() => !props.disabled && !props.readonly);
  6029. group?.onForceUpdate(() => {
  6030. if (input.value) {
  6031. input.value.checked = model.value;
  6032. }
  6033. });
  6034. function onFocus(e) {
  6035. if (!isInteractive.value) return;
  6036. isFocused.value = true;
  6037. if (matchesSelector(e.target, ':focus-visible') !== false) {
  6038. isFocusVisible.value = true;
  6039. }
  6040. }
  6041. function onBlur() {
  6042. isFocused.value = false;
  6043. isFocusVisible.value = false;
  6044. }
  6045. function onClickLabel(e) {
  6046. e.stopPropagation();
  6047. }
  6048. function onInput(e) {
  6049. if (!isInteractive.value) {
  6050. if (input.value) {
  6051. // model value is not updated when input is not interactive
  6052. // but the internal checked state of the input is still updated,
  6053. // so here it's value is restored
  6054. input.value.checked = model.value;
  6055. }
  6056. return;
  6057. }
  6058. if (props.readonly && group) {
  6059. vue.nextTick(() => group.forceUpdate());
  6060. }
  6061. model.value = e.target.checked;
  6062. }
  6063. useRender(() => {
  6064. const label = slots.label ? slots.label({
  6065. label: props.label,
  6066. props: {
  6067. for: id.value
  6068. }
  6069. }) : props.label;
  6070. const [rootAttrs, inputAttrs] = filterInputAttrs(attrs);
  6071. const inputNode = vue.createVNode("input", vue.mergeProps({
  6072. "ref": input,
  6073. "checked": model.value,
  6074. "disabled": !!props.disabled,
  6075. "id": id.value,
  6076. "onBlur": onBlur,
  6077. "onFocus": onFocus,
  6078. "onInput": onInput,
  6079. "aria-disabled": !!props.disabled,
  6080. "aria-label": props.label,
  6081. "type": props.type,
  6082. "value": trueValue.value,
  6083. "name": props.name,
  6084. "aria-checked": props.type === 'checkbox' ? model.value : undefined
  6085. }, inputAttrs), null);
  6086. return vue.createVNode("div", vue.mergeProps({
  6087. "class": ['v-selection-control', {
  6088. 'v-selection-control--dirty': model.value,
  6089. 'v-selection-control--disabled': props.disabled,
  6090. 'v-selection-control--error': props.error,
  6091. 'v-selection-control--focused': isFocused.value,
  6092. 'v-selection-control--focus-visible': isFocusVisible.value,
  6093. 'v-selection-control--inline': props.inline
  6094. }, densityClasses.value, props.class]
  6095. }, rootAttrs, {
  6096. "style": props.style
  6097. }), [vue.createVNode("div", {
  6098. "class": ['v-selection-control__wrapper', textColorClasses.value],
  6099. "style": textColorStyles.value
  6100. }, [slots.default?.({
  6101. backgroundColorClasses,
  6102. backgroundColorStyles
  6103. }), vue.withDirectives(vue.createVNode("div", {
  6104. "class": ['v-selection-control__input']
  6105. }, [slots.input?.({
  6106. model,
  6107. textColorClasses,
  6108. textColorStyles,
  6109. backgroundColorClasses,
  6110. backgroundColorStyles,
  6111. inputNode,
  6112. icon: icon.value,
  6113. props: {
  6114. onFocus,
  6115. onBlur,
  6116. id: id.value
  6117. }
  6118. }) ?? vue.createVNode(vue.Fragment, null, [icon.value && vue.createVNode(VIcon, {
  6119. "key": "icon",
  6120. "icon": icon.value
  6121. }, null), inputNode])]), [[vue.resolveDirective("ripple"), props.ripple && [!props.disabled && !props.readonly, null, ['center', 'circle']]]])]), label && vue.createVNode(VLabel, {
  6122. "for": id.value,
  6123. "onClick": onClickLabel
  6124. }, {
  6125. default: () => [label]
  6126. })]);
  6127. });
  6128. return {
  6129. isFocused,
  6130. input
  6131. };
  6132. }
  6133. });
  6134. // Types
  6135. const makeVCheckboxBtnProps = propsFactory({
  6136. indeterminate: Boolean,
  6137. indeterminateIcon: {
  6138. type: IconValue,
  6139. default: '$checkboxIndeterminate'
  6140. },
  6141. ...makeVSelectionControlProps({
  6142. falseIcon: '$checkboxOff',
  6143. trueIcon: '$checkboxOn'
  6144. })
  6145. }, 'VCheckboxBtn');
  6146. const VCheckboxBtn = genericComponent()({
  6147. name: 'VCheckboxBtn',
  6148. props: makeVCheckboxBtnProps(),
  6149. emits: {
  6150. 'update:modelValue': value => true,
  6151. 'update:indeterminate': value => true
  6152. },
  6153. setup(props, _ref) {
  6154. let {
  6155. slots
  6156. } = _ref;
  6157. const indeterminate = useProxiedModel(props, 'indeterminate');
  6158. const model = useProxiedModel(props, 'modelValue');
  6159. function onChange(v) {
  6160. if (indeterminate.value) {
  6161. indeterminate.value = false;
  6162. }
  6163. }
  6164. const falseIcon = vue.computed(() => {
  6165. return indeterminate.value ? props.indeterminateIcon : props.falseIcon;
  6166. });
  6167. const trueIcon = vue.computed(() => {
  6168. return indeterminate.value ? props.indeterminateIcon : props.trueIcon;
  6169. });
  6170. useRender(() => {
  6171. const controlProps = omit(VSelectionControl.filterProps(props), ['modelValue']);
  6172. return vue.createVNode(VSelectionControl, vue.mergeProps(controlProps, {
  6173. "modelValue": model.value,
  6174. "onUpdate:modelValue": [$event => model.value = $event, onChange],
  6175. "class": ['v-checkbox-btn', props.class],
  6176. "style": props.style,
  6177. "type": "checkbox",
  6178. "falseIcon": falseIcon.value,
  6179. "trueIcon": trueIcon.value,
  6180. "aria-checked": indeterminate.value ? 'mixed' : undefined
  6181. }), slots);
  6182. });
  6183. return {};
  6184. }
  6185. });
  6186. // Types
  6187. function useInputIcon(props) {
  6188. const {
  6189. t
  6190. } = useLocale();
  6191. function InputIcon(_ref) {
  6192. let {
  6193. name
  6194. } = _ref;
  6195. const localeKey = {
  6196. prepend: 'prependAction',
  6197. prependInner: 'prependAction',
  6198. append: 'appendAction',
  6199. appendInner: 'appendAction',
  6200. clear: 'clear'
  6201. }[name];
  6202. const listener = props[`onClick:${name}`];
  6203. const label = listener && localeKey ? t(`$vuetify.input.${localeKey}`, props.label ?? '') : undefined;
  6204. return vue.createVNode(VIcon, {
  6205. "icon": props[`${name}Icon`],
  6206. "aria-label": label,
  6207. "onClick": listener
  6208. }, null);
  6209. }
  6210. return {
  6211. InputIcon
  6212. };
  6213. }
  6214. // Types
  6215. const makeVMessagesProps = propsFactory({
  6216. active: Boolean,
  6217. color: String,
  6218. messages: {
  6219. type: [Array, String],
  6220. default: () => []
  6221. },
  6222. ...makeComponentProps(),
  6223. ...makeTransitionProps({
  6224. transition: {
  6225. component: VSlideYTransition,
  6226. leaveAbsolute: true,
  6227. group: true
  6228. }
  6229. })
  6230. }, 'VMessages');
  6231. const VMessages = genericComponent()({
  6232. name: 'VMessages',
  6233. props: makeVMessagesProps(),
  6234. setup(props, _ref) {
  6235. let {
  6236. slots
  6237. } = _ref;
  6238. const messages = vue.computed(() => wrapInArray(props.messages));
  6239. const {
  6240. textColorClasses,
  6241. textColorStyles
  6242. } = useTextColor(vue.computed(() => props.color));
  6243. useRender(() => vue.createVNode(MaybeTransition, {
  6244. "transition": props.transition,
  6245. "tag": "div",
  6246. "class": ['v-messages', textColorClasses.value, props.class],
  6247. "style": [textColorStyles.value, props.style],
  6248. "role": "alert",
  6249. "aria-live": "polite"
  6250. }, {
  6251. default: () => [props.active && messages.value.map((message, i) => vue.createVNode("div", {
  6252. "class": "v-messages__message",
  6253. "key": `${i}-${messages.value}`
  6254. }, [slots.message ? slots.message({
  6255. message
  6256. }) : message]))]
  6257. }));
  6258. return {};
  6259. }
  6260. });
  6261. // Composables
  6262. // Types
  6263. // Composables
  6264. const makeFocusProps = propsFactory({
  6265. focused: Boolean,
  6266. 'onUpdate:focused': EventProp()
  6267. }, 'focus');
  6268. function useFocus(props) {
  6269. let name = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : getCurrentInstanceName();
  6270. const isFocused = useProxiedModel(props, 'focused');
  6271. const focusClasses = vue.computed(() => {
  6272. return {
  6273. [`${name}--focused`]: isFocused.value
  6274. };
  6275. });
  6276. function focus() {
  6277. isFocused.value = true;
  6278. }
  6279. function blur() {
  6280. isFocused.value = false;
  6281. }
  6282. return {
  6283. focusClasses,
  6284. isFocused,
  6285. focus,
  6286. blur
  6287. };
  6288. }
  6289. // Composables
  6290. // Types
  6291. const FormKey = Symbol.for('vuetify:form');
  6292. const makeFormProps = propsFactory({
  6293. disabled: Boolean,
  6294. fastFail: Boolean,
  6295. readonly: Boolean,
  6296. modelValue: {
  6297. type: Boolean,
  6298. default: null
  6299. },
  6300. validateOn: {
  6301. type: String,
  6302. default: 'input'
  6303. }
  6304. }, 'form');
  6305. function createForm(props) {
  6306. const model = useProxiedModel(props, 'modelValue');
  6307. const isDisabled = vue.computed(() => props.disabled);
  6308. const isReadonly = vue.computed(() => props.readonly);
  6309. const isValidating = vue.shallowRef(false);
  6310. const items = vue.ref([]);
  6311. const errors = vue.ref([]);
  6312. async function validate() {
  6313. const results = [];
  6314. let valid = true;
  6315. errors.value = [];
  6316. isValidating.value = true;
  6317. for (const item of items.value) {
  6318. const itemErrorMessages = await item.validate();
  6319. if (itemErrorMessages.length > 0) {
  6320. valid = false;
  6321. results.push({
  6322. id: item.id,
  6323. errorMessages: itemErrorMessages
  6324. });
  6325. }
  6326. if (!valid && props.fastFail) break;
  6327. }
  6328. errors.value = results;
  6329. isValidating.value = false;
  6330. return {
  6331. valid,
  6332. errors: errors.value
  6333. };
  6334. }
  6335. function reset() {
  6336. items.value.forEach(item => item.reset());
  6337. }
  6338. function resetValidation() {
  6339. items.value.forEach(item => item.resetValidation());
  6340. }
  6341. vue.watch(items, () => {
  6342. let valid = 0;
  6343. let invalid = 0;
  6344. const results = [];
  6345. for (const item of items.value) {
  6346. if (item.isValid === false) {
  6347. invalid++;
  6348. results.push({
  6349. id: item.id,
  6350. errorMessages: item.errorMessages
  6351. });
  6352. } else if (item.isValid === true) valid++;
  6353. }
  6354. errors.value = results;
  6355. model.value = invalid > 0 ? false : valid === items.value.length ? true : null;
  6356. }, {
  6357. deep: true,
  6358. flush: 'post'
  6359. });
  6360. vue.provide(FormKey, {
  6361. register: _ref => {
  6362. let {
  6363. id,
  6364. vm,
  6365. validate,
  6366. reset,
  6367. resetValidation
  6368. } = _ref;
  6369. if (items.value.some(item => item.id === id)) {
  6370. consoleWarn(`Duplicate input name "${id}"`);
  6371. }
  6372. items.value.push({
  6373. id,
  6374. validate,
  6375. reset,
  6376. resetValidation,
  6377. vm: vue.markRaw(vm),
  6378. isValid: null,
  6379. errorMessages: []
  6380. });
  6381. },
  6382. unregister: id => {
  6383. items.value = items.value.filter(item => {
  6384. return item.id !== id;
  6385. });
  6386. },
  6387. update: (id, isValid, errorMessages) => {
  6388. const found = items.value.find(item => item.id === id);
  6389. if (!found) return;
  6390. found.isValid = isValid;
  6391. found.errorMessages = errorMessages;
  6392. },
  6393. isDisabled,
  6394. isReadonly,
  6395. isValidating,
  6396. isValid: model,
  6397. items,
  6398. validateOn: vue.toRef(props, 'validateOn')
  6399. });
  6400. return {
  6401. errors,
  6402. isDisabled,
  6403. isReadonly,
  6404. isValidating,
  6405. isValid: model,
  6406. items,
  6407. validate,
  6408. reset,
  6409. resetValidation
  6410. };
  6411. }
  6412. function useForm(props) {
  6413. const form = vue.inject(FormKey, null);
  6414. return {
  6415. ...form,
  6416. isReadonly: vue.computed(() => !!(props?.readonly ?? form?.isReadonly.value)),
  6417. isDisabled: vue.computed(() => !!(props?.disabled ?? form?.isDisabled.value))
  6418. };
  6419. }
  6420. // Composables
  6421. // Types
  6422. const makeValidationProps = propsFactory({
  6423. disabled: {
  6424. type: Boolean,
  6425. default: null
  6426. },
  6427. error: Boolean,
  6428. errorMessages: {
  6429. type: [Array, String],
  6430. default: () => []
  6431. },
  6432. maxErrors: {
  6433. type: [Number, String],
  6434. default: 1
  6435. },
  6436. name: String,
  6437. label: String,
  6438. readonly: {
  6439. type: Boolean,
  6440. default: null
  6441. },
  6442. rules: {
  6443. type: Array,
  6444. default: () => []
  6445. },
  6446. modelValue: null,
  6447. validateOn: String,
  6448. validationValue: null,
  6449. ...makeFocusProps()
  6450. }, 'validation');
  6451. function useValidation(props) {
  6452. let name = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : getCurrentInstanceName();
  6453. let id = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : getUid();
  6454. const model = useProxiedModel(props, 'modelValue');
  6455. const validationModel = vue.computed(() => props.validationValue === undefined ? model.value : props.validationValue);
  6456. const form = useForm(props);
  6457. const internalErrorMessages = vue.ref([]);
  6458. const isPristine = vue.shallowRef(true);
  6459. const isDirty = vue.computed(() => !!(wrapInArray(model.value === '' ? null : model.value).length || wrapInArray(validationModel.value === '' ? null : validationModel.value).length));
  6460. const errorMessages = vue.computed(() => {
  6461. return props.errorMessages?.length ? wrapInArray(props.errorMessages).concat(internalErrorMessages.value).slice(0, Math.max(0, +props.maxErrors)) : internalErrorMessages.value;
  6462. });
  6463. const validateOn = vue.computed(() => {
  6464. let value = (props.validateOn ?? form.validateOn?.value) || 'input';
  6465. if (value === 'lazy') value = 'input lazy';
  6466. if (value === 'eager') value = 'input eager';
  6467. const set = new Set(value?.split(' ') ?? []);
  6468. return {
  6469. input: set.has('input'),
  6470. blur: set.has('blur') || set.has('input') || set.has('invalid-input'),
  6471. invalidInput: set.has('invalid-input'),
  6472. lazy: set.has('lazy'),
  6473. eager: set.has('eager')
  6474. };
  6475. });
  6476. const isValid = vue.computed(() => {
  6477. if (props.error || props.errorMessages?.length) return false;
  6478. if (!props.rules.length) return true;
  6479. if (isPristine.value) {
  6480. return internalErrorMessages.value.length || validateOn.value.lazy ? null : true;
  6481. } else {
  6482. return !internalErrorMessages.value.length;
  6483. }
  6484. });
  6485. const isValidating = vue.shallowRef(false);
  6486. const validationClasses = vue.computed(() => {
  6487. return {
  6488. [`${name}--error`]: isValid.value === false,
  6489. [`${name}--dirty`]: isDirty.value,
  6490. [`${name}--disabled`]: form.isDisabled.value,
  6491. [`${name}--readonly`]: form.isReadonly.value
  6492. };
  6493. });
  6494. const vm = getCurrentInstance('validation');
  6495. const uid = vue.computed(() => props.name ?? vue.unref(id));
  6496. vue.onBeforeMount(() => {
  6497. form.register?.({
  6498. id: uid.value,
  6499. vm,
  6500. validate,
  6501. reset,
  6502. resetValidation
  6503. });
  6504. });
  6505. vue.onBeforeUnmount(() => {
  6506. form.unregister?.(uid.value);
  6507. });
  6508. vue.onMounted(async () => {
  6509. if (!validateOn.value.lazy) {
  6510. await validate(!validateOn.value.eager);
  6511. }
  6512. form.update?.(uid.value, isValid.value, errorMessages.value);
  6513. });
  6514. useToggleScope(() => validateOn.value.input || validateOn.value.invalidInput && isValid.value === false, () => {
  6515. vue.watch(validationModel, () => {
  6516. if (validationModel.value != null) {
  6517. validate();
  6518. } else if (props.focused) {
  6519. const unwatch = vue.watch(() => props.focused, val => {
  6520. if (!val) validate();
  6521. unwatch();
  6522. });
  6523. }
  6524. });
  6525. });
  6526. useToggleScope(() => validateOn.value.blur, () => {
  6527. vue.watch(() => props.focused, val => {
  6528. if (!val) validate();
  6529. });
  6530. });
  6531. vue.watch([isValid, errorMessages], () => {
  6532. form.update?.(uid.value, isValid.value, errorMessages.value);
  6533. });
  6534. async function reset() {
  6535. model.value = null;
  6536. await vue.nextTick();
  6537. await resetValidation();
  6538. }
  6539. async function resetValidation() {
  6540. isPristine.value = true;
  6541. if (!validateOn.value.lazy) {
  6542. await validate(!validateOn.value.eager);
  6543. } else {
  6544. internalErrorMessages.value = [];
  6545. }
  6546. }
  6547. async function validate() {
  6548. let silent = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : false;
  6549. const results = [];
  6550. isValidating.value = true;
  6551. for (const rule of props.rules) {
  6552. if (results.length >= +(props.maxErrors ?? 1)) {
  6553. break;
  6554. }
  6555. const handler = typeof rule === 'function' ? rule : () => rule;
  6556. const result = await handler(validationModel.value);
  6557. if (result === true) continue;
  6558. if (result !== false && typeof result !== 'string') {
  6559. // eslint-disable-next-line no-console
  6560. console.warn(`${result} is not a valid value. Rule functions must return boolean true or a string.`);
  6561. continue;
  6562. }
  6563. results.push(result || '');
  6564. }
  6565. internalErrorMessages.value = results;
  6566. isValidating.value = false;
  6567. isPristine.value = silent;
  6568. return internalErrorMessages.value;
  6569. }
  6570. return {
  6571. errorMessages,
  6572. isDirty,
  6573. isDisabled: form.isDisabled,
  6574. isReadonly: form.isReadonly,
  6575. isPristine,
  6576. isValid,
  6577. isValidating,
  6578. reset,
  6579. resetValidation,
  6580. validate,
  6581. validationClasses
  6582. };
  6583. }
  6584. // Types
  6585. const makeVInputProps = propsFactory({
  6586. id: String,
  6587. appendIcon: IconValue,
  6588. centerAffix: {
  6589. type: Boolean,
  6590. default: true
  6591. },
  6592. prependIcon: IconValue,
  6593. hideDetails: [Boolean, String],
  6594. hideSpinButtons: Boolean,
  6595. hint: String,
  6596. persistentHint: Boolean,
  6597. messages: {
  6598. type: [Array, String],
  6599. default: () => []
  6600. },
  6601. direction: {
  6602. type: String,
  6603. default: 'horizontal',
  6604. validator: v => ['horizontal', 'vertical'].includes(v)
  6605. },
  6606. 'onClick:prepend': EventProp(),
  6607. 'onClick:append': EventProp(),
  6608. ...makeComponentProps(),
  6609. ...makeDensityProps(),
  6610. ...only(makeDimensionProps(), ['maxWidth', 'minWidth', 'width']),
  6611. ...makeThemeProps(),
  6612. ...makeValidationProps()
  6613. }, 'VInput');
  6614. const VInput = genericComponent()({
  6615. name: 'VInput',
  6616. props: {
  6617. ...makeVInputProps()
  6618. },
  6619. emits: {
  6620. 'update:modelValue': value => true
  6621. },
  6622. setup(props, _ref) {
  6623. let {
  6624. attrs,
  6625. slots,
  6626. emit
  6627. } = _ref;
  6628. const {
  6629. densityClasses
  6630. } = useDensity(props);
  6631. const {
  6632. dimensionStyles
  6633. } = useDimension(props);
  6634. const {
  6635. themeClasses
  6636. } = provideTheme(props);
  6637. const {
  6638. rtlClasses
  6639. } = useRtl();
  6640. const {
  6641. InputIcon
  6642. } = useInputIcon(props);
  6643. const uid = getUid();
  6644. const id = vue.computed(() => props.id || `input-${uid}`);
  6645. const messagesId = vue.computed(() => `${id.value}-messages`);
  6646. const {
  6647. errorMessages,
  6648. isDirty,
  6649. isDisabled,
  6650. isReadonly,
  6651. isPristine,
  6652. isValid,
  6653. isValidating,
  6654. reset,
  6655. resetValidation,
  6656. validate,
  6657. validationClasses
  6658. } = useValidation(props, 'v-input', id);
  6659. const slotProps = vue.computed(() => ({
  6660. id,
  6661. messagesId,
  6662. isDirty,
  6663. isDisabled,
  6664. isReadonly,
  6665. isPristine,
  6666. isValid,
  6667. isValidating,
  6668. reset,
  6669. resetValidation,
  6670. validate
  6671. }));
  6672. const messages = vue.computed(() => {
  6673. if (props.errorMessages?.length || !isPristine.value && errorMessages.value.length) {
  6674. return errorMessages.value;
  6675. } else if (props.hint && (props.persistentHint || props.focused)) {
  6676. return props.hint;
  6677. } else {
  6678. return props.messages;
  6679. }
  6680. });
  6681. useRender(() => {
  6682. const hasPrepend = !!(slots.prepend || props.prependIcon);
  6683. const hasAppend = !!(slots.append || props.appendIcon);
  6684. const hasMessages = messages.value.length > 0;
  6685. const hasDetails = !props.hideDetails || props.hideDetails === 'auto' && (hasMessages || !!slots.details);
  6686. return vue.createVNode("div", {
  6687. "class": ['v-input', `v-input--${props.direction}`, {
  6688. 'v-input--center-affix': props.centerAffix,
  6689. 'v-input--hide-spin-buttons': props.hideSpinButtons
  6690. }, densityClasses.value, themeClasses.value, rtlClasses.value, validationClasses.value, props.class],
  6691. "style": [dimensionStyles.value, props.style]
  6692. }, [hasPrepend && vue.createVNode("div", {
  6693. "key": "prepend",
  6694. "class": "v-input__prepend"
  6695. }, [slots.prepend?.(slotProps.value), props.prependIcon && vue.createVNode(InputIcon, {
  6696. "key": "prepend-icon",
  6697. "name": "prepend"
  6698. }, null)]), slots.default && vue.createVNode("div", {
  6699. "class": "v-input__control"
  6700. }, [slots.default?.(slotProps.value)]), hasAppend && vue.createVNode("div", {
  6701. "key": "append",
  6702. "class": "v-input__append"
  6703. }, [props.appendIcon && vue.createVNode(InputIcon, {
  6704. "key": "append-icon",
  6705. "name": "append"
  6706. }, null), slots.append?.(slotProps.value)]), hasDetails && vue.createVNode("div", {
  6707. "class": "v-input__details"
  6708. }, [vue.createVNode(VMessages, {
  6709. "id": messagesId.value,
  6710. "active": hasMessages,
  6711. "messages": messages.value
  6712. }, {
  6713. message: slots.message
  6714. }), slots.details?.(slotProps.value)])]);
  6715. });
  6716. return {
  6717. reset,
  6718. resetValidation,
  6719. validate,
  6720. isValid,
  6721. errorMessages
  6722. };
  6723. }
  6724. });
  6725. // Types
  6726. const makeVCheckboxProps = propsFactory({
  6727. ...makeVInputProps(),
  6728. ...omit(makeVCheckboxBtnProps(), ['inline'])
  6729. }, 'VCheckbox');
  6730. const VCheckbox = genericComponent()({
  6731. name: 'VCheckbox',
  6732. inheritAttrs: false,
  6733. props: makeVCheckboxProps(),
  6734. emits: {
  6735. 'update:modelValue': value => true,
  6736. 'update:focused': focused => true
  6737. },
  6738. setup(props, _ref) {
  6739. let {
  6740. attrs,
  6741. slots
  6742. } = _ref;
  6743. const model = useProxiedModel(props, 'modelValue');
  6744. const {
  6745. isFocused,
  6746. focus,
  6747. blur
  6748. } = useFocus(props);
  6749. const uid = getUid();
  6750. const id = vue.computed(() => props.id || `checkbox-${uid}`);
  6751. useRender(() => {
  6752. const [rootAttrs, controlAttrs] = filterInputAttrs(attrs);
  6753. const inputProps = VInput.filterProps(props);
  6754. const checkboxProps = VCheckboxBtn.filterProps(props);
  6755. return vue.createVNode(VInput, vue.mergeProps({
  6756. "class": ['v-checkbox', props.class]
  6757. }, rootAttrs, inputProps, {
  6758. "modelValue": model.value,
  6759. "onUpdate:modelValue": $event => model.value = $event,
  6760. "id": id.value,
  6761. "focused": isFocused.value,
  6762. "style": props.style
  6763. }), {
  6764. ...slots,
  6765. default: _ref2 => {
  6766. let {
  6767. id,
  6768. messagesId,
  6769. isDisabled,
  6770. isReadonly,
  6771. isValid
  6772. } = _ref2;
  6773. return vue.createVNode(VCheckboxBtn, vue.mergeProps(checkboxProps, {
  6774. "id": id.value,
  6775. "aria-describedby": messagesId.value,
  6776. "disabled": isDisabled.value,
  6777. "readonly": isReadonly.value
  6778. }, controlAttrs, {
  6779. "error": isValid.value === false,
  6780. "modelValue": model.value,
  6781. "onUpdate:modelValue": $event => model.value = $event,
  6782. "onFocus": focus,
  6783. "onBlur": blur
  6784. }), slots);
  6785. }
  6786. });
  6787. });
  6788. return {};
  6789. }
  6790. });
  6791. // Utilities
  6792. // Types
  6793. const breakpoints = ['sm', 'md', 'lg', 'xl', 'xxl']; // no xs
  6794. const DisplaySymbol = Symbol.for('vuetify:display');
  6795. const defaultDisplayOptions = {
  6796. mobileBreakpoint: 'lg',
  6797. thresholds: {
  6798. xs: 0,
  6799. sm: 600,
  6800. md: 960,
  6801. lg: 1280,
  6802. xl: 1920,
  6803. xxl: 2560
  6804. }
  6805. };
  6806. const parseDisplayOptions = function () {
  6807. let options = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : defaultDisplayOptions;
  6808. return mergeDeep(defaultDisplayOptions, options);
  6809. };
  6810. function getClientWidth(ssr) {
  6811. return IN_BROWSER && !ssr ? window.innerWidth : typeof ssr === 'object' && ssr.clientWidth || 0;
  6812. }
  6813. function getClientHeight(ssr) {
  6814. return IN_BROWSER && !ssr ? window.innerHeight : typeof ssr === 'object' && ssr.clientHeight || 0;
  6815. }
  6816. function getPlatform(ssr) {
  6817. const userAgent = IN_BROWSER && !ssr ? window.navigator.userAgent : 'ssr';
  6818. function match(regexp) {
  6819. return Boolean(userAgent.match(regexp));
  6820. }
  6821. const android = match(/android/i);
  6822. const ios = match(/iphone|ipad|ipod/i);
  6823. const cordova = match(/cordova/i);
  6824. const electron = match(/electron/i);
  6825. const chrome = match(/chrome/i);
  6826. const edge = match(/edge/i);
  6827. const firefox = match(/firefox/i);
  6828. const opera = match(/opera/i);
  6829. const win = match(/win/i);
  6830. const mac = match(/mac/i);
  6831. const linux = match(/linux/i);
  6832. return {
  6833. android,
  6834. ios,
  6835. cordova,
  6836. electron,
  6837. chrome,
  6838. edge,
  6839. firefox,
  6840. opera,
  6841. win,
  6842. mac,
  6843. linux,
  6844. touch: SUPPORTS_TOUCH,
  6845. ssr: userAgent === 'ssr'
  6846. };
  6847. }
  6848. function createDisplay(options, ssr) {
  6849. const {
  6850. thresholds,
  6851. mobileBreakpoint
  6852. } = parseDisplayOptions(options);
  6853. const height = vue.shallowRef(getClientHeight(ssr));
  6854. const platform = vue.shallowRef(getPlatform(ssr));
  6855. const state = vue.reactive({});
  6856. const width = vue.shallowRef(getClientWidth(ssr));
  6857. function updateSize() {
  6858. height.value = getClientHeight();
  6859. width.value = getClientWidth();
  6860. }
  6861. function update() {
  6862. updateSize();
  6863. platform.value = getPlatform();
  6864. }
  6865. // eslint-disable-next-line max-statements
  6866. vue.watchEffect(() => {
  6867. const xs = width.value < thresholds.sm;
  6868. const sm = width.value < thresholds.md && !xs;
  6869. const md = width.value < thresholds.lg && !(sm || xs);
  6870. const lg = width.value < thresholds.xl && !(md || sm || xs);
  6871. const xl = width.value < thresholds.xxl && !(lg || md || sm || xs);
  6872. const xxl = width.value >= thresholds.xxl;
  6873. const name = xs ? 'xs' : sm ? 'sm' : md ? 'md' : lg ? 'lg' : xl ? 'xl' : 'xxl';
  6874. const breakpointValue = typeof mobileBreakpoint === 'number' ? mobileBreakpoint : thresholds[mobileBreakpoint];
  6875. const mobile = width.value < breakpointValue;
  6876. state.xs = xs;
  6877. state.sm = sm;
  6878. state.md = md;
  6879. state.lg = lg;
  6880. state.xl = xl;
  6881. state.xxl = xxl;
  6882. state.smAndUp = !xs;
  6883. state.mdAndUp = !(xs || sm);
  6884. state.lgAndUp = !(xs || sm || md);
  6885. state.xlAndUp = !(xs || sm || md || lg);
  6886. state.smAndDown = !(md || lg || xl || xxl);
  6887. state.mdAndDown = !(lg || xl || xxl);
  6888. state.lgAndDown = !(xl || xxl);
  6889. state.xlAndDown = !xxl;
  6890. state.name = name;
  6891. state.height = height.value;
  6892. state.width = width.value;
  6893. state.mobile = mobile;
  6894. state.mobileBreakpoint = mobileBreakpoint;
  6895. state.platform = platform.value;
  6896. state.thresholds = thresholds;
  6897. });
  6898. if (IN_BROWSER) {
  6899. window.addEventListener('resize', updateSize, {
  6900. passive: true
  6901. });
  6902. }
  6903. return {
  6904. ...vue.toRefs(state),
  6905. update,
  6906. ssr: !!ssr
  6907. };
  6908. }
  6909. const makeDisplayProps = propsFactory({
  6910. mobile: {
  6911. type: Boolean,
  6912. default: false
  6913. },
  6914. mobileBreakpoint: [Number, String]
  6915. }, 'display');
  6916. function useDisplay() {
  6917. let props = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
  6918. let name = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : getCurrentInstanceName();
  6919. const display = vue.inject(DisplaySymbol);
  6920. if (!display) throw new Error('Could not find Vuetify display injection');
  6921. const mobile = vue.computed(() => {
  6922. if (props.mobile != null) return props.mobile;
  6923. if (!props.mobileBreakpoint) return display.mobile.value;
  6924. const breakpointValue = typeof props.mobileBreakpoint === 'number' ? props.mobileBreakpoint : display.thresholds.value[props.mobileBreakpoint];
  6925. return display.width.value < breakpointValue;
  6926. });
  6927. const displayClasses = vue.computed(() => {
  6928. if (!name) return {};
  6929. return {
  6930. [`${name}--mobile`]: mobile.value
  6931. };
  6932. });
  6933. return {
  6934. ...display,
  6935. displayClasses,
  6936. mobile
  6937. };
  6938. }
  6939. // Utilities
  6940. // Types
  6941. const GoToSymbol = Symbol.for('vuetify:goto');
  6942. function genDefaults() {
  6943. return {
  6944. container: undefined,
  6945. duration: 300,
  6946. layout: false,
  6947. offset: 0,
  6948. easing: 'easeInOutCubic',
  6949. patterns: {
  6950. linear: t => t,
  6951. easeInQuad: t => t ** 2,
  6952. easeOutQuad: t => t * (2 - t),
  6953. easeInOutQuad: t => t < 0.5 ? 2 * t ** 2 : -1 + (4 - 2 * t) * t,
  6954. easeInCubic: t => t ** 3,
  6955. easeOutCubic: t => --t ** 3 + 1,
  6956. easeInOutCubic: t => t < 0.5 ? 4 * t ** 3 : (t - 1) * (2 * t - 2) * (2 * t - 2) + 1,
  6957. easeInQuart: t => t ** 4,
  6958. easeOutQuart: t => 1 - --t ** 4,
  6959. easeInOutQuart: t => t < 0.5 ? 8 * t ** 4 : 1 - 8 * --t ** 4,
  6960. easeInQuint: t => t ** 5,
  6961. easeOutQuint: t => 1 + --t ** 5,
  6962. easeInOutQuint: t => t < 0.5 ? 16 * t ** 5 : 1 + 16 * --t ** 5
  6963. }
  6964. };
  6965. }
  6966. function getContainer(el) {
  6967. return getTarget$1(el) ?? (document.scrollingElement || document.body);
  6968. }
  6969. function getTarget$1(el) {
  6970. return typeof el === 'string' ? document.querySelector(el) : refElement(el);
  6971. }
  6972. function getOffset$2(target, horizontal, rtl) {
  6973. if (typeof target === 'number') return horizontal && rtl ? -target : target;
  6974. let el = getTarget$1(target);
  6975. let totalOffset = 0;
  6976. while (el) {
  6977. totalOffset += horizontal ? el.offsetLeft : el.offsetTop;
  6978. el = el.offsetParent;
  6979. }
  6980. return totalOffset;
  6981. }
  6982. function createGoTo(options, locale) {
  6983. return {
  6984. rtl: locale.isRtl,
  6985. options: mergeDeep(genDefaults(), options)
  6986. };
  6987. }
  6988. async function scrollTo(_target, _options, horizontal, goTo) {
  6989. const property = horizontal ? 'scrollLeft' : 'scrollTop';
  6990. const options = mergeDeep(goTo?.options ?? genDefaults(), _options);
  6991. const rtl = goTo?.rtl.value;
  6992. const target = (typeof _target === 'number' ? _target : getTarget$1(_target)) ?? 0;
  6993. const container = options.container === 'parent' && target instanceof HTMLElement ? target.parentElement : getContainer(options.container);
  6994. const ease = typeof options.easing === 'function' ? options.easing : options.patterns[options.easing];
  6995. if (!ease) throw new TypeError(`Easing function "${options.easing}" not found.`);
  6996. let targetLocation;
  6997. if (typeof target === 'number') {
  6998. targetLocation = getOffset$2(target, horizontal, rtl);
  6999. } else {
  7000. targetLocation = getOffset$2(target, horizontal, rtl) - getOffset$2(container, horizontal, rtl);
  7001. if (options.layout) {
  7002. const styles = window.getComputedStyle(target);
  7003. const layoutOffset = styles.getPropertyValue('--v-layout-top');
  7004. if (layoutOffset) targetLocation -= parseInt(layoutOffset, 10);
  7005. }
  7006. }
  7007. targetLocation += options.offset;
  7008. targetLocation = clampTarget(container, targetLocation, !!rtl, !!horizontal);
  7009. const startLocation = container[property] ?? 0;
  7010. if (targetLocation === startLocation) return Promise.resolve(targetLocation);
  7011. const startTime = performance.now();
  7012. return new Promise(resolve => requestAnimationFrame(function step(currentTime) {
  7013. const timeElapsed = currentTime - startTime;
  7014. const progress = timeElapsed / options.duration;
  7015. const location = Math.floor(startLocation + (targetLocation - startLocation) * ease(clamp(progress, 0, 1)));
  7016. container[property] = location;
  7017. // Allow for some jitter if target time has elapsed
  7018. if (progress >= 1 && Math.abs(location - container[property]) < 10) {
  7019. return resolve(targetLocation);
  7020. } else if (progress > 2) {
  7021. // The target might not be reachable
  7022. consoleWarn('Scroll target is not reachable');
  7023. return resolve(container[property]);
  7024. }
  7025. requestAnimationFrame(step);
  7026. }));
  7027. }
  7028. function useGoTo() {
  7029. let _options = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
  7030. const goToInstance = vue.inject(GoToSymbol);
  7031. const {
  7032. isRtl
  7033. } = useRtl();
  7034. if (!goToInstance) throw new Error('[Vuetify] Could not find injected goto instance');
  7035. const goTo = {
  7036. ...goToInstance,
  7037. // can be set via VLocaleProvider
  7038. rtl: vue.computed(() => goToInstance.rtl.value || isRtl.value)
  7039. };
  7040. async function go(target, options) {
  7041. return scrollTo(target, mergeDeep(_options, options), false, goTo);
  7042. }
  7043. go.horizontal = async (target, options) => {
  7044. return scrollTo(target, mergeDeep(_options, options), true, goTo);
  7045. };
  7046. return go;
  7047. }
  7048. /**
  7049. * Clamp target value to achieve a smooth scroll animation
  7050. * when the value goes outside the scroll container size
  7051. */
  7052. function clampTarget(container, value, rtl, horizontal) {
  7053. const {
  7054. scrollWidth,
  7055. scrollHeight
  7056. } = container;
  7057. const [containerWidth, containerHeight] = container === document.scrollingElement ? [window.innerWidth, window.innerHeight] : [container.offsetWidth, container.offsetHeight];
  7058. let min;
  7059. let max;
  7060. if (horizontal) {
  7061. if (rtl) {
  7062. min = -(scrollWidth - containerWidth);
  7063. max = 0;
  7064. } else {
  7065. min = 0;
  7066. max = scrollWidth - containerWidth;
  7067. }
  7068. } else {
  7069. min = 0;
  7070. max = scrollHeight + -containerHeight;
  7071. }
  7072. return Math.max(Math.min(value, max), min);
  7073. }
  7074. function calculateUpdatedTarget(_ref) {
  7075. let {
  7076. selectedElement,
  7077. containerElement,
  7078. isRtl,
  7079. isHorizontal
  7080. } = _ref;
  7081. const containerSize = getOffsetSize(isHorizontal, containerElement);
  7082. const scrollPosition = getScrollPosition(isHorizontal, isRtl, containerElement);
  7083. const childrenSize = getOffsetSize(isHorizontal, selectedElement);
  7084. const childrenStartPosition = getOffsetPosition(isHorizontal, selectedElement);
  7085. const additionalOffset = childrenSize * 0.4;
  7086. if (scrollPosition > childrenStartPosition) {
  7087. return childrenStartPosition - additionalOffset;
  7088. } else if (scrollPosition + containerSize < childrenStartPosition + childrenSize) {
  7089. return childrenStartPosition - containerSize + childrenSize + additionalOffset;
  7090. }
  7091. return scrollPosition;
  7092. }
  7093. function calculateCenteredTarget(_ref2) {
  7094. let {
  7095. selectedElement,
  7096. containerElement,
  7097. isHorizontal
  7098. } = _ref2;
  7099. const containerOffsetSize = getOffsetSize(isHorizontal, containerElement);
  7100. const childrenOffsetPosition = getOffsetPosition(isHorizontal, selectedElement);
  7101. const childrenOffsetSize = getOffsetSize(isHorizontal, selectedElement);
  7102. return childrenOffsetPosition - containerOffsetSize / 2 + childrenOffsetSize / 2;
  7103. }
  7104. function getScrollSize(isHorizontal, element) {
  7105. const key = isHorizontal ? 'scrollWidth' : 'scrollHeight';
  7106. return element?.[key] || 0;
  7107. }
  7108. function getClientSize(isHorizontal, element) {
  7109. const key = isHorizontal ? 'clientWidth' : 'clientHeight';
  7110. return element?.[key] || 0;
  7111. }
  7112. function getScrollPosition(isHorizontal, rtl, element) {
  7113. if (!element) {
  7114. return 0;
  7115. }
  7116. const {
  7117. scrollLeft,
  7118. offsetWidth,
  7119. scrollWidth
  7120. } = element;
  7121. if (isHorizontal) {
  7122. return rtl ? scrollWidth - offsetWidth + scrollLeft : scrollLeft;
  7123. }
  7124. return element.scrollTop;
  7125. }
  7126. function getOffsetSize(isHorizontal, element) {
  7127. const key = isHorizontal ? 'offsetWidth' : 'offsetHeight';
  7128. return element?.[key] || 0;
  7129. }
  7130. function getOffsetPosition(isHorizontal, element) {
  7131. const key = isHorizontal ? 'offsetLeft' : 'offsetTop';
  7132. return element?.[key] || 0;
  7133. }
  7134. // Types
  7135. const VSlideGroupSymbol = Symbol.for('vuetify:v-slide-group');
  7136. const makeVSlideGroupProps = propsFactory({
  7137. centerActive: Boolean,
  7138. direction: {
  7139. type: String,
  7140. default: 'horizontal'
  7141. },
  7142. symbol: {
  7143. type: null,
  7144. default: VSlideGroupSymbol
  7145. },
  7146. nextIcon: {
  7147. type: IconValue,
  7148. default: '$next'
  7149. },
  7150. prevIcon: {
  7151. type: IconValue,
  7152. default: '$prev'
  7153. },
  7154. showArrows: {
  7155. type: [Boolean, String],
  7156. validator: v => typeof v === 'boolean' || ['always', 'desktop', 'mobile'].includes(v)
  7157. },
  7158. ...makeComponentProps(),
  7159. ...makeDisplayProps({
  7160. mobile: null
  7161. }),
  7162. ...makeTagProps(),
  7163. ...makeGroupProps({
  7164. selectedClass: 'v-slide-group-item--active'
  7165. })
  7166. }, 'VSlideGroup');
  7167. const VSlideGroup = genericComponent()({
  7168. name: 'VSlideGroup',
  7169. props: makeVSlideGroupProps(),
  7170. emits: {
  7171. 'update:modelValue': value => true
  7172. },
  7173. setup(props, _ref) {
  7174. let {
  7175. slots
  7176. } = _ref;
  7177. const {
  7178. isRtl
  7179. } = useRtl();
  7180. const {
  7181. displayClasses,
  7182. mobile
  7183. } = useDisplay(props);
  7184. const group = useGroup(props, props.symbol);
  7185. const isOverflowing = vue.shallowRef(false);
  7186. const scrollOffset = vue.shallowRef(0);
  7187. const containerSize = vue.shallowRef(0);
  7188. const contentSize = vue.shallowRef(0);
  7189. const isHorizontal = vue.computed(() => props.direction === 'horizontal');
  7190. const {
  7191. resizeRef: containerRef,
  7192. contentRect: containerRect
  7193. } = useResizeObserver();
  7194. const {
  7195. resizeRef: contentRef,
  7196. contentRect
  7197. } = useResizeObserver();
  7198. const goTo = useGoTo();
  7199. const goToOptions = vue.computed(() => {
  7200. return {
  7201. container: containerRef.el,
  7202. duration: 200,
  7203. easing: 'easeOutQuart'
  7204. };
  7205. });
  7206. const firstSelectedIndex = vue.computed(() => {
  7207. if (!group.selected.value.length) return -1;
  7208. return group.items.value.findIndex(item => item.id === group.selected.value[0]);
  7209. });
  7210. const lastSelectedIndex = vue.computed(() => {
  7211. if (!group.selected.value.length) return -1;
  7212. return group.items.value.findIndex(item => item.id === group.selected.value[group.selected.value.length - 1]);
  7213. });
  7214. if (IN_BROWSER) {
  7215. let frame = -1;
  7216. vue.watch(() => [group.selected.value, containerRect.value, contentRect.value, isHorizontal.value], () => {
  7217. cancelAnimationFrame(frame);
  7218. frame = requestAnimationFrame(() => {
  7219. if (containerRect.value && contentRect.value) {
  7220. const sizeProperty = isHorizontal.value ? 'width' : 'height';
  7221. containerSize.value = containerRect.value[sizeProperty];
  7222. contentSize.value = contentRect.value[sizeProperty];
  7223. isOverflowing.value = containerSize.value + 1 < contentSize.value;
  7224. }
  7225. if (firstSelectedIndex.value >= 0 && contentRef.el) {
  7226. // TODO: Is this too naive? Should we store element references in group composable?
  7227. const selectedElement = contentRef.el.children[lastSelectedIndex.value];
  7228. scrollToChildren(selectedElement, props.centerActive);
  7229. }
  7230. });
  7231. });
  7232. }
  7233. const isFocused = vue.shallowRef(false);
  7234. function scrollToChildren(children, center) {
  7235. let target = 0;
  7236. if (center) {
  7237. target = calculateCenteredTarget({
  7238. containerElement: containerRef.el,
  7239. isHorizontal: isHorizontal.value,
  7240. selectedElement: children
  7241. });
  7242. } else {
  7243. target = calculateUpdatedTarget({
  7244. containerElement: containerRef.el,
  7245. isHorizontal: isHorizontal.value,
  7246. isRtl: isRtl.value,
  7247. selectedElement: children
  7248. });
  7249. }
  7250. scrollToPosition(target);
  7251. }
  7252. function scrollToPosition(newPosition) {
  7253. if (!IN_BROWSER || !containerRef.el) return;
  7254. const offsetSize = getOffsetSize(isHorizontal.value, containerRef.el);
  7255. const scrollPosition = getScrollPosition(isHorizontal.value, isRtl.value, containerRef.el);
  7256. const scrollSize = getScrollSize(isHorizontal.value, containerRef.el);
  7257. if (scrollSize <= offsetSize ||
  7258. // Prevent scrolling by only a couple of pixels, which doesn't look smooth
  7259. Math.abs(newPosition - scrollPosition) < 16) return;
  7260. if (isHorizontal.value && isRtl.value && containerRef.el) {
  7261. const {
  7262. scrollWidth,
  7263. offsetWidth: containerWidth
  7264. } = containerRef.el;
  7265. newPosition = scrollWidth - containerWidth - newPosition;
  7266. }
  7267. if (isHorizontal.value) {
  7268. goTo.horizontal(newPosition, goToOptions.value);
  7269. } else {
  7270. goTo(newPosition, goToOptions.value);
  7271. }
  7272. }
  7273. function onScroll(e) {
  7274. const {
  7275. scrollTop,
  7276. scrollLeft
  7277. } = e.target;
  7278. scrollOffset.value = isHorizontal.value ? scrollLeft : scrollTop;
  7279. }
  7280. function onFocusin(e) {
  7281. isFocused.value = true;
  7282. if (!isOverflowing.value || !contentRef.el) return;
  7283. // Focused element is likely to be the root of an item, so a
  7284. // breadth-first search will probably find it in the first iteration
  7285. for (const el of e.composedPath()) {
  7286. for (const item of contentRef.el.children) {
  7287. if (item === el) {
  7288. scrollToChildren(item);
  7289. return;
  7290. }
  7291. }
  7292. }
  7293. }
  7294. function onFocusout(e) {
  7295. isFocused.value = false;
  7296. }
  7297. // Affix clicks produce onFocus that we have to ignore to avoid extra scrollToChildren
  7298. let ignoreFocusEvent = false;
  7299. function onFocus(e) {
  7300. if (!ignoreFocusEvent && !isFocused.value && !(e.relatedTarget && contentRef.el?.contains(e.relatedTarget))) focus();
  7301. ignoreFocusEvent = false;
  7302. }
  7303. function onFocusAffixes() {
  7304. ignoreFocusEvent = true;
  7305. }
  7306. function onKeydown(e) {
  7307. if (!contentRef.el) return;
  7308. function toFocus(location) {
  7309. e.preventDefault();
  7310. focus(location);
  7311. }
  7312. if (isHorizontal.value) {
  7313. if (e.key === 'ArrowRight') {
  7314. toFocus(isRtl.value ? 'prev' : 'next');
  7315. } else if (e.key === 'ArrowLeft') {
  7316. toFocus(isRtl.value ? 'next' : 'prev');
  7317. }
  7318. } else {
  7319. if (e.key === 'ArrowDown') {
  7320. toFocus('next');
  7321. } else if (e.key === 'ArrowUp') {
  7322. toFocus('prev');
  7323. }
  7324. }
  7325. if (e.key === 'Home') {
  7326. toFocus('first');
  7327. } else if (e.key === 'End') {
  7328. toFocus('last');
  7329. }
  7330. }
  7331. function focus(location) {
  7332. if (!contentRef.el) return;
  7333. let el;
  7334. if (!location) {
  7335. const focusable = focusableChildren(contentRef.el);
  7336. el = focusable[0];
  7337. } else if (location === 'next') {
  7338. el = contentRef.el.querySelector(':focus')?.nextElementSibling;
  7339. if (!el) return focus('first');
  7340. } else if (location === 'prev') {
  7341. el = contentRef.el.querySelector(':focus')?.previousElementSibling;
  7342. if (!el) return focus('last');
  7343. } else if (location === 'first') {
  7344. el = contentRef.el.firstElementChild;
  7345. } else if (location === 'last') {
  7346. el = contentRef.el.lastElementChild;
  7347. }
  7348. if (el) {
  7349. el.focus({
  7350. preventScroll: true
  7351. });
  7352. }
  7353. }
  7354. function scrollTo(location) {
  7355. const direction = isHorizontal.value && isRtl.value ? -1 : 1;
  7356. const offsetStep = (location === 'prev' ? -direction : direction) * containerSize.value;
  7357. let newPosition = scrollOffset.value + offsetStep;
  7358. // TODO: improve it
  7359. if (isHorizontal.value && isRtl.value && containerRef.el) {
  7360. const {
  7361. scrollWidth,
  7362. offsetWidth: containerWidth
  7363. } = containerRef.el;
  7364. newPosition += scrollWidth - containerWidth;
  7365. }
  7366. scrollToPosition(newPosition);
  7367. }
  7368. const slotProps = vue.computed(() => ({
  7369. next: group.next,
  7370. prev: group.prev,
  7371. select: group.select,
  7372. isSelected: group.isSelected
  7373. }));
  7374. const hasAffixes = vue.computed(() => {
  7375. switch (props.showArrows) {
  7376. // Always show arrows on desktop & mobile
  7377. case 'always':
  7378. return true;
  7379. // Always show arrows on desktop
  7380. case 'desktop':
  7381. return !mobile.value;
  7382. // Show arrows on mobile when overflowing.
  7383. // This matches the default 2.2 behavior
  7384. case true:
  7385. return isOverflowing.value || Math.abs(scrollOffset.value) > 0;
  7386. // Always show on mobile
  7387. case 'mobile':
  7388. return mobile.value || isOverflowing.value || Math.abs(scrollOffset.value) > 0;
  7389. // https://material.io/components/tabs#scrollable-tabs
  7390. // Always show arrows when
  7391. // overflowed on desktop
  7392. default:
  7393. return !mobile.value && (isOverflowing.value || Math.abs(scrollOffset.value) > 0);
  7394. }
  7395. });
  7396. const hasPrev = vue.computed(() => {
  7397. // 1 pixel in reserve, may be lost after rounding
  7398. return Math.abs(scrollOffset.value) > 1;
  7399. });
  7400. const hasNext = vue.computed(() => {
  7401. if (!containerRef.value) return false;
  7402. const scrollSize = getScrollSize(isHorizontal.value, containerRef.el);
  7403. const clientSize = getClientSize(isHorizontal.value, containerRef.el);
  7404. const scrollSizeMax = scrollSize - clientSize;
  7405. // 1 pixel in reserve, may be lost after rounding
  7406. return scrollSizeMax - Math.abs(scrollOffset.value) > 1;
  7407. });
  7408. useRender(() => vue.createVNode(props.tag, {
  7409. "class": ['v-slide-group', {
  7410. 'v-slide-group--vertical': !isHorizontal.value,
  7411. 'v-slide-group--has-affixes': hasAffixes.value,
  7412. 'v-slide-group--is-overflowing': isOverflowing.value
  7413. }, displayClasses.value, props.class],
  7414. "style": props.style,
  7415. "tabindex": isFocused.value || group.selected.value.length ? -1 : 0,
  7416. "onFocus": onFocus
  7417. }, {
  7418. default: () => [hasAffixes.value && vue.createVNode("div", {
  7419. "key": "prev",
  7420. "class": ['v-slide-group__prev', {
  7421. 'v-slide-group__prev--disabled': !hasPrev.value
  7422. }],
  7423. "onMousedown": onFocusAffixes,
  7424. "onClick": () => hasPrev.value && scrollTo('prev')
  7425. }, [slots.prev?.(slotProps.value) ?? vue.createVNode(VFadeTransition, null, {
  7426. default: () => [vue.createVNode(VIcon, {
  7427. "icon": isRtl.value ? props.nextIcon : props.prevIcon
  7428. }, null)]
  7429. })]), vue.createVNode("div", {
  7430. "key": "container",
  7431. "ref": containerRef,
  7432. "class": "v-slide-group__container",
  7433. "onScroll": onScroll
  7434. }, [vue.createVNode("div", {
  7435. "ref": contentRef,
  7436. "class": "v-slide-group__content",
  7437. "onFocusin": onFocusin,
  7438. "onFocusout": onFocusout,
  7439. "onKeydown": onKeydown
  7440. }, [slots.default?.(slotProps.value)])]), hasAffixes.value && vue.createVNode("div", {
  7441. "key": "next",
  7442. "class": ['v-slide-group__next', {
  7443. 'v-slide-group__next--disabled': !hasNext.value
  7444. }],
  7445. "onMousedown": onFocusAffixes,
  7446. "onClick": () => hasNext.value && scrollTo('next')
  7447. }, [slots.next?.(slotProps.value) ?? vue.createVNode(VFadeTransition, null, {
  7448. default: () => [vue.createVNode(VIcon, {
  7449. "icon": isRtl.value ? props.prevIcon : props.nextIcon
  7450. }, null)]
  7451. })])]
  7452. }));
  7453. return {
  7454. selected: group.selected,
  7455. scrollTo,
  7456. scrollOffset,
  7457. focus,
  7458. hasPrev,
  7459. hasNext
  7460. };
  7461. }
  7462. });
  7463. // Types
  7464. const VChipGroupSymbol = Symbol.for('vuetify:v-chip-group');
  7465. const makeVChipGroupProps = propsFactory({
  7466. column: Boolean,
  7467. filter: Boolean,
  7468. valueComparator: {
  7469. type: Function,
  7470. default: deepEqual
  7471. },
  7472. ...makeVSlideGroupProps(),
  7473. ...makeComponentProps(),
  7474. ...makeGroupProps({
  7475. selectedClass: 'v-chip--selected'
  7476. }),
  7477. ...makeTagProps(),
  7478. ...makeThemeProps(),
  7479. ...makeVariantProps({
  7480. variant: 'tonal'
  7481. })
  7482. }, 'VChipGroup');
  7483. const VChipGroup = genericComponent()({
  7484. name: 'VChipGroup',
  7485. props: makeVChipGroupProps(),
  7486. emits: {
  7487. 'update:modelValue': value => true
  7488. },
  7489. setup(props, _ref) {
  7490. let {
  7491. slots
  7492. } = _ref;
  7493. const {
  7494. themeClasses
  7495. } = provideTheme(props);
  7496. const {
  7497. isSelected,
  7498. select,
  7499. next,
  7500. prev,
  7501. selected
  7502. } = useGroup(props, VChipGroupSymbol);
  7503. provideDefaults({
  7504. VChip: {
  7505. color: vue.toRef(props, 'color'),
  7506. disabled: vue.toRef(props, 'disabled'),
  7507. filter: vue.toRef(props, 'filter'),
  7508. variant: vue.toRef(props, 'variant')
  7509. }
  7510. });
  7511. useRender(() => {
  7512. const slideGroupProps = VSlideGroup.filterProps(props);
  7513. return vue.createVNode(VSlideGroup, vue.mergeProps(slideGroupProps, {
  7514. "class": ['v-chip-group', {
  7515. 'v-chip-group--column': props.column
  7516. }, themeClasses.value, props.class],
  7517. "style": props.style
  7518. }), {
  7519. default: () => [slots.default?.({
  7520. isSelected,
  7521. select,
  7522. next,
  7523. prev,
  7524. selected: selected.value
  7525. })]
  7526. });
  7527. });
  7528. return {};
  7529. }
  7530. });
  7531. // Types
  7532. const makeVChipProps = propsFactory({
  7533. activeClass: String,
  7534. appendAvatar: String,
  7535. appendIcon: IconValue,
  7536. closable: Boolean,
  7537. closeIcon: {
  7538. type: IconValue,
  7539. default: '$delete'
  7540. },
  7541. closeLabel: {
  7542. type: String,
  7543. default: '$vuetify.close'
  7544. },
  7545. draggable: Boolean,
  7546. filter: Boolean,
  7547. filterIcon: {
  7548. type: IconValue,
  7549. default: '$complete'
  7550. },
  7551. label: Boolean,
  7552. link: {
  7553. type: Boolean,
  7554. default: undefined
  7555. },
  7556. pill: Boolean,
  7557. prependAvatar: String,
  7558. prependIcon: IconValue,
  7559. ripple: {
  7560. type: [Boolean, Object],
  7561. default: true
  7562. },
  7563. text: String,
  7564. modelValue: {
  7565. type: Boolean,
  7566. default: true
  7567. },
  7568. onClick: EventProp(),
  7569. onClickOnce: EventProp(),
  7570. ...makeBorderProps(),
  7571. ...makeComponentProps(),
  7572. ...makeDensityProps(),
  7573. ...makeElevationProps(),
  7574. ...makeGroupItemProps(),
  7575. ...makeRoundedProps(),
  7576. ...makeRouterProps(),
  7577. ...makeSizeProps(),
  7578. ...makeTagProps({
  7579. tag: 'span'
  7580. }),
  7581. ...makeThemeProps(),
  7582. ...makeVariantProps({
  7583. variant: 'tonal'
  7584. })
  7585. }, 'VChip');
  7586. const VChip = genericComponent()({
  7587. name: 'VChip',
  7588. directives: {
  7589. Ripple
  7590. },
  7591. props: makeVChipProps(),
  7592. emits: {
  7593. 'click:close': e => true,
  7594. 'update:modelValue': value => true,
  7595. 'group:selected': val => true,
  7596. click: e => true
  7597. },
  7598. setup(props, _ref) {
  7599. let {
  7600. attrs,
  7601. emit,
  7602. slots
  7603. } = _ref;
  7604. const {
  7605. t
  7606. } = useLocale();
  7607. const {
  7608. borderClasses
  7609. } = useBorder(props);
  7610. const {
  7611. colorClasses,
  7612. colorStyles,
  7613. variantClasses
  7614. } = useVariant(props);
  7615. const {
  7616. densityClasses
  7617. } = useDensity(props);
  7618. const {
  7619. elevationClasses
  7620. } = useElevation(props);
  7621. const {
  7622. roundedClasses
  7623. } = useRounded(props);
  7624. const {
  7625. sizeClasses
  7626. } = useSize(props);
  7627. const {
  7628. themeClasses
  7629. } = provideTheme(props);
  7630. const isActive = useProxiedModel(props, 'modelValue');
  7631. const group = useGroupItem(props, VChipGroupSymbol, false);
  7632. const link = useLink(props, attrs);
  7633. const isLink = vue.computed(() => props.link !== false && link.isLink.value);
  7634. const isClickable = vue.computed(() => !props.disabled && props.link !== false && (!!group || props.link || link.isClickable.value));
  7635. const closeProps = vue.computed(() => ({
  7636. 'aria-label': t(props.closeLabel),
  7637. onClick(e) {
  7638. e.preventDefault();
  7639. e.stopPropagation();
  7640. isActive.value = false;
  7641. emit('click:close', e);
  7642. }
  7643. }));
  7644. function onClick(e) {
  7645. emit('click', e);
  7646. if (!isClickable.value) return;
  7647. link.navigate?.(e);
  7648. group?.toggle();
  7649. }
  7650. function onKeyDown(e) {
  7651. if (e.key === 'Enter' || e.key === ' ') {
  7652. e.preventDefault();
  7653. onClick(e);
  7654. }
  7655. }
  7656. return () => {
  7657. const Tag = link.isLink.value ? 'a' : props.tag;
  7658. const hasAppendMedia = !!(props.appendIcon || props.appendAvatar);
  7659. const hasAppend = !!(hasAppendMedia || slots.append);
  7660. const hasClose = !!(slots.close || props.closable);
  7661. const hasFilter = !!(slots.filter || props.filter) && group;
  7662. const hasPrependMedia = !!(props.prependIcon || props.prependAvatar);
  7663. const hasPrepend = !!(hasPrependMedia || slots.prepend);
  7664. const hasColor = !group || group.isSelected.value;
  7665. return isActive.value && vue.withDirectives(vue.createVNode(Tag, vue.mergeProps({
  7666. "class": ['v-chip', {
  7667. 'v-chip--disabled': props.disabled,
  7668. 'v-chip--label': props.label,
  7669. 'v-chip--link': isClickable.value,
  7670. 'v-chip--filter': hasFilter,
  7671. 'v-chip--pill': props.pill,
  7672. [`${props.activeClass}`]: props.activeClass && link.isActive?.value
  7673. }, themeClasses.value, borderClasses.value, hasColor ? colorClasses.value : undefined, densityClasses.value, elevationClasses.value, roundedClasses.value, sizeClasses.value, variantClasses.value, group?.selectedClass.value, props.class],
  7674. "style": [hasColor ? colorStyles.value : undefined, props.style],
  7675. "disabled": props.disabled || undefined,
  7676. "draggable": props.draggable,
  7677. "tabindex": isClickable.value ? 0 : undefined,
  7678. "onClick": onClick,
  7679. "onKeydown": isClickable.value && !isLink.value && onKeyDown
  7680. }, link.linkProps), {
  7681. default: () => [genOverlays(isClickable.value, 'v-chip'), hasFilter && vue.createVNode(VExpandXTransition, {
  7682. "key": "filter"
  7683. }, {
  7684. default: () => [vue.withDirectives(vue.createVNode("div", {
  7685. "class": "v-chip__filter"
  7686. }, [!slots.filter ? vue.createVNode(VIcon, {
  7687. "key": "filter-icon",
  7688. "icon": props.filterIcon
  7689. }, null) : vue.createVNode(VDefaultsProvider, {
  7690. "key": "filter-defaults",
  7691. "disabled": !props.filterIcon,
  7692. "defaults": {
  7693. VIcon: {
  7694. icon: props.filterIcon
  7695. }
  7696. }
  7697. }, slots.filter)]), [[vue.vShow, group.isSelected.value]])]
  7698. }), hasPrepend && vue.createVNode("div", {
  7699. "key": "prepend",
  7700. "class": "v-chip__prepend"
  7701. }, [!slots.prepend ? vue.createVNode(vue.Fragment, null, [props.prependIcon && vue.createVNode(VIcon, {
  7702. "key": "prepend-icon",
  7703. "icon": props.prependIcon,
  7704. "start": true
  7705. }, null), props.prependAvatar && vue.createVNode(VAvatar, {
  7706. "key": "prepend-avatar",
  7707. "image": props.prependAvatar,
  7708. "start": true
  7709. }, null)]) : vue.createVNode(VDefaultsProvider, {
  7710. "key": "prepend-defaults",
  7711. "disabled": !hasPrependMedia,
  7712. "defaults": {
  7713. VAvatar: {
  7714. image: props.prependAvatar,
  7715. start: true
  7716. },
  7717. VIcon: {
  7718. icon: props.prependIcon,
  7719. start: true
  7720. }
  7721. }
  7722. }, slots.prepend)]), vue.createVNode("div", {
  7723. "class": "v-chip__content",
  7724. "data-no-activator": ""
  7725. }, [slots.default?.({
  7726. isSelected: group?.isSelected.value,
  7727. selectedClass: group?.selectedClass.value,
  7728. select: group?.select,
  7729. toggle: group?.toggle,
  7730. value: group?.value.value,
  7731. disabled: props.disabled
  7732. }) ?? props.text]), hasAppend && vue.createVNode("div", {
  7733. "key": "append",
  7734. "class": "v-chip__append"
  7735. }, [!slots.append ? vue.createVNode(vue.Fragment, null, [props.appendIcon && vue.createVNode(VIcon, {
  7736. "key": "append-icon",
  7737. "end": true,
  7738. "icon": props.appendIcon
  7739. }, null), props.appendAvatar && vue.createVNode(VAvatar, {
  7740. "key": "append-avatar",
  7741. "end": true,
  7742. "image": props.appendAvatar
  7743. }, null)]) : vue.createVNode(VDefaultsProvider, {
  7744. "key": "append-defaults",
  7745. "disabled": !hasAppendMedia,
  7746. "defaults": {
  7747. VAvatar: {
  7748. end: true,
  7749. image: props.appendAvatar
  7750. },
  7751. VIcon: {
  7752. end: true,
  7753. icon: props.appendIcon
  7754. }
  7755. }
  7756. }, slots.append)]), hasClose && vue.createVNode("button", vue.mergeProps({
  7757. "key": "close",
  7758. "class": "v-chip__close",
  7759. "type": "button",
  7760. "data-testid": "close-chip"
  7761. }, closeProps.value), [!slots.close ? vue.createVNode(VIcon, {
  7762. "key": "close-icon",
  7763. "icon": props.closeIcon,
  7764. "size": "x-small"
  7765. }, null) : vue.createVNode(VDefaultsProvider, {
  7766. "key": "close-defaults",
  7767. "defaults": {
  7768. VIcon: {
  7769. icon: props.closeIcon,
  7770. size: 'x-small'
  7771. }
  7772. }
  7773. }, slots.close)])]
  7774. }), [[vue.resolveDirective("ripple"), isClickable.value && props.ripple, null]]);
  7775. };
  7776. }
  7777. });
  7778. // Utilities
  7779. // List
  7780. const ListKey = Symbol.for('vuetify:list');
  7781. function createList() {
  7782. const parent = vue.inject(ListKey, {
  7783. hasPrepend: vue.shallowRef(false),
  7784. updateHasPrepend: () => null
  7785. });
  7786. const data = {
  7787. hasPrepend: vue.shallowRef(false),
  7788. updateHasPrepend: value => {
  7789. if (value) data.hasPrepend.value = value;
  7790. }
  7791. };
  7792. vue.provide(ListKey, data);
  7793. return parent;
  7794. }
  7795. function useList() {
  7796. return vue.inject(ListKey, null);
  7797. }
  7798. /* eslint-disable sonarjs/no-identical-functions */
  7799. // Utilities
  7800. const independentActiveStrategy = mandatory => {
  7801. const strategy = {
  7802. activate: _ref => {
  7803. let {
  7804. id,
  7805. value,
  7806. activated
  7807. } = _ref;
  7808. id = vue.toRaw(id);
  7809. // When mandatory and we're trying to deselect when id
  7810. // is the only currently selected item then do nothing
  7811. if (mandatory && !value && activated.size === 1 && activated.has(id)) return activated;
  7812. if (value) {
  7813. activated.add(id);
  7814. } else {
  7815. activated.delete(id);
  7816. }
  7817. return activated;
  7818. },
  7819. in: (v, children, parents) => {
  7820. let set = new Set();
  7821. if (v != null) {
  7822. for (const id of wrapInArray(v)) {
  7823. set = strategy.activate({
  7824. id,
  7825. value: true,
  7826. activated: new Set(set),
  7827. children,
  7828. parents
  7829. });
  7830. }
  7831. }
  7832. return set;
  7833. },
  7834. out: v => {
  7835. return Array.from(v);
  7836. }
  7837. };
  7838. return strategy;
  7839. };
  7840. const independentSingleActiveStrategy = mandatory => {
  7841. const parentStrategy = independentActiveStrategy(mandatory);
  7842. const strategy = {
  7843. activate: _ref2 => {
  7844. let {
  7845. activated,
  7846. id,
  7847. ...rest
  7848. } = _ref2;
  7849. id = vue.toRaw(id);
  7850. const singleSelected = activated.has(id) ? new Set([id]) : new Set();
  7851. return parentStrategy.activate({
  7852. ...rest,
  7853. id,
  7854. activated: singleSelected
  7855. });
  7856. },
  7857. in: (v, children, parents) => {
  7858. let set = new Set();
  7859. if (v != null) {
  7860. const arr = wrapInArray(v);
  7861. if (arr.length) {
  7862. set = parentStrategy.in(arr.slice(0, 1), children, parents);
  7863. }
  7864. }
  7865. return set;
  7866. },
  7867. out: (v, children, parents) => {
  7868. return parentStrategy.out(v, children, parents);
  7869. }
  7870. };
  7871. return strategy;
  7872. };
  7873. const leafActiveStrategy = mandatory => {
  7874. const parentStrategy = independentActiveStrategy(mandatory);
  7875. const strategy = {
  7876. activate: _ref3 => {
  7877. let {
  7878. id,
  7879. activated,
  7880. children,
  7881. ...rest
  7882. } = _ref3;
  7883. id = vue.toRaw(id);
  7884. if (children.has(id)) return activated;
  7885. return parentStrategy.activate({
  7886. id,
  7887. activated,
  7888. children,
  7889. ...rest
  7890. });
  7891. },
  7892. in: parentStrategy.in,
  7893. out: parentStrategy.out
  7894. };
  7895. return strategy;
  7896. };
  7897. const leafSingleActiveStrategy = mandatory => {
  7898. const parentStrategy = independentSingleActiveStrategy(mandatory);
  7899. const strategy = {
  7900. activate: _ref4 => {
  7901. let {
  7902. id,
  7903. activated,
  7904. children,
  7905. ...rest
  7906. } = _ref4;
  7907. id = vue.toRaw(id);
  7908. if (children.has(id)) return activated;
  7909. return parentStrategy.activate({
  7910. id,
  7911. activated,
  7912. children,
  7913. ...rest
  7914. });
  7915. },
  7916. in: parentStrategy.in,
  7917. out: parentStrategy.out
  7918. };
  7919. return strategy;
  7920. };
  7921. const singleOpenStrategy = {
  7922. open: _ref => {
  7923. let {
  7924. id,
  7925. value,
  7926. opened,
  7927. parents
  7928. } = _ref;
  7929. if (value) {
  7930. const newOpened = new Set();
  7931. newOpened.add(id);
  7932. let parent = parents.get(id);
  7933. while (parent != null) {
  7934. newOpened.add(parent);
  7935. parent = parents.get(parent);
  7936. }
  7937. return newOpened;
  7938. } else {
  7939. opened.delete(id);
  7940. return opened;
  7941. }
  7942. },
  7943. select: () => null
  7944. };
  7945. const multipleOpenStrategy = {
  7946. open: _ref2 => {
  7947. let {
  7948. id,
  7949. value,
  7950. opened,
  7951. parents
  7952. } = _ref2;
  7953. if (value) {
  7954. let parent = parents.get(id);
  7955. opened.add(id);
  7956. while (parent != null && parent !== id) {
  7957. opened.add(parent);
  7958. parent = parents.get(parent);
  7959. }
  7960. return opened;
  7961. } else {
  7962. opened.delete(id);
  7963. }
  7964. return opened;
  7965. },
  7966. select: () => null
  7967. };
  7968. const listOpenStrategy = {
  7969. open: multipleOpenStrategy.open,
  7970. select: _ref3 => {
  7971. let {
  7972. id,
  7973. value,
  7974. opened,
  7975. parents
  7976. } = _ref3;
  7977. if (!value) return opened;
  7978. const path = [];
  7979. let parent = parents.get(id);
  7980. while (parent != null) {
  7981. path.push(parent);
  7982. parent = parents.get(parent);
  7983. }
  7984. return new Set(path);
  7985. }
  7986. };
  7987. /* eslint-disable sonarjs/no-identical-functions */
  7988. // Utilities
  7989. const independentSelectStrategy = mandatory => {
  7990. const strategy = {
  7991. select: _ref => {
  7992. let {
  7993. id,
  7994. value,
  7995. selected
  7996. } = _ref;
  7997. id = vue.toRaw(id);
  7998. // When mandatory and we're trying to deselect when id
  7999. // is the only currently selected item then do nothing
  8000. if (mandatory && !value) {
  8001. const on = Array.from(selected.entries()).reduce((arr, _ref2) => {
  8002. let [key, value] = _ref2;
  8003. if (value === 'on') arr.push(key);
  8004. return arr;
  8005. }, []);
  8006. if (on.length === 1 && on[0] === id) return selected;
  8007. }
  8008. selected.set(id, value ? 'on' : 'off');
  8009. return selected;
  8010. },
  8011. in: (v, children, parents) => {
  8012. let map = new Map();
  8013. for (const id of v || []) {
  8014. map = strategy.select({
  8015. id,
  8016. value: true,
  8017. selected: new Map(map),
  8018. children,
  8019. parents
  8020. });
  8021. }
  8022. return map;
  8023. },
  8024. out: v => {
  8025. const arr = [];
  8026. for (const [key, value] of v.entries()) {
  8027. if (value === 'on') arr.push(key);
  8028. }
  8029. return arr;
  8030. }
  8031. };
  8032. return strategy;
  8033. };
  8034. const independentSingleSelectStrategy = mandatory => {
  8035. const parentStrategy = independentSelectStrategy(mandatory);
  8036. const strategy = {
  8037. select: _ref3 => {
  8038. let {
  8039. selected,
  8040. id,
  8041. ...rest
  8042. } = _ref3;
  8043. id = vue.toRaw(id);
  8044. const singleSelected = selected.has(id) ? new Map([[id, selected.get(id)]]) : new Map();
  8045. return parentStrategy.select({
  8046. ...rest,
  8047. id,
  8048. selected: singleSelected
  8049. });
  8050. },
  8051. in: (v, children, parents) => {
  8052. let map = new Map();
  8053. if (v?.length) {
  8054. map = parentStrategy.in(v.slice(0, 1), children, parents);
  8055. }
  8056. return map;
  8057. },
  8058. out: (v, children, parents) => {
  8059. return parentStrategy.out(v, children, parents);
  8060. }
  8061. };
  8062. return strategy;
  8063. };
  8064. const leafSelectStrategy = mandatory => {
  8065. const parentStrategy = independentSelectStrategy(mandatory);
  8066. const strategy = {
  8067. select: _ref4 => {
  8068. let {
  8069. id,
  8070. selected,
  8071. children,
  8072. ...rest
  8073. } = _ref4;
  8074. id = vue.toRaw(id);
  8075. if (children.has(id)) return selected;
  8076. return parentStrategy.select({
  8077. id,
  8078. selected,
  8079. children,
  8080. ...rest
  8081. });
  8082. },
  8083. in: parentStrategy.in,
  8084. out: parentStrategy.out
  8085. };
  8086. return strategy;
  8087. };
  8088. const leafSingleSelectStrategy = mandatory => {
  8089. const parentStrategy = independentSingleSelectStrategy(mandatory);
  8090. const strategy = {
  8091. select: _ref5 => {
  8092. let {
  8093. id,
  8094. selected,
  8095. children,
  8096. ...rest
  8097. } = _ref5;
  8098. id = vue.toRaw(id);
  8099. if (children.has(id)) return selected;
  8100. return parentStrategy.select({
  8101. id,
  8102. selected,
  8103. children,
  8104. ...rest
  8105. });
  8106. },
  8107. in: parentStrategy.in,
  8108. out: parentStrategy.out
  8109. };
  8110. return strategy;
  8111. };
  8112. const classicSelectStrategy = mandatory => {
  8113. const strategy = {
  8114. select: _ref6 => {
  8115. let {
  8116. id,
  8117. value,
  8118. selected,
  8119. children,
  8120. parents
  8121. } = _ref6;
  8122. id = vue.toRaw(id);
  8123. const original = new Map(selected);
  8124. const items = [id];
  8125. while (items.length) {
  8126. const item = items.shift();
  8127. selected.set(vue.toRaw(item), value ? 'on' : 'off');
  8128. if (children.has(item)) {
  8129. items.push(...children.get(item));
  8130. }
  8131. }
  8132. let parent = vue.toRaw(parents.get(id));
  8133. while (parent) {
  8134. const childrenIds = children.get(parent);
  8135. const everySelected = childrenIds.every(cid => selected.get(vue.toRaw(cid)) === 'on');
  8136. const noneSelected = childrenIds.every(cid => !selected.has(vue.toRaw(cid)) || selected.get(vue.toRaw(cid)) === 'off');
  8137. selected.set(parent, everySelected ? 'on' : noneSelected ? 'off' : 'indeterminate');
  8138. parent = vue.toRaw(parents.get(parent));
  8139. }
  8140. // If mandatory and planned deselect results in no selected
  8141. // items then we can't do it, so return original state
  8142. if (mandatory && !value) {
  8143. const on = Array.from(selected.entries()).reduce((arr, _ref7) => {
  8144. let [key, value] = _ref7;
  8145. if (value === 'on') arr.push(key);
  8146. return arr;
  8147. }, []);
  8148. if (on.length === 0) return original;
  8149. }
  8150. return selected;
  8151. },
  8152. in: (v, children, parents) => {
  8153. let map = new Map();
  8154. for (const id of v || []) {
  8155. map = strategy.select({
  8156. id,
  8157. value: true,
  8158. selected: new Map(map),
  8159. children,
  8160. parents
  8161. });
  8162. }
  8163. return map;
  8164. },
  8165. out: (v, children) => {
  8166. const arr = [];
  8167. for (const [key, value] of v.entries()) {
  8168. if (value === 'on' && !children.has(key)) arr.push(key);
  8169. }
  8170. return arr;
  8171. }
  8172. };
  8173. return strategy;
  8174. };
  8175. // Composables
  8176. // Types
  8177. const VNestedSymbol = Symbol.for('vuetify:nested');
  8178. const emptyNested = {
  8179. id: vue.shallowRef(),
  8180. root: {
  8181. register: () => null,
  8182. unregister: () => null,
  8183. parents: vue.ref(new Map()),
  8184. children: vue.ref(new Map()),
  8185. open: () => null,
  8186. openOnSelect: () => null,
  8187. activate: () => null,
  8188. select: () => null,
  8189. activatable: vue.ref(false),
  8190. selectable: vue.ref(false),
  8191. opened: vue.ref(new Set()),
  8192. activated: vue.ref(new Set()),
  8193. selected: vue.ref(new Map()),
  8194. selectedValues: vue.ref([]),
  8195. getPath: () => []
  8196. }
  8197. };
  8198. const makeNestedProps = propsFactory({
  8199. activatable: Boolean,
  8200. selectable: Boolean,
  8201. activeStrategy: [String, Function, Object],
  8202. selectStrategy: [String, Function, Object],
  8203. openStrategy: [String, Object],
  8204. opened: null,
  8205. activated: null,
  8206. selected: null,
  8207. mandatory: Boolean
  8208. }, 'nested');
  8209. const useNested = props => {
  8210. let isUnmounted = false;
  8211. const children = vue.ref(new Map());
  8212. const parents = vue.ref(new Map());
  8213. const opened = useProxiedModel(props, 'opened', props.opened, v => new Set(v), v => [...v.values()]);
  8214. const activeStrategy = vue.computed(() => {
  8215. if (typeof props.activeStrategy === 'object') return props.activeStrategy;
  8216. if (typeof props.activeStrategy === 'function') return props.activeStrategy(props.mandatory);
  8217. switch (props.activeStrategy) {
  8218. case 'leaf':
  8219. return leafActiveStrategy(props.mandatory);
  8220. case 'single-leaf':
  8221. return leafSingleActiveStrategy(props.mandatory);
  8222. case 'independent':
  8223. return independentActiveStrategy(props.mandatory);
  8224. case 'single-independent':
  8225. default:
  8226. return independentSingleActiveStrategy(props.mandatory);
  8227. }
  8228. });
  8229. const selectStrategy = vue.computed(() => {
  8230. if (typeof props.selectStrategy === 'object') return props.selectStrategy;
  8231. if (typeof props.selectStrategy === 'function') return props.selectStrategy(props.mandatory);
  8232. switch (props.selectStrategy) {
  8233. case 'single-leaf':
  8234. return leafSingleSelectStrategy(props.mandatory);
  8235. case 'leaf':
  8236. return leafSelectStrategy(props.mandatory);
  8237. case 'independent':
  8238. return independentSelectStrategy(props.mandatory);
  8239. case 'single-independent':
  8240. return independentSingleSelectStrategy(props.mandatory);
  8241. case 'classic':
  8242. default:
  8243. return classicSelectStrategy(props.mandatory);
  8244. }
  8245. });
  8246. const openStrategy = vue.computed(() => {
  8247. if (typeof props.openStrategy === 'object') return props.openStrategy;
  8248. switch (props.openStrategy) {
  8249. case 'list':
  8250. return listOpenStrategy;
  8251. case 'single':
  8252. return singleOpenStrategy;
  8253. case 'multiple':
  8254. default:
  8255. return multipleOpenStrategy;
  8256. }
  8257. });
  8258. const activated = useProxiedModel(props, 'activated', props.activated, v => activeStrategy.value.in(v, children.value, parents.value), v => activeStrategy.value.out(v, children.value, parents.value));
  8259. 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));
  8260. vue.onBeforeUnmount(() => {
  8261. isUnmounted = true;
  8262. });
  8263. function getPath(id) {
  8264. const path = [];
  8265. let parent = id;
  8266. while (parent != null) {
  8267. path.unshift(parent);
  8268. parent = parents.value.get(parent);
  8269. }
  8270. return path;
  8271. }
  8272. const vm = getCurrentInstance('nested');
  8273. const nodeIds = new Set();
  8274. const nested = {
  8275. id: vue.shallowRef(),
  8276. root: {
  8277. opened,
  8278. activatable: vue.toRef(props, 'activatable'),
  8279. selectable: vue.toRef(props, 'selectable'),
  8280. activated,
  8281. selected,
  8282. selectedValues: vue.computed(() => {
  8283. const arr = [];
  8284. for (const [key, value] of selected.value.entries()) {
  8285. if (value === 'on') arr.push(key);
  8286. }
  8287. return arr;
  8288. }),
  8289. register: (id, parentId, isGroup) => {
  8290. if (nodeIds.has(id)) {
  8291. const path = getPath(id).map(String).join(' -> ');
  8292. const newPath = getPath(parentId).concat(id).map(String).join(' -> ');
  8293. consoleError(`Multiple nodes with the same ID\n\t${path}\n\t${newPath}`);
  8294. return;
  8295. } else {
  8296. nodeIds.add(id);
  8297. }
  8298. parentId && id !== parentId && parents.value.set(id, parentId);
  8299. isGroup && children.value.set(id, []);
  8300. if (parentId != null) {
  8301. children.value.set(parentId, [...(children.value.get(parentId) || []), id]);
  8302. }
  8303. },
  8304. unregister: id => {
  8305. if (isUnmounted) return;
  8306. nodeIds.delete(id);
  8307. children.value.delete(id);
  8308. const parent = parents.value.get(id);
  8309. if (parent) {
  8310. const list = children.value.get(parent) ?? [];
  8311. children.value.set(parent, list.filter(child => child !== id));
  8312. }
  8313. parents.value.delete(id);
  8314. },
  8315. open: (id, value, event) => {
  8316. vm.emit('click:open', {
  8317. id,
  8318. value,
  8319. path: getPath(id),
  8320. event
  8321. });
  8322. const newOpened = openStrategy.value.open({
  8323. id,
  8324. value,
  8325. opened: new Set(opened.value),
  8326. children: children.value,
  8327. parents: parents.value,
  8328. event
  8329. });
  8330. newOpened && (opened.value = newOpened);
  8331. },
  8332. openOnSelect: (id, value, event) => {
  8333. const newOpened = openStrategy.value.select({
  8334. id,
  8335. value,
  8336. selected: new Map(selected.value),
  8337. opened: new Set(opened.value),
  8338. children: children.value,
  8339. parents: parents.value,
  8340. event
  8341. });
  8342. newOpened && (opened.value = newOpened);
  8343. },
  8344. select: (id, value, event) => {
  8345. vm.emit('click:select', {
  8346. id,
  8347. value,
  8348. path: getPath(id),
  8349. event
  8350. });
  8351. const newSelected = selectStrategy.value.select({
  8352. id,
  8353. value,
  8354. selected: new Map(selected.value),
  8355. children: children.value,
  8356. parents: parents.value,
  8357. event
  8358. });
  8359. newSelected && (selected.value = newSelected);
  8360. nested.root.openOnSelect(id, value, event);
  8361. },
  8362. activate: (id, value, event) => {
  8363. if (!props.activatable) {
  8364. return nested.root.select(id, true, event);
  8365. }
  8366. vm.emit('click:activate', {
  8367. id,
  8368. value,
  8369. path: getPath(id),
  8370. event
  8371. });
  8372. const newActivated = activeStrategy.value.activate({
  8373. id,
  8374. value,
  8375. activated: new Set(activated.value),
  8376. children: children.value,
  8377. parents: parents.value,
  8378. event
  8379. });
  8380. newActivated && (activated.value = newActivated);
  8381. },
  8382. children,
  8383. parents,
  8384. getPath
  8385. }
  8386. };
  8387. vue.provide(VNestedSymbol, nested);
  8388. return nested.root;
  8389. };
  8390. const useNestedItem = (id, isGroup) => {
  8391. const parent = vue.inject(VNestedSymbol, emptyNested);
  8392. const uidSymbol = Symbol(getUid());
  8393. const computedId = vue.computed(() => id.value !== undefined ? id.value : uidSymbol);
  8394. const item = {
  8395. ...parent,
  8396. id: computedId,
  8397. open: (open, e) => parent.root.open(computedId.value, open, e),
  8398. openOnSelect: (open, e) => parent.root.openOnSelect(computedId.value, open, e),
  8399. isOpen: vue.computed(() => parent.root.opened.value.has(computedId.value)),
  8400. parent: vue.computed(() => parent.root.parents.value.get(computedId.value)),
  8401. activate: (activated, e) => parent.root.activate(computedId.value, activated, e),
  8402. isActivated: vue.computed(() => parent.root.activated.value.has(vue.toRaw(computedId.value))),
  8403. select: (selected, e) => parent.root.select(computedId.value, selected, e),
  8404. isSelected: vue.computed(() => parent.root.selected.value.get(vue.toRaw(computedId.value)) === 'on'),
  8405. isIndeterminate: vue.computed(() => parent.root.selected.value.get(computedId.value) === 'indeterminate'),
  8406. isLeaf: vue.computed(() => !parent.root.children.value.get(computedId.value)),
  8407. isGroupActivator: parent.isGroupActivator
  8408. };
  8409. vue.onBeforeMount(() => {
  8410. !parent.isGroupActivator && parent.root.register(computedId.value, parent.id.value, isGroup);
  8411. });
  8412. vue.onBeforeUnmount(() => {
  8413. !parent.isGroupActivator && parent.root.unregister(computedId.value);
  8414. });
  8415. isGroup && vue.provide(VNestedSymbol, item);
  8416. return item;
  8417. };
  8418. const useNestedGroupActivator = () => {
  8419. const parent = vue.inject(VNestedSymbol, emptyNested);
  8420. vue.provide(VNestedSymbol, {
  8421. ...parent,
  8422. isGroupActivator: true
  8423. });
  8424. };
  8425. const VListGroupActivator = defineComponent({
  8426. name: 'VListGroupActivator',
  8427. setup(_, _ref) {
  8428. let {
  8429. slots
  8430. } = _ref;
  8431. useNestedGroupActivator();
  8432. return () => slots.default?.();
  8433. }
  8434. });
  8435. const makeVListGroupProps = propsFactory({
  8436. /* @deprecated */
  8437. activeColor: String,
  8438. baseColor: String,
  8439. color: String,
  8440. collapseIcon: {
  8441. type: IconValue,
  8442. default: '$collapse'
  8443. },
  8444. expandIcon: {
  8445. type: IconValue,
  8446. default: '$expand'
  8447. },
  8448. prependIcon: IconValue,
  8449. appendIcon: IconValue,
  8450. fluid: Boolean,
  8451. subgroup: Boolean,
  8452. title: String,
  8453. value: null,
  8454. ...makeComponentProps(),
  8455. ...makeTagProps()
  8456. }, 'VListGroup');
  8457. const VListGroup = genericComponent()({
  8458. name: 'VListGroup',
  8459. props: makeVListGroupProps(),
  8460. setup(props, _ref2) {
  8461. let {
  8462. slots
  8463. } = _ref2;
  8464. const {
  8465. isOpen,
  8466. open,
  8467. id: _id
  8468. } = useNestedItem(vue.toRef(props, 'value'), true);
  8469. const id = vue.computed(() => `v-list-group--id-${String(_id.value)}`);
  8470. const list = useList();
  8471. const {
  8472. isBooted
  8473. } = useSsrBoot();
  8474. function onClick(e) {
  8475. e.stopPropagation();
  8476. open(!isOpen.value, e);
  8477. }
  8478. const activatorProps = vue.computed(() => ({
  8479. onClick,
  8480. class: 'v-list-group__header',
  8481. id: id.value
  8482. }));
  8483. const toggleIcon = vue.computed(() => isOpen.value ? props.collapseIcon : props.expandIcon);
  8484. const activatorDefaults = vue.computed(() => ({
  8485. VListItem: {
  8486. active: isOpen.value,
  8487. activeColor: props.activeColor,
  8488. baseColor: props.baseColor,
  8489. color: props.color,
  8490. prependIcon: props.prependIcon || props.subgroup && toggleIcon.value,
  8491. appendIcon: props.appendIcon || !props.subgroup && toggleIcon.value,
  8492. title: props.title,
  8493. value: props.value
  8494. }
  8495. }));
  8496. useRender(() => vue.createVNode(props.tag, {
  8497. "class": ['v-list-group', {
  8498. 'v-list-group--prepend': list?.hasPrepend.value,
  8499. 'v-list-group--fluid': props.fluid,
  8500. 'v-list-group--subgroup': props.subgroup,
  8501. 'v-list-group--open': isOpen.value
  8502. }, props.class],
  8503. "style": props.style
  8504. }, {
  8505. default: () => [slots.activator && vue.createVNode(VDefaultsProvider, {
  8506. "defaults": activatorDefaults.value
  8507. }, {
  8508. default: () => [vue.createVNode(VListGroupActivator, null, {
  8509. default: () => [slots.activator({
  8510. props: activatorProps.value,
  8511. isOpen: isOpen.value
  8512. })]
  8513. })]
  8514. }), vue.createVNode(MaybeTransition, {
  8515. "transition": {
  8516. component: VExpandTransition
  8517. },
  8518. "disabled": !isBooted.value
  8519. }, {
  8520. default: () => [vue.withDirectives(vue.createVNode("div", {
  8521. "class": "v-list-group__items",
  8522. "role": "group",
  8523. "aria-labelledby": id.value
  8524. }, [slots.default?.()]), [[vue.vShow, isOpen.value]])]
  8525. })]
  8526. }));
  8527. return {
  8528. isOpen
  8529. };
  8530. }
  8531. });
  8532. const makeVListItemSubtitleProps = propsFactory({
  8533. opacity: [Number, String],
  8534. ...makeComponentProps(),
  8535. ...makeTagProps()
  8536. }, 'VListItemSubtitle');
  8537. const VListItemSubtitle = genericComponent()({
  8538. name: 'VListItemSubtitle',
  8539. props: makeVListItemSubtitleProps(),
  8540. setup(props, _ref) {
  8541. let {
  8542. slots
  8543. } = _ref;
  8544. useRender(() => vue.createVNode(props.tag, {
  8545. "class": ['v-list-item-subtitle', props.class],
  8546. "style": [{
  8547. '--v-list-item-subtitle-opacity': props.opacity
  8548. }, props.style]
  8549. }, slots));
  8550. return {};
  8551. }
  8552. });
  8553. // Utilities
  8554. const VListItemTitle = createSimpleFunctional('v-list-item-title');
  8555. // Types
  8556. const makeVListItemProps = propsFactory({
  8557. active: {
  8558. type: Boolean,
  8559. default: undefined
  8560. },
  8561. activeClass: String,
  8562. /* @deprecated */
  8563. activeColor: String,
  8564. appendAvatar: String,
  8565. appendIcon: IconValue,
  8566. baseColor: String,
  8567. disabled: Boolean,
  8568. lines: [Boolean, String],
  8569. link: {
  8570. type: Boolean,
  8571. default: undefined
  8572. },
  8573. nav: Boolean,
  8574. prependAvatar: String,
  8575. prependIcon: IconValue,
  8576. ripple: {
  8577. type: [Boolean, Object],
  8578. default: true
  8579. },
  8580. slim: Boolean,
  8581. subtitle: [String, Number],
  8582. title: [String, Number],
  8583. value: null,
  8584. onClick: EventProp(),
  8585. onClickOnce: EventProp(),
  8586. ...makeBorderProps(),
  8587. ...makeComponentProps(),
  8588. ...makeDensityProps(),
  8589. ...makeDimensionProps(),
  8590. ...makeElevationProps(),
  8591. ...makeRoundedProps(),
  8592. ...makeRouterProps(),
  8593. ...makeTagProps(),
  8594. ...makeThemeProps(),
  8595. ...makeVariantProps({
  8596. variant: 'text'
  8597. })
  8598. }, 'VListItem');
  8599. const VListItem = genericComponent()({
  8600. name: 'VListItem',
  8601. directives: {
  8602. Ripple
  8603. },
  8604. props: makeVListItemProps(),
  8605. emits: {
  8606. click: e => true
  8607. },
  8608. setup(props, _ref) {
  8609. let {
  8610. attrs,
  8611. slots,
  8612. emit
  8613. } = _ref;
  8614. const link = useLink(props, attrs);
  8615. const id = vue.computed(() => props.value === undefined ? link.href.value : props.value);
  8616. const {
  8617. activate,
  8618. isActivated,
  8619. select,
  8620. isOpen,
  8621. isSelected,
  8622. isIndeterminate,
  8623. isGroupActivator,
  8624. root,
  8625. parent,
  8626. openOnSelect,
  8627. id: uid
  8628. } = useNestedItem(id, false);
  8629. const list = useList();
  8630. const isActive = vue.computed(() => props.active !== false && (props.active || link.isActive?.value || (root.activatable.value ? isActivated.value : isSelected.value)));
  8631. const isLink = vue.computed(() => props.link !== false && link.isLink.value);
  8632. const isSelectable = vue.computed(() => !!list && (root.selectable.value || root.activatable.value || props.value != null));
  8633. const isClickable = vue.computed(() => !props.disabled && props.link !== false && (props.link || link.isClickable.value || isSelectable.value));
  8634. const roundedProps = vue.computed(() => props.rounded || props.nav);
  8635. const color = vue.computed(() => props.color ?? props.activeColor);
  8636. const variantProps = vue.computed(() => ({
  8637. color: isActive.value ? color.value ?? props.baseColor : props.baseColor,
  8638. variant: props.variant
  8639. }));
  8640. // useNestedItem doesn't call register until beforeMount,
  8641. // so this can't be an immediate watcher as we don't know parent yet
  8642. vue.watch(() => link.isActive?.value, val => {
  8643. if (!val) return;
  8644. handleActiveLink();
  8645. });
  8646. vue.onBeforeMount(() => {
  8647. if (link.isActive?.value) handleActiveLink();
  8648. });
  8649. function handleActiveLink() {
  8650. if (parent.value != null) {
  8651. root.open(parent.value, true);
  8652. }
  8653. openOnSelect(true);
  8654. }
  8655. const {
  8656. themeClasses
  8657. } = provideTheme(props);
  8658. const {
  8659. borderClasses
  8660. } = useBorder(props);
  8661. const {
  8662. colorClasses,
  8663. colorStyles,
  8664. variantClasses
  8665. } = useVariant(variantProps);
  8666. const {
  8667. densityClasses
  8668. } = useDensity(props);
  8669. const {
  8670. dimensionStyles
  8671. } = useDimension(props);
  8672. const {
  8673. elevationClasses
  8674. } = useElevation(props);
  8675. const {
  8676. roundedClasses
  8677. } = useRounded(roundedProps);
  8678. const lineClasses = vue.computed(() => props.lines ? `v-list-item--${props.lines}-line` : undefined);
  8679. const slotProps = vue.computed(() => ({
  8680. isActive: isActive.value,
  8681. select,
  8682. isOpen: isOpen.value,
  8683. isSelected: isSelected.value,
  8684. isIndeterminate: isIndeterminate.value
  8685. }));
  8686. function onClick(e) {
  8687. emit('click', e);
  8688. if (!isClickable.value) return;
  8689. link.navigate?.(e);
  8690. if (isGroupActivator) return;
  8691. if (root.activatable.value) {
  8692. activate(!isActivated.value, e);
  8693. } else if (root.selectable.value) {
  8694. select(!isSelected.value, e);
  8695. } else if (props.value != null) {
  8696. select(!isSelected.value, e);
  8697. }
  8698. }
  8699. function onKeyDown(e) {
  8700. if (e.key === 'Enter' || e.key === ' ') {
  8701. e.preventDefault();
  8702. e.target.dispatchEvent(new MouseEvent('click', e));
  8703. }
  8704. }
  8705. useRender(() => {
  8706. const Tag = isLink.value ? 'a' : props.tag;
  8707. const hasTitle = slots.title || props.title != null;
  8708. const hasSubtitle = slots.subtitle || props.subtitle != null;
  8709. const hasAppendMedia = !!(props.appendAvatar || props.appendIcon);
  8710. const hasAppend = !!(hasAppendMedia || slots.append);
  8711. const hasPrependMedia = !!(props.prependAvatar || props.prependIcon);
  8712. const hasPrepend = !!(hasPrependMedia || slots.prepend);
  8713. list?.updateHasPrepend(hasPrepend);
  8714. if (props.activeColor) {
  8715. deprecate('active-color', ['color', 'base-color']);
  8716. }
  8717. return vue.withDirectives(vue.createVNode(Tag, vue.mergeProps({
  8718. "class": ['v-list-item', {
  8719. 'v-list-item--active': isActive.value,
  8720. 'v-list-item--disabled': props.disabled,
  8721. 'v-list-item--link': isClickable.value,
  8722. 'v-list-item--nav': props.nav,
  8723. 'v-list-item--prepend': !hasPrepend && list?.hasPrepend.value,
  8724. 'v-list-item--slim': props.slim,
  8725. [`${props.activeClass}`]: props.activeClass && isActive.value
  8726. }, themeClasses.value, borderClasses.value, colorClasses.value, densityClasses.value, elevationClasses.value, lineClasses.value, roundedClasses.value, variantClasses.value, props.class],
  8727. "style": [colorStyles.value, dimensionStyles.value, props.style],
  8728. "tabindex": isClickable.value ? list ? -2 : 0 : undefined,
  8729. "aria-selected": isSelectable.value ? root.activatable.value ? isActivated.value : root.selectable.value ? isSelected.value : isActive.value : undefined,
  8730. "onClick": onClick,
  8731. "onKeydown": isClickable.value && !isLink.value && onKeyDown
  8732. }, link.linkProps), {
  8733. default: () => [genOverlays(isClickable.value || isActive.value, 'v-list-item'), hasPrepend && vue.createVNode("div", {
  8734. "key": "prepend",
  8735. "class": "v-list-item__prepend"
  8736. }, [!slots.prepend ? vue.createVNode(vue.Fragment, null, [props.prependAvatar && vue.createVNode(VAvatar, {
  8737. "key": "prepend-avatar",
  8738. "density": props.density,
  8739. "image": props.prependAvatar
  8740. }, null), props.prependIcon && vue.createVNode(VIcon, {
  8741. "key": "prepend-icon",
  8742. "density": props.density,
  8743. "icon": props.prependIcon
  8744. }, null)]) : vue.createVNode(VDefaultsProvider, {
  8745. "key": "prepend-defaults",
  8746. "disabled": !hasPrependMedia,
  8747. "defaults": {
  8748. VAvatar: {
  8749. density: props.density,
  8750. image: props.prependAvatar
  8751. },
  8752. VIcon: {
  8753. density: props.density,
  8754. icon: props.prependIcon
  8755. },
  8756. VListItemAction: {
  8757. start: true
  8758. }
  8759. }
  8760. }, {
  8761. default: () => [slots.prepend?.(slotProps.value)]
  8762. }), vue.createVNode("div", {
  8763. "class": "v-list-item__spacer"
  8764. }, null)]), vue.createVNode("div", {
  8765. "class": "v-list-item__content",
  8766. "data-no-activator": ""
  8767. }, [hasTitle && vue.createVNode(VListItemTitle, {
  8768. "key": "title"
  8769. }, {
  8770. default: () => [slots.title?.({
  8771. title: props.title
  8772. }) ?? props.title]
  8773. }), hasSubtitle && vue.createVNode(VListItemSubtitle, {
  8774. "key": "subtitle"
  8775. }, {
  8776. default: () => [slots.subtitle?.({
  8777. subtitle: props.subtitle
  8778. }) ?? props.subtitle]
  8779. }), slots.default?.(slotProps.value)]), hasAppend && vue.createVNode("div", {
  8780. "key": "append",
  8781. "class": "v-list-item__append"
  8782. }, [!slots.append ? vue.createVNode(vue.Fragment, null, [props.appendIcon && vue.createVNode(VIcon, {
  8783. "key": "append-icon",
  8784. "density": props.density,
  8785. "icon": props.appendIcon
  8786. }, null), props.appendAvatar && vue.createVNode(VAvatar, {
  8787. "key": "append-avatar",
  8788. "density": props.density,
  8789. "image": props.appendAvatar
  8790. }, null)]) : vue.createVNode(VDefaultsProvider, {
  8791. "key": "append-defaults",
  8792. "disabled": !hasAppendMedia,
  8793. "defaults": {
  8794. VAvatar: {
  8795. density: props.density,
  8796. image: props.appendAvatar
  8797. },
  8798. VIcon: {
  8799. density: props.density,
  8800. icon: props.appendIcon
  8801. },
  8802. VListItemAction: {
  8803. end: true
  8804. }
  8805. }
  8806. }, {
  8807. default: () => [slots.append?.(slotProps.value)]
  8808. }), vue.createVNode("div", {
  8809. "class": "v-list-item__spacer"
  8810. }, null)])]
  8811. }), [[vue.resolveDirective("ripple"), isClickable.value && props.ripple]]);
  8812. });
  8813. return {
  8814. activate,
  8815. isActivated,
  8816. isGroupActivator,
  8817. isSelected,
  8818. list,
  8819. select,
  8820. root,
  8821. id: uid
  8822. };
  8823. }
  8824. });
  8825. const makeVListSubheaderProps = propsFactory({
  8826. color: String,
  8827. inset: Boolean,
  8828. sticky: Boolean,
  8829. title: String,
  8830. ...makeComponentProps(),
  8831. ...makeTagProps()
  8832. }, 'VListSubheader');
  8833. const VListSubheader = genericComponent()({
  8834. name: 'VListSubheader',
  8835. props: makeVListSubheaderProps(),
  8836. setup(props, _ref) {
  8837. let {
  8838. slots
  8839. } = _ref;
  8840. const {
  8841. textColorClasses,
  8842. textColorStyles
  8843. } = useTextColor(vue.toRef(props, 'color'));
  8844. useRender(() => {
  8845. const hasText = !!(slots.default || props.title);
  8846. return vue.createVNode(props.tag, {
  8847. "class": ['v-list-subheader', {
  8848. 'v-list-subheader--inset': props.inset,
  8849. 'v-list-subheader--sticky': props.sticky
  8850. }, textColorClasses.value, props.class],
  8851. "style": [{
  8852. textColorStyles
  8853. }, props.style]
  8854. }, {
  8855. default: () => [hasText && vue.createVNode("div", {
  8856. "class": "v-list-subheader__text"
  8857. }, [slots.default?.() ?? props.title])]
  8858. });
  8859. });
  8860. return {};
  8861. }
  8862. });
  8863. const makeVDividerProps = propsFactory({
  8864. color: String,
  8865. inset: Boolean,
  8866. length: [Number, String],
  8867. opacity: [Number, String],
  8868. thickness: [Number, String],
  8869. vertical: Boolean,
  8870. ...makeComponentProps(),
  8871. ...makeThemeProps()
  8872. }, 'VDivider');
  8873. const VDivider = genericComponent()({
  8874. name: 'VDivider',
  8875. props: makeVDividerProps(),
  8876. setup(props, _ref) {
  8877. let {
  8878. attrs,
  8879. slots
  8880. } = _ref;
  8881. const {
  8882. themeClasses
  8883. } = provideTheme(props);
  8884. const {
  8885. textColorClasses,
  8886. textColorStyles
  8887. } = useTextColor(vue.toRef(props, 'color'));
  8888. const dividerStyles = vue.computed(() => {
  8889. const styles = {};
  8890. if (props.length) {
  8891. styles[props.vertical ? 'height' : 'width'] = convertToUnit(props.length);
  8892. }
  8893. if (props.thickness) {
  8894. styles[props.vertical ? 'borderRightWidth' : 'borderTopWidth'] = convertToUnit(props.thickness);
  8895. }
  8896. return styles;
  8897. });
  8898. useRender(() => {
  8899. const divider = vue.createVNode("hr", {
  8900. "class": [{
  8901. 'v-divider': true,
  8902. 'v-divider--inset': props.inset,
  8903. 'v-divider--vertical': props.vertical
  8904. }, themeClasses.value, textColorClasses.value, props.class],
  8905. "style": [dividerStyles.value, textColorStyles.value, {
  8906. '--v-border-opacity': props.opacity
  8907. }, props.style],
  8908. "aria-orientation": !attrs.role || attrs.role === 'separator' ? props.vertical ? 'vertical' : 'horizontal' : undefined,
  8909. "role": `${attrs.role || 'separator'}`
  8910. }, null);
  8911. if (!slots.default) return divider;
  8912. return vue.createVNode("div", {
  8913. "class": ['v-divider__wrapper', {
  8914. 'v-divider__wrapper--vertical': props.vertical,
  8915. 'v-divider__wrapper--inset': props.inset
  8916. }]
  8917. }, [divider, vue.createVNode("div", {
  8918. "class": "v-divider__content"
  8919. }, [slots.default()]), divider]);
  8920. });
  8921. return {};
  8922. }
  8923. });
  8924. // Types
  8925. const makeVListChildrenProps = propsFactory({
  8926. items: Array,
  8927. returnObject: Boolean
  8928. }, 'VListChildren');
  8929. const VListChildren = genericComponent()({
  8930. name: 'VListChildren',
  8931. props: makeVListChildrenProps(),
  8932. setup(props, _ref) {
  8933. let {
  8934. slots
  8935. } = _ref;
  8936. createList();
  8937. return () => slots.default?.() ?? props.items?.map(_ref2 => {
  8938. let {
  8939. children,
  8940. props: itemProps,
  8941. type,
  8942. raw: item
  8943. } = _ref2;
  8944. if (type === 'divider') {
  8945. return slots.divider?.({
  8946. props: itemProps
  8947. }) ?? vue.createVNode(VDivider, itemProps, null);
  8948. }
  8949. if (type === 'subheader') {
  8950. return slots.subheader?.({
  8951. props: itemProps
  8952. }) ?? vue.createVNode(VListSubheader, itemProps, null);
  8953. }
  8954. const slotsWithItem = {
  8955. subtitle: slots.subtitle ? slotProps => slots.subtitle?.({
  8956. ...slotProps,
  8957. item
  8958. }) : undefined,
  8959. prepend: slots.prepend ? slotProps => slots.prepend?.({
  8960. ...slotProps,
  8961. item
  8962. }) : undefined,
  8963. append: slots.append ? slotProps => slots.append?.({
  8964. ...slotProps,
  8965. item
  8966. }) : undefined,
  8967. title: slots.title ? slotProps => slots.title?.({
  8968. ...slotProps,
  8969. item
  8970. }) : undefined
  8971. };
  8972. const listGroupProps = VListGroup.filterProps(itemProps);
  8973. return children ? vue.createVNode(VListGroup, vue.mergeProps({
  8974. "value": itemProps?.value
  8975. }, listGroupProps), {
  8976. activator: _ref3 => {
  8977. let {
  8978. props: activatorProps
  8979. } = _ref3;
  8980. const listItemProps = {
  8981. ...itemProps,
  8982. ...activatorProps,
  8983. value: props.returnObject ? item : itemProps.value
  8984. };
  8985. return slots.header ? slots.header({
  8986. props: listItemProps
  8987. }) : vue.createVNode(VListItem, listItemProps, slotsWithItem);
  8988. },
  8989. default: () => vue.createVNode(VListChildren, {
  8990. "items": children,
  8991. "returnObject": props.returnObject
  8992. }, slots)
  8993. }) : slots.item ? slots.item({
  8994. props: itemProps
  8995. }) : vue.createVNode(VListItem, vue.mergeProps(itemProps, {
  8996. "value": props.returnObject ? item : itemProps.value
  8997. }), slotsWithItem);
  8998. });
  8999. }
  9000. });
  9001. // Utilities
  9002. // Types
  9003. // Composables
  9004. const makeItemsProps = propsFactory({
  9005. items: {
  9006. type: Array,
  9007. default: () => []
  9008. },
  9009. itemTitle: {
  9010. type: [String, Array, Function],
  9011. default: 'title'
  9012. },
  9013. itemValue: {
  9014. type: [String, Array, Function],
  9015. default: 'value'
  9016. },
  9017. itemChildren: {
  9018. type: [Boolean, String, Array, Function],
  9019. default: 'children'
  9020. },
  9021. itemProps: {
  9022. type: [Boolean, String, Array, Function],
  9023. default: 'props'
  9024. },
  9025. returnObject: Boolean,
  9026. valueComparator: {
  9027. type: Function,
  9028. default: deepEqual
  9029. }
  9030. }, 'list-items');
  9031. function transformItem$3(props, item) {
  9032. const title = getPropertyFromItem(item, props.itemTitle, item);
  9033. const value = getPropertyFromItem(item, props.itemValue, title);
  9034. const children = getPropertyFromItem(item, props.itemChildren);
  9035. const itemProps = props.itemProps === true ? typeof item === 'object' && item != null && !Array.isArray(item) ? 'children' in item ? omit(item, ['children']) : item : undefined : getPropertyFromItem(item, props.itemProps);
  9036. const _props = {
  9037. title,
  9038. value,
  9039. ...itemProps
  9040. };
  9041. return {
  9042. title: String(_props.title ?? ''),
  9043. value: _props.value,
  9044. props: _props,
  9045. children: Array.isArray(children) ? transformItems$3(props, children) : undefined,
  9046. raw: item
  9047. };
  9048. }
  9049. function transformItems$3(props, items) {
  9050. const array = [];
  9051. for (const item of items) {
  9052. array.push(transformItem$3(props, item));
  9053. }
  9054. return array;
  9055. }
  9056. function useItems(props) {
  9057. const items = vue.computed(() => transformItems$3(props, props.items));
  9058. const hasNullItem = vue.computed(() => items.value.some(item => item.value === null));
  9059. function transformIn(value) {
  9060. if (!hasNullItem.value) {
  9061. // When the model value is null, return an InternalItem
  9062. // based on null only if null is one of the items
  9063. value = value.filter(v => v !== null);
  9064. }
  9065. return value.map(v => {
  9066. if (props.returnObject && typeof v === 'string') {
  9067. // String model value means value is a custom input value from combobox
  9068. // Don't look up existing items if the model value is a string
  9069. return transformItem$3(props, v);
  9070. }
  9071. return items.value.find(item => props.valueComparator(v, item.value)) || transformItem$3(props, v);
  9072. });
  9073. }
  9074. function transformOut(value) {
  9075. return props.returnObject ? value.map(_ref => {
  9076. let {
  9077. raw
  9078. } = _ref;
  9079. return raw;
  9080. }) : value.map(_ref2 => {
  9081. let {
  9082. value
  9083. } = _ref2;
  9084. return value;
  9085. });
  9086. }
  9087. return {
  9088. items,
  9089. transformIn,
  9090. transformOut
  9091. };
  9092. }
  9093. // Types
  9094. function isPrimitive(value) {
  9095. return typeof value === 'string' || typeof value === 'number' || typeof value === 'boolean';
  9096. }
  9097. function transformItem$2(props, item) {
  9098. const type = getPropertyFromItem(item, props.itemType, 'item');
  9099. const title = isPrimitive(item) ? item : getPropertyFromItem(item, props.itemTitle);
  9100. const value = getPropertyFromItem(item, props.itemValue, undefined);
  9101. const children = getPropertyFromItem(item, props.itemChildren);
  9102. const itemProps = props.itemProps === true ? omit(item, ['children']) : getPropertyFromItem(item, props.itemProps);
  9103. const _props = {
  9104. title,
  9105. value,
  9106. ...itemProps
  9107. };
  9108. return {
  9109. type,
  9110. title: _props.title,
  9111. value: _props.value,
  9112. props: _props,
  9113. children: type === 'item' && children ? transformItems$2(props, children) : undefined,
  9114. raw: item
  9115. };
  9116. }
  9117. function transformItems$2(props, items) {
  9118. const array = [];
  9119. for (const item of items) {
  9120. array.push(transformItem$2(props, item));
  9121. }
  9122. return array;
  9123. }
  9124. function useListItems(props) {
  9125. const items = vue.computed(() => transformItems$2(props, props.items));
  9126. return {
  9127. items
  9128. };
  9129. }
  9130. const makeVListProps = propsFactory({
  9131. baseColor: String,
  9132. /* @deprecated */
  9133. activeColor: String,
  9134. activeClass: String,
  9135. bgColor: String,
  9136. disabled: Boolean,
  9137. expandIcon: IconValue,
  9138. collapseIcon: IconValue,
  9139. lines: {
  9140. type: [Boolean, String],
  9141. default: 'one'
  9142. },
  9143. slim: Boolean,
  9144. nav: Boolean,
  9145. 'onClick:open': EventProp(),
  9146. 'onClick:select': EventProp(),
  9147. 'onUpdate:opened': EventProp(),
  9148. ...makeNestedProps({
  9149. selectStrategy: 'single-leaf',
  9150. openStrategy: 'list'
  9151. }),
  9152. ...makeBorderProps(),
  9153. ...makeComponentProps(),
  9154. ...makeDensityProps(),
  9155. ...makeDimensionProps(),
  9156. ...makeElevationProps(),
  9157. itemType: {
  9158. type: String,
  9159. default: 'type'
  9160. },
  9161. ...makeItemsProps(),
  9162. ...makeRoundedProps(),
  9163. ...makeTagProps(),
  9164. ...makeThemeProps(),
  9165. ...makeVariantProps({
  9166. variant: 'text'
  9167. })
  9168. }, 'VList');
  9169. const VList = genericComponent()({
  9170. name: 'VList',
  9171. props: makeVListProps(),
  9172. emits: {
  9173. 'update:selected': value => true,
  9174. 'update:activated': value => true,
  9175. 'update:opened': value => true,
  9176. 'click:open': value => true,
  9177. 'click:activate': value => true,
  9178. 'click:select': value => true
  9179. },
  9180. setup(props, _ref) {
  9181. let {
  9182. slots
  9183. } = _ref;
  9184. const {
  9185. items
  9186. } = useListItems(props);
  9187. const {
  9188. themeClasses
  9189. } = provideTheme(props);
  9190. const {
  9191. backgroundColorClasses,
  9192. backgroundColorStyles
  9193. } = useBackgroundColor(vue.toRef(props, 'bgColor'));
  9194. const {
  9195. borderClasses
  9196. } = useBorder(props);
  9197. const {
  9198. densityClasses
  9199. } = useDensity(props);
  9200. const {
  9201. dimensionStyles
  9202. } = useDimension(props);
  9203. const {
  9204. elevationClasses
  9205. } = useElevation(props);
  9206. const {
  9207. roundedClasses
  9208. } = useRounded(props);
  9209. const {
  9210. children,
  9211. open,
  9212. parents,
  9213. select,
  9214. getPath
  9215. } = useNested(props);
  9216. const lineClasses = vue.computed(() => props.lines ? `v-list--${props.lines}-line` : undefined);
  9217. const activeColor = vue.toRef(props, 'activeColor');
  9218. const baseColor = vue.toRef(props, 'baseColor');
  9219. const color = vue.toRef(props, 'color');
  9220. createList();
  9221. provideDefaults({
  9222. VListGroup: {
  9223. activeColor,
  9224. baseColor,
  9225. color,
  9226. expandIcon: vue.toRef(props, 'expandIcon'),
  9227. collapseIcon: vue.toRef(props, 'collapseIcon')
  9228. },
  9229. VListItem: {
  9230. activeClass: vue.toRef(props, 'activeClass'),
  9231. activeColor,
  9232. baseColor,
  9233. color,
  9234. density: vue.toRef(props, 'density'),
  9235. disabled: vue.toRef(props, 'disabled'),
  9236. lines: vue.toRef(props, 'lines'),
  9237. nav: vue.toRef(props, 'nav'),
  9238. slim: vue.toRef(props, 'slim'),
  9239. variant: vue.toRef(props, 'variant')
  9240. }
  9241. });
  9242. const isFocused = vue.shallowRef(false);
  9243. const contentRef = vue.ref();
  9244. function onFocusin(e) {
  9245. isFocused.value = true;
  9246. }
  9247. function onFocusout(e) {
  9248. isFocused.value = false;
  9249. }
  9250. function onFocus(e) {
  9251. if (!isFocused.value && !(e.relatedTarget && contentRef.value?.contains(e.relatedTarget))) focus();
  9252. }
  9253. function onKeydown(e) {
  9254. const target = e.target;
  9255. if (!contentRef.value || ['INPUT', 'TEXTAREA'].includes(target.tagName)) return;
  9256. if (e.key === 'ArrowDown') {
  9257. focus('next');
  9258. } else if (e.key === 'ArrowUp') {
  9259. focus('prev');
  9260. } else if (e.key === 'Home') {
  9261. focus('first');
  9262. } else if (e.key === 'End') {
  9263. focus('last');
  9264. } else {
  9265. return;
  9266. }
  9267. e.preventDefault();
  9268. }
  9269. function onMousedown(e) {
  9270. isFocused.value = true;
  9271. }
  9272. function focus(location) {
  9273. if (contentRef.value) {
  9274. return focusChild(contentRef.value, location);
  9275. }
  9276. }
  9277. useRender(() => {
  9278. return vue.createVNode(props.tag, {
  9279. "ref": contentRef,
  9280. "class": ['v-list', {
  9281. 'v-list--disabled': props.disabled,
  9282. 'v-list--nav': props.nav,
  9283. 'v-list--slim': props.slim
  9284. }, themeClasses.value, backgroundColorClasses.value, borderClasses.value, densityClasses.value, elevationClasses.value, lineClasses.value, roundedClasses.value, props.class],
  9285. "style": [backgroundColorStyles.value, dimensionStyles.value, props.style],
  9286. "tabindex": props.disabled || isFocused.value ? -1 : 0,
  9287. "role": "listbox",
  9288. "aria-activedescendant": undefined,
  9289. "onFocusin": onFocusin,
  9290. "onFocusout": onFocusout,
  9291. "onFocus": onFocus,
  9292. "onKeydown": onKeydown,
  9293. "onMousedown": onMousedown
  9294. }, {
  9295. default: () => [vue.createVNode(VListChildren, {
  9296. "items": items.value,
  9297. "returnObject": props.returnObject
  9298. }, slots)]
  9299. });
  9300. });
  9301. return {
  9302. open,
  9303. select,
  9304. focus,
  9305. children,
  9306. parents,
  9307. getPath
  9308. };
  9309. }
  9310. });
  9311. // Utilities
  9312. const VListImg = createSimpleFunctional('v-list-img');
  9313. const makeVListItemActionProps = propsFactory({
  9314. start: Boolean,
  9315. end: Boolean,
  9316. ...makeComponentProps(),
  9317. ...makeTagProps()
  9318. }, 'VListItemAction');
  9319. const VListItemAction = genericComponent()({
  9320. name: 'VListItemAction',
  9321. props: makeVListItemActionProps(),
  9322. setup(props, _ref) {
  9323. let {
  9324. slots
  9325. } = _ref;
  9326. useRender(() => vue.createVNode(props.tag, {
  9327. "class": ['v-list-item-action', {
  9328. 'v-list-item-action--start': props.start,
  9329. 'v-list-item-action--end': props.end
  9330. }, props.class],
  9331. "style": props.style
  9332. }, slots));
  9333. return {};
  9334. }
  9335. });
  9336. const makeVListItemMediaProps = propsFactory({
  9337. start: Boolean,
  9338. end: Boolean,
  9339. ...makeComponentProps(),
  9340. ...makeTagProps()
  9341. }, 'VListItemMedia');
  9342. const VListItemMedia = genericComponent()({
  9343. name: 'VListItemMedia',
  9344. props: makeVListItemMediaProps(),
  9345. setup(props, _ref) {
  9346. let {
  9347. slots
  9348. } = _ref;
  9349. useRender(() => {
  9350. return vue.createVNode(props.tag, {
  9351. "class": ['v-list-item-media', {
  9352. 'v-list-item-media--start': props.start,
  9353. 'v-list-item-media--end': props.end
  9354. }, props.class],
  9355. "style": props.style
  9356. }, slots);
  9357. });
  9358. return {};
  9359. }
  9360. });
  9361. // Types
  9362. /** Convert a point in local space to viewport space */
  9363. function elementToViewport(point, offset) {
  9364. return {
  9365. x: point.x + offset.x,
  9366. y: point.y + offset.y
  9367. };
  9368. }
  9369. /** Get the difference between two points */
  9370. function getOffset$1(a, b) {
  9371. return {
  9372. x: a.x - b.x,
  9373. y: a.y - b.y
  9374. };
  9375. }
  9376. /** Convert an anchor object to a point in local space */
  9377. function anchorToPoint(anchor, box) {
  9378. if (anchor.side === 'top' || anchor.side === 'bottom') {
  9379. const {
  9380. side,
  9381. align
  9382. } = anchor;
  9383. const x = align === 'left' ? 0 : align === 'center' ? box.width / 2 : align === 'right' ? box.width : align;
  9384. const y = side === 'top' ? 0 : side === 'bottom' ? box.height : side;
  9385. return elementToViewport({
  9386. x,
  9387. y
  9388. }, box);
  9389. } else if (anchor.side === 'left' || anchor.side === 'right') {
  9390. const {
  9391. side,
  9392. align
  9393. } = anchor;
  9394. const x = side === 'left' ? 0 : side === 'right' ? box.width : side;
  9395. const y = align === 'top' ? 0 : align === 'center' ? box.height / 2 : align === 'bottom' ? box.height : align;
  9396. return elementToViewport({
  9397. x,
  9398. y
  9399. }, box);
  9400. }
  9401. return elementToViewport({
  9402. x: box.width / 2,
  9403. y: box.height / 2
  9404. }, box);
  9405. }
  9406. // Composables
  9407. // Types
  9408. const locationStrategies = {
  9409. static: staticLocationStrategy,
  9410. // specific viewport position, usually centered
  9411. connected: connectedLocationStrategy // connected to a certain element
  9412. };
  9413. const makeLocationStrategyProps = propsFactory({
  9414. locationStrategy: {
  9415. type: [String, Function],
  9416. default: 'static',
  9417. validator: val => typeof val === 'function' || val in locationStrategies
  9418. },
  9419. location: {
  9420. type: String,
  9421. default: 'bottom'
  9422. },
  9423. origin: {
  9424. type: String,
  9425. default: 'auto'
  9426. },
  9427. offset: [Number, String, Array]
  9428. }, 'VOverlay-location-strategies');
  9429. function useLocationStrategies(props, data) {
  9430. const contentStyles = vue.ref({});
  9431. const updateLocation = vue.ref();
  9432. if (IN_BROWSER) {
  9433. useToggleScope(() => !!(data.isActive.value && props.locationStrategy), reset => {
  9434. vue.watch(() => props.locationStrategy, reset);
  9435. vue.onScopeDispose(() => {
  9436. window.removeEventListener('resize', onResize);
  9437. updateLocation.value = undefined;
  9438. });
  9439. window.addEventListener('resize', onResize, {
  9440. passive: true
  9441. });
  9442. if (typeof props.locationStrategy === 'function') {
  9443. updateLocation.value = props.locationStrategy(data, props, contentStyles)?.updateLocation;
  9444. } else {
  9445. updateLocation.value = locationStrategies[props.locationStrategy](data, props, contentStyles)?.updateLocation;
  9446. }
  9447. });
  9448. }
  9449. function onResize(e) {
  9450. updateLocation.value?.(e);
  9451. }
  9452. return {
  9453. contentStyles,
  9454. updateLocation
  9455. };
  9456. }
  9457. function staticLocationStrategy() {
  9458. // TODO
  9459. }
  9460. /** Get size of element ignoring max-width/max-height */
  9461. function getIntrinsicSize(el, isRtl) {
  9462. // const scrollables = new Map<Element, [number, number]>()
  9463. // el.querySelectorAll('*').forEach(el => {
  9464. // const x = el.scrollLeft
  9465. // const y = el.scrollTop
  9466. // if (x || y) {
  9467. // scrollables.set(el, [x, y])
  9468. // }
  9469. // })
  9470. // const initialMaxWidth = el.style.maxWidth
  9471. // const initialMaxHeight = el.style.maxHeight
  9472. // el.style.removeProperty('max-width')
  9473. // el.style.removeProperty('max-height')
  9474. /* eslint-disable-next-line sonarjs/prefer-immediate-return */
  9475. const contentBox = nullifyTransforms(el);
  9476. if (isRtl) {
  9477. contentBox.x += parseFloat(el.style.right || 0);
  9478. } else {
  9479. contentBox.x -= parseFloat(el.style.left || 0);
  9480. }
  9481. contentBox.y -= parseFloat(el.style.top || 0);
  9482. // el.style.maxWidth = initialMaxWidth
  9483. // el.style.maxHeight = initialMaxHeight
  9484. // scrollables.forEach((position, el) => {
  9485. // el.scrollTo(...position)
  9486. // })
  9487. return contentBox;
  9488. }
  9489. function connectedLocationStrategy(data, props, contentStyles) {
  9490. const activatorFixed = Array.isArray(data.target.value) || isFixedPosition(data.target.value);
  9491. if (activatorFixed) {
  9492. Object.assign(contentStyles.value, {
  9493. position: 'fixed',
  9494. top: 0,
  9495. [data.isRtl.value ? 'right' : 'left']: 0
  9496. });
  9497. }
  9498. const {
  9499. preferredAnchor,
  9500. preferredOrigin
  9501. } = destructComputed(() => {
  9502. const parsedAnchor = parseAnchor(props.location, data.isRtl.value);
  9503. const parsedOrigin = props.origin === 'overlap' ? parsedAnchor : props.origin === 'auto' ? flipSide(parsedAnchor) : parseAnchor(props.origin, data.isRtl.value);
  9504. // Some combinations of props may produce an invalid origin
  9505. if (parsedAnchor.side === parsedOrigin.side && parsedAnchor.align === flipAlign(parsedOrigin).align) {
  9506. return {
  9507. preferredAnchor: flipCorner(parsedAnchor),
  9508. preferredOrigin: flipCorner(parsedOrigin)
  9509. };
  9510. } else {
  9511. return {
  9512. preferredAnchor: parsedAnchor,
  9513. preferredOrigin: parsedOrigin
  9514. };
  9515. }
  9516. });
  9517. const [minWidth, minHeight, maxWidth, maxHeight] = ['minWidth', 'minHeight', 'maxWidth', 'maxHeight'].map(key => {
  9518. return vue.computed(() => {
  9519. const val = parseFloat(props[key]);
  9520. return isNaN(val) ? Infinity : val;
  9521. });
  9522. });
  9523. const offset = vue.computed(() => {
  9524. if (Array.isArray(props.offset)) {
  9525. return props.offset;
  9526. }
  9527. if (typeof props.offset === 'string') {
  9528. const offset = props.offset.split(' ').map(parseFloat);
  9529. if (offset.length < 2) offset.push(0);
  9530. return offset;
  9531. }
  9532. return typeof props.offset === 'number' ? [props.offset, 0] : [0, 0];
  9533. });
  9534. let observe = false;
  9535. const observer = new ResizeObserver(() => {
  9536. if (observe) updateLocation();
  9537. });
  9538. vue.watch([data.target, data.contentEl], (_ref, _ref2) => {
  9539. let [newTarget, newContentEl] = _ref;
  9540. let [oldTarget, oldContentEl] = _ref2;
  9541. if (oldTarget && !Array.isArray(oldTarget)) observer.unobserve(oldTarget);
  9542. if (newTarget && !Array.isArray(newTarget)) observer.observe(newTarget);
  9543. if (oldContentEl) observer.unobserve(oldContentEl);
  9544. if (newContentEl) observer.observe(newContentEl);
  9545. }, {
  9546. immediate: true
  9547. });
  9548. vue.onScopeDispose(() => {
  9549. observer.disconnect();
  9550. });
  9551. // eslint-disable-next-line max-statements
  9552. function updateLocation() {
  9553. observe = false;
  9554. requestAnimationFrame(() => observe = true);
  9555. if (!data.target.value || !data.contentEl.value) return;
  9556. const targetBox = getTargetBox(data.target.value);
  9557. const contentBox = getIntrinsicSize(data.contentEl.value, data.isRtl.value);
  9558. const scrollParents = getScrollParents(data.contentEl.value);
  9559. const viewportMargin = 12;
  9560. if (!scrollParents.length) {
  9561. scrollParents.push(document.documentElement);
  9562. if (!(data.contentEl.value.style.top && data.contentEl.value.style.left)) {
  9563. contentBox.x -= parseFloat(document.documentElement.style.getPropertyValue('--v-body-scroll-x') || 0);
  9564. contentBox.y -= parseFloat(document.documentElement.style.getPropertyValue('--v-body-scroll-y') || 0);
  9565. }
  9566. }
  9567. const viewport = scrollParents.reduce((box, el) => {
  9568. const rect = el.getBoundingClientRect();
  9569. const scrollBox = new Box({
  9570. x: el === document.documentElement ? 0 : rect.x,
  9571. y: el === document.documentElement ? 0 : rect.y,
  9572. width: el.clientWidth,
  9573. height: el.clientHeight
  9574. });
  9575. if (box) {
  9576. return new Box({
  9577. x: Math.max(box.left, scrollBox.left),
  9578. y: Math.max(box.top, scrollBox.top),
  9579. width: Math.min(box.right, scrollBox.right) - Math.max(box.left, scrollBox.left),
  9580. height: Math.min(box.bottom, scrollBox.bottom) - Math.max(box.top, scrollBox.top)
  9581. });
  9582. }
  9583. return scrollBox;
  9584. }, undefined);
  9585. viewport.x += viewportMargin;
  9586. viewport.y += viewportMargin;
  9587. viewport.width -= viewportMargin * 2;
  9588. viewport.height -= viewportMargin * 2;
  9589. let placement = {
  9590. anchor: preferredAnchor.value,
  9591. origin: preferredOrigin.value
  9592. };
  9593. function checkOverflow(_placement) {
  9594. const box = new Box(contentBox);
  9595. const targetPoint = anchorToPoint(_placement.anchor, targetBox);
  9596. const contentPoint = anchorToPoint(_placement.origin, box);
  9597. let {
  9598. x,
  9599. y
  9600. } = getOffset$1(targetPoint, contentPoint);
  9601. switch (_placement.anchor.side) {
  9602. case 'top':
  9603. y -= offset.value[0];
  9604. break;
  9605. case 'bottom':
  9606. y += offset.value[0];
  9607. break;
  9608. case 'left':
  9609. x -= offset.value[0];
  9610. break;
  9611. case 'right':
  9612. x += offset.value[0];
  9613. break;
  9614. }
  9615. switch (_placement.anchor.align) {
  9616. case 'top':
  9617. y -= offset.value[1];
  9618. break;
  9619. case 'bottom':
  9620. y += offset.value[1];
  9621. break;
  9622. case 'left':
  9623. x -= offset.value[1];
  9624. break;
  9625. case 'right':
  9626. x += offset.value[1];
  9627. break;
  9628. }
  9629. box.x += x;
  9630. box.y += y;
  9631. box.width = Math.min(box.width, maxWidth.value);
  9632. box.height = Math.min(box.height, maxHeight.value);
  9633. const overflows = getOverflow(box, viewport);
  9634. return {
  9635. overflows,
  9636. x,
  9637. y
  9638. };
  9639. }
  9640. let x = 0;
  9641. let y = 0;
  9642. const available = {
  9643. x: 0,
  9644. y: 0
  9645. };
  9646. const flipped = {
  9647. x: false,
  9648. y: false
  9649. };
  9650. let resets = -1;
  9651. while (true) {
  9652. if (resets++ > 10) {
  9653. consoleError('Infinite loop detected in connectedLocationStrategy');
  9654. break;
  9655. }
  9656. const {
  9657. x: _x,
  9658. y: _y,
  9659. overflows
  9660. } = checkOverflow(placement);
  9661. x += _x;
  9662. y += _y;
  9663. contentBox.x += _x;
  9664. contentBox.y += _y;
  9665. // flip
  9666. {
  9667. const axis = getAxis(placement.anchor);
  9668. const hasOverflowX = overflows.x.before || overflows.x.after;
  9669. const hasOverflowY = overflows.y.before || overflows.y.after;
  9670. let reset = false;
  9671. ['x', 'y'].forEach(key => {
  9672. if (key === 'x' && hasOverflowX && !flipped.x || key === 'y' && hasOverflowY && !flipped.y) {
  9673. const newPlacement = {
  9674. anchor: {
  9675. ...placement.anchor
  9676. },
  9677. origin: {
  9678. ...placement.origin
  9679. }
  9680. };
  9681. const flip = key === 'x' ? axis === 'y' ? flipAlign : flipSide : axis === 'y' ? flipSide : flipAlign;
  9682. newPlacement.anchor = flip(newPlacement.anchor);
  9683. newPlacement.origin = flip(newPlacement.origin);
  9684. const {
  9685. overflows: newOverflows
  9686. } = checkOverflow(newPlacement);
  9687. 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) {
  9688. placement = newPlacement;
  9689. reset = flipped[key] = true;
  9690. }
  9691. }
  9692. });
  9693. if (reset) continue;
  9694. }
  9695. // shift
  9696. if (overflows.x.before) {
  9697. x += overflows.x.before;
  9698. contentBox.x += overflows.x.before;
  9699. }
  9700. if (overflows.x.after) {
  9701. x -= overflows.x.after;
  9702. contentBox.x -= overflows.x.after;
  9703. }
  9704. if (overflows.y.before) {
  9705. y += overflows.y.before;
  9706. contentBox.y += overflows.y.before;
  9707. }
  9708. if (overflows.y.after) {
  9709. y -= overflows.y.after;
  9710. contentBox.y -= overflows.y.after;
  9711. }
  9712. // size
  9713. {
  9714. const overflows = getOverflow(contentBox, viewport);
  9715. available.x = viewport.width - overflows.x.before - overflows.x.after;
  9716. available.y = viewport.height - overflows.y.before - overflows.y.after;
  9717. x += overflows.x.before;
  9718. contentBox.x += overflows.x.before;
  9719. y += overflows.y.before;
  9720. contentBox.y += overflows.y.before;
  9721. }
  9722. break;
  9723. }
  9724. const axis = getAxis(placement.anchor);
  9725. Object.assign(contentStyles.value, {
  9726. '--v-overlay-anchor-origin': `${placement.anchor.side} ${placement.anchor.align}`,
  9727. transformOrigin: `${placement.origin.side} ${placement.origin.align}`,
  9728. // transform: `translate(${pixelRound(x)}px, ${pixelRound(y)}px)`,
  9729. top: convertToUnit(pixelRound(y)),
  9730. left: data.isRtl.value ? undefined : convertToUnit(pixelRound(x)),
  9731. right: data.isRtl.value ? convertToUnit(pixelRound(-x)) : undefined,
  9732. minWidth: convertToUnit(axis === 'y' ? Math.min(minWidth.value, targetBox.width) : minWidth.value),
  9733. maxWidth: convertToUnit(pixelCeil(clamp(available.x, minWidth.value === Infinity ? 0 : minWidth.value, maxWidth.value))),
  9734. maxHeight: convertToUnit(pixelCeil(clamp(available.y, minHeight.value === Infinity ? 0 : minHeight.value, maxHeight.value)))
  9735. });
  9736. return {
  9737. available,
  9738. contentBox
  9739. };
  9740. }
  9741. vue.watch(() => [preferredAnchor.value, preferredOrigin.value, props.offset, props.minWidth, props.minHeight, props.maxWidth, props.maxHeight], () => updateLocation());
  9742. vue.nextTick(() => {
  9743. const result = updateLocation();
  9744. // TODO: overflowing content should only require a single updateLocation call
  9745. // Icky hack to make sure the content is positioned consistently
  9746. if (!result) return;
  9747. const {
  9748. available,
  9749. contentBox
  9750. } = result;
  9751. if (contentBox.height > available.y) {
  9752. requestAnimationFrame(() => {
  9753. updateLocation();
  9754. requestAnimationFrame(() => {
  9755. updateLocation();
  9756. });
  9757. });
  9758. }
  9759. });
  9760. return {
  9761. updateLocation
  9762. };
  9763. }
  9764. function pixelRound(val) {
  9765. return Math.round(val * devicePixelRatio) / devicePixelRatio;
  9766. }
  9767. function pixelCeil(val) {
  9768. return Math.ceil(val * devicePixelRatio) / devicePixelRatio;
  9769. }
  9770. let clean = true;
  9771. const frames = [];
  9772. /**
  9773. * Schedule a task to run in an animation frame on its own
  9774. * This is useful for heavy tasks that may cause jank if all ran together
  9775. */
  9776. function requestNewFrame(cb) {
  9777. if (!clean || frames.length) {
  9778. frames.push(cb);
  9779. run();
  9780. } else {
  9781. clean = false;
  9782. cb();
  9783. run();
  9784. }
  9785. }
  9786. let raf = -1;
  9787. function run() {
  9788. cancelAnimationFrame(raf);
  9789. raf = requestAnimationFrame(() => {
  9790. const frame = frames.shift();
  9791. if (frame) frame();
  9792. if (frames.length) run();else clean = true;
  9793. });
  9794. }
  9795. // Utilities
  9796. // Types
  9797. const scrollStrategies = {
  9798. none: null,
  9799. close: closeScrollStrategy,
  9800. block: blockScrollStrategy,
  9801. reposition: repositionScrollStrategy
  9802. };
  9803. const makeScrollStrategyProps = propsFactory({
  9804. scrollStrategy: {
  9805. type: [String, Function],
  9806. default: 'block',
  9807. validator: val => typeof val === 'function' || val in scrollStrategies
  9808. }
  9809. }, 'VOverlay-scroll-strategies');
  9810. function useScrollStrategies(props, data) {
  9811. if (!IN_BROWSER) return;
  9812. let scope;
  9813. vue.watchEffect(async () => {
  9814. scope?.stop();
  9815. if (!(data.isActive.value && props.scrollStrategy)) return;
  9816. scope = vue.effectScope();
  9817. await new Promise(resolve => setTimeout(resolve));
  9818. scope.active && scope.run(() => {
  9819. if (typeof props.scrollStrategy === 'function') {
  9820. props.scrollStrategy(data, props, scope);
  9821. } else {
  9822. scrollStrategies[props.scrollStrategy]?.(data, props, scope);
  9823. }
  9824. });
  9825. });
  9826. vue.onScopeDispose(() => {
  9827. scope?.stop();
  9828. });
  9829. }
  9830. function closeScrollStrategy(data) {
  9831. function onScroll(e) {
  9832. data.isActive.value = false;
  9833. }
  9834. bindScroll(data.targetEl.value ?? data.contentEl.value, onScroll);
  9835. }
  9836. function blockScrollStrategy(data, props) {
  9837. const offsetParent = data.root.value?.offsetParent;
  9838. const scrollElements = [...new Set([...getScrollParents(data.targetEl.value, props.contained ? offsetParent : undefined), ...getScrollParents(data.contentEl.value, props.contained ? offsetParent : undefined)])].filter(el => !el.classList.contains('v-overlay-scroll-blocked'));
  9839. const scrollbarWidth = window.innerWidth - document.documentElement.offsetWidth;
  9840. const scrollableParent = (el => hasScrollbar(el) && el)(offsetParent || document.documentElement);
  9841. if (scrollableParent) {
  9842. data.root.value.classList.add('v-overlay--scroll-blocked');
  9843. }
  9844. scrollElements.forEach((el, i) => {
  9845. el.style.setProperty('--v-body-scroll-x', convertToUnit(-el.scrollLeft));
  9846. el.style.setProperty('--v-body-scroll-y', convertToUnit(-el.scrollTop));
  9847. if (el !== document.documentElement) {
  9848. el.style.setProperty('--v-scrollbar-offset', convertToUnit(scrollbarWidth));
  9849. }
  9850. el.classList.add('v-overlay-scroll-blocked');
  9851. });
  9852. vue.onScopeDispose(() => {
  9853. scrollElements.forEach((el, i) => {
  9854. const x = parseFloat(el.style.getPropertyValue('--v-body-scroll-x'));
  9855. const y = parseFloat(el.style.getPropertyValue('--v-body-scroll-y'));
  9856. const scrollBehavior = el.style.scrollBehavior;
  9857. el.style.scrollBehavior = 'auto';
  9858. el.style.removeProperty('--v-body-scroll-x');
  9859. el.style.removeProperty('--v-body-scroll-y');
  9860. el.style.removeProperty('--v-scrollbar-offset');
  9861. el.classList.remove('v-overlay-scroll-blocked');
  9862. el.scrollLeft = -x;
  9863. el.scrollTop = -y;
  9864. el.style.scrollBehavior = scrollBehavior;
  9865. });
  9866. if (scrollableParent) {
  9867. data.root.value.classList.remove('v-overlay--scroll-blocked');
  9868. }
  9869. });
  9870. }
  9871. function repositionScrollStrategy(data, props, scope) {
  9872. let slow = false;
  9873. let raf = -1;
  9874. let ric = -1;
  9875. function update(e) {
  9876. requestNewFrame(() => {
  9877. const start = performance.now();
  9878. data.updateLocation.value?.(e);
  9879. const time = performance.now() - start;
  9880. slow = time / (1000 / 60) > 2;
  9881. });
  9882. }
  9883. ric = (typeof requestIdleCallback === 'undefined' ? cb => cb() : requestIdleCallback)(() => {
  9884. scope.run(() => {
  9885. bindScroll(data.targetEl.value ?? data.contentEl.value, e => {
  9886. if (slow) {
  9887. // If the position calculation is slow,
  9888. // defer updates until scrolling is finished.
  9889. // Browsers usually fire one scroll event per frame so
  9890. // we just wait until we've got two frames without an event
  9891. cancelAnimationFrame(raf);
  9892. raf = requestAnimationFrame(() => {
  9893. raf = requestAnimationFrame(() => {
  9894. update(e);
  9895. });
  9896. });
  9897. } else {
  9898. update(e);
  9899. }
  9900. });
  9901. });
  9902. });
  9903. vue.onScopeDispose(() => {
  9904. typeof cancelIdleCallback !== 'undefined' && cancelIdleCallback(ric);
  9905. cancelAnimationFrame(raf);
  9906. });
  9907. }
  9908. /** @private */
  9909. function bindScroll(el, onScroll) {
  9910. const scrollElements = [document, ...getScrollParents(el)];
  9911. scrollElements.forEach(el => {
  9912. el.addEventListener('scroll', onScroll, {
  9913. passive: true
  9914. });
  9915. });
  9916. vue.onScopeDispose(() => {
  9917. scrollElements.forEach(el => {
  9918. el.removeEventListener('scroll', onScroll);
  9919. });
  9920. });
  9921. }
  9922. // Types
  9923. const VMenuSymbol = Symbol.for('vuetify:v-menu');
  9924. // Utilities
  9925. // Types
  9926. // Composables
  9927. const makeDelayProps = propsFactory({
  9928. closeDelay: [Number, String],
  9929. openDelay: [Number, String]
  9930. }, 'delay');
  9931. function useDelay(props, cb) {
  9932. let clearDelay = () => {};
  9933. function runDelay(isOpening) {
  9934. clearDelay?.();
  9935. const delay = Number(isOpening ? props.openDelay : props.closeDelay);
  9936. return new Promise(resolve => {
  9937. clearDelay = defer(delay, () => {
  9938. cb?.(isOpening);
  9939. resolve(isOpening);
  9940. });
  9941. });
  9942. }
  9943. function runOpenDelay() {
  9944. return runDelay(true);
  9945. }
  9946. function runCloseDelay() {
  9947. return runDelay(false);
  9948. }
  9949. return {
  9950. clearDelay,
  9951. runOpenDelay,
  9952. runCloseDelay
  9953. };
  9954. }
  9955. // Components
  9956. // Types
  9957. const makeActivatorProps = propsFactory({
  9958. target: [String, Object],
  9959. activator: [String, Object],
  9960. activatorProps: {
  9961. type: Object,
  9962. default: () => ({})
  9963. },
  9964. openOnClick: {
  9965. type: Boolean,
  9966. default: undefined
  9967. },
  9968. openOnHover: Boolean,
  9969. openOnFocus: {
  9970. type: Boolean,
  9971. default: undefined
  9972. },
  9973. closeOnContentClick: Boolean,
  9974. ...makeDelayProps()
  9975. }, 'VOverlay-activator');
  9976. function useActivator(props, _ref) {
  9977. let {
  9978. isActive,
  9979. isTop,
  9980. contentEl
  9981. } = _ref;
  9982. const vm = getCurrentInstance('useActivator');
  9983. const activatorEl = vue.ref();
  9984. let isHovered = false;
  9985. let isFocused = false;
  9986. let firstEnter = true;
  9987. const openOnFocus = vue.computed(() => props.openOnFocus || props.openOnFocus == null && props.openOnHover);
  9988. const openOnClick = vue.computed(() => props.openOnClick || props.openOnClick == null && !props.openOnHover && !openOnFocus.value);
  9989. const {
  9990. runOpenDelay,
  9991. runCloseDelay
  9992. } = useDelay(props, value => {
  9993. if (value === (props.openOnHover && isHovered || openOnFocus.value && isFocused) && !(props.openOnHover && isActive.value && !isTop.value)) {
  9994. if (isActive.value !== value) {
  9995. firstEnter = true;
  9996. }
  9997. isActive.value = value;
  9998. }
  9999. });
  10000. const cursorTarget = vue.ref();
  10001. const availableEvents = {
  10002. onClick: e => {
  10003. e.stopPropagation();
  10004. activatorEl.value = e.currentTarget || e.target;
  10005. if (!isActive.value) {
  10006. cursorTarget.value = [e.clientX, e.clientY];
  10007. }
  10008. isActive.value = !isActive.value;
  10009. },
  10010. onMouseenter: e => {
  10011. if (e.sourceCapabilities?.firesTouchEvents) return;
  10012. isHovered = true;
  10013. activatorEl.value = e.currentTarget || e.target;
  10014. runOpenDelay();
  10015. },
  10016. onMouseleave: e => {
  10017. isHovered = false;
  10018. runCloseDelay();
  10019. },
  10020. onFocus: e => {
  10021. if (matchesSelector(e.target, ':focus-visible') === false) return;
  10022. isFocused = true;
  10023. e.stopPropagation();
  10024. activatorEl.value = e.currentTarget || e.target;
  10025. runOpenDelay();
  10026. },
  10027. onBlur: e => {
  10028. isFocused = false;
  10029. e.stopPropagation();
  10030. runCloseDelay();
  10031. }
  10032. };
  10033. const activatorEvents = vue.computed(() => {
  10034. const events = {};
  10035. if (openOnClick.value) {
  10036. events.onClick = availableEvents.onClick;
  10037. }
  10038. if (props.openOnHover) {
  10039. events.onMouseenter = availableEvents.onMouseenter;
  10040. events.onMouseleave = availableEvents.onMouseleave;
  10041. }
  10042. if (openOnFocus.value) {
  10043. events.onFocus = availableEvents.onFocus;
  10044. events.onBlur = availableEvents.onBlur;
  10045. }
  10046. return events;
  10047. });
  10048. const contentEvents = vue.computed(() => {
  10049. const events = {};
  10050. if (props.openOnHover) {
  10051. events.onMouseenter = () => {
  10052. isHovered = true;
  10053. runOpenDelay();
  10054. };
  10055. events.onMouseleave = () => {
  10056. isHovered = false;
  10057. runCloseDelay();
  10058. };
  10059. }
  10060. if (openOnFocus.value) {
  10061. events.onFocusin = () => {
  10062. isFocused = true;
  10063. runOpenDelay();
  10064. };
  10065. events.onFocusout = () => {
  10066. isFocused = false;
  10067. runCloseDelay();
  10068. };
  10069. }
  10070. if (props.closeOnContentClick) {
  10071. const menu = vue.inject(VMenuSymbol, null);
  10072. events.onClick = () => {
  10073. isActive.value = false;
  10074. menu?.closeParents();
  10075. };
  10076. }
  10077. return events;
  10078. });
  10079. const scrimEvents = vue.computed(() => {
  10080. const events = {};
  10081. if (props.openOnHover) {
  10082. events.onMouseenter = () => {
  10083. if (firstEnter) {
  10084. isHovered = true;
  10085. firstEnter = false;
  10086. runOpenDelay();
  10087. }
  10088. };
  10089. events.onMouseleave = () => {
  10090. isHovered = false;
  10091. runCloseDelay();
  10092. };
  10093. }
  10094. return events;
  10095. });
  10096. vue.watch(isTop, val => {
  10097. if (val && (props.openOnHover && !isHovered && (!openOnFocus.value || !isFocused) || openOnFocus.value && !isFocused && (!props.openOnHover || !isHovered)) && !contentEl.value?.contains(document.activeElement)) {
  10098. isActive.value = false;
  10099. }
  10100. });
  10101. vue.watch(isActive, val => {
  10102. if (!val) {
  10103. setTimeout(() => {
  10104. cursorTarget.value = undefined;
  10105. });
  10106. }
  10107. }, {
  10108. flush: 'post'
  10109. });
  10110. const activatorRef = templateRef();
  10111. vue.watchEffect(() => {
  10112. if (!activatorRef.value) return;
  10113. vue.nextTick(() => {
  10114. activatorEl.value = activatorRef.el;
  10115. });
  10116. });
  10117. const targetRef = templateRef();
  10118. const target = vue.computed(() => {
  10119. if (props.target === 'cursor' && cursorTarget.value) return cursorTarget.value;
  10120. if (targetRef.value) return targetRef.el;
  10121. return getTarget(props.target, vm) || activatorEl.value;
  10122. });
  10123. const targetEl = vue.computed(() => {
  10124. return Array.isArray(target.value) ? undefined : target.value;
  10125. });
  10126. let scope;
  10127. vue.watch(() => !!props.activator, val => {
  10128. if (val && IN_BROWSER) {
  10129. scope = vue.effectScope();
  10130. scope.run(() => {
  10131. _useActivator(props, vm, {
  10132. activatorEl,
  10133. activatorEvents
  10134. });
  10135. });
  10136. } else if (scope) {
  10137. scope.stop();
  10138. }
  10139. }, {
  10140. flush: 'post',
  10141. immediate: true
  10142. });
  10143. vue.onScopeDispose(() => {
  10144. scope?.stop();
  10145. });
  10146. return {
  10147. activatorEl,
  10148. activatorRef,
  10149. target,
  10150. targetEl,
  10151. targetRef,
  10152. activatorEvents,
  10153. contentEvents,
  10154. scrimEvents
  10155. };
  10156. }
  10157. function _useActivator(props, vm, _ref2) {
  10158. let {
  10159. activatorEl,
  10160. activatorEvents
  10161. } = _ref2;
  10162. vue.watch(() => props.activator, (val, oldVal) => {
  10163. if (oldVal && val !== oldVal) {
  10164. const activator = getActivator(oldVal);
  10165. activator && unbindActivatorProps(activator);
  10166. }
  10167. if (val) {
  10168. vue.nextTick(() => bindActivatorProps());
  10169. }
  10170. }, {
  10171. immediate: true
  10172. });
  10173. vue.watch(() => props.activatorProps, () => {
  10174. bindActivatorProps();
  10175. });
  10176. vue.onScopeDispose(() => {
  10177. unbindActivatorProps();
  10178. });
  10179. function bindActivatorProps() {
  10180. let el = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : getActivator();
  10181. let _props = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : props.activatorProps;
  10182. if (!el) return;
  10183. bindProps(el, vue.mergeProps(activatorEvents.value, _props));
  10184. }
  10185. function unbindActivatorProps() {
  10186. let el = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : getActivator();
  10187. let _props = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : props.activatorProps;
  10188. if (!el) return;
  10189. unbindProps(el, vue.mergeProps(activatorEvents.value, _props));
  10190. }
  10191. function getActivator() {
  10192. let selector = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : props.activator;
  10193. const activator = getTarget(selector, vm);
  10194. // The activator should only be a valid element (Ignore comments and text nodes)
  10195. activatorEl.value = activator?.nodeType === Node.ELEMENT_NODE ? activator : undefined;
  10196. return activatorEl.value;
  10197. }
  10198. }
  10199. function getTarget(selector, vm) {
  10200. if (!selector) return;
  10201. let target;
  10202. if (selector === 'parent') {
  10203. let el = vm?.proxy?.$el?.parentNode;
  10204. while (el?.hasAttribute('data-no-activator')) {
  10205. el = el.parentNode;
  10206. }
  10207. target = el;
  10208. } else if (typeof selector === 'string') {
  10209. // Selector
  10210. target = document.querySelector(selector);
  10211. } else if ('$el' in selector) {
  10212. // Component (ref)
  10213. target = selector.$el;
  10214. } else {
  10215. // HTMLElement | Element | [x, y]
  10216. target = selector;
  10217. }
  10218. return target;
  10219. }
  10220. // Composables
  10221. function useHydration() {
  10222. if (!IN_BROWSER) return vue.shallowRef(false);
  10223. const {
  10224. ssr
  10225. } = useDisplay();
  10226. if (ssr) {
  10227. const isMounted = vue.shallowRef(false);
  10228. vue.onMounted(() => {
  10229. isMounted.value = true;
  10230. });
  10231. return isMounted;
  10232. } else {
  10233. return vue.shallowRef(true);
  10234. }
  10235. }
  10236. // Utilities
  10237. // Types
  10238. const makeLazyProps = propsFactory({
  10239. eager: Boolean
  10240. }, 'lazy');
  10241. function useLazy(props, active) {
  10242. const isBooted = vue.shallowRef(false);
  10243. const hasContent = vue.computed(() => isBooted.value || props.eager || active.value);
  10244. vue.watch(active, () => isBooted.value = true);
  10245. function onAfterLeave() {
  10246. if (!props.eager) isBooted.value = false;
  10247. }
  10248. return {
  10249. isBooted,
  10250. hasContent,
  10251. onAfterLeave
  10252. };
  10253. }
  10254. // Utilities
  10255. function useScopeId() {
  10256. const vm = getCurrentInstance('useScopeId');
  10257. const scopeId = vm.vnode.scopeId;
  10258. return {
  10259. scopeId: scopeId ? {
  10260. [scopeId]: ''
  10261. } : undefined
  10262. };
  10263. }
  10264. // Composables
  10265. // Types
  10266. const StackSymbol = Symbol.for('vuetify:stack');
  10267. const globalStack = vue.reactive([]);
  10268. function useStack(isActive, zIndex, disableGlobalStack) {
  10269. const vm = getCurrentInstance('useStack');
  10270. const createStackEntry = !disableGlobalStack;
  10271. const parent = vue.inject(StackSymbol, undefined);
  10272. const stack = vue.reactive({
  10273. activeChildren: new Set()
  10274. });
  10275. vue.provide(StackSymbol, stack);
  10276. const _zIndex = vue.shallowRef(+zIndex.value);
  10277. useToggleScope(isActive, () => {
  10278. const lastZIndex = globalStack.at(-1)?.[1];
  10279. _zIndex.value = lastZIndex ? lastZIndex + 10 : +zIndex.value;
  10280. if (createStackEntry) {
  10281. globalStack.push([vm.uid, _zIndex.value]);
  10282. }
  10283. parent?.activeChildren.add(vm.uid);
  10284. vue.onScopeDispose(() => {
  10285. if (createStackEntry) {
  10286. const idx = vue.toRaw(globalStack).findIndex(v => v[0] === vm.uid);
  10287. globalStack.splice(idx, 1);
  10288. }
  10289. parent?.activeChildren.delete(vm.uid);
  10290. });
  10291. });
  10292. const globalTop = vue.shallowRef(true);
  10293. if (createStackEntry) {
  10294. vue.watchEffect(() => {
  10295. const _isTop = globalStack.at(-1)?.[0] === vm.uid;
  10296. setTimeout(() => globalTop.value = _isTop);
  10297. });
  10298. }
  10299. const localTop = vue.computed(() => !stack.activeChildren.size);
  10300. return {
  10301. globalTop: vue.readonly(globalTop),
  10302. localTop,
  10303. stackStyles: vue.computed(() => ({
  10304. zIndex: _zIndex.value
  10305. }))
  10306. };
  10307. }
  10308. // Utilities
  10309. function useTeleport(target) {
  10310. const teleportTarget = vue.computed(() => {
  10311. const _target = target();
  10312. if (_target === true || !IN_BROWSER) return undefined;
  10313. const targetElement = _target === false ? document.body : typeof _target === 'string' ? document.querySelector(_target) : _target;
  10314. if (targetElement == null) {
  10315. vue.warn(`Unable to locate target ${_target}`);
  10316. return undefined;
  10317. }
  10318. let container = [...targetElement.children].find(el => el.matches('.v-overlay-container'));
  10319. if (!container) {
  10320. container = document.createElement('div');
  10321. container.className = 'v-overlay-container';
  10322. targetElement.appendChild(container);
  10323. }
  10324. return container;
  10325. });
  10326. return {
  10327. teleportTarget
  10328. };
  10329. }
  10330. // Utilities
  10331. // Types
  10332. function defaultConditional() {
  10333. return true;
  10334. }
  10335. function checkEvent(e, el, binding) {
  10336. // The include element callbacks below can be expensive
  10337. // so we should avoid calling them when we're not active.
  10338. // Explicitly check for false to allow fallback compatibility
  10339. // with non-toggleable components
  10340. if (!e || checkIsActive(e, binding) === false) return false;
  10341. // If we're clicking inside the shadowroot, then the app root doesn't get the same
  10342. // level of introspection as to _what_ we're clicking. We want to check to see if
  10343. // our target is the shadowroot parent container, and if it is, ignore.
  10344. const root = attachedRoot(el);
  10345. if (typeof ShadowRoot !== 'undefined' && root instanceof ShadowRoot && root.host === e.target) return false;
  10346. // Check if additional elements were passed to be included in check
  10347. // (click must be outside all included elements, if any)
  10348. const elements = (typeof binding.value === 'object' && binding.value.include || (() => []))();
  10349. // Add the root element for the component this directive was defined on
  10350. elements.push(el);
  10351. // Check if it's a click outside our elements, and then if our callback returns true.
  10352. // Non-toggleable components should take action in their callback and return falsy.
  10353. // Toggleable can return true if it wants to deactivate.
  10354. // Note that, because we're in the capture phase, this callback will occur before
  10355. // the bubbling click event on any outside elements.
  10356. return !elements.some(el => el?.contains(e.target));
  10357. }
  10358. function checkIsActive(e, binding) {
  10359. const isActive = typeof binding.value === 'object' && binding.value.closeConditional || defaultConditional;
  10360. return isActive(e);
  10361. }
  10362. function directive(e, el, binding) {
  10363. const handler = typeof binding.value === 'function' ? binding.value : binding.value.handler;
  10364. // Clicks in the Shadow DOM change their target while using setTimeout, so the original target is saved here
  10365. e.shadowTarget = e.target;
  10366. el._clickOutside.lastMousedownWasOutside && checkEvent(e, el, binding) && setTimeout(() => {
  10367. checkIsActive(e, binding) && handler && handler(e);
  10368. }, 0);
  10369. }
  10370. function handleShadow(el, callback) {
  10371. const root = attachedRoot(el);
  10372. callback(document);
  10373. if (typeof ShadowRoot !== 'undefined' && root instanceof ShadowRoot) {
  10374. callback(root);
  10375. }
  10376. }
  10377. const ClickOutside = {
  10378. // [data-app] may not be found
  10379. // if using bind, inserted makes
  10380. // sure that the root element is
  10381. // available, iOS does not support
  10382. // clicks on body
  10383. mounted(el, binding) {
  10384. const onClick = e => directive(e, el, binding);
  10385. const onMousedown = e => {
  10386. el._clickOutside.lastMousedownWasOutside = checkEvent(e, el, binding);
  10387. };
  10388. handleShadow(el, app => {
  10389. app.addEventListener('click', onClick, true);
  10390. app.addEventListener('mousedown', onMousedown, true);
  10391. });
  10392. if (!el._clickOutside) {
  10393. el._clickOutside = {
  10394. lastMousedownWasOutside: false
  10395. };
  10396. }
  10397. el._clickOutside[binding.instance.$.uid] = {
  10398. onClick,
  10399. onMousedown
  10400. };
  10401. },
  10402. beforeUnmount(el, binding) {
  10403. if (!el._clickOutside) return;
  10404. handleShadow(el, app => {
  10405. if (!app || !el._clickOutside?.[binding.instance.$.uid]) return;
  10406. const {
  10407. onClick,
  10408. onMousedown
  10409. } = el._clickOutside[binding.instance.$.uid];
  10410. app.removeEventListener('click', onClick, true);
  10411. app.removeEventListener('mousedown', onMousedown, true);
  10412. });
  10413. delete el._clickOutside[binding.instance.$.uid];
  10414. }
  10415. };
  10416. // Types
  10417. function Scrim(props) {
  10418. const {
  10419. modelValue,
  10420. color,
  10421. ...rest
  10422. } = props;
  10423. return vue.createVNode(vue.Transition, {
  10424. "name": "fade-transition",
  10425. "appear": true
  10426. }, {
  10427. default: () => [props.modelValue && vue.createVNode("div", vue.mergeProps({
  10428. "class": ['v-overlay__scrim', props.color.backgroundColorClasses.value],
  10429. "style": props.color.backgroundColorStyles.value
  10430. }, rest), null)]
  10431. });
  10432. }
  10433. const makeVOverlayProps = propsFactory({
  10434. absolute: Boolean,
  10435. attach: [Boolean, String, Object],
  10436. closeOnBack: {
  10437. type: Boolean,
  10438. default: true
  10439. },
  10440. contained: Boolean,
  10441. contentClass: null,
  10442. contentProps: null,
  10443. disabled: Boolean,
  10444. opacity: [Number, String],
  10445. noClickAnimation: Boolean,
  10446. modelValue: Boolean,
  10447. persistent: Boolean,
  10448. scrim: {
  10449. type: [Boolean, String],
  10450. default: true
  10451. },
  10452. zIndex: {
  10453. type: [Number, String],
  10454. default: 2000
  10455. },
  10456. ...makeActivatorProps(),
  10457. ...makeComponentProps(),
  10458. ...makeDimensionProps(),
  10459. ...makeLazyProps(),
  10460. ...makeLocationStrategyProps(),
  10461. ...makeScrollStrategyProps(),
  10462. ...makeThemeProps(),
  10463. ...makeTransitionProps()
  10464. }, 'VOverlay');
  10465. const VOverlay = genericComponent()({
  10466. name: 'VOverlay',
  10467. directives: {
  10468. ClickOutside
  10469. },
  10470. inheritAttrs: false,
  10471. props: {
  10472. _disableGlobalStack: Boolean,
  10473. ...makeVOverlayProps()
  10474. },
  10475. emits: {
  10476. 'click:outside': e => true,
  10477. 'update:modelValue': value => true,
  10478. afterEnter: () => true,
  10479. afterLeave: () => true
  10480. },
  10481. setup(props, _ref) {
  10482. let {
  10483. slots,
  10484. attrs,
  10485. emit
  10486. } = _ref;
  10487. const vm = getCurrentInstance('VOverlay');
  10488. const root = vue.ref();
  10489. const scrimEl = vue.ref();
  10490. const contentEl = vue.ref();
  10491. const model = useProxiedModel(props, 'modelValue');
  10492. const isActive = vue.computed({
  10493. get: () => model.value,
  10494. set: v => {
  10495. if (!(v && props.disabled)) model.value = v;
  10496. }
  10497. });
  10498. const {
  10499. themeClasses
  10500. } = provideTheme(props);
  10501. const {
  10502. rtlClasses,
  10503. isRtl
  10504. } = useRtl();
  10505. const {
  10506. hasContent,
  10507. onAfterLeave: _onAfterLeave
  10508. } = useLazy(props, isActive);
  10509. const scrimColor = useBackgroundColor(vue.computed(() => {
  10510. return typeof props.scrim === 'string' ? props.scrim : null;
  10511. }));
  10512. const {
  10513. globalTop,
  10514. localTop,
  10515. stackStyles
  10516. } = useStack(isActive, vue.toRef(props, 'zIndex'), props._disableGlobalStack);
  10517. const {
  10518. activatorEl,
  10519. activatorRef,
  10520. target,
  10521. targetEl,
  10522. targetRef,
  10523. activatorEvents,
  10524. contentEvents,
  10525. scrimEvents
  10526. } = useActivator(props, {
  10527. isActive,
  10528. isTop: localTop,
  10529. contentEl
  10530. });
  10531. const {
  10532. teleportTarget
  10533. } = useTeleport(() => {
  10534. const target = props.attach || props.contained;
  10535. if (target) return target;
  10536. const rootNode = activatorEl?.value?.getRootNode() || vm.proxy?.$el?.getRootNode();
  10537. if (rootNode instanceof ShadowRoot) return rootNode;
  10538. return false;
  10539. });
  10540. const {
  10541. dimensionStyles
  10542. } = useDimension(props);
  10543. const isMounted = useHydration();
  10544. const {
  10545. scopeId
  10546. } = useScopeId();
  10547. vue.watch(() => props.disabled, v => {
  10548. if (v) isActive.value = false;
  10549. });
  10550. const {
  10551. contentStyles,
  10552. updateLocation
  10553. } = useLocationStrategies(props, {
  10554. isRtl,
  10555. contentEl,
  10556. target,
  10557. isActive
  10558. });
  10559. useScrollStrategies(props, {
  10560. root,
  10561. contentEl,
  10562. targetEl,
  10563. isActive,
  10564. updateLocation
  10565. });
  10566. function onClickOutside(e) {
  10567. emit('click:outside', e);
  10568. if (!props.persistent) isActive.value = false;else animateClick();
  10569. }
  10570. function closeConditional(e) {
  10571. return isActive.value && globalTop.value && (
  10572. // If using scrim, only close if clicking on it rather than anything opened on top
  10573. !props.scrim || e.target === scrimEl.value || e instanceof MouseEvent && e.shadowTarget === scrimEl.value);
  10574. }
  10575. IN_BROWSER && vue.watch(isActive, val => {
  10576. if (val) {
  10577. window.addEventListener('keydown', onKeydown);
  10578. } else {
  10579. window.removeEventListener('keydown', onKeydown);
  10580. }
  10581. }, {
  10582. immediate: true
  10583. });
  10584. vue.onBeforeUnmount(() => {
  10585. if (!IN_BROWSER) return;
  10586. window.removeEventListener('keydown', onKeydown);
  10587. });
  10588. function onKeydown(e) {
  10589. if (e.key === 'Escape' && globalTop.value) {
  10590. if (!props.persistent) {
  10591. isActive.value = false;
  10592. if (contentEl.value?.contains(document.activeElement)) {
  10593. activatorEl.value?.focus();
  10594. }
  10595. } else animateClick();
  10596. }
  10597. }
  10598. const router = useRouter();
  10599. useToggleScope(() => props.closeOnBack, () => {
  10600. useBackButton(router, next => {
  10601. if (globalTop.value && isActive.value) {
  10602. next(false);
  10603. if (!props.persistent) isActive.value = false;else animateClick();
  10604. } else {
  10605. next();
  10606. }
  10607. });
  10608. });
  10609. const top = vue.ref();
  10610. vue.watch(() => isActive.value && (props.absolute || props.contained) && teleportTarget.value == null, val => {
  10611. if (val) {
  10612. const scrollParent = getScrollParent(root.value);
  10613. if (scrollParent && scrollParent !== document.scrollingElement) {
  10614. top.value = scrollParent.scrollTop;
  10615. }
  10616. }
  10617. });
  10618. // Add a quick "bounce" animation to the content
  10619. function animateClick() {
  10620. if (props.noClickAnimation) return;
  10621. contentEl.value && animate(contentEl.value, [{
  10622. transformOrigin: 'center'
  10623. }, {
  10624. transform: 'scale(1.03)'
  10625. }, {
  10626. transformOrigin: 'center'
  10627. }], {
  10628. duration: 150,
  10629. easing: standardEasing
  10630. });
  10631. }
  10632. function onAfterEnter() {
  10633. emit('afterEnter');
  10634. }
  10635. function onAfterLeave() {
  10636. _onAfterLeave();
  10637. emit('afterLeave');
  10638. }
  10639. useRender(() => vue.createVNode(vue.Fragment, null, [slots.activator?.({
  10640. isActive: isActive.value,
  10641. targetRef,
  10642. props: vue.mergeProps({
  10643. ref: activatorRef
  10644. }, activatorEvents.value, props.activatorProps)
  10645. }), isMounted.value && hasContent.value && vue.createVNode(vue.Teleport, {
  10646. "disabled": !teleportTarget.value,
  10647. "to": teleportTarget.value
  10648. }, {
  10649. default: () => [vue.createVNode("div", vue.mergeProps({
  10650. "class": ['v-overlay', {
  10651. 'v-overlay--absolute': props.absolute || props.contained,
  10652. 'v-overlay--active': isActive.value,
  10653. 'v-overlay--contained': props.contained
  10654. }, themeClasses.value, rtlClasses.value, props.class],
  10655. "style": [stackStyles.value, {
  10656. '--v-overlay-opacity': props.opacity,
  10657. top: convertToUnit(top.value)
  10658. }, props.style],
  10659. "ref": root
  10660. }, scopeId, attrs), [vue.createVNode(Scrim, vue.mergeProps({
  10661. "color": scrimColor,
  10662. "modelValue": isActive.value && !!props.scrim,
  10663. "ref": scrimEl
  10664. }, scrimEvents.value), null), vue.createVNode(MaybeTransition, {
  10665. "appear": true,
  10666. "persisted": true,
  10667. "transition": props.transition,
  10668. "target": target.value,
  10669. "onAfterEnter": onAfterEnter,
  10670. "onAfterLeave": onAfterLeave
  10671. }, {
  10672. default: () => [vue.withDirectives(vue.createVNode("div", vue.mergeProps({
  10673. "ref": contentEl,
  10674. "class": ['v-overlay__content', props.contentClass],
  10675. "style": [dimensionStyles.value, contentStyles.value]
  10676. }, contentEvents.value, props.contentProps), [slots.default?.({
  10677. isActive
  10678. })]), [[vue.vShow, isActive.value], [vue.resolveDirective("click-outside"), {
  10679. handler: onClickOutside,
  10680. closeConditional,
  10681. include: () => [activatorEl.value]
  10682. }]])]
  10683. })])]
  10684. })]));
  10685. return {
  10686. activatorEl,
  10687. scrimEl,
  10688. target,
  10689. animateClick,
  10690. contentEl,
  10691. globalTop,
  10692. localTop,
  10693. updateLocation
  10694. };
  10695. }
  10696. });
  10697. // Types
  10698. const Refs = Symbol('Forwarded refs');
  10699. /** Omit properties starting with P */
  10700. /** Omit keyof $props from T */
  10701. function getDescriptor(obj, key) {
  10702. let currentObj = obj;
  10703. while (currentObj) {
  10704. const descriptor = Reflect.getOwnPropertyDescriptor(currentObj, key);
  10705. if (descriptor) return descriptor;
  10706. currentObj = Object.getPrototypeOf(currentObj);
  10707. }
  10708. return undefined;
  10709. }
  10710. function forwardRefs(target) {
  10711. for (var _len = arguments.length, refs = new Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) {
  10712. refs[_key - 1] = arguments[_key];
  10713. }
  10714. target[Refs] = refs;
  10715. return new Proxy(target, {
  10716. get(target, key) {
  10717. if (Reflect.has(target, key)) {
  10718. return Reflect.get(target, key);
  10719. }
  10720. // Skip internal properties
  10721. if (typeof key === 'symbol' || key.startsWith('$') || key.startsWith('__')) return;
  10722. for (const ref of refs) {
  10723. if (ref.value && Reflect.has(ref.value, key)) {
  10724. const val = Reflect.get(ref.value, key);
  10725. return typeof val === 'function' ? val.bind(ref.value) : val;
  10726. }
  10727. }
  10728. },
  10729. has(target, key) {
  10730. if (Reflect.has(target, key)) {
  10731. return true;
  10732. }
  10733. // Skip internal properties
  10734. if (typeof key === 'symbol' || key.startsWith('$') || key.startsWith('__')) return false;
  10735. for (const ref of refs) {
  10736. if (ref.value && Reflect.has(ref.value, key)) {
  10737. return true;
  10738. }
  10739. }
  10740. return false;
  10741. },
  10742. set(target, key, value) {
  10743. if (Reflect.has(target, key)) {
  10744. return Reflect.set(target, key, value);
  10745. }
  10746. // Skip internal properties
  10747. if (typeof key === 'symbol' || key.startsWith('$') || key.startsWith('__')) return false;
  10748. for (const ref of refs) {
  10749. if (ref.value && Reflect.has(ref.value, key)) {
  10750. return Reflect.set(ref.value, key, value);
  10751. }
  10752. }
  10753. return false;
  10754. },
  10755. getOwnPropertyDescriptor(target, key) {
  10756. const descriptor = Reflect.getOwnPropertyDescriptor(target, key);
  10757. if (descriptor) return descriptor;
  10758. // Skip internal properties
  10759. if (typeof key === 'symbol' || key.startsWith('$') || key.startsWith('__')) return;
  10760. // Check each ref's own properties
  10761. for (const ref of refs) {
  10762. if (!ref.value) continue;
  10763. const descriptor = getDescriptor(ref.value, key) ?? ('_' in ref.value ? getDescriptor(ref.value._?.setupState, key) : undefined);
  10764. if (descriptor) return descriptor;
  10765. }
  10766. // Recursive search up each ref's prototype
  10767. for (const ref of refs) {
  10768. const childRefs = ref.value && ref.value[Refs];
  10769. if (!childRefs) continue;
  10770. const queue = childRefs.slice();
  10771. while (queue.length) {
  10772. const ref = queue.shift();
  10773. const descriptor = getDescriptor(ref.value, key);
  10774. if (descriptor) return descriptor;
  10775. const childRefs = ref.value && ref.value[Refs];
  10776. if (childRefs) queue.push(...childRefs);
  10777. }
  10778. }
  10779. return undefined;
  10780. }
  10781. });
  10782. }
  10783. // Types
  10784. const makeVMenuProps = propsFactory({
  10785. // TODO
  10786. // disableKeys: Boolean,
  10787. id: String,
  10788. submenu: Boolean,
  10789. ...omit(makeVOverlayProps({
  10790. closeDelay: 250,
  10791. closeOnContentClick: true,
  10792. locationStrategy: 'connected',
  10793. location: undefined,
  10794. openDelay: 300,
  10795. scrim: false,
  10796. scrollStrategy: 'reposition',
  10797. transition: {
  10798. component: VDialogTransition
  10799. }
  10800. }), ['absolute'])
  10801. }, 'VMenu');
  10802. const VMenu = genericComponent()({
  10803. name: 'VMenu',
  10804. props: makeVMenuProps(),
  10805. emits: {
  10806. 'update:modelValue': value => true
  10807. },
  10808. setup(props, _ref) {
  10809. let {
  10810. slots
  10811. } = _ref;
  10812. const isActive = useProxiedModel(props, 'modelValue');
  10813. const {
  10814. scopeId
  10815. } = useScopeId();
  10816. const {
  10817. isRtl
  10818. } = useRtl();
  10819. const uid = getUid();
  10820. const id = vue.computed(() => props.id || `v-menu-${uid}`);
  10821. const overlay = vue.ref();
  10822. const parent = vue.inject(VMenuSymbol, null);
  10823. const openChildren = vue.shallowRef(new Set());
  10824. vue.provide(VMenuSymbol, {
  10825. register() {
  10826. openChildren.value.add(uid);
  10827. },
  10828. unregister() {
  10829. openChildren.value.delete(uid);
  10830. },
  10831. closeParents(e) {
  10832. setTimeout(() => {
  10833. if (!openChildren.value.size && !props.persistent && (e == null || overlay.value?.contentEl && !isClickInsideElement(e, overlay.value.contentEl))) {
  10834. isActive.value = false;
  10835. parent?.closeParents();
  10836. }
  10837. }, 40);
  10838. }
  10839. });
  10840. vue.onBeforeUnmount(() => {
  10841. parent?.unregister();
  10842. document.removeEventListener('focusin', onFocusIn);
  10843. });
  10844. vue.onDeactivated(() => isActive.value = false);
  10845. async function onFocusIn(e) {
  10846. const before = e.relatedTarget;
  10847. const after = e.target;
  10848. await vue.nextTick();
  10849. if (isActive.value && before !== after && overlay.value?.contentEl &&
  10850. // We're the topmost menu
  10851. overlay.value?.globalTop &&
  10852. // It isn't the document or the menu body
  10853. ![document, overlay.value.contentEl].includes(after) &&
  10854. // It isn't inside the menu body
  10855. !overlay.value.contentEl.contains(after)) {
  10856. const focusable = focusableChildren(overlay.value.contentEl);
  10857. focusable[0]?.focus();
  10858. }
  10859. }
  10860. vue.watch(isActive, val => {
  10861. if (val) {
  10862. parent?.register();
  10863. if (IN_BROWSER) {
  10864. document.addEventListener('focusin', onFocusIn, {
  10865. once: true
  10866. });
  10867. }
  10868. } else {
  10869. parent?.unregister();
  10870. if (IN_BROWSER) {
  10871. document.removeEventListener('focusin', onFocusIn);
  10872. }
  10873. }
  10874. }, {
  10875. immediate: true
  10876. });
  10877. function onClickOutside(e) {
  10878. parent?.closeParents(e);
  10879. }
  10880. function onKeydown(e) {
  10881. if (props.disabled) return;
  10882. if (e.key === 'Tab' || e.key === 'Enter' && !props.closeOnContentClick) {
  10883. if (e.key === 'Enter' && (e.target instanceof HTMLTextAreaElement || e.target instanceof HTMLInputElement && !!e.target.closest('form'))) return;
  10884. if (e.key === 'Enter') e.preventDefault();
  10885. const nextElement = getNextElement(focusableChildren(overlay.value?.contentEl, false), e.shiftKey ? 'prev' : 'next', el => el.tabIndex >= 0);
  10886. if (!nextElement) {
  10887. isActive.value = false;
  10888. overlay.value?.activatorEl?.focus();
  10889. }
  10890. } else if (props.submenu && e.key === (isRtl.value ? 'ArrowRight' : 'ArrowLeft')) {
  10891. isActive.value = false;
  10892. overlay.value?.activatorEl?.focus();
  10893. }
  10894. }
  10895. function onActivatorKeydown(e) {
  10896. if (props.disabled) return;
  10897. const el = overlay.value?.contentEl;
  10898. if (el && isActive.value) {
  10899. if (e.key === 'ArrowDown') {
  10900. e.preventDefault();
  10901. e.stopImmediatePropagation();
  10902. focusChild(el, 'next');
  10903. } else if (e.key === 'ArrowUp') {
  10904. e.preventDefault();
  10905. e.stopImmediatePropagation();
  10906. focusChild(el, 'prev');
  10907. } else if (props.submenu) {
  10908. if (e.key === (isRtl.value ? 'ArrowRight' : 'ArrowLeft')) {
  10909. isActive.value = false;
  10910. } else if (e.key === (isRtl.value ? 'ArrowLeft' : 'ArrowRight')) {
  10911. e.preventDefault();
  10912. focusChild(el, 'first');
  10913. }
  10914. }
  10915. } else if (props.submenu ? e.key === (isRtl.value ? 'ArrowLeft' : 'ArrowRight') : ['ArrowDown', 'ArrowUp'].includes(e.key)) {
  10916. isActive.value = true;
  10917. e.preventDefault();
  10918. setTimeout(() => setTimeout(() => onActivatorKeydown(e)));
  10919. }
  10920. }
  10921. const activatorProps = vue.computed(() => vue.mergeProps({
  10922. 'aria-haspopup': 'menu',
  10923. 'aria-expanded': String(isActive.value),
  10924. 'aria-owns': id.value,
  10925. onKeydown: onActivatorKeydown
  10926. }, props.activatorProps));
  10927. useRender(() => {
  10928. const overlayProps = VOverlay.filterProps(props);
  10929. return vue.createVNode(VOverlay, vue.mergeProps({
  10930. "ref": overlay,
  10931. "id": id.value,
  10932. "class": ['v-menu', props.class],
  10933. "style": props.style
  10934. }, overlayProps, {
  10935. "modelValue": isActive.value,
  10936. "onUpdate:modelValue": $event => isActive.value = $event,
  10937. "absolute": true,
  10938. "activatorProps": activatorProps.value,
  10939. "location": props.location ?? (props.submenu ? 'end' : 'bottom'),
  10940. "onClick:outside": onClickOutside,
  10941. "onKeydown": onKeydown
  10942. }, scopeId), {
  10943. activator: slots.activator,
  10944. default: function () {
  10945. for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) {
  10946. args[_key] = arguments[_key];
  10947. }
  10948. return vue.createVNode(VDefaultsProvider, {
  10949. "root": "VMenu"
  10950. }, {
  10951. default: () => [slots.default?.(...args)]
  10952. });
  10953. }
  10954. });
  10955. });
  10956. return forwardRefs({
  10957. id,
  10958. ΨopenChildren: openChildren
  10959. }, overlay);
  10960. }
  10961. });
  10962. // Types
  10963. const makeVCounterProps = propsFactory({
  10964. active: Boolean,
  10965. disabled: Boolean,
  10966. max: [Number, String],
  10967. value: {
  10968. type: [Number, String],
  10969. default: 0
  10970. },
  10971. ...makeComponentProps(),
  10972. ...makeTransitionProps({
  10973. transition: {
  10974. component: VSlideYTransition
  10975. }
  10976. })
  10977. }, 'VCounter');
  10978. const VCounter = genericComponent()({
  10979. name: 'VCounter',
  10980. functional: true,
  10981. props: makeVCounterProps(),
  10982. setup(props, _ref) {
  10983. let {
  10984. slots
  10985. } = _ref;
  10986. const counter = vue.computed(() => {
  10987. return props.max ? `${props.value} / ${props.max}` : String(props.value);
  10988. });
  10989. useRender(() => vue.createVNode(MaybeTransition, {
  10990. "transition": props.transition
  10991. }, {
  10992. default: () => [vue.withDirectives(vue.createVNode("div", {
  10993. "class": ['v-counter', {
  10994. 'text-error': props.max && !props.disabled && parseFloat(props.value) > parseFloat(props.max)
  10995. }, props.class],
  10996. "style": props.style
  10997. }, [slots.default ? slots.default({
  10998. counter: counter.value,
  10999. max: props.max,
  11000. value: props.value
  11001. }) : counter.value]), [[vue.vShow, props.active]])]
  11002. }));
  11003. return {};
  11004. }
  11005. });
  11006. const makeVFieldLabelProps = propsFactory({
  11007. floating: Boolean,
  11008. ...makeComponentProps()
  11009. }, 'VFieldLabel');
  11010. const VFieldLabel = genericComponent()({
  11011. name: 'VFieldLabel',
  11012. props: makeVFieldLabelProps(),
  11013. setup(props, _ref) {
  11014. let {
  11015. slots
  11016. } = _ref;
  11017. useRender(() => vue.createVNode(VLabel, {
  11018. "class": ['v-field-label', {
  11019. 'v-field-label--floating': props.floating
  11020. }, props.class],
  11021. "style": props.style,
  11022. "aria-hidden": props.floating || undefined
  11023. }, slots));
  11024. return {};
  11025. }
  11026. });
  11027. // Types
  11028. const allowedVariants$1 = ['underlined', 'outlined', 'filled', 'solo', 'solo-inverted', 'solo-filled', 'plain'];
  11029. const makeVFieldProps = propsFactory({
  11030. appendInnerIcon: IconValue,
  11031. bgColor: String,
  11032. clearable: Boolean,
  11033. clearIcon: {
  11034. type: IconValue,
  11035. default: '$clear'
  11036. },
  11037. active: Boolean,
  11038. centerAffix: {
  11039. type: Boolean,
  11040. default: undefined
  11041. },
  11042. color: String,
  11043. baseColor: String,
  11044. dirty: Boolean,
  11045. disabled: {
  11046. type: Boolean,
  11047. default: null
  11048. },
  11049. error: Boolean,
  11050. flat: Boolean,
  11051. label: String,
  11052. persistentClear: Boolean,
  11053. prependInnerIcon: IconValue,
  11054. reverse: Boolean,
  11055. singleLine: Boolean,
  11056. variant: {
  11057. type: String,
  11058. default: 'filled',
  11059. validator: v => allowedVariants$1.includes(v)
  11060. },
  11061. 'onClick:clear': EventProp(),
  11062. 'onClick:appendInner': EventProp(),
  11063. 'onClick:prependInner': EventProp(),
  11064. ...makeComponentProps(),
  11065. ...makeLoaderProps(),
  11066. ...makeRoundedProps(),
  11067. ...makeThemeProps()
  11068. }, 'VField');
  11069. const VField = genericComponent()({
  11070. name: 'VField',
  11071. inheritAttrs: false,
  11072. props: {
  11073. id: String,
  11074. ...makeFocusProps(),
  11075. ...makeVFieldProps()
  11076. },
  11077. emits: {
  11078. 'update:focused': focused => true,
  11079. 'update:modelValue': value => true
  11080. },
  11081. setup(props, _ref) {
  11082. let {
  11083. attrs,
  11084. emit,
  11085. slots
  11086. } = _ref;
  11087. const {
  11088. themeClasses
  11089. } = provideTheme(props);
  11090. const {
  11091. loaderClasses
  11092. } = useLoader(props);
  11093. const {
  11094. focusClasses,
  11095. isFocused,
  11096. focus,
  11097. blur
  11098. } = useFocus(props);
  11099. const {
  11100. InputIcon
  11101. } = useInputIcon(props);
  11102. const {
  11103. roundedClasses
  11104. } = useRounded(props);
  11105. const {
  11106. rtlClasses
  11107. } = useRtl();
  11108. const isActive = vue.computed(() => props.dirty || props.active);
  11109. const hasLabel = vue.computed(() => !props.singleLine && !!(props.label || slots.label));
  11110. const uid = getUid();
  11111. const id = vue.computed(() => props.id || `input-${uid}`);
  11112. const messagesId = vue.computed(() => `${id.value}-messages`);
  11113. const labelRef = vue.ref();
  11114. const floatingLabelRef = vue.ref();
  11115. const controlRef = vue.ref();
  11116. const isPlainOrUnderlined = vue.computed(() => ['plain', 'underlined'].includes(props.variant));
  11117. const {
  11118. backgroundColorClasses,
  11119. backgroundColorStyles
  11120. } = useBackgroundColor(vue.toRef(props, 'bgColor'));
  11121. const {
  11122. textColorClasses,
  11123. textColorStyles
  11124. } = useTextColor(vue.computed(() => {
  11125. return props.error || props.disabled ? undefined : isActive.value && isFocused.value ? props.color : props.baseColor;
  11126. }));
  11127. vue.watch(isActive, val => {
  11128. if (hasLabel.value) {
  11129. const el = labelRef.value.$el;
  11130. const targetEl = floatingLabelRef.value.$el;
  11131. requestAnimationFrame(() => {
  11132. const rect = nullifyTransforms(el);
  11133. const targetRect = targetEl.getBoundingClientRect();
  11134. const x = targetRect.x - rect.x;
  11135. const y = targetRect.y - rect.y - (rect.height / 2 - targetRect.height / 2);
  11136. const targetWidth = targetRect.width / 0.75;
  11137. const width = Math.abs(targetWidth - rect.width) > 1 ? {
  11138. maxWidth: convertToUnit(targetWidth)
  11139. } : undefined;
  11140. const style = getComputedStyle(el);
  11141. const targetStyle = getComputedStyle(targetEl);
  11142. const duration = parseFloat(style.transitionDuration) * 1000 || 150;
  11143. const scale = parseFloat(targetStyle.getPropertyValue('--v-field-label-scale'));
  11144. const color = targetStyle.getPropertyValue('color');
  11145. el.style.visibility = 'visible';
  11146. targetEl.style.visibility = 'hidden';
  11147. animate(el, {
  11148. transform: `translate(${x}px, ${y}px) scale(${scale})`,
  11149. color,
  11150. ...width
  11151. }, {
  11152. duration,
  11153. easing: standardEasing,
  11154. direction: val ? 'normal' : 'reverse'
  11155. }).finished.then(() => {
  11156. el.style.removeProperty('visibility');
  11157. targetEl.style.removeProperty('visibility');
  11158. });
  11159. });
  11160. }
  11161. }, {
  11162. flush: 'post'
  11163. });
  11164. const slotProps = vue.computed(() => ({
  11165. isActive,
  11166. isFocused,
  11167. controlRef,
  11168. blur,
  11169. focus
  11170. }));
  11171. function onClick(e) {
  11172. if (e.target !== document.activeElement) {
  11173. e.preventDefault();
  11174. }
  11175. }
  11176. function onKeydownClear(e) {
  11177. if (e.key !== 'Enter' && e.key !== ' ') return;
  11178. e.preventDefault();
  11179. e.stopPropagation();
  11180. props['onClick:clear']?.(new MouseEvent('click'));
  11181. }
  11182. useRender(() => {
  11183. const isOutlined = props.variant === 'outlined';
  11184. const hasPrepend = !!(slots['prepend-inner'] || props.prependInnerIcon);
  11185. const hasClear = !!(props.clearable || slots.clear);
  11186. const hasAppend = !!(slots['append-inner'] || props.appendInnerIcon || hasClear);
  11187. const label = () => slots.label ? slots.label({
  11188. ...slotProps.value,
  11189. label: props.label,
  11190. props: {
  11191. for: id.value
  11192. }
  11193. }) : props.label;
  11194. return vue.createVNode("div", vue.mergeProps({
  11195. "class": ['v-field', {
  11196. 'v-field--active': isActive.value,
  11197. 'v-field--appended': hasAppend,
  11198. 'v-field--center-affix': props.centerAffix ?? !isPlainOrUnderlined.value,
  11199. 'v-field--disabled': props.disabled,
  11200. 'v-field--dirty': props.dirty,
  11201. 'v-field--error': props.error,
  11202. 'v-field--flat': props.flat,
  11203. 'v-field--has-background': !!props.bgColor,
  11204. 'v-field--persistent-clear': props.persistentClear,
  11205. 'v-field--prepended': hasPrepend,
  11206. 'v-field--reverse': props.reverse,
  11207. 'v-field--single-line': props.singleLine,
  11208. 'v-field--no-label': !label(),
  11209. [`v-field--variant-${props.variant}`]: true
  11210. }, themeClasses.value, backgroundColorClasses.value, focusClasses.value, loaderClasses.value, roundedClasses.value, rtlClasses.value, props.class],
  11211. "style": [backgroundColorStyles.value, props.style],
  11212. "onClick": onClick
  11213. }, attrs), [vue.createVNode("div", {
  11214. "class": "v-field__overlay"
  11215. }, null), vue.createVNode(LoaderSlot, {
  11216. "name": "v-field",
  11217. "active": !!props.loading,
  11218. "color": props.error ? 'error' : typeof props.loading === 'string' ? props.loading : props.color
  11219. }, {
  11220. default: slots.loader
  11221. }), hasPrepend && vue.createVNode("div", {
  11222. "key": "prepend",
  11223. "class": "v-field__prepend-inner"
  11224. }, [props.prependInnerIcon && vue.createVNode(InputIcon, {
  11225. "key": "prepend-icon",
  11226. "name": "prependInner"
  11227. }, null), slots['prepend-inner']?.(slotProps.value)]), vue.createVNode("div", {
  11228. "class": "v-field__field",
  11229. "data-no-activator": ""
  11230. }, [['filled', 'solo', 'solo-inverted', 'solo-filled'].includes(props.variant) && hasLabel.value && vue.createVNode(VFieldLabel, {
  11231. "key": "floating-label",
  11232. "ref": floatingLabelRef,
  11233. "class": [textColorClasses.value],
  11234. "floating": true,
  11235. "for": id.value,
  11236. "style": textColorStyles.value
  11237. }, {
  11238. default: () => [label()]
  11239. }), hasLabel.value && vue.createVNode(VFieldLabel, {
  11240. "key": "label",
  11241. "ref": labelRef,
  11242. "for": id.value
  11243. }, {
  11244. default: () => [label()]
  11245. }), slots.default?.({
  11246. ...slotProps.value,
  11247. props: {
  11248. id: id.value,
  11249. class: 'v-field__input',
  11250. 'aria-describedby': messagesId.value
  11251. },
  11252. focus,
  11253. blur
  11254. })]), hasClear && vue.createVNode(VExpandXTransition, {
  11255. "key": "clear"
  11256. }, {
  11257. default: () => [vue.withDirectives(vue.createVNode("div", {
  11258. "class": "v-field__clearable",
  11259. "onMousedown": e => {
  11260. e.preventDefault();
  11261. e.stopPropagation();
  11262. }
  11263. }, [vue.createVNode(VDefaultsProvider, {
  11264. "defaults": {
  11265. VIcon: {
  11266. icon: props.clearIcon
  11267. }
  11268. }
  11269. }, {
  11270. default: () => [slots.clear ? slots.clear({
  11271. ...slotProps.value,
  11272. props: {
  11273. onKeydown: onKeydownClear,
  11274. onFocus: focus,
  11275. onBlur: blur,
  11276. onClick: props['onClick:clear']
  11277. }
  11278. }) : vue.createVNode(InputIcon, {
  11279. "name": "clear",
  11280. "onKeydown": onKeydownClear,
  11281. "onFocus": focus,
  11282. "onBlur": blur
  11283. }, null)]
  11284. })]), [[vue.vShow, props.dirty]])]
  11285. }), hasAppend && vue.createVNode("div", {
  11286. "key": "append",
  11287. "class": "v-field__append-inner"
  11288. }, [slots['append-inner']?.(slotProps.value), props.appendInnerIcon && vue.createVNode(InputIcon, {
  11289. "key": "append-icon",
  11290. "name": "appendInner"
  11291. }, null)]), vue.createVNode("div", {
  11292. "class": ['v-field__outline', textColorClasses.value],
  11293. "style": textColorStyles.value
  11294. }, [isOutlined && vue.createVNode(vue.Fragment, null, [vue.createVNode("div", {
  11295. "class": "v-field__outline__start"
  11296. }, null), hasLabel.value && vue.createVNode("div", {
  11297. "class": "v-field__outline__notch"
  11298. }, [vue.createVNode(VFieldLabel, {
  11299. "ref": floatingLabelRef,
  11300. "floating": true,
  11301. "for": id.value
  11302. }, {
  11303. default: () => [label()]
  11304. })]), vue.createVNode("div", {
  11305. "class": "v-field__outline__end"
  11306. }, null)]), isPlainOrUnderlined.value && hasLabel.value && vue.createVNode(VFieldLabel, {
  11307. "ref": floatingLabelRef,
  11308. "floating": true,
  11309. "for": id.value
  11310. }, {
  11311. default: () => [label()]
  11312. })])]);
  11313. });
  11314. return {
  11315. controlRef
  11316. };
  11317. }
  11318. });
  11319. // TODO: this is kinda slow, might be better to implicitly inherit props instead
  11320. function filterFieldProps(attrs) {
  11321. const keys = Object.keys(VField.props).filter(k => !isOn(k) && k !== 'class' && k !== 'style');
  11322. return pick(attrs, keys);
  11323. }
  11324. // Types
  11325. const activeTypes = ['color', 'file', 'time', 'date', 'datetime-local', 'week', 'month'];
  11326. const makeVTextFieldProps = propsFactory({
  11327. autofocus: Boolean,
  11328. counter: [Boolean, Number, String],
  11329. counterValue: [Number, Function],
  11330. prefix: String,
  11331. placeholder: String,
  11332. persistentPlaceholder: Boolean,
  11333. persistentCounter: Boolean,
  11334. suffix: String,
  11335. role: String,
  11336. type: {
  11337. type: String,
  11338. default: 'text'
  11339. },
  11340. modelModifiers: Object,
  11341. ...makeVInputProps(),
  11342. ...makeVFieldProps()
  11343. }, 'VTextField');
  11344. const VTextField = genericComponent()({
  11345. name: 'VTextField',
  11346. directives: {
  11347. Intersect
  11348. },
  11349. inheritAttrs: false,
  11350. props: makeVTextFieldProps(),
  11351. emits: {
  11352. 'click:control': e => true,
  11353. 'mousedown:control': e => true,
  11354. 'update:focused': focused => true,
  11355. 'update:modelValue': val => true
  11356. },
  11357. setup(props, _ref) {
  11358. let {
  11359. attrs,
  11360. emit,
  11361. slots
  11362. } = _ref;
  11363. const model = useProxiedModel(props, 'modelValue');
  11364. const {
  11365. isFocused,
  11366. focus,
  11367. blur
  11368. } = useFocus(props);
  11369. const counterValue = vue.computed(() => {
  11370. return typeof props.counterValue === 'function' ? props.counterValue(model.value) : typeof props.counterValue === 'number' ? props.counterValue : (model.value ?? '').toString().length;
  11371. });
  11372. const max = vue.computed(() => {
  11373. if (attrs.maxlength) return attrs.maxlength;
  11374. if (!props.counter || typeof props.counter !== 'number' && typeof props.counter !== 'string') return undefined;
  11375. return props.counter;
  11376. });
  11377. const isPlainOrUnderlined = vue.computed(() => ['plain', 'underlined'].includes(props.variant));
  11378. function onIntersect(isIntersecting, entries) {
  11379. if (!props.autofocus || !isIntersecting) return;
  11380. entries[0].target?.focus?.();
  11381. }
  11382. const vInputRef = vue.ref();
  11383. const vFieldRef = vue.ref();
  11384. const inputRef = vue.ref();
  11385. const isActive = vue.computed(() => activeTypes.includes(props.type) || props.persistentPlaceholder || isFocused.value || props.active);
  11386. function onFocus() {
  11387. if (inputRef.value !== document.activeElement) {
  11388. inputRef.value?.focus();
  11389. }
  11390. if (!isFocused.value) focus();
  11391. }
  11392. function onControlMousedown(e) {
  11393. emit('mousedown:control', e);
  11394. if (e.target === inputRef.value) return;
  11395. onFocus();
  11396. e.preventDefault();
  11397. }
  11398. function onControlClick(e) {
  11399. onFocus();
  11400. emit('click:control', e);
  11401. }
  11402. function onClear(e) {
  11403. e.stopPropagation();
  11404. onFocus();
  11405. vue.nextTick(() => {
  11406. model.value = null;
  11407. callEvent(props['onClick:clear'], e);
  11408. });
  11409. }
  11410. function onInput(e) {
  11411. const el = e.target;
  11412. model.value = el.value;
  11413. if (props.modelModifiers?.trim && ['text', 'search', 'password', 'tel', 'url'].includes(props.type)) {
  11414. const caretPosition = [el.selectionStart, el.selectionEnd];
  11415. vue.nextTick(() => {
  11416. el.selectionStart = caretPosition[0];
  11417. el.selectionEnd = caretPosition[1];
  11418. });
  11419. }
  11420. }
  11421. useRender(() => {
  11422. const hasCounter = !!(slots.counter || props.counter !== false && props.counter != null);
  11423. const hasDetails = !!(hasCounter || slots.details);
  11424. const [rootAttrs, inputAttrs] = filterInputAttrs(attrs);
  11425. const {
  11426. modelValue: _,
  11427. ...inputProps
  11428. } = VInput.filterProps(props);
  11429. const fieldProps = filterFieldProps(props);
  11430. return vue.createVNode(VInput, vue.mergeProps({
  11431. "ref": vInputRef,
  11432. "modelValue": model.value,
  11433. "onUpdate:modelValue": $event => model.value = $event,
  11434. "class": ['v-text-field', {
  11435. 'v-text-field--prefixed': props.prefix,
  11436. 'v-text-field--suffixed': props.suffix,
  11437. 'v-input--plain-underlined': isPlainOrUnderlined.value
  11438. }, props.class],
  11439. "style": props.style
  11440. }, rootAttrs, inputProps, {
  11441. "centerAffix": !isPlainOrUnderlined.value,
  11442. "focused": isFocused.value
  11443. }), {
  11444. ...slots,
  11445. default: _ref2 => {
  11446. let {
  11447. id,
  11448. isDisabled,
  11449. isDirty,
  11450. isReadonly,
  11451. isValid
  11452. } = _ref2;
  11453. return vue.createVNode(VField, vue.mergeProps({
  11454. "ref": vFieldRef,
  11455. "onMousedown": onControlMousedown,
  11456. "onClick": onControlClick,
  11457. "onClick:clear": onClear,
  11458. "onClick:prependInner": props['onClick:prependInner'],
  11459. "onClick:appendInner": props['onClick:appendInner'],
  11460. "role": props.role
  11461. }, fieldProps, {
  11462. "id": id.value,
  11463. "active": isActive.value || isDirty.value,
  11464. "dirty": isDirty.value || props.dirty,
  11465. "disabled": isDisabled.value,
  11466. "focused": isFocused.value,
  11467. "error": isValid.value === false
  11468. }), {
  11469. ...slots,
  11470. default: _ref3 => {
  11471. let {
  11472. props: {
  11473. class: fieldClass,
  11474. ...slotProps
  11475. }
  11476. } = _ref3;
  11477. const inputNode = vue.withDirectives(vue.createVNode("input", vue.mergeProps({
  11478. "ref": inputRef,
  11479. "value": model.value,
  11480. "onInput": onInput,
  11481. "autofocus": props.autofocus,
  11482. "readonly": isReadonly.value,
  11483. "disabled": isDisabled.value,
  11484. "name": props.name,
  11485. "placeholder": props.placeholder,
  11486. "size": 1,
  11487. "type": props.type,
  11488. "onFocus": onFocus,
  11489. "onBlur": blur
  11490. }, slotProps, inputAttrs), null), [[vue.resolveDirective("intersect"), {
  11491. handler: onIntersect
  11492. }, null, {
  11493. once: true
  11494. }]]);
  11495. return vue.createVNode(vue.Fragment, null, [props.prefix && vue.createVNode("span", {
  11496. "class": "v-text-field__prefix"
  11497. }, [vue.createVNode("span", {
  11498. "class": "v-text-field__prefix__text"
  11499. }, [props.prefix])]), slots.default ? vue.createVNode("div", {
  11500. "class": fieldClass,
  11501. "data-no-activator": ""
  11502. }, [slots.default(), inputNode]) : vue.cloneVNode(inputNode, {
  11503. class: fieldClass
  11504. }), props.suffix && vue.createVNode("span", {
  11505. "class": "v-text-field__suffix"
  11506. }, [vue.createVNode("span", {
  11507. "class": "v-text-field__suffix__text"
  11508. }, [props.suffix])])]);
  11509. }
  11510. });
  11511. },
  11512. 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, {
  11513. "active": props.persistentCounter || isFocused.value,
  11514. "value": counterValue.value,
  11515. "max": max.value,
  11516. "disabled": props.disabled
  11517. }, slots.counter)])]) : undefined
  11518. });
  11519. });
  11520. return forwardRefs({}, vInputRef, vFieldRef, inputRef);
  11521. }
  11522. });
  11523. // Types
  11524. const makeVVirtualScrollItemProps = propsFactory({
  11525. renderless: Boolean,
  11526. ...makeComponentProps()
  11527. }, 'VVirtualScrollItem');
  11528. const VVirtualScrollItem = genericComponent()({
  11529. name: 'VVirtualScrollItem',
  11530. inheritAttrs: false,
  11531. props: makeVVirtualScrollItemProps(),
  11532. emits: {
  11533. 'update:height': height => true
  11534. },
  11535. setup(props, _ref) {
  11536. let {
  11537. attrs,
  11538. emit,
  11539. slots
  11540. } = _ref;
  11541. const {
  11542. resizeRef,
  11543. contentRect
  11544. } = useResizeObserver(undefined, 'border');
  11545. vue.watch(() => contentRect.value?.height, height => {
  11546. if (height != null) emit('update:height', height);
  11547. });
  11548. useRender(() => props.renderless ? vue.createVNode(vue.Fragment, null, [slots.default?.({
  11549. itemRef: resizeRef
  11550. })]) : vue.createVNode("div", vue.mergeProps({
  11551. "ref": resizeRef,
  11552. "class": ['v-virtual-scroll__item', props.class],
  11553. "style": props.style
  11554. }, attrs), [slots.default?.()]));
  11555. }
  11556. });
  11557. // Composables
  11558. // Types
  11559. const UP = -1;
  11560. const DOWN = 1;
  11561. /** Determines how large each batch of items should be */
  11562. const BUFFER_PX = 100;
  11563. const makeVirtualProps = propsFactory({
  11564. itemHeight: {
  11565. type: [Number, String],
  11566. default: null
  11567. },
  11568. height: [Number, String]
  11569. }, 'virtual');
  11570. function useVirtual(props, items) {
  11571. const display = useDisplay();
  11572. const itemHeight = vue.shallowRef(0);
  11573. vue.watchEffect(() => {
  11574. itemHeight.value = parseFloat(props.itemHeight || 0);
  11575. });
  11576. const first = vue.shallowRef(0);
  11577. const last = vue.shallowRef(Math.ceil(
  11578. // Assume 16px items filling the entire screen height if
  11579. // not provided. This is probably incorrect but it minimises
  11580. // the chance of ending up with empty space at the bottom.
  11581. // The default value is set here to avoid poisoning getSize()
  11582. (parseInt(props.height) || display.height.value) / (itemHeight.value || 16)) || 1);
  11583. const paddingTop = vue.shallowRef(0);
  11584. const paddingBottom = vue.shallowRef(0);
  11585. /** The scrollable element */
  11586. const containerRef = vue.ref();
  11587. /** An element marking the top of the scrollable area,
  11588. * used to add an offset if there's padding or other elements above the virtual list */
  11589. const markerRef = vue.ref();
  11590. /** markerRef's offsetTop, lazily evaluated */
  11591. let markerOffset = 0;
  11592. const {
  11593. resizeRef,
  11594. contentRect
  11595. } = useResizeObserver();
  11596. vue.watchEffect(() => {
  11597. resizeRef.value = containerRef.value;
  11598. });
  11599. const viewportHeight = vue.computed(() => {
  11600. return containerRef.value === document.documentElement ? display.height.value : contentRect.value?.height || parseInt(props.height) || 0;
  11601. });
  11602. /** All static elements have been rendered and we have an assumed item height */
  11603. const hasInitialRender = vue.computed(() => {
  11604. return !!(containerRef.value && markerRef.value && viewportHeight.value && itemHeight.value);
  11605. });
  11606. let sizes = Array.from({
  11607. length: items.value.length
  11608. });
  11609. let offsets = Array.from({
  11610. length: items.value.length
  11611. });
  11612. const updateTime = vue.shallowRef(0);
  11613. let targetScrollIndex = -1;
  11614. function getSize(index) {
  11615. return sizes[index] || itemHeight.value;
  11616. }
  11617. const updateOffsets = debounce(() => {
  11618. const start = performance.now();
  11619. offsets[0] = 0;
  11620. const length = items.value.length;
  11621. for (let i = 1; i <= length - 1; i++) {
  11622. offsets[i] = (offsets[i - 1] || 0) + getSize(i - 1);
  11623. }
  11624. updateTime.value = Math.max(updateTime.value, performance.now() - start);
  11625. }, updateTime);
  11626. const unwatch = vue.watch(hasInitialRender, v => {
  11627. if (!v) return;
  11628. // First render is complete, update offsets and visible
  11629. // items in case our assumed item height was incorrect
  11630. unwatch();
  11631. markerOffset = markerRef.value.offsetTop;
  11632. updateOffsets.immediate();
  11633. calculateVisibleItems();
  11634. if (!~targetScrollIndex) return;
  11635. vue.nextTick(() => {
  11636. IN_BROWSER && window.requestAnimationFrame(() => {
  11637. scrollToIndex(targetScrollIndex);
  11638. targetScrollIndex = -1;
  11639. });
  11640. });
  11641. });
  11642. vue.onScopeDispose(() => {
  11643. updateOffsets.clear();
  11644. });
  11645. function handleItemResize(index, height) {
  11646. const prevHeight = sizes[index];
  11647. const prevMinHeight = itemHeight.value;
  11648. itemHeight.value = prevMinHeight ? Math.min(itemHeight.value, height) : height;
  11649. if (prevHeight !== height || prevMinHeight !== itemHeight.value) {
  11650. sizes[index] = height;
  11651. updateOffsets();
  11652. }
  11653. }
  11654. function calculateOffset(index) {
  11655. index = clamp(index, 0, items.value.length - 1);
  11656. return offsets[index] || 0;
  11657. }
  11658. function calculateIndex(scrollTop) {
  11659. return binaryClosest(offsets, scrollTop);
  11660. }
  11661. let lastScrollTop = 0;
  11662. let scrollVelocity = 0;
  11663. let lastScrollTime = 0;
  11664. vue.watch(viewportHeight, (val, oldVal) => {
  11665. if (oldVal) {
  11666. calculateVisibleItems();
  11667. if (val < oldVal) {
  11668. requestAnimationFrame(() => {
  11669. scrollVelocity = 0;
  11670. calculateVisibleItems();
  11671. });
  11672. }
  11673. }
  11674. });
  11675. let scrollTimeout = -1;
  11676. function handleScroll() {
  11677. if (!containerRef.value || !markerRef.value) return;
  11678. const scrollTop = containerRef.value.scrollTop;
  11679. const scrollTime = performance.now();
  11680. const scrollDeltaT = scrollTime - lastScrollTime;
  11681. if (scrollDeltaT > 500) {
  11682. scrollVelocity = Math.sign(scrollTop - lastScrollTop);
  11683. // Not super important, only update at the
  11684. // start of a scroll sequence to avoid reflows
  11685. markerOffset = markerRef.value.offsetTop;
  11686. } else {
  11687. scrollVelocity = scrollTop - lastScrollTop;
  11688. }
  11689. lastScrollTop = scrollTop;
  11690. lastScrollTime = scrollTime;
  11691. window.clearTimeout(scrollTimeout);
  11692. scrollTimeout = window.setTimeout(handleScrollend, 500);
  11693. calculateVisibleItems();
  11694. }
  11695. function handleScrollend() {
  11696. if (!containerRef.value || !markerRef.value) return;
  11697. scrollVelocity = 0;
  11698. lastScrollTime = 0;
  11699. window.clearTimeout(scrollTimeout);
  11700. calculateVisibleItems();
  11701. }
  11702. let raf = -1;
  11703. function calculateVisibleItems() {
  11704. cancelAnimationFrame(raf);
  11705. raf = requestAnimationFrame(_calculateVisibleItems);
  11706. }
  11707. function _calculateVisibleItems() {
  11708. if (!containerRef.value || !viewportHeight.value) return;
  11709. const scrollTop = lastScrollTop - markerOffset;
  11710. const direction = Math.sign(scrollVelocity);
  11711. const startPx = Math.max(0, scrollTop - BUFFER_PX);
  11712. const start = clamp(calculateIndex(startPx), 0, items.value.length);
  11713. const endPx = scrollTop + viewportHeight.value + BUFFER_PX;
  11714. const end = clamp(calculateIndex(endPx) + 1, start + 1, items.value.length);
  11715. if (
  11716. // Only update the side we're scrolling towards,
  11717. // the other side will be updated incidentally
  11718. (direction !== UP || start < first.value) && (direction !== DOWN || end > last.value)) {
  11719. const topOverflow = calculateOffset(first.value) - calculateOffset(start);
  11720. const bottomOverflow = calculateOffset(end) - calculateOffset(last.value);
  11721. const bufferOverflow = Math.max(topOverflow, bottomOverflow);
  11722. if (bufferOverflow > BUFFER_PX) {
  11723. first.value = start;
  11724. last.value = end;
  11725. } else {
  11726. // Only update the side that's reached its limit if there's still buffer left
  11727. if (start <= 0) first.value = start;
  11728. if (end >= items.value.length) last.value = end;
  11729. }
  11730. }
  11731. paddingTop.value = calculateOffset(first.value);
  11732. paddingBottom.value = calculateOffset(items.value.length) - calculateOffset(last.value);
  11733. }
  11734. function scrollToIndex(index) {
  11735. const offset = calculateOffset(index);
  11736. if (!containerRef.value || index && !offset) {
  11737. targetScrollIndex = index;
  11738. } else {
  11739. containerRef.value.scrollTop = offset;
  11740. }
  11741. }
  11742. const computedItems = vue.computed(() => {
  11743. return items.value.slice(first.value, last.value).map((item, index) => ({
  11744. raw: item,
  11745. index: index + first.value,
  11746. key: isObject(item) && 'value' in item ? item.value : index + first.value
  11747. }));
  11748. });
  11749. vue.watch(items, () => {
  11750. sizes = Array.from({
  11751. length: items.value.length
  11752. });
  11753. offsets = Array.from({
  11754. length: items.value.length
  11755. });
  11756. updateOffsets.immediate();
  11757. calculateVisibleItems();
  11758. }, {
  11759. deep: true
  11760. });
  11761. return {
  11762. calculateVisibleItems,
  11763. containerRef,
  11764. markerRef,
  11765. computedItems,
  11766. paddingTop,
  11767. paddingBottom,
  11768. scrollToIndex,
  11769. handleScroll,
  11770. handleScrollend,
  11771. handleItemResize
  11772. };
  11773. }
  11774. // https://gist.github.com/robertleeplummerjr/1cc657191d34ecd0a324
  11775. function binaryClosest(arr, val) {
  11776. let high = arr.length - 1;
  11777. let low = 0;
  11778. let mid = 0;
  11779. let item = null;
  11780. let target = -1;
  11781. if (arr[high] < val) {
  11782. return high;
  11783. }
  11784. while (low <= high) {
  11785. mid = low + high >> 1;
  11786. item = arr[mid];
  11787. if (item > val) {
  11788. high = mid - 1;
  11789. } else if (item < val) {
  11790. target = mid;
  11791. low = mid + 1;
  11792. } else if (item === val) {
  11793. return mid;
  11794. } else {
  11795. return low;
  11796. }
  11797. }
  11798. return target;
  11799. }
  11800. // Types
  11801. const makeVVirtualScrollProps = propsFactory({
  11802. items: {
  11803. type: Array,
  11804. default: () => []
  11805. },
  11806. renderless: Boolean,
  11807. ...makeVirtualProps(),
  11808. ...makeComponentProps(),
  11809. ...makeDimensionProps()
  11810. }, 'VVirtualScroll');
  11811. const VVirtualScroll = genericComponent()({
  11812. name: 'VVirtualScroll',
  11813. props: makeVVirtualScrollProps(),
  11814. setup(props, _ref) {
  11815. let {
  11816. slots
  11817. } = _ref;
  11818. const vm = getCurrentInstance('VVirtualScroll');
  11819. const {
  11820. dimensionStyles
  11821. } = useDimension(props);
  11822. const {
  11823. calculateVisibleItems,
  11824. containerRef,
  11825. markerRef,
  11826. handleScroll,
  11827. handleScrollend,
  11828. handleItemResize,
  11829. scrollToIndex,
  11830. paddingTop,
  11831. paddingBottom,
  11832. computedItems
  11833. } = useVirtual(props, vue.toRef(props, 'items'));
  11834. useToggleScope(() => props.renderless, () => {
  11835. function handleListeners() {
  11836. let add = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : false;
  11837. const method = add ? 'addEventListener' : 'removeEventListener';
  11838. if (containerRef.value === document.documentElement) {
  11839. document[method]('scroll', handleScroll, {
  11840. passive: true
  11841. });
  11842. document[method]('scrollend', handleScrollend);
  11843. } else {
  11844. containerRef.value?.[method]('scroll', handleScroll, {
  11845. passive: true
  11846. });
  11847. containerRef.value?.[method]('scrollend', handleScrollend);
  11848. }
  11849. }
  11850. vue.onMounted(() => {
  11851. containerRef.value = getScrollParent(vm.vnode.el, true);
  11852. handleListeners(true);
  11853. });
  11854. vue.onScopeDispose(handleListeners);
  11855. });
  11856. useRender(() => {
  11857. const children = computedItems.value.map(item => vue.createVNode(VVirtualScrollItem, {
  11858. "key": item.key,
  11859. "renderless": props.renderless,
  11860. "onUpdate:height": height => handleItemResize(item.index, height)
  11861. }, {
  11862. default: slotProps => slots.default?.({
  11863. item: item.raw,
  11864. index: item.index,
  11865. ...slotProps
  11866. })
  11867. }));
  11868. return props.renderless ? vue.createVNode(vue.Fragment, null, [vue.createVNode("div", {
  11869. "ref": markerRef,
  11870. "class": "v-virtual-scroll__spacer",
  11871. "style": {
  11872. paddingTop: convertToUnit(paddingTop.value)
  11873. }
  11874. }, null), children, vue.createVNode("div", {
  11875. "class": "v-virtual-scroll__spacer",
  11876. "style": {
  11877. paddingBottom: convertToUnit(paddingBottom.value)
  11878. }
  11879. }, null)]) : vue.createVNode("div", {
  11880. "ref": containerRef,
  11881. "class": ['v-virtual-scroll', props.class],
  11882. "onScrollPassive": handleScroll,
  11883. "onScrollend": handleScrollend,
  11884. "style": [dimensionStyles.value, props.style]
  11885. }, [vue.createVNode("div", {
  11886. "ref": markerRef,
  11887. "class": "v-virtual-scroll__container",
  11888. "style": {
  11889. paddingTop: convertToUnit(paddingTop.value),
  11890. paddingBottom: convertToUnit(paddingBottom.value)
  11891. }
  11892. }, [children])]);
  11893. });
  11894. return {
  11895. calculateVisibleItems,
  11896. scrollToIndex
  11897. };
  11898. }
  11899. });
  11900. // Utilities
  11901. // Types
  11902. function useScrolling(listRef, textFieldRef) {
  11903. const isScrolling = vue.shallowRef(false);
  11904. let scrollTimeout;
  11905. function onListScroll(e) {
  11906. cancelAnimationFrame(scrollTimeout);
  11907. isScrolling.value = true;
  11908. scrollTimeout = requestAnimationFrame(() => {
  11909. scrollTimeout = requestAnimationFrame(() => {
  11910. isScrolling.value = false;
  11911. });
  11912. });
  11913. }
  11914. async function finishScrolling() {
  11915. await new Promise(resolve => requestAnimationFrame(resolve));
  11916. await new Promise(resolve => requestAnimationFrame(resolve));
  11917. await new Promise(resolve => requestAnimationFrame(resolve));
  11918. await new Promise(resolve => {
  11919. if (isScrolling.value) {
  11920. const stop = vue.watch(isScrolling, () => {
  11921. stop();
  11922. resolve();
  11923. });
  11924. } else resolve();
  11925. });
  11926. }
  11927. async function onListKeydown(e) {
  11928. if (e.key === 'Tab') {
  11929. textFieldRef.value?.focus();
  11930. }
  11931. if (!['PageDown', 'PageUp', 'Home', 'End'].includes(e.key)) return;
  11932. const el = listRef.value?.$el;
  11933. if (!el) return;
  11934. if (e.key === 'Home' || e.key === 'End') {
  11935. el.scrollTo({
  11936. top: e.key === 'Home' ? 0 : el.scrollHeight,
  11937. behavior: 'smooth'
  11938. });
  11939. }
  11940. await finishScrolling();
  11941. const children = el.querySelectorAll(':scope > :not(.v-virtual-scroll__spacer)');
  11942. if (e.key === 'PageDown' || e.key === 'Home') {
  11943. const top = el.getBoundingClientRect().top;
  11944. for (const child of children) {
  11945. if (child.getBoundingClientRect().top >= top) {
  11946. child.focus();
  11947. break;
  11948. }
  11949. }
  11950. } else {
  11951. const bottom = el.getBoundingClientRect().bottom;
  11952. for (const child of [...children].reverse()) {
  11953. if (child.getBoundingClientRect().bottom <= bottom) {
  11954. child.focus();
  11955. break;
  11956. }
  11957. }
  11958. }
  11959. }
  11960. return {
  11961. onScrollPassive: onListScroll,
  11962. onKeydown: onListKeydown
  11963. }; // typescript doesn't know about vue's event merging
  11964. }
  11965. // Types
  11966. const makeSelectProps = propsFactory({
  11967. chips: Boolean,
  11968. closableChips: Boolean,
  11969. closeText: {
  11970. type: String,
  11971. default: '$vuetify.close'
  11972. },
  11973. openText: {
  11974. type: String,
  11975. default: '$vuetify.open'
  11976. },
  11977. eager: Boolean,
  11978. hideNoData: Boolean,
  11979. hideSelected: Boolean,
  11980. listProps: {
  11981. type: Object
  11982. },
  11983. menu: Boolean,
  11984. menuIcon: {
  11985. type: IconValue,
  11986. default: '$dropdown'
  11987. },
  11988. menuProps: {
  11989. type: Object
  11990. },
  11991. multiple: Boolean,
  11992. noDataText: {
  11993. type: String,
  11994. default: '$vuetify.noDataText'
  11995. },
  11996. openOnClear: Boolean,
  11997. itemColor: String,
  11998. ...makeItemsProps({
  11999. itemChildren: false
  12000. })
  12001. }, 'Select');
  12002. const makeVSelectProps = propsFactory({
  12003. ...makeSelectProps(),
  12004. ...omit(makeVTextFieldProps({
  12005. modelValue: null,
  12006. role: 'combobox'
  12007. }), ['validationValue', 'dirty', 'appendInnerIcon']),
  12008. ...makeTransitionProps({
  12009. transition: {
  12010. component: VDialogTransition
  12011. }
  12012. })
  12013. }, 'VSelect');
  12014. const VSelect = genericComponent()({
  12015. name: 'VSelect',
  12016. props: makeVSelectProps(),
  12017. emits: {
  12018. 'update:focused': focused => true,
  12019. 'update:modelValue': value => true,
  12020. 'update:menu': ue => true
  12021. },
  12022. setup(props, _ref) {
  12023. let {
  12024. slots
  12025. } = _ref;
  12026. const {
  12027. t
  12028. } = useLocale();
  12029. const vTextFieldRef = vue.ref();
  12030. const vMenuRef = vue.ref();
  12031. const vVirtualScrollRef = vue.ref();
  12032. const _menu = useProxiedModel(props, 'menu');
  12033. const menu = vue.computed({
  12034. get: () => _menu.value,
  12035. set: v => {
  12036. if (_menu.value && !v && vMenuRef.value?.ΨopenChildren.size) return;
  12037. _menu.value = v;
  12038. }
  12039. });
  12040. const {
  12041. items,
  12042. transformIn,
  12043. transformOut
  12044. } = useItems(props);
  12045. const model = useProxiedModel(props, 'modelValue', [], v => transformIn(v === null ? [null] : wrapInArray(v)), v => {
  12046. const transformed = transformOut(v);
  12047. return props.multiple ? transformed : transformed[0] ?? null;
  12048. });
  12049. const counterValue = vue.computed(() => {
  12050. return typeof props.counterValue === 'function' ? props.counterValue(model.value) : typeof props.counterValue === 'number' ? props.counterValue : model.value.length;
  12051. });
  12052. const form = useForm(props);
  12053. const selectedValues = vue.computed(() => model.value.map(selection => selection.value));
  12054. const isFocused = vue.shallowRef(false);
  12055. const label = vue.computed(() => menu.value ? props.closeText : props.openText);
  12056. let keyboardLookupPrefix = '';
  12057. let keyboardLookupLastTime;
  12058. const displayItems = vue.computed(() => {
  12059. if (props.hideSelected) {
  12060. return items.value.filter(item => !model.value.some(s => props.valueComparator(s, item)));
  12061. }
  12062. return items.value;
  12063. });
  12064. const menuDisabled = vue.computed(() => props.hideNoData && !displayItems.value.length || form.isReadonly.value || form.isDisabled.value);
  12065. const computedMenuProps = vue.computed(() => {
  12066. return {
  12067. ...props.menuProps,
  12068. activatorProps: {
  12069. ...(props.menuProps?.activatorProps || {}),
  12070. 'aria-haspopup': 'listbox' // Set aria-haspopup to 'listbox'
  12071. }
  12072. };
  12073. });
  12074. const listRef = vue.ref();
  12075. const listEvents = useScrolling(listRef, vTextFieldRef);
  12076. function onClear(e) {
  12077. if (props.openOnClear) {
  12078. menu.value = true;
  12079. }
  12080. }
  12081. function onMousedownControl() {
  12082. if (menuDisabled.value) return;
  12083. menu.value = !menu.value;
  12084. }
  12085. function onListKeydown(e) {
  12086. if (checkPrintable(e)) {
  12087. onKeydown(e);
  12088. }
  12089. }
  12090. function onKeydown(e) {
  12091. if (!e.key || form.isReadonly.value) return;
  12092. if (['Enter', ' ', 'ArrowDown', 'ArrowUp', 'Home', 'End'].includes(e.key)) {
  12093. e.preventDefault();
  12094. }
  12095. if (['Enter', 'ArrowDown', ' '].includes(e.key)) {
  12096. menu.value = true;
  12097. }
  12098. if (['Escape', 'Tab'].includes(e.key)) {
  12099. menu.value = false;
  12100. }
  12101. if (e.key === 'Home') {
  12102. listRef.value?.focus('first');
  12103. } else if (e.key === 'End') {
  12104. listRef.value?.focus('last');
  12105. }
  12106. // html select hotkeys
  12107. const KEYBOARD_LOOKUP_THRESHOLD = 1000; // milliseconds
  12108. if (props.multiple || !checkPrintable(e)) return;
  12109. const now = performance.now();
  12110. if (now - keyboardLookupLastTime > KEYBOARD_LOOKUP_THRESHOLD) {
  12111. keyboardLookupPrefix = '';
  12112. }
  12113. keyboardLookupPrefix += e.key.toLowerCase();
  12114. keyboardLookupLastTime = now;
  12115. const item = items.value.find(item => item.title.toLowerCase().startsWith(keyboardLookupPrefix));
  12116. if (item !== undefined) {
  12117. model.value = [item];
  12118. const index = displayItems.value.indexOf(item);
  12119. IN_BROWSER && window.requestAnimationFrame(() => {
  12120. index >= 0 && vVirtualScrollRef.value?.scrollToIndex(index);
  12121. });
  12122. }
  12123. }
  12124. /** @param set - null means toggle */
  12125. function select(item) {
  12126. let set = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : true;
  12127. if (item.props.disabled) return;
  12128. if (props.multiple) {
  12129. const index = model.value.findIndex(selection => props.valueComparator(selection.value, item.value));
  12130. const add = set == null ? !~index : set;
  12131. if (~index) {
  12132. const value = add ? [...model.value, item] : [...model.value];
  12133. value.splice(index, 1);
  12134. model.value = value;
  12135. } else if (add) {
  12136. model.value = [...model.value, item];
  12137. }
  12138. } else {
  12139. const add = set !== false;
  12140. model.value = add ? [item] : [];
  12141. vue.nextTick(() => {
  12142. menu.value = false;
  12143. });
  12144. }
  12145. }
  12146. function onBlur(e) {
  12147. if (!listRef.value?.$el.contains(e.relatedTarget)) {
  12148. menu.value = false;
  12149. }
  12150. }
  12151. function onAfterEnter() {
  12152. if (props.eager) {
  12153. vVirtualScrollRef.value?.calculateVisibleItems();
  12154. }
  12155. }
  12156. function onAfterLeave() {
  12157. if (isFocused.value) {
  12158. vTextFieldRef.value?.focus();
  12159. }
  12160. }
  12161. function onFocusin(e) {
  12162. isFocused.value = true;
  12163. }
  12164. function onModelUpdate(v) {
  12165. if (v == null) model.value = [];else if (matchesSelector(vTextFieldRef.value, ':autofill') || matchesSelector(vTextFieldRef.value, ':-webkit-autofill')) {
  12166. const item = items.value.find(item => item.title === v);
  12167. if (item) {
  12168. select(item);
  12169. }
  12170. } else if (vTextFieldRef.value) {
  12171. vTextFieldRef.value.value = '';
  12172. }
  12173. }
  12174. vue.watch(menu, () => {
  12175. if (!props.hideSelected && menu.value && model.value.length) {
  12176. const index = displayItems.value.findIndex(item => model.value.some(s => props.valueComparator(s.value, item.value)));
  12177. IN_BROWSER && window.requestAnimationFrame(() => {
  12178. index >= 0 && vVirtualScrollRef.value?.scrollToIndex(index);
  12179. });
  12180. }
  12181. });
  12182. vue.watch(() => props.items, (newVal, oldVal) => {
  12183. if (menu.value) return;
  12184. if (isFocused.value && !oldVal.length && newVal.length) {
  12185. menu.value = true;
  12186. }
  12187. });
  12188. useRender(() => {
  12189. const hasChips = !!(props.chips || slots.chip);
  12190. const hasList = !!(!props.hideNoData || displayItems.value.length || slots['prepend-item'] || slots['append-item'] || slots['no-data']);
  12191. const isDirty = model.value.length > 0;
  12192. const textFieldProps = VTextField.filterProps(props);
  12193. const placeholder = isDirty || !isFocused.value && props.label && !props.persistentPlaceholder ? undefined : props.placeholder;
  12194. return vue.createVNode(VTextField, vue.mergeProps({
  12195. "ref": vTextFieldRef
  12196. }, textFieldProps, {
  12197. "modelValue": model.value.map(v => v.props.value).join(', '),
  12198. "onUpdate:modelValue": onModelUpdate,
  12199. "focused": isFocused.value,
  12200. "onUpdate:focused": $event => isFocused.value = $event,
  12201. "validationValue": model.externalValue,
  12202. "counterValue": counterValue.value,
  12203. "dirty": isDirty,
  12204. "class": ['v-select', {
  12205. 'v-select--active-menu': menu.value,
  12206. 'v-select--chips': !!props.chips,
  12207. [`v-select--${props.multiple ? 'multiple' : 'single'}`]: true,
  12208. 'v-select--selected': model.value.length,
  12209. 'v-select--selection-slot': !!slots.selection
  12210. }, props.class],
  12211. "style": props.style,
  12212. "inputmode": "none",
  12213. "placeholder": placeholder,
  12214. "onClick:clear": onClear,
  12215. "onMousedown:control": onMousedownControl,
  12216. "onBlur": onBlur,
  12217. "onKeydown": onKeydown,
  12218. "aria-label": t(label.value),
  12219. "title": t(label.value)
  12220. }), {
  12221. ...slots,
  12222. default: () => vue.createVNode(vue.Fragment, null, [vue.createVNode(VMenu, vue.mergeProps({
  12223. "ref": vMenuRef,
  12224. "modelValue": menu.value,
  12225. "onUpdate:modelValue": $event => menu.value = $event,
  12226. "activator": "parent",
  12227. "contentClass": "v-select__content",
  12228. "disabled": menuDisabled.value,
  12229. "eager": props.eager,
  12230. "maxHeight": 310,
  12231. "openOnClick": false,
  12232. "closeOnContentClick": false,
  12233. "transition": props.transition,
  12234. "onAfterEnter": onAfterEnter,
  12235. "onAfterLeave": onAfterLeave
  12236. }, computedMenuProps.value), {
  12237. default: () => [hasList && vue.createVNode(VList, vue.mergeProps({
  12238. "ref": listRef,
  12239. "selected": selectedValues.value,
  12240. "selectStrategy": props.multiple ? 'independent' : 'single-independent',
  12241. "onMousedown": e => e.preventDefault(),
  12242. "onKeydown": onListKeydown,
  12243. "onFocusin": onFocusin,
  12244. "tabindex": "-1",
  12245. "aria-live": "polite",
  12246. "color": props.itemColor ?? props.color
  12247. }, listEvents, props.listProps), {
  12248. default: () => [slots['prepend-item']?.(), !displayItems.value.length && !props.hideNoData && (slots['no-data']?.() ?? vue.createVNode(VListItem, {
  12249. "key": "no-data",
  12250. "title": t(props.noDataText)
  12251. }, null)), vue.createVNode(VVirtualScroll, {
  12252. "ref": vVirtualScrollRef,
  12253. "renderless": true,
  12254. "items": displayItems.value
  12255. }, {
  12256. default: _ref2 => {
  12257. let {
  12258. item,
  12259. index,
  12260. itemRef
  12261. } = _ref2;
  12262. const itemProps = vue.mergeProps(item.props, {
  12263. ref: itemRef,
  12264. key: item.value,
  12265. onClick: () => select(item, null)
  12266. });
  12267. return slots.item?.({
  12268. item,
  12269. index,
  12270. props: itemProps
  12271. }) ?? vue.createVNode(VListItem, vue.mergeProps(itemProps, {
  12272. "role": "option"
  12273. }), {
  12274. prepend: _ref3 => {
  12275. let {
  12276. isSelected
  12277. } = _ref3;
  12278. return vue.createVNode(vue.Fragment, null, [props.multiple && !props.hideSelected ? vue.createVNode(VCheckboxBtn, {
  12279. "key": item.value,
  12280. "modelValue": isSelected,
  12281. "ripple": false,
  12282. "tabindex": "-1"
  12283. }, null) : undefined, item.props.prependAvatar && vue.createVNode(VAvatar, {
  12284. "image": item.props.prependAvatar
  12285. }, null), item.props.prependIcon && vue.createVNode(VIcon, {
  12286. "icon": item.props.prependIcon
  12287. }, null)]);
  12288. }
  12289. });
  12290. }
  12291. }), slots['append-item']?.()]
  12292. })]
  12293. }), model.value.map((item, index) => {
  12294. function onChipClose(e) {
  12295. e.stopPropagation();
  12296. e.preventDefault();
  12297. select(item, false);
  12298. }
  12299. const slotProps = {
  12300. 'onClick:close': onChipClose,
  12301. onKeydown(e) {
  12302. if (e.key !== 'Enter' && e.key !== ' ') return;
  12303. e.preventDefault();
  12304. e.stopPropagation();
  12305. onChipClose(e);
  12306. },
  12307. onMousedown(e) {
  12308. e.preventDefault();
  12309. e.stopPropagation();
  12310. },
  12311. modelValue: true,
  12312. 'onUpdate:modelValue': undefined
  12313. };
  12314. const hasSlot = hasChips ? !!slots.chip : !!slots.selection;
  12315. const slotContent = hasSlot ? ensureValidVNode(hasChips ? slots.chip({
  12316. item,
  12317. index,
  12318. props: slotProps
  12319. }) : slots.selection({
  12320. item,
  12321. index
  12322. })) : undefined;
  12323. if (hasSlot && !slotContent) return undefined;
  12324. return vue.createVNode("div", {
  12325. "key": item.value,
  12326. "class": "v-select__selection"
  12327. }, [hasChips ? !slots.chip ? vue.createVNode(VChip, vue.mergeProps({
  12328. "key": "chip",
  12329. "closable": props.closableChips,
  12330. "size": "small",
  12331. "text": item.title,
  12332. "disabled": item.props.disabled
  12333. }, slotProps), null) : vue.createVNode(VDefaultsProvider, {
  12334. "key": "chip-defaults",
  12335. "defaults": {
  12336. VChip: {
  12337. closable: props.closableChips,
  12338. size: 'small',
  12339. text: item.title
  12340. }
  12341. }
  12342. }, {
  12343. default: () => [slotContent]
  12344. }) : slotContent ?? vue.createVNode("span", {
  12345. "class": "v-select__selection-text"
  12346. }, [item.title, props.multiple && index < model.value.length - 1 && vue.createVNode("span", {
  12347. "class": "v-select__selection-comma"
  12348. }, [vue.createTextVNode(",")])])]);
  12349. })]),
  12350. 'append-inner': function () {
  12351. for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) {
  12352. args[_key] = arguments[_key];
  12353. }
  12354. return vue.createVNode(vue.Fragment, null, [slots['append-inner']?.(...args), props.menuIcon ? vue.createVNode(VIcon, {
  12355. "class": "v-select__menu-icon",
  12356. "icon": props.menuIcon
  12357. }, null) : undefined]);
  12358. }
  12359. });
  12360. });
  12361. return forwardRefs({
  12362. isFocused,
  12363. menu,
  12364. select
  12365. }, vTextFieldRef);
  12366. }
  12367. });
  12368. /* eslint-disable max-statements */
  12369. /* eslint-disable no-labels */
  12370. // Types
  12371. /**
  12372. * - match without highlight
  12373. * - single match (index), length already known
  12374. * - single match (start, end)
  12375. * - multiple matches (start, end), probably shouldn't overlap
  12376. */
  12377. // Composables
  12378. const defaultFilter = (value, query, item) => {
  12379. if (value == null || query == null) return -1;
  12380. return value.toString().toLocaleLowerCase().indexOf(query.toString().toLocaleLowerCase());
  12381. };
  12382. const makeFilterProps = propsFactory({
  12383. customFilter: Function,
  12384. customKeyFilter: Object,
  12385. filterKeys: [Array, String],
  12386. filterMode: {
  12387. type: String,
  12388. default: 'intersection'
  12389. },
  12390. noFilter: Boolean
  12391. }, 'filter');
  12392. function filterItems(items, query, options) {
  12393. const array = [];
  12394. // always ensure we fall back to a functioning filter
  12395. const filter = options?.default ?? defaultFilter;
  12396. const keys = options?.filterKeys ? wrapInArray(options.filterKeys) : false;
  12397. const customFiltersLength = Object.keys(options?.customKeyFilter ?? {}).length;
  12398. if (!items?.length) return array;
  12399. loop: for (let i = 0; i < items.length; i++) {
  12400. const [item, transformed = item] = wrapInArray(items[i]);
  12401. const customMatches = {};
  12402. const defaultMatches = {};
  12403. let match = -1;
  12404. if ((query || customFiltersLength > 0) && !options?.noFilter) {
  12405. if (typeof item === 'object') {
  12406. const filterKeys = keys || Object.keys(transformed);
  12407. for (const key of filterKeys) {
  12408. const value = getPropertyFromItem(transformed, key);
  12409. const keyFilter = options?.customKeyFilter?.[key];
  12410. match = keyFilter ? keyFilter(value, query, item) : filter(value, query, item);
  12411. if (match !== -1 && match !== false) {
  12412. if (keyFilter) customMatches[key] = match;else defaultMatches[key] = match;
  12413. } else if (options?.filterMode === 'every') {
  12414. continue loop;
  12415. }
  12416. }
  12417. } else {
  12418. match = filter(item, query, item);
  12419. if (match !== -1 && match !== false) {
  12420. defaultMatches.title = match;
  12421. }
  12422. }
  12423. const defaultMatchesLength = Object.keys(defaultMatches).length;
  12424. const customMatchesLength = Object.keys(customMatches).length;
  12425. if (!defaultMatchesLength && !customMatchesLength) continue;
  12426. if (options?.filterMode === 'union' && customMatchesLength !== customFiltersLength && !defaultMatchesLength) continue;
  12427. if (options?.filterMode === 'intersection' && (customMatchesLength !== customFiltersLength || !defaultMatchesLength)) continue;
  12428. }
  12429. array.push({
  12430. index: i,
  12431. matches: {
  12432. ...defaultMatches,
  12433. ...customMatches
  12434. }
  12435. });
  12436. }
  12437. return array;
  12438. }
  12439. function useFilter(props, items, query, options) {
  12440. const filteredItems = vue.ref([]);
  12441. const filteredMatches = vue.ref(new Map());
  12442. const transformedItems = vue.computed(() => options?.transform ? vue.unref(items).map(item => [item, options.transform(item)]) : vue.unref(items));
  12443. vue.watchEffect(() => {
  12444. const _query = typeof query === 'function' ? query() : vue.unref(query);
  12445. const strQuery = typeof _query !== 'string' && typeof _query !== 'number' ? '' : String(_query);
  12446. const results = filterItems(transformedItems.value, strQuery, {
  12447. customKeyFilter: {
  12448. ...props.customKeyFilter,
  12449. ...vue.unref(options?.customKeyFilter)
  12450. },
  12451. default: props.customFilter,
  12452. filterKeys: props.filterKeys,
  12453. filterMode: props.filterMode,
  12454. noFilter: props.noFilter
  12455. });
  12456. const originalItems = vue.unref(items);
  12457. const _filteredItems = [];
  12458. const _filteredMatches = new Map();
  12459. results.forEach(_ref => {
  12460. let {
  12461. index,
  12462. matches
  12463. } = _ref;
  12464. const item = originalItems[index];
  12465. _filteredItems.push(item);
  12466. _filteredMatches.set(item.value, matches);
  12467. });
  12468. filteredItems.value = _filteredItems;
  12469. filteredMatches.value = _filteredMatches;
  12470. });
  12471. function getMatches(item) {
  12472. return filteredMatches.value.get(item.value);
  12473. }
  12474. return {
  12475. filteredItems,
  12476. filteredMatches,
  12477. getMatches
  12478. };
  12479. }
  12480. // Types
  12481. function highlightResult$1(text, matches, length) {
  12482. if (matches == null) return text;
  12483. if (Array.isArray(matches)) throw new Error('Multiple matches is not implemented');
  12484. return typeof matches === 'number' && ~matches ? vue.createVNode(vue.Fragment, null, [vue.createVNode("span", {
  12485. "class": "v-autocomplete__unmask"
  12486. }, [text.substr(0, matches)]), vue.createVNode("span", {
  12487. "class": "v-autocomplete__mask"
  12488. }, [text.substr(matches, length)]), vue.createVNode("span", {
  12489. "class": "v-autocomplete__unmask"
  12490. }, [text.substr(matches + length)])]) : text;
  12491. }
  12492. const makeVAutocompleteProps = propsFactory({
  12493. autoSelectFirst: {
  12494. type: [Boolean, String]
  12495. },
  12496. clearOnSelect: Boolean,
  12497. search: String,
  12498. ...makeFilterProps({
  12499. filterKeys: ['title']
  12500. }),
  12501. ...makeSelectProps(),
  12502. ...omit(makeVTextFieldProps({
  12503. modelValue: null,
  12504. role: 'combobox'
  12505. }), ['validationValue', 'dirty', 'appendInnerIcon']),
  12506. ...makeTransitionProps({
  12507. transition: false
  12508. })
  12509. }, 'VAutocomplete');
  12510. const VAutocomplete = genericComponent()({
  12511. name: 'VAutocomplete',
  12512. props: makeVAutocompleteProps(),
  12513. emits: {
  12514. 'update:focused': focused => true,
  12515. 'update:search': value => true,
  12516. 'update:modelValue': value => true,
  12517. 'update:menu': value => true
  12518. },
  12519. setup(props, _ref) {
  12520. let {
  12521. slots
  12522. } = _ref;
  12523. const {
  12524. t
  12525. } = useLocale();
  12526. const vTextFieldRef = vue.ref();
  12527. const isFocused = vue.shallowRef(false);
  12528. const isPristine = vue.shallowRef(true);
  12529. const listHasFocus = vue.shallowRef(false);
  12530. const vMenuRef = vue.ref();
  12531. const vVirtualScrollRef = vue.ref();
  12532. const _menu = useProxiedModel(props, 'menu');
  12533. const menu = vue.computed({
  12534. get: () => _menu.value,
  12535. set: v => {
  12536. if (_menu.value && !v && vMenuRef.value?.ΨopenChildren.size) return;
  12537. _menu.value = v;
  12538. }
  12539. });
  12540. const selectionIndex = vue.shallowRef(-1);
  12541. const color = vue.computed(() => vTextFieldRef.value?.color);
  12542. const label = vue.computed(() => menu.value ? props.closeText : props.openText);
  12543. const {
  12544. items,
  12545. transformIn,
  12546. transformOut
  12547. } = useItems(props);
  12548. const {
  12549. textColorClasses,
  12550. textColorStyles
  12551. } = useTextColor(color);
  12552. const search = useProxiedModel(props, 'search', '');
  12553. const model = useProxiedModel(props, 'modelValue', [], v => transformIn(v === null ? [null] : wrapInArray(v)), v => {
  12554. const transformed = transformOut(v);
  12555. return props.multiple ? transformed : transformed[0] ?? null;
  12556. });
  12557. const counterValue = vue.computed(() => {
  12558. return typeof props.counterValue === 'function' ? props.counterValue(model.value) : typeof props.counterValue === 'number' ? props.counterValue : model.value.length;
  12559. });
  12560. const form = useForm(props);
  12561. const {
  12562. filteredItems,
  12563. getMatches
  12564. } = useFilter(props, items, () => isPristine.value ? '' : search.value);
  12565. const displayItems = vue.computed(() => {
  12566. if (props.hideSelected) {
  12567. return filteredItems.value.filter(filteredItem => !model.value.some(s => s.value === filteredItem.value));
  12568. }
  12569. return filteredItems.value;
  12570. });
  12571. const hasChips = vue.computed(() => !!(props.chips || slots.chip));
  12572. const hasSelectionSlot = vue.computed(() => hasChips.value || !!slots.selection);
  12573. const selectedValues = vue.computed(() => model.value.map(selection => selection.props.value));
  12574. const highlightFirst = vue.computed(() => {
  12575. const selectFirst = props.autoSelectFirst === true || props.autoSelectFirst === 'exact' && search.value === displayItems.value[0]?.title;
  12576. return selectFirst && displayItems.value.length > 0 && !isPristine.value && !listHasFocus.value;
  12577. });
  12578. const menuDisabled = vue.computed(() => props.hideNoData && !displayItems.value.length || form.isReadonly.value || form.isDisabled.value);
  12579. const listRef = vue.ref();
  12580. const listEvents = useScrolling(listRef, vTextFieldRef);
  12581. function onClear(e) {
  12582. if (props.openOnClear) {
  12583. menu.value = true;
  12584. }
  12585. search.value = '';
  12586. }
  12587. function onMousedownControl() {
  12588. if (menuDisabled.value) return;
  12589. menu.value = true;
  12590. }
  12591. function onMousedownMenuIcon(e) {
  12592. if (menuDisabled.value) return;
  12593. if (isFocused.value) {
  12594. e.preventDefault();
  12595. e.stopPropagation();
  12596. }
  12597. menu.value = !menu.value;
  12598. }
  12599. function onListKeydown(e) {
  12600. if (checkPrintable(e)) {
  12601. vTextFieldRef.value?.focus();
  12602. }
  12603. }
  12604. function onKeydown(e) {
  12605. if (form.isReadonly.value) return;
  12606. const selectionStart = vTextFieldRef.value.selectionStart;
  12607. const length = model.value.length;
  12608. if (selectionIndex.value > -1 || ['Enter', 'ArrowDown', 'ArrowUp'].includes(e.key)) {
  12609. e.preventDefault();
  12610. }
  12611. if (['Enter', 'ArrowDown'].includes(e.key)) {
  12612. menu.value = true;
  12613. }
  12614. if (['Escape'].includes(e.key)) {
  12615. menu.value = false;
  12616. }
  12617. if (highlightFirst.value && ['Enter', 'Tab'].includes(e.key) && !model.value.some(_ref2 => {
  12618. let {
  12619. value
  12620. } = _ref2;
  12621. return value === displayItems.value[0].value;
  12622. })) {
  12623. select(displayItems.value[0]);
  12624. }
  12625. if (e.key === 'ArrowDown' && highlightFirst.value) {
  12626. listRef.value?.focus('next');
  12627. }
  12628. if (['Backspace', 'Delete'].includes(e.key)) {
  12629. if (!props.multiple && hasSelectionSlot.value && model.value.length > 0 && !search.value) return select(model.value[0], false);
  12630. if (~selectionIndex.value) {
  12631. const originalSelectionIndex = selectionIndex.value;
  12632. select(model.value[selectionIndex.value], false);
  12633. selectionIndex.value = originalSelectionIndex >= length - 1 ? length - 2 : originalSelectionIndex;
  12634. } else if (e.key === 'Backspace' && !search.value) {
  12635. selectionIndex.value = length - 1;
  12636. }
  12637. }
  12638. if (!props.multiple) return;
  12639. if (e.key === 'ArrowLeft') {
  12640. if (selectionIndex.value < 0 && selectionStart > 0) return;
  12641. const prev = selectionIndex.value > -1 ? selectionIndex.value - 1 : length - 1;
  12642. if (model.value[prev]) {
  12643. selectionIndex.value = prev;
  12644. } else {
  12645. selectionIndex.value = -1;
  12646. vTextFieldRef.value.setSelectionRange(search.value?.length, search.value?.length);
  12647. }
  12648. }
  12649. if (e.key === 'ArrowRight') {
  12650. if (selectionIndex.value < 0) return;
  12651. const next = selectionIndex.value + 1;
  12652. if (model.value[next]) {
  12653. selectionIndex.value = next;
  12654. } else {
  12655. selectionIndex.value = -1;
  12656. vTextFieldRef.value.setSelectionRange(0, 0);
  12657. }
  12658. }
  12659. }
  12660. function onChange(e) {
  12661. if (matchesSelector(vTextFieldRef.value, ':autofill') || matchesSelector(vTextFieldRef.value, ':-webkit-autofill')) {
  12662. const item = items.value.find(item => item.title === e.target.value);
  12663. if (item) {
  12664. select(item);
  12665. }
  12666. }
  12667. }
  12668. function onAfterEnter() {
  12669. if (props.eager) {
  12670. vVirtualScrollRef.value?.calculateVisibleItems();
  12671. }
  12672. }
  12673. function onAfterLeave() {
  12674. if (isFocused.value) {
  12675. isPristine.value = true;
  12676. vTextFieldRef.value?.focus();
  12677. }
  12678. }
  12679. function onFocusin(e) {
  12680. isFocused.value = true;
  12681. setTimeout(() => {
  12682. listHasFocus.value = true;
  12683. });
  12684. }
  12685. function onFocusout(e) {
  12686. listHasFocus.value = false;
  12687. }
  12688. function onUpdateModelValue(v) {
  12689. if (v == null || v === '' && !props.multiple && !hasSelectionSlot.value) model.value = [];
  12690. }
  12691. const isSelecting = vue.shallowRef(false);
  12692. /** @param set - null means toggle */
  12693. function select(item) {
  12694. let set = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : true;
  12695. if (!item || item.props.disabled) return;
  12696. if (props.multiple) {
  12697. const index = model.value.findIndex(selection => props.valueComparator(selection.value, item.value));
  12698. const add = set == null ? !~index : set;
  12699. if (~index) {
  12700. const value = add ? [...model.value, item] : [...model.value];
  12701. value.splice(index, 1);
  12702. model.value = value;
  12703. } else if (add) {
  12704. model.value = [...model.value, item];
  12705. }
  12706. if (props.clearOnSelect) {
  12707. search.value = '';
  12708. }
  12709. } else {
  12710. const add = set !== false;
  12711. model.value = add ? [item] : [];
  12712. search.value = add && !hasSelectionSlot.value ? item.title : '';
  12713. // watch for search watcher to trigger
  12714. vue.nextTick(() => {
  12715. menu.value = false;
  12716. isPristine.value = true;
  12717. });
  12718. }
  12719. }
  12720. vue.watch(isFocused, (val, oldVal) => {
  12721. if (val === oldVal) return;
  12722. if (val) {
  12723. isSelecting.value = true;
  12724. search.value = props.multiple || hasSelectionSlot.value ? '' : String(model.value.at(-1)?.props.title ?? '');
  12725. isPristine.value = true;
  12726. vue.nextTick(() => isSelecting.value = false);
  12727. } else {
  12728. if (!props.multiple && search.value == null) model.value = [];
  12729. menu.value = false;
  12730. if (!model.value.some(_ref3 => {
  12731. let {
  12732. title
  12733. } = _ref3;
  12734. return title === search.value;
  12735. })) search.value = '';
  12736. selectionIndex.value = -1;
  12737. }
  12738. });
  12739. vue.watch(search, val => {
  12740. if (!isFocused.value || isSelecting.value) return;
  12741. if (val) menu.value = true;
  12742. isPristine.value = !val;
  12743. });
  12744. vue.watch(menu, () => {
  12745. if (!props.hideSelected && menu.value && model.value.length) {
  12746. const index = displayItems.value.findIndex(item => model.value.some(s => item.value === s.value));
  12747. IN_BROWSER && window.requestAnimationFrame(() => {
  12748. index >= 0 && vVirtualScrollRef.value?.scrollToIndex(index);
  12749. });
  12750. }
  12751. });
  12752. vue.watch(() => props.items, (newVal, oldVal) => {
  12753. if (menu.value) return;
  12754. if (isFocused.value && !oldVal.length && newVal.length) {
  12755. menu.value = true;
  12756. }
  12757. });
  12758. useRender(() => {
  12759. const hasList = !!(!props.hideNoData || displayItems.value.length || slots['prepend-item'] || slots['append-item'] || slots['no-data']);
  12760. const isDirty = model.value.length > 0;
  12761. const textFieldProps = VTextField.filterProps(props);
  12762. return vue.createVNode(VTextField, vue.mergeProps({
  12763. "ref": vTextFieldRef
  12764. }, textFieldProps, {
  12765. "modelValue": search.value,
  12766. "onUpdate:modelValue": [$event => search.value = $event, onUpdateModelValue],
  12767. "focused": isFocused.value,
  12768. "onUpdate:focused": $event => isFocused.value = $event,
  12769. "validationValue": model.externalValue,
  12770. "counterValue": counterValue.value,
  12771. "dirty": isDirty,
  12772. "onChange": onChange,
  12773. "class": ['v-autocomplete', `v-autocomplete--${props.multiple ? 'multiple' : 'single'}`, {
  12774. 'v-autocomplete--active-menu': menu.value,
  12775. 'v-autocomplete--chips': !!props.chips,
  12776. 'v-autocomplete--selection-slot': !!hasSelectionSlot.value,
  12777. 'v-autocomplete--selecting-index': selectionIndex.value > -1
  12778. }, props.class],
  12779. "style": props.style,
  12780. "readonly": form.isReadonly.value,
  12781. "placeholder": isDirty ? undefined : props.placeholder,
  12782. "onClick:clear": onClear,
  12783. "onMousedown:control": onMousedownControl,
  12784. "onKeydown": onKeydown
  12785. }), {
  12786. ...slots,
  12787. default: () => vue.createVNode(vue.Fragment, null, [vue.createVNode(VMenu, vue.mergeProps({
  12788. "ref": vMenuRef,
  12789. "modelValue": menu.value,
  12790. "onUpdate:modelValue": $event => menu.value = $event,
  12791. "activator": "parent",
  12792. "contentClass": "v-autocomplete__content",
  12793. "disabled": menuDisabled.value,
  12794. "eager": props.eager,
  12795. "maxHeight": 310,
  12796. "openOnClick": false,
  12797. "closeOnContentClick": false,
  12798. "transition": props.transition,
  12799. "onAfterEnter": onAfterEnter,
  12800. "onAfterLeave": onAfterLeave
  12801. }, props.menuProps), {
  12802. default: () => [hasList && vue.createVNode(VList, vue.mergeProps({
  12803. "ref": listRef,
  12804. "selected": selectedValues.value,
  12805. "selectStrategy": props.multiple ? 'independent' : 'single-independent',
  12806. "onMousedown": e => e.preventDefault(),
  12807. "onKeydown": onListKeydown,
  12808. "onFocusin": onFocusin,
  12809. "onFocusout": onFocusout,
  12810. "tabindex": "-1",
  12811. "aria-live": "polite",
  12812. "color": props.itemColor ?? props.color
  12813. }, listEvents, props.listProps), {
  12814. default: () => [slots['prepend-item']?.(), !displayItems.value.length && !props.hideNoData && (slots['no-data']?.() ?? vue.createVNode(VListItem, {
  12815. "key": "no-data",
  12816. "title": t(props.noDataText)
  12817. }, null)), vue.createVNode(VVirtualScroll, {
  12818. "ref": vVirtualScrollRef,
  12819. "renderless": true,
  12820. "items": displayItems.value
  12821. }, {
  12822. default: _ref4 => {
  12823. let {
  12824. item,
  12825. index,
  12826. itemRef
  12827. } = _ref4;
  12828. const itemProps = vue.mergeProps(item.props, {
  12829. ref: itemRef,
  12830. key: item.value,
  12831. active: highlightFirst.value && index === 0 ? true : undefined,
  12832. onClick: () => select(item, null)
  12833. });
  12834. return slots.item?.({
  12835. item,
  12836. index,
  12837. props: itemProps
  12838. }) ?? vue.createVNode(VListItem, vue.mergeProps(itemProps, {
  12839. "role": "option"
  12840. }), {
  12841. prepend: _ref5 => {
  12842. let {
  12843. isSelected
  12844. } = _ref5;
  12845. return vue.createVNode(vue.Fragment, null, [props.multiple && !props.hideSelected ? vue.createVNode(VCheckboxBtn, {
  12846. "key": item.value,
  12847. "modelValue": isSelected,
  12848. "ripple": false,
  12849. "tabindex": "-1"
  12850. }, null) : undefined, item.props.prependAvatar && vue.createVNode(VAvatar, {
  12851. "image": item.props.prependAvatar
  12852. }, null), item.props.prependIcon && vue.createVNode(VIcon, {
  12853. "icon": item.props.prependIcon
  12854. }, null)]);
  12855. },
  12856. title: () => {
  12857. return isPristine.value ? item.title : highlightResult$1(item.title, getMatches(item)?.title, search.value?.length ?? 0);
  12858. }
  12859. });
  12860. }
  12861. }), slots['append-item']?.()]
  12862. })]
  12863. }), model.value.map((item, index) => {
  12864. function onChipClose(e) {
  12865. e.stopPropagation();
  12866. e.preventDefault();
  12867. select(item, false);
  12868. }
  12869. const slotProps = {
  12870. 'onClick:close': onChipClose,
  12871. onKeydown(e) {
  12872. if (e.key !== 'Enter' && e.key !== ' ') return;
  12873. e.preventDefault();
  12874. e.stopPropagation();
  12875. onChipClose(e);
  12876. },
  12877. onMousedown(e) {
  12878. e.preventDefault();
  12879. e.stopPropagation();
  12880. },
  12881. modelValue: true,
  12882. 'onUpdate:modelValue': undefined
  12883. };
  12884. const hasSlot = hasChips.value ? !!slots.chip : !!slots.selection;
  12885. const slotContent = hasSlot ? ensureValidVNode(hasChips.value ? slots.chip({
  12886. item,
  12887. index,
  12888. props: slotProps
  12889. }) : slots.selection({
  12890. item,
  12891. index
  12892. })) : undefined;
  12893. if (hasSlot && !slotContent) return undefined;
  12894. return vue.createVNode("div", {
  12895. "key": item.value,
  12896. "class": ['v-autocomplete__selection', index === selectionIndex.value && ['v-autocomplete__selection--selected', textColorClasses.value]],
  12897. "style": index === selectionIndex.value ? textColorStyles.value : {}
  12898. }, [hasChips.value ? !slots.chip ? vue.createVNode(VChip, vue.mergeProps({
  12899. "key": "chip",
  12900. "closable": props.closableChips,
  12901. "size": "small",
  12902. "text": item.title,
  12903. "disabled": item.props.disabled
  12904. }, slotProps), null) : vue.createVNode(VDefaultsProvider, {
  12905. "key": "chip-defaults",
  12906. "defaults": {
  12907. VChip: {
  12908. closable: props.closableChips,
  12909. size: 'small',
  12910. text: item.title
  12911. }
  12912. }
  12913. }, {
  12914. default: () => [slotContent]
  12915. }) : slotContent ?? vue.createVNode("span", {
  12916. "class": "v-autocomplete__selection-text"
  12917. }, [item.title, props.multiple && index < model.value.length - 1 && vue.createVNode("span", {
  12918. "class": "v-autocomplete__selection-comma"
  12919. }, [vue.createTextVNode(",")])])]);
  12920. })]),
  12921. 'append-inner': function () {
  12922. for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) {
  12923. args[_key] = arguments[_key];
  12924. }
  12925. return vue.createVNode(vue.Fragment, null, [slots['append-inner']?.(...args), props.menuIcon ? vue.createVNode(VIcon, {
  12926. "class": "v-autocomplete__menu-icon",
  12927. "icon": props.menuIcon,
  12928. "onMousedown": onMousedownMenuIcon,
  12929. "onClick": noop,
  12930. "aria-label": t(label.value),
  12931. "title": t(label.value),
  12932. "tabindex": "-1"
  12933. }, null) : undefined]);
  12934. }
  12935. });
  12936. });
  12937. return forwardRefs({
  12938. isFocused,
  12939. isPristine,
  12940. menu,
  12941. search,
  12942. filteredItems,
  12943. select
  12944. }, vTextFieldRef);
  12945. }
  12946. });
  12947. const makeVBadgeProps = propsFactory({
  12948. bordered: Boolean,
  12949. color: String,
  12950. content: [Number, String],
  12951. dot: Boolean,
  12952. floating: Boolean,
  12953. icon: IconValue,
  12954. inline: Boolean,
  12955. label: {
  12956. type: String,
  12957. default: '$vuetify.badge'
  12958. },
  12959. max: [Number, String],
  12960. modelValue: {
  12961. type: Boolean,
  12962. default: true
  12963. },
  12964. offsetX: [Number, String],
  12965. offsetY: [Number, String],
  12966. textColor: String,
  12967. ...makeComponentProps(),
  12968. ...makeLocationProps({
  12969. location: 'top end'
  12970. }),
  12971. ...makeRoundedProps(),
  12972. ...makeTagProps(),
  12973. ...makeThemeProps(),
  12974. ...makeTransitionProps({
  12975. transition: 'scale-rotate-transition'
  12976. })
  12977. }, 'VBadge');
  12978. const VBadge = genericComponent()({
  12979. name: 'VBadge',
  12980. inheritAttrs: false,
  12981. props: makeVBadgeProps(),
  12982. setup(props, ctx) {
  12983. const {
  12984. backgroundColorClasses,
  12985. backgroundColorStyles
  12986. } = useBackgroundColor(vue.toRef(props, 'color'));
  12987. const {
  12988. roundedClasses
  12989. } = useRounded(props);
  12990. const {
  12991. t
  12992. } = useLocale();
  12993. const {
  12994. textColorClasses,
  12995. textColorStyles
  12996. } = useTextColor(vue.toRef(props, 'textColor'));
  12997. const {
  12998. themeClasses
  12999. } = useTheme();
  13000. const {
  13001. locationStyles
  13002. } = useLocation(props, true, side => {
  13003. const base = props.floating ? props.dot ? 2 : 4 : props.dot ? 8 : 12;
  13004. return base + (['top', 'bottom'].includes(side) ? +(props.offsetY ?? 0) : ['left', 'right'].includes(side) ? +(props.offsetX ?? 0) : 0);
  13005. });
  13006. useRender(() => {
  13007. const value = Number(props.content);
  13008. const content = !props.max || isNaN(value) ? props.content : value <= +props.max ? value : `${props.max}+`;
  13009. const [badgeAttrs, attrs] = pickWithRest(ctx.attrs, ['aria-atomic', 'aria-label', 'aria-live', 'role', 'title']);
  13010. return vue.createVNode(props.tag, vue.mergeProps({
  13011. "class": ['v-badge', {
  13012. 'v-badge--bordered': props.bordered,
  13013. 'v-badge--dot': props.dot,
  13014. 'v-badge--floating': props.floating,
  13015. 'v-badge--inline': props.inline
  13016. }, props.class]
  13017. }, attrs, {
  13018. "style": props.style
  13019. }), {
  13020. default: () => [vue.createVNode("div", {
  13021. "class": "v-badge__wrapper"
  13022. }, [ctx.slots.default?.(), vue.createVNode(MaybeTransition, {
  13023. "transition": props.transition
  13024. }, {
  13025. default: () => [vue.withDirectives(vue.createVNode("span", vue.mergeProps({
  13026. "class": ['v-badge__badge', themeClasses.value, backgroundColorClasses.value, roundedClasses.value, textColorClasses.value],
  13027. "style": [backgroundColorStyles.value, textColorStyles.value, props.inline ? {} : locationStyles.value],
  13028. "aria-atomic": "true",
  13029. "aria-label": t(props.label, value),
  13030. "aria-live": "polite",
  13031. "role": "status"
  13032. }, badgeAttrs), [props.dot ? undefined : ctx.slots.badge ? ctx.slots.badge?.() : props.icon ? vue.createVNode(VIcon, {
  13033. "icon": props.icon
  13034. }, null) : content]), [[vue.vShow, props.modelValue]])]
  13035. })])]
  13036. });
  13037. });
  13038. return {};
  13039. }
  13040. });
  13041. const makeVBannerActionsProps = propsFactory({
  13042. color: String,
  13043. density: String,
  13044. ...makeComponentProps()
  13045. }, 'VBannerActions');
  13046. const VBannerActions = genericComponent()({
  13047. name: 'VBannerActions',
  13048. props: makeVBannerActionsProps(),
  13049. setup(props, _ref) {
  13050. let {
  13051. slots
  13052. } = _ref;
  13053. provideDefaults({
  13054. VBtn: {
  13055. color: props.color,
  13056. density: props.density,
  13057. slim: true,
  13058. variant: 'text'
  13059. }
  13060. });
  13061. useRender(() => vue.createVNode("div", {
  13062. "class": ['v-banner-actions', props.class],
  13063. "style": props.style
  13064. }, [slots.default?.()]));
  13065. return {};
  13066. }
  13067. });
  13068. // Utilities
  13069. const VBannerText = createSimpleFunctional('v-banner-text');
  13070. // Types
  13071. const makeVBannerProps = propsFactory({
  13072. avatar: String,
  13073. bgColor: String,
  13074. color: String,
  13075. icon: IconValue,
  13076. lines: String,
  13077. stacked: Boolean,
  13078. sticky: Boolean,
  13079. text: String,
  13080. ...makeBorderProps(),
  13081. ...makeComponentProps(),
  13082. ...makeDensityProps(),
  13083. ...makeDimensionProps(),
  13084. ...makeDisplayProps({
  13085. mobile: null
  13086. }),
  13087. ...makeElevationProps(),
  13088. ...makeLocationProps(),
  13089. ...makePositionProps(),
  13090. ...makeRoundedProps(),
  13091. ...makeTagProps(),
  13092. ...makeThemeProps()
  13093. }, 'VBanner');
  13094. const VBanner = genericComponent()({
  13095. name: 'VBanner',
  13096. props: makeVBannerProps(),
  13097. setup(props, _ref) {
  13098. let {
  13099. slots
  13100. } = _ref;
  13101. const {
  13102. backgroundColorClasses,
  13103. backgroundColorStyles
  13104. } = useBackgroundColor(props, 'bgColor');
  13105. const {
  13106. borderClasses
  13107. } = useBorder(props);
  13108. const {
  13109. densityClasses
  13110. } = useDensity(props);
  13111. const {
  13112. displayClasses,
  13113. mobile
  13114. } = useDisplay(props);
  13115. const {
  13116. dimensionStyles
  13117. } = useDimension(props);
  13118. const {
  13119. elevationClasses
  13120. } = useElevation(props);
  13121. const {
  13122. locationStyles
  13123. } = useLocation(props);
  13124. const {
  13125. positionClasses
  13126. } = usePosition(props);
  13127. const {
  13128. roundedClasses
  13129. } = useRounded(props);
  13130. const {
  13131. themeClasses
  13132. } = provideTheme(props);
  13133. const color = vue.toRef(props, 'color');
  13134. const density = vue.toRef(props, 'density');
  13135. provideDefaults({
  13136. VBannerActions: {
  13137. color,
  13138. density
  13139. }
  13140. });
  13141. useRender(() => {
  13142. const hasText = !!(props.text || slots.text);
  13143. const hasPrependMedia = !!(props.avatar || props.icon);
  13144. const hasPrepend = !!(hasPrependMedia || slots.prepend);
  13145. return vue.createVNode(props.tag, {
  13146. "class": ['v-banner', {
  13147. 'v-banner--stacked': props.stacked || mobile.value,
  13148. 'v-banner--sticky': props.sticky,
  13149. [`v-banner--${props.lines}-line`]: !!props.lines
  13150. }, themeClasses.value, backgroundColorClasses.value, borderClasses.value, densityClasses.value, displayClasses.value, elevationClasses.value, positionClasses.value, roundedClasses.value, props.class],
  13151. "style": [backgroundColorStyles.value, dimensionStyles.value, locationStyles.value, props.style],
  13152. "role": "banner"
  13153. }, {
  13154. default: () => [hasPrepend && vue.createVNode("div", {
  13155. "key": "prepend",
  13156. "class": "v-banner__prepend"
  13157. }, [!slots.prepend ? vue.createVNode(VAvatar, {
  13158. "key": "prepend-avatar",
  13159. "color": color.value,
  13160. "density": density.value,
  13161. "icon": props.icon,
  13162. "image": props.avatar
  13163. }, null) : vue.createVNode(VDefaultsProvider, {
  13164. "key": "prepend-defaults",
  13165. "disabled": !hasPrependMedia,
  13166. "defaults": {
  13167. VAvatar: {
  13168. color: color.value,
  13169. density: density.value,
  13170. icon: props.icon,
  13171. image: props.avatar
  13172. }
  13173. }
  13174. }, slots.prepend)]), vue.createVNode("div", {
  13175. "class": "v-banner__content"
  13176. }, [hasText && vue.createVNode(VBannerText, {
  13177. "key": "text"
  13178. }, {
  13179. default: () => [slots.text?.() ?? props.text]
  13180. }), slots.default?.()]), slots.actions && vue.createVNode(VBannerActions, {
  13181. "key": "actions"
  13182. }, slots.actions)]
  13183. });
  13184. });
  13185. }
  13186. });
  13187. // Types
  13188. const makeVBottomNavigationProps = propsFactory({
  13189. baseColor: String,
  13190. bgColor: String,
  13191. color: String,
  13192. grow: Boolean,
  13193. mode: {
  13194. type: String,
  13195. validator: v => !v || ['horizontal', 'shift'].includes(v)
  13196. },
  13197. height: {
  13198. type: [Number, String],
  13199. default: 56
  13200. },
  13201. active: {
  13202. type: Boolean,
  13203. default: true
  13204. },
  13205. ...makeBorderProps(),
  13206. ...makeComponentProps(),
  13207. ...makeDensityProps(),
  13208. ...makeElevationProps(),
  13209. ...makeRoundedProps(),
  13210. ...makeLayoutItemProps({
  13211. name: 'bottom-navigation'
  13212. }),
  13213. ...makeTagProps({
  13214. tag: 'header'
  13215. }),
  13216. ...makeGroupProps({
  13217. selectedClass: 'v-btn--selected'
  13218. }),
  13219. ...makeThemeProps()
  13220. }, 'VBottomNavigation');
  13221. const VBottomNavigation = genericComponent()({
  13222. name: 'VBottomNavigation',
  13223. props: makeVBottomNavigationProps(),
  13224. emits: {
  13225. 'update:active': value => true,
  13226. 'update:modelValue': value => true
  13227. },
  13228. setup(props, _ref) {
  13229. let {
  13230. slots
  13231. } = _ref;
  13232. const {
  13233. themeClasses
  13234. } = useTheme();
  13235. const {
  13236. borderClasses
  13237. } = useBorder(props);
  13238. const {
  13239. backgroundColorClasses,
  13240. backgroundColorStyles
  13241. } = useBackgroundColor(vue.toRef(props, 'bgColor'));
  13242. const {
  13243. densityClasses
  13244. } = useDensity(props);
  13245. const {
  13246. elevationClasses
  13247. } = useElevation(props);
  13248. const {
  13249. roundedClasses
  13250. } = useRounded(props);
  13251. const {
  13252. ssrBootStyles
  13253. } = useSsrBoot();
  13254. const height = vue.computed(() => Number(props.height) - (props.density === 'comfortable' ? 8 : 0) - (props.density === 'compact' ? 16 : 0));
  13255. const isActive = useProxiedModel(props, 'active', props.active);
  13256. const {
  13257. layoutItemStyles
  13258. } = useLayoutItem({
  13259. id: props.name,
  13260. order: vue.computed(() => parseInt(props.order, 10)),
  13261. position: vue.computed(() => 'bottom'),
  13262. layoutSize: vue.computed(() => isActive.value ? height.value : 0),
  13263. elementSize: height,
  13264. active: isActive,
  13265. absolute: vue.toRef(props, 'absolute')
  13266. });
  13267. useGroup(props, VBtnToggleSymbol);
  13268. provideDefaults({
  13269. VBtn: {
  13270. baseColor: vue.toRef(props, 'baseColor'),
  13271. color: vue.toRef(props, 'color'),
  13272. density: vue.toRef(props, 'density'),
  13273. stacked: vue.computed(() => props.mode !== 'horizontal'),
  13274. variant: 'text'
  13275. }
  13276. }, {
  13277. scoped: true
  13278. });
  13279. useRender(() => {
  13280. return vue.createVNode(props.tag, {
  13281. "class": ['v-bottom-navigation', {
  13282. 'v-bottom-navigation--active': isActive.value,
  13283. 'v-bottom-navigation--grow': props.grow,
  13284. 'v-bottom-navigation--shift': props.mode === 'shift'
  13285. }, themeClasses.value, backgroundColorClasses.value, borderClasses.value, densityClasses.value, elevationClasses.value, roundedClasses.value, props.class],
  13286. "style": [backgroundColorStyles.value, layoutItemStyles.value, {
  13287. height: convertToUnit(height.value)
  13288. }, ssrBootStyles.value, props.style]
  13289. }, {
  13290. default: () => [slots.default && vue.createVNode("div", {
  13291. "class": "v-bottom-navigation__content"
  13292. }, [slots.default()])]
  13293. });
  13294. });
  13295. return {};
  13296. }
  13297. });
  13298. // Types
  13299. const makeVDialogProps = propsFactory({
  13300. fullscreen: Boolean,
  13301. retainFocus: {
  13302. type: Boolean,
  13303. default: true
  13304. },
  13305. scrollable: Boolean,
  13306. ...makeVOverlayProps({
  13307. origin: 'center center',
  13308. scrollStrategy: 'block',
  13309. transition: {
  13310. component: VDialogTransition
  13311. },
  13312. zIndex: 2400
  13313. })
  13314. }, 'VDialog');
  13315. const VDialog = genericComponent()({
  13316. name: 'VDialog',
  13317. props: makeVDialogProps(),
  13318. emits: {
  13319. 'update:modelValue': value => true,
  13320. afterEnter: () => true,
  13321. afterLeave: () => true
  13322. },
  13323. setup(props, _ref) {
  13324. let {
  13325. emit,
  13326. slots
  13327. } = _ref;
  13328. const isActive = useProxiedModel(props, 'modelValue');
  13329. const {
  13330. scopeId
  13331. } = useScopeId();
  13332. const overlay = vue.ref();
  13333. function onFocusin(e) {
  13334. const before = e.relatedTarget;
  13335. const after = e.target;
  13336. if (before !== after && overlay.value?.contentEl &&
  13337. // We're the topmost dialog
  13338. overlay.value?.globalTop &&
  13339. // It isn't the document or the dialog body
  13340. ![document, overlay.value.contentEl].includes(after) &&
  13341. // It isn't inside the dialog body
  13342. !overlay.value.contentEl.contains(after)) {
  13343. const focusable = focusableChildren(overlay.value.contentEl);
  13344. if (!focusable.length) return;
  13345. const firstElement = focusable[0];
  13346. const lastElement = focusable[focusable.length - 1];
  13347. if (before === firstElement) {
  13348. lastElement.focus();
  13349. } else {
  13350. firstElement.focus();
  13351. }
  13352. }
  13353. }
  13354. vue.onBeforeUnmount(() => {
  13355. document.removeEventListener('focusin', onFocusin);
  13356. });
  13357. if (IN_BROWSER) {
  13358. vue.watch(() => isActive.value && props.retainFocus, val => {
  13359. val ? document.addEventListener('focusin', onFocusin) : document.removeEventListener('focusin', onFocusin);
  13360. }, {
  13361. immediate: true
  13362. });
  13363. }
  13364. function onAfterEnter() {
  13365. emit('afterEnter');
  13366. if (overlay.value?.contentEl && !overlay.value.contentEl.contains(document.activeElement)) {
  13367. overlay.value.contentEl.focus({
  13368. preventScroll: true
  13369. });
  13370. }
  13371. }
  13372. function onAfterLeave() {
  13373. emit('afterLeave');
  13374. }
  13375. vue.watch(isActive, async val => {
  13376. if (!val) {
  13377. await vue.nextTick();
  13378. overlay.value.activatorEl?.focus({
  13379. preventScroll: true
  13380. });
  13381. }
  13382. });
  13383. useRender(() => {
  13384. const overlayProps = VOverlay.filterProps(props);
  13385. const activatorProps = vue.mergeProps({
  13386. 'aria-haspopup': 'dialog'
  13387. }, props.activatorProps);
  13388. const contentProps = vue.mergeProps({
  13389. tabindex: -1
  13390. }, props.contentProps);
  13391. return vue.createVNode(VOverlay, vue.mergeProps({
  13392. "ref": overlay,
  13393. "class": ['v-dialog', {
  13394. 'v-dialog--fullscreen': props.fullscreen,
  13395. 'v-dialog--scrollable': props.scrollable
  13396. }, props.class],
  13397. "style": props.style
  13398. }, overlayProps, {
  13399. "modelValue": isActive.value,
  13400. "onUpdate:modelValue": $event => isActive.value = $event,
  13401. "aria-modal": "true",
  13402. "activatorProps": activatorProps,
  13403. "contentProps": contentProps,
  13404. "height": !props.fullscreen ? props.height : undefined,
  13405. "width": !props.fullscreen ? props.width : undefined,
  13406. "maxHeight": !props.fullscreen ? props.maxHeight : undefined,
  13407. "maxWidth": !props.fullscreen ? props.maxWidth : undefined,
  13408. "role": "dialog",
  13409. "onAfterEnter": onAfterEnter,
  13410. "onAfterLeave": onAfterLeave
  13411. }, scopeId), {
  13412. activator: slots.activator,
  13413. default: function () {
  13414. for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) {
  13415. args[_key] = arguments[_key];
  13416. }
  13417. return vue.createVNode(VDefaultsProvider, {
  13418. "root": "VDialog"
  13419. }, {
  13420. default: () => [slots.default?.(...args)]
  13421. });
  13422. }
  13423. });
  13424. });
  13425. return forwardRefs({}, overlay);
  13426. }
  13427. });
  13428. // Types
  13429. const makeVBottomSheetProps = propsFactory({
  13430. inset: Boolean,
  13431. ...makeVDialogProps({
  13432. transition: 'bottom-sheet-transition'
  13433. })
  13434. }, 'VBottomSheet');
  13435. const VBottomSheet = genericComponent()({
  13436. name: 'VBottomSheet',
  13437. props: makeVBottomSheetProps(),
  13438. emits: {
  13439. 'update:modelValue': value => true
  13440. },
  13441. setup(props, _ref) {
  13442. let {
  13443. slots
  13444. } = _ref;
  13445. const isActive = useProxiedModel(props, 'modelValue');
  13446. useRender(() => {
  13447. const dialogProps = VDialog.filterProps(props);
  13448. return vue.createVNode(VDialog, vue.mergeProps(dialogProps, {
  13449. "contentClass": ['v-bottom-sheet__content', props.contentClass],
  13450. "modelValue": isActive.value,
  13451. "onUpdate:modelValue": $event => isActive.value = $event,
  13452. "class": ['v-bottom-sheet', {
  13453. 'v-bottom-sheet--inset': props.inset
  13454. }, props.class],
  13455. "style": props.style
  13456. }), slots);
  13457. });
  13458. return {};
  13459. }
  13460. });
  13461. const makeVBreadcrumbsDividerProps = propsFactory({
  13462. divider: [Number, String],
  13463. ...makeComponentProps()
  13464. }, 'VBreadcrumbsDivider');
  13465. const VBreadcrumbsDivider = genericComponent()({
  13466. name: 'VBreadcrumbsDivider',
  13467. props: makeVBreadcrumbsDividerProps(),
  13468. setup(props, _ref) {
  13469. let {
  13470. slots
  13471. } = _ref;
  13472. useRender(() => vue.createVNode("li", {
  13473. "class": ['v-breadcrumbs-divider', props.class],
  13474. "style": props.style
  13475. }, [slots?.default?.() ?? props.divider]));
  13476. return {};
  13477. }
  13478. });
  13479. const makeVBreadcrumbsItemProps = propsFactory({
  13480. active: Boolean,
  13481. activeClass: String,
  13482. activeColor: String,
  13483. color: String,
  13484. disabled: Boolean,
  13485. title: String,
  13486. ...makeComponentProps(),
  13487. ...makeRouterProps(),
  13488. ...makeTagProps({
  13489. tag: 'li'
  13490. })
  13491. }, 'VBreadcrumbsItem');
  13492. const VBreadcrumbsItem = genericComponent()({
  13493. name: 'VBreadcrumbsItem',
  13494. props: makeVBreadcrumbsItemProps(),
  13495. setup(props, _ref) {
  13496. let {
  13497. slots,
  13498. attrs
  13499. } = _ref;
  13500. const link = useLink(props, attrs);
  13501. const isActive = vue.computed(() => props.active || link.isActive?.value);
  13502. const color = vue.computed(() => isActive.value ? props.activeColor : props.color);
  13503. const {
  13504. textColorClasses,
  13505. textColorStyles
  13506. } = useTextColor(color);
  13507. useRender(() => {
  13508. return vue.createVNode(props.tag, {
  13509. "class": ['v-breadcrumbs-item', {
  13510. 'v-breadcrumbs-item--active': isActive.value,
  13511. 'v-breadcrumbs-item--disabled': props.disabled,
  13512. [`${props.activeClass}`]: isActive.value && props.activeClass
  13513. }, textColorClasses.value, props.class],
  13514. "style": [textColorStyles.value, props.style],
  13515. "aria-current": isActive.value ? 'page' : undefined
  13516. }, {
  13517. default: () => [!link.isLink.value ? slots.default?.() ?? props.title : vue.createVNode("a", vue.mergeProps({
  13518. "class": "v-breadcrumbs-item--link",
  13519. "onClick": link.navigate
  13520. }, link.linkProps), [slots.default?.() ?? props.title])]
  13521. });
  13522. });
  13523. return {};
  13524. }
  13525. });
  13526. // Types
  13527. const makeVBreadcrumbsProps = propsFactory({
  13528. activeClass: String,
  13529. activeColor: String,
  13530. bgColor: String,
  13531. color: String,
  13532. disabled: Boolean,
  13533. divider: {
  13534. type: String,
  13535. default: '/'
  13536. },
  13537. icon: IconValue,
  13538. items: {
  13539. type: Array,
  13540. default: () => []
  13541. },
  13542. ...makeComponentProps(),
  13543. ...makeDensityProps(),
  13544. ...makeRoundedProps(),
  13545. ...makeTagProps({
  13546. tag: 'ul'
  13547. })
  13548. }, 'VBreadcrumbs');
  13549. const VBreadcrumbs = genericComponent()({
  13550. name: 'VBreadcrumbs',
  13551. props: makeVBreadcrumbsProps(),
  13552. setup(props, _ref) {
  13553. let {
  13554. slots
  13555. } = _ref;
  13556. const {
  13557. backgroundColorClasses,
  13558. backgroundColorStyles
  13559. } = useBackgroundColor(vue.toRef(props, 'bgColor'));
  13560. const {
  13561. densityClasses
  13562. } = useDensity(props);
  13563. const {
  13564. roundedClasses
  13565. } = useRounded(props);
  13566. provideDefaults({
  13567. VBreadcrumbsDivider: {
  13568. divider: vue.toRef(props, 'divider')
  13569. },
  13570. VBreadcrumbsItem: {
  13571. activeClass: vue.toRef(props, 'activeClass'),
  13572. activeColor: vue.toRef(props, 'activeColor'),
  13573. color: vue.toRef(props, 'color'),
  13574. disabled: vue.toRef(props, 'disabled')
  13575. }
  13576. });
  13577. const items = vue.computed(() => props.items.map(item => {
  13578. return typeof item === 'string' ? {
  13579. item: {
  13580. title: item
  13581. },
  13582. raw: item
  13583. } : {
  13584. item,
  13585. raw: item
  13586. };
  13587. }));
  13588. useRender(() => {
  13589. const hasPrepend = !!(slots.prepend || props.icon);
  13590. return vue.createVNode(props.tag, {
  13591. "class": ['v-breadcrumbs', backgroundColorClasses.value, densityClasses.value, roundedClasses.value, props.class],
  13592. "style": [backgroundColorStyles.value, props.style]
  13593. }, {
  13594. default: () => [hasPrepend && vue.createVNode("li", {
  13595. "key": "prepend",
  13596. "class": "v-breadcrumbs__prepend"
  13597. }, [!slots.prepend ? vue.createVNode(VIcon, {
  13598. "key": "prepend-icon",
  13599. "start": true,
  13600. "icon": props.icon
  13601. }, null) : vue.createVNode(VDefaultsProvider, {
  13602. "key": "prepend-defaults",
  13603. "disabled": !props.icon,
  13604. "defaults": {
  13605. VIcon: {
  13606. icon: props.icon,
  13607. start: true
  13608. }
  13609. }
  13610. }, slots.prepend)]), items.value.map((_ref2, index, array) => {
  13611. let {
  13612. item,
  13613. raw
  13614. } = _ref2;
  13615. return vue.createVNode(vue.Fragment, null, [slots.item?.({
  13616. item,
  13617. index
  13618. }) ?? vue.createVNode(VBreadcrumbsItem, vue.mergeProps({
  13619. "key": index,
  13620. "disabled": index >= array.length - 1
  13621. }, typeof item === 'string' ? {
  13622. title: item
  13623. } : item), {
  13624. default: slots.title ? () => slots.title?.({
  13625. item,
  13626. index
  13627. }) : undefined
  13628. }), index < array.length - 1 && vue.createVNode(VBreadcrumbsDivider, null, {
  13629. default: slots.divider ? () => slots.divider?.({
  13630. item: raw,
  13631. index
  13632. }) : undefined
  13633. })]);
  13634. }), slots.default?.()]
  13635. });
  13636. });
  13637. return {};
  13638. }
  13639. });
  13640. const VCardActions = genericComponent()({
  13641. name: 'VCardActions',
  13642. props: makeComponentProps(),
  13643. setup(props, _ref) {
  13644. let {
  13645. slots
  13646. } = _ref;
  13647. provideDefaults({
  13648. VBtn: {
  13649. slim: true,
  13650. variant: 'text'
  13651. }
  13652. });
  13653. useRender(() => vue.createVNode("div", {
  13654. "class": ['v-card-actions', props.class],
  13655. "style": props.style
  13656. }, [slots.default?.()]));
  13657. return {};
  13658. }
  13659. });
  13660. const makeVCardSubtitleProps = propsFactory({
  13661. opacity: [Number, String],
  13662. ...makeComponentProps(),
  13663. ...makeTagProps()
  13664. }, 'VCardSubtitle');
  13665. const VCardSubtitle = genericComponent()({
  13666. name: 'VCardSubtitle',
  13667. props: makeVCardSubtitleProps(),
  13668. setup(props, _ref) {
  13669. let {
  13670. slots
  13671. } = _ref;
  13672. useRender(() => vue.createVNode(props.tag, {
  13673. "class": ['v-card-subtitle', props.class],
  13674. "style": [{
  13675. '--v-card-subtitle-opacity': props.opacity
  13676. }, props.style]
  13677. }, slots));
  13678. return {};
  13679. }
  13680. });
  13681. // Utilities
  13682. const VCardTitle = createSimpleFunctional('v-card-title');
  13683. const makeCardItemProps = propsFactory({
  13684. appendAvatar: String,
  13685. appendIcon: IconValue,
  13686. prependAvatar: String,
  13687. prependIcon: IconValue,
  13688. subtitle: [String, Number],
  13689. title: [String, Number],
  13690. ...makeComponentProps(),
  13691. ...makeDensityProps()
  13692. }, 'VCardItem');
  13693. const VCardItem = genericComponent()({
  13694. name: 'VCardItem',
  13695. props: makeCardItemProps(),
  13696. setup(props, _ref) {
  13697. let {
  13698. slots
  13699. } = _ref;
  13700. useRender(() => {
  13701. const hasPrependMedia = !!(props.prependAvatar || props.prependIcon);
  13702. const hasPrepend = !!(hasPrependMedia || slots.prepend);
  13703. const hasAppendMedia = !!(props.appendAvatar || props.appendIcon);
  13704. const hasAppend = !!(hasAppendMedia || slots.append);
  13705. const hasTitle = !!(props.title != null || slots.title);
  13706. const hasSubtitle = !!(props.subtitle != null || slots.subtitle);
  13707. return vue.createVNode("div", {
  13708. "class": ['v-card-item', props.class],
  13709. "style": props.style
  13710. }, [hasPrepend && vue.createVNode("div", {
  13711. "key": "prepend",
  13712. "class": "v-card-item__prepend"
  13713. }, [!slots.prepend ? vue.createVNode(vue.Fragment, null, [props.prependAvatar && vue.createVNode(VAvatar, {
  13714. "key": "prepend-avatar",
  13715. "density": props.density,
  13716. "image": props.prependAvatar
  13717. }, null), props.prependIcon && vue.createVNode(VIcon, {
  13718. "key": "prepend-icon",
  13719. "density": props.density,
  13720. "icon": props.prependIcon
  13721. }, null)]) : vue.createVNode(VDefaultsProvider, {
  13722. "key": "prepend-defaults",
  13723. "disabled": !hasPrependMedia,
  13724. "defaults": {
  13725. VAvatar: {
  13726. density: props.density,
  13727. image: props.prependAvatar
  13728. },
  13729. VIcon: {
  13730. density: props.density,
  13731. icon: props.prependIcon
  13732. }
  13733. }
  13734. }, slots.prepend)]), vue.createVNode("div", {
  13735. "class": "v-card-item__content"
  13736. }, [hasTitle && vue.createVNode(VCardTitle, {
  13737. "key": "title"
  13738. }, {
  13739. default: () => [slots.title?.() ?? props.title]
  13740. }), hasSubtitle && vue.createVNode(VCardSubtitle, {
  13741. "key": "subtitle"
  13742. }, {
  13743. default: () => [slots.subtitle?.() ?? props.subtitle]
  13744. }), slots.default?.()]), hasAppend && vue.createVNode("div", {
  13745. "key": "append",
  13746. "class": "v-card-item__append"
  13747. }, [!slots.append ? vue.createVNode(vue.Fragment, null, [props.appendIcon && vue.createVNode(VIcon, {
  13748. "key": "append-icon",
  13749. "density": props.density,
  13750. "icon": props.appendIcon
  13751. }, null), props.appendAvatar && vue.createVNode(VAvatar, {
  13752. "key": "append-avatar",
  13753. "density": props.density,
  13754. "image": props.appendAvatar
  13755. }, null)]) : vue.createVNode(VDefaultsProvider, {
  13756. "key": "append-defaults",
  13757. "disabled": !hasAppendMedia,
  13758. "defaults": {
  13759. VAvatar: {
  13760. density: props.density,
  13761. image: props.appendAvatar
  13762. },
  13763. VIcon: {
  13764. density: props.density,
  13765. icon: props.appendIcon
  13766. }
  13767. }
  13768. }, slots.append)])]);
  13769. });
  13770. return {};
  13771. }
  13772. });
  13773. const makeVCardTextProps = propsFactory({
  13774. opacity: [Number, String],
  13775. ...makeComponentProps(),
  13776. ...makeTagProps()
  13777. }, 'VCardText');
  13778. const VCardText = genericComponent()({
  13779. name: 'VCardText',
  13780. props: makeVCardTextProps(),
  13781. setup(props, _ref) {
  13782. let {
  13783. slots
  13784. } = _ref;
  13785. useRender(() => vue.createVNode(props.tag, {
  13786. "class": ['v-card-text', props.class],
  13787. "style": [{
  13788. '--v-card-text-opacity': props.opacity
  13789. }, props.style]
  13790. }, slots));
  13791. return {};
  13792. }
  13793. });
  13794. // Types
  13795. const makeVCardProps = propsFactory({
  13796. appendAvatar: String,
  13797. appendIcon: IconValue,
  13798. disabled: Boolean,
  13799. flat: Boolean,
  13800. hover: Boolean,
  13801. image: String,
  13802. link: {
  13803. type: Boolean,
  13804. default: undefined
  13805. },
  13806. prependAvatar: String,
  13807. prependIcon: IconValue,
  13808. ripple: {
  13809. type: [Boolean, Object],
  13810. default: true
  13811. },
  13812. subtitle: [String, Number],
  13813. text: [String, Number],
  13814. title: [String, Number],
  13815. ...makeBorderProps(),
  13816. ...makeComponentProps(),
  13817. ...makeDensityProps(),
  13818. ...makeDimensionProps(),
  13819. ...makeElevationProps(),
  13820. ...makeLoaderProps(),
  13821. ...makeLocationProps(),
  13822. ...makePositionProps(),
  13823. ...makeRoundedProps(),
  13824. ...makeRouterProps(),
  13825. ...makeTagProps(),
  13826. ...makeThemeProps(),
  13827. ...makeVariantProps({
  13828. variant: 'elevated'
  13829. })
  13830. }, 'VCard');
  13831. const VCard = genericComponent()({
  13832. name: 'VCard',
  13833. directives: {
  13834. Ripple
  13835. },
  13836. props: makeVCardProps(),
  13837. setup(props, _ref) {
  13838. let {
  13839. attrs,
  13840. slots
  13841. } = _ref;
  13842. const {
  13843. themeClasses
  13844. } = provideTheme(props);
  13845. const {
  13846. borderClasses
  13847. } = useBorder(props);
  13848. const {
  13849. colorClasses,
  13850. colorStyles,
  13851. variantClasses
  13852. } = useVariant(props);
  13853. const {
  13854. densityClasses
  13855. } = useDensity(props);
  13856. const {
  13857. dimensionStyles
  13858. } = useDimension(props);
  13859. const {
  13860. elevationClasses
  13861. } = useElevation(props);
  13862. const {
  13863. loaderClasses
  13864. } = useLoader(props);
  13865. const {
  13866. locationStyles
  13867. } = useLocation(props);
  13868. const {
  13869. positionClasses
  13870. } = usePosition(props);
  13871. const {
  13872. roundedClasses
  13873. } = useRounded(props);
  13874. const link = useLink(props, attrs);
  13875. const isLink = vue.computed(() => props.link !== false && link.isLink.value);
  13876. const isClickable = vue.computed(() => !props.disabled && props.link !== false && (props.link || link.isClickable.value));
  13877. useRender(() => {
  13878. const Tag = isLink.value ? 'a' : props.tag;
  13879. const hasTitle = !!(slots.title || props.title != null);
  13880. const hasSubtitle = !!(slots.subtitle || props.subtitle != null);
  13881. const hasHeader = hasTitle || hasSubtitle;
  13882. const hasAppend = !!(slots.append || props.appendAvatar || props.appendIcon);
  13883. const hasPrepend = !!(slots.prepend || props.prependAvatar || props.prependIcon);
  13884. const hasImage = !!(slots.image || props.image);
  13885. const hasCardItem = hasHeader || hasPrepend || hasAppend;
  13886. const hasText = !!(slots.text || props.text != null);
  13887. return vue.withDirectives(vue.createVNode(Tag, vue.mergeProps({
  13888. "class": ['v-card', {
  13889. 'v-card--disabled': props.disabled,
  13890. 'v-card--flat': props.flat,
  13891. 'v-card--hover': props.hover && !(props.disabled || props.flat),
  13892. 'v-card--link': isClickable.value
  13893. }, themeClasses.value, borderClasses.value, colorClasses.value, densityClasses.value, elevationClasses.value, loaderClasses.value, positionClasses.value, roundedClasses.value, variantClasses.value, props.class],
  13894. "style": [colorStyles.value, dimensionStyles.value, locationStyles.value, props.style],
  13895. "onClick": isClickable.value && link.navigate,
  13896. "tabindex": props.disabled ? -1 : undefined
  13897. }, link.linkProps), {
  13898. default: () => [hasImage && vue.createVNode("div", {
  13899. "key": "image",
  13900. "class": "v-card__image"
  13901. }, [!slots.image ? vue.createVNode(VImg, {
  13902. "key": "image-img",
  13903. "cover": true,
  13904. "src": props.image
  13905. }, null) : vue.createVNode(VDefaultsProvider, {
  13906. "key": "image-defaults",
  13907. "disabled": !props.image,
  13908. "defaults": {
  13909. VImg: {
  13910. cover: true,
  13911. src: props.image
  13912. }
  13913. }
  13914. }, slots.image)]), vue.createVNode(LoaderSlot, {
  13915. "name": "v-card",
  13916. "active": !!props.loading,
  13917. "color": typeof props.loading === 'boolean' ? undefined : props.loading
  13918. }, {
  13919. default: slots.loader
  13920. }), hasCardItem && vue.createVNode(VCardItem, {
  13921. "key": "item",
  13922. "prependAvatar": props.prependAvatar,
  13923. "prependIcon": props.prependIcon,
  13924. "title": props.title,
  13925. "subtitle": props.subtitle,
  13926. "appendAvatar": props.appendAvatar,
  13927. "appendIcon": props.appendIcon
  13928. }, {
  13929. default: slots.item,
  13930. prepend: slots.prepend,
  13931. title: slots.title,
  13932. subtitle: slots.subtitle,
  13933. append: slots.append
  13934. }), hasText && vue.createVNode(VCardText, {
  13935. "key": "text"
  13936. }, {
  13937. default: () => [slots.text?.() ?? props.text]
  13938. }), slots.default?.(), slots.actions && vue.createVNode(VCardActions, null, {
  13939. default: slots.actions
  13940. }), genOverlays(isClickable.value, 'v-card')]
  13941. }), [[vue.resolveDirective("ripple"), isClickable.value && props.ripple]]);
  13942. });
  13943. return {};
  13944. }
  13945. });
  13946. // Utilities
  13947. // Types
  13948. const handleGesture = wrapper => {
  13949. const {
  13950. touchstartX,
  13951. touchendX,
  13952. touchstartY,
  13953. touchendY
  13954. } = wrapper;
  13955. const dirRatio = 0.5;
  13956. const minDistance = 16;
  13957. wrapper.offsetX = touchendX - touchstartX;
  13958. wrapper.offsetY = touchendY - touchstartY;
  13959. if (Math.abs(wrapper.offsetY) < dirRatio * Math.abs(wrapper.offsetX)) {
  13960. wrapper.left && touchendX < touchstartX - minDistance && wrapper.left(wrapper);
  13961. wrapper.right && touchendX > touchstartX + minDistance && wrapper.right(wrapper);
  13962. }
  13963. if (Math.abs(wrapper.offsetX) < dirRatio * Math.abs(wrapper.offsetY)) {
  13964. wrapper.up && touchendY < touchstartY - minDistance && wrapper.up(wrapper);
  13965. wrapper.down && touchendY > touchstartY + minDistance && wrapper.down(wrapper);
  13966. }
  13967. };
  13968. function touchstart(event, wrapper) {
  13969. const touch = event.changedTouches[0];
  13970. wrapper.touchstartX = touch.clientX;
  13971. wrapper.touchstartY = touch.clientY;
  13972. wrapper.start?.({
  13973. originalEvent: event,
  13974. ...wrapper
  13975. });
  13976. }
  13977. function touchend(event, wrapper) {
  13978. const touch = event.changedTouches[0];
  13979. wrapper.touchendX = touch.clientX;
  13980. wrapper.touchendY = touch.clientY;
  13981. wrapper.end?.({
  13982. originalEvent: event,
  13983. ...wrapper
  13984. });
  13985. handleGesture(wrapper);
  13986. }
  13987. function touchmove(event, wrapper) {
  13988. const touch = event.changedTouches[0];
  13989. wrapper.touchmoveX = touch.clientX;
  13990. wrapper.touchmoveY = touch.clientY;
  13991. wrapper.move?.({
  13992. originalEvent: event,
  13993. ...wrapper
  13994. });
  13995. }
  13996. function createHandlers() {
  13997. let value = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
  13998. const wrapper = {
  13999. touchstartX: 0,
  14000. touchstartY: 0,
  14001. touchendX: 0,
  14002. touchendY: 0,
  14003. touchmoveX: 0,
  14004. touchmoveY: 0,
  14005. offsetX: 0,
  14006. offsetY: 0,
  14007. left: value.left,
  14008. right: value.right,
  14009. up: value.up,
  14010. down: value.down,
  14011. start: value.start,
  14012. move: value.move,
  14013. end: value.end
  14014. };
  14015. return {
  14016. touchstart: e => touchstart(e, wrapper),
  14017. touchend: e => touchend(e, wrapper),
  14018. touchmove: e => touchmove(e, wrapper)
  14019. };
  14020. }
  14021. function mounted$3(el, binding) {
  14022. const value = binding.value;
  14023. const target = value?.parent ? el.parentElement : el;
  14024. const options = value?.options ?? {
  14025. passive: true
  14026. };
  14027. const uid = binding.instance?.$.uid; // TODO: use custom uid generator
  14028. if (!target || !uid) return;
  14029. const handlers = createHandlers(binding.value);
  14030. target._touchHandlers = target._touchHandlers ?? Object.create(null);
  14031. target._touchHandlers[uid] = handlers;
  14032. keys(handlers).forEach(eventName => {
  14033. target.addEventListener(eventName, handlers[eventName], options);
  14034. });
  14035. }
  14036. function unmounted$3(el, binding) {
  14037. const target = binding.value?.parent ? el.parentElement : el;
  14038. const uid = binding.instance?.$.uid;
  14039. if (!target?._touchHandlers || !uid) return;
  14040. const handlers = target._touchHandlers[uid];
  14041. keys(handlers).forEach(eventName => {
  14042. target.removeEventListener(eventName, handlers[eventName]);
  14043. });
  14044. delete target._touchHandlers[uid];
  14045. }
  14046. const Touch = {
  14047. mounted: mounted$3,
  14048. unmounted: unmounted$3
  14049. };
  14050. // Types
  14051. const VWindowSymbol = Symbol.for('vuetify:v-window');
  14052. const VWindowGroupSymbol = Symbol.for('vuetify:v-window-group');
  14053. const makeVWindowProps = propsFactory({
  14054. continuous: Boolean,
  14055. nextIcon: {
  14056. type: [Boolean, String, Function, Object],
  14057. default: '$next'
  14058. },
  14059. prevIcon: {
  14060. type: [Boolean, String, Function, Object],
  14061. default: '$prev'
  14062. },
  14063. reverse: Boolean,
  14064. showArrows: {
  14065. type: [Boolean, String],
  14066. validator: v => typeof v === 'boolean' || v === 'hover'
  14067. },
  14068. touch: {
  14069. type: [Object, Boolean],
  14070. default: undefined
  14071. },
  14072. direction: {
  14073. type: String,
  14074. default: 'horizontal'
  14075. },
  14076. modelValue: null,
  14077. disabled: Boolean,
  14078. selectedClass: {
  14079. type: String,
  14080. default: 'v-window-item--active'
  14081. },
  14082. // TODO: mandatory should probably not be exposed but do this for now
  14083. mandatory: {
  14084. type: [Boolean, String],
  14085. default: 'force'
  14086. },
  14087. ...makeComponentProps(),
  14088. ...makeTagProps(),
  14089. ...makeThemeProps()
  14090. }, 'VWindow');
  14091. const VWindow = genericComponent()({
  14092. name: 'VWindow',
  14093. directives: {
  14094. Touch
  14095. },
  14096. props: makeVWindowProps(),
  14097. emits: {
  14098. 'update:modelValue': value => true
  14099. },
  14100. setup(props, _ref) {
  14101. let {
  14102. slots
  14103. } = _ref;
  14104. const {
  14105. themeClasses
  14106. } = provideTheme(props);
  14107. const {
  14108. isRtl
  14109. } = useRtl();
  14110. const {
  14111. t
  14112. } = useLocale();
  14113. const group = useGroup(props, VWindowGroupSymbol);
  14114. const rootRef = vue.ref();
  14115. const isRtlReverse = vue.computed(() => isRtl.value ? !props.reverse : props.reverse);
  14116. const isReversed = vue.shallowRef(false);
  14117. const transition = vue.computed(() => {
  14118. const axis = props.direction === 'vertical' ? 'y' : 'x';
  14119. const reverse = isRtlReverse.value ? !isReversed.value : isReversed.value;
  14120. const direction = reverse ? '-reverse' : '';
  14121. return `v-window-${axis}${direction}-transition`;
  14122. });
  14123. const transitionCount = vue.shallowRef(0);
  14124. const transitionHeight = vue.ref(undefined);
  14125. const activeIndex = vue.computed(() => {
  14126. return group.items.value.findIndex(item => group.selected.value.includes(item.id));
  14127. });
  14128. vue.watch(activeIndex, (newVal, oldVal) => {
  14129. const itemsLength = group.items.value.length;
  14130. const lastIndex = itemsLength - 1;
  14131. if (itemsLength <= 2) {
  14132. isReversed.value = newVal < oldVal;
  14133. } else if (newVal === lastIndex && oldVal === 0) {
  14134. isReversed.value = true;
  14135. } else if (newVal === 0 && oldVal === lastIndex) {
  14136. isReversed.value = false;
  14137. } else {
  14138. isReversed.value = newVal < oldVal;
  14139. }
  14140. });
  14141. vue.provide(VWindowSymbol, {
  14142. transition,
  14143. isReversed,
  14144. transitionCount,
  14145. transitionHeight,
  14146. rootRef
  14147. });
  14148. const canMoveBack = vue.computed(() => props.continuous || activeIndex.value !== 0);
  14149. const canMoveForward = vue.computed(() => props.continuous || activeIndex.value !== group.items.value.length - 1);
  14150. function prev() {
  14151. canMoveBack.value && group.prev();
  14152. }
  14153. function next() {
  14154. canMoveForward.value && group.next();
  14155. }
  14156. const arrows = vue.computed(() => {
  14157. const arrows = [];
  14158. const prevProps = {
  14159. icon: isRtl.value ? props.nextIcon : props.prevIcon,
  14160. class: `v-window__${isRtlReverse.value ? 'right' : 'left'}`,
  14161. onClick: group.prev,
  14162. 'aria-label': t('$vuetify.carousel.prev')
  14163. };
  14164. arrows.push(canMoveBack.value ? slots.prev ? slots.prev({
  14165. props: prevProps
  14166. }) : vue.createVNode(VBtn, prevProps, null) : vue.createVNode("div", null, null));
  14167. const nextProps = {
  14168. icon: isRtl.value ? props.prevIcon : props.nextIcon,
  14169. class: `v-window__${isRtlReverse.value ? 'left' : 'right'}`,
  14170. onClick: group.next,
  14171. 'aria-label': t('$vuetify.carousel.next')
  14172. };
  14173. arrows.push(canMoveForward.value ? slots.next ? slots.next({
  14174. props: nextProps
  14175. }) : vue.createVNode(VBtn, nextProps, null) : vue.createVNode("div", null, null));
  14176. return arrows;
  14177. });
  14178. const touchOptions = vue.computed(() => {
  14179. if (props.touch === false) return props.touch;
  14180. const options = {
  14181. left: () => {
  14182. isRtlReverse.value ? prev() : next();
  14183. },
  14184. right: () => {
  14185. isRtlReverse.value ? next() : prev();
  14186. },
  14187. start: _ref2 => {
  14188. let {
  14189. originalEvent
  14190. } = _ref2;
  14191. originalEvent.stopPropagation();
  14192. }
  14193. };
  14194. return {
  14195. ...options,
  14196. ...(props.touch === true ? {} : props.touch)
  14197. };
  14198. });
  14199. useRender(() => vue.withDirectives(vue.createVNode(props.tag, {
  14200. "ref": rootRef,
  14201. "class": ['v-window', {
  14202. 'v-window--show-arrows-on-hover': props.showArrows === 'hover'
  14203. }, themeClasses.value, props.class],
  14204. "style": props.style
  14205. }, {
  14206. default: () => [vue.createVNode("div", {
  14207. "class": "v-window__container",
  14208. "style": {
  14209. height: transitionHeight.value
  14210. }
  14211. }, [slots.default?.({
  14212. group
  14213. }), props.showArrows !== false && vue.createVNode("div", {
  14214. "class": "v-window__controls"
  14215. }, [arrows.value])]), slots.additional?.({
  14216. group
  14217. })]
  14218. }), [[vue.resolveDirective("touch"), touchOptions.value]]));
  14219. return {
  14220. group
  14221. };
  14222. }
  14223. });
  14224. // Types
  14225. const makeVCarouselProps = propsFactory({
  14226. color: String,
  14227. cycle: Boolean,
  14228. delimiterIcon: {
  14229. type: IconValue,
  14230. default: '$delimiter'
  14231. },
  14232. height: {
  14233. type: [Number, String],
  14234. default: 500
  14235. },
  14236. hideDelimiters: Boolean,
  14237. hideDelimiterBackground: Boolean,
  14238. interval: {
  14239. type: [Number, String],
  14240. default: 6000,
  14241. validator: value => Number(value) > 0
  14242. },
  14243. progress: [Boolean, String],
  14244. verticalDelimiters: [Boolean, String],
  14245. ...makeVWindowProps({
  14246. continuous: true,
  14247. mandatory: 'force',
  14248. showArrows: true
  14249. })
  14250. }, 'VCarousel');
  14251. const VCarousel = genericComponent()({
  14252. name: 'VCarousel',
  14253. props: makeVCarouselProps(),
  14254. emits: {
  14255. 'update:modelValue': value => true
  14256. },
  14257. setup(props, _ref) {
  14258. let {
  14259. slots
  14260. } = _ref;
  14261. const model = useProxiedModel(props, 'modelValue');
  14262. const {
  14263. t
  14264. } = useLocale();
  14265. const windowRef = vue.ref();
  14266. let slideTimeout = -1;
  14267. vue.watch(model, restartTimeout);
  14268. vue.watch(() => props.interval, restartTimeout);
  14269. vue.watch(() => props.cycle, val => {
  14270. if (val) restartTimeout();else window.clearTimeout(slideTimeout);
  14271. });
  14272. vue.onMounted(startTimeout);
  14273. function startTimeout() {
  14274. if (!props.cycle || !windowRef.value) return;
  14275. slideTimeout = window.setTimeout(windowRef.value.group.next, +props.interval > 0 ? +props.interval : 6000);
  14276. }
  14277. function restartTimeout() {
  14278. window.clearTimeout(slideTimeout);
  14279. window.requestAnimationFrame(startTimeout);
  14280. }
  14281. useRender(() => {
  14282. const windowProps = VWindow.filterProps(props);
  14283. return vue.createVNode(VWindow, vue.mergeProps({
  14284. "ref": windowRef
  14285. }, windowProps, {
  14286. "modelValue": model.value,
  14287. "onUpdate:modelValue": $event => model.value = $event,
  14288. "class": ['v-carousel', {
  14289. 'v-carousel--hide-delimiter-background': props.hideDelimiterBackground,
  14290. 'v-carousel--vertical-delimiters': props.verticalDelimiters
  14291. }, props.class],
  14292. "style": [{
  14293. height: convertToUnit(props.height)
  14294. }, props.style]
  14295. }), {
  14296. default: slots.default,
  14297. additional: _ref2 => {
  14298. let {
  14299. group
  14300. } = _ref2;
  14301. return vue.createVNode(vue.Fragment, null, [!props.hideDelimiters && vue.createVNode("div", {
  14302. "class": "v-carousel__controls",
  14303. "style": {
  14304. left: props.verticalDelimiters === 'left' && props.verticalDelimiters ? 0 : 'auto',
  14305. right: props.verticalDelimiters === 'right' ? 0 : 'auto'
  14306. }
  14307. }, [group.items.value.length > 0 && vue.createVNode(VDefaultsProvider, {
  14308. "defaults": {
  14309. VBtn: {
  14310. color: props.color,
  14311. icon: props.delimiterIcon,
  14312. size: 'x-small',
  14313. variant: 'text'
  14314. }
  14315. },
  14316. "scoped": true
  14317. }, {
  14318. default: () => [group.items.value.map((item, index) => {
  14319. const props = {
  14320. id: `carousel-item-${item.id}`,
  14321. 'aria-label': t('$vuetify.carousel.ariaLabel.delimiter', index + 1, group.items.value.length),
  14322. class: ['v-carousel__controls__item', group.isSelected(item.id) && 'v-btn--active'],
  14323. onClick: () => group.select(item.id, true)
  14324. };
  14325. return slots.item ? slots.item({
  14326. props,
  14327. item
  14328. }) : vue.createVNode(VBtn, vue.mergeProps(item, props), null);
  14329. })]
  14330. })]), props.progress && vue.createVNode(VProgressLinear, {
  14331. "class": "v-carousel__progress",
  14332. "color": typeof props.progress === 'string' ? props.progress : undefined,
  14333. "modelValue": (group.getItemIndex(model.value) + 1) / group.items.value.length * 100
  14334. }, null)]);
  14335. },
  14336. prev: slots.prev,
  14337. next: slots.next
  14338. });
  14339. });
  14340. return {};
  14341. }
  14342. });
  14343. const makeVWindowItemProps = propsFactory({
  14344. reverseTransition: {
  14345. type: [Boolean, String],
  14346. default: undefined
  14347. },
  14348. transition: {
  14349. type: [Boolean, String],
  14350. default: undefined
  14351. },
  14352. ...makeComponentProps(),
  14353. ...makeGroupItemProps(),
  14354. ...makeLazyProps()
  14355. }, 'VWindowItem');
  14356. const VWindowItem = genericComponent()({
  14357. name: 'VWindowItem',
  14358. directives: {
  14359. Touch
  14360. },
  14361. props: makeVWindowItemProps(),
  14362. emits: {
  14363. 'group:selected': val => true
  14364. },
  14365. setup(props, _ref) {
  14366. let {
  14367. slots
  14368. } = _ref;
  14369. const window = vue.inject(VWindowSymbol);
  14370. const groupItem = useGroupItem(props, VWindowGroupSymbol);
  14371. const {
  14372. isBooted
  14373. } = useSsrBoot();
  14374. if (!window || !groupItem) throw new Error('[Vuetify] VWindowItem must be used inside VWindow');
  14375. const isTransitioning = vue.shallowRef(false);
  14376. const hasTransition = vue.computed(() => isBooted.value && (window.isReversed.value ? props.reverseTransition !== false : props.transition !== false));
  14377. function onAfterTransition() {
  14378. if (!isTransitioning.value || !window) {
  14379. return;
  14380. }
  14381. // Finalize transition state.
  14382. isTransitioning.value = false;
  14383. if (window.transitionCount.value > 0) {
  14384. window.transitionCount.value -= 1;
  14385. // Remove container height if we are out of transition.
  14386. if (window.transitionCount.value === 0) {
  14387. window.transitionHeight.value = undefined;
  14388. }
  14389. }
  14390. }
  14391. function onBeforeTransition() {
  14392. if (isTransitioning.value || !window) {
  14393. return;
  14394. }
  14395. // Initialize transition state here.
  14396. isTransitioning.value = true;
  14397. if (window.transitionCount.value === 0) {
  14398. // Set initial height for height transition.
  14399. window.transitionHeight.value = convertToUnit(window.rootRef.value?.clientHeight);
  14400. }
  14401. window.transitionCount.value += 1;
  14402. }
  14403. function onTransitionCancelled() {
  14404. onAfterTransition(); // This should have the same path as normal transition end.
  14405. }
  14406. function onEnterTransition(el) {
  14407. if (!isTransitioning.value) {
  14408. return;
  14409. }
  14410. vue.nextTick(() => {
  14411. // Do not set height if no transition or cancelled.
  14412. if (!hasTransition.value || !isTransitioning.value || !window) {
  14413. return;
  14414. }
  14415. // Set transition target height.
  14416. window.transitionHeight.value = convertToUnit(el.clientHeight);
  14417. });
  14418. }
  14419. const transition = vue.computed(() => {
  14420. const name = window.isReversed.value ? props.reverseTransition : props.transition;
  14421. return !hasTransition.value ? false : {
  14422. name: typeof name !== 'string' ? window.transition.value : name,
  14423. onBeforeEnter: onBeforeTransition,
  14424. onAfterEnter: onAfterTransition,
  14425. onEnterCancelled: onTransitionCancelled,
  14426. onBeforeLeave: onBeforeTransition,
  14427. onAfterLeave: onAfterTransition,
  14428. onLeaveCancelled: onTransitionCancelled,
  14429. onEnter: onEnterTransition
  14430. };
  14431. });
  14432. const {
  14433. hasContent
  14434. } = useLazy(props, groupItem.isSelected);
  14435. useRender(() => vue.createVNode(MaybeTransition, {
  14436. "transition": transition.value,
  14437. "disabled": !isBooted.value
  14438. }, {
  14439. default: () => [vue.withDirectives(vue.createVNode("div", {
  14440. "class": ['v-window-item', groupItem.selectedClass.value, props.class],
  14441. "style": props.style
  14442. }, [hasContent.value && slots.default?.()]), [[vue.vShow, groupItem.isSelected.value]])]
  14443. }));
  14444. return {
  14445. groupItem
  14446. };
  14447. }
  14448. });
  14449. // Types
  14450. const makeVCarouselItemProps = propsFactory({
  14451. ...makeVImgProps(),
  14452. ...makeVWindowItemProps()
  14453. }, 'VCarouselItem');
  14454. const VCarouselItem = genericComponent()({
  14455. name: 'VCarouselItem',
  14456. inheritAttrs: false,
  14457. props: makeVCarouselItemProps(),
  14458. setup(props, _ref) {
  14459. let {
  14460. slots,
  14461. attrs
  14462. } = _ref;
  14463. useRender(() => {
  14464. const imgProps = VImg.filterProps(props);
  14465. const windowItemProps = VWindowItem.filterProps(props);
  14466. return vue.createVNode(VWindowItem, vue.mergeProps({
  14467. "class": ['v-carousel-item', props.class]
  14468. }, windowItemProps), {
  14469. default: () => [vue.createVNode(VImg, vue.mergeProps(attrs, imgProps), slots)]
  14470. });
  14471. });
  14472. }
  14473. });
  14474. // Styles
  14475. const VCode = createSimpleFunctional('v-code', 'code');
  14476. // Types
  14477. const makeVColorPickerCanvasProps = propsFactory({
  14478. color: {
  14479. type: Object
  14480. },
  14481. disabled: Boolean,
  14482. dotSize: {
  14483. type: [Number, String],
  14484. default: 10
  14485. },
  14486. height: {
  14487. type: [Number, String],
  14488. default: 150
  14489. },
  14490. width: {
  14491. type: [Number, String],
  14492. default: 300
  14493. },
  14494. ...makeComponentProps()
  14495. }, 'VColorPickerCanvas');
  14496. const VColorPickerCanvas = defineComponent({
  14497. name: 'VColorPickerCanvas',
  14498. props: makeVColorPickerCanvasProps(),
  14499. emits: {
  14500. 'update:color': color => true,
  14501. 'update:position': hue => true
  14502. },
  14503. setup(props, _ref) {
  14504. let {
  14505. emit
  14506. } = _ref;
  14507. const isInteracting = vue.shallowRef(false);
  14508. const canvasRef = vue.ref();
  14509. const canvasWidth = vue.shallowRef(parseFloat(props.width));
  14510. const canvasHeight = vue.shallowRef(parseFloat(props.height));
  14511. const _dotPosition = vue.ref({
  14512. x: 0,
  14513. y: 0
  14514. });
  14515. const dotPosition = vue.computed({
  14516. get: () => _dotPosition.value,
  14517. set(val) {
  14518. if (!canvasRef.value) return;
  14519. const {
  14520. x,
  14521. y
  14522. } = val;
  14523. _dotPosition.value = val;
  14524. emit('update:color', {
  14525. h: props.color?.h ?? 0,
  14526. s: clamp(x, 0, canvasWidth.value) / canvasWidth.value,
  14527. v: 1 - clamp(y, 0, canvasHeight.value) / canvasHeight.value,
  14528. a: props.color?.a ?? 1
  14529. });
  14530. }
  14531. });
  14532. const dotStyles = vue.computed(() => {
  14533. const {
  14534. x,
  14535. y
  14536. } = dotPosition.value;
  14537. const radius = parseInt(props.dotSize, 10) / 2;
  14538. return {
  14539. width: convertToUnit(props.dotSize),
  14540. height: convertToUnit(props.dotSize),
  14541. transform: `translate(${convertToUnit(x - radius)}, ${convertToUnit(y - radius)})`
  14542. };
  14543. });
  14544. const {
  14545. resizeRef
  14546. } = useResizeObserver(entries => {
  14547. if (!resizeRef.el?.offsetParent) return;
  14548. const {
  14549. width,
  14550. height
  14551. } = entries[0].contentRect;
  14552. canvasWidth.value = width;
  14553. canvasHeight.value = height;
  14554. });
  14555. function updateDotPosition(x, y, rect) {
  14556. const {
  14557. left,
  14558. top,
  14559. width,
  14560. height
  14561. } = rect;
  14562. dotPosition.value = {
  14563. x: clamp(x - left, 0, width),
  14564. y: clamp(y - top, 0, height)
  14565. };
  14566. }
  14567. function handleMouseDown(e) {
  14568. if (e.type === 'mousedown') {
  14569. // Prevent text selection while dragging
  14570. e.preventDefault();
  14571. }
  14572. if (props.disabled) return;
  14573. handleMouseMove(e);
  14574. window.addEventListener('mousemove', handleMouseMove);
  14575. window.addEventListener('mouseup', handleMouseUp);
  14576. window.addEventListener('touchmove', handleMouseMove);
  14577. window.addEventListener('touchend', handleMouseUp);
  14578. }
  14579. function handleMouseMove(e) {
  14580. if (props.disabled || !canvasRef.value) return;
  14581. isInteracting.value = true;
  14582. const coords = getEventCoordinates(e);
  14583. updateDotPosition(coords.clientX, coords.clientY, canvasRef.value.getBoundingClientRect());
  14584. }
  14585. function handleMouseUp() {
  14586. window.removeEventListener('mousemove', handleMouseMove);
  14587. window.removeEventListener('mouseup', handleMouseUp);
  14588. window.removeEventListener('touchmove', handleMouseMove);
  14589. window.removeEventListener('touchend', handleMouseUp);
  14590. }
  14591. function updateCanvas() {
  14592. if (!canvasRef.value) return;
  14593. const canvas = canvasRef.value;
  14594. const ctx = canvas.getContext('2d');
  14595. if (!ctx) return;
  14596. const saturationGradient = ctx.createLinearGradient(0, 0, canvas.width, 0);
  14597. saturationGradient.addColorStop(0, 'hsla(0, 0%, 100%, 1)'); // white
  14598. saturationGradient.addColorStop(1, `hsla(${props.color?.h ?? 0}, 100%, 50%, 1)`);
  14599. ctx.fillStyle = saturationGradient;
  14600. ctx.fillRect(0, 0, canvas.width, canvas.height);
  14601. const valueGradient = ctx.createLinearGradient(0, 0, 0, canvas.height);
  14602. valueGradient.addColorStop(0, 'hsla(0, 0%, 0%, 0)'); // transparent
  14603. valueGradient.addColorStop(1, 'hsla(0, 0%, 0%, 1)'); // black
  14604. ctx.fillStyle = valueGradient;
  14605. ctx.fillRect(0, 0, canvas.width, canvas.height);
  14606. }
  14607. vue.watch(() => props.color?.h, updateCanvas, {
  14608. immediate: true
  14609. });
  14610. vue.watch(() => [canvasWidth.value, canvasHeight.value], (newVal, oldVal) => {
  14611. updateCanvas();
  14612. _dotPosition.value = {
  14613. x: dotPosition.value.x * newVal[0] / oldVal[0],
  14614. y: dotPosition.value.y * newVal[1] / oldVal[1]
  14615. };
  14616. }, {
  14617. flush: 'post'
  14618. });
  14619. vue.watch(() => props.color, () => {
  14620. if (isInteracting.value) {
  14621. isInteracting.value = false;
  14622. return;
  14623. }
  14624. _dotPosition.value = props.color ? {
  14625. x: props.color.s * canvasWidth.value,
  14626. y: (1 - props.color.v) * canvasHeight.value
  14627. } : {
  14628. x: 0,
  14629. y: 0
  14630. };
  14631. }, {
  14632. deep: true,
  14633. immediate: true
  14634. });
  14635. vue.onMounted(() => updateCanvas());
  14636. useRender(() => vue.createVNode("div", {
  14637. "ref": resizeRef,
  14638. "class": ['v-color-picker-canvas', props.class],
  14639. "style": props.style,
  14640. "onMousedown": handleMouseDown,
  14641. "onTouchstartPassive": handleMouseDown
  14642. }, [vue.createVNode("canvas", {
  14643. "ref": canvasRef,
  14644. "width": canvasWidth.value,
  14645. "height": canvasHeight.value
  14646. }, null), props.color && vue.createVNode("div", {
  14647. "class": ['v-color-picker-canvas__dot', {
  14648. 'v-color-picker-canvas__dot--disabled': props.disabled
  14649. }],
  14650. "style": dotStyles.value
  14651. }, null)]));
  14652. return {};
  14653. }
  14654. });
  14655. // Utilities
  14656. // Types
  14657. function stripAlpha(color, stripAlpha) {
  14658. if (stripAlpha) {
  14659. const {
  14660. a,
  14661. ...rest
  14662. } = color;
  14663. return rest;
  14664. }
  14665. return color;
  14666. }
  14667. function extractColor(color, input) {
  14668. if (input == null || typeof input === 'string') {
  14669. const hex = HSVtoHex(color);
  14670. if (color.a === 1) return hex.slice(0, 7);else return hex;
  14671. }
  14672. if (typeof input === 'object') {
  14673. let converted;
  14674. 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;
  14675. return stripAlpha(converted, !has(input, ['a']) && color.a === 1);
  14676. }
  14677. return color;
  14678. }
  14679. const nullColor = {
  14680. h: 0,
  14681. s: 0,
  14682. v: 0,
  14683. a: 1
  14684. };
  14685. const rgba = {
  14686. inputProps: {
  14687. type: 'number',
  14688. min: 0
  14689. },
  14690. inputs: [{
  14691. label: 'R',
  14692. max: 255,
  14693. step: 1,
  14694. getValue: c => Math.round(c.r),
  14695. getColor: (c, v) => ({
  14696. ...c,
  14697. r: Number(v)
  14698. })
  14699. }, {
  14700. label: 'G',
  14701. max: 255,
  14702. step: 1,
  14703. getValue: c => Math.round(c.g),
  14704. getColor: (c, v) => ({
  14705. ...c,
  14706. g: Number(v)
  14707. })
  14708. }, {
  14709. label: 'B',
  14710. max: 255,
  14711. step: 1,
  14712. getValue: c => Math.round(c.b),
  14713. getColor: (c, v) => ({
  14714. ...c,
  14715. b: Number(v)
  14716. })
  14717. }, {
  14718. label: 'A',
  14719. max: 1,
  14720. step: 0.01,
  14721. getValue: _ref => {
  14722. let {
  14723. a
  14724. } = _ref;
  14725. return a != null ? Math.round(a * 100) / 100 : 1;
  14726. },
  14727. getColor: (c, v) => ({
  14728. ...c,
  14729. a: Number(v)
  14730. })
  14731. }],
  14732. to: HSVtoRGB,
  14733. from: RGBtoHSV
  14734. };
  14735. const rgb = {
  14736. ...rgba,
  14737. inputs: rgba.inputs?.slice(0, 3)
  14738. };
  14739. const hsla = {
  14740. inputProps: {
  14741. type: 'number',
  14742. min: 0
  14743. },
  14744. inputs: [{
  14745. label: 'H',
  14746. max: 360,
  14747. step: 1,
  14748. getValue: c => Math.round(c.h),
  14749. getColor: (c, v) => ({
  14750. ...c,
  14751. h: Number(v)
  14752. })
  14753. }, {
  14754. label: 'S',
  14755. max: 1,
  14756. step: 0.01,
  14757. getValue: c => Math.round(c.s * 100) / 100,
  14758. getColor: (c, v) => ({
  14759. ...c,
  14760. s: Number(v)
  14761. })
  14762. }, {
  14763. label: 'L',
  14764. max: 1,
  14765. step: 0.01,
  14766. getValue: c => Math.round(c.l * 100) / 100,
  14767. getColor: (c, v) => ({
  14768. ...c,
  14769. l: Number(v)
  14770. })
  14771. }, {
  14772. label: 'A',
  14773. max: 1,
  14774. step: 0.01,
  14775. getValue: _ref2 => {
  14776. let {
  14777. a
  14778. } = _ref2;
  14779. return a != null ? Math.round(a * 100) / 100 : 1;
  14780. },
  14781. getColor: (c, v) => ({
  14782. ...c,
  14783. a: Number(v)
  14784. })
  14785. }],
  14786. to: HSVtoHSL,
  14787. from: HSLtoHSV
  14788. };
  14789. const hsl = {
  14790. ...hsla,
  14791. inputs: hsla.inputs.slice(0, 3)
  14792. };
  14793. const hexa = {
  14794. inputProps: {
  14795. type: 'text'
  14796. },
  14797. inputs: [{
  14798. label: 'HEXA',
  14799. getValue: c => c,
  14800. getColor: (c, v) => v
  14801. }],
  14802. to: HSVtoHex,
  14803. from: HexToHSV
  14804. };
  14805. const hex = {
  14806. ...hexa,
  14807. inputs: [{
  14808. label: 'HEX',
  14809. getValue: c => c.slice(0, 7),
  14810. getColor: (c, v) => v
  14811. }]
  14812. };
  14813. const modes = {
  14814. rgb,
  14815. rgba,
  14816. hsl,
  14817. hsla,
  14818. hex,
  14819. hexa
  14820. };
  14821. // Types
  14822. const VColorPickerInput = _ref => {
  14823. let {
  14824. label,
  14825. ...rest
  14826. } = _ref;
  14827. return vue.createVNode("div", {
  14828. "class": "v-color-picker-edit__input"
  14829. }, [vue.createVNode("input", rest, null), vue.createVNode("span", null, [label])]);
  14830. };
  14831. const makeVColorPickerEditProps = propsFactory({
  14832. color: Object,
  14833. disabled: Boolean,
  14834. mode: {
  14835. type: String,
  14836. default: 'rgba',
  14837. validator: v => Object.keys(modes).includes(v)
  14838. },
  14839. modes: {
  14840. type: Array,
  14841. default: () => Object.keys(modes),
  14842. validator: v => Array.isArray(v) && v.every(m => Object.keys(modes).includes(m))
  14843. },
  14844. ...makeComponentProps()
  14845. }, 'VColorPickerEdit');
  14846. const VColorPickerEdit = defineComponent({
  14847. name: 'VColorPickerEdit',
  14848. props: makeVColorPickerEditProps(),
  14849. emits: {
  14850. 'update:color': color => true,
  14851. 'update:mode': mode => true
  14852. },
  14853. setup(props, _ref2) {
  14854. let {
  14855. emit
  14856. } = _ref2;
  14857. const enabledModes = vue.computed(() => {
  14858. return props.modes.map(key => ({
  14859. ...modes[key],
  14860. name: key
  14861. }));
  14862. });
  14863. const inputs = vue.computed(() => {
  14864. const mode = enabledModes.value.find(m => m.name === props.mode);
  14865. if (!mode) return [];
  14866. const color = props.color ? mode.to(props.color) : null;
  14867. return mode.inputs?.map(_ref3 => {
  14868. let {
  14869. getValue,
  14870. getColor,
  14871. ...inputProps
  14872. } = _ref3;
  14873. return {
  14874. ...mode.inputProps,
  14875. ...inputProps,
  14876. disabled: props.disabled,
  14877. value: color && getValue(color),
  14878. onChange: e => {
  14879. const target = e.target;
  14880. if (!target) return;
  14881. emit('update:color', mode.from(getColor(color ?? mode.to(nullColor), target.value)));
  14882. }
  14883. };
  14884. });
  14885. });
  14886. useRender(() => vue.createVNode("div", {
  14887. "class": ['v-color-picker-edit', props.class],
  14888. "style": props.style
  14889. }, [inputs.value?.map(props => vue.createVNode(VColorPickerInput, props, null)), enabledModes.value.length > 1 && vue.createVNode(VBtn, {
  14890. "icon": "$unfold",
  14891. "size": "x-small",
  14892. "variant": "plain",
  14893. "onClick": () => {
  14894. const mi = enabledModes.value.findIndex(m => m.name === props.mode);
  14895. emit('update:mode', enabledModes.value[(mi + 1) % enabledModes.value.length].name);
  14896. }
  14897. }, null)]));
  14898. return {};
  14899. }
  14900. });
  14901. /* eslint-disable max-statements */
  14902. // Composables
  14903. // Types
  14904. const VSliderSymbol = Symbol.for('vuetify:v-slider');
  14905. function getOffset(e, el, direction) {
  14906. const vertical = direction === 'vertical';
  14907. const rect = el.getBoundingClientRect();
  14908. const touch = 'touches' in e ? e.touches[0] : e;
  14909. return vertical ? touch.clientY - (rect.top + rect.height / 2) : touch.clientX - (rect.left + rect.width / 2);
  14910. }
  14911. function getPosition(e, position) {
  14912. 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];
  14913. }
  14914. const makeSliderProps = propsFactory({
  14915. disabled: {
  14916. type: Boolean,
  14917. default: null
  14918. },
  14919. error: Boolean,
  14920. readonly: {
  14921. type: Boolean,
  14922. default: null
  14923. },
  14924. max: {
  14925. type: [Number, String],
  14926. default: 100
  14927. },
  14928. min: {
  14929. type: [Number, String],
  14930. default: 0
  14931. },
  14932. step: {
  14933. type: [Number, String],
  14934. default: 0
  14935. },
  14936. thumbColor: String,
  14937. thumbLabel: {
  14938. type: [Boolean, String],
  14939. default: undefined,
  14940. validator: v => typeof v === 'boolean' || v === 'always'
  14941. },
  14942. thumbSize: {
  14943. type: [Number, String],
  14944. default: 20
  14945. },
  14946. showTicks: {
  14947. type: [Boolean, String],
  14948. default: false,
  14949. validator: v => typeof v === 'boolean' || v === 'always'
  14950. },
  14951. ticks: {
  14952. type: [Array, Object]
  14953. },
  14954. tickSize: {
  14955. type: [Number, String],
  14956. default: 2
  14957. },
  14958. color: String,
  14959. trackColor: String,
  14960. trackFillColor: String,
  14961. trackSize: {
  14962. type: [Number, String],
  14963. default: 4
  14964. },
  14965. direction: {
  14966. type: String,
  14967. default: 'horizontal',
  14968. validator: v => ['vertical', 'horizontal'].includes(v)
  14969. },
  14970. reverse: Boolean,
  14971. ...makeRoundedProps(),
  14972. ...makeElevationProps({
  14973. elevation: 2
  14974. }),
  14975. ripple: {
  14976. type: Boolean,
  14977. default: true
  14978. }
  14979. }, 'Slider');
  14980. const useSteps = props => {
  14981. const min = vue.computed(() => parseFloat(props.min));
  14982. const max = vue.computed(() => parseFloat(props.max));
  14983. const step = vue.computed(() => +props.step > 0 ? parseFloat(props.step) : 0);
  14984. const decimals = vue.computed(() => Math.max(getDecimals(step.value), getDecimals(min.value)));
  14985. function roundValue(value) {
  14986. value = parseFloat(value);
  14987. if (step.value <= 0) return value;
  14988. const clamped = clamp(value, min.value, max.value);
  14989. const offset = min.value % step.value;
  14990. const newValue = Math.round((clamped - offset) / step.value) * step.value + offset;
  14991. return parseFloat(Math.min(newValue, max.value).toFixed(decimals.value));
  14992. }
  14993. return {
  14994. min,
  14995. max,
  14996. step,
  14997. decimals,
  14998. roundValue
  14999. };
  15000. };
  15001. const useSlider = _ref => {
  15002. let {
  15003. props,
  15004. steps,
  15005. onSliderStart,
  15006. onSliderMove,
  15007. onSliderEnd,
  15008. getActiveThumb
  15009. } = _ref;
  15010. const {
  15011. isRtl
  15012. } = useRtl();
  15013. const isReversed = vue.toRef(props, 'reverse');
  15014. const vertical = vue.computed(() => props.direction === 'vertical');
  15015. const indexFromEnd = vue.computed(() => vertical.value !== isReversed.value);
  15016. const {
  15017. min,
  15018. max,
  15019. step,
  15020. decimals,
  15021. roundValue
  15022. } = steps;
  15023. const thumbSize = vue.computed(() => parseInt(props.thumbSize, 10));
  15024. const tickSize = vue.computed(() => parseInt(props.tickSize, 10));
  15025. const trackSize = vue.computed(() => parseInt(props.trackSize, 10));
  15026. const numTicks = vue.computed(() => (max.value - min.value) / step.value);
  15027. const disabled = vue.toRef(props, 'disabled');
  15028. const thumbColor = vue.computed(() => props.error || props.disabled ? undefined : props.thumbColor ?? props.color);
  15029. const trackColor = vue.computed(() => props.error || props.disabled ? undefined : props.trackColor ?? props.color);
  15030. const trackFillColor = vue.computed(() => props.error || props.disabled ? undefined : props.trackFillColor ?? props.color);
  15031. const mousePressed = vue.shallowRef(false);
  15032. const startOffset = vue.shallowRef(0);
  15033. const trackContainerRef = vue.ref();
  15034. const activeThumbRef = vue.ref();
  15035. function parseMouseMove(e) {
  15036. const vertical = props.direction === 'vertical';
  15037. const start = vertical ? 'top' : 'left';
  15038. const length = vertical ? 'height' : 'width';
  15039. const position = vertical ? 'clientY' : 'clientX';
  15040. const {
  15041. [start]: trackStart,
  15042. [length]: trackLength
  15043. } = trackContainerRef.value?.$el.getBoundingClientRect();
  15044. const clickOffset = getPosition(e, position);
  15045. // It is possible for left to be NaN, force to number
  15046. let clickPos = Math.min(Math.max((clickOffset - trackStart - startOffset.value) / trackLength, 0), 1) || 0;
  15047. if (vertical ? indexFromEnd.value : indexFromEnd.value !== isRtl.value) clickPos = 1 - clickPos;
  15048. return roundValue(min.value + clickPos * (max.value - min.value));
  15049. }
  15050. const handleStop = e => {
  15051. onSliderEnd({
  15052. value: parseMouseMove(e)
  15053. });
  15054. mousePressed.value = false;
  15055. startOffset.value = 0;
  15056. };
  15057. const handleStart = e => {
  15058. activeThumbRef.value = getActiveThumb(e);
  15059. if (!activeThumbRef.value) return;
  15060. activeThumbRef.value.focus();
  15061. mousePressed.value = true;
  15062. if (activeThumbRef.value.contains(e.target)) {
  15063. startOffset.value = getOffset(e, activeThumbRef.value, props.direction);
  15064. } else {
  15065. startOffset.value = 0;
  15066. onSliderMove({
  15067. value: parseMouseMove(e)
  15068. });
  15069. }
  15070. onSliderStart({
  15071. value: parseMouseMove(e)
  15072. });
  15073. };
  15074. const moveListenerOptions = {
  15075. passive: true,
  15076. capture: true
  15077. };
  15078. function onMouseMove(e) {
  15079. onSliderMove({
  15080. value: parseMouseMove(e)
  15081. });
  15082. }
  15083. function onSliderMouseUp(e) {
  15084. e.stopPropagation();
  15085. e.preventDefault();
  15086. handleStop(e);
  15087. window.removeEventListener('mousemove', onMouseMove, moveListenerOptions);
  15088. window.removeEventListener('mouseup', onSliderMouseUp);
  15089. }
  15090. function onSliderTouchend(e) {
  15091. handleStop(e);
  15092. window.removeEventListener('touchmove', onMouseMove, moveListenerOptions);
  15093. e.target?.removeEventListener('touchend', onSliderTouchend);
  15094. }
  15095. function onSliderTouchstart(e) {
  15096. handleStart(e);
  15097. window.addEventListener('touchmove', onMouseMove, moveListenerOptions);
  15098. e.target?.addEventListener('touchend', onSliderTouchend, {
  15099. passive: false
  15100. });
  15101. }
  15102. function onSliderMousedown(e) {
  15103. e.preventDefault();
  15104. handleStart(e);
  15105. window.addEventListener('mousemove', onMouseMove, moveListenerOptions);
  15106. window.addEventListener('mouseup', onSliderMouseUp, {
  15107. passive: false
  15108. });
  15109. }
  15110. const position = val => {
  15111. const percentage = (val - min.value) / (max.value - min.value) * 100;
  15112. return clamp(isNaN(percentage) ? 0 : percentage, 0, 100);
  15113. };
  15114. const showTicks = vue.toRef(props, 'showTicks');
  15115. const parsedTicks = vue.computed(() => {
  15116. if (!showTicks.value) return [];
  15117. if (!props.ticks) {
  15118. return numTicks.value !== Infinity ? createRange(numTicks.value + 1).map(t => {
  15119. const value = min.value + t * step.value;
  15120. return {
  15121. value,
  15122. position: position(value)
  15123. };
  15124. }) : [];
  15125. }
  15126. if (Array.isArray(props.ticks)) return props.ticks.map(t => ({
  15127. value: t,
  15128. position: position(t),
  15129. label: t.toString()
  15130. }));
  15131. return Object.keys(props.ticks).map(key => ({
  15132. value: parseFloat(key),
  15133. position: position(parseFloat(key)),
  15134. label: props.ticks[key]
  15135. }));
  15136. });
  15137. const hasLabels = vue.computed(() => parsedTicks.value.some(_ref2 => {
  15138. let {
  15139. label
  15140. } = _ref2;
  15141. return !!label;
  15142. }));
  15143. const data = {
  15144. activeThumbRef,
  15145. color: vue.toRef(props, 'color'),
  15146. decimals,
  15147. disabled,
  15148. direction: vue.toRef(props, 'direction'),
  15149. elevation: vue.toRef(props, 'elevation'),
  15150. hasLabels,
  15151. isReversed,
  15152. indexFromEnd,
  15153. min,
  15154. max,
  15155. mousePressed,
  15156. numTicks,
  15157. onSliderMousedown,
  15158. onSliderTouchstart,
  15159. parsedTicks,
  15160. parseMouseMove,
  15161. position,
  15162. readonly: vue.toRef(props, 'readonly'),
  15163. rounded: vue.toRef(props, 'rounded'),
  15164. roundValue,
  15165. showTicks,
  15166. startOffset,
  15167. step,
  15168. thumbSize,
  15169. thumbColor,
  15170. thumbLabel: vue.toRef(props, 'thumbLabel'),
  15171. ticks: vue.toRef(props, 'ticks'),
  15172. tickSize,
  15173. trackColor,
  15174. trackContainerRef,
  15175. trackFillColor,
  15176. trackSize,
  15177. vertical
  15178. };
  15179. vue.provide(VSliderSymbol, data);
  15180. return data;
  15181. };
  15182. // Types
  15183. const makeVSliderThumbProps = propsFactory({
  15184. focused: Boolean,
  15185. max: {
  15186. type: Number,
  15187. required: true
  15188. },
  15189. min: {
  15190. type: Number,
  15191. required: true
  15192. },
  15193. modelValue: {
  15194. type: Number,
  15195. required: true
  15196. },
  15197. position: {
  15198. type: Number,
  15199. required: true
  15200. },
  15201. ripple: {
  15202. type: [Boolean, Object],
  15203. default: true
  15204. },
  15205. name: String,
  15206. ...makeComponentProps()
  15207. }, 'VSliderThumb');
  15208. const VSliderThumb = genericComponent()({
  15209. name: 'VSliderThumb',
  15210. directives: {
  15211. Ripple
  15212. },
  15213. props: makeVSliderThumbProps(),
  15214. emits: {
  15215. 'update:modelValue': v => true
  15216. },
  15217. setup(props, _ref) {
  15218. let {
  15219. slots,
  15220. emit
  15221. } = _ref;
  15222. const slider = vue.inject(VSliderSymbol);
  15223. const {
  15224. isRtl,
  15225. rtlClasses
  15226. } = useRtl();
  15227. if (!slider) throw new Error('[Vuetify] v-slider-thumb must be used inside v-slider or v-range-slider');
  15228. const {
  15229. thumbColor,
  15230. step,
  15231. disabled,
  15232. thumbSize,
  15233. thumbLabel,
  15234. direction,
  15235. isReversed,
  15236. vertical,
  15237. readonly,
  15238. elevation,
  15239. mousePressed,
  15240. decimals,
  15241. indexFromEnd
  15242. } = slider;
  15243. const elevationProps = vue.computed(() => !disabled.value ? elevation.value : undefined);
  15244. const {
  15245. elevationClasses
  15246. } = useElevation(elevationProps);
  15247. const {
  15248. textColorClasses,
  15249. textColorStyles
  15250. } = useTextColor(thumbColor);
  15251. const {
  15252. pageup,
  15253. pagedown,
  15254. end,
  15255. home,
  15256. left,
  15257. right,
  15258. down,
  15259. up
  15260. } = keyValues;
  15261. const relevantKeys = [pageup, pagedown, end, home, left, right, down, up];
  15262. const multipliers = vue.computed(() => {
  15263. if (step.value) return [1, 2, 3];else return [1, 5, 10];
  15264. });
  15265. function parseKeydown(e, value) {
  15266. if (!relevantKeys.includes(e.key)) return;
  15267. e.preventDefault();
  15268. const _step = step.value || 0.1;
  15269. const steps = (props.max - props.min) / _step;
  15270. if ([left, right, down, up].includes(e.key)) {
  15271. const increase = vertical.value ? [isRtl.value ? left : right, isReversed.value ? down : up] : indexFromEnd.value !== isRtl.value ? [left, up] : [right, up];
  15272. const direction = increase.includes(e.key) ? 1 : -1;
  15273. const multiplier = e.shiftKey ? 2 : e.ctrlKey ? 1 : 0;
  15274. value = value + direction * _step * multipliers.value[multiplier];
  15275. } else if (e.key === home) {
  15276. value = props.min;
  15277. } else if (e.key === end) {
  15278. value = props.max;
  15279. } else {
  15280. const direction = e.key === pagedown ? 1 : -1;
  15281. value = value - direction * _step * (steps > 100 ? steps / 10 : 10);
  15282. }
  15283. return Math.max(props.min, Math.min(props.max, value));
  15284. }
  15285. function onKeydown(e) {
  15286. const newValue = parseKeydown(e, props.modelValue);
  15287. newValue != null && emit('update:modelValue', newValue);
  15288. }
  15289. useRender(() => {
  15290. const positionPercentage = convertToUnit(indexFromEnd.value ? 100 - props.position : props.position, '%');
  15291. return vue.createVNode("div", {
  15292. "class": ['v-slider-thumb', {
  15293. 'v-slider-thumb--focused': props.focused,
  15294. 'v-slider-thumb--pressed': props.focused && mousePressed.value
  15295. }, props.class, rtlClasses.value],
  15296. "style": [{
  15297. '--v-slider-thumb-position': positionPercentage,
  15298. '--v-slider-thumb-size': convertToUnit(thumbSize.value)
  15299. }, props.style],
  15300. "role": "slider",
  15301. "tabindex": disabled.value ? -1 : 0,
  15302. "aria-label": props.name,
  15303. "aria-valuemin": props.min,
  15304. "aria-valuemax": props.max,
  15305. "aria-valuenow": props.modelValue,
  15306. "aria-readonly": !!readonly.value,
  15307. "aria-orientation": direction.value,
  15308. "onKeydown": !readonly.value ? onKeydown : undefined
  15309. }, [vue.createVNode("div", {
  15310. "class": ['v-slider-thumb__surface', textColorClasses.value, elevationClasses.value],
  15311. "style": {
  15312. ...textColorStyles.value
  15313. }
  15314. }, null), vue.withDirectives(vue.createVNode("div", {
  15315. "class": ['v-slider-thumb__ripple', textColorClasses.value],
  15316. "style": textColorStyles.value
  15317. }, null), [[vue.resolveDirective("ripple"), props.ripple, null, {
  15318. circle: true,
  15319. center: true
  15320. }]]), vue.createVNode(VScaleTransition, {
  15321. "origin": "bottom center"
  15322. }, {
  15323. default: () => [vue.withDirectives(vue.createVNode("div", {
  15324. "class": "v-slider-thumb__label-container"
  15325. }, [vue.createVNode("div", {
  15326. "class": ['v-slider-thumb__label']
  15327. }, [vue.createVNode("div", null, [slots['thumb-label']?.({
  15328. modelValue: props.modelValue
  15329. }) ?? props.modelValue.toFixed(step.value ? decimals.value : 1)])])]), [[vue.vShow, thumbLabel.value && props.focused || thumbLabel.value === 'always']])]
  15330. })]);
  15331. });
  15332. return {};
  15333. }
  15334. });
  15335. // Types
  15336. const makeVSliderTrackProps = propsFactory({
  15337. start: {
  15338. type: Number,
  15339. required: true
  15340. },
  15341. stop: {
  15342. type: Number,
  15343. required: true
  15344. },
  15345. ...makeComponentProps()
  15346. }, 'VSliderTrack');
  15347. const VSliderTrack = genericComponent()({
  15348. name: 'VSliderTrack',
  15349. props: makeVSliderTrackProps(),
  15350. emits: {},
  15351. setup(props, _ref) {
  15352. let {
  15353. slots
  15354. } = _ref;
  15355. const slider = vue.inject(VSliderSymbol);
  15356. if (!slider) throw new Error('[Vuetify] v-slider-track must be inside v-slider or v-range-slider');
  15357. const {
  15358. color,
  15359. parsedTicks,
  15360. rounded,
  15361. showTicks,
  15362. tickSize,
  15363. trackColor,
  15364. trackFillColor,
  15365. trackSize,
  15366. vertical,
  15367. min,
  15368. max,
  15369. indexFromEnd
  15370. } = slider;
  15371. const {
  15372. roundedClasses
  15373. } = useRounded(rounded);
  15374. const {
  15375. backgroundColorClasses: trackFillColorClasses,
  15376. backgroundColorStyles: trackFillColorStyles
  15377. } = useBackgroundColor(trackFillColor);
  15378. const {
  15379. backgroundColorClasses: trackColorClasses,
  15380. backgroundColorStyles: trackColorStyles
  15381. } = useBackgroundColor(trackColor);
  15382. const startDir = vue.computed(() => `inset-${vertical.value ? 'block' : 'inline'}-${indexFromEnd.value ? 'end' : 'start'}`);
  15383. const endDir = vue.computed(() => vertical.value ? 'height' : 'width');
  15384. const backgroundStyles = vue.computed(() => {
  15385. return {
  15386. [startDir.value]: '0%',
  15387. [endDir.value]: '100%'
  15388. };
  15389. });
  15390. const trackFillWidth = vue.computed(() => props.stop - props.start);
  15391. const trackFillStyles = vue.computed(() => {
  15392. return {
  15393. [startDir.value]: convertToUnit(props.start, '%'),
  15394. [endDir.value]: convertToUnit(trackFillWidth.value, '%')
  15395. };
  15396. });
  15397. const computedTicks = vue.computed(() => {
  15398. if (!showTicks.value) return [];
  15399. const ticks = vertical.value ? parsedTicks.value.slice().reverse() : parsedTicks.value;
  15400. return ticks.map((tick, index) => {
  15401. const directionValue = tick.value !== min.value && tick.value !== max.value ? convertToUnit(tick.position, '%') : undefined;
  15402. return vue.createVNode("div", {
  15403. "key": tick.value,
  15404. "class": ['v-slider-track__tick', {
  15405. 'v-slider-track__tick--filled': tick.position >= props.start && tick.position <= props.stop,
  15406. 'v-slider-track__tick--first': tick.value === min.value,
  15407. 'v-slider-track__tick--last': tick.value === max.value
  15408. }],
  15409. "style": {
  15410. [startDir.value]: directionValue
  15411. }
  15412. }, [(tick.label || slots['tick-label']) && vue.createVNode("div", {
  15413. "class": "v-slider-track__tick-label"
  15414. }, [slots['tick-label']?.({
  15415. tick,
  15416. index
  15417. }) ?? tick.label])]);
  15418. });
  15419. });
  15420. useRender(() => {
  15421. return vue.createVNode("div", {
  15422. "class": ['v-slider-track', roundedClasses.value, props.class],
  15423. "style": [{
  15424. '--v-slider-track-size': convertToUnit(trackSize.value),
  15425. '--v-slider-tick-size': convertToUnit(tickSize.value)
  15426. }, props.style]
  15427. }, [vue.createVNode("div", {
  15428. "class": ['v-slider-track__background', trackColorClasses.value, {
  15429. 'v-slider-track__background--opacity': !!color.value || !trackFillColor.value
  15430. }],
  15431. "style": {
  15432. ...backgroundStyles.value,
  15433. ...trackColorStyles.value
  15434. }
  15435. }, null), vue.createVNode("div", {
  15436. "class": ['v-slider-track__fill', trackFillColorClasses.value],
  15437. "style": {
  15438. ...trackFillStyles.value,
  15439. ...trackFillColorStyles.value
  15440. }
  15441. }, null), showTicks.value && vue.createVNode("div", {
  15442. "class": ['v-slider-track__ticks', {
  15443. 'v-slider-track__ticks--always-show': showTicks.value === 'always'
  15444. }]
  15445. }, [computedTicks.value])]);
  15446. });
  15447. return {};
  15448. }
  15449. });
  15450. // Types
  15451. const makeVSliderProps = propsFactory({
  15452. ...makeFocusProps(),
  15453. ...makeSliderProps(),
  15454. ...makeVInputProps(),
  15455. modelValue: {
  15456. type: [Number, String],
  15457. default: 0
  15458. }
  15459. }, 'VSlider');
  15460. const VSlider = genericComponent()({
  15461. name: 'VSlider',
  15462. props: makeVSliderProps(),
  15463. emits: {
  15464. 'update:focused': value => true,
  15465. 'update:modelValue': v => true,
  15466. start: value => true,
  15467. end: value => true
  15468. },
  15469. setup(props, _ref) {
  15470. let {
  15471. slots,
  15472. emit
  15473. } = _ref;
  15474. const thumbContainerRef = vue.ref();
  15475. const {
  15476. rtlClasses
  15477. } = useRtl();
  15478. const steps = useSteps(props);
  15479. const model = useProxiedModel(props, 'modelValue', undefined, value => {
  15480. return steps.roundValue(value == null ? steps.min.value : value);
  15481. });
  15482. const {
  15483. min,
  15484. max,
  15485. mousePressed,
  15486. roundValue,
  15487. onSliderMousedown,
  15488. onSliderTouchstart,
  15489. trackContainerRef,
  15490. position,
  15491. hasLabels,
  15492. readonly
  15493. } = useSlider({
  15494. props,
  15495. steps,
  15496. onSliderStart: () => {
  15497. emit('start', model.value);
  15498. },
  15499. onSliderEnd: _ref2 => {
  15500. let {
  15501. value
  15502. } = _ref2;
  15503. const roundedValue = roundValue(value);
  15504. model.value = roundedValue;
  15505. emit('end', roundedValue);
  15506. },
  15507. onSliderMove: _ref3 => {
  15508. let {
  15509. value
  15510. } = _ref3;
  15511. return model.value = roundValue(value);
  15512. },
  15513. getActiveThumb: () => thumbContainerRef.value?.$el
  15514. });
  15515. const {
  15516. isFocused,
  15517. focus,
  15518. blur
  15519. } = useFocus(props);
  15520. const trackStop = vue.computed(() => position(model.value));
  15521. useRender(() => {
  15522. const inputProps = VInput.filterProps(props);
  15523. const hasPrepend = !!(props.label || slots.label || slots.prepend);
  15524. return vue.createVNode(VInput, vue.mergeProps({
  15525. "class": ['v-slider', {
  15526. 'v-slider--has-labels': !!slots['tick-label'] || hasLabels.value,
  15527. 'v-slider--focused': isFocused.value,
  15528. 'v-slider--pressed': mousePressed.value,
  15529. 'v-slider--disabled': props.disabled
  15530. }, rtlClasses.value, props.class],
  15531. "style": props.style
  15532. }, inputProps, {
  15533. "focused": isFocused.value
  15534. }), {
  15535. ...slots,
  15536. prepend: hasPrepend ? slotProps => vue.createVNode(vue.Fragment, null, [slots.label?.(slotProps) ?? (props.label ? vue.createVNode(VLabel, {
  15537. "id": slotProps.id.value,
  15538. "class": "v-slider__label",
  15539. "text": props.label
  15540. }, null) : undefined), slots.prepend?.(slotProps)]) : undefined,
  15541. default: _ref4 => {
  15542. let {
  15543. id,
  15544. messagesId
  15545. } = _ref4;
  15546. return vue.createVNode("div", {
  15547. "class": "v-slider__container",
  15548. "onMousedown": !readonly.value ? onSliderMousedown : undefined,
  15549. "onTouchstartPassive": !readonly.value ? onSliderTouchstart : undefined
  15550. }, [vue.createVNode("input", {
  15551. "id": id.value,
  15552. "name": props.name || id.value,
  15553. "disabled": !!props.disabled,
  15554. "readonly": !!props.readonly,
  15555. "tabindex": "-1",
  15556. "value": model.value
  15557. }, null), vue.createVNode(VSliderTrack, {
  15558. "ref": trackContainerRef,
  15559. "start": 0,
  15560. "stop": trackStop.value
  15561. }, {
  15562. 'tick-label': slots['tick-label']
  15563. }), vue.createVNode(VSliderThumb, {
  15564. "ref": thumbContainerRef,
  15565. "aria-describedby": messagesId.value,
  15566. "focused": isFocused.value,
  15567. "min": min.value,
  15568. "max": max.value,
  15569. "modelValue": model.value,
  15570. "onUpdate:modelValue": v => model.value = v,
  15571. "position": trackStop.value,
  15572. "elevation": props.elevation,
  15573. "onFocus": focus,
  15574. "onBlur": blur,
  15575. "ripple": props.ripple,
  15576. "name": props.name
  15577. }, {
  15578. 'thumb-label': slots['thumb-label']
  15579. })]);
  15580. }
  15581. });
  15582. });
  15583. return {};
  15584. }
  15585. });
  15586. // Types
  15587. const makeVColorPickerPreviewProps = propsFactory({
  15588. color: {
  15589. type: Object
  15590. },
  15591. disabled: Boolean,
  15592. hideAlpha: Boolean,
  15593. ...makeComponentProps()
  15594. }, 'VColorPickerPreview');
  15595. const VColorPickerPreview = defineComponent({
  15596. name: 'VColorPickerPreview',
  15597. props: makeVColorPickerPreviewProps(),
  15598. emits: {
  15599. 'update:color': color => true
  15600. },
  15601. setup(props, _ref) {
  15602. let {
  15603. emit
  15604. } = _ref;
  15605. const abortController = new AbortController();
  15606. vue.onUnmounted(() => abortController.abort());
  15607. async function openEyeDropper() {
  15608. if (!SUPPORTS_EYE_DROPPER) return;
  15609. const eyeDropper = new window.EyeDropper();
  15610. try {
  15611. const result = await eyeDropper.open({
  15612. signal: abortController.signal
  15613. });
  15614. const colorHexValue = HexToHSV(result.sRGBHex);
  15615. emit('update:color', {
  15616. ...(props.color ?? nullColor),
  15617. ...colorHexValue
  15618. });
  15619. } catch (e) {}
  15620. }
  15621. useRender(() => vue.createVNode("div", {
  15622. "class": ['v-color-picker-preview', {
  15623. 'v-color-picker-preview--hide-alpha': props.hideAlpha
  15624. }, props.class],
  15625. "style": props.style
  15626. }, [SUPPORTS_EYE_DROPPER && vue.createVNode("div", {
  15627. "class": "v-color-picker-preview__eye-dropper",
  15628. "key": "eyeDropper"
  15629. }, [vue.createVNode(VBtn, {
  15630. "onClick": openEyeDropper,
  15631. "icon": "$eyeDropper",
  15632. "variant": "plain",
  15633. "density": "comfortable"
  15634. }, null)]), vue.createVNode("div", {
  15635. "class": "v-color-picker-preview__dot"
  15636. }, [vue.createVNode("div", {
  15637. "style": {
  15638. background: HSVtoCSS(props.color ?? nullColor)
  15639. }
  15640. }, null)]), vue.createVNode("div", {
  15641. "class": "v-color-picker-preview__sliders"
  15642. }, [vue.createVNode(VSlider, {
  15643. "class": "v-color-picker-preview__track v-color-picker-preview__hue",
  15644. "modelValue": props.color?.h,
  15645. "onUpdate:modelValue": h => emit('update:color', {
  15646. ...(props.color ?? nullColor),
  15647. h
  15648. }),
  15649. "step": 0,
  15650. "min": 0,
  15651. "max": 360,
  15652. "disabled": props.disabled,
  15653. "thumbSize": 14,
  15654. "trackSize": 8,
  15655. "trackFillColor": "white",
  15656. "hideDetails": true
  15657. }, null), !props.hideAlpha && vue.createVNode(VSlider, {
  15658. "class": "v-color-picker-preview__track v-color-picker-preview__alpha",
  15659. "modelValue": props.color?.a ?? 1,
  15660. "onUpdate:modelValue": a => emit('update:color', {
  15661. ...(props.color ?? nullColor),
  15662. a
  15663. }),
  15664. "step": 1 / 256,
  15665. "min": 0,
  15666. "max": 1,
  15667. "disabled": props.disabled,
  15668. "thumbSize": 14,
  15669. "trackSize": 8,
  15670. "trackFillColor": "white",
  15671. "hideDetails": true
  15672. }, null)])]));
  15673. return {};
  15674. }
  15675. });
  15676. const red = {
  15677. base: '#f44336',
  15678. lighten5: '#ffebee',
  15679. lighten4: '#ffcdd2',
  15680. lighten3: '#ef9a9a',
  15681. lighten2: '#e57373',
  15682. lighten1: '#ef5350',
  15683. darken1: '#e53935',
  15684. darken2: '#d32f2f',
  15685. darken3: '#c62828',
  15686. darken4: '#b71c1c',
  15687. accent1: '#ff8a80',
  15688. accent2: '#ff5252',
  15689. accent3: '#ff1744',
  15690. accent4: '#d50000'
  15691. };
  15692. const pink = {
  15693. base: '#e91e63',
  15694. lighten5: '#fce4ec',
  15695. lighten4: '#f8bbd0',
  15696. lighten3: '#f48fb1',
  15697. lighten2: '#f06292',
  15698. lighten1: '#ec407a',
  15699. darken1: '#d81b60',
  15700. darken2: '#c2185b',
  15701. darken3: '#ad1457',
  15702. darken4: '#880e4f',
  15703. accent1: '#ff80ab',
  15704. accent2: '#ff4081',
  15705. accent3: '#f50057',
  15706. accent4: '#c51162'
  15707. };
  15708. const purple = {
  15709. base: '#9c27b0',
  15710. lighten5: '#f3e5f5',
  15711. lighten4: '#e1bee7',
  15712. lighten3: '#ce93d8',
  15713. lighten2: '#ba68c8',
  15714. lighten1: '#ab47bc',
  15715. darken1: '#8e24aa',
  15716. darken2: '#7b1fa2',
  15717. darken3: '#6a1b9a',
  15718. darken4: '#4a148c',
  15719. accent1: '#ea80fc',
  15720. accent2: '#e040fb',
  15721. accent3: '#d500f9',
  15722. accent4: '#aa00ff'
  15723. };
  15724. const deepPurple = {
  15725. base: '#673ab7',
  15726. lighten5: '#ede7f6',
  15727. lighten4: '#d1c4e9',
  15728. lighten3: '#b39ddb',
  15729. lighten2: '#9575cd',
  15730. lighten1: '#7e57c2',
  15731. darken1: '#5e35b1',
  15732. darken2: '#512da8',
  15733. darken3: '#4527a0',
  15734. darken4: '#311b92',
  15735. accent1: '#b388ff',
  15736. accent2: '#7c4dff',
  15737. accent3: '#651fff',
  15738. accent4: '#6200ea'
  15739. };
  15740. const indigo = {
  15741. base: '#3f51b5',
  15742. lighten5: '#e8eaf6',
  15743. lighten4: '#c5cae9',
  15744. lighten3: '#9fa8da',
  15745. lighten2: '#7986cb',
  15746. lighten1: '#5c6bc0',
  15747. darken1: '#3949ab',
  15748. darken2: '#303f9f',
  15749. darken3: '#283593',
  15750. darken4: '#1a237e',
  15751. accent1: '#8c9eff',
  15752. accent2: '#536dfe',
  15753. accent3: '#3d5afe',
  15754. accent4: '#304ffe'
  15755. };
  15756. const blue = {
  15757. base: '#2196f3',
  15758. lighten5: '#e3f2fd',
  15759. lighten4: '#bbdefb',
  15760. lighten3: '#90caf9',
  15761. lighten2: '#64b5f6',
  15762. lighten1: '#42a5f5',
  15763. darken1: '#1e88e5',
  15764. darken2: '#1976d2',
  15765. darken3: '#1565c0',
  15766. darken4: '#0d47a1',
  15767. accent1: '#82b1ff',
  15768. accent2: '#448aff',
  15769. accent3: '#2979ff',
  15770. accent4: '#2962ff'
  15771. };
  15772. const lightBlue = {
  15773. base: '#03a9f4',
  15774. lighten5: '#e1f5fe',
  15775. lighten4: '#b3e5fc',
  15776. lighten3: '#81d4fa',
  15777. lighten2: '#4fc3f7',
  15778. lighten1: '#29b6f6',
  15779. darken1: '#039be5',
  15780. darken2: '#0288d1',
  15781. darken3: '#0277bd',
  15782. darken4: '#01579b',
  15783. accent1: '#80d8ff',
  15784. accent2: '#40c4ff',
  15785. accent3: '#00b0ff',
  15786. accent4: '#0091ea'
  15787. };
  15788. const cyan = {
  15789. base: '#00bcd4',
  15790. lighten5: '#e0f7fa',
  15791. lighten4: '#b2ebf2',
  15792. lighten3: '#80deea',
  15793. lighten2: '#4dd0e1',
  15794. lighten1: '#26c6da',
  15795. darken1: '#00acc1',
  15796. darken2: '#0097a7',
  15797. darken3: '#00838f',
  15798. darken4: '#006064',
  15799. accent1: '#84ffff',
  15800. accent2: '#18ffff',
  15801. accent3: '#00e5ff',
  15802. accent4: '#00b8d4'
  15803. };
  15804. const teal = {
  15805. base: '#009688',
  15806. lighten5: '#e0f2f1',
  15807. lighten4: '#b2dfdb',
  15808. lighten3: '#80cbc4',
  15809. lighten2: '#4db6ac',
  15810. lighten1: '#26a69a',
  15811. darken1: '#00897b',
  15812. darken2: '#00796b',
  15813. darken3: '#00695c',
  15814. darken4: '#004d40',
  15815. accent1: '#a7ffeb',
  15816. accent2: '#64ffda',
  15817. accent3: '#1de9b6',
  15818. accent4: '#00bfa5'
  15819. };
  15820. const green = {
  15821. base: '#4caf50',
  15822. lighten5: '#e8f5e9',
  15823. lighten4: '#c8e6c9',
  15824. lighten3: '#a5d6a7',
  15825. lighten2: '#81c784',
  15826. lighten1: '#66bb6a',
  15827. darken1: '#43a047',
  15828. darken2: '#388e3c',
  15829. darken3: '#2e7d32',
  15830. darken4: '#1b5e20',
  15831. accent1: '#b9f6ca',
  15832. accent2: '#69f0ae',
  15833. accent3: '#00e676',
  15834. accent4: '#00c853'
  15835. };
  15836. const lightGreen = {
  15837. base: '#8bc34a',
  15838. lighten5: '#f1f8e9',
  15839. lighten4: '#dcedc8',
  15840. lighten3: '#c5e1a5',
  15841. lighten2: '#aed581',
  15842. lighten1: '#9ccc65',
  15843. darken1: '#7cb342',
  15844. darken2: '#689f38',
  15845. darken3: '#558b2f',
  15846. darken4: '#33691e',
  15847. accent1: '#ccff90',
  15848. accent2: '#b2ff59',
  15849. accent3: '#76ff03',
  15850. accent4: '#64dd17'
  15851. };
  15852. const lime = {
  15853. base: '#cddc39',
  15854. lighten5: '#f9fbe7',
  15855. lighten4: '#f0f4c3',
  15856. lighten3: '#e6ee9c',
  15857. lighten2: '#dce775',
  15858. lighten1: '#d4e157',
  15859. darken1: '#c0ca33',
  15860. darken2: '#afb42b',
  15861. darken3: '#9e9d24',
  15862. darken4: '#827717',
  15863. accent1: '#f4ff81',
  15864. accent2: '#eeff41',
  15865. accent3: '#c6ff00',
  15866. accent4: '#aeea00'
  15867. };
  15868. const yellow = {
  15869. base: '#ffeb3b',
  15870. lighten5: '#fffde7',
  15871. lighten4: '#fff9c4',
  15872. lighten3: '#fff59d',
  15873. lighten2: '#fff176',
  15874. lighten1: '#ffee58',
  15875. darken1: '#fdd835',
  15876. darken2: '#fbc02d',
  15877. darken3: '#f9a825',
  15878. darken4: '#f57f17',
  15879. accent1: '#ffff8d',
  15880. accent2: '#ffff00',
  15881. accent3: '#ffea00',
  15882. accent4: '#ffd600'
  15883. };
  15884. const amber = {
  15885. base: '#ffc107',
  15886. lighten5: '#fff8e1',
  15887. lighten4: '#ffecb3',
  15888. lighten3: '#ffe082',
  15889. lighten2: '#ffd54f',
  15890. lighten1: '#ffca28',
  15891. darken1: '#ffb300',
  15892. darken2: '#ffa000',
  15893. darken3: '#ff8f00',
  15894. darken4: '#ff6f00',
  15895. accent1: '#ffe57f',
  15896. accent2: '#ffd740',
  15897. accent3: '#ffc400',
  15898. accent4: '#ffab00'
  15899. };
  15900. const orange = {
  15901. base: '#ff9800',
  15902. lighten5: '#fff3e0',
  15903. lighten4: '#ffe0b2',
  15904. lighten3: '#ffcc80',
  15905. lighten2: '#ffb74d',
  15906. lighten1: '#ffa726',
  15907. darken1: '#fb8c00',
  15908. darken2: '#f57c00',
  15909. darken3: '#ef6c00',
  15910. darken4: '#e65100',
  15911. accent1: '#ffd180',
  15912. accent2: '#ffab40',
  15913. accent3: '#ff9100',
  15914. accent4: '#ff6d00'
  15915. };
  15916. const deepOrange = {
  15917. base: '#ff5722',
  15918. lighten5: '#fbe9e7',
  15919. lighten4: '#ffccbc',
  15920. lighten3: '#ffab91',
  15921. lighten2: '#ff8a65',
  15922. lighten1: '#ff7043',
  15923. darken1: '#f4511e',
  15924. darken2: '#e64a19',
  15925. darken3: '#d84315',
  15926. darken4: '#bf360c',
  15927. accent1: '#ff9e80',
  15928. accent2: '#ff6e40',
  15929. accent3: '#ff3d00',
  15930. accent4: '#dd2c00'
  15931. };
  15932. const brown = {
  15933. base: '#795548',
  15934. lighten5: '#efebe9',
  15935. lighten4: '#d7ccc8',
  15936. lighten3: '#bcaaa4',
  15937. lighten2: '#a1887f',
  15938. lighten1: '#8d6e63',
  15939. darken1: '#6d4c41',
  15940. darken2: '#5d4037',
  15941. darken3: '#4e342e',
  15942. darken4: '#3e2723'
  15943. };
  15944. const blueGrey = {
  15945. base: '#607d8b',
  15946. lighten5: '#eceff1',
  15947. lighten4: '#cfd8dc',
  15948. lighten3: '#b0bec5',
  15949. lighten2: '#90a4ae',
  15950. lighten1: '#78909c',
  15951. darken1: '#546e7a',
  15952. darken2: '#455a64',
  15953. darken3: '#37474f',
  15954. darken4: '#263238'
  15955. };
  15956. const grey = {
  15957. base: '#9e9e9e',
  15958. lighten5: '#fafafa',
  15959. lighten4: '#f5f5f5',
  15960. lighten3: '#eeeeee',
  15961. lighten2: '#e0e0e0',
  15962. lighten1: '#bdbdbd',
  15963. darken1: '#757575',
  15964. darken2: '#616161',
  15965. darken3: '#424242',
  15966. darken4: '#212121'
  15967. };
  15968. const shades = {
  15969. black: '#000000',
  15970. white: '#ffffff',
  15971. transparent: '#ffffff00'
  15972. };
  15973. var colors = {
  15974. red,
  15975. pink,
  15976. purple,
  15977. deepPurple,
  15978. indigo,
  15979. blue,
  15980. lightBlue,
  15981. cyan,
  15982. teal,
  15983. green,
  15984. lightGreen,
  15985. lime,
  15986. yellow,
  15987. amber,
  15988. orange,
  15989. deepOrange,
  15990. brown,
  15991. blueGrey,
  15992. grey,
  15993. shades
  15994. };
  15995. // Types
  15996. const makeVColorPickerSwatchesProps = propsFactory({
  15997. swatches: {
  15998. type: Array,
  15999. default: () => parseDefaultColors(colors)
  16000. },
  16001. disabled: Boolean,
  16002. color: Object,
  16003. maxHeight: [Number, String],
  16004. ...makeComponentProps()
  16005. }, 'VColorPickerSwatches');
  16006. function parseDefaultColors(colors) {
  16007. return Object.keys(colors).map(key => {
  16008. const color = colors[key];
  16009. 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];
  16010. });
  16011. }
  16012. const VColorPickerSwatches = defineComponent({
  16013. name: 'VColorPickerSwatches',
  16014. props: makeVColorPickerSwatchesProps(),
  16015. emits: {
  16016. 'update:color': color => true
  16017. },
  16018. setup(props, _ref) {
  16019. let {
  16020. emit
  16021. } = _ref;
  16022. useRender(() => vue.createVNode("div", {
  16023. "class": ['v-color-picker-swatches', props.class],
  16024. "style": [{
  16025. maxHeight: convertToUnit(props.maxHeight)
  16026. }, props.style]
  16027. }, [vue.createVNode("div", null, [props.swatches.map(swatch => vue.createVNode("div", {
  16028. "class": "v-color-picker-swatches__swatch"
  16029. }, [swatch.map(color => {
  16030. const rgba = parseColor(color);
  16031. const hsva = RGBtoHSV(rgba);
  16032. const background = RGBtoCSS(rgba);
  16033. return vue.createVNode("div", {
  16034. "class": "v-color-picker-swatches__color",
  16035. "onClick": () => hsva && emit('update:color', hsva)
  16036. }, [vue.createVNode("div", {
  16037. "style": {
  16038. background
  16039. }
  16040. }, [props.color && deepEqual(props.color, hsva) ? vue.createVNode(VIcon, {
  16041. "size": "x-small",
  16042. "icon": "$success",
  16043. "color": getContrast(color, '#FFFFFF') > 2 ? 'white' : 'black'
  16044. }, null) : undefined])]);
  16045. })]))])]));
  16046. return {};
  16047. }
  16048. });
  16049. const makeVSheetProps = propsFactory({
  16050. color: String,
  16051. ...makeBorderProps(),
  16052. ...makeComponentProps(),
  16053. ...makeDimensionProps(),
  16054. ...makeElevationProps(),
  16055. ...makeLocationProps(),
  16056. ...makePositionProps(),
  16057. ...makeRoundedProps(),
  16058. ...makeTagProps(),
  16059. ...makeThemeProps()
  16060. }, 'VSheet');
  16061. const VSheet = genericComponent()({
  16062. name: 'VSheet',
  16063. props: makeVSheetProps(),
  16064. setup(props, _ref) {
  16065. let {
  16066. slots
  16067. } = _ref;
  16068. const {
  16069. themeClasses
  16070. } = provideTheme(props);
  16071. const {
  16072. backgroundColorClasses,
  16073. backgroundColorStyles
  16074. } = useBackgroundColor(vue.toRef(props, 'color'));
  16075. const {
  16076. borderClasses
  16077. } = useBorder(props);
  16078. const {
  16079. dimensionStyles
  16080. } = useDimension(props);
  16081. const {
  16082. elevationClasses
  16083. } = useElevation(props);
  16084. const {
  16085. locationStyles
  16086. } = useLocation(props);
  16087. const {
  16088. positionClasses
  16089. } = usePosition(props);
  16090. const {
  16091. roundedClasses
  16092. } = useRounded(props);
  16093. useRender(() => vue.createVNode(props.tag, {
  16094. "class": ['v-sheet', themeClasses.value, backgroundColorClasses.value, borderClasses.value, elevationClasses.value, positionClasses.value, roundedClasses.value, props.class],
  16095. "style": [backgroundColorStyles.value, dimensionStyles.value, locationStyles.value, props.style]
  16096. }, slots));
  16097. return {};
  16098. }
  16099. });
  16100. // Types
  16101. const makeVColorPickerProps = propsFactory({
  16102. canvasHeight: {
  16103. type: [String, Number],
  16104. default: 150
  16105. },
  16106. disabled: Boolean,
  16107. dotSize: {
  16108. type: [Number, String],
  16109. default: 10
  16110. },
  16111. hideCanvas: Boolean,
  16112. hideSliders: Boolean,
  16113. hideInputs: Boolean,
  16114. mode: {
  16115. type: String,
  16116. default: 'rgba',
  16117. validator: v => Object.keys(modes).includes(v)
  16118. },
  16119. modes: {
  16120. type: Array,
  16121. default: () => Object.keys(modes),
  16122. validator: v => Array.isArray(v) && v.every(m => Object.keys(modes).includes(m))
  16123. },
  16124. showSwatches: Boolean,
  16125. swatches: Array,
  16126. swatchesMaxHeight: {
  16127. type: [Number, String],
  16128. default: 150
  16129. },
  16130. modelValue: {
  16131. type: [Object, String]
  16132. },
  16133. ...omit(makeVSheetProps({
  16134. width: 300
  16135. }), ['height', 'location', 'minHeight', 'maxHeight', 'minWidth', 'maxWidth'])
  16136. }, 'VColorPicker');
  16137. const VColorPicker = defineComponent({
  16138. name: 'VColorPicker',
  16139. props: makeVColorPickerProps(),
  16140. emits: {
  16141. 'update:modelValue': color => true,
  16142. 'update:mode': mode => true
  16143. },
  16144. setup(props) {
  16145. const mode = useProxiedModel(props, 'mode');
  16146. const hue = vue.ref(null);
  16147. const model = useProxiedModel(props, 'modelValue', undefined, v => {
  16148. if (v == null || v === '') return null;
  16149. let c;
  16150. try {
  16151. c = RGBtoHSV(parseColor(v));
  16152. } catch (err) {
  16153. consoleWarn(err);
  16154. return null;
  16155. }
  16156. return c;
  16157. }, v => {
  16158. if (!v) return null;
  16159. return extractColor(v, props.modelValue);
  16160. });
  16161. const currentColor = vue.computed(() => {
  16162. return model.value ? {
  16163. ...model.value,
  16164. h: hue.value ?? model.value.h
  16165. } : null;
  16166. });
  16167. const {
  16168. rtlClasses
  16169. } = useRtl();
  16170. let externalChange = true;
  16171. vue.watch(model, v => {
  16172. if (!externalChange) {
  16173. // prevent hue shift from rgb conversion inaccuracy
  16174. externalChange = true;
  16175. return;
  16176. }
  16177. if (!v) return;
  16178. hue.value = v.h;
  16179. }, {
  16180. immediate: true
  16181. });
  16182. const updateColor = hsva => {
  16183. externalChange = false;
  16184. hue.value = hsva.h;
  16185. model.value = hsva;
  16186. };
  16187. vue.onBeforeMount(() => {
  16188. if (!props.modes.includes(mode.value)) mode.value = props.modes[0];
  16189. });
  16190. provideDefaults({
  16191. VSlider: {
  16192. color: undefined,
  16193. trackColor: undefined,
  16194. trackFillColor: undefined
  16195. }
  16196. });
  16197. useRender(() => {
  16198. const sheetProps = VSheet.filterProps(props);
  16199. return vue.createVNode(VSheet, vue.mergeProps({
  16200. "rounded": props.rounded,
  16201. "elevation": props.elevation,
  16202. "theme": props.theme,
  16203. "class": ['v-color-picker', rtlClasses.value, props.class],
  16204. "style": [{
  16205. '--v-color-picker-color-hsv': HSVtoCSS({
  16206. ...(currentColor.value ?? nullColor),
  16207. a: 1
  16208. })
  16209. }, props.style]
  16210. }, sheetProps, {
  16211. "maxWidth": props.width
  16212. }), {
  16213. default: () => [!props.hideCanvas && vue.createVNode(VColorPickerCanvas, {
  16214. "key": "canvas",
  16215. "color": currentColor.value,
  16216. "onUpdate:color": updateColor,
  16217. "disabled": props.disabled,
  16218. "dotSize": props.dotSize,
  16219. "width": props.width,
  16220. "height": props.canvasHeight
  16221. }, null), (!props.hideSliders || !props.hideInputs) && vue.createVNode("div", {
  16222. "key": "controls",
  16223. "class": "v-color-picker__controls"
  16224. }, [!props.hideSliders && vue.createVNode(VColorPickerPreview, {
  16225. "key": "preview",
  16226. "color": currentColor.value,
  16227. "onUpdate:color": updateColor,
  16228. "hideAlpha": !mode.value.endsWith('a'),
  16229. "disabled": props.disabled
  16230. }, null), !props.hideInputs && vue.createVNode(VColorPickerEdit, {
  16231. "key": "edit",
  16232. "modes": props.modes,
  16233. "mode": mode.value,
  16234. "onUpdate:mode": m => mode.value = m,
  16235. "color": currentColor.value,
  16236. "onUpdate:color": updateColor,
  16237. "disabled": props.disabled
  16238. }, null)]), props.showSwatches && vue.createVNode(VColorPickerSwatches, {
  16239. "key": "swatches",
  16240. "color": currentColor.value,
  16241. "onUpdate:color": updateColor,
  16242. "maxHeight": props.swatchesMaxHeight,
  16243. "swatches": props.swatches,
  16244. "disabled": props.disabled
  16245. }, null)]
  16246. });
  16247. });
  16248. return {};
  16249. }
  16250. });
  16251. // Types
  16252. function highlightResult(text, matches, length) {
  16253. if (matches == null) return text;
  16254. if (Array.isArray(matches)) throw new Error('Multiple matches is not implemented');
  16255. return typeof matches === 'number' && ~matches ? vue.createVNode(vue.Fragment, null, [vue.createVNode("span", {
  16256. "class": "v-combobox__unmask"
  16257. }, [text.substr(0, matches)]), vue.createVNode("span", {
  16258. "class": "v-combobox__mask"
  16259. }, [text.substr(matches, length)]), vue.createVNode("span", {
  16260. "class": "v-combobox__unmask"
  16261. }, [text.substr(matches + length)])]) : text;
  16262. }
  16263. const makeVComboboxProps = propsFactory({
  16264. autoSelectFirst: {
  16265. type: [Boolean, String]
  16266. },
  16267. clearOnSelect: {
  16268. type: Boolean,
  16269. default: true
  16270. },
  16271. delimiters: Array,
  16272. ...makeFilterProps({
  16273. filterKeys: ['title']
  16274. }),
  16275. ...makeSelectProps({
  16276. hideNoData: true,
  16277. returnObject: true
  16278. }),
  16279. ...omit(makeVTextFieldProps({
  16280. modelValue: null,
  16281. role: 'combobox'
  16282. }), ['validationValue', 'dirty', 'appendInnerIcon']),
  16283. ...makeTransitionProps({
  16284. transition: false
  16285. })
  16286. }, 'VCombobox');
  16287. const VCombobox = genericComponent()({
  16288. name: 'VCombobox',
  16289. props: makeVComboboxProps(),
  16290. emits: {
  16291. 'update:focused': focused => true,
  16292. 'update:modelValue': value => true,
  16293. 'update:search': value => true,
  16294. 'update:menu': value => true
  16295. },
  16296. setup(props, _ref) {
  16297. let {
  16298. emit,
  16299. slots
  16300. } = _ref;
  16301. const {
  16302. t
  16303. } = useLocale();
  16304. const vTextFieldRef = vue.ref();
  16305. const isFocused = vue.shallowRef(false);
  16306. const isPristine = vue.shallowRef(true);
  16307. const listHasFocus = vue.shallowRef(false);
  16308. const vMenuRef = vue.ref();
  16309. const vVirtualScrollRef = vue.ref();
  16310. const _menu = useProxiedModel(props, 'menu');
  16311. const menu = vue.computed({
  16312. get: () => _menu.value,
  16313. set: v => {
  16314. if (_menu.value && !v && vMenuRef.value?.ΨopenChildren.size) return;
  16315. _menu.value = v;
  16316. }
  16317. });
  16318. const selectionIndex = vue.shallowRef(-1);
  16319. let cleared = false;
  16320. const color = vue.computed(() => vTextFieldRef.value?.color);
  16321. const label = vue.computed(() => menu.value ? props.closeText : props.openText);
  16322. const {
  16323. items,
  16324. transformIn,
  16325. transformOut
  16326. } = useItems(props);
  16327. const {
  16328. textColorClasses,
  16329. textColorStyles
  16330. } = useTextColor(color);
  16331. const model = useProxiedModel(props, 'modelValue', [], v => transformIn(wrapInArray(v)), v => {
  16332. const transformed = transformOut(v);
  16333. return props.multiple ? transformed : transformed[0] ?? null;
  16334. });
  16335. const form = useForm(props);
  16336. const hasChips = vue.computed(() => !!(props.chips || slots.chip));
  16337. const hasSelectionSlot = vue.computed(() => hasChips.value || !!slots.selection);
  16338. const _search = vue.shallowRef(!props.multiple && !hasSelectionSlot.value ? model.value[0]?.title ?? '' : '');
  16339. const search = vue.computed({
  16340. get: () => {
  16341. return _search.value;
  16342. },
  16343. set: val => {
  16344. _search.value = val ?? '';
  16345. if (!props.multiple && !hasSelectionSlot.value) {
  16346. model.value = [transformItem$3(props, val)];
  16347. }
  16348. if (val && props.multiple && props.delimiters?.length) {
  16349. const values = val.split(new RegExp(`(?:${props.delimiters.join('|')})+`));
  16350. if (values.length > 1) {
  16351. values.forEach(v => {
  16352. v = v.trim();
  16353. if (v) select(transformItem$3(props, v));
  16354. });
  16355. _search.value = '';
  16356. }
  16357. }
  16358. if (!val) selectionIndex.value = -1;
  16359. isPristine.value = !val;
  16360. }
  16361. });
  16362. const counterValue = vue.computed(() => {
  16363. return typeof props.counterValue === 'function' ? props.counterValue(model.value) : typeof props.counterValue === 'number' ? props.counterValue : props.multiple ? model.value.length : search.value.length;
  16364. });
  16365. vue.watch(_search, value => {
  16366. if (cleared) {
  16367. // wait for clear to finish, VTextField sets _search to null
  16368. // then search computed triggers and updates _search to ''
  16369. vue.nextTick(() => cleared = false);
  16370. } else if (isFocused.value && !menu.value) {
  16371. menu.value = true;
  16372. }
  16373. emit('update:search', value);
  16374. });
  16375. vue.watch(model, value => {
  16376. if (!props.multiple && !hasSelectionSlot.value) {
  16377. _search.value = value[0]?.title ?? '';
  16378. }
  16379. });
  16380. const {
  16381. filteredItems,
  16382. getMatches
  16383. } = useFilter(props, items, () => isPristine.value ? '' : search.value);
  16384. const displayItems = vue.computed(() => {
  16385. if (props.hideSelected) {
  16386. return filteredItems.value.filter(filteredItem => !model.value.some(s => s.value === filteredItem.value));
  16387. }
  16388. return filteredItems.value;
  16389. });
  16390. const selectedValues = vue.computed(() => model.value.map(selection => selection.value));
  16391. const highlightFirst = vue.computed(() => {
  16392. const selectFirst = props.autoSelectFirst === true || props.autoSelectFirst === 'exact' && search.value === displayItems.value[0]?.title;
  16393. return selectFirst && displayItems.value.length > 0 && !isPristine.value && !listHasFocus.value;
  16394. });
  16395. const menuDisabled = vue.computed(() => props.hideNoData && !displayItems.value.length || form.isReadonly.value || form.isDisabled.value);
  16396. const listRef = vue.ref();
  16397. const listEvents = useScrolling(listRef, vTextFieldRef);
  16398. function onClear(e) {
  16399. cleared = true;
  16400. if (props.openOnClear) {
  16401. menu.value = true;
  16402. }
  16403. }
  16404. function onMousedownControl() {
  16405. if (menuDisabled.value) return;
  16406. menu.value = true;
  16407. }
  16408. function onMousedownMenuIcon(e) {
  16409. if (menuDisabled.value) return;
  16410. if (isFocused.value) {
  16411. e.preventDefault();
  16412. e.stopPropagation();
  16413. }
  16414. menu.value = !menu.value;
  16415. }
  16416. function onListKeydown(e) {
  16417. if (checkPrintable(e)) {
  16418. vTextFieldRef.value?.focus();
  16419. }
  16420. }
  16421. // eslint-disable-next-line complexity
  16422. function onKeydown(e) {
  16423. if (isComposingIgnoreKey(e) || form.isReadonly.value) return;
  16424. const selectionStart = vTextFieldRef.value.selectionStart;
  16425. const length = model.value.length;
  16426. if (selectionIndex.value > -1 || ['Enter', 'ArrowDown', 'ArrowUp'].includes(e.key)) {
  16427. e.preventDefault();
  16428. }
  16429. if (['Enter', 'ArrowDown'].includes(e.key)) {
  16430. menu.value = true;
  16431. }
  16432. if (['Escape'].includes(e.key)) {
  16433. menu.value = false;
  16434. }
  16435. if (['Enter', 'Escape', 'Tab'].includes(e.key)) {
  16436. if (highlightFirst.value && ['Enter', 'Tab'].includes(e.key) && !model.value.some(_ref2 => {
  16437. let {
  16438. value
  16439. } = _ref2;
  16440. return value === displayItems.value[0].value;
  16441. })) {
  16442. select(filteredItems.value[0]);
  16443. }
  16444. isPristine.value = true;
  16445. }
  16446. if (e.key === 'ArrowDown' && highlightFirst.value) {
  16447. listRef.value?.focus('next');
  16448. }
  16449. if (e.key === 'Enter' && search.value) {
  16450. select(transformItem$3(props, search.value));
  16451. if (hasSelectionSlot.value) _search.value = '';
  16452. }
  16453. if (['Backspace', 'Delete'].includes(e.key)) {
  16454. if (!props.multiple && hasSelectionSlot.value && model.value.length > 0 && !search.value) return select(model.value[0], false);
  16455. if (~selectionIndex.value) {
  16456. const originalSelectionIndex = selectionIndex.value;
  16457. select(model.value[selectionIndex.value], false);
  16458. selectionIndex.value = originalSelectionIndex >= length - 1 ? length - 2 : originalSelectionIndex;
  16459. } else if (e.key === 'Backspace' && !search.value) {
  16460. selectionIndex.value = length - 1;
  16461. }
  16462. }
  16463. if (!props.multiple) return;
  16464. if (e.key === 'ArrowLeft') {
  16465. if (selectionIndex.value < 0 && selectionStart > 0) return;
  16466. const prev = selectionIndex.value > -1 ? selectionIndex.value - 1 : length - 1;
  16467. if (model.value[prev]) {
  16468. selectionIndex.value = prev;
  16469. } else {
  16470. selectionIndex.value = -1;
  16471. vTextFieldRef.value.setSelectionRange(search.value.length, search.value.length);
  16472. }
  16473. }
  16474. if (e.key === 'ArrowRight') {
  16475. if (selectionIndex.value < 0) return;
  16476. const next = selectionIndex.value + 1;
  16477. if (model.value[next]) {
  16478. selectionIndex.value = next;
  16479. } else {
  16480. selectionIndex.value = -1;
  16481. vTextFieldRef.value.setSelectionRange(0, 0);
  16482. }
  16483. }
  16484. }
  16485. function onAfterEnter() {
  16486. if (props.eager) {
  16487. vVirtualScrollRef.value?.calculateVisibleItems();
  16488. }
  16489. }
  16490. function onAfterLeave() {
  16491. if (isFocused.value) {
  16492. isPristine.value = true;
  16493. vTextFieldRef.value?.focus();
  16494. }
  16495. }
  16496. /** @param set - null means toggle */
  16497. function select(item) {
  16498. let set = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : true;
  16499. if (!item || item.props.disabled) return;
  16500. if (props.multiple) {
  16501. const index = model.value.findIndex(selection => props.valueComparator(selection.value, item.value));
  16502. const add = set == null ? !~index : set;
  16503. if (~index) {
  16504. const value = add ? [...model.value, item] : [...model.value];
  16505. value.splice(index, 1);
  16506. model.value = value;
  16507. } else if (add) {
  16508. model.value = [...model.value, item];
  16509. }
  16510. if (props.clearOnSelect) {
  16511. search.value = '';
  16512. }
  16513. } else {
  16514. const add = set !== false;
  16515. model.value = add ? [item] : [];
  16516. _search.value = add && !hasSelectionSlot.value ? item.title : '';
  16517. // watch for search watcher to trigger
  16518. vue.nextTick(() => {
  16519. menu.value = false;
  16520. isPristine.value = true;
  16521. });
  16522. }
  16523. }
  16524. function onFocusin(e) {
  16525. isFocused.value = true;
  16526. setTimeout(() => {
  16527. listHasFocus.value = true;
  16528. });
  16529. }
  16530. function onFocusout(e) {
  16531. listHasFocus.value = false;
  16532. }
  16533. function onUpdateModelValue(v) {
  16534. if (v == null || v === '' && !props.multiple && !hasSelectionSlot.value) model.value = [];
  16535. }
  16536. vue.watch(isFocused, (val, oldVal) => {
  16537. if (val || val === oldVal) return;
  16538. selectionIndex.value = -1;
  16539. menu.value = false;
  16540. if (search.value) {
  16541. if (props.multiple) {
  16542. select(transformItem$3(props, search.value));
  16543. return;
  16544. }
  16545. if (!hasSelectionSlot.value) return;
  16546. if (model.value.some(_ref3 => {
  16547. let {
  16548. title
  16549. } = _ref3;
  16550. return title === search.value;
  16551. })) {
  16552. _search.value = '';
  16553. } else {
  16554. select(transformItem$3(props, search.value));
  16555. }
  16556. }
  16557. });
  16558. vue.watch(menu, () => {
  16559. if (!props.hideSelected && menu.value && model.value.length) {
  16560. const index = displayItems.value.findIndex(item => model.value.some(s => props.valueComparator(s.value, item.value)));
  16561. IN_BROWSER && window.requestAnimationFrame(() => {
  16562. index >= 0 && vVirtualScrollRef.value?.scrollToIndex(index);
  16563. });
  16564. }
  16565. });
  16566. vue.watch(() => props.items, (newVal, oldVal) => {
  16567. if (menu.value) return;
  16568. if (isFocused.value && !oldVal.length && newVal.length) {
  16569. menu.value = true;
  16570. }
  16571. });
  16572. useRender(() => {
  16573. const hasList = !!(!props.hideNoData || displayItems.value.length || slots['prepend-item'] || slots['append-item'] || slots['no-data']);
  16574. const isDirty = model.value.length > 0;
  16575. const textFieldProps = VTextField.filterProps(props);
  16576. return vue.createVNode(VTextField, vue.mergeProps({
  16577. "ref": vTextFieldRef
  16578. }, textFieldProps, {
  16579. "modelValue": search.value,
  16580. "onUpdate:modelValue": [$event => search.value = $event, onUpdateModelValue],
  16581. "focused": isFocused.value,
  16582. "onUpdate:focused": $event => isFocused.value = $event,
  16583. "validationValue": model.externalValue,
  16584. "counterValue": counterValue.value,
  16585. "dirty": isDirty,
  16586. "class": ['v-combobox', {
  16587. 'v-combobox--active-menu': menu.value,
  16588. 'v-combobox--chips': !!props.chips,
  16589. 'v-combobox--selection-slot': !!hasSelectionSlot.value,
  16590. 'v-combobox--selecting-index': selectionIndex.value > -1,
  16591. [`v-combobox--${props.multiple ? 'multiple' : 'single'}`]: true
  16592. }, props.class],
  16593. "style": props.style,
  16594. "readonly": form.isReadonly.value,
  16595. "placeholder": isDirty ? undefined : props.placeholder,
  16596. "onClick:clear": onClear,
  16597. "onMousedown:control": onMousedownControl,
  16598. "onKeydown": onKeydown
  16599. }), {
  16600. ...slots,
  16601. default: () => vue.createVNode(vue.Fragment, null, [vue.createVNode(VMenu, vue.mergeProps({
  16602. "ref": vMenuRef,
  16603. "modelValue": menu.value,
  16604. "onUpdate:modelValue": $event => menu.value = $event,
  16605. "activator": "parent",
  16606. "contentClass": "v-combobox__content",
  16607. "disabled": menuDisabled.value,
  16608. "eager": props.eager,
  16609. "maxHeight": 310,
  16610. "openOnClick": false,
  16611. "closeOnContentClick": false,
  16612. "transition": props.transition,
  16613. "onAfterEnter": onAfterEnter,
  16614. "onAfterLeave": onAfterLeave
  16615. }, props.menuProps), {
  16616. default: () => [hasList && vue.createVNode(VList, vue.mergeProps({
  16617. "ref": listRef,
  16618. "selected": selectedValues.value,
  16619. "selectStrategy": props.multiple ? 'independent' : 'single-independent',
  16620. "onMousedown": e => e.preventDefault(),
  16621. "onKeydown": onListKeydown,
  16622. "onFocusin": onFocusin,
  16623. "onFocusout": onFocusout,
  16624. "tabindex": "-1",
  16625. "aria-live": "polite",
  16626. "color": props.itemColor ?? props.color
  16627. }, listEvents, props.listProps), {
  16628. default: () => [slots['prepend-item']?.(), !displayItems.value.length && !props.hideNoData && (slots['no-data']?.() ?? vue.createVNode(VListItem, {
  16629. "key": "no-data",
  16630. "title": t(props.noDataText)
  16631. }, null)), vue.createVNode(VVirtualScroll, {
  16632. "ref": vVirtualScrollRef,
  16633. "renderless": true,
  16634. "items": displayItems.value
  16635. }, {
  16636. default: _ref4 => {
  16637. let {
  16638. item,
  16639. index,
  16640. itemRef
  16641. } = _ref4;
  16642. const itemProps = vue.mergeProps(item.props, {
  16643. ref: itemRef,
  16644. key: item.value,
  16645. active: highlightFirst.value && index === 0 ? true : undefined,
  16646. onClick: () => select(item, null)
  16647. });
  16648. return slots.item?.({
  16649. item,
  16650. index,
  16651. props: itemProps
  16652. }) ?? vue.createVNode(VListItem, vue.mergeProps(itemProps, {
  16653. "role": "option"
  16654. }), {
  16655. prepend: _ref5 => {
  16656. let {
  16657. isSelected
  16658. } = _ref5;
  16659. return vue.createVNode(vue.Fragment, null, [props.multiple && !props.hideSelected ? vue.createVNode(VCheckboxBtn, {
  16660. "key": item.value,
  16661. "modelValue": isSelected,
  16662. "ripple": false,
  16663. "tabindex": "-1"
  16664. }, null) : undefined, item.props.prependAvatar && vue.createVNode(VAvatar, {
  16665. "image": item.props.prependAvatar
  16666. }, null), item.props.prependIcon && vue.createVNode(VIcon, {
  16667. "icon": item.props.prependIcon
  16668. }, null)]);
  16669. },
  16670. title: () => {
  16671. return isPristine.value ? item.title : highlightResult(item.title, getMatches(item)?.title, search.value?.length ?? 0);
  16672. }
  16673. });
  16674. }
  16675. }), slots['append-item']?.()]
  16676. })]
  16677. }), model.value.map((item, index) => {
  16678. function onChipClose(e) {
  16679. e.stopPropagation();
  16680. e.preventDefault();
  16681. select(item, false);
  16682. }
  16683. const slotProps = {
  16684. 'onClick:close': onChipClose,
  16685. onKeydown(e) {
  16686. if (e.key !== 'Enter' && e.key !== ' ') return;
  16687. e.preventDefault();
  16688. e.stopPropagation();
  16689. onChipClose(e);
  16690. },
  16691. onMousedown(e) {
  16692. e.preventDefault();
  16693. e.stopPropagation();
  16694. },
  16695. modelValue: true,
  16696. 'onUpdate:modelValue': undefined
  16697. };
  16698. const hasSlot = hasChips.value ? !!slots.chip : !!slots.selection;
  16699. const slotContent = hasSlot ? ensureValidVNode(hasChips.value ? slots.chip({
  16700. item,
  16701. index,
  16702. props: slotProps
  16703. }) : slots.selection({
  16704. item,
  16705. index
  16706. })) : undefined;
  16707. if (hasSlot && !slotContent) return undefined;
  16708. return vue.createVNode("div", {
  16709. "key": item.value,
  16710. "class": ['v-combobox__selection', index === selectionIndex.value && ['v-combobox__selection--selected', textColorClasses.value]],
  16711. "style": index === selectionIndex.value ? textColorStyles.value : {}
  16712. }, [hasChips.value ? !slots.chip ? vue.createVNode(VChip, vue.mergeProps({
  16713. "key": "chip",
  16714. "closable": props.closableChips,
  16715. "size": "small",
  16716. "text": item.title,
  16717. "disabled": item.props.disabled
  16718. }, slotProps), null) : vue.createVNode(VDefaultsProvider, {
  16719. "key": "chip-defaults",
  16720. "defaults": {
  16721. VChip: {
  16722. closable: props.closableChips,
  16723. size: 'small',
  16724. text: item.title
  16725. }
  16726. }
  16727. }, {
  16728. default: () => [slotContent]
  16729. }) : slotContent ?? vue.createVNode("span", {
  16730. "class": "v-combobox__selection-text"
  16731. }, [item.title, props.multiple && index < model.value.length - 1 && vue.createVNode("span", {
  16732. "class": "v-combobox__selection-comma"
  16733. }, [vue.createTextVNode(",")])])]);
  16734. })]),
  16735. 'append-inner': function () {
  16736. for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) {
  16737. args[_key] = arguments[_key];
  16738. }
  16739. return vue.createVNode(vue.Fragment, null, [slots['append-inner']?.(...args), (!props.hideNoData || props.items.length) && props.menuIcon ? vue.createVNode(VIcon, {
  16740. "class": "v-combobox__menu-icon",
  16741. "icon": props.menuIcon,
  16742. "onMousedown": onMousedownMenuIcon,
  16743. "onClick": noop,
  16744. "aria-label": t(label.value),
  16745. "title": t(label.value),
  16746. "tabindex": "-1"
  16747. }, null) : undefined]);
  16748. }
  16749. });
  16750. });
  16751. return forwardRefs({
  16752. isFocused,
  16753. isPristine,
  16754. menu,
  16755. search,
  16756. selectionIndex,
  16757. filteredItems,
  16758. select
  16759. }, vTextFieldRef);
  16760. }
  16761. });
  16762. // Utilities
  16763. // Types
  16764. const firstDay = {
  16765. '001': 1,
  16766. AD: 1,
  16767. AE: 6,
  16768. AF: 6,
  16769. AG: 0,
  16770. AI: 1,
  16771. AL: 1,
  16772. AM: 1,
  16773. AN: 1,
  16774. AR: 1,
  16775. AS: 0,
  16776. AT: 1,
  16777. AU: 1,
  16778. AX: 1,
  16779. AZ: 1,
  16780. BA: 1,
  16781. BD: 0,
  16782. BE: 1,
  16783. BG: 1,
  16784. BH: 6,
  16785. BM: 1,
  16786. BN: 1,
  16787. BR: 0,
  16788. BS: 0,
  16789. BT: 0,
  16790. BW: 0,
  16791. BY: 1,
  16792. BZ: 0,
  16793. CA: 0,
  16794. CH: 1,
  16795. CL: 1,
  16796. CM: 1,
  16797. CN: 1,
  16798. CO: 0,
  16799. CR: 1,
  16800. CY: 1,
  16801. CZ: 1,
  16802. DE: 1,
  16803. DJ: 6,
  16804. DK: 1,
  16805. DM: 0,
  16806. DO: 0,
  16807. DZ: 6,
  16808. EC: 1,
  16809. EE: 1,
  16810. EG: 6,
  16811. ES: 1,
  16812. ET: 0,
  16813. FI: 1,
  16814. FJ: 1,
  16815. FO: 1,
  16816. FR: 1,
  16817. GB: 1,
  16818. 'GB-alt-variant': 0,
  16819. GE: 1,
  16820. GF: 1,
  16821. GP: 1,
  16822. GR: 1,
  16823. GT: 0,
  16824. GU: 0,
  16825. HK: 0,
  16826. HN: 0,
  16827. HR: 1,
  16828. HU: 1,
  16829. ID: 0,
  16830. IE: 1,
  16831. IL: 0,
  16832. IN: 0,
  16833. IQ: 6,
  16834. IR: 6,
  16835. IS: 1,
  16836. IT: 1,
  16837. JM: 0,
  16838. JO: 6,
  16839. JP: 0,
  16840. KE: 0,
  16841. KG: 1,
  16842. KH: 0,
  16843. KR: 0,
  16844. KW: 6,
  16845. KZ: 1,
  16846. LA: 0,
  16847. LB: 1,
  16848. LI: 1,
  16849. LK: 1,
  16850. LT: 1,
  16851. LU: 1,
  16852. LV: 1,
  16853. LY: 6,
  16854. MC: 1,
  16855. MD: 1,
  16856. ME: 1,
  16857. MH: 0,
  16858. MK: 1,
  16859. MM: 0,
  16860. MN: 1,
  16861. MO: 0,
  16862. MQ: 1,
  16863. MT: 0,
  16864. MV: 5,
  16865. MX: 0,
  16866. MY: 1,
  16867. MZ: 0,
  16868. NI: 0,
  16869. NL: 1,
  16870. NO: 1,
  16871. NP: 0,
  16872. NZ: 1,
  16873. OM: 6,
  16874. PA: 0,
  16875. PE: 0,
  16876. PH: 0,
  16877. PK: 0,
  16878. PL: 1,
  16879. PR: 0,
  16880. PT: 0,
  16881. PY: 0,
  16882. QA: 6,
  16883. RE: 1,
  16884. RO: 1,
  16885. RS: 1,
  16886. RU: 1,
  16887. SA: 0,
  16888. SD: 6,
  16889. SE: 1,
  16890. SG: 0,
  16891. SI: 1,
  16892. SK: 1,
  16893. SM: 1,
  16894. SV: 0,
  16895. SY: 6,
  16896. TH: 0,
  16897. TJ: 1,
  16898. TM: 1,
  16899. TR: 1,
  16900. TT: 0,
  16901. TW: 0,
  16902. UA: 1,
  16903. UM: 0,
  16904. US: 0,
  16905. UY: 1,
  16906. UZ: 1,
  16907. VA: 1,
  16908. VE: 0,
  16909. VI: 0,
  16910. VN: 1,
  16911. WS: 0,
  16912. XK: 1,
  16913. YE: 0,
  16914. ZA: 0,
  16915. ZW: 0
  16916. };
  16917. function getWeekArray(date, locale, firstDayOfWeek) {
  16918. const weeks = [];
  16919. let currentWeek = [];
  16920. const firstDayOfMonth = startOfMonth(date);
  16921. const lastDayOfMonth = endOfMonth(date);
  16922. const first = firstDayOfWeek ?? firstDay[locale.slice(-2).toUpperCase()] ?? 0;
  16923. const firstDayWeekIndex = (firstDayOfMonth.getDay() - first + 7) % 7;
  16924. const lastDayWeekIndex = (lastDayOfMonth.getDay() - first + 7) % 7;
  16925. for (let i = 0; i < firstDayWeekIndex; i++) {
  16926. const adjacentDay = new Date(firstDayOfMonth);
  16927. adjacentDay.setDate(adjacentDay.getDate() - (firstDayWeekIndex - i));
  16928. currentWeek.push(adjacentDay);
  16929. }
  16930. for (let i = 1; i <= lastDayOfMonth.getDate(); i++) {
  16931. const day = new Date(date.getFullYear(), date.getMonth(), i);
  16932. // Add the day to the current week
  16933. currentWeek.push(day);
  16934. // If the current week has 7 days, add it to the weeks array and start a new week
  16935. if (currentWeek.length === 7) {
  16936. weeks.push(currentWeek);
  16937. currentWeek = [];
  16938. }
  16939. }
  16940. for (let i = 1; i < 7 - lastDayWeekIndex; i++) {
  16941. const adjacentDay = new Date(lastDayOfMonth);
  16942. adjacentDay.setDate(adjacentDay.getDate() + i);
  16943. currentWeek.push(adjacentDay);
  16944. }
  16945. if (currentWeek.length > 0) {
  16946. weeks.push(currentWeek);
  16947. }
  16948. return weeks;
  16949. }
  16950. function startOfWeek(date, locale, firstDayOfWeek) {
  16951. const day = firstDayOfWeek ?? firstDay[locale.slice(-2).toUpperCase()] ?? 0;
  16952. const d = new Date(date);
  16953. while (d.getDay() !== day) {
  16954. d.setDate(d.getDate() - 1);
  16955. }
  16956. return d;
  16957. }
  16958. function endOfWeek(date, locale) {
  16959. const d = new Date(date);
  16960. const lastDay = ((firstDay[locale.slice(-2).toUpperCase()] ?? 0) + 6) % 7;
  16961. while (d.getDay() !== lastDay) {
  16962. d.setDate(d.getDate() + 1);
  16963. }
  16964. return d;
  16965. }
  16966. function startOfMonth(date) {
  16967. return new Date(date.getFullYear(), date.getMonth(), 1);
  16968. }
  16969. function endOfMonth(date) {
  16970. return new Date(date.getFullYear(), date.getMonth() + 1, 0);
  16971. }
  16972. function parseLocalDate(value) {
  16973. const parts = value.split('-').map(Number);
  16974. // new Date() uses local time zone when passing individual date component values
  16975. return new Date(parts[0], parts[1] - 1, parts[2]);
  16976. }
  16977. const _YYYMMDD = /^([12]\d{3}-([1-9]|0[1-9]|1[0-2])-([1-9]|0[1-9]|[12]\d|3[01]))$/;
  16978. function date(value) {
  16979. if (value == null) return new Date();
  16980. if (value instanceof Date) return value;
  16981. if (typeof value === 'string') {
  16982. let parsed;
  16983. if (_YYYMMDD.test(value)) {
  16984. return parseLocalDate(value);
  16985. } else {
  16986. parsed = Date.parse(value);
  16987. }
  16988. if (!isNaN(parsed)) return new Date(parsed);
  16989. }
  16990. return null;
  16991. }
  16992. const sundayJanuarySecond2000 = new Date(2000, 0, 2);
  16993. function getWeekdays(locale, firstDayOfWeek) {
  16994. const daysFromSunday = firstDayOfWeek ?? firstDay[locale.slice(-2).toUpperCase()] ?? 0;
  16995. return createRange(7).map(i => {
  16996. const weekday = new Date(sundayJanuarySecond2000);
  16997. weekday.setDate(sundayJanuarySecond2000.getDate() + daysFromSunday + i);
  16998. return new Intl.DateTimeFormat(locale, {
  16999. weekday: 'narrow'
  17000. }).format(weekday);
  17001. });
  17002. }
  17003. function format(value, formatString, locale, formats) {
  17004. const newDate = date(value) ?? new Date();
  17005. const customFormat = formats?.[formatString];
  17006. if (typeof customFormat === 'function') {
  17007. return customFormat(newDate, formatString, locale);
  17008. }
  17009. let options = {};
  17010. switch (formatString) {
  17011. case 'fullDate':
  17012. options = {
  17013. year: 'numeric',
  17014. month: 'long',
  17015. day: 'numeric'
  17016. };
  17017. break;
  17018. case 'fullDateWithWeekday':
  17019. options = {
  17020. weekday: 'long',
  17021. year: 'numeric',
  17022. month: 'long',
  17023. day: 'numeric'
  17024. };
  17025. break;
  17026. case 'normalDate':
  17027. const day = newDate.getDate();
  17028. const month = new Intl.DateTimeFormat(locale, {
  17029. month: 'long'
  17030. }).format(newDate);
  17031. return `${day} ${month}`;
  17032. case 'normalDateWithWeekday':
  17033. options = {
  17034. weekday: 'short',
  17035. day: 'numeric',
  17036. month: 'short'
  17037. };
  17038. break;
  17039. case 'shortDate':
  17040. options = {
  17041. month: 'short',
  17042. day: 'numeric'
  17043. };
  17044. break;
  17045. case 'year':
  17046. options = {
  17047. year: 'numeric'
  17048. };
  17049. break;
  17050. case 'month':
  17051. options = {
  17052. month: 'long'
  17053. };
  17054. break;
  17055. case 'monthShort':
  17056. options = {
  17057. month: 'short'
  17058. };
  17059. break;
  17060. case 'monthAndYear':
  17061. options = {
  17062. month: 'long',
  17063. year: 'numeric'
  17064. };
  17065. break;
  17066. case 'monthAndDate':
  17067. options = {
  17068. month: 'long',
  17069. day: 'numeric'
  17070. };
  17071. break;
  17072. case 'weekday':
  17073. options = {
  17074. weekday: 'long'
  17075. };
  17076. break;
  17077. case 'weekdayShort':
  17078. options = {
  17079. weekday: 'short'
  17080. };
  17081. break;
  17082. case 'dayOfMonth':
  17083. return new Intl.NumberFormat(locale).format(newDate.getDate());
  17084. case 'hours12h':
  17085. options = {
  17086. hour: 'numeric',
  17087. hour12: true
  17088. };
  17089. break;
  17090. case 'hours24h':
  17091. options = {
  17092. hour: 'numeric',
  17093. hour12: false
  17094. };
  17095. break;
  17096. case 'minutes':
  17097. options = {
  17098. minute: 'numeric'
  17099. };
  17100. break;
  17101. case 'seconds':
  17102. options = {
  17103. second: 'numeric'
  17104. };
  17105. break;
  17106. case 'fullTime':
  17107. options = {
  17108. hour: 'numeric',
  17109. minute: 'numeric',
  17110. second: 'numeric',
  17111. hour12: true
  17112. };
  17113. break;
  17114. case 'fullTime12h':
  17115. options = {
  17116. hour: 'numeric',
  17117. minute: 'numeric',
  17118. second: 'numeric',
  17119. hour12: true
  17120. };
  17121. break;
  17122. case 'fullTime24h':
  17123. options = {
  17124. hour: 'numeric',
  17125. minute: 'numeric',
  17126. second: 'numeric',
  17127. hour12: false
  17128. };
  17129. break;
  17130. case 'fullDateTime':
  17131. options = {
  17132. year: 'numeric',
  17133. month: 'long',
  17134. day: 'numeric',
  17135. hour: 'numeric',
  17136. minute: 'numeric',
  17137. second: 'numeric',
  17138. hour12: true
  17139. };
  17140. break;
  17141. case 'fullDateTime12h':
  17142. options = {
  17143. year: 'numeric',
  17144. month: 'long',
  17145. day: 'numeric',
  17146. hour: 'numeric',
  17147. minute: 'numeric',
  17148. second: 'numeric',
  17149. hour12: true
  17150. };
  17151. break;
  17152. case 'fullDateTime24h':
  17153. options = {
  17154. year: 'numeric',
  17155. month: 'long',
  17156. day: 'numeric',
  17157. hour: 'numeric',
  17158. minute: 'numeric',
  17159. second: 'numeric',
  17160. hour12: false
  17161. };
  17162. break;
  17163. case 'keyboardDate':
  17164. options = {
  17165. year: 'numeric',
  17166. month: '2-digit',
  17167. day: '2-digit'
  17168. };
  17169. break;
  17170. case 'keyboardDateTime':
  17171. options = {
  17172. year: 'numeric',
  17173. month: '2-digit',
  17174. day: '2-digit',
  17175. hour: 'numeric',
  17176. minute: 'numeric',
  17177. second: 'numeric',
  17178. hour12: false
  17179. };
  17180. break;
  17181. case 'keyboardDateTime12h':
  17182. options = {
  17183. year: 'numeric',
  17184. month: '2-digit',
  17185. day: '2-digit',
  17186. hour: 'numeric',
  17187. minute: 'numeric',
  17188. second: 'numeric',
  17189. hour12: true
  17190. };
  17191. break;
  17192. case 'keyboardDateTime24h':
  17193. options = {
  17194. year: 'numeric',
  17195. month: '2-digit',
  17196. day: '2-digit',
  17197. hour: 'numeric',
  17198. minute: 'numeric',
  17199. second: 'numeric',
  17200. hour12: false
  17201. };
  17202. break;
  17203. default:
  17204. options = customFormat ?? {
  17205. timeZone: 'UTC',
  17206. timeZoneName: 'short'
  17207. };
  17208. }
  17209. return new Intl.DateTimeFormat(locale, options).format(newDate);
  17210. }
  17211. function toISO(adapter, value) {
  17212. const date = adapter.toJsDate(value);
  17213. const year = date.getFullYear();
  17214. const month = padStart(String(date.getMonth() + 1), 2, '0');
  17215. const day = padStart(String(date.getDate()), 2, '0');
  17216. return `${year}-${month}-${day}`;
  17217. }
  17218. function parseISO(value) {
  17219. const [year, month, day] = value.split('-').map(Number);
  17220. return new Date(year, month - 1, day);
  17221. }
  17222. function addMinutes(date, amount) {
  17223. const d = new Date(date);
  17224. d.setMinutes(d.getMinutes() + amount);
  17225. return d;
  17226. }
  17227. function addHours(date, amount) {
  17228. const d = new Date(date);
  17229. d.setHours(d.getHours() + amount);
  17230. return d;
  17231. }
  17232. function addDays(date, amount) {
  17233. const d = new Date(date);
  17234. d.setDate(d.getDate() + amount);
  17235. return d;
  17236. }
  17237. function addWeeks(date, amount) {
  17238. const d = new Date(date);
  17239. d.setDate(d.getDate() + amount * 7);
  17240. return d;
  17241. }
  17242. function addMonths(date, amount) {
  17243. const d = new Date(date);
  17244. d.setDate(1);
  17245. d.setMonth(d.getMonth() + amount);
  17246. return d;
  17247. }
  17248. function getYear(date) {
  17249. return date.getFullYear();
  17250. }
  17251. function getMonth(date) {
  17252. return date.getMonth();
  17253. }
  17254. function getDate(date) {
  17255. return date.getDate();
  17256. }
  17257. function getNextMonth(date) {
  17258. return new Date(date.getFullYear(), date.getMonth() + 1, 1);
  17259. }
  17260. function getPreviousMonth(date) {
  17261. return new Date(date.getFullYear(), date.getMonth() - 1, 1);
  17262. }
  17263. function getHours(date) {
  17264. return date.getHours();
  17265. }
  17266. function getMinutes(date) {
  17267. return date.getMinutes();
  17268. }
  17269. function startOfYear(date) {
  17270. return new Date(date.getFullYear(), 0, 1);
  17271. }
  17272. function endOfYear(date) {
  17273. return new Date(date.getFullYear(), 11, 31);
  17274. }
  17275. function isWithinRange(date, range) {
  17276. return isAfter(date, range[0]) && isBefore(date, range[1]);
  17277. }
  17278. function isValid(date) {
  17279. const d = new Date(date);
  17280. return d instanceof Date && !isNaN(d.getTime());
  17281. }
  17282. function isAfter(date, comparing) {
  17283. return date.getTime() > comparing.getTime();
  17284. }
  17285. function isAfterDay(date, comparing) {
  17286. return isAfter(startOfDay(date), startOfDay(comparing));
  17287. }
  17288. function isBefore(date, comparing) {
  17289. return date.getTime() < comparing.getTime();
  17290. }
  17291. function isEqual(date, comparing) {
  17292. return date.getTime() === comparing.getTime();
  17293. }
  17294. function isSameDay(date, comparing) {
  17295. return date.getDate() === comparing.getDate() && date.getMonth() === comparing.getMonth() && date.getFullYear() === comparing.getFullYear();
  17296. }
  17297. function isSameMonth(date, comparing) {
  17298. return date.getMonth() === comparing.getMonth() && date.getFullYear() === comparing.getFullYear();
  17299. }
  17300. function isSameYear(date, comparing) {
  17301. return date.getFullYear() === comparing.getFullYear();
  17302. }
  17303. function getDiff(date, comparing, unit) {
  17304. const d = new Date(date);
  17305. const c = new Date(comparing);
  17306. switch (unit) {
  17307. case 'years':
  17308. return d.getFullYear() - c.getFullYear();
  17309. case 'quarters':
  17310. return Math.floor((d.getMonth() - c.getMonth() + (d.getFullYear() - c.getFullYear()) * 12) / 4);
  17311. case 'months':
  17312. return d.getMonth() - c.getMonth() + (d.getFullYear() - c.getFullYear()) * 12;
  17313. case 'weeks':
  17314. return Math.floor((d.getTime() - c.getTime()) / (1000 * 60 * 60 * 24 * 7));
  17315. case 'days':
  17316. return Math.floor((d.getTime() - c.getTime()) / (1000 * 60 * 60 * 24));
  17317. case 'hours':
  17318. return Math.floor((d.getTime() - c.getTime()) / (1000 * 60 * 60));
  17319. case 'minutes':
  17320. return Math.floor((d.getTime() - c.getTime()) / (1000 * 60));
  17321. case 'seconds':
  17322. return Math.floor((d.getTime() - c.getTime()) / 1000);
  17323. default:
  17324. {
  17325. return d.getTime() - c.getTime();
  17326. }
  17327. }
  17328. }
  17329. function setHours(date, count) {
  17330. const d = new Date(date);
  17331. d.setHours(count);
  17332. return d;
  17333. }
  17334. function setMinutes(date, count) {
  17335. const d = new Date(date);
  17336. d.setMinutes(count);
  17337. return d;
  17338. }
  17339. function setMonth(date, count) {
  17340. const d = new Date(date);
  17341. d.setMonth(count);
  17342. return d;
  17343. }
  17344. function setDate(date, day) {
  17345. const d = new Date(date);
  17346. d.setDate(day);
  17347. return d;
  17348. }
  17349. function setYear(date, year) {
  17350. const d = new Date(date);
  17351. d.setFullYear(year);
  17352. return d;
  17353. }
  17354. function startOfDay(date) {
  17355. return new Date(date.getFullYear(), date.getMonth(), date.getDate(), 0, 0, 0, 0);
  17356. }
  17357. function endOfDay(date) {
  17358. return new Date(date.getFullYear(), date.getMonth(), date.getDate(), 23, 59, 59, 999);
  17359. }
  17360. class VuetifyDateAdapter {
  17361. constructor(options) {
  17362. this.locale = options.locale;
  17363. this.formats = options.formats;
  17364. }
  17365. date(value) {
  17366. return date(value);
  17367. }
  17368. toJsDate(date) {
  17369. return date;
  17370. }
  17371. toISO(date) {
  17372. return toISO(this, date);
  17373. }
  17374. parseISO(date) {
  17375. return parseISO(date);
  17376. }
  17377. addMinutes(date, amount) {
  17378. return addMinutes(date, amount);
  17379. }
  17380. addHours(date, amount) {
  17381. return addHours(date, amount);
  17382. }
  17383. addDays(date, amount) {
  17384. return addDays(date, amount);
  17385. }
  17386. addWeeks(date, amount) {
  17387. return addWeeks(date, amount);
  17388. }
  17389. addMonths(date, amount) {
  17390. return addMonths(date, amount);
  17391. }
  17392. getWeekArray(date, firstDayOfWeek) {
  17393. return getWeekArray(date, this.locale, firstDayOfWeek ? Number(firstDayOfWeek) : undefined);
  17394. }
  17395. startOfWeek(date, firstDayOfWeek) {
  17396. return startOfWeek(date, this.locale, firstDayOfWeek ? Number(firstDayOfWeek) : undefined);
  17397. }
  17398. endOfWeek(date) {
  17399. return endOfWeek(date, this.locale);
  17400. }
  17401. startOfMonth(date) {
  17402. return startOfMonth(date);
  17403. }
  17404. endOfMonth(date) {
  17405. return endOfMonth(date);
  17406. }
  17407. format(date, formatString) {
  17408. return format(date, formatString, this.locale, this.formats);
  17409. }
  17410. isEqual(date, comparing) {
  17411. return isEqual(date, comparing);
  17412. }
  17413. isValid(date) {
  17414. return isValid(date);
  17415. }
  17416. isWithinRange(date, range) {
  17417. return isWithinRange(date, range);
  17418. }
  17419. isAfter(date, comparing) {
  17420. return isAfter(date, comparing);
  17421. }
  17422. isAfterDay(date, comparing) {
  17423. return isAfterDay(date, comparing);
  17424. }
  17425. isBefore(date, comparing) {
  17426. return !isAfter(date, comparing) && !isEqual(date, comparing);
  17427. }
  17428. isSameDay(date, comparing) {
  17429. return isSameDay(date, comparing);
  17430. }
  17431. isSameMonth(date, comparing) {
  17432. return isSameMonth(date, comparing);
  17433. }
  17434. isSameYear(date, comparing) {
  17435. return isSameYear(date, comparing);
  17436. }
  17437. setMinutes(date, count) {
  17438. return setMinutes(date, count);
  17439. }
  17440. setHours(date, count) {
  17441. return setHours(date, count);
  17442. }
  17443. setMonth(date, count) {
  17444. return setMonth(date, count);
  17445. }
  17446. setDate(date, day) {
  17447. return setDate(date, day);
  17448. }
  17449. setYear(date, year) {
  17450. return setYear(date, year);
  17451. }
  17452. getDiff(date, comparing, unit) {
  17453. return getDiff(date, comparing, unit);
  17454. }
  17455. getWeekdays(firstDayOfWeek) {
  17456. return getWeekdays(this.locale, firstDayOfWeek ? Number(firstDayOfWeek) : undefined);
  17457. }
  17458. getYear(date) {
  17459. return getYear(date);
  17460. }
  17461. getMonth(date) {
  17462. return getMonth(date);
  17463. }
  17464. getDate(date) {
  17465. return getDate(date);
  17466. }
  17467. getNextMonth(date) {
  17468. return getNextMonth(date);
  17469. }
  17470. getPreviousMonth(date) {
  17471. return getPreviousMonth(date);
  17472. }
  17473. getHours(date) {
  17474. return getHours(date);
  17475. }
  17476. getMinutes(date) {
  17477. return getMinutes(date);
  17478. }
  17479. startOfDay(date) {
  17480. return startOfDay(date);
  17481. }
  17482. endOfDay(date) {
  17483. return endOfDay(date);
  17484. }
  17485. startOfYear(date) {
  17486. return startOfYear(date);
  17487. }
  17488. endOfYear(date) {
  17489. return endOfYear(date);
  17490. }
  17491. }
  17492. // Composables
  17493. const DateOptionsSymbol = Symbol.for('vuetify:date-options');
  17494. const DateAdapterSymbol = Symbol.for('vuetify:date-adapter');
  17495. function createDate(options, locale) {
  17496. const _options = mergeDeep({
  17497. adapter: VuetifyDateAdapter,
  17498. locale: {
  17499. af: 'af-ZA',
  17500. // ar: '', # not the same value for all variants
  17501. bg: 'bg-BG',
  17502. ca: 'ca-ES',
  17503. ckb: '',
  17504. cs: 'cs-CZ',
  17505. de: 'de-DE',
  17506. el: 'el-GR',
  17507. en: 'en-US',
  17508. // es: '', # not the same value for all variants
  17509. et: 'et-EE',
  17510. fa: 'fa-IR',
  17511. fi: 'fi-FI',
  17512. // fr: '', #not the same value for all variants
  17513. hr: 'hr-HR',
  17514. hu: 'hu-HU',
  17515. he: 'he-IL',
  17516. id: 'id-ID',
  17517. it: 'it-IT',
  17518. ja: 'ja-JP',
  17519. ko: 'ko-KR',
  17520. lv: 'lv-LV',
  17521. lt: 'lt-LT',
  17522. nl: 'nl-NL',
  17523. no: 'no-NO',
  17524. pl: 'pl-PL',
  17525. pt: 'pt-PT',
  17526. ro: 'ro-RO',
  17527. ru: 'ru-RU',
  17528. sk: 'sk-SK',
  17529. sl: 'sl-SI',
  17530. srCyrl: 'sr-SP',
  17531. srLatn: 'sr-SP',
  17532. sv: 'sv-SE',
  17533. th: 'th-TH',
  17534. tr: 'tr-TR',
  17535. az: 'az-AZ',
  17536. uk: 'uk-UA',
  17537. vi: 'vi-VN',
  17538. zhHans: 'zh-CN',
  17539. zhHant: 'zh-TW'
  17540. }
  17541. }, options);
  17542. return {
  17543. options: _options,
  17544. instance: createInstance(_options, locale)
  17545. };
  17546. }
  17547. function createInstance(options, locale) {
  17548. const instance = vue.reactive(typeof options.adapter === 'function'
  17549. // eslint-disable-next-line new-cap
  17550. ? new options.adapter({
  17551. locale: options.locale[locale.current.value] ?? locale.current.value,
  17552. formats: options.formats
  17553. }) : options.adapter);
  17554. vue.watch(locale.current, value => {
  17555. instance.locale = options.locale[value] ?? value ?? instance.locale;
  17556. });
  17557. return instance;
  17558. }
  17559. function useDate() {
  17560. const options = vue.inject(DateOptionsSymbol);
  17561. if (!options) throw new Error('[Vuetify] Could not find injected date options');
  17562. const locale = useLocale();
  17563. return createInstance(options, locale);
  17564. }
  17565. // https://stackoverflow.com/questions/274861/how-do-i-calculate-the-week-number-given-a-date/275024#275024
  17566. function getWeek(adapter, value) {
  17567. const date = adapter.toJsDate(value);
  17568. let year = date.getFullYear();
  17569. let d1w1 = new Date(year, 0, 1);
  17570. if (date < d1w1) {
  17571. year = year - 1;
  17572. d1w1 = new Date(year, 0, 1);
  17573. } else {
  17574. const tv = new Date(year + 1, 0, 1);
  17575. if (date >= tv) {
  17576. year = year + 1;
  17577. d1w1 = tv;
  17578. }
  17579. }
  17580. const diffTime = Math.abs(date.getTime() - d1w1.getTime());
  17581. const diffDays = Math.ceil(diffTime / (1000 * 60 * 60 * 24));
  17582. return Math.floor(diffDays / 7) + 1;
  17583. }
  17584. // Types
  17585. const makeVConfirmEditProps = propsFactory({
  17586. modelValue: null,
  17587. color: String,
  17588. cancelText: {
  17589. type: String,
  17590. default: '$vuetify.confirmEdit.cancel'
  17591. },
  17592. okText: {
  17593. type: String,
  17594. default: '$vuetify.confirmEdit.ok'
  17595. }
  17596. }, 'VConfirmEdit');
  17597. const VConfirmEdit = genericComponent()({
  17598. name: 'VConfirmEdit',
  17599. props: makeVConfirmEditProps(),
  17600. emits: {
  17601. cancel: () => true,
  17602. save: value => true,
  17603. 'update:modelValue': value => true
  17604. },
  17605. setup(props, _ref) {
  17606. let {
  17607. emit,
  17608. slots
  17609. } = _ref;
  17610. const model = useProxiedModel(props, 'modelValue');
  17611. const internalModel = vue.ref();
  17612. vue.watchEffect(() => {
  17613. internalModel.value = structuredClone(vue.toRaw(model.value));
  17614. });
  17615. const {
  17616. t
  17617. } = useLocale();
  17618. const isPristine = vue.computed(() => {
  17619. return deepEqual(model.value, internalModel.value);
  17620. });
  17621. function save() {
  17622. model.value = internalModel.value;
  17623. emit('save', internalModel.value);
  17624. }
  17625. function cancel() {
  17626. internalModel.value = structuredClone(vue.toRaw(model.value));
  17627. emit('cancel');
  17628. }
  17629. function actions(actionsProps) {
  17630. return vue.createVNode(vue.Fragment, null, [vue.createVNode(VBtn, vue.mergeProps({
  17631. "disabled": isPristine.value,
  17632. "variant": "text",
  17633. "color": props.color,
  17634. "onClick": cancel,
  17635. "text": t(props.cancelText)
  17636. }, actionsProps), null), vue.createVNode(VBtn, vue.mergeProps({
  17637. "disabled": isPristine.value,
  17638. "variant": "text",
  17639. "color": props.color,
  17640. "onClick": save,
  17641. "text": t(props.okText)
  17642. }, actionsProps), null)]);
  17643. }
  17644. let actionsUsed = false;
  17645. useRender(() => {
  17646. return vue.createVNode(vue.Fragment, null, [slots.default?.({
  17647. model: internalModel,
  17648. save,
  17649. cancel,
  17650. isPristine: isPristine.value,
  17651. get actions() {
  17652. actionsUsed = true;
  17653. return actions;
  17654. }
  17655. }), !actionsUsed && actions()]);
  17656. });
  17657. return {
  17658. save,
  17659. cancel,
  17660. isPristine
  17661. };
  17662. }
  17663. });
  17664. // Composables
  17665. // Types
  17666. const makeDataTableExpandProps = propsFactory({
  17667. expandOnClick: Boolean,
  17668. showExpand: Boolean,
  17669. expanded: {
  17670. type: Array,
  17671. default: () => []
  17672. }
  17673. }, 'DataTable-expand');
  17674. const VDataTableExpandedKey = Symbol.for('vuetify:datatable:expanded');
  17675. function provideExpanded(props) {
  17676. const expandOnClick = vue.toRef(props, 'expandOnClick');
  17677. const expanded = useProxiedModel(props, 'expanded', props.expanded, v => {
  17678. return new Set(v);
  17679. }, v => {
  17680. return [...v.values()];
  17681. });
  17682. function expand(item, value) {
  17683. const newExpanded = new Set(expanded.value);
  17684. if (!value) {
  17685. newExpanded.delete(item.value);
  17686. } else {
  17687. newExpanded.add(item.value);
  17688. }
  17689. expanded.value = newExpanded;
  17690. }
  17691. function isExpanded(item) {
  17692. return expanded.value.has(item.value);
  17693. }
  17694. function toggleExpand(item) {
  17695. expand(item, !isExpanded(item));
  17696. }
  17697. const data = {
  17698. expand,
  17699. expanded,
  17700. expandOnClick,
  17701. isExpanded,
  17702. toggleExpand
  17703. };
  17704. vue.provide(VDataTableExpandedKey, data);
  17705. return data;
  17706. }
  17707. function useExpanded() {
  17708. const data = vue.inject(VDataTableExpandedKey);
  17709. if (!data) throw new Error('foo');
  17710. return data;
  17711. }
  17712. // Composables
  17713. // Types
  17714. const makeDataTableGroupProps = propsFactory({
  17715. groupBy: {
  17716. type: Array,
  17717. default: () => []
  17718. }
  17719. }, 'DataTable-group');
  17720. const VDataTableGroupSymbol = Symbol.for('vuetify:data-table-group');
  17721. function createGroupBy(props) {
  17722. const groupBy = useProxiedModel(props, 'groupBy');
  17723. return {
  17724. groupBy
  17725. };
  17726. }
  17727. function provideGroupBy(options) {
  17728. const {
  17729. disableSort,
  17730. groupBy,
  17731. sortBy
  17732. } = options;
  17733. const opened = vue.ref(new Set());
  17734. const sortByWithGroups = vue.computed(() => {
  17735. return groupBy.value.map(val => ({
  17736. ...val,
  17737. order: val.order ?? false
  17738. })).concat(disableSort?.value ? [] : sortBy.value);
  17739. });
  17740. function isGroupOpen(group) {
  17741. return opened.value.has(group.id);
  17742. }
  17743. function toggleGroup(group) {
  17744. const newOpened = new Set(opened.value);
  17745. if (!isGroupOpen(group)) newOpened.add(group.id);else newOpened.delete(group.id);
  17746. opened.value = newOpened;
  17747. }
  17748. function extractRows(items) {
  17749. function dive(group) {
  17750. const arr = [];
  17751. for (const item of group.items) {
  17752. if ('type' in item && item.type === 'group') {
  17753. arr.push(...dive(item));
  17754. } else {
  17755. arr.push(item);
  17756. }
  17757. }
  17758. return arr;
  17759. }
  17760. return dive({
  17761. type: 'group',
  17762. items,
  17763. id: 'dummy',
  17764. key: 'dummy',
  17765. value: 'dummy',
  17766. depth: 0
  17767. });
  17768. }
  17769. // onBeforeMount(() => {
  17770. // for (const key of groupedItems.value.keys()) {
  17771. // opened.value.add(key)
  17772. // }
  17773. // })
  17774. const data = {
  17775. sortByWithGroups,
  17776. toggleGroup,
  17777. opened,
  17778. groupBy,
  17779. extractRows,
  17780. isGroupOpen
  17781. };
  17782. vue.provide(VDataTableGroupSymbol, data);
  17783. return data;
  17784. }
  17785. function useGroupBy() {
  17786. const data = vue.inject(VDataTableGroupSymbol);
  17787. if (!data) throw new Error('Missing group!');
  17788. return data;
  17789. }
  17790. function groupItemsByProperty(items, groupBy) {
  17791. if (!items.length) return [];
  17792. const groups = new Map();
  17793. for (const item of items) {
  17794. const value = getObjectValueByPath(item.raw, groupBy);
  17795. if (!groups.has(value)) {
  17796. groups.set(value, []);
  17797. }
  17798. groups.get(value).push(item);
  17799. }
  17800. return groups;
  17801. }
  17802. function groupItems(items, groupBy) {
  17803. let depth = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : 0;
  17804. let prefix = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : 'root';
  17805. if (!groupBy.length) return [];
  17806. const groupedItems = groupItemsByProperty(items, groupBy[0]);
  17807. const groups = [];
  17808. const rest = groupBy.slice(1);
  17809. groupedItems.forEach((items, value) => {
  17810. const key = groupBy[0];
  17811. const id = `${prefix}_${key}_${value}`;
  17812. groups.push({
  17813. depth,
  17814. id,
  17815. key,
  17816. value,
  17817. items: rest.length ? groupItems(items, rest, depth + 1, id) : items,
  17818. type: 'group'
  17819. });
  17820. });
  17821. return groups;
  17822. }
  17823. function flattenItems(items, opened) {
  17824. const flatItems = [];
  17825. for (const item of items) {
  17826. // TODO: make this better
  17827. if ('type' in item && item.type === 'group') {
  17828. if (item.value != null) {
  17829. flatItems.push(item);
  17830. }
  17831. if (opened.has(item.id) || item.value == null) {
  17832. flatItems.push(...flattenItems(item.items, opened));
  17833. }
  17834. } else {
  17835. flatItems.push(item);
  17836. }
  17837. }
  17838. return flatItems;
  17839. }
  17840. function useGroupedItems(items, groupBy, opened) {
  17841. const flatItems = vue.computed(() => {
  17842. if (!groupBy.value.length) return items.value;
  17843. const groupedItems = groupItems(items.value, groupBy.value.map(item => item.key));
  17844. return flattenItems(groupedItems, opened.value);
  17845. });
  17846. return {
  17847. flatItems
  17848. };
  17849. }
  17850. // Utilities
  17851. // Types
  17852. function useOptions(_ref) {
  17853. let {
  17854. page,
  17855. itemsPerPage,
  17856. sortBy,
  17857. groupBy,
  17858. search
  17859. } = _ref;
  17860. const vm = getCurrentInstance('VDataTable');
  17861. const options = vue.computed(() => ({
  17862. page: page.value,
  17863. itemsPerPage: itemsPerPage.value,
  17864. sortBy: sortBy.value,
  17865. groupBy: groupBy.value,
  17866. search: search.value
  17867. }));
  17868. let oldOptions = null;
  17869. vue.watch(options, () => {
  17870. if (deepEqual(oldOptions, options.value)) return;
  17871. // Reset page when searching
  17872. if (oldOptions && oldOptions.search !== options.value.search) {
  17873. page.value = 1;
  17874. }
  17875. vm.emit('update:options', options.value);
  17876. oldOptions = options.value;
  17877. }, {
  17878. deep: true,
  17879. immediate: true
  17880. });
  17881. }
  17882. // Composables
  17883. // Types
  17884. const makeDataTablePaginateProps = propsFactory({
  17885. page: {
  17886. type: [Number, String],
  17887. default: 1
  17888. },
  17889. itemsPerPage: {
  17890. type: [Number, String],
  17891. default: 10
  17892. }
  17893. }, 'DataTable-paginate');
  17894. const VDataTablePaginationSymbol = Symbol.for('vuetify:data-table-pagination');
  17895. function createPagination(props) {
  17896. const page = useProxiedModel(props, 'page', undefined, value => +(value ?? 1));
  17897. const itemsPerPage = useProxiedModel(props, 'itemsPerPage', undefined, value => +(value ?? 10));
  17898. return {
  17899. page,
  17900. itemsPerPage
  17901. };
  17902. }
  17903. function providePagination(options) {
  17904. const {
  17905. page,
  17906. itemsPerPage,
  17907. itemsLength
  17908. } = options;
  17909. const startIndex = vue.computed(() => {
  17910. if (itemsPerPage.value === -1) return 0;
  17911. return itemsPerPage.value * (page.value - 1);
  17912. });
  17913. const stopIndex = vue.computed(() => {
  17914. if (itemsPerPage.value === -1) return itemsLength.value;
  17915. return Math.min(itemsLength.value, startIndex.value + itemsPerPage.value);
  17916. });
  17917. const pageCount = vue.computed(() => {
  17918. if (itemsPerPage.value === -1 || itemsLength.value === 0) return 1;
  17919. return Math.ceil(itemsLength.value / itemsPerPage.value);
  17920. });
  17921. // Don't run immediately, items may not have been loaded yet: #17966
  17922. vue.watch([page, pageCount], () => {
  17923. if (page.value > pageCount.value) {
  17924. page.value = pageCount.value;
  17925. }
  17926. });
  17927. function setItemsPerPage(value) {
  17928. itemsPerPage.value = value;
  17929. page.value = 1;
  17930. }
  17931. function nextPage() {
  17932. page.value = clamp(page.value + 1, 1, pageCount.value);
  17933. }
  17934. function prevPage() {
  17935. page.value = clamp(page.value - 1, 1, pageCount.value);
  17936. }
  17937. function setPage(value) {
  17938. page.value = clamp(value, 1, pageCount.value);
  17939. }
  17940. const data = {
  17941. page,
  17942. itemsPerPage,
  17943. startIndex,
  17944. stopIndex,
  17945. pageCount,
  17946. itemsLength,
  17947. nextPage,
  17948. prevPage,
  17949. setPage,
  17950. setItemsPerPage
  17951. };
  17952. vue.provide(VDataTablePaginationSymbol, data);
  17953. return data;
  17954. }
  17955. function usePagination() {
  17956. const data = vue.inject(VDataTablePaginationSymbol);
  17957. if (!data) throw new Error('Missing pagination!');
  17958. return data;
  17959. }
  17960. function usePaginatedItems(options) {
  17961. const vm = getCurrentInstance('usePaginatedItems');
  17962. const {
  17963. items,
  17964. startIndex,
  17965. stopIndex,
  17966. itemsPerPage
  17967. } = options;
  17968. const paginatedItems = vue.computed(() => {
  17969. if (itemsPerPage.value <= 0) return items.value;
  17970. return items.value.slice(startIndex.value, stopIndex.value);
  17971. });
  17972. vue.watch(paginatedItems, val => {
  17973. vm.emit('update:currentItems', val);
  17974. });
  17975. return {
  17976. paginatedItems
  17977. };
  17978. }
  17979. // Composables
  17980. // Types
  17981. const singleSelectStrategy = {
  17982. showSelectAll: false,
  17983. allSelected: () => [],
  17984. select: _ref => {
  17985. let {
  17986. items,
  17987. value
  17988. } = _ref;
  17989. return new Set(value ? [items[0]?.value] : []);
  17990. },
  17991. selectAll: _ref2 => {
  17992. let {
  17993. selected
  17994. } = _ref2;
  17995. return selected;
  17996. }
  17997. };
  17998. const pageSelectStrategy = {
  17999. showSelectAll: true,
  18000. allSelected: _ref3 => {
  18001. let {
  18002. currentPage
  18003. } = _ref3;
  18004. return currentPage;
  18005. },
  18006. select: _ref4 => {
  18007. let {
  18008. items,
  18009. value,
  18010. selected
  18011. } = _ref4;
  18012. for (const item of items) {
  18013. if (value) selected.add(item.value);else selected.delete(item.value);
  18014. }
  18015. return selected;
  18016. },
  18017. selectAll: _ref5 => {
  18018. let {
  18019. value,
  18020. currentPage,
  18021. selected
  18022. } = _ref5;
  18023. return pageSelectStrategy.select({
  18024. items: currentPage,
  18025. value,
  18026. selected
  18027. });
  18028. }
  18029. };
  18030. const allSelectStrategy = {
  18031. showSelectAll: true,
  18032. allSelected: _ref6 => {
  18033. let {
  18034. allItems
  18035. } = _ref6;
  18036. return allItems;
  18037. },
  18038. select: _ref7 => {
  18039. let {
  18040. items,
  18041. value,
  18042. selected
  18043. } = _ref7;
  18044. for (const item of items) {
  18045. if (value) selected.add(item.value);else selected.delete(item.value);
  18046. }
  18047. return selected;
  18048. },
  18049. selectAll: _ref8 => {
  18050. let {
  18051. value,
  18052. allItems,
  18053. selected
  18054. } = _ref8;
  18055. return allSelectStrategy.select({
  18056. items: allItems,
  18057. value,
  18058. selected
  18059. });
  18060. }
  18061. };
  18062. const makeDataTableSelectProps = propsFactory({
  18063. showSelect: Boolean,
  18064. selectStrategy: {
  18065. type: [String, Object],
  18066. default: 'page'
  18067. },
  18068. modelValue: {
  18069. type: Array,
  18070. default: () => []
  18071. },
  18072. valueComparator: {
  18073. type: Function,
  18074. default: deepEqual
  18075. }
  18076. }, 'DataTable-select');
  18077. const VDataTableSelectionSymbol = Symbol.for('vuetify:data-table-selection');
  18078. function provideSelection(props, _ref9) {
  18079. let {
  18080. allItems,
  18081. currentPage
  18082. } = _ref9;
  18083. const selected = useProxiedModel(props, 'modelValue', props.modelValue, v => {
  18084. return new Set(wrapInArray(v).map(v => {
  18085. return allItems.value.find(item => props.valueComparator(v, item.value))?.value ?? v;
  18086. }));
  18087. }, v => {
  18088. return [...v.values()];
  18089. });
  18090. const allSelectable = vue.computed(() => allItems.value.filter(item => item.selectable));
  18091. const currentPageSelectable = vue.computed(() => currentPage.value.filter(item => item.selectable));
  18092. const selectStrategy = vue.computed(() => {
  18093. if (typeof props.selectStrategy === 'object') return props.selectStrategy;
  18094. switch (props.selectStrategy) {
  18095. case 'single':
  18096. return singleSelectStrategy;
  18097. case 'all':
  18098. return allSelectStrategy;
  18099. case 'page':
  18100. default:
  18101. return pageSelectStrategy;
  18102. }
  18103. });
  18104. function isSelected(items) {
  18105. return wrapInArray(items).every(item => selected.value.has(item.value));
  18106. }
  18107. function isSomeSelected(items) {
  18108. return wrapInArray(items).some(item => selected.value.has(item.value));
  18109. }
  18110. function select(items, value) {
  18111. const newSelected = selectStrategy.value.select({
  18112. items,
  18113. value,
  18114. selected: new Set(selected.value)
  18115. });
  18116. selected.value = newSelected;
  18117. }
  18118. function toggleSelect(item) {
  18119. select([item], !isSelected([item]));
  18120. }
  18121. function selectAll(value) {
  18122. const newSelected = selectStrategy.value.selectAll({
  18123. value,
  18124. allItems: allSelectable.value,
  18125. currentPage: currentPageSelectable.value,
  18126. selected: new Set(selected.value)
  18127. });
  18128. selected.value = newSelected;
  18129. }
  18130. const someSelected = vue.computed(() => selected.value.size > 0);
  18131. const allSelected = vue.computed(() => {
  18132. const items = selectStrategy.value.allSelected({
  18133. allItems: allSelectable.value,
  18134. currentPage: currentPageSelectable.value
  18135. });
  18136. return !!items.length && isSelected(items);
  18137. });
  18138. const showSelectAll = vue.computed(() => selectStrategy.value.showSelectAll);
  18139. const data = {
  18140. toggleSelect,
  18141. select,
  18142. selectAll,
  18143. isSelected,
  18144. isSomeSelected,
  18145. someSelected,
  18146. allSelected,
  18147. showSelectAll
  18148. };
  18149. vue.provide(VDataTableSelectionSymbol, data);
  18150. return data;
  18151. }
  18152. function useSelection() {
  18153. const data = vue.inject(VDataTableSelectionSymbol);
  18154. if (!data) throw new Error('Missing selection!');
  18155. return data;
  18156. }
  18157. // Composables
  18158. // Types
  18159. const makeDataTableSortProps = propsFactory({
  18160. sortBy: {
  18161. type: Array,
  18162. default: () => []
  18163. },
  18164. customKeySort: Object,
  18165. multiSort: Boolean,
  18166. mustSort: Boolean
  18167. }, 'DataTable-sort');
  18168. const VDataTableSortSymbol = Symbol.for('vuetify:data-table-sort');
  18169. function createSort(props) {
  18170. const sortBy = useProxiedModel(props, 'sortBy');
  18171. const mustSort = vue.toRef(props, 'mustSort');
  18172. const multiSort = vue.toRef(props, 'multiSort');
  18173. return {
  18174. sortBy,
  18175. mustSort,
  18176. multiSort
  18177. };
  18178. }
  18179. function provideSort(options) {
  18180. const {
  18181. sortBy,
  18182. mustSort,
  18183. multiSort,
  18184. page
  18185. } = options;
  18186. const toggleSort = column => {
  18187. if (column.key == null) return;
  18188. let newSortBy = sortBy.value.map(x => ({
  18189. ...x
  18190. })) ?? [];
  18191. const item = newSortBy.find(x => x.key === column.key);
  18192. if (!item) {
  18193. if (multiSort.value) newSortBy = [...newSortBy, {
  18194. key: column.key,
  18195. order: 'asc'
  18196. }];else newSortBy = [{
  18197. key: column.key,
  18198. order: 'asc'
  18199. }];
  18200. } else if (item.order === 'desc') {
  18201. if (mustSort.value) {
  18202. item.order = 'asc';
  18203. } else {
  18204. newSortBy = newSortBy.filter(x => x.key !== column.key);
  18205. }
  18206. } else {
  18207. item.order = 'desc';
  18208. }
  18209. sortBy.value = newSortBy;
  18210. if (page) page.value = 1;
  18211. };
  18212. function isSorted(column) {
  18213. return !!sortBy.value.find(item => item.key === column.key);
  18214. }
  18215. const data = {
  18216. sortBy,
  18217. toggleSort,
  18218. isSorted
  18219. };
  18220. vue.provide(VDataTableSortSymbol, data);
  18221. return data;
  18222. }
  18223. function useSort() {
  18224. const data = vue.inject(VDataTableSortSymbol);
  18225. if (!data) throw new Error('Missing sort!');
  18226. return data;
  18227. }
  18228. // TODO: abstract into project composable
  18229. function useSortedItems(props, items, sortBy, options) {
  18230. const locale = useLocale();
  18231. const sortedItems = vue.computed(() => {
  18232. if (!sortBy.value.length) return items.value;
  18233. return sortItems(items.value, sortBy.value, locale.current.value, {
  18234. transform: options?.transform,
  18235. sortFunctions: {
  18236. ...props.customKeySort,
  18237. ...options?.sortFunctions?.value
  18238. },
  18239. sortRawFunctions: options?.sortRawFunctions?.value
  18240. });
  18241. });
  18242. return {
  18243. sortedItems
  18244. };
  18245. }
  18246. function sortItems(items, sortByItems, locale, options) {
  18247. const stringCollator = new Intl.Collator(locale, {
  18248. sensitivity: 'accent',
  18249. usage: 'sort'
  18250. });
  18251. const transformedItems = items.map(item => [item, options?.transform ? options.transform(item) : item]);
  18252. return transformedItems.sort((a, b) => {
  18253. for (let i = 0; i < sortByItems.length; i++) {
  18254. let hasCustomResult = false;
  18255. const sortKey = sortByItems[i].key;
  18256. const sortOrder = sortByItems[i].order ?? 'asc';
  18257. if (sortOrder === false) continue;
  18258. let sortA = getObjectValueByPath(a[1], sortKey);
  18259. let sortB = getObjectValueByPath(b[1], sortKey);
  18260. let sortARaw = a[0].raw;
  18261. let sortBRaw = b[0].raw;
  18262. if (sortOrder === 'desc') {
  18263. [sortA, sortB] = [sortB, sortA];
  18264. [sortARaw, sortBRaw] = [sortBRaw, sortARaw];
  18265. }
  18266. if (options?.sortRawFunctions?.[sortKey]) {
  18267. const customResult = options.sortRawFunctions[sortKey](sortARaw, sortBRaw);
  18268. if (customResult == null) continue;
  18269. hasCustomResult = true;
  18270. if (customResult) return customResult;
  18271. }
  18272. if (options?.sortFunctions?.[sortKey]) {
  18273. const customResult = options.sortFunctions[sortKey](sortA, sortB);
  18274. if (customResult == null) continue;
  18275. hasCustomResult = true;
  18276. if (customResult) return customResult;
  18277. }
  18278. if (hasCustomResult) continue;
  18279. // Dates should be compared numerically
  18280. if (sortA instanceof Date && sortB instanceof Date) {
  18281. return sortA.getTime() - sortB.getTime();
  18282. }
  18283. [sortA, sortB] = [sortA, sortB].map(s => s != null ? s.toString().toLocaleLowerCase() : s);
  18284. if (sortA !== sortB) {
  18285. if (isEmpty(sortA) && isEmpty(sortB)) return 0;
  18286. if (isEmpty(sortA)) return -1;
  18287. if (isEmpty(sortB)) return 1;
  18288. if (!isNaN(sortA) && !isNaN(sortB)) return Number(sortA) - Number(sortB);
  18289. return stringCollator.compare(sortA, sortB);
  18290. }
  18291. }
  18292. return 0;
  18293. }).map(_ref => {
  18294. let [item] = _ref;
  18295. return item;
  18296. });
  18297. }
  18298. // Utilities
  18299. // Types
  18300. // Composables
  18301. const makeDataIteratorItemsProps = propsFactory({
  18302. items: {
  18303. type: Array,
  18304. default: () => []
  18305. },
  18306. itemValue: {
  18307. type: [String, Array, Function],
  18308. default: 'id'
  18309. },
  18310. itemSelectable: {
  18311. type: [String, Array, Function],
  18312. default: null
  18313. },
  18314. returnObject: Boolean
  18315. }, 'DataIterator-items');
  18316. function transformItem$1(props, item) {
  18317. const value = props.returnObject ? item : getPropertyFromItem(item, props.itemValue);
  18318. const selectable = getPropertyFromItem(item, props.itemSelectable, true);
  18319. return {
  18320. type: 'item',
  18321. value,
  18322. selectable,
  18323. raw: item
  18324. };
  18325. }
  18326. function transformItems$1(props, items) {
  18327. const array = [];
  18328. for (const item of items) {
  18329. array.push(transformItem$1(props, item));
  18330. }
  18331. return array;
  18332. }
  18333. function useDataIteratorItems(props) {
  18334. const items = vue.computed(() => transformItems$1(props, props.items));
  18335. return {
  18336. items
  18337. };
  18338. }
  18339. // Types
  18340. const makeVDataIteratorProps = propsFactory({
  18341. search: String,
  18342. loading: Boolean,
  18343. ...makeComponentProps(),
  18344. ...makeDataIteratorItemsProps(),
  18345. ...makeDataTableSelectProps(),
  18346. ...makeDataTableSortProps(),
  18347. ...makeDataTablePaginateProps({
  18348. itemsPerPage: 5
  18349. }),
  18350. ...makeDataTableExpandProps(),
  18351. ...makeDataTableGroupProps(),
  18352. ...makeFilterProps(),
  18353. ...makeTagProps(),
  18354. ...makeTransitionProps({
  18355. transition: {
  18356. component: VFadeTransition,
  18357. hideOnLeave: true
  18358. }
  18359. })
  18360. }, 'VDataIterator');
  18361. const VDataIterator = genericComponent()({
  18362. name: 'VDataIterator',
  18363. props: makeVDataIteratorProps(),
  18364. emits: {
  18365. 'update:modelValue': value => true,
  18366. 'update:groupBy': value => true,
  18367. 'update:page': value => true,
  18368. 'update:itemsPerPage': value => true,
  18369. 'update:sortBy': value => true,
  18370. 'update:options': value => true,
  18371. 'update:expanded': value => true,
  18372. 'update:currentItems': value => true
  18373. },
  18374. setup(props, _ref) {
  18375. let {
  18376. slots
  18377. } = _ref;
  18378. const groupBy = useProxiedModel(props, 'groupBy');
  18379. const search = vue.toRef(props, 'search');
  18380. const {
  18381. items
  18382. } = useDataIteratorItems(props);
  18383. const {
  18384. filteredItems
  18385. } = useFilter(props, items, search, {
  18386. transform: item => item.raw
  18387. });
  18388. const {
  18389. sortBy,
  18390. multiSort,
  18391. mustSort
  18392. } = createSort(props);
  18393. const {
  18394. page,
  18395. itemsPerPage
  18396. } = createPagination(props);
  18397. const {
  18398. toggleSort
  18399. } = provideSort({
  18400. sortBy,
  18401. multiSort,
  18402. mustSort,
  18403. page
  18404. });
  18405. const {
  18406. sortByWithGroups,
  18407. opened,
  18408. extractRows,
  18409. isGroupOpen,
  18410. toggleGroup
  18411. } = provideGroupBy({
  18412. groupBy,
  18413. sortBy
  18414. });
  18415. const {
  18416. sortedItems
  18417. } = useSortedItems(props, filteredItems, sortByWithGroups, {
  18418. transform: item => item.raw
  18419. });
  18420. const {
  18421. flatItems
  18422. } = useGroupedItems(sortedItems, groupBy, opened);
  18423. const itemsLength = vue.computed(() => flatItems.value.length);
  18424. const {
  18425. startIndex,
  18426. stopIndex,
  18427. pageCount,
  18428. prevPage,
  18429. nextPage,
  18430. setItemsPerPage,
  18431. setPage
  18432. } = providePagination({
  18433. page,
  18434. itemsPerPage,
  18435. itemsLength
  18436. });
  18437. const {
  18438. paginatedItems
  18439. } = usePaginatedItems({
  18440. items: flatItems,
  18441. startIndex,
  18442. stopIndex,
  18443. itemsPerPage
  18444. });
  18445. const paginatedItemsWithoutGroups = vue.computed(() => extractRows(paginatedItems.value));
  18446. const {
  18447. isSelected,
  18448. select,
  18449. selectAll,
  18450. toggleSelect
  18451. } = provideSelection(props, {
  18452. allItems: items,
  18453. currentPage: paginatedItemsWithoutGroups
  18454. });
  18455. const {
  18456. isExpanded,
  18457. toggleExpand
  18458. } = provideExpanded(props);
  18459. useOptions({
  18460. page,
  18461. itemsPerPage,
  18462. sortBy,
  18463. groupBy,
  18464. search
  18465. });
  18466. const slotProps = vue.computed(() => ({
  18467. page: page.value,
  18468. itemsPerPage: itemsPerPage.value,
  18469. sortBy: sortBy.value,
  18470. pageCount: pageCount.value,
  18471. toggleSort,
  18472. prevPage,
  18473. nextPage,
  18474. setPage,
  18475. setItemsPerPage,
  18476. isSelected,
  18477. select,
  18478. selectAll,
  18479. toggleSelect,
  18480. isExpanded,
  18481. toggleExpand,
  18482. isGroupOpen,
  18483. toggleGroup,
  18484. items: paginatedItemsWithoutGroups.value,
  18485. groupedItems: paginatedItems.value
  18486. }));
  18487. useRender(() => vue.createVNode(props.tag, {
  18488. "class": ['v-data-iterator', {
  18489. 'v-data-iterator--loading': props.loading
  18490. }, props.class],
  18491. "style": props.style
  18492. }, {
  18493. default: () => [slots.header?.(slotProps.value), vue.createVNode(MaybeTransition, {
  18494. "transition": props.transition
  18495. }, {
  18496. default: () => [props.loading ? vue.createVNode(LoaderSlot, {
  18497. "key": "loader",
  18498. "name": "v-data-iterator",
  18499. "active": true
  18500. }, {
  18501. default: slotProps => slots.loader?.(slotProps)
  18502. }) : vue.createVNode("div", {
  18503. "key": "items"
  18504. }, [!paginatedItems.value.length ? slots['no-data']?.() : slots.default?.(slotProps.value)])]
  18505. }), slots.footer?.(slotProps.value)]
  18506. }));
  18507. return {};
  18508. }
  18509. });
  18510. // Utilities
  18511. // Types
  18512. function useRefs() {
  18513. const refs = vue.ref([]);
  18514. vue.onBeforeUpdate(() => refs.value = []);
  18515. function updateRef(e, i) {
  18516. refs.value[i] = e;
  18517. }
  18518. return {
  18519. refs,
  18520. updateRef
  18521. };
  18522. }
  18523. // Types
  18524. const makeVPaginationProps = propsFactory({
  18525. activeColor: String,
  18526. start: {
  18527. type: [Number, String],
  18528. default: 1
  18529. },
  18530. modelValue: {
  18531. type: Number,
  18532. default: props => props.start
  18533. },
  18534. disabled: Boolean,
  18535. length: {
  18536. type: [Number, String],
  18537. default: 1,
  18538. validator: val => val % 1 === 0
  18539. },
  18540. totalVisible: [Number, String],
  18541. firstIcon: {
  18542. type: IconValue,
  18543. default: '$first'
  18544. },
  18545. prevIcon: {
  18546. type: IconValue,
  18547. default: '$prev'
  18548. },
  18549. nextIcon: {
  18550. type: IconValue,
  18551. default: '$next'
  18552. },
  18553. lastIcon: {
  18554. type: IconValue,
  18555. default: '$last'
  18556. },
  18557. ariaLabel: {
  18558. type: String,
  18559. default: '$vuetify.pagination.ariaLabel.root'
  18560. },
  18561. pageAriaLabel: {
  18562. type: String,
  18563. default: '$vuetify.pagination.ariaLabel.page'
  18564. },
  18565. currentPageAriaLabel: {
  18566. type: String,
  18567. default: '$vuetify.pagination.ariaLabel.currentPage'
  18568. },
  18569. firstAriaLabel: {
  18570. type: String,
  18571. default: '$vuetify.pagination.ariaLabel.first'
  18572. },
  18573. previousAriaLabel: {
  18574. type: String,
  18575. default: '$vuetify.pagination.ariaLabel.previous'
  18576. },
  18577. nextAriaLabel: {
  18578. type: String,
  18579. default: '$vuetify.pagination.ariaLabel.next'
  18580. },
  18581. lastAriaLabel: {
  18582. type: String,
  18583. default: '$vuetify.pagination.ariaLabel.last'
  18584. },
  18585. ellipsis: {
  18586. type: String,
  18587. default: '...'
  18588. },
  18589. showFirstLastPage: Boolean,
  18590. ...makeBorderProps(),
  18591. ...makeComponentProps(),
  18592. ...makeDensityProps(),
  18593. ...makeElevationProps(),
  18594. ...makeRoundedProps(),
  18595. ...makeSizeProps(),
  18596. ...makeTagProps({
  18597. tag: 'nav'
  18598. }),
  18599. ...makeThemeProps(),
  18600. ...makeVariantProps({
  18601. variant: 'text'
  18602. })
  18603. }, 'VPagination');
  18604. const VPagination = genericComponent()({
  18605. name: 'VPagination',
  18606. props: makeVPaginationProps(),
  18607. emits: {
  18608. 'update:modelValue': value => true,
  18609. first: value => true,
  18610. prev: value => true,
  18611. next: value => true,
  18612. last: value => true
  18613. },
  18614. setup(props, _ref) {
  18615. let {
  18616. slots,
  18617. emit
  18618. } = _ref;
  18619. const page = useProxiedModel(props, 'modelValue');
  18620. const {
  18621. t,
  18622. n
  18623. } = useLocale();
  18624. const {
  18625. isRtl
  18626. } = useRtl();
  18627. const {
  18628. themeClasses
  18629. } = provideTheme(props);
  18630. const {
  18631. width
  18632. } = useDisplay();
  18633. const maxButtons = vue.shallowRef(-1);
  18634. provideDefaults(undefined, {
  18635. scoped: true
  18636. });
  18637. const {
  18638. resizeRef
  18639. } = useResizeObserver(entries => {
  18640. if (!entries.length) return;
  18641. const {
  18642. target,
  18643. contentRect
  18644. } = entries[0];
  18645. const firstItem = target.querySelector('.v-pagination__list > *');
  18646. if (!firstItem) return;
  18647. const totalWidth = contentRect.width;
  18648. const itemWidth = firstItem.offsetWidth + parseFloat(getComputedStyle(firstItem).marginRight) * 2;
  18649. maxButtons.value = getMax(totalWidth, itemWidth);
  18650. });
  18651. const length = vue.computed(() => parseInt(props.length, 10));
  18652. const start = vue.computed(() => parseInt(props.start, 10));
  18653. const totalVisible = vue.computed(() => {
  18654. if (props.totalVisible != null) return parseInt(props.totalVisible, 10);else if (maxButtons.value >= 0) return maxButtons.value;
  18655. return getMax(width.value, 58);
  18656. });
  18657. function getMax(totalWidth, itemWidth) {
  18658. const minButtons = props.showFirstLastPage ? 5 : 3;
  18659. return Math.max(0, Math.floor(
  18660. // Round to two decimal places to avoid floating point errors
  18661. +((totalWidth - itemWidth * minButtons) / itemWidth).toFixed(2)));
  18662. }
  18663. const range = vue.computed(() => {
  18664. if (length.value <= 0 || isNaN(length.value) || length.value > Number.MAX_SAFE_INTEGER) return [];
  18665. if (totalVisible.value <= 0) return [];else if (totalVisible.value === 1) return [page.value];
  18666. if (length.value <= totalVisible.value) {
  18667. return createRange(length.value, start.value);
  18668. }
  18669. const even = totalVisible.value % 2 === 0;
  18670. const middle = even ? totalVisible.value / 2 : Math.floor(totalVisible.value / 2);
  18671. const left = even ? middle : middle + 1;
  18672. const right = length.value - middle;
  18673. if (left - page.value >= 0) {
  18674. return [...createRange(Math.max(1, totalVisible.value - 1), start.value), props.ellipsis, length.value];
  18675. } else if (page.value - right >= (even ? 1 : 0)) {
  18676. const rangeLength = totalVisible.value - 1;
  18677. const rangeStart = length.value - rangeLength + start.value;
  18678. return [start.value, props.ellipsis, ...createRange(rangeLength, rangeStart)];
  18679. } else {
  18680. const rangeLength = Math.max(1, totalVisible.value - 3);
  18681. const rangeStart = rangeLength === 1 ? page.value : page.value - Math.ceil(rangeLength / 2) + start.value;
  18682. return [start.value, props.ellipsis, ...createRange(rangeLength, rangeStart), props.ellipsis, length.value];
  18683. }
  18684. });
  18685. // TODO: 'first' | 'prev' | 'next' | 'last' does not work here?
  18686. function setValue(e, value, event) {
  18687. e.preventDefault();
  18688. page.value = value;
  18689. event && emit(event, value);
  18690. }
  18691. const {
  18692. refs,
  18693. updateRef
  18694. } = useRefs();
  18695. provideDefaults({
  18696. VPaginationBtn: {
  18697. color: vue.toRef(props, 'color'),
  18698. border: vue.toRef(props, 'border'),
  18699. density: vue.toRef(props, 'density'),
  18700. size: vue.toRef(props, 'size'),
  18701. variant: vue.toRef(props, 'variant'),
  18702. rounded: vue.toRef(props, 'rounded'),
  18703. elevation: vue.toRef(props, 'elevation')
  18704. }
  18705. });
  18706. const items = vue.computed(() => {
  18707. return range.value.map((item, index) => {
  18708. const ref = e => updateRef(e, index);
  18709. if (typeof item === 'string') {
  18710. return {
  18711. isActive: false,
  18712. key: `ellipsis-${index}`,
  18713. page: item,
  18714. props: {
  18715. ref,
  18716. ellipsis: true,
  18717. icon: true,
  18718. disabled: true
  18719. }
  18720. };
  18721. } else {
  18722. const isActive = item === page.value;
  18723. return {
  18724. isActive,
  18725. key: item,
  18726. page: n(item),
  18727. props: {
  18728. ref,
  18729. ellipsis: false,
  18730. icon: true,
  18731. disabled: !!props.disabled || +props.length < 2,
  18732. color: isActive ? props.activeColor : props.color,
  18733. 'aria-current': isActive,
  18734. 'aria-label': t(isActive ? props.currentPageAriaLabel : props.pageAriaLabel, item),
  18735. onClick: e => setValue(e, item)
  18736. }
  18737. };
  18738. }
  18739. });
  18740. });
  18741. const controls = vue.computed(() => {
  18742. const prevDisabled = !!props.disabled || page.value <= start.value;
  18743. const nextDisabled = !!props.disabled || page.value >= start.value + length.value - 1;
  18744. return {
  18745. first: props.showFirstLastPage ? {
  18746. icon: isRtl.value ? props.lastIcon : props.firstIcon,
  18747. onClick: e => setValue(e, start.value, 'first'),
  18748. disabled: prevDisabled,
  18749. 'aria-label': t(props.firstAriaLabel),
  18750. 'aria-disabled': prevDisabled
  18751. } : undefined,
  18752. prev: {
  18753. icon: isRtl.value ? props.nextIcon : props.prevIcon,
  18754. onClick: e => setValue(e, page.value - 1, 'prev'),
  18755. disabled: prevDisabled,
  18756. 'aria-label': t(props.previousAriaLabel),
  18757. 'aria-disabled': prevDisabled
  18758. },
  18759. next: {
  18760. icon: isRtl.value ? props.prevIcon : props.nextIcon,
  18761. onClick: e => setValue(e, page.value + 1, 'next'),
  18762. disabled: nextDisabled,
  18763. 'aria-label': t(props.nextAriaLabel),
  18764. 'aria-disabled': nextDisabled
  18765. },
  18766. last: props.showFirstLastPage ? {
  18767. icon: isRtl.value ? props.firstIcon : props.lastIcon,
  18768. onClick: e => setValue(e, start.value + length.value - 1, 'last'),
  18769. disabled: nextDisabled,
  18770. 'aria-label': t(props.lastAriaLabel),
  18771. 'aria-disabled': nextDisabled
  18772. } : undefined
  18773. };
  18774. });
  18775. function updateFocus() {
  18776. const currentIndex = page.value - start.value;
  18777. refs.value[currentIndex]?.$el.focus();
  18778. }
  18779. function onKeydown(e) {
  18780. if (e.key === keyValues.left && !props.disabled && page.value > +props.start) {
  18781. page.value = page.value - 1;
  18782. vue.nextTick(updateFocus);
  18783. } else if (e.key === keyValues.right && !props.disabled && page.value < start.value + length.value - 1) {
  18784. page.value = page.value + 1;
  18785. vue.nextTick(updateFocus);
  18786. }
  18787. }
  18788. useRender(() => vue.createVNode(props.tag, {
  18789. "ref": resizeRef,
  18790. "class": ['v-pagination', themeClasses.value, props.class],
  18791. "style": props.style,
  18792. "role": "navigation",
  18793. "aria-label": t(props.ariaLabel),
  18794. "onKeydown": onKeydown,
  18795. "data-test": "v-pagination-root"
  18796. }, {
  18797. default: () => [vue.createVNode("ul", {
  18798. "class": "v-pagination__list"
  18799. }, [props.showFirstLastPage && vue.createVNode("li", {
  18800. "key": "first",
  18801. "class": "v-pagination__first",
  18802. "data-test": "v-pagination-first"
  18803. }, [slots.first ? slots.first(controls.value.first) : vue.createVNode(VBtn, vue.mergeProps({
  18804. "_as": "VPaginationBtn"
  18805. }, controls.value.first), null)]), vue.createVNode("li", {
  18806. "key": "prev",
  18807. "class": "v-pagination__prev",
  18808. "data-test": "v-pagination-prev"
  18809. }, [slots.prev ? slots.prev(controls.value.prev) : vue.createVNode(VBtn, vue.mergeProps({
  18810. "_as": "VPaginationBtn"
  18811. }, controls.value.prev), null)]), items.value.map((item, index) => vue.createVNode("li", {
  18812. "key": item.key,
  18813. "class": ['v-pagination__item', {
  18814. 'v-pagination__item--is-active': item.isActive
  18815. }],
  18816. "data-test": "v-pagination-item"
  18817. }, [slots.item ? slots.item(item) : vue.createVNode(VBtn, vue.mergeProps({
  18818. "_as": "VPaginationBtn"
  18819. }, item.props), {
  18820. default: () => [item.page]
  18821. })])), vue.createVNode("li", {
  18822. "key": "next",
  18823. "class": "v-pagination__next",
  18824. "data-test": "v-pagination-next"
  18825. }, [slots.next ? slots.next(controls.value.next) : vue.createVNode(VBtn, vue.mergeProps({
  18826. "_as": "VPaginationBtn"
  18827. }, controls.value.next), null)]), props.showFirstLastPage && vue.createVNode("li", {
  18828. "key": "last",
  18829. "class": "v-pagination__last",
  18830. "data-test": "v-pagination-last"
  18831. }, [slots.last ? slots.last(controls.value.last) : vue.createVNode(VBtn, vue.mergeProps({
  18832. "_as": "VPaginationBtn"
  18833. }, controls.value.last), null)])])]
  18834. }));
  18835. return {};
  18836. }
  18837. });
  18838. // Types
  18839. const makeVDataTableFooterProps = propsFactory({
  18840. prevIcon: {
  18841. type: IconValue,
  18842. default: '$prev'
  18843. },
  18844. nextIcon: {
  18845. type: IconValue,
  18846. default: '$next'
  18847. },
  18848. firstIcon: {
  18849. type: IconValue,
  18850. default: '$first'
  18851. },
  18852. lastIcon: {
  18853. type: IconValue,
  18854. default: '$last'
  18855. },
  18856. itemsPerPageText: {
  18857. type: String,
  18858. default: '$vuetify.dataFooter.itemsPerPageText'
  18859. },
  18860. pageText: {
  18861. type: String,
  18862. default: '$vuetify.dataFooter.pageText'
  18863. },
  18864. firstPageLabel: {
  18865. type: String,
  18866. default: '$vuetify.dataFooter.firstPage'
  18867. },
  18868. prevPageLabel: {
  18869. type: String,
  18870. default: '$vuetify.dataFooter.prevPage'
  18871. },
  18872. nextPageLabel: {
  18873. type: String,
  18874. default: '$vuetify.dataFooter.nextPage'
  18875. },
  18876. lastPageLabel: {
  18877. type: String,
  18878. default: '$vuetify.dataFooter.lastPage'
  18879. },
  18880. itemsPerPageOptions: {
  18881. type: Array,
  18882. default: () => [{
  18883. value: 10,
  18884. title: '10'
  18885. }, {
  18886. value: 25,
  18887. title: '25'
  18888. }, {
  18889. value: 50,
  18890. title: '50'
  18891. }, {
  18892. value: 100,
  18893. title: '100'
  18894. }, {
  18895. value: -1,
  18896. title: '$vuetify.dataFooter.itemsPerPageAll'
  18897. }]
  18898. },
  18899. showCurrentPage: Boolean
  18900. }, 'VDataTableFooter');
  18901. const VDataTableFooter = genericComponent()({
  18902. name: 'VDataTableFooter',
  18903. props: makeVDataTableFooterProps(),
  18904. setup(props, _ref) {
  18905. let {
  18906. slots
  18907. } = _ref;
  18908. const {
  18909. t
  18910. } = useLocale();
  18911. const {
  18912. page,
  18913. pageCount,
  18914. startIndex,
  18915. stopIndex,
  18916. itemsLength,
  18917. itemsPerPage,
  18918. setItemsPerPage
  18919. } = usePagination();
  18920. const itemsPerPageOptions = vue.computed(() => props.itemsPerPageOptions.map(option => {
  18921. if (typeof option === 'number') {
  18922. return {
  18923. value: option,
  18924. title: option === -1 ? t('$vuetify.dataFooter.itemsPerPageAll') : String(option)
  18925. };
  18926. }
  18927. return {
  18928. ...option,
  18929. title: !isNaN(Number(option.title)) ? option.title : t(option.title)
  18930. };
  18931. }));
  18932. useRender(() => {
  18933. const paginationProps = VPagination.filterProps(props);
  18934. return vue.createVNode("div", {
  18935. "class": "v-data-table-footer"
  18936. }, [slots.prepend?.(), vue.createVNode("div", {
  18937. "class": "v-data-table-footer__items-per-page"
  18938. }, [vue.createVNode("span", null, [t(props.itemsPerPageText)]), vue.createVNode(VSelect, {
  18939. "items": itemsPerPageOptions.value,
  18940. "modelValue": itemsPerPage.value,
  18941. "onUpdate:modelValue": v => setItemsPerPage(Number(v)),
  18942. "density": "compact",
  18943. "variant": "outlined",
  18944. "hide-details": true
  18945. }, null)]), vue.createVNode("div", {
  18946. "class": "v-data-table-footer__info"
  18947. }, [vue.createVNode("div", null, [t(props.pageText, !itemsLength.value ? 0 : startIndex.value + 1, stopIndex.value, itemsLength.value)])]), vue.createVNode("div", {
  18948. "class": "v-data-table-footer__pagination"
  18949. }, [vue.createVNode(VPagination, vue.mergeProps({
  18950. "modelValue": page.value,
  18951. "onUpdate:modelValue": $event => page.value = $event,
  18952. "density": "comfortable",
  18953. "first-aria-label": props.firstPageLabel,
  18954. "last-aria-label": props.lastPageLabel,
  18955. "length": pageCount.value,
  18956. "next-aria-label": props.nextPageLabel,
  18957. "previous-aria-label": props.prevPageLabel,
  18958. "rounded": true,
  18959. "show-first-last-page": true,
  18960. "total-visible": props.showCurrentPage ? 1 : 0,
  18961. "variant": "plain"
  18962. }, paginationProps), null)])]);
  18963. });
  18964. return {};
  18965. }
  18966. });
  18967. // Types
  18968. const VDataTableColumn = defineFunctionalComponent({
  18969. align: {
  18970. type: String,
  18971. default: 'start'
  18972. },
  18973. fixed: Boolean,
  18974. fixedOffset: [Number, String],
  18975. height: [Number, String],
  18976. lastFixed: Boolean,
  18977. noPadding: Boolean,
  18978. tag: String,
  18979. width: [Number, String],
  18980. maxWidth: [Number, String],
  18981. nowrap: Boolean
  18982. }, (props, _ref) => {
  18983. let {
  18984. slots
  18985. } = _ref;
  18986. const Tag = props.tag ?? 'td';
  18987. return vue.createVNode(Tag, {
  18988. "class": ['v-data-table__td', {
  18989. 'v-data-table-column--fixed': props.fixed,
  18990. 'v-data-table-column--last-fixed': props.lastFixed,
  18991. 'v-data-table-column--no-padding': props.noPadding,
  18992. 'v-data-table-column--nowrap': props.nowrap
  18993. }, `v-data-table-column--align-${props.align}`],
  18994. "style": {
  18995. height: convertToUnit(props.height),
  18996. width: convertToUnit(props.width),
  18997. maxWidth: convertToUnit(props.maxWidth),
  18998. left: convertToUnit(props.fixedOffset || null)
  18999. }
  19000. }, {
  19001. default: () => [slots.default?.()]
  19002. });
  19003. });
  19004. // Utilities
  19005. // Types
  19006. const makeDataTableHeaderProps = propsFactory({
  19007. headers: Array
  19008. }, 'DataTable-header');
  19009. const VDataTableHeadersSymbol = Symbol.for('vuetify:data-table-headers');
  19010. const defaultHeader = {
  19011. title: '',
  19012. sortable: false
  19013. };
  19014. const defaultActionHeader = {
  19015. ...defaultHeader,
  19016. width: 48
  19017. };
  19018. function priorityQueue() {
  19019. let arr = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : [];
  19020. const queue = arr.map(element => ({
  19021. element,
  19022. priority: 0
  19023. }));
  19024. return {
  19025. enqueue: (element, priority) => {
  19026. let added = false;
  19027. for (let i = 0; i < queue.length; i++) {
  19028. const item = queue[i];
  19029. if (item.priority > priority) {
  19030. queue.splice(i, 0, {
  19031. element,
  19032. priority
  19033. });
  19034. added = true;
  19035. break;
  19036. }
  19037. }
  19038. if (!added) queue.push({
  19039. element,
  19040. priority
  19041. });
  19042. },
  19043. size: () => queue.length,
  19044. count: () => {
  19045. let count = 0;
  19046. if (!queue.length) return 0;
  19047. const whole = Math.floor(queue[0].priority);
  19048. for (let i = 0; i < queue.length; i++) {
  19049. if (Math.floor(queue[i].priority) === whole) count += 1;
  19050. }
  19051. return count;
  19052. },
  19053. dequeue: () => {
  19054. return queue.shift();
  19055. }
  19056. };
  19057. }
  19058. function extractLeaves(item) {
  19059. let columns = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : [];
  19060. if (!item.children) {
  19061. columns.push(item);
  19062. } else {
  19063. for (const child of item.children) {
  19064. extractLeaves(child, columns);
  19065. }
  19066. }
  19067. return columns;
  19068. }
  19069. function extractKeys(headers) {
  19070. let keys = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : new Set();
  19071. for (const item of headers) {
  19072. if (item.key) keys.add(item.key);
  19073. if (item.children) {
  19074. extractKeys(item.children, keys);
  19075. }
  19076. }
  19077. return keys;
  19078. }
  19079. function getDefaultItem(item) {
  19080. if (!item.key) return undefined;
  19081. if (item.key === 'data-table-group') return defaultHeader;
  19082. if (['data-table-expand', 'data-table-select'].includes(item.key)) return defaultActionHeader;
  19083. return undefined;
  19084. }
  19085. function getDepth(item) {
  19086. let depth = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 0;
  19087. if (!item.children) return depth;
  19088. return Math.max(depth, ...item.children.map(child => getDepth(child, depth + 1)));
  19089. }
  19090. function parseFixedColumns(items) {
  19091. let seenFixed = false;
  19092. function setFixed(item) {
  19093. let parentFixed = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : false;
  19094. if (!item) return;
  19095. if (parentFixed) {
  19096. item.fixed = true;
  19097. }
  19098. if (item.fixed) {
  19099. if (item.children) {
  19100. for (let i = item.children.length - 1; i >= 0; i--) {
  19101. setFixed(item.children[i], true);
  19102. }
  19103. } else {
  19104. if (!seenFixed) {
  19105. item.lastFixed = true;
  19106. } else if (isNaN(+item.width)) {
  19107. consoleError(`Multiple fixed columns should have a static width (key: ${item.key})`);
  19108. }
  19109. seenFixed = true;
  19110. }
  19111. } else {
  19112. if (item.children) {
  19113. for (let i = item.children.length - 1; i >= 0; i--) {
  19114. setFixed(item.children[i]);
  19115. }
  19116. } else {
  19117. seenFixed = false;
  19118. }
  19119. }
  19120. }
  19121. for (let i = items.length - 1; i >= 0; i--) {
  19122. setFixed(items[i]);
  19123. }
  19124. function setFixedOffset(item) {
  19125. let fixedOffset = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 0;
  19126. if (!item) return fixedOffset;
  19127. if (item.children) {
  19128. item.fixedOffset = fixedOffset;
  19129. for (const child of item.children) {
  19130. fixedOffset = setFixedOffset(child, fixedOffset);
  19131. }
  19132. } else if (item.fixed) {
  19133. item.fixedOffset = fixedOffset;
  19134. fixedOffset += parseFloat(item.width || '0') || 0;
  19135. }
  19136. return fixedOffset;
  19137. }
  19138. let fixedOffset = 0;
  19139. for (const item of items) {
  19140. fixedOffset = setFixedOffset(item, fixedOffset);
  19141. }
  19142. }
  19143. function parse(items, maxDepth) {
  19144. const headers = [];
  19145. let currentDepth = 0;
  19146. const queue = priorityQueue(items);
  19147. while (queue.size() > 0) {
  19148. let rowSize = queue.count();
  19149. const row = [];
  19150. let fraction = 1;
  19151. while (rowSize > 0) {
  19152. const {
  19153. element: item,
  19154. priority
  19155. } = queue.dequeue();
  19156. const diff = maxDepth - currentDepth - getDepth(item);
  19157. row.push({
  19158. ...item,
  19159. rowspan: diff ?? 1,
  19160. colspan: item.children ? extractLeaves(item).length : 1
  19161. });
  19162. if (item.children) {
  19163. for (const child of item.children) {
  19164. // This internally sorts items that are on the same priority "row"
  19165. const sort = priority % 1 + fraction / Math.pow(10, currentDepth + 2);
  19166. queue.enqueue(child, currentDepth + diff + sort);
  19167. }
  19168. }
  19169. fraction += 1;
  19170. rowSize -= 1;
  19171. }
  19172. currentDepth += 1;
  19173. headers.push(row);
  19174. }
  19175. const columns = items.map(item => extractLeaves(item)).flat();
  19176. return {
  19177. columns,
  19178. headers
  19179. };
  19180. }
  19181. function convertToInternalHeaders(items) {
  19182. const internalHeaders = [];
  19183. for (const item of items) {
  19184. const defaultItem = {
  19185. ...getDefaultItem(item),
  19186. ...item
  19187. };
  19188. const key = defaultItem.key ?? (typeof defaultItem.value === 'string' ? defaultItem.value : null);
  19189. const value = defaultItem.value ?? key ?? null;
  19190. const internalItem = {
  19191. ...defaultItem,
  19192. key,
  19193. value,
  19194. sortable: defaultItem.sortable ?? (defaultItem.key != null || !!defaultItem.sort),
  19195. children: defaultItem.children ? convertToInternalHeaders(defaultItem.children) : undefined
  19196. };
  19197. internalHeaders.push(internalItem);
  19198. }
  19199. return internalHeaders;
  19200. }
  19201. function createHeaders(props, options) {
  19202. const headers = vue.ref([]);
  19203. const columns = vue.ref([]);
  19204. const sortFunctions = vue.ref({});
  19205. const sortRawFunctions = vue.ref({});
  19206. const filterFunctions = vue.ref({});
  19207. vue.watchEffect(() => {
  19208. const _headers = props.headers || Object.keys(props.items[0] ?? {}).map(key => ({
  19209. key,
  19210. title: vue.capitalize(key)
  19211. }));
  19212. const items = _headers.slice();
  19213. const keys = extractKeys(items);
  19214. if (options?.groupBy?.value.length && !keys.has('data-table-group')) {
  19215. items.unshift({
  19216. key: 'data-table-group',
  19217. title: 'Group'
  19218. });
  19219. }
  19220. if (options?.showSelect?.value && !keys.has('data-table-select')) {
  19221. items.unshift({
  19222. key: 'data-table-select'
  19223. });
  19224. }
  19225. if (options?.showExpand?.value && !keys.has('data-table-expand')) {
  19226. items.push({
  19227. key: 'data-table-expand'
  19228. });
  19229. }
  19230. const internalHeaders = convertToInternalHeaders(items);
  19231. parseFixedColumns(internalHeaders);
  19232. const maxDepth = Math.max(...internalHeaders.map(item => getDepth(item))) + 1;
  19233. const parsed = parse(internalHeaders, maxDepth);
  19234. headers.value = parsed.headers;
  19235. columns.value = parsed.columns;
  19236. const flatHeaders = parsed.headers.flat(1);
  19237. for (const header of flatHeaders) {
  19238. if (!header.key) continue;
  19239. if (header.sortable) {
  19240. if (header.sort) {
  19241. sortFunctions.value[header.key] = header.sort;
  19242. }
  19243. if (header.sortRaw) {
  19244. sortRawFunctions.value[header.key] = header.sortRaw;
  19245. }
  19246. }
  19247. if (header.filter) {
  19248. filterFunctions.value[header.key] = header.filter;
  19249. }
  19250. }
  19251. });
  19252. const data = {
  19253. headers,
  19254. columns,
  19255. sortFunctions,
  19256. sortRawFunctions,
  19257. filterFunctions
  19258. };
  19259. vue.provide(VDataTableHeadersSymbol, data);
  19260. return data;
  19261. }
  19262. function useHeaders() {
  19263. const data = vue.inject(VDataTableHeadersSymbol);
  19264. if (!data) throw new Error('Missing headers!');
  19265. return data;
  19266. }
  19267. // Types
  19268. const makeVDataTableHeadersProps = propsFactory({
  19269. color: String,
  19270. sticky: Boolean,
  19271. disableSort: Boolean,
  19272. multiSort: Boolean,
  19273. sortAscIcon: {
  19274. type: IconValue,
  19275. default: '$sortAsc'
  19276. },
  19277. sortDescIcon: {
  19278. type: IconValue,
  19279. default: '$sortDesc'
  19280. },
  19281. headerProps: {
  19282. type: Object
  19283. },
  19284. ...makeDisplayProps(),
  19285. ...makeLoaderProps()
  19286. }, 'VDataTableHeaders');
  19287. const VDataTableHeaders = genericComponent()({
  19288. name: 'VDataTableHeaders',
  19289. props: makeVDataTableHeadersProps(),
  19290. setup(props, _ref) {
  19291. let {
  19292. slots
  19293. } = _ref;
  19294. const {
  19295. t
  19296. } = useLocale();
  19297. const {
  19298. toggleSort,
  19299. sortBy,
  19300. isSorted
  19301. } = useSort();
  19302. const {
  19303. someSelected,
  19304. allSelected,
  19305. selectAll,
  19306. showSelectAll
  19307. } = useSelection();
  19308. const {
  19309. columns,
  19310. headers
  19311. } = useHeaders();
  19312. const {
  19313. loaderClasses
  19314. } = useLoader(props);
  19315. function getFixedStyles(column, y) {
  19316. if (!props.sticky && !column.fixed) return undefined;
  19317. return {
  19318. position: 'sticky',
  19319. left: column.fixed ? convertToUnit(column.fixedOffset) : undefined,
  19320. top: props.sticky ? `calc(var(--v-table-header-height) * ${y})` : undefined
  19321. };
  19322. }
  19323. function getSortIcon(column) {
  19324. const item = sortBy.value.find(item => item.key === column.key);
  19325. if (!item) return props.sortAscIcon;
  19326. return item.order === 'asc' ? props.sortAscIcon : props.sortDescIcon;
  19327. }
  19328. const {
  19329. backgroundColorClasses,
  19330. backgroundColorStyles
  19331. } = useBackgroundColor(props, 'color');
  19332. const {
  19333. displayClasses,
  19334. mobile
  19335. } = useDisplay(props);
  19336. const slotProps = vue.computed(() => ({
  19337. headers: headers.value,
  19338. columns: columns.value,
  19339. toggleSort,
  19340. isSorted,
  19341. sortBy: sortBy.value,
  19342. someSelected: someSelected.value,
  19343. allSelected: allSelected.value,
  19344. selectAll,
  19345. getSortIcon
  19346. }));
  19347. const headerCellClasses = vue.computed(() => ['v-data-table__th', {
  19348. 'v-data-table__th--sticky': props.sticky
  19349. }, displayClasses.value, loaderClasses.value]);
  19350. const VDataTableHeaderCell = _ref2 => {
  19351. let {
  19352. column,
  19353. x,
  19354. y
  19355. } = _ref2;
  19356. const noPadding = column.key === 'data-table-select' || column.key === 'data-table-expand';
  19357. const headerProps = vue.mergeProps(props.headerProps ?? {}, column.headerProps ?? {});
  19358. return vue.createVNode(VDataTableColumn, vue.mergeProps({
  19359. "tag": "th",
  19360. "align": column.align,
  19361. "class": [{
  19362. 'v-data-table__th--sortable': column.sortable && !props.disableSort,
  19363. 'v-data-table__th--sorted': isSorted(column),
  19364. 'v-data-table__th--fixed': column.fixed
  19365. }, ...headerCellClasses.value],
  19366. "style": {
  19367. width: convertToUnit(column.width),
  19368. minWidth: convertToUnit(column.minWidth),
  19369. maxWidth: convertToUnit(column.maxWidth),
  19370. ...getFixedStyles(column, y)
  19371. },
  19372. "colspan": column.colspan,
  19373. "rowspan": column.rowspan,
  19374. "onClick": column.sortable ? () => toggleSort(column) : undefined,
  19375. "fixed": column.fixed,
  19376. "nowrap": column.nowrap,
  19377. "lastFixed": column.lastFixed,
  19378. "noPadding": noPadding
  19379. }, headerProps), {
  19380. default: () => {
  19381. const columnSlotName = `header.${column.key}`;
  19382. const columnSlotProps = {
  19383. column,
  19384. selectAll,
  19385. isSorted,
  19386. toggleSort,
  19387. sortBy: sortBy.value,
  19388. someSelected: someSelected.value,
  19389. allSelected: allSelected.value,
  19390. getSortIcon
  19391. };
  19392. if (slots[columnSlotName]) return slots[columnSlotName](columnSlotProps);
  19393. if (column.key === 'data-table-select') {
  19394. return slots['header.data-table-select']?.(columnSlotProps) ?? (showSelectAll.value && vue.createVNode(VCheckboxBtn, {
  19395. "modelValue": allSelected.value,
  19396. "indeterminate": someSelected.value && !allSelected.value,
  19397. "onUpdate:modelValue": selectAll
  19398. }, null));
  19399. }
  19400. return vue.createVNode("div", {
  19401. "class": "v-data-table-header__content"
  19402. }, [vue.createVNode("span", null, [column.title]), column.sortable && !props.disableSort && vue.createVNode(VIcon, {
  19403. "key": "icon",
  19404. "class": "v-data-table-header__sort-icon",
  19405. "icon": getSortIcon(column)
  19406. }, null), props.multiSort && isSorted(column) && vue.createVNode("div", {
  19407. "key": "badge",
  19408. "class": ['v-data-table-header__sort-badge', ...backgroundColorClasses.value],
  19409. "style": backgroundColorStyles.value
  19410. }, [sortBy.value.findIndex(x => x.key === column.key) + 1])]);
  19411. }
  19412. });
  19413. };
  19414. const VDataTableMobileHeaderCell = () => {
  19415. const headerProps = vue.mergeProps(props.headerProps ?? {} ?? {});
  19416. const displayItems = vue.computed(() => {
  19417. return columns.value.filter(column => column?.sortable && !props.disableSort);
  19418. });
  19419. const appendIcon = vue.computed(() => {
  19420. const showSelectColumn = columns.value.find(column => column.key === 'data-table-select');
  19421. if (showSelectColumn == null) return;
  19422. return allSelected.value ? '$checkboxOn' : someSelected.value ? '$checkboxIndeterminate' : '$checkboxOff';
  19423. });
  19424. return vue.createVNode(VDataTableColumn, vue.mergeProps({
  19425. "tag": "th",
  19426. "class": [...headerCellClasses.value],
  19427. "colspan": headers.value.length + 1
  19428. }, headerProps), {
  19429. default: () => [vue.createVNode("div", {
  19430. "class": "v-data-table-header__content"
  19431. }, [vue.createVNode(VSelect, {
  19432. "chips": true,
  19433. "class": "v-data-table__td-sort-select",
  19434. "clearable": true,
  19435. "density": "default",
  19436. "items": displayItems.value,
  19437. "label": t('$vuetify.dataTable.sortBy'),
  19438. "multiple": props.multiSort,
  19439. "variant": "underlined",
  19440. "onClick:clear": () => sortBy.value = [],
  19441. "appendIcon": appendIcon.value,
  19442. "onClick:append": () => selectAll(!allSelected.value)
  19443. }, {
  19444. ...slots,
  19445. chip: props => vue.createVNode(VChip, {
  19446. "onClick": props.item.raw?.sortable ? () => toggleSort(props.item.raw) : undefined,
  19447. "onMousedown": e => {
  19448. e.preventDefault();
  19449. e.stopPropagation();
  19450. }
  19451. }, {
  19452. default: () => [props.item.title, vue.createVNode(VIcon, {
  19453. "class": ['v-data-table__td-sort-icon', isSorted(props.item.raw) && 'v-data-table__td-sort-icon-active'],
  19454. "icon": getSortIcon(props.item.raw),
  19455. "size": "small"
  19456. }, null)]
  19457. })
  19458. })])]
  19459. });
  19460. };
  19461. useRender(() => {
  19462. return mobile.value ? vue.createVNode("tr", null, [vue.createVNode(VDataTableMobileHeaderCell, null, null)]) : vue.createVNode(vue.Fragment, null, [slots.headers ? slots.headers(slotProps.value) : headers.value.map((row, y) => vue.createVNode("tr", null, [row.map((column, x) => vue.createVNode(VDataTableHeaderCell, {
  19463. "column": column,
  19464. "x": x,
  19465. "y": y
  19466. }, null))])), props.loading && vue.createVNode("tr", {
  19467. "class": "v-data-table-progress"
  19468. }, [vue.createVNode("th", {
  19469. "colspan": columns.value.length
  19470. }, [vue.createVNode(LoaderSlot, {
  19471. "name": "v-data-table-progress",
  19472. "absolute": true,
  19473. "active": true,
  19474. "color": typeof props.loading === 'boolean' ? undefined : props.loading,
  19475. "indeterminate": true
  19476. }, {
  19477. default: slots.loader
  19478. })])])]);
  19479. });
  19480. }
  19481. });
  19482. // Types
  19483. const makeVDataTableGroupHeaderRowProps = propsFactory({
  19484. item: {
  19485. type: Object,
  19486. required: true
  19487. }
  19488. }, 'VDataTableGroupHeaderRow');
  19489. const VDataTableGroupHeaderRow = genericComponent()({
  19490. name: 'VDataTableGroupHeaderRow',
  19491. props: makeVDataTableGroupHeaderRowProps(),
  19492. setup(props, _ref) {
  19493. let {
  19494. slots
  19495. } = _ref;
  19496. const {
  19497. isGroupOpen,
  19498. toggleGroup,
  19499. extractRows
  19500. } = useGroupBy();
  19501. const {
  19502. isSelected,
  19503. isSomeSelected,
  19504. select
  19505. } = useSelection();
  19506. const {
  19507. columns
  19508. } = useHeaders();
  19509. const rows = vue.computed(() => {
  19510. return extractRows([props.item]);
  19511. });
  19512. return () => vue.createVNode("tr", {
  19513. "class": "v-data-table-group-header-row",
  19514. "style": {
  19515. '--v-data-table-group-header-row-depth': props.item.depth
  19516. }
  19517. }, [columns.value.map(column => {
  19518. if (column.key === 'data-table-group') {
  19519. const icon = isGroupOpen(props.item) ? '$expand' : '$next';
  19520. const onClick = () => toggleGroup(props.item);
  19521. return slots['data-table-group']?.({
  19522. item: props.item,
  19523. count: rows.value.length,
  19524. props: {
  19525. icon,
  19526. onClick
  19527. }
  19528. }) ?? vue.createVNode(VDataTableColumn, {
  19529. "class": "v-data-table-group-header-row__column"
  19530. }, {
  19531. default: () => [vue.createVNode(VBtn, {
  19532. "size": "small",
  19533. "variant": "text",
  19534. "icon": icon,
  19535. "onClick": onClick
  19536. }, null), vue.createVNode("span", null, [props.item.value]), vue.createVNode("span", null, [vue.createTextVNode("("), rows.value.length, vue.createTextVNode(")")])]
  19537. });
  19538. }
  19539. if (column.key === 'data-table-select') {
  19540. const modelValue = isSelected(rows.value);
  19541. const indeterminate = isSomeSelected(rows.value) && !modelValue;
  19542. const selectGroup = v => select(rows.value, v);
  19543. return slots['data-table-select']?.({
  19544. props: {
  19545. modelValue,
  19546. indeterminate,
  19547. 'onUpdate:modelValue': selectGroup
  19548. }
  19549. }) ?? vue.createVNode("td", null, [vue.createVNode(VCheckboxBtn, {
  19550. "modelValue": modelValue,
  19551. "indeterminate": indeterminate,
  19552. "onUpdate:modelValue": selectGroup
  19553. }, null)]);
  19554. }
  19555. return vue.createVNode("td", null, null);
  19556. })]);
  19557. }
  19558. });
  19559. // Types
  19560. const makeVDataTableRowProps = propsFactory({
  19561. index: Number,
  19562. item: Object,
  19563. cellProps: [Object, Function],
  19564. onClick: EventProp(),
  19565. onContextmenu: EventProp(),
  19566. onDblclick: EventProp(),
  19567. ...makeDisplayProps()
  19568. }, 'VDataTableRow');
  19569. const VDataTableRow = genericComponent()({
  19570. name: 'VDataTableRow',
  19571. props: makeVDataTableRowProps(),
  19572. setup(props, _ref) {
  19573. let {
  19574. slots
  19575. } = _ref;
  19576. const {
  19577. displayClasses,
  19578. mobile
  19579. } = useDisplay(props, 'v-data-table__tr');
  19580. const {
  19581. isSelected,
  19582. toggleSelect,
  19583. someSelected,
  19584. allSelected,
  19585. selectAll
  19586. } = useSelection();
  19587. const {
  19588. isExpanded,
  19589. toggleExpand
  19590. } = useExpanded();
  19591. const {
  19592. toggleSort,
  19593. sortBy,
  19594. isSorted
  19595. } = useSort();
  19596. const {
  19597. columns
  19598. } = useHeaders();
  19599. useRender(() => vue.createVNode("tr", {
  19600. "class": ['v-data-table__tr', {
  19601. 'v-data-table__tr--clickable': !!(props.onClick || props.onContextmenu || props.onDblclick)
  19602. }, displayClasses.value],
  19603. "onClick": props.onClick,
  19604. "onContextmenu": props.onContextmenu,
  19605. "onDblclick": props.onDblclick
  19606. }, [props.item && columns.value.map((column, i) => {
  19607. const item = props.item;
  19608. const slotName = `item.${column.key}`;
  19609. const headerSlotName = `header.${column.key}`;
  19610. const slotProps = {
  19611. index: props.index,
  19612. item: item.raw,
  19613. internalItem: item,
  19614. value: getObjectValueByPath(item.columns, column.key),
  19615. column,
  19616. isSelected,
  19617. toggleSelect,
  19618. isExpanded,
  19619. toggleExpand
  19620. };
  19621. const columnSlotProps = {
  19622. column,
  19623. selectAll,
  19624. isSorted,
  19625. toggleSort,
  19626. sortBy: sortBy.value,
  19627. someSelected: someSelected.value,
  19628. allSelected: allSelected.value,
  19629. getSortIcon: () => ''
  19630. };
  19631. const cellProps = typeof props.cellProps === 'function' ? props.cellProps({
  19632. index: slotProps.index,
  19633. item: slotProps.item,
  19634. internalItem: slotProps.internalItem,
  19635. value: slotProps.value,
  19636. column
  19637. }) : props.cellProps;
  19638. const columnCellProps = typeof column.cellProps === 'function' ? column.cellProps({
  19639. index: slotProps.index,
  19640. item: slotProps.item,
  19641. internalItem: slotProps.internalItem,
  19642. value: slotProps.value
  19643. }) : column.cellProps;
  19644. return vue.createVNode(VDataTableColumn, vue.mergeProps({
  19645. "align": column.align,
  19646. "class": {
  19647. 'v-data-table__td--expanded-row': column.key === 'data-table-expand',
  19648. 'v-data-table__td--select-row': column.key === 'data-table-select'
  19649. },
  19650. "fixed": column.fixed,
  19651. "fixedOffset": column.fixedOffset,
  19652. "lastFixed": column.lastFixed,
  19653. "maxWidth": !mobile.value ? column.maxWidth : undefined,
  19654. "noPadding": column.key === 'data-table-select' || column.key === 'data-table-expand',
  19655. "nowrap": column.nowrap,
  19656. "width": !mobile.value ? column.width : undefined
  19657. }, cellProps, columnCellProps), {
  19658. default: () => {
  19659. if (slots[slotName] && !mobile.value) return slots[slotName]?.(slotProps);
  19660. if (column.key === 'data-table-select') {
  19661. return slots['item.data-table-select']?.(slotProps) ?? vue.createVNode(VCheckboxBtn, {
  19662. "disabled": !item.selectable,
  19663. "modelValue": isSelected([item]),
  19664. "onClick": vue.withModifiers(() => toggleSelect(item), ['stop'])
  19665. }, null);
  19666. }
  19667. if (column.key === 'data-table-expand') {
  19668. return slots['item.data-table-expand']?.(slotProps) ?? vue.createVNode(VBtn, {
  19669. "icon": isExpanded(item) ? '$collapse' : '$expand',
  19670. "size": "small",
  19671. "variant": "text",
  19672. "onClick": vue.withModifiers(() => toggleExpand(item), ['stop'])
  19673. }, null);
  19674. }
  19675. const displayValue = vue.toDisplayString(slotProps.value);
  19676. return !mobile.value ? displayValue : vue.createVNode(vue.Fragment, null, [vue.createVNode("div", {
  19677. "class": "v-data-table__td-title"
  19678. }, [slots[headerSlotName]?.(columnSlotProps) ?? column.title]), vue.createVNode("div", {
  19679. "class": "v-data-table__td-value"
  19680. }, [slots[slotName]?.(slotProps) ?? displayValue])]);
  19681. }
  19682. });
  19683. })]));
  19684. }
  19685. });
  19686. // Types
  19687. const makeVDataTableRowsProps = propsFactory({
  19688. loading: [Boolean, String],
  19689. loadingText: {
  19690. type: String,
  19691. default: '$vuetify.dataIterator.loadingText'
  19692. },
  19693. hideNoData: Boolean,
  19694. items: {
  19695. type: Array,
  19696. default: () => []
  19697. },
  19698. noDataText: {
  19699. type: String,
  19700. default: '$vuetify.noDataText'
  19701. },
  19702. rowProps: [Object, Function],
  19703. cellProps: [Object, Function],
  19704. ...makeDisplayProps()
  19705. }, 'VDataTableRows');
  19706. const VDataTableRows = genericComponent()({
  19707. name: 'VDataTableRows',
  19708. inheritAttrs: false,
  19709. props: makeVDataTableRowsProps(),
  19710. setup(props, _ref) {
  19711. let {
  19712. attrs,
  19713. slots
  19714. } = _ref;
  19715. const {
  19716. columns
  19717. } = useHeaders();
  19718. const {
  19719. expandOnClick,
  19720. toggleExpand,
  19721. isExpanded
  19722. } = useExpanded();
  19723. const {
  19724. isSelected,
  19725. toggleSelect
  19726. } = useSelection();
  19727. const {
  19728. toggleGroup,
  19729. isGroupOpen
  19730. } = useGroupBy();
  19731. const {
  19732. t
  19733. } = useLocale();
  19734. const {
  19735. mobile
  19736. } = useDisplay(props);
  19737. useRender(() => {
  19738. if (props.loading && (!props.items.length || slots.loading)) {
  19739. return vue.createVNode("tr", {
  19740. "class": "v-data-table-rows-loading",
  19741. "key": "loading"
  19742. }, [vue.createVNode("td", {
  19743. "colspan": columns.value.length
  19744. }, [slots.loading?.() ?? t(props.loadingText)])]);
  19745. }
  19746. if (!props.loading && !props.items.length && !props.hideNoData) {
  19747. return vue.createVNode("tr", {
  19748. "class": "v-data-table-rows-no-data",
  19749. "key": "no-data"
  19750. }, [vue.createVNode("td", {
  19751. "colspan": columns.value.length
  19752. }, [slots['no-data']?.() ?? t(props.noDataText)])]);
  19753. }
  19754. return vue.createVNode(vue.Fragment, null, [props.items.map((item, index) => {
  19755. if (item.type === 'group') {
  19756. const slotProps = {
  19757. index,
  19758. item,
  19759. columns: columns.value,
  19760. isExpanded,
  19761. toggleExpand,
  19762. isSelected,
  19763. toggleSelect,
  19764. toggleGroup,
  19765. isGroupOpen
  19766. };
  19767. return slots['group-header'] ? slots['group-header'](slotProps) : vue.createVNode(VDataTableGroupHeaderRow, vue.mergeProps({
  19768. "key": `group-header_${item.id}`,
  19769. "item": item
  19770. }, getPrefixedEventHandlers(attrs, ':group-header', () => slotProps)), slots);
  19771. }
  19772. const slotProps = {
  19773. index,
  19774. item: item.raw,
  19775. internalItem: item,
  19776. columns: columns.value,
  19777. isExpanded,
  19778. toggleExpand,
  19779. isSelected,
  19780. toggleSelect
  19781. };
  19782. const itemSlotProps = {
  19783. ...slotProps,
  19784. props: vue.mergeProps({
  19785. key: `item_${item.key ?? item.index}`,
  19786. onClick: expandOnClick.value ? () => {
  19787. toggleExpand(item);
  19788. } : undefined,
  19789. index,
  19790. item,
  19791. cellProps: props.cellProps,
  19792. mobile: mobile.value
  19793. }, getPrefixedEventHandlers(attrs, ':row', () => slotProps), typeof props.rowProps === 'function' ? props.rowProps({
  19794. item: slotProps.item,
  19795. index: slotProps.index,
  19796. internalItem: slotProps.internalItem
  19797. }) : props.rowProps)
  19798. };
  19799. return vue.createVNode(vue.Fragment, {
  19800. "key": itemSlotProps.props.key
  19801. }, [slots.item ? slots.item(itemSlotProps) : vue.createVNode(VDataTableRow, itemSlotProps.props, slots), isExpanded(item) && slots['expanded-row']?.(slotProps)]);
  19802. })]);
  19803. });
  19804. return {};
  19805. }
  19806. });
  19807. const makeVTableProps = propsFactory({
  19808. fixedHeader: Boolean,
  19809. fixedFooter: Boolean,
  19810. height: [Number, String],
  19811. hover: Boolean,
  19812. ...makeComponentProps(),
  19813. ...makeDensityProps(),
  19814. ...makeTagProps(),
  19815. ...makeThemeProps()
  19816. }, 'VTable');
  19817. const VTable = genericComponent()({
  19818. name: 'VTable',
  19819. props: makeVTableProps(),
  19820. setup(props, _ref) {
  19821. let {
  19822. slots,
  19823. emit
  19824. } = _ref;
  19825. const {
  19826. themeClasses
  19827. } = provideTheme(props);
  19828. const {
  19829. densityClasses
  19830. } = useDensity(props);
  19831. useRender(() => vue.createVNode(props.tag, {
  19832. "class": ['v-table', {
  19833. 'v-table--fixed-height': !!props.height,
  19834. 'v-table--fixed-header': props.fixedHeader,
  19835. 'v-table--fixed-footer': props.fixedFooter,
  19836. 'v-table--has-top': !!slots.top,
  19837. 'v-table--has-bottom': !!slots.bottom,
  19838. 'v-table--hover': props.hover
  19839. }, themeClasses.value, densityClasses.value, props.class],
  19840. "style": props.style
  19841. }, {
  19842. default: () => [slots.top?.(), slots.default ? vue.createVNode("div", {
  19843. "class": "v-table__wrapper",
  19844. "style": {
  19845. height: convertToUnit(props.height)
  19846. }
  19847. }, [vue.createVNode("table", null, [slots.default()])]) : slots.wrapper?.(), slots.bottom?.()]
  19848. }));
  19849. return {};
  19850. }
  19851. });
  19852. // Utilities
  19853. // Types
  19854. // Composables
  19855. const makeDataTableItemsProps = propsFactory({
  19856. items: {
  19857. type: Array,
  19858. default: () => []
  19859. },
  19860. itemValue: {
  19861. type: [String, Array, Function],
  19862. default: 'id'
  19863. },
  19864. itemSelectable: {
  19865. type: [String, Array, Function],
  19866. default: null
  19867. },
  19868. rowProps: [Object, Function],
  19869. cellProps: [Object, Function],
  19870. returnObject: Boolean
  19871. }, 'DataTable-items');
  19872. function transformItem(props, item, index, columns) {
  19873. const value = props.returnObject ? item : getPropertyFromItem(item, props.itemValue);
  19874. const selectable = getPropertyFromItem(item, props.itemSelectable, true);
  19875. const itemColumns = columns.reduce((obj, column) => {
  19876. if (column.key != null) obj[column.key] = getPropertyFromItem(item, column.value);
  19877. return obj;
  19878. }, {});
  19879. return {
  19880. type: 'item',
  19881. key: props.returnObject ? getPropertyFromItem(item, props.itemValue) : value,
  19882. index,
  19883. value,
  19884. selectable,
  19885. columns: itemColumns,
  19886. raw: item
  19887. };
  19888. }
  19889. function transformItems(props, items, columns) {
  19890. return items.map((item, index) => transformItem(props, item, index, columns));
  19891. }
  19892. function useDataTableItems(props, columns) {
  19893. const items = vue.computed(() => transformItems(props, props.items, columns.value));
  19894. return {
  19895. items
  19896. };
  19897. }
  19898. // Types
  19899. const makeDataTableProps = propsFactory({
  19900. ...makeVDataTableRowsProps(),
  19901. hideDefaultBody: Boolean,
  19902. hideDefaultFooter: Boolean,
  19903. hideDefaultHeader: Boolean,
  19904. width: [String, Number],
  19905. search: String,
  19906. ...makeDataTableExpandProps(),
  19907. ...makeDataTableGroupProps(),
  19908. ...makeDataTableHeaderProps(),
  19909. ...makeDataTableItemsProps(),
  19910. ...makeDataTableSelectProps(),
  19911. ...makeDataTableSortProps(),
  19912. ...makeVDataTableHeadersProps(),
  19913. ...makeVTableProps()
  19914. }, 'DataTable');
  19915. const makeVDataTableProps = propsFactory({
  19916. ...makeDataTablePaginateProps(),
  19917. ...makeDataTableProps(),
  19918. ...makeFilterProps(),
  19919. ...makeVDataTableFooterProps()
  19920. }, 'VDataTable');
  19921. const VDataTable = genericComponent()({
  19922. name: 'VDataTable',
  19923. props: makeVDataTableProps(),
  19924. emits: {
  19925. 'update:modelValue': value => true,
  19926. 'update:page': value => true,
  19927. 'update:itemsPerPage': value => true,
  19928. 'update:sortBy': value => true,
  19929. 'update:options': value => true,
  19930. 'update:groupBy': value => true,
  19931. 'update:expanded': value => true,
  19932. 'update:currentItems': value => true
  19933. },
  19934. setup(props, _ref) {
  19935. let {
  19936. attrs,
  19937. slots
  19938. } = _ref;
  19939. const {
  19940. groupBy
  19941. } = createGroupBy(props);
  19942. const {
  19943. sortBy,
  19944. multiSort,
  19945. mustSort
  19946. } = createSort(props);
  19947. const {
  19948. page,
  19949. itemsPerPage
  19950. } = createPagination(props);
  19951. const {
  19952. disableSort
  19953. } = vue.toRefs(props);
  19954. const {
  19955. columns,
  19956. headers,
  19957. sortFunctions,
  19958. sortRawFunctions,
  19959. filterFunctions
  19960. } = createHeaders(props, {
  19961. groupBy,
  19962. showSelect: vue.toRef(props, 'showSelect'),
  19963. showExpand: vue.toRef(props, 'showExpand')
  19964. });
  19965. const {
  19966. items
  19967. } = useDataTableItems(props, columns);
  19968. const search = vue.toRef(props, 'search');
  19969. const {
  19970. filteredItems
  19971. } = useFilter(props, items, search, {
  19972. transform: item => item.columns,
  19973. customKeyFilter: filterFunctions
  19974. });
  19975. const {
  19976. toggleSort
  19977. } = provideSort({
  19978. sortBy,
  19979. multiSort,
  19980. mustSort,
  19981. page
  19982. });
  19983. const {
  19984. sortByWithGroups,
  19985. opened,
  19986. extractRows,
  19987. isGroupOpen,
  19988. toggleGroup
  19989. } = provideGroupBy({
  19990. groupBy,
  19991. sortBy,
  19992. disableSort
  19993. });
  19994. const {
  19995. sortedItems
  19996. } = useSortedItems(props, filteredItems, sortByWithGroups, {
  19997. transform: item => ({
  19998. ...item.raw,
  19999. ...item.columns
  20000. }),
  20001. sortFunctions,
  20002. sortRawFunctions
  20003. });
  20004. const {
  20005. flatItems
  20006. } = useGroupedItems(sortedItems, groupBy, opened);
  20007. const itemsLength = vue.computed(() => flatItems.value.length);
  20008. const {
  20009. startIndex,
  20010. stopIndex,
  20011. pageCount,
  20012. setItemsPerPage
  20013. } = providePagination({
  20014. page,
  20015. itemsPerPage,
  20016. itemsLength
  20017. });
  20018. const {
  20019. paginatedItems
  20020. } = usePaginatedItems({
  20021. items: flatItems,
  20022. startIndex,
  20023. stopIndex,
  20024. itemsPerPage
  20025. });
  20026. const paginatedItemsWithoutGroups = vue.computed(() => extractRows(paginatedItems.value));
  20027. const {
  20028. isSelected,
  20029. select,
  20030. selectAll,
  20031. toggleSelect,
  20032. someSelected,
  20033. allSelected
  20034. } = provideSelection(props, {
  20035. allItems: items,
  20036. currentPage: paginatedItemsWithoutGroups
  20037. });
  20038. const {
  20039. isExpanded,
  20040. toggleExpand
  20041. } = provideExpanded(props);
  20042. useOptions({
  20043. page,
  20044. itemsPerPage,
  20045. sortBy,
  20046. groupBy,
  20047. search
  20048. });
  20049. provideDefaults({
  20050. VDataTableRows: {
  20051. hideNoData: vue.toRef(props, 'hideNoData'),
  20052. noDataText: vue.toRef(props, 'noDataText'),
  20053. loading: vue.toRef(props, 'loading'),
  20054. loadingText: vue.toRef(props, 'loadingText')
  20055. }
  20056. });
  20057. const slotProps = vue.computed(() => ({
  20058. page: page.value,
  20059. itemsPerPage: itemsPerPage.value,
  20060. sortBy: sortBy.value,
  20061. pageCount: pageCount.value,
  20062. toggleSort,
  20063. setItemsPerPage,
  20064. someSelected: someSelected.value,
  20065. allSelected: allSelected.value,
  20066. isSelected,
  20067. select,
  20068. selectAll,
  20069. toggleSelect,
  20070. isExpanded,
  20071. toggleExpand,
  20072. isGroupOpen,
  20073. toggleGroup,
  20074. items: paginatedItemsWithoutGroups.value.map(item => item.raw),
  20075. internalItems: paginatedItemsWithoutGroups.value,
  20076. groupedItems: paginatedItems.value,
  20077. columns: columns.value,
  20078. headers: headers.value
  20079. }));
  20080. useRender(() => {
  20081. const dataTableFooterProps = VDataTableFooter.filterProps(props);
  20082. const dataTableHeadersProps = VDataTableHeaders.filterProps(props);
  20083. const dataTableRowsProps = VDataTableRows.filterProps(props);
  20084. const tableProps = VTable.filterProps(props);
  20085. return vue.createVNode(VTable, vue.mergeProps({
  20086. "class": ['v-data-table', {
  20087. 'v-data-table--show-select': props.showSelect,
  20088. 'v-data-table--loading': props.loading
  20089. }, props.class],
  20090. "style": props.style
  20091. }, tableProps), {
  20092. top: () => slots.top?.(slotProps.value),
  20093. default: () => slots.default ? slots.default(slotProps.value) : vue.createVNode(vue.Fragment, null, [slots.colgroup?.(slotProps.value), !props.hideDefaultHeader && vue.createVNode("thead", {
  20094. "key": "thead"
  20095. }, [vue.createVNode(VDataTableHeaders, dataTableHeadersProps, slots)]), slots.thead?.(slotProps.value), !props.hideDefaultBody && vue.createVNode("tbody", null, [slots['body.prepend']?.(slotProps.value), slots.body ? slots.body(slotProps.value) : vue.createVNode(VDataTableRows, vue.mergeProps(attrs, dataTableRowsProps, {
  20096. "items": paginatedItems.value
  20097. }), slots), slots['body.append']?.(slotProps.value)]), slots.tbody?.(slotProps.value), slots.tfoot?.(slotProps.value)]),
  20098. bottom: () => slots.bottom ? slots.bottom(slotProps.value) : !props.hideDefaultFooter && vue.createVNode(vue.Fragment, null, [vue.createVNode(VDivider, null, null), vue.createVNode(VDataTableFooter, dataTableFooterProps, {
  20099. prepend: slots['footer.prepend']
  20100. })])
  20101. });
  20102. });
  20103. return {};
  20104. }
  20105. });
  20106. // Types
  20107. const makeVDataTableVirtualProps = propsFactory({
  20108. ...makeDataTableProps(),
  20109. ...makeDataTableGroupProps(),
  20110. ...makeVirtualProps(),
  20111. ...makeFilterProps()
  20112. }, 'VDataTableVirtual');
  20113. const VDataTableVirtual = genericComponent()({
  20114. name: 'VDataTableVirtual',
  20115. props: makeVDataTableVirtualProps(),
  20116. emits: {
  20117. 'update:modelValue': value => true,
  20118. 'update:sortBy': value => true,
  20119. 'update:options': value => true,
  20120. 'update:groupBy': value => true,
  20121. 'update:expanded': value => true
  20122. },
  20123. setup(props, _ref) {
  20124. let {
  20125. attrs,
  20126. slots
  20127. } = _ref;
  20128. const {
  20129. groupBy
  20130. } = createGroupBy(props);
  20131. const {
  20132. sortBy,
  20133. multiSort,
  20134. mustSort
  20135. } = createSort(props);
  20136. const {
  20137. disableSort
  20138. } = vue.toRefs(props);
  20139. const {
  20140. columns,
  20141. headers,
  20142. filterFunctions,
  20143. sortFunctions,
  20144. sortRawFunctions
  20145. } = createHeaders(props, {
  20146. groupBy,
  20147. showSelect: vue.toRef(props, 'showSelect'),
  20148. showExpand: vue.toRef(props, 'showExpand')
  20149. });
  20150. const {
  20151. items
  20152. } = useDataTableItems(props, columns);
  20153. const search = vue.toRef(props, 'search');
  20154. const {
  20155. filteredItems
  20156. } = useFilter(props, items, search, {
  20157. transform: item => item.columns,
  20158. customKeyFilter: filterFunctions
  20159. });
  20160. const {
  20161. toggleSort
  20162. } = provideSort({
  20163. sortBy,
  20164. multiSort,
  20165. mustSort
  20166. });
  20167. const {
  20168. sortByWithGroups,
  20169. opened,
  20170. extractRows,
  20171. isGroupOpen,
  20172. toggleGroup
  20173. } = provideGroupBy({
  20174. groupBy,
  20175. sortBy,
  20176. disableSort
  20177. });
  20178. const {
  20179. sortedItems
  20180. } = useSortedItems(props, filteredItems, sortByWithGroups, {
  20181. transform: item => ({
  20182. ...item.raw,
  20183. ...item.columns
  20184. }),
  20185. sortFunctions,
  20186. sortRawFunctions
  20187. });
  20188. const {
  20189. flatItems
  20190. } = useGroupedItems(sortedItems, groupBy, opened);
  20191. const allItems = vue.computed(() => extractRows(flatItems.value));
  20192. const {
  20193. isSelected,
  20194. select,
  20195. selectAll,
  20196. toggleSelect,
  20197. someSelected,
  20198. allSelected
  20199. } = provideSelection(props, {
  20200. allItems,
  20201. currentPage: allItems
  20202. });
  20203. const {
  20204. isExpanded,
  20205. toggleExpand
  20206. } = provideExpanded(props);
  20207. const {
  20208. containerRef,
  20209. markerRef,
  20210. paddingTop,
  20211. paddingBottom,
  20212. computedItems,
  20213. handleItemResize,
  20214. handleScroll,
  20215. handleScrollend
  20216. } = useVirtual(props, flatItems);
  20217. const displayItems = vue.computed(() => computedItems.value.map(item => item.raw));
  20218. useOptions({
  20219. sortBy,
  20220. page: vue.shallowRef(1),
  20221. itemsPerPage: vue.shallowRef(-1),
  20222. groupBy,
  20223. search
  20224. });
  20225. provideDefaults({
  20226. VDataTableRows: {
  20227. hideNoData: vue.toRef(props, 'hideNoData'),
  20228. noDataText: vue.toRef(props, 'noDataText'),
  20229. loading: vue.toRef(props, 'loading'),
  20230. loadingText: vue.toRef(props, 'loadingText')
  20231. }
  20232. });
  20233. const slotProps = vue.computed(() => ({
  20234. sortBy: sortBy.value,
  20235. toggleSort,
  20236. someSelected: someSelected.value,
  20237. allSelected: allSelected.value,
  20238. isSelected,
  20239. select,
  20240. selectAll,
  20241. toggleSelect,
  20242. isExpanded,
  20243. toggleExpand,
  20244. isGroupOpen,
  20245. toggleGroup,
  20246. items: allItems.value.map(item => item.raw),
  20247. internalItems: allItems.value,
  20248. groupedItems: flatItems.value,
  20249. columns: columns.value,
  20250. headers: headers.value
  20251. }));
  20252. useRender(() => {
  20253. const dataTableHeadersProps = VDataTableHeaders.filterProps(props);
  20254. const dataTableRowsProps = VDataTableRows.filterProps(props);
  20255. const tableProps = VTable.filterProps(props);
  20256. return vue.createVNode(VTable, vue.mergeProps({
  20257. "class": ['v-data-table', {
  20258. 'v-data-table--loading': props.loading
  20259. }, props.class],
  20260. "style": props.style
  20261. }, tableProps), {
  20262. top: () => slots.top?.(slotProps.value),
  20263. wrapper: () => vue.createVNode("div", {
  20264. "ref": containerRef,
  20265. "onScrollPassive": handleScroll,
  20266. "onScrollend": handleScrollend,
  20267. "class": "v-table__wrapper",
  20268. "style": {
  20269. height: convertToUnit(props.height)
  20270. }
  20271. }, [vue.createVNode("table", null, [slots.colgroup?.(slotProps.value), !props.hideDefaultHeader && vue.createVNode("thead", {
  20272. "key": "thead"
  20273. }, [vue.createVNode(VDataTableHeaders, vue.mergeProps(dataTableHeadersProps, {
  20274. "sticky": props.fixedHeader
  20275. }), slots)]), !props.hideDefaultBody && vue.createVNode("tbody", null, [vue.createVNode("tr", {
  20276. "ref": markerRef,
  20277. "style": {
  20278. height: convertToUnit(paddingTop.value),
  20279. border: 0
  20280. }
  20281. }, [vue.createVNode("td", {
  20282. "colspan": columns.value.length,
  20283. "style": {
  20284. height: 0,
  20285. border: 0
  20286. }
  20287. }, null)]), slots['body.prepend']?.(slotProps.value), vue.createVNode(VDataTableRows, vue.mergeProps(attrs, dataTableRowsProps, {
  20288. "items": displayItems.value
  20289. }), {
  20290. ...slots,
  20291. item: itemSlotProps => vue.createVNode(VVirtualScrollItem, {
  20292. "key": itemSlotProps.internalItem.index,
  20293. "renderless": true,
  20294. "onUpdate:height": height => handleItemResize(itemSlotProps.internalItem.index, height)
  20295. }, {
  20296. default: _ref2 => {
  20297. let {
  20298. itemRef
  20299. } = _ref2;
  20300. return slots.item?.({
  20301. ...itemSlotProps,
  20302. itemRef
  20303. }) ?? vue.createVNode(VDataTableRow, vue.mergeProps(itemSlotProps.props, {
  20304. "ref": itemRef,
  20305. "key": itemSlotProps.internalItem.index,
  20306. "index": itemSlotProps.internalItem.index
  20307. }), slots);
  20308. }
  20309. })
  20310. }), slots['body.append']?.(slotProps.value), vue.createVNode("tr", {
  20311. "style": {
  20312. height: convertToUnit(paddingBottom.value),
  20313. border: 0
  20314. }
  20315. }, [vue.createVNode("td", {
  20316. "colspan": columns.value.length,
  20317. "style": {
  20318. height: 0,
  20319. border: 0
  20320. }
  20321. }, null)])])])]),
  20322. bottom: () => slots.bottom?.(slotProps.value)
  20323. });
  20324. });
  20325. }
  20326. });
  20327. // Types
  20328. const makeVDataTableServerProps = propsFactory({
  20329. itemsLength: {
  20330. type: [Number, String],
  20331. required: true
  20332. },
  20333. ...makeDataTablePaginateProps(),
  20334. ...makeDataTableProps(),
  20335. ...makeVDataTableFooterProps()
  20336. }, 'VDataTableServer');
  20337. const VDataTableServer = genericComponent()({
  20338. name: 'VDataTableServer',
  20339. props: makeVDataTableServerProps(),
  20340. emits: {
  20341. 'update:modelValue': value => true,
  20342. 'update:page': page => true,
  20343. 'update:itemsPerPage': page => true,
  20344. 'update:sortBy': sortBy => true,
  20345. 'update:options': options => true,
  20346. 'update:expanded': options => true,
  20347. 'update:groupBy': value => true
  20348. },
  20349. setup(props, _ref) {
  20350. let {
  20351. attrs,
  20352. slots
  20353. } = _ref;
  20354. const {
  20355. groupBy
  20356. } = createGroupBy(props);
  20357. const {
  20358. sortBy,
  20359. multiSort,
  20360. mustSort
  20361. } = createSort(props);
  20362. const {
  20363. page,
  20364. itemsPerPage
  20365. } = createPagination(props);
  20366. const {
  20367. disableSort
  20368. } = vue.toRefs(props);
  20369. const itemsLength = vue.computed(() => parseInt(props.itemsLength, 10));
  20370. const {
  20371. columns,
  20372. headers
  20373. } = createHeaders(props, {
  20374. groupBy,
  20375. showSelect: vue.toRef(props, 'showSelect'),
  20376. showExpand: vue.toRef(props, 'showExpand')
  20377. });
  20378. const {
  20379. items
  20380. } = useDataTableItems(props, columns);
  20381. const {
  20382. toggleSort
  20383. } = provideSort({
  20384. sortBy,
  20385. multiSort,
  20386. mustSort,
  20387. page
  20388. });
  20389. const {
  20390. opened,
  20391. isGroupOpen,
  20392. toggleGroup,
  20393. extractRows
  20394. } = provideGroupBy({
  20395. groupBy,
  20396. sortBy,
  20397. disableSort
  20398. });
  20399. const {
  20400. pageCount,
  20401. setItemsPerPage
  20402. } = providePagination({
  20403. page,
  20404. itemsPerPage,
  20405. itemsLength
  20406. });
  20407. const {
  20408. flatItems
  20409. } = useGroupedItems(items, groupBy, opened);
  20410. const {
  20411. isSelected,
  20412. select,
  20413. selectAll,
  20414. toggleSelect,
  20415. someSelected,
  20416. allSelected
  20417. } = provideSelection(props, {
  20418. allItems: items,
  20419. currentPage: items
  20420. });
  20421. const {
  20422. isExpanded,
  20423. toggleExpand
  20424. } = provideExpanded(props);
  20425. const itemsWithoutGroups = vue.computed(() => extractRows(items.value));
  20426. useOptions({
  20427. page,
  20428. itemsPerPage,
  20429. sortBy,
  20430. groupBy,
  20431. search: vue.toRef(props, 'search')
  20432. });
  20433. vue.provide('v-data-table', {
  20434. toggleSort,
  20435. sortBy
  20436. });
  20437. provideDefaults({
  20438. VDataTableRows: {
  20439. hideNoData: vue.toRef(props, 'hideNoData'),
  20440. noDataText: vue.toRef(props, 'noDataText'),
  20441. loading: vue.toRef(props, 'loading'),
  20442. loadingText: vue.toRef(props, 'loadingText')
  20443. }
  20444. });
  20445. const slotProps = vue.computed(() => ({
  20446. page: page.value,
  20447. itemsPerPage: itemsPerPage.value,
  20448. sortBy: sortBy.value,
  20449. pageCount: pageCount.value,
  20450. toggleSort,
  20451. setItemsPerPage,
  20452. someSelected: someSelected.value,
  20453. allSelected: allSelected.value,
  20454. isSelected,
  20455. select,
  20456. selectAll,
  20457. toggleSelect,
  20458. isExpanded,
  20459. toggleExpand,
  20460. isGroupOpen,
  20461. toggleGroup,
  20462. items: itemsWithoutGroups.value.map(item => item.raw),
  20463. internalItems: itemsWithoutGroups.value,
  20464. groupedItems: flatItems.value,
  20465. columns: columns.value,
  20466. headers: headers.value
  20467. }));
  20468. useRender(() => {
  20469. const dataTableFooterProps = VDataTableFooter.filterProps(props);
  20470. const dataTableHeadersProps = VDataTableHeaders.filterProps(props);
  20471. const dataTableRowsProps = VDataTableRows.filterProps(props);
  20472. const tableProps = VTable.filterProps(props);
  20473. return vue.createVNode(VTable, vue.mergeProps({
  20474. "class": ['v-data-table', {
  20475. 'v-data-table--loading': props.loading
  20476. }, props.class],
  20477. "style": props.style
  20478. }, tableProps), {
  20479. top: () => slots.top?.(slotProps.value),
  20480. default: () => slots.default ? slots.default(slotProps.value) : vue.createVNode(vue.Fragment, null, [slots.colgroup?.(slotProps.value), !props.hideDefaultHeader && vue.createVNode("thead", {
  20481. "key": "thead",
  20482. "class": "v-data-table__thead",
  20483. "role": "rowgroup"
  20484. }, [vue.createVNode(VDataTableHeaders, vue.mergeProps(dataTableHeadersProps, {
  20485. "sticky": props.fixedHeader
  20486. }), slots)]), slots.thead?.(slotProps.value), !props.hideDefaultBody && vue.createVNode("tbody", {
  20487. "class": "v-data-table__tbody",
  20488. "role": "rowgroup"
  20489. }, [slots['body.prepend']?.(slotProps.value), slots.body ? slots.body(slotProps.value) : vue.createVNode(VDataTableRows, vue.mergeProps(attrs, dataTableRowsProps, {
  20490. "items": flatItems.value
  20491. }), slots), slots['body.append']?.(slotProps.value)]), slots.tbody?.(slotProps.value), slots.tfoot?.(slotProps.value)]),
  20492. bottom: () => slots.bottom ? slots.bottom(slotProps.value) : !props.hideDefaultFooter && vue.createVNode(vue.Fragment, null, [vue.createVNode(VDivider, null, null), vue.createVNode(VDataTableFooter, dataTableFooterProps, {
  20493. prepend: slots['footer.prepend']
  20494. })])
  20495. });
  20496. });
  20497. }
  20498. });
  20499. const makeVContainerProps = propsFactory({
  20500. fluid: {
  20501. type: Boolean,
  20502. default: false
  20503. },
  20504. ...makeComponentProps(),
  20505. ...makeDimensionProps(),
  20506. ...makeTagProps()
  20507. }, 'VContainer');
  20508. const VContainer = genericComponent()({
  20509. name: 'VContainer',
  20510. props: makeVContainerProps(),
  20511. setup(props, _ref) {
  20512. let {
  20513. slots
  20514. } = _ref;
  20515. const {
  20516. rtlClasses
  20517. } = useRtl();
  20518. const {
  20519. dimensionStyles
  20520. } = useDimension(props);
  20521. useRender(() => vue.createVNode(props.tag, {
  20522. "class": ['v-container', {
  20523. 'v-container--fluid': props.fluid
  20524. }, rtlClasses.value, props.class],
  20525. "style": [dimensionStyles.value, props.style]
  20526. }, slots));
  20527. return {};
  20528. }
  20529. });
  20530. // Styles
  20531. // Types
  20532. const breakpointProps = (() => {
  20533. return breakpoints.reduce((props, val) => {
  20534. props[val] = {
  20535. type: [Boolean, String, Number],
  20536. default: false
  20537. };
  20538. return props;
  20539. }, {});
  20540. })();
  20541. const offsetProps = (() => {
  20542. return breakpoints.reduce((props, val) => {
  20543. const offsetKey = 'offset' + vue.capitalize(val);
  20544. props[offsetKey] = {
  20545. type: [String, Number],
  20546. default: null
  20547. };
  20548. return props;
  20549. }, {});
  20550. })();
  20551. const orderProps = (() => {
  20552. return breakpoints.reduce((props, val) => {
  20553. const orderKey = 'order' + vue.capitalize(val);
  20554. props[orderKey] = {
  20555. type: [String, Number],
  20556. default: null
  20557. };
  20558. return props;
  20559. }, {});
  20560. })();
  20561. const propMap$1 = {
  20562. col: Object.keys(breakpointProps),
  20563. offset: Object.keys(offsetProps),
  20564. order: Object.keys(orderProps)
  20565. };
  20566. function breakpointClass$1(type, prop, val) {
  20567. let className = type;
  20568. if (val == null || val === false) {
  20569. return undefined;
  20570. }
  20571. if (prop) {
  20572. const breakpoint = prop.replace(type, '');
  20573. className += `-${breakpoint}`;
  20574. }
  20575. if (type === 'col') {
  20576. className = 'v-' + className;
  20577. }
  20578. // Handling the boolean style prop when accepting [Boolean, String, Number]
  20579. // means Vue will not convert <v-col sm></v-col> to sm: true for us.
  20580. // Since the default is false, an empty string indicates the prop's presence.
  20581. if (type === 'col' && (val === '' || val === true)) {
  20582. // .v-col-md
  20583. return className.toLowerCase();
  20584. }
  20585. // .order-md-6
  20586. className += `-${val}`;
  20587. return className.toLowerCase();
  20588. }
  20589. const ALIGN_SELF_VALUES = ['auto', 'start', 'end', 'center', 'baseline', 'stretch'];
  20590. const makeVColProps = propsFactory({
  20591. cols: {
  20592. type: [Boolean, String, Number],
  20593. default: false
  20594. },
  20595. ...breakpointProps,
  20596. offset: {
  20597. type: [String, Number],
  20598. default: null
  20599. },
  20600. ...offsetProps,
  20601. order: {
  20602. type: [String, Number],
  20603. default: null
  20604. },
  20605. ...orderProps,
  20606. alignSelf: {
  20607. type: String,
  20608. default: null,
  20609. validator: str => ALIGN_SELF_VALUES.includes(str)
  20610. },
  20611. ...makeComponentProps(),
  20612. ...makeTagProps()
  20613. }, 'VCol');
  20614. const VCol = genericComponent()({
  20615. name: 'VCol',
  20616. props: makeVColProps(),
  20617. setup(props, _ref) {
  20618. let {
  20619. slots
  20620. } = _ref;
  20621. const classes = vue.computed(() => {
  20622. const classList = [];
  20623. // Loop through `col`, `offset`, `order` breakpoint props
  20624. let type;
  20625. for (type in propMap$1) {
  20626. propMap$1[type].forEach(prop => {
  20627. const value = props[prop];
  20628. const className = breakpointClass$1(type, prop, value);
  20629. if (className) classList.push(className);
  20630. });
  20631. }
  20632. const hasColClasses = classList.some(className => className.startsWith('v-col-'));
  20633. classList.push({
  20634. // Default to .v-col if no other col-{bp}-* classes generated nor `cols` specified.
  20635. 'v-col': !hasColClasses || !props.cols,
  20636. [`v-col-${props.cols}`]: props.cols,
  20637. [`offset-${props.offset}`]: props.offset,
  20638. [`order-${props.order}`]: props.order,
  20639. [`align-self-${props.alignSelf}`]: props.alignSelf
  20640. });
  20641. return classList;
  20642. });
  20643. return () => vue.h(props.tag, {
  20644. class: [classes.value, props.class],
  20645. style: props.style
  20646. }, slots.default?.());
  20647. }
  20648. });
  20649. // Styles
  20650. // Types
  20651. const ALIGNMENT = ['start', 'end', 'center'];
  20652. const SPACE = ['space-between', 'space-around', 'space-evenly'];
  20653. function makeRowProps(prefix, def) {
  20654. return breakpoints.reduce((props, val) => {
  20655. const prefixKey = prefix + vue.capitalize(val);
  20656. props[prefixKey] = def();
  20657. return props;
  20658. }, {});
  20659. }
  20660. const ALIGN_VALUES = [...ALIGNMENT, 'baseline', 'stretch'];
  20661. const alignValidator = str => ALIGN_VALUES.includes(str);
  20662. const alignProps = makeRowProps('align', () => ({
  20663. type: String,
  20664. default: null,
  20665. validator: alignValidator
  20666. }));
  20667. const JUSTIFY_VALUES = [...ALIGNMENT, ...SPACE];
  20668. const justifyValidator = str => JUSTIFY_VALUES.includes(str);
  20669. const justifyProps = makeRowProps('justify', () => ({
  20670. type: String,
  20671. default: null,
  20672. validator: justifyValidator
  20673. }));
  20674. const ALIGN_CONTENT_VALUES = [...ALIGNMENT, ...SPACE, 'stretch'];
  20675. const alignContentValidator = str => ALIGN_CONTENT_VALUES.includes(str);
  20676. const alignContentProps = makeRowProps('alignContent', () => ({
  20677. type: String,
  20678. default: null,
  20679. validator: alignContentValidator
  20680. }));
  20681. const propMap = {
  20682. align: Object.keys(alignProps),
  20683. justify: Object.keys(justifyProps),
  20684. alignContent: Object.keys(alignContentProps)
  20685. };
  20686. const classMap = {
  20687. align: 'align',
  20688. justify: 'justify',
  20689. alignContent: 'align-content'
  20690. };
  20691. function breakpointClass(type, prop, val) {
  20692. let className = classMap[type];
  20693. if (val == null) {
  20694. return undefined;
  20695. }
  20696. if (prop) {
  20697. // alignSm -> Sm
  20698. const breakpoint = prop.replace(type, '');
  20699. className += `-${breakpoint}`;
  20700. }
  20701. // .align-items-sm-center
  20702. className += `-${val}`;
  20703. return className.toLowerCase();
  20704. }
  20705. const makeVRowProps = propsFactory({
  20706. dense: Boolean,
  20707. noGutters: Boolean,
  20708. align: {
  20709. type: String,
  20710. default: null,
  20711. validator: alignValidator
  20712. },
  20713. ...alignProps,
  20714. justify: {
  20715. type: String,
  20716. default: null,
  20717. validator: justifyValidator
  20718. },
  20719. ...justifyProps,
  20720. alignContent: {
  20721. type: String,
  20722. default: null,
  20723. validator: alignContentValidator
  20724. },
  20725. ...alignContentProps,
  20726. ...makeComponentProps(),
  20727. ...makeTagProps()
  20728. }, 'VRow');
  20729. const VRow = genericComponent()({
  20730. name: 'VRow',
  20731. props: makeVRowProps(),
  20732. setup(props, _ref) {
  20733. let {
  20734. slots
  20735. } = _ref;
  20736. const classes = vue.computed(() => {
  20737. const classList = [];
  20738. // Loop through `align`, `justify`, `alignContent` breakpoint props
  20739. let type;
  20740. for (type in propMap) {
  20741. propMap[type].forEach(prop => {
  20742. const value = props[prop];
  20743. const className = breakpointClass(type, prop, value);
  20744. if (className) classList.push(className);
  20745. });
  20746. }
  20747. classList.push({
  20748. 'v-row--no-gutters': props.noGutters,
  20749. 'v-row--dense': props.dense,
  20750. [`align-${props.align}`]: props.align,
  20751. [`justify-${props.justify}`]: props.justify,
  20752. [`align-content-${props.alignContent}`]: props.alignContent
  20753. });
  20754. return classList;
  20755. });
  20756. return () => vue.h(props.tag, {
  20757. class: ['v-row', classes.value, props.class],
  20758. style: props.style
  20759. }, slots.default?.());
  20760. }
  20761. });
  20762. // Styles
  20763. const VSpacer = createSimpleFunctional('v-spacer', 'div', 'VSpacer');
  20764. // Types
  20765. const makeVDatePickerControlsProps = propsFactory({
  20766. active: {
  20767. type: [String, Array],
  20768. default: undefined
  20769. },
  20770. disabled: {
  20771. type: [Boolean, String, Array],
  20772. default: false
  20773. },
  20774. nextIcon: {
  20775. type: IconValue,
  20776. default: '$next'
  20777. },
  20778. prevIcon: {
  20779. type: IconValue,
  20780. default: '$prev'
  20781. },
  20782. modeIcon: {
  20783. type: IconValue,
  20784. default: '$subgroup'
  20785. },
  20786. text: String,
  20787. viewMode: {
  20788. type: String,
  20789. default: 'month'
  20790. }
  20791. }, 'VDatePickerControls');
  20792. const VDatePickerControls = genericComponent()({
  20793. name: 'VDatePickerControls',
  20794. props: makeVDatePickerControlsProps(),
  20795. emits: {
  20796. 'click:year': () => true,
  20797. 'click:month': () => true,
  20798. 'click:prev': () => true,
  20799. 'click:next': () => true,
  20800. 'click:text': () => true
  20801. },
  20802. setup(props, _ref) {
  20803. let {
  20804. emit
  20805. } = _ref;
  20806. const disableMonth = vue.computed(() => {
  20807. return Array.isArray(props.disabled) ? props.disabled.includes('text') : !!props.disabled;
  20808. });
  20809. const disableYear = vue.computed(() => {
  20810. return Array.isArray(props.disabled) ? props.disabled.includes('mode') : !!props.disabled;
  20811. });
  20812. const disablePrev = vue.computed(() => {
  20813. return Array.isArray(props.disabled) ? props.disabled.includes('prev') : !!props.disabled;
  20814. });
  20815. const disableNext = vue.computed(() => {
  20816. return Array.isArray(props.disabled) ? props.disabled.includes('next') : !!props.disabled;
  20817. });
  20818. function onClickPrev() {
  20819. emit('click:prev');
  20820. }
  20821. function onClickNext() {
  20822. emit('click:next');
  20823. }
  20824. function onClickYear() {
  20825. emit('click:year');
  20826. }
  20827. function onClickMonth() {
  20828. emit('click:month');
  20829. }
  20830. useRender(() => {
  20831. // TODO: add slot support and scope defaults
  20832. return vue.createVNode("div", {
  20833. "class": ['v-date-picker-controls']
  20834. }, [vue.createVNode(VBtn, {
  20835. "class": "v-date-picker-controls__month-btn",
  20836. "disabled": disableMonth.value,
  20837. "text": props.text,
  20838. "variant": "text",
  20839. "rounded": true,
  20840. "onClick": onClickMonth
  20841. }, null), vue.createVNode(VBtn, {
  20842. "key": "mode-btn",
  20843. "class": "v-date-picker-controls__mode-btn",
  20844. "disabled": disableYear.value,
  20845. "density": "comfortable",
  20846. "icon": props.modeIcon,
  20847. "variant": "text",
  20848. "onClick": onClickYear
  20849. }, null), vue.createVNode(VSpacer, {
  20850. "key": "mode-spacer"
  20851. }, null), vue.createVNode("div", {
  20852. "key": "month-buttons",
  20853. "class": "v-date-picker-controls__month"
  20854. }, [vue.createVNode(VBtn, {
  20855. "disabled": disablePrev.value,
  20856. "icon": props.prevIcon,
  20857. "variant": "text",
  20858. "onClick": onClickPrev
  20859. }, null), vue.createVNode(VBtn, {
  20860. "disabled": disableNext.value,
  20861. "icon": props.nextIcon,
  20862. "variant": "text",
  20863. "onClick": onClickNext
  20864. }, null)])]);
  20865. });
  20866. return {};
  20867. }
  20868. });
  20869. // Types
  20870. const makeVDatePickerHeaderProps = propsFactory({
  20871. appendIcon: IconValue,
  20872. color: String,
  20873. header: String,
  20874. transition: String,
  20875. onClick: EventProp()
  20876. }, 'VDatePickerHeader');
  20877. const VDatePickerHeader = genericComponent()({
  20878. name: 'VDatePickerHeader',
  20879. props: makeVDatePickerHeaderProps(),
  20880. emits: {
  20881. click: () => true,
  20882. 'click:append': () => true
  20883. },
  20884. setup(props, _ref) {
  20885. let {
  20886. emit,
  20887. slots
  20888. } = _ref;
  20889. const {
  20890. backgroundColorClasses,
  20891. backgroundColorStyles
  20892. } = useBackgroundColor(props, 'color');
  20893. function onClick() {
  20894. emit('click');
  20895. }
  20896. function onClickAppend() {
  20897. emit('click:append');
  20898. }
  20899. useRender(() => {
  20900. const hasContent = !!(slots.default || props.header);
  20901. const hasAppend = !!(slots.append || props.appendIcon);
  20902. return vue.createVNode("div", {
  20903. "class": ['v-date-picker-header', {
  20904. 'v-date-picker-header--clickable': !!props.onClick
  20905. }, backgroundColorClasses.value],
  20906. "style": backgroundColorStyles.value,
  20907. "onClick": onClick
  20908. }, [slots.prepend && vue.createVNode("div", {
  20909. "key": "prepend",
  20910. "class": "v-date-picker-header__prepend"
  20911. }, [slots.prepend()]), hasContent && vue.createVNode(MaybeTransition, {
  20912. "key": "content",
  20913. "name": props.transition
  20914. }, {
  20915. default: () => [vue.createVNode("div", {
  20916. "key": props.header,
  20917. "class": "v-date-picker-header__content"
  20918. }, [slots.default?.() ?? props.header])]
  20919. }), hasAppend && vue.createVNode("div", {
  20920. "class": "v-date-picker-header__append"
  20921. }, [!slots.append ? vue.createVNode(VBtn, {
  20922. "key": "append-btn",
  20923. "icon": props.appendIcon,
  20924. "variant": "text",
  20925. "onClick": onClickAppend
  20926. }, null) : vue.createVNode(VDefaultsProvider, {
  20927. "key": "append-defaults",
  20928. "disabled": !props.appendIcon,
  20929. "defaults": {
  20930. VBtn: {
  20931. icon: props.appendIcon,
  20932. variant: 'text'
  20933. }
  20934. }
  20935. }, {
  20936. default: () => [slots.append?.()]
  20937. })])]);
  20938. });
  20939. return {};
  20940. }
  20941. });
  20942. // Composables
  20943. // Types
  20944. // Types
  20945. // Composables
  20946. const makeCalendarProps = propsFactory({
  20947. allowedDates: [Array, Function],
  20948. disabled: Boolean,
  20949. displayValue: null,
  20950. modelValue: Array,
  20951. month: [Number, String],
  20952. max: null,
  20953. min: null,
  20954. showAdjacentMonths: Boolean,
  20955. year: [Number, String],
  20956. weekdays: {
  20957. type: Array,
  20958. default: () => [0, 1, 2, 3, 4, 5, 6]
  20959. },
  20960. weeksInMonth: {
  20961. type: String,
  20962. default: 'dynamic'
  20963. },
  20964. firstDayOfWeek: [Number, String]
  20965. }, 'calendar');
  20966. function useCalendar(props) {
  20967. const adapter = useDate();
  20968. const model = useProxiedModel(props, 'modelValue', [], v => wrapInArray(v));
  20969. const displayValue = vue.computed(() => {
  20970. if (props.displayValue) return adapter.date(props.displayValue);
  20971. if (model.value.length > 0) return adapter.date(model.value[0]);
  20972. if (props.min) return adapter.date(props.min);
  20973. if (Array.isArray(props.allowedDates)) return adapter.date(props.allowedDates[0]);
  20974. return adapter.date();
  20975. });
  20976. const year = useProxiedModel(props, 'year', undefined, v => {
  20977. const value = v != null ? Number(v) : adapter.getYear(displayValue.value);
  20978. return adapter.startOfYear(adapter.setYear(adapter.date(), value));
  20979. }, v => adapter.getYear(v));
  20980. const month = useProxiedModel(props, 'month', undefined, v => {
  20981. const value = v != null ? Number(v) : adapter.getMonth(displayValue.value);
  20982. const date = adapter.setYear(adapter.startOfMonth(adapter.date()), adapter.getYear(year.value));
  20983. return adapter.setMonth(date, value);
  20984. }, v => adapter.getMonth(v));
  20985. const weekDays = vue.computed(() => {
  20986. const firstDayOfWeek = Number(props.firstDayOfWeek ?? 0);
  20987. return props.weekdays.map(day => (day + firstDayOfWeek) % 7);
  20988. });
  20989. const weeksInMonth = vue.computed(() => {
  20990. const weeks = adapter.getWeekArray(month.value, props.firstDayOfWeek);
  20991. const days = weeks.flat();
  20992. // Make sure there's always 6 weeks in month (6 * 7 days)
  20993. // if weeksInMonth is 'static'
  20994. const daysInMonth = 6 * 7;
  20995. if (props.weeksInMonth === 'static' && days.length < daysInMonth) {
  20996. const lastDay = days[days.length - 1];
  20997. let week = [];
  20998. for (let day = 1; day <= daysInMonth - days.length; day++) {
  20999. week.push(adapter.addDays(lastDay, day));
  21000. if (day % 7 === 0) {
  21001. weeks.push(week);
  21002. week = [];
  21003. }
  21004. }
  21005. }
  21006. return weeks;
  21007. });
  21008. function genDays(days, today) {
  21009. return days.filter(date => {
  21010. return weekDays.value.includes(adapter.toJsDate(date).getDay());
  21011. }).map((date, index) => {
  21012. const isoDate = adapter.toISO(date);
  21013. const isAdjacent = !adapter.isSameMonth(date, month.value);
  21014. const isStart = adapter.isSameDay(date, adapter.startOfMonth(month.value));
  21015. const isEnd = adapter.isSameDay(date, adapter.endOfMonth(month.value));
  21016. const isSame = adapter.isSameDay(date, month.value);
  21017. return {
  21018. date,
  21019. isoDate,
  21020. formatted: adapter.format(date, 'keyboardDate'),
  21021. year: adapter.getYear(date),
  21022. month: adapter.getMonth(date),
  21023. isDisabled: isDisabled(date),
  21024. isWeekStart: index % 7 === 0,
  21025. isWeekEnd: index % 7 === 6,
  21026. isToday: adapter.isSameDay(date, today),
  21027. isAdjacent,
  21028. isHidden: isAdjacent && !props.showAdjacentMonths,
  21029. isStart,
  21030. isSelected: model.value.some(value => adapter.isSameDay(date, value)),
  21031. isEnd,
  21032. isSame,
  21033. localized: adapter.format(date, 'dayOfMonth')
  21034. };
  21035. });
  21036. }
  21037. const daysInWeek = vue.computed(() => {
  21038. const lastDay = adapter.startOfWeek(displayValue.value, props.firstDayOfWeek);
  21039. const week = [];
  21040. for (let day = 0; day <= 6; day++) {
  21041. week.push(adapter.addDays(lastDay, day));
  21042. }
  21043. const today = adapter.date();
  21044. return genDays(week, today);
  21045. });
  21046. const daysInMonth = vue.computed(() => {
  21047. const days = weeksInMonth.value.flat();
  21048. const today = adapter.date();
  21049. return genDays(days, today);
  21050. });
  21051. const weekNumbers = vue.computed(() => {
  21052. return weeksInMonth.value.map(week => {
  21053. return week.length ? getWeek(adapter, week[0]) : null;
  21054. });
  21055. });
  21056. function isDisabled(value) {
  21057. if (props.disabled) return true;
  21058. const date = adapter.date(value);
  21059. if (props.min && adapter.isAfter(adapter.date(props.min), date)) return true;
  21060. if (props.max && adapter.isAfter(date, adapter.date(props.max))) return true;
  21061. if (Array.isArray(props.allowedDates) && props.allowedDates.length > 0) {
  21062. return !props.allowedDates.some(d => adapter.isSameDay(adapter.date(d), date));
  21063. }
  21064. if (typeof props.allowedDates === 'function') {
  21065. return !props.allowedDates(date);
  21066. }
  21067. return false;
  21068. }
  21069. return {
  21070. displayValue,
  21071. daysInMonth,
  21072. daysInWeek,
  21073. genDays,
  21074. model,
  21075. weeksInMonth,
  21076. weekDays,
  21077. weekNumbers
  21078. };
  21079. }
  21080. // Types
  21081. const makeVDatePickerMonthProps = propsFactory({
  21082. color: String,
  21083. hideWeekdays: Boolean,
  21084. multiple: [Boolean, Number, String],
  21085. showWeek: Boolean,
  21086. transition: {
  21087. type: String,
  21088. default: 'picker-transition'
  21089. },
  21090. reverseTransition: {
  21091. type: String,
  21092. default: 'picker-reverse-transition'
  21093. },
  21094. ...makeCalendarProps()
  21095. }, 'VDatePickerMonth');
  21096. const VDatePickerMonth = genericComponent()({
  21097. name: 'VDatePickerMonth',
  21098. props: makeVDatePickerMonthProps(),
  21099. emits: {
  21100. 'update:modelValue': date => true,
  21101. 'update:month': date => true,
  21102. 'update:year': date => true
  21103. },
  21104. setup(props, _ref) {
  21105. let {
  21106. emit,
  21107. slots
  21108. } = _ref;
  21109. const daysRef = vue.ref();
  21110. const {
  21111. daysInMonth,
  21112. model,
  21113. weekNumbers
  21114. } = useCalendar(props);
  21115. const adapter = useDate();
  21116. const rangeStart = vue.shallowRef();
  21117. const rangeStop = vue.shallowRef();
  21118. const isReverse = vue.shallowRef(false);
  21119. const transition = vue.computed(() => {
  21120. return !isReverse.value ? props.transition : props.reverseTransition;
  21121. });
  21122. if (props.multiple === 'range' && model.value.length > 0) {
  21123. rangeStart.value = model.value[0];
  21124. if (model.value.length > 1) {
  21125. rangeStop.value = model.value[model.value.length - 1];
  21126. }
  21127. }
  21128. const atMax = vue.computed(() => {
  21129. const max = ['number', 'string'].includes(typeof props.multiple) ? Number(props.multiple) : Infinity;
  21130. return model.value.length >= max;
  21131. });
  21132. vue.watch(daysInMonth, (val, oldVal) => {
  21133. if (!oldVal) return;
  21134. isReverse.value = adapter.isBefore(val[0].date, oldVal[0].date);
  21135. });
  21136. function onRangeClick(value) {
  21137. const _value = adapter.startOfDay(value);
  21138. if (model.value.length === 0) {
  21139. rangeStart.value = undefined;
  21140. } else if (model.value.length === 1) {
  21141. rangeStart.value = model.value[0];
  21142. rangeStop.value = undefined;
  21143. }
  21144. if (!rangeStart.value) {
  21145. rangeStart.value = _value;
  21146. model.value = [rangeStart.value];
  21147. } else if (!rangeStop.value) {
  21148. if (adapter.isSameDay(_value, rangeStart.value)) {
  21149. rangeStart.value = undefined;
  21150. model.value = [];
  21151. return;
  21152. } else if (adapter.isBefore(_value, rangeStart.value)) {
  21153. rangeStop.value = adapter.endOfDay(rangeStart.value);
  21154. rangeStart.value = _value;
  21155. } else {
  21156. rangeStop.value = adapter.endOfDay(_value);
  21157. }
  21158. const diff = adapter.getDiff(rangeStop.value, rangeStart.value, 'days');
  21159. const datesInRange = [rangeStart.value];
  21160. for (let i = 1; i < diff; i++) {
  21161. const nextDate = adapter.addDays(rangeStart.value, i);
  21162. datesInRange.push(nextDate);
  21163. }
  21164. datesInRange.push(rangeStop.value);
  21165. model.value = datesInRange;
  21166. } else {
  21167. rangeStart.value = value;
  21168. rangeStop.value = undefined;
  21169. model.value = [rangeStart.value];
  21170. }
  21171. }
  21172. function onMultipleClick(value) {
  21173. const index = model.value.findIndex(selection => adapter.isSameDay(selection, value));
  21174. if (index === -1) {
  21175. model.value = [...model.value, value];
  21176. } else {
  21177. const value = [...model.value];
  21178. value.splice(index, 1);
  21179. model.value = value;
  21180. }
  21181. }
  21182. function onClick(value) {
  21183. if (props.multiple === 'range') {
  21184. onRangeClick(value);
  21185. } else if (props.multiple) {
  21186. onMultipleClick(value);
  21187. } else {
  21188. model.value = [value];
  21189. }
  21190. }
  21191. return () => vue.createVNode("div", {
  21192. "class": "v-date-picker-month"
  21193. }, [props.showWeek && vue.createVNode("div", {
  21194. "key": "weeks",
  21195. "class": "v-date-picker-month__weeks"
  21196. }, [!props.hideWeekdays && vue.createVNode("div", {
  21197. "key": "hide-week-days",
  21198. "class": "v-date-picker-month__day"
  21199. }, [vue.createTextVNode("\xA0")]), weekNumbers.value.map(week => vue.createVNode("div", {
  21200. "class": ['v-date-picker-month__day', 'v-date-picker-month__day--adjacent']
  21201. }, [week]))]), vue.createVNode(MaybeTransition, {
  21202. "name": transition.value
  21203. }, {
  21204. default: () => [vue.createVNode("div", {
  21205. "ref": daysRef,
  21206. "key": daysInMonth.value[0].date?.toString(),
  21207. "class": "v-date-picker-month__days"
  21208. }, [!props.hideWeekdays && adapter.getWeekdays(props.firstDayOfWeek).map(weekDay => vue.createVNode("div", {
  21209. "class": ['v-date-picker-month__day', 'v-date-picker-month__weekday']
  21210. }, [weekDay])), daysInMonth.value.map((item, i) => {
  21211. const slotProps = {
  21212. props: {
  21213. onClick: () => onClick(item.date)
  21214. },
  21215. item,
  21216. i
  21217. };
  21218. if (atMax.value && !item.isSelected) {
  21219. item.isDisabled = true;
  21220. }
  21221. return vue.createVNode("div", {
  21222. "class": ['v-date-picker-month__day', {
  21223. 'v-date-picker-month__day--adjacent': item.isAdjacent,
  21224. 'v-date-picker-month__day--hide-adjacent': item.isHidden,
  21225. 'v-date-picker-month__day--selected': item.isSelected,
  21226. 'v-date-picker-month__day--week-end': item.isWeekEnd,
  21227. 'v-date-picker-month__day--week-start': item.isWeekStart
  21228. }],
  21229. "data-v-date": !item.isDisabled ? item.isoDate : undefined
  21230. }, [(props.showAdjacentMonths || !item.isAdjacent) && vue.createVNode(VDefaultsProvider, {
  21231. "defaults": {
  21232. VBtn: {
  21233. class: 'v-date-picker-month__day-btn',
  21234. color: (item.isSelected || item.isToday) && !item.isDisabled ? props.color : undefined,
  21235. disabled: item.isDisabled,
  21236. icon: true,
  21237. ripple: false,
  21238. text: item.localized,
  21239. variant: item.isDisabled ? item.isToday ? 'outlined' : 'text' : item.isToday && !item.isSelected ? 'outlined' : 'flat',
  21240. onClick: () => onClick(item.date)
  21241. }
  21242. }
  21243. }, {
  21244. default: () => [slots.day?.(slotProps) ?? vue.createVNode(VBtn, slotProps.props, null)]
  21245. })]);
  21246. })])]
  21247. })]);
  21248. }
  21249. });
  21250. // Types
  21251. const makeVDatePickerMonthsProps = propsFactory({
  21252. color: String,
  21253. height: [String, Number],
  21254. min: null,
  21255. max: null,
  21256. modelValue: Number,
  21257. year: Number
  21258. }, 'VDatePickerMonths');
  21259. const VDatePickerMonths = genericComponent()({
  21260. name: 'VDatePickerMonths',
  21261. props: makeVDatePickerMonthsProps(),
  21262. emits: {
  21263. 'update:modelValue': date => true
  21264. },
  21265. setup(props, _ref) {
  21266. let {
  21267. emit,
  21268. slots
  21269. } = _ref;
  21270. const adapter = useDate();
  21271. const model = useProxiedModel(props, 'modelValue');
  21272. const months = vue.computed(() => {
  21273. let date = adapter.startOfYear(adapter.date());
  21274. if (props.year) {
  21275. date = adapter.setYear(date, props.year);
  21276. }
  21277. return createRange(12).map(i => {
  21278. const text = adapter.format(date, 'monthShort');
  21279. const isDisabled = !!(props.min && adapter.isAfter(adapter.startOfMonth(adapter.date(props.min)), date) || props.max && adapter.isAfter(date, adapter.startOfMonth(adapter.date(props.max))));
  21280. date = adapter.getNextMonth(date);
  21281. return {
  21282. isDisabled,
  21283. text,
  21284. value: i
  21285. };
  21286. });
  21287. });
  21288. vue.watchEffect(() => {
  21289. model.value = model.value ?? adapter.getMonth(adapter.date());
  21290. });
  21291. useRender(() => vue.createVNode("div", {
  21292. "class": "v-date-picker-months",
  21293. "style": {
  21294. height: convertToUnit(props.height)
  21295. }
  21296. }, [vue.createVNode("div", {
  21297. "class": "v-date-picker-months__content"
  21298. }, [months.value.map((month, i) => {
  21299. const btnProps = {
  21300. active: model.value === i,
  21301. color: model.value === i ? props.color : undefined,
  21302. disabled: month.isDisabled,
  21303. rounded: true,
  21304. text: month.text,
  21305. variant: model.value === month.value ? 'flat' : 'text',
  21306. onClick: () => onClick(i)
  21307. };
  21308. function onClick(i) {
  21309. if (model.value === i) {
  21310. emit('update:modelValue', model.value);
  21311. return;
  21312. }
  21313. model.value = i;
  21314. }
  21315. return slots.month?.({
  21316. month,
  21317. i,
  21318. props: btnProps
  21319. }) ?? vue.createVNode(VBtn, vue.mergeProps({
  21320. "key": "month"
  21321. }, btnProps), null);
  21322. })])]));
  21323. return {};
  21324. }
  21325. });
  21326. // Types
  21327. // Types
  21328. const makeVDatePickerYearsProps = propsFactory({
  21329. color: String,
  21330. height: [String, Number],
  21331. min: null,
  21332. max: null,
  21333. modelValue: Number
  21334. }, 'VDatePickerYears');
  21335. const VDatePickerYears = genericComponent()({
  21336. name: 'VDatePickerYears',
  21337. props: makeVDatePickerYearsProps(),
  21338. emits: {
  21339. 'update:modelValue': year => true
  21340. },
  21341. setup(props, _ref) {
  21342. let {
  21343. emit,
  21344. slots
  21345. } = _ref;
  21346. const adapter = useDate();
  21347. const model = useProxiedModel(props, 'modelValue');
  21348. const years = vue.computed(() => {
  21349. const year = adapter.getYear(adapter.date());
  21350. let min = year - 100;
  21351. let max = year + 52;
  21352. if (props.min) {
  21353. min = adapter.getYear(adapter.date(props.min));
  21354. }
  21355. if (props.max) {
  21356. max = adapter.getYear(adapter.date(props.max));
  21357. }
  21358. let date = adapter.startOfYear(adapter.date());
  21359. date = adapter.setYear(date, min);
  21360. return createRange(max - min + 1, min).map(i => {
  21361. const text = adapter.format(date, 'year');
  21362. date = adapter.setYear(date, adapter.getYear(date) + 1);
  21363. return {
  21364. text,
  21365. value: i
  21366. };
  21367. });
  21368. });
  21369. vue.watchEffect(() => {
  21370. model.value = model.value ?? adapter.getYear(adapter.date());
  21371. });
  21372. const yearRef = templateRef();
  21373. vue.onMounted(async () => {
  21374. await vue.nextTick();
  21375. yearRef.el?.scrollIntoView({
  21376. block: 'center'
  21377. });
  21378. });
  21379. useRender(() => vue.createVNode("div", {
  21380. "class": "v-date-picker-years",
  21381. "style": {
  21382. height: convertToUnit(props.height)
  21383. }
  21384. }, [vue.createVNode("div", {
  21385. "class": "v-date-picker-years__content"
  21386. }, [years.value.map((year, i) => {
  21387. const btnProps = {
  21388. ref: model.value === year.value ? yearRef : undefined,
  21389. active: model.value === year.value,
  21390. color: model.value === year.value ? props.color : undefined,
  21391. rounded: true,
  21392. text: year.text,
  21393. variant: model.value === year.value ? 'flat' : 'text',
  21394. onClick: () => {
  21395. if (model.value === year.value) {
  21396. emit('update:modelValue', model.value);
  21397. return;
  21398. }
  21399. model.value = year.value;
  21400. }
  21401. };
  21402. return slots.year?.({
  21403. year,
  21404. i,
  21405. props: btnProps
  21406. }) ?? vue.createVNode(VBtn, vue.mergeProps({
  21407. "key": "month"
  21408. }, btnProps), null);
  21409. })])]));
  21410. return {};
  21411. }
  21412. });
  21413. // Utilities
  21414. const VPickerTitle = createSimpleFunctional('v-picker-title');
  21415. // Types
  21416. const makeVPickerProps = propsFactory({
  21417. bgColor: String,
  21418. landscape: Boolean,
  21419. title: String,
  21420. hideHeader: Boolean,
  21421. ...makeVSheetProps()
  21422. }, 'VPicker');
  21423. const VPicker = genericComponent()({
  21424. name: 'VPicker',
  21425. props: makeVPickerProps(),
  21426. setup(props, _ref) {
  21427. let {
  21428. slots
  21429. } = _ref;
  21430. const {
  21431. backgroundColorClasses,
  21432. backgroundColorStyles
  21433. } = useBackgroundColor(vue.toRef(props, 'color'));
  21434. useRender(() => {
  21435. const sheetProps = VSheet.filterProps(props);
  21436. const hasTitle = !!(props.title || slots.title);
  21437. return vue.createVNode(VSheet, vue.mergeProps(sheetProps, {
  21438. "color": props.bgColor,
  21439. "class": ['v-picker', {
  21440. 'v-picker--landscape': props.landscape,
  21441. 'v-picker--with-actions': !!slots.actions
  21442. }, props.class],
  21443. "style": props.style
  21444. }), {
  21445. default: () => [!props.hideHeader && vue.createVNode("div", {
  21446. "key": "header",
  21447. "class": [backgroundColorClasses.value],
  21448. "style": [backgroundColorStyles.value]
  21449. }, [hasTitle && vue.createVNode(VPickerTitle, {
  21450. "key": "picker-title"
  21451. }, {
  21452. default: () => [slots.title?.() ?? props.title]
  21453. }), slots.header && vue.createVNode("div", {
  21454. "class": "v-picker__header"
  21455. }, [slots.header()])]), vue.createVNode("div", {
  21456. "class": "v-picker__body"
  21457. }, [slots.default?.()]), slots.actions && vue.createVNode(VDefaultsProvider, {
  21458. "defaults": {
  21459. VBtn: {
  21460. slim: true,
  21461. variant: 'text'
  21462. }
  21463. }
  21464. }, {
  21465. default: () => [vue.createVNode("div", {
  21466. "class": "v-picker__actions"
  21467. }, [slots.actions()])]
  21468. })]
  21469. });
  21470. });
  21471. return {};
  21472. }
  21473. });
  21474. // Types
  21475. // Types
  21476. const makeVDatePickerProps = propsFactory({
  21477. // TODO: implement in v3.5
  21478. // calendarIcon: {
  21479. // type: String,
  21480. // default: '$calendar',
  21481. // },
  21482. // keyboardIcon: {
  21483. // type: String,
  21484. // default: '$edit',
  21485. // },
  21486. // inputMode: {
  21487. // type: String as PropType<'calendar' | 'keyboard'>,
  21488. // default: 'calendar',
  21489. // },
  21490. // inputText: {
  21491. // type: String,
  21492. // default: '$vuetify.datePicker.input.placeholder',
  21493. // },
  21494. // inputPlaceholder: {
  21495. // type: String,
  21496. // default: 'dd/mm/yyyy',
  21497. // },
  21498. header: {
  21499. type: String,
  21500. default: '$vuetify.datePicker.header'
  21501. },
  21502. ...makeVDatePickerControlsProps(),
  21503. ...makeVDatePickerMonthProps({
  21504. weeksInMonth: 'static'
  21505. }),
  21506. ...omit(makeVDatePickerMonthsProps(), ['modelValue']),
  21507. ...omit(makeVDatePickerYearsProps(), ['modelValue']),
  21508. ...makeVPickerProps({
  21509. title: '$vuetify.datePicker.title'
  21510. }),
  21511. modelValue: null
  21512. }, 'VDatePicker');
  21513. const VDatePicker = genericComponent()({
  21514. name: 'VDatePicker',
  21515. props: makeVDatePickerProps(),
  21516. emits: {
  21517. 'update:modelValue': date => true,
  21518. 'update:month': date => true,
  21519. 'update:year': date => true,
  21520. // 'update:inputMode': (date: any) => true,
  21521. 'update:viewMode': date => true
  21522. },
  21523. setup(props, _ref) {
  21524. let {
  21525. emit,
  21526. slots
  21527. } = _ref;
  21528. const adapter = useDate();
  21529. const {
  21530. t
  21531. } = useLocale();
  21532. const model = useProxiedModel(props, 'modelValue', undefined, v => wrapInArray(v), v => props.multiple ? v : v[0]);
  21533. const viewMode = useProxiedModel(props, 'viewMode');
  21534. // const inputMode = useProxiedModel(props, 'inputMode')
  21535. const internal = vue.computed(() => {
  21536. const value = adapter.date(model.value?.[0]);
  21537. return value && adapter.isValid(value) ? value : adapter.date();
  21538. });
  21539. const month = vue.ref(Number(props.month ?? adapter.getMonth(adapter.startOfMonth(internal.value))));
  21540. const year = vue.ref(Number(props.year ?? adapter.getYear(adapter.startOfYear(adapter.setMonth(internal.value, month.value)))));
  21541. const isReversing = vue.shallowRef(false);
  21542. const header = vue.computed(() => {
  21543. if (props.multiple && model.value.length > 1) {
  21544. return t('$vuetify.datePicker.itemsSelected', model.value.length);
  21545. }
  21546. return model.value[0] && adapter.isValid(model.value[0]) ? adapter.format(adapter.date(model.value[0]), 'normalDateWithWeekday') : t(props.header);
  21547. });
  21548. const text = vue.computed(() => {
  21549. let date = adapter.date();
  21550. date = adapter.setDate(date, 1);
  21551. date = adapter.setMonth(date, month.value);
  21552. date = adapter.setYear(date, year.value);
  21553. return adapter.format(date, 'monthAndYear');
  21554. });
  21555. // const headerIcon = computed(() => props.inputMode === 'calendar' ? props.keyboardIcon : props.calendarIcon)
  21556. const headerTransition = vue.computed(() => `date-picker-header${isReversing.value ? '-reverse' : ''}-transition`);
  21557. const minDate = vue.computed(() => {
  21558. const date = adapter.date(props.min);
  21559. return props.min && adapter.isValid(date) ? date : null;
  21560. });
  21561. const maxDate = vue.computed(() => {
  21562. const date = adapter.date(props.max);
  21563. return props.max && adapter.isValid(date) ? date : null;
  21564. });
  21565. const disabled = vue.computed(() => {
  21566. if (props.disabled) return true;
  21567. const targets = [];
  21568. if (viewMode.value !== 'month') {
  21569. targets.push(...['prev', 'next']);
  21570. } else {
  21571. let _date = adapter.date();
  21572. _date = adapter.setYear(_date, year.value);
  21573. _date = adapter.setMonth(_date, month.value);
  21574. if (minDate.value) {
  21575. const date = adapter.addDays(adapter.startOfMonth(_date), -1);
  21576. adapter.isAfter(minDate.value, date) && targets.push('prev');
  21577. }
  21578. if (maxDate.value) {
  21579. const date = adapter.addDays(adapter.endOfMonth(_date), 1);
  21580. adapter.isAfter(date, maxDate.value) && targets.push('next');
  21581. }
  21582. }
  21583. return targets;
  21584. });
  21585. // function onClickAppend () {
  21586. // inputMode.value = inputMode.value === 'calendar' ? 'keyboard' : 'calendar'
  21587. // }
  21588. function onClickNext() {
  21589. if (month.value < 11) {
  21590. month.value++;
  21591. } else {
  21592. year.value++;
  21593. month.value = 0;
  21594. onUpdateYear(year.value);
  21595. }
  21596. onUpdateMonth(month.value);
  21597. }
  21598. function onClickPrev() {
  21599. if (month.value > 0) {
  21600. month.value--;
  21601. } else {
  21602. year.value--;
  21603. month.value = 11;
  21604. onUpdateYear(year.value);
  21605. }
  21606. onUpdateMonth(month.value);
  21607. }
  21608. function onClickDate() {
  21609. viewMode.value = 'month';
  21610. }
  21611. function onClickMonth() {
  21612. viewMode.value = viewMode.value === 'months' ? 'month' : 'months';
  21613. }
  21614. function onClickYear() {
  21615. viewMode.value = viewMode.value === 'year' ? 'month' : 'year';
  21616. }
  21617. function onUpdateMonth(value) {
  21618. if (viewMode.value === 'months') onClickMonth();
  21619. emit('update:month', value);
  21620. }
  21621. function onUpdateYear(value) {
  21622. if (viewMode.value === 'year') onClickYear();
  21623. emit('update:year', value);
  21624. }
  21625. vue.watch(model, (val, oldVal) => {
  21626. const arrBefore = wrapInArray(oldVal);
  21627. const arrAfter = wrapInArray(val);
  21628. if (!arrAfter.length) return;
  21629. const before = adapter.date(arrBefore[arrBefore.length - 1]);
  21630. const after = adapter.date(arrAfter[arrAfter.length - 1]);
  21631. const newMonth = adapter.getMonth(after);
  21632. const newYear = adapter.getYear(after);
  21633. if (newMonth !== month.value) {
  21634. month.value = newMonth;
  21635. onUpdateMonth(month.value);
  21636. }
  21637. if (newYear !== year.value) {
  21638. year.value = newYear;
  21639. onUpdateYear(year.value);
  21640. }
  21641. isReversing.value = adapter.isBefore(before, after);
  21642. });
  21643. useRender(() => {
  21644. const pickerProps = VPicker.filterProps(props);
  21645. const datePickerControlsProps = VDatePickerControls.filterProps(props);
  21646. const datePickerHeaderProps = VDatePickerHeader.filterProps(props);
  21647. const datePickerMonthProps = VDatePickerMonth.filterProps(props);
  21648. const datePickerMonthsProps = omit(VDatePickerMonths.filterProps(props), ['modelValue']);
  21649. const datePickerYearsProps = omit(VDatePickerYears.filterProps(props), ['modelValue']);
  21650. const headerProps = {
  21651. header: header.value,
  21652. transition: headerTransition.value
  21653. };
  21654. return vue.createVNode(VPicker, vue.mergeProps(pickerProps, {
  21655. "class": ['v-date-picker', `v-date-picker--${viewMode.value}`, {
  21656. 'v-date-picker--show-week': props.showWeek
  21657. }, props.class],
  21658. "style": props.style
  21659. }), {
  21660. title: () => slots.title?.() ?? vue.createVNode("div", {
  21661. "class": "v-date-picker__title"
  21662. }, [t(props.title)]),
  21663. header: () => slots.header ? vue.createVNode(VDefaultsProvider, {
  21664. "defaults": {
  21665. VDatePickerHeader: {
  21666. ...headerProps
  21667. }
  21668. }
  21669. }, {
  21670. default: () => [slots.header?.(headerProps)]
  21671. }) : vue.createVNode(VDatePickerHeader, vue.mergeProps({
  21672. "key": "header"
  21673. }, datePickerHeaderProps, headerProps, {
  21674. "onClick": viewMode.value !== 'month' ? onClickDate : undefined
  21675. }), {
  21676. ...slots,
  21677. default: undefined
  21678. }),
  21679. default: () => vue.createVNode(vue.Fragment, null, [vue.createVNode(VDatePickerControls, vue.mergeProps(datePickerControlsProps, {
  21680. "disabled": disabled.value,
  21681. "text": text.value,
  21682. "onClick:next": onClickNext,
  21683. "onClick:prev": onClickPrev,
  21684. "onClick:month": onClickMonth,
  21685. "onClick:year": onClickYear
  21686. }), null), vue.createVNode(VFadeTransition, {
  21687. "hideOnLeave": true
  21688. }, {
  21689. default: () => [viewMode.value === 'months' ? vue.createVNode(VDatePickerMonths, vue.mergeProps({
  21690. "key": "date-picker-months"
  21691. }, datePickerMonthsProps, {
  21692. "modelValue": month.value,
  21693. "onUpdate:modelValue": [$event => month.value = $event, onUpdateMonth],
  21694. "min": minDate.value,
  21695. "max": maxDate.value,
  21696. "year": year.value
  21697. }), null) : viewMode.value === 'year' ? vue.createVNode(VDatePickerYears, vue.mergeProps({
  21698. "key": "date-picker-years"
  21699. }, datePickerYearsProps, {
  21700. "modelValue": year.value,
  21701. "onUpdate:modelValue": [$event => year.value = $event, onUpdateYear],
  21702. "min": minDate.value,
  21703. "max": maxDate.value
  21704. }), null) : vue.createVNode(VDatePickerMonth, vue.mergeProps({
  21705. "key": "date-picker-month"
  21706. }, datePickerMonthProps, {
  21707. "modelValue": model.value,
  21708. "onUpdate:modelValue": $event => model.value = $event,
  21709. "month": month.value,
  21710. "onUpdate:month": [$event => month.value = $event, onUpdateMonth],
  21711. "year": year.value,
  21712. "onUpdate:year": [$event => year.value = $event, onUpdateYear],
  21713. "min": minDate.value,
  21714. "max": maxDate.value
  21715. }), null)]
  21716. })]),
  21717. actions: slots.actions
  21718. });
  21719. });
  21720. return {};
  21721. }
  21722. });
  21723. // Types
  21724. // Types
  21725. const makeVEmptyStateProps = propsFactory({
  21726. actionText: String,
  21727. bgColor: String,
  21728. color: String,
  21729. icon: IconValue,
  21730. image: String,
  21731. justify: {
  21732. type: String,
  21733. default: 'center'
  21734. },
  21735. headline: String,
  21736. title: String,
  21737. text: String,
  21738. textWidth: {
  21739. type: [Number, String],
  21740. default: 500
  21741. },
  21742. href: String,
  21743. to: String,
  21744. ...makeComponentProps(),
  21745. ...makeDimensionProps(),
  21746. ...makeSizeProps({
  21747. size: undefined
  21748. }),
  21749. ...makeThemeProps()
  21750. }, 'VEmptyState');
  21751. const VEmptyState = genericComponent()({
  21752. name: 'VEmptyState',
  21753. props: makeVEmptyStateProps(),
  21754. emits: {
  21755. 'click:action': e => true
  21756. },
  21757. setup(props, _ref) {
  21758. let {
  21759. emit,
  21760. slots
  21761. } = _ref;
  21762. const {
  21763. themeClasses
  21764. } = provideTheme(props);
  21765. const {
  21766. backgroundColorClasses,
  21767. backgroundColorStyles
  21768. } = useBackgroundColor(vue.toRef(props, 'bgColor'));
  21769. const {
  21770. dimensionStyles
  21771. } = useDimension(props);
  21772. const {
  21773. displayClasses
  21774. } = useDisplay();
  21775. function onClickAction(e) {
  21776. emit('click:action', e);
  21777. }
  21778. useRender(() => {
  21779. const hasActions = !!(slots.actions || props.actionText);
  21780. const hasHeadline = !!(slots.headline || props.headline);
  21781. const hasTitle = !!(slots.title || props.title);
  21782. const hasText = !!(slots.text || props.text);
  21783. const hasMedia = !!(slots.media || props.image || props.icon);
  21784. const size = props.size || (props.image ? 200 : 96);
  21785. return vue.createVNode("div", {
  21786. "class": ['v-empty-state', {
  21787. [`v-empty-state--${props.justify}`]: true
  21788. }, themeClasses.value, backgroundColorClasses.value, displayClasses.value, props.class],
  21789. "style": [backgroundColorStyles.value, dimensionStyles.value, props.style]
  21790. }, [hasMedia && vue.createVNode("div", {
  21791. "key": "media",
  21792. "class": "v-empty-state__media"
  21793. }, [!slots.media ? vue.createVNode(vue.Fragment, null, [props.image ? vue.createVNode(VImg, {
  21794. "key": "image",
  21795. "src": props.image,
  21796. "height": size
  21797. }, null) : props.icon ? vue.createVNode(VIcon, {
  21798. "key": "icon",
  21799. "color": props.color,
  21800. "size": size,
  21801. "icon": props.icon
  21802. }, null) : undefined]) : vue.createVNode(VDefaultsProvider, {
  21803. "key": "media-defaults",
  21804. "defaults": {
  21805. VImg: {
  21806. src: props.image,
  21807. height: size
  21808. },
  21809. VIcon: {
  21810. size,
  21811. icon: props.icon
  21812. }
  21813. }
  21814. }, {
  21815. default: () => [slots.media()]
  21816. })]), hasHeadline && vue.createVNode("div", {
  21817. "key": "headline",
  21818. "class": "v-empty-state__headline"
  21819. }, [slots.headline?.() ?? props.headline]), hasTitle && vue.createVNode("div", {
  21820. "key": "title",
  21821. "class": "v-empty-state__title"
  21822. }, [slots.title?.() ?? props.title]), hasText && vue.createVNode("div", {
  21823. "key": "text",
  21824. "class": "v-empty-state__text",
  21825. "style": {
  21826. maxWidth: convertToUnit(props.textWidth)
  21827. }
  21828. }, [slots.text?.() ?? props.text]), slots.default && vue.createVNode("div", {
  21829. "key": "content",
  21830. "class": "v-empty-state__content"
  21831. }, [slots.default()]), hasActions && vue.createVNode("div", {
  21832. "key": "actions",
  21833. "class": "v-empty-state__actions"
  21834. }, [vue.createVNode(VDefaultsProvider, {
  21835. "defaults": {
  21836. VBtn: {
  21837. class: 'v-empty-state__action-btn',
  21838. color: props.color ?? 'surface-variant',
  21839. text: props.actionText
  21840. }
  21841. }
  21842. }, {
  21843. default: () => [slots.actions?.({
  21844. props: {
  21845. onClick: onClickAction
  21846. }
  21847. }) ?? vue.createVNode(VBtn, {
  21848. "onClick": onClickAction
  21849. }, null)]
  21850. })])]);
  21851. });
  21852. return {};
  21853. }
  21854. });
  21855. // Types
  21856. const VExpansionPanelSymbol = Symbol.for('vuetify:v-expansion-panel');
  21857. const makeVExpansionPanelTextProps = propsFactory({
  21858. ...makeComponentProps(),
  21859. ...makeLazyProps()
  21860. }, 'VExpansionPanelText');
  21861. const VExpansionPanelText = genericComponent()({
  21862. name: 'VExpansionPanelText',
  21863. props: makeVExpansionPanelTextProps(),
  21864. setup(props, _ref) {
  21865. let {
  21866. slots
  21867. } = _ref;
  21868. const expansionPanel = vue.inject(VExpansionPanelSymbol);
  21869. if (!expansionPanel) throw new Error('[Vuetify] v-expansion-panel-text needs to be placed inside v-expansion-panel');
  21870. const {
  21871. hasContent,
  21872. onAfterLeave
  21873. } = useLazy(props, expansionPanel.isSelected);
  21874. useRender(() => vue.createVNode(VExpandTransition, {
  21875. "onAfterLeave": onAfterLeave
  21876. }, {
  21877. default: () => [vue.withDirectives(vue.createVNode("div", {
  21878. "class": ['v-expansion-panel-text', props.class],
  21879. "style": props.style
  21880. }, [slots.default && hasContent.value && vue.createVNode("div", {
  21881. "class": "v-expansion-panel-text__wrapper"
  21882. }, [slots.default?.()])]), [[vue.vShow, expansionPanel.isSelected.value]])]
  21883. }));
  21884. return {};
  21885. }
  21886. });
  21887. // Types
  21888. const makeVExpansionPanelTitleProps = propsFactory({
  21889. color: String,
  21890. expandIcon: {
  21891. type: IconValue,
  21892. default: '$expand'
  21893. },
  21894. collapseIcon: {
  21895. type: IconValue,
  21896. default: '$collapse'
  21897. },
  21898. hideActions: Boolean,
  21899. focusable: Boolean,
  21900. static: Boolean,
  21901. ripple: {
  21902. type: [Boolean, Object],
  21903. default: false
  21904. },
  21905. readonly: Boolean,
  21906. ...makeComponentProps(),
  21907. ...makeDimensionProps()
  21908. }, 'VExpansionPanelTitle');
  21909. const VExpansionPanelTitle = genericComponent()({
  21910. name: 'VExpansionPanelTitle',
  21911. directives: {
  21912. Ripple
  21913. },
  21914. props: makeVExpansionPanelTitleProps(),
  21915. setup(props, _ref) {
  21916. let {
  21917. slots
  21918. } = _ref;
  21919. const expansionPanel = vue.inject(VExpansionPanelSymbol);
  21920. if (!expansionPanel) throw new Error('[Vuetify] v-expansion-panel-title needs to be placed inside v-expansion-panel');
  21921. const {
  21922. backgroundColorClasses,
  21923. backgroundColorStyles
  21924. } = useBackgroundColor(props, 'color');
  21925. const {
  21926. dimensionStyles
  21927. } = useDimension(props);
  21928. const slotProps = vue.computed(() => ({
  21929. collapseIcon: props.collapseIcon,
  21930. disabled: expansionPanel.disabled.value,
  21931. expanded: expansionPanel.isSelected.value,
  21932. expandIcon: props.expandIcon,
  21933. readonly: props.readonly
  21934. }));
  21935. const icon = vue.computed(() => expansionPanel.isSelected.value ? props.collapseIcon : props.expandIcon);
  21936. useRender(() => vue.withDirectives(vue.createVNode("button", {
  21937. "class": ['v-expansion-panel-title', {
  21938. 'v-expansion-panel-title--active': expansionPanel.isSelected.value,
  21939. 'v-expansion-panel-title--focusable': props.focusable,
  21940. 'v-expansion-panel-title--static': props.static
  21941. }, backgroundColorClasses.value, props.class],
  21942. "style": [backgroundColorStyles.value, dimensionStyles.value, props.style],
  21943. "type": "button",
  21944. "tabindex": expansionPanel.disabled.value ? -1 : undefined,
  21945. "disabled": expansionPanel.disabled.value,
  21946. "aria-expanded": expansionPanel.isSelected.value,
  21947. "onClick": !props.readonly ? expansionPanel.toggle : undefined
  21948. }, [vue.createVNode("span", {
  21949. "class": "v-expansion-panel-title__overlay"
  21950. }, null), slots.default?.(slotProps.value), !props.hideActions && vue.createVNode(VDefaultsProvider, {
  21951. "defaults": {
  21952. VIcon: {
  21953. icon: icon.value
  21954. }
  21955. }
  21956. }, {
  21957. default: () => [vue.createVNode("span", {
  21958. "class": "v-expansion-panel-title__icon"
  21959. }, [slots.actions?.(slotProps.value) ?? vue.createVNode(VIcon, null, null)])]
  21960. })]), [[vue.resolveDirective("ripple"), props.ripple]]));
  21961. return {};
  21962. }
  21963. });
  21964. const makeVExpansionPanelProps = propsFactory({
  21965. title: String,
  21966. text: String,
  21967. bgColor: String,
  21968. ...makeElevationProps(),
  21969. ...makeGroupItemProps(),
  21970. ...makeRoundedProps(),
  21971. ...makeTagProps(),
  21972. ...makeVExpansionPanelTitleProps(),
  21973. ...makeVExpansionPanelTextProps()
  21974. }, 'VExpansionPanel');
  21975. const VExpansionPanel = genericComponent()({
  21976. name: 'VExpansionPanel',
  21977. props: makeVExpansionPanelProps(),
  21978. emits: {
  21979. 'group:selected': val => true
  21980. },
  21981. setup(props, _ref) {
  21982. let {
  21983. slots
  21984. } = _ref;
  21985. const groupItem = useGroupItem(props, VExpansionPanelSymbol);
  21986. const {
  21987. backgroundColorClasses,
  21988. backgroundColorStyles
  21989. } = useBackgroundColor(props, 'bgColor');
  21990. const {
  21991. elevationClasses
  21992. } = useElevation(props);
  21993. const {
  21994. roundedClasses
  21995. } = useRounded(props);
  21996. const isDisabled = vue.computed(() => groupItem?.disabled.value || props.disabled);
  21997. const selectedIndices = vue.computed(() => groupItem.group.items.value.reduce((arr, item, index) => {
  21998. if (groupItem.group.selected.value.includes(item.id)) arr.push(index);
  21999. return arr;
  22000. }, []));
  22001. const isBeforeSelected = vue.computed(() => {
  22002. const index = groupItem.group.items.value.findIndex(item => item.id === groupItem.id);
  22003. return !groupItem.isSelected.value && selectedIndices.value.some(selectedIndex => selectedIndex - index === 1);
  22004. });
  22005. const isAfterSelected = vue.computed(() => {
  22006. const index = groupItem.group.items.value.findIndex(item => item.id === groupItem.id);
  22007. return !groupItem.isSelected.value && selectedIndices.value.some(selectedIndex => selectedIndex - index === -1);
  22008. });
  22009. vue.provide(VExpansionPanelSymbol, groupItem);
  22010. useRender(() => {
  22011. const hasText = !!(slots.text || props.text);
  22012. const hasTitle = !!(slots.title || props.title);
  22013. const expansionPanelTitleProps = VExpansionPanelTitle.filterProps(props);
  22014. const expansionPanelTextProps = VExpansionPanelText.filterProps(props);
  22015. return vue.createVNode(props.tag, {
  22016. "class": ['v-expansion-panel', {
  22017. 'v-expansion-panel--active': groupItem.isSelected.value,
  22018. 'v-expansion-panel--before-active': isBeforeSelected.value,
  22019. 'v-expansion-panel--after-active': isAfterSelected.value,
  22020. 'v-expansion-panel--disabled': isDisabled.value
  22021. }, roundedClasses.value, backgroundColorClasses.value, props.class],
  22022. "style": [backgroundColorStyles.value, props.style]
  22023. }, {
  22024. default: () => [vue.createVNode("div", {
  22025. "class": ['v-expansion-panel__shadow', ...elevationClasses.value]
  22026. }, null), vue.createVNode(VDefaultsProvider, {
  22027. "defaults": {
  22028. VExpansionPanelTitle: {
  22029. ...expansionPanelTitleProps
  22030. },
  22031. VExpansionPanelText: {
  22032. ...expansionPanelTextProps
  22033. }
  22034. }
  22035. }, {
  22036. default: () => [hasTitle && vue.createVNode(VExpansionPanelTitle, {
  22037. "key": "title"
  22038. }, {
  22039. default: () => [slots.title ? slots.title() : props.title]
  22040. }), hasText && vue.createVNode(VExpansionPanelText, {
  22041. "key": "text"
  22042. }, {
  22043. default: () => [slots.text ? slots.text() : props.text]
  22044. }), slots.default?.()]
  22045. })]
  22046. });
  22047. });
  22048. return {
  22049. groupItem
  22050. };
  22051. }
  22052. });
  22053. // Types
  22054. const allowedVariants = ['default', 'accordion', 'inset', 'popout'];
  22055. const makeVExpansionPanelsProps = propsFactory({
  22056. flat: Boolean,
  22057. ...makeGroupProps(),
  22058. ...pick(makeVExpansionPanelProps(), ['bgColor', 'collapseIcon', 'color', 'eager', 'elevation', 'expandIcon', 'focusable', 'hideActions', 'readonly', 'ripple', 'rounded', 'tile', 'static']),
  22059. ...makeThemeProps(),
  22060. ...makeComponentProps(),
  22061. ...makeTagProps(),
  22062. variant: {
  22063. type: String,
  22064. default: 'default',
  22065. validator: v => allowedVariants.includes(v)
  22066. }
  22067. }, 'VExpansionPanels');
  22068. const VExpansionPanels = genericComponent()({
  22069. name: 'VExpansionPanels',
  22070. props: makeVExpansionPanelsProps(),
  22071. emits: {
  22072. 'update:modelValue': val => true
  22073. },
  22074. setup(props, _ref) {
  22075. let {
  22076. slots
  22077. } = _ref;
  22078. const {
  22079. next,
  22080. prev
  22081. } = useGroup(props, VExpansionPanelSymbol);
  22082. const {
  22083. themeClasses
  22084. } = provideTheme(props);
  22085. const variantClass = vue.computed(() => props.variant && `v-expansion-panels--variant-${props.variant}`);
  22086. provideDefaults({
  22087. VExpansionPanel: {
  22088. bgColor: vue.toRef(props, 'bgColor'),
  22089. collapseIcon: vue.toRef(props, 'collapseIcon'),
  22090. color: vue.toRef(props, 'color'),
  22091. eager: vue.toRef(props, 'eager'),
  22092. elevation: vue.toRef(props, 'elevation'),
  22093. expandIcon: vue.toRef(props, 'expandIcon'),
  22094. focusable: vue.toRef(props, 'focusable'),
  22095. hideActions: vue.toRef(props, 'hideActions'),
  22096. readonly: vue.toRef(props, 'readonly'),
  22097. ripple: vue.toRef(props, 'ripple'),
  22098. rounded: vue.toRef(props, 'rounded'),
  22099. static: vue.toRef(props, 'static')
  22100. }
  22101. });
  22102. useRender(() => vue.createVNode(props.tag, {
  22103. "class": ['v-expansion-panels', {
  22104. 'v-expansion-panels--flat': props.flat,
  22105. 'v-expansion-panels--tile': props.tile
  22106. }, themeClasses.value, variantClass.value, props.class],
  22107. "style": props.style
  22108. }, {
  22109. default: () => [slots.default?.({
  22110. prev,
  22111. next
  22112. })]
  22113. }));
  22114. return {
  22115. next,
  22116. prev
  22117. };
  22118. }
  22119. });
  22120. // Types
  22121. const makeVFabProps = propsFactory({
  22122. app: Boolean,
  22123. appear: Boolean,
  22124. extended: Boolean,
  22125. layout: Boolean,
  22126. offset: Boolean,
  22127. modelValue: {
  22128. type: Boolean,
  22129. default: true
  22130. },
  22131. ...omit(makeVBtnProps({
  22132. active: true
  22133. }), ['location']),
  22134. ...makeLayoutItemProps(),
  22135. ...makeLocationProps(),
  22136. ...makeTransitionProps({
  22137. transition: 'fab-transition'
  22138. })
  22139. }, 'VFab');
  22140. const VFab = genericComponent()({
  22141. name: 'VFab',
  22142. props: makeVFabProps(),
  22143. emits: {
  22144. 'update:modelValue': value => true
  22145. },
  22146. setup(props, _ref) {
  22147. let {
  22148. slots
  22149. } = _ref;
  22150. const model = useProxiedModel(props, 'modelValue');
  22151. const height = vue.shallowRef(56);
  22152. const layoutItemStyles = vue.ref();
  22153. const {
  22154. resizeRef
  22155. } = useResizeObserver(entries => {
  22156. if (!entries.length) return;
  22157. height.value = entries[0].target.clientHeight;
  22158. });
  22159. const hasPosition = vue.computed(() => props.app || props.absolute);
  22160. const position = vue.computed(() => {
  22161. if (!hasPosition.value) return false;
  22162. return props.location?.split(' ').shift() ?? 'bottom';
  22163. });
  22164. const orientation = vue.computed(() => {
  22165. if (!hasPosition.value) return false;
  22166. return props.location?.split(' ')[1] ?? 'end';
  22167. });
  22168. useToggleScope(() => props.app, () => {
  22169. const layout = useLayoutItem({
  22170. id: props.name,
  22171. order: vue.computed(() => parseInt(props.order, 10)),
  22172. position,
  22173. layoutSize: vue.computed(() => props.layout ? height.value + 24 : 0),
  22174. elementSize: vue.computed(() => height.value + 24),
  22175. active: vue.computed(() => props.app && model.value),
  22176. absolute: vue.toRef(props, 'absolute')
  22177. });
  22178. vue.watchEffect(() => {
  22179. layoutItemStyles.value = layout.layoutItemStyles.value;
  22180. });
  22181. });
  22182. const vFabRef = vue.ref();
  22183. useRender(() => {
  22184. const btnProps = VBtn.filterProps(props);
  22185. return vue.createVNode("div", {
  22186. "ref": vFabRef,
  22187. "class": ['v-fab', {
  22188. 'v-fab--absolute': props.absolute,
  22189. 'v-fab--app': !!props.app,
  22190. 'v-fab--extended': props.extended,
  22191. 'v-fab--offset': props.offset,
  22192. [`v-fab--${position.value}`]: hasPosition.value,
  22193. [`v-fab--${orientation.value}`]: hasPosition.value
  22194. }, props.class],
  22195. "style": [props.app ? {
  22196. ...layoutItemStyles.value
  22197. } : {
  22198. height: 'inherit',
  22199. width: undefined
  22200. }, props.style]
  22201. }, [vue.createVNode("div", {
  22202. "class": "v-fab__container"
  22203. }, [vue.createVNode(MaybeTransition, {
  22204. "appear": props.appear,
  22205. "transition": props.transition
  22206. }, {
  22207. default: () => [vue.withDirectives(vue.createVNode(VBtn, vue.mergeProps({
  22208. "ref": resizeRef
  22209. }, btnProps, {
  22210. "active": undefined,
  22211. "location": undefined
  22212. }), slots), [[vue.vShow, props.active]])]
  22213. })])]);
  22214. });
  22215. return {};
  22216. }
  22217. });
  22218. // Types
  22219. const makeVFileInputProps = propsFactory({
  22220. chips: Boolean,
  22221. counter: Boolean,
  22222. counterSizeString: {
  22223. type: String,
  22224. default: '$vuetify.fileInput.counterSize'
  22225. },
  22226. counterString: {
  22227. type: String,
  22228. default: '$vuetify.fileInput.counter'
  22229. },
  22230. hideInput: Boolean,
  22231. multiple: Boolean,
  22232. showSize: {
  22233. type: [Boolean, Number, String],
  22234. default: false,
  22235. validator: v => {
  22236. return typeof v === 'boolean' || [1000, 1024].includes(Number(v));
  22237. }
  22238. },
  22239. ...makeVInputProps({
  22240. prependIcon: '$file'
  22241. }),
  22242. modelValue: {
  22243. type: [Array, Object],
  22244. default: props => props.multiple ? [] : null,
  22245. validator: val => {
  22246. return wrapInArray(val).every(v => v != null && typeof v === 'object');
  22247. }
  22248. },
  22249. ...makeVFieldProps({
  22250. clearable: true
  22251. })
  22252. }, 'VFileInput');
  22253. const VFileInput = genericComponent()({
  22254. name: 'VFileInput',
  22255. inheritAttrs: false,
  22256. props: makeVFileInputProps(),
  22257. emits: {
  22258. 'click:control': e => true,
  22259. 'mousedown:control': e => true,
  22260. 'update:focused': focused => true,
  22261. 'update:modelValue': files => true
  22262. },
  22263. setup(props, _ref) {
  22264. let {
  22265. attrs,
  22266. emit,
  22267. slots
  22268. } = _ref;
  22269. const {
  22270. t
  22271. } = useLocale();
  22272. const model = useProxiedModel(props, 'modelValue', props.modelValue, val => wrapInArray(val), val => !props.multiple && Array.isArray(val) ? val[0] : val);
  22273. const {
  22274. isFocused,
  22275. focus,
  22276. blur
  22277. } = useFocus(props);
  22278. const base = vue.computed(() => typeof props.showSize !== 'boolean' ? props.showSize : undefined);
  22279. const totalBytes = vue.computed(() => (model.value ?? []).reduce((bytes, _ref2) => {
  22280. let {
  22281. size = 0
  22282. } = _ref2;
  22283. return bytes + size;
  22284. }, 0));
  22285. const totalBytesReadable = vue.computed(() => humanReadableFileSize(totalBytes.value, base.value));
  22286. const fileNames = vue.computed(() => (model.value ?? []).map(file => {
  22287. const {
  22288. name = '',
  22289. size = 0
  22290. } = file;
  22291. return !props.showSize ? name : `${name} (${humanReadableFileSize(size, base.value)})`;
  22292. }));
  22293. const counterValue = vue.computed(() => {
  22294. const fileCount = model.value?.length ?? 0;
  22295. if (props.showSize) return t(props.counterSizeString, fileCount, totalBytesReadable.value);else return t(props.counterString, fileCount);
  22296. });
  22297. const vInputRef = vue.ref();
  22298. const vFieldRef = vue.ref();
  22299. const inputRef = vue.ref();
  22300. const isActive = vue.computed(() => isFocused.value || props.active);
  22301. const isPlainOrUnderlined = vue.computed(() => ['plain', 'underlined'].includes(props.variant));
  22302. function onFocus() {
  22303. if (inputRef.value !== document.activeElement) {
  22304. inputRef.value?.focus();
  22305. }
  22306. if (!isFocused.value) focus();
  22307. }
  22308. function onClickPrepend(e) {
  22309. inputRef.value?.click();
  22310. }
  22311. function onControlMousedown(e) {
  22312. emit('mousedown:control', e);
  22313. }
  22314. function onControlClick(e) {
  22315. inputRef.value?.click();
  22316. emit('click:control', e);
  22317. }
  22318. function onClear(e) {
  22319. e.stopPropagation();
  22320. onFocus();
  22321. vue.nextTick(() => {
  22322. model.value = [];
  22323. callEvent(props['onClick:clear'], e);
  22324. });
  22325. }
  22326. vue.watch(model, newValue => {
  22327. const hasModelReset = !Array.isArray(newValue) || !newValue.length;
  22328. if (hasModelReset && inputRef.value) {
  22329. inputRef.value.value = '';
  22330. }
  22331. });
  22332. useRender(() => {
  22333. const hasCounter = !!(slots.counter || props.counter);
  22334. const hasDetails = !!(hasCounter || slots.details);
  22335. const [rootAttrs, inputAttrs] = filterInputAttrs(attrs);
  22336. const {
  22337. modelValue: _,
  22338. ...inputProps
  22339. } = VInput.filterProps(props);
  22340. const fieldProps = filterFieldProps(props);
  22341. return vue.createVNode(VInput, vue.mergeProps({
  22342. "ref": vInputRef,
  22343. "modelValue": model.value,
  22344. "onUpdate:modelValue": $event => model.value = $event,
  22345. "class": ['v-file-input', {
  22346. 'v-file-input--chips': !!props.chips,
  22347. 'v-file-input--hide': props.hideInput,
  22348. 'v-input--plain-underlined': isPlainOrUnderlined.value
  22349. }, props.class],
  22350. "style": props.style,
  22351. "onClick:prepend": onClickPrepend
  22352. }, rootAttrs, inputProps, {
  22353. "centerAffix": !isPlainOrUnderlined.value,
  22354. "focused": isFocused.value
  22355. }), {
  22356. ...slots,
  22357. default: _ref3 => {
  22358. let {
  22359. id,
  22360. isDisabled,
  22361. isDirty,
  22362. isReadonly,
  22363. isValid
  22364. } = _ref3;
  22365. return vue.createVNode(VField, vue.mergeProps({
  22366. "ref": vFieldRef,
  22367. "prepend-icon": props.prependIcon,
  22368. "onMousedown": onControlMousedown,
  22369. "onClick": onControlClick,
  22370. "onClick:clear": onClear,
  22371. "onClick:prependInner": props['onClick:prependInner'],
  22372. "onClick:appendInner": props['onClick:appendInner']
  22373. }, fieldProps, {
  22374. "id": id.value,
  22375. "active": isActive.value || isDirty.value,
  22376. "dirty": isDirty.value || props.dirty,
  22377. "disabled": isDisabled.value,
  22378. "focused": isFocused.value,
  22379. "error": isValid.value === false
  22380. }), {
  22381. ...slots,
  22382. default: _ref4 => {
  22383. let {
  22384. props: {
  22385. class: fieldClass,
  22386. ...slotProps
  22387. }
  22388. } = _ref4;
  22389. return vue.createVNode(vue.Fragment, null, [vue.createVNode("input", vue.mergeProps({
  22390. "ref": inputRef,
  22391. "type": "file",
  22392. "readonly": isReadonly.value,
  22393. "disabled": isDisabled.value,
  22394. "multiple": props.multiple,
  22395. "name": props.name,
  22396. "onClick": e => {
  22397. e.stopPropagation();
  22398. if (isReadonly.value) e.preventDefault();
  22399. onFocus();
  22400. },
  22401. "onChange": e => {
  22402. if (!e.target) return;
  22403. const target = e.target;
  22404. model.value = [...(target.files ?? [])];
  22405. },
  22406. "onFocus": onFocus,
  22407. "onBlur": blur
  22408. }, slotProps, inputAttrs), null), vue.createVNode("div", {
  22409. "class": fieldClass
  22410. }, [!!model.value?.length && !props.hideInput && (slots.selection ? slots.selection({
  22411. fileNames: fileNames.value,
  22412. totalBytes: totalBytes.value,
  22413. totalBytesReadable: totalBytesReadable.value
  22414. }) : props.chips ? fileNames.value.map(text => vue.createVNode(VChip, {
  22415. "key": text,
  22416. "size": "small",
  22417. "text": text
  22418. }, null)) : fileNames.value.join(', '))])]);
  22419. }
  22420. });
  22421. },
  22422. 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, {
  22423. "active": !!model.value?.length,
  22424. "value": counterValue.value,
  22425. "disabled": props.disabled
  22426. }, slots.counter)])]) : undefined
  22427. });
  22428. });
  22429. return forwardRefs({}, vInputRef, vFieldRef, inputRef);
  22430. }
  22431. });
  22432. const makeVFooterProps = propsFactory({
  22433. app: Boolean,
  22434. color: String,
  22435. height: {
  22436. type: [Number, String],
  22437. default: 'auto'
  22438. },
  22439. ...makeBorderProps(),
  22440. ...makeComponentProps(),
  22441. ...makeElevationProps(),
  22442. ...makeLayoutItemProps(),
  22443. ...makeRoundedProps(),
  22444. ...makeTagProps({
  22445. tag: 'footer'
  22446. }),
  22447. ...makeThemeProps()
  22448. }, 'VFooter');
  22449. const VFooter = genericComponent()({
  22450. name: 'VFooter',
  22451. props: makeVFooterProps(),
  22452. setup(props, _ref) {
  22453. let {
  22454. slots
  22455. } = _ref;
  22456. const layoutItemStyles = vue.ref();
  22457. const {
  22458. themeClasses
  22459. } = provideTheme(props);
  22460. const {
  22461. backgroundColorClasses,
  22462. backgroundColorStyles
  22463. } = useBackgroundColor(vue.toRef(props, 'color'));
  22464. const {
  22465. borderClasses
  22466. } = useBorder(props);
  22467. const {
  22468. elevationClasses
  22469. } = useElevation(props);
  22470. const {
  22471. roundedClasses
  22472. } = useRounded(props);
  22473. const autoHeight = vue.shallowRef(32);
  22474. const {
  22475. resizeRef
  22476. } = useResizeObserver(entries => {
  22477. if (!entries.length) return;
  22478. autoHeight.value = entries[0].target.clientHeight;
  22479. });
  22480. const height = vue.computed(() => props.height === 'auto' ? autoHeight.value : parseInt(props.height, 10));
  22481. useToggleScope(() => props.app, () => {
  22482. const layout = useLayoutItem({
  22483. id: props.name,
  22484. order: vue.computed(() => parseInt(props.order, 10)),
  22485. position: vue.computed(() => 'bottom'),
  22486. layoutSize: height,
  22487. elementSize: vue.computed(() => props.height === 'auto' ? undefined : height.value),
  22488. active: vue.computed(() => props.app),
  22489. absolute: vue.toRef(props, 'absolute')
  22490. });
  22491. vue.watchEffect(() => {
  22492. layoutItemStyles.value = layout.layoutItemStyles.value;
  22493. });
  22494. });
  22495. useRender(() => vue.createVNode(props.tag, {
  22496. "ref": resizeRef,
  22497. "class": ['v-footer', themeClasses.value, backgroundColorClasses.value, borderClasses.value, elevationClasses.value, roundedClasses.value, props.class],
  22498. "style": [backgroundColorStyles.value, props.app ? layoutItemStyles.value : {
  22499. height: convertToUnit(props.height)
  22500. }, props.style]
  22501. }, slots));
  22502. return {};
  22503. }
  22504. });
  22505. // Types
  22506. const makeVFormProps = propsFactory({
  22507. ...makeComponentProps(),
  22508. ...makeFormProps()
  22509. }, 'VForm');
  22510. const VForm = genericComponent()({
  22511. name: 'VForm',
  22512. props: makeVFormProps(),
  22513. emits: {
  22514. 'update:modelValue': val => true,
  22515. submit: e => true
  22516. },
  22517. setup(props, _ref) {
  22518. let {
  22519. slots,
  22520. emit
  22521. } = _ref;
  22522. const form = createForm(props);
  22523. const formRef = vue.ref();
  22524. function onReset(e) {
  22525. e.preventDefault();
  22526. form.reset();
  22527. }
  22528. function onSubmit(_e) {
  22529. const e = _e;
  22530. const ready = form.validate();
  22531. e.then = ready.then.bind(ready);
  22532. e.catch = ready.catch.bind(ready);
  22533. e.finally = ready.finally.bind(ready);
  22534. emit('submit', e);
  22535. if (!e.defaultPrevented) {
  22536. ready.then(_ref2 => {
  22537. let {
  22538. valid
  22539. } = _ref2;
  22540. if (valid) {
  22541. formRef.value?.submit();
  22542. }
  22543. });
  22544. }
  22545. e.preventDefault();
  22546. }
  22547. useRender(() => vue.createVNode("form", {
  22548. "ref": formRef,
  22549. "class": ['v-form', props.class],
  22550. "style": props.style,
  22551. "novalidate": true,
  22552. "onReset": onReset,
  22553. "onSubmit": onSubmit
  22554. }, [slots.default?.(form)]));
  22555. return forwardRefs(form, formRef);
  22556. }
  22557. });
  22558. // Composables
  22559. const makeVHoverProps = propsFactory({
  22560. disabled: Boolean,
  22561. modelValue: {
  22562. type: Boolean,
  22563. default: null
  22564. },
  22565. ...makeDelayProps()
  22566. }, 'VHover');
  22567. const VHover = genericComponent()({
  22568. name: 'VHover',
  22569. props: makeVHoverProps(),
  22570. emits: {
  22571. 'update:modelValue': value => true
  22572. },
  22573. setup(props, _ref) {
  22574. let {
  22575. slots
  22576. } = _ref;
  22577. const isHovering = useProxiedModel(props, 'modelValue');
  22578. const {
  22579. runOpenDelay,
  22580. runCloseDelay
  22581. } = useDelay(props, value => !props.disabled && (isHovering.value = value));
  22582. return () => slots.default?.({
  22583. isHovering: isHovering.value,
  22584. props: {
  22585. onMouseenter: runOpenDelay,
  22586. onMouseleave: runCloseDelay
  22587. }
  22588. });
  22589. }
  22590. });
  22591. // Types
  22592. const makeVInfiniteScrollProps = propsFactory({
  22593. color: String,
  22594. direction: {
  22595. type: String,
  22596. default: 'vertical',
  22597. validator: v => ['vertical', 'horizontal'].includes(v)
  22598. },
  22599. side: {
  22600. type: String,
  22601. default: 'end',
  22602. validator: v => ['start', 'end', 'both'].includes(v)
  22603. },
  22604. mode: {
  22605. type: String,
  22606. default: 'intersect',
  22607. validator: v => ['intersect', 'manual'].includes(v)
  22608. },
  22609. margin: [Number, String],
  22610. loadMoreText: {
  22611. type: String,
  22612. default: '$vuetify.infiniteScroll.loadMore'
  22613. },
  22614. emptyText: {
  22615. type: String,
  22616. default: '$vuetify.infiniteScroll.empty'
  22617. },
  22618. ...makeDimensionProps(),
  22619. ...makeTagProps()
  22620. }, 'VInfiniteScroll');
  22621. const VInfiniteScrollIntersect = defineComponent({
  22622. name: 'VInfiniteScrollIntersect',
  22623. props: {
  22624. side: {
  22625. type: String,
  22626. required: true
  22627. },
  22628. rootMargin: String
  22629. },
  22630. emits: {
  22631. intersect: (side, isIntersecting) => true
  22632. },
  22633. setup(props, _ref) {
  22634. let {
  22635. emit
  22636. } = _ref;
  22637. const {
  22638. intersectionRef,
  22639. isIntersecting
  22640. } = useIntersectionObserver();
  22641. vue.watch(isIntersecting, async val => {
  22642. emit('intersect', props.side, val);
  22643. });
  22644. useRender(() => vue.createVNode("div", {
  22645. "class": "v-infinite-scroll-intersect",
  22646. "style": {
  22647. '--v-infinite-margin-size': props.rootMargin
  22648. },
  22649. "ref": intersectionRef
  22650. }, [vue.createTextVNode("\xA0")]));
  22651. return {};
  22652. }
  22653. });
  22654. const VInfiniteScroll = genericComponent()({
  22655. name: 'VInfiniteScroll',
  22656. props: makeVInfiniteScrollProps(),
  22657. emits: {
  22658. load: options => true
  22659. },
  22660. setup(props, _ref2) {
  22661. let {
  22662. slots,
  22663. emit
  22664. } = _ref2;
  22665. const rootEl = vue.ref();
  22666. const startStatus = vue.shallowRef('ok');
  22667. const endStatus = vue.shallowRef('ok');
  22668. const margin = vue.computed(() => convertToUnit(props.margin));
  22669. const isIntersecting = vue.shallowRef(false);
  22670. function setScrollAmount(amount) {
  22671. if (!rootEl.value) return;
  22672. const property = props.direction === 'vertical' ? 'scrollTop' : 'scrollLeft';
  22673. rootEl.value[property] = amount;
  22674. }
  22675. function getScrollAmount() {
  22676. if (!rootEl.value) return 0;
  22677. const property = props.direction === 'vertical' ? 'scrollTop' : 'scrollLeft';
  22678. return rootEl.value[property];
  22679. }
  22680. function getScrollSize() {
  22681. if (!rootEl.value) return 0;
  22682. const property = props.direction === 'vertical' ? 'scrollHeight' : 'scrollWidth';
  22683. return rootEl.value[property];
  22684. }
  22685. function getContainerSize() {
  22686. if (!rootEl.value) return 0;
  22687. const property = props.direction === 'vertical' ? 'clientHeight' : 'clientWidth';
  22688. return rootEl.value[property];
  22689. }
  22690. vue.onMounted(() => {
  22691. if (!rootEl.value) return;
  22692. if (props.side === 'start') {
  22693. setScrollAmount(getScrollSize());
  22694. } else if (props.side === 'both') {
  22695. setScrollAmount(getScrollSize() / 2 - getContainerSize() / 2);
  22696. }
  22697. });
  22698. function setStatus(side, status) {
  22699. if (side === 'start') {
  22700. startStatus.value = status;
  22701. } else if (side === 'end') {
  22702. endStatus.value = status;
  22703. }
  22704. }
  22705. function getStatus(side) {
  22706. return side === 'start' ? startStatus.value : endStatus.value;
  22707. }
  22708. let previousScrollSize = 0;
  22709. function handleIntersect(side, _isIntersecting) {
  22710. isIntersecting.value = _isIntersecting;
  22711. if (isIntersecting.value) {
  22712. intersecting(side);
  22713. }
  22714. }
  22715. function intersecting(side) {
  22716. if (props.mode !== 'manual' && !isIntersecting.value) return;
  22717. const status = getStatus(side);
  22718. if (!rootEl.value || ['empty', 'loading'].includes(status)) return;
  22719. previousScrollSize = getScrollSize();
  22720. setStatus(side, 'loading');
  22721. function done(status) {
  22722. setStatus(side, status);
  22723. vue.nextTick(() => {
  22724. if (status === 'empty' || status === 'error') return;
  22725. if (status === 'ok' && side === 'start') {
  22726. setScrollAmount(getScrollSize() - previousScrollSize + getScrollAmount());
  22727. }
  22728. if (props.mode !== 'manual') {
  22729. vue.nextTick(() => {
  22730. window.requestAnimationFrame(() => {
  22731. window.requestAnimationFrame(() => {
  22732. window.requestAnimationFrame(() => {
  22733. intersecting(side);
  22734. });
  22735. });
  22736. });
  22737. });
  22738. }
  22739. });
  22740. }
  22741. emit('load', {
  22742. side,
  22743. done
  22744. });
  22745. }
  22746. const {
  22747. t
  22748. } = useLocale();
  22749. function renderSide(side, status) {
  22750. if (props.side !== side && props.side !== 'both') return;
  22751. const onClick = () => intersecting(side);
  22752. const slotProps = {
  22753. side,
  22754. props: {
  22755. onClick,
  22756. color: props.color
  22757. }
  22758. };
  22759. if (status === 'error') return slots.error?.(slotProps);
  22760. if (status === 'empty') return slots.empty?.(slotProps) ?? vue.createVNode("div", null, [t(props.emptyText)]);
  22761. if (props.mode === 'manual') {
  22762. if (status === 'loading') {
  22763. return slots.loading?.(slotProps) ?? vue.createVNode(VProgressCircular, {
  22764. "indeterminate": true,
  22765. "color": props.color
  22766. }, null);
  22767. }
  22768. return slots['load-more']?.(slotProps) ?? vue.createVNode(VBtn, {
  22769. "variant": "outlined",
  22770. "color": props.color,
  22771. "onClick": onClick
  22772. }, {
  22773. default: () => [t(props.loadMoreText)]
  22774. });
  22775. }
  22776. return slots.loading?.(slotProps) ?? vue.createVNode(VProgressCircular, {
  22777. "indeterminate": true,
  22778. "color": props.color
  22779. }, null);
  22780. }
  22781. const {
  22782. dimensionStyles
  22783. } = useDimension(props);
  22784. useRender(() => {
  22785. const Tag = props.tag;
  22786. const hasStartIntersect = props.side === 'start' || props.side === 'both';
  22787. const hasEndIntersect = props.side === 'end' || props.side === 'both';
  22788. const intersectMode = props.mode === 'intersect';
  22789. return vue.createVNode(Tag, {
  22790. "ref": rootEl,
  22791. "class": ['v-infinite-scroll', `v-infinite-scroll--${props.direction}`, {
  22792. 'v-infinite-scroll--start': hasStartIntersect,
  22793. 'v-infinite-scroll--end': hasEndIntersect
  22794. }],
  22795. "style": dimensionStyles.value
  22796. }, {
  22797. default: () => [vue.createVNode("div", {
  22798. "class": "v-infinite-scroll__side"
  22799. }, [renderSide('start', startStatus.value)]), hasStartIntersect && intersectMode && vue.createVNode(VInfiniteScrollIntersect, {
  22800. "key": "start",
  22801. "side": "start",
  22802. "onIntersect": handleIntersect,
  22803. "rootMargin": margin.value
  22804. }, null), slots.default?.(), hasEndIntersect && intersectMode && vue.createVNode(VInfiniteScrollIntersect, {
  22805. "key": "end",
  22806. "side": "end",
  22807. "onIntersect": handleIntersect,
  22808. "rootMargin": margin.value
  22809. }, null), vue.createVNode("div", {
  22810. "class": "v-infinite-scroll__side"
  22811. }, [renderSide('end', endStatus.value)])]
  22812. });
  22813. });
  22814. }
  22815. });
  22816. // Types
  22817. const VItemGroupSymbol = Symbol.for('vuetify:v-item-group');
  22818. const makeVItemGroupProps = propsFactory({
  22819. ...makeComponentProps(),
  22820. ...makeGroupProps({
  22821. selectedClass: 'v-item--selected'
  22822. }),
  22823. ...makeTagProps(),
  22824. ...makeThemeProps()
  22825. }, 'VItemGroup');
  22826. const VItemGroup = genericComponent()({
  22827. name: 'VItemGroup',
  22828. props: makeVItemGroupProps(),
  22829. emits: {
  22830. 'update:modelValue': value => true
  22831. },
  22832. setup(props, _ref) {
  22833. let {
  22834. slots
  22835. } = _ref;
  22836. const {
  22837. themeClasses
  22838. } = provideTheme(props);
  22839. const {
  22840. isSelected,
  22841. select,
  22842. next,
  22843. prev,
  22844. selected
  22845. } = useGroup(props, VItemGroupSymbol);
  22846. return () => vue.createVNode(props.tag, {
  22847. "class": ['v-item-group', themeClasses.value, props.class],
  22848. "style": props.style
  22849. }, {
  22850. default: () => [slots.default?.({
  22851. isSelected,
  22852. select,
  22853. next,
  22854. prev,
  22855. selected: selected.value
  22856. })]
  22857. });
  22858. }
  22859. });
  22860. // Composables
  22861. const VItem = genericComponent()({
  22862. name: 'VItem',
  22863. props: makeGroupItemProps(),
  22864. emits: {
  22865. 'group:selected': val => true
  22866. },
  22867. setup(props, _ref) {
  22868. let {
  22869. slots
  22870. } = _ref;
  22871. const {
  22872. isSelected,
  22873. select,
  22874. toggle,
  22875. selectedClass,
  22876. value,
  22877. disabled
  22878. } = useGroupItem(props, VItemGroupSymbol);
  22879. return () => slots.default?.({
  22880. isSelected: isSelected.value,
  22881. selectedClass: selectedClass.value,
  22882. select,
  22883. toggle,
  22884. value: value.value,
  22885. disabled: disabled.value
  22886. });
  22887. }
  22888. });
  22889. // Styles
  22890. const VKbd = createSimpleFunctional('v-kbd', 'kbd');
  22891. const makeVLayoutProps = propsFactory({
  22892. ...makeComponentProps(),
  22893. ...makeDimensionProps(),
  22894. ...makeLayoutProps()
  22895. }, 'VLayout');
  22896. const VLayout = genericComponent()({
  22897. name: 'VLayout',
  22898. props: makeVLayoutProps(),
  22899. setup(props, _ref) {
  22900. let {
  22901. slots
  22902. } = _ref;
  22903. const {
  22904. layoutClasses,
  22905. layoutStyles,
  22906. getLayoutItem,
  22907. items,
  22908. layoutRef
  22909. } = createLayout(props);
  22910. const {
  22911. dimensionStyles
  22912. } = useDimension(props);
  22913. useRender(() => vue.createVNode("div", {
  22914. "ref": layoutRef,
  22915. "class": [layoutClasses.value, props.class],
  22916. "style": [dimensionStyles.value, layoutStyles.value, props.style]
  22917. }, [slots.default?.()]));
  22918. return {
  22919. getLayoutItem,
  22920. items
  22921. };
  22922. }
  22923. });
  22924. // Types
  22925. const makeVLayoutItemProps = propsFactory({
  22926. position: {
  22927. type: String,
  22928. required: true
  22929. },
  22930. size: {
  22931. type: [Number, String],
  22932. default: 300
  22933. },
  22934. modelValue: Boolean,
  22935. ...makeComponentProps(),
  22936. ...makeLayoutItemProps()
  22937. }, 'VLayoutItem');
  22938. const VLayoutItem = genericComponent()({
  22939. name: 'VLayoutItem',
  22940. props: makeVLayoutItemProps(),
  22941. setup(props, _ref) {
  22942. let {
  22943. slots
  22944. } = _ref;
  22945. const {
  22946. layoutItemStyles
  22947. } = useLayoutItem({
  22948. id: props.name,
  22949. order: vue.computed(() => parseInt(props.order, 10)),
  22950. position: vue.toRef(props, 'position'),
  22951. elementSize: vue.toRef(props, 'size'),
  22952. layoutSize: vue.toRef(props, 'size'),
  22953. active: vue.toRef(props, 'modelValue'),
  22954. absolute: vue.toRef(props, 'absolute')
  22955. });
  22956. return () => vue.createVNode("div", {
  22957. "class": ['v-layout-item', props.class],
  22958. "style": [layoutItemStyles.value, props.style]
  22959. }, [slots.default?.()]);
  22960. }
  22961. });
  22962. // Types
  22963. const makeVLazyProps = propsFactory({
  22964. modelValue: Boolean,
  22965. options: {
  22966. type: Object,
  22967. // For more information on types, navigate to:
  22968. // https://developer.mozilla.org/en-US/docs/Web/API/Intersection_Observer_API
  22969. default: () => ({
  22970. root: undefined,
  22971. rootMargin: undefined,
  22972. threshold: undefined
  22973. })
  22974. },
  22975. ...makeComponentProps(),
  22976. ...makeDimensionProps(),
  22977. ...makeTagProps(),
  22978. ...makeTransitionProps({
  22979. transition: 'fade-transition'
  22980. })
  22981. }, 'VLazy');
  22982. const VLazy = genericComponent()({
  22983. name: 'VLazy',
  22984. directives: {
  22985. intersect: Intersect
  22986. },
  22987. props: makeVLazyProps(),
  22988. emits: {
  22989. 'update:modelValue': value => true
  22990. },
  22991. setup(props, _ref) {
  22992. let {
  22993. slots
  22994. } = _ref;
  22995. const {
  22996. dimensionStyles
  22997. } = useDimension(props);
  22998. const isActive = useProxiedModel(props, 'modelValue');
  22999. function onIntersect(isIntersecting) {
  23000. if (isActive.value) return;
  23001. isActive.value = isIntersecting;
  23002. }
  23003. useRender(() => vue.withDirectives(vue.createVNode(props.tag, {
  23004. "class": ['v-lazy', props.class],
  23005. "style": [dimensionStyles.value, props.style]
  23006. }, {
  23007. default: () => [isActive.value && vue.createVNode(MaybeTransition, {
  23008. "transition": props.transition,
  23009. "appear": true
  23010. }, {
  23011. default: () => [slots.default?.()]
  23012. })]
  23013. }), [[vue.resolveDirective("intersect"), {
  23014. handler: onIntersect,
  23015. options: props.options
  23016. }, null]]));
  23017. return {};
  23018. }
  23019. });
  23020. const makeVLocaleProviderProps = propsFactory({
  23021. locale: String,
  23022. fallbackLocale: String,
  23023. messages: Object,
  23024. rtl: {
  23025. type: Boolean,
  23026. default: undefined
  23027. },
  23028. ...makeComponentProps()
  23029. }, 'VLocaleProvider');
  23030. const VLocaleProvider = genericComponent()({
  23031. name: 'VLocaleProvider',
  23032. props: makeVLocaleProviderProps(),
  23033. setup(props, _ref) {
  23034. let {
  23035. slots
  23036. } = _ref;
  23037. const {
  23038. rtlClasses
  23039. } = provideLocale(props);
  23040. useRender(() => vue.createVNode("div", {
  23041. "class": ['v-locale-provider', rtlClasses.value, props.class],
  23042. "style": props.style
  23043. }, [slots.default?.()]));
  23044. return {};
  23045. }
  23046. });
  23047. const makeVMainProps = propsFactory({
  23048. scrollable: Boolean,
  23049. ...makeComponentProps(),
  23050. ...makeDimensionProps(),
  23051. ...makeTagProps({
  23052. tag: 'main'
  23053. })
  23054. }, 'VMain');
  23055. const VMain = genericComponent()({
  23056. name: 'VMain',
  23057. props: makeVMainProps(),
  23058. setup(props, _ref) {
  23059. let {
  23060. slots
  23061. } = _ref;
  23062. const {
  23063. dimensionStyles
  23064. } = useDimension(props);
  23065. const {
  23066. mainStyles
  23067. } = useLayout();
  23068. const {
  23069. ssrBootStyles
  23070. } = useSsrBoot();
  23071. useRender(() => vue.createVNode(props.tag, {
  23072. "class": ['v-main', {
  23073. 'v-main--scrollable': props.scrollable
  23074. }, props.class],
  23075. "style": [mainStyles.value, ssrBootStyles.value, dimensionStyles.value, props.style]
  23076. }, {
  23077. default: () => [props.scrollable ? vue.createVNode("div", {
  23078. "class": "v-main__scroller"
  23079. }, [slots.default?.()]) : slots.default?.()]
  23080. }));
  23081. return {};
  23082. }
  23083. });
  23084. // Utilities
  23085. // Types
  23086. function useSticky(_ref) {
  23087. let {
  23088. rootEl,
  23089. isSticky,
  23090. layoutItemStyles
  23091. } = _ref;
  23092. const isStuck = vue.shallowRef(false);
  23093. const stuckPosition = vue.shallowRef(0);
  23094. const stickyStyles = vue.computed(() => {
  23095. const side = typeof isStuck.value === 'boolean' ? 'top' : isStuck.value;
  23096. return [isSticky.value ? {
  23097. top: 'auto',
  23098. bottom: 'auto',
  23099. height: undefined
  23100. } : undefined, isStuck.value ? {
  23101. [side]: convertToUnit(stuckPosition.value)
  23102. } : {
  23103. top: layoutItemStyles.value.top
  23104. }];
  23105. });
  23106. vue.onMounted(() => {
  23107. vue.watch(isSticky, val => {
  23108. if (val) {
  23109. window.addEventListener('scroll', onScroll, {
  23110. passive: true
  23111. });
  23112. } else {
  23113. window.removeEventListener('scroll', onScroll);
  23114. }
  23115. }, {
  23116. immediate: true
  23117. });
  23118. });
  23119. vue.onBeforeUnmount(() => {
  23120. window.removeEventListener('scroll', onScroll);
  23121. });
  23122. let lastScrollTop = 0;
  23123. function onScroll() {
  23124. const direction = lastScrollTop > window.scrollY ? 'up' : 'down';
  23125. const rect = rootEl.value.getBoundingClientRect();
  23126. const layoutTop = parseFloat(layoutItemStyles.value.top ?? 0);
  23127. const top = window.scrollY - Math.max(0, stuckPosition.value - layoutTop);
  23128. const bottom = rect.height + Math.max(stuckPosition.value, layoutTop) - window.scrollY - window.innerHeight;
  23129. const bodyScroll = parseFloat(getComputedStyle(rootEl.value).getPropertyValue('--v-body-scroll-y')) || 0;
  23130. if (rect.height < window.innerHeight - layoutTop) {
  23131. isStuck.value = 'top';
  23132. stuckPosition.value = layoutTop;
  23133. } else if (direction === 'up' && isStuck.value === 'bottom' || direction === 'down' && isStuck.value === 'top') {
  23134. stuckPosition.value = window.scrollY + rect.top - bodyScroll;
  23135. isStuck.value = true;
  23136. } else if (direction === 'down' && bottom <= 0) {
  23137. stuckPosition.value = 0;
  23138. isStuck.value = 'bottom';
  23139. } else if (direction === 'up' && top <= 0) {
  23140. if (!bodyScroll) {
  23141. stuckPosition.value = rect.top + top;
  23142. isStuck.value = 'top';
  23143. } else if (isStuck.value !== 'top') {
  23144. stuckPosition.value = -top + bodyScroll + layoutTop;
  23145. isStuck.value = 'top';
  23146. }
  23147. }
  23148. lastScrollTop = window.scrollY;
  23149. }
  23150. return {
  23151. isStuck,
  23152. stickyStyles
  23153. };
  23154. }
  23155. // Utilities
  23156. const HORIZON = 100; // ms
  23157. const HISTORY = 20; // number of samples to keep
  23158. /** @see https://android.googlesource.com/platform/frameworks/native/+/master/libs/input/VelocityTracker.cpp */
  23159. function kineticEnergyToVelocity(work) {
  23160. const sqrt2 = 1.41421356237;
  23161. return (work < 0 ? -1.0 : 1.0) * Math.sqrt(Math.abs(work)) * sqrt2;
  23162. }
  23163. /**
  23164. * Returns pointer velocity in px/s
  23165. */
  23166. function calculateImpulseVelocity(samples) {
  23167. // The input should be in reversed time order (most recent sample at index i=0)
  23168. if (samples.length < 2) {
  23169. // if 0 or 1 points, velocity is zero
  23170. return 0;
  23171. }
  23172. // if (samples[1].t > samples[0].t) {
  23173. // // Algorithm will still work, but not perfectly
  23174. // consoleWarn('Samples provided to calculateImpulseVelocity in the wrong order')
  23175. // }
  23176. if (samples.length === 2) {
  23177. // if 2 points, basic linear calculation
  23178. if (samples[1].t === samples[0].t) {
  23179. // consoleWarn(`Events have identical time stamps t=${samples[0].t}, setting velocity = 0`)
  23180. return 0;
  23181. }
  23182. return (samples[1].d - samples[0].d) / (samples[1].t - samples[0].t);
  23183. }
  23184. // Guaranteed to have at least 3 points here
  23185. // start with the oldest sample and go forward in time
  23186. let work = 0;
  23187. for (let i = samples.length - 1; i > 0; i--) {
  23188. if (samples[i].t === samples[i - 1].t) {
  23189. // consoleWarn(`Events have identical time stamps t=${samples[i].t}, skipping sample`)
  23190. continue;
  23191. }
  23192. const vprev = kineticEnergyToVelocity(work); // v[i-1]
  23193. const vcurr = (samples[i].d - samples[i - 1].d) / (samples[i].t - samples[i - 1].t); // v[i]
  23194. work += (vcurr - vprev) * Math.abs(vcurr);
  23195. if (i === samples.length - 1) {
  23196. work *= 0.5;
  23197. }
  23198. }
  23199. return kineticEnergyToVelocity(work) * 1000;
  23200. }
  23201. function useVelocity() {
  23202. const touches = {};
  23203. function addMovement(e) {
  23204. Array.from(e.changedTouches).forEach(touch => {
  23205. const samples = touches[touch.identifier] ?? (touches[touch.identifier] = new CircularBuffer(HISTORY));
  23206. samples.push([e.timeStamp, touch]);
  23207. });
  23208. }
  23209. function endTouch(e) {
  23210. Array.from(e.changedTouches).forEach(touch => {
  23211. delete touches[touch.identifier];
  23212. });
  23213. }
  23214. function getVelocity(id) {
  23215. const samples = touches[id]?.values().reverse();
  23216. if (!samples) {
  23217. throw new Error(`No samples for touch id ${id}`);
  23218. }
  23219. const newest = samples[0];
  23220. const x = [];
  23221. const y = [];
  23222. for (const val of samples) {
  23223. if (newest[0] - val[0] > HORIZON) break;
  23224. x.push({
  23225. t: val[0],
  23226. d: val[1].clientX
  23227. });
  23228. y.push({
  23229. t: val[0],
  23230. d: val[1].clientY
  23231. });
  23232. }
  23233. return {
  23234. x: calculateImpulseVelocity(x),
  23235. y: calculateImpulseVelocity(y),
  23236. get direction() {
  23237. const {
  23238. x,
  23239. y
  23240. } = this;
  23241. const [absX, absY] = [Math.abs(x), Math.abs(y)];
  23242. return absX > absY && x >= 0 ? 'right' : absX > absY && x <= 0 ? 'left' : absY > absX && y >= 0 ? 'down' : absY > absX && y <= 0 ? 'up' : oops$1();
  23243. }
  23244. };
  23245. }
  23246. return {
  23247. addMovement,
  23248. endTouch,
  23249. getVelocity
  23250. };
  23251. }
  23252. function oops$1() {
  23253. throw new Error();
  23254. }
  23255. // Composables
  23256. // Types
  23257. function useTouch(_ref) {
  23258. let {
  23259. el,
  23260. isActive,
  23261. isTemporary,
  23262. width,
  23263. touchless,
  23264. position
  23265. } = _ref;
  23266. vue.onMounted(() => {
  23267. window.addEventListener('touchstart', onTouchstart, {
  23268. passive: true
  23269. });
  23270. window.addEventListener('touchmove', onTouchmove, {
  23271. passive: false
  23272. });
  23273. window.addEventListener('touchend', onTouchend, {
  23274. passive: true
  23275. });
  23276. });
  23277. vue.onBeforeUnmount(() => {
  23278. window.removeEventListener('touchstart', onTouchstart);
  23279. window.removeEventListener('touchmove', onTouchmove);
  23280. window.removeEventListener('touchend', onTouchend);
  23281. });
  23282. const isHorizontal = vue.computed(() => ['left', 'right'].includes(position.value));
  23283. const {
  23284. addMovement,
  23285. endTouch,
  23286. getVelocity
  23287. } = useVelocity();
  23288. let maybeDragging = false;
  23289. const isDragging = vue.shallowRef(false);
  23290. const dragProgress = vue.shallowRef(0);
  23291. const offset = vue.shallowRef(0);
  23292. let start;
  23293. function getOffset(pos, active) {
  23294. 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);
  23295. }
  23296. function getProgress(pos) {
  23297. let limit = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : true;
  23298. 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();
  23299. return limit ? Math.max(0, Math.min(1, progress)) : progress;
  23300. }
  23301. function onTouchstart(e) {
  23302. if (touchless.value) return;
  23303. const touchX = e.changedTouches[0].clientX;
  23304. const touchY = e.changedTouches[0].clientY;
  23305. const touchZone = 25;
  23306. 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();
  23307. 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());
  23308. if (inTouchZone || inElement || isActive.value && isTemporary.value) {
  23309. start = [touchX, touchY];
  23310. offset.value = getOffset(isHorizontal.value ? touchX : touchY, isActive.value);
  23311. dragProgress.value = getProgress(isHorizontal.value ? touchX : touchY);
  23312. maybeDragging = offset.value > -20 && offset.value < 80;
  23313. endTouch(e);
  23314. addMovement(e);
  23315. }
  23316. }
  23317. function onTouchmove(e) {
  23318. const touchX = e.changedTouches[0].clientX;
  23319. const touchY = e.changedTouches[0].clientY;
  23320. if (maybeDragging) {
  23321. if (!e.cancelable) {
  23322. maybeDragging = false;
  23323. return;
  23324. }
  23325. const dx = Math.abs(touchX - start[0]);
  23326. const dy = Math.abs(touchY - start[1]);
  23327. const thresholdMet = isHorizontal.value ? dx > dy && dx > 3 : dy > dx && dy > 3;
  23328. if (thresholdMet) {
  23329. isDragging.value = true;
  23330. maybeDragging = false;
  23331. } else if ((isHorizontal.value ? dy : dx) > 3) {
  23332. maybeDragging = false;
  23333. }
  23334. }
  23335. if (!isDragging.value) return;
  23336. e.preventDefault();
  23337. addMovement(e);
  23338. const progress = getProgress(isHorizontal.value ? touchX : touchY, false);
  23339. dragProgress.value = Math.max(0, Math.min(1, progress));
  23340. if (progress > 1) {
  23341. offset.value = getOffset(isHorizontal.value ? touchX : touchY, true);
  23342. } else if (progress < 0) {
  23343. offset.value = getOffset(isHorizontal.value ? touchX : touchY, false);
  23344. }
  23345. }
  23346. function onTouchend(e) {
  23347. maybeDragging = false;
  23348. if (!isDragging.value) return;
  23349. addMovement(e);
  23350. isDragging.value = false;
  23351. const velocity = getVelocity(e.changedTouches[0].identifier);
  23352. const vx = Math.abs(velocity.x);
  23353. const vy = Math.abs(velocity.y);
  23354. const thresholdMet = isHorizontal.value ? vx > vy && vx > 400 : vy > vx && vy > 3;
  23355. if (thresholdMet) {
  23356. isActive.value = velocity.direction === ({
  23357. left: 'right',
  23358. right: 'left',
  23359. top: 'down',
  23360. bottom: 'up'
  23361. }[position.value] || oops());
  23362. } else {
  23363. isActive.value = dragProgress.value > 0.5;
  23364. }
  23365. }
  23366. const dragStyles = vue.computed(() => {
  23367. return isDragging.value ? {
  23368. 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(),
  23369. transition: 'none'
  23370. } : undefined;
  23371. });
  23372. useToggleScope(isDragging, () => {
  23373. const transform = el.value?.style.transform ?? null;
  23374. const transition = el.value?.style.transition ?? null;
  23375. vue.watchEffect(() => {
  23376. el.value?.style.setProperty('transform', dragStyles.value?.transform || 'none');
  23377. el.value?.style.setProperty('transition', dragStyles.value?.transition || null);
  23378. });
  23379. vue.onScopeDispose(() => {
  23380. el.value?.style.setProperty('transform', transform);
  23381. el.value?.style.setProperty('transition', transition);
  23382. });
  23383. });
  23384. return {
  23385. isDragging,
  23386. dragProgress,
  23387. dragStyles
  23388. };
  23389. }
  23390. function oops() {
  23391. throw new Error();
  23392. }
  23393. // Types
  23394. const locations = ['start', 'end', 'left', 'right', 'top', 'bottom'];
  23395. const makeVNavigationDrawerProps = propsFactory({
  23396. color: String,
  23397. disableResizeWatcher: Boolean,
  23398. disableRouteWatcher: Boolean,
  23399. expandOnHover: Boolean,
  23400. floating: Boolean,
  23401. modelValue: {
  23402. type: Boolean,
  23403. default: null
  23404. },
  23405. permanent: Boolean,
  23406. rail: {
  23407. type: Boolean,
  23408. default: null
  23409. },
  23410. railWidth: {
  23411. type: [Number, String],
  23412. default: 56
  23413. },
  23414. scrim: {
  23415. type: [Boolean, String],
  23416. default: true
  23417. },
  23418. image: String,
  23419. temporary: Boolean,
  23420. persistent: Boolean,
  23421. touchless: Boolean,
  23422. width: {
  23423. type: [Number, String],
  23424. default: 256
  23425. },
  23426. location: {
  23427. type: String,
  23428. default: 'start',
  23429. validator: value => locations.includes(value)
  23430. },
  23431. sticky: Boolean,
  23432. ...makeBorderProps(),
  23433. ...makeComponentProps(),
  23434. ...makeDelayProps(),
  23435. ...makeDisplayProps({
  23436. mobile: null
  23437. }),
  23438. ...makeElevationProps(),
  23439. ...makeLayoutItemProps(),
  23440. ...makeRoundedProps(),
  23441. ...makeTagProps({
  23442. tag: 'nav'
  23443. }),
  23444. ...makeThemeProps()
  23445. }, 'VNavigationDrawer');
  23446. const VNavigationDrawer = genericComponent()({
  23447. name: 'VNavigationDrawer',
  23448. props: makeVNavigationDrawerProps(),
  23449. emits: {
  23450. 'update:modelValue': val => true,
  23451. 'update:rail': val => true
  23452. },
  23453. setup(props, _ref) {
  23454. let {
  23455. attrs,
  23456. emit,
  23457. slots
  23458. } = _ref;
  23459. const {
  23460. isRtl
  23461. } = useRtl();
  23462. const {
  23463. themeClasses
  23464. } = provideTheme(props);
  23465. const {
  23466. borderClasses
  23467. } = useBorder(props);
  23468. const {
  23469. backgroundColorClasses,
  23470. backgroundColorStyles
  23471. } = useBackgroundColor(vue.toRef(props, 'color'));
  23472. const {
  23473. elevationClasses
  23474. } = useElevation(props);
  23475. const {
  23476. displayClasses,
  23477. mobile
  23478. } = useDisplay(props);
  23479. const {
  23480. roundedClasses
  23481. } = useRounded(props);
  23482. const router = useRouter();
  23483. const isActive = useProxiedModel(props, 'modelValue', null, v => !!v);
  23484. const {
  23485. ssrBootStyles
  23486. } = useSsrBoot();
  23487. const {
  23488. scopeId
  23489. } = useScopeId();
  23490. const rootEl = vue.ref();
  23491. const isHovering = vue.shallowRef(false);
  23492. const {
  23493. runOpenDelay,
  23494. runCloseDelay
  23495. } = useDelay(props, value => {
  23496. isHovering.value = value;
  23497. });
  23498. const width = vue.computed(() => {
  23499. return props.rail && props.expandOnHover && isHovering.value ? Number(props.width) : Number(props.rail ? props.railWidth : props.width);
  23500. });
  23501. const location = vue.computed(() => {
  23502. return toPhysical(props.location, isRtl.value);
  23503. });
  23504. const isPersistent = vue.computed(() => props.persistent);
  23505. const isTemporary = vue.computed(() => !props.permanent && (mobile.value || props.temporary));
  23506. const isSticky = vue.computed(() => props.sticky && !isTemporary.value && location.value !== 'bottom');
  23507. useToggleScope(() => props.expandOnHover && props.rail != null, () => {
  23508. vue.watch(isHovering, val => emit('update:rail', !val));
  23509. });
  23510. useToggleScope(() => !props.disableResizeWatcher, () => {
  23511. vue.watch(isTemporary, val => !props.permanent && vue.nextTick(() => isActive.value = !val));
  23512. });
  23513. useToggleScope(() => !props.disableRouteWatcher && !!router, () => {
  23514. vue.watch(router.currentRoute, () => isTemporary.value && (isActive.value = false));
  23515. });
  23516. vue.watch(() => props.permanent, val => {
  23517. if (val) isActive.value = true;
  23518. });
  23519. if (props.modelValue == null && !isTemporary.value) {
  23520. isActive.value = props.permanent || !mobile.value;
  23521. }
  23522. const {
  23523. isDragging,
  23524. dragProgress
  23525. } = useTouch({
  23526. el: rootEl,
  23527. isActive,
  23528. isTemporary,
  23529. width,
  23530. touchless: vue.toRef(props, 'touchless'),
  23531. position: location
  23532. });
  23533. const layoutSize = vue.computed(() => {
  23534. const size = isTemporary.value ? 0 : props.rail && props.expandOnHover ? Number(props.railWidth) : width.value;
  23535. return isDragging.value ? size * dragProgress.value : size;
  23536. });
  23537. const elementSize = vue.computed(() => ['top', 'bottom'].includes(props.location) ? 0 : width.value);
  23538. const {
  23539. layoutItemStyles,
  23540. layoutItemScrimStyles
  23541. } = useLayoutItem({
  23542. id: props.name,
  23543. order: vue.computed(() => parseInt(props.order, 10)),
  23544. position: location,
  23545. layoutSize,
  23546. elementSize,
  23547. active: vue.computed(() => isActive.value || isDragging.value),
  23548. disableTransitions: vue.computed(() => isDragging.value),
  23549. absolute: vue.computed(() =>
  23550. // eslint-disable-next-line @typescript-eslint/no-use-before-define
  23551. props.absolute || isSticky.value && typeof isStuck.value !== 'string')
  23552. });
  23553. const {
  23554. isStuck,
  23555. stickyStyles
  23556. } = useSticky({
  23557. rootEl,
  23558. isSticky,
  23559. layoutItemStyles
  23560. });
  23561. const scrimColor = useBackgroundColor(vue.computed(() => {
  23562. return typeof props.scrim === 'string' ? props.scrim : null;
  23563. }));
  23564. const scrimStyles = vue.computed(() => ({
  23565. ...(isDragging.value ? {
  23566. opacity: dragProgress.value * 0.2,
  23567. transition: 'none'
  23568. } : undefined),
  23569. ...layoutItemScrimStyles.value
  23570. }));
  23571. provideDefaults({
  23572. VList: {
  23573. bgColor: 'transparent'
  23574. }
  23575. });
  23576. useRender(() => {
  23577. const hasImage = slots.image || props.image;
  23578. return vue.createVNode(vue.Fragment, null, [vue.createVNode(props.tag, vue.mergeProps({
  23579. "ref": rootEl,
  23580. "onMouseenter": runOpenDelay,
  23581. "onMouseleave": runCloseDelay,
  23582. "class": ['v-navigation-drawer', `v-navigation-drawer--${location.value}`, {
  23583. 'v-navigation-drawer--expand-on-hover': props.expandOnHover,
  23584. 'v-navigation-drawer--floating': props.floating,
  23585. 'v-navigation-drawer--is-hovering': isHovering.value,
  23586. 'v-navigation-drawer--rail': props.rail,
  23587. 'v-navigation-drawer--temporary': isTemporary.value,
  23588. 'v-navigation-drawer--persistent': isPersistent.value,
  23589. 'v-navigation-drawer--active': isActive.value,
  23590. 'v-navigation-drawer--sticky': isSticky.value
  23591. }, themeClasses.value, backgroundColorClasses.value, borderClasses.value, displayClasses.value, elevationClasses.value, roundedClasses.value, props.class],
  23592. "style": [backgroundColorStyles.value, layoutItemStyles.value, ssrBootStyles.value, stickyStyles.value, props.style, ['top', 'bottom'].includes(location.value) ? {
  23593. height: 'auto'
  23594. } : {}]
  23595. }, scopeId, attrs), {
  23596. default: () => [hasImage && vue.createVNode("div", {
  23597. "key": "image",
  23598. "class": "v-navigation-drawer__img"
  23599. }, [!slots.image ? vue.createVNode(VImg, {
  23600. "key": "image-img",
  23601. "alt": "",
  23602. "cover": true,
  23603. "height": "inherit",
  23604. "src": props.image
  23605. }, null) : vue.createVNode(VDefaultsProvider, {
  23606. "key": "image-defaults",
  23607. "disabled": !props.image,
  23608. "defaults": {
  23609. VImg: {
  23610. alt: '',
  23611. cover: true,
  23612. height: 'inherit',
  23613. src: props.image
  23614. }
  23615. }
  23616. }, slots.image)]), slots.prepend && vue.createVNode("div", {
  23617. "class": "v-navigation-drawer__prepend"
  23618. }, [slots.prepend?.()]), vue.createVNode("div", {
  23619. "class": "v-navigation-drawer__content"
  23620. }, [slots.default?.()]), slots.append && vue.createVNode("div", {
  23621. "class": "v-navigation-drawer__append"
  23622. }, [slots.append?.()])]
  23623. }), vue.createVNode(vue.Transition, {
  23624. "name": "fade-transition"
  23625. }, {
  23626. default: () => [isTemporary.value && (isDragging.value || isActive.value) && !!props.scrim && vue.createVNode("div", vue.mergeProps({
  23627. "class": ['v-navigation-drawer__scrim', scrimColor.backgroundColorClasses.value],
  23628. "style": [scrimStyles.value, scrimColor.backgroundColorStyles.value],
  23629. "onClick": () => {
  23630. if (isPersistent.value) return;
  23631. isActive.value = false;
  23632. }
  23633. }, scopeId), null)]
  23634. })]);
  23635. });
  23636. return {
  23637. isStuck
  23638. };
  23639. }
  23640. });
  23641. // Composables
  23642. const VNoSsr = defineComponent({
  23643. name: 'VNoSsr',
  23644. setup(_, _ref) {
  23645. let {
  23646. slots
  23647. } = _ref;
  23648. const show = useHydration();
  23649. return () => show.value && slots.default?.();
  23650. }
  23651. });
  23652. // Types
  23653. // Types
  23654. const makeVOtpInputProps = propsFactory({
  23655. autofocus: Boolean,
  23656. divider: String,
  23657. focusAll: Boolean,
  23658. label: {
  23659. type: String,
  23660. default: '$vuetify.input.otp'
  23661. },
  23662. length: {
  23663. type: [Number, String],
  23664. default: 6
  23665. },
  23666. modelValue: {
  23667. type: [Number, String],
  23668. default: undefined
  23669. },
  23670. placeholder: String,
  23671. type: {
  23672. type: String,
  23673. default: 'number'
  23674. },
  23675. ...makeDimensionProps(),
  23676. ...makeFocusProps(),
  23677. ...only(makeVFieldProps({
  23678. variant: 'outlined'
  23679. }), ['baseColor', 'bgColor', 'class', 'color', 'disabled', 'error', 'loading', 'rounded', 'style', 'theme', 'variant'])
  23680. }, 'VOtpInput');
  23681. const VOtpInput = genericComponent()({
  23682. name: 'VOtpInput',
  23683. props: makeVOtpInputProps(),
  23684. emits: {
  23685. finish: val => true,
  23686. 'update:focused': val => true,
  23687. 'update:modelValue': val => true
  23688. },
  23689. setup(props, _ref) {
  23690. let {
  23691. attrs,
  23692. emit,
  23693. slots
  23694. } = _ref;
  23695. const {
  23696. dimensionStyles
  23697. } = useDimension(props);
  23698. const {
  23699. isFocused,
  23700. focus,
  23701. blur
  23702. } = useFocus(props);
  23703. const model = useProxiedModel(props, 'modelValue', '', val => val == null ? [] : String(val).split(''), val => val.join(''));
  23704. const {
  23705. t
  23706. } = useLocale();
  23707. const length = vue.computed(() => Number(props.length));
  23708. const fields = vue.computed(() => Array(length.value).fill(0));
  23709. const focusIndex = vue.ref(-1);
  23710. const contentRef = vue.ref();
  23711. const inputRef = vue.ref([]);
  23712. const current = vue.computed(() => inputRef.value[focusIndex.value]);
  23713. function onInput() {
  23714. // The maxlength attribute doesn't work for the number type input, so the text type is used.
  23715. // The following logic simulates the behavior of a number input.
  23716. if (isValidNumber(current.value.value)) {
  23717. current.value.value = '';
  23718. return;
  23719. }
  23720. const array = model.value.slice();
  23721. const value = current.value.value;
  23722. array[focusIndex.value] = value;
  23723. let target = null;
  23724. if (focusIndex.value > model.value.length) {
  23725. target = model.value.length + 1;
  23726. } else if (focusIndex.value + 1 !== length.value) {
  23727. target = 'next';
  23728. }
  23729. model.value = array;
  23730. if (target) focusChild(contentRef.value, target);
  23731. }
  23732. function onKeydown(e) {
  23733. const array = model.value.slice();
  23734. const index = focusIndex.value;
  23735. let target = null;
  23736. if (!['ArrowLeft', 'ArrowRight', 'Backspace', 'Delete'].includes(e.key)) return;
  23737. e.preventDefault();
  23738. if (e.key === 'ArrowLeft') {
  23739. target = 'prev';
  23740. } else if (e.key === 'ArrowRight') {
  23741. target = 'next';
  23742. } else if (['Backspace', 'Delete'].includes(e.key)) {
  23743. array[focusIndex.value] = '';
  23744. model.value = array;
  23745. if (focusIndex.value > 0 && e.key === 'Backspace') {
  23746. target = 'prev';
  23747. } else {
  23748. requestAnimationFrame(() => {
  23749. inputRef.value[index]?.select();
  23750. });
  23751. }
  23752. }
  23753. requestAnimationFrame(() => {
  23754. if (target != null) {
  23755. focusChild(contentRef.value, target);
  23756. }
  23757. });
  23758. }
  23759. function onPaste(index, e) {
  23760. e.preventDefault();
  23761. e.stopPropagation();
  23762. const clipboardText = e?.clipboardData?.getData('Text').slice(0, length.value) ?? '';
  23763. if (isValidNumber(clipboardText)) return;
  23764. model.value = clipboardText.split('');
  23765. inputRef.value?.[index].blur();
  23766. }
  23767. function reset() {
  23768. model.value = [];
  23769. }
  23770. function onFocus(e, index) {
  23771. focus();
  23772. focusIndex.value = index;
  23773. }
  23774. function onBlur() {
  23775. blur();
  23776. focusIndex.value = -1;
  23777. }
  23778. function isValidNumber(value) {
  23779. return props.type === 'number' && /[^0-9]/g.test(value);
  23780. }
  23781. provideDefaults({
  23782. VField: {
  23783. color: vue.computed(() => props.color),
  23784. bgColor: vue.computed(() => props.color),
  23785. baseColor: vue.computed(() => props.baseColor),
  23786. disabled: vue.computed(() => props.disabled),
  23787. error: vue.computed(() => props.error),
  23788. variant: vue.computed(() => props.variant)
  23789. }
  23790. }, {
  23791. scoped: true
  23792. });
  23793. vue.watch(model, val => {
  23794. if (val.length === length.value) emit('finish', val.join(''));
  23795. }, {
  23796. deep: true
  23797. });
  23798. vue.watch(focusIndex, val => {
  23799. if (val < 0) return;
  23800. vue.nextTick(() => {
  23801. inputRef.value[val]?.select();
  23802. });
  23803. });
  23804. useRender(() => {
  23805. const [rootAttrs, inputAttrs] = filterInputAttrs(attrs);
  23806. return vue.createVNode("div", vue.mergeProps({
  23807. "class": ['v-otp-input', {
  23808. 'v-otp-input--divided': !!props.divider
  23809. }, props.class],
  23810. "style": [props.style]
  23811. }, rootAttrs), [vue.createVNode("div", {
  23812. "ref": contentRef,
  23813. "class": "v-otp-input__content",
  23814. "style": [dimensionStyles.value]
  23815. }, [fields.value.map((_, i) => vue.createVNode(vue.Fragment, null, [props.divider && i !== 0 && vue.createVNode("span", {
  23816. "class": "v-otp-input__divider"
  23817. }, [props.divider]), vue.createVNode(VField, {
  23818. "focused": isFocused.value && props.focusAll || focusIndex.value === i,
  23819. "key": i
  23820. }, {
  23821. ...slots,
  23822. loader: undefined,
  23823. default: () => {
  23824. return vue.createVNode("input", {
  23825. "ref": val => inputRef.value[i] = val,
  23826. "aria-label": t(props.label, i + 1),
  23827. "autofocus": i === 0 && props.autofocus,
  23828. "autocomplete": "one-time-code",
  23829. "class": ['v-otp-input__field'],
  23830. "disabled": props.disabled,
  23831. "inputmode": props.type === 'number' ? 'numeric' : 'text',
  23832. "min": props.type === 'number' ? 0 : undefined,
  23833. "maxlength": "1",
  23834. "placeholder": props.placeholder,
  23835. "type": props.type === 'number' ? 'text' : props.type,
  23836. "value": model.value[i],
  23837. "onInput": onInput,
  23838. "onFocus": e => onFocus(e, i),
  23839. "onBlur": onBlur,
  23840. "onKeydown": onKeydown,
  23841. "onPaste": event => onPaste(i, event)
  23842. }, null);
  23843. }
  23844. })])), vue.createVNode("input", vue.mergeProps({
  23845. "class": "v-otp-input-input",
  23846. "type": "hidden"
  23847. }, inputAttrs, {
  23848. "value": model.value.join('')
  23849. }), null), vue.createVNode(VOverlay, {
  23850. "contained": true,
  23851. "content-class": "v-otp-input__loader",
  23852. "model-value": !!props.loading,
  23853. "persistent": true
  23854. }, {
  23855. default: () => [slots.loader?.() ?? vue.createVNode(VProgressCircular, {
  23856. "color": typeof props.loading === 'boolean' ? undefined : props.loading,
  23857. "indeterminate": true,
  23858. "size": "24",
  23859. "width": "2"
  23860. }, null)]
  23861. }), slots.default?.()])]);
  23862. });
  23863. return {
  23864. blur: () => {
  23865. inputRef.value?.some(input => input.blur());
  23866. },
  23867. focus: () => {
  23868. inputRef.value?.[0].focus();
  23869. },
  23870. reset,
  23871. isFocused
  23872. };
  23873. }
  23874. });
  23875. // Types
  23876. function floor(val) {
  23877. return Math.floor(Math.abs(val)) * Math.sign(val);
  23878. }
  23879. const makeVParallaxProps = propsFactory({
  23880. scale: {
  23881. type: [Number, String],
  23882. default: 0.5
  23883. },
  23884. ...makeComponentProps()
  23885. }, 'VParallax');
  23886. const VParallax = genericComponent()({
  23887. name: 'VParallax',
  23888. props: makeVParallaxProps(),
  23889. setup(props, _ref) {
  23890. let {
  23891. slots
  23892. } = _ref;
  23893. const {
  23894. intersectionRef,
  23895. isIntersecting
  23896. } = useIntersectionObserver();
  23897. const {
  23898. resizeRef,
  23899. contentRect
  23900. } = useResizeObserver();
  23901. const {
  23902. height: displayHeight
  23903. } = useDisplay();
  23904. const root = vue.ref();
  23905. vue.watchEffect(() => {
  23906. intersectionRef.value = resizeRef.value = root.value?.$el;
  23907. });
  23908. let scrollParent;
  23909. vue.watch(isIntersecting, val => {
  23910. if (val) {
  23911. scrollParent = getScrollParent(intersectionRef.value);
  23912. scrollParent = scrollParent === document.scrollingElement ? document : scrollParent;
  23913. scrollParent.addEventListener('scroll', onScroll, {
  23914. passive: true
  23915. });
  23916. onScroll();
  23917. } else {
  23918. scrollParent.removeEventListener('scroll', onScroll);
  23919. }
  23920. });
  23921. vue.onBeforeUnmount(() => {
  23922. scrollParent?.removeEventListener('scroll', onScroll);
  23923. });
  23924. vue.watch(displayHeight, onScroll);
  23925. vue.watch(() => contentRect.value?.height, onScroll);
  23926. const scale = vue.computed(() => {
  23927. return 1 - clamp(+props.scale);
  23928. });
  23929. let frame = -1;
  23930. function onScroll() {
  23931. if (!isIntersecting.value) return;
  23932. cancelAnimationFrame(frame);
  23933. frame = requestAnimationFrame(() => {
  23934. const el = (root.value?.$el).querySelector('.v-img__img');
  23935. if (!el) return;
  23936. const scrollHeight = scrollParent instanceof Document ? document.documentElement.clientHeight : scrollParent.clientHeight;
  23937. const scrollPos = scrollParent instanceof Document ? window.scrollY : scrollParent.scrollTop;
  23938. const top = intersectionRef.value.getBoundingClientRect().top + scrollPos;
  23939. const height = contentRect.value.height;
  23940. const center = top + (height - scrollHeight) / 2;
  23941. const translate = floor((scrollPos - center) * scale.value);
  23942. const sizeScale = Math.max(1, (scale.value * (scrollHeight - height) + height) / height);
  23943. el.style.setProperty('transform', `translateY(${translate}px) scale(${sizeScale})`);
  23944. });
  23945. }
  23946. useRender(() => vue.createVNode(VImg, {
  23947. "class": ['v-parallax', {
  23948. 'v-parallax--active': isIntersecting.value
  23949. }, props.class],
  23950. "style": props.style,
  23951. "ref": root,
  23952. "cover": true,
  23953. "onLoadstart": onScroll,
  23954. "onLoad": onScroll
  23955. }, slots));
  23956. return {};
  23957. }
  23958. });
  23959. // Types
  23960. const makeVRadioProps = propsFactory({
  23961. ...makeVSelectionControlProps({
  23962. falseIcon: '$radioOff',
  23963. trueIcon: '$radioOn'
  23964. })
  23965. }, 'VRadio');
  23966. const VRadio = genericComponent()({
  23967. name: 'VRadio',
  23968. props: makeVRadioProps(),
  23969. setup(props, _ref) {
  23970. let {
  23971. slots
  23972. } = _ref;
  23973. useRender(() => {
  23974. const controlProps = VSelectionControl.filterProps(props);
  23975. return vue.createVNode(VSelectionControl, vue.mergeProps(controlProps, {
  23976. "class": ['v-radio', props.class],
  23977. "style": props.style,
  23978. "type": "radio"
  23979. }), slots);
  23980. });
  23981. return {};
  23982. }
  23983. });
  23984. // Types
  23985. const makeVRadioGroupProps = propsFactory({
  23986. height: {
  23987. type: [Number, String],
  23988. default: 'auto'
  23989. },
  23990. ...makeVInputProps(),
  23991. ...omit(makeSelectionControlGroupProps(), ['multiple']),
  23992. trueIcon: {
  23993. type: IconValue,
  23994. default: '$radioOn'
  23995. },
  23996. falseIcon: {
  23997. type: IconValue,
  23998. default: '$radioOff'
  23999. },
  24000. type: {
  24001. type: String,
  24002. default: 'radio'
  24003. }
  24004. }, 'VRadioGroup');
  24005. const VRadioGroup = genericComponent()({
  24006. name: 'VRadioGroup',
  24007. inheritAttrs: false,
  24008. props: makeVRadioGroupProps(),
  24009. emits: {
  24010. 'update:modelValue': value => true
  24011. },
  24012. setup(props, _ref) {
  24013. let {
  24014. attrs,
  24015. slots
  24016. } = _ref;
  24017. const uid = getUid();
  24018. const id = vue.computed(() => props.id || `radio-group-${uid}`);
  24019. const model = useProxiedModel(props, 'modelValue');
  24020. useRender(() => {
  24021. const [rootAttrs, controlAttrs] = filterInputAttrs(attrs);
  24022. const inputProps = VInput.filterProps(props);
  24023. const controlProps = VSelectionControl.filterProps(props);
  24024. const label = slots.label ? slots.label({
  24025. label: props.label,
  24026. props: {
  24027. for: id.value
  24028. }
  24029. }) : props.label;
  24030. return vue.createVNode(VInput, vue.mergeProps({
  24031. "class": ['v-radio-group', props.class],
  24032. "style": props.style
  24033. }, rootAttrs, inputProps, {
  24034. "modelValue": model.value,
  24035. "onUpdate:modelValue": $event => model.value = $event,
  24036. "id": id.value
  24037. }), {
  24038. ...slots,
  24039. default: _ref2 => {
  24040. let {
  24041. id,
  24042. messagesId,
  24043. isDisabled,
  24044. isReadonly
  24045. } = _ref2;
  24046. return vue.createVNode(vue.Fragment, null, [label && vue.createVNode(VLabel, {
  24047. "id": id.value
  24048. }, {
  24049. default: () => [label]
  24050. }), vue.createVNode(VSelectionControlGroup, vue.mergeProps(controlProps, {
  24051. "id": id.value,
  24052. "aria-describedby": messagesId.value,
  24053. "defaultsTarget": "VRadio",
  24054. "trueIcon": props.trueIcon,
  24055. "falseIcon": props.falseIcon,
  24056. "type": props.type,
  24057. "disabled": isDisabled.value,
  24058. "readonly": isReadonly.value,
  24059. "aria-labelledby": label ? id.value : undefined,
  24060. "multiple": false
  24061. }, controlAttrs, {
  24062. "modelValue": model.value,
  24063. "onUpdate:modelValue": $event => model.value = $event
  24064. }), slots)]);
  24065. }
  24066. });
  24067. });
  24068. return {};
  24069. }
  24070. });
  24071. // Types
  24072. const makeVRangeSliderProps = propsFactory({
  24073. ...makeFocusProps(),
  24074. ...makeVInputProps(),
  24075. ...makeSliderProps(),
  24076. strict: Boolean,
  24077. modelValue: {
  24078. type: Array,
  24079. default: () => [0, 0]
  24080. }
  24081. }, 'VRangeSlider');
  24082. const VRangeSlider = genericComponent()({
  24083. name: 'VRangeSlider',
  24084. props: makeVRangeSliderProps(),
  24085. emits: {
  24086. 'update:focused': value => true,
  24087. 'update:modelValue': value => true,
  24088. end: value => true,
  24089. start: value => true
  24090. },
  24091. setup(props, _ref) {
  24092. let {
  24093. slots,
  24094. emit
  24095. } = _ref;
  24096. const startThumbRef = vue.ref();
  24097. const stopThumbRef = vue.ref();
  24098. const inputRef = vue.ref();
  24099. const {
  24100. rtlClasses
  24101. } = useRtl();
  24102. function getActiveThumb(e) {
  24103. if (!startThumbRef.value || !stopThumbRef.value) return;
  24104. const startOffset = getOffset(e, startThumbRef.value.$el, props.direction);
  24105. const stopOffset = getOffset(e, stopThumbRef.value.$el, props.direction);
  24106. const a = Math.abs(startOffset);
  24107. const b = Math.abs(stopOffset);
  24108. return a < b || a === b && startOffset < 0 ? startThumbRef.value.$el : stopThumbRef.value.$el;
  24109. }
  24110. const steps = useSteps(props);
  24111. const model = useProxiedModel(props, 'modelValue', undefined, arr => {
  24112. if (!arr?.length) return [0, 0];
  24113. return arr.map(value => steps.roundValue(value));
  24114. });
  24115. const {
  24116. activeThumbRef,
  24117. hasLabels,
  24118. max,
  24119. min,
  24120. mousePressed,
  24121. onSliderMousedown,
  24122. onSliderTouchstart,
  24123. position,
  24124. trackContainerRef,
  24125. readonly
  24126. } = useSlider({
  24127. props,
  24128. steps,
  24129. onSliderStart: () => {
  24130. emit('start', model.value);
  24131. },
  24132. onSliderEnd: _ref2 => {
  24133. let {
  24134. value
  24135. } = _ref2;
  24136. const newValue = activeThumbRef.value === startThumbRef.value?.$el ? [value, model.value[1]] : [model.value[0], value];
  24137. if (!props.strict && newValue[0] < newValue[1]) {
  24138. model.value = newValue;
  24139. }
  24140. emit('end', model.value);
  24141. },
  24142. onSliderMove: _ref3 => {
  24143. let {
  24144. value
  24145. } = _ref3;
  24146. const [start, stop] = model.value;
  24147. if (!props.strict && start === stop && start !== min.value) {
  24148. activeThumbRef.value = value > start ? stopThumbRef.value?.$el : startThumbRef.value?.$el;
  24149. activeThumbRef.value?.focus();
  24150. }
  24151. if (activeThumbRef.value === startThumbRef.value?.$el) {
  24152. model.value = [Math.min(value, stop), stop];
  24153. } else {
  24154. model.value = [start, Math.max(start, value)];
  24155. }
  24156. },
  24157. getActiveThumb
  24158. });
  24159. const {
  24160. isFocused,
  24161. focus,
  24162. blur
  24163. } = useFocus(props);
  24164. const trackStart = vue.computed(() => position(model.value[0]));
  24165. const trackStop = vue.computed(() => position(model.value[1]));
  24166. useRender(() => {
  24167. const inputProps = VInput.filterProps(props);
  24168. const hasPrepend = !!(props.label || slots.label || slots.prepend);
  24169. return vue.createVNode(VInput, vue.mergeProps({
  24170. "class": ['v-slider', 'v-range-slider', {
  24171. 'v-slider--has-labels': !!slots['tick-label'] || hasLabels.value,
  24172. 'v-slider--focused': isFocused.value,
  24173. 'v-slider--pressed': mousePressed.value,
  24174. 'v-slider--disabled': props.disabled
  24175. }, rtlClasses.value, props.class],
  24176. "style": props.style,
  24177. "ref": inputRef
  24178. }, inputProps, {
  24179. "focused": isFocused.value
  24180. }), {
  24181. ...slots,
  24182. prepend: hasPrepend ? slotProps => vue.createVNode(vue.Fragment, null, [slots.label?.(slotProps) ?? (props.label ? vue.createVNode(VLabel, {
  24183. "class": "v-slider__label",
  24184. "text": props.label
  24185. }, null) : undefined), slots.prepend?.(slotProps)]) : undefined,
  24186. default: _ref4 => {
  24187. let {
  24188. id,
  24189. messagesId
  24190. } = _ref4;
  24191. return vue.createVNode("div", {
  24192. "class": "v-slider__container",
  24193. "onMousedown": !readonly.value ? onSliderMousedown : undefined,
  24194. "onTouchstartPassive": !readonly.value ? onSliderTouchstart : undefined
  24195. }, [vue.createVNode("input", {
  24196. "id": `${id.value}_start`,
  24197. "name": props.name || id.value,
  24198. "disabled": !!props.disabled,
  24199. "readonly": !!props.readonly,
  24200. "tabindex": "-1",
  24201. "value": model.value[0]
  24202. }, null), vue.createVNode("input", {
  24203. "id": `${id.value}_stop`,
  24204. "name": props.name || id.value,
  24205. "disabled": !!props.disabled,
  24206. "readonly": !!props.readonly,
  24207. "tabindex": "-1",
  24208. "value": model.value[1]
  24209. }, null), vue.createVNode(VSliderTrack, {
  24210. "ref": trackContainerRef,
  24211. "start": trackStart.value,
  24212. "stop": trackStop.value
  24213. }, {
  24214. 'tick-label': slots['tick-label']
  24215. }), vue.createVNode(VSliderThumb, {
  24216. "ref": startThumbRef,
  24217. "aria-describedby": messagesId.value,
  24218. "focused": isFocused && activeThumbRef.value === startThumbRef.value?.$el,
  24219. "modelValue": model.value[0],
  24220. "onUpdate:modelValue": v => model.value = [v, model.value[1]],
  24221. "onFocus": e => {
  24222. focus();
  24223. activeThumbRef.value = startThumbRef.value?.$el;
  24224. // Make sure second thumb is focused if
  24225. // the thumbs are on top of each other
  24226. // and they are both at minimum value
  24227. // but only if focused from outside.
  24228. if (max.value !== min.value && model.value[0] === model.value[1] && model.value[1] === min.value && e.relatedTarget !== stopThumbRef.value?.$el) {
  24229. startThumbRef.value?.$el.blur();
  24230. stopThumbRef.value?.$el.focus();
  24231. }
  24232. },
  24233. "onBlur": () => {
  24234. blur();
  24235. activeThumbRef.value = undefined;
  24236. },
  24237. "min": min.value,
  24238. "max": model.value[1],
  24239. "position": trackStart.value,
  24240. "ripple": props.ripple
  24241. }, {
  24242. 'thumb-label': slots['thumb-label']
  24243. }), vue.createVNode(VSliderThumb, {
  24244. "ref": stopThumbRef,
  24245. "aria-describedby": messagesId.value,
  24246. "focused": isFocused && activeThumbRef.value === stopThumbRef.value?.$el,
  24247. "modelValue": model.value[1],
  24248. "onUpdate:modelValue": v => model.value = [model.value[0], v],
  24249. "onFocus": e => {
  24250. focus();
  24251. activeThumbRef.value = stopThumbRef.value?.$el;
  24252. // Make sure first thumb is focused if
  24253. // the thumbs are on top of each other
  24254. // and they are both at maximum value
  24255. // but only if focused from outside.
  24256. if (max.value !== min.value && model.value[0] === model.value[1] && model.value[0] === max.value && e.relatedTarget !== startThumbRef.value?.$el) {
  24257. stopThumbRef.value?.$el.blur();
  24258. startThumbRef.value?.$el.focus();
  24259. }
  24260. },
  24261. "onBlur": () => {
  24262. blur();
  24263. activeThumbRef.value = undefined;
  24264. },
  24265. "min": model.value[0],
  24266. "max": max.value,
  24267. "position": trackStop.value,
  24268. "ripple": props.ripple
  24269. }, {
  24270. 'thumb-label': slots['thumb-label']
  24271. })]);
  24272. }
  24273. });
  24274. });
  24275. return {};
  24276. }
  24277. });
  24278. // Types
  24279. const makeVRatingProps = propsFactory({
  24280. name: String,
  24281. itemAriaLabel: {
  24282. type: String,
  24283. default: '$vuetify.rating.ariaLabel.item'
  24284. },
  24285. activeColor: String,
  24286. color: String,
  24287. clearable: Boolean,
  24288. disabled: Boolean,
  24289. emptyIcon: {
  24290. type: IconValue,
  24291. default: '$ratingEmpty'
  24292. },
  24293. fullIcon: {
  24294. type: IconValue,
  24295. default: '$ratingFull'
  24296. },
  24297. halfIncrements: Boolean,
  24298. hover: Boolean,
  24299. length: {
  24300. type: [Number, String],
  24301. default: 5
  24302. },
  24303. readonly: Boolean,
  24304. modelValue: {
  24305. type: [Number, String],
  24306. default: 0
  24307. },
  24308. itemLabels: Array,
  24309. itemLabelPosition: {
  24310. type: String,
  24311. default: 'top',
  24312. validator: v => ['top', 'bottom'].includes(v)
  24313. },
  24314. ripple: Boolean,
  24315. ...makeComponentProps(),
  24316. ...makeDensityProps(),
  24317. ...makeSizeProps(),
  24318. ...makeTagProps(),
  24319. ...makeThemeProps()
  24320. }, 'VRating');
  24321. const VRating = genericComponent()({
  24322. name: 'VRating',
  24323. props: makeVRatingProps(),
  24324. emits: {
  24325. 'update:modelValue': value => true
  24326. },
  24327. setup(props, _ref) {
  24328. let {
  24329. slots
  24330. } = _ref;
  24331. const {
  24332. t
  24333. } = useLocale();
  24334. const {
  24335. themeClasses
  24336. } = provideTheme(props);
  24337. const rating = useProxiedModel(props, 'modelValue');
  24338. const normalizedValue = vue.computed(() => clamp(parseFloat(rating.value), 0, +props.length));
  24339. const range = vue.computed(() => createRange(Number(props.length), 1));
  24340. const increments = vue.computed(() => range.value.flatMap(v => props.halfIncrements ? [v - 0.5, v] : [v]));
  24341. const hoverIndex = vue.shallowRef(-1);
  24342. const itemState = vue.computed(() => increments.value.map(value => {
  24343. const isHovering = props.hover && hoverIndex.value > -1;
  24344. const isFilled = normalizedValue.value >= value;
  24345. const isHovered = hoverIndex.value >= value;
  24346. const isFullIcon = isHovering ? isHovered : isFilled;
  24347. const icon = isFullIcon ? props.fullIcon : props.emptyIcon;
  24348. const activeColor = props.activeColor ?? props.color;
  24349. const color = isFilled || isHovered ? activeColor : props.color;
  24350. return {
  24351. isFilled,
  24352. isHovered,
  24353. icon,
  24354. color
  24355. };
  24356. }));
  24357. const eventState = vue.computed(() => [0, ...increments.value].map(value => {
  24358. function onMouseenter() {
  24359. hoverIndex.value = value;
  24360. }
  24361. function onMouseleave() {
  24362. hoverIndex.value = -1;
  24363. }
  24364. function onClick() {
  24365. if (props.disabled || props.readonly) return;
  24366. rating.value = normalizedValue.value === value && props.clearable ? 0 : value;
  24367. }
  24368. return {
  24369. onMouseenter: props.hover ? onMouseenter : undefined,
  24370. onMouseleave: props.hover ? onMouseleave : undefined,
  24371. onClick
  24372. };
  24373. }));
  24374. const name = vue.computed(() => props.name ?? `v-rating-${getUid()}`);
  24375. function VRatingItem(_ref2) {
  24376. let {
  24377. value,
  24378. index,
  24379. showStar = true
  24380. } = _ref2;
  24381. const {
  24382. onMouseenter,
  24383. onMouseleave,
  24384. onClick
  24385. } = eventState.value[index + 1];
  24386. const id = `${name.value}-${String(value).replace('.', '-')}`;
  24387. const btnProps = {
  24388. color: itemState.value[index]?.color,
  24389. density: props.density,
  24390. disabled: props.disabled,
  24391. icon: itemState.value[index]?.icon,
  24392. ripple: props.ripple,
  24393. size: props.size,
  24394. variant: 'plain'
  24395. };
  24396. return vue.createVNode(vue.Fragment, null, [vue.createVNode("label", {
  24397. "for": id,
  24398. "class": {
  24399. 'v-rating__item--half': props.halfIncrements && value % 1 > 0,
  24400. 'v-rating__item--full': props.halfIncrements && value % 1 === 0
  24401. },
  24402. "onMouseenter": onMouseenter,
  24403. "onMouseleave": onMouseleave,
  24404. "onClick": onClick
  24405. }, [vue.createVNode("span", {
  24406. "class": "v-rating__hidden"
  24407. }, [t(props.itemAriaLabel, value, props.length)]), !showStar ? undefined : slots.item ? slots.item({
  24408. ...itemState.value[index],
  24409. props: btnProps,
  24410. value,
  24411. index,
  24412. rating: normalizedValue.value
  24413. }) : vue.createVNode(VBtn, vue.mergeProps({
  24414. "aria-label": t(props.itemAriaLabel, value, props.length)
  24415. }, btnProps), null)]), vue.createVNode("input", {
  24416. "class": "v-rating__hidden",
  24417. "name": name.value,
  24418. "id": id,
  24419. "type": "radio",
  24420. "value": value,
  24421. "checked": normalizedValue.value === value,
  24422. "tabindex": -1,
  24423. "readonly": props.readonly,
  24424. "disabled": props.disabled
  24425. }, null)]);
  24426. }
  24427. function createLabel(labelProps) {
  24428. if (slots['item-label']) return slots['item-label'](labelProps);
  24429. if (labelProps.label) return vue.createVNode("span", null, [labelProps.label]);
  24430. return vue.createVNode("span", null, [vue.createTextVNode("\xA0")]);
  24431. }
  24432. useRender(() => {
  24433. const hasLabels = !!props.itemLabels?.length || slots['item-label'];
  24434. return vue.createVNode(props.tag, {
  24435. "class": ['v-rating', {
  24436. 'v-rating--hover': props.hover,
  24437. 'v-rating--readonly': props.readonly
  24438. }, themeClasses.value, props.class],
  24439. "style": props.style
  24440. }, {
  24441. default: () => [vue.createVNode(VRatingItem, {
  24442. "value": 0,
  24443. "index": -1,
  24444. "showStar": false
  24445. }, null), range.value.map((value, i) => vue.createVNode("div", {
  24446. "class": "v-rating__wrapper"
  24447. }, [hasLabels && props.itemLabelPosition === 'top' ? createLabel({
  24448. value,
  24449. index: i,
  24450. label: props.itemLabels?.[i]
  24451. }) : undefined, vue.createVNode("div", {
  24452. "class": "v-rating__item"
  24453. }, [props.halfIncrements ? vue.createVNode(vue.Fragment, null, [vue.createVNode(VRatingItem, {
  24454. "value": value - 0.5,
  24455. "index": i * 2
  24456. }, null), vue.createVNode(VRatingItem, {
  24457. "value": value,
  24458. "index": i * 2 + 1
  24459. }, null)]) : vue.createVNode(VRatingItem, {
  24460. "value": value,
  24461. "index": i
  24462. }, null)]), hasLabels && props.itemLabelPosition === 'bottom' ? createLabel({
  24463. value,
  24464. index: i,
  24465. label: props.itemLabels?.[i]
  24466. }) : undefined]))]
  24467. });
  24468. });
  24469. return {};
  24470. }
  24471. });
  24472. // Types
  24473. const rootTypes = {
  24474. actions: 'button@2',
  24475. article: 'heading, paragraph',
  24476. avatar: 'avatar',
  24477. button: 'button',
  24478. card: 'image, heading',
  24479. 'card-avatar': 'image, list-item-avatar',
  24480. chip: 'chip',
  24481. 'date-picker': 'list-item, heading, divider, date-picker-options, date-picker-days, actions',
  24482. 'date-picker-options': 'text, avatar@2',
  24483. 'date-picker-days': 'avatar@28',
  24484. divider: 'divider',
  24485. heading: 'heading',
  24486. image: 'image',
  24487. 'list-item': 'text',
  24488. 'list-item-avatar': 'avatar, text',
  24489. 'list-item-two-line': 'sentences',
  24490. 'list-item-avatar-two-line': 'avatar, sentences',
  24491. 'list-item-three-line': 'paragraph',
  24492. 'list-item-avatar-three-line': 'avatar, paragraph',
  24493. ossein: 'ossein',
  24494. paragraph: 'text@3',
  24495. sentences: 'text@2',
  24496. subtitle: 'text',
  24497. table: 'table-heading, table-thead, table-tbody, table-tfoot',
  24498. 'table-heading': 'chip, text',
  24499. 'table-thead': 'heading@6',
  24500. 'table-tbody': 'table-row-divider@6',
  24501. 'table-row-divider': 'table-row, divider',
  24502. 'table-row': 'text@6',
  24503. 'table-tfoot': 'text@2, avatar@2',
  24504. text: 'text'
  24505. };
  24506. function genBone(type) {
  24507. let children = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : [];
  24508. return vue.createVNode("div", {
  24509. "class": ['v-skeleton-loader__bone', `v-skeleton-loader__${type}`]
  24510. }, [children]);
  24511. }
  24512. function genBones(bone) {
  24513. // e.g. 'text@3'
  24514. const [type, length] = bone.split('@');
  24515. // Generate a length array based upon
  24516. // value after @ in the bone string
  24517. return Array.from({
  24518. length
  24519. }).map(() => genStructure(type));
  24520. }
  24521. function genStructure(type) {
  24522. let children = [];
  24523. if (!type) return children;
  24524. // TODO: figure out a better way to type this
  24525. const bone = rootTypes[type];
  24526. // End of recursion, do nothing
  24527. /* eslint-disable-next-line no-empty, brace-style */
  24528. if (type === bone) ;
  24529. // Array of values - e.g. 'heading, paragraph, text@2'
  24530. else if (type.includes(',')) return mapBones(type);
  24531. // Array of values - e.g. 'paragraph@4'
  24532. else if (type.includes('@')) return genBones(type);
  24533. // Array of values - e.g. 'card@2'
  24534. else if (bone.includes(',')) children = mapBones(bone);
  24535. // Array of values - e.g. 'list-item@2'
  24536. else if (bone.includes('@')) children = genBones(bone);
  24537. // Single value - e.g. 'card-heading'
  24538. else if (bone) children.push(genStructure(bone));
  24539. return [genBone(type, children)];
  24540. }
  24541. function mapBones(bones) {
  24542. // Remove spaces and return array of structures
  24543. return bones.replace(/\s/g, '').split(',').map(genStructure);
  24544. }
  24545. const makeVSkeletonLoaderProps = propsFactory({
  24546. boilerplate: Boolean,
  24547. color: String,
  24548. loading: Boolean,
  24549. loadingText: {
  24550. type: String,
  24551. default: '$vuetify.loading'
  24552. },
  24553. type: {
  24554. type: [String, Array],
  24555. default: 'ossein'
  24556. },
  24557. ...makeDimensionProps(),
  24558. ...makeElevationProps(),
  24559. ...makeThemeProps()
  24560. }, 'VSkeletonLoader');
  24561. const VSkeletonLoader = genericComponent()({
  24562. name: 'VSkeletonLoader',
  24563. props: makeVSkeletonLoaderProps(),
  24564. setup(props, _ref) {
  24565. let {
  24566. slots
  24567. } = _ref;
  24568. const {
  24569. backgroundColorClasses,
  24570. backgroundColorStyles
  24571. } = useBackgroundColor(vue.toRef(props, 'color'));
  24572. const {
  24573. dimensionStyles
  24574. } = useDimension(props);
  24575. const {
  24576. elevationClasses
  24577. } = useElevation(props);
  24578. const {
  24579. themeClasses
  24580. } = provideTheme(props);
  24581. const {
  24582. t
  24583. } = useLocale();
  24584. const items = vue.computed(() => genStructure(wrapInArray(props.type).join(',')));
  24585. useRender(() => {
  24586. const isLoading = !slots.default || props.loading;
  24587. const loadingProps = props.boilerplate || !isLoading ? {} : {
  24588. ariaLive: 'polite',
  24589. ariaLabel: t(props.loadingText),
  24590. role: 'alert'
  24591. };
  24592. return vue.createVNode("div", vue.mergeProps({
  24593. "class": ['v-skeleton-loader', {
  24594. 'v-skeleton-loader--boilerplate': props.boilerplate
  24595. }, themeClasses.value, backgroundColorClasses.value, elevationClasses.value],
  24596. "style": [backgroundColorStyles.value, isLoading ? dimensionStyles.value : {}]
  24597. }, loadingProps), [isLoading ? items.value : slots.default?.()]);
  24598. });
  24599. return {};
  24600. }
  24601. });
  24602. // Composables
  24603. // Types
  24604. const VSlideGroupItem = genericComponent()({
  24605. name: 'VSlideGroupItem',
  24606. props: makeGroupItemProps(),
  24607. emits: {
  24608. 'group:selected': val => true
  24609. },
  24610. setup(props, _ref) {
  24611. let {
  24612. slots
  24613. } = _ref;
  24614. const slideGroupItem = useGroupItem(props, VSlideGroupSymbol);
  24615. return () => slots.default?.({
  24616. isSelected: slideGroupItem.isSelected.value,
  24617. select: slideGroupItem.select,
  24618. toggle: slideGroupItem.toggle,
  24619. selectedClass: slideGroupItem.selectedClass.value
  24620. });
  24621. }
  24622. });
  24623. // Types
  24624. function useCountdown(milliseconds) {
  24625. const time = vue.shallowRef(milliseconds());
  24626. let timer = -1;
  24627. function clear() {
  24628. clearInterval(timer);
  24629. }
  24630. function reset() {
  24631. clear();
  24632. vue.nextTick(() => time.value = milliseconds());
  24633. }
  24634. function start(el) {
  24635. const style = el ? getComputedStyle(el) : {
  24636. transitionDuration: 0.2
  24637. };
  24638. const interval = parseFloat(style.transitionDuration) * 1000 || 200;
  24639. clear();
  24640. if (time.value <= 0) return;
  24641. const startTime = performance.now();
  24642. timer = window.setInterval(() => {
  24643. const elapsed = performance.now() - startTime + interval;
  24644. time.value = Math.max(milliseconds() - elapsed, 0);
  24645. if (time.value <= 0) clear();
  24646. }, interval);
  24647. }
  24648. vue.onScopeDispose(clear);
  24649. return {
  24650. clear,
  24651. time,
  24652. start,
  24653. reset
  24654. };
  24655. }
  24656. const makeVSnackbarProps = propsFactory({
  24657. multiLine: Boolean,
  24658. text: String,
  24659. timer: [Boolean, String],
  24660. timeout: {
  24661. type: [Number, String],
  24662. default: 5000
  24663. },
  24664. vertical: Boolean,
  24665. ...makeLocationProps({
  24666. location: 'bottom'
  24667. }),
  24668. ...makePositionProps(),
  24669. ...makeRoundedProps(),
  24670. ...makeVariantProps(),
  24671. ...makeThemeProps(),
  24672. ...omit(makeVOverlayProps({
  24673. transition: 'v-snackbar-transition'
  24674. }), ['persistent', 'noClickAnimation', 'scrim', 'scrollStrategy'])
  24675. }, 'VSnackbar');
  24676. const VSnackbar = genericComponent()({
  24677. name: 'VSnackbar',
  24678. props: makeVSnackbarProps(),
  24679. emits: {
  24680. 'update:modelValue': v => true
  24681. },
  24682. setup(props, _ref) {
  24683. let {
  24684. slots
  24685. } = _ref;
  24686. const isActive = useProxiedModel(props, 'modelValue');
  24687. const {
  24688. positionClasses
  24689. } = usePosition(props);
  24690. const {
  24691. scopeId
  24692. } = useScopeId();
  24693. const {
  24694. themeClasses
  24695. } = provideTheme(props);
  24696. const {
  24697. colorClasses,
  24698. colorStyles,
  24699. variantClasses
  24700. } = useVariant(props);
  24701. const {
  24702. roundedClasses
  24703. } = useRounded(props);
  24704. const countdown = useCountdown(() => Number(props.timeout));
  24705. const overlay = vue.ref();
  24706. const timerRef = vue.ref();
  24707. const isHovering = vue.shallowRef(false);
  24708. const startY = vue.shallowRef(0);
  24709. const mainStyles = vue.ref();
  24710. const hasLayout = vue.inject(VuetifyLayoutKey, undefined);
  24711. useToggleScope(() => !!hasLayout, () => {
  24712. const layout = useLayout();
  24713. vue.watchEffect(() => {
  24714. mainStyles.value = layout.mainStyles.value;
  24715. });
  24716. });
  24717. vue.watch(isActive, startTimeout);
  24718. vue.watch(() => props.timeout, startTimeout);
  24719. vue.onMounted(() => {
  24720. if (isActive.value) startTimeout();
  24721. });
  24722. let activeTimeout = -1;
  24723. function startTimeout() {
  24724. countdown.reset();
  24725. window.clearTimeout(activeTimeout);
  24726. const timeout = Number(props.timeout);
  24727. if (!isActive.value || timeout === -1) return;
  24728. const element = refElement(timerRef.value);
  24729. countdown.start(element);
  24730. activeTimeout = window.setTimeout(() => {
  24731. isActive.value = false;
  24732. }, timeout);
  24733. }
  24734. function clearTimeout() {
  24735. countdown.reset();
  24736. window.clearTimeout(activeTimeout);
  24737. }
  24738. function onPointerenter() {
  24739. isHovering.value = true;
  24740. clearTimeout();
  24741. }
  24742. function onPointerleave() {
  24743. isHovering.value = false;
  24744. startTimeout();
  24745. }
  24746. function onTouchstart(event) {
  24747. startY.value = event.touches[0].clientY;
  24748. }
  24749. function onTouchend(event) {
  24750. if (Math.abs(startY.value - event.changedTouches[0].clientY) > 50) {
  24751. isActive.value = false;
  24752. }
  24753. }
  24754. function onAfterLeave() {
  24755. if (isHovering.value) onPointerleave();
  24756. }
  24757. const locationClasses = vue.computed(() => {
  24758. return props.location.split(' ').reduce((acc, loc) => {
  24759. acc[`v-snackbar--${loc}`] = true;
  24760. return acc;
  24761. }, {});
  24762. });
  24763. useRender(() => {
  24764. const overlayProps = VOverlay.filterProps(props);
  24765. const hasContent = !!(slots.default || slots.text || props.text);
  24766. return vue.createVNode(VOverlay, vue.mergeProps({
  24767. "ref": overlay,
  24768. "class": ['v-snackbar', {
  24769. 'v-snackbar--active': isActive.value,
  24770. 'v-snackbar--multi-line': props.multiLine && !props.vertical,
  24771. 'v-snackbar--timer': !!props.timer,
  24772. 'v-snackbar--vertical': props.vertical
  24773. }, locationClasses.value, positionClasses.value, props.class],
  24774. "style": [mainStyles.value, props.style]
  24775. }, overlayProps, {
  24776. "modelValue": isActive.value,
  24777. "onUpdate:modelValue": $event => isActive.value = $event,
  24778. "contentProps": vue.mergeProps({
  24779. class: ['v-snackbar__wrapper', themeClasses.value, colorClasses.value, roundedClasses.value, variantClasses.value],
  24780. style: [colorStyles.value],
  24781. onPointerenter,
  24782. onPointerleave
  24783. }, overlayProps.contentProps),
  24784. "persistent": true,
  24785. "noClickAnimation": true,
  24786. "scrim": false,
  24787. "scrollStrategy": "none",
  24788. "_disableGlobalStack": true,
  24789. "onTouchstartPassive": onTouchstart,
  24790. "onTouchend": onTouchend,
  24791. "onAfterLeave": onAfterLeave
  24792. }, scopeId), {
  24793. default: () => [genOverlays(false, 'v-snackbar'), props.timer && !isHovering.value && vue.createVNode("div", {
  24794. "key": "timer",
  24795. "class": "v-snackbar__timer"
  24796. }, [vue.createVNode(VProgressLinear, {
  24797. "ref": timerRef,
  24798. "color": typeof props.timer === 'string' ? props.timer : 'info',
  24799. "max": props.timeout,
  24800. "model-value": countdown.time.value
  24801. }, null)]), hasContent && vue.createVNode("div", {
  24802. "key": "content",
  24803. "class": "v-snackbar__content",
  24804. "role": "status",
  24805. "aria-live": "polite"
  24806. }, [slots.text?.() ?? props.text, slots.default?.()]), slots.actions && vue.createVNode(VDefaultsProvider, {
  24807. "defaults": {
  24808. VBtn: {
  24809. variant: 'text',
  24810. ripple: false,
  24811. slim: true
  24812. }
  24813. }
  24814. }, {
  24815. default: () => [vue.createVNode("div", {
  24816. "class": "v-snackbar__actions"
  24817. }, [slots.actions({
  24818. isActive
  24819. })])]
  24820. })],
  24821. activator: slots.activator
  24822. });
  24823. });
  24824. return forwardRefs({}, overlay);
  24825. }
  24826. });
  24827. // Utilities
  24828. // Types
  24829. const makeLineProps = propsFactory({
  24830. autoDraw: Boolean,
  24831. autoDrawDuration: [Number, String],
  24832. autoDrawEasing: {
  24833. type: String,
  24834. default: 'ease'
  24835. },
  24836. color: String,
  24837. gradient: {
  24838. type: Array,
  24839. default: () => []
  24840. },
  24841. gradientDirection: {
  24842. type: String,
  24843. validator: val => ['top', 'bottom', 'left', 'right'].includes(val),
  24844. default: 'top'
  24845. },
  24846. height: {
  24847. type: [String, Number],
  24848. default: 75
  24849. },
  24850. labels: {
  24851. type: Array,
  24852. default: () => []
  24853. },
  24854. labelSize: {
  24855. type: [Number, String],
  24856. default: 7
  24857. },
  24858. lineWidth: {
  24859. type: [String, Number],
  24860. default: 4
  24861. },
  24862. id: String,
  24863. itemValue: {
  24864. type: String,
  24865. default: 'value'
  24866. },
  24867. modelValue: {
  24868. type: Array,
  24869. default: () => []
  24870. },
  24871. min: [String, Number],
  24872. max: [String, Number],
  24873. padding: {
  24874. type: [String, Number],
  24875. default: 8
  24876. },
  24877. showLabels: Boolean,
  24878. smooth: Boolean,
  24879. width: {
  24880. type: [Number, String],
  24881. default: 300
  24882. }
  24883. }, 'Line');
  24884. // Types
  24885. const makeVBarlineProps = propsFactory({
  24886. autoLineWidth: Boolean,
  24887. ...makeLineProps()
  24888. }, 'VBarline');
  24889. const VBarline = genericComponent()({
  24890. name: 'VBarline',
  24891. props: makeVBarlineProps(),
  24892. setup(props, _ref) {
  24893. let {
  24894. slots
  24895. } = _ref;
  24896. const uid = getUid();
  24897. const id = vue.computed(() => props.id || `barline-${uid}`);
  24898. const autoDrawDuration = vue.computed(() => Number(props.autoDrawDuration) || 500);
  24899. const hasLabels = vue.computed(() => {
  24900. return Boolean(props.showLabels || props.labels.length > 0 || !!slots?.label);
  24901. });
  24902. const lineWidth = vue.computed(() => parseFloat(props.lineWidth) || 4);
  24903. const totalWidth = vue.computed(() => Math.max(props.modelValue.length * lineWidth.value, Number(props.width)));
  24904. const boundary = vue.computed(() => {
  24905. return {
  24906. minX: 0,
  24907. maxX: totalWidth.value,
  24908. minY: 0,
  24909. maxY: parseInt(props.height, 10)
  24910. };
  24911. });
  24912. const items = vue.computed(() => props.modelValue.map(item => getPropertyFromItem(item, props.itemValue, item)));
  24913. function genBars(values, boundary) {
  24914. const {
  24915. minX,
  24916. maxX,
  24917. minY,
  24918. maxY
  24919. } = boundary;
  24920. const totalValues = values.length;
  24921. let maxValue = props.max != null ? Number(props.max) : Math.max(...values);
  24922. let minValue = props.min != null ? Number(props.min) : Math.min(...values);
  24923. if (minValue > 0 && props.min == null) minValue = 0;
  24924. if (maxValue < 0 && props.max == null) maxValue = 0;
  24925. const gridX = maxX / totalValues;
  24926. const gridY = (maxY - minY) / (maxValue - minValue || 1);
  24927. const horizonY = maxY - Math.abs(minValue * gridY);
  24928. return values.map((value, index) => {
  24929. const height = Math.abs(gridY * value);
  24930. return {
  24931. x: minX + index * gridX,
  24932. y: horizonY - height + +(value < 0) * height,
  24933. height,
  24934. value
  24935. };
  24936. });
  24937. }
  24938. const parsedLabels = vue.computed(() => {
  24939. const labels = [];
  24940. const points = genBars(items.value, boundary.value);
  24941. const len = points.length;
  24942. for (let i = 0; labels.length < len; i++) {
  24943. const item = points[i];
  24944. let value = props.labels[i];
  24945. if (!value) {
  24946. value = typeof item === 'object' ? item.value : item;
  24947. }
  24948. labels.push({
  24949. x: item.x,
  24950. value: String(value)
  24951. });
  24952. }
  24953. return labels;
  24954. });
  24955. const bars = vue.computed(() => genBars(items.value, boundary.value));
  24956. const offsetX = vue.computed(() => (Math.abs(bars.value[0].x - bars.value[1].x) - lineWidth.value) / 2);
  24957. useRender(() => {
  24958. const gradientData = !props.gradient.slice().length ? [''] : props.gradient.slice().reverse();
  24959. return vue.createVNode("svg", {
  24960. "display": "block"
  24961. }, [vue.createVNode("defs", null, [vue.createVNode("linearGradient", {
  24962. "id": id.value,
  24963. "gradientUnits": "userSpaceOnUse",
  24964. "x1": props.gradientDirection === 'left' ? '100%' : '0',
  24965. "y1": props.gradientDirection === 'top' ? '100%' : '0',
  24966. "x2": props.gradientDirection === 'right' ? '100%' : '0',
  24967. "y2": props.gradientDirection === 'bottom' ? '100%' : '0'
  24968. }, [gradientData.map((color, index) => vue.createVNode("stop", {
  24969. "offset": index / Math.max(gradientData.length - 1, 1),
  24970. "stop-color": color || 'currentColor'
  24971. }, null))])]), vue.createVNode("clipPath", {
  24972. "id": `${id.value}-clip`
  24973. }, [bars.value.map(item => vue.createVNode("rect", {
  24974. "x": item.x + offsetX.value,
  24975. "y": item.y,
  24976. "width": lineWidth.value,
  24977. "height": item.height,
  24978. "rx": typeof props.smooth === 'number' ? props.smooth : props.smooth ? 2 : 0,
  24979. "ry": typeof props.smooth === 'number' ? props.smooth : props.smooth ? 2 : 0
  24980. }, [props.autoDraw && vue.createVNode(vue.Fragment, null, [vue.createVNode("animate", {
  24981. "attributeName": "y",
  24982. "from": item.y + item.height,
  24983. "to": item.y,
  24984. "dur": `${autoDrawDuration.value}ms`,
  24985. "fill": "freeze"
  24986. }, null), vue.createVNode("animate", {
  24987. "attributeName": "height",
  24988. "from": "0",
  24989. "to": item.height,
  24990. "dur": `${autoDrawDuration.value}ms`,
  24991. "fill": "freeze"
  24992. }, null)])]))]), hasLabels.value && vue.createVNode("g", {
  24993. "key": "labels",
  24994. "style": {
  24995. textAnchor: 'middle',
  24996. dominantBaseline: 'mathematical',
  24997. fill: 'currentColor'
  24998. }
  24999. }, [parsedLabels.value.map((item, i) => vue.createVNode("text", {
  25000. "x": item.x + offsetX.value + lineWidth.value / 2,
  25001. "y": parseInt(props.height, 10) - 2 + (parseInt(props.labelSize, 10) || 7 * 0.75),
  25002. "font-size": Number(props.labelSize) || 7
  25003. }, [slots.label?.({
  25004. index: i,
  25005. value: item.value
  25006. }) ?? item.value]))]), vue.createVNode("g", {
  25007. "clip-path": `url(#${id.value}-clip)`,
  25008. "fill": `url(#${id.value})`
  25009. }, [vue.createVNode("rect", {
  25010. "x": 0,
  25011. "y": 0,
  25012. "width": Math.max(props.modelValue.length * lineWidth.value, Number(props.width)),
  25013. "height": props.height
  25014. }, null)])]);
  25015. });
  25016. }
  25017. });
  25018. // @ts-nocheck
  25019. /* eslint-disable */
  25020. // import { checkCollinear, getDistance, moveTo } from './math'
  25021. /**
  25022. * From https://github.com/unsplash/react-trend/blob/master/src/helpers/DOM.helpers.js#L18
  25023. */
  25024. function genPath(points, radius) {
  25025. let fill = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : false;
  25026. let height = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : 75;
  25027. if (points.length === 0) return '';
  25028. const start = points.shift();
  25029. const end = points[points.length - 1];
  25030. return (fill ? `M${start.x} ${height - start.x + 2} L${start.x} ${start.y}` : `M${start.x} ${start.y}`) + points.map((point, index) => {
  25031. const next = points[index + 1];
  25032. const prev = points[index - 1] || start;
  25033. const isCollinear = next && checkCollinear(next, point, prev);
  25034. if (!next || isCollinear) {
  25035. return `L${point.x} ${point.y}`;
  25036. }
  25037. const threshold = Math.min(getDistance(prev, point), getDistance(next, point));
  25038. const isTooCloseForRadius = threshold / 2 < radius;
  25039. const radiusForPoint = isTooCloseForRadius ? threshold / 2 : radius;
  25040. const before = moveTo(prev, point, radiusForPoint);
  25041. const after = moveTo(next, point, radiusForPoint);
  25042. return `L${before.x} ${before.y}S${point.x} ${point.y} ${after.x} ${after.y}`;
  25043. }).join('') + (fill ? `L${end.x} ${height - start.x + 2} Z` : '');
  25044. }
  25045. function int(value) {
  25046. return parseInt(value, 10);
  25047. }
  25048. /**
  25049. * https://en.wikipedia.org/wiki/Collinearity
  25050. * x=(x1+x2)/2
  25051. * y=(y1+y2)/2
  25052. */
  25053. function checkCollinear(p0, p1, p2) {
  25054. return int(p0.x + p2.x) === int(2 * p1.x) && int(p0.y + p2.y) === int(2 * p1.y);
  25055. }
  25056. function getDistance(p1, p2) {
  25057. return Math.sqrt(Math.pow(p2.x - p1.x, 2) + Math.pow(p2.y - p1.y, 2));
  25058. }
  25059. function moveTo(to, from, radius) {
  25060. const vector = {
  25061. x: to.x - from.x,
  25062. y: to.y - from.y
  25063. };
  25064. const length = Math.sqrt(vector.x * vector.x + vector.y * vector.y);
  25065. const unitVector = {
  25066. x: vector.x / length,
  25067. y: vector.y / length
  25068. };
  25069. return {
  25070. x: from.x + unitVector.x * radius,
  25071. y: from.y + unitVector.y * radius
  25072. };
  25073. }
  25074. // Types
  25075. const makeVTrendlineProps = propsFactory({
  25076. fill: Boolean,
  25077. ...makeLineProps()
  25078. }, 'VTrendline');
  25079. const VTrendline = genericComponent()({
  25080. name: 'VTrendline',
  25081. props: makeVTrendlineProps(),
  25082. setup(props, _ref) {
  25083. let {
  25084. slots
  25085. } = _ref;
  25086. const uid = getUid();
  25087. const id = vue.computed(() => props.id || `trendline-${uid}`);
  25088. const autoDrawDuration = vue.computed(() => Number(props.autoDrawDuration) || (props.fill ? 500 : 2000));
  25089. const lastLength = vue.ref(0);
  25090. const path = vue.ref(null);
  25091. function genPoints(values, boundary) {
  25092. const {
  25093. minX,
  25094. maxX,
  25095. minY,
  25096. maxY
  25097. } = boundary;
  25098. const totalValues = values.length;
  25099. const maxValue = props.max != null ? Number(props.max) : Math.max(...values);
  25100. const minValue = props.min != null ? Number(props.min) : Math.min(...values);
  25101. const gridX = (maxX - minX) / (totalValues - 1);
  25102. const gridY = (maxY - minY) / (maxValue - minValue || 1);
  25103. return values.map((value, index) => {
  25104. return {
  25105. x: minX + index * gridX,
  25106. y: maxY - (value - minValue) * gridY,
  25107. value
  25108. };
  25109. });
  25110. }
  25111. const hasLabels = vue.computed(() => {
  25112. return Boolean(props.showLabels || props.labels.length > 0 || !!slots?.label);
  25113. });
  25114. const lineWidth = vue.computed(() => {
  25115. return parseFloat(props.lineWidth) || 4;
  25116. });
  25117. const totalWidth = vue.computed(() => Number(props.width));
  25118. const boundary = vue.computed(() => {
  25119. const padding = Number(props.padding);
  25120. return {
  25121. minX: padding,
  25122. maxX: totalWidth.value - padding,
  25123. minY: padding,
  25124. maxY: parseInt(props.height, 10) - padding
  25125. };
  25126. });
  25127. const items = vue.computed(() => props.modelValue.map(item => getPropertyFromItem(item, props.itemValue, item)));
  25128. const parsedLabels = vue.computed(() => {
  25129. const labels = [];
  25130. const points = genPoints(items.value, boundary.value);
  25131. const len = points.length;
  25132. for (let i = 0; labels.length < len; i++) {
  25133. const item = points[i];
  25134. let value = props.labels[i];
  25135. if (!value) {
  25136. value = typeof item === 'object' ? item.value : item;
  25137. }
  25138. labels.push({
  25139. x: item.x,
  25140. value: String(value)
  25141. });
  25142. }
  25143. return labels;
  25144. });
  25145. vue.watch(() => props.modelValue, async () => {
  25146. await vue.nextTick();
  25147. if (!props.autoDraw || !path.value) return;
  25148. const pathRef = path.value;
  25149. const length = pathRef.getTotalLength();
  25150. if (!props.fill) {
  25151. // Initial setup to "hide" the line by using the stroke dash array
  25152. pathRef.style.strokeDasharray = `${length}`;
  25153. pathRef.style.strokeDashoffset = `${length}`;
  25154. // Force reflow to ensure the transition starts from this state
  25155. pathRef.getBoundingClientRect();
  25156. // Animate the stroke dash offset to "draw" the line
  25157. pathRef.style.transition = `stroke-dashoffset ${autoDrawDuration.value}ms ${props.autoDrawEasing}`;
  25158. pathRef.style.strokeDashoffset = '0';
  25159. } else {
  25160. // Your existing logic for filled paths remains the same
  25161. pathRef.style.transformOrigin = 'bottom center';
  25162. pathRef.style.transition = 'none';
  25163. pathRef.style.transform = `scaleY(0)`;
  25164. pathRef.getBoundingClientRect();
  25165. pathRef.style.transition = `transform ${autoDrawDuration.value}ms ${props.autoDrawEasing}`;
  25166. pathRef.style.transform = `scaleY(1)`;
  25167. }
  25168. lastLength.value = length;
  25169. }, {
  25170. immediate: true
  25171. });
  25172. function genPath$1(fill) {
  25173. return genPath(genPoints(items.value, boundary.value), props.smooth ? 8 : Number(props.smooth), fill, parseInt(props.height, 10));
  25174. }
  25175. useRender(() => {
  25176. const gradientData = !props.gradient.slice().length ? [''] : props.gradient.slice().reverse();
  25177. return vue.createVNode("svg", {
  25178. "display": "block",
  25179. "stroke-width": parseFloat(props.lineWidth) ?? 4
  25180. }, [vue.createVNode("defs", null, [vue.createVNode("linearGradient", {
  25181. "id": id.value,
  25182. "gradientUnits": "userSpaceOnUse",
  25183. "x1": props.gradientDirection === 'left' ? '100%' : '0',
  25184. "y1": props.gradientDirection === 'top' ? '100%' : '0',
  25185. "x2": props.gradientDirection === 'right' ? '100%' : '0',
  25186. "y2": props.gradientDirection === 'bottom' ? '100%' : '0'
  25187. }, [gradientData.map((color, index) => vue.createVNode("stop", {
  25188. "offset": index / Math.max(gradientData.length - 1, 1),
  25189. "stop-color": color || 'currentColor'
  25190. }, null))])]), hasLabels.value && vue.createVNode("g", {
  25191. "key": "labels",
  25192. "style": {
  25193. textAnchor: 'middle',
  25194. dominantBaseline: 'mathematical',
  25195. fill: 'currentColor'
  25196. }
  25197. }, [parsedLabels.value.map((item, i) => vue.createVNode("text", {
  25198. "x": item.x + lineWidth.value / 2 + lineWidth.value / 2,
  25199. "y": parseInt(props.height, 10) - 4 + (parseInt(props.labelSize, 10) || 7 * 0.75),
  25200. "font-size": Number(props.labelSize) || 7
  25201. }, [slots.label?.({
  25202. index: i,
  25203. value: item.value
  25204. }) ?? item.value]))]), vue.createVNode("path", {
  25205. "ref": path,
  25206. "d": genPath$1(props.fill),
  25207. "fill": props.fill ? `url(#${id.value})` : 'none',
  25208. "stroke": props.fill ? 'none' : `url(#${id.value})`
  25209. }, null), props.fill && vue.createVNode("path", {
  25210. "d": genPath$1(false),
  25211. "fill": "none",
  25212. "stroke": props.color ?? props.gradient?.[0]
  25213. }, null)]);
  25214. });
  25215. }
  25216. });
  25217. // Types
  25218. // Types
  25219. const makeVSparklineProps = propsFactory({
  25220. type: {
  25221. type: String,
  25222. default: 'trend'
  25223. },
  25224. ...makeVBarlineProps(),
  25225. ...makeVTrendlineProps()
  25226. }, 'VSparkline');
  25227. const VSparkline = genericComponent()({
  25228. name: 'VSparkline',
  25229. props: makeVSparklineProps(),
  25230. setup(props, _ref) {
  25231. let {
  25232. slots
  25233. } = _ref;
  25234. const {
  25235. textColorClasses,
  25236. textColorStyles
  25237. } = useTextColor(vue.toRef(props, 'color'));
  25238. const hasLabels = vue.computed(() => {
  25239. return Boolean(props.showLabels || props.labels.length > 0 || !!slots?.label);
  25240. });
  25241. const totalHeight = vue.computed(() => {
  25242. let height = parseInt(props.height, 10);
  25243. if (hasLabels.value) height += parseInt(props.labelSize, 10) * 1.5;
  25244. return height;
  25245. });
  25246. useRender(() => {
  25247. const Tag = props.type === 'trend' ? VTrendline : VBarline;
  25248. const lineProps = props.type === 'trend' ? VTrendline.filterProps(props) : VBarline.filterProps(props);
  25249. return vue.createVNode(Tag, vue.mergeProps({
  25250. "key": props.type,
  25251. "class": textColorClasses.value,
  25252. "style": textColorStyles.value,
  25253. "viewBox": `0 0 ${props.width} ${parseInt(totalHeight.value, 10)}`
  25254. }, lineProps), slots);
  25255. });
  25256. }
  25257. });
  25258. // Types
  25259. const makeVSpeedDialProps = propsFactory({
  25260. ...makeComponentProps(),
  25261. ...makeVMenuProps({
  25262. offset: 8,
  25263. minWidth: 0,
  25264. openDelay: 0,
  25265. closeDelay: 100,
  25266. location: 'top center',
  25267. transition: 'scale-transition'
  25268. })
  25269. }, 'VSpeedDial');
  25270. const VSpeedDial = genericComponent()({
  25271. name: 'VSpeedDial',
  25272. props: makeVSpeedDialProps(),
  25273. emits: {
  25274. 'update:modelValue': value => true
  25275. },
  25276. setup(props, _ref) {
  25277. let {
  25278. slots
  25279. } = _ref;
  25280. const model = useProxiedModel(props, 'modelValue');
  25281. const menuRef = vue.ref();
  25282. const location = vue.computed(() => {
  25283. const [y, x = 'center'] = props.location?.split(' ') ?? [];
  25284. return `${y} ${x}`;
  25285. });
  25286. const locationClasses = vue.computed(() => ({
  25287. [`v-speed-dial__content--${location.value.replace(' ', '-')}`]: true
  25288. }));
  25289. useRender(() => {
  25290. const menuProps = VMenu.filterProps(props);
  25291. return vue.createVNode(VMenu, vue.mergeProps(menuProps, {
  25292. "modelValue": model.value,
  25293. "onUpdate:modelValue": $event => model.value = $event,
  25294. "class": props.class,
  25295. "style": props.style,
  25296. "contentClass": ['v-speed-dial__content', locationClasses.value, props.contentClass],
  25297. "location": location.value,
  25298. "ref": menuRef,
  25299. "transition": "fade-transition"
  25300. }), {
  25301. ...slots,
  25302. default: slotProps => vue.createVNode(VDefaultsProvider, {
  25303. "defaults": {
  25304. VBtn: {
  25305. size: 'small'
  25306. }
  25307. }
  25308. }, {
  25309. default: () => [vue.createVNode(MaybeTransition, {
  25310. "appear": true,
  25311. "group": true,
  25312. "transition": props.transition
  25313. }, {
  25314. default: () => [slots.default?.(slotProps)]
  25315. })]
  25316. })
  25317. });
  25318. });
  25319. return {};
  25320. }
  25321. });
  25322. // Types
  25323. const VStepperSymbol = Symbol.for('vuetify:v-stepper');
  25324. // Types
  25325. const makeVStepperActionsProps = propsFactory({
  25326. color: String,
  25327. disabled: {
  25328. type: [Boolean, String],
  25329. default: false
  25330. },
  25331. prevText: {
  25332. type: String,
  25333. default: '$vuetify.stepper.prev'
  25334. },
  25335. nextText: {
  25336. type: String,
  25337. default: '$vuetify.stepper.next'
  25338. }
  25339. }, 'VStepperActions');
  25340. const VStepperActions = genericComponent()({
  25341. name: 'VStepperActions',
  25342. props: makeVStepperActionsProps(),
  25343. emits: {
  25344. 'click:prev': () => true,
  25345. 'click:next': () => true
  25346. },
  25347. setup(props, _ref) {
  25348. let {
  25349. emit,
  25350. slots
  25351. } = _ref;
  25352. const {
  25353. t
  25354. } = useLocale();
  25355. function onClickPrev() {
  25356. emit('click:prev');
  25357. }
  25358. function onClickNext() {
  25359. emit('click:next');
  25360. }
  25361. useRender(() => {
  25362. const prevSlotProps = {
  25363. onClick: onClickPrev
  25364. };
  25365. const nextSlotProps = {
  25366. onClick: onClickNext
  25367. };
  25368. return vue.createVNode("div", {
  25369. "class": "v-stepper-actions"
  25370. }, [vue.createVNode(VDefaultsProvider, {
  25371. "defaults": {
  25372. VBtn: {
  25373. disabled: ['prev', true].includes(props.disabled),
  25374. text: t(props.prevText),
  25375. variant: 'text'
  25376. }
  25377. }
  25378. }, {
  25379. default: () => [slots.prev?.({
  25380. props: prevSlotProps
  25381. }) ?? vue.createVNode(VBtn, prevSlotProps, null)]
  25382. }), vue.createVNode(VDefaultsProvider, {
  25383. "defaults": {
  25384. VBtn: {
  25385. color: props.color,
  25386. disabled: ['next', true].includes(props.disabled),
  25387. text: t(props.nextText),
  25388. variant: 'tonal'
  25389. }
  25390. }
  25391. }, {
  25392. default: () => [slots.next?.({
  25393. props: nextSlotProps
  25394. }) ?? vue.createVNode(VBtn, nextSlotProps, null)]
  25395. })]);
  25396. });
  25397. return {};
  25398. }
  25399. });
  25400. // Utilities
  25401. const VStepperHeader = createSimpleFunctional('v-stepper-header');
  25402. // Types
  25403. const makeStepperItemProps = propsFactory({
  25404. color: String,
  25405. title: String,
  25406. subtitle: String,
  25407. complete: Boolean,
  25408. completeIcon: {
  25409. type: IconValue,
  25410. default: '$complete'
  25411. },
  25412. editable: Boolean,
  25413. editIcon: {
  25414. type: IconValue,
  25415. default: '$edit'
  25416. },
  25417. error: Boolean,
  25418. errorIcon: {
  25419. type: IconValue,
  25420. default: '$error'
  25421. },
  25422. icon: IconValue,
  25423. ripple: {
  25424. type: [Boolean, Object],
  25425. default: true
  25426. },
  25427. rules: {
  25428. type: Array,
  25429. default: () => []
  25430. }
  25431. }, 'StepperItem');
  25432. const makeVStepperItemProps = propsFactory({
  25433. ...makeStepperItemProps(),
  25434. ...makeGroupItemProps()
  25435. }, 'VStepperItem');
  25436. const VStepperItem = genericComponent()({
  25437. name: 'VStepperItem',
  25438. directives: {
  25439. Ripple
  25440. },
  25441. props: makeVStepperItemProps(),
  25442. emits: {
  25443. 'group:selected': val => true
  25444. },
  25445. setup(props, _ref) {
  25446. let {
  25447. slots
  25448. } = _ref;
  25449. const group = useGroupItem(props, VStepperSymbol, true);
  25450. const step = vue.computed(() => group?.value.value ?? props.value);
  25451. const isValid = vue.computed(() => props.rules.every(handler => handler() === true));
  25452. const isClickable = vue.computed(() => !props.disabled && props.editable);
  25453. const canEdit = vue.computed(() => !props.disabled && props.editable);
  25454. const hasError = vue.computed(() => props.error || !isValid.value);
  25455. const hasCompleted = vue.computed(() => props.complete || props.rules.length > 0 && isValid.value);
  25456. const icon = vue.computed(() => {
  25457. if (hasError.value) return props.errorIcon;
  25458. if (hasCompleted.value) return props.completeIcon;
  25459. if (group.isSelected.value && props.editable) return props.editIcon;
  25460. return props.icon;
  25461. });
  25462. const slotProps = vue.computed(() => ({
  25463. canEdit: canEdit.value,
  25464. hasError: hasError.value,
  25465. hasCompleted: hasCompleted.value,
  25466. title: props.title,
  25467. subtitle: props.subtitle,
  25468. step: step.value,
  25469. value: props.value
  25470. }));
  25471. useRender(() => {
  25472. const hasColor = (!group || group.isSelected.value || hasCompleted.value || canEdit.value) && !hasError.value && !props.disabled;
  25473. const hasTitle = !!(props.title != null || slots.title);
  25474. const hasSubtitle = !!(props.subtitle != null || slots.subtitle);
  25475. function onClick() {
  25476. group?.toggle();
  25477. }
  25478. return vue.withDirectives(vue.createVNode("button", {
  25479. "class": ['v-stepper-item', {
  25480. 'v-stepper-item--complete': hasCompleted.value,
  25481. 'v-stepper-item--disabled': props.disabled,
  25482. 'v-stepper-item--error': hasError.value
  25483. }, group?.selectedClass.value],
  25484. "disabled": !props.editable,
  25485. "onClick": onClick
  25486. }, [isClickable.value && genOverlays(true, 'v-stepper-item'), vue.createVNode(VAvatar, {
  25487. "key": "stepper-avatar",
  25488. "class": "v-stepper-item__avatar",
  25489. "color": hasColor ? props.color : undefined,
  25490. "size": 24
  25491. }, {
  25492. default: () => [slots.icon?.(slotProps.value) ?? (icon.value ? vue.createVNode(VIcon, {
  25493. "icon": icon.value
  25494. }, null) : step.value)]
  25495. }), vue.createVNode("div", {
  25496. "class": "v-stepper-item__content"
  25497. }, [hasTitle && vue.createVNode("div", {
  25498. "key": "title",
  25499. "class": "v-stepper-item__title"
  25500. }, [slots.title?.(slotProps.value) ?? props.title]), hasSubtitle && vue.createVNode("div", {
  25501. "key": "subtitle",
  25502. "class": "v-stepper-item__subtitle"
  25503. }, [slots.subtitle?.(slotProps.value) ?? props.subtitle]), slots.default?.(slotProps.value)])]), [[vue.resolveDirective("ripple"), props.ripple && props.editable, null]]);
  25504. });
  25505. return {};
  25506. }
  25507. });
  25508. const makeVStepperWindowProps = propsFactory({
  25509. ...omit(makeVWindowProps(), ['continuous', 'nextIcon', 'prevIcon', 'showArrows', 'touch', 'mandatory'])
  25510. }, 'VStepperWindow');
  25511. const VStepperWindow = genericComponent()({
  25512. name: 'VStepperWindow',
  25513. props: makeVStepperWindowProps(),
  25514. emits: {
  25515. 'update:modelValue': v => true
  25516. },
  25517. setup(props, _ref) {
  25518. let {
  25519. slots
  25520. } = _ref;
  25521. const group = vue.inject(VStepperSymbol, null);
  25522. const _model = useProxiedModel(props, 'modelValue');
  25523. const model = vue.computed({
  25524. get() {
  25525. // Always return modelValue if defined
  25526. // or if not within a VStepper group
  25527. if (_model.value != null || !group) return _model.value;
  25528. // If inside of a VStepper, find the currently selected
  25529. // item by id. Item value may be assigned by its index
  25530. return group.items.value.find(item => group.selected.value.includes(item.id))?.value;
  25531. },
  25532. set(val) {
  25533. _model.value = val;
  25534. }
  25535. });
  25536. useRender(() => {
  25537. const windowProps = VWindow.filterProps(props);
  25538. return vue.createVNode(VWindow, vue.mergeProps({
  25539. "_as": "VStepperWindow"
  25540. }, windowProps, {
  25541. "modelValue": model.value,
  25542. "onUpdate:modelValue": $event => model.value = $event,
  25543. "class": ['v-stepper-window', props.class],
  25544. "style": props.style,
  25545. "mandatory": false,
  25546. "touch": false
  25547. }), slots);
  25548. });
  25549. return {};
  25550. }
  25551. });
  25552. const makeVStepperWindowItemProps = propsFactory({
  25553. ...makeVWindowItemProps()
  25554. }, 'VStepperWindowItem');
  25555. const VStepperWindowItem = genericComponent()({
  25556. name: 'VStepperWindowItem',
  25557. props: makeVStepperWindowItemProps(),
  25558. setup(props, _ref) {
  25559. let {
  25560. slots
  25561. } = _ref;
  25562. useRender(() => {
  25563. const windowItemProps = VWindowItem.filterProps(props);
  25564. return vue.createVNode(VWindowItem, vue.mergeProps({
  25565. "_as": "VStepperWindowItem"
  25566. }, windowItemProps, {
  25567. "class": ['v-stepper-window-item', props.class],
  25568. "style": props.style
  25569. }), slots);
  25570. });
  25571. return {};
  25572. }
  25573. });
  25574. // Types
  25575. const makeStepperProps = propsFactory({
  25576. altLabels: Boolean,
  25577. bgColor: String,
  25578. completeIcon: IconValue,
  25579. editIcon: IconValue,
  25580. editable: Boolean,
  25581. errorIcon: IconValue,
  25582. hideActions: Boolean,
  25583. items: {
  25584. type: Array,
  25585. default: () => []
  25586. },
  25587. itemTitle: {
  25588. type: String,
  25589. default: 'title'
  25590. },
  25591. itemValue: {
  25592. type: String,
  25593. default: 'value'
  25594. },
  25595. nonLinear: Boolean,
  25596. flat: Boolean,
  25597. ...makeDisplayProps()
  25598. }, 'Stepper');
  25599. const makeVStepperProps = propsFactory({
  25600. ...makeStepperProps(),
  25601. ...makeGroupProps({
  25602. mandatory: 'force',
  25603. selectedClass: 'v-stepper-item--selected'
  25604. }),
  25605. ...makeVSheetProps(),
  25606. ...only(makeVStepperActionsProps(), ['prevText', 'nextText'])
  25607. }, 'VStepper');
  25608. const VStepper = genericComponent()({
  25609. name: 'VStepper',
  25610. props: makeVStepperProps(),
  25611. emits: {
  25612. 'update:modelValue': v => true
  25613. },
  25614. setup(props, _ref) {
  25615. let {
  25616. slots
  25617. } = _ref;
  25618. const {
  25619. items: _items,
  25620. next,
  25621. prev,
  25622. selected
  25623. } = useGroup(props, VStepperSymbol);
  25624. const {
  25625. displayClasses,
  25626. mobile
  25627. } = useDisplay(props);
  25628. const {
  25629. completeIcon,
  25630. editIcon,
  25631. errorIcon,
  25632. color,
  25633. editable,
  25634. prevText,
  25635. nextText
  25636. } = vue.toRefs(props);
  25637. const items = vue.computed(() => props.items.map((item, index) => {
  25638. const title = getPropertyFromItem(item, props.itemTitle, item);
  25639. const value = getPropertyFromItem(item, props.itemValue, index + 1);
  25640. return {
  25641. title,
  25642. value,
  25643. raw: item
  25644. };
  25645. }));
  25646. const activeIndex = vue.computed(() => {
  25647. return _items.value.findIndex(item => selected.value.includes(item.id));
  25648. });
  25649. const disabled = vue.computed(() => {
  25650. if (props.disabled) return props.disabled;
  25651. if (activeIndex.value === 0) return 'prev';
  25652. if (activeIndex.value === _items.value.length - 1) return 'next';
  25653. return false;
  25654. });
  25655. provideDefaults({
  25656. VStepperItem: {
  25657. editable,
  25658. errorIcon,
  25659. completeIcon,
  25660. editIcon,
  25661. prevText,
  25662. nextText
  25663. },
  25664. VStepperActions: {
  25665. color,
  25666. disabled,
  25667. prevText,
  25668. nextText
  25669. }
  25670. });
  25671. useRender(() => {
  25672. const sheetProps = VSheet.filterProps(props);
  25673. const hasHeader = !!(slots.header || props.items.length);
  25674. const hasWindow = props.items.length > 0;
  25675. const hasActions = !props.hideActions && !!(hasWindow || slots.actions);
  25676. return vue.createVNode(VSheet, vue.mergeProps(sheetProps, {
  25677. "color": props.bgColor,
  25678. "class": ['v-stepper', {
  25679. 'v-stepper--alt-labels': props.altLabels,
  25680. 'v-stepper--flat': props.flat,
  25681. 'v-stepper--non-linear': props.nonLinear,
  25682. 'v-stepper--mobile': mobile.value
  25683. }, displayClasses.value, props.class],
  25684. "style": props.style
  25685. }), {
  25686. default: () => [hasHeader && vue.createVNode(VStepperHeader, {
  25687. "key": "stepper-header"
  25688. }, {
  25689. default: () => [items.value.map((_ref2, index) => {
  25690. let {
  25691. raw,
  25692. ...item
  25693. } = _ref2;
  25694. return vue.createVNode(vue.Fragment, null, [!!index && vue.createVNode(VDivider, null, null), vue.createVNode(VStepperItem, item, {
  25695. default: slots[`header-item.${item.value}`] ?? slots.header,
  25696. icon: slots.icon,
  25697. title: slots.title,
  25698. subtitle: slots.subtitle
  25699. })]);
  25700. })]
  25701. }), hasWindow && vue.createVNode(VStepperWindow, {
  25702. "key": "stepper-window"
  25703. }, {
  25704. default: () => [items.value.map(item => vue.createVNode(VStepperWindowItem, {
  25705. "value": item.value
  25706. }, {
  25707. default: () => slots[`item.${item.value}`]?.(item) ?? slots.item?.(item)
  25708. }))]
  25709. }), slots.default?.({
  25710. prev,
  25711. next
  25712. }), hasActions && (slots.actions?.({
  25713. next,
  25714. prev
  25715. }) ?? vue.createVNode(VStepperActions, {
  25716. "key": "stepper-actions",
  25717. "onClick:prev": prev,
  25718. "onClick:next": next
  25719. }, slots))]
  25720. });
  25721. });
  25722. return {
  25723. prev,
  25724. next
  25725. };
  25726. }
  25727. });
  25728. // Types
  25729. const makeVSwitchProps = propsFactory({
  25730. indeterminate: Boolean,
  25731. inset: Boolean,
  25732. flat: Boolean,
  25733. loading: {
  25734. type: [Boolean, String],
  25735. default: false
  25736. },
  25737. ...makeVInputProps(),
  25738. ...makeVSelectionControlProps()
  25739. }, 'VSwitch');
  25740. const VSwitch = genericComponent()({
  25741. name: 'VSwitch',
  25742. inheritAttrs: false,
  25743. props: makeVSwitchProps(),
  25744. emits: {
  25745. 'update:focused': focused => true,
  25746. 'update:modelValue': value => true,
  25747. 'update:indeterminate': value => true
  25748. },
  25749. setup(props, _ref) {
  25750. let {
  25751. attrs,
  25752. slots
  25753. } = _ref;
  25754. const indeterminate = useProxiedModel(props, 'indeterminate');
  25755. const model = useProxiedModel(props, 'modelValue');
  25756. const {
  25757. loaderClasses
  25758. } = useLoader(props);
  25759. const {
  25760. isFocused,
  25761. focus,
  25762. blur
  25763. } = useFocus(props);
  25764. const control = vue.ref();
  25765. const isForcedColorsModeActive = IN_BROWSER && window.matchMedia('(forced-colors: active)').matches;
  25766. const loaderColor = vue.computed(() => {
  25767. return typeof props.loading === 'string' && props.loading !== '' ? props.loading : props.color;
  25768. });
  25769. const uid = getUid();
  25770. const id = vue.computed(() => props.id || `switch-${uid}`);
  25771. function onChange() {
  25772. if (indeterminate.value) {
  25773. indeterminate.value = false;
  25774. }
  25775. }
  25776. function onTrackClick(e) {
  25777. e.stopPropagation();
  25778. e.preventDefault();
  25779. control.value?.input?.click();
  25780. }
  25781. useRender(() => {
  25782. const [rootAttrs, controlAttrs] = filterInputAttrs(attrs);
  25783. const inputProps = VInput.filterProps(props);
  25784. const controlProps = VSelectionControl.filterProps(props);
  25785. return vue.createVNode(VInput, vue.mergeProps({
  25786. "class": ['v-switch', {
  25787. 'v-switch--flat': props.flat
  25788. }, {
  25789. 'v-switch--inset': props.inset
  25790. }, {
  25791. 'v-switch--indeterminate': indeterminate.value
  25792. }, loaderClasses.value, props.class]
  25793. }, rootAttrs, inputProps, {
  25794. "modelValue": model.value,
  25795. "onUpdate:modelValue": $event => model.value = $event,
  25796. "id": id.value,
  25797. "focused": isFocused.value,
  25798. "style": props.style
  25799. }), {
  25800. ...slots,
  25801. default: _ref2 => {
  25802. let {
  25803. id,
  25804. messagesId,
  25805. isDisabled,
  25806. isReadonly,
  25807. isValid
  25808. } = _ref2;
  25809. const slotProps = {
  25810. model,
  25811. isValid
  25812. };
  25813. return vue.createVNode(VSelectionControl, vue.mergeProps({
  25814. "ref": control
  25815. }, controlProps, {
  25816. "modelValue": model.value,
  25817. "onUpdate:modelValue": [$event => model.value = $event, onChange],
  25818. "id": id.value,
  25819. "aria-describedby": messagesId.value,
  25820. "type": "checkbox",
  25821. "aria-checked": indeterminate.value ? 'mixed' : undefined,
  25822. "disabled": isDisabled.value,
  25823. "readonly": isReadonly.value,
  25824. "onFocus": focus,
  25825. "onBlur": blur
  25826. }, controlAttrs), {
  25827. ...slots,
  25828. default: _ref3 => {
  25829. let {
  25830. backgroundColorClasses,
  25831. backgroundColorStyles
  25832. } = _ref3;
  25833. return vue.createVNode("div", {
  25834. "class": ['v-switch__track', !isForcedColorsModeActive ? backgroundColorClasses.value : undefined],
  25835. "style": backgroundColorStyles.value,
  25836. "onClick": onTrackClick
  25837. }, [slots['track-true'] && vue.createVNode("div", {
  25838. "key": "prepend",
  25839. "class": "v-switch__track-true"
  25840. }, [slots['track-true'](slotProps)]), slots['track-false'] && vue.createVNode("div", {
  25841. "key": "append",
  25842. "class": "v-switch__track-false"
  25843. }, [slots['track-false'](slotProps)])]);
  25844. },
  25845. input: _ref4 => {
  25846. let {
  25847. inputNode,
  25848. icon,
  25849. backgroundColorClasses,
  25850. backgroundColorStyles
  25851. } = _ref4;
  25852. return vue.createVNode(vue.Fragment, null, [inputNode, vue.createVNode("div", {
  25853. "class": ['v-switch__thumb', {
  25854. 'v-switch__thumb--filled': icon || props.loading
  25855. }, props.inset || isForcedColorsModeActive ? undefined : backgroundColorClasses.value],
  25856. "style": props.inset ? undefined : backgroundColorStyles.value
  25857. }, [slots.thumb ? vue.createVNode(VDefaultsProvider, {
  25858. "defaults": {
  25859. VIcon: {
  25860. icon,
  25861. size: 'x-small'
  25862. }
  25863. }
  25864. }, {
  25865. default: () => [slots.thumb({
  25866. ...slotProps,
  25867. icon
  25868. })]
  25869. }) : vue.createVNode(VScaleTransition, null, {
  25870. default: () => [!props.loading ? icon && vue.createVNode(VIcon, {
  25871. "key": String(icon),
  25872. "icon": icon,
  25873. "size": "x-small"
  25874. }, null) : vue.createVNode(LoaderSlot, {
  25875. "name": "v-switch",
  25876. "active": true,
  25877. "color": isValid.value === false ? undefined : loaderColor.value
  25878. }, {
  25879. default: slotProps => slots.loader ? slots.loader(slotProps) : vue.createVNode(VProgressCircular, {
  25880. "active": slotProps.isActive,
  25881. "color": slotProps.color,
  25882. "indeterminate": true,
  25883. "size": "16",
  25884. "width": "2"
  25885. }, null)
  25886. })]
  25887. })])]);
  25888. }
  25889. });
  25890. }
  25891. });
  25892. });
  25893. return {};
  25894. }
  25895. });
  25896. const makeVSystemBarProps = propsFactory({
  25897. color: String,
  25898. height: [Number, String],
  25899. window: Boolean,
  25900. ...makeComponentProps(),
  25901. ...makeElevationProps(),
  25902. ...makeLayoutItemProps(),
  25903. ...makeRoundedProps(),
  25904. ...makeTagProps(),
  25905. ...makeThemeProps()
  25906. }, 'VSystemBar');
  25907. const VSystemBar = genericComponent()({
  25908. name: 'VSystemBar',
  25909. props: makeVSystemBarProps(),
  25910. setup(props, _ref) {
  25911. let {
  25912. slots
  25913. } = _ref;
  25914. const {
  25915. themeClasses
  25916. } = provideTheme(props);
  25917. const {
  25918. backgroundColorClasses,
  25919. backgroundColorStyles
  25920. } = useBackgroundColor(vue.toRef(props, 'color'));
  25921. const {
  25922. elevationClasses
  25923. } = useElevation(props);
  25924. const {
  25925. roundedClasses
  25926. } = useRounded(props);
  25927. const {
  25928. ssrBootStyles
  25929. } = useSsrBoot();
  25930. const height = vue.computed(() => props.height ?? (props.window ? 32 : 24));
  25931. const {
  25932. layoutItemStyles
  25933. } = useLayoutItem({
  25934. id: props.name,
  25935. order: vue.computed(() => parseInt(props.order, 10)),
  25936. position: vue.shallowRef('top'),
  25937. layoutSize: height,
  25938. elementSize: height,
  25939. active: vue.computed(() => true),
  25940. absolute: vue.toRef(props, 'absolute')
  25941. });
  25942. useRender(() => vue.createVNode(props.tag, {
  25943. "class": ['v-system-bar', {
  25944. 'v-system-bar--window': props.window
  25945. }, themeClasses.value, backgroundColorClasses.value, elevationClasses.value, roundedClasses.value, props.class],
  25946. "style": [backgroundColorStyles.value, layoutItemStyles.value, ssrBootStyles.value, props.style]
  25947. }, slots));
  25948. return {};
  25949. }
  25950. });
  25951. // Types
  25952. const VTabsSymbol = Symbol.for('vuetify:v-tabs');
  25953. // Types
  25954. const makeVTabProps = propsFactory({
  25955. fixed: Boolean,
  25956. sliderColor: String,
  25957. hideSlider: Boolean,
  25958. direction: {
  25959. type: String,
  25960. default: 'horizontal'
  25961. },
  25962. ...omit(makeVBtnProps({
  25963. selectedClass: 'v-tab--selected',
  25964. variant: 'text'
  25965. }), ['active', 'block', 'flat', 'location', 'position', 'symbol'])
  25966. }, 'VTab');
  25967. const VTab = genericComponent()({
  25968. name: 'VTab',
  25969. props: makeVTabProps(),
  25970. setup(props, _ref) {
  25971. let {
  25972. slots,
  25973. attrs
  25974. } = _ref;
  25975. const {
  25976. textColorClasses: sliderColorClasses,
  25977. textColorStyles: sliderColorStyles
  25978. } = useTextColor(props, 'sliderColor');
  25979. const rootEl = vue.ref();
  25980. const sliderEl = vue.ref();
  25981. const isHorizontal = vue.computed(() => props.direction === 'horizontal');
  25982. const isSelected = vue.computed(() => rootEl.value?.group?.isSelected.value ?? false);
  25983. function updateSlider(_ref2) {
  25984. let {
  25985. value
  25986. } = _ref2;
  25987. if (value) {
  25988. const prevEl = rootEl.value?.$el.parentElement?.querySelector('.v-tab--selected .v-tab__slider');
  25989. const nextEl = sliderEl.value;
  25990. if (!prevEl || !nextEl) return;
  25991. const color = getComputedStyle(prevEl).color;
  25992. const prevBox = prevEl.getBoundingClientRect();
  25993. const nextBox = nextEl.getBoundingClientRect();
  25994. const xy = isHorizontal.value ? 'x' : 'y';
  25995. const XY = isHorizontal.value ? 'X' : 'Y';
  25996. const rightBottom = isHorizontal.value ? 'right' : 'bottom';
  25997. const widthHeight = isHorizontal.value ? 'width' : 'height';
  25998. const prevPos = prevBox[xy];
  25999. const nextPos = nextBox[xy];
  26000. const delta = prevPos > nextPos ? prevBox[rightBottom] - nextBox[rightBottom] : prevBox[xy] - nextBox[xy];
  26001. const origin = Math.sign(delta) > 0 ? isHorizontal.value ? 'right' : 'bottom' : Math.sign(delta) < 0 ? isHorizontal.value ? 'left' : 'top' : 'center';
  26002. const size = Math.abs(delta) + (Math.sign(delta) < 0 ? prevBox[widthHeight] : nextBox[widthHeight]);
  26003. const scale = size / Math.max(prevBox[widthHeight], nextBox[widthHeight]) || 0;
  26004. const initialScale = prevBox[widthHeight] / nextBox[widthHeight] || 0;
  26005. const sigma = 1.5;
  26006. animate(nextEl, {
  26007. backgroundColor: [color, 'currentcolor'],
  26008. transform: [`translate${XY}(${delta}px) scale${XY}(${initialScale})`, `translate${XY}(${delta / sigma}px) scale${XY}(${(scale - 1) / sigma + 1})`, 'none'],
  26009. transformOrigin: Array(3).fill(origin)
  26010. }, {
  26011. duration: 225,
  26012. easing: standardEasing
  26013. });
  26014. }
  26015. }
  26016. useRender(() => {
  26017. const btnProps = VBtn.filterProps(props);
  26018. return vue.createVNode(VBtn, vue.mergeProps({
  26019. "symbol": VTabsSymbol,
  26020. "ref": rootEl,
  26021. "class": ['v-tab', props.class],
  26022. "style": props.style,
  26023. "tabindex": isSelected.value ? 0 : -1,
  26024. "role": "tab",
  26025. "aria-selected": String(isSelected.value),
  26026. "active": false
  26027. }, btnProps, attrs, {
  26028. "block": props.fixed,
  26029. "maxWidth": props.fixed ? 300 : undefined,
  26030. "onGroup:selected": updateSlider
  26031. }), {
  26032. ...slots,
  26033. default: () => vue.createVNode(vue.Fragment, null, [slots.default?.() ?? props.text, !props.hideSlider && vue.createVNode("div", {
  26034. "ref": sliderEl,
  26035. "class": ['v-tab__slider', sliderColorClasses.value],
  26036. "style": sliderColorStyles.value
  26037. }, null)])
  26038. });
  26039. });
  26040. return forwardRefs({}, rootEl);
  26041. }
  26042. });
  26043. const makeVTabsWindowProps = propsFactory({
  26044. ...omit(makeVWindowProps(), ['continuous', 'nextIcon', 'prevIcon', 'showArrows', 'touch', 'mandatory'])
  26045. }, 'VTabsWindow');
  26046. const VTabsWindow = genericComponent()({
  26047. name: 'VTabsWindow',
  26048. props: makeVTabsWindowProps(),
  26049. emits: {
  26050. 'update:modelValue': v => true
  26051. },
  26052. setup(props, _ref) {
  26053. let {
  26054. slots
  26055. } = _ref;
  26056. const group = vue.inject(VTabsSymbol, null);
  26057. const _model = useProxiedModel(props, 'modelValue');
  26058. const model = vue.computed({
  26059. get() {
  26060. // Always return modelValue if defined
  26061. // or if not within a VTabs group
  26062. if (_model.value != null || !group) return _model.value;
  26063. // If inside of a VTabs, find the currently selected
  26064. // item by id. Item value may be assigned by its index
  26065. return group.items.value.find(item => group.selected.value.includes(item.id))?.value;
  26066. },
  26067. set(val) {
  26068. _model.value = val;
  26069. }
  26070. });
  26071. useRender(() => {
  26072. const windowProps = VWindow.filterProps(props);
  26073. return vue.createVNode(VWindow, vue.mergeProps({
  26074. "_as": "VTabsWindow"
  26075. }, windowProps, {
  26076. "modelValue": model.value,
  26077. "onUpdate:modelValue": $event => model.value = $event,
  26078. "class": ['v-tabs-window', props.class],
  26079. "style": props.style,
  26080. "mandatory": false,
  26081. "touch": false
  26082. }), slots);
  26083. });
  26084. return {};
  26085. }
  26086. });
  26087. const makeVTabsWindowItemProps = propsFactory({
  26088. ...makeVWindowItemProps()
  26089. }, 'VTabsWindowItem');
  26090. const VTabsWindowItem = genericComponent()({
  26091. name: 'VTabsWindowItem',
  26092. props: makeVTabsWindowItemProps(),
  26093. setup(props, _ref) {
  26094. let {
  26095. slots
  26096. } = _ref;
  26097. useRender(() => {
  26098. const windowItemProps = VWindowItem.filterProps(props);
  26099. return vue.createVNode(VWindowItem, vue.mergeProps({
  26100. "_as": "VTabsWindowItem"
  26101. }, windowItemProps, {
  26102. "class": ['v-tabs-window-item', props.class],
  26103. "style": props.style
  26104. }), slots);
  26105. });
  26106. return {};
  26107. }
  26108. });
  26109. function parseItems(items) {
  26110. if (!items) return [];
  26111. return items.map(item => {
  26112. if (!isObject(item)) return {
  26113. text: item,
  26114. value: item
  26115. };
  26116. return item;
  26117. });
  26118. }
  26119. const makeVTabsProps = propsFactory({
  26120. alignTabs: {
  26121. type: String,
  26122. default: 'start'
  26123. },
  26124. color: String,
  26125. fixedTabs: Boolean,
  26126. items: {
  26127. type: Array,
  26128. default: () => []
  26129. },
  26130. stacked: Boolean,
  26131. bgColor: String,
  26132. grow: Boolean,
  26133. height: {
  26134. type: [Number, String],
  26135. default: undefined
  26136. },
  26137. hideSlider: Boolean,
  26138. sliderColor: String,
  26139. ...makeVSlideGroupProps({
  26140. mandatory: 'force',
  26141. selectedClass: 'v-tab-item--selected'
  26142. }),
  26143. ...makeDensityProps(),
  26144. ...makeTagProps()
  26145. }, 'VTabs');
  26146. const VTabs = genericComponent()({
  26147. name: 'VTabs',
  26148. props: makeVTabsProps(),
  26149. emits: {
  26150. 'update:modelValue': v => true
  26151. },
  26152. setup(props, _ref) {
  26153. let {
  26154. attrs,
  26155. slots
  26156. } = _ref;
  26157. const model = useProxiedModel(props, 'modelValue');
  26158. const items = vue.computed(() => parseItems(props.items));
  26159. const {
  26160. densityClasses
  26161. } = useDensity(props);
  26162. const {
  26163. backgroundColorClasses,
  26164. backgroundColorStyles
  26165. } = useBackgroundColor(vue.toRef(props, 'bgColor'));
  26166. const {
  26167. scopeId
  26168. } = useScopeId();
  26169. provideDefaults({
  26170. VTab: {
  26171. color: vue.toRef(props, 'color'),
  26172. direction: vue.toRef(props, 'direction'),
  26173. stacked: vue.toRef(props, 'stacked'),
  26174. fixed: vue.toRef(props, 'fixedTabs'),
  26175. sliderColor: vue.toRef(props, 'sliderColor'),
  26176. hideSlider: vue.toRef(props, 'hideSlider')
  26177. }
  26178. });
  26179. useRender(() => {
  26180. const slideGroupProps = VSlideGroup.filterProps(props);
  26181. const hasWindow = !!(slots.window || props.items.length > 0);
  26182. return vue.createVNode(vue.Fragment, null, [vue.createVNode(VSlideGroup, vue.mergeProps(slideGroupProps, {
  26183. "modelValue": model.value,
  26184. "onUpdate:modelValue": $event => model.value = $event,
  26185. "class": ['v-tabs', `v-tabs--${props.direction}`, `v-tabs--align-tabs-${props.alignTabs}`, {
  26186. 'v-tabs--fixed-tabs': props.fixedTabs,
  26187. 'v-tabs--grow': props.grow,
  26188. 'v-tabs--stacked': props.stacked
  26189. }, densityClasses.value, backgroundColorClasses.value, props.class],
  26190. "style": [{
  26191. '--v-tabs-height': convertToUnit(props.height)
  26192. }, backgroundColorStyles.value, props.style],
  26193. "role": "tablist",
  26194. "symbol": VTabsSymbol
  26195. }, scopeId, attrs), {
  26196. default: () => [slots.default?.() ?? items.value.map(item => slots.tab?.({
  26197. item
  26198. }) ?? vue.createVNode(VTab, vue.mergeProps(item, {
  26199. "key": item.text,
  26200. "value": item.value
  26201. }), {
  26202. default: slots[`tab.${item.value}`] ? () => slots[`tab.${item.value}`]?.({
  26203. item
  26204. }) : undefined
  26205. }))]
  26206. }), hasWindow && vue.createVNode(VTabsWindow, vue.mergeProps({
  26207. "modelValue": model.value,
  26208. "onUpdate:modelValue": $event => model.value = $event,
  26209. "key": "tabs-window"
  26210. }, scopeId), {
  26211. default: () => [items.value.map(item => slots.item?.({
  26212. item
  26213. }) ?? vue.createVNode(VTabsWindowItem, {
  26214. "value": item.value
  26215. }, {
  26216. default: () => slots[`item.${item.value}`]?.({
  26217. item
  26218. })
  26219. })), slots.window?.()]
  26220. })]);
  26221. });
  26222. return {};
  26223. }
  26224. });
  26225. // Types
  26226. const makeVTextareaProps = propsFactory({
  26227. autoGrow: Boolean,
  26228. autofocus: Boolean,
  26229. counter: [Boolean, Number, String],
  26230. counterValue: Function,
  26231. prefix: String,
  26232. placeholder: String,
  26233. persistentPlaceholder: Boolean,
  26234. persistentCounter: Boolean,
  26235. noResize: Boolean,
  26236. rows: {
  26237. type: [Number, String],
  26238. default: 5,
  26239. validator: v => !isNaN(parseFloat(v))
  26240. },
  26241. maxRows: {
  26242. type: [Number, String],
  26243. validator: v => !isNaN(parseFloat(v))
  26244. },
  26245. suffix: String,
  26246. modelModifiers: Object,
  26247. ...makeVInputProps(),
  26248. ...makeVFieldProps()
  26249. }, 'VTextarea');
  26250. const VTextarea = genericComponent()({
  26251. name: 'VTextarea',
  26252. directives: {
  26253. Intersect
  26254. },
  26255. inheritAttrs: false,
  26256. props: makeVTextareaProps(),
  26257. emits: {
  26258. 'click:control': e => true,
  26259. 'mousedown:control': e => true,
  26260. 'update:focused': focused => true,
  26261. 'update:modelValue': val => true
  26262. },
  26263. setup(props, _ref) {
  26264. let {
  26265. attrs,
  26266. emit,
  26267. slots
  26268. } = _ref;
  26269. const model = useProxiedModel(props, 'modelValue');
  26270. const {
  26271. isFocused,
  26272. focus,
  26273. blur
  26274. } = useFocus(props);
  26275. const counterValue = vue.computed(() => {
  26276. return typeof props.counterValue === 'function' ? props.counterValue(model.value) : (model.value || '').toString().length;
  26277. });
  26278. const max = vue.computed(() => {
  26279. if (attrs.maxlength) return attrs.maxlength;
  26280. if (!props.counter || typeof props.counter !== 'number' && typeof props.counter !== 'string') return undefined;
  26281. return props.counter;
  26282. });
  26283. function onIntersect(isIntersecting, entries) {
  26284. if (!props.autofocus || !isIntersecting) return;
  26285. entries[0].target?.focus?.();
  26286. }
  26287. const vInputRef = vue.ref();
  26288. const vFieldRef = vue.ref();
  26289. const controlHeight = vue.shallowRef('');
  26290. const textareaRef = vue.ref();
  26291. const isActive = vue.computed(() => props.persistentPlaceholder || isFocused.value || props.active);
  26292. function onFocus() {
  26293. if (textareaRef.value !== document.activeElement) {
  26294. textareaRef.value?.focus();
  26295. }
  26296. if (!isFocused.value) focus();
  26297. }
  26298. function onControlClick(e) {
  26299. onFocus();
  26300. emit('click:control', e);
  26301. }
  26302. function onControlMousedown(e) {
  26303. emit('mousedown:control', e);
  26304. }
  26305. function onClear(e) {
  26306. e.stopPropagation();
  26307. onFocus();
  26308. vue.nextTick(() => {
  26309. model.value = '';
  26310. callEvent(props['onClick:clear'], e);
  26311. });
  26312. }
  26313. function onInput(e) {
  26314. const el = e.target;
  26315. model.value = el.value;
  26316. if (props.modelModifiers?.trim) {
  26317. const caretPosition = [el.selectionStart, el.selectionEnd];
  26318. vue.nextTick(() => {
  26319. el.selectionStart = caretPosition[0];
  26320. el.selectionEnd = caretPosition[1];
  26321. });
  26322. }
  26323. }
  26324. const sizerRef = vue.ref();
  26325. const rows = vue.ref(+props.rows);
  26326. const isPlainOrUnderlined = vue.computed(() => ['plain', 'underlined'].includes(props.variant));
  26327. vue.watchEffect(() => {
  26328. if (!props.autoGrow) rows.value = +props.rows;
  26329. });
  26330. function calculateInputHeight() {
  26331. if (!props.autoGrow) return;
  26332. vue.nextTick(() => {
  26333. if (!sizerRef.value || !vFieldRef.value) return;
  26334. const style = getComputedStyle(sizerRef.value);
  26335. const fieldStyle = getComputedStyle(vFieldRef.value.$el);
  26336. const padding = parseFloat(style.getPropertyValue('--v-field-padding-top')) + parseFloat(style.getPropertyValue('--v-input-padding-top')) + parseFloat(style.getPropertyValue('--v-field-padding-bottom'));
  26337. const height = sizerRef.value.scrollHeight;
  26338. const lineHeight = parseFloat(style.lineHeight);
  26339. const minHeight = Math.max(parseFloat(props.rows) * lineHeight + padding, parseFloat(fieldStyle.getPropertyValue('--v-input-control-height')));
  26340. const maxHeight = parseFloat(props.maxRows) * lineHeight + padding || Infinity;
  26341. const newHeight = clamp(height ?? 0, minHeight, maxHeight);
  26342. rows.value = Math.floor((newHeight - padding) / lineHeight);
  26343. controlHeight.value = convertToUnit(newHeight);
  26344. });
  26345. }
  26346. vue.onMounted(calculateInputHeight);
  26347. vue.watch(model, calculateInputHeight);
  26348. vue.watch(() => props.rows, calculateInputHeight);
  26349. vue.watch(() => props.maxRows, calculateInputHeight);
  26350. vue.watch(() => props.density, calculateInputHeight);
  26351. let observer;
  26352. vue.watch(sizerRef, val => {
  26353. if (val) {
  26354. observer = new ResizeObserver(calculateInputHeight);
  26355. observer.observe(sizerRef.value);
  26356. } else {
  26357. observer?.disconnect();
  26358. }
  26359. });
  26360. vue.onBeforeUnmount(() => {
  26361. observer?.disconnect();
  26362. });
  26363. useRender(() => {
  26364. const hasCounter = !!(slots.counter || props.counter || props.counterValue);
  26365. const hasDetails = !!(hasCounter || slots.details);
  26366. const [rootAttrs, inputAttrs] = filterInputAttrs(attrs);
  26367. const {
  26368. modelValue: _,
  26369. ...inputProps
  26370. } = VInput.filterProps(props);
  26371. const fieldProps = filterFieldProps(props);
  26372. return vue.createVNode(VInput, vue.mergeProps({
  26373. "ref": vInputRef,
  26374. "modelValue": model.value,
  26375. "onUpdate:modelValue": $event => model.value = $event,
  26376. "class": ['v-textarea v-text-field', {
  26377. 'v-textarea--prefixed': props.prefix,
  26378. 'v-textarea--suffixed': props.suffix,
  26379. 'v-text-field--prefixed': props.prefix,
  26380. 'v-text-field--suffixed': props.suffix,
  26381. 'v-textarea--auto-grow': props.autoGrow,
  26382. 'v-textarea--no-resize': props.noResize || props.autoGrow,
  26383. 'v-input--plain-underlined': isPlainOrUnderlined.value
  26384. }, props.class],
  26385. "style": props.style
  26386. }, rootAttrs, inputProps, {
  26387. "centerAffix": rows.value === 1 && !isPlainOrUnderlined.value,
  26388. "focused": isFocused.value
  26389. }), {
  26390. ...slots,
  26391. default: _ref2 => {
  26392. let {
  26393. id,
  26394. isDisabled,
  26395. isDirty,
  26396. isReadonly,
  26397. isValid
  26398. } = _ref2;
  26399. return vue.createVNode(VField, vue.mergeProps({
  26400. "ref": vFieldRef,
  26401. "style": {
  26402. '--v-textarea-control-height': controlHeight.value
  26403. },
  26404. "onClick": onControlClick,
  26405. "onMousedown": onControlMousedown,
  26406. "onClick:clear": onClear,
  26407. "onClick:prependInner": props['onClick:prependInner'],
  26408. "onClick:appendInner": props['onClick:appendInner']
  26409. }, fieldProps, {
  26410. "id": id.value,
  26411. "active": isActive.value || isDirty.value,
  26412. "centerAffix": rows.value === 1 && !isPlainOrUnderlined.value,
  26413. "dirty": isDirty.value || props.dirty,
  26414. "disabled": isDisabled.value,
  26415. "focused": isFocused.value,
  26416. "error": isValid.value === false
  26417. }), {
  26418. ...slots,
  26419. default: _ref3 => {
  26420. let {
  26421. props: {
  26422. class: fieldClass,
  26423. ...slotProps
  26424. }
  26425. } = _ref3;
  26426. return vue.createVNode(vue.Fragment, null, [props.prefix && vue.createVNode("span", {
  26427. "class": "v-text-field__prefix"
  26428. }, [props.prefix]), vue.withDirectives(vue.createVNode("textarea", vue.mergeProps({
  26429. "ref": textareaRef,
  26430. "class": fieldClass,
  26431. "value": model.value,
  26432. "onInput": onInput,
  26433. "autofocus": props.autofocus,
  26434. "readonly": isReadonly.value,
  26435. "disabled": isDisabled.value,
  26436. "placeholder": props.placeholder,
  26437. "rows": props.rows,
  26438. "name": props.name,
  26439. "onFocus": onFocus,
  26440. "onBlur": blur
  26441. }, slotProps, inputAttrs), null), [[vue.resolveDirective("intersect"), {
  26442. handler: onIntersect
  26443. }, null, {
  26444. once: true
  26445. }]]), props.autoGrow && vue.withDirectives(vue.createVNode("textarea", {
  26446. "class": [fieldClass, 'v-textarea__sizer'],
  26447. "id": `${slotProps.id}-sizer`,
  26448. "onUpdate:modelValue": $event => model.value = $event,
  26449. "ref": sizerRef,
  26450. "readonly": true,
  26451. "aria-hidden": "true"
  26452. }, null), [[vue.vModelText, model.value]]), props.suffix && vue.createVNode("span", {
  26453. "class": "v-text-field__suffix"
  26454. }, [props.suffix])]);
  26455. }
  26456. });
  26457. },
  26458. 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, {
  26459. "active": props.persistentCounter || isFocused.value,
  26460. "value": counterValue.value,
  26461. "max": max.value,
  26462. "disabled": props.disabled
  26463. }, slots.counter)])]) : undefined
  26464. });
  26465. });
  26466. return forwardRefs({}, vInputRef, vFieldRef, textareaRef);
  26467. }
  26468. });
  26469. const makeVThemeProviderProps = propsFactory({
  26470. withBackground: Boolean,
  26471. ...makeComponentProps(),
  26472. ...makeThemeProps(),
  26473. ...makeTagProps()
  26474. }, 'VThemeProvider');
  26475. const VThemeProvider = genericComponent()({
  26476. name: 'VThemeProvider',
  26477. props: makeVThemeProviderProps(),
  26478. setup(props, _ref) {
  26479. let {
  26480. slots
  26481. } = _ref;
  26482. const {
  26483. themeClasses
  26484. } = provideTheme(props);
  26485. return () => {
  26486. if (!props.withBackground) return slots.default?.();
  26487. return vue.createVNode(props.tag, {
  26488. "class": ['v-theme-provider', themeClasses.value, props.class],
  26489. "style": props.style
  26490. }, {
  26491. default: () => [slots.default?.()]
  26492. });
  26493. };
  26494. }
  26495. });
  26496. const makeVTimelineDividerProps = propsFactory({
  26497. dotColor: String,
  26498. fillDot: Boolean,
  26499. hideDot: Boolean,
  26500. icon: IconValue,
  26501. iconColor: String,
  26502. lineColor: String,
  26503. ...makeComponentProps(),
  26504. ...makeRoundedProps(),
  26505. ...makeSizeProps(),
  26506. ...makeElevationProps()
  26507. }, 'VTimelineDivider');
  26508. const VTimelineDivider = genericComponent()({
  26509. name: 'VTimelineDivider',
  26510. props: makeVTimelineDividerProps(),
  26511. setup(props, _ref) {
  26512. let {
  26513. slots
  26514. } = _ref;
  26515. const {
  26516. sizeClasses,
  26517. sizeStyles
  26518. } = useSize(props, 'v-timeline-divider__dot');
  26519. const {
  26520. backgroundColorStyles,
  26521. backgroundColorClasses
  26522. } = useBackgroundColor(vue.toRef(props, 'dotColor'));
  26523. const {
  26524. roundedClasses
  26525. } = useRounded(props, 'v-timeline-divider__dot');
  26526. const {
  26527. elevationClasses
  26528. } = useElevation(props);
  26529. const {
  26530. backgroundColorClasses: lineColorClasses,
  26531. backgroundColorStyles: lineColorStyles
  26532. } = useBackgroundColor(vue.toRef(props, 'lineColor'));
  26533. useRender(() => vue.createVNode("div", {
  26534. "class": ['v-timeline-divider', {
  26535. 'v-timeline-divider--fill-dot': props.fillDot
  26536. }, props.class],
  26537. "style": props.style
  26538. }, [vue.createVNode("div", {
  26539. "class": ['v-timeline-divider__before', lineColorClasses.value],
  26540. "style": lineColorStyles.value
  26541. }, null), !props.hideDot && vue.createVNode("div", {
  26542. "key": "dot",
  26543. "class": ['v-timeline-divider__dot', elevationClasses.value, roundedClasses.value, sizeClasses.value],
  26544. "style": sizeStyles.value
  26545. }, [vue.createVNode("div", {
  26546. "class": ['v-timeline-divider__inner-dot', backgroundColorClasses.value, roundedClasses.value],
  26547. "style": backgroundColorStyles.value
  26548. }, [!slots.default ? vue.createVNode(VIcon, {
  26549. "key": "icon",
  26550. "color": props.iconColor,
  26551. "icon": props.icon,
  26552. "size": props.size
  26553. }, null) : vue.createVNode(VDefaultsProvider, {
  26554. "key": "icon-defaults",
  26555. "disabled": !props.icon,
  26556. "defaults": {
  26557. VIcon: {
  26558. color: props.iconColor,
  26559. icon: props.icon,
  26560. size: props.size
  26561. }
  26562. }
  26563. }, slots.default)])]), vue.createVNode("div", {
  26564. "class": ['v-timeline-divider__after', lineColorClasses.value],
  26565. "style": lineColorStyles.value
  26566. }, null)]));
  26567. return {};
  26568. }
  26569. });
  26570. // Types
  26571. // Types
  26572. const makeVTimelineItemProps = propsFactory({
  26573. density: String,
  26574. dotColor: String,
  26575. fillDot: Boolean,
  26576. hideDot: Boolean,
  26577. hideOpposite: {
  26578. type: Boolean,
  26579. default: undefined
  26580. },
  26581. icon: IconValue,
  26582. iconColor: String,
  26583. lineInset: [Number, String],
  26584. ...makeComponentProps(),
  26585. ...makeDimensionProps(),
  26586. ...makeElevationProps(),
  26587. ...makeRoundedProps(),
  26588. ...makeSizeProps(),
  26589. ...makeTagProps()
  26590. }, 'VTimelineItem');
  26591. const VTimelineItem = genericComponent()({
  26592. name: 'VTimelineItem',
  26593. props: makeVTimelineItemProps(),
  26594. setup(props, _ref) {
  26595. let {
  26596. slots
  26597. } = _ref;
  26598. const {
  26599. dimensionStyles
  26600. } = useDimension(props);
  26601. const dotSize = vue.shallowRef(0);
  26602. const dotRef = vue.ref();
  26603. vue.watch(dotRef, newValue => {
  26604. if (!newValue) return;
  26605. dotSize.value = newValue.$el.querySelector('.v-timeline-divider__dot')?.getBoundingClientRect().width ?? 0;
  26606. }, {
  26607. flush: 'post'
  26608. });
  26609. useRender(() => vue.createVNode("div", {
  26610. "class": ['v-timeline-item', {
  26611. 'v-timeline-item--fill-dot': props.fillDot
  26612. }, props.class],
  26613. "style": [{
  26614. '--v-timeline-dot-size': convertToUnit(dotSize.value),
  26615. '--v-timeline-line-inset': props.lineInset ? `calc(var(--v-timeline-dot-size) / 2 + ${convertToUnit(props.lineInset)})` : convertToUnit(0)
  26616. }, props.style]
  26617. }, [vue.createVNode("div", {
  26618. "class": "v-timeline-item__body",
  26619. "style": dimensionStyles.value
  26620. }, [slots.default?.()]), vue.createVNode(VTimelineDivider, {
  26621. "ref": dotRef,
  26622. "hideDot": props.hideDot,
  26623. "icon": props.icon,
  26624. "iconColor": props.iconColor,
  26625. "size": props.size,
  26626. "elevation": props.elevation,
  26627. "dotColor": props.dotColor,
  26628. "fillDot": props.fillDot,
  26629. "rounded": props.rounded
  26630. }, {
  26631. default: slots.icon
  26632. }), props.density !== 'compact' && vue.createVNode("div", {
  26633. "class": "v-timeline-item__opposite"
  26634. }, [!props.hideOpposite && slots.opposite?.()])]));
  26635. return {};
  26636. }
  26637. });
  26638. const makeVTimelineProps = propsFactory({
  26639. align: {
  26640. type: String,
  26641. default: 'center',
  26642. validator: v => ['center', 'start'].includes(v)
  26643. },
  26644. direction: {
  26645. type: String,
  26646. default: 'vertical',
  26647. validator: v => ['vertical', 'horizontal'].includes(v)
  26648. },
  26649. justify: {
  26650. type: String,
  26651. default: 'auto',
  26652. validator: v => ['auto', 'center'].includes(v)
  26653. },
  26654. side: {
  26655. type: String,
  26656. validator: v => v == null || ['start', 'end'].includes(v)
  26657. },
  26658. lineThickness: {
  26659. type: [String, Number],
  26660. default: 2
  26661. },
  26662. lineColor: String,
  26663. truncateLine: {
  26664. type: String,
  26665. validator: v => ['start', 'end', 'both'].includes(v)
  26666. },
  26667. ...only(makeVTimelineItemProps({
  26668. lineInset: 0
  26669. }), ['dotColor', 'fillDot', 'hideOpposite', 'iconColor', 'lineInset', 'size']),
  26670. ...makeComponentProps(),
  26671. ...makeDensityProps(),
  26672. ...makeTagProps(),
  26673. ...makeThemeProps()
  26674. }, 'VTimeline');
  26675. const VTimeline = genericComponent()({
  26676. name: 'VTimeline',
  26677. props: makeVTimelineProps(),
  26678. setup(props, _ref) {
  26679. let {
  26680. slots
  26681. } = _ref;
  26682. const {
  26683. themeClasses
  26684. } = provideTheme(props);
  26685. const {
  26686. densityClasses
  26687. } = useDensity(props);
  26688. const {
  26689. rtlClasses
  26690. } = useRtl();
  26691. provideDefaults({
  26692. VTimelineDivider: {
  26693. lineColor: vue.toRef(props, 'lineColor')
  26694. },
  26695. VTimelineItem: {
  26696. density: vue.toRef(props, 'density'),
  26697. dotColor: vue.toRef(props, 'dotColor'),
  26698. fillDot: vue.toRef(props, 'fillDot'),
  26699. hideOpposite: vue.toRef(props, 'hideOpposite'),
  26700. iconColor: vue.toRef(props, 'iconColor'),
  26701. lineColor: vue.toRef(props, 'lineColor'),
  26702. lineInset: vue.toRef(props, 'lineInset'),
  26703. size: vue.toRef(props, 'size')
  26704. }
  26705. });
  26706. const sideClasses = vue.computed(() => {
  26707. const side = props.side ? props.side : props.density !== 'default' ? 'end' : null;
  26708. return side && `v-timeline--side-${side}`;
  26709. });
  26710. const truncateClasses = vue.computed(() => {
  26711. const classes = ['v-timeline--truncate-line-start', 'v-timeline--truncate-line-end'];
  26712. switch (props.truncateLine) {
  26713. case 'both':
  26714. return classes;
  26715. case 'start':
  26716. return classes[0];
  26717. case 'end':
  26718. return classes[1];
  26719. default:
  26720. return null;
  26721. }
  26722. });
  26723. useRender(() => vue.createVNode(props.tag, {
  26724. "class": ['v-timeline', `v-timeline--${props.direction}`, `v-timeline--align-${props.align}`, `v-timeline--justify-${props.justify}`, truncateClasses.value, {
  26725. 'v-timeline--inset-line': !!props.lineInset
  26726. }, themeClasses.value, densityClasses.value, sideClasses.value, rtlClasses.value, props.class],
  26727. "style": [{
  26728. '--v-timeline-line-thickness': convertToUnit(props.lineThickness)
  26729. }, props.style]
  26730. }, slots));
  26731. return {};
  26732. }
  26733. });
  26734. const makeVToolbarItemsProps = propsFactory({
  26735. ...makeComponentProps(),
  26736. ...makeVariantProps({
  26737. variant: 'text'
  26738. })
  26739. }, 'VToolbarItems');
  26740. const VToolbarItems = genericComponent()({
  26741. name: 'VToolbarItems',
  26742. props: makeVToolbarItemsProps(),
  26743. setup(props, _ref) {
  26744. let {
  26745. slots
  26746. } = _ref;
  26747. provideDefaults({
  26748. VBtn: {
  26749. color: vue.toRef(props, 'color'),
  26750. height: 'inherit',
  26751. variant: vue.toRef(props, 'variant')
  26752. }
  26753. });
  26754. useRender(() => vue.createVNode("div", {
  26755. "class": ['v-toolbar-items', props.class],
  26756. "style": props.style
  26757. }, [slots.default?.()]));
  26758. return {};
  26759. }
  26760. });
  26761. // Types
  26762. const makeVTooltipProps = propsFactory({
  26763. id: String,
  26764. text: String,
  26765. ...omit(makeVOverlayProps({
  26766. closeOnBack: false,
  26767. location: 'end',
  26768. locationStrategy: 'connected',
  26769. eager: true,
  26770. minWidth: 0,
  26771. offset: 10,
  26772. openOnClick: false,
  26773. openOnHover: true,
  26774. origin: 'auto',
  26775. scrim: false,
  26776. scrollStrategy: 'reposition',
  26777. transition: false
  26778. }), ['absolute', 'persistent'])
  26779. }, 'VTooltip');
  26780. const VTooltip = genericComponent()({
  26781. name: 'VTooltip',
  26782. props: makeVTooltipProps(),
  26783. emits: {
  26784. 'update:modelValue': value => true
  26785. },
  26786. setup(props, _ref) {
  26787. let {
  26788. slots
  26789. } = _ref;
  26790. const isActive = useProxiedModel(props, 'modelValue');
  26791. const {
  26792. scopeId
  26793. } = useScopeId();
  26794. const uid = getUid();
  26795. const id = vue.computed(() => props.id || `v-tooltip-${uid}`);
  26796. const overlay = vue.ref();
  26797. const location = vue.computed(() => {
  26798. return props.location.split(' ').length > 1 ? props.location : props.location + ' center';
  26799. });
  26800. const origin = vue.computed(() => {
  26801. return props.origin === 'auto' || props.origin === 'overlap' || props.origin.split(' ').length > 1 || props.location.split(' ').length > 1 ? props.origin : props.origin + ' center';
  26802. });
  26803. const transition = vue.computed(() => {
  26804. if (props.transition) return props.transition;
  26805. return isActive.value ? 'scale-transition' : 'fade-transition';
  26806. });
  26807. const activatorProps = vue.computed(() => vue.mergeProps({
  26808. 'aria-describedby': id.value
  26809. }, props.activatorProps));
  26810. useRender(() => {
  26811. const overlayProps = VOverlay.filterProps(props);
  26812. return vue.createVNode(VOverlay, vue.mergeProps({
  26813. "ref": overlay,
  26814. "class": ['v-tooltip', props.class],
  26815. "style": props.style,
  26816. "id": id.value
  26817. }, overlayProps, {
  26818. "modelValue": isActive.value,
  26819. "onUpdate:modelValue": $event => isActive.value = $event,
  26820. "transition": transition.value,
  26821. "absolute": true,
  26822. "location": location.value,
  26823. "origin": origin.value,
  26824. "persistent": true,
  26825. "role": "tooltip",
  26826. "activatorProps": activatorProps.value,
  26827. "_disableGlobalStack": true
  26828. }, scopeId), {
  26829. activator: slots.activator,
  26830. default: function () {
  26831. for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) {
  26832. args[_key] = arguments[_key];
  26833. }
  26834. return slots.default?.(...args) ?? props.text;
  26835. }
  26836. });
  26837. });
  26838. return forwardRefs({}, overlay);
  26839. }
  26840. });
  26841. // Composables
  26842. // Types
  26843. const VValidation = genericComponent()({
  26844. name: 'VValidation',
  26845. props: makeValidationProps(),
  26846. emits: {
  26847. 'update:modelValue': value => true
  26848. },
  26849. setup(props, _ref) {
  26850. let {
  26851. slots
  26852. } = _ref;
  26853. const validation = useValidation(props, 'validation');
  26854. return () => slots.default?.(validation);
  26855. }
  26856. });
  26857. const makeVCalendarIntervalEventProps = propsFactory({
  26858. allDay: Boolean,
  26859. interval: Object,
  26860. intervalDivisions: {
  26861. type: Number,
  26862. required: true
  26863. },
  26864. intervalDuration: {
  26865. type: Number,
  26866. required: true
  26867. },
  26868. intervalHeight: {
  26869. type: Number,
  26870. required: true
  26871. },
  26872. event: Object
  26873. }, 'VCalendarIntervalEvent');
  26874. const VCalendarIntervalEvent = genericComponent()({
  26875. name: 'VCalendarIntervalEvent',
  26876. props: makeVCalendarIntervalEventProps(),
  26877. setup(props) {
  26878. const adapter = useDate();
  26879. const calcHeight = () => {
  26880. if (!props.event?.first && !props.event?.last || adapter.isEqual(props.event?.start, props.interval?.start)) {
  26881. return {
  26882. height: '100%',
  26883. margin: convertToUnit(0)
  26884. };
  26885. } else {
  26886. const {
  26887. height,
  26888. margin
  26889. } = Array.from({
  26890. length: props.intervalDivisions
  26891. }, x => x * (props.intervalDuration / props.intervalDivisions)).reduce((total, div, index) => {
  26892. if (adapter.isBefore(adapter.addMinutes(props.interval?.start, div), props.event?.start)) {
  26893. return {
  26894. height: convertToUnit(props.intervalHeight / props.intervalDivisions * index),
  26895. margin: convertToUnit(props.intervalHeight / props.intervalDivisions * index)
  26896. };
  26897. }
  26898. return {
  26899. height: total.height,
  26900. margin: total.margin
  26901. };
  26902. }, {
  26903. height: '',
  26904. margin: ''
  26905. });
  26906. return {
  26907. height,
  26908. margin
  26909. };
  26910. }
  26911. };
  26912. useRender(() => {
  26913. return vue.createVNode(VSheet, {
  26914. "height": calcHeight().height,
  26915. "density": "comfortable",
  26916. "style": `margin-top: ${calcHeight().margin}`,
  26917. "class": "v-calendar-internal-event",
  26918. "color": props.event?.color ?? undefined,
  26919. "rounded": props.event?.first && props.event?.last ? true : props.event?.first ? 't' : props.event?.last ? 'b' : false
  26920. }, {
  26921. default: () => [props.event?.first ? props.event?.title : '']
  26922. });
  26923. });
  26924. return {};
  26925. }
  26926. });
  26927. const makeVCalendarIntervalProps = propsFactory({
  26928. day: {
  26929. type: Object,
  26930. default: () => ({})
  26931. },
  26932. dayIndex: Number,
  26933. events: Array,
  26934. intervalDivisions: {
  26935. type: Number,
  26936. default: 2
  26937. },
  26938. intervalDuration: {
  26939. type: Number,
  26940. default: 60
  26941. },
  26942. intervalHeight: {
  26943. type: Number,
  26944. default: 48
  26945. },
  26946. intervalFormat: {
  26947. type: [String, Function],
  26948. default: 'fullTime12h'
  26949. },
  26950. intervalStart: {
  26951. type: Number,
  26952. default: 0
  26953. }
  26954. }, 'VCalendarInterval');
  26955. const VCalendarInterval = genericComponent()({
  26956. name: 'VCalendarInterval',
  26957. props: {
  26958. index: {
  26959. type: Number,
  26960. required: true
  26961. },
  26962. ...makeVCalendarIntervalProps()
  26963. },
  26964. setup(props, _ref) {
  26965. const adapter = useDate();
  26966. const interval = vue.computed(() => {
  26967. const start = adapter.addMinutes(adapter.startOfDay(props.day.date), props.intervalDuration * (props.index + props.intervalStart));
  26968. const end = adapter.addMinutes(adapter.startOfDay(props.day.date), props.intervalDuration * (props.index + props.intervalStart + 1) - 1);
  26969. return {
  26970. ...props.day,
  26971. label: adapter.format(start, 'fullTime24h'),
  26972. start,
  26973. end,
  26974. events: props.events ? props.events.filter(e => !e.allDay && (adapter.isEqual(start, e.start) || adapter.isWithinRange(e.start, [start, end]) || adapter.isWithinRange(start, [e.start, e.end]) || adapter.isEqual(end, e.end))).map(e => {
  26975. return {
  26976. ...e,
  26977. first: adapter.isEqual(start, e.start) || adapter.isWithinRange(e.start, [start, end]),
  26978. last: adapter.isEqual(end, e.end) || adapter.isWithinRange(e.end, [start, end])
  26979. };
  26980. }) : []
  26981. };
  26982. });
  26983. useRender(() => {
  26984. return props.dayIndex === 0 ? vue.createVNode("div", {
  26985. "class": "v-calendar-day__row-with-label",
  26986. "style": `height: ${convertToUnit(props.intervalHeight)}`
  26987. }, [vue.createVNode("div", {
  26988. "class": "v-calendar-day__row-label"
  26989. }, [vue.createVNode("slot", {
  26990. "name": "intervalFormat",
  26991. "interval": interval.value
  26992. }, [props.index ? props.intervalFormat ? typeof props.intervalFormat === 'string' ? adapter.format(interval.value.start, 'hours12h') : props.intervalFormat(interval.value) : interval.value.label : ''])]), vue.createVNode("div", {
  26993. "class": "v-calendar-day__row-hairline"
  26994. }, null), vue.createVNode("div", {
  26995. "class": ['v-calendar-day__row-content', interval.value.events.some(e => !e.last) ? 'v-calendar-day__row-content-through' : '']
  26996. }, [vue.createVNode("slot", {
  26997. "name": "intervalBody",
  26998. "interval": interval.value
  26999. }, [interval.value.events?.map(event => vue.createVNode(VCalendarIntervalEvent, {
  27000. "event": event,
  27001. "interval": interval.value,
  27002. "intervalDivisions": props.intervalDivisions,
  27003. "intervalDuration": props.intervalDuration,
  27004. "intervalHeight": props.intervalHeight
  27005. }, null))])])]) : vue.createVNode("div", {
  27006. "class": "v-calendar-day__row-without-label",
  27007. "style": `height: ${convertToUnit(props.intervalHeight)}`
  27008. }, [vue.createVNode("div", {
  27009. "class": ['v-calendar-day__row-content', interval.value.events.some(e => !e.last) ? 'v-calendar-day__row-content-through' : '']
  27010. }, [vue.createVNode("slot", {
  27011. "name": "intervalBody",
  27012. "interval": interval.value
  27013. }, [interval.value.events?.filter(event => !event.allDay).map(event => vue.createVNode(VCalendarIntervalEvent, {
  27014. "event": event,
  27015. "interval": interval.value,
  27016. "intervalDivisions": props.intervalDivisions,
  27017. "intervalDuration": props.intervalDuration,
  27018. "intervalHeight": props.intervalHeight
  27019. }, null))])])]);
  27020. });
  27021. return {
  27022. interval
  27023. };
  27024. }
  27025. });
  27026. const makeVCalendarDayProps = propsFactory({
  27027. hideDayHeader: Boolean,
  27028. intervals: {
  27029. type: Number,
  27030. default: 24
  27031. },
  27032. ...makeVCalendarIntervalProps()
  27033. }, 'VCalendarDay');
  27034. const VCalendarDay = genericComponent()({
  27035. name: 'VCalendarDay',
  27036. props: makeVCalendarDayProps(),
  27037. setup(props) {
  27038. const adapter = useDate();
  27039. const intervals = vue.computed(() => [...Array.from({
  27040. length: props.intervals
  27041. }, (v, i) => i).filter((int, index) => props.intervalDuration * (index + props.intervalStart) < 1440)]);
  27042. useRender(() => {
  27043. const calendarIntervalProps = VCalendarInterval.filterProps(props);
  27044. return vue.createVNode("div", {
  27045. "class": "v-calendar-day__container"
  27046. }, [!props.hideDayHeader && vue.createVNode("div", {
  27047. "key": "calender-week-name",
  27048. "class": "v-calendar-weekly__head-weekday"
  27049. }, [adapter.format(props.day.date, 'weekdayShort'), vue.createVNode("div", null, [vue.createVNode(VBtn, {
  27050. "icon": true,
  27051. "text": adapter.format(props.day.date, 'dayOfMonth'),
  27052. "variant": "text"
  27053. }, null)])]), intervals.value.map((_, index) => vue.createVNode(VCalendarInterval, vue.mergeProps({
  27054. "index": index
  27055. }, calendarIntervalProps), null))]);
  27056. });
  27057. return {
  27058. intervals
  27059. };
  27060. }
  27061. });
  27062. // Types
  27063. const makeVCalendarHeaderProps = propsFactory({
  27064. nextIcon: {
  27065. type: String,
  27066. default: '$next'
  27067. },
  27068. prevIcon: {
  27069. type: String,
  27070. default: '$prev'
  27071. },
  27072. title: String,
  27073. text: {
  27074. type: String,
  27075. default: '$vuetify.calendar.today'
  27076. },
  27077. viewMode: {
  27078. type: String,
  27079. default: 'month'
  27080. }
  27081. }, 'VCalendarHeader');
  27082. const VCalendarHeader = genericComponent()({
  27083. name: 'VCalendarHeader',
  27084. props: makeVCalendarHeaderProps(),
  27085. emits: {
  27086. 'click:next': () => true,
  27087. 'click:prev': () => true,
  27088. 'click:toToday': () => true
  27089. },
  27090. setup(props, _ref) {
  27091. let {
  27092. emit
  27093. } = _ref;
  27094. const {
  27095. t
  27096. } = useLocale();
  27097. function prev() {
  27098. emit('click:prev');
  27099. }
  27100. function next() {
  27101. emit('click:next');
  27102. }
  27103. function toToday() {
  27104. emit('click:toToday');
  27105. }
  27106. useRender(() => vue.createVNode("div", {
  27107. "class": "v-calendar-header"
  27108. }, [props.text && vue.createVNode(VBtn, {
  27109. "key": "today",
  27110. "class": "v-calendar-header__today",
  27111. "text": t(props.text),
  27112. "variant": "outlined",
  27113. "onClick": toToday
  27114. }, null), vue.createVNode(VBtn, {
  27115. "density": "comfortable",
  27116. "icon": props.prevIcon,
  27117. "variant": "text",
  27118. "onClick": prev
  27119. }, null), vue.createVNode(VBtn, {
  27120. "density": "comfortable",
  27121. "icon": props.nextIcon,
  27122. "variant": "text",
  27123. "onClick": next
  27124. }, null), vue.createVNode("div", {
  27125. "class": "v-calendar-header__title"
  27126. }, [props.title])]));
  27127. return {};
  27128. }
  27129. });
  27130. const makeVCalendarEventProps = propsFactory({
  27131. allDay: Boolean,
  27132. day: Object,
  27133. event: Object
  27134. }, 'VCalendarEvent');
  27135. const VCalendarEvent = genericComponent()({
  27136. name: 'VCalendarEvent',
  27137. props: makeVCalendarEventProps(),
  27138. setup(props) {
  27139. useRender(() => vue.createVNode(VChip, {
  27140. "color": props.allDay ? 'primary' : undefined,
  27141. "density": "comfortable",
  27142. "label": props.allDay,
  27143. "width": "100%"
  27144. }, {
  27145. default: () => [vue.createVNode(VBadge, {
  27146. "inline": true,
  27147. "dot": true,
  27148. "color": props.event?.color
  27149. }, null), props.event?.title]
  27150. }));
  27151. return {};
  27152. }
  27153. });
  27154. const makeVCalendarMonthDayProps = propsFactory({
  27155. active: Boolean,
  27156. color: String,
  27157. day: Object,
  27158. disabled: Boolean,
  27159. events: Array,
  27160. title: [Number, String]
  27161. }, 'VCalendarMonthDay');
  27162. const VCalendarMonthDay = genericComponent()({
  27163. name: 'VCalendarMonthDay',
  27164. props: makeVCalendarMonthDayProps(),
  27165. setup(props, _ref) {
  27166. let {
  27167. emit,
  27168. slots
  27169. } = _ref;
  27170. useRender(() => {
  27171. const hasTitle = !!(props.title || slots.title?.({
  27172. title: props.title
  27173. }));
  27174. return vue.createVNode("div", {
  27175. "class": ['v-calendar-month__day']
  27176. }, [!props.day?.isHidden && hasTitle && vue.createVNode("div", {
  27177. "key": "title",
  27178. "class": "v-calendar-weekly__day-label"
  27179. }, [slots.title?.({
  27180. title: props.title
  27181. }) ?? vue.createVNode(VBtn, {
  27182. "class": props.day?.isToday ? 'v-calendar-weekly__day-label__today' : undefined,
  27183. "color": props.color,
  27184. "disabled": props.disabled,
  27185. "icon": true,
  27186. "size": "x-small",
  27187. "variant": props.day?.isToday ? undefined : 'flat'
  27188. }, {
  27189. default: () => [props.title]
  27190. })]), !props.day?.isHidden && vue.createVNode("div", {
  27191. "key": "content",
  27192. "class": "v-calendar-weekly__day-content"
  27193. }, [slots.content?.() ?? vue.createVNode("div", null, [vue.createVNode("div", {
  27194. "class": "v-calendar-weekly__day-alldayevents-container"
  27195. }, [props.events?.filter(event => event.allDay).map(event => slots.event ? slots.event({
  27196. day: props.day,
  27197. allDay: true,
  27198. event
  27199. }) : vue.createVNode(VCalendarEvent, {
  27200. "day": props.day,
  27201. "event": event,
  27202. "allDay": true
  27203. }, null))]), vue.createVNode("div", {
  27204. "class": "v-calendar-weekly__day-events-container"
  27205. }, [props.events?.filter(event => !event.allDay).map(event => slots.event ? slots.event({
  27206. day: props.day,
  27207. event,
  27208. allDay: false
  27209. }) : vue.createVNode(VCalendarEvent, {
  27210. "day": props.day,
  27211. "event": event
  27212. }, null))])])]), !props.day?.isHidden && slots.default?.()]);
  27213. });
  27214. return {};
  27215. }
  27216. });
  27217. const makeVCalendarProps = propsFactory({
  27218. hideHeader: Boolean,
  27219. hideWeekNumber: Boolean,
  27220. ...makeCalendarProps(),
  27221. ...makeVCalendarDayProps(),
  27222. ...makeVCalendarHeaderProps()
  27223. }, 'VCalender');
  27224. const VCalendar = genericComponent()({
  27225. name: 'VCalendar',
  27226. props: makeVCalendarProps(),
  27227. emits: {
  27228. next: null,
  27229. prev: null,
  27230. 'update:modelValue': null
  27231. },
  27232. setup(props, _ref) {
  27233. let {
  27234. emit,
  27235. slots
  27236. } = _ref;
  27237. const adapter = useDate();
  27238. const {
  27239. daysInMonth,
  27240. daysInWeek,
  27241. genDays,
  27242. model,
  27243. displayValue,
  27244. weekNumbers,
  27245. weekDays
  27246. } = useCalendar(props);
  27247. const dayNames = adapter.getWeekdays();
  27248. function onClickNext() {
  27249. if (props.viewMode === 'month') {
  27250. model.value = [adapter.addMonths(displayValue.value, 1)];
  27251. }
  27252. if (props.viewMode === 'week') {
  27253. model.value = [adapter.addDays(displayValue.value, 7)];
  27254. }
  27255. if (props.viewMode === 'day') {
  27256. model.value = [adapter.addDays(displayValue.value, 1)];
  27257. }
  27258. }
  27259. function onClickPrev() {
  27260. if (props.viewMode === 'month') {
  27261. model.value = [adapter.addMonths(displayValue.value, -1)];
  27262. }
  27263. if (props.viewMode === 'week') {
  27264. model.value = [adapter.addDays(displayValue.value, -7)];
  27265. }
  27266. if (props.viewMode === 'day') {
  27267. model.value = [adapter.addDays(displayValue.value, -1)];
  27268. }
  27269. }
  27270. function onClickToday() {
  27271. model.value = [adapter.date()];
  27272. }
  27273. const title = vue.computed(() => {
  27274. return adapter.format(displayValue.value, 'monthAndYear');
  27275. });
  27276. useRender(() => {
  27277. const calendarDayProps = VCalendarDay.filterProps(props);
  27278. const calendarHeaderProps = VCalendarHeader.filterProps(props);
  27279. return vue.createVNode("div", {
  27280. "class": ['v-calendar', {
  27281. 'v-calendar-monthly': props.viewMode === 'month',
  27282. 'v-calendar-weekly': props.viewMode === 'week',
  27283. 'v-calendar-day': props.viewMode === 'day'
  27284. }]
  27285. }, [vue.createVNode("div", null, [!props.hideHeader && (!slots.header ? vue.createVNode(VCalendarHeader, vue.mergeProps({
  27286. "key": "calendar-header"
  27287. }, calendarHeaderProps, {
  27288. "title": title.value,
  27289. "onClick:next": onClickNext,
  27290. "onClick:prev": onClickPrev,
  27291. "onClick:toToday": onClickToday
  27292. }), null) : slots.header({
  27293. title: title.value
  27294. }))]), vue.createVNode("div", {
  27295. "class": ['v-calendar__container', `days__${weekDays.value.length}`]
  27296. }, [props.viewMode === 'month' && !props.hideDayHeader && vue.createVNode("div", {
  27297. "class": ['v-calendar-weekly__head', `days__${weekDays.value.length}`, ...(!props.hideWeekNumber ? ['v-calendar-weekly__head-weeknumbers'] : [])],
  27298. "key": "calenderWeeklyHead"
  27299. }, [!props.hideWeekNumber ? vue.createVNode("div", {
  27300. "key": "weekNumber0",
  27301. "class": "v-calendar-weekly__head-weeknumber"
  27302. }, null) : '', weekDays.value.map(weekday => vue.createVNode("div", {
  27303. "class": `v-calendar-weekly__head-weekday${!props.hideWeekNumber ? '-with-weeknumber' : ''}`
  27304. }, [dayNames[weekday]]))]), props.viewMode === 'month' && vue.createVNode("div", {
  27305. "key": "VCalendarMonth",
  27306. "class": ['v-calendar-month__days', `days${!props.hideWeekNumber ? '-with-weeknumbers' : ''}__${weekDays.value.length}`, ...(!props.hideWeekNumber ? ['v-calendar-month__weeknumbers'] : [])]
  27307. }, [chunkArray(daysInMonth.value, weekDays.value.length).map((week, wi) => [!props.hideWeekNumber ? vue.createVNode("div", {
  27308. "class": "v-calendar-month__weeknumber"
  27309. }, [weekNumbers.value[wi]]) : '', week.map(day => vue.createVNode(VCalendarMonthDay, {
  27310. "color": adapter.isSameDay(adapter.date(), day.date) ? 'primary' : undefined,
  27311. "day": day,
  27312. "title": day ? adapter.format(day.date, 'dayOfMonth') : 'NaN',
  27313. "events": props.events?.filter(e => adapter.isSameDay(day.date, e.start) || adapter.isSameDay(day.date, e.end))
  27314. }, {
  27315. event: slots.event
  27316. }))])]), props.viewMode === 'week' && daysInWeek.value.map((day, i) => vue.createVNode(VCalendarDay, vue.mergeProps(calendarDayProps, {
  27317. "day": day,
  27318. "dayIndex": i,
  27319. "events": props.events?.filter(e => adapter.isSameDay(e.start, day.date) || adapter.isSameDay(e.end, day.date))
  27320. }), null)), props.viewMode === 'day' && vue.createVNode(VCalendarDay, vue.mergeProps(calendarDayProps, {
  27321. "day": genDays([displayValue.value], adapter.date())[0],
  27322. "dayIndex": 0,
  27323. "events": props.events?.filter(e => adapter.isSameDay(e.start, genDays([displayValue.value], adapter.date())[0].date) || adapter.isSameDay(e.end, genDays([displayValue.value], adapter.date())[0].date))
  27324. }), null)])]);
  27325. });
  27326. return {
  27327. daysInMonth,
  27328. daysInWeek,
  27329. genDays
  27330. };
  27331. }
  27332. });
  27333. // Types
  27334. const makeVDateInputProps = propsFactory({
  27335. hideActions: Boolean,
  27336. ...makeFocusProps(),
  27337. ...makeVConfirmEditProps(),
  27338. ...makeVTextFieldProps({
  27339. placeholder: 'mm/dd/yyyy',
  27340. prependIcon: '$calendar'
  27341. }),
  27342. ...omit(makeVDatePickerProps({
  27343. weeksInMonth: 'dynamic',
  27344. hideHeader: true
  27345. }), ['active'])
  27346. }, 'VDateInput');
  27347. const VDateInput = genericComponent()({
  27348. name: 'VDateInput',
  27349. props: makeVDateInputProps(),
  27350. emits: {
  27351. 'update:modelValue': val => true
  27352. },
  27353. setup(props, _ref) {
  27354. let {
  27355. slots
  27356. } = _ref;
  27357. const {
  27358. t
  27359. } = useLocale();
  27360. const adapter = useDate();
  27361. const {
  27362. isFocused,
  27363. focus,
  27364. blur
  27365. } = useFocus(props);
  27366. const model = useProxiedModel(props, 'modelValue', props.multiple ? [] : null);
  27367. const menu = vue.shallowRef(false);
  27368. const display = vue.computed(() => {
  27369. const value = wrapInArray(model.value);
  27370. if (!value.length) return null;
  27371. if (props.multiple === true) {
  27372. return t('$vuetify.datePicker.itemsSelected', value.length);
  27373. }
  27374. if (props.multiple === 'range') {
  27375. const start = value[0];
  27376. const end = value[value.length - 1];
  27377. return adapter.isValid(start) && adapter.isValid(end) ? `${adapter.format(start, 'keyboardDate')} - ${adapter.format(end, 'keyboardDate')}` : '';
  27378. }
  27379. return adapter.isValid(model.value) ? adapter.format(model.value, 'keyboardDate') : '';
  27380. });
  27381. const isInteractive = vue.computed(() => !props.disabled && !props.readonly);
  27382. function onKeydown(e) {
  27383. if (e.key !== 'Enter') return;
  27384. if (!menu.value || !isFocused.value) {
  27385. menu.value = true;
  27386. return;
  27387. }
  27388. const target = e.target;
  27389. model.value = adapter.date(target.value);
  27390. }
  27391. function onClick(e) {
  27392. e.preventDefault();
  27393. e.stopPropagation();
  27394. menu.value = true;
  27395. }
  27396. function onSave() {
  27397. menu.value = false;
  27398. }
  27399. useRender(() => {
  27400. const confirmEditProps = VConfirmEdit.filterProps(props);
  27401. const datePickerProps = VDatePicker.filterProps(omit(props, ['active']));
  27402. const textFieldProps = VTextField.filterProps(props);
  27403. return vue.createVNode(VTextField, vue.mergeProps(textFieldProps, {
  27404. "class": props.class,
  27405. "style": props.style,
  27406. "modelValue": display.value,
  27407. "onKeydown": isInteractive.value ? onKeydown : undefined,
  27408. "focused": menu.value || isFocused.value,
  27409. "onFocus": focus,
  27410. "onBlur": blur,
  27411. "onClick:control": isInteractive.value ? onClick : undefined,
  27412. "onClick:prepend": isInteractive.value ? onClick : undefined
  27413. }), {
  27414. default: () => [vue.createVNode(VMenu, {
  27415. "modelValue": menu.value,
  27416. "onUpdate:modelValue": $event => menu.value = $event,
  27417. "activator": "parent",
  27418. "min-width": "0",
  27419. "closeOnContentClick": false,
  27420. "openOnClick": false
  27421. }, {
  27422. default: () => [vue.createVNode(VConfirmEdit, vue.mergeProps(confirmEditProps, {
  27423. "modelValue": model.value,
  27424. "onUpdate:modelValue": $event => model.value = $event,
  27425. "onSave": onSave
  27426. }), {
  27427. default: _ref2 => {
  27428. let {
  27429. actions,
  27430. model: proxyModel
  27431. } = _ref2;
  27432. return vue.createVNode(VDatePicker, vue.mergeProps(datePickerProps, {
  27433. "modelValue": props.hideActions ? model.value : proxyModel.value,
  27434. "onUpdate:modelValue": val => {
  27435. if (!props.hideActions) {
  27436. proxyModel.value = val;
  27437. } else {
  27438. model.value = val;
  27439. if (!props.multiple) menu.value = false;
  27440. }
  27441. },
  27442. "onMousedown": e => e.preventDefault()
  27443. }), {
  27444. actions: !props.hideActions ? actions : undefined
  27445. });
  27446. }
  27447. })]
  27448. }), slots.default?.()]
  27449. });
  27450. });
  27451. }
  27452. });
  27453. // Types
  27454. const makeVFileUploadItemProps = propsFactory({
  27455. clearable: Boolean,
  27456. file: {
  27457. type: Object,
  27458. default: null
  27459. },
  27460. fileIcon: {
  27461. type: String,
  27462. // TODO: setup up a proper aliased icon
  27463. default: 'mdi-file-document'
  27464. },
  27465. showSize: Boolean,
  27466. ...makeVListItemProps({
  27467. border: true,
  27468. rounded: true,
  27469. lines: 'two'
  27470. })
  27471. }, 'VFileUploadItem');
  27472. const VFileUploadItem = genericComponent()({
  27473. name: 'VFileUploadItem',
  27474. props: makeVFileUploadItemProps(),
  27475. emits: {
  27476. 'click:remove': () => true,
  27477. click: e => true
  27478. },
  27479. setup(props, _ref) {
  27480. let {
  27481. emit,
  27482. slots
  27483. } = _ref;
  27484. const preview = vue.ref();
  27485. const base = vue.computed(() => typeof props.showSize !== 'boolean' ? props.showSize : undefined);
  27486. function onClickRemove() {
  27487. emit('click:remove');
  27488. }
  27489. vue.watchEffect(() => {
  27490. preview.value = props.file?.type.startsWith('image') ? URL.createObjectURL(props.file) : undefined;
  27491. });
  27492. useRender(() => {
  27493. const listItemProps = VListItem.filterProps(props);
  27494. return vue.createVNode(VListItem, vue.mergeProps(listItemProps, {
  27495. "title": props.title ?? props.file?.name,
  27496. "subtitle": props.showSize ? humanReadableFileSize(props.file?.size, base.value) : props.file?.type,
  27497. "class": "v-file-upload-item"
  27498. }), {
  27499. ...slots,
  27500. prepend: slotProps => vue.createVNode(vue.Fragment, null, [!slots.prepend ? vue.createVNode(VAvatar, {
  27501. "icon": props.fileIcon,
  27502. "image": preview.value,
  27503. "rounded": true
  27504. }, null) : vue.createVNode(VDefaultsProvider, {
  27505. "defaults": {
  27506. VAvatar: {
  27507. image: preview.value,
  27508. icon: !preview.value ? props.fileIcon : undefined,
  27509. rounded: true
  27510. }
  27511. }
  27512. }, {
  27513. default: () => [slots.prepend?.(slotProps) ?? vue.createVNode(VAvatar, null, null)]
  27514. })]),
  27515. append: slotProps => vue.createVNode(vue.Fragment, null, [props.clearable && vue.createVNode(vue.Fragment, null, [!slots.clear ? vue.createVNode(VBtn, {
  27516. "icon": "$clear",
  27517. "density": "comfortable",
  27518. "variant": "text",
  27519. "onClick": onClickRemove
  27520. }, null) : vue.createVNode(VDefaultsProvider, {
  27521. "defaults": {
  27522. VBtn: {
  27523. icon: '$clear',
  27524. density: 'comfortable',
  27525. variant: 'text'
  27526. }
  27527. }
  27528. }, {
  27529. default: () => [slots.clear?.({
  27530. ...slotProps,
  27531. props: {
  27532. onClick: onClickRemove
  27533. }
  27534. }) ?? vue.createVNode(VBtn, null, null)]
  27535. })]), slots.append?.(slotProps)])
  27536. });
  27537. });
  27538. }
  27539. });
  27540. // Types
  27541. const makeVFileUploadProps = propsFactory({
  27542. browseText: {
  27543. type: String,
  27544. default: '$vuetify.fileUpload.browse'
  27545. },
  27546. dividerText: {
  27547. type: String,
  27548. default: '$vuetify.fileUpload.divider'
  27549. },
  27550. title: {
  27551. type: String,
  27552. default: '$vuetify.fileUpload.title'
  27553. },
  27554. subtitle: String,
  27555. icon: {
  27556. type: IconValue,
  27557. default: '$upload'
  27558. },
  27559. modelValue: {
  27560. type: [Array, Object],
  27561. default: null,
  27562. validator: val => {
  27563. return wrapInArray(val).every(v => v != null && typeof v === 'object');
  27564. }
  27565. },
  27566. clearable: Boolean,
  27567. disabled: Boolean,
  27568. hideBrowse: Boolean,
  27569. multiple: Boolean,
  27570. scrim: {
  27571. type: [Boolean, String],
  27572. default: true
  27573. },
  27574. showSize: Boolean,
  27575. name: String,
  27576. ...makeDelayProps(),
  27577. ...makeDensityProps(),
  27578. ...only(makeVDividerProps({
  27579. length: 150
  27580. }), ['length', 'thickness', 'opacity']),
  27581. ...makeVSheetProps()
  27582. }, 'VFileUpload');
  27583. const VFileUpload = genericComponent()({
  27584. name: 'VFileUpload',
  27585. inheritAttrs: false,
  27586. props: makeVFileUploadProps(),
  27587. emits: {
  27588. 'update:modelValue': files => true
  27589. },
  27590. setup(props, _ref) {
  27591. let {
  27592. attrs,
  27593. slots
  27594. } = _ref;
  27595. const {
  27596. t
  27597. } = useLocale();
  27598. const {
  27599. densityClasses
  27600. } = useDensity(props);
  27601. const model = useProxiedModel(props, 'modelValue', props.modelValue, val => wrapInArray(val), val => props.multiple || Array.isArray(props.modelValue) ? val : val[0]);
  27602. const dragOver = vue.shallowRef(false);
  27603. const vSheetRef = vue.ref(null);
  27604. const inputRef = vue.ref(null);
  27605. vue.onMounted(() => {
  27606. vSheetRef.value?.$el.addEventListener('dragover', onDragOver);
  27607. vSheetRef.value?.$el.addEventListener('drop', onDrop);
  27608. });
  27609. vue.onUnmounted(() => {
  27610. vSheetRef.value?.$el.removeEventListener('dragover', onDragOver);
  27611. vSheetRef.value?.$el.removeEventListener('drop', onDrop);
  27612. });
  27613. function onDragOver(e) {
  27614. e.preventDefault();
  27615. e.stopImmediatePropagation();
  27616. dragOver.value = true;
  27617. }
  27618. function onDragLeave(e) {
  27619. e.preventDefault();
  27620. dragOver.value = false;
  27621. }
  27622. function onDrop(e) {
  27623. e.preventDefault();
  27624. e.stopImmediatePropagation();
  27625. dragOver.value = false;
  27626. const files = Array.from(e.dataTransfer?.files ?? []);
  27627. if (!files.length) return;
  27628. if (!props.multiple) {
  27629. model.value = [files[0]];
  27630. return;
  27631. }
  27632. const array = model.value.slice();
  27633. for (const file of files) {
  27634. if (!array.some(f => f.name === file.name)) {
  27635. array.push(file);
  27636. }
  27637. }
  27638. model.value = array;
  27639. }
  27640. function onClick() {
  27641. inputRef.value?.click();
  27642. }
  27643. function onClickRemove(index) {
  27644. model.value = model.value.filter((_, i) => i !== index);
  27645. if (model.value.length > 0 || !inputRef.value) return;
  27646. inputRef.value.value = '';
  27647. }
  27648. useRender(() => {
  27649. const hasTitle = !!(slots.title || props.title);
  27650. const hasIcon = !!(slots.icon || props.icon);
  27651. const hasBrowse = !!(!props.hideBrowse && (slots.browse || props.density === 'default'));
  27652. const cardProps = VSheet.filterProps(props);
  27653. const dividerProps = VDivider.filterProps(props);
  27654. const [rootAttrs, inputAttrs] = filterInputAttrs(attrs);
  27655. const inputNode = vue.createVNode("input", vue.mergeProps({
  27656. "ref": inputRef,
  27657. "type": "file",
  27658. "disabled": props.disabled,
  27659. "multiple": props.multiple,
  27660. "name": props.name,
  27661. "onChange": e => {
  27662. if (!e.target) return;
  27663. const target = e.target;
  27664. model.value = [...(target.files ?? [])];
  27665. }
  27666. }, inputAttrs), null);
  27667. return vue.createVNode(vue.Fragment, null, [vue.createVNode(VSheet, vue.mergeProps({
  27668. "ref": vSheetRef
  27669. }, cardProps, {
  27670. "class": ['v-file-upload', {
  27671. 'v-file-upload--clickable': !hasBrowse,
  27672. 'v-file-upload--disabled': props.disabled,
  27673. 'v-file-upload--dragging': dragOver.value
  27674. }, densityClasses.value],
  27675. "onDragleave": onDragLeave,
  27676. "onDragover": onDragOver,
  27677. "onDrop": onDrop,
  27678. "onClick": !hasBrowse ? onClick : undefined
  27679. }, rootAttrs), {
  27680. default: () => [hasIcon && vue.createVNode("div", {
  27681. "key": "icon",
  27682. "class": "v-file-upload-icon"
  27683. }, [!slots.icon ? vue.createVNode(VIcon, {
  27684. "key": "icon-icon",
  27685. "icon": props.icon
  27686. }, null) : vue.createVNode(VDefaultsProvider, {
  27687. "key": "icon-defaults",
  27688. "defaults": {
  27689. VIcon: {
  27690. icon: props.icon
  27691. }
  27692. }
  27693. }, {
  27694. default: () => [slots.icon()]
  27695. })]), hasTitle && vue.createVNode("div", {
  27696. "key": "title",
  27697. "class": "v-file-upload-title"
  27698. }, [slots.title?.() ?? t(props.title)]), props.density === 'default' && vue.createVNode(vue.Fragment, null, [vue.createVNode("div", {
  27699. "key": "upload-divider",
  27700. "class": "v-file-upload-divider"
  27701. }, [slots.divider?.() ?? vue.createVNode(VDivider, dividerProps, {
  27702. default: () => [t(props.dividerText)]
  27703. })]), hasBrowse && vue.createVNode(vue.Fragment, null, [!slots.browse ? vue.createVNode(VBtn, {
  27704. "readonly": props.disabled,
  27705. "size": "large",
  27706. "text": t(props.browseText),
  27707. "variant": "tonal",
  27708. "onClick": onClick
  27709. }, null) : vue.createVNode(VDefaultsProvider, {
  27710. "defaults": {
  27711. VBtn: {
  27712. readonly: props.disabled,
  27713. size: 'large',
  27714. text: t(props.browseText),
  27715. variant: 'tonal'
  27716. }
  27717. }
  27718. }, {
  27719. default: () => [slots.browse({
  27720. props: {
  27721. onClick
  27722. }
  27723. })]
  27724. })]), props.subtitle && vue.createVNode("div", {
  27725. "class": "v-file-upload-subtitle"
  27726. }, [props.subtitle])]), vue.createVNode(VOverlay, {
  27727. "model-value": dragOver.value,
  27728. "contained": true,
  27729. "scrim": props.scrim
  27730. }, null), slots.input?.({
  27731. inputNode
  27732. }) ?? inputNode]
  27733. }), model.value.length > 0 && vue.createVNode("div", {
  27734. "class": "v-file-upload-items"
  27735. }, [model.value.map((file, i) => {
  27736. const slotProps = {
  27737. file,
  27738. props: {
  27739. 'onClick:remove': () => onClickRemove(i)
  27740. }
  27741. };
  27742. return vue.createVNode(VDefaultsProvider, {
  27743. "key": i,
  27744. "defaults": {
  27745. VFileUploadItem: {
  27746. file,
  27747. clearable: props.clearable,
  27748. disabled: props.disabled,
  27749. showSize: props.showSize
  27750. }
  27751. }
  27752. }, {
  27753. default: () => [slots.item?.(slotProps) ?? vue.createVNode(VFileUploadItem, {
  27754. "key": i,
  27755. "onClick:remove": () => onClickRemove(i)
  27756. }, slots)]
  27757. });
  27758. })])]);
  27759. });
  27760. }
  27761. });
  27762. // Types
  27763. const makeVNumberInputProps = propsFactory({
  27764. controlVariant: {
  27765. type: String,
  27766. default: 'default'
  27767. },
  27768. inset: Boolean,
  27769. hideInput: Boolean,
  27770. modelValue: {
  27771. type: Number,
  27772. default: null
  27773. },
  27774. min: {
  27775. type: Number,
  27776. default: Number.MIN_SAFE_INTEGER
  27777. },
  27778. max: {
  27779. type: Number,
  27780. default: Number.MAX_SAFE_INTEGER
  27781. },
  27782. step: {
  27783. type: Number,
  27784. default: 1
  27785. },
  27786. ...omit(makeVTextFieldProps({}), ['appendInnerIcon', 'modelValue', 'prependInnerIcon'])
  27787. }, 'VNumberInput');
  27788. const VNumberInput = genericComponent()({
  27789. name: 'VNumberInput',
  27790. props: {
  27791. ...makeVNumberInputProps()
  27792. },
  27793. emits: {
  27794. 'update:modelValue': val => true
  27795. },
  27796. setup(props, _ref) {
  27797. let {
  27798. slots
  27799. } = _ref;
  27800. const _model = useProxiedModel(props, 'modelValue');
  27801. const model = vue.computed({
  27802. get: () => _model.value,
  27803. // model.value could be empty string from VTextField
  27804. // but _model.value should be eventually kept in type Number | null
  27805. set(val) {
  27806. if (val === null || val === '') {
  27807. _model.value = null;
  27808. return;
  27809. }
  27810. const value = Number(val);
  27811. if (!isNaN(value) && value <= props.max && value >= props.min) {
  27812. _model.value = value;
  27813. }
  27814. }
  27815. });
  27816. const vTextFieldRef = vue.ref();
  27817. const stepDecimals = vue.computed(() => getDecimals(props.step));
  27818. const modelDecimals = vue.computed(() => typeof model.value === 'number' ? getDecimals(model.value) : 0);
  27819. const form = useForm(props);
  27820. const controlsDisabled = vue.computed(() => form.isDisabled.value || form.isReadonly.value);
  27821. const canIncrease = vue.computed(() => {
  27822. if (controlsDisabled.value) return false;
  27823. return (model.value ?? 0) + props.step <= props.max;
  27824. });
  27825. const canDecrease = vue.computed(() => {
  27826. if (controlsDisabled.value) return false;
  27827. return (model.value ?? 0) - props.step >= props.min;
  27828. });
  27829. const controlVariant = vue.computed(() => {
  27830. return props.hideInput ? 'stacked' : props.controlVariant;
  27831. });
  27832. const incrementIcon = vue.computed(() => controlVariant.value === 'split' ? '$plus' : '$collapse');
  27833. const decrementIcon = vue.computed(() => controlVariant.value === 'split' ? '$minus' : '$expand');
  27834. const controlNodeSize = vue.computed(() => controlVariant.value === 'split' ? 'default' : 'small');
  27835. const controlNodeDefaultHeight = vue.computed(() => controlVariant.value === 'stacked' ? 'auto' : '100%');
  27836. const incrementSlotProps = vue.computed(() => ({
  27837. click: onClickUp
  27838. }));
  27839. const decrementSlotProps = vue.computed(() => ({
  27840. click: onClickDown
  27841. }));
  27842. vue.onMounted(() => {
  27843. if (!controlsDisabled.value) {
  27844. clampModel();
  27845. }
  27846. });
  27847. function toggleUpDown() {
  27848. let increment = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : true;
  27849. if (controlsDisabled.value) return;
  27850. if (model.value == null) {
  27851. model.value = clamp(0, props.min, props.max);
  27852. return;
  27853. }
  27854. const decimals = Math.max(modelDecimals.value, stepDecimals.value);
  27855. if (increment) {
  27856. if (canIncrease.value) model.value = +(model.value + props.step).toFixed(decimals);
  27857. } else {
  27858. if (canDecrease.value) model.value = +(model.value - props.step).toFixed(decimals);
  27859. }
  27860. }
  27861. function onClickUp(e) {
  27862. e.stopPropagation();
  27863. toggleUpDown();
  27864. }
  27865. function onClickDown(e) {
  27866. e.stopPropagation();
  27867. toggleUpDown(false);
  27868. }
  27869. function onBeforeinput(e) {
  27870. if (!e.data) return;
  27871. const existingTxt = e.target?.value;
  27872. const selectionStart = e.target?.selectionStart;
  27873. const selectionEnd = e.target?.selectionEnd;
  27874. const potentialNewInputVal = existingTxt ? existingTxt.slice(0, selectionStart) + e.data + existingTxt.slice(selectionEnd) : e.data;
  27875. // Only numbers, "-", "." are allowed
  27876. // AND "-", "." are allowed only once
  27877. // AND "-" is only allowed at the start
  27878. if (!/^-?(\d+(\.\d*)?|(\.\d+)|\d*|\.)$/.test(potentialNewInputVal)) {
  27879. e.preventDefault();
  27880. }
  27881. }
  27882. async function onKeydown(e) {
  27883. if (['Enter', 'ArrowLeft', 'ArrowRight', 'Backspace', 'Delete', 'Tab'].includes(e.key) || e.ctrlKey) return;
  27884. if (['ArrowDown', 'ArrowUp'].includes(e.key)) {
  27885. e.preventDefault();
  27886. clampModel();
  27887. // _model is controlled, so need to wait until props['modelValue'] is updated
  27888. await vue.nextTick();
  27889. if (e.key === 'ArrowDown') {
  27890. toggleUpDown(false);
  27891. } else {
  27892. toggleUpDown();
  27893. }
  27894. }
  27895. }
  27896. function onControlMousedown(e) {
  27897. e.stopPropagation();
  27898. }
  27899. function clampModel() {
  27900. if (!vTextFieldRef.value) return;
  27901. const inputText = vTextFieldRef.value.value;
  27902. if (inputText && !isNaN(+inputText)) {
  27903. model.value = clamp(+inputText, props.min, props.max);
  27904. } else {
  27905. model.value = null;
  27906. }
  27907. }
  27908. useRender(() => {
  27909. const {
  27910. modelValue: _,
  27911. ...textFieldProps
  27912. } = VTextField.filterProps(props);
  27913. function incrementControlNode() {
  27914. return !slots.increment ? vue.createVNode(VBtn, {
  27915. "disabled": !canIncrease.value,
  27916. "flat": true,
  27917. "key": "increment-btn",
  27918. "height": controlNodeDefaultHeight.value,
  27919. "data-testid": "increment",
  27920. "aria-hidden": "true",
  27921. "icon": incrementIcon.value,
  27922. "onClick": onClickUp,
  27923. "onMousedown": onControlMousedown,
  27924. "size": controlNodeSize.value,
  27925. "tabindex": "-1"
  27926. }, null) : vue.createVNode(VDefaultsProvider, {
  27927. "key": "increment-defaults",
  27928. "defaults": {
  27929. VBtn: {
  27930. disabled: !canIncrease.value,
  27931. flat: true,
  27932. height: controlNodeDefaultHeight.value,
  27933. size: controlNodeSize.value,
  27934. icon: incrementIcon.value
  27935. }
  27936. }
  27937. }, {
  27938. default: () => [slots.increment(incrementSlotProps.value)]
  27939. });
  27940. }
  27941. function decrementControlNode() {
  27942. return !slots.decrement ? vue.createVNode(VBtn, {
  27943. "disabled": !canDecrease.value,
  27944. "flat": true,
  27945. "key": "decrement-btn",
  27946. "height": controlNodeDefaultHeight.value,
  27947. "data-testid": "decrement",
  27948. "aria-hidden": "true",
  27949. "icon": decrementIcon.value,
  27950. "size": controlNodeSize.value,
  27951. "tabindex": "-1",
  27952. "onClick": onClickDown,
  27953. "onMousedown": onControlMousedown
  27954. }, null) : vue.createVNode(VDefaultsProvider, {
  27955. "key": "decrement-defaults",
  27956. "defaults": {
  27957. VBtn: {
  27958. disabled: !canDecrease.value,
  27959. flat: true,
  27960. height: controlNodeDefaultHeight.value,
  27961. size: controlNodeSize.value,
  27962. icon: decrementIcon.value
  27963. }
  27964. }
  27965. }, {
  27966. default: () => [slots.decrement(decrementSlotProps.value)]
  27967. });
  27968. }
  27969. function controlNode() {
  27970. return vue.createVNode("div", {
  27971. "class": "v-number-input__control"
  27972. }, [decrementControlNode(), vue.createVNode(VDivider, {
  27973. "vertical": controlVariant.value !== 'stacked'
  27974. }, null), incrementControlNode()]);
  27975. }
  27976. function dividerNode() {
  27977. return !props.hideInput && !props.inset ? vue.createVNode(VDivider, {
  27978. "vertical": true
  27979. }, null) : undefined;
  27980. }
  27981. const appendInnerControl = controlVariant.value === 'split' ? vue.createVNode("div", {
  27982. "class": "v-number-input__control"
  27983. }, [vue.createVNode(VDivider, {
  27984. "vertical": true
  27985. }, null), incrementControlNode()]) : props.reverse ? undefined : vue.createVNode(vue.Fragment, null, [dividerNode(), controlNode()]);
  27986. const hasAppendInner = slots['append-inner'] || appendInnerControl;
  27987. const prependInnerControl = controlVariant.value === 'split' ? vue.createVNode("div", {
  27988. "class": "v-number-input__control"
  27989. }, [decrementControlNode(), vue.createVNode(VDivider, {
  27990. "vertical": true
  27991. }, null)]) : props.reverse ? vue.createVNode(vue.Fragment, null, [controlNode(), dividerNode()]) : undefined;
  27992. const hasPrependInner = slots['prepend-inner'] || prependInnerControl;
  27993. return vue.createVNode(VTextField, vue.mergeProps({
  27994. "ref": vTextFieldRef,
  27995. "modelValue": model.value,
  27996. "onUpdate:modelValue": $event => model.value = $event,
  27997. "onBeforeinput": onBeforeinput,
  27998. "onChange": clampModel,
  27999. "onKeydown": onKeydown,
  28000. "class": ['v-number-input', {
  28001. 'v-number-input--default': controlVariant.value === 'default',
  28002. 'v-number-input--hide-input': props.hideInput,
  28003. 'v-number-input--inset': props.inset,
  28004. 'v-number-input--reverse': props.reverse,
  28005. 'v-number-input--split': controlVariant.value === 'split',
  28006. 'v-number-input--stacked': controlVariant.value === 'stacked'
  28007. }, props.class]
  28008. }, textFieldProps, {
  28009. "style": props.style,
  28010. "inputmode": "decimal"
  28011. }), {
  28012. ...slots,
  28013. 'append-inner': hasAppendInner ? function () {
  28014. for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) {
  28015. args[_key] = arguments[_key];
  28016. }
  28017. return vue.createVNode(vue.Fragment, null, [slots['append-inner']?.(...args), appendInnerControl]);
  28018. } : undefined,
  28019. 'prepend-inner': hasPrependInner ? function () {
  28020. for (var _len2 = arguments.length, args = new Array(_len2), _key2 = 0; _key2 < _len2; _key2++) {
  28021. args[_key2] = arguments[_key2];
  28022. }
  28023. return vue.createVNode(vue.Fragment, null, [prependInnerControl, slots['prepend-inner']?.(...args)]);
  28024. } : undefined
  28025. });
  28026. });
  28027. return forwardRefs({}, vTextFieldRef);
  28028. }
  28029. });
  28030. // Types
  28031. const makeVStepperVerticalActionsProps = propsFactory({
  28032. ...makeVStepperActionsProps()
  28033. }, 'VStepperActions');
  28034. const VStepperVerticalActions = genericComponent()({
  28035. name: 'VStepperVerticalActions',
  28036. props: makeVStepperVerticalActionsProps(),
  28037. emits: {
  28038. 'click:prev': () => true,
  28039. 'click:next': () => true
  28040. },
  28041. setup(props, _ref) {
  28042. let {
  28043. emit,
  28044. slots
  28045. } = _ref;
  28046. function onClickPrev() {
  28047. emit('click:prev');
  28048. }
  28049. function onClickNext() {
  28050. emit('click:next');
  28051. }
  28052. useRender(() => {
  28053. const stepperActionsProps = VStepperActions.filterProps(props);
  28054. return vue.createVNode(VStepperActions, vue.mergeProps({
  28055. "class": "v-stepper-vertical-actions"
  28056. }, stepperActionsProps, {
  28057. "onClick:prev": onClickPrev,
  28058. "onClick:next": onClickNext
  28059. }), slots);
  28060. });
  28061. return {};
  28062. }
  28063. });
  28064. // Types
  28065. const makeVStepperVerticalItemProps = propsFactory({
  28066. hideActions: Boolean,
  28067. ...makeStepperItemProps(),
  28068. ...omit(makeVExpansionPanelProps({
  28069. expandIcon: '',
  28070. collapseIcon: ''
  28071. }), ['hideActions'])
  28072. }, 'VStepperVerticalItem');
  28073. const VStepperVerticalItem = genericComponent()({
  28074. name: 'VStepperVerticalItem',
  28075. props: makeVStepperVerticalItemProps(),
  28076. emits: {
  28077. 'click:next': () => true,
  28078. 'click:prev': () => true,
  28079. 'click:finish': () => true
  28080. },
  28081. setup(props, _ref) {
  28082. let {
  28083. emit,
  28084. slots
  28085. } = _ref;
  28086. const vExpansionPanelRef = vue.ref();
  28087. const step = vue.computed(() => !isNaN(parseInt(props.value)) ? Number(props.value) : props.value);
  28088. const groupItem = vue.computed(() => vExpansionPanelRef.value?.groupItem);
  28089. const isSelected = vue.computed(() => groupItem.value?.isSelected.value ?? false);
  28090. const isValid = vue.computed(() => isSelected.value ? props.rules.every(handler => handler() === true) : null);
  28091. const canEdit = vue.computed(() => !props.disabled && props.editable);
  28092. const hasError = vue.computed(() => props.error || isSelected.value && !isValid.value);
  28093. const hasCompleted = vue.computed(() => props.complete || props.rules.length > 0 && isValid.value === true);
  28094. const disabled = vue.computed(() => {
  28095. if (props.disabled) return props.disabled;
  28096. if (groupItem.value?.isFirst.value) return 'prev';
  28097. return false;
  28098. });
  28099. const icon = vue.computed(() => {
  28100. if (hasError.value) return props.errorIcon;
  28101. if (hasCompleted.value) return props.completeIcon;
  28102. if (groupItem.value?.isSelected.value && props.editable) return props.editIcon;
  28103. return props.icon;
  28104. });
  28105. const slotProps = vue.computed(() => ({
  28106. canEdit: canEdit.value,
  28107. hasError: hasError.value,
  28108. hasCompleted: hasCompleted.value,
  28109. title: props.title,
  28110. subtitle: props.subtitle,
  28111. step: step.value,
  28112. value: props.value
  28113. }));
  28114. const actionProps = vue.computed(() => ({
  28115. ...slotProps.value,
  28116. prev: onClickPrev,
  28117. next: onClickNext
  28118. }));
  28119. function onClickNext() {
  28120. emit('click:next');
  28121. if (groupItem.value?.isLast.value) return;
  28122. groupItem.value.group.next();
  28123. }
  28124. function onClickPrev() {
  28125. emit('click:prev');
  28126. groupItem.value.group.prev();
  28127. }
  28128. useRender(() => {
  28129. const hasColor = (hasCompleted.value || groupItem.value?.isSelected.value) && !hasError.value && !props.disabled;
  28130. const hasActions = !props.hideActions || !!slots.actions;
  28131. const expansionPanelProps = VExpansionPanel.filterProps(props);
  28132. return vue.createVNode(VExpansionPanel, vue.mergeProps({
  28133. "_as": "VStepperVerticalItem",
  28134. "ref": vExpansionPanelRef
  28135. }, expansionPanelProps, {
  28136. "class": ['v-stepper-vertical-item', {
  28137. 'v-stepper-vertical-item--complete': hasCompleted.value,
  28138. 'v-stepper-vertical-item--disabled': props.disabled,
  28139. 'v-stepper-vertical-item--editable': canEdit.value,
  28140. 'v-stepper-vertical-item--error': hasError.value
  28141. }, props.class],
  28142. "readonly": !props.editable,
  28143. "style": props.style,
  28144. "color": "",
  28145. "hide-actions": false,
  28146. "value": step.value
  28147. }), {
  28148. title: () => vue.createVNode(vue.Fragment, null, [vue.createVNode(VAvatar, {
  28149. "key": "stepper-avatar",
  28150. "class": "v-stepper-vertical-item__avatar",
  28151. "color": hasColor ? props.color : undefined,
  28152. "size": 24,
  28153. "start": true
  28154. }, {
  28155. default: () => [slots.icon?.(slotProps.value) ?? (icon.value ? vue.createVNode(VIcon, {
  28156. "icon": icon.value
  28157. }, null) : step.value)]
  28158. }), vue.createVNode("div", null, [vue.createVNode("div", {
  28159. "class": "v-stepper-vertical-item__title"
  28160. }, [slots.title?.(slotProps.value) ?? props.title]), vue.createVNode("div", {
  28161. "class": "v-stepper-vertical-item__subtitle"
  28162. }, [slots.subtitle?.(slotProps.value) ?? props.subtitle])])]),
  28163. text: () => vue.createVNode(vue.Fragment, null, [slots.default?.(slotProps.value) ?? props.text, hasActions && vue.createVNode(VDefaultsProvider, {
  28164. "defaults": {
  28165. VStepperVerticalActions: {
  28166. disabled: disabled.value,
  28167. finish: groupItem.value?.isLast.value
  28168. }
  28169. }
  28170. }, {
  28171. default: () => [slots.actions?.(actionProps.value) ?? vue.createVNode(VStepperVerticalActions, {
  28172. "onClick:next": onClickNext,
  28173. "onClick:prev": onClickPrev
  28174. }, {
  28175. prev: slots.prev ? () => slots.prev?.(actionProps.value) : undefined,
  28176. next: slots.next ? () => slots.next?.(actionProps.value) : undefined
  28177. })]
  28178. })])
  28179. });
  28180. });
  28181. return {};
  28182. }
  28183. });
  28184. // Types
  28185. const makeVStepperVerticalProps = propsFactory({
  28186. prevText: {
  28187. type: String,
  28188. default: '$vuetify.stepper.prev'
  28189. },
  28190. nextText: {
  28191. type: String,
  28192. default: '$vuetify.stepper.next'
  28193. },
  28194. ...makeStepperProps(),
  28195. ...omit(makeVExpansionPanelsProps({
  28196. mandatory: 'force',
  28197. variant: 'accordion'
  28198. }), ['static'])
  28199. }, 'VStepperVertical');
  28200. const VStepperVertical = genericComponent()({
  28201. name: 'VStepperVertical',
  28202. props: makeVStepperVerticalProps(),
  28203. emits: {
  28204. 'update:modelValue': val => true
  28205. },
  28206. setup(props, _ref) {
  28207. let {
  28208. slots
  28209. } = _ref;
  28210. const vExpansionPanelsRef = vue.ref();
  28211. const {
  28212. color,
  28213. eager,
  28214. editable,
  28215. prevText,
  28216. nextText,
  28217. hideActions
  28218. } = vue.toRefs(props);
  28219. const model = useProxiedModel(props, 'modelValue');
  28220. const items = vue.computed(() => props.items.map((item, index) => {
  28221. const title = getPropertyFromItem(item, props.itemTitle, item);
  28222. const value = getPropertyFromItem(item, props.itemValue, index + 1);
  28223. return {
  28224. title,
  28225. value,
  28226. raw: item
  28227. };
  28228. }));
  28229. provideDefaults({
  28230. VStepperVerticalItem: {
  28231. color,
  28232. eager,
  28233. editable,
  28234. prevText,
  28235. nextText,
  28236. hideActions,
  28237. static: true
  28238. },
  28239. VStepperActions: {
  28240. color
  28241. }
  28242. });
  28243. useRender(() => {
  28244. const expansionPanelProps = VExpansionPanels.filterProps(props);
  28245. return vue.createVNode(VExpansionPanels, vue.mergeProps(expansionPanelProps, {
  28246. "modelValue": model.value,
  28247. "onUpdate:modelValue": $event => model.value = $event,
  28248. "ref": vExpansionPanelsRef,
  28249. "class": ['v-stepper', {
  28250. 'v-stepper--alt-labels': props.altLabels,
  28251. 'v-stepper--flat': props.flat,
  28252. 'v-stepper--non-linear': props.nonLinear,
  28253. 'v-stepper--mobile': props.mobile
  28254. }, props.class],
  28255. "style": props.style
  28256. }), {
  28257. ...slots,
  28258. default: _ref2 => {
  28259. let {
  28260. prev,
  28261. next
  28262. } = _ref2;
  28263. return vue.createVNode(vue.Fragment, null, [items.value.map(_ref3 => {
  28264. let {
  28265. raw,
  28266. ...item
  28267. } = _ref3;
  28268. return vue.createVNode(VStepperVerticalItem, item, {
  28269. ...slots,
  28270. default: slots[`item.${item.value}`]
  28271. });
  28272. }), slots.default?.({
  28273. prev,
  28274. next,
  28275. step: model.value
  28276. })]);
  28277. }
  28278. });
  28279. });
  28280. return {};
  28281. }
  28282. });
  28283. const VPullToRefresh = genericComponent()({
  28284. name: 'VPullToRefresh',
  28285. props: {
  28286. disabled: Boolean,
  28287. pullDownThreshold: {
  28288. type: Number,
  28289. default: 64
  28290. }
  28291. },
  28292. emits: {
  28293. load: options => true
  28294. },
  28295. setup(props, _ref) {
  28296. let {
  28297. slots,
  28298. emit
  28299. } = _ref;
  28300. let touchstartY = 0;
  28301. let scrollParents = [];
  28302. const touchDiff = vue.shallowRef(0);
  28303. const containerRef = vue.ref();
  28304. const refreshing = vue.shallowRef(false);
  28305. const goingUp = vue.shallowRef(false);
  28306. const touching = vue.shallowRef(false);
  28307. const canRefresh = vue.computed(() => touchDiff.value >= props.pullDownThreshold && !refreshing.value);
  28308. const topOffset = vue.computed(() => clamp(touchDiff.value, 0, props.pullDownThreshold));
  28309. function onTouchstart(e) {
  28310. if (refreshing.value || props.disabled) return;
  28311. touching.value = true;
  28312. touchstartY = 'clientY' in e ? e.clientY : e.touches[0].clientY;
  28313. }
  28314. function onTouchmove(e) {
  28315. if (refreshing.value || !touching.value || props.disabled) return;
  28316. const touchY = 'clientY' in e ? e.clientY : e.touches[0].clientY;
  28317. if (scrollParents.length && !scrollParents[0].scrollTop) {
  28318. touchDiff.value = touchY - touchstartY;
  28319. }
  28320. }
  28321. function onTouchend(e) {
  28322. if (refreshing.value || props.disabled) return;
  28323. touching.value = false;
  28324. if (canRefresh.value) {
  28325. function done() {
  28326. if (!refreshing.value) return;
  28327. touchDiff.value = 0;
  28328. refreshing.value = false;
  28329. }
  28330. emit('load', {
  28331. done
  28332. });
  28333. refreshing.value = true;
  28334. } else {
  28335. touchDiff.value = 0;
  28336. }
  28337. }
  28338. vue.onMounted(() => {
  28339. scrollParents = getScrollParents(containerRef.value);
  28340. });
  28341. vue.watch([topOffset, refreshing], () => {
  28342. if (scrollParents.length) {
  28343. const stopScrolling = topOffset.value && !refreshing.value;
  28344. scrollParents.forEach(p => p.style.overflow = stopScrolling ? 'hidden' : 'auto');
  28345. }
  28346. });
  28347. vue.watch(topOffset, (newVal, oldVal) => {
  28348. goingUp.value = newVal < oldVal;
  28349. });
  28350. useRender(() => {
  28351. return vue.createVNode("div", {
  28352. "class": ['v-pull-to-refresh'],
  28353. "onTouchstart": onTouchstart,
  28354. "onTouchmove": onTouchmove,
  28355. "onTouchend": onTouchend,
  28356. "onMousedown": onTouchstart,
  28357. "onMouseup": onTouchend,
  28358. "onMouseleave": onTouchend,
  28359. "onMousemove": onTouchmove,
  28360. "ref": containerRef
  28361. }, [vue.createVNode("div", {
  28362. "class": ['v-pull-to-refresh__pull-down', {
  28363. 'v-pull-to-refresh__pull-down--touching': touching.value
  28364. }],
  28365. "style": {
  28366. top: convertToUnit(-1 * props.pullDownThreshold + topOffset.value),
  28367. height: convertToUnit(props.pullDownThreshold)
  28368. }
  28369. }, [slots.pullDownPanel ? slots.pullDownPanel({
  28370. canRefresh: canRefresh.value,
  28371. goingUp: goingUp.value,
  28372. refreshing: refreshing.value
  28373. }) : vue.createVNode("div", {
  28374. "class": ['v-pull-to-refresh__pull-down-default']
  28375. }, [refreshing.value ? vue.createVNode(VProgressCircular, {
  28376. "indeterminate": true,
  28377. "active": false
  28378. }, null) : vue.createVNode(VIcon, {
  28379. "icon": canRefresh.value || goingUp.value ? '$sortAsc' : '$sortDesc'
  28380. }, null)])]), vue.createVNode("div", {
  28381. "class": ['v-pull-to-refresh__scroll-container', {
  28382. 'v-pull-to-refresh__scroll-container--touching': touching.value
  28383. }],
  28384. "style": {
  28385. top: convertToUnit(topOffset.value)
  28386. }
  28387. }, [slots.default?.()])]);
  28388. });
  28389. }
  28390. });
  28391. // Types
  28392. const makeVSnackbarQueueProps = propsFactory({
  28393. // TODO: Port this to Snackbar on dev
  28394. closable: [Boolean, String],
  28395. closeText: {
  28396. type: String,
  28397. default: '$vuetify.dismiss'
  28398. },
  28399. modelValue: {
  28400. type: Array,
  28401. default: () => []
  28402. },
  28403. ...omit(makeVSnackbarProps(), ['modelValue'])
  28404. }, 'VSnackbarQueue');
  28405. const VSnackbarQueue = genericComponent()({
  28406. name: 'VSnackbarQueue',
  28407. props: makeVSnackbarQueueProps(),
  28408. emits: {
  28409. 'update:modelValue': val => true
  28410. },
  28411. setup(props, _ref) {
  28412. let {
  28413. emit,
  28414. slots
  28415. } = _ref;
  28416. const {
  28417. t
  28418. } = useLocale();
  28419. const isActive = vue.shallowRef(false);
  28420. const isVisible = vue.shallowRef(false);
  28421. const current = vue.shallowRef();
  28422. vue.watch(() => props.modelValue.length, (val, oldVal) => {
  28423. if (!isVisible.value && val > oldVal) {
  28424. showNext();
  28425. }
  28426. });
  28427. vue.watch(isActive, val => {
  28428. if (val) isVisible.value = true;
  28429. });
  28430. function onAfterLeave() {
  28431. if (props.modelValue.length) {
  28432. showNext();
  28433. } else {
  28434. current.value = undefined;
  28435. isVisible.value = false;
  28436. }
  28437. }
  28438. function showNext() {
  28439. const [next, ...rest] = props.modelValue;
  28440. emit('update:modelValue', rest);
  28441. current.value = typeof next === 'string' ? {
  28442. text: next
  28443. } : next;
  28444. vue.nextTick(() => {
  28445. isActive.value = true;
  28446. });
  28447. }
  28448. function onClickClose() {
  28449. isActive.value = false;
  28450. }
  28451. const btnProps = vue.computed(() => ({
  28452. color: typeof props.closable === 'string' ? props.closable : undefined,
  28453. text: t(props.closeText)
  28454. }));
  28455. useRender(() => {
  28456. const hasActions = !!(props.closable || slots.actions);
  28457. const {
  28458. modelValue: _,
  28459. ...snackbarProps
  28460. } = VSnackbar.filterProps(props);
  28461. return vue.createVNode(vue.Fragment, null, [isVisible.value && !!current.value && (slots.default ? vue.createVNode(VDefaultsProvider, {
  28462. "defaults": {
  28463. VSnackbar: current.value
  28464. }
  28465. }, {
  28466. default: () => [slots.default({
  28467. item: current.value
  28468. })]
  28469. }) : vue.createVNode(VSnackbar, vue.mergeProps(snackbarProps, current.value, {
  28470. "modelValue": isActive.value,
  28471. "onUpdate:modelValue": $event => isActive.value = $event,
  28472. "onAfterLeave": onAfterLeave
  28473. }), {
  28474. text: slots.text ? () => slots.text?.({
  28475. item: current.value
  28476. }) : undefined,
  28477. actions: hasActions ? () => vue.createVNode(vue.Fragment, null, [!slots.actions ? vue.createVNode(VBtn, vue.mergeProps(btnProps.value, {
  28478. "onClick": onClickClose
  28479. }), null) : vue.createVNode(VDefaultsProvider, {
  28480. "defaults": {
  28481. VBtn: btnProps.value
  28482. }
  28483. }, {
  28484. default: () => [slots.actions({
  28485. item: current.value,
  28486. props: {
  28487. onClick: onClickClose
  28488. }
  28489. })]
  28490. })]) : undefined
  28491. }))]);
  28492. });
  28493. }
  28494. });
  28495. function pad(n) {
  28496. let length = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 2;
  28497. return String(n).padStart(length, '0');
  28498. }
  28499. // Types
  28500. const makeVTimePickerClockProps = propsFactory({
  28501. allowedValues: Function,
  28502. ampm: Boolean,
  28503. color: String,
  28504. disabled: Boolean,
  28505. displayedValue: null,
  28506. double: Boolean,
  28507. format: {
  28508. type: Function,
  28509. default: val => val
  28510. },
  28511. max: {
  28512. type: Number,
  28513. required: true
  28514. },
  28515. min: {
  28516. type: Number,
  28517. required: true
  28518. },
  28519. scrollable: Boolean,
  28520. readonly: Boolean,
  28521. rotate: {
  28522. type: Number,
  28523. default: 0
  28524. },
  28525. step: {
  28526. type: Number,
  28527. default: 1
  28528. },
  28529. modelValue: {
  28530. type: Number
  28531. }
  28532. }, 'VTimePickerClock');
  28533. const VTimePickerClock = genericComponent()({
  28534. name: 'VTimePickerClock',
  28535. props: makeVTimePickerClockProps(),
  28536. emits: {
  28537. change: val => true,
  28538. input: val => true
  28539. },
  28540. setup(props, _ref) {
  28541. let {
  28542. emit
  28543. } = _ref;
  28544. const clockRef = vue.ref(null);
  28545. const innerClockRef = vue.ref(null);
  28546. const inputValue = vue.ref(undefined);
  28547. const isDragging = vue.ref(false);
  28548. const valueOnMouseDown = vue.ref(null);
  28549. const valueOnMouseUp = vue.ref(null);
  28550. const {
  28551. textColorClasses,
  28552. textColorStyles
  28553. } = useTextColor(vue.toRef(props, 'color'));
  28554. const {
  28555. backgroundColorClasses,
  28556. backgroundColorStyles
  28557. } = useBackgroundColor(vue.toRef(props, 'color'));
  28558. const count = vue.computed(() => props.max - props.min + 1);
  28559. const roundCount = vue.computed(() => props.double ? count.value / 2 : count.value);
  28560. const degreesPerUnit = vue.computed(() => 360 / roundCount.value);
  28561. const degrees = vue.computed(() => degreesPerUnit.value * Math.PI / 180);
  28562. const displayedValue = vue.computed(() => props.modelValue == null ? props.min : props.modelValue);
  28563. const innerRadiusScale = vue.computed(() => 0.62);
  28564. const genChildren = vue.computed(() => {
  28565. const children = [];
  28566. for (let value = props.min; value <= props.max; value = value + props.step) {
  28567. children.push(value);
  28568. }
  28569. return children;
  28570. });
  28571. vue.watch(() => props.modelValue, val => {
  28572. inputValue.value = val;
  28573. });
  28574. function update(value) {
  28575. if (inputValue.value !== value) {
  28576. inputValue.value = value;
  28577. }
  28578. emit('input', value);
  28579. }
  28580. function isAllowed(value) {
  28581. return !props.allowedValues || props.allowedValues(value);
  28582. }
  28583. function wheel(e) {
  28584. if (!props.scrollable || props.disabled) return;
  28585. e.preventDefault();
  28586. const delta = Math.sign(-e.deltaY || 1);
  28587. let value = displayedValue.value;
  28588. do {
  28589. value = value + delta;
  28590. value = (value - props.min + count.value) % count.value + props.min;
  28591. } while (!isAllowed(value) && value !== displayedValue.value);
  28592. if (value !== props.displayedValue) {
  28593. update(value);
  28594. }
  28595. }
  28596. function isInner(value) {
  28597. return props.double && value - props.min >= roundCount.value;
  28598. }
  28599. function handScale(value) {
  28600. return isInner(value) ? innerRadiusScale.value : 1;
  28601. }
  28602. function getPosition(value) {
  28603. const rotateRadians = props.rotate * Math.PI / 180;
  28604. return {
  28605. x: Math.sin((value - props.min) * degrees.value + rotateRadians) * handScale(value),
  28606. y: -Math.cos((value - props.min) * degrees.value + rotateRadians) * handScale(value)
  28607. };
  28608. }
  28609. function angleToValue(angle, insideClick) {
  28610. const value = (Math.round(angle / degreesPerUnit.value) + (insideClick ? roundCount.value : 0)) % count.value + props.min;
  28611. // Necessary to fix edge case when selecting left part of the value(s) at 12 o'clock
  28612. if (angle < 360 - degreesPerUnit.value / 2) return value;
  28613. return insideClick ? props.max - roundCount.value + 1 : props.min;
  28614. }
  28615. function getTransform(i) {
  28616. const {
  28617. x,
  28618. y
  28619. } = getPosition(i);
  28620. return {
  28621. left: `${50 + x * 50}%`,
  28622. top: `${50 + y * 50}%`
  28623. };
  28624. }
  28625. function euclidean(p0, p1) {
  28626. const dx = p1.x - p0.x;
  28627. const dy = p1.y - p0.y;
  28628. return Math.sqrt(dx * dx + dy * dy);
  28629. }
  28630. function angle(center, p1) {
  28631. const value = 2 * Math.atan2(p1.y - center.y - euclidean(center, p1), p1.x - center.x);
  28632. return Math.abs(value * 180 / Math.PI);
  28633. }
  28634. function setMouseDownValue(value) {
  28635. if (valueOnMouseDown.value === null) {
  28636. valueOnMouseDown.value = value;
  28637. }
  28638. valueOnMouseUp.value = value;
  28639. update(value);
  28640. }
  28641. function onDragMove(e) {
  28642. e.preventDefault();
  28643. if (!isDragging.value && e.type !== 'click' || !clockRef.value) return;
  28644. const {
  28645. width,
  28646. top,
  28647. left
  28648. } = clockRef.value?.getBoundingClientRect();
  28649. const {
  28650. width: innerWidth
  28651. } = innerClockRef.value?.getBoundingClientRect() ?? {
  28652. width: 0
  28653. };
  28654. const {
  28655. clientX,
  28656. clientY
  28657. } = 'touches' in e ? e.touches[0] : e;
  28658. const center = {
  28659. x: width / 2,
  28660. y: -width / 2
  28661. };
  28662. const coords = {
  28663. x: clientX - left,
  28664. y: top - clientY
  28665. };
  28666. const handAngle = Math.round(angle(center, coords) - props.rotate + 360) % 360;
  28667. const insideClick = props.double && euclidean(center, coords) < (innerWidth + innerWidth * innerRadiusScale.value) / 4;
  28668. const checksCount = Math.ceil(15 / degreesPerUnit.value);
  28669. let value;
  28670. for (let i = 0; i < checksCount; i++) {
  28671. value = angleToValue(handAngle + i * degreesPerUnit.value, insideClick);
  28672. if (isAllowed(value)) return setMouseDownValue(value);
  28673. value = angleToValue(handAngle - i * degreesPerUnit.value, insideClick);
  28674. if (isAllowed(value)) return setMouseDownValue(value);
  28675. }
  28676. }
  28677. function onMouseDown(e) {
  28678. if (props.disabled) return;
  28679. e.preventDefault();
  28680. window.addEventListener('mousemove', onDragMove);
  28681. window.addEventListener('touchmove', onDragMove);
  28682. window.addEventListener('mouseup', onMouseUp);
  28683. window.addEventListener('touchend', onMouseUp);
  28684. valueOnMouseDown.value = null;
  28685. valueOnMouseUp.value = null;
  28686. isDragging.value = true;
  28687. onDragMove(e);
  28688. }
  28689. function onMouseUp(e) {
  28690. e.stopPropagation();
  28691. window.removeEventListener('mousemove', onDragMove);
  28692. window.removeEventListener('touchmove', onDragMove);
  28693. window.removeEventListener('mouseup', onMouseUp);
  28694. window.removeEventListener('touchend', onMouseUp);
  28695. isDragging.value = false;
  28696. if (valueOnMouseUp.value !== null && isAllowed(valueOnMouseUp.value)) {
  28697. emit('change', valueOnMouseUp.value);
  28698. }
  28699. }
  28700. useRender(() => {
  28701. return vue.createVNode("div", {
  28702. "class": [{
  28703. 'v-time-picker-clock': true,
  28704. 'v-time-picker-clock--indeterminate': props.modelValue == null,
  28705. 'v-time-picker-clock--readonly': props.readonly
  28706. }],
  28707. "onMousedown": onMouseDown,
  28708. "onTouchstart": onMouseDown,
  28709. "onWheel": wheel,
  28710. "ref": clockRef
  28711. }, [vue.createVNode("div", {
  28712. "class": "v-time-picker-clock__inner",
  28713. "ref": innerClockRef
  28714. }, [vue.createVNode("div", {
  28715. "class": [{
  28716. 'v-time-picker-clock__hand': true,
  28717. 'v-time-picker-clock__hand--inner': isInner(props.modelValue)
  28718. }, textColorClasses.value],
  28719. "style": [{
  28720. transform: `rotate(${props.rotate + degreesPerUnit.value * (displayedValue.value - props.min)}deg) scaleY(${handScale(displayedValue.value)})`
  28721. }, textColorStyles.value]
  28722. }, null), genChildren.value.map(value => {
  28723. const isActive = value === displayedValue.value;
  28724. return vue.createVNode("div", {
  28725. "class": [{
  28726. 'v-time-picker-clock__item': true,
  28727. 'v-time-picker-clock__item--active': isActive,
  28728. 'v-time-picker-clock__item--disabled': props.disabled || !isAllowed(value)
  28729. }, isActive && backgroundColorClasses.value],
  28730. "style": [getTransform(value), isActive && backgroundColorStyles.value]
  28731. }, [vue.createVNode("span", null, [props.format(value)])]);
  28732. })])]);
  28733. });
  28734. }
  28735. });
  28736. // @ts-nocheck
  28737. /* eslint-disable */
  28738. var SelectingTimes = /*#__PURE__*/function (SelectingTimes) {
  28739. SelectingTimes[SelectingTimes["Hour"] = 1] = "Hour";
  28740. SelectingTimes[SelectingTimes["Minute"] = 2] = "Minute";
  28741. SelectingTimes[SelectingTimes["Second"] = 3] = "Second";
  28742. return SelectingTimes;
  28743. }(SelectingTimes || {});
  28744. const makeVTimePickerControlsProps = propsFactory({
  28745. ampm: Boolean,
  28746. ampmInTitle: Boolean,
  28747. ampmReadonly: Boolean,
  28748. color: String,
  28749. disabled: Boolean,
  28750. hour: Number,
  28751. minute: Number,
  28752. second: Number,
  28753. period: String,
  28754. readonly: Boolean,
  28755. useSeconds: Boolean,
  28756. selecting: Number,
  28757. value: Number
  28758. }, 'VTimePickerControls');
  28759. const VTimePickerControls = genericComponent()({
  28760. name: 'VTimePickerControls',
  28761. props: makeVTimePickerControlsProps(),
  28762. emits: {
  28763. 'update:period': data => true,
  28764. 'update:selecting': data => true
  28765. },
  28766. setup(props, _ref) {
  28767. let {
  28768. emit,
  28769. slots
  28770. } = _ref;
  28771. const {
  28772. t
  28773. } = useLocale();
  28774. useRender(() => {
  28775. let hour = props.hour;
  28776. if (props.ampm) {
  28777. hour = hour ? (hour - 1) % 12 + 1 : 12;
  28778. }
  28779. return vue.createVNode("div", {
  28780. "class": "v-time-picker-controls"
  28781. }, [vue.createVNode("div", {
  28782. "class": {
  28783. 'v-time-picker-controls__time': true,
  28784. 'v-time-picker-controls__time--with-seconds': props.useSeconds
  28785. }
  28786. }, [vue.createVNode(VBtn, {
  28787. "active": props.selecting === 1,
  28788. "color": props.selecting === 1 ? props.color : undefined,
  28789. "disabled": props.disabled,
  28790. "variant": "tonal",
  28791. "class": {
  28792. 'v-time-picker-controls__time__btn': true,
  28793. 'v-time-picker-controls__time--with-ampm__btn': props.ampm,
  28794. 'v-time-picker-controls__time--with-seconds__btn': props.useSeconds
  28795. },
  28796. "text": props.hour == null ? '--' : pad(`${hour}`),
  28797. "onClick": () => emit('update:selecting', SelectingTimes.Hour)
  28798. }, null), vue.createVNode("span", {
  28799. "class": ['v-time-picker-controls__time__separator', {
  28800. 'v-time-picker-controls--with-seconds__time__separator': props.useSeconds
  28801. }]
  28802. }, [vue.createTextVNode(":")]), vue.createVNode(VBtn, {
  28803. "active": props.selecting === 2,
  28804. "color": props.selecting === 2 ? props.color : undefined,
  28805. "class": {
  28806. 'v-time-picker-controls__time__btn': true,
  28807. 'v-time-picker-controls__time__btn__active': props.selecting === 2,
  28808. 'v-time-picker-controls__time--with-ampm__btn': props.ampm,
  28809. 'v-time-picker-controls__time--with-seconds__btn': props.useSeconds
  28810. },
  28811. "disabled": props.disabled,
  28812. "variant": "tonal",
  28813. "text": props.minute == null ? '--' : pad(props.minute),
  28814. "onClick": () => emit('update:selecting', SelectingTimes.Minute)
  28815. }, null), props.useSeconds && vue.createVNode("span", {
  28816. "class": ['v-time-picker-controls__time__separator', {
  28817. 'v-time-picker-controls--with-seconds__time__separator': props.useSeconds
  28818. }],
  28819. "key": "secondsDivider"
  28820. }, [vue.createTextVNode(":")]), props.useSeconds && vue.createVNode(VBtn, {
  28821. "key": "secondsVal",
  28822. "variant": "tonal",
  28823. "onClick": () => emit('update:selecting', SelectingTimes.Second),
  28824. "class": {
  28825. 'v-time-picker-controls__time__btn': true,
  28826. 'v-time-picker-controls__time__btn__active': props.selecting === 3,
  28827. 'v-time-picker-controls__time--with-seconds__btn': props.useSeconds
  28828. },
  28829. "disabled": props.disabled,
  28830. "text": props.second == null ? '--' : pad(props.second)
  28831. }, null), props.ampm && props.ampmInTitle && vue.createVNode("div", {
  28832. "class": ['v-time-picker-controls__ampm', {
  28833. 'v-time-picker-controls__ampm--readonly': props.ampmReadonly
  28834. }]
  28835. }, [vue.createVNode(VBtn, {
  28836. "active": props.period === 'am',
  28837. "color": props.period === 'am' ? props.color : undefined,
  28838. "class": {
  28839. 'v-time-picker-controls__ampm__am': true,
  28840. 'v-time-picker-controls__ampm__btn': true,
  28841. 'v-time-picker-controls__ampm__btn__active': props.period === 'am'
  28842. },
  28843. "disabled": props.disabled,
  28844. "text": t('$vuetify.timePicker.am'),
  28845. "variant": props.disabled && props.period === 'am' ? 'elevated' : 'tonal',
  28846. "onClick": () => props.period !== 'am' ? emit('update:period', 'am') : null
  28847. }, null), vue.createVNode(VBtn, {
  28848. "active": props.period === 'pm',
  28849. "color": props.period === 'pm' ? props.color : undefined,
  28850. "class": {
  28851. 'v-time-picker-controls__ampm__pm': true,
  28852. 'v-time-picker-controls__ampm__btn': true,
  28853. 'v-time-picker-controls__ampm__btn__active': props.period === 'pm'
  28854. },
  28855. "disabled": props.disabled,
  28856. "text": t('$vuetify.timePicker.pm'),
  28857. "variant": props.disabled && props.period === 'pm' ? 'elevated' : 'tonal',
  28858. "onClick": () => props.period !== 'pm' ? emit('update:period', 'pm') : null
  28859. }, null)])])]);
  28860. });
  28861. return {};
  28862. }
  28863. });
  28864. // Types
  28865. const rangeHours24 = createRange(24);
  28866. const rangeHours12am = createRange(12);
  28867. const rangeHours12pm = rangeHours12am.map(v => v + 12);
  28868. const range60 = createRange(60);
  28869. const selectingNames = {
  28870. 1: 'hour',
  28871. 2: 'minute',
  28872. 3: 'second'
  28873. };
  28874. const makeVTimePickerProps = propsFactory({
  28875. allowedHours: [Function, Array],
  28876. allowedMinutes: [Function, Array],
  28877. allowedSeconds: [Function, Array],
  28878. ampmInTitle: Boolean,
  28879. disabled: Boolean,
  28880. format: {
  28881. type: String,
  28882. default: 'ampm'
  28883. },
  28884. max: String,
  28885. min: String,
  28886. modelValue: null,
  28887. readonly: Boolean,
  28888. scrollable: Boolean,
  28889. useSeconds: Boolean,
  28890. ...omit(makeVPickerProps({
  28891. title: '$vuetify.timePicker.title'
  28892. }), ['landscape'])
  28893. }, 'VTimePicker');
  28894. const VTimePicker = genericComponent()({
  28895. name: 'VTimePicker',
  28896. props: makeVTimePickerProps(),
  28897. emits: {
  28898. 'update:hour': val => true,
  28899. 'update:minute': val => true,
  28900. 'update:period': val => true,
  28901. 'update:second': val => true,
  28902. 'update:modelValue': val => true
  28903. },
  28904. setup(props, _ref) {
  28905. let {
  28906. emit,
  28907. slots
  28908. } = _ref;
  28909. const {
  28910. t
  28911. } = useLocale();
  28912. const inputHour = vue.ref(null);
  28913. const inputMinute = vue.ref(null);
  28914. const inputSecond = vue.ref(null);
  28915. const lazyInputHour = vue.ref(null);
  28916. const lazyInputMinute = vue.ref(null);
  28917. const lazyInputSecond = vue.ref(null);
  28918. const period = vue.ref('am');
  28919. const selecting = vue.ref(SelectingTimes.Hour);
  28920. const controlsRef = vue.ref(null);
  28921. const clockRef = vue.ref(null);
  28922. const isAllowedHourCb = vue.computed(() => {
  28923. let cb;
  28924. if (props.allowedHours instanceof Array) {
  28925. cb = val => props.allowedHours.includes(val);
  28926. } else {
  28927. cb = props.allowedHours;
  28928. }
  28929. if (!props.min && !props.max) return cb;
  28930. const minHour = props.min ? Number(props.min.split(':')[0]) : 0;
  28931. const maxHour = props.max ? Number(props.max.split(':')[0]) : 23;
  28932. return val => {
  28933. return val >= minHour * 1 && val <= maxHour * 1 && (!cb || cb(val));
  28934. };
  28935. });
  28936. const isAllowedMinuteCb = vue.computed(() => {
  28937. let cb;
  28938. const isHourAllowed = !isAllowedHourCb.value || inputHour.value === null || isAllowedHourCb.value(inputHour.value);
  28939. if (props.allowedMinutes instanceof Array) {
  28940. cb = val => props.allowedMinutes.includes(val);
  28941. } else {
  28942. cb = props.allowedMinutes;
  28943. }
  28944. if (!props.min && !props.max) {
  28945. return isHourAllowed ? cb : () => false;
  28946. }
  28947. const [minHour, minMinute] = props.min ? props.min.split(':').map(Number) : [0, 0];
  28948. const [maxHour, maxMinute] = props.max ? props.max.split(':').map(Number) : [23, 59];
  28949. const minTime = minHour * 60 + minMinute * 1;
  28950. const maxTime = maxHour * 60 + maxMinute * 1;
  28951. return val => {
  28952. const time = 60 * inputHour.value + val;
  28953. return time >= minTime && time <= maxTime && isHourAllowed && (!cb || cb(val));
  28954. };
  28955. });
  28956. const isAllowedSecondCb = vue.computed(() => {
  28957. let cb;
  28958. const isHourAllowed = !isAllowedHourCb.value || inputHour.value === null || isAllowedHourCb.value(inputHour.value);
  28959. const isMinuteAllowed = isHourAllowed && (!isAllowedMinuteCb.value || inputMinute.value === null || isAllowedMinuteCb.value(inputMinute.value));
  28960. if (props.allowedSeconds instanceof Array) {
  28961. cb = val => props.allowedSeconds.includes(val);
  28962. } else {
  28963. cb = props.allowedSeconds;
  28964. }
  28965. if (!props.min && !props.max) {
  28966. return isMinuteAllowed ? cb : () => false;
  28967. }
  28968. const [minHour, minMinute, minSecond] = props.min ? props.min.split(':').map(Number) : [0, 0, 0];
  28969. const [maxHour, maxMinute, maxSecond] = props.max ? props.max.split(':').map(Number) : [23, 59, 59];
  28970. const minTime = minHour * 3600 + minMinute * 60 + (minSecond || 0) * 1;
  28971. const maxTime = maxHour * 3600 + maxMinute * 60 + (maxSecond || 0) * 1;
  28972. return val => {
  28973. const time = 3600 * inputHour.value + 60 * inputMinute.value + val;
  28974. return time >= minTime && time <= maxTime && isMinuteAllowed && (!cb || cb(val));
  28975. };
  28976. });
  28977. const isAmPm = vue.computed(() => {
  28978. return props.format === 'ampm';
  28979. });
  28980. vue.watch(() => props.modelValue, val => setInputData(val));
  28981. vue.onMounted(() => {
  28982. setInputData(props.modelValue);
  28983. });
  28984. function genValue() {
  28985. if (inputHour.value != null && inputMinute.value != null && (!props.useSeconds || inputSecond.value != null)) {
  28986. return `${pad(inputHour.value)}:${pad(inputMinute.value)}` + (props.useSeconds ? `:${pad(inputSecond.value)}` : '');
  28987. }
  28988. return null;
  28989. }
  28990. function emitValue() {
  28991. const value = genValue();
  28992. if (value !== null) emit('update:modelValue', value);
  28993. }
  28994. function convert24to12(hour) {
  28995. return hour ? (hour - 1) % 12 + 1 : 12;
  28996. }
  28997. function convert12to24(hour, period) {
  28998. return hour % 12 + (period === 'pm' ? 12 : 0);
  28999. }
  29000. function setInputData(value) {
  29001. if (value == null || value === '') {
  29002. inputHour.value = null;
  29003. inputMinute.value = null;
  29004. inputSecond.value = null;
  29005. } else if (value instanceof Date) {
  29006. inputHour.value = value.getHours();
  29007. inputMinute.value = value.getMinutes();
  29008. inputSecond.value = value.getSeconds();
  29009. } else {
  29010. const [hour,, minute,, second, period] = value.trim().toLowerCase().match(/^(\d+):(\d+)(:(\d+))?([ap]m)?$/) || new Array(6);
  29011. inputHour.value = period ? convert12to24(parseInt(hour, 10), period) : parseInt(hour, 10);
  29012. inputMinute.value = parseInt(minute, 10);
  29013. inputSecond.value = parseInt(second || 0, 10);
  29014. }
  29015. period.value = inputHour.value == null || inputHour.value < 12 ? 'am' : 'pm';
  29016. }
  29017. function firstAllowed(type, value) {
  29018. const allowedFn = type === 'hour' ? isAllowedHourCb.value : type === 'minute' ? isAllowedMinuteCb.value : isAllowedSecondCb.value;
  29019. if (!allowedFn) return value;
  29020. // TODO: clean up (Note from V2 code)
  29021. const range = type === 'minute' ? range60 : type === 'second' ? range60 : isAmPm.value ? value < 12 ? rangeHours12am : rangeHours12pm : rangeHours24;
  29022. const first = range.find(v => allowedFn((v + value) % range.length + range[0]));
  29023. return ((first || 0) + value) % range.length + range[0];
  29024. }
  29025. function setPeriod(val) {
  29026. period.value = val;
  29027. if (inputHour.value != null) {
  29028. const newHour = inputHour.value + (period.value === 'am' ? -12 : 12);
  29029. inputHour.value = firstAllowed('hour', newHour);
  29030. }
  29031. emit('update:period', val);
  29032. emitValue();
  29033. return true;
  29034. }
  29035. function onInput(value) {
  29036. if (selecting.value === SelectingTimes.Hour) {
  29037. inputHour.value = isAmPm.value ? convert12to24(value, period.value) : value;
  29038. } else if (selecting.value === SelectingTimes.Minute) {
  29039. inputMinute.value = value;
  29040. } else {
  29041. inputSecond.value = value;
  29042. }
  29043. }
  29044. function onChange(value) {
  29045. switch (selectingNames[selecting.value]) {
  29046. case 'hour':
  29047. emit('update:hour', value);
  29048. break;
  29049. case 'minute':
  29050. emit('update:minute', value);
  29051. break;
  29052. case 'second':
  29053. emit('update:second', value);
  29054. break;
  29055. }
  29056. const emitChange = selecting.value === (props.useSeconds ? SelectingTimes.Second : SelectingTimes.Minute);
  29057. if (selecting.value === SelectingTimes.Hour) {
  29058. selecting.value = SelectingTimes.Minute;
  29059. } else if (props.useSeconds && selecting.value === SelectingTimes.Minute) {
  29060. selecting.value = SelectingTimes.Second;
  29061. }
  29062. if (inputHour.value === lazyInputHour.value && inputMinute.value === lazyInputMinute.value && (!props.useSeconds || inputSecond.value === lazyInputSecond.value)) return;
  29063. const time = genValue();
  29064. if (time === null) return;
  29065. lazyInputHour.value = inputHour.value;
  29066. lazyInputMinute.value = inputMinute.value;
  29067. props.useSeconds && (lazyInputSecond.value = inputSecond.value);
  29068. emitChange && emitValue();
  29069. }
  29070. useRender(() => {
  29071. const pickerProps = VPicker.filterProps(props);
  29072. const timePickerControlsProps = VTimePickerControls.filterProps(props);
  29073. const timePickerClockProps = VTimePickerClock.filterProps(omit(props, ['format', 'modelValue', 'min', 'max']));
  29074. return vue.createVNode(VPicker, vue.mergeProps(pickerProps, {
  29075. "color": undefined,
  29076. "class": ['v-time-picker', props.class],
  29077. "style": props.style
  29078. }), {
  29079. title: () => slots.title?.() ?? vue.createVNode("div", {
  29080. "class": "v-time-picker__title"
  29081. }, [t(props.title)]),
  29082. header: () => vue.createVNode(VTimePickerControls, vue.mergeProps(timePickerControlsProps, {
  29083. "ampm": isAmPm.value || props.ampmInTitle,
  29084. "ampmReadonly": isAmPm.value && !props.ampmInTitle,
  29085. "hour": inputHour.value,
  29086. "minute": inputMinute.value,
  29087. "period": period.value,
  29088. "second": inputSecond.value,
  29089. "selecting": selecting.value,
  29090. "onUpdate:period": val => setPeriod(val),
  29091. "onUpdate:selecting": value => selecting.value = value,
  29092. "ref": controlsRef
  29093. }), null),
  29094. default: () => vue.createVNode(VTimePickerClock, vue.mergeProps(timePickerClockProps, {
  29095. "allowedValues": selecting.value === SelectingTimes.Hour ? isAllowedHourCb.value : selecting.value === SelectingTimes.Minute ? isAllowedMinuteCb.value : isAllowedSecondCb.value,
  29096. "double": selecting.value === SelectingTimes.Hour && !isAmPm.value,
  29097. "format": selecting.value === SelectingTimes.Hour ? isAmPm.value ? convert24to12 : val => val : val => pad(val, 2),
  29098. "max": selecting.value === SelectingTimes.Hour ? isAmPm.value && period.value === 'am' ? 11 : 23 : 59,
  29099. "min": selecting.value === SelectingTimes.Hour && isAmPm.value && period.value === 'pm' ? 12 : 0,
  29100. "size": 20,
  29101. "step": selecting.value === SelectingTimes.Hour ? 1 : 5,
  29102. "modelValue": selecting.value === SelectingTimes.Hour ? inputHour.value : selecting.value === SelectingTimes.Minute ? inputMinute.value : inputSecond.value,
  29103. "onChange": onChange,
  29104. "onInput": onInput,
  29105. "ref": clockRef
  29106. }), null),
  29107. actions: slots.actions
  29108. });
  29109. });
  29110. }
  29111. });
  29112. // Types
  29113. const makeVTreeviewGroupProps = propsFactory({
  29114. ...omit(makeVListGroupProps({
  29115. collapseIcon: '$treeviewCollapse',
  29116. expandIcon: '$treeviewExpand'
  29117. }), ['subgroup'])
  29118. }, 'VTreeviewGroup');
  29119. const VTreeviewGroup = genericComponent()({
  29120. name: 'VTreeviewGroup',
  29121. props: makeVTreeviewGroupProps(),
  29122. setup(props, _ref) {
  29123. let {
  29124. slots
  29125. } = _ref;
  29126. const vListGroupRef = vue.ref();
  29127. const toggleIcon = vue.computed(() => vListGroupRef.value?.isOpen ? props.collapseIcon : props.expandIcon);
  29128. const activatorDefaults = vue.computed(() => ({
  29129. VTreeviewItem: {
  29130. prependIcon: undefined,
  29131. appendIcon: undefined,
  29132. active: vListGroupRef.value?.isOpen,
  29133. toggleIcon: toggleIcon.value
  29134. }
  29135. }));
  29136. useRender(() => {
  29137. const listGroupProps = VListGroup.filterProps(props);
  29138. return vue.createVNode(VListGroup, vue.mergeProps(listGroupProps, {
  29139. "ref": vListGroupRef,
  29140. "class": ['v-treeview-group', props.class],
  29141. "subgroup": true
  29142. }), {
  29143. ...slots,
  29144. activator: slots.activator ? slotProps => vue.createVNode(vue.Fragment, null, [vue.createVNode(VDefaultsProvider, {
  29145. "defaults": activatorDefaults.value
  29146. }, {
  29147. default: () => [slots.activator?.(slotProps)]
  29148. })]) : undefined
  29149. });
  29150. });
  29151. return {};
  29152. }
  29153. });
  29154. // Types
  29155. const VTreeviewSymbol = Symbol.for('vuetify:v-treeview');
  29156. const makeVTreeviewItemProps = propsFactory({
  29157. loading: Boolean,
  29158. onToggleExpand: EventProp(),
  29159. toggleIcon: IconValue,
  29160. ...makeVListItemProps({
  29161. slim: true
  29162. })
  29163. }, 'VTreeviewItem');
  29164. const VTreeviewItem = genericComponent()({
  29165. name: 'VTreeviewItem',
  29166. props: makeVTreeviewItemProps(),
  29167. setup(props, _ref) {
  29168. let {
  29169. attrs,
  29170. slots,
  29171. emit
  29172. } = _ref;
  29173. const link = useLink(props, attrs);
  29174. const vListItemRef = vue.ref();
  29175. const isActivatableGroupActivator = vue.computed(() => vListItemRef.value?.root.activatable.value && vListItemRef.value?.isGroupActivator);
  29176. const isClickable = vue.computed(() => !props.disabled && props.link !== false && (props.link || link.isClickable.value || props.value != null && !!vListItemRef.value?.list || isActivatableGroupActivator.value));
  29177. function activateGroupActivator(e) {
  29178. if (isClickable.value && isActivatableGroupActivator.value) {
  29179. vListItemRef.value?.activate(!vListItemRef.value?.isActivated, e);
  29180. }
  29181. }
  29182. const visibleIds = vue.inject(VTreeviewSymbol, {
  29183. visibleIds: vue.ref()
  29184. }).visibleIds;
  29185. useRender(() => {
  29186. const listItemProps = omit(VListItem.filterProps(props), ['onClick']);
  29187. const hasPrepend = slots.prepend || props.toggleIcon;
  29188. return vue.createVNode(VListItem, vue.mergeProps({
  29189. "ref": vListItemRef
  29190. }, listItemProps, {
  29191. "active": vListItemRef.value?.isActivated,
  29192. "class": ['v-treeview-item', {
  29193. 'v-treeview-item--activatable-group-activator': isActivatableGroupActivator.value,
  29194. 'v-treeview-item--filtered': visibleIds.value && !visibleIds.value.has(vListItemRef.value?.id)
  29195. }, props.class],
  29196. "ripple": false,
  29197. "onClick": props.onClick ?? activateGroupActivator
  29198. }), {
  29199. ...slots,
  29200. prepend: hasPrepend ? slotProps => {
  29201. return vue.createVNode(vue.Fragment, null, [props.toggleIcon && vue.createVNode(VListItemAction, {
  29202. "start": false
  29203. }, {
  29204. default: () => [vue.createVNode(VBtn, {
  29205. "density": "compact",
  29206. "icon": props.toggleIcon,
  29207. "loading": props.loading,
  29208. "variant": "text",
  29209. "onClick": props.onToggleExpand
  29210. }, {
  29211. loader() {
  29212. return vue.createVNode(VProgressCircular, {
  29213. "indeterminate": "disable-shrink",
  29214. "size": "20",
  29215. "width": "2"
  29216. }, null);
  29217. }
  29218. })]
  29219. }), slots.prepend?.(slotProps)]);
  29220. } : undefined
  29221. });
  29222. });
  29223. return {};
  29224. }
  29225. });
  29226. // Types
  29227. const makeVTreeviewChildrenProps = propsFactory({
  29228. loadChildren: Function,
  29229. loadingIcon: {
  29230. type: String,
  29231. default: '$loading'
  29232. },
  29233. items: Array,
  29234. openOnClick: {
  29235. type: Boolean,
  29236. default: undefined
  29237. },
  29238. indeterminateIcon: {
  29239. type: IconValue,
  29240. default: '$checkboxIndeterminate'
  29241. },
  29242. falseIcon: IconValue,
  29243. trueIcon: IconValue,
  29244. returnObject: Boolean,
  29245. selectable: Boolean,
  29246. selectedColor: String,
  29247. selectStrategy: [String, Function, Object]
  29248. }, 'VTreeviewChildren');
  29249. const VTreeviewChildren = genericComponent()({
  29250. name: 'VTreeviewChildren',
  29251. props: makeVTreeviewChildrenProps(),
  29252. setup(props, _ref) {
  29253. let {
  29254. slots
  29255. } = _ref;
  29256. const isLoading = vue.reactive(new Set());
  29257. const isClickOnOpen = vue.computed(() => props.openOnClick != null ? props.openOnClick : props.selectable);
  29258. async function checkChildren(item) {
  29259. try {
  29260. if (!props.items?.length || !props.loadChildren) return;
  29261. if (item?.children?.length === 0) {
  29262. isLoading.add(item.value);
  29263. await props.loadChildren(item.raw);
  29264. }
  29265. } finally {
  29266. isLoading.delete(item.value);
  29267. }
  29268. }
  29269. function selectItem(select, isSelected) {
  29270. if (props.selectable) {
  29271. select(!isSelected);
  29272. }
  29273. }
  29274. return () => slots.default?.() ?? props.items?.map(item => {
  29275. const {
  29276. children,
  29277. props: itemProps
  29278. } = item;
  29279. const loading = isLoading.has(item.value);
  29280. const slotsWithItem = {
  29281. prepend: slotProps => vue.createVNode(vue.Fragment, null, [props.selectable && (!children || children && !['leaf', 'single-leaf'].includes(props.selectStrategy)) && vue.createVNode("div", null, [vue.createVNode(VCheckboxBtn, {
  29282. "key": item.value,
  29283. "modelValue": slotProps.isSelected,
  29284. "loading": loading,
  29285. "color": props.selectedColor,
  29286. "indeterminate": slotProps.isIndeterminate,
  29287. "indeterminateIcon": props.indeterminateIcon,
  29288. "falseIcon": props.falseIcon,
  29289. "trueIcon": props.trueIcon,
  29290. "onClick": vue.withModifiers(() => selectItem(slotProps.select, slotProps.isSelected), ['stop']),
  29291. "onKeydown": e => {
  29292. if (!['Enter', 'Space'].includes(e.key)) return;
  29293. e.stopPropagation();
  29294. selectItem(slotProps.select, slotProps.isSelected);
  29295. }
  29296. }, null)]), slots.prepend?.({
  29297. ...slotProps,
  29298. item: item.raw,
  29299. internalItem: item
  29300. })]),
  29301. append: slots.append ? slotProps => slots.append?.({
  29302. ...slotProps,
  29303. item: item.raw,
  29304. internalItem: item
  29305. }) : undefined,
  29306. title: slots.title ? slotProps => slots.title?.({
  29307. ...slotProps,
  29308. item: item.raw,
  29309. internalItem: item
  29310. }) : undefined
  29311. };
  29312. const treeviewGroupProps = VTreeviewGroup.filterProps(itemProps);
  29313. const treeviewChildrenProps = VTreeviewChildren.filterProps(props);
  29314. return children ? vue.createVNode(VTreeviewGroup, vue.mergeProps(treeviewGroupProps, {
  29315. "value": props.returnObject ? item.raw : treeviewGroupProps?.value
  29316. }), {
  29317. activator: _ref2 => {
  29318. let {
  29319. props: activatorProps
  29320. } = _ref2;
  29321. const listItemProps = {
  29322. ...itemProps,
  29323. ...activatorProps,
  29324. value: itemProps?.value,
  29325. onToggleExpand: [() => checkChildren(item), activatorProps.onClick],
  29326. onClick: isClickOnOpen.value ? [() => checkChildren(item), activatorProps.onClick] : undefined
  29327. };
  29328. return vue.createVNode(VTreeviewItem, vue.mergeProps(listItemProps, {
  29329. "value": props.returnObject ? vue.toRaw(item.raw) : itemProps.value,
  29330. "loading": loading
  29331. }), slotsWithItem);
  29332. },
  29333. default: () => vue.createVNode(VTreeviewChildren, vue.mergeProps(treeviewChildrenProps, {
  29334. "items": children,
  29335. "returnObject": props.returnObject
  29336. }), slots)
  29337. }) : slots.item?.({
  29338. props: itemProps,
  29339. item: item.raw,
  29340. internalItem: item
  29341. }) ?? vue.createVNode(VTreeviewItem, vue.mergeProps(itemProps, {
  29342. "value": props.returnObject ? vue.toRaw(item.raw) : itemProps.value
  29343. }), slotsWithItem);
  29344. });
  29345. }
  29346. });
  29347. function flatten(items) {
  29348. let flat = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : [];
  29349. for (const item of items) {
  29350. flat.push(item);
  29351. if (item.children) flatten(item.children, flat);
  29352. }
  29353. return flat;
  29354. }
  29355. const makeVTreeviewProps = propsFactory({
  29356. openAll: Boolean,
  29357. search: String,
  29358. ...makeFilterProps({
  29359. filterKeys: ['title']
  29360. }),
  29361. ...makeVTreeviewChildrenProps(),
  29362. ...omit(makeVListProps({
  29363. collapseIcon: '$treeviewCollapse',
  29364. expandIcon: '$treeviewExpand',
  29365. slim: true
  29366. }), ['itemType', 'nav', 'openStrategy']),
  29367. modelValue: {
  29368. type: Array,
  29369. default: () => []
  29370. }
  29371. }, 'VTreeview');
  29372. const VTreeview = genericComponent()({
  29373. name: 'VTreeview',
  29374. props: makeVTreeviewProps(),
  29375. emits: {
  29376. 'update:opened': val => true,
  29377. 'update:activated': val => true,
  29378. 'update:selected': val => true,
  29379. 'update:modelValue': val => true,
  29380. 'click:open': value => true,
  29381. 'click:select': value => true
  29382. },
  29383. setup(props, _ref) {
  29384. let {
  29385. slots
  29386. } = _ref;
  29387. const {
  29388. items
  29389. } = useListItems(props);
  29390. const activeColor = vue.toRef(props, 'activeColor');
  29391. const baseColor = vue.toRef(props, 'baseColor');
  29392. const color = vue.toRef(props, 'color');
  29393. const activated = useProxiedModel(props, 'activated');
  29394. const model = useProxiedModel(props, 'modelValue');
  29395. const _selected = useProxiedModel(props, 'selected', props.modelValue);
  29396. const selected = vue.computed({
  29397. get: () => _selected.value,
  29398. set(val) {
  29399. _selected.value = val;
  29400. model.value = val;
  29401. }
  29402. });
  29403. const vListRef = vue.ref();
  29404. const opened = vue.computed(() => props.openAll ? openAll(items.value) : props.opened);
  29405. const flatItems = vue.computed(() => flatten(items.value));
  29406. const search = vue.toRef(props, 'search');
  29407. const {
  29408. filteredItems
  29409. } = useFilter(props, flatItems, search);
  29410. const visibleIds = vue.computed(() => {
  29411. if (!search.value) return null;
  29412. const getPath = vListRef.value?.getPath;
  29413. if (!getPath) return null;
  29414. return new Set(filteredItems.value.flatMap(item => {
  29415. const itemVal = props.returnObject ? item.raw : item.props.value;
  29416. return [...getPath(itemVal), ...getChildren(itemVal)].map(vue.toRaw);
  29417. }));
  29418. });
  29419. function getChildren(id) {
  29420. const arr = [];
  29421. const queue = (vListRef.value?.children.get(id) ?? []).slice();
  29422. while (queue.length) {
  29423. const child = queue.shift();
  29424. if (!child) continue;
  29425. arr.push(child);
  29426. queue.push(...(vListRef.value?.children.get(child) ?? []).slice());
  29427. }
  29428. return arr;
  29429. }
  29430. function openAll(items) {
  29431. let ids = [];
  29432. for (const i of items) {
  29433. if (!i.children) continue;
  29434. ids.push(props.returnObject ? vue.toRaw(i.raw) : i.value);
  29435. if (i.children) {
  29436. ids = ids.concat(openAll(i.children));
  29437. }
  29438. }
  29439. return ids;
  29440. }
  29441. vue.provide(VTreeviewSymbol, {
  29442. visibleIds
  29443. });
  29444. provideDefaults({
  29445. VTreeviewGroup: {
  29446. activeColor,
  29447. baseColor,
  29448. color,
  29449. collapseIcon: vue.toRef(props, 'collapseIcon'),
  29450. expandIcon: vue.toRef(props, 'expandIcon')
  29451. },
  29452. VTreeviewItem: {
  29453. activeClass: vue.toRef(props, 'activeClass'),
  29454. activeColor,
  29455. baseColor,
  29456. color,
  29457. density: vue.toRef(props, 'density'),
  29458. disabled: vue.toRef(props, 'disabled'),
  29459. lines: vue.toRef(props, 'lines'),
  29460. variant: vue.toRef(props, 'variant')
  29461. }
  29462. });
  29463. useRender(() => {
  29464. const listProps = VList.filterProps(props);
  29465. const treeviewChildrenProps = VTreeviewChildren.filterProps(props);
  29466. return vue.createVNode(VList, vue.mergeProps({
  29467. "ref": vListRef
  29468. }, listProps, {
  29469. "class": ['v-treeview', props.class],
  29470. "open-strategy": "multiple",
  29471. "style": props.style,
  29472. "opened": opened.value,
  29473. "activated": activated.value,
  29474. "onUpdate:activated": $event => activated.value = $event,
  29475. "selected": selected.value,
  29476. "onUpdate:selected": $event => selected.value = $event
  29477. }), {
  29478. default: () => [vue.createVNode(VTreeviewChildren, vue.mergeProps(treeviewChildrenProps, {
  29479. "returnObject": props.returnObject,
  29480. "items": items.value
  29481. }), slots)]
  29482. });
  29483. });
  29484. return {};
  29485. }
  29486. });
  29487. var components = /*#__PURE__*/Object.freeze({
  29488. __proto__: null,
  29489. VAlert: VAlert,
  29490. VAlertTitle: VAlertTitle,
  29491. VApp: VApp,
  29492. VAppBar: VAppBar,
  29493. VAppBarNavIcon: VAppBarNavIcon,
  29494. VAppBarTitle: VAppBarTitle,
  29495. VAutocomplete: VAutocomplete,
  29496. VAvatar: VAvatar,
  29497. VBadge: VBadge,
  29498. VBanner: VBanner,
  29499. VBannerActions: VBannerActions,
  29500. VBannerText: VBannerText,
  29501. VBottomNavigation: VBottomNavigation,
  29502. VBottomSheet: VBottomSheet,
  29503. VBreadcrumbs: VBreadcrumbs,
  29504. VBreadcrumbsDivider: VBreadcrumbsDivider,
  29505. VBreadcrumbsItem: VBreadcrumbsItem,
  29506. VBtn: VBtn,
  29507. VBtnGroup: VBtnGroup,
  29508. VBtnToggle: VBtnToggle,
  29509. VCalendar: VCalendar,
  29510. VCalendarDay: VCalendarDay,
  29511. VCalendarHeader: VCalendarHeader,
  29512. VCalendarInterval: VCalendarInterval,
  29513. VCalendarIntervalEvent: VCalendarIntervalEvent,
  29514. VCalendarMonthDay: VCalendarMonthDay,
  29515. VCard: VCard,
  29516. VCardActions: VCardActions,
  29517. VCardItem: VCardItem,
  29518. VCardSubtitle: VCardSubtitle,
  29519. VCardText: VCardText,
  29520. VCardTitle: VCardTitle,
  29521. VCarousel: VCarousel,
  29522. VCarouselItem: VCarouselItem,
  29523. VCheckbox: VCheckbox,
  29524. VCheckboxBtn: VCheckboxBtn,
  29525. VChip: VChip,
  29526. VChipGroup: VChipGroup,
  29527. VClassIcon: VClassIcon,
  29528. VCode: VCode,
  29529. VCol: VCol,
  29530. VColorPicker: VColorPicker,
  29531. VCombobox: VCombobox,
  29532. VComponentIcon: VComponentIcon,
  29533. VConfirmEdit: VConfirmEdit,
  29534. VContainer: VContainer,
  29535. VCounter: VCounter,
  29536. VDataIterator: VDataIterator,
  29537. VDataTable: VDataTable,
  29538. VDataTableFooter: VDataTableFooter,
  29539. VDataTableHeaders: VDataTableHeaders,
  29540. VDataTableRow: VDataTableRow,
  29541. VDataTableRows: VDataTableRows,
  29542. VDataTableServer: VDataTableServer,
  29543. VDataTableVirtual: VDataTableVirtual,
  29544. VDateInput: VDateInput,
  29545. VDatePicker: VDatePicker,
  29546. VDatePickerControls: VDatePickerControls,
  29547. VDatePickerHeader: VDatePickerHeader,
  29548. VDatePickerMonth: VDatePickerMonth,
  29549. VDatePickerMonths: VDatePickerMonths,
  29550. VDatePickerYears: VDatePickerYears,
  29551. VDefaultsProvider: VDefaultsProvider,
  29552. VDialog: VDialog,
  29553. VDialogBottomTransition: VDialogBottomTransition,
  29554. VDialogTopTransition: VDialogTopTransition,
  29555. VDialogTransition: VDialogTransition,
  29556. VDivider: VDivider,
  29557. VEmptyState: VEmptyState,
  29558. VExpandTransition: VExpandTransition,
  29559. VExpandXTransition: VExpandXTransition,
  29560. VExpansionPanel: VExpansionPanel,
  29561. VExpansionPanelText: VExpansionPanelText,
  29562. VExpansionPanelTitle: VExpansionPanelTitle,
  29563. VExpansionPanels: VExpansionPanels,
  29564. VFab: VFab,
  29565. VFabTransition: VFabTransition,
  29566. VFadeTransition: VFadeTransition,
  29567. VField: VField,
  29568. VFieldLabel: VFieldLabel,
  29569. VFileInput: VFileInput,
  29570. VFileUpload: VFileUpload,
  29571. VFileUploadItem: VFileUploadItem,
  29572. VFooter: VFooter,
  29573. VForm: VForm,
  29574. VHover: VHover,
  29575. VIcon: VIcon,
  29576. VImg: VImg,
  29577. VInfiniteScroll: VInfiniteScroll,
  29578. VInput: VInput,
  29579. VItem: VItem,
  29580. VItemGroup: VItemGroup,
  29581. VKbd: VKbd,
  29582. VLabel: VLabel,
  29583. VLayout: VLayout,
  29584. VLayoutItem: VLayoutItem,
  29585. VLazy: VLazy,
  29586. VLigatureIcon: VLigatureIcon,
  29587. VList: VList,
  29588. VListGroup: VListGroup,
  29589. VListImg: VListImg,
  29590. VListItem: VListItem,
  29591. VListItemAction: VListItemAction,
  29592. VListItemMedia: VListItemMedia,
  29593. VListItemSubtitle: VListItemSubtitle,
  29594. VListItemTitle: VListItemTitle,
  29595. VListSubheader: VListSubheader,
  29596. VLocaleProvider: VLocaleProvider,
  29597. VMain: VMain,
  29598. VMenu: VMenu,
  29599. VMessages: VMessages,
  29600. VNavigationDrawer: VNavigationDrawer,
  29601. VNoSsr: VNoSsr,
  29602. VNumberInput: VNumberInput,
  29603. VOtpInput: VOtpInput,
  29604. VOverlay: VOverlay,
  29605. VPagination: VPagination,
  29606. VParallax: VParallax,
  29607. VPicker: VPicker,
  29608. VPickerTitle: VPickerTitle,
  29609. VProgressCircular: VProgressCircular,
  29610. VProgressLinear: VProgressLinear,
  29611. VPullToRefresh: VPullToRefresh,
  29612. VRadio: VRadio,
  29613. VRadioGroup: VRadioGroup,
  29614. VRangeSlider: VRangeSlider,
  29615. VRating: VRating,
  29616. VResponsive: VResponsive,
  29617. VRow: VRow,
  29618. VScaleTransition: VScaleTransition,
  29619. VScrollXReverseTransition: VScrollXReverseTransition,
  29620. VScrollXTransition: VScrollXTransition,
  29621. VScrollYReverseTransition: VScrollYReverseTransition,
  29622. VScrollYTransition: VScrollYTransition,
  29623. VSelect: VSelect,
  29624. VSelectionControl: VSelectionControl,
  29625. VSelectionControlGroup: VSelectionControlGroup,
  29626. VSheet: VSheet,
  29627. VSkeletonLoader: VSkeletonLoader,
  29628. VSlideGroup: VSlideGroup,
  29629. VSlideGroupItem: VSlideGroupItem,
  29630. VSlideXReverseTransition: VSlideXReverseTransition,
  29631. VSlideXTransition: VSlideXTransition,
  29632. VSlideYReverseTransition: VSlideYReverseTransition,
  29633. VSlideYTransition: VSlideYTransition,
  29634. VSlider: VSlider,
  29635. VSnackbar: VSnackbar,
  29636. VSnackbarQueue: VSnackbarQueue,
  29637. VSpacer: VSpacer,
  29638. VSparkline: VSparkline,
  29639. VSpeedDial: VSpeedDial,
  29640. VStepper: VStepper,
  29641. VStepperActions: VStepperActions,
  29642. VStepperHeader: VStepperHeader,
  29643. VStepperItem: VStepperItem,
  29644. VStepperVertical: VStepperVertical,
  29645. VStepperVerticalActions: VStepperVerticalActions,
  29646. VStepperVerticalItem: VStepperVerticalItem,
  29647. VStepperWindow: VStepperWindow,
  29648. VStepperWindowItem: VStepperWindowItem,
  29649. VSvgIcon: VSvgIcon,
  29650. VSwitch: VSwitch,
  29651. VSystemBar: VSystemBar,
  29652. VTab: VTab,
  29653. VTable: VTable,
  29654. VTabs: VTabs,
  29655. VTabsWindow: VTabsWindow,
  29656. VTabsWindowItem: VTabsWindowItem,
  29657. VTextField: VTextField,
  29658. VTextarea: VTextarea,
  29659. VThemeProvider: VThemeProvider,
  29660. VTimePicker: VTimePicker,
  29661. VTimePickerClock: VTimePickerClock,
  29662. VTimePickerControls: VTimePickerControls,
  29663. VTimeline: VTimeline,
  29664. VTimelineItem: VTimelineItem,
  29665. VToolbar: VToolbar,
  29666. VToolbarItems: VToolbarItems,
  29667. VToolbarTitle: VToolbarTitle,
  29668. VTooltip: VTooltip,
  29669. VTreeview: VTreeview,
  29670. VTreeviewGroup: VTreeviewGroup,
  29671. VTreeviewItem: VTreeviewItem,
  29672. VValidation: VValidation,
  29673. VVirtualScroll: VVirtualScroll,
  29674. VWindow: VWindow,
  29675. VWindowItem: VWindowItem
  29676. });
  29677. // Types
  29678. function mounted$2(el, binding) {
  29679. const modifiers = binding.modifiers || {};
  29680. const value = binding.value;
  29681. const {
  29682. once,
  29683. immediate,
  29684. ...modifierKeys
  29685. } = modifiers;
  29686. const defaultValue = !Object.keys(modifierKeys).length;
  29687. const {
  29688. handler,
  29689. options
  29690. } = typeof value === 'object' ? value : {
  29691. handler: value,
  29692. options: {
  29693. attributes: modifierKeys?.attr ?? defaultValue,
  29694. characterData: modifierKeys?.char ?? defaultValue,
  29695. childList: modifierKeys?.child ?? defaultValue,
  29696. subtree: modifierKeys?.sub ?? defaultValue
  29697. }
  29698. };
  29699. const observer = new MutationObserver(function () {
  29700. let mutations = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : [];
  29701. let observer = arguments.length > 1 ? arguments[1] : undefined;
  29702. handler?.(mutations, observer);
  29703. if (once) unmounted$2(el, binding);
  29704. });
  29705. if (immediate) handler?.([], observer);
  29706. el._mutate = Object(el._mutate);
  29707. el._mutate[binding.instance.$.uid] = {
  29708. observer
  29709. };
  29710. observer.observe(el, options);
  29711. }
  29712. function unmounted$2(el, binding) {
  29713. if (!el._mutate?.[binding.instance.$.uid]) return;
  29714. el._mutate[binding.instance.$.uid].observer.disconnect();
  29715. delete el._mutate[binding.instance.$.uid];
  29716. }
  29717. const Mutate = {
  29718. mounted: mounted$2,
  29719. unmounted: unmounted$2
  29720. };
  29721. // Types
  29722. function mounted$1(el, binding) {
  29723. const handler = binding.value;
  29724. const options = {
  29725. passive: !binding.modifiers?.active
  29726. };
  29727. window.addEventListener('resize', handler, options);
  29728. el._onResize = Object(el._onResize);
  29729. el._onResize[binding.instance.$.uid] = {
  29730. handler,
  29731. options
  29732. };
  29733. if (!binding.modifiers?.quiet) {
  29734. handler();
  29735. }
  29736. }
  29737. function unmounted$1(el, binding) {
  29738. if (!el._onResize?.[binding.instance.$.uid]) return;
  29739. const {
  29740. handler,
  29741. options
  29742. } = el._onResize[binding.instance.$.uid];
  29743. window.removeEventListener('resize', handler, options);
  29744. delete el._onResize[binding.instance.$.uid];
  29745. }
  29746. const Resize = {
  29747. mounted: mounted$1,
  29748. unmounted: unmounted$1
  29749. };
  29750. // Types
  29751. function mounted(el, binding) {
  29752. const {
  29753. self = false
  29754. } = binding.modifiers ?? {};
  29755. const value = binding.value;
  29756. const options = typeof value === 'object' && value.options || {
  29757. passive: true
  29758. };
  29759. const handler = typeof value === 'function' || 'handleEvent' in value ? value : value.handler;
  29760. const target = self ? el : binding.arg ? document.querySelector(binding.arg) : window;
  29761. if (!target) return;
  29762. target.addEventListener('scroll', handler, options);
  29763. el._onScroll = Object(el._onScroll);
  29764. el._onScroll[binding.instance.$.uid] = {
  29765. handler,
  29766. options,
  29767. // Don't reference self
  29768. target: self ? undefined : target
  29769. };
  29770. }
  29771. function unmounted(el, binding) {
  29772. if (!el._onScroll?.[binding.instance.$.uid]) return;
  29773. const {
  29774. handler,
  29775. options,
  29776. target = el
  29777. } = el._onScroll[binding.instance.$.uid];
  29778. target.removeEventListener('scroll', handler, options);
  29779. delete el._onScroll[binding.instance.$.uid];
  29780. }
  29781. function updated(el, binding) {
  29782. if (binding.value === binding.oldValue) return;
  29783. unmounted(el, binding);
  29784. mounted(el, binding);
  29785. }
  29786. const Scroll = {
  29787. mounted,
  29788. unmounted,
  29789. updated
  29790. };
  29791. // Utilities
  29792. // Types
  29793. function useDirectiveComponent(component, props) {
  29794. const concreteComponent = typeof component === 'string' ? vue.resolveComponent(component) : component;
  29795. const hook = mountComponent(concreteComponent, props);
  29796. return {
  29797. mounted: hook,
  29798. updated: hook,
  29799. unmounted(el) {
  29800. vue.render(null, el);
  29801. }
  29802. };
  29803. }
  29804. function mountComponent(component, props) {
  29805. return function (el, binding, vnode) {
  29806. const _props = typeof props === 'function' ? props(binding) : props;
  29807. const text = binding.value?.text ?? binding.value ?? _props?.text;
  29808. const value = isObject(binding.value) ? binding.value : {};
  29809. // Get the children from the props or directive value, or the element's children
  29810. const children = () => text ?? el.textContent;
  29811. // If vnode.ctx is the same as the instance, then we're bound to a plain element
  29812. // and need to find the nearest parent component instance to inherit provides from
  29813. const provides = (vnode.ctx === binding.instance.$ ? findComponentParent(vnode, binding.instance.$)?.provides : vnode.ctx?.provides) ?? binding.instance.$.provides;
  29814. const node = vue.h(component, vue.mergeProps(_props, value), children);
  29815. node.appContext = Object.assign(Object.create(null), binding.instance.$.appContext, {
  29816. provides
  29817. });
  29818. vue.render(node, el);
  29819. };
  29820. }
  29821. function findComponentParent(vnode, root) {
  29822. // Walk the tree from root until we find the child vnode
  29823. const stack = new Set();
  29824. const walk = children => {
  29825. for (const child of children) {
  29826. if (!child) continue;
  29827. if (child === vnode || child.el && vnode.el && child.el === vnode.el) {
  29828. return true;
  29829. }
  29830. stack.add(child);
  29831. let result;
  29832. if (child.suspense) {
  29833. result = walk([child.ssContent]);
  29834. } else if (Array.isArray(child.children)) {
  29835. result = walk(child.children);
  29836. } else if (child.component?.vnode) {
  29837. result = walk([child.component?.subTree]);
  29838. }
  29839. if (result) {
  29840. return result;
  29841. }
  29842. stack.delete(child);
  29843. }
  29844. return false;
  29845. };
  29846. if (!walk([root.subTree])) {
  29847. consoleError('Could not find original vnode, component will not inherit provides');
  29848. return root;
  29849. }
  29850. // Return the first component parent
  29851. const result = Array.from(stack).reverse();
  29852. for (const child of result) {
  29853. if (child.component) {
  29854. return child.component;
  29855. }
  29856. }
  29857. return root;
  29858. }
  29859. // Components
  29860. // Types
  29861. const Tooltip = useDirectiveComponent(VTooltip, binding => {
  29862. return {
  29863. activator: 'parent',
  29864. location: binding.arg?.replace('-', ' '),
  29865. text: typeof binding.value === 'boolean' ? undefined : binding.value
  29866. };
  29867. });
  29868. var directives = /*#__PURE__*/Object.freeze({
  29869. __proto__: null,
  29870. ClickOutside: ClickOutside,
  29871. Intersect: Intersect,
  29872. Mutate: Mutate,
  29873. Resize: Resize,
  29874. Ripple: Ripple,
  29875. Scroll: Scroll,
  29876. Tooltip: Tooltip,
  29877. Touch: Touch
  29878. });
  29879. // Composables
  29880. function createVuetify$1() {
  29881. let vuetify = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
  29882. const {
  29883. blueprint,
  29884. ...rest
  29885. } = vuetify;
  29886. const options = mergeDeep(blueprint, rest);
  29887. const {
  29888. aliases = {},
  29889. components = {},
  29890. directives = {}
  29891. } = options;
  29892. const defaults = createDefaults(options.defaults);
  29893. const display = createDisplay(options.display, options.ssr);
  29894. const theme = createTheme(options.theme);
  29895. const icons = createIcons(options.icons);
  29896. const locale = createLocale(options.locale);
  29897. const date = createDate(options.date, locale);
  29898. const goTo = createGoTo(options.goTo, locale);
  29899. const install = app => {
  29900. for (const key in directives) {
  29901. app.directive(key, directives[key]);
  29902. }
  29903. for (const key in components) {
  29904. app.component(key, components[key]);
  29905. }
  29906. for (const key in aliases) {
  29907. app.component(key, defineComponent({
  29908. ...aliases[key],
  29909. name: key,
  29910. aliasName: aliases[key].name
  29911. }));
  29912. }
  29913. theme.install(app);
  29914. app.provide(DefaultsSymbol, defaults);
  29915. app.provide(DisplaySymbol, display);
  29916. app.provide(ThemeSymbol, theme);
  29917. app.provide(IconSymbol, icons);
  29918. app.provide(LocaleSymbol, locale);
  29919. app.provide(DateOptionsSymbol, date.options);
  29920. app.provide(DateAdapterSymbol, date.instance);
  29921. app.provide(GoToSymbol, goTo);
  29922. if (IN_BROWSER && options.ssr) {
  29923. if (app.$nuxt) {
  29924. app.$nuxt.hook('app:suspense:resolve', () => {
  29925. display.update();
  29926. });
  29927. } else {
  29928. const {
  29929. mount
  29930. } = app;
  29931. app.mount = function () {
  29932. const vm = mount(...arguments);
  29933. vue.nextTick(() => display.update());
  29934. app.mount = mount;
  29935. return vm;
  29936. };
  29937. }
  29938. }
  29939. getUid.reset();
  29940. if (typeof __VUE_OPTIONS_API__ !== 'boolean' || __VUE_OPTIONS_API__) {
  29941. app.mixin({
  29942. computed: {
  29943. $vuetify() {
  29944. return vue.reactive({
  29945. defaults: inject.call(this, DefaultsSymbol),
  29946. display: inject.call(this, DisplaySymbol),
  29947. theme: inject.call(this, ThemeSymbol),
  29948. icons: inject.call(this, IconSymbol),
  29949. locale: inject.call(this, LocaleSymbol),
  29950. date: inject.call(this, DateAdapterSymbol)
  29951. });
  29952. }
  29953. }
  29954. });
  29955. }
  29956. };
  29957. return {
  29958. install,
  29959. defaults,
  29960. display,
  29961. theme,
  29962. icons,
  29963. locale,
  29964. date,
  29965. goTo
  29966. };
  29967. }
  29968. const version$1 = "3.7.6";
  29969. createVuetify$1.version = version$1;
  29970. // Vue's inject() can only be used in setup
  29971. function inject(key) {
  29972. const vm = this.$;
  29973. const provides = vm.parent?.provides ?? vm.vnode.appContext?.provides;
  29974. if (provides && key in provides) {
  29975. return provides[key];
  29976. }
  29977. }
  29978. // Icons
  29979. // Types
  29980. const md1 = {
  29981. defaults: {
  29982. global: {
  29983. rounded: 'sm'
  29984. },
  29985. VAvatar: {
  29986. rounded: 'circle'
  29987. },
  29988. VAutocomplete: {
  29989. variant: 'underlined'
  29990. },
  29991. VBanner: {
  29992. color: 'primary'
  29993. },
  29994. VBtn: {
  29995. color: 'primary',
  29996. rounded: 0
  29997. },
  29998. VCheckbox: {
  29999. color: 'secondary'
  30000. },
  30001. VCombobox: {
  30002. variant: 'underlined'
  30003. },
  30004. VSelect: {
  30005. variant: 'underlined'
  30006. },
  30007. VSlider: {
  30008. color: 'primary'
  30009. },
  30010. VTabs: {
  30011. color: 'primary'
  30012. },
  30013. VTextarea: {
  30014. variant: 'underlined'
  30015. },
  30016. VTextField: {
  30017. variant: 'underlined'
  30018. },
  30019. VToolbar: {
  30020. VBtn: {
  30021. color: null
  30022. }
  30023. }
  30024. },
  30025. icons: {
  30026. defaultSet: 'mdi',
  30027. sets: {
  30028. mdi
  30029. }
  30030. },
  30031. theme: {
  30032. themes: {
  30033. light: {
  30034. colors: {
  30035. primary: '#3F51B5',
  30036. 'primary-darken-1': '#303F9F',
  30037. 'primary-lighten-1': '#C5CAE9',
  30038. secondary: '#FF4081',
  30039. 'secondary-darken-1': '#F50057',
  30040. 'secondary-lighten-1': '#FF80AB',
  30041. accent: '#009688'
  30042. }
  30043. }
  30044. }
  30045. }
  30046. };
  30047. // Icons
  30048. // Types
  30049. const md2 = {
  30050. defaults: {
  30051. global: {
  30052. rounded: 'md'
  30053. },
  30054. VAvatar: {
  30055. rounded: 'circle'
  30056. },
  30057. VAutocomplete: {
  30058. variant: 'filled'
  30059. },
  30060. VBanner: {
  30061. color: 'primary'
  30062. },
  30063. VBtn: {
  30064. color: 'primary'
  30065. },
  30066. VCheckbox: {
  30067. color: 'secondary'
  30068. },
  30069. VCombobox: {
  30070. variant: 'filled'
  30071. },
  30072. VSelect: {
  30073. variant: 'filled'
  30074. },
  30075. VSlider: {
  30076. color: 'primary'
  30077. },
  30078. VTabs: {
  30079. color: 'primary'
  30080. },
  30081. VTextarea: {
  30082. variant: 'filled'
  30083. },
  30084. VTextField: {
  30085. variant: 'filled'
  30086. },
  30087. VToolbar: {
  30088. VBtn: {
  30089. color: null
  30090. }
  30091. }
  30092. },
  30093. icons: {
  30094. defaultSet: 'mdi',
  30095. sets: {
  30096. mdi
  30097. }
  30098. },
  30099. theme: {
  30100. themes: {
  30101. light: {
  30102. colors: {
  30103. primary: '#6200EE',
  30104. 'primary-darken-1': '#3700B3',
  30105. secondary: '#03DAC6',
  30106. 'secondary-darken-1': '#018786',
  30107. error: '#B00020'
  30108. }
  30109. }
  30110. }
  30111. }
  30112. };
  30113. // Icons
  30114. // Types
  30115. const md3 = {
  30116. defaults: {
  30117. VAppBar: {
  30118. flat: true
  30119. },
  30120. VAutocomplete: {
  30121. variant: 'filled'
  30122. },
  30123. VBanner: {
  30124. color: 'primary'
  30125. },
  30126. VBottomSheet: {
  30127. contentClass: 'rounded-t-xl overflow-hidden'
  30128. },
  30129. VBtn: {
  30130. color: 'primary',
  30131. rounded: 'xl'
  30132. },
  30133. VBtnGroup: {
  30134. rounded: 'xl',
  30135. VBtn: {
  30136. rounded: null
  30137. }
  30138. },
  30139. VCard: {
  30140. rounded: 'lg'
  30141. },
  30142. VCheckbox: {
  30143. color: 'secondary',
  30144. inset: true
  30145. },
  30146. VChip: {
  30147. rounded: 'sm'
  30148. },
  30149. VCombobox: {
  30150. variant: 'filled'
  30151. },
  30152. VNavigationDrawer: {
  30153. // VList: {
  30154. // nav: true,
  30155. // VListItem: {
  30156. // rounded: 'xl',
  30157. // },
  30158. // },
  30159. },
  30160. VSelect: {
  30161. variant: 'filled'
  30162. },
  30163. VSlider: {
  30164. color: 'primary'
  30165. },
  30166. VTabs: {
  30167. color: 'primary'
  30168. },
  30169. VTextarea: {
  30170. variant: 'filled'
  30171. },
  30172. VTextField: {
  30173. variant: 'filled'
  30174. },
  30175. VToolbar: {
  30176. VBtn: {
  30177. color: null
  30178. }
  30179. }
  30180. },
  30181. icons: {
  30182. defaultSet: 'mdi',
  30183. sets: {
  30184. mdi
  30185. }
  30186. },
  30187. theme: {
  30188. themes: {
  30189. light: {
  30190. colors: {
  30191. primary: '#6750a4',
  30192. secondary: '#b4b0bb',
  30193. tertiary: '#7d5260',
  30194. error: '#b3261e',
  30195. surface: '#fffbfe'
  30196. }
  30197. }
  30198. }
  30199. }
  30200. };
  30201. var index = /*#__PURE__*/Object.freeze({
  30202. __proto__: null,
  30203. md1: md1,
  30204. md2: md2,
  30205. md3: md3
  30206. });
  30207. /* eslint-disable local-rules/sort-imports */
  30208. const version = "3.7.6";
  30209. /* eslint-disable local-rules/sort-imports */
  30210. const createVuetify = function () {
  30211. let options = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
  30212. return createVuetify$1({
  30213. components,
  30214. directives,
  30215. ...options
  30216. });
  30217. };
  30218. exports.blueprints = index;
  30219. exports.components = components;
  30220. exports.createVuetify = createVuetify;
  30221. exports.directives = directives;
  30222. exports.useDate = useDate;
  30223. exports.useDefaults = useDefaults;
  30224. exports.useDisplay = useDisplay;
  30225. exports.useGoTo = useGoTo;
  30226. exports.useLayout = useLayout;
  30227. exports.useLocale = useLocale;
  30228. exports.useRtl = useRtl;
  30229. exports.useTheme = useTheme;
  30230. exports.version = version;
  30231. }));