UX consistancy changes.

This commit is contained in:
2026-04-16 18:41:01 -07:00
parent 8ff071c69b
commit 7545441a3e
675 changed files with 70964 additions and 593 deletions

View File

@@ -0,0 +1,37 @@
name: Bug 🐞
description: Report a bug
labels: [support, bug]
body:
- type: markdown
attributes:
value: |
Thanks for taking the time to fill out this bug report! ☺️
- type: textarea
attributes:
label: Steps to reproduce
validations:
required: true
- type: textarea
attributes:
label: What is expected?
validations:
required: true
- type: textarea
attributes:
label: What is actually happening?
validations:
required: true
- type: textarea
attributes:
label: Additional data
value: |
<!-- If technical bug
NodeJS Version:
Package manager(npm|yarn|pnpm):
Browser name & version:
System:
-->
<!-- If design file bug
Technology(figma|sketch):
-->

View File

@@ -0,0 +1 @@
blank_issues_enabled: false

View File

@@ -0,0 +1,18 @@
name: Feature request ✨
description: Suggest an idea or ask for a feature that you would like to have
labels: [support, feature-req]
body:
- type: markdown
attributes:
value: |
Thanks for letting us know how we can improve our product! ☺️
- type: textarea
attributes:
label: What problem does this feature solve?
validations:
required: true
- type: textarea
attributes:
label: What does the proposed solution look like?
validations:
required: true

View File

@@ -0,0 +1,51 @@
name: 🚀 Deploy Demo
on: [workflow_dispatch]
jobs:
build:
runs-on: ubuntu-latest
steps:
- name: ⚙️ Setup pnpm
uses: pnpm/action-setup@v3
with:
version: 8
- name: ⚙️ Set BRAND_NAME environment variable from repo name
run: echo BRAND_NAME=${{ github.event.repository.name }} | cut -d '-' -f1 >> $GITHUB_ENV
- name: ⬇️ Clone current repo under /<brand-name>/vue-free
uses: actions/checkout@v4
with:
path: ${{ env.BRAND_NAME }}/vue-free
- name: ⬇️ Clone automation scripts repo under /automation-scripts
uses: actions/checkout@v4
with:
repository: themeselection/automation-scripts
token: ${{ secrets.GH_PAT }}
path: automation-scripts
- name: ⬇️ Install packages in automation-scripts dir
working-directory: automation-scripts/vue
run: pnpm install
- name: ⚙️ Prepare free demo
working-directory: automation-scripts/vue
run: pnpm tsx src/templates/${{ env.BRAND_NAME }}/scripts/prepareVueFreeDemo.ts
- name: 📦 Generate demo
working-directory: ${{ env.BRAND_NAME }}/vue-free/typescript-version
run: pnpm i && pnpm build --base=/${{ env.BRAND_NAME }}-vuetify-vuejs-admin-template-free/demo/
- name: 🚀 Upload demo
uses: appleboy/scp-action@master
with:
HOST: ${{ secrets.HOST }}
USERNAME: ${{ secrets.USERNAME }}
PORT: ${{ secrets.PORT }}
KEY: ${{ secrets.SSHKEY }}
source: ${{ env.BRAND_NAME }}/vue-free/typescript-version/dist
target: ${{ secrets.PROD_DIR }}/demo
rm: true
strip_components: 4

View File

@@ -0,0 +1,14 @@
name: 'Handle new issue comment'
on:
issue_comment:
types: [created]
jobs:
handle_new_issue_comment:
runs-on: ubuntu-latest
name: Handle new issue comment
steps:
- name: Toggle awaiting-reply label
uses: jd-solanki/gh-action-toggle-awaiting-reply-label@v2.1.0
with:
label: awaiting-reply

View File

@@ -0,0 +1,19 @@
name: 'Handle new issue'
on:
issues:
types: [opened]
jobs:
handle_new_issue:
runs-on: ubuntu-latest
name: Handle new issue
steps:
- name: Find duplicates
uses: wow-actions/potential-duplicates@v1.0.8
with:
GITHUB_TOKEN: ${{ github.token }}
label: duplicate
comment: >
Potential duplicates: {{#issues}}
- #{{ number }} _({{ accuracy }}% Match)_
{{/issues}}

View File

@@ -0,0 +1,18 @@
name: 'Close stale issues and PRs'
on:
schedule:
- cron: '30 1 * * *'
jobs:
stale:
runs-on: ubuntu-latest
steps:
- uses: actions/stale@v4
with:
stale-issue-message: 'This issue has been automatically marked as stale because it has no recent activity. It will be closed if no further activity occurs. Thank you for raising the concern.'
close-issue-message: 'This issue has been automatically marked as closed because it has no recent activity.'
stale-issue-label: 'stale'
only-labels: 'awaiting-reply'
exempt-issue-labels: 'triage'
days-before-stale: 7
days-before-close: 7

View File

@@ -0,0 +1 @@
node_modules

View File

@@ -0,0 +1,87 @@
<!-- Available h3 headings: Added, Fixed, Updated, Removed, Deprecated -->
# Changelog
All notable changes to this template will be documented in this file
## v2.3.0 (2025-01-01)
### Updated
- Updated Vue & Vuetify to the latest version
## v2.2.2 (2024-07-29)
### Updated
- Updated all the libraries to the latest version
## v2.2.1 (2024-01-05)
### Added
- Added Hire Us file
- Added Documentation File
## v2.2.0 (2024-01-04)
### Updated
- Updated all dependencies and devDependencies to latest
### Added
- Added Remix Icons
### Removed
- Material Design icons removed
## v2.1.0 (2023-05-26)
### Updated
- Updated repo according to pro template
- Use Vuetify's official release instead of BETA
## v2.0.0 (2022-10-15)
### Added
- Vue 3 version added
- Vuetify 3 support added
- TypeScript version added (Vue 3 only)
## v1.0.3 (2021-11-12)
### Updated
- Updated [@vue/composition-api](https://github.com/vuejs/composition-api) package to v1.3.3 to mitigate composition api error
## v1.0.2 (2021-08-18)
### Fixed
- broken links updated in footer
## Updates
- "Basic Cards" page renamed to "Cards"
- `README.md` updated
## v1.0.1 (2021-08-13)
### Fixed
- Fixed missing fonts + branding updated
### Updated
- public path updated in `vue.config.js`
- `README.md` updated
## v1.0.0 (2021-08-13)
### Added
- Initial Release

View File

@@ -0,0 +1,21 @@
MIT License
Copyright (c) 2022 ThemeSelection
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

View File

@@ -0,0 +1,197 @@
<p align="center"></p>
<p align="center">
<a href="https://themeselection.com/item/materio-free-vuetify-vuejs-admin-template/" target="_blank">
<img src="https://cdn.themeselection.com/ts-assets/materio/logo/logo.png" alt="materio-logo" width="60px" height="auto">
</a>
</p>
<h1 align="center">
<a href="https://themeselection.com/item/materio-free-vuetify-vuejs-admin-template/" target="_blank" align="center">
Materio Vuetify Vuejs Admin Template Free
</a>
</h1>
<p align="center">Production Ready, Carefully Crafted, Extensive Vuetifty Admin Template</p>
<p align="center">
<a href="https://github.com/themeselection/materio-vuetify-vuejs-admin-template-free/blob/main/LICENSE">
<img src="https://img.shields.io/github/license/themeselection/materio-vuetify-vuejs-admin-template-free" alt="license">
</a>
<img alt="GitHub Workflow Status" src="https://img.shields.io/github/actions/workflow/status/themeselection/materio-vuetify-vuejs-admin-template-free/deploy-demos.yml">
<a href="https://github.com/themeselection/materio-vuetify-vuejs-admin-template-free/releases">
<img src="https://img.shields.io/github/release/themeselection/materio-vuetify-vuejs-admin-template-free.svg" alt="GitHub release">
</a>
<a href="https://twitter.com/Theme_Selection" target="_blank">
<img alt="Twitter Follow" src="https://img.shields.io/twitter/follow/Theme_Selection">
</a>
</p>
<kbd>[![Materio Vuetify Vuejs Admin Template Demo Screenshot](https://cdn.themeselection.com/ts-assets/materio/materio-vuetify-vuejs-admin-template-free/banner/banner.png)](https://themeselection.com/item/materio-free-vuetify-vuejs-admin-template/)</kbd>
## Introduction 🚀
If you're a developer looking for an admin dashboard that is developer-friendly, rich with features, and highly customizable look no further than Materio. We've followed the highest industry standards to bring you the very best [Vue Admin Template](https://themeselection.com/item/category/vuejs-admin-templates/) that is not only fast and easy to use but highly scalable. Offering ultimate convenience and flexibility, you'll be able to build whatever application you want with very little hassle.
- ⚡️ [Vue 3](https://github.com/vuejs/core), [Vite 3](https://github.com/vitejs/vite) & [Vuetify 3](https://next.vuetifyjs.com/en/) - Uses the latest Vuetify 3
- 🗂 [File based routing](https://github.com/hannoeru/vite-plugin-pages)
- 📦 [Components auto importing](https://github.com/antfu/unplugin-vue-components)
- 📑 [Layout system](https://github.com/JohnCampionJr/vite-plugin-vue-layouts)
- 😃 Use icons from any icon sets with classes by [Iconify](https://iconify.design/)
- 🌍 I18n ready
- 🔥 Use the [`<script setup>`](https://vuejs.org/api/sfc-script-setup.html) syntax
- 📥 [APIs auto importing](https://github.com/antfu/unplugin-auto-import) - use Composition API and others directly
- 🦾 TypeScript & JavaScript versions
[View Demo](https://demos.themeselection.com/materio-vuetify-vuejs-admin-template-free/demo/dashboard)
## Installation ⚒️
Please [visit](https://demos.themeselection.com/materio-vuetify-vuejs-admin-template/documentation/guide/installation.html) our docs for the installation guide.
## What's Included 📦
- Dashboard
- Account Settings
- Pages
- Login
- Register
- Error
- Typography
- Material Design Icons
- Cards
- Form layouts
- Horizontal Form
- Horizontal Form with Icons
- Vertical Form
- Vertical Form with Icons
- Multiple Column
- Tables
## What's in Premium Version 💎
| Materio Free Version | Materio Premium Version |
| ------------------------------------------------------------------------------------------------ | :--------------------------------------------------------------------------------------------- |
| [Demo](https://demos.themeselection.com/materio-vuetify-vuejs-admin-template-free/demo/dashboard) | [Demo](https://themeselection.com/item/materio-free-vuetify-vuejs-admin-template/?tab=details#details) |
| [Download](https://themeselection.com/item/materio-free-vuetify-vuejs-admin-template/) | [Purchase](https://themeselection.com/item/materio-vuetify-vuejs-admin-template/) |
| Single vertical menu | Vertical (+ vertical collapsed) & Horizontal menu |
| Simple Light/Dark theme | 3 Skin variants w/ light/dark theme support: Default, Bordered & Semi-dark |
| 1 Simple Dashboard | 3 Niche Dashboards |
| - | 5 API ready applications |
| Simple From Elements | Advance form elements, validation & form wizard |
| Basic Cards | Basic Cards + Advanced Cards + Statistics Cards |
| - | API ready JWT Authentication flow |
| - | Access Control (even on CRUD operations) |
| - | Quick Search - Quickly navigate between pages (w/ hotkey support) |
| Basic Pages | Authentication Pages in 2 variants + Ready-to-use pages like Pricing, FAQ, Knowledge base, etc |
| - | 3D Characters + Illustrations |
| Basic tables | Advanced tables |
| Manual customization | Quick customization using theme config file |
| - | Advanced Charts |
| 1 Chart Library | 2 Chart Libraries |
| - | Multiple Navbar & Menu Options |
| - | Starter-kit |
| - | Internationalization support in components |
| Regular Support | Priority Support |
| Basic Documentation
## Documentation 📜
Check out our live [Documentation](https://demos.themeselection.com/materio-vuetify-vuejs-admin-template/documentation/)
## Browser Support 🖥️
![chrome](https://github.com/nuxt/nuxt/assets/47495003/bbb6d7b0-2db6-4af4-abdc-a73de71dd287)
&nbsp;&nbsp;![firefox](https://github.com/nuxt/nuxt/assets/47495003/bca1f2d0-d597-453b-8525-5c94e36bfc33)
&nbsp;&nbsp;![safari](https://github.com/nuxt/nuxt/assets/47495003/8ecbb395-78fb-40fb-bb59-7301bf8a7e5d)
&nbsp;&nbsp;![Microsoft Edge](https://github.com/nuxt/nuxt/assets/47495003/f945821b-0cbd-464d-8103-824d4d5c4e9a)
*_It also supports other browser which implemented latest CSS standards_
## Contributing 🦸
Contributions are always welcome and recommended! Here is how:
- Fork the repository ([here is the guide](https://docs.github.com/en/get-started/quickstart/fork-a-repo)).
- Clone to your machine `git clone https://github.com/YOUR_USERNAME/REPO_NAME` Make your changes
- Create a pull request
### Contribution Requirements 🧰
- When you contribute, you agree to give a non-exclusive license to ThemeSelection to use that contribution in any context as we (ThemeSelection) see appropriate.
- If you use content provided by another party, it must be appropriately licensed using an open-source license.
- Contributions are only accepted through Github pull requests.
- Finally, the contributed code must work in all supported browsers (see above for browser support).
## Changelog 📆
Please refer to the [CHANGELOG](CHANGELOG.md) file. We will add detailed release notes to each new release.
## Support 🧑🏻‍💻
For free products, enjoy community support via GitHub issues. Upgrade to Premium for dedicated support from our expert team.
## License &copy;
- Copyright © [ThemeSelection](https://themeselection.com/)
- Licensed under [MIT](LICENSE)
- All our free items are Open Source and licensed under MIT. You can use our free items for personal as well as commercial purposes. We just need an attribution from your end. Copy the below link and paste it at the footer of your web application or project.
```html
<a href="https://themeselection.com/">ThemeSelection</a>
```
## Also Available In
<p>
<!-- Figma -->
<a href="https://themeselection.com/item/materio-figma-admin-dashboard-ui-kit/" target="_blank"><picture><source width="auto" height="74px" media="(prefers-color-scheme: dark)" srcset="https://github.com/microsoft/vscode/assets/47495003/0318a6c8-4f9b-4cf6-af5e-d357f909ea2b"><source width="auto" height="74px" media="(prefers-color-scheme: light)" srcset="https://github.com/microsoft/vscode/assets/47495003/47f21dfe-c1fc-4a7d-859e-4d98f8cdded1"><img width="auto" height="74px" alt="html" src="https://github.com/microsoft/vscode/assets/47495003/47f21dfe-c1fc-4a7d-859e-4d98f8cdded1"></picture></img></a>&nbsp;&nbsp;
<!-- HTML -->
<a href="https://themeselection.com/item/materio-bootstrap-html-admin-template/" target="_blank"><picture><source width="auto" height="74px" media="(prefers-color-scheme: dark)" srcset="https://github.com/microsoft/vscode/assets/47495003/5fe77c46-2e4c-475a-8dec-e30e2badddee"><source width="auto" height="74px" media="(prefers-color-scheme: light)" srcset="https://github.com/microsoft/vscode/assets/47495003/3f5decd8-cd99-4ed3-aa76-528ca061385b"><img width="auto" height="74px" alt="html" src="https://github.com/microsoft/vscode/assets/47495003/3f5decd8-cd99-4ed3-aa76-528ca061385b"></picture></img></a>&nbsp;&nbsp;
<!-- HTML + Laravel -->
<a href="https://themeselection.com/item/materio-bootstrap-laravel-admin-template/" target="_blank"><picture><source width="auto" height="74px" media="(prefers-color-scheme: dark)" srcset="https://github.com/microsoft/vscode/assets/47495003/efe420e4-9863-41b7-9eda-47ea94f21a62"><source width="auto" height="74px" media="(prefers-color-scheme: light)" srcset="https://github.com/microsoft/vscode/assets/47495003/be3b86e0-4d5e-4736-bf89-4267fb4d6710"><img width="auto" height="74px" alt="html_laravel" src="https://github.com/microsoft/vscode/assets/47495003/be3b86e0-4d5e-4736-bf89-4267fb4d6710"></picture></img></a>&nbsp;&nbsp;
<!-- HTML + Django -->
<a href="https://themeselection.com/item/materio-bootstrap-django-admin-template/" target="_blank"><picture><source width="auto" height="74px" media="(prefers-color-scheme: dark)" srcset="https://github.com/microsoft/vscode/assets/47495003/3c87d33b-1223-4aaa-a652-388dcb714c98"><source width="auto" height="74px" media="(prefers-color-scheme: light)" srcset="https://github.com/microsoft/vscode/assets/47495003/51db1947-eac1-466f-87fd-5a209010fe9c"><img width="auto" height="74px" alt="html_django" src="https://github.com/microsoft/vscode/assets/47495003/51db1947-eac1-466f-87fd-5a209010fe9c"></picture></img></a>&nbsp;&nbsp;
<!-- .Net Core -->
<a href="https://themeselection.com/item/materio-aspnet-core-mvc-admin-template/" target="_blank"><picture><source width="auto" height="74px" media="(prefers-color-scheme: dark)" srcset="https://github.com/microsoft/vscode/assets/47495003/6327fd7b-9c54-4189-a852-28551ad0e002"><source width="auto" height="74px" media="(prefers-color-scheme: light)" srcset="https://github.com/microsoft/vscode/assets/47495003/9856e9d5-021f-4573-902a-702e80dd0102"><img width="auto" height="74px" alt="net_core" src="https://github.com/microsoft/vscode/assets/47495003/9856e9d5-021f-4573-902a-702e80dd0102"></picture></img></a>&nbsp;&nbsp;
<!-- NextJS -->
<a href="https://themeselection.com/item/materio-mui-react-nextjs-admin-template/" target="_blank"><picture><source width="auto" height="74px" media="(prefers-color-scheme: dark)" srcset="https://github.com/microsoft/vscode/assets/47495003/66344629-6d21-4f92-9078-f479b39cb34e"><source width="auto" height="74px" media="(prefers-color-scheme: light)" srcset="https://github.com/microsoft/vscode/assets/47495003/e1daf4e1-3fa5-4a44-969a-6143ddd67310"><img width="auto" height="74px" alt="next.js" src="https://github.com/microsoft/vscode/assets/47495003/e1daf4e1-3fa5-4a44-969a-6143ddd67310"></picture></img></a>&nbsp;&nbsp;
<!-- React -->
<a href="{pro_react_version_item_page_link_on_themeselection}" target="_blank"><picture><source width="auto" height="74px" media="(prefers-color-scheme: dark)" srcset="https://github.com/microsoft/vscode/assets/47495003/3877046e-c652-4b3d-99e9-2e134da1d6cf"><source width="auto" height="74px" media="(prefers-color-scheme: light)" srcset="https://github.com/microsoft/vscode/assets/47495003/8c8c940e-d8f9-4213-a7f7-f8bc4968f169"><img width="auto" height="74px" alt="react" src="https://github.com/microsoft/vscode/assets/47495003/8c8c940e-d8f9-4213-a7f7-f8bc4968f169"></picture></img></a>&nbsp;&nbsp;
<!-- Vue -->
<a href="https://themeselection.com/item/materio-vuetify-vuejs-admin-template/" target="_blank"><picture><source width="auto" height="74px" media="(prefers-color-scheme: dark)" srcset="https://github.com/microsoft/vscode/assets/47495003/881bbbb8-d1c9-421c-9bce-4ea43dfa9e6e"><source width="auto" height="74px" media="(prefers-color-scheme: light)" srcset="https://github.com/microsoft/vscode/assets/47495003/b02d6473-0345-42c2-be58-e648806104fa"><img width="auto" height="74px" alt="vue" src="https://github.com/microsoft/vscode/assets/47495003/b02d6473-0345-42c2-be58-e648806104fa"></picture></img></a>&nbsp;&nbsp;
<!-- Vue + Laravel -->
<a href="https://themeselection.com/item/materio-vuetify-vuejs-laravel-admin-template/" target="_blank"><picture><source width="auto" height="74px" media="(prefers-color-scheme: dark)" srcset="https://github.com/microsoft/vscode/assets/47495003/20b6428e-3fa5-4f80-a389-9e4cd732c2de"><source width="auto" height="74px" media="(prefers-color-scheme: light)" srcset="https://github.com/microsoft/vscode/assets/47495003/3008d3eb-7b5b-4d9c-8563-837744a901da"><img width="auto" height="74px" alt="vue_laravel" src="https://github.com/microsoft/vscode/assets/47495003/3008d3eb-7b5b-4d9c-8563-837744a901da"></picture></img></a>&nbsp;&nbsp;
</p>
<!-- Add other pro variants here. You can get the logo URL from here: https://icones.js.org/collection/logos -->
## Looking For Premium Admin Templates ?? 👀
**[ThemeSelection](https://themeselection.com/)** provides Selected high quality, modern design, professional and easy-to-use **Fully Coded Dashboard Templates & UI Kits** to create your applications faster!
- [Bootstrap Admin Templates](https://themeselection.com/item/category/bootstrap-admin-template/)
- [VueJS Admin Templates](https://themeselection.com/item/category/vuejs-admin-templates/)
- [Laravel Admin Templates](https://themeselection.com/item/category/laravel-admin-templates/)
- [Django Admin Templates](https://themeselection.com/item/category/django-admin-template/)
- [React (NextJS) Admin Templates](https://themeselection.com/item/category/next-js-admin-template/)
- [ASP.Net Core Admin Templates](https://themeselection.com/item/category/asp-net-dashboard/)
- [Free UI Kits](https://themeselection.com/item/category/free-ui-kits/)
If you want to [Download Free Admin Templates](https://themeselection.com/item/category/free-admin-templates/) like Materio then do visit [ThemeSelection](https://themeselection.com/).
## Useful Links 🎁
- [Vue CheatSheet](https://vue-cheatsheet.themeselection.com/)
- [Freebies](https://themeselection.com/item/category/free-admin-templates/)
- [Download Free Admin Templates](https://themeselection.com/item/category/free-admin-templates/)
- [Bootstrap 5 CheatSheet](https://bootstrap-cheatsheet.themeselection.com/)
## Social Media :earth_africa:
- [Twitter](https://twitter.com/Theme_Selection)
- [Facebook](https://www.facebook.com/ThemeSelections/)
- [Pinterest](https://pinterest.com/themeselect/)
- [Instagram](https://www.instagram.com/themeselection/)
- [Discord](https://discord.gg/kBHkY7DekX)
- [YouTube](https://www.youtube.com/channel/UCuryo5s0CW4aP83itLjIdZg)

View File

@@ -0,0 +1,16 @@
<!DOCTYPE html>
<html>
<head>
<title>Materio - Vuetify Vuejs Admin Template Free</title>
<meta http-equiv="refresh"
content="0; URL=https://demos.themeselection.com/materio-vuetify-vuejs-admin-template/documentation/" />
</head>
<body>
<p>If you do not redirect please visit : <a
href="https://demos.themeselection.com/materio-vuetify-vuejs-admin-template/documentation/">https://demos.themeselection.com/materio-vuetify-vuejs-admin-template/documentation/</a>
</p>
</body>
</html>

View File

@@ -0,0 +1,14 @@
<!DOCTYPE html>
<html>
<head>
<title>Hire Us</title>
<meta http-equiv="refresh"
content="0; URL='https://themeselection.com/hire-us/'" />
</head>
<body>
<p>If you do not redirect please visit : <a href="https://themeselection.com/hire-us/">https://themeselection.com/hire-us/</a></p>
</body>
</html>

View File

@@ -0,0 +1,38 @@
# EditorConfig is awesome: https://EditorConfig.org
# top-most EditorConfig file
root = true
# Unix-style newlines with a newline ending every file
[*]
end_of_line = lf
insert_final_newline = true
# Matches multiple files with brace expansion notation
# Set default charset
[*.{js,py}]
charset = utf-8
# 4 space indentation
[*.py]
indent_style = space
indent_size = 4
# 2 space indentation
[*.{vue,scss,ts}]
indent_style = space
indent_size = 2
# Tab indentation (no size specified)
[Makefile]
indent_style = tab
# Indentation override for all JS under lib directory
[lib/**.js]
indent_style = space
indent_size = 2
# Matches the exact files either package.json or .travis.yml
[{package.json,.travis.yml}]
indent_style = space
indent_size = 2

View File

@@ -0,0 +1,329 @@
{
"globals": {
"Component": true,
"ComponentPublicInstance": true,
"ComputedRef": true,
"DirectiveBinding": true,
"EffectScope": true,
"ExtractDefaultPropTypes": true,
"ExtractPropTypes": true,
"ExtractPublicPropTypes": true,
"InjectionKey": true,
"MaybeRef": true,
"MaybeRefOrGetter": true,
"PropType": true,
"Ref": true,
"VNode": true,
"WritableComputedRef": true,
"acceptHMRUpdate": true,
"asyncComputed": true,
"autoResetRef": true,
"computed": true,
"computedAsync": true,
"computedEager": true,
"computedInject": true,
"computedWithControl": true,
"controlledComputed": true,
"controlledRef": true,
"createApp": true,
"createEventHook": true,
"createGenericProjection": true,
"createGlobalState": true,
"createInjectionState": true,
"createPinia": true,
"createProjection": true,
"createReactiveFn": true,
"createReusableTemplate": true,
"createSharedComposable": true,
"createTemplatePromise": true,
"createUnrefFn": true,
"customRef": true,
"debouncedRef": true,
"debouncedWatch": true,
"defineAsyncComponent": true,
"defineComponent": true,
"defineStore": true,
"eagerComputed": true,
"effectScope": true,
"extendRef": true,
"getActivePinia": true,
"getCurrentInstance": true,
"getCurrentScope": true,
"h": true,
"ignorableWatch": true,
"inject": true,
"injectLocal": true,
"isDefined": true,
"isProxy": true,
"isReactive": true,
"isReadonly": true,
"isRef": true,
"logicAnd": true,
"logicNot": true,
"logicOr": true,
"makeDestructurable": true,
"mapActions": true,
"mapGetters": true,
"mapState": true,
"mapStores": true,
"mapWritableState": true,
"markRaw": true,
"nextTick": true,
"onActivated": true,
"onBeforeMount": true,
"onBeforeRouteLeave": true,
"onBeforeRouteUpdate": true,
"onBeforeUnmount": true,
"onBeforeUpdate": true,
"onClickOutside": true,
"onDeactivated": true,
"onErrorCaptured": true,
"onKeyStroke": true,
"onLongPress": true,
"onMounted": true,
"onRenderTracked": true,
"onRenderTriggered": true,
"onScopeDispose": true,
"onServerPrefetch": true,
"onStartTyping": true,
"onUnmounted": true,
"onUpdated": true,
"onWatcherCleanup": true,
"pausableWatch": true,
"provide": true,
"provideLocal": true,
"reactify": true,
"reactifyObject": true,
"reactive": true,
"reactiveComputed": true,
"reactiveOmit": true,
"reactivePick": true,
"readonly": true,
"ref": true,
"refAutoReset": true,
"refDebounced": true,
"refDefault": true,
"refThrottled": true,
"refWithControl": true,
"resolveComponent": true,
"resolveRef": true,
"resolveUnref": true,
"setActivePinia": true,
"setMapStoreSuffix": true,
"shallowReactive": true,
"shallowReadonly": true,
"shallowRef": true,
"storeToRefs": true,
"syncRef": true,
"syncRefs": true,
"templateRef": true,
"throttledRef": true,
"throttledWatch": true,
"toRaw": true,
"toReactive": true,
"toRef": true,
"toRefs": true,
"toValue": true,
"triggerRef": true,
"tryOnBeforeMount": true,
"tryOnBeforeUnmount": true,
"tryOnMounted": true,
"tryOnScopeDispose": true,
"tryOnUnmounted": true,
"unref": true,
"unrefElement": true,
"until": true,
"useAbs": true,
"useActiveElement": true,
"useAnimate": true,
"useArrayDifference": true,
"useArrayEvery": true,
"useArrayFilter": true,
"useArrayFind": true,
"useArrayFindIndex": true,
"useArrayFindLast": true,
"useArrayIncludes": true,
"useArrayJoin": true,
"useArrayMap": true,
"useArrayReduce": true,
"useArraySome": true,
"useArrayUnique": true,
"useAsyncQueue": true,
"useAsyncState": true,
"useAttrs": true,
"useAverage": true,
"useBase64": true,
"useBattery": true,
"useBluetooth": true,
"useBreakpoints": true,
"useBroadcastChannel": true,
"useBrowserLocation": true,
"useCached": true,
"useCeil": true,
"useClamp": true,
"useClipboard": true,
"useClipboardItems": true,
"useCloned": true,
"useColorMode": true,
"useConfirmDialog": true,
"useCounter": true,
"useCssModule": true,
"useCssVar": true,
"useCssVars": true,
"useCurrentElement": true,
"useCycleList": true,
"useDark": true,
"useDateFormat": true,
"useDebounce": true,
"useDebounceFn": true,
"useDebouncedRefHistory": true,
"useDeviceMotion": true,
"useDeviceOrientation": true,
"useDevicePixelRatio": true,
"useDevicesList": true,
"useDisplayMedia": true,
"useDocumentVisibility": true,
"useDraggable": true,
"useDropZone": true,
"useElementBounding": true,
"useElementByPoint": true,
"useElementHover": true,
"useElementSize": true,
"useElementVisibility": true,
"useEventBus": true,
"useEventListener": true,
"useEventSource": true,
"useEyeDropper": true,
"useFavicon": true,
"useFetch": true,
"useFileDialog": true,
"useFileSystemAccess": true,
"useFloor": true,
"useFocus": true,
"useFocusWithin": true,
"useFps": true,
"useFullscreen": true,
"useGamepad": true,
"useGeolocation": true,
"useId": true,
"useIdle": true,
"useImage": true,
"useInfiniteScroll": true,
"useIntersectionObserver": true,
"useInterval": true,
"useIntervalFn": true,
"useKeyModifier": true,
"useLastChanged": true,
"useLink": true,
"useLocalStorage": true,
"useMagicKeys": true,
"useManualRefHistory": true,
"useMath": true,
"useMax": true,
"useMediaControls": true,
"useMediaQuery": true,
"useMemoize": true,
"useMemory": true,
"useMin": true,
"useModel": true,
"useMounted": true,
"useMouse": true,
"useMouseInElement": true,
"useMousePressed": true,
"useMutationObserver": true,
"useNavigatorLanguage": true,
"useNetwork": true,
"useNow": true,
"useObjectUrl": true,
"useOffsetPagination": true,
"useOnline": true,
"usePageLeave": true,
"useParallax": true,
"useParentElement": true,
"usePerformanceObserver": true,
"usePermission": true,
"usePointer": true,
"usePointerLock": true,
"usePointerSwipe": true,
"usePrecision": true,
"usePreferredColorScheme": true,
"usePreferredContrast": true,
"usePreferredDark": true,
"usePreferredLanguages": true,
"usePreferredReducedMotion": true,
"usePrevious": true,
"useProjection": true,
"useRafFn": true,
"useRefHistory": true,
"useResizeObserver": true,
"useRound": true,
"useRoute": true,
"useRouter": true,
"useScreenOrientation": true,
"useScreenSafeArea": true,
"useScriptTag": true,
"useScroll": true,
"useScrollLock": true,
"useSessionStorage": true,
"useShare": true,
"useSlots": true,
"useSorted": true,
"useSpeechRecognition": true,
"useSpeechSynthesis": true,
"useStepper": true,
"useStorageAsync": true,
"useStyleTag": true,
"useSum": true,
"useSupported": true,
"useSwipe": true,
"useTemplateRef": true,
"useTemplateRefsList": true,
"useTextDirection": true,
"useTextSelection": true,
"useTextareaAutosize": true,
"useThrottle": true,
"useThrottleFn": true,
"useThrottledRefHistory": true,
"useTimeAgo": true,
"useTimeout": true,
"useTimeoutFn": true,
"useTimeoutPoll": true,
"useTimestamp": true,
"useTitle": true,
"useToNumber": true,
"useToString": true,
"useToggle": true,
"useTransition": true,
"useTrunc": true,
"useUrlSearchParams": true,
"useUserMedia": true,
"useVModel": true,
"useVModels": true,
"useVibrate": true,
"useVirtualList": true,
"useWakeLock": true,
"useWebNotification": true,
"useWebSocket": true,
"useWebWorker": true,
"useWebWorkerFn": true,
"useWindowFocus": true,
"useWindowScroll": true,
"useWindowSize": true,
"watch": true,
"watchArray": true,
"watchAtMost": true,
"watchDebounced": true,
"watchDeep": true,
"watchEffect": true,
"watchIgnorable": true,
"watchImmediate": true,
"watchOnce": true,
"watchPausable": true,
"watchPostEffect": true,
"watchSyncEffect": true,
"watchThrottled": true,
"watchTriggerable": true,
"watchWithFilter": true,
"whenever": true
}
}

View File

@@ -0,0 +1,238 @@
module.exports = {
env: {
browser: true,
es2021: true,
},
extends: [
'.eslintrc-auto-import.json',
'plugin:vue/vue3-recommended',
'plugin:import/recommended',
'plugin:promise/recommended',
'plugin:sonarjs/recommended',
'plugin:case-police/recommended',
'plugin:regexp/recommended',
// 'plugin:unicorn/recommended',
],
parser: 'vue-eslint-parser',
parserOptions: {
ecmaVersion: 13,
sourceType: 'module',
},
plugins: [
'vue',
'regex',
'regexp',
],
ignorePatterns: ['src/plugins/iconify/*.js', 'node_modules', 'dist', '*.d.ts', 'vendor', '*.json'],
rules: {
'no-console': process.env.NODE_ENV === 'production' ? 'warn' : 'off',
'no-debugger': process.env.NODE_ENV === 'production' ? 'warn' : 'off',
// indentation (Already present in TypeScript)
'comma-spacing': ['error', { before: false, after: true }],
'key-spacing': ['error', { afterColon: true }],
'n/prefer-global/process': ['off'],
'sonarjs/cognitive-complexity': ['off'],
'vue/first-attribute-linebreak': ['error', {
singleline: 'beside',
multiline: 'below',
}],
// indentation (Already present in TypeScript)
'indent': ['error', 2],
// Enforce trailing comma (Already present in TypeScript)
'comma-dangle': ['error', 'always-multiline'],
// Enforce consistent spacing inside braces of object (Already present in TypeScript)
'object-curly-spacing': ['error', 'always'],
// Enforce camelCase naming convention
'camelcase': 'error',
// Disable max-len
'max-len': 'off',
// we don't want it
'semi': ['error', 'never'],
// add parens ony when required in arrow function
'arrow-parens': ['error', 'as-needed'],
// add new line above comment
'newline-before-return': 'error',
// add new line above comment
'lines-around-comment': [
'error',
{
beforeBlockComment: true,
beforeLineComment: true,
allowBlockStart: true,
allowClassStart: true,
allowObjectStart: true,
allowArrayStart: true,
// We don't want to add extra space above closing SECTION
ignorePattern: '!SECTION',
},
],
// Ignore _ as unused variable
'array-element-newline': ['error', 'consistent'],
'array-bracket-newline': ['error', 'consistent'],
'vue/multi-word-component-names': 'off',
'padding-line-between-statements': [
'error',
{ blankLine: 'always', prev: 'expression', next: 'const' },
{ blankLine: 'always', prev: 'const', next: 'expression' },
{ blankLine: 'always', prev: 'multiline-const', next: '*' },
{ blankLine: 'always', prev: '*', next: 'multiline-const' },
],
// Plugin: eslint-plugin-import
'import/prefer-default-export': 'off',
'import/newline-after-import': ['error', { count: 1 }],
'no-restricted-imports': ['error', 'vuetify/components', {
name: 'vue3-apexcharts',
message: 'apexcharts are auto imported',
}],
// For omitting extension for ts files
'import/extensions': [
'error',
'ignorePackages',
{
js: 'never',
jsx: 'never',
ts: 'never',
tsx: 'never',
},
],
// ignore virtual files
'import/no-unresolved': [2, {
ignore: [
'~pages$',
'virtual:generated-layouts',
'#auth$',
'#components$',
// Ignore vite's ?raw imports
'.*\?raw',
],
}],
// Thanks: https://stackoverflow.com/a/63961972/10796681
'no-shadow': 'off',
// Plugin: eslint-plugin-promise
'promise/always-return': 'off',
'promise/catch-or-return': 'off',
// ESLint plugin vue
'vue/block-tag-newline': 'error',
'vue/component-api-style': 'error',
'vue/component-name-in-template-casing': ['error', 'PascalCase', { registeredComponentsOnly: false, ignores: ['/^swiper-/'] }],
'vue/custom-event-name-casing': ['error', 'camelCase', {
ignores: [
'/^(click):[a-z]+((\d)|([A-Z0-9][a-z0-9]+))*([A-Z])?/',
],
}],
'vue/define-macros-order': 'error',
'vue/html-comment-content-newline': 'error',
'vue/html-comment-content-spacing': 'error',
'vue/html-comment-indent': 'error',
'vue/match-component-file-name': 'error',
'vue/no-child-content': 'error',
'vue/require-default-prop': 'off',
'vue/no-duplicate-attr-inheritance': 'error',
'vue/no-empty-component-block': 'error',
'vue/no-multiple-objects-in-class': 'error',
'vue/no-reserved-component-names': 'error',
'vue/no-template-target-blank': 'error',
'vue/no-useless-mustaches': 'error',
'vue/no-useless-v-bind': 'error',
'vue/padding-line-between-blocks': 'error',
'vue/prefer-separate-static-class': 'error',
'vue/prefer-true-attribute-shorthand': 'error',
'vue/v-on-function-call': 'error',
'vue/no-restricted-class': ['error', '/^(p|m)(l|r)-/'],
'vue/valid-v-slot': ['error', {
allowModifiers: true,
}],
// -- Extension Rules
'vue/no-irregular-whitespace': 'error',
'vue/template-curly-spacing': 'error',
// -- Sonarlint
'sonarjs/no-duplicate-string': 'off',
'sonarjs/no-nested-template-literals': 'off',
// -- Unicorn
// 'unicorn/filename-case': 'off',
// 'unicorn/prevent-abbreviations': ['error', {
// replacements: {
// props: false,
// },
// }],
// Internal Rules
// https://github.com/gmullerb/eslint-plugin-regex
'regex/invalid': [
'error',
[
{
regex: '@/assets/images',
replacement: '@images',
message: 'Use \'@images\' path alias for image imports',
},
{
regex: '@/assets/styles',
replacement: '@styles',
message: 'Use \'@styles\' path alias for importing styles from \'src/assets/styles\'',
},
{
id: 'Disallow icon of icon library',
regex: 'mdi-\\w',
message: 'Only \'remix\' icons are allowed',
},
{
regex: '@core/\\w',
message: 'You can\'t use @core when you are in @layouts module',
files: {
inspect: '@layouts/.*',
},
},
{
regex: 'useLayouts\\(',
message: '`useLayouts` composable is only allowed in @layouts & @core directory. Please use `useThemeConfig` composable instead.',
files: {
inspect: '^(?!.*(@core|@layouts)).*',
},
},
],
// Ignore files
'\.eslintrc\.cjs',
],
},
settings: {
'import/resolver': {
node: true,
typescript: { project: './jsconfig.json' },
},
},
}

View File

@@ -0,0 +1,207 @@
## GITATTRIBUTES FOR WEB PROJECTS
#
# These settings are for any web project.
#
# Details per file setting:
# text These files should be normalized (i.e. convert CRLF to LF).
# binary These files are binary and should be left untouched.
#
# Note that binary is a macro for -text -diff.
######################################################################
# Auto detect
## Handle line endings automatically for files detected as
## text and leave all files detected as binary untouched.
## This will handle all files NOT defined below.
* text=auto
# Source code
*.bash text eol=lf
*.bat text eol=crlf
*.cmd text eol=crlf
*.coffee text
*.css text diff=css
*.htm text diff=html
*.html text diff=html
*.inc text
*.ini text
*.js text
*.json text
*.jsx text
*.less text
*.ls text
*.map text -diff
*.od text
*.onlydata text
*.php text diff=php
*.pl text
*.ps1 text eol=crlf
*.py text diff=python
*.rb text diff=ruby
*.sass text
*.scm text
*.scss text diff=css
*.sh text eol=lf
.husky/* text eol=lf
*.sql text
*.styl text
*.tag text
*.ts text
*.tsx text
*.xml text
*.xhtml text diff=html
# Docker
Dockerfile text
# Documentation
*.ipynb text eol=lf
*.markdown text diff=markdown
*.md text diff=markdown
*.mdwn text diff=markdown
*.mdown text diff=markdown
*.mkd text diff=markdown
*.mkdn text diff=markdown
*.mdtxt text
*.mdtext text
*.txt text
AUTHORS text
CHANGELOG text
CHANGES text
CONTRIBUTING text
COPYING text
copyright text
*COPYRIGHT* text
INSTALL text
license text
LICENSE text
NEWS text
readme text
*README* text
TODO text
# Templates
*.dot text
*.ejs text
*.erb text
*.haml text
*.handlebars text
*.hbs text
*.hbt text
*.jade text
*.latte text
*.mustache text
*.njk text
*.phtml text
*.svelte text
*.tmpl text
*.tpl text
*.twig text
*.vue text
# Configs
*.cnf text
*.conf text
*.config text
.editorconfig text
.env text
.gitattributes text
.gitconfig text
.htaccess text
*.lock text -diff
package.json text eol=lf
package-lock.json text eol=lf -diff
pnpm-lock.yaml text eol=lf -diff
.prettierrc text
yarn.lock text -diff
*.toml text
*.yaml text
*.yml text
browserslist text
Makefile text
makefile text
# Heroku
Procfile text
# Graphics
*.ai binary
*.bmp binary
*.eps binary
*.gif binary
*.gifv binary
*.ico binary
*.jng binary
*.jp2 binary
*.jpg binary
*.jpeg binary
*.jpx binary
*.jxr binary
*.pdf binary
*.png binary
*.psb binary
*.psd binary
# SVG treated as an asset (binary) by default.
*.svg text
# If you want to treat it as binary,
# use the following line instead.
# *.svg binary
*.svgz binary
*.tif binary
*.tiff binary
*.wbmp binary
*.webp binary
# Audio
*.kar binary
*.m4a binary
*.mid binary
*.midi binary
*.mp3 binary
*.ogg binary
*.ra binary
# Video
*.3gpp binary
*.3gp binary
*.as binary
*.asf binary
*.asx binary
*.avi binary
*.fla binary
*.flv binary
*.m4v binary
*.mng binary
*.mov binary
*.mp4 binary
*.mpeg binary
*.mpg binary
*.ogv binary
*.swc binary
*.swf binary
*.webm binary
# Archives
*.7z binary
*.gz binary
*.jar binary
*.rar binary
*.tar binary
*.zip binary
# Fonts
*.ttf binary
*.eot binary
*.otf binary
*.woff binary
*.woff2 binary
# Executables
*.exe binary
*.pyc binary
# RC files (like .babelrc or .eslintrc)
*.*rc text
# Ignore files (like .npmignore or .gitignore)
*.*ignore text

View File

@@ -0,0 +1,43 @@
# Logs
logs
*.log
npm-debug.log*
yarn-debug.log*
yarn-error.log*
pnpm-debug.log*
lerna-debug.log*
node_modules
.DS_Store
dist
dist-ssr
*.local
/cypress/videos/
/cypress/screenshots/
# 👉 Custom Git ignores
# Editor directories and files
.vscode/*
!.vscode/extensions.json
!.vscode/settings.json
!.vscode/*.code-snippets
!.vscode/tours
.idea
*.suo
*.ntvs*
*.njsproj
*.sln
*.sw?
.yarn
# iconify dist files
src/plugins/iconify/icons.css
# Ignore MSW script
public/mockServiceWorker.js
# Env files
.env*
!.env.example

View File

@@ -0,0 +1,2 @@
auto-install-peers=true
shamefully-hoist=true

View File

@@ -0,0 +1,2 @@
dist
node_modules

View File

@@ -0,0 +1,20 @@
{
"arrowParens": "avoid",
"bracketSpacing": true,
"htmlWhitespaceSensitivity": "css",
"insertPragma": false,
"jsxBracketSameLine": false,
"jsxSingleQuote": true,
"printWidth": 120,
"proseWrap": "preserve",
"quoteProps": "as-needed",
"requirePragma": false,
"semi": false,
"singleQuote": true,
"tabWidth": 2,
"trailingComma": "all",
"useTabs": false,
"vueIndentScriptAndStyle": false,
"endOfLine": "lf",
"singleAttributePerLine": true
}

View File

@@ -0,0 +1,46 @@
{
"extends": [
"stylelint-config-standard-scss",
"stylelint-config-idiomatic-order",
"@stylistic/stylelint-config"
],
"plugins": [
"stylelint-use-logical-spec",
"@stylistic/stylelint-plugin"
],
"overrides": [
{
"files": [
"**/*.scss"
],
"customSyntax": "postcss-scss"
},
{
"files": [
"**/*.vue"
],
"customSyntax": "postcss-html"
}
],
"rules": {
"@stylistic/max-line-length": [
220,
{
"ignore": "comments"
}
],
"@stylistic/indentation": 2,
"liberty/use-logical-spec": true,
"selector-class-pattern": null,
"color-function-notation": null,
"annotation-no-unknown": [
true,
{
"ignoreAnnotations": [
"default"
]
}
],
"media-feature-range-notation": null
}
}

View File

@@ -0,0 +1,23 @@
{
"Add hand emoji": {
"prefix": "cm-hand-emoji",
"body": [
"👉"
],
"description": "Add hand emoji"
},
"Add info emoji": {
"prefix": "cm-info-emoji",
"body": [
""
],
"description": "Add info emoji"
},
"Add warning emoji": {
"prefix": "cm-warning-emoji",
"body": [
"❗"
],
"description": "Add warning emoji"
}
}

View File

@@ -0,0 +1,15 @@
{
"recommendations": [
"dbaeumer.vscode-eslint",
"editorconfig.editorconfig",
"xabikos.javascriptsnippets",
"stylelint.vscode-stylelint",
"fabiospampinato.vscode-highlight",
"github.vscode-pull-request-github",
"vue.volar",
"antfu.iconify",
"cipchk.cssrem",
"matijao.vue-nuxt-snippets",
"dongido.sync-env"
]
}

View File

@@ -0,0 +1,109 @@
{
"editor.formatOnSave": true,
"files.insertFinalNewline": true,
"javascript.updateImportsOnFileMove.enabled": "always",
"[javascript]": {
"editor.defaultFormatter": "dbaeumer.vscode-eslint"
},
"[typescript]": {
"editor.defaultFormatter": "dbaeumer.vscode-eslint",
"editor.autoClosingBrackets": "always"
},
"[markdown]": {
"editor.defaultFormatter": "DavidAnson.vscode-markdownlint"
},
// SCSS
"[scss]": {
"editor.defaultFormatter": "stylelint.vscode-stylelint"
},
// JSON
"[json]": {
"editor.defaultFormatter": "vscode.json-language-features"
},
"[jsonc]": {
"editor.defaultFormatter": "vscode.json-language-features"
},
// Vue
"[vue]": {
"editor.defaultFormatter": "dbaeumer.vscode-eslint",
},
// Extension: Volar
"volar.preview.port": 3000,
"volar.completion.preferredTagNameCase": "pascal",
// Extension: ESLint
"editor.codeActionsOnSave": {
"source.fixAll.eslint": "explicit",
"source.fixAll.stylelint": "explicit",
"source.organizeImports": "explicit"
},
"eslint.alwaysShowStatus": true,
"eslint.format.enable": true,
"eslint.packageManager": "pnpm",
// Extension: Stylelint
"stylelint.packageManager": "pnpm",
"stylelint.validate": [
"css",
"scss",
"vue"
],
// Extension: Spell Checker
"cSpell.words": [
"Composables",
"Customizer",
"destr",
"flagpack",
"Iconify",
"ofetch",
"psudo",
"stylelint",
"touchless",
"triggerer",
"vuetify",
"nuxt"
],
// Extension: Comment Anchors
"commentAnchors.tags.anchors": {
"": {
"scope": "hidden",
// This color is taken from "Better Comments" Extension (?)
"highlightColor": "#3498DB",
"styleComment": true,
"isItalic": false,
},
"👉": {
"scope": "file",
// This color is taken from "Better Comments" Extension (*)
"highlightColor": "#98C379",
"styleComment": true,
"isItalic": false
},
"❗": {
"scope": "hidden",
// This color is taken from "Better Comments" Extension (*)
"highlightColor": "#FF2D00",
"styleComment": true,
"isItalic": false,
},
},
// Extension: fabiospampinato.vscode-highlight
"highlight.regexFlags": "gi",
"highlight.regexes": {
// We flaged this for enforcing logical CSS properties
"(100vh|translate|margin:|padding:|margin-left|margin-right|rotate|text-align|border-top|border-right|border-bottom|border-left|float|background-position|transform|width|height|top|left|bottom|right|float|clear|(p|m)(l|r)-|border-(start|end)-(start|end)-radius)": [
{
// "rangeBehavior": 1,
"borderWidth": "1px",
"borderColor": "tomato",
"borderStyle": "solid"
}
],
"(overflow-x:|overflow-y:)": [
{
// "rangeBehavior": 1,
"borderWidth": "1px",
"borderColor": "green",
"borderStyle": "solid"
}
]
}
}

View File

@@ -0,0 +1,18 @@
{
"Vue TS - DefineProps": {
"prefix": "dprops",
"body": [
"defineProps<${1:Props}>()"
],
"description": "DefineProps in script setup"
},
"Vue TS - Props interface": {
"prefix": "iprops",
"body": [
"interface Props {",
" ${1}",
"}"
],
"description": "Create props interface in script setup"
}
}

View File

@@ -0,0 +1,63 @@
{
"script": {
"prefix": "vue-sfc-ts",
"body": [
"<script lang=\"ts\" setup>",
"",
"</script>",
"",
"<template>",
" ",
"</template>",
"",
"<style lang=\"scss\">",
"",
"</style>",
""
],
"description": "Vue SFC Typescript"
},
"template": {
"scope": "vue",
"prefix": "template",
"body": [
"<template>",
" $1",
"</template>"
],
"description": "Create <template> block"
},
"Script setup + TS": {
"prefix": "script-setup-ts",
"body": [
"<script setup lang=\"ts\">",
"${1}",
"</script>"
],
"description": "Script setup + TS"
},
"style": {
"scope": "vue",
"prefix": "style",
"body": [
"<style lang=\"scss\">",
"$1",
"</style>"
],
"description": "Create <style> block"
},
"use composable": {
"prefix": "use-composable",
"body": [
"const { $2 } = ${1:useComposable}()"
],
"description": "We frequently uses composable in our components and writing const {} = useModule() is tedious. This snippet helps you to write it quickly."
},
"template interpolation": {
"prefix": "cc",
"body": [
"{{ ${1} }}"
],
"description": "We are just making writing template interpolation easier."
}
}

View File

@@ -0,0 +1,52 @@
{
"Vuetify Menu -- Parent Activator": {
"prefix": "v-menu",
"body": [
"<v-btn color=\"primary\">",
" Activator",
" <v-menu activator=\"parent\">",
" <v-list>",
" <v-list-item",
" v-for=\"(item, index) in ['apple', 'banana', 'cherry']\"",
" :key=\"index\"",
" :value=\"index\"",
" >",
" <v-list-item-title>{{ item }}</v-list-item-title>",
" </v-list-item>",
" </v-list>",
" </v-menu>",
"</v-btn>"
],
"description": "We use menu component with parent activator mostly because it is compact and easy to understand."
},
"Vuetify CSS variable": {
"prefix": "v-css-var",
"body": [
"rgb(var(--v-${1:theme}))"
],
"description": "Vuetify CSS variable"
},
"Icon only button": {
"prefix": "IconBtn",
"body": [
"<IconBtn>",
" <VIcon icon=\"ri-${1}\" />",
"</IconBtn>"
],
"description": "Icon only button"
},
"Radio Group": {
"prefix": "v-radio-grp",
"body": [
"<v-radio-group v-model=\"${1:modelValue}\">",
" <v-radio",
" v-for=\"item in ['apple', 'banana', 'cherry']\"",
" :key=\"item\"",
" :label=\"item\"",
" :value=\"item\"",
" />",
"</v-radio-group>"
],
"description": "Radio Group"
}
}

View File

@@ -0,0 +1,35 @@
# vue
This template should help get you started developing with Vue 3 in Vite.
## Recommended IDE Setup
[VS Code](https://code.visualstudio.com/) + [Volar](https://marketplace.visualstudio.com/items?itemName=johnsoncodehk.volar) (and disable Vetur).
## Type Support for `.vue` Imports in TS
Since TypeScript cannot handle type information for `.vue` imports, they are shimmed to be a generic Vue component type by default. In most cases this is fine if you don't really care about component prop types outside of templates.
However, if you wish to get actual prop types in `.vue` imports (for example to get props validation when using manual `h(...)` calls), you can run `Volar: Switch TS Plugin on/off` from VS Code command palette.
## Customize configuration
See [Vite Configuration Reference](https://vitejs.dev/config/).
## Project Setup
```sh
npm install
```
### Compile and Hot-Reload for Development
```sh
npm run dev
```
### Type-Check, Compile and Minify for Production
```sh
npm run build
```

View File

@@ -0,0 +1,645 @@
/* eslint-disable */
/* prettier-ignore */
// @ts-nocheck
// noinspection JSUnusedGlobalSymbols
// Generated by unplugin-auto-import
// biome-ignore lint: disable
export {}
declare global {
const EffectScope: typeof import('vue')['EffectScope']
const acceptHMRUpdate: typeof import('pinia')['acceptHMRUpdate']
const asyncComputed: typeof import('@vueuse/core')['asyncComputed']
const autoResetRef: typeof import('@vueuse/core')['autoResetRef']
const computed: typeof import('vue')['computed']
const computedAsync: typeof import('@vueuse/core')['computedAsync']
const computedEager: typeof import('@vueuse/core')['computedEager']
const computedInject: typeof import('@vueuse/core')['computedInject']
const computedWithControl: typeof import('@vueuse/core')['computedWithControl']
const controlledComputed: typeof import('@vueuse/core')['controlledComputed']
const controlledRef: typeof import('@vueuse/core')['controlledRef']
const createApp: typeof import('vue')['createApp']
const createEventHook: typeof import('@vueuse/core')['createEventHook']
const createGenericProjection: typeof import('@vueuse/math')['createGenericProjection']
const createGlobalState: typeof import('@vueuse/core')['createGlobalState']
const createInjectionState: typeof import('@vueuse/core')['createInjectionState']
const createPinia: typeof import('pinia')['createPinia']
const createProjection: typeof import('@vueuse/math')['createProjection']
const createReactiveFn: typeof import('@vueuse/core')['createReactiveFn']
const createReusableTemplate: typeof import('@vueuse/core')['createReusableTemplate']
const createSharedComposable: typeof import('@vueuse/core')['createSharedComposable']
const createTemplatePromise: typeof import('@vueuse/core')['createTemplatePromise']
const createUnrefFn: typeof import('@vueuse/core')['createUnrefFn']
const customRef: typeof import('vue')['customRef']
const debouncedRef: typeof import('@vueuse/core')['debouncedRef']
const debouncedWatch: typeof import('@vueuse/core')['debouncedWatch']
const defineAsyncComponent: typeof import('vue')['defineAsyncComponent']
const defineComponent: typeof import('vue')['defineComponent']
const defineStore: typeof import('pinia')['defineStore']
const eagerComputed: typeof import('@vueuse/core')['eagerComputed']
const effectScope: typeof import('vue')['effectScope']
const extendRef: typeof import('@vueuse/core')['extendRef']
const getActivePinia: typeof import('pinia')['getActivePinia']
const getCurrentInstance: typeof import('vue')['getCurrentInstance']
const getCurrentScope: typeof import('vue')['getCurrentScope']
const h: typeof import('vue')['h']
const ignorableWatch: typeof import('@vueuse/core')['ignorableWatch']
const inject: typeof import('vue')['inject']
const injectLocal: typeof import('@vueuse/core')['injectLocal']
const isDefined: typeof import('@vueuse/core')['isDefined']
const isProxy: typeof import('vue')['isProxy']
const isReactive: typeof import('vue')['isReactive']
const isReadonly: typeof import('vue')['isReadonly']
const isRef: typeof import('vue')['isRef']
const logicAnd: typeof import('@vueuse/math')['logicAnd']
const logicNot: typeof import('@vueuse/math')['logicNot']
const logicOr: typeof import('@vueuse/math')['logicOr']
const makeDestructurable: typeof import('@vueuse/core')['makeDestructurable']
const mapActions: typeof import('pinia')['mapActions']
const mapGetters: typeof import('pinia')['mapGetters']
const mapState: typeof import('pinia')['mapState']
const mapStores: typeof import('pinia')['mapStores']
const mapWritableState: typeof import('pinia')['mapWritableState']
const markRaw: typeof import('vue')['markRaw']
const nextTick: typeof import('vue')['nextTick']
const onActivated: typeof import('vue')['onActivated']
const onBeforeMount: typeof import('vue')['onBeforeMount']
const onBeforeRouteLeave: typeof import('vue-router')['onBeforeRouteLeave']
const onBeforeRouteUpdate: typeof import('vue-router')['onBeforeRouteUpdate']
const onBeforeUnmount: typeof import('vue')['onBeforeUnmount']
const onBeforeUpdate: typeof import('vue')['onBeforeUpdate']
const onClickOutside: typeof import('@vueuse/core')['onClickOutside']
const onDeactivated: typeof import('vue')['onDeactivated']
const onErrorCaptured: typeof import('vue')['onErrorCaptured']
const onKeyStroke: typeof import('@vueuse/core')['onKeyStroke']
const onLongPress: typeof import('@vueuse/core')['onLongPress']
const onMounted: typeof import('vue')['onMounted']
const onRenderTracked: typeof import('vue')['onRenderTracked']
const onRenderTriggered: typeof import('vue')['onRenderTriggered']
const onScopeDispose: typeof import('vue')['onScopeDispose']
const onServerPrefetch: typeof import('vue')['onServerPrefetch']
const onStartTyping: typeof import('@vueuse/core')['onStartTyping']
const onUnmounted: typeof import('vue')['onUnmounted']
const onUpdated: typeof import('vue')['onUpdated']
const onWatcherCleanup: typeof import('vue')['onWatcherCleanup']
const pausableWatch: typeof import('@vueuse/core')['pausableWatch']
const provide: typeof import('vue')['provide']
const provideLocal: typeof import('@vueuse/core')['provideLocal']
const reactify: typeof import('@vueuse/core')['reactify']
const reactifyObject: typeof import('@vueuse/core')['reactifyObject']
const reactive: typeof import('vue')['reactive']
const reactiveComputed: typeof import('@vueuse/core')['reactiveComputed']
const reactiveOmit: typeof import('@vueuse/core')['reactiveOmit']
const reactivePick: typeof import('@vueuse/core')['reactivePick']
const readonly: typeof import('vue')['readonly']
const ref: typeof import('vue')['ref']
const refAutoReset: typeof import('@vueuse/core')['refAutoReset']
const refDebounced: typeof import('@vueuse/core')['refDebounced']
const refDefault: typeof import('@vueuse/core')['refDefault']
const refThrottled: typeof import('@vueuse/core')['refThrottled']
const refWithControl: typeof import('@vueuse/core')['refWithControl']
const resolveComponent: typeof import('vue')['resolveComponent']
const resolveRef: typeof import('@vueuse/core')['resolveRef']
const resolveUnref: typeof import('@vueuse/core')['resolveUnref']
const setActivePinia: typeof import('pinia')['setActivePinia']
const setMapStoreSuffix: typeof import('pinia')['setMapStoreSuffix']
const shallowReactive: typeof import('vue')['shallowReactive']
const shallowReadonly: typeof import('vue')['shallowReadonly']
const shallowRef: typeof import('vue')['shallowRef']
const storeToRefs: typeof import('pinia')['storeToRefs']
const syncRef: typeof import('@vueuse/core')['syncRef']
const syncRefs: typeof import('@vueuse/core')['syncRefs']
const templateRef: typeof import('@vueuse/core')['templateRef']
const throttledRef: typeof import('@vueuse/core')['throttledRef']
const throttledWatch: typeof import('@vueuse/core')['throttledWatch']
const toRaw: typeof import('vue')['toRaw']
const toReactive: typeof import('@vueuse/core')['toReactive']
const toRef: typeof import('vue')['toRef']
const toRefs: typeof import('vue')['toRefs']
const toValue: typeof import('vue')['toValue']
const triggerRef: typeof import('vue')['triggerRef']
const tryOnBeforeMount: typeof import('@vueuse/core')['tryOnBeforeMount']
const tryOnBeforeUnmount: typeof import('@vueuse/core')['tryOnBeforeUnmount']
const tryOnMounted: typeof import('@vueuse/core')['tryOnMounted']
const tryOnScopeDispose: typeof import('@vueuse/core')['tryOnScopeDispose']
const tryOnUnmounted: typeof import('@vueuse/core')['tryOnUnmounted']
const unref: typeof import('vue')['unref']
const unrefElement: typeof import('@vueuse/core')['unrefElement']
const until: typeof import('@vueuse/core')['until']
const useAbs: typeof import('@vueuse/math')['useAbs']
const useActiveElement: typeof import('@vueuse/core')['useActiveElement']
const useAnimate: typeof import('@vueuse/core')['useAnimate']
const useArrayDifference: typeof import('@vueuse/core')['useArrayDifference']
const useArrayEvery: typeof import('@vueuse/core')['useArrayEvery']
const useArrayFilter: typeof import('@vueuse/core')['useArrayFilter']
const useArrayFind: typeof import('@vueuse/core')['useArrayFind']
const useArrayFindIndex: typeof import('@vueuse/core')['useArrayFindIndex']
const useArrayFindLast: typeof import('@vueuse/core')['useArrayFindLast']
const useArrayIncludes: typeof import('@vueuse/core')['useArrayIncludes']
const useArrayJoin: typeof import('@vueuse/core')['useArrayJoin']
const useArrayMap: typeof import('@vueuse/core')['useArrayMap']
const useArrayReduce: typeof import('@vueuse/core')['useArrayReduce']
const useArraySome: typeof import('@vueuse/core')['useArraySome']
const useArrayUnique: typeof import('@vueuse/core')['useArrayUnique']
const useAsyncQueue: typeof import('@vueuse/core')['useAsyncQueue']
const useAsyncState: typeof import('@vueuse/core')['useAsyncState']
const useAttrs: typeof import('vue')['useAttrs']
const useAverage: typeof import('@vueuse/math')['useAverage']
const useBase64: typeof import('@vueuse/core')['useBase64']
const useBattery: typeof import('@vueuse/core')['useBattery']
const useBluetooth: typeof import('@vueuse/core')['useBluetooth']
const useBreakpoints: typeof import('@vueuse/core')['useBreakpoints']
const useBroadcastChannel: typeof import('@vueuse/core')['useBroadcastChannel']
const useBrowserLocation: typeof import('@vueuse/core')['useBrowserLocation']
const useCached: typeof import('@vueuse/core')['useCached']
const useCeil: typeof import('@vueuse/math')['useCeil']
const useClamp: typeof import('@vueuse/math')['useClamp']
const useClipboard: typeof import('@vueuse/core')['useClipboard']
const useClipboardItems: typeof import('@vueuse/core')['useClipboardItems']
const useCloned: typeof import('@vueuse/core')['useCloned']
const useColorMode: typeof import('@vueuse/core')['useColorMode']
const useConfirmDialog: typeof import('@vueuse/core')['useConfirmDialog']
const useCounter: typeof import('@vueuse/core')['useCounter']
const useCssModule: typeof import('vue')['useCssModule']
const useCssVar: typeof import('@vueuse/core')['useCssVar']
const useCssVars: typeof import('vue')['useCssVars']
const useCurrentElement: typeof import('@vueuse/core')['useCurrentElement']
const useCycleList: typeof import('@vueuse/core')['useCycleList']
const useDark: typeof import('@vueuse/core')['useDark']
const useDateFormat: typeof import('@vueuse/core')['useDateFormat']
const useDebounce: typeof import('@vueuse/core')['useDebounce']
const useDebounceFn: typeof import('@vueuse/core')['useDebounceFn']
const useDebouncedRefHistory: typeof import('@vueuse/core')['useDebouncedRefHistory']
const useDeviceMotion: typeof import('@vueuse/core')['useDeviceMotion']
const useDeviceOrientation: typeof import('@vueuse/core')['useDeviceOrientation']
const useDevicePixelRatio: typeof import('@vueuse/core')['useDevicePixelRatio']
const useDevicesList: typeof import('@vueuse/core')['useDevicesList']
const useDisplayMedia: typeof import('@vueuse/core')['useDisplayMedia']
const useDocumentVisibility: typeof import('@vueuse/core')['useDocumentVisibility']
const useDraggable: typeof import('@vueuse/core')['useDraggable']
const useDropZone: typeof import('@vueuse/core')['useDropZone']
const useElementBounding: typeof import('@vueuse/core')['useElementBounding']
const useElementByPoint: typeof import('@vueuse/core')['useElementByPoint']
const useElementHover: typeof import('@vueuse/core')['useElementHover']
const useElementSize: typeof import('@vueuse/core')['useElementSize']
const useElementVisibility: typeof import('@vueuse/core')['useElementVisibility']
const useEventBus: typeof import('@vueuse/core')['useEventBus']
const useEventListener: typeof import('@vueuse/core')['useEventListener']
const useEventSource: typeof import('@vueuse/core')['useEventSource']
const useEyeDropper: typeof import('@vueuse/core')['useEyeDropper']
const useFavicon: typeof import('@vueuse/core')['useFavicon']
const useFetch: typeof import('@vueuse/core')['useFetch']
const useFileDialog: typeof import('@vueuse/core')['useFileDialog']
const useFileSystemAccess: typeof import('@vueuse/core')['useFileSystemAccess']
const useFloor: typeof import('@vueuse/math')['useFloor']
const useFocus: typeof import('@vueuse/core')['useFocus']
const useFocusWithin: typeof import('@vueuse/core')['useFocusWithin']
const useFps: typeof import('@vueuse/core')['useFps']
const useFullscreen: typeof import('@vueuse/core')['useFullscreen']
const useGamepad: typeof import('@vueuse/core')['useGamepad']
const useGeolocation: typeof import('@vueuse/core')['useGeolocation']
const useId: typeof import('vue')['useId']
const useIdle: typeof import('@vueuse/core')['useIdle']
const useImage: typeof import('@vueuse/core')['useImage']
const useInfiniteScroll: typeof import('@vueuse/core')['useInfiniteScroll']
const useIntersectionObserver: typeof import('@vueuse/core')['useIntersectionObserver']
const useInterval: typeof import('@vueuse/core')['useInterval']
const useIntervalFn: typeof import('@vueuse/core')['useIntervalFn']
const useKeyModifier: typeof import('@vueuse/core')['useKeyModifier']
const useLastChanged: typeof import('@vueuse/core')['useLastChanged']
const useLink: typeof import('vue-router')['useLink']
const useLocalStorage: typeof import('@vueuse/core')['useLocalStorage']
const useMagicKeys: typeof import('@vueuse/core')['useMagicKeys']
const useManualRefHistory: typeof import('@vueuse/core')['useManualRefHistory']
const useMath: typeof import('@vueuse/math')['useMath']
const useMax: typeof import('@vueuse/math')['useMax']
const useMediaControls: typeof import('@vueuse/core')['useMediaControls']
const useMediaQuery: typeof import('@vueuse/core')['useMediaQuery']
const useMemoize: typeof import('@vueuse/core')['useMemoize']
const useMemory: typeof import('@vueuse/core')['useMemory']
const useMin: typeof import('@vueuse/math')['useMin']
const useModel: typeof import('vue')['useModel']
const useMounted: typeof import('@vueuse/core')['useMounted']
const useMouse: typeof import('@vueuse/core')['useMouse']
const useMouseInElement: typeof import('@vueuse/core')['useMouseInElement']
const useMousePressed: typeof import('@vueuse/core')['useMousePressed']
const useMutationObserver: typeof import('@vueuse/core')['useMutationObserver']
const useNavigatorLanguage: typeof import('@vueuse/core')['useNavigatorLanguage']
const useNetwork: typeof import('@vueuse/core')['useNetwork']
const useNow: typeof import('@vueuse/core')['useNow']
const useObjectUrl: typeof import('@vueuse/core')['useObjectUrl']
const useOffsetPagination: typeof import('@vueuse/core')['useOffsetPagination']
const useOnline: typeof import('@vueuse/core')['useOnline']
const usePageLeave: typeof import('@vueuse/core')['usePageLeave']
const useParallax: typeof import('@vueuse/core')['useParallax']
const useParentElement: typeof import('@vueuse/core')['useParentElement']
const usePerformanceObserver: typeof import('@vueuse/core')['usePerformanceObserver']
const usePermission: typeof import('@vueuse/core')['usePermission']
const usePointer: typeof import('@vueuse/core')['usePointer']
const usePointerLock: typeof import('@vueuse/core')['usePointerLock']
const usePointerSwipe: typeof import('@vueuse/core')['usePointerSwipe']
const usePrecision: typeof import('@vueuse/math')['usePrecision']
const usePreferredColorScheme: typeof import('@vueuse/core')['usePreferredColorScheme']
const usePreferredContrast: typeof import('@vueuse/core')['usePreferredContrast']
const usePreferredDark: typeof import('@vueuse/core')['usePreferredDark']
const usePreferredLanguages: typeof import('@vueuse/core')['usePreferredLanguages']
const usePreferredReducedMotion: typeof import('@vueuse/core')['usePreferredReducedMotion']
const usePrevious: typeof import('@vueuse/core')['usePrevious']
const useProjection: typeof import('@vueuse/math')['useProjection']
const useRafFn: typeof import('@vueuse/core')['useRafFn']
const useRefHistory: typeof import('@vueuse/core')['useRefHistory']
const useResizeObserver: typeof import('@vueuse/core')['useResizeObserver']
const useRound: typeof import('@vueuse/math')['useRound']
const useRoute: typeof import('vue-router')['useRoute']
const useRouter: typeof import('vue-router')['useRouter']
const useScreenOrientation: typeof import('@vueuse/core')['useScreenOrientation']
const useScreenSafeArea: typeof import('@vueuse/core')['useScreenSafeArea']
const useScriptTag: typeof import('@vueuse/core')['useScriptTag']
const useScroll: typeof import('@vueuse/core')['useScroll']
const useScrollLock: typeof import('@vueuse/core')['useScrollLock']
const useSessionStorage: typeof import('@vueuse/core')['useSessionStorage']
const useShare: typeof import('@vueuse/core')['useShare']
const useSlots: typeof import('vue')['useSlots']
const useSorted: typeof import('@vueuse/core')['useSorted']
const useSpeechRecognition: typeof import('@vueuse/core')['useSpeechRecognition']
const useSpeechSynthesis: typeof import('@vueuse/core')['useSpeechSynthesis']
const useStepper: typeof import('@vueuse/core')['useStepper']
const useStorageAsync: typeof import('@vueuse/core')['useStorageAsync']
const useStyleTag: typeof import('@vueuse/core')['useStyleTag']
const useSum: typeof import('@vueuse/math')['useSum']
const useSupported: typeof import('@vueuse/core')['useSupported']
const useSwipe: typeof import('@vueuse/core')['useSwipe']
const useTemplateRef: typeof import('vue')['useTemplateRef']
const useTemplateRefsList: typeof import('@vueuse/core')['useTemplateRefsList']
const useTextDirection: typeof import('@vueuse/core')['useTextDirection']
const useTextSelection: typeof import('@vueuse/core')['useTextSelection']
const useTextareaAutosize: typeof import('@vueuse/core')['useTextareaAutosize']
const useThrottle: typeof import('@vueuse/core')['useThrottle']
const useThrottleFn: typeof import('@vueuse/core')['useThrottleFn']
const useThrottledRefHistory: typeof import('@vueuse/core')['useThrottledRefHistory']
const useTimeAgo: typeof import('@vueuse/core')['useTimeAgo']
const useTimeout: typeof import('@vueuse/core')['useTimeout']
const useTimeoutFn: typeof import('@vueuse/core')['useTimeoutFn']
const useTimeoutPoll: typeof import('@vueuse/core')['useTimeoutPoll']
const useTimestamp: typeof import('@vueuse/core')['useTimestamp']
const useTitle: typeof import('@vueuse/core')['useTitle']
const useToNumber: typeof import('@vueuse/core')['useToNumber']
const useToString: typeof import('@vueuse/core')['useToString']
const useToggle: typeof import('@vueuse/core')['useToggle']
const useTransition: typeof import('@vueuse/core')['useTransition']
const useTrunc: typeof import('@vueuse/math')['useTrunc']
const useUrlSearchParams: typeof import('@vueuse/core')['useUrlSearchParams']
const useUserMedia: typeof import('@vueuse/core')['useUserMedia']
const useVModel: typeof import('@vueuse/core')['useVModel']
const useVModels: typeof import('@vueuse/core')['useVModels']
const useVibrate: typeof import('@vueuse/core')['useVibrate']
const useVirtualList: typeof import('@vueuse/core')['useVirtualList']
const useWakeLock: typeof import('@vueuse/core')['useWakeLock']
const useWebNotification: typeof import('@vueuse/core')['useWebNotification']
const useWebSocket: typeof import('@vueuse/core')['useWebSocket']
const useWebWorker: typeof import('@vueuse/core')['useWebWorker']
const useWebWorkerFn: typeof import('@vueuse/core')['useWebWorkerFn']
const useWindowFocus: typeof import('@vueuse/core')['useWindowFocus']
const useWindowScroll: typeof import('@vueuse/core')['useWindowScroll']
const useWindowSize: typeof import('@vueuse/core')['useWindowSize']
const watch: typeof import('vue')['watch']
const watchArray: typeof import('@vueuse/core')['watchArray']
const watchAtMost: typeof import('@vueuse/core')['watchAtMost']
const watchDebounced: typeof import('@vueuse/core')['watchDebounced']
const watchDeep: typeof import('@vueuse/core')['watchDeep']
const watchEffect: typeof import('vue')['watchEffect']
const watchIgnorable: typeof import('@vueuse/core')['watchIgnorable']
const watchImmediate: typeof import('@vueuse/core')['watchImmediate']
const watchOnce: typeof import('@vueuse/core')['watchOnce']
const watchPausable: typeof import('@vueuse/core')['watchPausable']
const watchPostEffect: typeof import('vue')['watchPostEffect']
const watchSyncEffect: typeof import('vue')['watchSyncEffect']
const watchThrottled: typeof import('@vueuse/core')['watchThrottled']
const watchTriggerable: typeof import('@vueuse/core')['watchTriggerable']
const watchWithFilter: typeof import('@vueuse/core')['watchWithFilter']
const whenever: typeof import('@vueuse/core')['whenever']
}
// for type re-export
declare global {
// @ts-ignore
export type { Component, ComponentPublicInstance, ComputedRef, DirectiveBinding, ExtractDefaultPropTypes, ExtractPropTypes, ExtractPublicPropTypes, InjectionKey, PropType, Ref, MaybeRef, MaybeRefOrGetter, VNode, WritableComputedRef } from 'vue'
import('vue')
}
// for vue template auto import
import { UnwrapRef } from 'vue'
declare module 'vue' {
interface GlobalComponents {}
interface ComponentCustomProperties {
readonly EffectScope: UnwrapRef<typeof import('vue')['EffectScope']>
readonly acceptHMRUpdate: UnwrapRef<typeof import('pinia')['acceptHMRUpdate']>
readonly asyncComputed: UnwrapRef<typeof import('@vueuse/core')['asyncComputed']>
readonly autoResetRef: UnwrapRef<typeof import('@vueuse/core')['autoResetRef']>
readonly computed: UnwrapRef<typeof import('vue')['computed']>
readonly computedAsync: UnwrapRef<typeof import('@vueuse/core')['computedAsync']>
readonly computedEager: UnwrapRef<typeof import('@vueuse/core')['computedEager']>
readonly computedInject: UnwrapRef<typeof import('@vueuse/core')['computedInject']>
readonly computedWithControl: UnwrapRef<typeof import('@vueuse/core')['computedWithControl']>
readonly controlledComputed: UnwrapRef<typeof import('@vueuse/core')['controlledComputed']>
readonly controlledRef: UnwrapRef<typeof import('@vueuse/core')['controlledRef']>
readonly createApp: UnwrapRef<typeof import('vue')['createApp']>
readonly createEventHook: UnwrapRef<typeof import('@vueuse/core')['createEventHook']>
readonly createGenericProjection: UnwrapRef<typeof import('@vueuse/math')['createGenericProjection']>
readonly createGlobalState: UnwrapRef<typeof import('@vueuse/core')['createGlobalState']>
readonly createInjectionState: UnwrapRef<typeof import('@vueuse/core')['createInjectionState']>
readonly createPinia: UnwrapRef<typeof import('pinia')['createPinia']>
readonly createProjection: UnwrapRef<typeof import('@vueuse/math')['createProjection']>
readonly createReactiveFn: UnwrapRef<typeof import('@vueuse/core')['createReactiveFn']>
readonly createReusableTemplate: UnwrapRef<typeof import('@vueuse/core')['createReusableTemplate']>
readonly createSharedComposable: UnwrapRef<typeof import('@vueuse/core')['createSharedComposable']>
readonly createTemplatePromise: UnwrapRef<typeof import('@vueuse/core')['createTemplatePromise']>
readonly createUnrefFn: UnwrapRef<typeof import('@vueuse/core')['createUnrefFn']>
readonly customRef: UnwrapRef<typeof import('vue')['customRef']>
readonly debouncedRef: UnwrapRef<typeof import('@vueuse/core')['debouncedRef']>
readonly debouncedWatch: UnwrapRef<typeof import('@vueuse/core')['debouncedWatch']>
readonly defineAsyncComponent: UnwrapRef<typeof import('vue')['defineAsyncComponent']>
readonly defineComponent: UnwrapRef<typeof import('vue')['defineComponent']>
readonly defineStore: UnwrapRef<typeof import('pinia')['defineStore']>
readonly eagerComputed: UnwrapRef<typeof import('@vueuse/core')['eagerComputed']>
readonly effectScope: UnwrapRef<typeof import('vue')['effectScope']>
readonly extendRef: UnwrapRef<typeof import('@vueuse/core')['extendRef']>
readonly getActivePinia: UnwrapRef<typeof import('pinia')['getActivePinia']>
readonly getCurrentInstance: UnwrapRef<typeof import('vue')['getCurrentInstance']>
readonly getCurrentScope: UnwrapRef<typeof import('vue')['getCurrentScope']>
readonly h: UnwrapRef<typeof import('vue')['h']>
readonly ignorableWatch: UnwrapRef<typeof import('@vueuse/core')['ignorableWatch']>
readonly inject: UnwrapRef<typeof import('vue')['inject']>
readonly injectLocal: UnwrapRef<typeof import('@vueuse/core')['injectLocal']>
readonly isDefined: UnwrapRef<typeof import('@vueuse/core')['isDefined']>
readonly isProxy: UnwrapRef<typeof import('vue')['isProxy']>
readonly isReactive: UnwrapRef<typeof import('vue')['isReactive']>
readonly isReadonly: UnwrapRef<typeof import('vue')['isReadonly']>
readonly isRef: UnwrapRef<typeof import('vue')['isRef']>
readonly logicAnd: UnwrapRef<typeof import('@vueuse/math')['logicAnd']>
readonly logicNot: UnwrapRef<typeof import('@vueuse/math')['logicNot']>
readonly logicOr: UnwrapRef<typeof import('@vueuse/math')['logicOr']>
readonly makeDestructurable: UnwrapRef<typeof import('@vueuse/core')['makeDestructurable']>
readonly mapActions: UnwrapRef<typeof import('pinia')['mapActions']>
readonly mapGetters: UnwrapRef<typeof import('pinia')['mapGetters']>
readonly mapState: UnwrapRef<typeof import('pinia')['mapState']>
readonly mapStores: UnwrapRef<typeof import('pinia')['mapStores']>
readonly mapWritableState: UnwrapRef<typeof import('pinia')['mapWritableState']>
readonly markRaw: UnwrapRef<typeof import('vue')['markRaw']>
readonly nextTick: UnwrapRef<typeof import('vue')['nextTick']>
readonly onActivated: UnwrapRef<typeof import('vue')['onActivated']>
readonly onBeforeMount: UnwrapRef<typeof import('vue')['onBeforeMount']>
readonly onBeforeRouteLeave: UnwrapRef<typeof import('vue-router')['onBeforeRouteLeave']>
readonly onBeforeRouteUpdate: UnwrapRef<typeof import('vue-router')['onBeforeRouteUpdate']>
readonly onBeforeUnmount: UnwrapRef<typeof import('vue')['onBeforeUnmount']>
readonly onBeforeUpdate: UnwrapRef<typeof import('vue')['onBeforeUpdate']>
readonly onClickOutside: UnwrapRef<typeof import('@vueuse/core')['onClickOutside']>
readonly onDeactivated: UnwrapRef<typeof import('vue')['onDeactivated']>
readonly onErrorCaptured: UnwrapRef<typeof import('vue')['onErrorCaptured']>
readonly onKeyStroke: UnwrapRef<typeof import('@vueuse/core')['onKeyStroke']>
readonly onLongPress: UnwrapRef<typeof import('@vueuse/core')['onLongPress']>
readonly onMounted: UnwrapRef<typeof import('vue')['onMounted']>
readonly onRenderTracked: UnwrapRef<typeof import('vue')['onRenderTracked']>
readonly onRenderTriggered: UnwrapRef<typeof import('vue')['onRenderTriggered']>
readonly onScopeDispose: UnwrapRef<typeof import('vue')['onScopeDispose']>
readonly onServerPrefetch: UnwrapRef<typeof import('vue')['onServerPrefetch']>
readonly onStartTyping: UnwrapRef<typeof import('@vueuse/core')['onStartTyping']>
readonly onUnmounted: UnwrapRef<typeof import('vue')['onUnmounted']>
readonly onUpdated: UnwrapRef<typeof import('vue')['onUpdated']>
readonly onWatcherCleanup: UnwrapRef<typeof import('vue')['onWatcherCleanup']>
readonly pausableWatch: UnwrapRef<typeof import('@vueuse/core')['pausableWatch']>
readonly provide: UnwrapRef<typeof import('vue')['provide']>
readonly provideLocal: UnwrapRef<typeof import('@vueuse/core')['provideLocal']>
readonly reactify: UnwrapRef<typeof import('@vueuse/core')['reactify']>
readonly reactifyObject: UnwrapRef<typeof import('@vueuse/core')['reactifyObject']>
readonly reactive: UnwrapRef<typeof import('vue')['reactive']>
readonly reactiveComputed: UnwrapRef<typeof import('@vueuse/core')['reactiveComputed']>
readonly reactiveOmit: UnwrapRef<typeof import('@vueuse/core')['reactiveOmit']>
readonly reactivePick: UnwrapRef<typeof import('@vueuse/core')['reactivePick']>
readonly readonly: UnwrapRef<typeof import('vue')['readonly']>
readonly ref: UnwrapRef<typeof import('vue')['ref']>
readonly refAutoReset: UnwrapRef<typeof import('@vueuse/core')['refAutoReset']>
readonly refDebounced: UnwrapRef<typeof import('@vueuse/core')['refDebounced']>
readonly refDefault: UnwrapRef<typeof import('@vueuse/core')['refDefault']>
readonly refThrottled: UnwrapRef<typeof import('@vueuse/core')['refThrottled']>
readonly refWithControl: UnwrapRef<typeof import('@vueuse/core')['refWithControl']>
readonly resolveComponent: UnwrapRef<typeof import('vue')['resolveComponent']>
readonly resolveRef: UnwrapRef<typeof import('@vueuse/core')['resolveRef']>
readonly resolveUnref: UnwrapRef<typeof import('@vueuse/core')['resolveUnref']>
readonly setActivePinia: UnwrapRef<typeof import('pinia')['setActivePinia']>
readonly setMapStoreSuffix: UnwrapRef<typeof import('pinia')['setMapStoreSuffix']>
readonly shallowReactive: UnwrapRef<typeof import('vue')['shallowReactive']>
readonly shallowReadonly: UnwrapRef<typeof import('vue')['shallowReadonly']>
readonly shallowRef: UnwrapRef<typeof import('vue')['shallowRef']>
readonly storeToRefs: UnwrapRef<typeof import('pinia')['storeToRefs']>
readonly syncRef: UnwrapRef<typeof import('@vueuse/core')['syncRef']>
readonly syncRefs: UnwrapRef<typeof import('@vueuse/core')['syncRefs']>
readonly templateRef: UnwrapRef<typeof import('@vueuse/core')['templateRef']>
readonly throttledRef: UnwrapRef<typeof import('@vueuse/core')['throttledRef']>
readonly throttledWatch: UnwrapRef<typeof import('@vueuse/core')['throttledWatch']>
readonly toRaw: UnwrapRef<typeof import('vue')['toRaw']>
readonly toReactive: UnwrapRef<typeof import('@vueuse/core')['toReactive']>
readonly toRef: UnwrapRef<typeof import('vue')['toRef']>
readonly toRefs: UnwrapRef<typeof import('vue')['toRefs']>
readonly toValue: UnwrapRef<typeof import('vue')['toValue']>
readonly triggerRef: UnwrapRef<typeof import('vue')['triggerRef']>
readonly tryOnBeforeMount: UnwrapRef<typeof import('@vueuse/core')['tryOnBeforeMount']>
readonly tryOnBeforeUnmount: UnwrapRef<typeof import('@vueuse/core')['tryOnBeforeUnmount']>
readonly tryOnMounted: UnwrapRef<typeof import('@vueuse/core')['tryOnMounted']>
readonly tryOnScopeDispose: UnwrapRef<typeof import('@vueuse/core')['tryOnScopeDispose']>
readonly tryOnUnmounted: UnwrapRef<typeof import('@vueuse/core')['tryOnUnmounted']>
readonly unref: UnwrapRef<typeof import('vue')['unref']>
readonly unrefElement: UnwrapRef<typeof import('@vueuse/core')['unrefElement']>
readonly until: UnwrapRef<typeof import('@vueuse/core')['until']>
readonly useAbs: UnwrapRef<typeof import('@vueuse/math')['useAbs']>
readonly useActiveElement: UnwrapRef<typeof import('@vueuse/core')['useActiveElement']>
readonly useAnimate: UnwrapRef<typeof import('@vueuse/core')['useAnimate']>
readonly useArrayDifference: UnwrapRef<typeof import('@vueuse/core')['useArrayDifference']>
readonly useArrayEvery: UnwrapRef<typeof import('@vueuse/core')['useArrayEvery']>
readonly useArrayFilter: UnwrapRef<typeof import('@vueuse/core')['useArrayFilter']>
readonly useArrayFind: UnwrapRef<typeof import('@vueuse/core')['useArrayFind']>
readonly useArrayFindIndex: UnwrapRef<typeof import('@vueuse/core')['useArrayFindIndex']>
readonly useArrayFindLast: UnwrapRef<typeof import('@vueuse/core')['useArrayFindLast']>
readonly useArrayIncludes: UnwrapRef<typeof import('@vueuse/core')['useArrayIncludes']>
readonly useArrayJoin: UnwrapRef<typeof import('@vueuse/core')['useArrayJoin']>
readonly useArrayMap: UnwrapRef<typeof import('@vueuse/core')['useArrayMap']>
readonly useArrayReduce: UnwrapRef<typeof import('@vueuse/core')['useArrayReduce']>
readonly useArraySome: UnwrapRef<typeof import('@vueuse/core')['useArraySome']>
readonly useArrayUnique: UnwrapRef<typeof import('@vueuse/core')['useArrayUnique']>
readonly useAsyncQueue: UnwrapRef<typeof import('@vueuse/core')['useAsyncQueue']>
readonly useAsyncState: UnwrapRef<typeof import('@vueuse/core')['useAsyncState']>
readonly useAttrs: UnwrapRef<typeof import('vue')['useAttrs']>
readonly useAverage: UnwrapRef<typeof import('@vueuse/math')['useAverage']>
readonly useBase64: UnwrapRef<typeof import('@vueuse/core')['useBase64']>
readonly useBattery: UnwrapRef<typeof import('@vueuse/core')['useBattery']>
readonly useBluetooth: UnwrapRef<typeof import('@vueuse/core')['useBluetooth']>
readonly useBreakpoints: UnwrapRef<typeof import('@vueuse/core')['useBreakpoints']>
readonly useBroadcastChannel: UnwrapRef<typeof import('@vueuse/core')['useBroadcastChannel']>
readonly useBrowserLocation: UnwrapRef<typeof import('@vueuse/core')['useBrowserLocation']>
readonly useCached: UnwrapRef<typeof import('@vueuse/core')['useCached']>
readonly useCeil: UnwrapRef<typeof import('@vueuse/math')['useCeil']>
readonly useClamp: UnwrapRef<typeof import('@vueuse/math')['useClamp']>
readonly useClipboard: UnwrapRef<typeof import('@vueuse/core')['useClipboard']>
readonly useClipboardItems: UnwrapRef<typeof import('@vueuse/core')['useClipboardItems']>
readonly useCloned: UnwrapRef<typeof import('@vueuse/core')['useCloned']>
readonly useColorMode: UnwrapRef<typeof import('@vueuse/core')['useColorMode']>
readonly useConfirmDialog: UnwrapRef<typeof import('@vueuse/core')['useConfirmDialog']>
readonly useCounter: UnwrapRef<typeof import('@vueuse/core')['useCounter']>
readonly useCssModule: UnwrapRef<typeof import('vue')['useCssModule']>
readonly useCssVar: UnwrapRef<typeof import('@vueuse/core')['useCssVar']>
readonly useCssVars: UnwrapRef<typeof import('vue')['useCssVars']>
readonly useCurrentElement: UnwrapRef<typeof import('@vueuse/core')['useCurrentElement']>
readonly useCycleList: UnwrapRef<typeof import('@vueuse/core')['useCycleList']>
readonly useDark: UnwrapRef<typeof import('@vueuse/core')['useDark']>
readonly useDateFormat: UnwrapRef<typeof import('@vueuse/core')['useDateFormat']>
readonly useDebounce: UnwrapRef<typeof import('@vueuse/core')['useDebounce']>
readonly useDebounceFn: UnwrapRef<typeof import('@vueuse/core')['useDebounceFn']>
readonly useDebouncedRefHistory: UnwrapRef<typeof import('@vueuse/core')['useDebouncedRefHistory']>
readonly useDeviceMotion: UnwrapRef<typeof import('@vueuse/core')['useDeviceMotion']>
readonly useDeviceOrientation: UnwrapRef<typeof import('@vueuse/core')['useDeviceOrientation']>
readonly useDevicePixelRatio: UnwrapRef<typeof import('@vueuse/core')['useDevicePixelRatio']>
readonly useDevicesList: UnwrapRef<typeof import('@vueuse/core')['useDevicesList']>
readonly useDisplayMedia: UnwrapRef<typeof import('@vueuse/core')['useDisplayMedia']>
readonly useDocumentVisibility: UnwrapRef<typeof import('@vueuse/core')['useDocumentVisibility']>
readonly useDraggable: UnwrapRef<typeof import('@vueuse/core')['useDraggable']>
readonly useDropZone: UnwrapRef<typeof import('@vueuse/core')['useDropZone']>
readonly useElementBounding: UnwrapRef<typeof import('@vueuse/core')['useElementBounding']>
readonly useElementByPoint: UnwrapRef<typeof import('@vueuse/core')['useElementByPoint']>
readonly useElementHover: UnwrapRef<typeof import('@vueuse/core')['useElementHover']>
readonly useElementSize: UnwrapRef<typeof import('@vueuse/core')['useElementSize']>
readonly useElementVisibility: UnwrapRef<typeof import('@vueuse/core')['useElementVisibility']>
readonly useEventBus: UnwrapRef<typeof import('@vueuse/core')['useEventBus']>
readonly useEventListener: UnwrapRef<typeof import('@vueuse/core')['useEventListener']>
readonly useEventSource: UnwrapRef<typeof import('@vueuse/core')['useEventSource']>
readonly useEyeDropper: UnwrapRef<typeof import('@vueuse/core')['useEyeDropper']>
readonly useFavicon: UnwrapRef<typeof import('@vueuse/core')['useFavicon']>
readonly useFetch: UnwrapRef<typeof import('@vueuse/core')['useFetch']>
readonly useFileDialog: UnwrapRef<typeof import('@vueuse/core')['useFileDialog']>
readonly useFileSystemAccess: UnwrapRef<typeof import('@vueuse/core')['useFileSystemAccess']>
readonly useFloor: UnwrapRef<typeof import('@vueuse/math')['useFloor']>
readonly useFocus: UnwrapRef<typeof import('@vueuse/core')['useFocus']>
readonly useFocusWithin: UnwrapRef<typeof import('@vueuse/core')['useFocusWithin']>
readonly useFps: UnwrapRef<typeof import('@vueuse/core')['useFps']>
readonly useFullscreen: UnwrapRef<typeof import('@vueuse/core')['useFullscreen']>
readonly useGamepad: UnwrapRef<typeof import('@vueuse/core')['useGamepad']>
readonly useGeolocation: UnwrapRef<typeof import('@vueuse/core')['useGeolocation']>
readonly useId: UnwrapRef<typeof import('vue')['useId']>
readonly useIdle: UnwrapRef<typeof import('@vueuse/core')['useIdle']>
readonly useImage: UnwrapRef<typeof import('@vueuse/core')['useImage']>
readonly useInfiniteScroll: UnwrapRef<typeof import('@vueuse/core')['useInfiniteScroll']>
readonly useIntersectionObserver: UnwrapRef<typeof import('@vueuse/core')['useIntersectionObserver']>
readonly useInterval: UnwrapRef<typeof import('@vueuse/core')['useInterval']>
readonly useIntervalFn: UnwrapRef<typeof import('@vueuse/core')['useIntervalFn']>
readonly useKeyModifier: UnwrapRef<typeof import('@vueuse/core')['useKeyModifier']>
readonly useLastChanged: UnwrapRef<typeof import('@vueuse/core')['useLastChanged']>
readonly useLink: UnwrapRef<typeof import('vue-router')['useLink']>
readonly useLocalStorage: UnwrapRef<typeof import('@vueuse/core')['useLocalStorage']>
readonly useMagicKeys: UnwrapRef<typeof import('@vueuse/core')['useMagicKeys']>
readonly useManualRefHistory: UnwrapRef<typeof import('@vueuse/core')['useManualRefHistory']>
readonly useMath: UnwrapRef<typeof import('@vueuse/math')['useMath']>
readonly useMax: UnwrapRef<typeof import('@vueuse/math')['useMax']>
readonly useMediaControls: UnwrapRef<typeof import('@vueuse/core')['useMediaControls']>
readonly useMediaQuery: UnwrapRef<typeof import('@vueuse/core')['useMediaQuery']>
readonly useMemoize: UnwrapRef<typeof import('@vueuse/core')['useMemoize']>
readonly useMemory: UnwrapRef<typeof import('@vueuse/core')['useMemory']>
readonly useMin: UnwrapRef<typeof import('@vueuse/math')['useMin']>
readonly useModel: UnwrapRef<typeof import('vue')['useModel']>
readonly useMounted: UnwrapRef<typeof import('@vueuse/core')['useMounted']>
readonly useMouse: UnwrapRef<typeof import('@vueuse/core')['useMouse']>
readonly useMouseInElement: UnwrapRef<typeof import('@vueuse/core')['useMouseInElement']>
readonly useMousePressed: UnwrapRef<typeof import('@vueuse/core')['useMousePressed']>
readonly useMutationObserver: UnwrapRef<typeof import('@vueuse/core')['useMutationObserver']>
readonly useNavigatorLanguage: UnwrapRef<typeof import('@vueuse/core')['useNavigatorLanguage']>
readonly useNetwork: UnwrapRef<typeof import('@vueuse/core')['useNetwork']>
readonly useNow: UnwrapRef<typeof import('@vueuse/core')['useNow']>
readonly useObjectUrl: UnwrapRef<typeof import('@vueuse/core')['useObjectUrl']>
readonly useOffsetPagination: UnwrapRef<typeof import('@vueuse/core')['useOffsetPagination']>
readonly useOnline: UnwrapRef<typeof import('@vueuse/core')['useOnline']>
readonly usePageLeave: UnwrapRef<typeof import('@vueuse/core')['usePageLeave']>
readonly useParallax: UnwrapRef<typeof import('@vueuse/core')['useParallax']>
readonly useParentElement: UnwrapRef<typeof import('@vueuse/core')['useParentElement']>
readonly usePerformanceObserver: UnwrapRef<typeof import('@vueuse/core')['usePerformanceObserver']>
readonly usePermission: UnwrapRef<typeof import('@vueuse/core')['usePermission']>
readonly usePointer: UnwrapRef<typeof import('@vueuse/core')['usePointer']>
readonly usePointerLock: UnwrapRef<typeof import('@vueuse/core')['usePointerLock']>
readonly usePointerSwipe: UnwrapRef<typeof import('@vueuse/core')['usePointerSwipe']>
readonly usePrecision: UnwrapRef<typeof import('@vueuse/math')['usePrecision']>
readonly usePreferredColorScheme: UnwrapRef<typeof import('@vueuse/core')['usePreferredColorScheme']>
readonly usePreferredContrast: UnwrapRef<typeof import('@vueuse/core')['usePreferredContrast']>
readonly usePreferredDark: UnwrapRef<typeof import('@vueuse/core')['usePreferredDark']>
readonly usePreferredLanguages: UnwrapRef<typeof import('@vueuse/core')['usePreferredLanguages']>
readonly usePreferredReducedMotion: UnwrapRef<typeof import('@vueuse/core')['usePreferredReducedMotion']>
readonly usePrevious: UnwrapRef<typeof import('@vueuse/core')['usePrevious']>
readonly useProjection: UnwrapRef<typeof import('@vueuse/math')['useProjection']>
readonly useRafFn: UnwrapRef<typeof import('@vueuse/core')['useRafFn']>
readonly useRefHistory: UnwrapRef<typeof import('@vueuse/core')['useRefHistory']>
readonly useResizeObserver: UnwrapRef<typeof import('@vueuse/core')['useResizeObserver']>
readonly useRound: UnwrapRef<typeof import('@vueuse/math')['useRound']>
readonly useRoute: UnwrapRef<typeof import('vue-router')['useRoute']>
readonly useRouter: UnwrapRef<typeof import('vue-router')['useRouter']>
readonly useScreenOrientation: UnwrapRef<typeof import('@vueuse/core')['useScreenOrientation']>
readonly useScreenSafeArea: UnwrapRef<typeof import('@vueuse/core')['useScreenSafeArea']>
readonly useScriptTag: UnwrapRef<typeof import('@vueuse/core')['useScriptTag']>
readonly useScroll: UnwrapRef<typeof import('@vueuse/core')['useScroll']>
readonly useScrollLock: UnwrapRef<typeof import('@vueuse/core')['useScrollLock']>
readonly useSessionStorage: UnwrapRef<typeof import('@vueuse/core')['useSessionStorage']>
readonly useShare: UnwrapRef<typeof import('@vueuse/core')['useShare']>
readonly useSlots: UnwrapRef<typeof import('vue')['useSlots']>
readonly useSorted: UnwrapRef<typeof import('@vueuse/core')['useSorted']>
readonly useSpeechRecognition: UnwrapRef<typeof import('@vueuse/core')['useSpeechRecognition']>
readonly useSpeechSynthesis: UnwrapRef<typeof import('@vueuse/core')['useSpeechSynthesis']>
readonly useStepper: UnwrapRef<typeof import('@vueuse/core')['useStepper']>
readonly useStorageAsync: UnwrapRef<typeof import('@vueuse/core')['useStorageAsync']>
readonly useStyleTag: UnwrapRef<typeof import('@vueuse/core')['useStyleTag']>
readonly useSum: UnwrapRef<typeof import('@vueuse/math')['useSum']>
readonly useSupported: UnwrapRef<typeof import('@vueuse/core')['useSupported']>
readonly useSwipe: UnwrapRef<typeof import('@vueuse/core')['useSwipe']>
readonly useTemplateRef: UnwrapRef<typeof import('vue')['useTemplateRef']>
readonly useTemplateRefsList: UnwrapRef<typeof import('@vueuse/core')['useTemplateRefsList']>
readonly useTextDirection: UnwrapRef<typeof import('@vueuse/core')['useTextDirection']>
readonly useTextSelection: UnwrapRef<typeof import('@vueuse/core')['useTextSelection']>
readonly useTextareaAutosize: UnwrapRef<typeof import('@vueuse/core')['useTextareaAutosize']>
readonly useThrottle: UnwrapRef<typeof import('@vueuse/core')['useThrottle']>
readonly useThrottleFn: UnwrapRef<typeof import('@vueuse/core')['useThrottleFn']>
readonly useThrottledRefHistory: UnwrapRef<typeof import('@vueuse/core')['useThrottledRefHistory']>
readonly useTimeAgo: UnwrapRef<typeof import('@vueuse/core')['useTimeAgo']>
readonly useTimeout: UnwrapRef<typeof import('@vueuse/core')['useTimeout']>
readonly useTimeoutFn: UnwrapRef<typeof import('@vueuse/core')['useTimeoutFn']>
readonly useTimeoutPoll: UnwrapRef<typeof import('@vueuse/core')['useTimeoutPoll']>
readonly useTimestamp: UnwrapRef<typeof import('@vueuse/core')['useTimestamp']>
readonly useTitle: UnwrapRef<typeof import('@vueuse/core')['useTitle']>
readonly useToNumber: UnwrapRef<typeof import('@vueuse/core')['useToNumber']>
readonly useToString: UnwrapRef<typeof import('@vueuse/core')['useToString']>
readonly useToggle: UnwrapRef<typeof import('@vueuse/core')['useToggle']>
readonly useTransition: UnwrapRef<typeof import('@vueuse/core')['useTransition']>
readonly useTrunc: UnwrapRef<typeof import('@vueuse/math')['useTrunc']>
readonly useUrlSearchParams: UnwrapRef<typeof import('@vueuse/core')['useUrlSearchParams']>
readonly useUserMedia: UnwrapRef<typeof import('@vueuse/core')['useUserMedia']>
readonly useVModel: UnwrapRef<typeof import('@vueuse/core')['useVModel']>
readonly useVModels: UnwrapRef<typeof import('@vueuse/core')['useVModels']>
readonly useVibrate: UnwrapRef<typeof import('@vueuse/core')['useVibrate']>
readonly useVirtualList: UnwrapRef<typeof import('@vueuse/core')['useVirtualList']>
readonly useWakeLock: UnwrapRef<typeof import('@vueuse/core')['useWakeLock']>
readonly useWebNotification: UnwrapRef<typeof import('@vueuse/core')['useWebNotification']>
readonly useWebSocket: UnwrapRef<typeof import('@vueuse/core')['useWebSocket']>
readonly useWebWorker: UnwrapRef<typeof import('@vueuse/core')['useWebWorker']>
readonly useWebWorkerFn: UnwrapRef<typeof import('@vueuse/core')['useWebWorkerFn']>
readonly useWindowFocus: UnwrapRef<typeof import('@vueuse/core')['useWindowFocus']>
readonly useWindowScroll: UnwrapRef<typeof import('@vueuse/core')['useWindowScroll']>
readonly useWindowSize: UnwrapRef<typeof import('@vueuse/core')['useWindowSize']>
readonly watch: UnwrapRef<typeof import('vue')['watch']>
readonly watchArray: UnwrapRef<typeof import('@vueuse/core')['watchArray']>
readonly watchAtMost: UnwrapRef<typeof import('@vueuse/core')['watchAtMost']>
readonly watchDebounced: UnwrapRef<typeof import('@vueuse/core')['watchDebounced']>
readonly watchDeep: UnwrapRef<typeof import('@vueuse/core')['watchDeep']>
readonly watchEffect: UnwrapRef<typeof import('vue')['watchEffect']>
readonly watchIgnorable: UnwrapRef<typeof import('@vueuse/core')['watchIgnorable']>
readonly watchImmediate: UnwrapRef<typeof import('@vueuse/core')['watchImmediate']>
readonly watchOnce: UnwrapRef<typeof import('@vueuse/core')['watchOnce']>
readonly watchPausable: UnwrapRef<typeof import('@vueuse/core')['watchPausable']>
readonly watchPostEffect: UnwrapRef<typeof import('vue')['watchPostEffect']>
readonly watchSyncEffect: UnwrapRef<typeof import('vue')['watchSyncEffect']>
readonly watchThrottled: UnwrapRef<typeof import('@vueuse/core')['watchThrottled']>
readonly watchTriggerable: UnwrapRef<typeof import('@vueuse/core')['watchTriggerable']>
readonly watchWithFilter: UnwrapRef<typeof import('@vueuse/core')['watchWithFilter']>
readonly whenever: UnwrapRef<typeof import('@vueuse/core')['whenever']>
}
}

View File

@@ -0,0 +1,21 @@
/* eslint-disable */
// @ts-nocheck
// Generated by unplugin-vue-components
// Read more: https://github.com/vuejs/core/pull/3399
export {}
/* prettier-ignore */
declare module 'vue' {
export interface GlobalComponents {
CardStatisticsHorizontal: typeof import('./src/@core/components/cards/CardStatisticsHorizontal.vue')['default']
CardStatisticsVertical: typeof import('./src/@core/components/cards/CardStatisticsVertical.vue')['default']
CardStatisticsWithImages: typeof import('./src/@core/components/cards/CardStatisticsWithImages.vue')['default']
ErrorHeader: typeof import('./src/components/ErrorHeader.vue')['default']
MoreBtn: typeof import('./src/@core/components/MoreBtn.vue')['default']
RouterLink: typeof import('vue-router')['RouterLink']
RouterView: typeof import('vue-router')['RouterView']
ThemeSwitcher: typeof import('./src/@core/components/ThemeSwitcher.vue')['default']
UpgradeToPro: typeof import('./src/components/UpgradeToPro.vue')['default']
VueApexCharts: typeof import('vue3-apexcharts')['default']
}
}

View File

@@ -0,0 +1,53 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<link rel="icon" href="/favicon.ico" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Materio - Vuetify Vuejs Admin Template</title>
<link rel="stylesheet" type="text/css" href="/loader.css" />
</head>
<body>
<div id="app">
<div id="loading-bg">
<div class="loading-logo">
<!-- SVG Logo -->
<svg width="86" height="48" viewBox="0 0 30 24" xmlns="http://www.w3.org/2000/svg">
<g fill="none" fill-rule="evenodd">
<path d="M30 21.392a2 2 0 0 1-3.027 1.716l-3.258-1.95a2 2 0 0 1-.973-1.716l-.001-6.7L15
17.178l-7.742-4.434v6.7a2 2 0 0 1-.973 1.715l-3.258 1.95A2 2 0 0 1 0 21.392V3.585l.005-.15L0 3.572a2 2 0 0
1 3.045-1.706L15 9.194l11.955-7.328A2 2 0 0 1 30 3.572Z" fill="var(--initial-loader-color)" />
<path fill="var(--initial-loader-color)" opacity=".078" d="m0 8.589 7.258 4.162v4.08z" />
<path fill="var(--initial-loader-color)" opacity=".078" d=" m0 8.589 7.258 4.056v2.492zm30 0-7.258
4.153v4.212z" />
<path fill="var(--initial-loader-color)" opacity=".078" d="m30 8.589-7.258 4.052v2.62z" />
<path d="M3.045 1.866 15 9.194v7.983L0 8.587V3.571a2 2 0 0 1 3.045-1.706Z" fill-opacity=".15" fill="
#FFF" />
<path d="M26.955 1.866 15 9.194v7.983l15-8.59V3.571a2 2 0 0 0-3.045-1.706Z" fill-opacity=".35"
fill="#FFF" />
</g>
</svg>
</div>
<div class="loading">
<div class="effect-1 effects"></div>
<div class="effect-2 effects"></div>
<div class="effect-3 effects"></div>
</div>
</div>
</div>
<script type="module" src="/src/main.js"></script>
<script>
const loaderColor = localStorage.getItem('materio-initial-loader-bg') || '#FFFFFF'
const primaryColor = localStorage.getItem('materio-initial-loader-color') || '#9155FD'
if (loaderColor)
document.documentElement.style.setProperty('--initial-loader-bg', loaderColor)
if (primaryColor)
document.documentElement.style.setProperty('--initial-loader-color', primaryColor)
</script>
</body>
</html>

View File

@@ -0,0 +1,45 @@
{
"include": [
"./vite.config.*",
"./src/**/*",
"./src/**/*.vue",
"./themeConfig.js"
],
"exclude": [
"./dist",
"./node_modules"
],
"compilerOptions": {
"target": "esnext",
"module": "esnext",
"moduleResolution": "Bundler",
"jsx": "preserve",
"paths": {
"@/*": [
"./src/*"
],
"@layouts/*": [
"./src/@layouts/*"
],
"@layouts": [
"./src/@layouts"
],
"@core/*": [
"./src/@core/*"
],
"@core": [
"./src/@core"
],
"@images/*": [
"./src/assets/images/*"
],
"@styles/*": [
"./src/styles/*"
]
},
"types": [
"vite/client",
"vite-plugin-vue-layouts/client"
]
}
}

View File

@@ -0,0 +1,79 @@
{
"name": "materio-vuetify-vuejs-admin-template-free",
"version": "2.3.0",
"private": true,
"type": "module",
"scripts": {
"dev": "vite",
"build": "vite build",
"preview": "vite preview --port 5050",
"lint": "eslint . -c .eslintrc.cjs --fix --ext .ts,.js,.cjs,.vue,.tsx,.jsx",
"build:icons": "tsx src/plugins/iconify/build-icons.js",
"postinstall": "npm run build:icons"
},
"dependencies": {
"@floating-ui/dom": "1.6.8",
"@iconify-json/bxl": "^1.1.10",
"@stylistic/stylelint-config": "^1.0.1",
"@vueuse/core": "^10.11.1",
"@vueuse/math": "^10.11.1",
"apexcharts": "^3.54.1",
"pinia": "^2.3.0",
"prismjs": "^1.29.0",
"roboto-fontface": "^0.10.0",
"vue": "^3.5.13",
"vue-flatpickr-component": "11.0.5",
"vue-prism-component": "^2.0.0",
"vue-router": "^4.5.0",
"vue3-apexcharts": "1.5.2",
"vue3-perfect-scrollbar": "^2.0.0",
"vuetify": "3.7.5",
"webfontloader": "^1.6.28"
},
"devDependencies": {
"@antfu/eslint-config-vue": "^0.43.1",
"@antfu/utils": "^0.7.10",
"@iconify-json/ri": "^1.2.1",
"@iconify/tools": "^4.0.7",
"@iconify/utils": "^2.1.13",
"@iconify/vue": "4.1.2",
"@vitejs/plugin-vue": "^5.2.1",
"@vitejs/plugin-vue-jsx": "^4.1.1",
"eslint": "^8.57.1",
"eslint-config-airbnb-base": "^15.0.0",
"eslint-plugin-case-police": "^0.6.1",
"eslint-plugin-import": "^2.31.0",
"eslint-plugin-promise": "^6.6.0",
"eslint-plugin-regex": "^1.10.0",
"eslint-plugin-regexp": "^2.6.0",
"eslint-plugin-sonarjs": "^0.24.0",
"eslint-plugin-unicorn": "^51.0.1",
"eslint-import-resolver-typescript": "^3.6.1",
"eslint-plugin-vue": "^9.32.0",
"postcss-html": "^1.7.0",
"postcss-scss": "^4.0.9",
"sass": "~1.76.0",
"stylelint": "16.8.0",
"stylelint-codeguide": "2.0.0",
"stylelint-config-idiomatic-order": "10.0.0",
"stylelint-config-standard-scss": "13.1.0",
"stylelint-use-logical-spec": "5.0.1",
"tsx": "^4.19.2",
"unplugin-auto-import": "^0.18.6",
"unplugin-vue-components": "^0.27.5",
"vite": "^5.4.11",
"vite-plugin-vue-layouts": "^0.11.0",
"vite-plugin-vuetify": "2.0.3",
"vite-svg-loader": "^5.1.0"
},
"resolutions": {
"postcss": "^8",
"stylelint-order": "6.0.3",
"@types/video.js": "^7"
},
"overrides": {
"postcss": "^8",
"stylelint-order": "6.0.3",
"@types/video.js": "^7"
}
}

File diff suppressed because it is too large Load Diff

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

View File

@@ -0,0 +1,79 @@
body {
margin: 0;
}
html {
overflow-x: hidden;
overflow-y: scroll;
}
#loading-bg {
position: absolute;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
background: var(--initial-loader-bg, #fff);
block-size: 100%;
gap: 1rem 0;
inline-size: 100%;
}
.loading {
position: relative;
box-sizing: border-box;
border: 3px solid transparent;
border-radius: 50%;
block-size: 55px;
inline-size: 55px;
}
.loading .effect-1,
.loading .effect-2,
.loading .effect-3 {
position: absolute;
box-sizing: border-box;
border: 3px solid transparent;
border-radius: 50%;
block-size: 100%;
border-inline-start: 3px solid var(--initial-loader-color, #eee);
inline-size: 100%;
}
.loading .effect-1 {
animation: rotate 1s ease infinite;
}
.loading .effect-2 {
animation: rotate-opacity 1s ease infinite 0.1s;
}
.loading .effect-3 {
animation: rotate-opacity 1s ease infinite 0.2s;
}
.loading .effects {
transition: all 0.3s ease;
}
@keyframes rotate {
0% {
transform: rotate(0deg);
}
100% {
transform: rotate(1turn);
}
}
@keyframes rotate-opacity {
0% {
opacity: 0.1;
transform: rotate(0deg);
}
100% {
opacity: 1;
transform: rotate(1turn);
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.0 KiB

View File

@@ -0,0 +1,35 @@
<script setup>
const props = defineProps({
menuList: {
type: Array,
required: false,
},
itemProps: {
type: Boolean,
required: false,
},
iconSize: {
type: String,
required: false,
},
})
</script>
<template>
<IconBtn>
<VIcon
:size="iconSize"
icon="ri-more-2-line"
/>
<VMenu
v-if="props.menuList"
activator="parent"
>
<VList
:items="props.menuList"
:item-props="props.itemProps"
/>
</VMenu>
</IconBtn>
</template>

View File

@@ -0,0 +1,43 @@
<script setup>
import { useTheme } from 'vuetify'
const props = defineProps({
themes: {
type: Array,
required: true,
},
})
const {
name: themeName,
global: globalTheme,
} = useTheme()
const {
state: currentThemeName,
next: getNextThemeName,
index: currentThemeIndex,
} = useCycleList(props.themes.map(t => t.name), { initialValue: themeName })
const changeTheme = () => {
globalTheme.name.value = getNextThemeName()
}
// Update icon if theme is changed from other sources
watch(() => globalTheme.name.value, val => {
currentThemeName.value = val
})
</script>
<template>
<IconBtn @click="changeTheme">
<VIcon :icon="props.themes[currentThemeIndex].icon" />
<VTooltip
activator="parent"
open-delay="1000"
scroll-strategy="close"
>
<span class="text-capitalize">{{ currentThemeName }}</span>
</VTooltip>
</IconBtn>
</template>

View File

@@ -0,0 +1,65 @@
<script setup>
const props = defineProps({
title: {
type: String,
required: true,
},
color: {
type: String,
required: false,
default: 'primary',
},
icon: {
type: String,
required: true,
},
stats: {
type: Number,
required: true,
},
change: {
type: Number,
required: true,
},
})
const isPositive = controlledComputed(() => props.change, () => Math.sign(props.change) === 1)
</script>
<template>
<VCard>
<VCardText class="d-flex align-center">
<VAvatar
size="44"
rounded
:color="props.color"
variant="tonal"
class="me-4"
>
<VIcon
:icon="props.icon"
size="30"
/>
</VAvatar>
<div>
<span class="text-caption">{{ props.title }}</span>
<div class="d-flex align-center flex-wrap">
<span class="text-h6 font-weight-semibold">{{ kFormatter(props.stats) }}</span>
<div
v-if="props.change"
:class="`${isPositive ? 'text-success' : 'text-error'} mt-1`"
>
<VIcon
:icon="isPositive ? 'ri-arrow-up-s-line' : 'ri-arrow-down-s-line'"
size="24"
/>
<span class="text-base">
{{ Math.abs(props.change) }}%
</span>
</div>
</div>
</div>
</VCardText>
</VCard>
</template>

View File

@@ -0,0 +1,95 @@
<script setup>
const props = defineProps({
title: {
type: String,
required: true,
},
color: {
type: String,
required: false,
default: 'primary',
},
icon: {
type: String,
required: true,
},
stats: {
type: String,
required: true,
},
change: {
type: Number,
required: true,
},
subtitle: {
type: String,
required: true,
},
})
const isPositive = computed(() => Math.sign(props.change) === 1)
const moreList = [
{
title: 'Share',
value: 'Share',
},
{
title: 'Refresh',
value: 'Refresh',
},
{
title: 'Update',
value: 'Update',
},
]
</script>
<template>
<VCard>
<VCardText class="d-flex align-center">
<VAvatar
v-if="props.icon"
size="40"
:color="props.color"
class="elevation-2"
>
<VIcon
:icon="props.icon"
size="24"
/>
</VAvatar>
<VSpacer />
<MoreBtn
class="me-n3 mt-n1"
:menu-list="moreList"
/>
</VCardText>
<VCardText>
<h6 class="text-h6 mb-1">
{{ props.title }}
</h6>
<div
v-if="props.change"
class="d-flex align-center mb-1 flex-wrap"
>
<h4 class="text-h4 me-2">
{{ props.stats }}
</h4>
<div
:class="isPositive ? 'text-success' : 'text-error'"
class="text-body-1"
>
{{ isPositive ? `+${props.change}` : props.change }}%
</div>
</div>
<div class="text-body-2">
{{ props.subtitle }}
</div>
</VCardText>
</VCard>
</template>

View File

@@ -0,0 +1,80 @@
<script setup>
const props = defineProps({
title: {
type: String,
required: true,
},
subtitle: {
type: String,
required: true,
},
stats: {
type: String,
required: true,
},
change: {
type: Number,
required: true,
},
image: {
type: String,
required: true,
},
color: {
type: String,
required: false,
default: 'primary',
},
})
const isPositive = controlledComputed(() => props.change, () => Math.sign(props.change) === 1)
</script>
<template>
<VCard class="overflow-visible">
<div class="d-flex position-relative">
<VCardText>
<h6 class="text-base font-weight-semibold mb-4">
{{ props.title }}
</h6>
<div class="d-flex align-center flex-wrap mb-4">
<h5 class="text-h5 font-weight-semibold me-2">
{{ props.stats }}
</h5>
<span
class="text-caption"
:class="isPositive ? 'text-success' : 'text-error'"
>
{{ isPositive ? `+${props.change}` : props.change }}%
</span>
</div>
<VChip
v-if="props.subtitle"
size="small"
:color="props.color"
>
{{ props.subtitle }}
</VChip>
</VCardText>
<VSpacer />
<div class="illustrator-img">
<VImg
v-if="props.image"
:src="props.image"
:width="110"
/>
</div>
</div>
</VCard>
</template>
<style lang="scss">
.illustrator-img {
position: absolute;
inset-block-end: 0;
inset-inline-end: 5%;
}
</style>

View File

@@ -0,0 +1,191 @@
@use "mixins";
@use "@layouts/styles/placeholders";
@use "@layouts/styles/mixins" as layoutMixins;
@use "@configured-variables" as variables;
@use "@styles/variables/_vuetify.scss" as vuetify;
// 👉 Avatar group
.v-avatar-group {
display: flex;
align-items: center;
> * {
&:not(:first-child) {
margin-inline-start: -0.8rem;
}
transition: transform 0.25s ease, box-shadow 0.15s ease;
&:hover {
z-index: 2;
transform: translateY(-5px) scale(1.05);
@include mixins.elevation(3);
}
}
> .v-avatar {
border: 2px solid rgb(var(--v-theme-surface));
transition: transform 0.15s ease;
}
}
// 👉 Button outline with default color border color
.v-alert--variant-outlined,
.v-avatar--variant-outlined,
.v-btn.v-btn--variant-outlined,
.v-card--variant-outlined,
.v-chip--variant-outlined,
.v-list-item--variant-outlined {
&:not([class*="text-"]) {
border-color: rgba(var(--v-border-color), var(--v-border-opacity));
}
&.text-default {
border-color: rgba(var(--v-border-color), var(--v-border-opacity));
}
}
// 👉 Custom Input
.v-label.custom-input {
padding: 1rem;
border: 1px solid rgba(var(--v-border-color), var(--v-border-opacity));
opacity: 1;
white-space: normal;
&:hover {
border-color: rgba(var(--v-border-color), 0.25);
}
&.active {
border-color: rgb(var(--v-theme-primary));
.v-icon {
color: rgb(var(--v-theme-primary)) !important;
}
}
&.custom-checkbox,
&.custom-radio {
.v-input__control {
grid-area: none;
}
}
}
// 👉 Datatable
.v-data-table-footer__pagination {
@include layoutMixins.rtl {
.v-btn {
.v-icon {
transform: rotate(180deg);
}
}
}
}
// Dialog responsive width
.v-dialog {
// dialog custom close btn
.v-dialog-close-btn {
position: absolute;
z-index: 1;
color: rgba(var(--v-theme-on-surface), var(--v-disabled-opacity)) !important;
inset-block-start: 0.5rem;
inset-inline-end: 0.5rem;
.v-btn__overlay {
display: none;
}
}
.v-card {
@extend %style-scroll-bar;
}
}
@media (min-width: 600px) {
.v-dialog {
&.v-dialog-sm,
&.v-dialog-lg,
&.v-dialog-xl {
.v-overlay__content {
inline-size: 565px !important;
}
}
}
}
@media (min-width: 960px) {
.v-dialog {
&.v-dialog-lg,
&.v-dialog-xl {
.v-overlay__content {
inline-size: 865px !important;
}
}
}
}
@media (min-width: 1264px) {
.v-dialog.v-dialog-xl {
.v-overlay__content {
inline-size: 1165px !important;
}
}
}
// 👉 Expansion panel
.v-expansion-panels.customized-panels {
border: 1px solid rgba(var(--v-border-color), var(--v-border-opacity));
border-radius: vuetify.$border-radius-root;
.v-expansion-panel-title {
background-color: rgb(var(--v-theme-expansion-panel-text-custom-bg));
border-block-end: 1px solid rgba(var(--v-border-color), var(--v-border-opacity));
margin-block-end: -1px;
}
.v-expansion-panel-text__wrapper {
padding: 20px;
}
}
// v-tab with pill support
.v-tabs.v-tabs-pill {
.v-tab.v-btn {
border-radius: 0.25rem !important;
transition: none;
.v-tab__slider {
visibility: hidden;
}
}
}
// loop for all colors bg
@each $color-name in variables.$theme-colors-name {
body .v-tabs.v-tabs-pill {
.v-slide-group__content {
gap: 0.25rem;
}
.v-tab--selected.text-#{$color-name} {
background-color: rgb(var(--v-theme-#{$color-name}));
color: rgb(var(--v-theme-on-#{$color-name})) !important;
}
}
}
// We are make even width of all v-timeline body
.v-timeline--vertical.v-timeline {
.v-timeline-item {
.v-timeline-item__body {
justify-self: stretch !important;
}
}
}
// 👉 Switch
.v-switch .v-selection-control:not(.v-selection-control--dirty) .v-switch__thumb {
color: #fff !important;
}

View File

@@ -0,0 +1,16 @@
@use "@configured-variables" as variables;
//
// * Perfect Scrollbar
//
body.v-theme--dark {
.ps__rail-y,
.ps__rail-x {
background-color: transparent !important;
}
.ps__thumb-y {
background-color: variables.$plugin-ps-thumb-y-dark;
}
}

View File

@@ -0,0 +1,103 @@
@use "@configured-variables" as variables;
@use "@core/scss/base/placeholders" as *;
@use "@core/scss/template/placeholders" as *;
@use "misc";
@use "@core/scss/base/mixins";
$header: ".layout-navbar";
@if variables.$layout-vertical-nav-navbar-is-contained {
$header: ".layout-navbar .navbar-content-container";
}
.layout-wrapper.layout-nav-type-vertical {
// SECTION Layout Navbar
// 👉 Elevated navbar
@if variables.$vertical-nav-navbar-style == "elevated" {
// Add transition
#{$header} {
transition: padding 0.2s ease, background-color 0.18s ease;
}
// If navbar is contained => Add border radius to header
@if variables.$layout-vertical-nav-navbar-is-contained {
#{$header} {
border-radius: 0 0 variables.$default-layout-with-vertical-nav-navbar-footer-roundness variables.$default-layout-with-vertical-nav-navbar-footer-roundness;
}
}
// Scrolled styles for sticky navbar
@at-root {
/* This html selector with not selector is required when:
dialog is opened and window don't have any scroll. This removes window-scrolled class from layout and our style broke
*/
html.v-overlay-scroll-blocked:not([style*="--v-body-scroll-y: 0px;"]) .layout-navbar-sticky,
&.window-scrolled.layout-navbar-sticky {
#{$header} {
@extend %default-layout-vertical-nav-scrolled-sticky-elevated-nav;
@extend %default-layout-vertical-nav-floating-navbar-and-sticky-elevated-navbar-scrolled;
}
.navbar-blur#{$header} {
@extend %blurry-bg;
}
}
}
}
// 👉 Floating navbar
@else if variables.$vertical-nav-navbar-style == "floating" {
// Regardless of navbar is contained or not => Apply overlay to .layout-navbar
.layout-navbar {
&.navbar-blur {
@extend %default-layout-vertical-nav-floating-navbar-overlay;
}
}
&:not(.layout-navbar-sticky) {
#{$header} {
margin-block-start: variables.$vertical-nav-floating-navbar-top;
}
}
#{$header} {
@if variables.$layout-vertical-nav-navbar-is-contained {
border-radius: variables.$default-layout-with-vertical-nav-navbar-footer-roundness;
}
background-color: rgb(var(--v-theme-surface));
@extend %default-layout-vertical-nav-floating-navbar-and-sticky-elevated-navbar-scrolled;
}
.navbar-blur#{$header} {
@extend %blurry-bg;
}
}
// !SECTION
// 👉 Layout footer
.layout-footer {
$ele-layout-footer: &;
.footer-content-container {
border-radius: variables.$default-layout-with-vertical-nav-navbar-footer-roundness variables.$default-layout-with-vertical-nav-navbar-footer-roundness 0 0;
// Sticky footer
@at-root {
// .layout-footer-sticky#{$ele-layout-footer} => .layout-footer-sticky.layout-wrapper.layout-nav-type-vertical .layout-footer
.layout-footer-sticky#{$ele-layout-footer} {
.footer-content-container {
background-color: rgb(var(--v-theme-surface));
padding-block: 0;
padding-inline: 1.2rem;
@include mixins.elevation(3);
}
}
}
}
}
}

View File

@@ -0,0 +1,16 @@
@use "@core/scss/base/placeholders";
@use "@core/scss/base/variables";
.layout-vertical-nav,
.layout-horizontal-nav {
ol,
ul {
list-style: none;
}
}
.layout-navbar {
@if variables.$navbar-high-emphasis-text {
@extend %layout-navbar;
}
}

View File

@@ -0,0 +1,40 @@
@use "sass:map";
// Layout
@use "vertical-nav";
@use "default-layout";
@use "default-layout-w-vertical-nav";
// Layouts package
@use "layouts";
// Components
@use "components";
// Utilities
@use "utilities";
// Misc
@use "misc";
// Dark
@use "dark";
// libs
@use "libs/perfect-scrollbar";
a {
color: rgb(var(--v-theme-primary));
text-decoration: none;
}
// Vuetify 3 don't provide margin bottom style like vuetify 2
p {
margin-block-end: 1rem;
}
// Iconify icon size
svg.iconify {
block-size: 1em;
inline-size: 1em;
}

View File

@@ -0,0 +1,63 @@
@use "@configured-variables" as variables;
/* This styles extends the existing layout package's styles for handling cases that aren't related to layouts package */
/*
When we use v-layout as immediate first child of `.page-content-container`, it adds display:flex and page doesn't get contained height
*/
// .layout-wrapper.layout-nav-type-vertical {
// &.layout-content-height-fixed {
// .page-content-container {
// > .v-layout:first-child > :not(.v-navigation-drawer):first-child {
// flex-grow: 1;
// block-size: 100%;
// }
// }
// }
// }
.layout-wrapper.layout-nav-type-vertical {
&.layout-content-height-fixed {
.page-content-container {
> .v-layout:first-child {
overflow: hidden;
min-block-size: 100%;
> .v-main {
// overflow-y: auto;
.v-main__wrap > :first-child {
block-size: 100%;
overflow-y: auto;
}
}
}
}
}
}
// Let div/v-layout take full height. E.g. Email App
.layout-wrapper.layout-nav-type-horizontal {
&.layout-content-height-fixed {
> .layout-page-content {
display: flex;
}
}
}
// 👉 Floating navbar styles
@if variables.$vertical-nav-navbar-style == "floating" {
// Add spacing above navbar if navbar is floating (was in %layout-navbar-sticky placeholder)
body .layout-wrapper.layout-nav-type-vertical.layout-navbar-sticky {
.layout-navbar {
inset-block-start: variables.$vertical-nav-floating-navbar-top;
}
/*
If it's floating navbar
Add `vertical-nav-floating-navbar-top` as margin top to .layout-page-content
*/
.layout-page-content {
margin-block-start: variables.$vertical-nav-floating-navbar-top;
}
}
}

View File

@@ -0,0 +1,20 @@
// scrollable-content allows creating fixed header and scrollable content for VNavigationDrawer (Used when perfect scrollbar is used)
.scrollable-content {
&.v-navigation-drawer {
.v-navigation-drawer__content {
display: flex;
overflow: hidden;
flex-direction: column;
}
}
}
// adding styling for code tag
code {
border-radius: 3px;
color: rgb(var(--v-code-color));
font-size: 90%;
font-weight: 400;
padding-block: 0.2em;
padding-inline: 0.4em;
}

View File

@@ -0,0 +1,63 @@
@use "sass:map";
@use "@styles/variables/vuetify.scss";
@mixin elevation($z, $important: false) {
box-shadow: map.get(vuetify.$shadow-key-umbra, $z), map.get(vuetify.$shadow-key-penumbra, $z), map.get(vuetify.$shadow-key-ambient, $z) if($important, !important, null);
}
// #region before-pseudo
// This mixin is inspired from vuetify for adding hover styles via before pseudo element
@mixin before-pseudo() {
position: relative;
&::before {
position: absolute;
border-radius: inherit;
background: currentcolor;
block-size: 100%;
content: "";
inline-size: 100%;
inset: 0;
opacity: 0;
pointer-events: none;
}
}
// #endregion before-pseudo
@mixin bordered-skin($component, $border-property: "border", $important: false) {
#{$component} {
box-shadow: none !important;
// stylelint-disable-next-line annotation-no-unknown
#{$border-property}: 1px solid rgba(var(--v-border-color), var(--v-border-opacity)) if($important, !important, null);
}
}
// #region selected-states
// Inspired from vuetify's active-states mixin
// focus => 0.12 & selected => 0.08
@mixin selected-states($selector) {
#{$selector} {
opacity: calc(var(--v-selected-opacity) * var(--v-theme-overlay-multiplier));
}
&:hover
#{$selector} {
opacity: calc(var(--v-selected-opacity) + var(--v-hover-opacity) * var(--v-theme-overlay-multiplier));
}
&:focus-visible
#{$selector} {
opacity: calc(var(--v-selected-opacity) + var(--v-focus-opacity) * var(--v-theme-overlay-multiplier));
}
@supports not selector(:focus-visible) {
&:focus {
#{$selector} {
opacity: calc(var(--v-selected-opacity) + var(--v-focus-opacity) * var(--v-theme-overlay-multiplier));
}
}
}
}
// #endregion selected-states

View File

@@ -0,0 +1,184 @@
@use "@configured-variables" as variables;
@use "@layouts/styles/mixins" as layoutsMixins;
/* 👉 Demo spacers */
/* TODO: Use vuetify SCSS variable here; */
$card-spacer-content: 16px;
.demo-space-x {
display: flex;
flex-wrap: wrap;
align-items: center;
margin-block-start: -$card-spacer-content;
& > * {
margin-block-start: $card-spacer-content;
margin-inline-end: $card-spacer-content;
}
}
.demo-space-y {
& > * {
margin-block-end: $card-spacer-content;
&:last-child {
margin-block-end: 0;
}
}
}
// 👉 Card match height
.match-height.v-row {
.v-card {
block-size: 100%;
}
}
// 👉 Whitespace
.whitespace-no-wrap {
white-space: nowrap;
}
// 👉 Colors
/*
Vuetify is applying `.text-white` class to badge icon but don't provide its styles
Moreover, we also use this class in some places
In vuetify 2 with `$color-pack: false` SCSS var config this class was getting generated but this is not the case in v3
We also need !important to get correct color in badge icon
*/
.text-white {
color: #fff !important;
}
.text-white-variant {
color: rgba(255, 255, 255, var(--v-high-emphasis-opacity));
}
.text-link {
&:not(:hover) {
color: rgba(var(--v-theme-on-surface), var(--v-high-emphasis-opacity));
}
}
.bg-var-theme-background {
background-color: rgba(var(--v-theme-on-background), var(--v-hover-opacity)) !important;
}
.bg-global-primary {
background-color: rgb(var(--v-theme-primary)) !important;
color: rgb(var(--v-theme-on-primary)) !important;
}
// [/^bg-light-(\w+)$/, ([, w]) => ({ backgroundColor: `rgba(var(--v-theme-${w}), var(--v-activated-opacity))` })],
@each $color-name in variables.$theme-colors-name {
.bg-light-#{$color-name} {
background-color: rgba(var(--v-theme-#{$color-name}), var(--v-activated-opacity)) !important;
}
}
// 👉 clamp text
.clamp-text {
display: -webkit-box;
overflow: hidden;
-webkit-box-orient: vertical;
-webkit-line-clamp: 2;
text-overflow: ellipsis;
}
.custom-badge {
.v-badge__badge {
border-radius: 6px !important;
block-size: 12px !important;
inline-size: 12px !important;
}
}
.leading-normal {
line-height: normal !important;
}
// 👉 for rtl only
.flip-in-rtl {
@include layoutsMixins.rtl {
transform: scaleX(-1);
}
}
// 👉 Carousel
.carousel-delimiter-top-end {
.v-carousel__controls {
justify-content: end;
block-size: 40px;
inset-block-start: 0;
padding-inline: 1rem;
.v-btn--icon.v-btn--density-default {
block-size: calc(var(--v-btn-height) + -10px);
color: rgba(var(--v-theme-on-surface), var(--v-medium-emphasis-opacity));
inline-size: calc(var(--v-btn-height) + -8px);
&.v-btn--active {
color: #fff;
}
.v-btn__overlay {
opacity: 0;
}
.v-ripple__container {
display: none;
}
.v-btn__content {
.v-icon {
block-size: 8px !important;
font-size: 8px !important;
inline-size: 8px !important;
}
}
}
}
@each $color-name in variables.$theme-colors-name {
&.dots-active-#{$color-name} {
.v-carousel__controls {
.v-btn--active {
color: rgb(var(--v-theme-#{$color-name})) !important;
}
}
}
}
}
.v-timeline-item {
.app-timeline-title {
color: rgba(var(--v-theme-on-surface), var(--v-high-emphasis-opacity));
font-size: 16px;
font-weight: 500;
line-height: 1.3125rem;
}
.app-timeline-meta {
color: rgba(var(--v-theme-on-surface), var(--v-disabled-opacity));
font-size: 12px;
line-height: 0.875rem;
}
.app-timeline-text {
color: rgba(var(--v-theme-on-surface), var(--v-medium-emphasis-opacity));
font-size: 14px;
line-height: 1.25rem;
}
.timeline-chip {
border-radius: 6px;
background: rgba(var(--v-theme-on-surface), var(--v-hover-opacity));
padding-block: 5px;
padding-inline: 10px;
}
}

View File

@@ -0,0 +1,90 @@
@use "sass:map";
@use "sass:list";
@use "@configured-variables" as variables;
// Thanks: https://css-tricks.com/snippets/sass/deep-getset-maps/
@function map-deep-get($map, $keys...) {
@each $key in $keys {
$map: map.get($map, $key);
}
@return $map;
}
@function map-deep-set($map, $keys, $value) {
$maps: ($map,);
$result: null;
// If the last key is a map already
// Warn the user we will be overriding it with $value
@if type-of(nth($keys, -1)) == "map" {
@warn "The last key you specified is a map; it will be overrided with `#{$value}`.";
}
// If $keys is a single key
// Just merge and return
@if length($keys) == 1 {
@return map-merge($map, ($keys: $value));
}
// Loop from the first to the second to last key from $keys
// Store the associated map to this key in the $maps list
// If the key doesn't exist, throw an error
@for $i from 1 through length($keys) - 1 {
$current-key: list.nth($keys, $i);
$current-map: list.nth($maps, -1);
$current-get: map.get($current-map, $current-key);
@if not $current-get {
@error "Key `#{$key}` doesn't exist at current level in map.";
}
$maps: list.append($maps, $current-get);
}
// Loop from the last map to the first one
// Merge it with the previous one
@for $i from length($maps) through 1 {
$current-map: list.nth($maps, $i);
$current-key: list.nth($keys, $i);
$current-val: if($i == list.length($maps), $value, $result);
$result: map.map-merge($current-map, ($current-key: $current-val));
}
// Return result
@return $result;
}
// font size utility classes
@each $name, $size in variables.$font-sizes {
.text-#{$name} {
font-size: $size;
line-height: map.get(variables.$font-line-height, $name);
}
}
// truncate utility class
.truncate {
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
// gap utility class
@each $name, $size in variables.$gap {
.gap-#{$name} {
gap: $size;
}
.gap-x-#{$name} {
column-gap: $size;
}
.gap-y-#{$name} {
row-gap: $size;
}
}
.list-none {
list-style-type: none;
}

View File

@@ -0,0 +1,198 @@
@use "vuetify/lib/styles/tools/functions" as *;
/*
TODO: Add docs on when to use placeholder vs when to use SASS variable
Placeholder
- When we want to keep customization to our self between templates use it
Variables
- When we want to allow customization from both user and our side
- You can also use variable for consistency (e.g. mx 1 rem should be applied to both vertical nav items and vertical nav header)
*/
@forward "@layouts/styles/variables" with (
// Adjust z-index so vertical nav & overlay stays on top of v-layout in v-main. E.g. Email app
$layout-vertical-nav-z-index: 1003,
$layout-overlay-z-index: 1002,
);
@use "@layouts/styles/variables" as *;
// 👉 Default layout
$navbar-high-emphasis-text: true !default;
// @forward "@layouts/styles/variables" with (
// $layout-vertical-nav-width: 350px !default,
// );
$theme-colors-name: (
"primary",
"secondary",
"error",
"info",
"success",
"warning"
) !default;
// 👉 Default layout with vertical nav
$default-layout-with-vertical-nav-navbar-footer-roundness: 10px !default;
// 👉 Vertical nav
$vertical-nav-background-color-rgb: var(--v-theme-background) !default;
$vertical-nav-background-color: rgb(#{$vertical-nav-background-color-rgb}) !default;
// This is used to keep consistency between nav items and nav header left & right margin
// This is used by nav items & nav header
$vertical-nav-horizontal-spacing: 1rem !default;
$vertical-nav-horizontal-padding: 0.75rem !default;
// Vertical nav header height. Mostly we will align it with navbar height;
$vertical-nav-header-height: $layout-vertical-nav-navbar-height !default;
$vertical-nav-navbar-elevation: 3 !default;
$vertical-nav-navbar-style: "elevated" !default; // options: elevated, floating
$vertical-nav-floating-navbar-top: 1rem !default;
// Vertical nav header padding
$vertical-nav-header-padding: 1rem $vertical-nav-horizontal-padding !default;
$vertical-nav-header-inline-spacing: $vertical-nav-horizontal-spacing !default;
// Move logo when vertical nav is mini (collapsed but not hovered)
$vertical-nav-header-logo-translate-x-when-vertical-nav-mini: -4px !default;
// Space between logo and title
$vertical-nav-header-logo-title-spacing: 0.9rem !default;
// Section title margin top (when its not first child)
$vertical-nav-section-title-mt: 1.5rem !default;
// Section title margin bottom
$vertical-nav-section-title-mb: 0.5rem !default;
// Vertical nav icons
$vertical-nav-items-icon-size: 1.5rem !default;
$vertical-nav-items-nested-icon-size: 0.9rem !default;
$vertical-nav-items-icon-margin-inline-end: 0.5rem !default;
// Transition duration for nav group arrow
$vertical-nav-nav-group-arrow-transition-duration: 0.15s !default;
// Timing function for nav group arrow
$vertical-nav-nav-group-arrow-transition-timing-function: ease-in-out !default;
// 👉 Horizontal nav
/*
Heads up
==================
Here we assume we will always use shorthand property which will apply same padding on four side
This is because this have been used as value of top property by `.popper-content`
*/
$horizontal-nav-padding: 0.6875rem !default;
// Gap between top level horizontal nav items
$horizontal-nav-top-level-items-gap: 4px !default;
// Horizontal nav icons
$horizontal-nav-items-icon-size: 1.5rem !default;
$horizontal-nav-third-level-icon-size: 0.9rem !default;
$horizontal-nav-items-icon-margin-inline-end: 0.625rem !default;
$horizontal-nav-group-arrow-icon-size: 1.375rem !default;
// We used SCSS variable because we want to allow users to update max height of popper content
// 120px is combined height of navbar & horizontal nav
$horizontal-nav-popper-content-max-height: calc(100dvh - 120px - 4rem) !default;
// This variable is used for horizontal nav popper content's `margin-top` and "The bridge"'s height. We need to sync both values.
$horizontal-nav-popper-content-top: calc($horizontal-nav-padding + 0.375rem) !default;
// 👉 Plugins
$plugin-ps-thumb-y-dark: rgba(var(--v-theme-surface-variant), 0.35) !default;
// 👉 Vuetify
// Used in src/@core/scss/base/libs/vuetify/_overrides.scss
$vuetify-reduce-default-compact-button-icon-size: true !default;
// 👉 Custom variables
// for utility classes
$font-sizes: () !default;
$font-sizes: map-deep-merge(
(
"xs": 0.75rem,
"sm": 0.875rem,
"base": 1rem,
"lg": 1.125rem,
"xl": 1.25rem,
"2xl": 1.5rem,
"3xl": 1.875rem,
"4xl": 2.25rem,
"5xl": 3rem,
"6xl": 3.75rem,
"7xl": 4.5rem,
"8xl": 6rem,
"9xl": 8rem
),
$font-sizes
);
// line height
$font-line-height: () !default;
$font-line-height: map-deep-merge(
(
"xs": 1rem,
"sm": 1.25rem,
"base": 1.5rem,
"lg": 1.75rem,
"xl": 1.75rem,
"2xl": 2rem,
"3xl": 2.25rem,
"4xl": 2.5rem,
"5xl": 1,
"6xl": 1,
"7xl": 1,
"8xl": 1,
"9xl": 1
),
$font-line-height
);
// gap utility class
$gap: () !default;
$gap: map-deep-merge(
(
"0": 0,
"1": 0.25rem,
"2": 0.5rem,
"3": 0.75rem,
"4": 1rem,
"5": 1.25rem,
"6":1.5rem,
"7": 1.75rem,
"8": 2rem,
"9": 2.25rem,
"10": 2.5rem,
"11": 2.75rem,
"12": 3rem,
"14": 3.5rem,
"16": 4rem,
"20": 5rem,
"24": 6rem,
"28": 7rem,
"32": 8rem,
"36": 9rem,
"40": 10rem,
"44": 11rem,
"48": 12rem,
"52": 13rem,
"56": 14rem,
"60": 15rem,
"64": 16rem,
"72": 18rem,
"80": 20rem,
"96": 24rem
),
$gap
);

View File

@@ -0,0 +1,259 @@
@use "@core/scss/base/placeholders" as *;
@use "@core/scss/template/placeholders" as *;
@use "@layouts/styles/mixins" as layoutsMixins;
@use "@configured-variables" as variables;
@use "@core/scss/base/mixins" as mixins;
@use "vuetify/lib/styles/tools/states" as vuetifyStates;
.layout-nav-type-vertical {
// 👉 Layout Vertical nav
.layout-vertical-nav {
$sl-layout-nav-type-vertical: &;
@extend %nav;
@at-root {
// Add styles for collapsed vertical nav
.layout-vertical-nav-collapsed#{$sl-layout-nav-type-vertical}.hovered {
@include mixins.elevation(6);
}
}
background-color: variables.$vertical-nav-background-color;
// 👉 Nav header
.nav-header {
overflow: hidden;
padding: variables.$vertical-nav-header-padding;
margin-inline: variables.$vertical-nav-header-inline-spacing;
min-block-size: variables.$vertical-nav-header-height;
// TEMPLATE: Check if we need to move this to master
.app-logo {
flex-shrink: 0;
transition: transform 0.25s ease-in-out;
@at-root {
// Move logo a bit to align center with the icons in vertical nav mini variant
.layout-vertical-nav-collapsed#{$sl-layout-nav-type-vertical}:not(.hovered) .nav-header .app-logo {
transform: translateX(variables.$vertical-nav-header-logo-translate-x-when-vertical-nav-mini);
@include layoutsMixins.rtl {
transform: translateX(-(variables.$vertical-nav-header-logo-translate-x-when-vertical-nav-mini));
}
}
}
}
.app-title {
margin-inline-start: variables.$vertical-nav-header-logo-title-spacing;
}
.header-action {
@extend %nav-header-action;
}
}
// 👉 Nav items shadow
.vertical-nav-items-shadow {
position: absolute;
z-index: 1;
background:
linear-gradient(
rgb(#{variables.$vertical-nav-background-color-rgb}) 5%,
rgba(#{variables.$vertical-nav-background-color-rgb}, 75%) 45%,
rgba(#{variables.$vertical-nav-background-color-rgb}, 20%) 80%,
transparent
);
block-size: 55px;
inline-size: 100%;
inset-block-start: calc(#{variables.$vertical-nav-header-height} - 2px);
opacity: 0;
pointer-events: none;
transition: opacity 0.15s ease-in-out;
will-change: opacity;
@include layoutsMixins.rtl {
transform: translateX(8px);
}
}
&.scrolled {
.vertical-nav-items-shadow {
opacity: 1;
}
}
// Setting z-index 1 will make perfect scrollbar thumb appear on top of vertical nav items shadow;
.ps__rail-y {
z-index: 1;
}
// 👉 Nav section title
.nav-section-title {
@extend %vertical-nav-item;
@extend %vertical-nav-section-title;
margin-block-end: variables.$vertical-nav-section-title-mb;
&:not(:first-child) {
margin-block-start: variables.$vertical-nav-section-title-mt;
}
.placeholder-icon {
margin-inline: auto;
}
}
// Nav item badge
.nav-item-badge {
@extend %vertical-nav-item-badge;
}
// 👉 Nav group & Link
.nav-link,
.nav-group {
overflow: hidden;
> :first-child {
@extend %vertical-nav-item;
@extend %vertical-nav-item-interactive;
}
.nav-item-icon {
@extend %vertical-nav-items-icon;
}
&.disabled {
opacity: var(--v-disabled-opacity);
pointer-events: none;
}
a {
outline: none;
}
}
// 👉 Vertical nav link
.nav-link {
@extend %nav-link;
> .router-link-exact-active {
@extend %nav-link-active;
}
> a {
// Adds before psudo element to style hover state
@include mixins.before-pseudo;
// Adds vuetify states
&:not(.router-link-active, .router-link-exact-active) {
@include vuetifyStates.states($active: false);
}
}
}
// 👉 Vertical nav group
.nav-group {
// Reduce the size of icon if link/group is inside group
.nav-group,
.nav-link {
.nav-item-icon {
@extend %vertical-nav-items-nested-icon;
}
}
// Hide icons after 2nd level
& .nav-group {
.nav-link,
.nav-group {
.nav-item-icon {
@extend %vertical-nav-items-icon-after-2nd-level;
}
}
}
.nav-group-arrow {
flex-shrink: 0;
transform-origin: center;
transition: transform variables.$vertical-nav-nav-group-arrow-transition-duration variables.$vertical-nav-nav-group-arrow-transition-timing-function;
will-change: transform;
}
// Rotate arrow icon if group is opened
&.open {
> .nav-group-label .nav-group-arrow {
transform: rotateZ(90deg);
}
}
// Nav group label
> :first-child {
// Adds before psudo element to style hover state
@include mixins.before-pseudo;
}
&:not(.active,.open) > :first-child {
// Adds vuetify states
@include vuetifyStates.states($active: false);
}
// Active & open states for nav group label
&.active,
&.open {
> :first-child {
@extend %vertical-nav-group-open-active;
}
}
}
}
}
// SECTION: Transitions
.vertical-nav-section-title-enter-active,
.vertical-nav-section-title-leave-active {
transition: opacity 0.1s ease-in-out, transform 0.1s ease-in-out;
}
.vertical-nav-section-title-enter-from,
.vertical-nav-section-title-leave-to {
opacity: 0;
transform: translateX(15px);
@include layoutsMixins.rtl {
transform: translateX(-15px);
}
}
.transition-slide-x-enter-active,
.transition-slide-x-leave-active {
transition: opacity 0.1s ease-in-out, transform 0.12s ease-in-out;
}
.transition-slide-x-enter-from,
.transition-slide-x-leave-to {
opacity: 0;
transform: translateX(-15px);
@include layoutsMixins.rtl {
transform: translateX(15px);
}
}
.vertical-nav-app-title-enter-active,
.vertical-nav-app-title-leave-active {
transition: opacity 0.1s ease-in-out, transform 0.12s ease-in-out;
}
.vertical-nav-app-title-enter-from,
.vertical-nav-app-title-leave-to {
opacity: 0;
transform: translateX(-15px);
@include layoutsMixins.rtl {
transform: translateX(15px);
}
}
// !SECTION

View File

@@ -0,0 +1,35 @@
$ps-size: 0.25rem;
$ps-hover-size: 0.375rem;
$ps-track-size: 0.5rem;
.ps__thumb-y {
inline-size: $ps-size !important;
inset-inline-end: 0.0625rem;
}
.ps__thumb-y,
.ps__thumb-x {
background-color: rgb(var(--v-theme-perfect-scrollbar-thumb)) !important;
}
.ps__thumb-x {
block-size: $ps-size !important;
}
.ps__rail-x {
background: transparent !important;
block-size: $ps-track-size;
}
.ps__rail-y {
background: transparent !important;
inline-size: $ps-track-size !important;
inset-inline-end: 0.125rem !important;
inset-inline-start: unset !important;
}
.ps__rail-y.ps--clicking .ps__thumb-y,
.ps__rail-y:focus > .ps__thumb-y,
.ps__rail-y:hover > .ps__thumb-y {
inline-size: $ps-hover-size !important;
}

View File

@@ -0,0 +1,257 @@
@use "@core/scss/base/utils";
@use "@configured-variables" as variables;
// 👉 Application
// We need accurate vh in mobile devices as well
.v-application__wrap {
/* stylelint-disable-next-line liberty/use-logical-spec */
min-height: 100dvh;
}
// 👉 Typography
h1,
h2,
h3,
h4,
h5,
h6,
.text-h1,
.text-h2,
.text-h3,
.text-h4,
.text-h5,
.text-h6,
.text-button,
.text-overline,
.v-card-title {
color: rgba(var(--v-theme-on-background), var(--v-high-emphasis-opacity));
}
body,
.text-body-1,
.text-body-2,
.text-subtitle-1,
.text-subtitle-2 {
color: rgba(var(--v-theme-on-background), var(--v-medium-emphasis-opacity));
}
// 👉 Grid
// Remove margin-bottom of v-input_details inside grid (validation error message)
.v-row {
.v-col,
[class^="v-col-*"] {
.v-input__details {
margin-block-end: 0;
}
}
}
// 👉 Button
@if variables.$vuetify-reduce-default-compact-button-icon-size {
.v-btn--density-compact.v-btn--size-default {
.v-btn__content > svg {
block-size: 22px;
font-size: 22px;
inline-size: 22px;
}
}
}
// 👉 Card
// Removes padding-top for immediately placed v-card-text after itself
.v-card-text {
& + & {
padding-block-start: 0 !important;
}
}
/*
👉 Checkbox & Radio Ripple
TODO Checkbox and switch component. Remove it when vuetify resolve the extra spacing: https://github.com/vuetifyjs/vuetify/issues/15519
We need this because form elements likes checkbox and switches are by default set to height of textfield height which is way big than we want
Tested with checkbox & switches
*/
.v-checkbox.v-input,
.v-switch.v-input {
--v-input-control-height: auto;
flex: unset;
}
.v-radio-group {
.v-selection-control-group {
.v-radio:not(:last-child) {
margin-inline-end: 0.9rem;
}
}
}
/*
👉 Tabs
Disable tab transition
This is for tabs where we don't have card wrapper to tabs and have multiple cards as tab content.
This class will disable transition and adds `overflow: unset` on `VWindow` to allow spreading shadow
*/
.disable-tab-transition {
overflow: unset !important;
.v-window__container {
block-size: auto !important;
}
.v-window-item:not(.v-window-item--active) {
display: none !important;
}
.v-window__container .v-window-item {
transform: none !important;
}
}
// 👉 List
.v-list {
// Set icons opacity to .87
.v-list-item__prepend > .v-icon,
.v-list-item__append > .v-icon {
opacity: var(--v-high-emphasis-opacity);
}
}
// 👉 Card list
/*
Custom class
Remove list spacing inside card
This is because card title gets padding of 20px and list item have padding of 16px. Moreover, list container have padding-bottom as well.
*/
.card-list {
--v-card-list-gap: 20px;
&.v-list {
padding-block: 0;
}
.v-list-item {
min-block-size: unset;
min-block-size: auto !important;
padding-block: 0 !important;
padding-inline: 0 !important;
> .v-ripple__container {
opacity: 0;
}
&:not(:last-child) {
padding-block-end: var(--v-card-list-gap) !important;
}
}
.v-list-item:hover,
.v-list-item:focus,
.v-list-item:active,
.v-list-item.active {
> .v-list-item__overlay {
opacity: 0 !important;
}
}
}
// 👉 Divider
.v-divider {
color: rgb(var(--v-border-color));
}
.v-divider.v-divider--vertical {
block-size: inherit;
}
// 👉 DataTable
.v-data-table {
/* stylelint-disable-next-line no-descending-specificity */
.v-checkbox-btn .v-selection-control__wrapper {
margin-inline-start: 0 !important;
}
.v-selection-control {
display: flex !important;
}
.v-pagination {
color: rgba(var(--v-theme-on-surface), var(--v-medium-emphasis-opacity));
}
}
// 👉 v-field
.v-field:hover .v-field__outline {
--v-field-border-opacity: var(--v-medium-emphasis-opacity);
}
// 👉 VLabel
.v-label {
opacity: 1 !important;
&:not(.v-field-label--floating) {
color: rgba(var(--v-theme-on-background), var(--v-medium-emphasis-opacity));
}
}
// 👉 Overlay
.v-overlay__scrim,
.v-navigation-drawer__scrim {
background: rgba(var(--v-overlay-scrim-background), var(--v-overlay-scrim-opacity)) !important;
opacity: 1 !important;
}
// 👉 VMessages
.v-messages {
color: rgba(var(--v-theme-on-surface), var(--v-medium-emphasis-opacity));
opacity: 1 !important;
}
// 👉 Alert close btn
.v-alert__close {
.v-btn--icon .v-icon {
--v-icon-size-multiplier: 1.5;
}
}
// 👉 Badge icon alignment
.v-badge__badge {
display: flex;
align-items: center;
}
// 👉 Btn focus outline style removed
.v-btn:focus-visible::after {
opacity: 0 !important;
}
// .v-select chip spacing for slot
.v-input:not(.v-select--chips) .v-select__selection {
.v-chip {
margin-block: 2px var(--select-chips-margin-bottom);
}
}
// 👉 VCard and VList subtitle color
.v-card-subtitle,
.v-list-item-subtitle {
color: rgba(var(--v-theme-on-background), var(--v-medium-emphasis-opacity));
}
// 👉 placeholders
.v-field__input {
@at-root {
& input::placeholder,
input#{&}::placeholder,
textarea#{&}::placeholder {
color: rgba(var(--v-theme-on-surface), var(--v-disabled-opacity)) !important;
opacity: 1 !important;
}
}
}

View File

@@ -0,0 +1,64 @@
@use "sass:map";
/* 👉 Shadow opacities */
$shadow-key-umbra-opacity-custom: var(--v-shadow-key-umbra-opacity);
$shadow-key-penumbra-opacity-custom: var(--v-shadow-key-penumbra-opacity);
$shadow-key-ambient-opacity-custom: var(--v-shadow-key-ambient-opacity);
/* 👉 Card transition properties */
$card-transition-property-custom: box-shadow, opacity;
@forward "vuetify/settings" with (
// 👉 General settings
$color-pack: false !default,
// 👉 Shadow opacity
$shadow-key-umbra-opacity: $shadow-key-umbra-opacity-custom !default,
$shadow-key-penumbra-opacity: $shadow-key-penumbra-opacity-custom !default,
$shadow-key-ambient-opacity: $shadow-key-ambient-opacity-custom !default,
// 👉 Card
$card-color: rgba(var(--v-theme-on-surface), var(--v-medium-emphasis-opacity)) !default,
$card-elevation: 6 !default,
$card-title-line-height: 1.6 !default,
$card-actions-min-height: unset !default,
$card-text-padding: 1.25rem !default,
$card-item-padding: 1.25rem !default,
$card-actions-padding: 0 12px 12px !default,
$card-transition-property: $card-transition-property-custom !default,
$card-subtitle-opacity: 1 !default,
// 👉 Expansion Panel
$expansion-panel-active-title-min-height: 48px !default,
// 👉 List
$list-item-icon-margin-end: 16px !default,
$list-item-icon-margin-start: 16px !default,
$list-item-subtitle-opacity: 1 !default,
// 👉 Navigation Drawer
$navigation-drawer-content-overflow-y: hidden !default,
// 👉 Tooltip
$tooltip-background-color: rgba(59, 55, 68, 0.9) !default,
$tooltip-text-color: rgb(var(--v-theme-on-primary)) !default,
$tooltip-font-size: 0.75rem !default,
$button-icon-density: ("default": 2, "comfortable": 0, "compact": -1 ) !default,
// 👉 VTimeline
$timeline-dot-size: 34px !default,
// 👉 table
$table-transition-property: height !default,
// 👉 VOverlay
$overlay-opacity: 1 !default,
// 👉 VContainer
$container-max-widths: (
"xl": 1440px,
"xxl": 1440px
) !default,
);

View File

@@ -0,0 +1,45 @@
@use "@configured-variables" as variables;
@use "misc";
@use "@core/scss/base/mixins";
%default-layout-vertical-nav-scrolled-sticky-elevated-nav {
background-color: rgb(var(--v-theme-surface));
}
%default-layout-vertical-nav-floating-navbar-and-sticky-elevated-navbar-scrolled {
@include mixins.elevation(variables.$vertical-nav-navbar-elevation);
// If navbar is contained => Squeeze navbar content on scroll
@if variables.$layout-vertical-nav-navbar-is-contained {
padding-inline: 1.2rem;
}
}
%default-layout-vertical-nav-floating-navbar-overlay {
isolation: isolate;
&::after {
position: absolute;
z-index: -1;
/* stylelint-disable property-no-vendor-prefix */
-webkit-backdrop-filter: blur(10px);
backdrop-filter: blur(10px);
/* stylelint-enable */
background:
linear-gradient(
180deg,
rgba(var(--v-theme-background), 70%) 44%,
rgba(var(--v-theme-background), 43%) 73%,
rgba(var(--v-theme-background), 0%)
);
background-repeat: repeat;
block-size: calc(variables.$layout-vertical-nav-navbar-height + variables.$vertical-nav-floating-navbar-top + 0.5rem);
content: "";
inset-block-start: -(variables.$vertical-nav-floating-navbar-top);
inset-inline: 0 0;
/* stylelint-disable property-no-vendor-prefix */
-webkit-mask: linear-gradient(black, black 18%, transparent 100%);
mask: linear-gradient(black, black 18%, transparent 100%);
/* stylelint-enable */
}
}

View File

@@ -0,0 +1,3 @@
%layout-navbar {
color: rgba(var(--v-theme-on-surface), var(--v-high-emphasis-opacity));
}

View File

@@ -0,0 +1,5 @@
@forward "vertical-nav";
@forward "nav";
@forward "default-layout";
@forward "default-layout-vertical-nav";
@forward "misc";

View File

@@ -0,0 +1,7 @@
%blurry-bg {
/* stylelint-disable property-no-vendor-prefix */
-webkit-backdrop-filter: blur(6px);
backdrop-filter: blur(6px);
/* stylelint-enable */
background-color: rgb(var(--v-theme-surface), 0.9);
}

View File

@@ -0,0 +1,33 @@
@use "@core/scss/base/mixins";
// This is common style that needs to be applied to both navs
%nav {
color: rgba(var(--v-theme-on-surface), var(--v-high-emphasis-opacity));
.nav-item-title {
letter-spacing: 0.15px;
}
.nav-section-title {
letter-spacing: 0.4px;
}
}
/*
Active nav link styles for horizontal & vertical nav
For horizontal nav it will be only applied to top level nav items
For vertical nav it will be only applied to nav links (not nav groups)
*/
%nav-link-active {
background-color: rgb(var(--v-theme-primary));
color: rgb(var(--v-theme-on-primary));
@include mixins.elevation(3);
}
%nav-link {
a {
color: inherit;
}
}

View File

@@ -0,0 +1,80 @@
@use "@core/scss/base/mixins";
@use "@configured-variables" as variables;
@use "vuetify/lib/styles/tools/states" as vuetifyStates;
%nav-header-action {
font-size: 1.25rem;
}
// Nav items styles (including section title)
%vertical-nav-item {
margin-block: 0;
margin-inline: variables.$vertical-nav-horizontal-spacing;
padding-block: 0;
padding-inline: variables.$vertical-nav-horizontal-padding;
white-space: nowrap;
}
// This is same as `%vertical-nav-item` except section title is excluded
%vertical-nav-item-interactive {
border-radius: 0.4rem;
block-size: 2.75rem;
/*
We will use `margin-block-end` instead of `margin-block` to give more space for shadow to appear.
With `margin-block`, due to small space (space gets divided between top & bottom) shadow cuts
*/
margin-block-end: 0.375rem;
}
// Common styles for nav item icon styles
// Nav group's children icon styles are not here (Adjusts height, width & margin)
%vertical-nav-items-icon {
flex-shrink: 0;
font-size: variables.$vertical-nav-items-icon-size;
margin-inline-end: variables.$vertical-nav-items-icon-margin-inline-end;
}
// Icon styling for icon nested inside another nav item (2nd level)
%vertical-nav-items-nested-icon {
/*
`margin-inline` will be (normal icon font-size - small icon font-size) / 2
(1.5rem - 0.9rem) / 2 => 0.6rem / 2 => 0.3rem
*/
$vertical-nav-items-nested-icon-margin-inline: calc((variables.$vertical-nav-items-icon-size - variables.$vertical-nav-items-nested-icon-size) / 2);
font-size: variables.$vertical-nav-items-nested-icon-size;
margin-inline: $vertical-nav-items-nested-icon-margin-inline $vertical-nav-items-nested-icon-margin-inline + variables.$vertical-nav-items-icon-margin-inline-end;
}
%vertical-nav-items-icon-after-2nd-level {
visibility: hidden;
}
// Open & Active nav group styles
%vertical-nav-group-open-active {
@include mixins.selected-states("&::before");
}
// Section title
// Setting height will prevent jerking when text & icon is toggled
%vertical-nav-section-title {
block-size: 1.5rem;
color: rgba(var(--v-theme-on-surface), var(--v-disabled-opacity));
font-size: 0.75rem;
text-transform: uppercase;
}
// Vertical nav item badge styles
%vertical-nav-item-badge {
display: inline-block;
border-radius: 1.5rem;
font-size: 0.8em;
font-weight: 500;
line-height: 1;
padding-block: 0.25em;
padding-inline: 0.55em;
text-align: center;
vertical-align: baseline;
white-space: nowrap;
}

View File

@@ -0,0 +1,28 @@
@use "@configured-variables" as variables;
@use "@core/scss/base/mixins";
$header: ".layout-navbar";
@if variables.$layout-vertical-nav-navbar-is-contained {
$header: ".layout-navbar .navbar-content-container";
}
.layout-wrapper.layout-nav-type-vertical {
// 👉 Layout footer
.layout-footer {
$ele-layout-footer: &;
.footer-content-container {
// Sticky footer
@at-root {
// .layout-footer-sticky#{$ele-layout-footer} => .layout-footer-sticky.layout-wrapper.layout-nav-type-vertical .layout-footer
.layout-footer-sticky#{$ele-layout-footer} {
.footer-content-container {
box-shadow: 0 -4px 8px -4px rgba(var(--v-shadow-key-umbra-color), 42%);
padding-inline: 1.5rem;
}
}
}
}
}
}

View File

@@ -0,0 +1,12 @@
@use "vuetify/lib/styles/settings" as vuetify_settings;
@mixin avatar-font-sizes($map: $avatar-sizes) {
@each $sizeName, $multiplier in vuetify_settings.$size-scales {
/* stylelint-disable-next-line scss/no-global-function-names */
$size: map-get($map, $sizeName);
&.v-avatar--size-#{$sizeName} {
font-size: #{$size}px;
}
}
}

View File

@@ -0,0 +1,51 @@
.v-timeline{
.v-timeline-item {
.app-timeline-title {
color: rgba(var(--v-theme-on-surface), var(--v-high-emphasis-opacity));
font-size: 15px;
font-weight: 500;
letter-spacing: 0.15px;
line-height: 1.375rem;
}
.app-timeline-meta {
color: rgba(var(--v-theme-on-surface), var(--v-disabled-opacity));
font-size: 13px;
letter-spacing: 0.4px;
line-height: 1.125rem;
}
.app-timeline-text {
color: rgba(var(--v-theme-on-surface), var(--v-medium-emphasis-opacity));
font-size: .9375rem;
line-height: 1.375rem;
}
}
}
.per-page-select {
margin-block: auto;
.v-field__input {
align-items: center;
padding: 2px;
}
.v-field__append-inner {
align-items: center;
padding: 0;
.v-icon {
margin-inline-start: 0 !important;
}
}
}
.leading-normal {
font-weight: 600;
letter-spacing: .0094rem;
}
.bg-custom-background{
background-color: rgb(var(--v-table-header-color)) !important;
}

View File

@@ -0,0 +1,41 @@
@use "sass:string";
/*
This function is helpful when we have multi dimensional value
Assume we have padding variable `$nav-padding-horizontal: 10px;`
With above variable let's say we use it in some style:
```scss
.selector {
margin-left: $nav-padding-horizontal;
}
```
Now, problem is we can also have value as `$nav-padding-horizontal: 10px 15px;`
In this case above style will be invalid.
This function will extract the left most value from the variable value.
$nav-padding-horizontal: 10px; => 10px;
$nav-padding-horizontal: 10px 15px; => 10px;
This is safe:
```scss
.selector {
margin-left: get-first-value($nav-padding-horizontal);
}
```
*/
@function get-first-value($var) {
$start-at: string.index(#{$var}, " ");
@if $start-at {
@return string.slice(
#{$var},
0,
$start-at
);
} @else {
@return $var;
}
}

View File

@@ -0,0 +1,56 @@
@use "sass:map";
@use "utils";
$vertical-nav-horizontal-padding-custom: 1.4375rem 1rem;
// We created this SCSS var to extract the start padding
// Docs: https://sass-lang.com/documentation/modules/string
// $vertical-nav-horizontal-padding => 0 8px;
// string.index(#{$vertical-nav-horizontal-padding}, " ") + 1 => 2
// string.index(#{$vertical-nav-horizontal-padding}, " ") => 1
// string.slice(0 8px, 2, -1) => 8px => $card-actions-padding-x
$vertical-nav-horizontal-padding-start: utils.get-first-value($vertical-nav-horizontal-padding-custom) !default;
$vertical-nav-items-icon-margin-inline-end: 0 !default;
@forward "@core/scss/base/variables" with (
$layout-vertical-nav-collapsed-width: 68px !default,
// This is used to keep consistency between nav items and nav header left & right margin
// This is used by nav items & nav header
$vertical-nav-horizontal-spacing: 0 1rem !default,
$vertical-nav-horizontal-padding: $vertical-nav-horizontal-padding-custom !default,
// Vertical nav header padding
$vertical-nav-header-padding: 1.25rem 0 1.25rem $vertical-nav-horizontal-padding-start !default,
// Vertical nav icons
$vertical-nav-items-icon-size: 1.375rem !default,
$vertical-nav-items-nested-icon-size: 0.75rem !default,
// Section title margin top (when its not first child)
$vertical-nav-section-title-mt: 1.25rem !default,
$layout-vertical-nav-footer-height: 54px !default,
// Horizontal nav icons
$horizontal-nav-items-icon-size: 1.375rem !default,
$horizontal-nav-items-icon-margin-inline-end: 0.5rem !default,
// 👉 Horizontal nav
$horizontal-nav-padding: 0.625rem !default,
$horizontal-nav-third-level-icon-size: 0.75rem !default,
// Gap between top level horizontal nav items
$horizontal-nav-top-level-items-gap: 8px !default,
// This variable is used for horizontal nav popper content's `margin-top` and "The bridge"'s height. We need to sync both values.
$horizontal-nav-popper-content-top: calc(0.625rem + 0.375rem - 0.25rem) !default,
$font-sizes: (
"sm": 0.8125rem,
"base": 0.9375rem,
),
$font-line-height: (
"base": 1.375rem,
),
);

View File

@@ -0,0 +1,51 @@
@use "@layouts/styles/mixins" as layoutsMixins;
.layout-nav-type-vertical {
// 👉 Layout Vertical nav
.layout-vertical-nav {
.nav-items{
padding-block-start: .25rem;
}
// 👉 Vertical nav group
.nav-group {
.nav-group-arrow {
font-size: 1.375rem;
}
}
// 👉 Nav group & Link
.nav-link,
.nav-group {
// shadow cut issue fix
margin-block-end: -0.5rem;
padding-block-end: 0.5rem;
a {
outline: none;
}
}
// 👉 Nav section title
.nav-section-title {
.placeholder-icon {
transform: translateX(-3px);
@include layoutsMixins.rtl {
transform: translateX(3px);
}
}
}
// 👉 Nav header
.nav-header {
padding-block: 1.25rem;
padding-inline: 23px 0;
}
}
}
// 👉 Overlay
.layout-overlay{
touch-action: none;
}

View File

@@ -0,0 +1,10 @@
@use "sass:map";
@use "@core/scss/base";
// layouts
@use "vertical-nav";
@use "default-layout-w-vertical-nav";
// Utilities
@use "utilities";

View File

@@ -0,0 +1,107 @@
@use "@styles/variables/_vuetify.scss" as vuetify;
@use "@layouts/styles/mixins" as layoutsMixins;
@use "@core/scss/base/mixins";
body .apexcharts-canvas {
&line[stroke="transparent"] {
display: "none";
}
.apexcharts-tooltip {
@include mixins.elevation(3);
border-color: rgba(var(--v-border-color), var(--v-border-opacity));
background: rgb(var(--v-theme-surface));
.apexcharts-tooltip-title {
border-color: rgba(var(--v-border-color), var(--v-border-opacity));
background: rgb(var(--v-theme-surface));
font-weight: 600;
}
&.apexcharts-theme-light {
color: rgba(var(--v-theme-on-background), var(--v-high-emphasis-opacity));
}
&.apexcharts-theme-dark {
color: white;
}
.apexcharts-tooltip-series-group:first-of-type {
padding-block-end: 0;
}
}
.apexcharts-xaxistooltip {
border-color: rgba(var(--v-border-color), var(--v-border-opacity));
background: rgb(var(--v-theme-grey-50));
color: rgba(var(--v-theme-on-background), var(--v-high-emphasis-opacity));
&::after {
border-block-end-color: rgb(var(--v-theme-grey-50));
}
&::before {
border-block-end-color: rgba(var(--v-border-color), var(--v-border-opacity));
}
}
.apexcharts-yaxistooltip {
border-color: rgba(var(--v-border-color), var(--v-border-opacity));
background: rgb(var(--v-theme-grey-50));
&::after {
border-inline-start-color: rgb(var(--v-theme-grey-50));
}
&::before {
border-inline-start-color: rgba(var(--v-border-color), var(--v-border-opacity));
}
}
.apexcharts-xaxistooltip-text,
.apexcharts-yaxistooltip-text {
color: rgba(var(--v-theme-on-background), var(--v-high-emphasis-opacity));
}
.apexcharts-yaxis .apexcharts-yaxis-texts-g .apexcharts-yaxis-label {
@include layoutsMixins.rtl {
text-anchor: start;
}
}
.apexcharts-text,
.apexcharts-tooltip-text,
.apexcharts-datalabel-label,
.apexcharts-datalabel,
.apexcharts-xaxistooltip-text,
.apexcharts-yaxistooltip-text,
.apexcharts-legend-text {
font-family: vuetify.$body-font-family !important;
}
.apexcharts-pie-label {
fill: white;
filter: none;
}
.apexcharts-marker {
box-shadow: none;
}
.apexcharts-tooltip-marker {
margin-inline-end: 0.625rem;
@include layoutsMixins.rtl {
margin-inline: 0 0.625rem !important;
}
}
.apexcharts-legend-marker {
margin-inline-end: 0.3875rem !important;
@include layoutsMixins.rtl {
margin-inline-end: 0.75rem !important;
}
}
}

View File

@@ -0,0 +1,38 @@
@use "@core/scss/base/utils";
@use "@configured-variables" as variables;
// 👉 Body
// set body font size 15px
body {
font-size: 15px !important;
}
// 👉 Typography
.text-h1,
.text-h2,
.text-h3,
.text-h4,
.text-h5,
.text-h6,
.text-overline,
.v-input {
color: rgba(var(--v-theme-on-background), var(--v-high-emphasis-opacity));
}
.text-caption{
color: rgba(var(--v-theme-on-background), var(--v-disabled-opacity));
}
.v-card-subtitle,
.text-subtitle-1,
.text-subtitle-2 {
color: rgba(var(--v-theme-on-background), 0.55);
}
// 👉 Input placeholder alignment
.v-input--density-compact{
input::placeholder {
position: relative;
inset-block-start: 1px;
}
}

View File

@@ -0,0 +1,323 @@
$font-family-custom: "Inter", sans-serif, -apple-system, blinkmacsystemfont, "Segoe UI", roboto,
"Helvetica Neue", arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol";
/* stylelint-disable length-zero-no-unit */
@forward "../../../base/libs/vuetify/variables" with (
$body-font-family: $font-family-custom !default,
$border-radius-root: 6px,
$rounded: (
"sm": 4px,
"shaped": 25px 0,
"lg":8px,
) !default,
// 👉 Typography
$typography: (
"h1": (
"size": 2.875rem,
"weight": 500,
"line-height": 4.25rem,
"letter-spacing": normal,
),
"h2": (
"size": 2.375rem,
"weight": 500,
"line-height": 3.5rem,
"letter-spacing": normal,
),
"h3": (
"size": 1.75rem,
"weight": 500,
"line-height": 2.625rem,
"letter-spacing": normal,
),
"h4": (
"size": 1.5rem,
"weight": 500,
"line-height": 2.375rem,
"letter-spacing": normal,
),
"h5": (
"size": 1.125rem,
"weight": 500,
"line-height": 1.75rem,
"letter-spacing": normal,
),
"h6": (
"size": 0.9375rem,
"line-height": 1.375rem,
"letter-spacing": normal,
),
"subtitle-1": (
"size": 0.9375rem,
"line-height": 1.375rem,
"letter-spacing": normal,
),
"subtitle-2": (
"size": 0.8125rem,
"line-height": 1.25rem,
"letter-spacing": normal,
),
"body-1": (
"size": 0.9375rem,
"line-height": 1.375rem,
"letter-spacing": normal,
),
"body-2": (
"size": 0.8125rem,
"line-height": 1.25rem,
"letter-spacing": normal,
),
"caption": (
"size": 0.8125rem,
"line-height": 1.125rem,
"letter-spacing": 0.025rem,
),
"overline": (
"weight": 400,
"line-height": 0.875rem,
"letter-spacing": 0.05rem,
),
"button": (
"size": 0.9375rem,
"weight": 500,
"letter-spacing": normal,
"font-family": $font-family-custom,
"text-transform": capitalize,
),
)!default,
// 👉 Shadows
$shadow-key-umbra: (
0: (0 0 0 0 rgba(var(--v-shadow-key-umbra-color), 1)),
1: (0 2px 4px rgba(var(--v-shadow-key-umbra-color), 0.12)),
2: (0 2px 4px 0 rgba(var(--v-shadow-key-umbra-color), var(--v-shadow-xs-opacity))),
3: (0 3px 8px rgba(var(--v-shadow-key-umbra-color), 0.14)),
4: (0 3px 6px 0 rgba(var(--v-shadow-key-umbra-color), var(--v-shadow-sm-opacity))),
5: (0 4px 10px rgba(var(--v-shadow-key-umbra-color), 0.15)),
6: (0 4px 10px 0 rgba(var(--v-shadow-key-umbra-color), var(--v-shadow-md-opacity))),
7: (0 4px 18px rgba(var(--v-shadow-key-umbra-color), 0.1)),
8: (0 6px 16px 0 rgba(var(--v-shadow-key-umbra-color), var(--v-shadow-lg-opacity))),
9: (0 5px 14px rgba(var(--v-shadow-key-umbra-color), 0.18)),
10: (0 8px 28px 0 rgba(var(--v-shadow-key-umbra-color), var(--v-shadow-xl-opacity))),
11: (0 5px 16px rgba(var(--v-shadow-key-umbra-color), 0.2)),
12: (0 6px 17px rgba(var(--v-shadow-key-umbra-color), 0.22)),
13: (0 6px 18px rgba(var(--v-shadow-key-umbra-color), 0.22)),
14: (0 6px 19px rgba(var(--v-shadow-key-umbra-color), 0.24)),
15: (0 7px 20px rgba(var(--v-shadow-key-umbra-color), 0.24)),
16: (0 7px 21px rgba(var(--v-shadow-key-umbra-color), 0.26)),
17: (0 7px 22px rgba(var(--v-shadow-key-umbra-color), 0.26)),
18: (0 8px 23px rgba(var(--v-shadow-key-umbra-color), 0.28)),
19: (0 8px 24px 6px rgba(var(--v-shadow-key-umbra-color), 0.28)),
20: (0 9px 25px rgba(var(--v-shadow-key-umbra-color), 0.3)),
21: (0 9px 26px rgba(var(--v-shadow-key-umbra-color), 0.32)),
22: (0 9px 27px rgba(var(--v-shadow-key-umbra-color), 0.32)),
23: (0 10px 28px rgba(var(--v-shadow-key-umbra-color), 0.34)),
24: (0 10px 30px rgba(var(--v-shadow-key-umbra-color), 0.34))
) !default,
$shadow-key-penumbra: (
0: (0 0 transparent),
1: (0 0 transparent),
2: (0 0 transparent),
3: (0 0 transparent),
4: (0 0 transparent),
5: (0 0 transparent),
6: (0 0 transparent),
7: (0 0 transparent),
8: (0 0 transparent),
9: (0 0 transparent),
10: (0 0 transparent),
11: (0 0 transparent),
12: (0 0 transparent),
13: (0 0 transparent),
14: (0 0 transparent),
15: (0 0 transparent),
16: (0 0 transparent),
17: (0 0 transparent),
18: (0 0 transparent),
19: (0 0 transparent),
20: (0 0 transparent),
21: (0 0 transparent),
22: (0 0 transparent),
23: (0 0 transparent),
24: (0 0 transparent),
) !default,
$shadow-key-ambient: (
0: (0 0 transparent),
1: (0 0 transparent),
2: (0 0 transparent),
3: (0 0 transparent),
4: (0 0 transparent),
5: (0 0 transparent),
6: (0 0 transparent),
7: (0 0 transparent),
8: (0 0 transparent),
9: (0 0 transparent),
10: (0 0 transparent),
11: (0 0 transparent),
12: (0 0 transparent),
13: (0 0 transparent),
14: (0 0 transparent),
15: (0 0 transparent),
16: (0 0 transparent),
17: (0 0 transparent),
18: (0 0 transparent),
19: (0 0 transparent),
20: (0 0 transparent),
21: (0 0 transparent),
22: (0 0 transparent),
23: (0 0 transparent),
24: (0 0 transparent),
) !default,
// 👉 Avatar
$avatar-color: rgba(var(--v-theme-on-surface), var(--v-high-emphasis-opacity)) !default,
// 👉 Alert
$alert-title-font-size: 1.125rem !default,
$alert-text-line-height: 1.625rem !default,
// 👉 Autocomplete
$autocomplete-content-elevation: 8 !default,
$combobox-content-elevation: 8 !default,
$select-content-elevation: 8 !default,
// 👉 Badge
$badge-height: 1.375rem !default,
$badge-min-width: 1.375rem !default,
$badge-dot-height: 8px !default,
$badge-dot-width: 8px !default,
$badge-border-radius: 50px !default,
$badge-font-size: 0.8125rem !default,
// 👉 Buttons
$button-height: 38px !default,
$button-padding-ratio: 2.15 !default,
$button-margin-start: 0 !default,
$button-disabled-opacity: .45 !default,
$button-elevation: ('default': 2, 'hover': 2, 'active': 0) !default,
$button-density: ('default': 0, 'comfortable': -1, 'compact': -2) !default,
$button-line-height: 1.375rem !default,
$button-margin-end: 0.375rem !default,
$button-card-actions-padding: 0 18px !default,
// 👉 Chip
$chip-font-size: 13px !default,
$chip-close-size: 20px !default,
$chip-font-weight: 500 !default,
// 👉 Cards
$card-actions-padding: 0 6px 6px !default,
$card-title-font-size: 1.125rem !default,
$card-title-line-height: 1.75rem !default,
$card-text-font-size: 0.9375rem !default,
$card-text-line-height: 1.375rem !default,
$card-subtitle-font-size: 0.9375rem !default,
$card-subtitle-line-height: 1.375rem !default,
$card-subtitle-font-weight: 400 !default,
$card-subtitle-header-padding: 0 !default,
// 👉 Dialog
$dialog-elevation: 10 !default,
$dialog-card-header-padding: 20px !default,
$dialog-card-text-padding: 0 20px 20px !default,
// 👉 Expansion Panel
$expansion-panel-active-margin: 0.5rem !default,
$expansion-panel-text-padding: 0 20px 20px !default,
$expansion-panel-title-padding: 12px 20px !default,
$expansion-panel-title-min-height: 46px !default,
$expansion-panel-active-title-min-height: 46px !default,
// 👉 Field
$field-outline-opacity: 0.22 !default,
$field-control-affixed-padding: 16px !default,
$field-control-affixed-inner-padding: 10px !default,
$field-font-size: 15px !default,
// 👉 Label
$label-font-size: 0.9375rem !default,
$label-letter-spacing: normal !default,
// 👉 List
$list-item-one-line-min-height: 38px !default,
$list-subheader-min-height: 38px !default,
$list-item-padding: 8px 20px !default,
$list-subheader-font-weight: 500 !default,
$list-item-icon-margin-start: 12px !default,
$list-item-min-height: 38px !default,
$list-item-nav-title-font-size: 0.9375rem !default,
$list-item-nav-title-font-weight: 400 !default,
$list-item-nav-subtitle-font-size: 0.8125rem !default,
$list-item-subtitle-line-height: 1.25rem !default,
// 👉 label
$field-label-floating-scale: 0.8125 !default,
// 👉 Snackbar
$snackbar-background: rgb(var(--v-tooltip-background)) !default,
$snackbar-color: rgb(var(--v-theme-surface)) !default,
$snackbar-content-padding: 12px 16px !default,
$snackbar-wrapper-padding: 0 !default,
$snackbar-wrapper-min-height: 44px !default,
$snackbar-elevation: 2 !default,
$snackbar-btn-padding: 0 10px !default,
$snackbar-action-margin: 16px !default,
// 👉 Slider
$slider-thumb-hover-opacity: var(--v-activated-opacity) !default,
// 👉 Switch
$switch-inset-track-width: 1.875rem !default,
$switch-inset-track-height: 1.125rem !default,
$switch-inset-thumb-height: 0.875rem !default,
$switch-inset-thumb-width: 0.875rem !default,
$switch-inset-thumb-off-height: 0.875rem !default,
$switch-track-opacity: 1 !default,
$switch-track-background: rgba(var(--v-theme-on-surface), var(--v-focus-opacity)) !default,
// 👉 Tooltip
$tooltip-background-color: rgb(var(--v-tooltip-background)) !default,
$tooltip-text-color: rgb(var(--v-theme-surface)) !default,
$tooltip-border-radius: 0.25rem !default,
$tooltip-font-size: 0.8125rem !default,
$tooltip-padding: 4px 12px !default,
$tooltip-line-height: 1.25rem !default,
// 👉 VPagination
$pagination-item-margin: 0.1875rem !default,
// 👉 Tabs
$tabs-height: 38px !default,
$tab-min-width: 60px !default,
// 👉 Timeline
$timeline-divider-line-background: rgba(var(--v-border-color), var(--v-border-opacity)) !default,
$timeline-divider-line-thickness: 1.5px !default,
$timeline-item-padding: 16px !default,
// 👉 Slider
$slider-track-active-size-offset: 0px !default,
$slider-thumb-label-border-radius: 6px !default,
$slider-thumb-label-height: 28px !default,
$slider-thumb-label-padding: 4px 10px !default,
// 👉 Table
$table-row-height: 50px !default,
$table-header-font-weight: 500 !default,
$table-color: rgba(var(--v-theme-on-surface), var(--v-medium-emphasis-opacity)) !default,
$table-font-size: 15px !default,
$table-column-padding: 0 20px !default,
// 👉 Radio
$radio-group-label-selection-group-padding-inline: 0 !default,
// 👉 navigation drawer
$navigation-drawer-temporary-elevation: 8 !default,
$navigation-drawer-transition-duration: 0.4s !default,
// 👉 Messages
$messages-font-size: 13px !default,
);

View File

@@ -0,0 +1,103 @@
@use "@core/scss/base/mixins";
@use "@configured-variables" as variables;
/* 👉 Alert
/ custom icon styling */
// 👉 Alert
.v-alert {
.v-alert__content {
font-size: 0.9375rem;
font-weight: 400;
line-height: 1.375rem;
.v-alert-title {
margin-block-end: 0.25rem;
}
}
&:not(.v-alert--prominent) .v-alert__prepend {
border-radius: 0.375rem;
block-size: 1.875rem;
inline-size: 1.875rem;
.v-icon {
margin: auto;
block-size: 1.375rem !important;
font-size: 1.375rem !important;
inline-size: 1.375rem !important;
}
}
&:not(.v-alert--prominent) {
&.v-alert--variant-flat,
&.v-alert--variant-elevated {
.v-alert__prepend {
background-color: #fff;
@include mixins.elevation(2);
}
}
&.v-alert--variant-tonal {
.v-alert__prepend {
z-index: 1;
}
}
}
.v-alert__close {
.v-btn--icon {
--v-btn-height: 34px;
.v-btn__content {
padding: 0.375rem;
.v-icon {
block-size: 1.25rem;
font-size: 1.25rem;
inline-size: 1.25rem;
}
}
}
}
}
@each $color-name in variables.$theme-colors-name {
.v-alert {
&:not(.v-alert--prominent) {
&.bg-#{$color-name},
&.text-#{$color-name} {
.v-alert__prepend .v-icon {
color: rgb(var(--v-theme-#{$color-name})) !important;
}
}
&.v-alert--variant-tonal {
&.text-#{$color-name},
&.bg-#{$color-name} {
.v-alert__underlay {
background: rgb(var(--v-theme-#{$color-name})) !important;
}
.v-alert__prepend {
background-color: rgb(var(--v-theme-#{$color-name}));
.v-icon {
color: #fff !important;
}
}
}
}
&.v-alert--variant-outlined {
&.text-#{$color-name},
&.bg-#{$color-name} {
.v-alert__prepend {
background-color: rgba(var(--v-theme-#{$color-name}), 0.16);
}
}
}
}
}
}

View File

@@ -0,0 +1,28 @@
@use "@core/scss/base/mixins";
// 👉 Avatar
body {
.v-avatar {
font-size: 0.9375rem;
.v-icon {
block-size: 1.5rem;
font-size: 1.5rem;
inline-size: 1.5rem;
}
&.v-avatar--variant-tonal:not([class*="text-"]) {
.v-avatar__underlay {
--v-activated-opacity: 0.08;
}
}
}
.v-avatar-group {
> * {
&:hover {
@include mixins.elevation(6);
}
}
}
}

View File

@@ -0,0 +1,35 @@
@use "@configured-variables" as variables;
// 👉 Badge
.v-badge {
&.v-badge--inline:not(.v-badge--dot) {
.v-badge__wrapper {
.v-badge__badge {
padding-block: 4px;
padding-inline: 8px;
}
}
}
&.v-badge--tonal {
@each $color-name in variables.$theme-colors-name {
.v-badge__wrapper {
.v-badge__badge.bg-#{$color-name} {
background-color: rgba(var(--v-theme-#{$color-name}), var(--v-activated-opacity)) !important;
color: rgb(var(--v-theme-#{$color-name})) !important;
}
}
}
}
/* stylelint-disable-next-line no-descending-specificity */
&.v-badge--bordered.v-badge--dot .v-badge__badge {
border-radius: 10px;
block-size: 12px;
inline-size: 12px;
&::after {
border-width: 2px;
}
}
}

View File

@@ -0,0 +1,271 @@
/* stylelint-disable no-descending-specificity */
@use "sass:list";
@use "sass:map";
@use "@configured-variables" as variables;
/* 👉 Button
Above map but opacity values as key and variant as value */
body {
.v-btn {
&:not(.v-btn--block) {
min-inline-size: auto;
}
&--variant-elevated,
&--variant-flat {
&.v-btn--disabled {
.v-btn__overlay {
opacity: 0.45;
}
}
}
// Default (elevated) button
/* stylelint-disable-next-line no-duplicate-selectors */
&--variant-elevated,
&--variant-flat {
// We want darker background on hover instead of light
&:hover {
.v-btn__overlay {
opacity: 0;
}
}
&:not(.v-btn--loading, .v-btn--disabled) {
@each $color-name in variables.$theme-colors-name {
&.bg-#{$color-name} {
&:hover,
&:active,
&:focus {
background-color: rgb(var(--v-theme-#{$color-name}-darken-1)) !important;
}
}
}
}
}
&--variant-elevated {
&:active {
box-shadow: none;
}
}
// Outlined variant
&--variant-outlined,
&--variant-text {
.v-btn__overlay {
--v-hover-opacity: 0.08;
}
&:active {
.v-btn__overlay {
opacity: var(--v-hover-opacity);
}
}
&:focus {
.v-btn__overlay {
opacity: var(--v-hover-opacity);
}
}
}
// Tonal variant
&--variant-tonal {
&:hover {
.v-btn__underlay {
opacity: 0;
}
.v-btn__overlay {
--v-hover-opacity: 0.24;
}
}
&:active {
.v-btn__overlay {
--v-hover-opacity: 0.24;
opacity: var(--v-hover-opacity);
}
.v-btn__underlay {
opacity: 0;
}
}
&:focus {
.v-btn__overlay {
--v-hover-opacity: 0.24;
opacity: var(--v-hover-opacity);
}
.v-btn__underlay {
opacity: 0;
}
}
}
&--icon.v-btn--density-default {
block-size: var(--v-btn-height);
inline-size: var(--v-btn-height);
padding-inline: 6px;
&.v-btn--size-default {
.v-icon {
--v-icon-size-multiplier: 1 !important;
}
}
&.v-btn--size-small {
.v-icon {
block-size: 20px;
font-size: 20px;
inline-size: 20px;
}
}
&.v-btn--size-large {
.v-icon {
block-size: 28px;
font-size: 28px;
inline-size: 28px;
}
}
}
&:not(.v-btn--icon) .v-icon {
--v-icon-size-multiplier: 0.7115;
inline-size: auto;
}
&--variant-text,
&--variant-plain {
&:not(.v-btn--icon) {
padding-inline: 14px;
}
}
// Button Size
&--size-x-small {
--v-btn-height: 28px;
--v-btn-size: 11px;
&:not(.v-btn--icon) {
border-radius: 0.125rem;
}
line-height: 14px;
padding-block: 0;
padding-inline: 10px;
}
&--size-small {
--v-btn-height: 34px;
--v-btn-size: 13px;
&:not(.v-btn--icon) {
border-radius: 0.25rem;
}
line-height: 18px;
padding-block: 0;
padding-inline: 14px;
.v-icon {
--v-icon-size-multiplier: 0.718;
}
}
&--size-large {
--v-btn-height: 42px;
--v-btn-size: 17px;
&:not(.v-btn--icon) {
border-radius: 0.5rem;
}
line-height: 26px;
padding-block: 0;
padding-inline: 22px;
}
&--size-x-large {
--v-btn-height: 48px;
--v-btn-size: 19px;
&:not(.v-btn--icon) {
border-radius: 0.625rem;
}
line-height: 30px;
padding-block: 0;
padding-inline: 26px;
}
// Toggle Button
&-toggle {
.v-btn {
border-radius: 0.375rem;
block-size: 52px !important;
border-inline-end: none;
inline-size: 52px !important;
&.v-btn--density-comfortable {
block-size: 44px !important;
inline-size: 44px !important;
}
&.v-btn--density-compact {
block-size: 36px !important;
inline-size: 36px !important;
}
.v-icon {
color: rgba(var(--v-theme-on-surface), var(--v-medium-emphasis-opacity));
font-size: 24px;
}
&--active {
.v-icon {
color: rgba(var(--v-theme-on-surface), var(--v-high-emphasis-opacity));
}
}
}
&.v-btn-group {
align-items: center;
padding: 7px;
border: 1px solid rgba(var(--v-border-color), var(--v-border-opacity));
block-size: 66px;
.v-btn.v-btn--active {
.v-btn__overlay {
--v-activated-opacity: 0.08;
}
}
&.v-btn-group--density-compact {
block-size: 50px;
}
&.v-btn-group--density-comfortable {
block-size: 58px;
}
}
}
}
// 👉 Btn group
.v-btn-group {
border: none;
&.v-btn-group--divided .v-btn:not(:last-child) {
border-inline-end-color: unset;
}
}
}

View File

@@ -0,0 +1,42 @@
@use "sass:list";
@use "sass:map";
@use "@styles/variables/vuetify";
@use "@configured-variables" as variables;
// 👉 checkbox box shadow
.v-checkbox-btn {
&.v-selection-control--dirty {
.v-selection-control__input {
.v-icon.custom-checkbox-checked,
.v-icon.custom-checkbox-indeterminate {
// Using filter: drop-shadow() instead of box-shadow because box-shadow creates white background for SVG;Usingfilter
filter: drop-shadow(rgba(var(--v-shadow-key-umbra-color), 16%) 0 2px 4px);
}
}
}
&.v-selection-control {
.v-label {
color: rgba(var(--v-theme-on-background), var(--v-high-emphasis-opacity));
}
.v-selection-control__input {
svg {
font-size: 1.5rem;
}
}
}
&:not(.v-selection-control--dirty) {
.v-selection-control__input {
> .v-icon {
color: rgba(var(--v-theme-on-surface), var(--v-medium-emphasis-opacity));
opacity: 1;
}
> .custom-checkbox-indeterminate {
color: rgb(var(--v-theme-primary));
}
}
}
}

View File

@@ -0,0 +1,99 @@
// 👉 Chip
.v-chip {
line-height: 1.25rem !important;
&:not(.v-chip--variant-elevated) {
color: rgba(var(--v-theme-on-surface), var(--v-high-emphasis-opacity));
}
.v-chip__close {
margin-inline: 4px -8px !important;
.v-icon {
opacity: 0.7;
}
}
&:not([class*="text-"]) {
--v-activated-opacity: 0.08;
}
&.v-chip--size-small {
--v-chip-height: 24px !important;
font-size: 13px !important;
padding-block: 0 !important;
padding-inline: 12px !important;
.v-chip__prepend {
.v-icon--start {
font-size: 1rem;
margin-inline: -8px 4px;
}
.v-avatar {
--v-avatar-height: 16px;
}
.v-avatar--start {
margin-inline: -8px 4px;
}
}
.v-chip__append {
.v-icon--end {
font-size: 1rem;
margin-inline: 4px -8px;
}
.v-avatar {
--v-avatar-height: 16px;
}
.v-avatar--end {
margin-inline: 4px -8px;
}
}
.v-chip__close {
font-size: 16px;
max-block-size: 16px;
max-inline-size: 16px;
}
}
&.v-chip--size-default {
padding-block: 0 !important;
padding-inline: 16px !important;
.v-chip__prepend {
.v-icon--start {
font-size: 1.25rem;
margin-inline: -8px 4px;
}
.v-avatar {
--v-avatar-height: 20px;
}
.v-avatar--start {
margin-inline: -8px 4px;
}
}
.v-chip__append {
.v-icon--end {
font-size: 1.25rem;
margin-inline: 4px -8px;
}
.v-avatar {
--v-avatar-height: 20px;
}
.v-avatar--end {
margin-inline: 4px -8px;
}
}
}
}

View File

@@ -0,0 +1,12 @@
// 👉 Dialog
body {
.v-dialog {
font-size: 0.9375rem;
line-height: 1.375rem;
.v-dialog-close-btn {
color: rgb(var(--v-theme-secondary)) !important;
}
}
}

View File

@@ -0,0 +1,47 @@
@use "@core/scss/base/mixins";
// 👉 Expansion Panel
.v-expansion-panels {
.v-expansion-panel {
.v-expansion-panel-title {
font-weight: 500;
&--active {
.v-expansion-panel-title__overlay,
&:hover .v-expansion-panel-title__overlay {
opacity: 0 !important;
}
}
.v-expansion-panel-title__icon {
.v-icon {
block-size: 1.25rem;
font-size: 1.25rem;
inline-size: 1.25rem;
}
}
&:hover {
.v-expansion-panel-title__overlay {
opacity: 0 !important;
}
}
}
.v-expansion-panel-text {
color: rgba(var(--v-theme-on-surface), var(--v-medium-emphasis-opacity));
font-size: 15px;
line-height: 1.375rem;
}
}
&:not(.v-expansion-panels--variant-accordion) {
.v-expansion-panel {
&.v-expansion-panel--active {
.v-expansion-panel__shadow {
@include mixins.elevation(6);
}
}
}
}
}

View File

@@ -0,0 +1,58 @@
@use "@configured-variables" as variables;
@use "sass:map";
@use "@styles/variables/vuetify";
@use "@core/scss/base/mixins";
@use "@core/scss/base/utils";
// 👉 VField
// Override Vuetify's default outline color for text fields to match the theme
// We cannot override directly border color because it does not work with dirty or focus state
.v-field__outline {
color: rgba(var(--v-theme-on-surface));
&:not([class*="text-"]) .v-label {
color: rgba(var(--v-theme-on-surface), var(--v-medium-emphasis-opacity));
}
}
// override input height on comfortable and compact density
.v-text-field,
.v-autocomplete,
.v-combobox,
.v-file-input,
.v-select {
&.v-input.v-input--density-default:not(.v-textarea) .v-field__input {
min-block-size: 56px;
}
&.v-input.v-input--density-comfortable:not(.v-textarea) .v-field__input {
min-block-size: 48px;
}
&.v-input.v-input--density-compact:not(.v-textarea) .v-field__input {
min-block-size: 40px;
}
}
.v-field.v-field--focused .v-field__outline,
.v-input.v-input--error .v-field__outline {
--v-field-border-opacity: 1 !important;
}
// hover state outline color
@media (hover: hover) {
.v-field:not(.v-field--focused, .v-field--error):hover .v-field__outline {
--v-field-border-opacity: 0.6 !important;
}
}
.v-field__prepend-inner,
.v-field__append-inner,
.v-field__clearable,
.v-input__prepend,
.v-input__append {
> .v-icon {
font-size: 20px;
opacity: var(--v-high-emphasis-opacity) !important;
}
}

View File

@@ -0,0 +1,22 @@
// 👉 VList
.v-list {
// .v-icon {
// font-size: 1.375rem;font-sizefont-size
// }
.v-list-item {
&.v-list-item--active:not(.v-list-group__header) {
.v-list-item__content,
.v-list-item__prepend {
* {
color: rgb(var(--v-theme-primary));
}
}
.v-list-item__overlay {
background: rgb(var(--v-theme-primary));
}
}
}
}

View File

@@ -0,0 +1,6 @@
// 👉 VMenu
.v-menu {
.v-list-item--density-default:not(.v-list-item--nav).v-list-item--one-line {
padding-inline: 16px;
}
}

View File

@@ -0,0 +1,18 @@
// 👉 Otp input
.v-otp-input {
justify-content: unset !important;
.v-otp-input__content {
max-inline-size: 100%;
.v-field.v-field--focused {
.v-field__outline {
.v-field__outline__start,
.v-field__outline__end {
border-color: rgb(var(--v-theme-primary)) !important;
}
}
}
}
}

View File

@@ -0,0 +1,172 @@
/* stylelint-disable no-descending-specificity */
@use "@configured-variables" as variables;
@use "@core/scss/base/mixins";
// 👉 VPagination
.v-pagination {
.v-pagination__list {
.v-pagination__next,
.v-pagination__last,
.v-pagination__first,
.v-pagination__prev {
.v-btn {
&.v-btn--icon {
&.v-btn--size-default {
.v-icon {
block-size: 1.375rem;
font-size: 1.375rem;
inline-size: 1.375rem;
}
}
&.v-btn--size-small {
.v-icon {
block-size: 1.25rem;
font-size: 1.25rem;
inline-size: 1.25rem;
}
}
&.v-btn--size-large {
.v-icon {
block-size: 1.5rem;
font-size: 1.5rem;
inline-size: 1.5rem;
}
}
}
}
}
// Common styles for buttons
.v-pagination__item,
.v-pagination__next,
.v-pagination__last,
.v-pagination__first,
.v-pagination__prev {
.v-btn {
color: rgba(var(--v-theme-on-surface), var(--v-high-emphasis-opacity));
font-weight: 400;
line-height: 1;
transform: none;
&--size-default {
--v-btn-size: 13px;
}
&--size-large {
--v-btn-size: 15px;
}
&.v-btn--disabled {
opacity: 0.4;
}
&--variant-tonal {
.v-btn__underlay {
--v-activated-opacity: 0.08;
}
&:hover {
.v-btn__underlay {
--v-activated-opacity: 0;
}
.v-btn__overlay {
--v-hover-opacity: 0.16;
}
}
}
@each $color-name in variables.$theme-colors-name {
&--variant-tonal.text-#{$color-name} {
.v-btn__underlay {
background: rgb(var(--v-theme-on-surface));
}
.v-btn__content {
color: rgba(var(--v-theme-on-surface), var(--v-high-emphasis-opacity));
}
&:hover {
.v-btn__content {
color: rgb(var(--v-theme-#{$color-name}));
}
}
}
}
&--variant-outlined {
&:hover {
.v-btn__overlay {
--v-hover-opacity: 0.06;
}
}
}
}
}
.v-pagination__item--is-active {
.v-btn {
&:not([class*="text-"]) {
color: rgb(var(--v-theme-primary));
}
}
.v-btn.v-btn--variant-tonal {
.v-btn__overlay {
--v-hover-opacity: 0.16;
background: rgb(var(--v-theme-primary));
opacity: var(--v-hover-opacity);
}
.v-btn__content {
color: rgb(var(--v-theme-primary));
}
.v-btn__underlay {
opacity: 0;
}
&:hover {
.v-btn__overlay {
--v-hover-opacity: 0.24;
}
}
}
@each $color-name in variables.$theme-colors-name {
.v-btn.v-btn--variant-tonal.text-#{$color-name} {
@include mixins.elevation(2);
.v-btn__overlay {
background: rgb(var(--v-theme-#{$color-name}));
opacity: 1;
}
.v-btn__content {
z-index: 1;
color: #fff;
}
}
}
.v-btn.v-btn--variant-outlined {
border-color: rgb(var(--v-theme-primary));
.v-btn__content {
color: rgb(var(--v-theme-primary));
}
.v-btn__overlay {
--v-hover-opacity: 0.16;
background: rgb(var(--v-theme-primary));
opacity: var(--v-hover-opacity);
}
}
}
}
}

View File

@@ -0,0 +1,3 @@
@use "@configured-variables" as variables;
// 👉 Progress

View File

@@ -0,0 +1,47 @@
@use "@core/scss/base/mixins";
@use "@configured-variables" as variables;
// 👉 Radio
.v-radio,
.v-radio-btn {
&.v-selection-control--dirty {
.v-selection-control__input {
.custom-radio-checked {
filter: drop-shadow(rgba(var(--v-shadow-key-umbra-color), 16%) 0 2px 4px);
}
}
}
&.v-selection-control {
.v-selection-control__input {
svg {
font-size: 1.5rem;
}
}
.v-label {
color: rgba(var(--v-theme-on-background), var(--v-high-emphasis-opacity));
}
}
&:not(.v-selection-control--dirty) {
.v-selection-control__input > .v-icon {
color: rgba(var(--v-theme-on-surface), var(--v-medium-emphasis-opacity));
opacity: 1;
}
}
}
.v-radio-group.v-input > .v-input__control > .v-label {
font-size: 0.9375rem;
line-height: 22px;
margin-inline-start: 0;
}
.v-radio-group {
.v-selection-control-group {
.v-radio:not(:last-child) {
margin-inline-end: 0;
}
}
}

View File

@@ -0,0 +1,14 @@
// // 👉 Rating
// .v-rating {
// .v-rating__wrapper {
// .v-btn {
// &:hover {
// transform: none;transform
// }
// .v-icon {
// --v-icon-size-multiplier: 1;--v-icon-size-multiplier
// }
// }
// }
// }

View File

@@ -0,0 +1,28 @@
// 👉 Slider
.v-slider {
.v-slider-track__background--opacity {
opacity: 0.16;
}
}
.v-slider-thumb {
.v-slider-thumb__surface::after {
border-radius: 50%;
background-color: #fff;
block-size: calc(var(--v-slider-thumb-size) - 10px);
inline-size: calc(var(--v-slider-thumb-size) - 10px);
}
.v-slider-thumb__label {
background-color: rgb(var(--v-tooltip-background));
color: rgb(var(--v-theme-surface));
font-weight: 500;
letter-spacing: 0.15px;
line-height: 1.25rem;
&::before {
content: none;
}
}
}

View File

@@ -0,0 +1,10 @@
// 👉 snackbar
.v-snackbar {
.v-snackbar__actions {
.v-btn {
padding-block: 0;
padding-inline: 10px;
}
}
}

View File

@@ -0,0 +1,57 @@
@use "@configured-variables" as variables;
@use "@core/scss/base/mixins";
// 👉 Switch
.v-switch {
.v-label {
color: rgba(var(--v-theme-on-background), var(--v-high-emphasis-opacity));
line-height: 22px;
}
}
.v-switch.v-switch--inset {
.v-selection-control .v-selection-control__wrapper {
block-size: 36px;
}
.v-ripple__container {
opacity: 0;
}
.v-switch__track {
background-color: rgba(var(--v-theme-on-surface), var(--v-focus-opacity));
box-shadow: 0 0 4px 0 rgba(0, 0, 0, 16%) inset;
opacity: 1;
}
.v-selection-control__input {
transform: translateX(-5px) !important;
--v-selection-control-size: 1.125rem;
.v-switch__thumb {
background-color: #fff;
block-size: 0.875rem;
box-shadow: none;
filter: drop-shadow(0 2px 4px rgba(var(--v-shadow-key-umbra-color), 16%));
inline-size: 0.875rem;
transform: scale(1);
}
}
.v-selection-control--dirty {
@each $color-name in variables.$theme-colors-name {
.text-#{$color-name} {
.v-switch__track {
border-color: rgb(var(--v-theme-#{$color-name}));
background-color: rgb(var(--v-theme-#{$color-name}));
}
}
}
.v-selection-control__input {
transform: translateX(5px) !important;
}
}
}

View File

@@ -0,0 +1,36 @@
.v-data-table {
table {
tbody {
tr {
&.v-data-table-group-header-row {
td {
background: none;
}
}
}
}
}
}
// 👉 Table
.v-table {
.v-table__wrapper {
border-radius: 0;
table {
thead {
tr {
th {
background: rgb(var(--v-table-header-color)) !important;
border-block-end: none !important;
color: rgba(var(--v-theme-on-surface), var(--v-high-emphasis-opacity)) !important;
font-size: 0.8125rem;
letter-spacing: 0.2px;
line-height: 24px;
text-transform: uppercase;
}
}
}
}
}
}

View File

@@ -0,0 +1,113 @@
@use "@configured-variables" as variables;
@use "@core/scss/base/mixins";
body {
.v-tabs {
.v-tab.v-btn {
color: rgba(var(--v-theme-on-surface), var(--v-high-emphasis-opacity));
padding-block: 0;
padding-inline: 1.375rem;
.v-icon {
block-size: 1.125rem;
font-size: 1.125rem;
inline-size: 1.125rem;
}
&.v-btn--stacked {
.v-icon {
block-size: 1.5rem !important;
font-size: 1.5rem !important;
inline-size: 1.5rem !important;
}
}
}
&:not(.v-tabs-pill) {
&.v-tabs--vertical {
border-inline-end: 1px solid rgba(var(--v-border-color), var(--v-border-opacity));
.v-tab__slider {
inset-inline-end: 0;
inset-inline-start: unset;
}
}
&.v-tabs--horizontal {
border-block-end: 1px solid rgba(var(--v-border-color), var(--v-border-opacity));
.v-tab__slider {
inset-block-end: 1px;
inset-block-start: unset;
}
}
.v-tab {
&.v-tab--selected {
&.v-btn.v-btn--variant-text {
&:hover,
&:active,
&:focus {
.v-btn__overlay {
--v-hover-opacity: 0;
}
}
}
}
&:not(.v-tab--selected) {
&.v-btn.v-btn--variant-text {
&:hover,
&:active,
&:focus {
color: rgb(var(--v-theme-primary));
.v-btn__overlay {
--v-hover-opacity: 0;
}
.v-btn__content {
.v-tab__slider {
opacity: var(--v-activated-opacity);
}
}
}
}
}
}
}
&.v-tabs-pill {
.v-slide-group__content {
gap: 0.25rem;
}
&.v-slide-group,
.v-slide-group__container {
box-sizing: content-box;
padding: 1rem;
margin: -1rem;
}
/* stylelint-disable-next-line no-descending-specificity */
.v-tab {
&.v-btn {
border-radius: 0.375rem !important;
}
&:not(.v-tab--selected) {
/* stylelint-disable-next-line no-descending-specificity */
&.v-btn.v-btn--variant-text {
&:hover {
color: rgb(var(--v-theme-primary));
}
}
}
&.v-tab--selected {
@include mixins.elevation(2);
}
}
}
}
}

Some files were not shown because too many files have changed in this diff Show More