Compare commits
4 Commits
8d57a507d1
...
main
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
07b42ccbc3 | ||
|
|
f1c7c340f9 | ||
|
|
f8861666dd | ||
|
|
cd5f92b55f |
@@ -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
BIN
ui/_/images/knight.webp
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 177 KiB |
@@ -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()
|
||||||
|
|||||||
@@ -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 {
|
||||||
|
|||||||
@@ -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)
|
||||||
|
|||||||
@@ -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()
|
||||||
|
|||||||
@@ -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);
|
|
||||||
@@ -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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Reference in New Issue
Block a user