🚨 (component)

This commit is contained in:
2021-05-06 00:02:37 +02:00
parent 198a64d18d
commit 271412f6f7
3 changed files with 249 additions and 254 deletions

View File

@@ -6,12 +6,8 @@ module.exports = {
extends: [ extends: [
'plugin:vue/vue3-essential', 'plugin:vue/vue3-essential',
'eslint:recommended', 'eslint:recommended',
'@vue/typescript/recommended',
'@vue/prettier',
'@vue/prettier/@typescript-eslint',
'plugin:vue/recommended', 'plugin:vue/recommended',
'plugin:prettier-vue/recommended', 'plugin:prettier-vue/recommended'
'prettier'
], ],
parserOptions: { parserOptions: {
ecmaVersion: 2020 ecmaVersion: 2020
@@ -29,7 +25,8 @@ module.exports = {
trailingComma: 'none', trailingComma: 'none',
arrowParens: 'always' arrowParens: 'always'
} }
] ],
'vue/no-v-html': 'off'
}, },
overrides: [ overrides: [
{ {

View File

@@ -1,244 +1,242 @@
<template> <template>
<main class="flux-note content note-container"> <main class="flux-note content note-container">
<div class="note readme"> <div class="note readme">
<header-note v-if="withHeader" class="header" :user="user" :repo="repo" /> <header-note v-if="withHeader" class="header" :user="user" :repo="repo" />
<div class="repo-title-breadcrumb"> <div class="repo-title-breadcrumb">
<a @click.prevent="focus">{{ repo }}</a> <a @click.prevent="focus">{{ repo }}</a>
</div> </div>
<div class="repo-title"> <div class="repo-title">
<h1 class="title is-1"> <h1 class="title is-1">
[<router-link [<router-link
:to="{ name: 'Home', params: { user, repo } }" :to="{ name: 'Home', params: { user, repo } }"
@click="resetStackedNotes" @click="resetStackedNotes"
>{{ repo }}</router-link >{{ repo }}</router-link
>] >]
</h1> </h1>
<h4 class="subtitle is-4"> <h4 class="subtitle is-4">
<em>{{ user }}</em> <em>{{ user }}</em>
</h4> </h4>
</div> </div>
<slot /> <slot />
<div v-if="isLoading" class="loading"> <div v-if="isLoading" class="loading">
<img <img
class="is-loading" class="is-loading"
src="@/assets/icons/loading.svg" src="@/assets/icons/loading.svg"
alt="loading..." alt="loading..."
/> />
</div> </div>
<div v-else-if="!hasContent"> <div v-else-if="!hasContent">No content here 📝</div>
No content here 📝 <p class="note-display" v-html="renderedContent"></p>
</div> </div>
<p class="note-display" v-html="renderedContent"></p> <stacked-note
</div> v-for="(stackedNote, index) in stackedNotes"
<stacked-note :key="stackedNote"
class="note" class="note"
v-for="(stackedNote, index) in stackedNotes" :index="index"
:key="stackedNote" :sha="stackedNote"
:index="index" :user="user"
:sha="stackedNote" :repo="repo"
:user="user" :title="titles[stackedNote ?? '']"
:repo="repo" />
:title="titles[stackedNote ?? '']" </main>
/> </template>
</main>
</template> <script lang="ts">
import { useQueryStackedNotes } from '@/hooks/useQueryStackedNotes.hook'
<script lang="ts"> import {
import { useQueryStackedNotes } from '@/hooks/useQueryStackedNotes.hook' defineComponent,
import { defineAsyncComponent,
defineComponent, computed,
defineAsyncComponent, watch,
computed, nextTick,
watch, toRefs,
nextTick, onUnmounted
toRefs, } from 'vue'
onUnmounted import HeaderNote from '@/components/HeaderNote.vue'
} from 'vue' import { useNote } from '@/hooks/useNote.hook'
import HeaderNote from '@/components/HeaderNote.vue' import { useMarkdown } from '@/hooks/useMarkdown.hook'
import { useNote } from '@/hooks/useNote.hook' import { useLinks } from '@/hooks/useLinks.hook'
import { useMarkdown } from '@/hooks/useMarkdown.hook' import { useUserRepoStore } from '@/modules/repo/store/userRepo.store'
import { useLinks } from '@/hooks/useLinks.hook' import { useUserSettings } from '@/modules/user/hooks/useUserSettings.hook'
import { useUserRepoStore } from '@/modules/repo/store/userRepo.store' import { useFocus } from '@/hooks/useFocus.hook'
import { useUserSettings } from '@/modules/user/hooks/useUserSettings.hook'
import { useFocus } from '@/hooks/useFocus.hook' const StackedNote = defineAsyncComponent(
() => import('@/components/StackedNote.vue')
const StackedNote = defineAsyncComponent(() => )
import('@/components/StackedNote.vue')
) export default defineComponent({
name: 'FluxNote',
export default defineComponent({ components: {
name: 'FluxNote', HeaderNote,
components: { StackedNote
HeaderNote, },
StackedNote props: {
}, user: { type: String, required: true },
props: { repo: { type: String, required: true },
user: { type: String, required: true }, content: { type: String, required: false, default: null },
repo: { type: String, required: true }, withHeader: { type: Boolean, required: false, default: true }
content: { type: String, required: false, default: null }, },
withHeader: { type: Boolean, required: false, default: true } setup(props) {
}, const refProps = toRefs(props)
setup(props) { const store = useUserRepoStore()
const refProps = toRefs(props) useUserSettings()
const store = useUserRepoStore() const { renderString } = useMarkdown()
useUserSettings() const { listenToClick } = useLinks('note-display')
const { renderString } = useMarkdown() const { stackedNotes, resetStackedNotes } = useQueryStackedNotes()
const { listenToClick } = useLinks('note-display') const { scrollToFocusedNote } = useFocus()
const { stackedNotes, resetStackedNotes } = useQueryStackedNotes()
const { scrollToFocusedNote } = useFocus() const { titles } = useNote('note-container')
const { titles } = useNote('note-container') const renderedContent = computed(() =>
props.content !== null ? renderString(props.content) : store.readme
const renderedContent = computed(() => )
props.content !== null ? renderString(props.content) : store.readme
) const hasContent = computed(() => !!renderedContent.value)
const isLoading = computed(() => renderedContent.value === undefined)
const hasContent = computed(() => !!renderedContent.value)
const isLoading = computed(() => renderedContent.value === undefined) watch(
renderedContent,
watch( () =>
renderedContent, nextTick(() => {
() => listenToClick()
nextTick(() => { }),
listenToClick() { immediate: true }
}), )
{ immediate: true }
) watch(
[refProps.user, refProps.repo],
watch( () => {
[refProps.user, refProps.repo], store.setUserRepo(props.user, props.repo)
() => { },
store.setUserRepo(props.user, props.repo) { immediate: true }
}, )
{ immediate: true }
) onUnmounted(() => {
store.resetFiles()
onUnmounted(() => { resetStackedNotes()
store.resetFiles() })
resetStackedNotes()
}) return {
hasContent,
return { isLoading,
hasContent, renderedContent,
isLoading, stackedNotes,
renderedContent, resetStackedNotes,
stackedNotes, userSettings: computed(() => store.userSettings),
resetStackedNotes, focus: () => scrollToFocusedNote(undefined, true),
userSettings: computed(() => store.userSettings), titles
focus: () => scrollToFocusedNote(undefined, true), }
titles }
} })
} </script>
})
</script> <style lang="scss">
$header-height: 40px;
<style lang="scss">
$header-height: 40px; .flux-note {
font-family: var(--font-family);
.flux-note { color: var(--font-color);
font-family: var(--font-family); background-color: var(--background-color);
color: var(--font-color); transition-property: color, background-color;
background-color: var(--background-color); transition: cubic-bezier(0.39, 0.575, 0.565, 1) 0.2s;
transition-property: color, background-color;
transition: cubic-bezier(0.39, 0.575, 0.565, 1) 0.2s; display: flex;
flex: 1;
display: flex;
flex: 1; &.content {
.title,
&.content { h1,
.title, h2,
h1, h3,
h2, h4,
h3, h5,
h4, h6,
h5, strong {
h6, color: var(--font-color);
strong { }
color: var(--font-color);
} blockquote {
background-color: var(--background-color);
blockquote { }
background-color: var(--background-color); }
}
} .header {
height: $header-height;
.header { }
height: $header-height;
} .readme {
position: sticky;
.readme { left: 0;
position: sticky; top: 0;
left: 0; padding: 0 2rem 1rem;
top: 0;
padding: 0 2rem 1rem; .repo-title {
margin-top: 1rem;
.repo-title { text-align: center;
margin-top: 1rem; }
text-align: center; }
}
} .note-display {
padding-bottom: 2rem;
.note-display { }
padding-bottom: 2rem;
} .note {
text-align: left;
.note { overflow-y: auto;
text-align: left; height: 100vh;
overflow-y: auto; position: sticky;
height: 100vh;
position: sticky; &:not(:first-child) {
border-top: 1px solid rgba(18, 19, 58, 0.2);
&:not(:first-child) { }
border-top: 1px solid rgba(18, 19, 58, 0.2); }
}
} @media screen and (min-width: 769px) {
.repo-title-breadcrumb {
@media screen and (min-width: 769px) { padding: 0.5rem 1rem 0;
.repo-title-breadcrumb { transform-origin: 0 0;
padding: 0.5rem 1rem 0; transform: rotate(90deg);
transform-origin: 0 0; font-size: 0.8em;
transform: rotate(90deg);
font-size: 0.8em; a {
color: var(--font-color);
a { display: block;
color: var(--font-color); text-align: center;
display: block; }
text-align: center; }
}
} .note {
min-width: var(--note-width);
.note { max-width: var(--note-width);
min-width: var(--note-width); height: auto;
max-width: var(--note-width); }
height: auto; }
}
} .loading {
display: flex;
.loading { flex: 1;
display: flex; justify-content: center;
flex: 1; align-items: center;
justify-content: center;
align-items: center; .is-loading {
animation: spinAround 0.8s infinite linear;
.is-loading { }
animation: spinAround 0.8s infinite linear; }
} }
}
} @media print, screen and (max-width: 768px) {
.flux-note {
@media print, screen and (max-width: 768px) { flex-wrap: wrap;
.flux-note { }
flex-wrap: wrap;
} .note {
width: 100vw;
.note { overflow-y: visible;
width: 100vw; }
overflow-y: visible;
} .repo-title-breadcrumb {
display: none;
.repo-title-breadcrumb { visibility: hidden;
display: none; }
visibility: hidden; }
} </style>
}
</style>

View File

@@ -1,10 +1,10 @@
<template> <template>
<div class="home content" v-if="!user || !repo"> <div v-if="!user || !repo" class="home content">
<authorize class="authorize" /> <authorize class="authorize" />
<new-version class="new-version" /> <new-version class="new-version" />
<welcome-world /> <welcome-world />
</div> </div>
<flux-note :user="user" :repo="repo" :key="routeKey" v-else /> <flux-note v-else :key="routeKey" :user="user" :repo="repo" />
</template> </template>
<script lang="ts"> <script lang="ts">
@@ -15,8 +15,8 @@ import Authorize from '@/components/Authorize.vue'
const FluxNote = defineAsyncComponent(() => import('@/components/FluxNote.vue')) const FluxNote = defineAsyncComponent(() => import('@/components/FluxNote.vue'))
const WelcomeWorld = defineAsyncComponent(() => const WelcomeWorld = defineAsyncComponent(
import('@/components/WelcomeWorld.vue') () => import('@/components/WelcomeWorld.vue')
) )
export default defineComponent({ export default defineComponent({