├── .browserslistrc
├── .env.local.example
├── .eslintrc.js
├── .gitignore
├── README.md
├── babel.config.js
├── package.json
├── public
├── favicon.ico
├── img
│ └── icons
│ │ ├── android-chrome-192x192.png
│ │ ├── android-chrome-512x512.png
│ │ ├── android-chrome-maskable-192x192.png
│ │ ├── android-chrome-maskable-512x512.png
│ │ ├── apple-touch-icon-120x120.png
│ │ ├── apple-touch-icon-152x152.png
│ │ ├── apple-touch-icon-180x180.png
│ │ ├── apple-touch-icon-60x60.png
│ │ ├── apple-touch-icon-76x76.png
│ │ ├── apple-touch-icon.png
│ │ ├── favicon-16x16.png
│ │ ├── favicon-32x32.png
│ │ ├── msapplication-icon-144x144.png
│ │ ├── mstile-150x150.png
│ │ └── safari-pinned-tab.svg
├── index.html
└── robots.txt
├── src
├── App.vue
├── assets
│ ├── logo.png
│ └── logo.svg
├── components
│ ├── ColorPickerMenu.vue
│ ├── Create.vue
│ ├── Note.vue
│ ├── NoteModal.vue
│ └── Notes.vue
├── firebase
│ ├── db.ts
│ ├── firebase.ts
│ └── index.ts
├── main.ts
├── plugins
│ └── vuetify.ts
├── registerServiceWorker.ts
├── shims-tsx.d.ts
├── shims-vue.d.ts
└── store
│ ├── index.ts
│ ├── modules
│ ├── global.ts
│ └── notes.ts
│ └── types.ts
├── tsconfig.json
├── vue.config.js
└── yarn.lock
/.browserslistrc:
--------------------------------------------------------------------------------
1 | > 1%
2 | last 2 versions
3 | not dead
4 |
--------------------------------------------------------------------------------
/.env.local.example:
--------------------------------------------------------------------------------
1 | VUE_APP_FB_API_KEY=
2 | VUE_APP_FB_AUTH_DOMAIN=
3 | VUE_APP_FB_DATABASE_URL=
4 | VUE_APP_FB_PROJECT_ID=
5 | VUE_APP_FB_STORAGE_BUCKET=
6 | VUE_APP_FB_MESSAGING_SENDER_ID=
7 | VUE_APP_FB_APP_ID=
--------------------------------------------------------------------------------
/.eslintrc.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | root: true,
3 | env: {
4 | node: true
5 | },
6 | 'extends': [
7 | 'plugin:vue/essential',
8 | 'eslint:recommended',
9 | '@vue/typescript/recommended'
10 | ],
11 | parserOptions: {
12 | ecmaVersion: 2020
13 | },
14 | rules: {
15 | 'no-console': process.env.NODE_ENV === 'production' ? 'warn' : 'off',
16 | 'no-debugger': process.env.NODE_ENV === 'production' ? 'warn' : 'off'
17 | }
18 | }
19 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | .DS_Store
2 | node_modules
3 | /dist
4 |
5 | # local env files
6 | .env.local
7 | .env.*.local
8 |
9 | # Log files
10 | npm-debug.log*
11 | yarn-debug.log*
12 | yarn-error.log*
13 | pnpm-debug.log*
14 |
15 | # Editor directories and files
16 | .idea
17 | .vscode
18 | *.suo
19 | *.ntvs*
20 | *.njsproj
21 | *.sln
22 | *.sw?
23 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Vue Keep
2 |
3 | A Google Keep clone with Vue, Typescript and Firestore.
4 |
5 | Demo: https://vue-keep-sepia.vercel.app/
6 |
7 | ## Usage
8 |
9 | Create a `.env.local` file at the root path and enter your firebase project creds:
10 |
11 | ```
12 | VUE_APP_FB_API_KEY=
13 | VUE_APP_FB_AUTH_DOMAIN=
14 | VUE_APP_FB_DATABASE_URL=
15 | VUE_APP_FB_PROJECT_ID=
16 | VUE_APP_FB_STORAGE_BUCKET=
17 | VUE_APP_FB_MESSAGING_SENDER_ID=
18 | VUE_APP_FB_APP_ID=
19 | ```
20 |
21 | ```bash
22 | # Install dependencies
23 | $ npm install
24 |
25 | # Compiles and hot-reloads for development
26 | $ npm run serve
27 |
28 | # Compiles and minifies for production
29 | $ npm run build
30 |
31 | # Lints and fixes files
32 | $ npm run lint
33 | ```
34 |
--------------------------------------------------------------------------------
/babel.config.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | presets: [
3 | '@vue/cli-plugin-babel/preset'
4 | ]
5 | }
6 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "vue-keep",
3 | "version": "0.1.0",
4 | "private": true,
5 | "scripts": {
6 | "serve": "vue-cli-service serve",
7 | "build": "vue-cli-service build",
8 | "lint": "vue-cli-service lint"
9 | },
10 | "dependencies": {
11 | "core-js": "^3.6.5",
12 | "firebase": "^9.12.1",
13 | "register-service-worker": "^1.7.2",
14 | "vue": "^2.7.13",
15 | "vue-class-component": "^7.2.6",
16 | "vue-property-decorator": "^9.1.2",
17 | "vuetify": "^2.6.12",
18 | "vuex": "^3.4.0",
19 | "vuex-class": "^0.3.2"
20 | },
21 | "devDependencies": {
22 | "@typescript-eslint/eslint-plugin": "^5.40.1",
23 | "@typescript-eslint/parser": "^5.40.1",
24 | "@vue/cli-plugin-babel": "~5.0.6",
25 | "@vue/cli-plugin-eslint": "~5.0.6",
26 | "@vue/cli-plugin-pwa": "~5.0.6",
27 | "@vue/cli-plugin-typescript": "~5.0.6",
28 | "@vue/cli-plugin-vuex": "~5.0.6",
29 | "@vue/cli-service": "~5.0.6",
30 | "@vue/eslint-config-typescript": "^11.0.2",
31 | "eslint": "^8.25.0",
32 | "eslint-plugin-vue": "^9.6.0",
33 | "sass": "^1.32.0",
34 | "sass-loader": "^13.1.0",
35 | "typescript": "~4.5.5",
36 | "vue-cli-plugin-vuetify": "~2.5.8",
37 | "vuetify-loader": "^1.9.2",
38 | "vuex-module-decorators": "^1.2.0"
39 | }
40 | }
41 |
--------------------------------------------------------------------------------
/public/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wobsoriano/vue-keep/9594411ffc54a0c97d35c101915e70da7c5eef30/public/favicon.ico
--------------------------------------------------------------------------------
/public/img/icons/android-chrome-192x192.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wobsoriano/vue-keep/9594411ffc54a0c97d35c101915e70da7c5eef30/public/img/icons/android-chrome-192x192.png
--------------------------------------------------------------------------------
/public/img/icons/android-chrome-512x512.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wobsoriano/vue-keep/9594411ffc54a0c97d35c101915e70da7c5eef30/public/img/icons/android-chrome-512x512.png
--------------------------------------------------------------------------------
/public/img/icons/android-chrome-maskable-192x192.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wobsoriano/vue-keep/9594411ffc54a0c97d35c101915e70da7c5eef30/public/img/icons/android-chrome-maskable-192x192.png
--------------------------------------------------------------------------------
/public/img/icons/android-chrome-maskable-512x512.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wobsoriano/vue-keep/9594411ffc54a0c97d35c101915e70da7c5eef30/public/img/icons/android-chrome-maskable-512x512.png
--------------------------------------------------------------------------------
/public/img/icons/apple-touch-icon-120x120.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wobsoriano/vue-keep/9594411ffc54a0c97d35c101915e70da7c5eef30/public/img/icons/apple-touch-icon-120x120.png
--------------------------------------------------------------------------------
/public/img/icons/apple-touch-icon-152x152.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wobsoriano/vue-keep/9594411ffc54a0c97d35c101915e70da7c5eef30/public/img/icons/apple-touch-icon-152x152.png
--------------------------------------------------------------------------------
/public/img/icons/apple-touch-icon-180x180.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wobsoriano/vue-keep/9594411ffc54a0c97d35c101915e70da7c5eef30/public/img/icons/apple-touch-icon-180x180.png
--------------------------------------------------------------------------------
/public/img/icons/apple-touch-icon-60x60.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wobsoriano/vue-keep/9594411ffc54a0c97d35c101915e70da7c5eef30/public/img/icons/apple-touch-icon-60x60.png
--------------------------------------------------------------------------------
/public/img/icons/apple-touch-icon-76x76.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wobsoriano/vue-keep/9594411ffc54a0c97d35c101915e70da7c5eef30/public/img/icons/apple-touch-icon-76x76.png
--------------------------------------------------------------------------------
/public/img/icons/apple-touch-icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wobsoriano/vue-keep/9594411ffc54a0c97d35c101915e70da7c5eef30/public/img/icons/apple-touch-icon.png
--------------------------------------------------------------------------------
/public/img/icons/favicon-16x16.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wobsoriano/vue-keep/9594411ffc54a0c97d35c101915e70da7c5eef30/public/img/icons/favicon-16x16.png
--------------------------------------------------------------------------------
/public/img/icons/favicon-32x32.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wobsoriano/vue-keep/9594411ffc54a0c97d35c101915e70da7c5eef30/public/img/icons/favicon-32x32.png
--------------------------------------------------------------------------------
/public/img/icons/msapplication-icon-144x144.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wobsoriano/vue-keep/9594411ffc54a0c97d35c101915e70da7c5eef30/public/img/icons/msapplication-icon-144x144.png
--------------------------------------------------------------------------------
/public/img/icons/mstile-150x150.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wobsoriano/vue-keep/9594411ffc54a0c97d35c101915e70da7c5eef30/public/img/icons/mstile-150x150.png
--------------------------------------------------------------------------------
/public/img/icons/safari-pinned-tab.svg:
--------------------------------------------------------------------------------
1 |
4 |
--------------------------------------------------------------------------------
/public/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 | <%= htmlWebpackPlugin.options.title %>
9 |
10 |
11 |
12 |
13 |
14 |
17 |
18 |
19 |
20 |
21 |
--------------------------------------------------------------------------------
/public/robots.txt:
--------------------------------------------------------------------------------
1 | User-agent: *
2 | Disallow:
3 |
--------------------------------------------------------------------------------
/src/App.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
13 |
14 | VueKeep
15 |
16 |
17 |
18 |
19 | mdi-refresh
20 |
21 |
22 | mdi-github
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 | {{ snackbar.text }}
38 |
39 |
40 |
41 |
42 |
43 |
84 |
--------------------------------------------------------------------------------
/src/assets/logo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wobsoriano/vue-keep/9594411ffc54a0c97d35c101915e70da7c5eef30/src/assets/logo.png
--------------------------------------------------------------------------------
/src/assets/logo.svg:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/src/components/ColorPickerMenu.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | mdi-palette-outline
6 |
7 |
8 |
9 |
10 |
16 |
17 |
24 |
25 | {{
26 | name !== 'Default'
27 | ? selectedIcon(value, false)
28 | : selectedIcon(value, true)
29 | }}
30 |
31 |
32 |
33 | {{ name }}
34 |
35 |
36 |
37 |
38 |
39 |
40 |
81 |
--------------------------------------------------------------------------------
/src/components/Create.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
17 |
30 |
31 |
32 |
33 |
34 | Close
35 |
36 |
37 |
38 |
39 |
40 |
41 |
119 |
--------------------------------------------------------------------------------
/src/components/Note.vue:
--------------------------------------------------------------------------------
1 |
2 |
11 |
12 | {{ note.title }}
13 |
14 |
15 | mdi-pencil-outline
16 |
17 |
18 |
19 | {{ note.content }}
20 |
21 |
22 |
23 |
24 |
54 |
--------------------------------------------------------------------------------
/src/components/NoteModal.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
16 |
28 |
29 |
30 |
31 | mdi-delete-outline
32 |
33 |
34 |
35 | Close
36 | Save
37 |
38 |
39 |
40 |
41 |
42 |
128 |
--------------------------------------------------------------------------------
/src/components/Notes.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
13 |
14 |
15 |
16 |
17 |
18 |
36 |
--------------------------------------------------------------------------------
/src/firebase/db.ts:
--------------------------------------------------------------------------------
1 | import { db } from './firebase';
2 | import { collection, doc, updateDoc, getDocs, addDoc, deleteDoc } from 'firebase/firestore/lite';
3 | import { Note, NewNote } from '@/store/types';
4 |
5 | const collectionName = 'notes'
6 |
7 | export const createNote = async (note: NewNote): Promise => {
8 | const newDoc = await addDoc(collection(db, collectionName), note);
9 | return {
10 | id: newDoc.id,
11 | ...note
12 | };
13 | };
14 |
15 | export const getNotes = async (): Promise => {
16 | const querySnapshot = await getDocs(collection(db, collectionName));
17 | return querySnapshot.docs.map(doc => {
18 | const { title, content, color } = doc.data();
19 | return {
20 | id: doc.id,
21 | title,
22 | content,
23 | color
24 | };
25 | });
26 | };
27 |
28 | export const updateNote = async (note: Note): Promise => {
29 | const noteRef = doc(db, collectionName, note.id);
30 | await updateDoc(noteRef, {
31 | title: note.title,
32 | content: note.content,
33 | color: note.color
34 | });
35 | return note;
36 | };
37 |
38 | export const deleteNote = async (id: string): Promise => {
39 | const noteRef = doc(db, collectionName, id);
40 | await deleteDoc(noteRef);
41 | return id;
42 | };
43 |
--------------------------------------------------------------------------------
/src/firebase/firebase.ts:
--------------------------------------------------------------------------------
1 | import { initializeApp } from 'firebase/app';
2 | import { getFirestore } from 'firebase/firestore/lite'
3 |
4 | const config = {
5 | apiKey: process.env.VUE_APP_FB_API_KEY,
6 | authDomain: process.env.VUE_APP_FB_AUTH_DOMAIN,
7 | databaseURL: process.env.VUE_APP_FB_DATABASE_URL,
8 | projectId: process.env.VUE_APP_FB_PROJECT_ID,
9 | storageBucket: process.env.VUE_APP_FB_STORAGE_BUCKET,
10 | messagingSenderId: process.env.VUE_APP_FB_MESSAGING_SENDER_ID,
11 | };
12 |
13 | initializeApp(config)
14 |
15 | const db = getFirestore();
16 |
17 | export { db };
18 |
--------------------------------------------------------------------------------
/src/firebase/index.ts:
--------------------------------------------------------------------------------
1 | import * as db from './db';
2 |
3 | export { db };
4 |
--------------------------------------------------------------------------------
/src/main.ts:
--------------------------------------------------------------------------------
1 | import Vue from 'vue'
2 | import App from './App.vue'
3 | import './registerServiceWorker'
4 | import store from './store'
5 | import vuetify from './plugins/vuetify';
6 |
7 | Vue.config.productionTip = false
8 |
9 | new Vue({
10 | store,
11 | vuetify,
12 | render: h => h(App)
13 | }).$mount('#app')
14 |
--------------------------------------------------------------------------------
/src/plugins/vuetify.ts:
--------------------------------------------------------------------------------
1 | import Vue from 'vue';
2 | import Vuetify from 'vuetify/lib';
3 |
4 | Vue.use(Vuetify);
5 |
6 | export default new Vuetify({
7 | });
8 |
--------------------------------------------------------------------------------
/src/registerServiceWorker.ts:
--------------------------------------------------------------------------------
1 | /* eslint-disable no-console */
2 |
3 | import { register } from 'register-service-worker';
4 |
5 | if (process.env.NODE_ENV === 'production') {
6 | register(`${process.env.BASE_URL}service-worker.js`, {
7 | ready() {
8 | console.log(
9 | 'App is being served from cache by a service worker.\n' +
10 | 'For more details, visit https://goo.gl/AFskqB'
11 | );
12 | },
13 | registered() {
14 | console.log('Service worker has been registered.');
15 | },
16 | cached() {
17 | console.log('Content has been cached for offline use.');
18 | },
19 | updatefound() {
20 | console.log('New content is downloading.');
21 | },
22 | updated() {
23 | console.log('New content is available; reloading...');
24 | window.location.reload();
25 | },
26 | offline() {
27 | console.log(
28 | 'No internet connection found. App is running in offline mode.'
29 | );
30 | },
31 | error(error) {
32 | console.error('Error during service worker registration:', error);
33 | }
34 | });
35 | }
36 |
--------------------------------------------------------------------------------
/src/shims-tsx.d.ts:
--------------------------------------------------------------------------------
1 | import Vue, { VNode } from 'vue'
2 |
3 | declare global {
4 | namespace JSX {
5 | // tslint:disable no-empty-interface
6 | interface Element extends VNode {}
7 | // tslint:disable no-empty-interface
8 | interface ElementClass extends Vue {}
9 | interface IntrinsicElements {
10 | [elem: string]: any;
11 | }
12 | }
13 | }
14 |
--------------------------------------------------------------------------------
/src/shims-vue.d.ts:
--------------------------------------------------------------------------------
1 | declare module '*.vue' {
2 | import Vue from 'vue'
3 | export default Vue
4 | }
5 |
--------------------------------------------------------------------------------
/src/store/index.ts:
--------------------------------------------------------------------------------
1 | import Vue from 'vue';
2 | import Vuex from 'vuex';
3 |
4 | import global from '@/store/modules/global';
5 | import notes from '@/store/modules/notes';
6 |
7 | Vue.use(Vuex);
8 |
9 | export default new Vuex.Store({
10 | modules: {
11 | global,
12 | notes
13 | }
14 | });
15 |
--------------------------------------------------------------------------------
/src/store/modules/global.ts:
--------------------------------------------------------------------------------
1 | import { Module, VuexModule, Mutation } from 'vuex-module-decorators';
2 | import { Note, Snackbar, EditNoteField } from '@/store/types';
3 | import { SnackbarColorTypes, CardColorTypes } from '@/store/types';
4 |
5 | @Module({
6 | namespaced: true
7 | })
8 | export default class GlobalModal extends VuexModule {
9 | selectedNote: Note = {
10 | id: '',
11 | title: '',
12 | content: '',
13 | color: CardColorTypes.Default
14 | };
15 | showNoteDialog = false;
16 | snackbar: Snackbar = {
17 | open: false,
18 | text: '',
19 | color: SnackbarColorTypes.Success
20 | };
21 | colorMenuOpen = false;
22 |
23 | @Mutation
24 | setSelectedNote(note: Note) {
25 | this.selectedNote = note;
26 | }
27 |
28 | @Mutation
29 | setNoteField(payload: EditNoteField) {
30 | this.selectedNote = {
31 | ...this.selectedNote,
32 | [payload.name]: payload.value
33 | };
34 | }
35 |
36 | @Mutation
37 | setShowNoteDialog(payload: boolean) {
38 | this.showNoteDialog = payload;
39 | }
40 |
41 | @Mutation
42 | showSnackbar(payload: Snackbar) {
43 | this.snackbar = payload;
44 | }
45 |
46 | @Mutation
47 | setColorMenuOpen(payload: boolean) {
48 | this.colorMenuOpen = payload;
49 | }
50 | }
51 |
--------------------------------------------------------------------------------
/src/store/modules/notes.ts:
--------------------------------------------------------------------------------
1 | import { Module, VuexModule, Mutation, Action } from 'vuex-module-decorators';
2 | import { Note, NewNote } from '../types';
3 | import { db } from '@/firebase';
4 | import { CardColorTypes } from '@/store/types';
5 |
6 | @Module({
7 | namespaced: true
8 | })
9 | export default class NotesModule extends VuexModule {
10 | notes: Note[] = [];
11 |
12 | @Mutation
13 | setNotes(notes: Note[]) {
14 | this.notes = notes;
15 | }
16 |
17 | @Mutation
18 | addNote(note: Note) {
19 | this.notes.unshift(note);
20 | }
21 |
22 | @Mutation
23 | removeNote(id: string) {
24 | const idx = this.notes.findIndex(i => i.id === id);
25 | if (idx !== -1) {
26 | this.notes.splice(idx, 1);
27 | }
28 | }
29 |
30 | @Mutation
31 | setNote(note: Note) {
32 | const idx = this.notes.findIndex(i => i.id === note.id);
33 | if (idx !== -1) {
34 | this.notes[idx].title = note.title;
35 | this.notes[idx].content = note.content;
36 | this.notes[idx].color = note.color || CardColorTypes.Default;
37 | }
38 | }
39 |
40 | @Action({ commit: 'setNotes' })
41 | async getNotes() {
42 | const notes = await db.getNotes();
43 | return notes;
44 | }
45 |
46 | @Action({ commit: 'addNote' })
47 | async createNote(note: NewNote) {
48 | const data = await db.createNote(note);
49 | return data;
50 | }
51 |
52 | @Action({ commit: 'removeNote' })
53 | async removeNoteAsync(id: string) {
54 | await db.deleteNote(id);
55 | return id;
56 | }
57 |
58 | @Action({ commit: 'setNote' })
59 | async updateNote(note: Note) {
60 | await db.updateNote(note);
61 | return note;
62 | }
63 | }
64 |
--------------------------------------------------------------------------------
/src/store/types.ts:
--------------------------------------------------------------------------------
1 | export enum SnackbarColorTypes {
2 | Success = 'success',
3 | Error = 'error',
4 | Info = 'info'
5 | }
6 |
7 | export enum CardColorTypes {
8 | Default = 'none',
9 | Red = 'red accent-1',
10 | Orange = 'orange accent-2',
11 | Yellow = 'yellow accent-1',
12 | Green = 'light-green accent-1',
13 | Blue = 'cyan lighten-4',
14 | Purple = 'purple lighten-4',
15 | Pink = 'pink lighten-4'
16 | }
17 |
18 | export interface Note {
19 | id: string;
20 | title: string;
21 | content: string;
22 | color: string;
23 | }
24 |
25 | export type NewNote = Omit;
26 |
27 | export interface Snackbar {
28 | open: boolean;
29 | text: string;
30 | color: SnackbarColorTypes;
31 | }
32 |
33 | export interface EditNoteField {
34 | name: string;
35 | value: string;
36 | }
37 |
38 | export type CardColors = keyof typeof CardColorTypes;
--------------------------------------------------------------------------------
/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "compilerOptions": {
3 | "target": "esnext",
4 | "module": "esnext",
5 | "strict": true,
6 | "jsx": "preserve",
7 | "importHelpers": true,
8 | "moduleResolution": "node",
9 | "experimentalDecorators": true,
10 | "esModuleInterop": true,
11 | "allowSyntheticDefaultImports": true,
12 | "sourceMap": true,
13 | "baseUrl": ".",
14 | "typeRoots": ["./node_modules/@types", "./node_modules/vuetify/types"],
15 | "types": ["webpack-env", "vuetify"],
16 | "paths": {
17 | "@/*": ["src/*"]
18 | },
19 | "lib": ["esnext", "dom", "dom.iterable", "scripthost"]
20 | },
21 | "include": [
22 | "src/**/*.ts",
23 | "src/**/*.tsx",
24 | "src/**/*.vue",
25 | "tests/**/*.ts",
26 | "tests/**/*.tsx"
27 | ],
28 | "exclude": ["node_modules"],
29 | "vueCompilerOptions": {
30 | "target": 2.7
31 | }
32 | }
33 |
--------------------------------------------------------------------------------
/vue.config.js:
--------------------------------------------------------------------------------
1 | const { defineConfig } = require("@vue/cli-service");
2 |
3 | module.exports = defineConfig({
4 | transpileDependencies: [
5 | "vuetify"
6 | ],
7 | pwa: {
8 | "workboxOptions": {
9 | "skipWaiting": true
10 | }
11 | },
12 | css: {
13 | loaderOptions: {
14 | sass: {
15 | sassOptions: {
16 | quietDeps: true,
17 | },
18 | },
19 | },
20 | },
21 | });
22 |
--------------------------------------------------------------------------------