Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .env
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
VITE_ROOT = "https://auth.zoe.rip"
1 change: 1 addition & 0 deletions .env.development
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
VITE_ROOT = "127.0.0.1"
9 changes: 9 additions & 0 deletions environment.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
declare global {
namespace NodeJS {
interface ProcessEnv {
VITE_ROOT : "127.0.0.1:8099" | "https://auth.zoe.rip"
}
}
}

export {}
40 changes: 37 additions & 3 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 2 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,13 @@
"preview": "vite preview"
},
"dependencies": {
"typescript": "^5.9.3",
"vue": "^3.5.18",
"vue-router": "^4.6.3"
},
"devDependencies": {
"@vitejs/plugin-vue": "^6.0.1",
"@vue/tsconfig": "^0.8.1",
"vite": "^7.1.2"
}
}
43 changes: 42 additions & 1 deletion src/components/CRTContainer.vue
Original file line number Diff line number Diff line change
Expand Up @@ -9,24 +9,63 @@
</template>

<script setup>
import { onUnmounted } from "vue"
import { onMounted, onUnmounted } from "vue"
import { RouterView } from "vue-router"
import { resetElementShadow, updateShadowPos } from "../composables/glow"

import Navigation from "./Navigation.vue"
import CursorGlow from "./CursorGlow.vue"

const appendClass = (selector, className, delay = 0, first) => {
(first ? [document.querySelector(`${selector}:not(.${className})`)].filter(Boolean) : document.querySelectorAll(selector)).forEach(e => setTimeout(() => e.classList.add(className), delay))
}
const removeClass = (selector, className) => {
document.querySelectorAll(selector).forEach(e => e.classList.remove(className))
}

onMounted(() => {
appendClass(".crtContainer", "vignette")
})

// cleanup
onUnmounted(() => {
removeClass(".crtContainer", "vignette")
})

</script>

<style>
@keyframes type {
from { width: 0; }
to { width: 100% }
}

@keyframes backspace {
from { width: 100% }
to { width: 0; }
}

@keyframes grow {
from { height: 0 }
to { height: auto }
}

@keyframes grow {
from { height: auto }
to { height: 0 }
}

@keyframes slideUp {
from { max-height: 100vh }
to { max-height: 0 }
}

@keyframes slideDown {
from { max-height: 0 }
to { max-height: 100vh }
}
</style>

<style scoped>
* {
color: #42b983;
Expand All @@ -49,6 +88,7 @@ onUnmounted(() => {
will-change: border, border-radius, box-shadow, padding;
transition: border 2s cubic-bezier(0.75, 1, 0.25, 1), border-radius 2s cubic-bezier(0.75, 1, 0.25, 1), box-shadow 2s cubic-bezier(0.75, 1, 0.25, 1), padding 2s cubic-bezier(0.75, 1, 0.25, 1);


&::after {
background-color: #2F2F35;
color: #2F2F35;
Expand All @@ -73,6 +113,7 @@ onUnmounted(() => {
will-change: border, border-radius, box-shadow, padding;
/* transition: border 2s cubic-bezier(0.75, 1, 0.25, 1), border-radius 2s cubic-bezier(0.75, 1, 0.25, 1); */
transition: all 2s ease-in;
pointer-events: none;
}

&.vignette {
Expand Down
175 changes: 175 additions & 0 deletions src/components/Console.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,175 @@
<template>
<div>
<div>
<div id="consoleOutput" ref="outputEl">
<Navigation @handleClick="typeIntoInput" />
</div>
</div>
<div style="position: relative;">
<div id="caret" ref="caretEl" :style="caretStyle" />
<span id="consoleInput-container">
<input id="consoleInput"
autofocus
autocorrect="false"
autocomplete="false"
autocapitalize="false"
autosave="false"
spellcheck="false"
@input="scheduleUpdate"
@keydown="scheduleUpdate"
@click="scheduleUpdate"
@keyup.enter="sendCommand"
ref="inputEl"
/>
</span>
</div>
</div>
</template>

<script setup>
import { computed, nextTick, onMounted, onUnmounted, ref } from 'vue'
import { useRouter } from 'vue-router'
import { useCaret } from "../composables/caret"
import Navigation from './Navigation.vue'

const props = defineProps(['delay'])
const router = useRouter()

const outputEl = ref(null)
const inputEl = ref(null)

const appendToOutput = text => {
const vEl = document.createElement("p")
vEl.innerHTML = text
const oEl = outputEl.value
// random small delay to help prevent spam
setTimeout(() => oEl.appendChild(vEl), Math.random() * 250)
}

const sendCommand = (e) => {
const input = e.target.value
appendToOutput(input)
// process command

const [command, ...args] = input.split(" ")
if (command === "cd") {
setTimeout(() => navigateTo(args[0]), 750)
} else {
appendToOutput(`unknown command: ${command}`)
}
// reset input
e.target.value = ""
}

// simulate running commands
const typeIntoInput = text => {
const iEl = inputEl.value
if (!iEl) return
for (let char in text.split("")) {
setTimeout(() => iEl.dispatchEvent(new KeyboardEvent("keyup", { key: char })), 75)
}
iEl.dispatchEvent(new KeyboardEvent("keyup", {
key: "enter"
}))
}

const navigateTo = (path) => {
if (path === "..") {
router.back()
} else {
try {
router.push({path: path})
} catch {
try {
router.push({ name: path })
} catch {
appendToOutput(`path "${path}" not found.`)
}
}
}
}

// caret positioning
const caretEl = ref(null)
const text = ref(null)

const {caretStyle, scheduleUpdate} = useCaret({
target: inputEl,
caret: caretEl
})


onMounted(() => {
// delay showing until ready
const inputContainer = document.querySelector("#consoleInput-container:not(.shown)")
inputContainer.setAttribute("style", `animation: type 1s steps(1, end) ${props.delay}s;`)
setTimeout(() => inputContainer.classList.add("shown"), props.delay * 1001)
})

</script>

<style scoped>
#consoleOutput {
text-align: left;
}

#consoleInput {
color:#42b983ee;
caret-color: transparent;
background: transparent;
border: none;
width: 100%;
line-height: 1.25rem;
font-family:'Courier New', Courier, monospace;
font-size: 1rem;
text-shadow: 0 0 1rem #42b983aa;

align-self: flex-start;

&:focus {
border: none;
outline: none;
}

}

#consoleInput-container {
position: relative;
display: block;
width: 0;
height: 0;

&.shown {
width: 100%;
height: auto;

&::before {
content: ">";
}
}
&::before {
content: "";
position: absolute;
left: -1.25rem;
font-weight: 600;
line-height: 1.25;
}
}
</style>

<style>
#caret {
visibility: hidden;
}

@keyframes blink {
0% {opacity: 1}
50% {opacity: 0}
100% { opacity: 1}
}

.blinking {
visibility: visible !important;
animation: blink 1s step-end infinite
}
</style>
27 changes: 0 additions & 27 deletions src/components/Counter.vue

This file was deleted.

1 change: 1 addition & 0 deletions src/components/CursorGlow.vue
Original file line number Diff line number Diff line change
Expand Up @@ -13,5 +13,6 @@
width: 3rem;
aspect-ratio: 1 / 1;
border-radius: 100%;
pointer-events: none;
}
</style>
Loading