diff --git a/server/auth.js b/server/auth.js index 7f7c0d9..9f76804 100644 --- a/server/auth.js +++ b/server/auth.js @@ -36,26 +36,18 @@ export default class AuthHandler { const payload = jwt.verify(token, process.env.JWT_SECRET); const email = payload.email; - const user = db.members.getByEmail(email); - res.send({ email: user.email, name: user.firstName + " " + user.lastName }); + res.send({ email: "sam@hyperia.so", name: "Sam Russell" }); } catch (err) { res.status(401).send({ error: "Invalid token" }); } } async login(req, res) { - const { email, password } = req.body; - let foundUser = global.db.members.getByEmail(email) - if(!foundUser) { - res.status(400).json({ error: 'Incorrect email.' }); - return; - } - const storedHash = foundUser.password - const valid = await argon2.verify(storedHash, password); - if (!valid) { + const { password } = req.body; + if (!(password === process.env.PASSWORD)) { res.status(400).json({ error: 'Incorrect password.' }); } else { - const payload = { email: foundUser.email }; + const payload = { email: "sam@hyperia.so" }; console.log(payload) const secret = process.env.JWT_SECRET; const options = { expiresIn: "2h" }; @@ -67,7 +59,7 @@ export default class AuthHandler { sameSite: "lax", // like SameSiteLaxMode maxAge: 2 * 60 * 60 * 1000, // 2 hours in milliseconds path: "/", // available on entire site - domain: process.env.ENV === "production" ? "." + process.env.BASE_URL : undefined + domain: process.env.ENV === "production" ? process.env.BASE_URL : undefined }); res.redirect("/") diff --git a/ui/_/code/quill.js b/ui/_/code/quill.js index fcebb29..98d7bd5 100644 --- a/ui/_/code/quill.js +++ b/ui/_/code/quill.js @@ -1,6 +1,8 @@ /* Sam Russell Captured Sun + 12.17.25 - [Hyperia] - adding width, height functions. adding "e" to onClick. adding the non-window $$ funcs. + 12.16.25 - [comalyr] - State 11.25.25.1 - Added minHeight and minWidth to be counted as numerical styles 11.25.25 - Added onChange for check boxes, added setQuery / onQueryChanged for easy filtering 11.24.25 - Fixing onClick because it was reversed, adding event to onHover params @@ -68,6 +70,12 @@ window.$ = function(selector, el = document) { window.$$ = function(selector, el = document) { return Array.from(el.querySelectorAll(selector)) } +HTMLElement.prototype.$$ = function(selector) { + return window.$$(selector, this) +} +DocumentFragment.prototype.$$ = function(selector) { + return window.$$(selector, this) +} /* CONSOLE */ @@ -163,6 +171,7 @@ Object.defineProperty(Array.prototype, 'last', { window.quill = { rendering: [], + lastState: null, render: (el) => { if(el instanceof Shadow) { @@ -193,19 +202,6 @@ window.quill = { quill.rendering.pop() }, - loadPage: () => { - let URL = window.location.pathname - if(!window.routes[URL]) { - throw new Error("No URL for this route: ", URL) - } - - let pageClass = window[routes[URL]] - document.title = pageClass.title ?? document.title - document.body.innerHTML = "" - let page = new pageClass() - quill.render(page) - }, - isStack: (el) => { return el.classList.contains("HStack") || el.classList.contains("ZStack") || el.classList.contains("VStack") }, @@ -216,6 +212,7 @@ window.Shadow = class extends HTMLElement { super() } } + window.register = (el, tagname) => { if (typeof el.prototype.render !== 'function') { throw new Error("Element must have a render: " + el.prototype.constructor.name) @@ -230,6 +227,42 @@ window.register = (el, tagname) => { window[el.prototype.constructor.name] = function (...params) { let instance = new el(...params) + if(instance.state) { + let proxy = new Proxy(instance.state, { + get(target, prop, receiver) { + if (typeof prop === "symbol") { // Ignore internal / symbol accesses + return Reflect.get(target, prop, receiver); + } + + quill.lastLastState = quill.lastState + quill.lastState = prop; + return Reflect.get(target, prop, receiver); + }, + set(target, prop, value, receiver) { + const oldValue = target[prop]; + if (oldValue === value) return true; + + const result = Reflect.set(target, prop, value, receiver); + instance.stateWatchers[prop].forEach((cb) => cb()) + return result; + } + }); + Object.defineProperty(instance, "state", { + value: proxy, + writable: false, + configurable: false, + enumerable: true + }); + + let stateWatchers = {} + Object.keys(instance.state).forEach((key) => stateWatchers[key] = []) + Object.defineProperty(instance, "stateWatchers", { + value: stateWatchers, + writable: false, + configurable: false, + enumerable: true + }); + } quill.render(instance) return instance } @@ -333,24 +366,27 @@ function extendHTMLElementWithStyleSetters() { switch (type) { case "unit-number": - HTMLElement.prototype[prop] = function(value, unit = "px") { - if ((typeof value !== "number" || isNaN(value)) && value !== "auto") { - throw new Error(`Invalid value for ${prop}: ${value}. Expected a number.`); - } + HTMLElement.prototype[prop] = StyleFunction(function(value, unit = "px") { if(value === "auto") { this.style[prop] = value return this } this.style[prop] = value + unit; + if (value !== "" && this.style[prop] === "") { + throw new Error(`Invalid CSS value for ${prop}: ` + value + unit); + } return this; - }; + }); break; case "string": - HTMLElement.prototype[prop] = function(value) { + HTMLElement.prototype[prop] = StyleFunction(function(value) { this.style[prop] = value; + if (value !== "" && this.style[prop] === "") { + throw new Error(`Invalid CSS value for ${prop}: ` + value); + } return this; - }; + }); break; } }); @@ -358,46 +394,86 @@ function extendHTMLElementWithStyleSetters() { extendHTMLElementWithStyleSetters(); +HTMLElement.prototype.addStateWatcher = function(field, cb) { + let parent = this + while(!(parent instanceof Shadow)) { + parent = parent.parentNode + } + parent.stateWatchers[field].push(cb) +} + +// Currently only works for one state variable in the function +// Could probably be fixed by just making lastState an array and clearing it out every function call? +HTMLElement.prototype.setUpState = function(styleFunc, cb) { + let format = (value) => {return Array.isArray(value) ? value : [value]} + + // 1. Run the callback to get the style argument and also update lastState + let styleArgs = format(cb()) + + // 2. Check if lastState has really been updated. If not, the user-provided cb did not access valid state + if(!quill.lastState) { + throw new Error("Quill: style state function does not access valid state") + } + + // 3. Construct function to run when state changes + let onStateChange = () => { + styleFunc.call(this, ...format(cb())) + } + + // 4. Now listen for the state to change + this.addStateWatcher(quill.lastState, onStateChange) + + // 5. Run the original function again, this time with the actual arguments + quill.lastState = null + styleFunc.call(this, ...styleArgs) +} + +function StyleFunction(func) { + let styleFunction = function(value, unit = "px") { + if(typeof value === 'function') { + this.setUpState(styleFunction, value) + return this + } else { + func.call(this, value, unit); // ".call" ensures that "this" is correct + return this + } + } + + return styleFunction +} + HTMLElement.prototype.styles = function(cb) { cb.call(this, this) return this } -HTMLElement.prototype.paddingVertical = function(value, unit = "px") { - if ((typeof value !== 'number' && value !== "auto") || Number.isNaN(value)) - throw new Error(`Invalid value: ${value}. Expected a number.`); +/* Type 1 */ + +HTMLElement.prototype.paddingVertical = StyleFunction(function(value, unit = "px") { this.style.paddingTop = value + unit this.style.paddingBottom = value + unit return this -} +}) -HTMLElement.prototype.paddingHorizontal = function(value, unit = "px") { - if ((typeof value !== 'number' && value !== "auto") || Number.isNaN(value)) - throw new Error(`Invalid value: ${value}. Expected a number.`); +HTMLElement.prototype.paddingHorizontal = StyleFunction(function(value, unit = "px") { this.style.paddingRight = value + unit this.style.paddingLeft = value + unit return this -} +}) -HTMLElement.prototype.marginVertical = function(value, unit = "px") { - if ((typeof value !== 'number' && value !== "auto") || Number.isNaN(value)) - throw new Error(`Invalid value: ${value}. Expected a number.`); +HTMLElement.prototype.marginVertical = StyleFunction(function(value, unit = "px") { this.style.marginTop = value + unit this.style.marginBottom = value + unit return this -} +}) -HTMLElement.prototype.marginHorizontal = function(value, unit = "px") { - if ((typeof value !== 'number' && value !== "auto") || Number.isNaN(value)) - throw new Error(`Invalid value: ${value}. Expected a number.`); +HTMLElement.prototype.marginHorizontal = StyleFunction(function(value, unit = "px") { this.style.marginRight = value + unit this.style.marginLeft = value + unit return this -} +}) -HTMLElement.prototype.fontSize = function(value, unit = "px") { - if ((typeof value !== 'number' && value !== "auto") || Number.isNaN(value)) - throw new Error(`Invalid value: ${value}. Expected a number.`); +HTMLElement.prototype.fontSize = StyleFunction(function(value, unit = "px") { switch(value) { case "6xl": @@ -441,7 +517,7 @@ HTMLElement.prototype.fontSize = function(value, unit = "px") { } this.style.fontSize = value + unit return this -} +}) function checkPositionType(el) { let computed = window.getComputedStyle(el).position @@ -450,6 +526,26 @@ function checkPositionType(el) { } } +HTMLElement.prototype.width = function(value, unit = "px") { + if ((typeof value !== 'number' && value !== "auto") || Number.isNaN(value)) + throw new Error(`Invalid value: ${value}. Expected a number.`); + this.style.width = value + unit + if(window.getComputedStyle(this).display === "inline") { + this.style.display = "block" + } + return this +} + +HTMLElement.prototype.height = function(value, unit = "px") { + if ((typeof value !== 'number' && value !== "auto") || Number.isNaN(value)) + throw new Error(`Invalid value: ${value}. Expected a number.`); + this.style.height = value + unit + if(window.getComputedStyle(this).display === "inline") { + this.style.display = "block" + } + return this +} + HTMLElement.prototype.x = function(value, unit = "px") { if (typeof value !== 'number' || isNaN(value)) throw new Error(`Invalid value: ${value}. Expected a number.`); @@ -661,7 +757,7 @@ window.form = function(cb) { return el } -window.input = function(placeholder, width, height) { +window.input = function(placeholder = "", width, height) { let el = document.createElement("input") el.placeholder = placeholder el.style.width = width @@ -670,14 +766,18 @@ window.input = function(placeholder, width, height) { return el } -window.label = function(text) { +window.label = function(inside) { let el = document.createElement("label") - el.innerText = text + if(typeof inside === "string") { + el.innerText = inside + } else { + el.render = inside + } quill.render(el) return el } -window.textarea = function(placeholder) { +window.textarea = function(placeholder = "") { let el = document.createElement("textarea") el.placeholder = placeholder quill.render(el) @@ -845,8 +945,8 @@ HTMLElement.prototype.onAppear = function(func) { }; HTMLElement.prototype.onClick = function(func) { - const onMouseDown = () => func.call(this, false); - const onMouseUp = () => func.call(this, true); + const onMouseDown = (e) => func.call(this, false, e); + const onMouseUp = (e) => func.call(this, true, e); this._storeListener("mousedown", onMouseDown); this._storeListener("mouseup", onMouseUp); return this; @@ -929,34 +1029,38 @@ HTMLElement.prototype.onTap = function(cb) { }; /* WHY THIS LISTENER IS THE WAY IT IS: -- If we dispatch the "navigate" event on the window (as one would expect for a "navigate" event), a listener placed on the element will not pick it up. -- However, if we add the listener on the window, it won't have the "this" scope that a callback normally would. Which makes it much less useful. -- Then, if we try to add that scope using bind(), it makes the function.toString() unreadable, which means we cannot detect duplicate listeners. -- Therefore, we just have to attach the navigate event to the element, and manually trigger that when the window listener fires. +- We can't just put a listener on the element, because a window "navigate" event won't trigger it +- We can't just put a listener on the window, because the "this" variable will only refer to the window +- And, if we try to re-add that scope using bind(), it makes the return value of .toString() unreadable, which means we cannot detect duplicate listeners. +- Therefore, we attach a global navigate event to the window, and each navigate event in this array, and manually trigger each event when the global one fires. */ navigateListeners = [] -HTMLElement.prototype.onNavigate = function(cb) { - this._storeListener("navigate", cb); - - let found = false - for(entry of navigateListeners) { - if(entry.cb.toString() === cb.toString() && - this.nodeName === entry.el.nodeName) { - found = true - break; - } - } - if(found === false) { - navigateListeners.push({el: this, cb: cb}) - } - - return this; -}; window.addEventListener("navigate", () => { for(entry of navigateListeners) { entry.el.dispatchEvent(new CustomEvent("navigate")) } }) +HTMLElement.prototype.onNavigate = function(cb) { + this._storeListener("navigate", cb); + + let found = false + let elementIndex = Array.from(this.parentNode.children).indexOf(this) + for(entry of navigateListeners) { + if( + entry.cb.toString() === cb.toString() + && entry.index === elementIndex + && this.nodeName === entry.el.nodeName + ) { + found = true + break; + } + } + if(found === false) { + navigateListeners.push({el: this, cb: cb, index: elementIndex}) + } + + return this; +}; /* Same principle applies @@ -1045,3 +1149,7 @@ HTMLElement.prototype.attr = function(attributes) { } return this; }; + + +/*! Axios v1.13.2 Copyright (c) 2025 Matt Zabriskie and contributors */ +!function(e,t){"object"==typeof exports&&"undefined"!=typeof module?module.exports=t():"function"==typeof define&&define.amd?define(t):(e="undefined"!=typeof globalThis?globalThis:e||self).axios=t()}(this,(function(){"use strict";function e(e){var r,n;function o(r,n){try{var a=e[r](n),u=a.value,s=u instanceof t;Promise.resolve(s?u.v:u).then((function(t){if(s){var n="return"===r?"return":"next";if(!u.k||t.done)return o(n,t);t=e[n](t).value}i(a.done?"return":"normal",t)}),(function(e){o("throw",e)}))}catch(e){i("throw",e)}}function i(e,t){switch(e){case"return":r.resolve({value:t,done:!0});break;case"throw":r.reject(t);break;default:r.resolve({value:t,done:!1})}(r=r.next)?o(r.key,r.arg):n=null}this._invoke=function(e,t){return new Promise((function(i,a){var u={key:e,arg:t,resolve:i,reject:a,next:null};n?n=n.next=u:(r=n=u,o(e,t))}))},"function"!=typeof e.return&&(this.return=void 0)}function t(e,t){this.v=e,this.k=t}function r(e){var r={},n=!1;function o(r,o){return n=!0,o=new Promise((function(t){t(e[r](o))})),{done:!1,value:new t(o,1)}}return r["undefined"!=typeof Symbol&&Symbol.iterator||"@@iterator"]=function(){return this},r.next=function(e){return n?(n=!1,e):o("next",e)},"function"==typeof e.throw&&(r.throw=function(e){if(n)throw n=!1,e;return o("throw",e)}),"function"==typeof e.return&&(r.return=function(e){return n?(n=!1,e):o("return",e)}),r}function n(e){var t,r,n,i=2;for("undefined"!=typeof Symbol&&(r=Symbol.asyncIterator,n=Symbol.iterator);i--;){if(r&&null!=(t=e[r]))return t.call(e);if(n&&null!=(t=e[n]))return new o(t.call(e));r="@@asyncIterator",n="@@iterator"}throw new TypeError("Object is not async iterable")}function o(e){function t(e){if(Object(e)!==e)return Promise.reject(new TypeError(e+" is not an object."));var t=e.done;return Promise.resolve(e.value).then((function(e){return{value:e,done:t}}))}return o=function(e){this.s=e,this.n=e.next},o.prototype={s:null,n:null,next:function(){return t(this.n.apply(this.s,arguments))},return:function(e){var r=this.s.return;return void 0===r?Promise.resolve({value:e,done:!0}):t(r.apply(this.s,arguments))},throw:function(e){var r=this.s.return;return void 0===r?Promise.reject(e):t(r.apply(this.s,arguments))}},new o(e)}function i(e){return new t(e,0)}function a(e,t){var r=Object.keys(e);if(Object.getOwnPropertySymbols){var n=Object.getOwnPropertySymbols(e);t&&(n=n.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),r.push.apply(r,n)}return r}function u(e){for(var t=1;t=0;--i){var a=this.tryEntries[i],u=a.completion;if("root"===a.tryLoc)return o("end");if(a.tryLoc<=this.prev){var s=n.call(a,"catchLoc"),c=n.call(a,"finallyLoc");if(s&&c){if(this.prev=0;--r){var o=this.tryEntries[r];if(o.tryLoc<=this.prev&&n.call(o,"finallyLoc")&&this.prev=0;--t){var r=this.tryEntries[t];if(r.finallyLoc===e)return this.complete(r.completion,r.afterLoc),A(r),y}},catch:function(e){for(var t=this.tryEntries.length-1;t>=0;--t){var r=this.tryEntries[t];if(r.tryLoc===e){var n=r.completion;if("throw"===n.type){var o=n.arg;A(r)}return o}}throw new Error("illegal catch attempt")},delegateYield:function(t,r,n){return this.delegate={iterator:L(t),resultName:r,nextLoc:n},"next"===this.method&&(this.arg=e),y}},t}function c(e){var t=function(e,t){if("object"!=typeof e||!e)return e;var r=e[Symbol.toPrimitive];if(void 0!==r){var n=r.call(e,t||"default");if("object"!=typeof n)return n;throw new TypeError("@@toPrimitive must return a primitive value.")}return("string"===t?String:Number)(e)}(e,"string");return"symbol"==typeof t?t:String(t)}function f(e){return f="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(e){return typeof e}:function(e){return e&&"function"==typeof Symbol&&e.constructor===Symbol&&e!==Symbol.prototype?"symbol":typeof e},f(e)}function l(t){return function(){return new e(t.apply(this,arguments))}}function p(e,t,r,n,o,i,a){try{var u=e[i](a),s=u.value}catch(e){return void r(e)}u.done?t(s):Promise.resolve(s).then(n,o)}function d(e){return function(){var t=this,r=arguments;return new Promise((function(n,o){var i=e.apply(t,r);function a(e){p(i,n,o,a,u,"next",e)}function u(e){p(i,n,o,a,u,"throw",e)}a(void 0)}))}}function h(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}function v(e,t){for(var r=0;re.length)&&(t=e.length);for(var r=0,n=new Array(t);r2&&void 0!==arguments[2]?arguments[2]:{},i=o.allOwnKeys,a=void 0!==i&&i;if(null!=e)if("object"!==f(e)&&(e=[e]),L(e))for(r=0,n=e.length;r0;)if(t===(r=n[o]).toLowerCase())return r;return null}var Q="undefined"!=typeof globalThis?globalThis:"undefined"!=typeof self?self:"undefined"!=typeof window?window:global,Z=function(e){return!N(e)&&e!==Q};var ee,te=(ee="undefined"!=typeof Uint8Array&&R(Uint8Array),function(e){return ee&&e instanceof ee}),re=A("HTMLFormElement"),ne=function(e){var t=Object.prototype.hasOwnProperty;return function(e,r){return t.call(e,r)}}(),oe=A("RegExp"),ie=function(e,t){var r=Object.getOwnPropertyDescriptors(e),n={};$(r,(function(r,o){var i;!1!==(i=t(r,o,e))&&(n[o]=i||r)})),Object.defineProperties(e,n)};var ae,ue,se,ce,fe=A("AsyncFunction"),le=(ae="function"==typeof setImmediate,ue=F(Q.postMessage),ae?setImmediate:ue?(se="axios@".concat(Math.random()),ce=[],Q.addEventListener("message",(function(e){var t=e.source,r=e.data;t===Q&&r===se&&ce.length&&ce.shift()()}),!1),function(e){ce.push(e),Q.postMessage(se,"*")}):function(e){return setTimeout(e)}),pe="undefined"!=typeof queueMicrotask?queueMicrotask.bind(Q):"undefined"!=typeof process&&process.nextTick||le,de={isArray:L,isArrayBuffer:_,isBuffer:C,isFormData:function(e){var t;return e&&("function"==typeof FormData&&e instanceof FormData||F(e.append)&&("formdata"===(t=j(e))||"object"===t&&F(e.toString)&&"[object FormData]"===e.toString()))},isArrayBufferView:function(e){return"undefined"!=typeof ArrayBuffer&&ArrayBuffer.isView?ArrayBuffer.isView(e):e&&e.buffer&&_(e.buffer)},isString:U,isNumber:B,isBoolean:function(e){return!0===e||!1===e},isObject:D,isPlainObject:I,isEmptyObject:function(e){if(!D(e)||C(e))return!1;try{return 0===Object.keys(e).length&&Object.getPrototypeOf(e)===Object.prototype}catch(e){return!1}},isReadableStream:K,isRequest:V,isResponse:G,isHeaders:X,isUndefined:N,isDate:q,isFile:M,isBlob:z,isRegExp:oe,isFunction:F,isStream:function(e){return D(e)&&F(e.pipe)},isURLSearchParams:J,isTypedArray:te,isFileList:H,forEach:$,merge:function e(){for(var t=Z(this)&&this||{},r=t.caseless,n=t.skipUndefined,o={},i=function(t,i){var a=r&&Y(o,i)||i;I(o[a])&&I(t)?o[a]=e(o[a],t):I(t)?o[a]=e({},t):L(t)?o[a]=t.slice():n&&N(t)||(o[a]=t)},a=0,u=arguments.length;a3&&void 0!==arguments[3]?arguments[3]:{},o=n.allOwnKeys;return $(t,(function(t,n){r&&F(t)?e[n]=O(t,r):e[n]=t}),{allOwnKeys:o}),e},trim:function(e){return e.trim?e.trim():e.replace(/^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/g,"")},stripBOM:function(e){return 65279===e.charCodeAt(0)&&(e=e.slice(1)),e},inherits:function(e,t,r,n){e.prototype=Object.create(t.prototype,n),e.prototype.constructor=e,Object.defineProperty(e,"super",{value:t.prototype}),r&&Object.assign(e.prototype,r)},toFlatObject:function(e,t,r,n){var o,i,a,u={};if(t=t||{},null==e)return t;do{for(i=(o=Object.getOwnPropertyNames(e)).length;i-- >0;)a=o[i],n&&!n(a,e,t)||u[a]||(t[a]=e[a],u[a]=!0);e=!1!==r&&R(e)}while(e&&(!r||r(e,t))&&e!==Object.prototype);return t},kindOf:j,kindOfTest:A,endsWith:function(e,t,r){e=String(e),(void 0===r||r>e.length)&&(r=e.length),r-=t.length;var n=e.indexOf(t,r);return-1!==n&&n===r},toArray:function(e){if(!e)return null;if(L(e))return e;var t=e.length;if(!B(t))return null;for(var r=new Array(t);t-- >0;)r[t]=e[t];return r},forEachEntry:function(e,t){for(var r,n=(e&&e[k]).call(e);(r=n.next())&&!r.done;){var o=r.value;t.call(e,o[0],o[1])}},matchAll:function(e,t){for(var r,n=[];null!==(r=e.exec(t));)n.push(r);return n},isHTMLForm:re,hasOwnProperty:ne,hasOwnProp:ne,reduceDescriptors:ie,freezeMethods:function(e){ie(e,(function(t,r){if(F(e)&&-1!==["arguments","caller","callee"].indexOf(r))return!1;var n=e[r];F(n)&&(t.enumerable=!1,"writable"in t?t.writable=!1:t.set||(t.set=function(){throw Error("Can not rewrite read-only method '"+r+"'")}))}))},toObjectSet:function(e,t){var r={},n=function(e){e.forEach((function(e){r[e]=!0}))};return L(e)?n(e):n(String(e).split(t)),r},toCamelCase:function(e){return e.toLowerCase().replace(/[-_\s]([a-z\d])(\w*)/g,(function(e,t,r){return t.toUpperCase()+r}))},noop:function(){},toFiniteNumber:function(e,t){return null!=e&&Number.isFinite(e=+e)?e:t},findKey:Y,global:Q,isContextDefined:Z,isSpecCompliantForm:function(e){return!!(e&&F(e.append)&&"FormData"===e[T]&&e[k])},toJSONObject:function(e){var t=new Array(10);return function e(r,n){if(D(r)){if(t.indexOf(r)>=0)return;if(C(r))return r;if(!("toJSON"in r)){t[n]=r;var o=L(r)?[]:{};return $(r,(function(t,r){var i=e(t,n+1);!N(i)&&(o[r]=i)})),t[n]=void 0,o}}return r}(e,0)},isAsyncFn:fe,isThenable:function(e){return e&&(D(e)||F(e))&&F(e.then)&&F(e.catch)},setImmediate:le,asap:pe,isIterable:function(e){return null!=e&&F(e[k])}};function he(e,t,r,n,o){Error.call(this),Error.captureStackTrace?Error.captureStackTrace(this,this.constructor):this.stack=(new Error).stack,this.message=e,this.name="AxiosError",t&&(this.code=t),r&&(this.config=r),n&&(this.request=n),o&&(this.response=o,this.status=o.status?o.status:null)}de.inherits(he,Error,{toJSON:function(){return{message:this.message,name:this.name,description:this.description,number:this.number,fileName:this.fileName,lineNumber:this.lineNumber,columnNumber:this.columnNumber,stack:this.stack,config:de.toJSONObject(this.config),code:this.code,status:this.status}}});var ve=he.prototype,ye={};["ERR_BAD_OPTION_VALUE","ERR_BAD_OPTION","ECONNABORTED","ETIMEDOUT","ERR_NETWORK","ERR_FR_TOO_MANY_REDIRECTS","ERR_DEPRECATED","ERR_BAD_RESPONSE","ERR_BAD_REQUEST","ERR_CANCELED","ERR_NOT_SUPPORT","ERR_INVALID_URL"].forEach((function(e){ye[e]={value:e}})),Object.defineProperties(he,ye),Object.defineProperty(ve,"isAxiosError",{value:!0}),he.from=function(e,t,r,n,o,i){var a=Object.create(ve);de.toFlatObject(e,a,(function(e){return e!==Error.prototype}),(function(e){return"isAxiosError"!==e}));var u=e&&e.message?e.message:"Error",s=null==t&&e?e.code:t;return he.call(a,u,s,r,n,o),e&&null==a.cause&&Object.defineProperty(a,"cause",{value:e,configurable:!0}),a.name=e&&e.name||"Error",i&&Object.assign(a,i),a};function me(e){return de.isPlainObject(e)||de.isArray(e)}function be(e){return de.endsWith(e,"[]")?e.slice(0,-2):e}function ge(e,t,r){return e?e.concat(t).map((function(e,t){return e=be(e),!r&&t?"["+e+"]":e})).join(r?".":""):t}var we=de.toFlatObject(de,{},null,(function(e){return/^is[A-Z]/.test(e)}));function Ee(e,t,r){if(!de.isObject(e))throw new TypeError("target must be an object");t=t||new FormData;var n=(r=de.toFlatObject(r,{metaTokens:!0,dots:!1,indexes:!1},!1,(function(e,t){return!de.isUndefined(t[e])}))).metaTokens,o=r.visitor||c,i=r.dots,a=r.indexes,u=(r.Blob||"undefined"!=typeof Blob&&Blob)&&de.isSpecCompliantForm(t);if(!de.isFunction(o))throw new TypeError("visitor must be a function");function s(e){if(null===e)return"";if(de.isDate(e))return e.toISOString();if(de.isBoolean(e))return e.toString();if(!u&&de.isBlob(e))throw new he("Blob is not supported. Use a Buffer instead.");return de.isArrayBuffer(e)||de.isTypedArray(e)?u&&"function"==typeof Blob?new Blob([e]):Buffer.from(e):e}function c(e,r,o){var u=e;if(e&&!o&&"object"===f(e))if(de.endsWith(r,"{}"))r=n?r:r.slice(0,-2),e=JSON.stringify(e);else if(de.isArray(e)&&function(e){return de.isArray(e)&&!e.some(me)}(e)||(de.isFileList(e)||de.endsWith(r,"[]"))&&(u=de.toArray(e)))return r=be(r),u.forEach((function(e,n){!de.isUndefined(e)&&null!==e&&t.append(!0===a?ge([r],n,i):null===a?r:r+"[]",s(e))})),!1;return!!me(e)||(t.append(ge(o,r,i),s(e)),!1)}var l=[],p=Object.assign(we,{defaultVisitor:c,convertValue:s,isVisitable:me});if(!de.isObject(e))throw new TypeError("data must be an object");return function e(r,n){if(!de.isUndefined(r)){if(-1!==l.indexOf(r))throw Error("Circular reference detected in "+n.join("."));l.push(r),de.forEach(r,(function(r,i){!0===(!(de.isUndefined(r)||null===r)&&o.call(t,r,de.isString(i)?i.trim():i,n,p))&&e(r,n?n.concat(i):[i])})),l.pop()}}(e),t}function Oe(e){var t={"!":"%21","'":"%27","(":"%28",")":"%29","~":"%7E","%20":"+","%00":"\0"};return encodeURIComponent(e).replace(/[!'()~]|%20|%00/g,(function(e){return t[e]}))}function Se(e,t){this._pairs=[],e&&Ee(e,this,t)}var xe=Se.prototype;function Re(e){return encodeURIComponent(e).replace(/%3A/gi,":").replace(/%24/g,"$").replace(/%2C/gi,",").replace(/%20/g,"+")}function ke(e,t,r){if(!t)return e;var n=r&&r.encode||Re;de.isFunction(r)&&(r={serialize:r});var o,i=r&&r.serialize;if(o=i?i(t,r):de.isURLSearchParams(t)?t.toString():new Se(t,r).toString(n)){var a=e.indexOf("#");-1!==a&&(e=e.slice(0,a)),e+=(-1===e.indexOf("?")?"?":"&")+o}return e}xe.append=function(e,t){this._pairs.push([e,t])},xe.toString=function(e){var t=e?function(t){return e.call(this,t,Oe)}:Oe;return this._pairs.map((function(e){return t(e[0])+"="+t(e[1])}),"").join("&")};var Te=function(){function e(){h(this,e),this.handlers=[]}return y(e,[{key:"use",value:function(e,t,r){return this.handlers.push({fulfilled:e,rejected:t,synchronous:!!r&&r.synchronous,runWhen:r?r.runWhen:null}),this.handlers.length-1}},{key:"eject",value:function(e){this.handlers[e]&&(this.handlers[e]=null)}},{key:"clear",value:function(){this.handlers&&(this.handlers=[])}},{key:"forEach",value:function(e){de.forEach(this.handlers,(function(t){null!==t&&e(t)}))}}]),e}(),je={silentJSONParsing:!0,forcedJSONParsing:!0,clarifyTimeoutError:!1},Ae={isBrowser:!0,classes:{URLSearchParams:"undefined"!=typeof URLSearchParams?URLSearchParams:Se,FormData:"undefined"!=typeof FormData?FormData:null,Blob:"undefined"!=typeof Blob?Blob:null},protocols:["http","https","file","blob","url","data"]},Pe="undefined"!=typeof window&&"undefined"!=typeof document,Le="object"===("undefined"==typeof navigator?"undefined":f(navigator))&&navigator||void 0,Ne=Pe&&(!Le||["ReactNative","NativeScript","NS"].indexOf(Le.product)<0),Ce="undefined"!=typeof WorkerGlobalScope&&self instanceof WorkerGlobalScope&&"function"==typeof self.importScripts,_e=Pe&&window.location.href||"http://localhost",Ue=u(u({},Object.freeze({__proto__:null,hasBrowserEnv:Pe,hasStandardBrowserWebWorkerEnv:Ce,hasStandardBrowserEnv:Ne,navigator:Le,origin:_e})),Ae);function Fe(e){function t(e,r,n,o){var i=e[o++];if("__proto__"===i)return!0;var a=Number.isFinite(+i),u=o>=e.length;return i=!i&&de.isArray(n)?n.length:i,u?(de.hasOwnProp(n,i)?n[i]=[n[i],r]:n[i]=r,!a):(n[i]&&de.isObject(n[i])||(n[i]=[]),t(e,r,n[i],o)&&de.isArray(n[i])&&(n[i]=function(e){var t,r,n={},o=Object.keys(e),i=o.length;for(t=0;t-1,i=de.isObject(e);if(i&&de.isHTMLForm(e)&&(e=new FormData(e)),de.isFormData(e))return o?JSON.stringify(Fe(e)):e;if(de.isArrayBuffer(e)||de.isBuffer(e)||de.isStream(e)||de.isFile(e)||de.isBlob(e)||de.isReadableStream(e))return e;if(de.isArrayBufferView(e))return e.buffer;if(de.isURLSearchParams(e))return t.setContentType("application/x-www-form-urlencoded;charset=utf-8",!1),e.toString();if(i){if(n.indexOf("application/x-www-form-urlencoded")>-1)return function(e,t){return Ee(e,new Ue.classes.URLSearchParams,u({visitor:function(e,t,r,n){return Ue.isNode&&de.isBuffer(e)?(this.append(t,e.toString("base64")),!1):n.defaultVisitor.apply(this,arguments)}},t))}(e,this.formSerializer).toString();if((r=de.isFileList(e))||n.indexOf("multipart/form-data")>-1){var a=this.env&&this.env.FormData;return Ee(r?{"files[]":e}:e,a&&new a,this.formSerializer)}}return i||o?(t.setContentType("application/json",!1),function(e,t,r){if(de.isString(e))try{return(t||JSON.parse)(e),de.trim(e)}catch(e){if("SyntaxError"!==e.name)throw e}return(r||JSON.stringify)(e)}(e)):e}],transformResponse:[function(e){var t=this.transitional||Be.transitional,r=t&&t.forcedJSONParsing,n="json"===this.responseType;if(de.isResponse(e)||de.isReadableStream(e))return e;if(e&&de.isString(e)&&(r&&!this.responseType||n)){var o=!(t&&t.silentJSONParsing)&&n;try{return JSON.parse(e,this.parseReviver)}catch(e){if(o){if("SyntaxError"===e.name)throw he.from(e,he.ERR_BAD_RESPONSE,this,null,this.response);throw e}}}return e}],timeout:0,xsrfCookieName:"XSRF-TOKEN",xsrfHeaderName:"X-XSRF-TOKEN",maxContentLength:-1,maxBodyLength:-1,env:{FormData:Ue.classes.FormData,Blob:Ue.classes.Blob},validateStatus:function(e){return e>=200&&e<300},headers:{common:{Accept:"application/json, text/plain, */*","Content-Type":void 0}}};de.forEach(["delete","get","head","post","put","patch"],(function(e){Be.headers[e]={}}));var De=Be,Ie=de.toObjectSet(["age","authorization","content-length","content-type","etag","expires","from","host","if-modified-since","if-unmodified-since","last-modified","location","max-forwards","proxy-authorization","referer","retry-after","user-agent"]),qe=Symbol("internals");function Me(e){return e&&String(e).trim().toLowerCase()}function ze(e){return!1===e||null==e?e:de.isArray(e)?e.map(ze):String(e)}function He(e,t,r,n,o){return de.isFunction(n)?n.call(this,t,r):(o&&(t=r),de.isString(t)?de.isString(n)?-1!==t.indexOf(n):de.isRegExp(n)?n.test(t):void 0:void 0)}var Je=function(e,t){function r(e){h(this,r),e&&this.set(e)}return y(r,[{key:"set",value:function(e,t,r){var n=this;function o(e,t,r){var o=Me(t);if(!o)throw new Error("header name must be a non-empty string");var i=de.findKey(n,o);(!i||void 0===n[i]||!0===r||void 0===r&&!1!==n[i])&&(n[i||t]=ze(e))}var i=function(e,t){return de.forEach(e,(function(e,r){return o(e,r,t)}))};if(de.isPlainObject(e)||e instanceof this.constructor)i(e,t);else if(de.isString(e)&&(e=e.trim())&&!/^[-_a-zA-Z0-9^`|~,!#$%&'*+.]+$/.test(e.trim()))i(function(e){var t,r,n,o={};return e&&e.split("\n").forEach((function(e){n=e.indexOf(":"),t=e.substring(0,n).trim().toLowerCase(),r=e.substring(n+1).trim(),!t||o[t]&&Ie[t]||("set-cookie"===t?o[t]?o[t].push(r):o[t]=[r]:o[t]=o[t]?o[t]+", "+r:r)})),o}(e),t);else if(de.isObject(e)&&de.isIterable(e)){var a,u,s,c={},f=function(e,t){var r="undefined"!=typeof Symbol&&e[Symbol.iterator]||e["@@iterator"];if(!r){if(Array.isArray(e)||(r=w(e))||t&&e&&"number"==typeof e.length){r&&(e=r);var n=0,o=function(){};return{s:o,n:function(){return n>=e.length?{done:!0}:{done:!1,value:e[n++]}},e:function(e){throw e},f:o}}throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}var i,a=!0,u=!1;return{s:function(){r=r.call(e)},n:function(){var e=r.next();return a=e.done,e},e:function(e){u=!0,i=e},f:function(){try{a||null==r.return||r.return()}finally{if(u)throw i}}}}(e);try{for(f.s();!(s=f.n()).done;){var l=s.value;if(!de.isArray(l))throw TypeError("Object iterator must return a key-value pair");c[u=l[0]]=(a=c[u])?de.isArray(a)?[].concat(g(a),[l[1]]):[a,l[1]]:l[1]}}catch(e){f.e(e)}finally{f.f()}i(c,t)}else null!=e&&o(t,e,r);return this}},{key:"get",value:function(e,t){if(e=Me(e)){var r=de.findKey(this,e);if(r){var n=this[r];if(!t)return n;if(!0===t)return function(e){for(var t,r=Object.create(null),n=/([^\s,;=]+)\s*(?:=\s*([^,;]+))?/g;t=n.exec(e);)r[t[1]]=t[2];return r}(n);if(de.isFunction(t))return t.call(this,n,r);if(de.isRegExp(t))return t.exec(n);throw new TypeError("parser must be boolean|regexp|function")}}}},{key:"has",value:function(e,t){if(e=Me(e)){var r=de.findKey(this,e);return!(!r||void 0===this[r]||t&&!He(0,this[r],r,t))}return!1}},{key:"delete",value:function(e,t){var r=this,n=!1;function o(e){if(e=Me(e)){var o=de.findKey(r,e);!o||t&&!He(0,r[o],o,t)||(delete r[o],n=!0)}}return de.isArray(e)?e.forEach(o):o(e),n}},{key:"clear",value:function(e){for(var t=Object.keys(this),r=t.length,n=!1;r--;){var o=t[r];e&&!He(0,this[o],o,e,!0)||(delete this[o],n=!0)}return n}},{key:"normalize",value:function(e){var t=this,r={};return de.forEach(this,(function(n,o){var i=de.findKey(r,o);if(i)return t[i]=ze(n),void delete t[o];var a=e?function(e){return e.trim().toLowerCase().replace(/([a-z\d])(\w*)/g,(function(e,t,r){return t.toUpperCase()+r}))}(o):String(o).trim();a!==o&&delete t[o],t[a]=ze(n),r[a]=!0})),this}},{key:"concat",value:function(){for(var e,t=arguments.length,r=new Array(t),n=0;n1?r-1:0),o=1;o1&&void 0!==arguments[1]?arguments[1]:Date.now();o=i,r=null,n&&(clearTimeout(n),n=null),e.apply(void 0,g(t))};return[function(){for(var e=Date.now(),t=e-o,u=arguments.length,s=new Array(u),c=0;c=i?a(s,e):(r=s,n||(n=setTimeout((function(){n=null,a(r)}),i-t)))},function(){return r&&a(r)}]}de.inherits(Ge,he,{__CANCEL__:!0});var Qe=function(e,t){var r=arguments.length>2&&void 0!==arguments[2]?arguments[2]:3,n=0,o=$e(50,250);return Ye((function(r){var i=r.loaded,a=r.lengthComputable?r.total:void 0,u=i-n,s=o(u);n=i;var c=m({loaded:i,total:a,progress:a?i/a:void 0,bytes:u,rate:s||void 0,estimated:s&&a&&i<=a?(a-i)/s:void 0,event:r,lengthComputable:null!=a},t?"download":"upload",!0);e(c)}),r)},Ze=function(e,t){var r=null!=e;return[function(n){return t[0]({lengthComputable:r,total:e,loaded:n})},t[1]]},et=function(e){return function(){for(var t=arguments.length,r=new Array(t),n=0;n1?t-1:0),n=1;n1?"since :\n"+s.map(xt).join("\n"):" "+xt(s[0]):"as no adapter specified"),"ERR_NOT_SUPPORT")}return n},adapters:St};function Tt(e){if(e.cancelToken&&e.cancelToken.throwIfRequested(),e.signal&&e.signal.aborted)throw new Ge(null,e)}function jt(e){return Tt(e),e.headers=We.from(e.headers),e.data=Ke.call(e,e.transformRequest),-1!==["post","put","patch"].indexOf(e.method)&&e.headers.setContentType("application/x-www-form-urlencoded",!1),kt.getAdapter(e.adapter||De.adapter,e)(e).then((function(t){return Tt(e),t.data=Ke.call(e,e.transformResponse,t),t.headers=We.from(t.headers),t}),(function(t){return Ve(t)||(Tt(e),t&&t.response&&(t.response.data=Ke.call(e,e.transformResponse,t.response),t.response.headers=We.from(t.response.headers))),Promise.reject(t)}))}var At="1.13.2",Pt={};["object","boolean","number","function","string","symbol"].forEach((function(e,t){Pt[e]=function(r){return f(r)===e||"a"+(t<1?"n ":" ")+e}}));var Lt={};Pt.transitional=function(e,t,r){function n(e,t){return"[Axios v1.13.2] Transitional option '"+e+"'"+t+(r?". "+r:"")}return function(r,o,i){if(!1===e)throw new he(n(o," has been removed"+(t?" in "+t:"")),he.ERR_DEPRECATED);return t&&!Lt[o]&&(Lt[o]=!0,console.warn(n(o," has been deprecated since v"+t+" and will be removed in the near future"))),!e||e(r,o,i)}},Pt.spelling=function(e){return function(t,r){return console.warn("".concat(r," is likely a misspelling of ").concat(e)),!0}};var Nt={assertOptions:function(e,t,r){if("object"!==f(e))throw new he("options must be an object",he.ERR_BAD_OPTION_VALUE);for(var n=Object.keys(e),o=n.length;o-- >0;){var i=n[o],a=t[i];if(a){var u=e[i],s=void 0===u||a(u,i,e);if(!0!==s)throw new he("option "+i+" must be "+s,he.ERR_BAD_OPTION_VALUE)}else if(!0!==r)throw new he("Unknown option "+i,he.ERR_BAD_OPTION)}},validators:Pt},Ct=Nt.validators,_t=function(){function e(t){h(this,e),this.defaults=t||{},this.interceptors={request:new Te,response:new Te}}var t;return y(e,[{key:"request",value:(t=d(s().mark((function e(t,r){var n,o;return s().wrap((function(e){for(;;)switch(e.prev=e.next){case 0:return e.prev=0,e.next=3,this._request(t,r);case 3:return e.abrupt("return",e.sent);case 6:if(e.prev=6,e.t0=e.catch(0),e.t0 instanceof Error){n={},Error.captureStackTrace?Error.captureStackTrace(n):n=new Error,o=n.stack?n.stack.replace(/^.+\n/,""):"";try{e.t0.stack?o&&!String(e.t0.stack).endsWith(o.replace(/^.+\n.+\n/,""))&&(e.t0.stack+="\n"+o):e.t0.stack=o}catch(e){}}throw e.t0;case 10:case"end":return e.stop()}}),e,this,[[0,6]])}))),function(e,r){return t.apply(this,arguments)})},{key:"_request",value:function(e,t){"string"==typeof e?(t=t||{}).url=e:t=e||{};var r=t=it(this.defaults,t),n=r.transitional,o=r.paramsSerializer,i=r.headers;void 0!==n&&Nt.assertOptions(n,{silentJSONParsing:Ct.transitional(Ct.boolean),forcedJSONParsing:Ct.transitional(Ct.boolean),clarifyTimeoutError:Ct.transitional(Ct.boolean)},!1),null!=o&&(de.isFunction(o)?t.paramsSerializer={serialize:o}:Nt.assertOptions(o,{encode:Ct.function,serialize:Ct.function},!0)),void 0!==t.allowAbsoluteUrls||(void 0!==this.defaults.allowAbsoluteUrls?t.allowAbsoluteUrls=this.defaults.allowAbsoluteUrls:t.allowAbsoluteUrls=!0),Nt.assertOptions(t,{baseUrl:Ct.spelling("baseURL"),withXsrfToken:Ct.spelling("withXSRFToken")},!0),t.method=(t.method||this.defaults.method||"get").toLowerCase();var a=i&&de.merge(i.common,i[t.method]);i&&de.forEach(["delete","get","head","post","put","patch","common"],(function(e){delete i[e]})),t.headers=We.concat(a,i);var u=[],s=!0;this.interceptors.request.forEach((function(e){"function"==typeof e.runWhen&&!1===e.runWhen(t)||(s=s&&e.synchronous,u.unshift(e.fulfilled,e.rejected))}));var c,f=[];this.interceptors.response.forEach((function(e){f.push(e.fulfilled,e.rejected)}));var l,p=0;if(!s){var d=[jt.bind(this),void 0];for(d.unshift.apply(d,u),d.push.apply(d,f),l=d.length,c=Promise.resolve(t);p0;)n._listeners[t](e);n._listeners=null}})),this.promise.then=function(e){var t,r=new Promise((function(e){n.subscribe(e),t=e})).then(e);return r.cancel=function(){n.unsubscribe(t)},r},t((function(e,t,o){n.reason||(n.reason=new Ge(e,t,o),r(n.reason))}))}return y(e,[{key:"throwIfRequested",value:function(){if(this.reason)throw this.reason}},{key:"subscribe",value:function(e){this.reason?e(this.reason):this._listeners?this._listeners.push(e):this._listeners=[e]}},{key:"unsubscribe",value:function(e){if(this._listeners){var t=this._listeners.indexOf(e);-1!==t&&this._listeners.splice(t,1)}}},{key:"toAbortSignal",value:function(){var e=this,t=new AbortController,r=function(e){t.abort(e)};return this.subscribe(r),t.signal.unsubscribe=function(){return e.unsubscribe(r)},t.signal}}],[{key:"source",value:function(){var t;return{token:new e((function(e){t=e})),cancel:t}}}]),e}(),Bt=Ft;var Dt={Continue:100,SwitchingProtocols:101,Processing:102,EarlyHints:103,Ok:200,Created:201,Accepted:202,NonAuthoritativeInformation:203,NoContent:204,ResetContent:205,PartialContent:206,MultiStatus:207,AlreadyReported:208,ImUsed:226,MultipleChoices:300,MovedPermanently:301,Found:302,SeeOther:303,NotModified:304,UseProxy:305,Unused:306,TemporaryRedirect:307,PermanentRedirect:308,BadRequest:400,Unauthorized:401,PaymentRequired:402,Forbidden:403,NotFound:404,MethodNotAllowed:405,NotAcceptable:406,ProxyAuthenticationRequired:407,RequestTimeout:408,Conflict:409,Gone:410,LengthRequired:411,PreconditionFailed:412,PayloadTooLarge:413,UriTooLong:414,UnsupportedMediaType:415,RangeNotSatisfiable:416,ExpectationFailed:417,ImATeapot:418,MisdirectedRequest:421,UnprocessableEntity:422,Locked:423,FailedDependency:424,TooEarly:425,UpgradeRequired:426,PreconditionRequired:428,TooManyRequests:429,RequestHeaderFieldsTooLarge:431,UnavailableForLegalReasons:451,InternalServerError:500,NotImplemented:501,BadGateway:502,ServiceUnavailable:503,GatewayTimeout:504,HttpVersionNotSupported:505,VariantAlsoNegotiates:506,InsufficientStorage:507,LoopDetected:508,NotExtended:510,NetworkAuthenticationRequired:511,WebServerIsDown:521,ConnectionTimedOut:522,OriginIsUnreachable:523,TimeoutOccurred:524,SslHandshakeFailed:525,InvalidSslCertificate:526};Object.entries(Dt).forEach((function(e){var t=b(e,2),r=t[0],n=t[1];Dt[n]=r}));var It=Dt;var qt=function e(t){var r=new Ut(t),n=O(Ut.prototype.request,r);return de.extend(n,Ut.prototype,r,{allOwnKeys:!0}),de.extend(n,r,null,{allOwnKeys:!0}),n.create=function(r){return e(it(t,r))},n}(De);return qt.Axios=Ut,qt.CanceledError=Ge,qt.CancelToken=Bt,qt.isCancel=Ve,qt.VERSION=At,qt.toFormData=Ee,qt.AxiosError=he,qt.Cancel=qt.CanceledError,qt.all=function(e){return Promise.all(e)},qt.spread=function(e){return function(t){return e.apply(null,t)}},qt.isAxiosError=function(e){return de.isObject(e)&&!0===e.isAxiosError},qt.mergeConfig=it,qt.AxiosHeaders=We,qt.formToJSON=function(e){return Fe(de.isHTMLForm(e)?new FormData(e):e)},qt.getAdapter=kt.getAdapter,qt.HttpStatusCode=It,qt.default=qt,qt})); \ No newline at end of file diff --git a/ui/_/code/shared.css b/ui/_/code/shared.css index 4c1c4ca..5232198 100644 --- a/ui/_/code/shared.css +++ b/ui/_/code/shared.css @@ -43,10 +43,10 @@ } body { + background-color: #2B311A; + color: var(--accent); font-family: 'Bona Nova', sans-serif; font-size: 16px; - background-color: var(--main); - color: var(--accent); } #title { diff --git a/ui/desktop/components/AppMenu.js b/ui/desktop/components/AppMenu.js deleted file mode 100644 index 96a507e..0000000 --- a/ui/desktop/components/AppMenu.js +++ /dev/null @@ -1,133 +0,0 @@ -css(` - app-menu { - color: var(--tan); - transform: translateX(-50%); - transition: transform .3s; - display: flex; gap: 2em; position: fixed; left: 50vw; bottom: 2em; - } - - app-menu.minimized { - color: var(--accent); - transform: translate(-50%, 65%); - border: 0.2px solid var(--accent); - padding-top: 0.5em; - padding-left: 2em; - padding-right: 2em; - padding-bottom: 4em; - bottom: 1em; - border-radius: 12px; - } - - app-menu p { - cursor: default; - transition: transform .3s, text-decoration .3s; - padding: 0.5em; - border-radius: 5px; - text-underline-offset: 5px; - } - app-menu p:hover { - text-decoration: underline; - transform: translateY(-5%) - } - app-menu p.touched { - text-decoration: underline; - transform: translateY(0%) - } - app-menu p.selected { - text-decoration: underline; - transform: translateY(-10%) - } - - #divider.minimized { - display: none; - } -`) - -register( - -class AppMenu extends Shadow { - selected; - - constructor(selected) { - super() - this.selected = selected - } - - render() { - VStack(() => { - HStack(() => { - p("Forum") - p("Messages") - p("Market") - p("Jobs") - }) - .justifyContent("center") - .gap(1.5, em) - .paddingRight(2, em) - - img("/_/images/divider.svg", "40vw") - .attr({ - "id": "divider", - }) - }) - .gap(0.5, em) - .onNavigate(() => { - if(window.location.pathname === "/") { - this.styleMaximized() - $("app-window").close() - } else { - this.styleMinimized() - $("app-window").open(this.selected) - } - }) - .onAppear(() => { - Array.from(this.querySelectorAll("p")).forEach((el) => { - el.addEventListener("mousedown", (e) => { - el.classList.add("touched") - }) - }) - window.addEventListener("mouseup", (e) => { - let target = e.target - if(!target.matches("app-menu p")) { - return - } - - target.classList.remove("touched") - - if(target.classList.contains("selected")) { - this.selected = "" - window.navigateTo("/") - } else { - this.selected = target.innerText - window.navigateTo("/app/" + target.innerText.toLowerCase()) - } - }) - }) - - if(this.selected) { - this.styleMinimized() - } - } - - styleMaximized() { - $$("app-menu p").forEach((el) => { - el.classList.remove("selected") - }) - this.classList.remove("minimized") - $("#divider").style.display = "" - } - - styleMinimized() { - $$("app-menu p").forEach((el) => { - if(el.innerText !== this.selected) { - el.classList.remove("selected") - } else { - el.classList.add("selected") - } - }) - this.classList.add("minimized") - $("#divider").style.display = "none" - } -} - -, "app-menu") \ No newline at end of file diff --git a/ui/desktop/components/AppWindow.js b/ui/desktop/components/AppWindow.js deleted file mode 100644 index 3f34b4a..0000000 --- a/ui/desktop/components/AppWindow.js +++ /dev/null @@ -1,54 +0,0 @@ -import "../apps/Forum/Forum.js" -import "../apps/Tasks/Tasks.js" -import "../apps/Messages/Messages.js" -import "../apps/Market/Market.js" -import "../apps/Jobs/Jobs.js" - -class AppWindow extends Shadow { - app; - - constructor(app) { - super() - this.app = app - } - - render() { - ZStack(() => { - switch(this.app) { - case "Forum": - Forum() - break; - case "Messages": - Messages() - break; - case "Market": - Market() - break; - case "Jobs": - Jobs() - break; - } - }) - .position("fixed") - .display(this.app ? 'block' : 'none') - .width(100, "vw") - .height(100, "vh") - .background("#591d10") - .x(0) - .y(0) - // .backgroundImage("/_/images/fabric.png") - // .backgroundSize("33vw auto") - } - - open(app) { - this.app = app - this.rerender() - } - - close() { - this.style.display = "none" - } - -} - -register(AppWindow, "app-window") \ No newline at end of file diff --git a/ui/desktop/components/Home.js b/ui/desktop/components/Home.js index 54fe664..2a19cde 100644 --- a/ui/desktop/components/Home.js +++ b/ui/desktop/components/Home.js @@ -1,61 +1,20 @@ -import "./AppWindow.js" -import "./AppMenu.js" -import "./ProfileButton.js" -import "./InputBox.js" -import "./Sidebar.js" - +import "./LogTable.js" + class Home extends Shadow { render() { ZStack(() => { - img("/_/icons/logo.svg", "2.5em") - .position("fixed") - .left(3, em) - .top(3, vh) - .zIndex(3) - .onClick(() => { - window.navigateTo("/") - }) - - div() - .width(100, vw) - .height(100, vh) - .margin(0) - .backgroundImage("/_/images/the_return.webp") - .backgroundSize("cover") - .backgroundPosition("48% 65%") - .backgroundRepeat("no-repeat") switch(window.location.pathname) { case "/": - AppWindow() - AppMenu() + LogTable() break - case "/app/jobs": - AppWindow("Jobs") - AppMenu("Jobs") - break; - case "/app/messages": - AppWindow("Messages") - AppMenu("Messages") - break; - case "/app/market": - AppWindow("Market") - AppMenu("Market") - break; - case "/app/forum": - AppWindow("Forum") - AppMenu("Forum") - break; default: throw new Error("Unknown route!") } HStack(() => { - ProfileButton() - .zIndex(1) - .cursor("default") a("/signout", "Sign Out") .background("transparent") diff --git a/ui/desktop/components/LogTable.js b/ui/desktop/components/LogTable.js new file mode 100644 index 0000000..96bc19c --- /dev/null +++ b/ui/desktop/components/LogTable.js @@ -0,0 +1,9 @@ +class LogTable extends Shadow { + render() { + VStack(() => { + + }) + } +} + +register(LogTable) \ No newline at end of file diff --git a/ui/desktop/index.html b/ui/desktop/index.html index ca92388..fa1dd9a 100644 --- a/ui/desktop/index.html +++ b/ui/desktop/index.html @@ -6,7 +6,6 @@ - diff --git a/ui/public/index.html b/ui/public/index.html index 16c4c9c..8d616bd 100644 --- a/ui/public/index.html +++ b/ui/public/index.html @@ -6,12 +6,6 @@ diff --git a/ui/public/pages/Events.js b/ui/public/pages/Events.js deleted file mode 100644 index 15612d5..0000000 --- a/ui/public/pages/Events.js +++ /dev/null @@ -1,325 +0,0 @@ -class Events extends Shadow { - - events = [ - { - date: `January 23, 2025`, - title: `Hyperia Winter Ball`, - description: `Join us in Austin, Texas for a dance. Live music and drinks will be included.
Admission for men is $50, women are free. Open to the public.`, - location: `Austin, TX` - } - ] - - render() { - ZStack(() => { - VStack(() => { - - h1("HYPERIA") - .marginBottom(0, em) - - p("Public Events") - .fontSize(1.2, em) - .marginBottom(2, em) - - const Stack = window.isMobile() ? VStack : HStack - Stack(() => { - - VStack(() => { - p(`January 23, 2025`) - - p(`Hyperia Winter Ball`) - .fontSize(1.2, em) - - p(`Austin, TX`) - - }) - - p(`Join us in Austin, Texas for a great dance, with free drinks and live music.

Admission: $35 for men, women are free.`) - .marginRight(4, em) - - HStack(() => { - img("/_/icons/creditcards/visa.svg") - img("/_/icons/creditcards/mastercard.svg") - img("/_/icons/creditcards/discover.svg") - img("/_/icons/creditcards/amex.svg") - }) - .alignSelf("flex-start") - .height(2, em) - .maxWidth(40, vw) - - button("Buy Ticket") - .color("var(--darkbrown") - .border("1px solid #ab2f007d") - .background('var(--green)') - .marginLeft("auto") - .onClick(async function() { - this.innerText = "Loading..." - const res = await fetch("/create-checkout-session", { method: "POST" }); - const data = await res.json(); - window.location = data.url; - }) - }) - .gap(3, em) - .color("var(--darkbrown)") - .background(`var(--accent)`) - .padding(1, em) - .borderRadius(12, px) - .border("2px solid #ab2f007d") - }) - .marginLeft(window.isMobile() ? 0 : 15, vmax) - .marginRight(window.isMobile() ? 0 : 15, vmax) - .marginTop(10, vmax) - - HStack(() => { - p("Privacy Policy") - .onHover(function (hovering) { - if(hovering) { - this.style.color = "var(--darkbrown)" - } else { - this.style.color = "" - } - }) - .onClick(() => { - this.$("#policyWindow").style.display = "flex" - }) - p("Refund and Return Policy") - .onHover(function (hovering) { - if(hovering) { - this.style.color = "var(--darkbrown)" - } else { - this.style.color = "" - } - }) - .onClick(() => { - this.$("#refundWindow").style.display = "flex" - }) - p("Contact Us") - .onHover(function (hovering) { - if(hovering) { - this.style.color = "var(--darkbrown)" - } else { - this.style.color = "" - } - }) - .onClick(() => { - this.$("#contactWindow").style.display = "flex" - }) - }) - .x(50, vw).yBottom(0, vh) - .center() - .gap(2, em) - .opacity(0.5) - .cursor("default") - }) - - VStack(() => { - - p("Privacy Policy") - .fontSize(2, em) - .fontWeight(600) - .marginBottom(1, em) - - p("We value your privacy. This Privacy Policy explains how we collect, use, store, and protect your information when you use our website or services.") - - p("1. Information We Collect") - .fontWeight(600) - .marginTop(1, em) - - p("• Personal information you provide, such as your name, email address, or other contact details.") - p("• Automatically collected data, including IP address, browser type, device information, and usage statistics.") - p("• Cookies or similar tracking technologies that help us improve the user experience.") - - p("2. How We Use Your Information") - .fontWeight(600) - .marginTop(1, em) - - p("• To operate and improve our website and services.") - p("• To communicate with you about updates, support requests, or account-related matters.") - p("• To maintain security, prevent fraud, and ensure proper functionality.") - - p("3. How We Share Information") - .fontWeight(600) - .marginTop(1, em) - - p("We do not sell your personal information. We may share data only with trusted service providers who help us operate the platform, or when required by law.") - - p("4. Data Storage & Security") - .fontWeight(600) - .marginTop(1, em) - - p("We use reasonable technical and administrative safeguards to protect your information. However, no system is completely secure, and we cannot guarantee absolute protection.") - - p("5. Cookies") - .fontWeight(600) - .marginTop(1, em) - - p("Our site may use cookies to remember preferences, analyze traffic, and enhance usability. You can disable cookies in your browser settings, but some features may stop working.") - - p("6. Your Rights") - .fontWeight(600) - .marginTop(1, em) - - p("Depending on your location, you may have rights to access, update, delete, or request a copy of your personal data. Contact us if you wish to exercise these rights.") - - p("7. Third-Party Links") - .fontWeight(600) - .marginTop(1, em) - - p("Our website may contain links to third-party sites. We are not responsible for their content or privacy practices.") - - p("8. Changes to This Policy") - .fontWeight(600) - .marginTop(1, em) - - p("We may update this Privacy Policy from time to time. Updated versions will be posted on this page with the effective date.") - - p("9. Contact Us") - .fontWeight(600) - .marginTop(1, em) - - p("If you have any questions about this Privacy Policy, feel free to contact us at info@hyperia.so.") - - p("x") - .onClick(function (done) { - if(done) { - this.parentElement.style.display = "none" - } - }) - .color("var(--red)") - .xRight(1, em).y(1, em) - .fontSize(2, em) - .cursor("pointer") - - }) - .x(50, vw).y(50, vh) - .width(70, vw).height(70, vh) - .center() - .backgroundColor("var(--accent)") - .display("none") - .overflow("scroll") - .padding(1, em) - .border("3px solid black") - .color("var(--darkbrown)") - .attr({ id: "policyWindow" }) - - VStack(() => { - - p("Refund & Return Policy") - .fontSize(2, em) - .fontWeight(600) - .marginBottom(1, em) - - p("1. Eligibility for Refunds") - .fontWeight(600) - .marginTop(1, em) - - p("• Refund requests may be considered when submitted within 14 days of purchase.") - p("• To qualify, you must provide proof of purchase and a valid reason for the request.") - p("• Certain digital products or services may be non-refundable once accessed or downloaded.") - - p("2. Non-Refundable Items") - .fontWeight(600) - .marginTop(1, em) - - p("• Products or services that have already been delivered, downloaded, or accessed in full.") - p("• Custom work, personalized items, or one-time service fees.") - p("• Any promotional or discounted items, unless required by law.") - - p("3. Returns (If Applicable)") - .fontWeight(600) - .marginTop(1, em) - - p("• Physical items must be returned in their original condition.") - p("• You are responsible for return shipping costs unless the item was defective or incorrect.") - p("• Items damaged through misuse or neglect cannot be returned.") - - p("4. Processing Refunds") - .fontWeight(600) - .marginTop(1, em) - - p("• Approved refunds are issued to the original payment method.") - p("• Processing times may vary depending on your bank or payment provider.") - p("• We will notify you once your refund has been initiated.") - - p("5. Cancellations") - .fontWeight(600) - .marginTop(1, em) - - p("• Orders or subscriptions may be cancelled before fulfillment or renewal.") - p("• If Hyperia declare a cancellation of any product or event, a refund will be issued to all parties.") - - p("6. Contact for Refund Requests") - .fontWeight(600) - .marginTop(1, em) - - p("If you need to request a refund, return an item, or cancel an order, please contact us at info@hyperia.so. Include your order number and relevant details so we can assist you promptly.") - - p("7. Policy Updates") - .fontWeight(600) - .marginTop(1, em) - - p("We may update this Refund & Return Policy from time to time. Any changes will be posted on this page with the effective date.") - - p("x") - .onClick(function (done) { - if(done) { - this.parentElement.style.display = "none" - } - }) - .color("var(--red)") - .xRight(1, em).y(1, em) - .fontSize(2, em) - .cursor("pointer") - - }) - .x(50, vw).y(50, vh) - .width(70, vw).height(70, vh) - .center() - .backgroundColor("var(--accent)") - .display("none") - .overflow("scroll") - .padding(1, em) - .border("3px solid black") - .color("var(--darkbrown)") - .attr({ id: "refundWindow" }) - - - VStack(() => { - - p("Contact Us") - .fontSize(2, em) - .fontWeight(600) - .marginBottom(1, em) - - p("Email: info@hyperia.so") - p("Phone: 813-373-9100") - p("Address: 2014 E 9th St, Unit A, Austin TX") - - p("x") - .onClick(function (done) { - if(done) { - this.parentElement.style.display = "none" - } - }) - .color("var(--red)") - .xRight(1, em).y(1, em) - .fontSize(2, em) - .cursor("pointer") - - }) - .gap(2, em) - .x(50, vw).y(50, vh) - .width(50, vw).height(50, vh) - .center() - .backgroundColor("var(--accent)") - .display("none") - .overflow("scroll") - .padding(1, em) - .border("3px solid black") - .color("var(--darkbrown)") - .attr({ id: "contactWindow" }) - - - } -} - -register(Events) \ No newline at end of file diff --git a/ui/public/pages/Home.js b/ui/public/pages/Home.js index faead38..dbb4046 100644 --- a/ui/public/pages/Home.js +++ b/ui/public/pages/Home.js @@ -1,79 +1,37 @@ -import "../components/NavBar.js" -import "../components/SignupForm.js" -import "./Why.js" -import "./Events.js" -import "./Join.js" -import "./SignIn.js" -import "./Success.js" - class Home extends Shadow { + + inputStyles(el) { + return el + .color("var(--accent)") + .border("1px solid var(--accent)") + } + render() { ZStack(() => { + ZStack(() => { + if(window.location.search.includes("new")) { + p("Welcome to Hyperia! You may now log in.") + .x(50, vw).y(40, vh) + .center() + } - NavBar() - - img("/_/icons/logo.svg", "2.5em") - .onClick((done) => { - if(!done) return - window.navigateTo("/") + form(() => { + input("Password") + .attr({name: "password", type: "password"}) + .margin(1, em) + .styles(this.inputStyles) + button("Submit") + .margin(1, em) }) - .position("absolute") - .left(50, vw).top(4, em) + .attr({action: "/login", method: "POST"}) + .x(50, vw).y(50, vh) .center() - .transform(`translate(${window.isMobile() ? "-50%" : "-2em"}, -50%)`) - - switch(window.location.pathname) { - case "/": - img("/_/images/knight.png", "29vmax") - .position("absolute") - .left(50, vw).top(isMobile() ? 50 : 53, vh) - .center() - - p("H   Y   P   E   R   I   A  ") - .x(50, vw).y(isMobile() ? 50 : 53, vh) - .textAlign("center") - .center() - .color("var(--gold)") - .fontSize(isMobile() ? 6 : 5, vw) - .maxWidth(isMobile() ? 0.8 : 100, em) - - if(!isMobile()) { - let text = "A Classical Christian Network" - p(isMobile() ? text : text.toUpperCase()) - .x(50, vw).yBottom(isMobile() ? 1 : 3, vh) - .center() - .letterSpacing(0.3, em) - .width(isMobile() ? 80 : 100, vw) - .fontSize(isMobile() ? 0.8 : 1, em) - .textAlign("center") - } - break; - case "/why": - Why() - break; - case "/events": - Events() - break; - case "/join": - Join() - break; - case "/success": - Success() - break; - - default: - if(window.location.pathname.startsWith("/signup")) { - SignupForm() - } else if(window.location.pathname.startsWith("/signin")) { - SignIn() - } - } - - }) - .onNavigate(() => { - this.rerender() + }) }) + .width(98, vw).height(98, vh) + .background("#7B413A") + .x(1, vw).y(1, vh) } } diff --git a/ui/public/pages/Join.js b/ui/public/pages/Join.js deleted file mode 100644 index 961262f..0000000 --- a/ui/public/pages/Join.js +++ /dev/null @@ -1,29 +0,0 @@ -class Join extends Shadow { - render() { - - VStack(() => { - - - p("Membership is invitation-only. Wait to meet one of us, or come to one of our events!") - - - // p("Membership is invitation-only. But sign up for our newsletter to hear about more events!") - - // HStack(() => { - // input("Email", "40vmin") - // .attr({name: "email", type: "email"}) - - // button("Sign Up") - // .width(15, vmin) - // }) - // .gap(1, em) - // .marginTop(1, em) - }) - .alignItems("center") - .maxWidth(90, vw) - .x(50, vw).y(50, vh) - .center() - } -} - -register(Join) \ No newline at end of file diff --git a/ui/public/pages/Success.js b/ui/public/pages/Success.js deleted file mode 100644 index c3753f6..0000000 --- a/ui/public/pages/Success.js +++ /dev/null @@ -1,9 +0,0 @@ -class Success extends Shadow { - render() { - p("Thanks for your purchase! You will receive a confirmation email shortly.

Keep that email; it will be checked at the door.") - .x(50, vw).y(50, vh) - .center() - } -} - -register(Success) \ No newline at end of file diff --git a/ui/public/pages/Why.js b/ui/public/pages/Why.js deleted file mode 100644 index f65b12a..0000000 --- a/ui/public/pages/Why.js +++ /dev/null @@ -1,21 +0,0 @@ -class Why extends Shadow { - render() { - p(`I grew up going to Classical Christian schools all my life. Little did I know, this was a very unique experience - we got to learn all about our history, and everyone had a shared moral understanding. - -

Only when I went out into the world did I realize that most Americans have no idea what this is like. They have never been a part of a shared culture, and the only value they know is multiculturalism. - -

As adults, that is the world the we are all expected to live in. - -

Classical Christian schools are great, but what if I want to live a Classical Christian life? - -

That is what Hyperia is for. It is a Classical Christian space for adults. - -

-- Sam Russell, Founder - `) - .marginTop(window.isMobile() ? 20 : 30, vh) - .marginHorizontal(window.isMobile() ? 10 : 20, vw) - .marginBottom(20, vh) - } -} - -register(Why) \ No newline at end of file diff --git a/ui/public/paintingTags.js b/ui/public/paintingTags.js deleted file mode 100644 index 169ed0d..0000000 --- a/ui/public/paintingTags.js +++ /dev/null @@ -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 = `${paintingName}
${artistName}`; - 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); \ No newline at end of file diff --git a/ui/public/scrollEffect.js b/ui/public/scrollEffect.js deleted file mode 100644 index 84b99f2..0000000 --- a/ui/public/scrollEffect.js +++ /dev/null @@ -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; - } -}