Compare commits

..

4 Commits

Author SHA1 Message Date
metacryst
07b42ccbc3 partiful link 2026-01-22 19:21:38 -06:00
metacryst
f1c7c340f9 new quill 2025-12-26 06:13:29 -06:00
metacryst
f8861666dd cleaning 2025-12-19 04:49:28 -06:00
metacryst
cd5f92b55f making loading faster 2025-12-19 04:34:53 -06:00
8 changed files with 106 additions and 195 deletions

View File

@@ -1,6 +1,7 @@
/* /*
Sam Russell Sam Russell
Captured Sun Captured Sun
12.26.25 - State for arrays, nested objects. State for stacks (Shadow-only)
12.17.25 - [Hyperia] - adding width, height functions. adding "e" to onClick. adding the non-window $$ funcs. 12.17.25 - [Hyperia] - adding width, height functions. adding "e" to onClick. adding the non-window $$ funcs.
12.16.25 - [comalyr] - State 12.16.25 - [comalyr] - State
11.25.25.1 - Added minHeight and minWidth to be counted as numerical styles 11.25.25.1 - Added minHeight and minWidth to be counted as numerical styles
@@ -228,25 +229,58 @@ window.register = (el, tagname) => {
window[el.prototype.constructor.name] = function (...params) { window[el.prototype.constructor.name] = function (...params) {
let instance = new el(...params) let instance = new el(...params)
if(instance.state) { if(instance.state) {
let proxy = new Proxy(instance.state, { const proxyCache = new WeakMap();
get(target, prop, receiver) {
if (typeof prop === "symbol") { // Ignore internal / symbol accesses
return Reflect.get(target, prop, receiver);
}
quill.lastLastState = quill.lastState function reactive(value, path=[]) {
quill.lastState = prop; if (value && typeof value === "object") {
return Reflect.get(target, prop, receiver); if (proxyCache.has(value)) return proxyCache.get(value);
},
set(target, prop, value, receiver) {
const oldValue = target[prop];
if (oldValue === value) return true;
const result = Reflect.set(target, prop, value, receiver); const p = new Proxy(value, createHandlers(path));
instance.stateWatchers[prop].forEach((cb) => cb()) proxyCache.set(value, p);
return result; return p;
} }
}); return value;
}
function isNumericKey(prop) {
return typeof prop === "string" && prop !== "" && String(+prop) === prop;
}
function createHandlers(path) {
return {
get(target, prop, receiver) {
if (typeof prop === "symbol") {
return Reflect.get(target, prop, receiver);
}
let nextPath = (Array.isArray(target) && !isNumericKey(prop)) ? path : path.concat(prop) // To filter out arr.length, arr.map, arr.forEach, etc.
quill.lastState = nextPath.join(".");
const v = Reflect.get(target, prop, receiver);
return reactive(v, nextPath);
},
set(target, prop, value, receiver) {
const oldLength = Array.isArray(target) ? target.length : undefined;
const oldValue = target[prop];
if (oldValue === value) return true;
const result = Reflect.set(target, prop, value, receiver);
let changedPath = (Array.isArray(target) && (!isNumericKey(prop) || target.length !== oldLength)) ? path : path.concat(prop).join("."); // To filter out arr.length, arr.map, arr.forEach, and also a push/pop/unshift.
const watchers = instance.stateWatchers[changedPath];
if (watchers) {
watchers.forEach(cb => cb());
}
return result;
}
};
}
let proxy = reactive(instance.state)
Object.defineProperty(instance, "state", { Object.defineProperty(instance, "state", {
value: proxy, value: proxy,
writable: false, writable: false,
@@ -520,12 +554,6 @@ HTMLElement.prototype.fontSize = StyleFunction(function(value, unit = "px") {
return this return this
}) })
function checkPositionType(el) {
let computed = window.getComputedStyle(el).position
if(!(computed === "absolute" || computed === "fixed")) {
el.style.position = "absolute"
}
}
HTMLElement.prototype.width = function(value, unit = "px") { HTMLElement.prototype.width = function(value, unit = "px") {
if ((typeof value !== 'number' && value !== "auto") || Number.isNaN(value)) if ((typeof value !== 'number' && value !== "auto") || Number.isNaN(value))
@@ -547,6 +575,13 @@ HTMLElement.prototype.height = function(value, unit = "px") {
return this return this
} }
function checkPositionType(el) {
let computed = window.getComputedStyle(el).position
if(!(computed === "absolute" || computed === "fixed")) {
el.style.position = "absolute"
}
}
HTMLElement.prototype.x = function(value, unit = "px") { HTMLElement.prototype.x = function(value, unit = "px") {
if (typeof value !== 'number' || isNaN(value)) if (typeof value !== 'number' || isNaN(value))
throw new Error(`Invalid value: ${value}. Expected a number.`); throw new Error(`Invalid value: ${value}. Expected a number.`);
@@ -788,61 +823,47 @@ window.textarea = function(placeholder = "") {
/* STACKS */ /* STACKS */
window.VStack = function (cb = () => {}) { handleStack = function(cb, name, styles="") {
let styles = `
display: flex;
flex-direction: column;
`
let nowRendering = quill.rendering[quill.rendering.length-1] let nowRendering = quill.rendering[quill.rendering.length-1]
if (nowRendering.innerHTML.trim() === "" && !quill.isStack(nowRendering)) { if (nowRendering.innerHTML.trim() === "" && !quill.isStack(nowRendering)) {
nowRendering.style.cssText += styles nowRendering.style.cssText += styles
nowRendering.classList.add("VStack") nowRendering.classList.add(name)
cb() cb()
if(quill.lastState) {
nowRendering.addStateWatcher(quill.lastState, () => {
nowRendering.innerHTML = ""
cb()
})
}
return nowRendering return nowRendering
} else {
let div = document.createElement("div")
div.classList.add(name)
div.style.cssText += styles
div.render = cb
quill.render(div)
return div
} }
}
let div = document.createElement("div") window.VStack = function (cb = () => {}) {
div.classList.add("VStack") let styles = `
div.style.cssText += styles display: flex;
div.render = cb flex-direction: column;
quill.render(div) `
return div return handleStack(cb, "VStack", styles)
} }
window.HStack = function (cb = () => {}) { window.HStack = function (cb = () => {}) {
let styles = ` let styles = `
display: flex; display: flex;
flex-direction: row; flex-direction: row;
`; `;
let nowRendering = quill.rendering[quill.rendering.length - 1]; return handleStack(cb, "HStack", styles)
if (nowRendering.innerHTML.trim() === "" && !quill.isStack(nowRendering)) {
nowRendering.style.cssText += styles;
nowRendering.classList.add("HStack")
cb();
return nowRendering;
}
let div = document.createElement("div");
div.classList.add("HStack");
div.style.cssText += styles;
div.render = cb;
quill.render(div);
return div;
}; };
window.ZStack = function (cb = () => {}) { window.ZStack = function (cb = () => {}) {
let nowRendering = quill.rendering[quill.rendering.length - 1]; return handleStack(cb, "ZStack")
if (nowRendering.innerHTML.trim() === "" && !quill.isStack(nowRendering)) {
nowRendering.classList.add("ZStack")
cb();
return nowRendering;
}
let div = document.createElement("div");
div.classList.add("ZStack");
div.render = cb;
quill.render(div);
return div;
}; };
/* SHAPES */ /* SHAPES */

BIN
ui/_/images/knight.webp Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 177 KiB

View File

@@ -9,7 +9,6 @@ class Home extends Shadow {
ZStack(() => { ZStack(() => {
ZStack(() => { ZStack(() => {
console.log("it's happening", window.location.pathname)
switch(window.location.pathname) { switch(window.location.pathname) {
case "/": case "/":
Forum() Forum()

View File

@@ -5,6 +5,20 @@
<meta name="viewport" content="width=device-width, initial-scale=1"> <meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="icon" href="/_/icons/logo.svg"> <link rel="icon" href="/_/icons/logo.svg">
<link rel="stylesheet" href="/_/code/shared.css"> <link rel="stylesheet" href="/_/code/shared.css">
<link
rel="preload"
href="/_/fonts/BonaNova/BonaNova-Regular.woff"
as="font"
type="font/woff2"
crossorigin
>
<link
rel="preload"
href="/_/fonts/BonaNova/BonaNova-Bold.woff"
as="font"
type="font/woff"
crossorigin
>
<style> <style>
body { body {

View File

@@ -24,7 +24,7 @@ class Events extends Shadow {
Stack(() => { Stack(() => {
VStack(() => { VStack(() => {
p(`January 23, 2025`) p(`February 7, 2026`)
p(`Hyperia Winter Ball`) p(`Hyperia Winter Ball`)
.fontSize(1.2, em) .fontSize(1.2, em)
@@ -33,7 +33,7 @@ class Events extends Shadow {
}) })
p(`Join us in Austin, Texas for a great dance, with free drinks and live music. <br><br>Admission: $35 for men, women are free.`) p(`Join us in Austin, Texas for two-stepping and live music by Noah Kurtis. 21 and up.`)
.marginRight(4, em) .marginRight(4, em)
HStack(() => { HStack(() => {
@@ -46,16 +46,17 @@ class Events extends Shadow {
.height(2, em) .height(2, em)
.maxWidth(40, vw) .maxWidth(40, vw)
button("Buy Ticket") button("RSVP")
.color("var(--darkbrown") .color("var(--darkbrown")
.border("1px solid #ab2f007d") .border("1px solid #ab2f007d")
.background('var(--green)') .background('var(--green)')
.marginLeft("auto") .marginLeft("auto")
.onClick(async function() { .onClick(async function() {
this.innerText = "Loading..." window.open("https://partiful.com/e/XqnPwBKS9vUMd8GYX3xz?c=HLU81h69", "_blank", "noopener");
const res = await fetch("/create-checkout-session", { method: "POST" }); // this.innerText = "Loading..."
const data = await res.json(); // const res = await fetch("/create-checkout-session", { method: "POST" });
window.location = data.url; // const data = await res.json();
// window.location = data.url;
}) })
}) })
.gap(3, em) .gap(3, em)

View File

@@ -25,7 +25,7 @@ class Home extends Shadow {
switch(window.location.pathname) { switch(window.location.pathname) {
case "/": case "/":
img("/_/images/knight.png", "29vmax") img("/_/images/knight.webp", "29vmax")
.position("absolute") .position("absolute")
.left(50, vw).top(isMobile() ? 50 : 53, vh) .left(50, vw).top(isMobile() ? 50 : 53, vh)
.center() .center()

View File

@@ -1,68 +0,0 @@
// Create the hover display element
const hoverBox = document.createElement('div');
hoverBox.style.id = "hoverBox"
hoverBox.style.position = 'fixed';
hoverBox.style.padding = '8px 12px';
hoverBox.style.backgroundColor = 'var(--green)';
hoverBox.style.border = '1px solid var(--tan)';
hoverBox.style.color = 'var(--tan)';
hoverBox.style.opacity = '80%';
hoverBox.style.pointerEvents = 'none';
hoverBox.style.zIndex = '9999';
hoverBox.style.fontFamily = 'sans-serif';
hoverBox.style.fontSize = '14px';
hoverBox.style.display = 'none';
document.body.appendChild(hoverBox);
let currentTarget = null;
function capitalizeWords(str) {
return str
.split('-')
.map(word => word.charAt(0).toUpperCase() + word.slice(1))
.join(' ');
}
function onMouseOver(e) {
const target = e.target;
let paintingName; let artistName;
if(target.id === "back") {
paintingName = "The Garden Terrace"
artistName = "Caspar David Friedrich"
} else if (target.tagName.toLowerCase() === 'img' && target.classList.contains('interactive')) {
const match = target.src.match(/([^\/]+)\.([a-z]{3,4})(\?.*)?$/i); // extract filename
if (!match) return;
const filename = match[1];
const parts = filename.split('_');
if (parts.length !== 2) return;
paintingName = capitalizeWords(parts[0]);
artistName = capitalizeWords(parts[1]);
} else {
return
}
hoverBox.innerHTML = `<strong>${paintingName}</strong><br><span style="font-size: 12px;">${artistName}</span>`;
hoverBox.style.display = 'block';
currentTarget = target;
hoverBox.style.left = `${e.clientX + 15}px`;
hoverBox.style.top = `${e.clientY + 15}px`;
}
function onMouseOut(e) {
if (e.target === currentTarget) {
hoverBox.style.display = 'none';
currentTarget = null;
}
}
function onMouseMove(e) {
if (hoverBox.style.display === 'block') {
hoverBox.style.left = `${e.clientX + 15}px`;
hoverBox.style.top = `${e.clientY + 15}px`;
}
}
document.addEventListener('mouseover', onMouseOver);
document.addEventListener('mouseout', onMouseOut);
document.addEventListener('mousemove', onMouseMove);

View File

@@ -1,56 +0,0 @@
let treeOriginalTop = null;
let currentVelocity = 0;
let isAnimating = false;
window.addEventListener('wheel', (e) => {
if(window.innerWidth < 600) {
return;
}
// Add scroll delta to the velocity
currentVelocity += e.deltaY;
// Start animation loop if not running
if (!isAnimating) {
isAnimating = true;
requestAnimationFrame(animateScroll);
}
}, { passive: false });
function animateScroll() {
const tree = document.getElementById("tree");
if (!treeOriginalTop) {
treeOriginalTop = parseInt(getComputedStyle(tree).top);
}
const treeHeightPX = 0.83 * window.innerHeight;
let treeTopPX = parseInt(getComputedStyle(tree).top);
// Limit per-frame speed (but NOT total speed)
let multiplier = window.innerHeight / 2000;
let delta = Math.max(-100 * multiplier, Math.min(100 * multiplier, currentVelocity));
// Apply the scroll
let newTop = treeTopPX - delta;
// Clamp top/bottom bounds
const maxTop = treeOriginalTop;
const minTop = treeOriginalTop - treeHeightPX;
if (newTop > maxTop) newTop = maxTop;
if (newTop < minTop) newTop = minTop;
tree.style.top = `${newTop}px`;
// Slowly reduce velocity
currentVelocity *= 0.85;
// If velocity is small, stop
if (Math.abs(currentVelocity) > 0.5) {
requestAnimationFrame(animateScroll);
} else {
isAnimating = false;
currentVelocity = 0;
}
}