chore: init

This commit is contained in:
Anthony Fu committed 2020-08-10 02:43:04 +08:00
commit 76fb0845ec
24 files changed
+4433

No files matched your search

+4
View File
@@ -0,0 +1,4 @@
node_modules
.DS_Store
dist
*.local
+22
View File
@@ -0,0 +1,22 @@
MIT License
// as this is a project template, free feel to it change to your name.
Copyright (c) 2020 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.
+56
View File
@@ -0,0 +1,56 @@
<h1 align='center'><samp>Vitesse</samp></h1>
<p align='center'>
<samp>Opinionated <a href="https://github.com/vitejs/vite">Vite</a> Starter Template</samp>
</p>
<p align='center'>
<sup><em>Mocking up web app with <b>⚡️vitesse</b></em></sup>
</p>
<br>
<p align='center'>
<a href="https://vitesse.netilfy.app">Live Example</a>
</p>
<br>
## Pre-packed
### UI Frameworks
- [Tailwind CSS](https://tailwindcss.com/)
- [tailwindcss-dark-mode](https://github.com/ChanceArthur/tailwindcss-dark-mode)
- [Iconify](https://iconify.design) - use icons from your favorite sets. [🔍Icônes](https://icones.netlify.app/)
<!-- - [variantwind](https://github.com/sibbngheid/variantwind) -->
### Router
- [Vue Router](https://github.com/vuejs/vue-router)
- [Voie](https://github.com/vamplate/vite-plugin-voie) - file based routing
### Utils
- [VueUse](https://github.com/antfu/vueuse)
### Misc
- Use Composition API with [`<script setup>` SFC](https://github.com/vuejs/rfcs/blob/sfc-improvements/active-rfcs/0000-sfc-script-setup.md)
### Dev tools
- [Typescript](https://www.typescriptlang.org/)
- [pnpm](https://pnpm.js.org/)
- [Netlify](https://www.netlify.com/)
- [ESLint](https://eslint.org/) with [@antfu/eslint-config-vue](https://github.com/antfu/eslint-config)
## Use It!
```bash
git clone https://github.com/antfu/vite-starter && cd vite-starter && rm -rf .git && git init && pnpm i
```
## Why
I have created several Vite apps recently. Setting the configs up is kinda the bottleneck for me to make the idea simply comes true in very a short time. So I made this starter template for myself to create apps more easily, along with some good practices that I have learned during making those apps. It's strongly opinionated, but feel free to tweak it or even maintains your own forks.
+14
View File
@@ -0,0 +1,14 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<link rel="icon" href="/favicon.svg" />
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Vitesse</title>
<script src="https://cdn.jsdelivr.net/npm/@iconify/iconify@1.0.7/dist/iconify.min.js"></script>
</head>
<body>
<div id="app"></div>
<script type="module" src="/src/main.ts"></script>
</body>
</html>
Executable
+12
View File
@@ -0,0 +1,12 @@
[build.environment]
# to disable npm auto install. see https://community.netlify.com/t/using-pnpm-and-pnpm-workspaces/2759
NPM_FLAGS="--prefix=/"
[build]
publish = "dist"
command = "npx pnpm i && npm run build"
[[redirects]]
from = "/*"
to = "/index.html"
status = 200
+34
View File
@@ -0,0 +1,34 @@
{
"name": "@vitesse/template",
"version": "0.0.0",
"private": true,
"scripts": {
"dev": "vite",
"build": "vite build"
},
"dependencies": {
"@iconify/core": "^1.0.0-beta.3",
"@vueuse/core": "^4.0.0-beta.4",
"variantwind": "^0.3.4",
"vue": "^3.0.0-rc.1",
"vue-router": "^4.0.0-beta.6"
},
"devDependencies": {
"@antfu/eslint-config-vue": "^0.2.14",
"@typescript-eslint/eslint-plugin": "^3.8.0",
"@vue/compiler-sfc": "^3.0.0-rc.5",
"eslint": "^7.6.0",
"pnpm": "^5.4.12",
"tailwindcss": "^1.6.2",
"tailwindcss-dark-mode": "^1.1.6",
"typescript": "^3.9.7",
"vite": "^1.0.0-rc.1",
"vite-plugin-voie": "^0.2.0"
},
"eslintConfig": {
"extends": "@antfu/eslint-config-vue",
"rules": {
"import/no-absolute-path": "off"
}
}
}
+3913
View File
File diff suppressed because it is too large. Load diff
+6
View File
@@ -0,0 +1,6 @@
module.exports = {
plugins: [
require('tailwindcss'),
require('autoprefixer'),
],
}
+6
View File
@@ -0,0 +1,6 @@
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="32" height="32"
preserveAspectRatio="xMidYMid meet" viewBox="0 0 32 32">
<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"
fill="#fff" />
</svg>

After

Width:  |  Height:  |  Size: 346 B

+6
View File
@@ -0,0 +1,6 @@
<template>
<div class="px-4 py-10 text-center text-gray-700 dark:text-gray-200">
<router-view />
<Footer />
</div>
</template>
+31
View File
@@ -0,0 +1,31 @@
<template>
<div
class="text-xl mt-4"
>
<div
class="inline-block mx-2 cursor-pointer select-none"
@click="isDark = !isDark"
>
<Icon
class="inline-block"
:icon="isDark ? 'carbon:moon' : 'carbon:sun'"
/>
</div>
<a
class="mx-2"
href="https://github.com/antfu/vitesse"
target="_blank"
>
<Icon
class="inline-block"
icon="carbon:code"
/>
</a>
</div>
</template>
<script setup lang='ts'>
export { isDark } from '../utils/dark'
</script>
+49
View File
@@ -0,0 +1,49 @@
<template>
<div ref="el" :class="$attrs.class" style="vertical-align: text-bottom" />
</template>
<script setup="props" lang="ts">
import { watch, ref, onMounted, nextTick } from 'vue'
declare const props: {
icon: string
}
export const el = ref<HTMLElement | null>(null)
const update = async() => {
if (el.value) {
await nextTick()
// @ts-ignore
const data = window.Iconify.getSVGObject(props.icon)
if (data) {
const svg = document.createElementNS('http://www.w3.org/2000/svg', 'svg')
for (const key of Object.keys(data.attributes))
svg.setAttribute(key, data.attributes[key])
svg.innerHTML = data ? data.body : null
el.value.textContent = ''
el.value.appendChild(svg)
}
else {
const span = document.createElement('span')
span.className = 'iconify'
span.dataset.icon = props.icon
el.value.textContent = ''
el.value.appendChild(span)
}
}
}
watch(() => props.icon, update, { flush: 'post' })
onMounted(update)
</script>
<style>
span.iconify {
background: #5551;
border-radius: 100%;
min-width: 10px;
min-height: 1em;
}
</style>
+56
View File
@@ -0,0 +1,56 @@
<template>
<div
class="fixed top-0 bottom-0 left-0 right-0 z-40"
:class="value ? '': 'pointer-events-none'"
>
<div
class="bg-white bg-opacity-85 bottom-0 left-0 right-0 top-0 absolute transition-opacity duration-500 ease-out"
:class="value ? '': 'opacity-0'"
@click="$emit('update:value', false)"
/>
<div
class="bg-white absolute transition-all duration-200 ease-out border-gray-200"
:class="positionClass"
:style="value ? {}: {transform}"
>
<slot />
</div>
</div>
</template>
<script setup="props" lang="ts">
import { computed } from 'vue'
declare const props: {
value?: boolean
direction?: 'bottom' | 'top' | 'left' | 'right'
}
const defaultDirection = 'bottom'
export const positionClass = computed(() => {
switch (props.direction || defaultDirection) {
case 'bottom':
return 'bottom-0 left-0 right-0 border-t'
case 'top':
return 'top-0 left-0 right-0 border-b'
case 'left':
return 'bottom-0 left-0 top-0 border-r'
case 'right':
return 'bottom-0 top-0 right-0 border-l'
}
})
export const transform = computed(() => {
switch (props.direction || defaultDirection) {
case 'bottom':
return 'translateY(100%)'
case 'top':
return 'translateY(-100%)'
case 'left':
return 'translateX(-100%)'
case 'right':
return 'translateX(100%)'
}
})
</script>
+12
View File
@@ -0,0 +1,12 @@
import { Plugin } from 'vue'
import Modal from './Modal.vue'
import Icon from './Icon.vue'
import Footer from './Footer.vue'
export const registerComponents: Plugin = {
install(app) {
app.component('Modal', Modal)
app.component('Icon', Icon)
app.component('Footer', Footer)
},
}
+26
View File
@@ -0,0 +1,26 @@
@import 'tailwindcss/base';
@import 'tailwindcss/components';
@import 'tailwindcss/utilities';
html, body, #app {
height: 100vh;
width: 100vw;
margin: 0;
padding: 0;
}
.schema-dark {
background: #222;
}
.btn {
@apply px-4 py-1 rounded bg-teal-600 inline-block text-white cursor-pointer;
}
.btn:hover {
@apply bg-teal-700;
}
.btn[disabled] {
@apply cursor-default bg-gray-600 opacity-50;
}
+18
View File
@@ -0,0 +1,18 @@
import './main.postcss'
import { createApp } from 'vue'
import { createRouter, createWebHistory } from 'vue-router'
// @ts-ignore
import routes from '/@voie/pages'
import { registerComponents } from './components'
import App from './App.vue'
const app = createApp(App)
const router = createRouter({
history: createWebHistory(),
routes,
})
app.use(router)
app.use(registerComponents)
app.mount('#app')
+31
View File
@@ -0,0 +1,31 @@
<template>
<div>
<p class="text-4xl">
<Icon class="iconify inline-block" icon="carbon:pedestrian" />
</p>
<p>
Hi, {{ name }}!
</p>
<div>
<button
class="btn m-3 text-sm mt-8"
@click="back"
>
Back
</button>
</div>
</div>
</template>
<script setup='props' lang='ts'>
import { useRouter } from 'vue-router'
declare const props: {
name: string
}
const router = useRouter()
export const back = () => router.push('/')
</script>
+43
View File
@@ -0,0 +1,43 @@
<template>
<div>
<p class="text-4xl">
<Icon class="iconify inline-block" icon="carbon:campsite" />
</p>
<p>
Vitesse
</p>
<div class="py-4" />
<input
v-model="name"
placeholder="What's your name?"
class="px-4 py-2 border border-gray-200 rounded text-center outline-none active:outline-none bg-transparent dark:border-gray-700"
@keydown.enter="go"
>
<div>
<button
class="btn m-3 text-sm"
:disabled="!name"
@click="go"
>
GO
</button>
</div>
</div>
</template>
<script setup='props' lang='ts'>
import { ref } from 'vue'
import { useRouter } from 'vue-router'
export const name = ref('')
const router = useRouter()
export const go = () => {
if (name.value)
router.push(`/hi/${name.value}`)
}
</script>
+5
View File
@@ -0,0 +1,5 @@
declare module '*.vue' {
import { defineComponent } from 'vue'
const Component: ReturnType<typeof defineComponent>
export default Component
}
+26
View File
@@ -0,0 +1,26 @@
import { watch, computed, Ref } from 'vue'
import { useStorage, usePreferredDark } from '@vueuse/core'
const preferredDark = usePreferredDark()
const schema = useStorage('vitesse-schema', 'auto') as Ref<'auto' | 'dark' | 'light'>
export const isDark = computed({
get() {
return schema.value === 'auto' ? preferredDark.value : schema.value === 'dark'
},
set(v: boolean) {
if (v === preferredDark.value)
schema.value = 'auto'
else
schema.value = v ? 'dark' : 'light'
},
})
watch(
isDark,
(v) => {
const html = document.getElementsByTagName('html')[0]
html.classList.toggle('schema-dark', v)
},
{ immediate: true },
)
+3
View File
@@ -0,0 +1,3 @@
declare interface Window {
// extend the window
}
+32
View File
@@ -0,0 +1,32 @@
/* eslint-disable @typescript-eslint/no-var-requires */
module.exports = {
purge: {
content: [
'./index.html',
'./src/**/*.vue',
'./src/**/*.js',
'./src/**/*.ts',
],
whitelist: [
'schema-dark',
],
},
theme: {
darkSelector: '.schema-dark',
extend: {
opacity: {
10: '0.1',
85: '0.85',
},
},
},
variants: {
backgroundColor: ['dark', 'dark-hover', 'dark-group-hover', 'hover'],
borderColor: ['dark', 'dark-disabled', 'dark-focus', 'dark-active'],
textColor: ['dark', 'dark-hover', 'dark-active', 'hover', 'active'],
},
plugins: [
require('tailwindcss-dark-mode')(),
],
}
+18
View File
@@ -0,0 +1,18 @@
{
"compilerOptions": {
"module": "ESNext",
"target": "es2016",
"lib": ["DOM", "ESNext"],
"strict": true,
"esModuleInterop": true,
"incremental": true,
"skipLibCheck": true,
"moduleResolution": "node",
"resolveJsonModule": true,
"forceConsistentCasingInFileNames": true
},
"exclude": [
"dist",
"node_modules"
]
}
+10
View File
@@ -0,0 +1,10 @@
import voie from 'vite-plugin-voie'
export default {
plugins: [
voie({
pagesDir: 'src/pages',
extensions: ['vue', 'ts'],
}),
],
}