2
This commit is contained in:
commit
5f2483c511
9
.editorconfig
Normal file
9
.editorconfig
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
root = true
|
||||||
|
|
||||||
|
[*]
|
||||||
|
charset = utf-8
|
||||||
|
indent_style = space
|
||||||
|
indent_size = 2
|
||||||
|
end_of_line = lf
|
||||||
|
insert_final_newline = true
|
||||||
|
trim_trailing_whitespace = true
|
||||||
2
.github/FUNDING.yml
vendored
Normal file
2
.github/FUNDING.yml
vendored
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
open_collective: antfu
|
||||||
|
github: [antfu]
|
||||||
47
.github/workflows/test.yml
vendored
Normal file
47
.github/workflows/test.yml
vendored
Normal file
@ -0,0 +1,47 @@
|
|||||||
|
name: Test
|
||||||
|
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
branches:
|
||||||
|
- main
|
||||||
|
|
||||||
|
pull_request:
|
||||||
|
branches:
|
||||||
|
- main
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
build:
|
||||||
|
runs-on: ${{ matrix.os }}
|
||||||
|
|
||||||
|
timeout-minutes: 10
|
||||||
|
|
||||||
|
strategy:
|
||||||
|
matrix:
|
||||||
|
node_version: [lts/*]
|
||||||
|
os: [ubuntu-latest, windows-latest]
|
||||||
|
fail-fast: false
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v3
|
||||||
|
- uses: pnpm/action-setup@v2
|
||||||
|
|
||||||
|
- name: Set node version to ${{ matrix.node_version }}
|
||||||
|
uses: actions/setup-node@v3
|
||||||
|
with:
|
||||||
|
node-version: ${{ matrix.node_version }}
|
||||||
|
cache: pnpm
|
||||||
|
|
||||||
|
- name: Install
|
||||||
|
run: pnpm i
|
||||||
|
|
||||||
|
- name: Build
|
||||||
|
run: pnpm run build
|
||||||
|
|
||||||
|
- name: Test
|
||||||
|
run: pnpm run test
|
||||||
|
|
||||||
|
- name: Lint
|
||||||
|
run: pnpm run lint
|
||||||
|
|
||||||
|
- name: TypeCheck
|
||||||
|
run: pnpm run typecheck
|
||||||
9
.gitignore
vendored
Normal file
9
.gitignore
vendored
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
.DS_Store
|
||||||
|
.vite-ssg-dist
|
||||||
|
.vite-ssg-temp
|
||||||
|
*.local
|
||||||
|
dist
|
||||||
|
dist-ssr
|
||||||
|
node_modules
|
||||||
|
.idea/
|
||||||
|
*.log
|
||||||
11
.vscode/extensions.json
vendored
Normal file
11
.vscode/extensions.json
vendored
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
{
|
||||||
|
"recommendations": [
|
||||||
|
"antfu.vite",
|
||||||
|
"antfu.iconify",
|
||||||
|
"antfu.unocss",
|
||||||
|
"antfu.goto-alias",
|
||||||
|
"vue.volar",
|
||||||
|
"dbaeumer.vscode-eslint",
|
||||||
|
"EditorConfig.EditorConfig"
|
||||||
|
]
|
||||||
|
}
|
||||||
48
.vscode/settings.json
vendored
Normal file
48
.vscode/settings.json
vendored
Normal file
@ -0,0 +1,48 @@
|
|||||||
|
{
|
||||||
|
"files.associations": {
|
||||||
|
"*.css": "postcss"
|
||||||
|
},
|
||||||
|
|
||||||
|
// Enable the ESlint flat config support
|
||||||
|
"eslint.experimental.useFlatConfig": true,
|
||||||
|
|
||||||
|
// Disable the default formatter
|
||||||
|
"prettier.enable": false,
|
||||||
|
"editor.formatOnSave": false,
|
||||||
|
|
||||||
|
// Auto fix
|
||||||
|
"editor.codeActionsOnSave": {
|
||||||
|
"source.fixAll.eslint": "explicit",
|
||||||
|
"source.organizeImports": "never"
|
||||||
|
},
|
||||||
|
|
||||||
|
// Silent the stylistic rules in you IDE, but still auto fix them
|
||||||
|
"eslint.rules.customizations": [
|
||||||
|
{ "rule": "style/*", "severity": "off" },
|
||||||
|
{ "rule": "*-indent", "severity": "off" },
|
||||||
|
{ "rule": "*-spacing", "severity": "off" },
|
||||||
|
{ "rule": "*-spaces", "severity": "off" },
|
||||||
|
{ "rule": "*-order", "severity": "off" },
|
||||||
|
{ "rule": "*-dangle", "severity": "off" },
|
||||||
|
{ "rule": "*-newline", "severity": "off" },
|
||||||
|
{ "rule": "*quotes", "severity": "off" },
|
||||||
|
{ "rule": "*semi", "severity": "off" }
|
||||||
|
],
|
||||||
|
|
||||||
|
// The following is optional.
|
||||||
|
// It's better to put under project setting `.vscode/settings.json`
|
||||||
|
// to avoid conflicts with working with different eslint configs
|
||||||
|
// that does not support all formats.
|
||||||
|
"eslint.validate": [
|
||||||
|
"javascript",
|
||||||
|
"javascriptreact",
|
||||||
|
"typescript",
|
||||||
|
"typescriptreact",
|
||||||
|
"vue",
|
||||||
|
"html",
|
||||||
|
"markdown",
|
||||||
|
"json",
|
||||||
|
"jsonc",
|
||||||
|
"yaml"
|
||||||
|
]
|
||||||
|
}
|
||||||
21
LICENSE
Normal file
21
LICENSE
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
MIT License
|
||||||
|
|
||||||
|
Copyright (c) 2020-PRESENT Anthony Fu
|
||||||
|
|
||||||
|
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.
|
||||||
86
README.md
Normal file
86
README.md
Normal file
@ -0,0 +1,86 @@
|
|||||||
|
<p align='center'>
|
||||||
|
<img src='https://user-images.githubusercontent.com/11247099/111864893-a457fd00-899e-11eb-9f05-f4b88987541d.png' alt='Vitesse - Opinionated Vite Starter Template' width='600'/>
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<h6 align='center'>
|
||||||
|
<a href="https://vitesse-lite.netlify.app/">Live Demo</a>
|
||||||
|
</h6>
|
||||||
|
|
||||||
|
<h5 align='center'>
|
||||||
|
<b>Lightweight version of <a href="https://github.com/antfu/vitesse">Vitesse</a></b>
|
||||||
|
</h5>
|
||||||
|
|
||||||
|
<br>
|
||||||
|
|
||||||
|
<p align='center'>
|
||||||
|
<b>English</b> | <a href="https://github.com/antfu-collective/vitesse-lite/blob/main/README.zh-CN.md">简体中文</a>
|
||||||
|
<!-- Contributors: Thanks for geting interested, however we DON'T accept new transitions to the README, thanks. -->
|
||||||
|
</p>
|
||||||
|
|
||||||
|
## Features
|
||||||
|
|
||||||
|
- ⚡️ [Vue 3](https://github.com/vuejs/core), [Vite](https://github.com/vitejs/vite), [pnpm](https://pnpm.io/), [ESBuild](https://github.com/evanw/esbuild) - born with fastness
|
||||||
|
|
||||||
|
- 🗂 [File based routing](./src/pages)
|
||||||
|
|
||||||
|
- 📦 [Components auto importing](./src/components)
|
||||||
|
|
||||||
|
- 🎨 [UnoCSS](https://github.com/antfu/unocss) - The instant on-demand atomic CSS engine.
|
||||||
|
|
||||||
|
- 😃 Use icons from any icon sets in [Pure CSS](https://github.com/antfu/unocss/tree/main/packages/preset-icons)
|
||||||
|
|
||||||
|
- 🔥 Use the [new `<script setup>` style](https://github.com/vuejs/rfcs/pull/227)
|
||||||
|
|
||||||
|
- ✅ Use [Vitest](http://vitest.dev/) for unit and components testing
|
||||||
|
|
||||||
|
- 🦾 TypeScript, of course
|
||||||
|
|
||||||
|
- ☁️ Deploy on Netlify, zero-config
|
||||||
|
|
||||||
|
<br>
|
||||||
|
|
||||||
|
See [Vitesse](https://github.com/antfu/vitesse) for full featureset.
|
||||||
|
|
||||||
|
## Dropped Features from [Vitesse](https://github.com/antfu/vitesse)
|
||||||
|
|
||||||
|
- ~~i18n~~
|
||||||
|
- ~~Layouts~~
|
||||||
|
- ~~SSG~~
|
||||||
|
- ~~PWA~~
|
||||||
|
- ~~Markdown~~
|
||||||
|
|
||||||
|
## Pre-packed
|
||||||
|
|
||||||
|
### UI Frameworks
|
||||||
|
|
||||||
|
- [UnoCSS](https://github.com/antfu/unocss) - The instant on-demand atomic CSS engine.
|
||||||
|
|
||||||
|
### Icons
|
||||||
|
|
||||||
|
- [Iconify](https://iconify.design) - use icons from any icon sets [🔍Icônes](https://icones.netlify.app/)
|
||||||
|
- [Pure CSS Icons via UnoCSS](https://github.com/antfu/unocss/tree/main/packages/preset-icons)
|
||||||
|
|
||||||
|
### Plugins
|
||||||
|
|
||||||
|
- [Vue Router](https://github.com/vuejs/vue-router)
|
||||||
|
- [`unplugin-vue-router`](https://github.com/posva/unplugin-vue-router) - file system based routing
|
||||||
|
- [`unplugin-auto-import`](https://github.com/antfu/unplugin-auto-import) - Directly use Vue Composition API and others without importing
|
||||||
|
- [`unplugin-vue-components`](https://github.com/antfu/unplugin-vue-components) - components auto import
|
||||||
|
- [`unplugin-vue-macros`](https://github.com/sxzz/unplugin-vue-macros) - Explore and extend more macros and syntax sugar to Vue.
|
||||||
|
- [VueUse](https://github.com/antfu/vueuse) - collection of useful composition APIs
|
||||||
|
|
||||||
|
## Try it now!
|
||||||
|
|
||||||
|
### GitHub Template
|
||||||
|
|
||||||
|
[Create a repo from this template on GitHub](https://github.com/antfu-collective/vitesse-lite/generate).
|
||||||
|
|
||||||
|
### Clone to local
|
||||||
|
|
||||||
|
If you prefer to do it manually with the cleaner git history
|
||||||
|
|
||||||
|
```bash
|
||||||
|
npx degit antfu-collective/vitesse-lite my-vitesse-app
|
||||||
|
cd my-vitesse-app
|
||||||
|
pnpm i # If you don't have pnpm installed, run: npm install -g pnpm
|
||||||
|
```
|
||||||
87
README.zh-CN.md
Normal file
87
README.zh-CN.md
Normal file
@ -0,0 +1,87 @@
|
|||||||
|
<p align='center'>
|
||||||
|
<img src='https://user-images.githubusercontent.com/11247099/111864893-a457fd00-899e-11eb-9f05-f4b88987541d.png' alt='Vitesse - Opinionated Vite Starter Template' width='600'/>
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<h6 align='center'>
|
||||||
|
<a href="https://vitesse-lite.netlify.app/">在线 Demo</a>
|
||||||
|
</h6>
|
||||||
|
|
||||||
|
<h5 align='center'>
|
||||||
|
<b>轻量版的 <a href="https://github.com/antfu/vitesse">Vitesse</a></b>
|
||||||
|
</h5>
|
||||||
|
|
||||||
|
<br>
|
||||||
|
|
||||||
|
<p align='center'>
|
||||||
|
<a href="https://github.com/antfu-collective/vitesse-lite/blob/main/README.md">English</a> | <b>简体中文</b>
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<br>
|
||||||
|
|
||||||
|
## 特性
|
||||||
|
|
||||||
|
- ⚡️ [Vue 3](https://github.com/vuejs/core), [Vite](https://github.com/vitejs/vite), [pnpm](https://pnpm.io/), [ESBuild](https://github.com/evanw/esbuild) - 就是快!
|
||||||
|
|
||||||
|
- 🗂 [基于文件的路由](./src/pages)
|
||||||
|
|
||||||
|
- 📦 [组件自动化加载](./src/components)
|
||||||
|
|
||||||
|
- 🎨 [UnoCSS](https://github.com/unocss/unocss) - 高性能且极具灵活性的即时原子化 CSS 引擎
|
||||||
|
|
||||||
|
- 😃 [各种图标集为你所用](https://github.com/antfu/unocss/tree/main/packages/preset-icons)
|
||||||
|
|
||||||
|
- 🔥 使用 [新的 `<script setup>` 语法](https://github.com/vuejs/rfcs/pull/227)
|
||||||
|
|
||||||
|
- ✅ 使用 [Vitest](http://vitest.dev/) 进行单元和组件测试
|
||||||
|
|
||||||
|
- 🦾 TypeScript, 当然
|
||||||
|
|
||||||
|
- ☁️ 零配置部署 Netlify
|
||||||
|
|
||||||
|
<br>
|
||||||
|
|
||||||
|
完整特性,请查看 [Vitesse](https://github.com/antfu/vitesse)
|
||||||
|
|
||||||
|
## 从 [Vitesse](https://github.com/antfu/vitesse) 中删除了以下特性
|
||||||
|
|
||||||
|
- ~~i18n~~
|
||||||
|
- ~~Layouts~~
|
||||||
|
- ~~SSG~~
|
||||||
|
- ~~PWA~~
|
||||||
|
- ~~Markdown~~
|
||||||
|
|
||||||
|
## 预配置
|
||||||
|
|
||||||
|
### UI 框架
|
||||||
|
|
||||||
|
- [UnoCSS](https://github.com/antfu/unocss) - 高性能且极具灵活性的即时原子化 CSS 引擎
|
||||||
|
|
||||||
|
### Icons
|
||||||
|
|
||||||
|
- [Iconify](https://iconify.design) - 使用任意的图标集,浏览:[🔍Icônes](https://icones.netlify.app/)
|
||||||
|
- [UnoCSS 的纯 CSS 图标方案](https://github.com/antfu/unocss/tree/main/packages/preset-icons)
|
||||||
|
|
||||||
|
### 插件
|
||||||
|
|
||||||
|
- [Vue Router](https://github.com/vuejs/vue-router)
|
||||||
|
- [`unplugin-vue-router`](https://github.com/posva/unplugin-vue-router) - 以文件系统为基础的路由
|
||||||
|
- [`unplugin-auto-import`](https://github.com/antfu/unplugin-auto-import) - 直接使用 Composition API 等,无需导入
|
||||||
|
- [`unplugin-vue-components`](https://github.com/antfu/unplugin-vue-components) - 自动加载组件
|
||||||
|
- [`unplugin-vue-macros`](https://github.com/sxzz/unplugin-vue-macros) - 探索并扩展更多的宏和语法糖到 Vue 中
|
||||||
|
- [VueUse](https://github.com/antfu/vueuse) - 实用的 Composition API 工具合集
|
||||||
|
|
||||||
|
## 现在可以试试!
|
||||||
|
|
||||||
|
### GitHub 模板
|
||||||
|
|
||||||
|
[使用这个模板创建仓库](https://github.com/antfu-collective/vitesse-lite/generate).
|
||||||
|
|
||||||
|
### 克隆到本地
|
||||||
|
|
||||||
|
如果您更喜欢使用更干净的 git 历史记录手动执行此操作
|
||||||
|
|
||||||
|
```bash
|
||||||
|
npx degit antfu-collective/vitesse-lite my-vitesse-app
|
||||||
|
cd my-vitesse-app
|
||||||
|
pnpm i # 如果你没装过 pnpm, 可以先运行: npm install -g pnpm
|
||||||
|
```
|
||||||
593
auto-imports.d.ts
vendored
Normal file
593
auto-imports.d.ts
vendored
Normal file
@ -0,0 +1,593 @@
|
|||||||
|
/* 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 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 createGlobalState: typeof import('@vueuse/core')['createGlobalState']
|
||||||
|
const createInjectionState: typeof import('@vueuse/core')['createInjectionState']
|
||||||
|
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 defineLoader: typeof import('vue-router/auto')['defineLoader']
|
||||||
|
const definePage: typeof import('unplugin-vue-router/runtime')['definePage']
|
||||||
|
const eagerComputed: typeof import('@vueuse/core')['eagerComputed']
|
||||||
|
const effectScope: typeof import('vue')['effectScope']
|
||||||
|
const extendRef: typeof import('@vueuse/core')['extendRef']
|
||||||
|
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 isDark: typeof import('./src/composables/dark')['isDark']
|
||||||
|
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 makeDestructurable: typeof import('@vueuse/core')['makeDestructurable']
|
||||||
|
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 shallowReactive: typeof import('vue')['shallowReactive']
|
||||||
|
const shallowReadonly: typeof import('vue')['shallowReadonly']
|
||||||
|
const shallowRef: typeof import('vue')['shallowRef']
|
||||||
|
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 toggleDark: typeof import('./src/composables/dark')['toggleDark']
|
||||||
|
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 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 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 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 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/auto')['useLink']
|
||||||
|
const useLocalStorage: typeof import('@vueuse/core')['useLocalStorage']
|
||||||
|
const useMagicKeys: typeof import('@vueuse/core')['useMagicKeys']
|
||||||
|
const useManualRefHistory: typeof import('@vueuse/core')['useManualRefHistory']
|
||||||
|
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 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 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 useRafFn: typeof import('@vueuse/core')['useRafFn']
|
||||||
|
const useRefHistory: typeof import('@vueuse/core')['useRefHistory']
|
||||||
|
const useResizeObserver: typeof import('@vueuse/core')['useResizeObserver']
|
||||||
|
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 useStorage: typeof import('@vueuse/core')['useStorage']
|
||||||
|
const useStorageAsync: typeof import('@vueuse/core')['useStorageAsync']
|
||||||
|
const useStyleTag: typeof import('@vueuse/core')['useStyleTag']
|
||||||
|
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 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 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 createGlobalState: UnwrapRef<typeof import('@vueuse/core')['createGlobalState']>
|
||||||
|
readonly createInjectionState: UnwrapRef<typeof import('@vueuse/core')['createInjectionState']>
|
||||||
|
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 eagerComputed: UnwrapRef<typeof import('@vueuse/core')['eagerComputed']>
|
||||||
|
readonly effectScope: UnwrapRef<typeof import('vue')['effectScope']>
|
||||||
|
readonly extendRef: UnwrapRef<typeof import('@vueuse/core')['extendRef']>
|
||||||
|
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 isDark: UnwrapRef<typeof import('./src/composables/dark')['isDark']>
|
||||||
|
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 makeDestructurable: UnwrapRef<typeof import('@vueuse/core')['makeDestructurable']>
|
||||||
|
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 shallowReactive: UnwrapRef<typeof import('vue')['shallowReactive']>
|
||||||
|
readonly shallowReadonly: UnwrapRef<typeof import('vue')['shallowReadonly']>
|
||||||
|
readonly shallowRef: UnwrapRef<typeof import('vue')['shallowRef']>
|
||||||
|
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 toggleDark: UnwrapRef<typeof import('./src/composables/dark')['toggleDark']>
|
||||||
|
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 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 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 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 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/auto')['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 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 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 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 useRafFn: UnwrapRef<typeof import('@vueuse/core')['useRafFn']>
|
||||||
|
readonly useRefHistory: UnwrapRef<typeof import('@vueuse/core')['useRefHistory']>
|
||||||
|
readonly useResizeObserver: UnwrapRef<typeof import('@vueuse/core')['useResizeObserver']>
|
||||||
|
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 useStorage: UnwrapRef<typeof import('@vueuse/core')['useStorage']>
|
||||||
|
readonly useStorageAsync: UnwrapRef<typeof import('@vueuse/core')['useStorageAsync']>
|
||||||
|
readonly useStyleTag: UnwrapRef<typeof import('@vueuse/core')['useStyleTag']>
|
||||||
|
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 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']>
|
||||||
|
}
|
||||||
|
}
|
||||||
41
components.d.ts
vendored
Normal file
41
components.d.ts
vendored
Normal file
@ -0,0 +1,41 @@
|
|||||||
|
/* 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 {
|
||||||
|
NavigationMenu: typeof import('./src/components/ui/navigation-menu/NavigationMenu.vue')['default']
|
||||||
|
NavigationMenuContent: typeof import('./src/components/ui/navigation-menu/NavigationMenuContent.vue')['default']
|
||||||
|
NavigationMenuIndicator: typeof import('./src/components/ui/navigation-menu/NavigationMenuIndicator.vue')['default']
|
||||||
|
NavigationMenuItem: typeof import('./src/components/ui/navigation-menu/NavigationMenuItem.vue')['default']
|
||||||
|
NavigationMenuLink: typeof import('./src/components/ui/navigation-menu/NavigationMenuLink.vue')['default']
|
||||||
|
NavigationMenuList: typeof import('./src/components/ui/navigation-menu/NavigationMenuList.vue')['default']
|
||||||
|
NavigationMenuTrigger: typeof import('./src/components/ui/navigation-menu/NavigationMenuTrigger.vue')['default']
|
||||||
|
NavigationMenuViewport: typeof import('./src/components/ui/navigation-menu/NavigationMenuViewport.vue')['default']
|
||||||
|
NumberField: typeof import('./src/components/ui/number-field/NumberField.vue')['default']
|
||||||
|
NumberFieldContent: typeof import('./src/components/ui/number-field/NumberFieldContent.vue')['default']
|
||||||
|
NumberFieldDecrement: typeof import('./src/components/ui/number-field/NumberFieldDecrement.vue')['default']
|
||||||
|
NumberFieldIncrement: typeof import('./src/components/ui/number-field/NumberFieldIncrement.vue')['default']
|
||||||
|
NumberFieldInput: typeof import('./src/components/ui/number-field/NumberFieldInput.vue')['default']
|
||||||
|
RouterLink: typeof import('vue-router')['RouterLink']
|
||||||
|
RouterView: typeof import('vue-router')['RouterView']
|
||||||
|
Select: typeof import('./src/components/ui/select/Select.vue')['default']
|
||||||
|
SelectContent: typeof import('./src/components/ui/select/SelectContent.vue')['default']
|
||||||
|
SelectGroup: typeof import('./src/components/ui/select/SelectGroup.vue')['default']
|
||||||
|
SelectItem: typeof import('./src/components/ui/select/SelectItem.vue')['default']
|
||||||
|
SelectItemText: typeof import('./src/components/ui/select/SelectItemText.vue')['default']
|
||||||
|
SelectLabel: typeof import('./src/components/ui/select/SelectLabel.vue')['default']
|
||||||
|
SelectScrollDownButton: typeof import('./src/components/ui/select/SelectScrollDownButton.vue')['default']
|
||||||
|
SelectScrollUpButton: typeof import('./src/components/ui/select/SelectScrollUpButton.vue')['default']
|
||||||
|
SelectSeparator: typeof import('./src/components/ui/select/SelectSeparator.vue')['default']
|
||||||
|
SelectTrigger: typeof import('./src/components/ui/select/SelectTrigger.vue')['default']
|
||||||
|
SelectValue: typeof import('./src/components/ui/select/SelectValue.vue')['default']
|
||||||
|
TheCounter: typeof import('./src/components/TheCounter.vue')['default']
|
||||||
|
TheFooter: typeof import('./src/components/TheFooter.vue')['default']
|
||||||
|
TheHeader: typeof import('./src/components/TheHeader.vue')['default']
|
||||||
|
TheInput: typeof import('./src/components/TheInput.vue')['default']
|
||||||
|
}
|
||||||
|
}
|
||||||
18
components.json
Normal file
18
components.json
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
{
|
||||||
|
"$schema": "https://shadcn-vue.com/schema.json",
|
||||||
|
"style": "default",
|
||||||
|
"typescript": true,
|
||||||
|
"tsConfigPath": "./tsconfig.json",
|
||||||
|
"tailwind": {
|
||||||
|
"config": "tailwind.config.js",
|
||||||
|
"css": "src/assets/index.css",
|
||||||
|
"baseColor": "neutral",
|
||||||
|
"cssVariables": true,
|
||||||
|
"prefix": ""
|
||||||
|
},
|
||||||
|
"framework": "vite",
|
||||||
|
"aliases": {
|
||||||
|
"components": "~/components",
|
||||||
|
"utils": "~/lib/utils"
|
||||||
|
}
|
||||||
|
}
|
||||||
8
eslint.config.js
Normal file
8
eslint.config.js
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
import antfu from '@antfu/eslint-config'
|
||||||
|
|
||||||
|
export default antfu(
|
||||||
|
{
|
||||||
|
unocss: true,
|
||||||
|
formatters: true,
|
||||||
|
},
|
||||||
|
)
|
||||||
25
index.html
Normal file
25
index.html
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
<!doctype html>
|
||||||
|
<html lang="en">
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8" />
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||||
|
<link rel="icon" href="/favicon.svg" type="image/svg+xml" />
|
||||||
|
<title>Vitesse Lite</title>
|
||||||
|
<meta name="description" content="Opinionated Vite Starter Template" />
|
||||||
|
</head>
|
||||||
|
<body class="font-sans dark:text-white dark:bg-hex-121212">
|
||||||
|
<div id="app"></div>
|
||||||
|
<noscript>
|
||||||
|
<div>Please enable JavaScript to use this application.</div>
|
||||||
|
</noscript>
|
||||||
|
<script>
|
||||||
|
;(function () {
|
||||||
|
const prefersDark = window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches
|
||||||
|
const setting = localStorage.getItem('color-schema') || 'auto'
|
||||||
|
if (setting === 'dark' || (prefersDark && setting !== 'light'))
|
||||||
|
document.documentElement.classList.toggle('dark', true)
|
||||||
|
})()
|
||||||
|
</script>
|
||||||
|
<script type="module" src="/src/main.ts"></script>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
11
netlify.toml
Executable file
11
netlify.toml
Executable file
@ -0,0 +1,11 @@
|
|||||||
|
[build]
|
||||||
|
publish = "dist"
|
||||||
|
command = "pnpm run build"
|
||||||
|
|
||||||
|
[build.environment]
|
||||||
|
NODE_VERSION = "20"
|
||||||
|
|
||||||
|
[[redirects]]
|
||||||
|
from = "/*"
|
||||||
|
to = "/index.html"
|
||||||
|
status = 200
|
||||||
66
package.json
Normal file
66
package.json
Normal file
@ -0,0 +1,66 @@
|
|||||||
|
{
|
||||||
|
"type": "module",
|
||||||
|
"private": true,
|
||||||
|
"packageManager": "pnpm@9.14.4",
|
||||||
|
"scripts": {
|
||||||
|
"build": "vite build",
|
||||||
|
"dev": "vite --port 3333 --open",
|
||||||
|
"lint": "eslint .",
|
||||||
|
"typecheck": "vue-tsc --noEmit",
|
||||||
|
"preview": "vite preview",
|
||||||
|
"test": "vitest",
|
||||||
|
"up": "taze major -I",
|
||||||
|
"postinstall": "npx simple-git-hooks"
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"@vueuse/core": "^12.0.0",
|
||||||
|
"class-variance-authority": "^0.7.1",
|
||||||
|
"clsx": "^2.1.1",
|
||||||
|
"lucide-vue-next": "^0.468.0",
|
||||||
|
"radix-vue": "^1.9.11",
|
||||||
|
"shadcn-vue": "^0.11.3",
|
||||||
|
"tailwind-merge": "^2.5.5",
|
||||||
|
"tailwindcss-animate": "^1.0.7",
|
||||||
|
"vue": "^3.5.13",
|
||||||
|
"vue-router": "^4.5.0"
|
||||||
|
},
|
||||||
|
"devDependencies": {
|
||||||
|
"@antfu/eslint-config": "^3.12.0",
|
||||||
|
"@iconify-json/carbon": "^1.2.4",
|
||||||
|
"@types/node": "^22.10.2",
|
||||||
|
"@unocss/eslint-config": "^0.65.1",
|
||||||
|
"@unocss/eslint-plugin": "^0.65.1",
|
||||||
|
"@unocss/reset": "^0.65.1",
|
||||||
|
"@vitejs/plugin-vue": "^5.2.1",
|
||||||
|
"@vue-macros/volar": "^0.30.8",
|
||||||
|
"@vue/test-utils": "^2.4.6",
|
||||||
|
"eslint": "^9.17.0",
|
||||||
|
"eslint-plugin-format": "^0.1.3",
|
||||||
|
"jsdom": "^25.0.1",
|
||||||
|
"lint-staged": "^15.2.11",
|
||||||
|
"pnpm": "^9.15.0",
|
||||||
|
"simple-git-hooks": "^2.11.1",
|
||||||
|
"taze": "^0.18.0",
|
||||||
|
"typescript": "~5.6.3",
|
||||||
|
"unocss": "^0.65.1",
|
||||||
|
"unocss-preset-animations": "^1.1.0",
|
||||||
|
"unocss-preset-shadcn": "^0.3.1",
|
||||||
|
"unplugin-auto-import": "^0.19.0",
|
||||||
|
"unplugin-vue-components": "^0.28.0",
|
||||||
|
"unplugin-vue-macros": "^2.13.6",
|
||||||
|
"unplugin-vue-router": "^0.10.9",
|
||||||
|
"vite": "^6.0.3",
|
||||||
|
"vitest": "^2.1.8",
|
||||||
|
"vue-tsc": "^2.1.10"
|
||||||
|
},
|
||||||
|
"resolutions": {
|
||||||
|
"unplugin": "^2.1.0",
|
||||||
|
"vite": "^6.0.3"
|
||||||
|
},
|
||||||
|
"simple-git-hooks": {
|
||||||
|
"pre-commit": "pnpm lint-staged"
|
||||||
|
},
|
||||||
|
"lint-staged": {
|
||||||
|
"*": "eslint --fix"
|
||||||
|
}
|
||||||
|
}
|
||||||
8113
pnpm-lock.yaml
generated
Normal file
8113
pnpm-lock.yaml
generated
Normal file
File diff suppressed because it is too large
Load Diff
9
public/favicon.svg
Normal file
9
public/favicon.svg
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 32 32">
|
||||||
|
<style>
|
||||||
|
path { fill: #222; }
|
||||||
|
@media (prefers-color-scheme: dark) {
|
||||||
|
path { fill: #ffffff; }
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
<path d="M27.562 26L17.17 8.928l2.366-3.888L17.828 4L16 7.005L14.17 4l-1.708 1.04l2.366 3.888L4.438 26H2v2h28v-2zM16 10.85L25.22 26H17v-8h-2v8H6.78z" />
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 347 B |
6
shims.d.ts
vendored
Normal file
6
shims.d.ts
vendored
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
declare module '*.vue' {
|
||||||
|
import type { DefineComponent } from 'vue'
|
||||||
|
|
||||||
|
const component: DefineComponent<object, object, any>
|
||||||
|
export default component
|
||||||
|
}
|
||||||
13
src/App.vue
Normal file
13
src/App.vue
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
<template>
|
||||||
|
<div class="w-full flex items-center justify-center">
|
||||||
|
<div class="max-w-[980px]">
|
||||||
|
<TheHeader />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<main font-sans p="x-4 y-10" text="center gray-700 dark:gray-200">
|
||||||
|
<div class="mx-auto max-w-[980px]">
|
||||||
|
<RouterView />
|
||||||
|
</div>
|
||||||
|
</main>
|
||||||
|
<TheFooter />
|
||||||
|
</template>
|
||||||
1
src/CONSTANT.ts
Normal file
1
src/CONSTANT.ts
Normal file
@ -0,0 +1 @@
|
|||||||
|
export const API_BASE_URL = 'http://localhost:5000'
|
||||||
78
src/assets/index.css
Normal file
78
src/assets/index.css
Normal file
@ -0,0 +1,78 @@
|
|||||||
|
@tailwind base;
|
||||||
|
@tailwind components;
|
||||||
|
@tailwind utilities;
|
||||||
|
|
||||||
|
@layer base {
|
||||||
|
:root {
|
||||||
|
--background: 0 0% 100%;
|
||||||
|
--foreground: 222.2 84% 4.9%;
|
||||||
|
|
||||||
|
--muted: 210 40% 96.1%;
|
||||||
|
--muted-foreground: 215.4 16.3% 46.9%;
|
||||||
|
|
||||||
|
--popover: 0 0% 100%;
|
||||||
|
--popover-foreground: 222.2 84% 4.9%;
|
||||||
|
|
||||||
|
--card: 0 0% 100%;
|
||||||
|
--card-foreground: 222.2 84% 4.9%;
|
||||||
|
|
||||||
|
--border: 214.3 31.8% 91.4%;
|
||||||
|
--input: 214.3 31.8% 91.4%;
|
||||||
|
|
||||||
|
--primary: 222.2 47.4% 11.2%;
|
||||||
|
--primary-foreground: 210 40% 98%;
|
||||||
|
|
||||||
|
--secondary: 210 40% 96.1%;
|
||||||
|
--secondary-foreground: 222.2 47.4% 11.2%;
|
||||||
|
|
||||||
|
--accent: 210 40% 96.1%;
|
||||||
|
--accent-foreground: 222.2 47.4% 11.2%;
|
||||||
|
|
||||||
|
--destructive: 0 84.2% 60.2%;
|
||||||
|
--destructive-foreground: 210 40% 98%;
|
||||||
|
|
||||||
|
--ring: 222.2 84% 4.9%;
|
||||||
|
|
||||||
|
--radius: 0.5rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.dark {
|
||||||
|
--background: 222.2 84% 4.9%;
|
||||||
|
--foreground: 210 40% 98%;
|
||||||
|
|
||||||
|
--muted: 217.2 32.6% 17.5%;
|
||||||
|
--muted-foreground: 215 20.2% 65.1%;
|
||||||
|
|
||||||
|
--popover: 222.2 84% 4.9%;
|
||||||
|
--popover-foreground: 210 40% 98%;
|
||||||
|
|
||||||
|
--card: 222.2 84% 4.9%;
|
||||||
|
--card-foreground: 210 40% 98%;
|
||||||
|
|
||||||
|
--border: 217.2 32.6% 17.5%;
|
||||||
|
--input: 217.2 32.6% 17.5%;
|
||||||
|
|
||||||
|
--primary: 210 40% 98%;
|
||||||
|
--primary-foreground: 222.2 47.4% 11.2%;
|
||||||
|
|
||||||
|
--secondary: 217.2 32.6% 17.5%;
|
||||||
|
--secondary-foreground: 210 40% 98%;
|
||||||
|
|
||||||
|
--accent: 217.2 32.6% 17.5%;
|
||||||
|
--accent-foreground: 210 40% 98%;
|
||||||
|
|
||||||
|
--destructive: 0 62.8% 30.6%;
|
||||||
|
--destructive-foreground: 210 40% 98%;
|
||||||
|
|
||||||
|
--ring: 212.7 26.8% 83.9%;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@layer base {
|
||||||
|
* {
|
||||||
|
@apply border-border;
|
||||||
|
}
|
||||||
|
body {
|
||||||
|
@apply bg-background text-foreground;
|
||||||
|
}
|
||||||
|
}
|
||||||
3
src/components/TheFooter.vue
Normal file
3
src/components/TheFooter.vue
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
<template>
|
||||||
|
<div />
|
||||||
|
</template>
|
||||||
139
src/components/TheHeader.vue
Normal file
139
src/components/TheHeader.vue
Normal file
@ -0,0 +1,139 @@
|
|||||||
|
<script setup lang="ts">
|
||||||
|
import {
|
||||||
|
NavigationMenu,
|
||||||
|
NavigationMenuContent,
|
||||||
|
NavigationMenuItem,
|
||||||
|
NavigationMenuLink,
|
||||||
|
NavigationMenuList,
|
||||||
|
NavigationMenuTrigger,
|
||||||
|
navigationMenuTriggerStyle,
|
||||||
|
} from './ui/navigation-menu'
|
||||||
|
|
||||||
|
/**
|
||||||
|
* comboType = [
|
||||||
|
"探空气球",
|
||||||
|
"流星雷达",
|
||||||
|
"Saber",
|
||||||
|
"TIDI",
|
||||||
|
"COSMIC",
|
||||||
|
]
|
||||||
|
|
||||||
|
comboMode = [
|
||||||
|
["重力波单次", "重力波统计"],
|
||||||
|
["重力波月统计", "潮汐波单次", "潮汐波月统计"],
|
||||||
|
["行星波月统计", "重力波单次", "重力波月统计"],
|
||||||
|
["行星波月统计"],
|
||||||
|
["行星波月统计"],
|
||||||
|
]
|
||||||
|
*/
|
||||||
|
const components: { title: string, href: string, description: string }[] = [
|
||||||
|
{
|
||||||
|
title: '探空气球',
|
||||||
|
href: '/ballon',
|
||||||
|
description:
|
||||||
|
'探空气球',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: 'Hover Card',
|
||||||
|
href: '/docs/components/hover-card',
|
||||||
|
description:
|
||||||
|
'For sighted users to preview content available behind a link.',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: 'Progress',
|
||||||
|
href: '/docs/components/progress',
|
||||||
|
description:
|
||||||
|
'Displays an indicator showing the completion progress of a task, typically displayed as a progress bar.',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: 'Scroll-area',
|
||||||
|
href: '/docs/components/scroll-area',
|
||||||
|
description: 'Visually or semantically separates content.',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: 'Tabs',
|
||||||
|
href: '/docs/components/tabs',
|
||||||
|
description:
|
||||||
|
'A set of layered sections of content—known as tab panels—that are displayed one at a time.',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: 'Tooltip',
|
||||||
|
href: '/docs/components/tooltip',
|
||||||
|
description:
|
||||||
|
'A popup that displays information related to an element when the element receives keyboard focus or the mouse hovers over it.',
|
||||||
|
},
|
||||||
|
]
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<NavigationMenu>
|
||||||
|
<NavigationMenuList>
|
||||||
|
<NavigationMenuItem>
|
||||||
|
<NavigationMenuLink href="/" :class="navigationMenuTriggerStyle()">
|
||||||
|
主页
|
||||||
|
</NavigationMenuLink>
|
||||||
|
</NavigationMenuItem>
|
||||||
|
<NavigationMenuItem>
|
||||||
|
<NavigationMenuTrigger>探空气球</NavigationMenuTrigger>
|
||||||
|
<NavigationMenuContent>
|
||||||
|
<ul class="grid gap-3 p-6 lg:grid-cols-[minmax(0,.75fr)_minmax(0,1fr)] lg:w-[500px] md:w-[400px]">
|
||||||
|
<li class="row-span-3">
|
||||||
|
<NavigationMenuLink as-child>
|
||||||
|
<a
|
||||||
|
class="block select-none rounded-md p-3 leading-none no-underline outline-none transition-colors space-y-1 focus:bg-accent hover:bg-accent focus:text-accent-foreground hover:text-accent-foreground"
|
||||||
|
href="/balloon/single"
|
||||||
|
>
|
||||||
|
<div class="text-sm font-medium leading-none">
|
||||||
|
探空气球 - 重力波单次
|
||||||
|
</div>
|
||||||
|
<p class="line-clamp-2 text-sm text-muted-foreground leading-tight">
|
||||||
|
探空气球 - 重力波单次
|
||||||
|
</p>
|
||||||
|
</a>
|
||||||
|
</NavigationMenuLink>
|
||||||
|
</li>
|
||||||
|
|
||||||
|
<li>
|
||||||
|
<NavigationMenuLink as-child>
|
||||||
|
<a
|
||||||
|
href="/balloon/year"
|
||||||
|
class="block select-none rounded-md p-3 leading-none no-underline outline-none transition-colors space-y-1 focus:bg-accent hover:bg-accent focus:text-accent-foreground hover:text-accent-foreground"
|
||||||
|
>
|
||||||
|
<div class="text-sm font-medium leading-none">探空气球 - 重力波统计</div>
|
||||||
|
<p class="line-clamp-2 text-sm text-muted-foreground leading-tight">
|
||||||
|
探空气球 - 重力波统计
|
||||||
|
</p>
|
||||||
|
</a>
|
||||||
|
</NavigationMenuLink>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</NavigationMenuContent>
|
||||||
|
</NavigationMenuItem>
|
||||||
|
<NavigationMenuItem>
|
||||||
|
<NavigationMenuTrigger>Components</NavigationMenuTrigger>
|
||||||
|
<NavigationMenuContent>
|
||||||
|
<ul class="grid w-[400px] gap-3 p-4 md:grid-cols-2 lg:w-[600px] md:w-[500px]">
|
||||||
|
<li v-for="component in components" :key="component.title">
|
||||||
|
<NavigationMenuLink as-child>
|
||||||
|
<a
|
||||||
|
:href="component.href"
|
||||||
|
class="block select-none rounded-md p-3 leading-none no-underline outline-none transition-colors space-y-1 focus:bg-accent hover:bg-accent focus:text-accent-foreground hover:text-accent-foreground"
|
||||||
|
>
|
||||||
|
<div class="text-sm font-medium leading-none">{{ component.title }}</div>
|
||||||
|
<p class="line-clamp-2 text-sm text-muted-foreground leading-snug">
|
||||||
|
{{ component.description }}
|
||||||
|
</p>
|
||||||
|
</a>
|
||||||
|
</NavigationMenuLink>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</NavigationMenuContent>
|
||||||
|
</NavigationMenuItem>
|
||||||
|
<NavigationMenuItem>
|
||||||
|
<NavigationMenuLink href="/docs/introduction" :class="navigationMenuTriggerStyle()">
|
||||||
|
Documentation
|
||||||
|
</NavigationMenuLink>
|
||||||
|
</NavigationMenuItem>
|
||||||
|
</NavigationMenuList>
|
||||||
|
</NavigationMenu>
|
||||||
|
</template>
|
||||||
33
src/components/ui/navigation-menu/NavigationMenu.vue
Normal file
33
src/components/ui/navigation-menu/NavigationMenu.vue
Normal file
@ -0,0 +1,33 @@
|
|||||||
|
<script setup lang="ts">
|
||||||
|
import {
|
||||||
|
NavigationMenuRoot,
|
||||||
|
type NavigationMenuRootEmits,
|
||||||
|
type NavigationMenuRootProps,
|
||||||
|
useForwardPropsEmits,
|
||||||
|
} from 'radix-vue'
|
||||||
|
import { computed, type HTMLAttributes } from 'vue'
|
||||||
|
import { cn } from '~/lib/utils'
|
||||||
|
import NavigationMenuViewport from './NavigationMenuViewport.vue'
|
||||||
|
|
||||||
|
const props = defineProps<NavigationMenuRootProps & { class?: HTMLAttributes['class'] }>()
|
||||||
|
|
||||||
|
const emits = defineEmits<NavigationMenuRootEmits>()
|
||||||
|
|
||||||
|
const delegatedProps = computed(() => {
|
||||||
|
const { class: _, ...delegated } = props
|
||||||
|
|
||||||
|
return delegated
|
||||||
|
})
|
||||||
|
|
||||||
|
const forwarded = useForwardPropsEmits(delegatedProps, emits)
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<NavigationMenuRoot
|
||||||
|
v-bind="forwarded"
|
||||||
|
:class="cn('relative z-10 flex max-w-max flex-1 items-center justify-center', props.class)"
|
||||||
|
>
|
||||||
|
<slot />
|
||||||
|
<NavigationMenuViewport />
|
||||||
|
</NavigationMenuRoot>
|
||||||
|
</template>
|
||||||
34
src/components/ui/navigation-menu/NavigationMenuContent.vue
Normal file
34
src/components/ui/navigation-menu/NavigationMenuContent.vue
Normal file
@ -0,0 +1,34 @@
|
|||||||
|
<script setup lang="ts">
|
||||||
|
import {
|
||||||
|
NavigationMenuContent,
|
||||||
|
type NavigationMenuContentEmits,
|
||||||
|
type NavigationMenuContentProps,
|
||||||
|
useForwardPropsEmits,
|
||||||
|
} from 'radix-vue'
|
||||||
|
import { computed, type HTMLAttributes } from 'vue'
|
||||||
|
import { cn } from '~/lib/utils'
|
||||||
|
|
||||||
|
const props = defineProps<NavigationMenuContentProps & { class?: HTMLAttributes['class'] }>()
|
||||||
|
|
||||||
|
const emits = defineEmits<NavigationMenuContentEmits>()
|
||||||
|
|
||||||
|
const delegatedProps = computed(() => {
|
||||||
|
const { class: _, ...delegated } = props
|
||||||
|
|
||||||
|
return delegated
|
||||||
|
})
|
||||||
|
|
||||||
|
const forwarded = useForwardPropsEmits(delegatedProps, emits)
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<NavigationMenuContent
|
||||||
|
v-bind="forwarded"
|
||||||
|
:class="cn(
|
||||||
|
'left-0 top-0 w-full data-[motion^=from-]:animate-in data-[motion^=to-]:animate-out data-[motion^=from-]:fade-in data-[motion^=to-]:fade-out data-[motion=from-end]:slide-in-from-right-52 data-[motion=from-start]:slide-in-from-left-52 data-[motion=to-end]:slide-out-to-right-52 data-[motion=to-start]:slide-out-to-left-52 md:absolute md:w-auto',
|
||||||
|
props.class,
|
||||||
|
)"
|
||||||
|
>
|
||||||
|
<slot />
|
||||||
|
</NavigationMenuContent>
|
||||||
|
</template>
|
||||||
@ -0,0 +1,24 @@
|
|||||||
|
<script setup lang="ts">
|
||||||
|
import { NavigationMenuIndicator, type NavigationMenuIndicatorProps, useForwardProps } from 'radix-vue'
|
||||||
|
import { computed, type HTMLAttributes } from 'vue'
|
||||||
|
import { cn } from '~/lib/utils'
|
||||||
|
|
||||||
|
const props = defineProps<NavigationMenuIndicatorProps & { class?: HTMLAttributes['class'] }>()
|
||||||
|
|
||||||
|
const delegatedProps = computed(() => {
|
||||||
|
const { class: _, ...delegated } = props
|
||||||
|
|
||||||
|
return delegated
|
||||||
|
})
|
||||||
|
|
||||||
|
const forwardedProps = useForwardProps(delegatedProps)
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<NavigationMenuIndicator
|
||||||
|
v-bind="forwardedProps"
|
||||||
|
:class="cn('top-full z-[1] flex h-1.5 items-end justify-center overflow-hidden data-[state=visible]:animate-in data-[state=hidden]:animate-out data-[state=hidden]:fade-out data-[state=visible]:fade-in', props.class)"
|
||||||
|
>
|
||||||
|
<div class="relative top-[60%] h-2 w-2 rotate-45 rounded-tl-sm bg-border shadow-md" />
|
||||||
|
</NavigationMenuIndicator>
|
||||||
|
</template>
|
||||||
11
src/components/ui/navigation-menu/NavigationMenuItem.vue
Normal file
11
src/components/ui/navigation-menu/NavigationMenuItem.vue
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
<script setup lang="ts">
|
||||||
|
import { NavigationMenuItem, type NavigationMenuItemProps } from 'radix-vue'
|
||||||
|
|
||||||
|
const props = defineProps<NavigationMenuItemProps>()
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<NavigationMenuItem v-bind="props">
|
||||||
|
<slot />
|
||||||
|
</NavigationMenuItem>
|
||||||
|
</template>
|
||||||
19
src/components/ui/navigation-menu/NavigationMenuLink.vue
Normal file
19
src/components/ui/navigation-menu/NavigationMenuLink.vue
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
<script setup lang="ts">
|
||||||
|
import {
|
||||||
|
NavigationMenuLink,
|
||||||
|
type NavigationMenuLinkEmits,
|
||||||
|
type NavigationMenuLinkProps,
|
||||||
|
useForwardPropsEmits,
|
||||||
|
} from 'radix-vue'
|
||||||
|
|
||||||
|
const props = defineProps<NavigationMenuLinkProps>()
|
||||||
|
const emits = defineEmits<NavigationMenuLinkEmits>()
|
||||||
|
|
||||||
|
const forwarded = useForwardPropsEmits(props, emits)
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<NavigationMenuLink v-bind="forwarded">
|
||||||
|
<slot />
|
||||||
|
</NavigationMenuLink>
|
||||||
|
</template>
|
||||||
29
src/components/ui/navigation-menu/NavigationMenuList.vue
Normal file
29
src/components/ui/navigation-menu/NavigationMenuList.vue
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
<script setup lang="ts">
|
||||||
|
import { NavigationMenuList, type NavigationMenuListProps, useForwardProps } from 'radix-vue'
|
||||||
|
import { computed, type HTMLAttributes } from 'vue'
|
||||||
|
import { cn } from '~/lib/utils'
|
||||||
|
|
||||||
|
const props = defineProps<NavigationMenuListProps & { class?: HTMLAttributes['class'] }>()
|
||||||
|
|
||||||
|
const delegatedProps = computed(() => {
|
||||||
|
const { class: _, ...delegated } = props
|
||||||
|
|
||||||
|
return delegated
|
||||||
|
})
|
||||||
|
|
||||||
|
const forwardedProps = useForwardProps(delegatedProps)
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<NavigationMenuList
|
||||||
|
v-bind="forwardedProps"
|
||||||
|
:class="
|
||||||
|
cn(
|
||||||
|
'group flex flex-1 list-none items-center justify-center gap-x-1',
|
||||||
|
props.class,
|
||||||
|
)
|
||||||
|
"
|
||||||
|
>
|
||||||
|
<slot />
|
||||||
|
</NavigationMenuList>
|
||||||
|
</template>
|
||||||
34
src/components/ui/navigation-menu/NavigationMenuTrigger.vue
Normal file
34
src/components/ui/navigation-menu/NavigationMenuTrigger.vue
Normal file
@ -0,0 +1,34 @@
|
|||||||
|
<script setup lang="ts">
|
||||||
|
import { ChevronDown } from 'lucide-vue-next'
|
||||||
|
import {
|
||||||
|
NavigationMenuTrigger,
|
||||||
|
type NavigationMenuTriggerProps,
|
||||||
|
useForwardProps,
|
||||||
|
} from 'radix-vue'
|
||||||
|
import { computed, type HTMLAttributes } from 'vue'
|
||||||
|
import { cn } from '~/lib/utils'
|
||||||
|
import { navigationMenuTriggerStyle } from '.'
|
||||||
|
|
||||||
|
const props = defineProps<NavigationMenuTriggerProps & { class?: HTMLAttributes['class'] }>()
|
||||||
|
|
||||||
|
const delegatedProps = computed(() => {
|
||||||
|
const { class: _, ...delegated } = props
|
||||||
|
|
||||||
|
return delegated
|
||||||
|
})
|
||||||
|
|
||||||
|
const forwardedProps = useForwardProps(delegatedProps)
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<NavigationMenuTrigger
|
||||||
|
v-bind="forwardedProps"
|
||||||
|
:class="cn(navigationMenuTriggerStyle(), 'group', props.class)"
|
||||||
|
>
|
||||||
|
<slot />
|
||||||
|
<ChevronDown
|
||||||
|
class="relative top-px ml-1 h-3 w-3 transition duration-200 group-data-[state=open]:rotate-180"
|
||||||
|
aria-hidden="true"
|
||||||
|
/>
|
||||||
|
</NavigationMenuTrigger>
|
||||||
|
</template>
|
||||||
33
src/components/ui/navigation-menu/NavigationMenuViewport.vue
Normal file
33
src/components/ui/navigation-menu/NavigationMenuViewport.vue
Normal file
@ -0,0 +1,33 @@
|
|||||||
|
<script setup lang="ts">
|
||||||
|
import {
|
||||||
|
NavigationMenuViewport,
|
||||||
|
type NavigationMenuViewportProps,
|
||||||
|
useForwardProps,
|
||||||
|
} from 'radix-vue'
|
||||||
|
import { computed, type HTMLAttributes } from 'vue'
|
||||||
|
import { cn } from '~/lib/utils'
|
||||||
|
|
||||||
|
const props = defineProps<NavigationMenuViewportProps & { class?: HTMLAttributes['class'] }>()
|
||||||
|
|
||||||
|
const delegatedProps = computed(() => {
|
||||||
|
const { class: _, ...delegated } = props
|
||||||
|
|
||||||
|
return delegated
|
||||||
|
})
|
||||||
|
|
||||||
|
const forwardedProps = useForwardProps(delegatedProps)
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<div class="absolute left-0 top-full flex justify-center">
|
||||||
|
<NavigationMenuViewport
|
||||||
|
v-bind="forwardedProps"
|
||||||
|
:class="
|
||||||
|
cn(
|
||||||
|
'origin-top-center relative mt-1.5 h-[--radix-navigation-menu-viewport-height] w-full overflow-hidden rounded-md border bg-popover text-popover-foreground shadow-lg data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-90 md:w-[--radix-navigation-menu-viewport-width]',
|
||||||
|
props.class,
|
||||||
|
)
|
||||||
|
"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
13
src/components/ui/navigation-menu/index.ts
Normal file
13
src/components/ui/navigation-menu/index.ts
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
import { cva } from 'class-variance-authority'
|
||||||
|
|
||||||
|
export { default as NavigationMenu } from './NavigationMenu.vue'
|
||||||
|
export { default as NavigationMenuContent } from './NavigationMenuContent.vue'
|
||||||
|
export { default as NavigationMenuItem } from './NavigationMenuItem.vue'
|
||||||
|
export { default as NavigationMenuLink } from './NavigationMenuLink.vue'
|
||||||
|
export { default as NavigationMenuList } from './NavigationMenuList.vue'
|
||||||
|
export { default as NavigationMenuTrigger } from './NavigationMenuTrigger.vue'
|
||||||
|
export { default as NavigationMenuViewport } from './NavigationMenuViewport.vue'
|
||||||
|
|
||||||
|
export const navigationMenuTriggerStyle = cva(
|
||||||
|
'group inline-flex h-10 w-max items-center justify-center rounded-md bg-background px-4 py-2 text-sm font-medium transition-colors hover:bg-accent hover:text-accent-foreground focus:bg-accent focus:text-accent-foreground focus:outline-none disabled:pointer-events-none disabled:opacity-50 data-[active]:bg-accent/50 data-[state=open]:bg-accent/50',
|
||||||
|
)
|
||||||
23
src/components/ui/number-field/NumberField.vue
Normal file
23
src/components/ui/number-field/NumberField.vue
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
<script setup lang="ts">
|
||||||
|
import type { NumberFieldRootEmits, NumberFieldRootProps } from 'radix-vue'
|
||||||
|
import { NumberFieldRoot, useForwardPropsEmits } from 'radix-vue'
|
||||||
|
import { computed, type HTMLAttributes } from 'vue'
|
||||||
|
import { cn } from '~/lib/utils'
|
||||||
|
|
||||||
|
const props = defineProps<NumberFieldRootProps & { class?: HTMLAttributes['class'] }>()
|
||||||
|
const emits = defineEmits<NumberFieldRootEmits>()
|
||||||
|
|
||||||
|
const delegatedProps = computed(() => {
|
||||||
|
const { class: _, ...delegated } = props
|
||||||
|
|
||||||
|
return delegated
|
||||||
|
})
|
||||||
|
|
||||||
|
const forwarded = useForwardPropsEmits(delegatedProps, emits)
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<NumberFieldRoot v-bind="forwarded" :class="cn('grid gap-1.5', props.class)">
|
||||||
|
<slot />
|
||||||
|
</NumberFieldRoot>
|
||||||
|
</template>
|
||||||
14
src/components/ui/number-field/NumberFieldContent.vue
Normal file
14
src/components/ui/number-field/NumberFieldContent.vue
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
<script setup lang="ts">
|
||||||
|
import type { HTMLAttributes } from 'vue'
|
||||||
|
import { cn } from '~/lib/utils'
|
||||||
|
|
||||||
|
const props = defineProps<{
|
||||||
|
class?: HTMLAttributes['class']
|
||||||
|
}>()
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<div :class="cn('relative [&>[data-slot=input]]:has-[[data-slot=increment]]:pr-5 [&>[data-slot=input]]:has-[[data-slot=decrement]]:pl-5', props.class)">
|
||||||
|
<slot />
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
25
src/components/ui/number-field/NumberFieldDecrement.vue
Normal file
25
src/components/ui/number-field/NumberFieldDecrement.vue
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
<script setup lang="ts">
|
||||||
|
import type { NumberFieldDecrementProps } from 'radix-vue'
|
||||||
|
import { Minus } from 'lucide-vue-next'
|
||||||
|
import { NumberFieldDecrement, useForwardProps } from 'radix-vue'
|
||||||
|
import { computed, type HTMLAttributes } from 'vue'
|
||||||
|
import { cn } from '~/lib/utils'
|
||||||
|
|
||||||
|
const props = defineProps<NumberFieldDecrementProps & { class?: HTMLAttributes['class'] }>()
|
||||||
|
|
||||||
|
const delegatedProps = computed(() => {
|
||||||
|
const { class: _, ...delegated } = props
|
||||||
|
|
||||||
|
return delegated
|
||||||
|
})
|
||||||
|
|
||||||
|
const forwarded = useForwardProps(delegatedProps)
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<NumberFieldDecrement data-slot="decrement" v-bind="forwarded" :class="cn('absolute top-1/2 -translate-y-1/2 left-0 p-3 disabled:cursor-not-allowed disabled:opacity-20', props.class)">
|
||||||
|
<slot>
|
||||||
|
<Minus class="h-4 w-4" />
|
||||||
|
</slot>
|
||||||
|
</NumberFieldDecrement>
|
||||||
|
</template>
|
||||||
25
src/components/ui/number-field/NumberFieldIncrement.vue
Normal file
25
src/components/ui/number-field/NumberFieldIncrement.vue
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
<script setup lang="ts">
|
||||||
|
import type { NumberFieldIncrementProps } from 'radix-vue'
|
||||||
|
import { Plus } from 'lucide-vue-next'
|
||||||
|
import { NumberFieldIncrement, useForwardProps } from 'radix-vue'
|
||||||
|
import { computed, type HTMLAttributes } from 'vue'
|
||||||
|
import { cn } from '~/lib/utils'
|
||||||
|
|
||||||
|
const props = defineProps<NumberFieldIncrementProps & { class?: HTMLAttributes['class'] }>()
|
||||||
|
|
||||||
|
const delegatedProps = computed(() => {
|
||||||
|
const { class: _, ...delegated } = props
|
||||||
|
|
||||||
|
return delegated
|
||||||
|
})
|
||||||
|
|
||||||
|
const forwarded = useForwardProps(delegatedProps)
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<NumberFieldIncrement data-slot="increment" v-bind="forwarded" :class="cn('absolute top-1/2 -translate-y-1/2 right-0 disabled:cursor-not-allowed disabled:opacity-20 p-3', props.class)">
|
||||||
|
<slot>
|
||||||
|
<Plus class="h-4 w-4" />
|
||||||
|
</slot>
|
||||||
|
</NumberFieldIncrement>
|
||||||
|
</template>
|
||||||
16
src/components/ui/number-field/NumberFieldInput.vue
Normal file
16
src/components/ui/number-field/NumberFieldInput.vue
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
<script setup lang="ts">
|
||||||
|
import type { HTMLAttributes } from 'vue'
|
||||||
|
import { NumberFieldInput } from 'radix-vue'
|
||||||
|
import { cn } from '~/lib/utils'
|
||||||
|
|
||||||
|
const props = defineProps<{
|
||||||
|
class?: HTMLAttributes['class']
|
||||||
|
}>()
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<NumberFieldInput
|
||||||
|
data-slot="input"
|
||||||
|
:class="cn('flex h-10 w-full rounded-md border border-input bg-background py-2 text-sm text-center ring-offset-background placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50', props.class)"
|
||||||
|
/>
|
||||||
|
</template>
|
||||||
5
src/components/ui/number-field/index.ts
Normal file
5
src/components/ui/number-field/index.ts
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
export { default as NumberField } from './NumberField.vue'
|
||||||
|
export { default as NumberFieldContent } from './NumberFieldContent.vue'
|
||||||
|
export { default as NumberFieldDecrement } from './NumberFieldDecrement.vue'
|
||||||
|
export { default as NumberFieldIncrement } from './NumberFieldIncrement.vue'
|
||||||
|
export { default as NumberFieldInput } from './NumberFieldInput.vue'
|
||||||
15
src/components/ui/select/Select.vue
Normal file
15
src/components/ui/select/Select.vue
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
<script setup lang="ts">
|
||||||
|
import type { SelectRootEmits, SelectRootProps } from 'radix-vue'
|
||||||
|
import { SelectRoot, useForwardPropsEmits } from 'radix-vue'
|
||||||
|
|
||||||
|
const props = defineProps<SelectRootProps>()
|
||||||
|
const emits = defineEmits<SelectRootEmits>()
|
||||||
|
|
||||||
|
const forwarded = useForwardPropsEmits(props, emits)
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<SelectRoot v-bind="forwarded">
|
||||||
|
<slot />
|
||||||
|
</SelectRoot>
|
||||||
|
</template>
|
||||||
53
src/components/ui/select/SelectContent.vue
Normal file
53
src/components/ui/select/SelectContent.vue
Normal file
@ -0,0 +1,53 @@
|
|||||||
|
<script setup lang="ts">
|
||||||
|
import {
|
||||||
|
SelectContent,
|
||||||
|
type SelectContentEmits,
|
||||||
|
type SelectContentProps,
|
||||||
|
SelectPortal,
|
||||||
|
SelectViewport,
|
||||||
|
useForwardPropsEmits,
|
||||||
|
} from 'radix-vue'
|
||||||
|
import { computed, type HTMLAttributes } from 'vue'
|
||||||
|
import { cn } from '~/lib/utils'
|
||||||
|
import { SelectScrollDownButton, SelectScrollUpButton } from '.'
|
||||||
|
|
||||||
|
defineOptions({
|
||||||
|
inheritAttrs: false,
|
||||||
|
})
|
||||||
|
|
||||||
|
const props = withDefaults(
|
||||||
|
defineProps<SelectContentProps & { class?: HTMLAttributes['class'] }>(),
|
||||||
|
{
|
||||||
|
position: 'popper',
|
||||||
|
},
|
||||||
|
)
|
||||||
|
const emits = defineEmits<SelectContentEmits>()
|
||||||
|
|
||||||
|
const delegatedProps = computed(() => {
|
||||||
|
const { class: _, ...delegated } = props
|
||||||
|
|
||||||
|
return delegated
|
||||||
|
})
|
||||||
|
|
||||||
|
const forwarded = useForwardPropsEmits(delegatedProps, emits)
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<SelectPortal>
|
||||||
|
<SelectContent
|
||||||
|
v-bind="{ ...forwarded, ...$attrs }" :class="cn(
|
||||||
|
'relative z-50 max-h-96 min-w-32 overflow-hidden rounded-md border bg-popover text-popover-foreground shadow-md data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2',
|
||||||
|
position === 'popper'
|
||||||
|
&& 'data-[side=bottom]:translate-y-1 data-[side=left]:-translate-x-1 data-[side=right]:translate-x-1 data-[side=top]:-translate-y-1',
|
||||||
|
props.class,
|
||||||
|
)
|
||||||
|
"
|
||||||
|
>
|
||||||
|
<SelectScrollUpButton />
|
||||||
|
<SelectViewport :class="cn('p-1', position === 'popper' && 'h-[--radix-select-trigger-height] w-full min-w-[--radix-select-trigger-width]')">
|
||||||
|
<slot />
|
||||||
|
</SelectViewport>
|
||||||
|
<SelectScrollDownButton />
|
||||||
|
</SelectContent>
|
||||||
|
</SelectPortal>
|
||||||
|
</template>
|
||||||
19
src/components/ui/select/SelectGroup.vue
Normal file
19
src/components/ui/select/SelectGroup.vue
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
<script setup lang="ts">
|
||||||
|
import { SelectGroup, type SelectGroupProps } from 'radix-vue'
|
||||||
|
import { computed, type HTMLAttributes } from 'vue'
|
||||||
|
import { cn } from '~/lib/utils'
|
||||||
|
|
||||||
|
const props = defineProps<SelectGroupProps & { class?: HTMLAttributes['class'] }>()
|
||||||
|
|
||||||
|
const delegatedProps = computed(() => {
|
||||||
|
const { class: _, ...delegated } = props
|
||||||
|
|
||||||
|
return delegated
|
||||||
|
})
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<SelectGroup :class="cn('p-1 w-full', props.class)" v-bind="delegatedProps">
|
||||||
|
<slot />
|
||||||
|
</SelectGroup>
|
||||||
|
</template>
|
||||||
44
src/components/ui/select/SelectItem.vue
Normal file
44
src/components/ui/select/SelectItem.vue
Normal file
@ -0,0 +1,44 @@
|
|||||||
|
<script setup lang="ts">
|
||||||
|
import { Check } from 'lucide-vue-next'
|
||||||
|
import {
|
||||||
|
SelectItem,
|
||||||
|
SelectItemIndicator,
|
||||||
|
type SelectItemProps,
|
||||||
|
SelectItemText,
|
||||||
|
useForwardProps,
|
||||||
|
} from 'radix-vue'
|
||||||
|
import { computed, type HTMLAttributes } from 'vue'
|
||||||
|
import { cn } from '~/lib/utils'
|
||||||
|
|
||||||
|
const props = defineProps<SelectItemProps & { class?: HTMLAttributes['class'] }>()
|
||||||
|
|
||||||
|
const delegatedProps = computed(() => {
|
||||||
|
const { class: _, ...delegated } = props
|
||||||
|
|
||||||
|
return delegated
|
||||||
|
})
|
||||||
|
|
||||||
|
const forwardedProps = useForwardProps(delegatedProps)
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<SelectItem
|
||||||
|
v-bind="forwardedProps"
|
||||||
|
:class="
|
||||||
|
cn(
|
||||||
|
'relative flex w-full cursor-default select-none items-center rounded-sm py-1.5 pl-8 pr-2 text-sm outline-none focus:bg-accent focus:text-accent-foreground data-[disabled]:pointer-events-none data-[disabled]:opacity-50',
|
||||||
|
props.class,
|
||||||
|
)
|
||||||
|
"
|
||||||
|
>
|
||||||
|
<span class="absolute left-2 h-3.5 w-3.5 flex items-center justify-center">
|
||||||
|
<SelectItemIndicator>
|
||||||
|
<Check class="h-4 w-4" />
|
||||||
|
</SelectItemIndicator>
|
||||||
|
</span>
|
||||||
|
|
||||||
|
<SelectItemText>
|
||||||
|
<slot />
|
||||||
|
</SelectItemText>
|
||||||
|
</SelectItem>
|
||||||
|
</template>
|
||||||
11
src/components/ui/select/SelectItemText.vue
Normal file
11
src/components/ui/select/SelectItemText.vue
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
<script setup lang="ts">
|
||||||
|
import { SelectItemText, type SelectItemTextProps } from 'radix-vue'
|
||||||
|
|
||||||
|
const props = defineProps<SelectItemTextProps>()
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<SelectItemText v-bind="props">
|
||||||
|
<slot />
|
||||||
|
</SelectItemText>
|
||||||
|
</template>
|
||||||
13
src/components/ui/select/SelectLabel.vue
Normal file
13
src/components/ui/select/SelectLabel.vue
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
<script setup lang="ts">
|
||||||
|
import type { HTMLAttributes } from 'vue'
|
||||||
|
import { SelectLabel, type SelectLabelProps } from 'radix-vue'
|
||||||
|
import { cn } from '~/lib/utils'
|
||||||
|
|
||||||
|
const props = defineProps<SelectLabelProps & { class?: HTMLAttributes['class'] }>()
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<SelectLabel :class="cn('py-1.5 pl-8 pr-2 text-sm font-semibold', props.class)">
|
||||||
|
<slot />
|
||||||
|
</SelectLabel>
|
||||||
|
</template>
|
||||||
24
src/components/ui/select/SelectScrollDownButton.vue
Normal file
24
src/components/ui/select/SelectScrollDownButton.vue
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
<script setup lang="ts">
|
||||||
|
import { ChevronDown } from 'lucide-vue-next'
|
||||||
|
import { SelectScrollDownButton, type SelectScrollDownButtonProps, useForwardProps } from 'radix-vue'
|
||||||
|
import { computed, type HTMLAttributes } from 'vue'
|
||||||
|
import { cn } from '~/lib/utils'
|
||||||
|
|
||||||
|
const props = defineProps<SelectScrollDownButtonProps & { class?: HTMLAttributes['class'] }>()
|
||||||
|
|
||||||
|
const delegatedProps = computed(() => {
|
||||||
|
const { class: _, ...delegated } = props
|
||||||
|
|
||||||
|
return delegated
|
||||||
|
})
|
||||||
|
|
||||||
|
const forwardedProps = useForwardProps(delegatedProps)
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<SelectScrollDownButton v-bind="forwardedProps" :class="cn('flex cursor-default items-center justify-center py-1', props.class)">
|
||||||
|
<slot>
|
||||||
|
<ChevronDown class="h-4 w-4" />
|
||||||
|
</slot>
|
||||||
|
</SelectScrollDownButton>
|
||||||
|
</template>
|
||||||
24
src/components/ui/select/SelectScrollUpButton.vue
Normal file
24
src/components/ui/select/SelectScrollUpButton.vue
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
<script setup lang="ts">
|
||||||
|
import { ChevronUp } from 'lucide-vue-next'
|
||||||
|
import { SelectScrollUpButton, type SelectScrollUpButtonProps, useForwardProps } from 'radix-vue'
|
||||||
|
import { computed, type HTMLAttributes } from 'vue'
|
||||||
|
import { cn } from '~/lib/utils'
|
||||||
|
|
||||||
|
const props = defineProps<SelectScrollUpButtonProps & { class?: HTMLAttributes['class'] }>()
|
||||||
|
|
||||||
|
const delegatedProps = computed(() => {
|
||||||
|
const { class: _, ...delegated } = props
|
||||||
|
|
||||||
|
return delegated
|
||||||
|
})
|
||||||
|
|
||||||
|
const forwardedProps = useForwardProps(delegatedProps)
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<SelectScrollUpButton v-bind="forwardedProps" :class="cn('flex cursor-default items-center justify-center py-1', props.class)">
|
||||||
|
<slot>
|
||||||
|
<ChevronUp class="h-4 w-4" />
|
||||||
|
</slot>
|
||||||
|
</SelectScrollUpButton>
|
||||||
|
</template>
|
||||||
17
src/components/ui/select/SelectSeparator.vue
Normal file
17
src/components/ui/select/SelectSeparator.vue
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
<script setup lang="ts">
|
||||||
|
import { SelectSeparator, type SelectSeparatorProps } from 'radix-vue'
|
||||||
|
import { computed, type HTMLAttributes } from 'vue'
|
||||||
|
import { cn } from '~/lib/utils'
|
||||||
|
|
||||||
|
const props = defineProps<SelectSeparatorProps & { class?: HTMLAttributes['class'] }>()
|
||||||
|
|
||||||
|
const delegatedProps = computed(() => {
|
||||||
|
const { class: _, ...delegated } = props
|
||||||
|
|
||||||
|
return delegated
|
||||||
|
})
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<SelectSeparator v-bind="delegatedProps" :class="cn('-mx-1 my-1 h-px bg-muted', props.class)" />
|
||||||
|
</template>
|
||||||
31
src/components/ui/select/SelectTrigger.vue
Normal file
31
src/components/ui/select/SelectTrigger.vue
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
<script setup lang="ts">
|
||||||
|
import { ChevronDown } from 'lucide-vue-next'
|
||||||
|
import { SelectIcon, SelectTrigger, type SelectTriggerProps, useForwardProps } from 'radix-vue'
|
||||||
|
import { computed, type HTMLAttributes } from 'vue'
|
||||||
|
import { cn } from '~/lib/utils'
|
||||||
|
|
||||||
|
const props = defineProps<SelectTriggerProps & { class?: HTMLAttributes['class'] }>()
|
||||||
|
|
||||||
|
const delegatedProps = computed(() => {
|
||||||
|
const { class: _, ...delegated } = props
|
||||||
|
|
||||||
|
return delegated
|
||||||
|
})
|
||||||
|
|
||||||
|
const forwardedProps = useForwardProps(delegatedProps)
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<SelectTrigger
|
||||||
|
v-bind="forwardedProps"
|
||||||
|
:class="cn(
|
||||||
|
'flex h-10 w-full items-center justify-between rounded-md border border-input bg-background px-3 py-2 text-sm ring-offset-background data-[placeholder]:text-muted-foreground focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50 [&>span]:truncate text-start',
|
||||||
|
props.class,
|
||||||
|
)"
|
||||||
|
>
|
||||||
|
<slot />
|
||||||
|
<SelectIcon as-child>
|
||||||
|
<ChevronDown class="h-4 w-4 shrink-0 opacity-50" />
|
||||||
|
</SelectIcon>
|
||||||
|
</SelectTrigger>
|
||||||
|
</template>
|
||||||
11
src/components/ui/select/SelectValue.vue
Normal file
11
src/components/ui/select/SelectValue.vue
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
<script setup lang="ts">
|
||||||
|
import { SelectValue, type SelectValueProps } from 'radix-vue'
|
||||||
|
|
||||||
|
const props = defineProps<SelectValueProps>()
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<SelectValue v-bind="props">
|
||||||
|
<slot />
|
||||||
|
</SelectValue>
|
||||||
|
</template>
|
||||||
11
src/components/ui/select/index.ts
Normal file
11
src/components/ui/select/index.ts
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
export { default as Select } from './Select.vue'
|
||||||
|
export { default as SelectContent } from './SelectContent.vue'
|
||||||
|
export { default as SelectGroup } from './SelectGroup.vue'
|
||||||
|
export { default as SelectItem } from './SelectItem.vue'
|
||||||
|
export { default as SelectItemText } from './SelectItemText.vue'
|
||||||
|
export { default as SelectLabel } from './SelectLabel.vue'
|
||||||
|
export { default as SelectScrollDownButton } from './SelectScrollDownButton.vue'
|
||||||
|
export { default as SelectScrollUpButton } from './SelectScrollUpButton.vue'
|
||||||
|
export { default as SelectSeparator } from './SelectSeparator.vue'
|
||||||
|
export { default as SelectTrigger } from './SelectTrigger.vue'
|
||||||
|
export { default as SelectValue } from './SelectValue.vue'
|
||||||
2
src/composables/dark.ts
Normal file
2
src/composables/dark.ts
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
export const isDark = useDark()
|
||||||
|
export const toggleDark = useToggle(isDark)
|
||||||
1
src/composables/index.ts
Normal file
1
src/composables/index.ts
Normal file
@ -0,0 +1 @@
|
|||||||
|
export * from './dark'
|
||||||
6
src/lib/utils.ts
Normal file
6
src/lib/utils.ts
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
import { type ClassValue, clsx } from 'clsx'
|
||||||
|
import { twMerge } from 'tailwind-merge'
|
||||||
|
|
||||||
|
export function cn(...inputs: ClassValue[]) {
|
||||||
|
return twMerge(clsx(inputs))
|
||||||
|
}
|
||||||
17
src/main.ts
Normal file
17
src/main.ts
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
import { createApp } from 'vue'
|
||||||
|
import { createRouter, createWebHistory } from 'vue-router'
|
||||||
|
import { routes } from 'vue-router/auto-routes'
|
||||||
|
import App from './App.vue'
|
||||||
|
|
||||||
|
import '@unocss/reset/tailwind.css'
|
||||||
|
import './styles/main.css'
|
||||||
|
import './assets/index.css'
|
||||||
|
import 'uno.css'
|
||||||
|
|
||||||
|
const app = createApp(App)
|
||||||
|
const router = createRouter({
|
||||||
|
routes,
|
||||||
|
history: createWebHistory(import.meta.env.BASE_URL),
|
||||||
|
})
|
||||||
|
app.use(router)
|
||||||
|
app.mount('#app')
|
||||||
20
src/pages/README.md
Normal file
20
src/pages/README.md
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
## File-based Routing
|
||||||
|
|
||||||
|
Routes will be auto-generated for Vue files in this dir with the same file structure.
|
||||||
|
Check out [`unplugin-vue-router`](https://github.com/posva/unplugin-vue-router) for more details.
|
||||||
|
|
||||||
|
### Path Aliasing
|
||||||
|
|
||||||
|
`~/` is aliased to `./src/` folder.
|
||||||
|
|
||||||
|
For example, instead of having
|
||||||
|
|
||||||
|
```ts
|
||||||
|
import { isDark } from '../../../../composables'
|
||||||
|
```
|
||||||
|
|
||||||
|
now, you can use
|
||||||
|
|
||||||
|
```ts
|
||||||
|
import { isDark } from '~/composables'
|
||||||
|
```
|
||||||
5
src/pages/[...all].vue
Executable file
5
src/pages/[...all].vue
Executable file
@ -0,0 +1,5 @@
|
|||||||
|
<template>
|
||||||
|
<div>
|
||||||
|
Not Found
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
94
src/pages/balloon/single.vue
Normal file
94
src/pages/balloon/single.vue
Normal file
@ -0,0 +1,94 @@
|
|||||||
|
<script setup lang="ts">
|
||||||
|
const selectedMode = ref('观测的二阶多项式拟合')
|
||||||
|
|
||||||
|
const imageUrl = ref('')
|
||||||
|
const hasWaveThisDay = ref(false)
|
||||||
|
|
||||||
|
const modes = [
|
||||||
|
'观测的二阶多项式拟合',
|
||||||
|
'扰动分量的正弦波拟合',
|
||||||
|
'径向风-纬向风矢量图',
|
||||||
|
'温度-水平风矢量图',
|
||||||
|
]
|
||||||
|
|
||||||
|
const selectedDate = ref('2022-01-01')
|
||||||
|
|
||||||
|
const dates = ref([] as string[])
|
||||||
|
|
||||||
|
onMounted(async () => {
|
||||||
|
const resp = await fetch('http://localhost:5000/balloon/metadata')
|
||||||
|
const data = await resp.json()
|
||||||
|
dates.value = data
|
||||||
|
})
|
||||||
|
|
||||||
|
async function get_image() {
|
||||||
|
const resp = await fetch(`http://localhost:5000/balloon/render/single?mode=${encodeURIComponent(selectedMode.value)}&path=${encodeURIComponent(selectedDate.value)}`)
|
||||||
|
// check for MIME Type, check if is png
|
||||||
|
const isPng = resp.headers.get('Content-Type') === 'image/png'
|
||||||
|
if (!isPng) {
|
||||||
|
hasWaveThisDay.value = false
|
||||||
|
return
|
||||||
|
// return alert('No image available for this mode and date')
|
||||||
|
}
|
||||||
|
hasWaveThisDay.value = true
|
||||||
|
const blob = await resp.blob()
|
||||||
|
const url = URL.createObjectURL(blob)
|
||||||
|
imageUrl.value = url
|
||||||
|
}
|
||||||
|
|
||||||
|
watch([selectedMode, selectedDate], () => {
|
||||||
|
get_image()
|
||||||
|
})
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<div flex="~ col items-center">
|
||||||
|
<div>
|
||||||
|
<div flex="~ row items-center gap-3" py-3>
|
||||||
|
<Select v-model="selectedMode">
|
||||||
|
<SelectTrigger class="w-[180px]">
|
||||||
|
<SelectValue placeholder="Select a fruit" />
|
||||||
|
</SelectTrigger>
|
||||||
|
<SelectContent>
|
||||||
|
<SelectGroup>
|
||||||
|
<SelectLabel>计算模式</SelectLabel>
|
||||||
|
<SelectItem v-for="mode in modes" :key="mode" :value="mode">
|
||||||
|
{{ mode }}
|
||||||
|
</SelectItem>
|
||||||
|
</SelectGroup>
|
||||||
|
</SelectContent>
|
||||||
|
</Select>
|
||||||
|
<Select v-model="selectedDate">
|
||||||
|
<SelectTrigger class="w-[180px]">
|
||||||
|
<SelectValue placeholder="Select a fruit" />
|
||||||
|
</SelectTrigger>
|
||||||
|
<SelectContent>
|
||||||
|
<SelectGroup>
|
||||||
|
<SelectLabel>天</SelectLabel>
|
||||||
|
<SelectItem v-for="date in dates" :key="date" :value="date">
|
||||||
|
{{ date.match(/_(\d{8}T\d{6})/)?.[1] }}
|
||||||
|
</SelectItem>
|
||||||
|
</SelectGroup>
|
||||||
|
</SelectContent>
|
||||||
|
</Select>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
{{ selectedMode }}
|
||||||
|
{{ selectedDate }}
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<div v-if="hasWaveThisDay">
|
||||||
|
<img :src="imageUrl">
|
||||||
|
</div>
|
||||||
|
<div v-else h-40 flex="~ col items-center justify-center" text-xl>
|
||||||
|
{{ selectedDate.match(/_(\d{8}T\d{6})/)?.[1] }} <br>
|
||||||
|
这个时刻没有数据
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<style lang="scss" scoped>
|
||||||
|
|
||||||
|
</style>
|
||||||
115
src/pages/balloon/year.vue
Normal file
115
src/pages/balloon/year.vue
Normal file
@ -0,0 +1,115 @@
|
|||||||
|
<script setup lang="ts">
|
||||||
|
const selectedMode = ref('w/f值统计结果')
|
||||||
|
|
||||||
|
const isIllegal = ref(false)
|
||||||
|
const imageUrl = ref('')
|
||||||
|
|
||||||
|
const startYear = ref(2017)
|
||||||
|
const endYear = ref(2024)
|
||||||
|
|
||||||
|
const modes = [
|
||||||
|
|
||||||
|
'w/f值统计结果',
|
||||||
|
'周期统计结果',
|
||||||
|
'垂直波长分布',
|
||||||
|
'水平波长分布',
|
||||||
|
'纬向本征相速度',
|
||||||
|
'经向本征相速度',
|
||||||
|
'垂直本征相速度',
|
||||||
|
'Zonal wind amplitude (m/s)',
|
||||||
|
'扰动振幅统计结果',
|
||||||
|
'Temperature amplitude (K)',
|
||||||
|
'纬向动量通量统计结果',
|
||||||
|
'经向动量通量统计结果',
|
||||||
|
'horizontal propagation',
|
||||||
|
'每月上传/下传重力波占比',
|
||||||
|
'动能和势能分布情况',
|
||||||
|
]
|
||||||
|
|
||||||
|
async function refreshImage() {
|
||||||
|
const url = `http://localhost:5000/balloon/render/year?mode=${encodeURIComponent(selectedMode.value)}&start_year=${startYear.value}&end_year=${endYear.value}`
|
||||||
|
const resp = await fetch(url)
|
||||||
|
const blob = await resp.blob()
|
||||||
|
const u = URL.createObjectURL(blob)
|
||||||
|
imageUrl.value = u
|
||||||
|
}
|
||||||
|
|
||||||
|
watch([selectedMode, startYear, endYear], () => {
|
||||||
|
if (startYear.value > endYear.value) {
|
||||||
|
isIllegal.value = true
|
||||||
|
return
|
||||||
|
}
|
||||||
|
isIllegal.value = false
|
||||||
|
refreshImage()
|
||||||
|
})
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<div>
|
||||||
|
<div>
|
||||||
|
<div flex="row ~ items-center justify-center">
|
||||||
|
<div>
|
||||||
|
<Label>计算模式</Label>
|
||||||
|
<Select v-model="selectedMode">
|
||||||
|
<SelectTrigger class="w-[180px]">
|
||||||
|
<SelectValue placeholder="Select a fruit" />
|
||||||
|
</SelectTrigger>
|
||||||
|
<SelectContent>
|
||||||
|
<SelectGroup>
|
||||||
|
<SelectLabel>模式</SelectLabel>
|
||||||
|
<SelectItem v-for="mode in modes" :key="mode" :value="mode">
|
||||||
|
{{ mode }}
|
||||||
|
</SelectItem>
|
||||||
|
</SelectGroup>
|
||||||
|
</SelectContent>
|
||||||
|
</Select>
|
||||||
|
</div>
|
||||||
|
<NumberField
|
||||||
|
id="start"
|
||||||
|
v-model:model-value="startYear" :format-options="{
|
||||||
|
useGrouping: false,
|
||||||
|
}" :default-value="2017" :min="2017" :max="2024"
|
||||||
|
>
|
||||||
|
<Label for="start">起始年</Label>
|
||||||
|
<NumberFieldContent>
|
||||||
|
<NumberFieldDecrement />
|
||||||
|
<NumberFieldInput />
|
||||||
|
<NumberFieldIncrement />
|
||||||
|
</NumberFieldContent>
|
||||||
|
</NumberField>
|
||||||
|
<NumberField
|
||||||
|
id="end"
|
||||||
|
v-model:model-value="endYear" :format-options="{
|
||||||
|
style: 'decimal',
|
||||||
|
notation: 'standard',
|
||||||
|
useGrouping: false,
|
||||||
|
}" :default-value="2017" :min="2017" :max="2024"
|
||||||
|
>
|
||||||
|
<Label for="end">终止年</Label>
|
||||||
|
<NumberFieldContent>
|
||||||
|
<NumberFieldDecrement />
|
||||||
|
<NumberFieldInput />
|
||||||
|
<NumberFieldIncrement />
|
||||||
|
</NumberFieldContent>
|
||||||
|
</NumberField>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<div v-if="!isIllegal && imageUrl">
|
||||||
|
<img :src="imageUrl">
|
||||||
|
</div>
|
||||||
|
<div v-else h-40 flex="~ col items-center justify-center" text-xl>
|
||||||
|
<div v-if="isIllegal">
|
||||||
|
<div>Start year should be less than end year</div>
|
||||||
|
</div>
|
||||||
|
<div v-else>
|
||||||
|
<div>There is no data</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
|
||||||
|
</style>
|
||||||
46
src/pages/index.vue
Normal file
46
src/pages/index.vue
Normal file
@ -0,0 +1,46 @@
|
|||||||
|
<script setup lang="ts" generic="T extends any, O extends any">
|
||||||
|
defineOptions({
|
||||||
|
name: 'IndexPage',
|
||||||
|
})
|
||||||
|
|
||||||
|
const name = ref('')
|
||||||
|
|
||||||
|
const router = useRouter()
|
||||||
|
function go() {
|
||||||
|
if (name.value)
|
||||||
|
router.push(`/hi/${encodeURIComponent(name.value)}`)
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<div>
|
||||||
|
<div i-carbon-campsite inline-block text-4xl />
|
||||||
|
<p>
|
||||||
|
<a rel="noreferrer" href="https://github.com/antfu-collective/vitesse-lite" target="_blank">
|
||||||
|
Vitesse Lite
|
||||||
|
</a>
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
<em text-sm op75>Opinionated Vite Starter Template</em>
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<div py-4 />
|
||||||
|
|
||||||
|
<TheInput
|
||||||
|
v-model="name"
|
||||||
|
placeholder="What's your name?"
|
||||||
|
autocomplete="false"
|
||||||
|
@keydown.enter="go"
|
||||||
|
/>
|
||||||
|
|
||||||
|
<div>
|
||||||
|
<button
|
||||||
|
class="m-3 text-sm btn"
|
||||||
|
:disabled="!name"
|
||||||
|
@click="go"
|
||||||
|
>
|
||||||
|
Go
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
129
src/pages/radar/v1.vue
Normal file
129
src/pages/radar/v1.vue
Normal file
@ -0,0 +1,129 @@
|
|||||||
|
<script setup lang="ts">
|
||||||
|
import { API_BASE_URL } from '~/CONSTANT'
|
||||||
|
|
||||||
|
const selectedMode = ref('潮汐波')
|
||||||
|
const selectedStation = ref('武汉左岭镇站')
|
||||||
|
const selectedYear = ref('2017')
|
||||||
|
const selectedWindType = ref('uwind')
|
||||||
|
const selectedH = ref(90000)
|
||||||
|
const imageUrl = ref('')
|
||||||
|
|
||||||
|
const modes = [
|
||||||
|
'潮汐波',
|
||||||
|
'2日行星波',
|
||||||
|
'5日行星波',
|
||||||
|
'10日行星波',
|
||||||
|
'16日行星波',
|
||||||
|
]
|
||||||
|
|
||||||
|
const paths = ref([] as string[])
|
||||||
|
const stations = ref<Set<string>>(new Set())
|
||||||
|
const years = ref<Set<string>>(new Set())
|
||||||
|
|
||||||
|
const queryUrl = computed(() => {
|
||||||
|
const station = encodeURIComponent(selectedStation.value)
|
||||||
|
const year = encodeURIComponent(selectedYear.value)
|
||||||
|
const mode = encodeURIComponent(selectedMode.value)
|
||||||
|
const windType = encodeURIComponent(selectedWindType.value)
|
||||||
|
const query = `?station=${station}&year=${year}&model_name=${mode}&wind_type=${windType}&H=${selectedH.value}`
|
||||||
|
const path = `${API_BASE_URL}/radar/render/v1${query}`
|
||||||
|
return path
|
||||||
|
})
|
||||||
|
|
||||||
|
const { onFetchResponse, isFetching } = useFetch(queryUrl, { refetch: true })
|
||||||
|
|
||||||
|
onFetchResponse(async (resp) => {
|
||||||
|
const blob = await resp.blob()
|
||||||
|
const url = URL.createObjectURL(blob)
|
||||||
|
imageUrl.value = url
|
||||||
|
})
|
||||||
|
|
||||||
|
onMounted(async () => {
|
||||||
|
const resp = await fetch('http://localhost:5000/radar/metadata')
|
||||||
|
const data = await resp.json()
|
||||||
|
// use regex to extract the year from the path,
|
||||||
|
// ./radar/data\\武汉左岭镇站\\2017\\ZLT_MET01_DLL_L21_01D_20170316.txt
|
||||||
|
const station_pattern = /data\\(.*?)\\/
|
||||||
|
const year_pattern = /(\d{4})\\ZLT_/
|
||||||
|
const pairs = data.map((source_text: string) => {
|
||||||
|
const station = source_text.match(station_pattern)?.[1]
|
||||||
|
const year = source_text.match(year_pattern)?.[1]
|
||||||
|
return { station, year }
|
||||||
|
})
|
||||||
|
pairs.forEach(({ station, year }: {
|
||||||
|
station: string
|
||||||
|
year: string
|
||||||
|
}) => {
|
||||||
|
stations.value.add(station)
|
||||||
|
years.value.add(year)
|
||||||
|
})
|
||||||
|
|
||||||
|
paths.value = data
|
||||||
|
})
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<div flex="~ col items-center">
|
||||||
|
<div>
|
||||||
|
<div flex="~ row items-center gap-3" py-3>
|
||||||
|
{{ stations }}
|
||||||
|
{{ years }}
|
||||||
|
<Select v-model="selectedMode">
|
||||||
|
<SelectTrigger class="w-[180px]">
|
||||||
|
<SelectValue placeholder="Select a fruit" />
|
||||||
|
</SelectTrigger>
|
||||||
|
<SelectContent>
|
||||||
|
<SelectGroup>
|
||||||
|
<SelectLabel>计算模式</SelectLabel>
|
||||||
|
<SelectItem v-for="mode in modes" :key="mode" :value="mode">
|
||||||
|
{{ mode }}
|
||||||
|
</SelectItem>
|
||||||
|
</SelectGroup>
|
||||||
|
</SelectContent>
|
||||||
|
</Select>
|
||||||
|
<Select v-model="selectedStation">
|
||||||
|
<SelectTrigger class="w-[180px]">
|
||||||
|
<SelectValue placeholder="Select a fruit" />
|
||||||
|
</SelectTrigger>
|
||||||
|
<SelectContent>
|
||||||
|
<SelectGroup>
|
||||||
|
<SelectLabel>观测站</SelectLabel>
|
||||||
|
<SelectItem v-for="station in stations" :key="station" :value="station">
|
||||||
|
{{ station }}
|
||||||
|
</SelectItem>
|
||||||
|
</SelectGroup>
|
||||||
|
</SelectContent>
|
||||||
|
</Select>
|
||||||
|
<Select v-model="selectedYear">
|
||||||
|
<SelectTrigger class="w-[180px]">
|
||||||
|
<SelectValue placeholder="Select a fruit" />
|
||||||
|
</SelectTrigger>
|
||||||
|
<SelectContent>
|
||||||
|
<SelectGroup>
|
||||||
|
<SelectLabel>天</SelectLabel>
|
||||||
|
<SelectItem v-for="year in years" :key="year" :value="year">
|
||||||
|
{{ year }}
|
||||||
|
</SelectItem>
|
||||||
|
</SelectGroup>
|
||||||
|
</SelectContent>
|
||||||
|
</Select>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
{{ selectedMode }}
|
||||||
|
{{ selectedYear }}
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<div v-if="!isFetching && imageUrl !== ''">
|
||||||
|
<img :src="imageUrl">
|
||||||
|
</div>
|
||||||
|
<div v-else h-40 flex="~ col items-center justify-center" text-xl>
|
||||||
|
loading...
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<style lang="scss" scoped>
|
||||||
|
|
||||||
|
</style>
|
||||||
13
src/pages/radar/v2.vue
Normal file
13
src/pages/radar/v2.vue
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
<script setup lang="ts">
|
||||||
|
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<div>
|
||||||
|
a
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
|
||||||
|
</style>
|
||||||
11
src/styles/main.css
Executable file
11
src/styles/main.css
Executable file
@ -0,0 +1,11 @@
|
|||||||
|
html,
|
||||||
|
body,
|
||||||
|
#app {
|
||||||
|
height: 100%;
|
||||||
|
margin: 0;
|
||||||
|
padding: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
html.dark {
|
||||||
|
background: #121212;
|
||||||
|
}
|
||||||
3
test/__snapshots__/component.test.ts.snap
Normal file
3
test/__snapshots__/component.test.ts.snap
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html
|
||||||
|
|
||||||
|
exports[`component of TheCounter.vue > should render 1`] = `"<div>10 <button class="inc"> + </button><button class="dec"> - </button></div>"`;
|
||||||
7
test/basic.test.ts
Normal file
7
test/basic.test.ts
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
import { describe, expect, it } from 'vitest'
|
||||||
|
|
||||||
|
describe('hi', () => {
|
||||||
|
it('should works', () => {
|
||||||
|
expect(1 + 1).toEqual(2)
|
||||||
|
})
|
||||||
|
})
|
||||||
22
test/component.test.ts
Normal file
22
test/component.test.ts
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
import { mount } from '@vue/test-utils'
|
||||||
|
import { describe, expect, it } from 'vitest'
|
||||||
|
import TheCounter from '../src/components/TheCounter.vue'
|
||||||
|
|
||||||
|
describe('component of TheCounter.vue', () => {
|
||||||
|
it('should render', () => {
|
||||||
|
const wrapper = mount(TheCounter, { props: { initial: 10 } })
|
||||||
|
expect(wrapper.text()).toContain('10')
|
||||||
|
expect(wrapper.html()).toMatchSnapshot()
|
||||||
|
})
|
||||||
|
|
||||||
|
it('should be interactive', async () => {
|
||||||
|
const wrapper = mount(TheCounter, { props: { initial: 0 } })
|
||||||
|
expect(wrapper.text()).toContain('0')
|
||||||
|
|
||||||
|
expect(wrapper.find('.inc').exists()).toBe(true)
|
||||||
|
|
||||||
|
await wrapper.get('button').trigger('click')
|
||||||
|
|
||||||
|
expect(wrapper.text()).toContain('1')
|
||||||
|
})
|
||||||
|
})
|
||||||
31
tsconfig.json
Normal file
31
tsconfig.json
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
{
|
||||||
|
"compilerOptions": {
|
||||||
|
"target": "es2016",
|
||||||
|
"jsx": "preserve",
|
||||||
|
"lib": ["DOM", "ESNext"],
|
||||||
|
"baseUrl": ".",
|
||||||
|
"module": "ESNext",
|
||||||
|
"moduleResolution": "bundler",
|
||||||
|
"paths": {
|
||||||
|
"~/*": ["src/*"]
|
||||||
|
},
|
||||||
|
"resolveJsonModule": true,
|
||||||
|
"types": [
|
||||||
|
"vite/client",
|
||||||
|
"unplugin-vue-macros/macros-global",
|
||||||
|
"unplugin-vue-router/client"
|
||||||
|
],
|
||||||
|
"allowJs": true,
|
||||||
|
"strict": true,
|
||||||
|
"strictNullChecks": true,
|
||||||
|
"noUnusedLocals": true,
|
||||||
|
"esModuleInterop": true,
|
||||||
|
"forceConsistentCasingInFileNames": true,
|
||||||
|
"skipLibCheck": true
|
||||||
|
},
|
||||||
|
"exclude": [
|
||||||
|
"dist",
|
||||||
|
"node_modules",
|
||||||
|
"eslint.config.js"
|
||||||
|
]
|
||||||
|
}
|
||||||
28
typed-router.d.ts
vendored
Normal file
28
typed-router.d.ts
vendored
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
/* eslint-disable */
|
||||||
|
/* prettier-ignore */
|
||||||
|
// @ts-nocheck
|
||||||
|
// Generated by unplugin-vue-router. ‼️ DO NOT MODIFY THIS FILE ‼️
|
||||||
|
// It's recommended to commit this file.
|
||||||
|
// Make sure to add this file to your tsconfig.json file as an "includes" or "files" entry.
|
||||||
|
|
||||||
|
declare module 'vue-router/auto-routes' {
|
||||||
|
import type {
|
||||||
|
RouteRecordInfo,
|
||||||
|
ParamValue,
|
||||||
|
ParamValueOneOrMore,
|
||||||
|
ParamValueZeroOrMore,
|
||||||
|
ParamValueZeroOrOne,
|
||||||
|
} from 'vue-router'
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Route name map generated by unplugin-vue-router
|
||||||
|
*/
|
||||||
|
export interface RouteNamedMap {
|
||||||
|
'/': RouteRecordInfo<'/', '/', Record<never, never>, Record<never, never>>,
|
||||||
|
'/[...all]': RouteRecordInfo<'/[...all]', '/:all(.*)', { all: ParamValue<true> }, { all: ParamValue<false> }>,
|
||||||
|
'/balloon/single': RouteRecordInfo<'/balloon/single', '/balloon/single', Record<never, never>, Record<never, never>>,
|
||||||
|
'/balloon/year': RouteRecordInfo<'/balloon/year', '/balloon/year', Record<never, never>, Record<never, never>>,
|
||||||
|
'/radar/v1': RouteRecordInfo<'/radar/v1', '/radar/v1', Record<never, never>, Record<never, never>>,
|
||||||
|
'/radar/v2': RouteRecordInfo<'/radar/v2', '/radar/v2', Record<never, never>, Record<never, never>>,
|
||||||
|
}
|
||||||
|
}
|
||||||
46
uno.config.ts
Normal file
46
uno.config.ts
Normal file
@ -0,0 +1,46 @@
|
|||||||
|
import {
|
||||||
|
defineConfig,
|
||||||
|
presetAttributify,
|
||||||
|
presetIcons,
|
||||||
|
presetUno,
|
||||||
|
presetWebFonts,
|
||||||
|
} from 'unocss'
|
||||||
|
import presetAnimations from 'unocss-preset-animations'
|
||||||
|
import { presetShadcn } from 'unocss-preset-shadcn'
|
||||||
|
|
||||||
|
export default defineConfig({
|
||||||
|
shortcuts: [
|
||||||
|
['btn', 'px-4 py-1 rounded inline-block bg-teal-600 text-white cursor-pointer hover:bg-teal-700 disabled:cursor-default disabled:bg-gray-600 disabled:opacity-50'],
|
||||||
|
['icon-btn', 'text-[0.9em] inline-block cursor-pointer select-none opacity-75 transition duration-200 ease-in-out hover:opacity-100 hover:text-teal-600 !outline-none'],
|
||||||
|
],
|
||||||
|
presets: [
|
||||||
|
presetUno(),
|
||||||
|
presetAttributify(),
|
||||||
|
presetIcons({
|
||||||
|
scale: 1.2,
|
||||||
|
warn: true,
|
||||||
|
}),
|
||||||
|
presetWebFonts({
|
||||||
|
fonts: {
|
||||||
|
sans: 'DM Sans',
|
||||||
|
serif: 'DM Serif Display',
|
||||||
|
mono: 'DM Mono',
|
||||||
|
},
|
||||||
|
}),
|
||||||
|
presetAnimations(),
|
||||||
|
presetShadcn({
|
||||||
|
// With default setting for SolidUI, you need to set the darkSelector option.
|
||||||
|
darkSelector: '[data-kb-theme="dark"]',
|
||||||
|
}),
|
||||||
|
],
|
||||||
|
content: {
|
||||||
|
pipeline: {
|
||||||
|
include: [
|
||||||
|
// the default
|
||||||
|
/\.(vue|svelte|[jt]sx|mdx?|astro|elm|php|phtml|html)($|\?)/,
|
||||||
|
// include js/ts files
|
||||||
|
'(components|src)/**/*.{js,ts}',
|
||||||
|
],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
})
|
||||||
68
vite.config.ts
Normal file
68
vite.config.ts
Normal file
@ -0,0 +1,68 @@
|
|||||||
|
/// <reference types="vitest" />
|
||||||
|
|
||||||
|
import path from 'node:path'
|
||||||
|
import Vue from '@vitejs/plugin-vue'
|
||||||
|
import UnoCSS from 'unocss/vite'
|
||||||
|
import AutoImport from 'unplugin-auto-import/vite'
|
||||||
|
import Components from 'unplugin-vue-components/vite'
|
||||||
|
import VueMacros from 'unplugin-vue-macros/vite'
|
||||||
|
import { VueRouterAutoImports } from 'unplugin-vue-router'
|
||||||
|
import VueRouter from 'unplugin-vue-router/vite'
|
||||||
|
import { defineConfig } from 'vite'
|
||||||
|
|
||||||
|
export default defineConfig({
|
||||||
|
resolve: {
|
||||||
|
alias: {
|
||||||
|
'~/': `${path.resolve(__dirname, 'src')}/`,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
plugins: [
|
||||||
|
VueMacros({
|
||||||
|
defineOptions: false,
|
||||||
|
defineModels: false,
|
||||||
|
plugins: {
|
||||||
|
vue: Vue({
|
||||||
|
script: {
|
||||||
|
propsDestructure: true,
|
||||||
|
defineModel: true,
|
||||||
|
},
|
||||||
|
}),
|
||||||
|
},
|
||||||
|
}),
|
||||||
|
|
||||||
|
// https://github.com/posva/unplugin-vue-router
|
||||||
|
VueRouter(),
|
||||||
|
|
||||||
|
// https://github.com/antfu/unplugin-auto-import
|
||||||
|
AutoImport({
|
||||||
|
imports: [
|
||||||
|
'vue',
|
||||||
|
'@vueuse/core',
|
||||||
|
VueRouterAutoImports,
|
||||||
|
{
|
||||||
|
// add any other imports you were relying on
|
||||||
|
'vue-router/auto': ['useLink'],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
dts: true,
|
||||||
|
dirs: [
|
||||||
|
'./src/composables',
|
||||||
|
],
|
||||||
|
vueTemplate: true,
|
||||||
|
}),
|
||||||
|
|
||||||
|
// https://github.com/antfu/vite-plugin-components
|
||||||
|
Components({
|
||||||
|
dts: true,
|
||||||
|
}),
|
||||||
|
|
||||||
|
// https://github.com/antfu/unocss
|
||||||
|
// see uno.config.ts for config
|
||||||
|
UnoCSS(),
|
||||||
|
],
|
||||||
|
|
||||||
|
// https://github.com/vitest-dev/vitest
|
||||||
|
test: {
|
||||||
|
environment: 'jsdom',
|
||||||
|
},
|
||||||
|
})
|
||||||
Loading…
x
Reference in New Issue
Block a user