Merge branch 'vercel' into dev
This commit is contained in:
commit
2a172494e7
22 changed files with 3461 additions and 2436 deletions
50
.vscode/settings.json
vendored
50
.vscode/settings.json
vendored
|
|
@ -1,4 +1,50 @@
|
||||||
{
|
{
|
||||||
// Enable ESlint flat config support
|
// Disable the default formatter, use eslint instead
|
||||||
"eslint.useFlatConfig": true
|
"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", "fixable": true },
|
||||||
|
{ "rule": "format/*", "severity": "off", "fixable": true },
|
||||||
|
{ "rule": "*-indent", "severity": "off", "fixable": true },
|
||||||
|
{ "rule": "*-spacing", "severity": "off", "fixable": true },
|
||||||
|
{ "rule": "*-spaces", "severity": "off", "fixable": true },
|
||||||
|
{ "rule": "*-order", "severity": "off", "fixable": true },
|
||||||
|
{ "rule": "*-dangle", "severity": "off", "fixable": true },
|
||||||
|
{ "rule": "*-newline", "severity": "off", "fixable": true },
|
||||||
|
{ "rule": "*quotes", "severity": "off", "fixable": true },
|
||||||
|
{ "rule": "*semi", "severity": "off", "fixable": true }
|
||||||
|
],
|
||||||
|
|
||||||
|
// Enable eslint for all supported languages
|
||||||
|
"eslint.validate": [
|
||||||
|
"javascript",
|
||||||
|
"javascriptreact",
|
||||||
|
"typescript",
|
||||||
|
"typescriptreact",
|
||||||
|
"vue",
|
||||||
|
"html",
|
||||||
|
"markdown",
|
||||||
|
"json",
|
||||||
|
"jsonc",
|
||||||
|
"yaml",
|
||||||
|
"toml",
|
||||||
|
"xml",
|
||||||
|
"gql",
|
||||||
|
"graphql",
|
||||||
|
"astro",
|
||||||
|
"svelte",
|
||||||
|
"css",
|
||||||
|
"less",
|
||||||
|
"scss",
|
||||||
|
"pcss",
|
||||||
|
"postcss"
|
||||||
|
]
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
<script setup>
|
<script setup>
|
||||||
import { Flame, MousePointerClick, Users } from 'lucide-vue-next'
|
|
||||||
import NumberFlow from '@number-flow/vue'
|
import NumberFlow from '@number-flow/vue'
|
||||||
|
import { Flame, MousePointerClick, Users } from 'lucide-vue-next'
|
||||||
|
|
||||||
const defaultData = Object.freeze({
|
const defaultData = Object.freeze({
|
||||||
visits: 0,
|
visits: 0,
|
||||||
|
|
|
||||||
|
|
@ -1,11 +1,11 @@
|
||||||
<script setup>
|
<script setup>
|
||||||
import { z } from 'zod'
|
|
||||||
import { useForm } from 'vee-validate'
|
|
||||||
import { toTypedSchema } from '@vee-validate/zod'
|
|
||||||
import { Shuffle, Sparkles } from 'lucide-vue-next'
|
|
||||||
import { toast } from 'vue-sonner'
|
|
||||||
import { DependencyType } from '@/components/ui/auto-form/interface'
|
import { DependencyType } from '@/components/ui/auto-form/interface'
|
||||||
import { LinkSchema, nanoid } from '@/schemas/link'
|
import { LinkSchema, nanoid } from '@/schemas/link'
|
||||||
|
import { toTypedSchema } from '@vee-validate/zod'
|
||||||
|
import { Shuffle, Sparkles } from 'lucide-vue-next'
|
||||||
|
import { useForm } from 'vee-validate'
|
||||||
|
import { toast } from 'vue-sonner'
|
||||||
|
import { z } from 'zod'
|
||||||
|
|
||||||
const props = defineProps({
|
const props = defineProps({
|
||||||
link: {
|
link: {
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
<script setup>
|
<script setup>
|
||||||
import { Loader } from 'lucide-vue-next'
|
|
||||||
import { useInfiniteScroll } from '@vueuse/core'
|
import { useInfiniteScroll } from '@vueuse/core'
|
||||||
|
import { Loader } from 'lucide-vue-next'
|
||||||
|
|
||||||
const links = ref([])
|
const links = ref([])
|
||||||
const limit = 24
|
const limit = 24
|
||||||
|
|
|
||||||
|
|
@ -1,8 +1,8 @@
|
||||||
<script setup>
|
<script setup>
|
||||||
import { CalendarPlus2, Copy, CopyCheck, Eraser, Hourglass, Link as LinkIcon, QrCode, SquareChevronDown, SquarePen } from 'lucide-vue-next'
|
|
||||||
import { useClipboard } from '@vueuse/core'
|
import { useClipboard } from '@vueuse/core'
|
||||||
import { toast } from 'vue-sonner'
|
import { CalendarPlus2, Copy, CopyCheck, Eraser, Hourglass, Link as LinkIcon, QrCode, SquareChevronDown, SquarePen } from 'lucide-vue-next'
|
||||||
import { parseURL } from 'ufo'
|
import { parseURL } from 'ufo'
|
||||||
|
import { toast } from 'vue-sonner'
|
||||||
import QRCode from './QRCode.vue'
|
import QRCode from './QRCode.vue'
|
||||||
|
|
||||||
const props = defineProps({
|
const props = defineProps({
|
||||||
|
|
|
||||||
|
|
@ -63,7 +63,7 @@ onMounted(() => {
|
||||||
</Button>
|
</Button>
|
||||||
<Dialog :open="isOpen" @update:open="isOpen = !isOpen">
|
<Dialog :open="isOpen" @update:open="isOpen = !isOpen">
|
||||||
<DialogContent class="overflow-hidden p-0 shadow-lg">
|
<DialogContent class="overflow-hidden p-0 shadow-lg">
|
||||||
<Command v-model:searchTerm="searchTerm" v-model="selectedLink" class="[&_[cmdk-group-heading]]:px-2 [&_[cmdk-group-heading]]:font-medium [&_[cmdk-group-heading]]:text-muted-foreground [&_[cmdk-group]:not([hidden])_~[cmdk-group]]:pt-0 [&_[cmdk-group]]:px-2 [&_[cmdk-input-wrapper]_svg]:h-5 [&_[cmdk-input-wrapper]_svg]:w-5 [&_[cmdk-input]]:h-12 [&_[cmdk-item]]:px-2 [&_[cmdk-item]]:py-3 [&_[cmdk-item]_svg]:h-5 [&_[cmdk-item]_svg]:w-5">
|
<Command v-model:search-term="searchTerm" v-model="selectedLink" class="[&_[cmdk-group-heading]]:px-2 [&_[cmdk-group-heading]]:font-medium [&_[cmdk-group-heading]]:text-muted-foreground [&_[cmdk-group]:not([hidden])_~[cmdk-group]]:pt-0 [&_[cmdk-group]]:px-2 [&_[cmdk-input-wrapper]_svg]:h-5 [&_[cmdk-input-wrapper]_svg]:w-5 [&_[cmdk-input]]:h-12 [&_[cmdk-item]]:px-2 [&_[cmdk-item]]:py-3 [&_[cmdk-item]_svg]:h-5 [&_[cmdk-item]_svg]:w-5">
|
||||||
<CommandInput placeholder="Type to search..." />
|
<CommandInput placeholder="Type to search..." />
|
||||||
<CommandList>
|
<CommandList>
|
||||||
<CommandEmpty v-if="searchTerm">
|
<CommandEmpty v-if="searchTerm">
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
<script setup>
|
<script setup>
|
||||||
import { VisSingleContainer, VisTopoJSONMap, VisTopoJSONMapSelectors } from '@unovis/vue'
|
|
||||||
import { ChartTooltip } from '@/components/ui/chart'
|
import { ChartTooltip } from '@/components/ui/chart'
|
||||||
|
import { VisSingleContainer, VisTopoJSONMap, VisTopoJSONMapSelectors } from '@unovis/vue'
|
||||||
|
|
||||||
const id = inject('id')
|
const id = inject('id')
|
||||||
const startAt = inject('startAt')
|
const startAt = inject('startAt')
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,13 @@
|
||||||
<script setup>
|
<script setup>
|
||||||
|
import {
|
||||||
|
Globe,
|
||||||
|
Laptop,
|
||||||
|
MonitorCheck,
|
||||||
|
Smartphone,
|
||||||
|
Tablet,
|
||||||
|
Terminal,
|
||||||
|
} from 'lucide-vue-next'
|
||||||
|
|
||||||
// https://vue3-simple-icons.wyatt-herkamp.dev/
|
// https://vue3-simple-icons.wyatt-herkamp.dev/
|
||||||
import {
|
import {
|
||||||
AndroidIcon,
|
AndroidIcon,
|
||||||
|
|
@ -20,23 +29,14 @@ import {
|
||||||
SamsungIcon,
|
SamsungIcon,
|
||||||
UbuntuIcon,
|
UbuntuIcon,
|
||||||
VivoIcon,
|
VivoIcon,
|
||||||
WeChatIcon,
|
|
||||||
WearOsIcon,
|
WearOsIcon,
|
||||||
|
WeChatIcon,
|
||||||
|
XiaomiIcon,
|
||||||
// WindowsIcon,
|
// WindowsIcon,
|
||||||
XIcon,
|
XIcon,
|
||||||
XiaomiIcon,
|
|
||||||
YandexCloudIcon,
|
YandexCloudIcon,
|
||||||
} from 'vue3-simple-icons'
|
} from 'vue3-simple-icons'
|
||||||
|
|
||||||
import {
|
|
||||||
Globe,
|
|
||||||
Laptop,
|
|
||||||
MonitorCheck,
|
|
||||||
Smartphone,
|
|
||||||
Tablet,
|
|
||||||
Terminal,
|
|
||||||
} from 'lucide-vue-next'
|
|
||||||
|
|
||||||
defineProps({
|
defineProps({
|
||||||
name: {
|
name: {
|
||||||
type: String,
|
type: String,
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
<script setup>
|
<script setup>
|
||||||
|
import heroImg from '@/assets/images/hero.svg?raw'
|
||||||
import { AreaChart } from 'lucide-vue-next'
|
import { AreaChart } from 'lucide-vue-next'
|
||||||
import { GitHubIcon } from 'vue3-simple-icons'
|
import { GitHubIcon } from 'vue3-simple-icons'
|
||||||
import heroImg from '@/assets/images/hero.svg?raw'
|
|
||||||
|
|
||||||
const { title, description, github } = useAppConfig()
|
const { title, description, github } = useAppConfig()
|
||||||
</script>
|
</script>
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
<script setup>
|
<script setup>
|
||||||
import { XIcon } from 'vue3-simple-icons'
|
|
||||||
import { ArrowRight } from 'lucide-vue-next'
|
import { ArrowRight } from 'lucide-vue-next'
|
||||||
|
import { XIcon } from 'vue3-simple-icons'
|
||||||
|
|
||||||
const { twitter } = useAppConfig()
|
const { twitter } = useAppConfig()
|
||||||
</script>
|
</script>
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
<script setup>
|
<script setup>
|
||||||
import { AlertCircle } from 'lucide-vue-next'
|
import { AlertCircle } from 'lucide-vue-next'
|
||||||
import { z } from 'zod'
|
|
||||||
import { toast } from 'vue-sonner'
|
import { toast } from 'vue-sonner'
|
||||||
|
import { z } from 'zod'
|
||||||
|
|
||||||
const LoginSchema = z.object({
|
const LoginSchema = z.object({
|
||||||
token: z.string().describe('SiteToken'),
|
token: z.string().describe('SiteToken'),
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,5 @@
|
||||||
// https://nuxt.com/docs/api/configuration/nuxt-config
|
// https://nuxt.com/docs/api/configuration/nuxt-config
|
||||||
export default defineNuxtConfig({
|
export default defineNuxtConfig({
|
||||||
devtools: { enabled: true },
|
|
||||||
|
|
||||||
modules: [
|
modules: [
|
||||||
'@nuxthub/core',
|
'@nuxthub/core',
|
||||||
|
|
@ -9,46 +8,12 @@ export default defineNuxtConfig({
|
||||||
'@nuxtjs/tailwindcss',
|
'@nuxtjs/tailwindcss',
|
||||||
'@nuxtjs/color-mode',
|
'@nuxtjs/color-mode',
|
||||||
],
|
],
|
||||||
|
devtools: { enabled: true },
|
||||||
|
|
||||||
colorMode: {
|
colorMode: {
|
||||||
classSuffix: '',
|
classSuffix: '',
|
||||||
},
|
},
|
||||||
|
|
||||||
routeRules: {
|
|
||||||
'/': {
|
|
||||||
prerender: true,
|
|
||||||
},
|
|
||||||
'/dashboard/**': {
|
|
||||||
ssr: false,
|
|
||||||
},
|
|
||||||
'/dashboard': {
|
|
||||||
redirect: '/dashboard/links',
|
|
||||||
},
|
|
||||||
},
|
|
||||||
|
|
||||||
hub: {
|
|
||||||
ai: true,
|
|
||||||
analytics: true,
|
|
||||||
blob: false,
|
|
||||||
cache: false,
|
|
||||||
database: false,
|
|
||||||
kv: true,
|
|
||||||
},
|
|
||||||
|
|
||||||
eslint: {
|
|
||||||
config: {
|
|
||||||
stylistic: true,
|
|
||||||
standalone: false,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
|
|
||||||
nitro: {
|
|
||||||
experimental: {
|
|
||||||
// Enable Server API documentation within NuxtHub
|
|
||||||
openAPI: true,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
|
|
||||||
runtimeConfig: {
|
runtimeConfig: {
|
||||||
siteToken: 'SinkCool',
|
siteToken: 'SinkCool',
|
||||||
redirectStatusCode: '301',
|
redirectStatusCode: '301',
|
||||||
|
|
@ -67,5 +32,40 @@ export default defineNuxtConfig({
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|
||||||
|
routeRules: {
|
||||||
|
'/': {
|
||||||
|
prerender: true,
|
||||||
|
},
|
||||||
|
'/dashboard/**': {
|
||||||
|
ssr: false,
|
||||||
|
},
|
||||||
|
'/dashboard': {
|
||||||
|
redirect: '/dashboard/links',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
|
||||||
compatibilityDate: '2024-07-08',
|
compatibilityDate: '2024-07-08',
|
||||||
|
|
||||||
|
nitro: {
|
||||||
|
experimental: {
|
||||||
|
// Enable Server API documentation within NuxtHub
|
||||||
|
openAPI: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
|
||||||
|
hub: {
|
||||||
|
ai: true,
|
||||||
|
analytics: true,
|
||||||
|
blob: false,
|
||||||
|
cache: false,
|
||||||
|
database: false,
|
||||||
|
kv: true,
|
||||||
|
},
|
||||||
|
|
||||||
|
eslint: {
|
||||||
|
config: {
|
||||||
|
stylistic: true,
|
||||||
|
standalone: false,
|
||||||
|
},
|
||||||
|
},
|
||||||
})
|
})
|
||||||
|
|
|
||||||
52
package.json
52
package.json
|
|
@ -3,7 +3,7 @@
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"version": "0.1.7",
|
"version": "0.1.7",
|
||||||
"private": true,
|
"private": true,
|
||||||
"packageManager": "pnpm@9.7.1",
|
"packageManager": "pnpm@9.15.1",
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=20.11"
|
"node": ">=20.11"
|
||||||
},
|
},
|
||||||
|
|
@ -22,44 +22,44 @@
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@number-flow/vue": "^0.3.3",
|
"@number-flow/vue": "^0.3.3",
|
||||||
"@unovis/ts": "^1.4.4",
|
"@unovis/ts": "^1.5.0",
|
||||||
"@unovis/vue": "^1.4.4",
|
"@unovis/vue": "^1.5.0",
|
||||||
"@vee-validate/zod": "^4.13.2",
|
"@vee-validate/zod": "^4.15.0",
|
||||||
"@vueuse/core": "^11.0.0",
|
"@vueuse/core": "^12.2.0",
|
||||||
"fuse.js": "^7.0.0",
|
"fuse.js": "^7.0.0",
|
||||||
"intl-parse-accept-language": "^1.0.0",
|
"intl-parse-accept-language": "^1.0.0",
|
||||||
"lucide-vue-next": "^0.428.0",
|
"lucide-vue-next": "^0.469.0",
|
||||||
"mysql-bricks": "^1.1.2",
|
"mysql-bricks": "^1.1.2",
|
||||||
"nanoid": "^5.0.7",
|
"nanoid": "^5.0.9",
|
||||||
"pluralize": "^8.0.0",
|
"pluralize": "^8.0.0",
|
||||||
"qr-code-styling": "1.6.0-rc.1",
|
"qr-code-styling": "1.6.0-rc.1",
|
||||||
"radix-vue": "^1.9.4",
|
"radix-vue": "^1.9.11",
|
||||||
"ua-parser-js": "next",
|
"ua-parser-js": "next",
|
||||||
"vee-validate": "^4.13.2",
|
"vee-validate": "^4.15.0",
|
||||||
"virtua": "^0.33.7",
|
"virtua": "^0.39.2",
|
||||||
"vue-sonner": "^1.1.4",
|
"vue-sonner": "^1.3.0",
|
||||||
"vue3-simple-icons": "^13.2.0",
|
"vue3-simple-icons": "^13.2.0",
|
||||||
"zod": "^3.23.8"
|
"zod": "^3.24.1"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@antfu/eslint-config": "^2.26.0",
|
"@antfu/eslint-config": "^3.12.1",
|
||||||
"@nuxt/eslint": "^0.5.0",
|
"@nuxt/eslint": "^0.7.4",
|
||||||
"@nuxt/eslint-config": "^0.5.0",
|
"@nuxt/eslint-config": "^0.7.4",
|
||||||
"@nuxthub/core": "^0.7.3",
|
"@nuxthub/core": "^0.8.10",
|
||||||
"@nuxtjs/color-mode": "^3.4.4",
|
"@nuxtjs/color-mode": "^3.5.2",
|
||||||
"@nuxtjs/tailwindcss": "^6.12.1",
|
"@nuxtjs/tailwindcss": "^6.12.2",
|
||||||
"@vueuse/integrations": "^12.2.0",
|
"@vueuse/integrations": "^12.2.0",
|
||||||
"class-variance-authority": "^0.7.0",
|
"class-variance-authority": "^0.7.1",
|
||||||
"clsx": "^2.1.1",
|
"clsx": "^2.1.1",
|
||||||
"eslint": "^9.9.0",
|
"eslint": "^9.17.0",
|
||||||
"lint-staged": "^15.2.9",
|
"lint-staged": "^15.2.11",
|
||||||
"nuxt": "^3.12.4",
|
"nuxt": "^3.14.1592",
|
||||||
"shadcn-nuxt": "^0.10.4",
|
"shadcn-nuxt": "^0.11.3",
|
||||||
"simple-git-hooks": "^2.11.1",
|
"simple-git-hooks": "^2.11.1",
|
||||||
"tailwind-merge": "^2.5.2",
|
"tailwind-merge": "^2.6.0",
|
||||||
"tailwindcss-animate": "^1.0.7",
|
"tailwindcss-animate": "^1.0.7",
|
||||||
"vue-tsc": "^2.0.29",
|
"vue-tsc": "^2.2.0",
|
||||||
"wrangler": "^3.72.0"
|
"wrangler": "^3.99.0"
|
||||||
},
|
},
|
||||||
"simple-git-hooks": {
|
"simple-git-hooks": {
|
||||||
"pre-commit": "npm run lint-staged"
|
"pre-commit": "npm run lint-staged"
|
||||||
|
|
|
||||||
5651
pnpm-lock.yaml
5651
pnpm-lock.yaml
File diff suppressed because it is too large
Load diff
|
|
@ -1,5 +1,5 @@
|
||||||
import { z } from 'zod'
|
|
||||||
import { customAlphabet } from 'nanoid'
|
import { customAlphabet } from 'nanoid'
|
||||||
|
import { z } from 'zod'
|
||||||
|
|
||||||
const { slugRegex } = useAppConfig()
|
const { slugRegex } = useAppConfig()
|
||||||
const { caseSensitive } = useRuntimeConfig()
|
const { caseSensitive } = useRuntimeConfig()
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
import { z } from 'zod'
|
|
||||||
import { destr } from 'destr'
|
import { destr } from 'destr'
|
||||||
|
import { z } from 'zod'
|
||||||
|
|
||||||
export default eventHandler(async (event) => {
|
export default eventHandler(async (event) => {
|
||||||
const url = (await getValidatedQuery(event, z.object({
|
const url = (await getValidatedQuery(event, z.object({
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
import type { H3Event } from 'h3'
|
import type { H3Event } from 'h3'
|
||||||
import { z } from 'zod'
|
|
||||||
import { QuerySchema } from '@/schemas/query'
|
import { QuerySchema } from '@/schemas/query'
|
||||||
|
import { z } from 'zod'
|
||||||
|
|
||||||
const { select } = SqlBricks
|
const { select } = SqlBricks
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
import type { H3Event } from 'h3'
|
import type { H3Event } from 'h3'
|
||||||
import { z } from 'zod'
|
|
||||||
import { QuerySchema } from '@/schemas/query'
|
import { QuerySchema } from '@/schemas/query'
|
||||||
|
import { z } from 'zod'
|
||||||
|
|
||||||
const { select } = SqlBricks
|
const { select } = SqlBricks
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
|
import type { LinkSchema } from '@/schemas/link'
|
||||||
import type { z } from 'zod'
|
import type { z } from 'zod'
|
||||||
import { parsePath, withQuery } from 'ufo'
|
import { parsePath, withQuery } from 'ufo'
|
||||||
import type { LinkSchema } from '@/schemas/link'
|
|
||||||
|
|
||||||
export default eventHandler(async (event) => {
|
export default eventHandler(async (event) => {
|
||||||
const { pathname: slug } = parsePath(event.path.replace(/^\/|\/$/g, '')) // remove leading and trailing slashes
|
const { pathname: slug } = parsePath(event.path.replace(/^\/|\/$/g, '')) // remove leading and trailing slashes
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,6 @@
|
||||||
import type { H3Event } from 'h3'
|
import type { H3Event } from 'h3'
|
||||||
import { parseURL } from 'ufo'
|
import { getFlag } from '@/utils/flag'
|
||||||
|
import { parseAcceptLanguage } from 'intl-parse-accept-language'
|
||||||
import { UAParser } from 'ua-parser-js'
|
import { UAParser } from 'ua-parser-js'
|
||||||
import {
|
import {
|
||||||
CLIs,
|
CLIs,
|
||||||
|
|
@ -11,8 +12,7 @@ import {
|
||||||
MediaPlayers,
|
MediaPlayers,
|
||||||
Modules,
|
Modules,
|
||||||
} from 'ua-parser-js/extensions'
|
} from 'ua-parser-js/extensions'
|
||||||
import { parseAcceptLanguage } from 'intl-parse-accept-language'
|
import { parseURL } from 'ufo'
|
||||||
import { getFlag } from '@/utils/flag'
|
|
||||||
|
|
||||||
function toBlobNumber(blob: string) {
|
function toBlobNumber(blob: string) {
|
||||||
return +blob.replace(/\D/g, '')
|
return +blob.replace(/\D/g, '')
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
import type { z } from 'zod'
|
|
||||||
import type { SelectStatement } from 'sql-bricks'
|
|
||||||
import type { FilterSchema, QuerySchema } from '@/schemas/query'
|
import type { FilterSchema, QuerySchema } from '@/schemas/query'
|
||||||
|
import type { SelectStatement } from 'sql-bricks'
|
||||||
|
import type { z } from 'zod'
|
||||||
|
|
||||||
export type Query = z.infer<typeof QuerySchema>
|
export type Query = z.infer<typeof QuerySchema>
|
||||||
export type Filter = z.infer<typeof FilterSchema>
|
export type Filter = z.infer<typeof FilterSchema>
|
||||||
|
|
|
||||||
|
|
@ -1,3 +1,3 @@
|
||||||
export function colorGradation(count: number) {
|
export function colorGradation(count: number) {
|
||||||
return Array.from(Array(count).keys()).map(i => `hsl(var(--vis-secondary-color) / ${1 - (1 / count) * i})`)
|
return Array.from({ length: count }, (_, i) => `hsl(var(--vis-secondary-color) / ${1 - (1 / count) * i})`)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue