Skip to content

Commit ea9e7e2

Browse files
committed
📂: New Structure Scripts
1 parent 43ee8ba commit ea9e7e2

3 files changed

Lines changed: 383 additions & 0 deletions

File tree

‎src/header.js‎

Lines changed: 206 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,206 @@
1+
import { modules as pages } from "../data/pages.config"
2+
import { minify } from "../helpers/stringMinify"
3+
export class Header {
4+
5+
constructor() {
6+
this.#navigation()
7+
this.sidebar()
8+
}
9+
10+
/**
11+
* Create Munu List
12+
* @returns
13+
*/
14+
#menu = () => {
15+
return (
16+
minify(
17+
String(`
18+
<ul role="menu" class="items-center justify-end gap-1 hidden sm:flex">
19+
${String(pages.map(
20+
page => {
21+
const path = window.location.pathname
22+
const activeByMenu = (
23+
path.replaceAll('/', '').toLocaleLowerCase() == (page.route).toLocaleLowerCase() ||
24+
path.replaceAll('/', '').toLocaleLowerCase() == "" && (page.route).toLocaleLowerCase() == "home"
25+
) ? "active" : null
26+
return (`
27+
<li role="presentation">
28+
<a role="menuitem" href="/${page?.route == "home" ? '' : page?.route}" data-route-name="${page?.route}" class="${activeByMenu} justify-center flex gap-x-2 relative px-2 py-1.5 text-sm font-semibold leading-6 text-gray-900 transition-all rounded-md group whitespace-nowrap hover:ring-black/10 hover:ring-1 hover:dark:ring-white/20 hover:backdrop-blur-sm dark:hover:bg-white/10 dark:text-slate-100 hover:bg-white/20">
29+
${page?.name}
30+
</a>
31+
</li>
32+
`)
33+
}
34+
))}
35+
</ul>
36+
`)
37+
)
38+
)
39+
}
40+
41+
/**
42+
* Brand Logo
43+
* @returns
44+
*/
45+
#logo = () => {
46+
return (`
47+
<div class="flex-shrink-0 w-16 px-4 py-2">
48+
<a href="/" class="pb-2" aria-label="Logo Leat Sophat">
49+
<svg class="inline-block w-full h-8 align-middle sm:h-14 sm:w-14 dark:text-white text-slate-950" viewBox="0 0 512 450" fill="none" xmlns="http://www.w3.org/2000/svg">
50+
<path class="mt-2" fill="currentColor"
51+
d="M48.25 308.581c-1.165 0-2.162.554-2.993 1.662-.776 1.053-1.164 3.963-1.164 8.728 0 4.766.388
52+
7.703 1.164 8.811.83 1.053 1.828 1.58 2.992 1.58s2.134-.527 2.91-1.58c.83-1.108
53+
1.246-4.045 1.246-8.811 0-4.765-.415-7.675-1.247-8.728-.775-1.108-1.745-1.662-2.909-1.662Zm120.527-62.342c0-3.879-4.156-8.035-12.468-12.469v-8.312c0-8.312 4.156-12.468 12.468-12.468h12.469v8.312h-12.469c-2.771
54+
0-4.156 1.385-4.156 4.156v4.156c8.312 4.434 12.469 9.975 12.469 16.625v49.874c0 27.707-12.469
55+
41.561-37.406 41.561-24.937 0-37.405-13.854-37.405-41.561v-16.625c0-22.166-9.698-33.249-29.093-33.249s-29.093
56+
11.083-29.093 33.249V301.1c1.274-.554 2.66-.831 4.156-.831 3.491 0 6.428 1.496 8.811 4.488 2.438 2.937 3.658 7.675 3.658 14.214 0 6.539-1.22
57+
11.305-3.658 14.298-2.383 2.937-5.32 4.405-8.81 4.405-3.492 0-6.457-1.468-8.895-4.405-2.383-2.993-3.574-7.759-3.574-14.298v-39.483c0-18.73
58+
5.07-31.143 15.211-37.239-1.828-2.715-5.514-5.542-11.055-8.479v-8.312c0-8.312 4.156-12.468 12.468-12.468h45.718v8.312H52.405c-2.77 0-4.156 1.385-4.156 4.156v4.156c5.098
59+
2.716 8.645 5.874 10.64 9.476 3.048-.775 7.813-1.163 14.297-1.163 24.937 0 37.405 13.853 37.405 41.561v16.625c0 22.166 9.698 33.249 29.093 33.249 19.396 0 29.093-11.083
60+
29.093-33.249v-49.874Zm8.313 99.747v45.718h-8.313v-45.718h8.313Zm112.215-91.435c-1.163 0-2.161.554-2.992 1.663-.776 1.053-1.164 2.576-1.164 4.571 0 1.995.388 3.547 1.164
61+
4.655.831 1.053 1.829 1.58 2.992 1.58 1.164 0 2.134-.527 2.91-1.58.831-1.108 1.246-2.66 1.246-4.655s-.415-3.518-1.246-4.571c-.776-1.109-1.746-1.663-2.91-1.663Zm4.156
62+
74.811V274.75c-1.274.388-2.659.582-4.156.582-4.045 0-7.148-1.33-9.309-3.99-2.106-2.715-3.159-6.234-3.159-10.557 0-4.322 1.053-7.813 3.159-10.473 2.161-2.715 5.264-4.073 9.309-4.073 4.046 0 7.121 1.358
63+
9.227 4.073 2.161 2.66 3.242 6.151 3.242 10.473v76.889h-12.469l-29.093-24.937-29.093 24.937h-12.468v-91.435c0-3.879-1.385-8.035-4.156-12.469v-4.156c0-11.083 5.541-16.624 16.624-16.624h24.937l19.118 12.468h12.469c3.879 0
64+
5.818-1.939 5.818-5.818v-19.119h8.313v19.119c0 9.42-4.711 14.13-14.131 14.13h-14.962l-19.118-12.468h-22.444c-5.541 0-8.312 2.771-8.312 8.312v.832c2.771 4.433 4.156 9.697 4.156 15.793v83.123l33.249-29.093 33.249 29.093Zm8.313-116.372h16.624c22.166 0 33.249 11.083
65+
33.249 33.249v91.435h-8.312v-91.435c0-16.625-8.312-24.937-24.937-24.937h-16.624v-8.312Zm103.903 95.591c-1.163 0-2.161.554-2.992 1.662-.776 1.053-1.164 3.963-1.164 8.728 0 4.766.388 7.703 1.164 8.811.831 1.053 1.829 1.58 2.992 1.58 1.164 0 2.134-.527 2.91-1.58.831-1.108
66+
1.246-4.045 1.246-8.811 0-4.765-.415-7.675-1.246-8.728-.776-1.108-1.746-1.662-2.91-1.662Zm70.655-95.591v8.312h-83.123v-8.312h83.123Zm-83.123 66.498c0-27.708 13.854-41.561 41.561-41.561 27.708 0 41.562 13.853 41.562 41.561v58.186h-8.313v-58.186c0-22.166-11.083-33.249-33.249-33.249-22.166
67+
0-33.249 11.083-33.249 33.249V301.1c1.275-.554 2.66-.831 4.156-.831 3.491 0 6.428 1.496 8.811 4.488 2.439 2.937 3.658 7.675 3.658 14.214 0 6.539-1.219 11.305-3.658 14.298-2.383 2.937-5.32 4.405-8.811 4.405-3.491
68+
0-6.428-1.496-8.811-4.489-1.884-2.272-3.048-5.624-3.491-10.057h-.166v-43.64ZM52.405 171.786c1.718 0 2.826-.36 3.325-1.081.554-.775.831-1.967.831-3.574 0-1.662-.277-2.854-.83-3.574-.5-.721-1.608-1.136-3.326-1.247v9.476Zm-16.624-68.909c0-27.707
69+
14.075-41.561 42.226-41.561 28.096 0 42.143 13.854 42.143 41.561v41.562c0 16.624 7.62 24.936 22.859 24.936 13.3 0 19.95-8.312 19.95-24.936V94.565c0-4.544-2.771-9.033-8.313-13.466v-7.315c0-8.312 5.265-12.468
70+
15.794-12.468h17.455V77.94h-14.13v.998c6.649 4.433 9.974 9.642 9.974 15.627v49.874c0 27.707-13.576 41.561-40.73 41.561-29.093 0-43.64-13.854-43.64-41.561v-41.562c0-16.624-7.12-24.937-21.362-24.937-14.297 0-21.446 8.313-21.446 24.937v45.219c4.212.332 7.343
71+
1.995 9.393 4.987 2.05 2.937 3.076 7.675 3.076 14.214 0 5.431-1.441 9.92-4.323 13.466-2.881 3.491-6.982 5.237-12.302 5.237-5.32 0-9.42-1.607-12.302-4.821-2.882-3.27-4.322-7.897-4.322-13.882v-64.42Zm147.958-41.561h19.95c28.262 0 42.392 11.083 42.392 33.249V186h-20.78V94.565c0-11.083-7.204-16.625-21.612-16.625h-19.95V61.316Zm120.528 110.47c1.718 0
72+
2.827-.36 3.325-1.081.555-.775.832-1.967.832-3.574 0-1.662-.277-2.854-.832-3.574-.498-.721-1.607-1.136-3.325-1.247v9.476Zm73.149-110.47V77.94h-89.773V61.316h89.773Zm-89.773 66.498c0-27.708 14.962-41.561 44.886-41.561 29.924 0 44.887 13.853 44.887 41.561V186h-20.781v-58.186c0-16.625-8.035-24.937-24.106-24.937-16.07 0-24.105
73+
8.312-24.105 24.937v20.282c4.211.332 7.342 1.995 9.392 4.987 2.051 2.937 3.076 7.675 3.076 14.214 0 5.431-1.441 9.92-4.322 13.466-2.882 3.491-6.983 5.237-12.303 5.237-5.319 0-9.42-1.607-12.302-4.821-2.881-3.27-4.322-7.897-4.322-13.882v-39.483Z">
74+
</path>
75+
</svg>
76+
</a>
77+
</div>
78+
`)
79+
}
80+
81+
82+
/**
83+
* Right Navigation
84+
* @returns
85+
*/
86+
#rightNavigation = () => {
87+
return (`
88+
<div class="flex items-center justify-end gap-3 mr-4">
89+
<button type="button" onclick="toggleTheme()" class="px-3 py-1 text-sm transition-colors border rounded-full border-stone-200 drop-shadow-sm text-stone-800 dark:text-white bg-white/40 dark:bg-black/20 backdrop-blur-lg hover:border-stone-300 dark:border-stone-500 dark:hover:border-stone-400">🌞</button>
90+
<button data-sidebar-toggle aria-label="Menu" class="px-2 py-2 text-sm transition-colors border rounded-full sm:hidden border-stone-200 drop-shadow-sm text-stone-800 dark:text-white bg-white/40 dark:bg-black/20 backdrop-blur-lg hover:border-stone-300 dark:border-stone-500 dark:hover:border-stone-400">
91+
<svg xmlns="http://www.w3.org/2000/svg" class="w-4 h-4" viewBox="0 0 512 512">
92+
<circle cx="256" cy="256" r="32" fill="none" stroke="currentColor" stroke-miterlimit="10" stroke-width="32" />
93+
<circle cx="256" cy="416" r="32" fill="none" stroke="currentColor" stroke-miterlimit="10" stroke-width="32" />
94+
<circle cx="256" cy="96" r="32" fill="none" stroke="currentColor" stroke-miterlimit="10" stroke-width="32" />
95+
</svg>
96+
</button>
97+
<a href="https://github.com/pphatdev" target="_blank" class="flex items-center gap-1">
98+
<svg xmlns="http://www.w3.org/2000/svg" fill="currentColor" class="w-6 h-6 dark:text-white" viewBox="0 0 24 24">
99+
<path d="M12 0c-6.626 0-12 5.373-12 12 0 5.302 3.438 9.8 8.207 11.387.599.111.793-.261.793-.577v-2.234c-3.338.726-4.033-1.416-4.033-1.416-.546-1.387-1.333-1.756-1.333-1.756-1.089-.745.083-.729.083-.729 1.205.084 1.839 1.237 1.839 1.237 1.07 1.834 2.807 1.304 3.492.997.107-.775.418-1.305.762-1.604-2.665-.305-5.467-1.334-5.467-5.931 0-1.311.469-2.381 1.236-3.221-.124-.303-.535-1.524.117-3.176 0 0 1.008-.322 3.301 1.23.957-.266 1.983-.399 3.003-.404 1.02.005 2.047.138 3.006.404 2.291-1.552 3.297-1.23 3.297-1.23.653 1.653.242 2.874.118 3.176.77.84 1.235 1.911 1.235 3.221 0 4.609-2.807 5.624-5.479 5.921.43.372.823 1.102.823 2.222v3.293c0 .319.192.694.801.576 4.765-1.589 8.199-6.086 8.199-11.386 0-6.627-5.373-12-12-12z"/>
100+
</svg>
101+
</a>
102+
</div>
103+
`)
104+
}
105+
106+
/**
107+
* Menu List Item
108+
* @returns
109+
*/
110+
menuList = () => {
111+
return String(pages.map(
112+
page => {
113+
const path = window.location.pathname
114+
const activeByMenu = (
115+
path.replaceAll('/', '').toLocaleLowerCase() == (page.route).toLocaleLowerCase() ||
116+
path.replaceAll('/', '').toLocaleLowerCase() == "" && (page.route).toLocaleLowerCase() == "home"
117+
) ? "text-primary" : ""
118+
return (`
119+
<li>
120+
<a class="hover:text-primary-500 ${activeByMenu} dark:hover:text-primary-400" href="/${page.route == "home" ? '' : page?.route}">${page?.name}</a>
121+
</li>
122+
`)
123+
}
124+
))
125+
}
126+
127+
/**
128+
* Apply sidebar
129+
*/
130+
sidebar = () => {
131+
const sidebar = document.querySelector('#menu')
132+
sidebar.innerHTML = minify(String(this.menuList()))
133+
}
134+
135+
/**
136+
* Main Header Navigation
137+
*/
138+
#navigation = () => {
139+
const header = document.querySelector('#header')
140+
header.innerHTML = minify(`
141+
<nav class="flex items-center justify-between w-full max-w-6xl mx-auto">
142+
${this.#logo()}
143+
${this.#menu()}
144+
${this.#rightNavigation()}
145+
</nav>
146+
`)
147+
}
148+
}
149+
150+
151+
export const activeHeader = () => {
152+
const currentURL = window.location.pathname
153+
const header = document.querySelector('#header')
154+
const match = header.querySelectorAll('ul>li [href]')
155+
const sidebar = document.querySelector('[data-sidebar-target]')
156+
const sidebarMatch = document.querySelectorAll('[data-sidebar-target] ul>li>a')
157+
Array.from(match).forEach(element => {
158+
const matchURL = element.getAttribute('href')
159+
const div = element.querySelector('a>div')
160+
if (matchURL.replaceAll('/', '') === currentURL.replaceAll('/', '')) {
161+
element.classList.add('active')
162+
div.classList.remove('hidden')
163+
div.classList.remove('translate-y-[14px]')
164+
div.classList.add('translate-y-8', 'hover:translate-y-[14px]')
165+
}
166+
})
167+
168+
Array.from(sidebarMatch).forEach(element => {
169+
const match = element.getAttribute('href')
170+
if (match.replaceAll('/', '') === currentURL.replaceAll('/', '')) {
171+
element.classList.add('active')
172+
}
173+
})
174+
}
175+
176+
export const sidebar = () => {
177+
const buttons = document.querySelectorAll('[data-sidebar-toggle]')
178+
179+
180+
Array.from(buttons).forEach(button => {
181+
button.addEventListener('click', () => {
182+
const backdrop = document.querySelector('[data-sidebar-backdrop]')
183+
const content = document.querySelector('[data-sidebar-target]')
184+
try {
185+
if (content.classList.contains('hidden')) {
186+
backdrop.classList.remove('hidden')
187+
content.classList.remove('hidden')
188+
}
189+
else {
190+
backdrop.classList.add('hidden')
191+
content.classList.add('hidden')
192+
}
193+
} catch (error) {
194+
console.log(error);
195+
}
196+
})
197+
})
198+
}
199+
200+
201+
export const toggleTheme = () => {
202+
if (document.querySelector('html').classList.contains("dark"))
203+
document.querySelector('html').classList.remove("dark");
204+
else
205+
document.querySelector('html').classList.add("dark");
206+
}

‎src/index.js‎

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
2+
import { Header, sidebar, toggleTheme } from "./header.js";
3+
import { renderCanvas } from "./render-canvas.js";
4+
5+
6+
document.addEventListener('DomContentLoaded', new Header())
7+
document.addEventListener('DomContentLoaded', codingWith())
8+
document.addEventListener('DomContentLoaded', sidebar())
9+
document.addEventListener('DomContentLoaded', renderCanvas())
10+
11+
12+
if (typeof window !== "undefined") {
13+
window.renderCanvas = renderCanvas
14+
}

‎src/render-canvas.js‎

Lines changed: 163 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,163 @@
1+
function n(e) {
2+
this.init(e || {});
3+
}
4+
5+
n.prototype = {
6+
init: function (e) {
7+
this.phase = e.phase || 0;
8+
this.offset = e.offset || 0;
9+
this.frequency = e.frequency || 0.001;
10+
this.amplitude = e.amplitude || 1;
11+
},
12+
update: function () {
13+
return (
14+
(this.phase += this.frequency), (e = this.offset + Math.sin(this.phase) * this.amplitude)
15+
);
16+
},
17+
value: function () {
18+
return e;
19+
},
20+
};
21+
22+
function Line(e) {
23+
this.init(e || {});
24+
}
25+
26+
Line.prototype = {
27+
init: function (e) {
28+
this.spring = e.spring + 0.1 * Math.random() - 0.05;
29+
this.friction = E.friction + 0.01 * Math.random() - 0.005;
30+
this.nodes = [];
31+
for (var t, n = 0; n < E.size; n++) {
32+
t = new Node();
33+
t.x = pos.x;
34+
t.y = pos.y;
35+
this.nodes.push(t);
36+
}
37+
},
38+
update: function () {
39+
var e = this.spring,
40+
t = this.nodes[0];
41+
t.vx += (pos.x - t.x) * e;
42+
t.vy += (pos.y - t.y) * e;
43+
for (var n, i = 0, a = this.nodes.length; i < a; i++)
44+
(t = this.nodes[i]), 0 < i &&
45+
(
46+
(n = this.nodes[i - 1]),
47+
(t.vx += (n.x - t.x) * e),
48+
(t.vy += (n.y - t.y) * e),
49+
(t.vx += n.vx * E.dampening),
50+
(t.vy += n.vy * E.dampening)
51+
),
52+
(t.vx *= this.friction),
53+
(t.vy *= this.friction),
54+
(t.x += t.vx),
55+
(t.y += t.vy),
56+
(e *= E.tension);
57+
},
58+
draw: function () {
59+
var e, t, n = this.nodes[0].x, i = this.nodes[0].y;
60+
ctx.beginPath();
61+
ctx.moveTo(n, i);
62+
for (var a = 1, o = this.nodes.length - 2; a < o; a++) {
63+
e = this.nodes[a];
64+
t = this.nodes[a + 1];
65+
n = 0.5 * (e.x + t.x);
66+
i = 0.5 * (e.y + t.y);
67+
ctx.quadraticCurveTo(e.x, e.y, n, i);
68+
}
69+
e = this.nodes[a];
70+
t = this.nodes[a + 1];
71+
ctx.quadraticCurveTo(e.x, e.y, t.x, t.y);
72+
ctx.stroke();
73+
ctx.closePath();
74+
},
75+
};
76+
77+
function onMousemove(e) {
78+
function o() {
79+
lines = [];
80+
for (var e = 0; e < E.trails; e++)
81+
lines.push(new Line({ spring: 0.45 + (e / E.trails) * 0.025 }));
82+
}
83+
function c(e) {
84+
e.touches
85+
? ((pos.x = e.touches[0].pageX), (pos.y = e.touches[0].pageY))
86+
: ((pos.x = e.clientX), (pos.y = e.clientY)),
87+
e.preventDefault();
88+
}
89+
function l(e) {
90+
1 == e.touches.length && ((pos.x = e.touches[0].pageX), (pos.y = e.touches[0].pageY));
91+
}
92+
document.removeEventListener('mousemove', onMousemove),
93+
document.removeEventListener('touchstart', onMousemove),
94+
document.addEventListener('mousemove', c),
95+
document.addEventListener('touchmove', c),
96+
document.addEventListener('touchstart', l),
97+
c(e),
98+
o(),
99+
render();
100+
}
101+
102+
function render() {
103+
if (ctx.running) {
104+
ctx.globalCompositeOperation = 'source-over';
105+
ctx.clearRect(0, 0, ctx.canvas.width, ctx.canvas.height);
106+
ctx.globalCompositeOperation = 'lighter';
107+
ctx.strokeStyle = 'hsla(' + Math.round(f.update()) + ',90%,50%,0.25)';
108+
ctx.lineWidth = 1;
109+
for (var e, t = 0; t < E.trails; t++) {
110+
(e = lines[t]).update();
111+
e.draw();
112+
}
113+
ctx.frame++;
114+
window.requestAnimationFrame(render);
115+
}
116+
}
117+
118+
function resizeCanvas() {
119+
ctx.canvas.width = window.innerWidth - 20;
120+
ctx.canvas.height = window.innerHeight;
121+
}
122+
123+
var ctx, f, e = 0, pos = {}, lines = [], E = {
124+
debug: true,
125+
friction: 0.5,
126+
trails: 20,
127+
size: 50,
128+
dampening: 0.25,
129+
tension: 0.98,
130+
};
131+
132+
function Node() {
133+
this.x = 0;
134+
this.y = 0;
135+
this.vy = 0;
136+
this.vx = 0;
137+
}
138+
139+
export const renderCanvas = function () {
140+
ctx = document.getElementById('canvas').getContext('2d');
141+
ctx.running = true;
142+
ctx.frame = 1;
143+
f = new n({
144+
phase: Math.random() * 2 * Math.PI,
145+
amplitude: 85,
146+
frequency: 0.0015,
147+
offset: 285,
148+
});
149+
document.addEventListener('mousemove', onMousemove);
150+
document.addEventListener('touchstart', onMousemove);
151+
document.body.addEventListener('orientationchange', resizeCanvas);
152+
window.addEventListener('resize', resizeCanvas);
153+
window.addEventListener('focus', () => {
154+
if (!ctx.running) {
155+
ctx.running = true;
156+
render();
157+
}
158+
});
159+
window.addEventListener('blur', () => {
160+
ctx.running = true;
161+
});
162+
resizeCanvas();
163+
};

0 commit comments

Comments
 (0)