Rework and finished the boot sequence.

This commit is contained in:
Thomas Cole 2023-03-24 18:59:30 -04:00
parent 80ad010cfd
commit bb8c83bb9b
23 changed files with 800 additions and 109 deletions

View File

@ -1,23 +1,24 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<link rel="icon" type="image/svg+xml" href="/vite.svg" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>thomaspcole.com</title>
<link rel="preconnect" href="https://fonts.googleapis.com" />
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
<link
href="https://fonts.googleapis.com/css2?family=Montserrat:ital,wght@0,100;0,200;0,300;0,400;0,500;0,600;0,700;0,800;0,900;1,100;1,200;1,300;1,400;1,500;1,600;1,700;1,800;1,900&display=swap"
rel="stylesheet"
/>
<link
href="https://fonts.googleapis.com/css2?family=Share+Tech+Mono&display=swap"
rel="stylesheet"
/>
</head>
<body>
<div id="app"></div>
<script type="module" src="/src/main.ts"></script>
</body>
</html>
<head>
<meta charset="UTF-8" />
<link rel="icon" type="image/svg+xml" href="/vite.svg" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>thomaspcole.com</title>
<link rel="preconnect" href="https://fonts.googleapis.com" />
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
<link
href="https://fonts.googleapis.com/css2?family=Montserrat:ital,wght@0,100;0,200;0,300;0,400;0,500;0,600;0,700;0,800;0,900;1,100;1,200;1,300;1,400;1,500;1,600;1,700;1,800;1,900&display=swap"
rel="stylesheet" />
<link href="https://fonts.googleapis.com/css2?family=Share+Tech+Mono&display=swap" rel="stylesheet" />
<link rel="stylesheet"
href="https://fonts.googleapis.com/css2?family=Material+Symbols+Outlined:opsz,wght,FILL,GRAD@20..48,100..700,0..1,-50..200" />
</head>
<body>
<div id="app"></div>
<script type="module" src="/src/main.ts"></script>
</body>
</html>

54
package-lock.json generated
View File

@ -8,7 +8,9 @@
"name": "temppersonal",
"version": "0.0.0",
"dependencies": {
"@types/node": "^18.15.7",
"@types/three": "^0.149.0",
"p5-svelte": "^3.1.2",
"svelte-cubed": "^0.2.1",
"three": "^0.150.1"
},
@ -472,6 +474,17 @@
"@types/unist": "*"
}
},
"node_modules/@types/node": {
"version": "18.15.7",
"resolved": "https://registry.npmjs.org/@types/node/-/node-18.15.7.tgz",
"integrity": "sha512-LFmUbFunqmBn26wJZgZPYZPrDR1RwGOu2v79Mgcka1ndO6V0/cwjivPTc4yoK6n9kmw4/ls1r8cLrvh2iMibFA=="
},
"node_modules/@types/p5": {
"version": "1.5.0",
"resolved": "https://registry.npmjs.org/@types/p5/-/p5-1.5.0.tgz",
"integrity": "sha512-EhaRGjqGcv5lKWvBUfC4Oxi2J5T1C1HuoQnJCdxJJMrRf+HTVdh7hCgBo88nHe6LbUXxkrxVj9tc1zOuemefFA==",
"peer": true
},
"node_modules/@types/pug": {
"version": "2.0.6",
"resolved": "https://registry.npmjs.org/@types/pug/-/pug-2.0.6.tgz",
@ -1273,6 +1286,23 @@
"wrappy": "1"
}
},
"node_modules/p5": {
"version": "1.6.0",
"resolved": "https://registry.npmjs.org/p5/-/p5-1.6.0.tgz",
"integrity": "sha512-RowF+RxfVUhJm/YKXL5TCFzTqnwAIwK6W1VGs9LAqSf3PCmLz9Igbxzlf0Ry5IMV71L42wipCdH/bDiNsqAstA=="
},
"node_modules/p5-svelte": {
"version": "3.1.2",
"resolved": "https://registry.npmjs.org/p5-svelte/-/p5-svelte-3.1.2.tgz",
"integrity": "sha512-lcfWh+cJ1/wRdIXHnjpYmDgj2h3TCy1QJVQnf/cBcFWS8CSkvyAN5F8u8H2U8qBUtZ4XaD3nd+1NoYUMHaMExQ==",
"dependencies": {
"p5": "^1.4.1"
},
"peerDependencies": {
"@types/p5": "^1.4.2",
"p5": "^1.4.0"
}
},
"node_modules/parent-module": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz",
@ -2302,6 +2332,17 @@
"@types/unist": "*"
}
},
"@types/node": {
"version": "18.15.7",
"resolved": "https://registry.npmjs.org/@types/node/-/node-18.15.7.tgz",
"integrity": "sha512-LFmUbFunqmBn26wJZgZPYZPrDR1RwGOu2v79Mgcka1ndO6V0/cwjivPTc4yoK6n9kmw4/ls1r8cLrvh2iMibFA=="
},
"@types/p5": {
"version": "1.5.0",
"resolved": "https://registry.npmjs.org/@types/p5/-/p5-1.5.0.tgz",
"integrity": "sha512-EhaRGjqGcv5lKWvBUfC4Oxi2J5T1C1HuoQnJCdxJJMrRf+HTVdh7hCgBo88nHe6LbUXxkrxVj9tc1zOuemefFA==",
"peer": true
},
"@types/pug": {
"version": "2.0.6",
"resolved": "https://registry.npmjs.org/@types/pug/-/pug-2.0.6.tgz",
@ -2878,6 +2919,19 @@
"wrappy": "1"
}
},
"p5": {
"version": "1.6.0",
"resolved": "https://registry.npmjs.org/p5/-/p5-1.6.0.tgz",
"integrity": "sha512-RowF+RxfVUhJm/YKXL5TCFzTqnwAIwK6W1VGs9LAqSf3PCmLz9Igbxzlf0Ry5IMV71L42wipCdH/bDiNsqAstA=="
},
"p5-svelte": {
"version": "3.1.2",
"resolved": "https://registry.npmjs.org/p5-svelte/-/p5-svelte-3.1.2.tgz",
"integrity": "sha512-lcfWh+cJ1/wRdIXHnjpYmDgj2h3TCy1QJVQnf/cBcFWS8CSkvyAN5F8u8H2U8qBUtZ4XaD3nd+1NoYUMHaMExQ==",
"requires": {
"p5": "^1.4.1"
}
},
"parent-module": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz",

View File

@ -22,7 +22,9 @@
"vite": "^4.2.0"
},
"dependencies": {
"@types/node": "^18.15.7",
"@types/three": "^0.149.0",
"p5-svelte": "^3.1.2",
"svelte-cubed": "^0.2.1",
"three": "^0.150.1"
}

View File

@ -1,60 +1,44 @@
<script lang="ts">
import GlitchText from "./lib/GlitchText.svelte";
import ThreeScene from "./lib/ThreeScene.svelte";
import { onMount } from "svelte";
import Background from "./components/Background.svelte";
import Bootup from "./components/Bootup.svelte";
import Footer from "./components/Footer.svelte";
import NameSplash from "./components/NameSplash.svelte";
import About from "./components/About.svelte";
import Projects from "./components/Projects.svelte";
import Modal from "./utils/Modal.svelte";
let bootDone = false;
let mainContent;
async function finishBoot() {
bootDone = true;
await new Promise((r) => setTimeout(r, 300));
mainContent.classList.add("opacity-100");
}
onMount(() => {
if ("skip_boot" in localStorage) {
console.log("Skipping boot sequence");
finishBoot();
}
});
</script>
<ThreeScene/>
<div class="fixed w-full h-full bg-green-700/20 rounded-3xl border-solid border-2 border-green-300/50">
<div class="absolute screendim"></div>
<div class="absolute scanlines"></div>
</div>
<section class="h-screen relative">
<div class="relative top-1/2 left-1/2 -translate-x-1/2 -translate-y-1/2">
<img class="w-1/4 mx-auto rounded-full aspect-square object-cover mb-6" src="/profile.jpg" alt="">
<h1 class="text-center font-mono text-6xl text-white drop-shadow-screen ">Thomas Cole</h1>
<GlitchText strings={["system administrator", "Linux Enthusiast", "Web Developer", "Network Engineer"]} classVars="text-neutral-50 drop-shadow-screen text-center text-xl font-mono w-fit mx-auto capitalize"/>
</div>
<Background />
<section class="h-screen relative p-4" class:hidden={bootDone}>
<Bootup on:boot_done={finishBoot} />
</section>
<section class="h-screen"></section>
<style>
.scanlines{
background: linear-gradient(
rgb(134,239,172,.15),
rgb(134,239,172,.15) 3px,
transparent 3px,
transparent 9px
);
background-size: 100% 9px;
border-radius: 1.5rem;
height: 100%;
width: 100%;
overflow: hidden;
animation: scan 120s infinite linear;
}
.screendim{
background: radial-gradient(
circle,
rgba(0,0,0,0) 0%,
rgba(0,0,0,0) 50%,
rgba(0,0,0,1) 100%
);
border-radius: 1.5rem;
height: 100%;
width: 100%;
overflow: hidden;
}
@keyframes scan{
from{
background-position: 0% 0%;
}
to{
background-position: 0% -100%;
}
}
</style>
<div
bind:this={mainContent}
class="trasnition-all ease-in duration-300 opacity-0"
class:hidden={!bootDone}
>
<NameSplash />
<div class="py-6" />
<About />
<div class="py-6" />
<Projects />
<Footer />
</div>

View File

@ -10,4 +10,5 @@ body {
-ms-overflow-style: none;
scrollbar-width: none;
background-color: black;
user-select: none;
}

View File

@ -0,0 +1,17 @@
<script lang="ts">
</script>
<section
id="projects"
class="w-5/6 lg:xl:w-4/5 mx-auto font-mono text-neutral-50 rounded-xl drop-shadow-screen p-4 border-2 border-solid border-green-700"
>
<p class="font-bold text-2xl pb-6 ">&gt; About Me</p>
<p>
Detail oriented IT professional with 5+ years in systems and network
administration. Excellent problem-solving skills and ability to perform
well in a team. Responsible for operation and maintenance of a
multicampus enterprise network with 500+ average daily users.
Demonstrated experience in reducing operating expenses by implementing
open-source solutions and services.
</p>
</section>

View File

@ -0,0 +1,46 @@
<div
class="fixed w-full h-screen top-0 left-0 bg-green-700/20 rounded-3xl border-solid border-2 border-green-300/50 -z-10 "
>
<div class="absolute screendim" />
<div class="absolute scanlines" />
</div>
<style>
.scanlines {
background: linear-gradient(
rgb(134, 239, 172, 0.15),
rgb(134, 239, 172, 0.15) 3px,
transparent 3px,
transparent 9px
);
background-size: 100% 9px;
border-radius: 1.5rem;
height: 100%;
width: 100%;
overflow: hidden;
animation: scan 120s infinite linear;
}
.screendim {
background: radial-gradient(
circle,
rgba(0, 0, 0, 0) 0%,
rgba(0, 0, 0, 0) 70%,
rgba(0, 0, 0, 1) 100%
);
border-radius: 1.5rem;
height: 100%;
width: 100%;
overflow: hidden;
}
@keyframes scan {
from {
background-position: 0% 0%;
}
to {
background-position: 0% -100%;
}
}
</style>

View File

@ -0,0 +1,82 @@
<script lang="ts">
import { onMount, createEventDispatcher } from "svelte";
import Progress from "../utils/Progress.svelte";
const dispatch = createEventDispatcher();
let bootStage1;
let bootStage2;
let hexDumpContainer;
let percentage = 0;
onMount(async ()=>{
await bootPart1();
await bootPart2();
})
function makeConsoleString(text:string){
const e = document.createElement('p');
e.className = baseTextClass;
e.innerText = text;
return e;
}
function generateHexString(){
return "0x" + (Math.random()*4096).toString(16).replace('.','').slice(0,8).toUpperCase();
}
async function bootPart1() {
bootStage1.insertBefore(makeConsoleString("> System Boot Start..."), hexDumpContainer);
await sleep(100);
for (let i = 0; i <4 ; i++) {
var hexCol = document.createElement('div');
hexCol.className = "flex flex-col mr-4"
hexDumpContainer.appendChild(hexCol);
for (let j = 0; j<16; j++){
hexCol.appendChild(makeConsoleString(generateHexString()));
await sleep(50);
}
}
await sleep(500);
bootStage1.appendChild(makeConsoleString("> Boot ROM Initialized"));
await sleep(750);
bootStage1.appendChild(makeConsoleString("> Checking Integrity"));
await sleep(750);
bootStage1.appendChild(makeConsoleString("> Checksums OK"));
await sleep(750);
bootStage1.appendChild(makeConsoleString("> Starting DisplayOS"));
await sleep(2000);
bootStage1.classList.add("hidden");
}
async function bootPart2(){
bootStage2.classList.remove("hidden");
await sleep(500)
while(percentage < 100){
percentage += 10;
await sleep(Math.random()*500);
}
bootStage2.classList.add("opacity-0");
await sleep(300);
dispatch("boot_done");
}
async function sleep(delay:number){
await new Promise(r => setTimeout(r, delay));
}
const baseTextClass = "text-neutral-50 drop-shadow-screen text-xl font-mono";
</script>
<div bind:this={bootStage1}>
<div bind:this={hexDumpContainer} class="flex flex-row"/>
</div>
<div bind:this={bootStage2} class="hidden w-full h-full transition-all duration-300 ease-out">
<div class="relative top-1/2 left-1/2 -translate-x-1/2 -translate-y-1/2 text-center">
<img class="w-1/5 mx-auto" src="/vite.svg" alt="" draggable="false">
<div class="h-2 w-4/5 mx-auto mt-8 relative drop-shadow-screen bg-green-700 rounded-md">
<Progress color="#fafafa" percentage={percentage}/>
</div>
</div>
</div>

View File

@ -0,0 +1,12 @@
<footer
class="w-5/6 xl:lg:w-4/5 mx-auto text-neutral-50 drop-shadow-screen font-mono font-light m-2 p-4"
>
<div class="flex gap-4 place-content-center underline">
<a href="mailto:thomas.patrick.cole@gmail.com">Contact</a>
<a href="https://github.com/thomaspcole">Github</a>
<a href="https://git.thomaspcole.com/thomascole">Gitea</a>
<a href="https://www.linkedin.com/in/thomaspcole/">Linkedin</a>
</div>
<br />
<p class="text-sm text-center font-sans">&copy; 2023 Thomas Cole</p>
</footer>

View File

@ -0,0 +1,30 @@
<script>
import GlitchText from "../utils/GlitchText.svelte";
</script>
<section id="top" class="h-screen">
<div class="relative top-1/2 left-1/2 -translate-x-1/2 -translate-y-1/2">
<img
class="w-1/2 lg:xl:w-1/4 mx-auto rounded-full aspect-square object-cover mb-6"
src="/profile.jpg"
alt=""
/>
<h1
class="text-center font-mono text-4xl lg:xl:text-6xl text-neutral-50 drop-shadow-screen "
>
Thomas Cole
</h1>
<GlitchText
strings={[
"system administrator",
"linux enthusiast",
"web developer",
"network engineer",
]}
classVars="text-neutral-50 drop-shadow-screen text-center text-xl lg:xl:text-2xl font-mono w-fit mx-auto capitalize"
/>
</div>
<span class="material-symbols-outlined absolute bottom-[10px] left-1/2 -translate-x-1/2 text-neutral-50 drop-shadow-screen text-4xl lg:xl:text-6xl animate-[pulse_4s_cubic-bezier(0.4,0,0.6,1)_infinite]">
expand_more
</span>
</section>

10
src/components/Nav.svelte Normal file
View File

@ -0,0 +1,10 @@
<script lang="ts">
</script>
<section class="h-[10vh] w-5/6 lg:xl:w-4/5 mx-auto text-neutral-50 drop-shadow-screen font-mono">
<div class="flex flex-col text-2xl">
<p>&gt; <a href="#projects" class="underline">Latest Projects</a></p>
<p>&gt; <a href="#about" class="underline">About Me</a></p>
</div>
</section>

View File

@ -0,0 +1,14 @@
<script lang="ts">
import ProjectCard from "../utils/ProjectCard.svelte";
import LocalDemo from "../utils/LocalDemo.svelte";
import Quicksort from "../demos/quicksort.svelte";
</script>
<section
id="projects"
class="w-5/6 lg:xl:w-4/5 mx-auto font-mono text-neutral-50 rounded-xl drop-shadow-screen p-4 border-2 border-solid border-green-700"
>
<p class="font-bold text-2xl pb-6 ">&gt; Projects and Demos</p>
<ProjectCard title="Pedal-pi" subtitle="A custom effects processor using MODEP" image="https://images.unsplash.com/photo-1511203438670-49f8ea8441c6?ixlib=rb-4.0.3&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=1470&q=80" link="#" callback={undefined}/>
<LocalDemo title="Quicksort Demo" subtitle="A simple visualization of the quicksort algorithm using p5.js" modalComponent="" image="https://images.unsplash.com/photo-1669399213378-2853e748f217?ixlib=rb-4.0.3&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=1632&q=80"/>
</section>

View File

@ -0,0 +1,119 @@
<script lang="ts">
import ResumeItem from "../utils/ResumeItem.svelte";
</script>
<section
id="about"
class="w-5/6 lg:xl:w-4/5 mx-auto font-mono text-neutral-50 rounded-xl drop-shadow-screen p-4 border-2 border-solid border-green-700"
>
<a href="#top" class="text-sm font-thin underline">Back to Top</a>
<!-- <a href="#top" class="text-sm font-thin underline">Download as PDF</a> -->
<p class="font-bold text-2xl py-6 ">&gt; Work Experience</p>
<ResumeItem
title="Director Of Information Technology"
subtitle="Christ Lutheran Church | December 2020 - Present"
>
<ul class="mt-2 mb-4">
<li>
&gt; Maintain and upgrade critical network infrastructure for a
multi-campus environment.
</li>
<li>&gt; Facilitate backups and ensure their integrity.</li>
<li>
&gt; Integrate with action teams to develop technology plans and
solutions.
</li>
<li>
&gt; Implement new software and hardware solutions with
increased functionality while reducing costs by $50,000/yr.
</li>
</ul>
</ResumeItem>
<ResumeItem
title="Tech Associate"
subtitle="Christ Lutheran Church | August 2019 - December 2020 (Part Time)"
>
<ul class="mt-2 mb-4">
<li>
&gt; Develop and implement new strategies in collaboration with
the Christ Providence Tech team to improve live stream services
and reach a broader audience.
</li>
<li>
&gt; Facilitated building and installation of new computer
systems to improve recording and streaming capabilities of
worship services.
</li>
<li>
&gt; Run graphics for in house worship and live stream services.
</li>
</ul>
</ResumeItem>
<ResumeItem
title="Tier II Managed Services Technician"
subtitle="ScanOnline | June 2019 - December 2020"
>
<ul class="mt-2 mb-4">
<li>
&gt; Administer Office 365 and Windows Active Directory
infrastructure.
</li>
<li>
&gt; Manage company VOIP phone system and extension listings.
</li>
<li>
&gt; Deploy and configure virtual machines to align with
business needs.
</li>
<li>
&gt; Develop new Android applications to suit the business needs
of customers operating in the logistics industry.
</li>
<li>
&gt; Maintain legacy Windows Mobile applications for existing
customers.
</li>
<li>
&gt; Preform configuration and maintenance of customer hardware
and software.
</li>
</ul>
</ResumeItem>
<ResumeItem
title="Student Network Analyst"
subtitle="University of North Carolina at Greensboro | February 2018 - May 2019"
>
<ul class="mt-2 mb-4">
<li>
&gt; Assisted in maintenance and troubleshooting of enterprise
network systems.
</li>
<li>
&gt; Preformed on-boarding of new network devices at the
physical level.
</li>
</ul>
</ResumeItem>
<p class="font-bold text-2xl py-6 ">&gt; Education</p>
<ResumeItem
title="The University of North Carolina at Greensboro"
subtitle=""
>
<ul class="mt-2 mb-4">
<li>
&gt; Bachelor Of Science Information Systems and Supply Chain
Management
</li>
<li>&gt; Minor in Computer Science</li>
</ul>
</ResumeItem>
<p class="font-bold text-2xl py-6 ">&gt; Professional Certifications</p>
<ResumeItem title="Dante Level 3" subtitle="">
<ul class="mt-2 mb-4">
<li>&gt; Audinate | Certificate earned March 2021</li>
</ul>
</ResumeItem>
</section>

195
src/demos/quicksort.svelte Normal file
View File

@ -0,0 +1,195 @@
<script lang="ts">
import P5, { type Sketch } from "p5-svelte";
import { onMount } from "svelte";
// Demo modified from a very old p5js sketch written in college.
// The original was part of a the application process to work for the university IT department
// https://github.com/thomaspcole/p5QuicksortVisualization
let data = [];
let animArray = [];
let valuesToGenerate = 200;
let frame = 0;
let parentContainer;
let sketch:Sketch;
//Added controls for play/pause and stepping frame by frame.
let playpause = false;
onMount(()=>{
const sketchWidth = parentContainer.offsetWidth;
const barWidth = (sketchWidth-20)/valuesToGenerate;
sketch = (p5) => {
p5.setup = () => {
for (let i = 0; i < valuesToGenerate; i++) {
data[i]=(i%700);
}
p5.shuffle(data, true)
quicksort(data, 0, data.length-1);
animArray.push(new arrayFrame(data.toString(), null, null, null));
//setup the canvas
p5.createCanvas(sketchWidth,400);
p5.frameRate(30);
}
p5.draw = () => {
if(playpause){
if(frame == animArray.length-1){
playpause = !playpause;
} else {
drawFrame(frame);
frame++;
}
} else {
drawFrame(frame);
}
}
function drawFrame(index){
let dataFrame = animArray[index];
p5.background(28);
for (var i = 0; i < valuesToGenerate; i++){
p5.fill(255)
if(dataFrame.midIndex == i){
p5.fill(255,0,0);
}
if(dataFrame.lowVal == i || dataFrame.highVal == i){
p5.fill(0,255,0);
}
p5.rect(barWidth*i+10,350, barWidth,-dataFrame.getArray()[i]);
}
}
}
})
/**
* Copied directly from original code
* @param array the array of data being worked on
* @param low the low values
* @param high the high value
*/
function quicksort(array, low, high){
animArray.push(new arrayFrame(array.toString(), 0, array.length, 0));
//Do we need to sort?
if(low >= high){
return;
}
//Pick a pivot point in the middle of the passed array.
let mid = Math.floor(low + ((high-low) / 2));
let pivot = array[mid];
let l = low;
let h = high;
while(l <= h){
while(array[l] < pivot){
l++;
}
while(array[h] > pivot){
h--;
}
if(l <= h){
//console.log(array, l, h, mid);
//console.log("Switch: " + array[l] + ":" + array[h]);
animArray.push(new arrayFrame(array.toString(), l, h, mid));
let tmp = array[l];
array[l] = array[h];
array[h] = tmp;
l++;
h--;
}
}
if(low < h){
quicksort(array, low, h);
}
if(high > l){
quicksort(array, l, high);
}
}
/**
* Constructor for a arrayFrame object
* @param arrayState the array of data at a current point in time
* @param lowVal the low index
* @param highVal the high midIndex
* @param midIndex the pivot index
* @param getArray Returns the array at the current time
*/
function arrayFrame(arrayState, lowVal, highVal, midIndex){
this.arrayState = arrayState;
this.lowVal = lowVal;
this.highVal = highVal;
this.midIndex = midIndex;
this.getArray = function(){
return this.arrayState.split(",");
}
}
function prevFrame(){
if(frame == 0){
return;
}
frame--;
}
function nextFrame(){
if(frame == animArray.length-1){
return;
}
frame++;
}
function reset(){
frame=0;
}
</script>
<div bind:this={parentContainer} class="w-full">
<P5 {sketch}/>
</div>
<div class="flex justify-evenly mt-6 mb-4">
<button on:click={prevFrame}>
<span class="material-symbols-outlined">
skip_previous
</span>
</button>
<button on:click={()=>{
if(frame==animArray.length-1){
reset();
} else {
playpause = !playpause;
}
}}>
{#if playpause}
<span class="material-symbols-outlined">
pause
</span>
{:else if frame==animArray.length-1}
<span class="material-symbols-outlined">
restart_alt
</span>
{:else}
<span class="material-symbols-outlined">
play_arrow
</span>
{/if}
</button>
<button on:click={nextFrame}>
<span class="material-symbols-outlined">
skip_next
</span>
</button>
</div>

View File

@ -1,26 +0,0 @@
<script>
import * as THREE from 'three';
import * as SC from 'svelte-cubed';
let y;
$: camZpos = (y*.1)+1;
//Animation callback
SC.onFrame(()=>{
});
</script>
<svelte:window bind:scrollY={y}/>
<SC.Canvas>
<SC.Mesh
geometry={new THREE.BoxGeometry()}
material={new THREE.MeshStandardMaterial({
color: 0xff00ff
})}
/>
<SC.PerspectiveCamera position={[0,0,camZpos]}/>
<SC.AmbientLight intensity={0.6} />
<SC.DirectionalLight intensity={0.6} position={[-2, 3, 2]} />
</SC.Canvas>

1
src/utils/Divider.svelte Normal file
View File

@ -0,0 +1 @@
<div class="my-6 h-0.5 mx-auto bg-neutral-50 drop-shadow-screen rounded"/>

View File

@ -36,19 +36,19 @@
}
itterations ++;
}, 30);
}, 40);
}
onMount(()=>{
stringIndex = Math.floor(Math.random()*strings.length)
pickNextWord();
setInterval(pickNextWord,5000);
})
</script>
<style>
</style>
<!-- svelte-ignore a11y-mouse-events-have-key-events -->
<p class={classVars} on:mouseover={pickNextWord}>
<!-- <p class={classVars} on:mouseover={pickNextWord}> -->
<p class={classVars}>
{text}
</p>

View File

@ -0,0 +1,23 @@
<script lang="ts">
import ProjectCard from "./ProjectCard.svelte";
import Modal from "./Modal.svelte";
import type { SvelteComponent } from "svelte";
import Quicksort from "../demos/quicksort.svelte";
export let image:string;
export let title:string;
export let subtitle:string;
export let modalComponent:string;
let showModal = false;
function callback(){
showModal = true;
}
</script>
<ProjectCard title={title} subtitle={subtitle} image={image} link={undefined} callback={callback}/>
<Modal bind:showModal>
<!-- <svelte:component this={modalComponent.component}/> -->
<Quicksort/>
</Modal>

64
src/utils/Modal.svelte Normal file
View File

@ -0,0 +1,64 @@
<script>
//Modal from example on svelte website. https://svelte.dev/examples/modal
export let showModal;
let dialog;
$: if (dialog && showModal) dialog.showModal();
</script>
<!-- svelte-ignore a11y-click-events-have-key-events -->
<dialog
bind:this={dialog}
on:close={() => (showModal = false)}
on:click|self={() => dialog.close()}
class="w-4/5"
>
<div on:click|stopPropagation>
<slot name="header"/>
<hr>
<slot />
<hr />
<!-- svelte-ignore a11y-autofocus -->
<button autofocus on:click={() => dialog.close()}>close modal</button>
</div>
</dialog>
<style>
dialog {
max-width: 32em;
width: 80%;
border-radius: 0.2em;
border: none;
padding: 0;
}
dialog::backdrop {
background: rgba(0, 0, 0, 0.3);
}
dialog > div {
padding: 1em;
}
dialog[open] {
animation: zoom 0.3s cubic-bezier(0.34, 1.56, 0.64, 1);
}
@keyframes zoom {
from {
transform: scale(0.95);
}
to {
transform: scale(1);
}
}
dialog[open]::backdrop {
animation: fade 0.2s ease-out;
}
@keyframes fade {
from {
opacity: 0;
}
to {
opacity: 1;
}
}
button {
display: block;
}
</style>

21
src/utils/Progress.svelte Normal file
View File

@ -0,0 +1,21 @@
<script lang="ts">
export let percentage: number | 0;
export let color: string | "#FFFFFF";
</script>
<div
class="progress left rounded-md"
style="background-color: {color}; clip-path: polygon(0% 0%, 0% 100%, {percentage}% 100%, {percentage}% 0%);"
/>
<style>
.progress {
position: absolute;
top: 0;
bottom: 0;
left: 0;
right: 0;
transition: 0.4s clip-path;
clip-path: polygon(0% 0%, 0% 100%, 0% 100%, 0% 0%);
}
</style>

View File

@ -0,0 +1,30 @@
<script lang="ts">
export let link:string;
export let image:string;
export let title:string;
export let subtitle:string;
export let callback;
let url;
if(typeof link === undefined){
url = "javascript:void(0)"
} else {
url = link;
}
if(typeof callback === undefined){
callback = ()=>{};
}
</script>
<div class="rounded-lg transition ease-in-out hover:scale-[101%]">
<a href={url} on:click={callback}>
<div class="ml-2 my-2 flex flex-col sm:flex-col md:flex-col lg:flex-row xl:flex-row 2xl:flex-row w-11/12 mx-auto">
<img class="h-28 my-2 aspect-video object-cover rounded-lg" src={image} alt="">
<div class="lg:ml-4 xl:ml-4 2xl:ml-4 grow">
<p class="mt-2 font-semibold text-2xl py-2 sm:text-2xl md:text-2xl lg:text-3xl xl:text-3xl 2xl:text-3xl">{title}</p>
<p>{subtitle}</p>
</div>
</div>
</a>
</div>

View File

@ -0,0 +1,11 @@
<script lang="ts">
export let title: string;
export let subtitle: string;
</script>
<div class="px-5">
<p class="text-xl font-bold">{title}</p>
<p class="">{subtitle}</p>
<hr />
<slot />
</div>

View File

@ -15,6 +15,6 @@
"checkJs": true,
"isolatedModules": true
},
"include": ["src/**/*.d.ts", "src/**/*.ts", "src/**/*.js", "src/**/*.svelte"],
"include": ["./**/*.d.ts", "./**/*.ts", "./**/*.js", "./**/*.svelte"],
"references": [{ "path": "./tsconfig.node.json" }]
}