From ed6d885557a18c86f683101474173ed6e0ca938a Mon Sep 17 00:00:00 2001 From: metacryst Date: Sun, 30 Nov 2025 02:50:10 -0600 Subject: [PATCH] 11.2025: new version released, sample folder added --- .env | 1 + Sample/.gitignore | 2 + Sample/db/db.json | 0 Sample/package.json | 18 + Sample/server/db/db.js | 12 + Sample/server/index.js | 100 ++ Sample/ui/_/code/quill.js | 1047 ++++++++++++++++++ Sample/ui/_/code/shared.css | 0 Sample/ui/components/Home.js | 7 + Sample/ui/index.html | 13 + Sample/ui/index.js | 2 + VSCode/README.md | 2 +- VSCode/deploy-howto.md | 15 + VSCode/package.json | 2 +- VSCode/quill-1.0.5.vsix | Bin 0 -> 166836 bytes VSCode/snippets-html.json | 43 +- VSCode/snippets-js.json | 34 +- about.md | 26 - app.js | 13 - deploy-howto.md | 5 - index.html | 20 - index.js | 1939 +++++++++++++++------------------- notes.txt | 151 --- path.js | 151 --- 24 files changed, 2098 insertions(+), 1505 deletions(-) create mode 100644 .env create mode 100644 Sample/.gitignore create mode 100644 Sample/db/db.json create mode 100644 Sample/package.json create mode 100644 Sample/server/db/db.js create mode 100644 Sample/server/index.js create mode 100644 Sample/ui/_/code/quill.js create mode 100644 Sample/ui/_/code/shared.css create mode 100644 Sample/ui/components/Home.js create mode 100644 Sample/ui/index.html create mode 100644 Sample/ui/index.js create mode 100644 VSCode/deploy-howto.md create mode 100644 VSCode/quill-1.0.5.vsix delete mode 100644 about.md delete mode 100644 app.js delete mode 100644 deploy-howto.md delete mode 100644 index.html delete mode 100644 notes.txt delete mode 100644 path.js diff --git a/.env b/.env new file mode 100644 index 0000000..b117f22 --- /dev/null +++ b/.env @@ -0,0 +1 @@ +VSCE_PAT=9wucEHBNFD5RTS403Oyoflyi984cAwAfa42FHN7tmqmzfbXsSKP9JQQJ99BKACAAAAAAAAAAAAAGAZDO25Ro \ No newline at end of file diff --git a/Sample/.gitignore b/Sample/.gitignore new file mode 100644 index 0000000..25c8fdb --- /dev/null +++ b/Sample/.gitignore @@ -0,0 +1,2 @@ +node_modules +package-lock.json \ No newline at end of file diff --git a/Sample/db/db.json b/Sample/db/db.json new file mode 100644 index 0000000..e69de29 diff --git a/Sample/package.json b/Sample/package.json new file mode 100644 index 0000000..e7632af --- /dev/null +++ b/Sample/package.json @@ -0,0 +1,18 @@ +{ + "name": "Quill Starter", + "version": "1.0.0", + "description": "", + "main": "index.js", + "scripts": { + "start": "node server/index.js", + "test": "echo \"Error: no test specified\" && exit 1" + }, + "author": "", + "license": "ISC", + "dependencies": { + "chalk": "^4.1.2", + "cors": "^2.8.5", + "express": "^4.18.2", + "moment": "^2.30.1" + } +} diff --git a/Sample/server/db/db.js b/Sample/server/db/db.js new file mode 100644 index 0000000..dc4198b --- /dev/null +++ b/Sample/server/db/db.js @@ -0,0 +1,12 @@ +const fs = require('fs/promises'); + +export default class Database { + + constructor() { + + } + + async saveData() { + + } +} \ No newline at end of file diff --git a/Sample/server/index.js b/Sample/server/index.js new file mode 100644 index 0000000..a44f3e0 --- /dev/null +++ b/Sample/server/index.js @@ -0,0 +1,100 @@ +const express = require('express'); +const cors = require('cors'); +const http = require('http'); +const chalk = require('chalk'); +const moment = require('moment'); +const path = require('path'); + +class Server { + db; + UIPath = path.join(__dirname, '../ui') + + registerRoutes(router) { + router.post('/join', this.join) + router.post('/contact', this.contact) + router.get('/*', this.get) + return router + } + + join = (req, res) => { + + } + + contact = (req, res) => { + + } + + get = async (req, res) => { + console.log(this.UIPath) + let url = req.url + let filePath; + if(url.startsWith("/_")) { + filePath = path.join(this.UIPath, url); + } else if(url.includes("75820185")) { + filePath = path.join(this.UIPath, url.split("75820185")[1]); + } else { + filePath = path.join(this.UIPath, "index.html"); + } + + res.sendFile(filePath); + } + + logRequest(req, res, next) { + const formattedDate = moment().format('M.D'); + const formattedTime = moment().format('h:mma'); + if(req.url.includes("/api/")) { + console.log(chalk.blue(` ${req.method} ${req.url} | ${formattedDate} ${formattedTime}`)); + } else { + if(req.url === "/") + console.log(chalk.gray(` ${req.method} ${req.url} | ${formattedDate} ${formattedTime}`)); + } + next(); + } + + logResponse(req, res, next) { + const originalSend = res.send; + res.send = function (body) { + if(res.statusCode >= 400) { + console.log(chalk.blue( `<-${chalk.red(res.statusCode)}- ${req.method} ${req.url} | ${chalk.red(body)}`)); + } else { + console.log(chalk.blue(`<-${res.statusCode}- ${req.method} ${req.url}`)); + } + originalSend.call(this, body); + }; + next(); + } + + constructor() { + const app = express(); + app.use(cors({ origin: '*' })); + app.use(express.json()); + app.use(express.urlencoded({ extended: true })); + + app.use(this.logRequest); + app.use(this.logResponse); + + let router = express.Router(); + this.registerRoutes(router) + app.use('/', router); + + const server = http.createServer(app); + const PORT = 3004; + server.listen(PORT, () => { + console.log("\n") + console.log(chalk.yellow("*************** Comal YR ***************")) + console.log(chalk.yellowBright(`Server is running on port ${PORT}: http://localhost`)); + console.log(chalk.yellow("***************************************")) + console.log("\n") + }); + + process.on('SIGINT', async () => { + console.log(chalk.red('Closing server...')); + console.log(chalk.green('Database connection closed.')); + process.exit(0); + }); + + Object.preventExtensions(this); + } +} + +const server = new Server() \ No newline at end of file diff --git a/Sample/ui/_/code/quill.js b/Sample/ui/_/code/quill.js new file mode 100644 index 0000000..fcebb29 --- /dev/null +++ b/Sample/ui/_/code/quill.js @@ -0,0 +1,1047 @@ +/* + Sam Russell + Captured Sun + 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 + 11.23.25 - Added onSubmit() event for form submission, added marginHorizontal() and marginVertical() + 11.20.25 - Added "pct" style unit, added alignVertical and alignHorizontal for flex boxes + 11.19.25 - Allowing for "auto" values in otherwise numeric styles, adding vmin and vmax units + 11.17.25.3 - Adding styles() and fixing dynamic function from earlier + 11.17.25.2 - Fixing onNavigate() and onAppear() + 11.17.25 - Added dynamic function to have units in style func parameters. + 11.14.25 - Added onTouch, onTap. Changed style setters to work with Safari. Added center() funcs. + 11.13.25 - changed onFocus() to be a boolean event, added onInput() + 11.9.25 - changed p(innerText) to p(innerHTML), adjusted onNavigate to work for multiple elements and with correct "this" scope + 11.7.25 - changed registerShadow() to register(), changed onClick() to be like onHover() + 11.6.25 - adding default value for "button()" "children" parameter + 10.29.25 - adding "gap()" and "label()" functions +*/ + +/* $ NAVIGATION */ +let oldPushState = history.pushState; +history.pushState = function pushState() { + let ret = oldPushState.apply(this, arguments); + window.dispatchEvent(new Event('pushstate')); + window.dispatchEvent(new Event('navigate')); + return ret; +}; + +window.addEventListener('popstate', () => { + window.dispatchEvent(new Event('navigate')); +}); + +window.setQuery = function(key, value) { + const url = new URL(window.location.href); + const params = url.searchParams; + + if (value === null || value === undefined) { + params.delete(key); + } else { + params.set(key, value); + } + + const newUrl = url.toString(); + history.replaceState(null, "", newUrl); + window.dispatchEvent(new Event('query-changed')); + + return newUrl; +}; + +window.navigateTo = function(url) { + window.dispatchEvent(new Event('navigate')); + window.history.pushState({}, '', url); +} + +/* $ SELECTOR */ + +HTMLElement.prototype.$ = function(selector) { + return window.$(selector, this) +} +DocumentFragment.prototype.$ = function(selector) { + return window.$(selector, this) +} +window.$ = function(selector, el = document) { + return el.querySelector(selector) +} + +window.$$ = function(selector, el = document) { + return Array.from(el.querySelectorAll(selector)) +} + +/* CONSOLE */ + +console.red = function(message) { + this.log(`%c${message}`, "color: rgb(254, 79, 42);"); +}; + +console.green = function(message) { + this.log(`%c${message}`, "color: rgb(79, 254, 42);"); + +} + +/* GET CSS VARIABLES FOR DARK OR LIGHT MODE */ +window.darkMode = window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches; +document.documentElement.classList.add(darkMode ? 'dark' : 'light'); + +window.getColor = function(name) { + const rootStyles = getComputedStyle(document.documentElement); + const color = rootStyles.getPropertyValue(`--${name}`).trim(); + if(!color) { + throw new Error("Color not found") + } + return color +} + +/* MOBILE */ + +window.isMobile = function isMobile() { + return /Android|iPhone|iPad|iPod|Opera Mini|IEMobile|WPDesktop/i.test(navigator.userAgent); +} + +window.css = function css(cssString) { + let container = document.querySelector("style#pageStyle"); + if(!container) { + container = document.createElement('style'); + container.id = "pageStyle"; + document.head.appendChild(container); + } + + let primarySelector = cssString.substring(0, cssString.indexOf("{")).trim(); + primarySelector = primarySelector.replace(/\*/g, "all"); + primarySelector = primarySelector.replace(/#/g, "id-"); + primarySelector = primarySelector.replace(/,/g, ""); + let stylesheet = container.querySelector(`:scope > style[id='${primarySelector}']`) + if(!stylesheet) { + stylesheet = document.createElement('style'); + stylesheet.id = primarySelector; + stylesheet.appendChild(document.createTextNode(cssString)); + container.appendChild(stylesheet); + } else { + stylesheet.innerText = cssString + } +} + +window.html = function html(elementString) { + let parser = new DOMParser(); + let doc = parser.parseFromString(elementString, 'text/html'); + return doc.body.firstChild; +} + +window.util = {} +window.util.observeClassChange = (el, callback) => { + if (!el || !(el instanceof Element)) { + throw new Error("observeClassChange requires a valid DOM element."); + } + + const observer = new MutationObserver((mutations) => { + for (const mutation of mutations) { + if (mutation.type === "attributes" && mutation.attributeName === "class") { + callback(el.classList); + } + } + }); + + observer.observe(el, { + attributes: true, + attributeFilter: ["class"] + }); + + return observer; // Optional: return it so you can disconnect later +} + +/* PAGE SETUP */ + +Object.defineProperty(Array.prototype, 'last', { + get() { + return this[this.length - 1]; + }, + enumerable: false, +}); + +/* QUILL */ + +window.quill = { + rendering: [], + + render: (el) => { + if(el instanceof Shadow) { + let parent = quill.rendering[quill.rendering.length-1] + if(!parent) { + parent = document.body + } + parent.appendChild(el) + } else { + if(!el.render) {el.render = () => {}} + let parent = quill.rendering[quill.rendering.length-1] + if(!parent) throw new Error("Quill: no parent for element") + parent.appendChild(el) + } + + quill.rendering.push(el) + el.render() + quill.rendering.pop(el) + }, + + rerender: (el) => { + Array.from(el.attributes).forEach(attr => el.removeAttribute(attr.name)); + el.innerHTML = "" + el.removeAllListeners() + + quill.rendering.push(el) + el.render() + 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") + }, +} + +window.Shadow = class extends HTMLElement { + constructor() { + super() + } +} +window.register = (el, tagname) => { + if (typeof el.prototype.render !== 'function') { + throw new Error("Element must have a render: " + el.prototype.constructor.name) + } + if(!tagname) { + tagname = el.prototype.constructor.name.toLowerCase() + "-" + } + customElements.define(tagname, el) + if(el.css) { + css(el.css) + } + + window[el.prototype.constructor.name] = function (...params) { + let instance = new el(...params) + quill.render(instance) + return instance + } +} + +HTMLElement.prototype.rerender = function() { + quill.rerender(this) +} + +/* Styling */ + +window.pct = "%" +window.vmin = "vmin" +window.vmax = "vmax" +window.vh = "vh" +window.vw = "vw" +window.px = "px" +window.em = "em" +window.rem = "rem" +window.inches = "in" + +HTMLElement.prototype.addStyle = function(func) { + return func(this) +} + +window.css = function css(cssString) { + let container = document.querySelector("style#pageStyle"); + if(!container) { + container = document.createElement('style'); + container.id = "pageStyle"; + document.head.appendChild(container); + } + + let primarySelector = cssString.substring(0, cssString.indexOf("{")).trim(); + primarySelector = primarySelector.replace(/\*/g, "all"); + primarySelector = primarySelector.replace(/#/g, "id-"); + primarySelector = primarySelector.replace(/,/g, ""); + let stylesheet = container.querySelector(`:scope > style[id='${primarySelector}']`) + if(!stylesheet) { + stylesheet = document.createElement('style'); + stylesheet.id = primarySelector; + stylesheet.appendChild(document.createTextNode(cssString)); + container.appendChild(stylesheet); + } else { + stylesheet.innerText = cssString + } +} + +function extendHTMLElementWithStyleSetters() { + + function cssValueType(prop) { + const div = document.createElement("div"); + const style = div.style; + if (!(prop in style)) return "invalid"; + + switch(prop) { + + case "gap": + case "borderRadius": + case "width": + case "height": + case "maxWidth": + case "maxHeight": + case "minWidth": + case "minHeight": + + case "left": + case "top": + case "bottom": + case "right": + + case "padding": + case "paddingLeft": + case "paddingTop": + case "paddingBottom": + case "paddingRight": + + case "margin": + case "marginLeft": + case "marginTop": + case "marginBottom": + case "marginRight": + + case "textUnderlineOffset": + + return "unit-number" + + default: + + return "string" + } + + } + + let allStyleProps = ["accentColor", "additiveSymbols", "alignContent", "alignItems", "alignSelf", "alignmentBaseline", "all", "anchorName", "anchorScope", "animation", "animationComposition", "animationDelay", "animationDirection", "animationDuration", "animationFillMode", "animationIterationCount", "animationName", "animationPlayState", "animationRange", "animationRangeEnd", "animationRangeStart", "animationTimeline", "animationTimingFunction", "appRegion", "appearance", "ascentOverride", "aspectRatio", "backdropFilter", "backfaceVisibility", "background", "backgroundAttachment", "backgroundBlendMode", "backgroundClip", "backgroundColor", "backgroundImage", "backgroundOrigin", "backgroundPosition", "backgroundPositionX", "backgroundPositionY", "backgroundRepeat", "backgroundSize", "basePalette", "baselineShift", "baselineSource", "blockSize", "border", "borderBlock", "borderBlockColor", "borderBlockEnd", "borderBlockEndColor", "borderBlockEndStyle", "borderBlockEndWidth", "borderBlockStart", "borderBlockStartColor", "borderBlockStartStyle", "borderBlockStartWidth", "borderBlockStyle", "borderBlockWidth", "borderBottom", "borderBottomColor", "borderBottomLeftRadius", "borderBottomRightRadius", "borderBottomStyle", "borderBottomWidth", "borderCollapse", "borderColor", "borderEndEndRadius", "borderEndStartRadius", "borderImage", "borderImageOutset", "borderImageRepeat", "borderImageSlice", "borderImageSource", "borderImageWidth", "borderInline", "borderInlineColor", "borderInlineEnd", "borderInlineEndColor", "borderInlineEndStyle", "borderInlineEndWidth", "borderInlineStart", "borderInlineStartColor", "borderInlineStartStyle", "borderInlineStartWidth", "borderInlineStyle", "borderInlineWidth", "borderLeft", "borderLeftColor", "borderLeftStyle", "borderLeftWidth", "borderRadius", "borderRight", "borderRightColor", "borderRightStyle", "borderRightWidth", "borderSpacing", "borderStartEndRadius", "borderStartStartRadius", "borderStyle", "borderTop", "borderTopColor", "borderTopLeftRadius", "borderTopRightRadius", "borderTopStyle", "borderTopWidth", "borderWidth", "bottom", "boxDecorationBreak", "boxShadow", "boxSizing", "breakAfter", "breakBefore", "breakInside", "bufferedRendering", "captionSide", "caretAnimation", "caretColor", "clear", "clip", "clipPath", "clipRule", "color", "colorInterpolation", "colorInterpolationFilters", "colorRendering", "colorScheme", "columnCount", "columnFill", "columnGap", "columnRule", "columnRuleColor", "columnRuleStyle", "columnRuleWidth", "columnSpan", "columnWidth", "columns", "contain", "containIntrinsicBlockSize", "containIntrinsicHeight", "containIntrinsicInlineSize", "containIntrinsicSize", "containIntrinsicWidth", "container", "containerName", "containerType", "content", "contentVisibility", "cornerBlockEndShape", "cornerBlockStartShape", "cornerBottomLeftShape", "cornerBottomRightShape", "cornerBottomShape", "cornerEndEndShape", "cornerEndStartShape", "cornerInlineEndShape", "cornerInlineStartShape", "cornerLeftShape", "cornerRightShape", "cornerShape", "cornerStartEndShape", "cornerStartStartShape", "cornerTopLeftShape", "cornerTopRightShape", "cornerTopShape", "counterIncrement", "counterReset", "counterSet", "cursor", "cx", "cy", "d", "descentOverride", "direction", "display", "dominantBaseline", "dynamicRangeLimit", "emptyCells", "fallback", "fieldSizing", "fill", "fillOpacity", "fillRule", "filter", "flex", "flexBasis", "flexDirection", "flexFlow", "flexGrow", "flexShrink", "flexWrap", "float", "floodColor", "floodOpacity", "font", "fontDisplay", "fontFamily", "fontFeatureSettings", "fontKerning", "fontOpticalSizing", "fontPalette", "fontSize", "fontSizeAdjust", "fontStretch", "fontStyle", "fontSynthesis", "fontSynthesisSmallCaps", "fontSynthesisStyle", "fontSynthesisWeight", "fontVariant", "fontVariantAlternates", "fontVariantCaps", "fontVariantEastAsian", "fontVariantEmoji", "fontVariantLigatures", "fontVariantNumeric", "fontVariantPosition", "fontVariationSettings", "fontWeight", "forcedColorAdjust", "gap", "grid", "gridArea", "gridAutoColumns", "gridAutoFlow", "gridAutoRows", "gridColumn", "gridColumnEnd", "gridColumnGap", "gridColumnStart", "gridGap", "gridRow", "gridRowEnd", "gridRowGap", "gridRowStart", "gridTemplate", "gridTemplateAreas", "gridTemplateColumns", "gridTemplateRows", "height", "hyphenateCharacter", "hyphenateLimitChars", "hyphens", "imageOrientation", "imageRendering", "inherits", "initialLetter", "initialValue", "inlineSize", "inset", "insetBlock", "insetBlockEnd", "insetBlockStart", "insetInline", "insetInlineEnd", "insetInlineStart", "interactivity", "interpolateSize", "isolation", "justifyContent", "justifyItems", "justifySelf", "left", "letterSpacing", "lightingColor", "lineBreak", "lineGapOverride", "lineHeight", "listStyle", "listStyleImage", "listStylePosition", "listStyleType", "margin", "marginBlock", "marginBlockEnd", "marginBlockStart", "marginBottom", "marginInline", "marginInlineEnd", "marginInlineStart", "marginLeft", "marginRight", "marginTop", "marker", "markerEnd", "markerMid", "markerStart", "mask", "maskClip", "maskComposite", "maskImage", "maskMode", "maskOrigin", "maskPosition", "maskRepeat", "maskSize", "maskType", "mathDepth", "mathShift", "mathStyle", "maxBlockSize", "maxHeight", "maxInlineSize", "maxWidth", "minBlockSize", "minHeight", "minInlineSize", "minWidth", "mixBlendMode", "navigation", "negative", "objectFit", "objectPosition", "objectViewBox", "offset", "offsetAnchor", "offsetDistance", "offsetPath", "offsetPosition", "offsetRotate", "opacity", "order", "orphans", "outline", "outlineColor", "outlineOffset", "outlineStyle", "outlineWidth", "overflow", "overflowAnchor", "overflowBlock", "overflowClipMargin", "overflowInline", "overflowWrap", "overflowX", "overflowY", "overlay", "overrideColors", "overscrollBehavior", "overscrollBehaviorBlock", "overscrollBehaviorInline", "overscrollBehaviorX", "overscrollBehaviorY", "pad", "padding", "paddingBlock", "paddingBlockEnd", "paddingBlockStart", "paddingBottom", "paddingInline", "paddingInlineEnd", "paddingInlineStart", "paddingLeft", "paddingRight", "paddingTop", "page", "pageBreakAfter", "pageBreakBefore", "pageBreakInside", "pageOrientation", "paintOrder", "perspective", "perspectiveOrigin", "placeContent", "placeItems", "placeSelf", "pointerEvents", "position", "positionAnchor", "positionArea", "positionTry", "positionTryFallbacks", "positionTryOrder", "positionVisibility", "prefix", "printColorAdjust", "quotes", "r", "range", "readingFlow", "readingOrder", "resize", "result", "right", "rotate", "rowGap", "rubyAlign", "rubyPosition", "rx", "ry", "scale", "scrollBehavior", "scrollInitialTarget", "scrollMargin", "scrollMarginBlock", "scrollMarginBlockEnd", "scrollMarginBlockStart", "scrollMarginBottom", "scrollMarginInline", "scrollMarginInlineEnd", "scrollMarginInlineStart", "scrollMarginLeft", "scrollMarginRight", "scrollMarginTop", "scrollMarkerGroup", "scrollPadding", "scrollPaddingBlock", "scrollPaddingBlockEnd", "scrollPaddingBlockStart", "scrollPaddingBottom", "scrollPaddingInline", "scrollPaddingInlineEnd", "scrollPaddingInlineStart", "scrollPaddingLeft", "scrollPaddingRight", "scrollPaddingTop", "scrollSnapAlign", "scrollSnapStop", "scrollSnapType", "scrollTargetGroup", "scrollTimeline", "scrollTimelineAxis", "scrollTimelineName", "scrollbarColor", "scrollbarGutter", "scrollbarWidth", "shapeImageThreshold", "shapeMargin", "shapeOutside", "shapeRendering", "size", "sizeAdjust", "speak", "speakAs", "src", "stopColor", "stopOpacity", "stroke", "strokeDasharray", "strokeDashoffset", "strokeLinecap", "strokeLinejoin", "strokeMiterlimit", "strokeOpacity", "strokeWidth", "suffix", "symbols", "syntax", "system", "tabSize", "tableLayout", "textAlign", "textAlignLast", "textAnchor", "textAutospace", "textBox", "textBoxEdge", "textBoxTrim", "textCombineUpright", "textDecoration", "textDecorationColor", "textDecorationLine", "textDecorationSkipInk", "textDecorationStyle", "textDecorationThickness", "textEmphasis", "textEmphasisColor", "textEmphasisPosition", "textEmphasisStyle", "textIndent", "textOrientation", "textOverflow", "textRendering", "textShadow", "textSizeAdjust", "textSpacingTrim", "textTransform", "textUnderlineOffset", "textUnderlinePosition", "textWrap", "textWrapMode", "textWrapStyle", "timelineScope", "top", "touchAction", "transform", "transformBox", "transformOrigin", "transformStyle", "transition", "transitionBehavior", "transitionDelay", "transitionDuration", "transitionProperty", "transitionTimingFunction", "translate", "types", "unicodeBidi", "unicodeRange", "userSelect", "vectorEffect", "verticalAlign", "viewTimeline", "viewTimelineAxis", "viewTimelineInset", "viewTimelineName", "viewTransitionClass", "viewTransitionGroup", "viewTransitionName", "visibility", "webkitAlignContent", "webkitAlignItems", "webkitAlignSelf", "webkitAnimation", "webkitAnimationDelay", "webkitAnimationDirection", "webkitAnimationDuration", "webkitAnimationFillMode", "webkitAnimationIterationCount", "webkitAnimationName", "webkitAnimationPlayState", "webkitAnimationTimingFunction", "webkitAppRegion", "webkitAppearance", "webkitBackfaceVisibility", "webkitBackgroundClip", "webkitBackgroundOrigin", "webkitBackgroundSize", "webkitBorderAfter", "webkitBorderAfterColor", "webkitBorderAfterStyle", "webkitBorderAfterWidth", "webkitBorderBefore", "webkitBorderBeforeColor", "webkitBorderBeforeStyle", "webkitBorderBeforeWidth", "webkitBorderBottomLeftRadius", "webkitBorderBottomRightRadius", "webkitBorderEnd", "webkitBorderEndColor", "webkitBorderEndStyle", "webkitBorderEndWidth", "webkitBorderHorizontalSpacing", "webkitBorderImage", "webkitBorderRadius", "webkitBorderStart", "webkitBorderStartColor", "webkitBorderStartStyle", "webkitBorderStartWidth", "webkitBorderTopLeftRadius", "webkitBorderTopRightRadius", "webkitBorderVerticalSpacing", "webkitBoxAlign", "webkitBoxDecorationBreak", "webkitBoxDirection", "webkitBoxFlex", "webkitBoxOrdinalGroup", "webkitBoxOrient", "webkitBoxPack", "webkitBoxReflect", "webkitBoxShadow", "webkitBoxSizing", "webkitClipPath", "webkitColumnBreakAfter", "webkitColumnBreakBefore", "webkitColumnBreakInside", "webkitColumnCount", "webkitColumnGap", "webkitColumnRule", "webkitColumnRuleColor", "webkitColumnRuleStyle", "webkitColumnRuleWidth", "webkitColumnSpan", "webkitColumnWidth", "webkitColumns", "webkitFilter", "webkitFlex", "webkitFlexBasis", "webkitFlexDirection", "webkitFlexFlow", "webkitFlexGrow", "webkitFlexShrink", "webkitFlexWrap", "webkitFontFeatureSettings", "webkitFontSmoothing", "webkitHyphenateCharacter", "webkitJustifyContent", "webkitLineBreak", "webkitLineClamp", "webkitLocale", "webkitLogicalHeight", "webkitLogicalWidth", "webkitMarginAfter", "webkitMarginBefore", "webkitMarginEnd", "webkitMarginStart", "webkitMask", "webkitMaskBoxImage", "webkitMaskBoxImageOutset", "webkitMaskBoxImageRepeat", "webkitMaskBoxImageSlice", "webkitMaskBoxImageSource", "webkitMaskBoxImageWidth", "webkitMaskClip", "webkitMaskComposite", "webkitMaskImage", "webkitMaskOrigin", "webkitMaskPosition", "webkitMaskPositionX", "webkitMaskPositionY", "webkitMaskRepeat", "webkitMaskSize", "webkitMaxLogicalHeight", "webkitMaxLogicalWidth", "webkitMinLogicalHeight", "webkitMinLogicalWidth", "webkitOpacity", "webkitOrder", "webkitPaddingAfter", "webkitPaddingBefore", "webkitPaddingEnd", "webkitPaddingStart", "webkitPerspective", "webkitPerspectiveOrigin", "webkitPerspectiveOriginX", "webkitPerspectiveOriginY", "webkitPrintColorAdjust", "webkitRtlOrdering", "webkitRubyPosition", "webkitShapeImageThreshold", "webkitShapeMargin", "webkitShapeOutside", "webkitTapHighlightColor", "webkitTextCombine", "webkitTextDecorationsInEffect", "webkitTextEmphasis", "webkitTextEmphasisColor", "webkitTextEmphasisPosition", "webkitTextEmphasisStyle", "webkitTextFillColor", "webkitTextOrientation", "webkitTextSecurity", "webkitTextSizeAdjust", "webkitTextStroke", "webkitTextStrokeColor", "webkitTextStrokeWidth", "webkitTransform", "webkitTransformOrigin", "webkitTransformOriginX", "webkitTransformOriginY", "webkitTransformOriginZ", "webkitTransformStyle", "webkitTransition", "webkitTransitionDelay", "webkitTransitionDuration", "webkitTransitionProperty", "webkitTransitionTimingFunction", "webkitUserDrag", "webkitUserModify", "webkitUserSelect", "webkitWritingMode", "whiteSpace", "whiteSpaceCollapse", "widows", "width", "willChange", "wordBreak", "wordSpacing", "wordWrap", "writingMode", "x", "y", "zIndex", "zoom"] + + allStyleProps.forEach(prop => { + if (prop === "translate") return; + + const type = cssValueType(prop); + + 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.`); + } + if(value === "auto") { + this.style[prop] = value + return this + } + this.style[prop] = value + unit; + return this; + }; + break; + + case "string": + HTMLElement.prototype[prop] = function(value) { + this.style[prop] = value; + return this; + }; + break; + } + }); +} + +extendHTMLElementWithStyleSetters(); + +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.`); + 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.`); + 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.`); + 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.`); + 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.`); + + switch(value) { + case "6xl": + value = "3.75"; unit = "rem" + break; + + case "5xl": + value = "3"; unit = "rem" + break; + + case "4xl": + value = "2.25"; unit = "rem" + break; + + case "3xl": + value = "1.875"; unit = "rem" + break; + + case "2xl": + value = "1.5"; unit = "rem" + break; + + case "xl": + value = "1.25"; unit = "rem" + break; + + case "l": + value = "1.125"; unit = "rem" + break; + + case "s": + value = "0.875"; unit = "rem" + break; + + case "xs": + value = "0.75"; unit = "rem" + break; + + default: + break; + } + this.style.fontSize = value + unit + 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") { + if (typeof value !== 'number' || isNaN(value)) + throw new Error(`Invalid value: ${value}. Expected a number.`); + checkPositionType(this) + this.style.left = value + unit + return this +} + +HTMLElement.prototype.y = function(value, unit = "px") { + if (typeof value !== 'number' || isNaN(value)) + throw new Error(`Invalid value: ${value}. Expected a number.`); + checkPositionType(this) + this.style.top = value + unit + return this +} + +HTMLElement.prototype.xRight = function(value, unit = "px") { + if (typeof value !== 'number' || isNaN(value)) + throw new Error(`Invalid value: ${value}. Expected a number.`); + checkPositionType(this) + this.style.right = value + unit + return this +} + +HTMLElement.prototype.yBottom = function(value, unit = "px") { + if (typeof value !== 'number' || isNaN(value)) + throw new Error(`Invalid value: ${value}. Expected a number.`); + checkPositionType(this) + this.style.bottom = value + unit + return this +} + +HTMLElement.prototype.backgroundImage = function (...values) { + const formatted = values + .map(v => { + if(v.includes("/") && !v.includes("gradient")) { + v = "url(" + v + ")" + } + return String(v).trim(); + }) + .join(", "); + + this.style.backgroundImage = formatted; + return this; +}; + +HTMLElement.prototype.center = function () { + this.style.transform = "translate(-50%, -50%)" + return this; +}; + +HTMLElement.prototype.centerX = function () { + this.style.transform = "translateX(-50%)" + return this; +}; + +HTMLElement.prototype.centerY = function () { + this.style.transform = "translateY(-50%)" + return this; +}; + +HTMLElement.prototype.alignVertical = function (value) { + const direction = getComputedStyle(this).flexDirection; + if(!direction) { + throw new Error("alignVertical can be only be used on HStacks or VStacks!") + } + + if (direction === "column" || direction === "column-reverse") { + this.style.justifyContent = value; + } else { + this.style.alignItems = value; + } + return this +} + +HTMLElement.prototype.alignHorizontal = function (value) { + const direction = getComputedStyle(this).flexDirection; + if(!direction) { + throw new Error("alignHorizontal can be only be used on HStacks or VStacks!") + } + + if (direction === "column" || direction === "column-reverse") { + this.style.alignItems = value; + } else { + this.style.justifyContent = value; + } + return this +} + + +/* Elements */ + +quill.setChildren = function(el, innerContent) { + if(typeof innerContent === "string") { + el.innerText = innerContent + } else if(typeof innerContent === "function") { + el.render = innerContent + } else { + throw new Error("Children of unknown type") + } +} + +window.a = function a( href, inner=href ) { + if(!href) throw new Error("quill a: missing href argument. Function: a( href, inner=href )") + let link = document.createElement("a") + link.setAttribute('href', href); + quill.setChildren(link, inner) + quill.render(link) + return link +} + +window.img = function img(src, width="", height="") { + let image = document.createElement("img") + + if(!src || !(typeof src==="string")) { + throw new Error("img: missing first argument: src | String") + } else { + image.src = src + } + if(width && typeof width === "string") { + image.style.width = width + } else if(width) { + image.style.width = width + "px" + } + if(height && typeof height === "string") { + image.style.height = height + } else if(height) { + image.style.height = height + "px" + } + quill.render(image) + return image +} + +HTMLImageElement.prototype.backgroundColor = function(value) { + if (this.src.endsWith('.svg') || this.src.startsWith('data:image/svg+xml')) { + fetch(this.src).then(response => response.text()) + .then(svgText => { + const modifiedSvg = svgText.replace(/\bfill="[^"]*"/g, `fill="${value}"`); + const blob = new Blob([modifiedSvg], { type: 'image/svg+xml' }); + this.src = URL.createObjectURL(blob); + }).catch(error => { + console.error('Error updating SVG fill:', error); + }); + } else { + this.style.backgroundColor = value; + } + + return this; // Always returns the element itself + }; + +window.p = function p(innerHTML) { + let el = document.createElement("p") + if(typeof innerText === "function") { + el.render = innerHTML + } else { + el.innerHTML = innerHTML + } + el.style.margin = "0"; + quill.render(el) + return el +} + +window.h1 = function h1(innerText) { + let el = document.createElement("h1") + el.innerText = innerText + quill.render(el) + return el +} + +window.h2 = function h2(innerText) { + let el = document.createElement("h2") + el.innerText = innerText + quill.render(el) + return el +} + +window.h3 = function h3(innerText) { + let el = document.createElement("h3") + el.innerText = innerText + quill.render(el) + return el +} + +window.div = function (innerText) { + let el = document.createElement("div") + el.innerText = innerText ?? "" + quill.render(el) + return el +} + +window.span = function (innerText) { + let el = document.createElement("span") + el.innerText = innerText + quill.render(el) + return el +} + +window.button = function (children = "") { + let el = document.createElement("button") + quill.setChildren(el, children) + quill.render(el) + return el +} + +window.form = function(cb) { + let el = document.createElement("form") + el.render = cb + quill.render(el) + return el +} + +window.input = function(placeholder, width, height) { + let el = document.createElement("input") + el.placeholder = placeholder + el.style.width = width + el.style.height = height + quill.render(el) + return el +} + +window.label = function(text) { + let el = document.createElement("label") + el.innerText = text + quill.render(el) + return el +} + +window.textarea = function(placeholder) { + let el = document.createElement("textarea") + el.placeholder = placeholder + quill.render(el) + return el +} + + +/* STACKS */ + +window.VStack = function (cb = () => {}) { + let styles = ` + display: flex; + flex-direction: column; + ` + let nowRendering = quill.rendering[quill.rendering.length-1] + if (nowRendering.innerHTML.trim() === "" && !quill.isStack(nowRendering)) { + nowRendering.style.cssText += styles + nowRendering.classList.add("VStack") + cb() + return nowRendering + } + + let div = document.createElement("div") + div.classList.add("VStack") + div.style.cssText += styles + div.render = cb + quill.render(div) + return div +} + +window.HStack = function (cb = () => {}) { + let styles = ` + display: flex; + flex-direction: row; + `; + let nowRendering = quill.rendering[quill.rendering.length - 1]; + 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 = () => {}) { + let nowRendering = quill.rendering[quill.rendering.length - 1]; + 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 */ + +window.svgMethods = function(svg) { + svg.pulse = function (duration = 600) { + this.style.transition = `transform ${duration}ms ease-in-out` + this.style.transform = "scale(1.2)" + setTimeout(() => { + this.style.transform = "scale(1)" + }, duration / 2) + return this + } + + // Rotate (e.g. loading spinner) + svg.rotate = function (degrees = 360, duration = 1000) { + this.style.transition = `transform ${duration}ms linear` + this.style.transform = `rotate(${degrees}deg)` + return this + } + + // Change color + svg.fill = function (color) { + this.setAttribute("fill", color) + return this + } + + svg.height = function (height) { + this.setAttribute("height", height) + return this + } + + svg.width = function (width) { + this.setAttribute("width", width) + return this + } + + svg.stroke = function (width, color) { + this.setAttribute("stroke", color) + this.setAttribute("stroke-width", width) + return this + } + + // Toggle visibility + svg.toggle = function () { + this.style.display = this.style.display === "none" ? "" : "none" + return this + } +} + +window.Rectangle = function (width = "40px", height = "40px") { + const svgNS = "http://www.w3.org/2000/svg"; + const svgEl = document.createElementNS(svgNS, "svg"); + const rectEl = document.createElementNS(svgNS, "rect"); + + // SVG size + svgEl.setAttribute("width", width); + svgEl.setAttribute("height", height); + svgEl.setAttribute("viewBox", "0 0 100 100"); + svgEl.setAttribute("preserveAspectRatio", "xMidYMid meet"); + + // Rectangle: full size, slightly rounded corners + rectEl.setAttribute("x", "15"); // 15% margin from edges + rectEl.setAttribute("y", "15"); + rectEl.setAttribute("width", "70"); // 70% of viewBox + rectEl.setAttribute("height", "70"); + // rectEl.setAttribute("rx", "8"); // rounded corners (optional) + // rectEl.setAttribute("ry", "8"); + + svgEl.appendChild(rectEl); + svgMethods(svgEl); // assuming you have this + quill.render(svgEl); + return svgEl; +} + +window.Triangle = function (width = "40px", height = "40px") { + const svgNS = "http://www.w3.org/2000/svg" + const svgEl = document.createElementNS(svgNS, "svg") + const pathEl = document.createElementNS(svgNS, "path") + + // SVG size + svgEl.setAttribute("width", width) + svgEl.setAttribute("height", height) + svgEl.setAttribute("viewBox", "0 0 100 100") + svgEl.setAttribute("preserveAspectRatio", "xMidYMid meet") + // Right-pointing triangle (Play icon) + pathEl.setAttribute("d", "M 25 15 L 90 50 L 25 85 Z") // ◄ adjust points if needed + + svgEl.appendChild(pathEl) + svgMethods(svgEl) + quill.render(svgEl) + return svgEl +} + + +/* EVENTS */ + +HTMLElement.prototype.onAppear = function(func) { + func.call(this); + return this; +}; + +HTMLElement.prototype.onClick = function(func) { + const onMouseDown = () => func.call(this, false); + const onMouseUp = () => func.call(this, true); + this._storeListener("mousedown", onMouseDown); + this._storeListener("mouseup", onMouseUp); + return this; +}; + +HTMLElement.prototype.onMouseDown = function(func) { + this._storeListener("mousedown", func); + return this; +}; + +HTMLElement.prototype.onMouseUp = function(func) { + this._storeListener("mouseup", func); + return this; +}; + +HTMLElement.prototype.onRightClick = function(func) { + this._storeListener("contextmenu", func); + return this; +}; + +HTMLElement.prototype.onHover = function(cb) { + const onEnter = (e) => cb.call(this, true, e); + const onLeave = (e) => cb.call(this, false, e); + this._storeListener("mouseover", onEnter); + this._storeListener("mouseleave", onLeave); + return this; +}; + +HTMLElement.prototype.onFocus = function(cb) { + if (!this.matches('input, textarea, select, button')) { + throw new Error("Can't put focus event on non-form element!"); + } + const onFocus = () => cb.call(this, true); + const onBlur = () => cb.call(this, false); + this._storeListener("focus", onFocus); + this._storeListener("blur", onBlur); + return this; +}; + +HTMLElement.prototype.onKeyDown = function(cb) { + this._storeListener("keydown", cb); + return this; +}; + +HTMLElement.prototype.onInput = function(cb) { + if(!this.matches('input, textarea, [contenteditable=""], [contenteditable="true"]')) + throw new Error("Can't put input event on non-input element!") + this._storeListener("input", cb); + return this; +}; + +HTMLElement.prototype.onChange = function(cb) { + if(!this.matches('input, textarea, [contenteditable=""], [contenteditable="true"]')) + throw new Error("Can't put input event on non-input element!") + this._storeListener("change", cb); + return this; +}; + + +HTMLElement.prototype.onSubmit = function(cb) { + if(!this.matches('form')) + throw new Error("Can't put form event on non-form element!") + this._storeListener("submit", cb); + return this; +}; + +HTMLElement.prototype.onTouch = function(cb) { + const onStart = () => cb.call(this, true); + const onEnd = () => cb.call(this, false); + const onCancel = () => cb.call(this, null); + this._storeListener("touchstart", onStart); + this._storeListener("touchend", onEnd); + this._storeListener("touchcancel", onCancel); + return this; +}; + +HTMLElement.prototype.onTap = function(cb) { + this._storeListener("touchend", cb); + return this; +}; + +/* 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. +*/ +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")) + } +}) + +/* +Same principle applies +*/ +queryListeners = [] +HTMLElement.prototype.onQueryChanged = function(cb) { + this._storeListener("query-changed", cb); + + let found = false + for(entry of queryListeners) { + if(entry.cb.toString() === cb.toString() && + this.nodeName === entry.el.nodeName) { + found = true + break; + } + } + if(found === false) { + queryListeners.push({el: this, cb: cb}) + } + + return this; +}; +window.addEventListener("query-changed", () => { + for(entry of queryListeners) { + entry.el.dispatchEvent(new CustomEvent("query-changed")) + } +}) + +HTMLElement.prototype.onEvent = function(name, cb) { + window._storeListener(window, name, cb); + return this; +}; + +HTMLElement.prototype._storeListener = function(type, handler, options) { + window._storeListener(this, type, handler, options) +} + +window.__listeners = [] + +function _storeListener(target, type, handler, options) { + if (!target.__listeners) target.__listeners = []; + + const optionsString = JSON.stringify(options); + + const index = target.__listeners.findIndex(listener => + listener.type === type && + listener.handler.toString() === handler.toString() && + JSON.stringify(listener.options) === optionsString + ); + + if (index === -1) { // Listener is new + target.addEventListener(type, handler, options); + target.__listeners.push({ type, handler, options }); + } else { // Listener is a duplicate, can be replaced + const old = target.__listeners[index]; + target.removeEventListener(old.type, old.handler, old.options); + + // Replace with the new one + target.addEventListener(type, handler, options); + target.__listeners[index] = { type, handler, options }; + } +} + +HTMLElement.prototype.removeAllListeners = function() { + if (!this.__listeners) return; + for (const { type, handler, options } of this.__listeners) { + this.removeEventListener(type, handler, options); + } + this.__listeners = []; + return this; +}; + +/* ATTRIBUTES */ + +HTMLElement.prototype.attr = function(attributes) { + if ( + typeof attributes !== "object" || + attributes === null || + Array.isArray(attributes) + ) { + throw new TypeError("attr() expects an object with key-value pairs"); + } + + for (const [key, value] of Object.entries(attributes)) { + this.setAttribute(key, value); + } + return this; +}; diff --git a/Sample/ui/_/code/shared.css b/Sample/ui/_/code/shared.css new file mode 100644 index 0000000..e69de29 diff --git a/Sample/ui/components/Home.js b/Sample/ui/components/Home.js new file mode 100644 index 0000000..848b517 --- /dev/null +++ b/Sample/ui/components/Home.js @@ -0,0 +1,7 @@ +class Home extends Shadow { + render() { + + } +} + +register(Home) \ No newline at end of file diff --git a/Sample/ui/index.html b/Sample/ui/index.html new file mode 100644 index 0000000..4b63e31 --- /dev/null +++ b/Sample/ui/index.html @@ -0,0 +1,13 @@ + + + + Quill Starter + + + + + + + + + \ No newline at end of file diff --git a/Sample/ui/index.js b/Sample/ui/index.js new file mode 100644 index 0000000..b14af88 --- /dev/null +++ b/Sample/ui/index.js @@ -0,0 +1,2 @@ +import "./components/Home.js" +Home() \ No newline at end of file diff --git a/VSCode/README.md b/VSCode/README.md index 787d9bb..d0b2fe4 100644 --- a/VSCode/README.md +++ b/VSCode/README.md @@ -5,7 +5,7 @@ Forked from this repository: ## Boilerplate: - ```*html```: Type in an HTML file and select the suggestion to create HTML boilerplate. -- ```*element```: Type in a JS file and select the suggestion to create JS Custom Element boilerplate. +- ```*shadow```: Type in a JS file and select the suggestion to create JS Custom Element boilerplate. ## Functions: Clone this repository into the top level of the project you are working on, so the HTML can find the "quill.js" functions. diff --git a/VSCode/deploy-howto.md b/VSCode/deploy-howto.md new file mode 100644 index 0000000..2320f8a --- /dev/null +++ b/VSCode/deploy-howto.md @@ -0,0 +1,15 @@ +# To Deploy Extension + +```vsce package``` + +```vsce publish``` + +# To Get PAT + +Login to Azure +Search "Devops" +Login to devops (samuel@sun.museum) +Click "User Settings" in the top right > "Personal Access Tokens" +Create one which has "Allow all Organizations" and "Marketplace" > "Manage" selected +Put it in the .env file here +set it in the terminal like `export VSCE_PAT=""` \ No newline at end of file diff --git a/VSCode/package.json b/VSCode/package.json index 0564d2d..d2f5525 100644 --- a/VSCode/package.json +++ b/VSCode/package.json @@ -2,7 +2,7 @@ "name": "quill", "displayName": "Quill", "description": "HTML/CSS Syntax highlighting, best used with the Quill framework", - "version": "1.0.4", + "version": "1.0.6", "publisher": "capturedsun", "icon": "docs/Quill.png", "engines": { diff --git a/VSCode/quill-1.0.5.vsix b/VSCode/quill-1.0.5.vsix new file mode 100644 index 0000000000000000000000000000000000000000..b2ce258e78514625f5aedb927e31f96193df1f41 GIT binary patch literal 166836 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 z zP497!MB%>XEbn`3@q675^}I8tQM?STjTn=GvRvYdxv~Z-auk<`voJj%EB(rC>dUIm z$uS$3zxZl1X|*=Zz(T~}LV&@8VJIv6v!AGrCmMv_w;GxL)%!(0_W5}umdwGGE9ksS z5yCm*#cDhg9lG5|t)yKuG=O`?G^@mlGdAG$_`Ht&z|yY#--O($YX`Q0Py9IGt!>!< zdapT0SF9vdIbI{QrsCRqm2MzWIy$DycURTgHET&PL_yOcR54sscrs7A+?-A=_}25O z+5O|WC5O>b^@Q@ed~IcRN{IW4+L*FGosmpx{WGucdD7|*Qc+iT1O@Q&r&unNIdgQyd6?l{o{fTna-={kRH~TZyk7Q8cw147oF|EI zYcMuE=NVtRk?)R>et4Xco&^)AJ2q`VOvX(aUfsh!bj9ivd^ZEP+zdrMJW6h;hzN0M zQtWiLqcn6~duVC3HxM#==c@|(fQZMN;hWnL*=s6Xdk>r8${~tG+~3?L``k?s`S$YR zuyHk%mjnkWE8pHwd*=2HS2OCg5b#VPM3$9{0+rX%%#Mx!)zy_92n5=$G)?+Fk65zj zD^gQ4G40om3wE!ru7Y$AyuY-f0w5>`}H#2gFw9$HQ< zzO5QfZ0-^6C@;3OAsX*7l$?~z?(0aj+;v;o+KQG;eaP8o<1F8X8EdbfUF-{f+umtMau?dr-I48HH+lS{~&?SvKyMW$e48aGPM9Kzln zKkB#q)#}+OGxdLk_FzKow6(P-j&I+OK{!5+)MYHGpZzn4qP~I8l_A8I5?_4)ZLM%p zctWLPoX~zXAGB5%b}@L*eIr9VJiN0PnoCA%Mjp~aYb>GAM@JoW^Gm12w8D5yO1%EqTCbSjGs^z&u{#WYU&j={a-$iVYmYE zAsO)A$M?{nOOv>=HlDjZfwX1aXL$r+e`gvYcoY6s+ef1cN;UA75XV zbXmqXLpXuNMsK$Jb})_BdX)&J#zNI6wf~VaZvGV;$VQ`L|HW?a;~c*WlUxhl50k`i zhRNI0Vzh5##7fBqBovF;uQ~Ml=w{)n5w{k;Q;7A+K95rcs@YDms##h!#?V$)dYMP_ ze3fYg=kOx)@6Fh;{R++ zele{8td8oh+SuCe3^R3@PW%)ir=nu>d+{90;^_velvr9?{+ZE@)m{8%^Ri!+&62c7 zs^PWynIO<$N-n9RqYK2y&z}_(1Vu_pN=-v!G@c_cGs~mEXl-r1(BTij=dwR>_Z1TQ zz|?+&#+n`#O5_!0Hk|T)8pz_j4t)ya;ICR<2%W}&jg1XPlnht)!%M{I+BcoKz^9rF zUQ2FYjE+LM2a2egb$!TX9yS)1_=N?{qobpL#jNd>=3Ko2%@OvT(c&8J(4!HCLczKS z7eGaWe-z#r0fqCG0CNAdbqqRAw&cly)XCF@oA{VcROnJ@Hm<)5&)ymPp$(yST=F|y znDWHC0}n0DMC_eVc!!WLWf0hFntx>b;jocm_hvIUjDR&_An9|`E)S*T(DzRnL-3-` z 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

a!Myu&4RKY3=>_wb&1Og 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%0DoDTy@zRpuFXx1Tpgh&p1Gmk~Vp$VHB8ehW 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", + "", "", " ", " Quill", - " ", - " ", - " ", - " ", + " ", + " ", + " ", + " ", + " ", " ", - " ", - "", + " ", " ", "" ], diff --git a/VSCode/snippets-js.json b/VSCode/snippets-js.json index 798cc06..ef107f7 100644 --- a/VSCode/snippets-js.json +++ b/VSCode/snippets-js.json @@ -2,7 +2,7 @@ "html": { "prefix": "html", "body": [ - "html(`$1`);" + "html(`$`);" ], "description": "Create a DOM node" }, @@ -15,35 +15,17 @@ "description": "Use the DOM collection of functions" }, - "*element": { - "prefix": "*element", + "*shadow": { + "prefix": "*shadow", "body": [ - "class Index extends HTMLElement {", - "", - " css = /*css*/ `", - " index-el {", - " ", - " }", - " `", - "", - " html = /*html*/ `", - " `", - "", - " constructor() {", - " super();", - " addStyle(this.css);", - " this.innerHTML = this.html;", - " }", - "", - " connectedCallback() {", + "class Index extends Shadow {", + " render() {", " ", " }", - "", "}", - "", - "customElements.define('index-el', Index);", - "export default Index;" + " ", + "register(Index)" ], - "description": "Custom Element Template" + "description": "Custom Shadow Template" } } \ No newline at end of file diff --git a/about.md b/about.md deleted file mode 100644 index a5b7d1c..0000000 --- a/about.md +++ /dev/null @@ -1,26 +0,0 @@ -Attribute/State Cases: - -Dual Instantiation -- HTML-first instantiation from attributes (when first loaded and parsed) - observedAttributes will pick this up -- JS-first instantiation where attributes are set from constructor (or) from init function (or) - press puts attributes on from state before saving - init function can set attributes and variables - perhaps state is always required to be passed in - -Usage Flexibility -- attributes can have default values - $url = "hey" -- attributes can be named or unnamed when passed in to constructor functions - -Attribute / State Reflexivity -- when attribute is changed, state value is changed - modify prototype at runtime? Add overrides for setattr and remove? || - use observedAttributes + attributeChanged (not good) - Forms parent element? -- when state is changed, attribute value is changed - modify prototype at runtime to add a setter for the state such that when it is set it sets the attribute - -Bindings -- should be able to have a child variable be bound to that of a parent - -Binding is denoted by prior to variable -State is denoted by "$" prior to variable \ No newline at end of file diff --git a/app.js b/app.js deleted file mode 100644 index 2735a2e..0000000 --- a/app.js +++ /dev/null @@ -1,13 +0,0 @@ -/* -Captured Sun -*/ - -"use strict"; - -class Home extends Page { - render = () => { - ("hello world") - } -} - -export default Home \ No newline at end of file diff --git a/deploy-howto.md b/deploy-howto.md deleted file mode 100644 index a817a79..0000000 --- a/deploy-howto.md +++ /dev/null @@ -1,5 +0,0 @@ -# To Deploy Extension - -```vsce package``` - -```vsce publish``` \ No newline at end of file diff --git a/index.html b/index.html deleted file mode 100644 index be47f22..0000000 --- a/index.html +++ /dev/null @@ -1,20 +0,0 @@ - - - - Quill - - - - - - - - - - diff --git a/index.js b/index.js index 6320184..fcebb29 100644 --- a/index.js +++ b/index.js @@ -1,62 +1,59 @@ -/* NAVIGATION */ +/* + Sam Russell + Captured Sun + 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 + 11.23.25 - Added onSubmit() event for form submission, added marginHorizontal() and marginVertical() + 11.20.25 - Added "pct" style unit, added alignVertical and alignHorizontal for flex boxes + 11.19.25 - Allowing for "auto" values in otherwise numeric styles, adding vmin and vmax units + 11.17.25.3 - Adding styles() and fixing dynamic function from earlier + 11.17.25.2 - Fixing onNavigate() and onAppear() + 11.17.25 - Added dynamic function to have units in style func parameters. + 11.14.25 - Added onTouch, onTap. Changed style setters to work with Safari. Added center() funcs. + 11.13.25 - changed onFocus() to be a boolean event, added onInput() + 11.9.25 - changed p(innerText) to p(innerHTML), adjusted onNavigate to work for multiple elements and with correct "this" scope + 11.7.25 - changed registerShadow() to register(), changed onClick() to be like onHover() + 11.6.25 - adding default value for "button()" "children" parameter + 10.29.25 - adding "gap()" and "label()" functions +*/ +/* $ NAVIGATION */ let oldPushState = history.pushState; history.pushState = function pushState() { let ret = oldPushState.apply(this, arguments); window.dispatchEvent(new Event('pushstate')); - window.dispatchEvent(new Event('locationchange')); + window.dispatchEvent(new Event('navigate')); return ret; }; window.addEventListener('popstate', () => { - window.dispatchEvent(new Event('locationchange')); + window.dispatchEvent(new Event('navigate')); }); - -window.addEventListener('locationchange', locationChange); -let urlBeforeChange = window.location.href; + +window.setQuery = function(key, value) { + const url = new URL(window.location.href); + const params = url.searchParams; + + if (value === null || value === undefined) { + params.delete(key); + } else { + params.set(key, value); + } + + const newUrl = url.toString(); + history.replaceState(null, "", newUrl); + window.dispatchEvent(new Event('query-changed')); + + return newUrl; +}; window.navigateTo = function(url) { + window.dispatchEvent(new Event('navigate')); window.history.pushState({}, '', url); } -Object.defineProperty(window, 'routes', { - configurable: true, - enumerable: true, - set: function(newValue) { - Object.defineProperty(window, 'routes', { - value: newValue, - writable: false, - configurable: false, - enumerable: true - }); - - locationChange(); - }, - get: function() { - return window.routes; - } -}); - -function locationChange() { - let URL = window.location.pathname.split("/").filter(d => (d !== 'Web') && (!d.includes('.html'))).join("/") - if(URL === "") URL = "/" - - console.log("Location change: ", URL) - - if(!window.routes[URL]) { - console.error("Quill: no URL for this route: ", URL) - return - } - - let page = new window.routes[URL]() - window.rendering.push(page) - page.render() - window.rendering.pop(page) - - urlBeforeChange = window.location.href; -} - -/* $() */ +/* $ SELECTOR */ HTMLElement.prototype.$ = function(selector) { return window.$(selector, this) @@ -65,11 +62,11 @@ DocumentFragment.prototype.$ = function(selector) { return window.$(selector, this) } window.$ = function(selector, el = document) { - if(selector[0] === "#" || selector.includes("[name")) { - return el.querySelector(selector) - } else { - return el.querySelectorAll(selector); - } + return el.querySelector(selector) +} + +window.$$ = function(selector, el = document) { + return Array.from(el.querySelectorAll(selector)) } /* CONSOLE */ @@ -83,556 +80,484 @@ console.green = function(message) { } -/* HTML */ +/* GET CSS VARIABLES FOR DARK OR LIGHT MODE */ +window.darkMode = window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches; +document.documentElement.classList.add(darkMode ? 'dark' : 'light'); -window.Group = function Group(func) { - let container = document.createElement('div'); - container.render = func - Registry.render(container) - return container +window.getColor = function(name) { + const rootStyles = getComputedStyle(document.documentElement); + const color = rootStyles.getPropertyValue(`--${name}`).trim(); + if(!color) { + throw new Error("Color not found") + } + return color } -window.html = function html(htmlString) { - let container = document.createElement('div'); - container.innerHTML = htmlString; +/* MOBILE */ - if (container.children.length === 1) { - Registry.render(container.children[0]) - return container.children[0]; - } - - let fragment = document.createDocumentFragment(); - while (container.firstChild) { - fragment.appendChild(container.firstChild); - } - - Registry.render(fragment) - return fragment; -}; - -/* COMPATIBILITY */ - -function detectMobile() { - const mobileDeviceRegex = /Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i; - return mobileDeviceRegex.test(navigator.userAgent); +window.isMobile = function isMobile() { + return /Android|iPhone|iPad|iPod|Opera Mini|IEMobile|WPDesktop/i.test(navigator.userAgent); } + +window.css = function css(cssString) { + let container = document.querySelector("style#pageStyle"); + if(!container) { + container = document.createElement('style'); + container.id = "pageStyle"; + document.head.appendChild(container); + } -function getSafariVersion() { - const userAgent = navigator.userAgent; - const isSafari = userAgent.includes("Safari") && !userAgent.includes("Chrome"); - if (isSafari) { - const safariVersionMatch = userAgent.match(/Version\/(\d+\.\d+)/); - const safariVersion = safariVersionMatch ? parseFloat(safariVersionMatch[1]) : null; - return safariVersion; + let primarySelector = cssString.substring(0, cssString.indexOf("{")).trim(); + primarySelector = primarySelector.replace(/\*/g, "all"); + primarySelector = primarySelector.replace(/#/g, "id-"); + primarySelector = primarySelector.replace(/,/g, ""); + let stylesheet = container.querySelector(`:scope > style[id='${primarySelector}']`) + if(!stylesheet) { + stylesheet = document.createElement('style'); + stylesheet.id = primarySelector; + stylesheet.appendChild(document.createTextNode(cssString)); + container.appendChild(stylesheet); + } else { + stylesheet.innerText = cssString } } -/* REGISTER */ - -class ObservedObject { - - constructor() { - this._observers = {} - } - - static create(obj = {}) { - let instance = new this() - - Object.keys(instance).forEach((key) => { - if(key[0] === "$") { - key = key.slice(1) - instance._observers[key] = new Map() - const backingFieldName = `_${key}`; - instance[backingFieldName] = instance["$" + key] - Object.defineProperty(instance, key, { - set: function(newValue) { - if(Array.isArray(newValue) && newValue.parent === undefined) { - instance[backingFieldName] = new ObservedObject.ObservedArray(newValue, this, key) - } else { - instance[backingFieldName] = newValue; - } - for (let [observer, properties] of instance._observers[key]) { - for (let property of properties) { - if(property === "children") { - Registry.rerender(observer) - } else { - if(Array.isArray(property)) { - observer[property[0]][property[1]] = newValue; - } else { - observer[property] = newValue; - } - } - } - } - }, - get: function() { - if(Registry.lastState) { - Registry.lastState = [...Registry.lastState, key, instance[backingFieldName]] - } - return instance[backingFieldName]; - }, - enumerable: true, - configurable: true - }); - - delete instance["$" + key] - } - - if(obj[key]) { - instance[key] = obj[key] - } else { - if(instance[key] === undefined || instance[key] === null) { - throw new Error(`ObservedObject: Non-default value "${key}" must be initialized!`) - } - } - }) - - return instance - } - - static ObservedArray = class ObservedArray extends Array { - parent; - name; - - constructor(arr = [], parent, name) { - super(); - this.parent = parent - this.name = name - this.push(...arr); - } - - triggerParent() { - this.parent[this.name] = this - } - - push(...args) { - const result = super.push(...args); - this.triggerParent() - return result; - } - - pop() { - const result = super.pop(); - this.triggerParent() - return result; - } - - shift() { - const result = super.shift(); - this.triggerParent() - return result; - } - - unshift(...args) { - const result = super.unshift(...args); - this.triggerParent() - return result; - } - - splice(start, deleteCount, ...items) { - const removedItems = super.splice(start, deleteCount, ...items); - if (items.length > 0) { - console.log(`Inserted ${items.length} items:`, items); - } - if (removedItems.length > 0) { - console.log(`Removed ${removedItems.length} items:`, removedItems); - } - this.triggerParent() - return removedItems; - } - } +window.html = function html(elementString) { + let parser = new DOMParser(); + let doc = parser.parseFromString(elementString, 'text/html'); + return doc.body.firstChild; } -window.Page = class Page { - constructor() { - return new Proxy(this, { - get(target, prop) { - if (prop in target) { - return target[prop]; - } - - if (prop in document.body) { - if (typeof document.body[prop] === 'function') { - return document.body[prop].bind(document.body); - } - return document.body[prop]; - } - - return undefined; - } - }); +window.util = {} +window.util.observeClassChange = (el, callback) => { + if (!el || !(el instanceof Element)) { + throw new Error("observeClassChange requires a valid DOM element."); } -}; -window.Shadow = class Shadow extends HTMLElement { + const observer = new MutationObserver((mutations) => { + for (const mutation of mutations) { + if (mutation.type === "attributes" && mutation.attributeName === "class") { + callback(el.classList); + } + } + }); + + observer.observe(el, { + attributes: true, + attributeFilter: ["class"] + }); + + return observer; // Optional: return it so you can disconnect later +} + +/* PAGE SETUP */ + +Object.defineProperty(Array.prototype, 'last', { + get() { + return this[this.length - 1]; + }, + enumerable: false, +}); + +/* QUILL */ + +window.quill = { + rendering: [], + + render: (el) => { + if(el instanceof Shadow) { + let parent = quill.rendering[quill.rendering.length-1] + if(!parent) { + parent = document.body + } + parent.appendChild(el) + } else { + if(!el.render) {el.render = () => {}} + let parent = quill.rendering[quill.rendering.length-1] + if(!parent) throw new Error("Quill: no parent for element") + parent.appendChild(el) + } + + quill.rendering.push(el) + el.render() + quill.rendering.pop(el) + }, + + rerender: (el) => { + Array.from(el.attributes).forEach(attr => el.removeAttribute(attr.name)); + el.innerHTML = "" + el.removeAllListeners() + + quill.rendering.push(el) + el.render() + 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") + }, +} + +window.Shadow = class extends HTMLElement { constructor() { super() } } - -window.Registry = class Registry { - - static style = document.querySelector("style#shadows"); - - /* - State Reactivity [stateName].get(elem).push(attribute) - _observers = { - name: Map( -

: [innerText, background] - ), - } - - OO Reactivity: [objectName][objectField].get(elem).push(attribute) - $$form: extends ObservedObject { - _observers = { - canvasPosition: Map( -

: [position] - ), - path: Map( -

: [innerText] - ) - } - } - */ - - static initReactivity(elem, attr, value) { - if(!Registry.lastState || Registry.lastState.length === 0) { - return - } - let parent = window.rendering.last() - - if(Registry.lastState.length === 3) { - let [objName, objField, fieldValue] = Registry.lastState - if(!objName) return; - - let valueCheck = parent[objName][objField] - if(valueCheck !== undefined && valueCheck === value) { - if(!parent[objName]._observers[objField].get(elem)) { - parent[objName]._observers[objField].set(elem, []) - } - let properties = parent[objName]._observers[objField].get(elem) - if(!properties.includes(attr)) { - properties.push(attr) - } - } - } else { - let [stateUsed, stateValue] = Registry.lastState - if(!stateUsed) return; - - if(parent[stateUsed] === value) { - if(!parent._observers[stateUsed].get(elem)) { - parent._observers[stateUsed].set(elem, []) - } - parent._observers[stateUsed].get(elem).push(attr) - } else { - // TODO: Enable this code to get the dynamic value to be called when state changes - // console.log('not equal to the value') - // const dynamicFunction = new Function(expressionString); - // parent.getValue = dynamicFunction; - // const boundFunction = parent.getValue.bind(parent); - // let value = parent.getValue() - } - } - Registry.lastState = [] +window.register = (el, tagname) => { + if (typeof el.prototype.render !== 'function') { + throw new Error("Element must have a render: " + el.prototype.constructor.name) + } + if(!tagname) { + tagname = el.prototype.constructor.name.toLowerCase() + "-" + } + customElements.define(tagname, el) + if(el.css) { + css(el.css) } - static render = (el, parent) => { - let renderParent = window.rendering[window.rendering.length-1] - if(renderParent) { - renderParent.appendChild(el) - if(el._onAppear) { - el._onAppear() - } - } - window.rendering.push(el) - el.render() - window.rendering.pop(el) + window[el.prototype.constructor.name] = function (...params) { + let instance = new el(...params) + quill.render(instance) + return instance } - - static rerender = (el) => { - if(el.parentElement) { - window.rendering.push(el.parentElement) - } - window.rendering.push(el) - el.innerHTML = "" - el.render() - window.rendering.pop() - window.rendering.pop() - } - - static testInitialized(el) { - let fields = Object.keys(el).filter(key => - typeof el[key] !== 'function' && key !== "_observers" - ) - - for(let field of fields) { - if(el[field] === undefined) { - throw new Error(`Quill: field "${field}" must be initialized`) - } - } - } - - static construct = (elem) => { // After default params are set, but before body of constructor - const params = window.Registry.currentParams - const allNames = Object.keys(elem).filter(key => typeof elem[key] !== 'function') - const stateNames = allNames.filter(field => /^[$][^$]/.test(field)).map(str => str.substring(1)); - const observedObjectNames = allNames.filter(field => /^[$][$][^$]/.test(field)).map(str => str.substring(2)); - - function catalogReactivity(elem, stateNames, observedObjectNames) { - const renderString = elem.render.toString().replace(/\s/g, ""); - - const regex = /this\.([a-zA-Z0-9_$]+)/g; - let match; - let matches = []; - - while ((match = regex.exec(renderString)) !== null) { - matches.push({index: match.index, identifier: match[1]}); - } - - let foundReactives = [] - - matches.forEach(match => { - let {index: statePos, identifier} = match; - - if (stateNames.includes(identifier) || observedObjectNames.includes(identifier)) { - let charBefore = renderString[statePos - 1]; - - if (charBefore === "(") { - function getIdentifier() { - let startIndex = statePos - 2; - let identifier = ''; - - while (startIndex >= 0 && /^[a-zA-Z0-9_$]$/.test(renderString[startIndex])) { - identifier = renderString[startIndex] + identifier; - startIndex--; - } - return identifier - } - - function getExpression(renderString, startPos) { - let endIndex = startPos; - while (endIndex < renderString.length && ![')', ','].includes(renderString[endIndex])) { - endIndex++; - } - - return renderString.substring(startPos, endIndex).trim(); - } - - function containsOperators(expression) { - const operatorRegex = /[+\-*/%=&|<>!^]/; - return operatorRegex.test(expression); - } - - let identifier = getIdentifier() - let expression = getExpression(renderString, statePos) - let operators = containsOperators(expression) - - foundReactives.push([identifier, expression, operators]) - } else { - // console.log("Variable or other usage at position:", statePos); - } - - if (observedObjectNames.includes(identifier)) { - } else if (stateNames.includes(identifier)) { - } - } - }); - - elem.reactives = foundReactives - } - - catalogReactivity(elem, stateNames, observedObjectNames) - - function makeState(elem, stateNames, params) { - elem._observers = {} - - // State -> Attributes: set each state value as getter and setter - stateNames.forEach(name => { - const backingFieldName = `_${name}`; - elem._observers[name] = new Map() - - Object.defineProperty(elem, name, { - set: function(newValue) { - elem[backingFieldName] = newValue; - elem.setAttribute(name, typeof newValue === "object" ? "{..}" : newValue); - for (let [element, properties] of elem._observers[name]) { - for (let property of properties) { - if(Array.isArray(property)) { - element[property[0]][property[1]] = newValue; - } else { - element[property] = newValue; - } - } - } - }, - get: function() { - let rendering = window.rendering[window.rendering.length - 1] - let value = elem[backingFieldName] - if(!rendering) return value - - Registry.lastState = [name, value] - return value; - }, - enumerable: true, - configurable: true - }); - - if(elem["$" + name] !== undefined) { - elem[name] = elem["$" + name] - } - - delete elem["$" + name] - }); - } - - function makeObservedObjects(elem, objectNames, params) { - objectNames.forEach(name => { - const backingFieldName = `_${name}`; - - Object.defineProperty(elem, name, { - set: function(newValue) { - elem[backingFieldName] = newValue; - }, - get: function() { - Registry.lastState = [name] - return elem[backingFieldName]; - }, - enumerable: true, - configurable: true - }); - - if(elem["$$" + name] !== undefined) { - elem[name] = elem["$$" + name] - } - - delete elem["$$" + name] - }); - } - - makeState(elem, stateNames, params) - makeObservedObjects(elem, observedObjectNames, params) - - for(let name of allNames) { - if(name.replace(/^\$+/, '') in elem.style) { - throw new Error(`Quill: Property name "${name.replace(/^\$+/, '')}" is not valid`) - } - } - - let i = -1 - for (let param of params) { - i++ - - if(i >= allNames.length) { - throw new Error(`${elem.constructor.name}: ${params.length} arguments passed in where ${allNames.length} expected!`) - } - - let bareName = allNames[i].replace(/^(\$\$|\$)/, ''); - - if(elem[bareName] === undefined) { - if(allNames[i].startsWith("$$") && !(param instanceof ObservedObject)) { - throw new Error(`Field ${allNames[i]} must be an Observed Object!`) - } - elem[bareName] = param - } - } - } - - static register = (el, tagname) => { - let stateVariables = this.parseClassFields(el).filter(field => /^[$][^$]/.test(field)).map(str => str.substring(1)); - el = this.parseConstructor(el) - - // Observe attributes - Object.defineProperty(el, 'observedAttributes', { - get: function() { - return stateVariables; - } - }); - - // Attributes -> State - Object.defineProperty(el.prototype, 'attributeChangedCallback', { - value: function(name, oldValue, newValue) { - const fieldName = `${name}`; - let blacklistedValues = ["[object Object]", "{..}", this[fieldName]] - if (stateVariables.includes(fieldName) && !blacklistedValues.includes(newValue)) { - this[fieldName] = newValue; - } - }, - writable: true, - configurable: true - }); - - customElements.define(tagname, el) - this.addStyle(tagname) - - // Actual Constructor - window[el.prototype.constructor.name] = function (...params) { - window.Registry.currentParams = params - let elIncarnate = new el(...params) - Registry.render(elIncarnate) - return elIncarnate - } - } - - static getStyle = function(el) { - let stylesheet = this.styles.querySelector(`:scope > style[id='${el.tagName.toLowerCase()}']`) - return stylesheet?.sheet.cssRules[0]?.cssText - } - - static removeStyle = function(el) { - let stylesheet = document.getElementById(el.tagName.toLowerCase())?.sheet - if(stylesheet.cssRules.length > 0) { - stylesheet.deleteRule(0) - } - } - - static addStyle = function(tag) { - let stylesheet = this.styles.querySelector(`:scope > style[id='${tag}']`) - tag = tag.replace(/\*/g, "all"); - tag = tag.replace(/#/g, "id-"); - tag = tag.replace(/,/g, ""); - if(!stylesheet) { - stylesheet = document.createElement('style'); - stylesheet.id = tag; - this.styles.appendChild(stylesheet); - } - } - - static updateStyle = function(tag, string) { - let sheet = this.styles.querySelector(`:scope > style[id='${tag}']`)?.sheet - if(!sheet) console.error('Quill: could not find stylesheet to update!') - - for (let i = 0; i < sheet.cssRules.length; i++) { - let rule = sheet.cssRules[i]; - - if (rule.selectorText === tag || rule.selectorText === `${tag.toLowerCase()}`) { - sheet.deleteRule(i); - break; - } - } - - sheet.insertRule(`${tag} { ${string} }`, sheet.cssRules.length); - } -} - -if(!Registry.styles) { - Registry.styles = document.createElement('style'); - Registry.styles.id = "shadows"; - document.head.appendChild(Registry.styles); } HTMLElement.prototype.rerender = function() { - Registry.rerender(this) + quill.rerender(this) } -/* DEFAULT WRAPPERS */ +/* Styling */ -let allStyleProps = ["accentColor", "additiveSymbols", "alignContent", "alignItems", "alignSelf", "alignmentBaseline", "all", "animation", "animationComposition", "animationDelay", "animationDirection", "animationDuration", "animationFillMode", "animationIterationCount", "animationName", "animationPlayState", "animationRange", "animationRangeEnd", "animationRangeStart", "animationTimeline", "animationTimingFunction", "appRegion", "appearance", "ascentOverride", "aspectRatio", "backdropFilter", "backfaceVisibility", "background", "backgroundAttachment", "backgroundBlendMode", "backgroundClip", "backgroundColor", "backgroundImage", "backgroundOrigin", "backgroundPosition", "backgroundPositionX", "backgroundPositionY", "backgroundRepeat", "backgroundSize", "basePalette", "baselineShift", "baselineSource", "blockSize", "border", "borderBlock", "borderBlockColor", "borderBlockEnd", "borderBlockEndColor", "borderBlockEndStyle", "borderBlockEndWidth", "borderBlockStart", "borderBlockStartColor", "borderBlockStartStyle", "borderBlockStartWidth", "borderBlockStyle", "borderBlockWidth", "borderBottom", "borderBottomColor", "borderBottomLeftRadius", "borderBottomRightRadius", "borderBottomStyle", "borderBottomWidth", "borderCollapse", "borderColor", "borderEndEndRadius", "borderEndStartRadius", "borderImage", "borderImageOutset", "borderImageRepeat", "borderImageSlice", "borderImageSource", "borderImageWidth", "borderInline", "borderInlineColor", "borderInlineEnd", "borderInlineEndColor", "borderInlineEndStyle", "borderInlineEndWidth", "borderInlineStart", "borderInlineStartColor", "borderInlineStartStyle", "borderInlineStartWidth", "borderInlineStyle", "borderInlineWidth", "borderLeft", "borderLeftColor", "borderLeftStyle", "borderLeftWidth", "borderRadius", "borderRight", "borderRightColor", "borderRightStyle", "borderRightWidth", "borderSpacing", "borderStartEndRadius", "borderStartStartRadius", "borderStyle", "borderTop", "borderTopColor", "borderTopLeftRadius", "borderTopRightRadius", "borderTopStyle", "borderTopWidth", "borderWidth", "bottom", "boxShadow", "boxSizing", "breakAfter", "breakBefore", "breakInside", "bufferedRendering", "captionSide", "caretColor", "clear", "clip", "clipPath", "clipRule", "color", "colorInterpolation", "colorInterpolationFilters", "colorRendering", "colorScheme", "columnCount", "columnFill", "columnGap", "columnRule", "columnRuleColor", "columnRuleStyle", "columnRuleWidth", "columnSpan", "columnWidth", "columns", "contain", "containIntrinsicBlockSize", "containIntrinsicHeight", "containIntrinsicInlineSize", "containIntrinsicSize", "containIntrinsicWidth", "container", "containerName", "containerType", "content", "contentVisibility", "counterIncrement", "counterReset", "counterSet", "cursor", "cx", "cy", "d", "descentOverride", "direction", "display", "dominantBaseline", "emptyCells", "fallback", "fieldSizing", "fill", "fillOpacity", "fillRule", "filter", "flex", "flexBasis", "flexDirection", "flexFlow", "flexGrow", "flexShrink", "flexWrap", "float", "floodColor", "floodOpacity", "font", "fontDisplay", "fontFamily", "fontFeatureSettings", "fontKerning", "fontOpticalSizing", "fontPalette", "fontSize", "fontStretch", "fontStyle", "fontSynthesis", "fontSynthesisSmallCaps", "fontSynthesisStyle", "fontSynthesisWeight", "fontVariant", "fontVariantAlternates", "fontVariantCaps", "fontVariantEastAsian", "fontVariantLigatures", "fontVariantNumeric", "fontVariantPosition", "fontVariationSettings", "fontWeight", "forcedColorAdjust", "gap", "grid", "gridArea", "gridAutoColumns", "gridAutoFlow", "gridAutoRows", "gridColumn", "gridColumnEnd", "gridColumnGap", "gridColumnStart", "gridGap", "gridRow", "gridRowEnd", "gridRowGap", "gridRowStart", "gridTemplate", "gridTemplateAreas", "gridTemplateColumns", "gridTemplateRows", "height", "hyphenateCharacter", "hyphenateLimitChars", "hyphens", "imageOrientation", "imageRendering", "inherits", "initialLetter", "initialValue", "inlineSize", "inset", "insetBlock", "insetBlockEnd", "insetBlockStart", "insetInline", "insetInlineEnd", "insetInlineStart", "isolation", "justifyContent", "justifyItems", "justifySelf", "left", "letterSpacing", "lightingColor", "lineBreak", "lineGapOverride", "lineHeight", "listStyle", "listStyleImage", "listStylePosition", "listStyleType", "margin", "marginBlock", "marginBlockEnd", "marginBlockStart", "marginBottom", "marginInline", "marginInlineEnd", "marginInlineStart", "marginLeft", "marginRight", "marginTop", "marker", "markerEnd", "markerMid", "markerStart", "mask", "maskClip", "maskComposite", "maskImage", "maskMode", "maskOrigin", "maskPosition", "maskRepeat", "maskSize", "maskType", "mathDepth", "mathShift", "mathStyle", "maxBlockSize", "maxHeight", "maxInlineSize", "maxWidth", "minBlockSize", "minHeight", "minInlineSize", "minWidth", "mixBlendMode", "negative", "objectFit", "objectPosition", "objectViewBox", "offset", "offsetAnchor", "offsetDistance", "offsetPath", "offsetPosition", "offsetRotate", "opacity", "order", "orphans", "outline", "outlineColor", "outlineOffset", "outlineStyle", "outlineWidth", "overflow", "overflowAnchor", "overflowClipMargin", "overflowWrap", "overflowX", "overflowY", "overlay", "overrideColors", "overscrollBehavior", "overscrollBehaviorBlock", "overscrollBehaviorInline", "overscrollBehaviorX", "overscrollBehaviorY", "pad", "padding", "paddingBlock", "paddingBlockEnd", "paddingBlockStart", "paddingBottom", "paddingInline", "paddingInlineEnd", "paddingInlineStart", "paddingLeft", "paddingRight", "paddingTop", "page", "pageBreakAfter", "pageBreakBefore", "pageBreakInside", "pageOrientation", "paintOrder", "perspective", "perspectiveOrigin", "placeContent", "placeItems", "placeSelf", "pointerEvents", "position", "prefix", "quotes", "r", "range", "resize", "right", "rotate", "rowGap", "rubyPosition", "rx", "ry", "scale", "scrollBehavior", "scrollMargin", "scrollMarginBlock", "scrollMarginBlockEnd", "scrollMarginBlockStart", "scrollMarginBottom", "scrollMarginInline", "scrollMarginInlineEnd", "scrollMarginInlineStart", "scrollMarginLeft", "scrollMarginRight", "scrollMarginTop", "scrollPadding", "scrollPaddingBlock", "scrollPaddingBlockEnd", "scrollPaddingBlockStart", "scrollPaddingBottom", "scrollPaddingInline", "scrollPaddingInlineEnd", "scrollPaddingInlineStart", "scrollPaddingLeft", "scrollPaddingRight", "scrollPaddingTop", "scrollSnapAlign", "scrollSnapStop", "scrollSnapType", "scrollTimeline", "scrollTimelineAxis", "scrollTimelineName", "scrollbarColor", "scrollbarGutter", "scrollbarWidth", "shapeImageThreshold", "shapeMargin", "shapeOutside", "shapeRendering", "size", "sizeAdjust", "speak", "speakAs", "src", "stopColor", "stopOpacity", "stroke", "strokeDasharray", "strokeDashoffset", "strokeLinecap", "strokeLinejoin", "strokeMiterlimit", "strokeOpacity", "strokeWidth", "suffix", "symbols", "syntax", "system", "tabSize", "tableLayout", "textAlign", "textAlignLast", "textAnchor", "textCombineUpright", "textDecoration", "textDecorationColor", "textDecorationLine", "textDecorationSkipInk", "textDecorationStyle", "textDecorationThickness", "textEmphasis", "textEmphasisColor", "textEmphasisPosition", "textEmphasisStyle", "textIndent", "textOrientation", "textOverflow", "textRendering", "textShadow", "textSizeAdjust", "textSpacingTrim", "textTransform", "textUnderlineOffset", "textUnderlinePosition", "textWrap", "timelineScope", "top", "touchAction", "transform", "transformBox", "transformOrigin", "transformStyle", "transition", "transitionBehavior", "transitionDelay", "transitionDuration", "transitionProperty", "transitionTimingFunction", "translate", "unicodeBidi", "unicodeRange", "userSelect", "vectorEffect", "verticalAlign", "viewTimeline", "viewTimelineAxis", "viewTimelineInset", "viewTimelineName", "viewTransitionName", "visibility", "webkitAlignContent", "webkitAlignItems", "webkitAlignSelf", "webkitAnimation", "webkitAnimationDelay", "webkitAnimationDirection", "webkitAnimationDuration", "webkitAnimationFillMode", "webkitAnimationIterationCount", "webkitAnimationName", "webkitAnimationPlayState", "webkitAnimationTimingFunction", "webkitAppRegion", "webkitAppearance", "webkitBackfaceVisibility", "webkitBackgroundClip", "webkitBackgroundOrigin", "webkitBackgroundSize", "webkitBorderAfter", "webkitBorderAfterColor", "webkitBorderAfterStyle", "webkitBorderAfterWidth", "webkitBorderBefore", "webkitBorderBeforeColor", "webkitBorderBeforeStyle", "webkitBorderBeforeWidth", "webkitBorderBottomLeftRadius", "webkitBorderBottomRightRadius", "webkitBorderEnd", "webkitBorderEndColor", "webkitBorderEndStyle", "webkitBorderEndWidth", "webkitBorderHorizontalSpacing", "webkitBorderImage", "webkitBorderRadius", "webkitBorderStart", "webkitBorderStartColor", "webkitBorderStartStyle", "webkitBorderStartWidth", "webkitBorderTopLeftRadius", "webkitBorderTopRightRadius", "webkitBorderVerticalSpacing", "webkitBoxAlign", "webkitBoxDecorationBreak", "webkitBoxDirection", "webkitBoxFlex", "webkitBoxOrdinalGroup", "webkitBoxOrient", "webkitBoxPack", "webkitBoxReflect", "webkitBoxShadow", "webkitBoxSizing", "webkitClipPath", "webkitColumnBreakAfter", "webkitColumnBreakBefore", "webkitColumnBreakInside", "webkitColumnCount", "webkitColumnGap", "webkitColumnRule", "webkitColumnRuleColor", "webkitColumnRuleStyle", "webkitColumnRuleWidth", "webkitColumnSpan", "webkitColumnWidth", "webkitColumns", "webkitFilter", "webkitFlex", "webkitFlexBasis", "webkitFlexDirection", "webkitFlexFlow", "webkitFlexGrow", "webkitFlexShrink", "webkitFlexWrap", "webkitFontFeatureSettings", "webkitFontSmoothing", "webkitHyphenateCharacter", "webkitJustifyContent", "webkitLineBreak", "webkitLineClamp", "webkitLocale", "webkitLogicalHeight", "webkitLogicalWidth", "webkitMarginAfter", "webkitMarginBefore", "webkitMarginEnd", "webkitMarginStart", "webkitMask", "webkitMaskBoxImage", "webkitMaskBoxImageOutset", "webkitMaskBoxImageRepeat", "webkitMaskBoxImageSlice", "webkitMaskBoxImageSource", "webkitMaskBoxImageWidth", "webkitMaskClip", "webkitMaskComposite", "webkitMaskImage", "webkitMaskOrigin", "webkitMaskPosition", "webkitMaskPositionX", "webkitMaskPositionY", "webkitMaskRepeat", "webkitMaskSize", "webkitMaxLogicalHeight", "webkitMaxLogicalWidth", "webkitMinLogicalHeight", "webkitMinLogicalWidth", "webkitOpacity", "webkitOrder", "webkitPaddingAfter", "webkitPaddingBefore", "webkitPaddingEnd", "webkitPaddingStart", "webkitPerspective", "webkitPerspectiveOrigin", "webkitPerspectiveOriginX", "webkitPerspectiveOriginY", "webkitPrintColorAdjust", "webkitRtlOrdering", "webkitRubyPosition", "webkitShapeImageThreshold", "webkitShapeMargin", "webkitShapeOutside", "webkitTapHighlightColor", "webkitTextCombine", "webkitTextDecorationsInEffect", "webkitTextEmphasis", "webkitTextEmphasisColor", "webkitTextEmphasisPosition", "webkitTextEmphasisStyle", "webkitTextFillColor", "webkitTextOrientation", "webkitTextSecurity", "webkitTextSizeAdjust", "webkitTextStroke", "webkitTextStrokeColor", "webkitTextStrokeWidth", "webkitTransform", "webkitTransformOrigin", "webkitTransformOriginX", "webkitTransformOriginY", "webkitTransformOriginZ", "webkitTransformStyle", "webkitTransition", "webkitTransitionDelay", "webkitTransitionDuration", "webkitTransitionProperty", "webkitTransitionTimingFunction", "webkitUserDrag", "webkitUserModify", "webkitUserSelect", "webkitWritingMode", "whiteSpace", "whiteSpaceCollapse", "widows", "width", "willChange", "wordBreak", "wordSpacing", "wordWrap", "writingMode", "x", "y", "zIndex", "zoom"] +window.pct = "%" +window.vmin = "vmin" +window.vmax = "vmax" +window.vh = "vh" +window.vw = "vw" +window.px = "px" +window.em = "em" +window.rem = "rem" +window.inches = "in" -window.a = function a({ href, name=href } = {}) { +HTMLElement.prototype.addStyle = function(func) { + return func(this) +} + +window.css = function css(cssString) { + let container = document.querySelector("style#pageStyle"); + if(!container) { + container = document.createElement('style'); + container.id = "pageStyle"; + document.head.appendChild(container); + } + + let primarySelector = cssString.substring(0, cssString.indexOf("{")).trim(); + primarySelector = primarySelector.replace(/\*/g, "all"); + primarySelector = primarySelector.replace(/#/g, "id-"); + primarySelector = primarySelector.replace(/,/g, ""); + let stylesheet = container.querySelector(`:scope > style[id='${primarySelector}']`) + if(!stylesheet) { + stylesheet = document.createElement('style'); + stylesheet.id = primarySelector; + stylesheet.appendChild(document.createTextNode(cssString)); + container.appendChild(stylesheet); + } else { + stylesheet.innerText = cssString + } +} + +function extendHTMLElementWithStyleSetters() { + + function cssValueType(prop) { + const div = document.createElement("div"); + const style = div.style; + if (!(prop in style)) return "invalid"; + + switch(prop) { + + case "gap": + case "borderRadius": + case "width": + case "height": + case "maxWidth": + case "maxHeight": + case "minWidth": + case "minHeight": + + case "left": + case "top": + case "bottom": + case "right": + + case "padding": + case "paddingLeft": + case "paddingTop": + case "paddingBottom": + case "paddingRight": + + case "margin": + case "marginLeft": + case "marginTop": + case "marginBottom": + case "marginRight": + + case "textUnderlineOffset": + + return "unit-number" + + default: + + return "string" + } + + } + + let allStyleProps = ["accentColor", "additiveSymbols", "alignContent", "alignItems", "alignSelf", "alignmentBaseline", "all", "anchorName", "anchorScope", "animation", "animationComposition", "animationDelay", "animationDirection", "animationDuration", "animationFillMode", "animationIterationCount", "animationName", "animationPlayState", "animationRange", "animationRangeEnd", "animationRangeStart", "animationTimeline", "animationTimingFunction", "appRegion", "appearance", "ascentOverride", "aspectRatio", "backdropFilter", "backfaceVisibility", "background", "backgroundAttachment", "backgroundBlendMode", "backgroundClip", "backgroundColor", "backgroundImage", "backgroundOrigin", "backgroundPosition", "backgroundPositionX", "backgroundPositionY", "backgroundRepeat", "backgroundSize", "basePalette", "baselineShift", "baselineSource", "blockSize", "border", "borderBlock", "borderBlockColor", "borderBlockEnd", "borderBlockEndColor", "borderBlockEndStyle", "borderBlockEndWidth", "borderBlockStart", "borderBlockStartColor", "borderBlockStartStyle", "borderBlockStartWidth", "borderBlockStyle", "borderBlockWidth", "borderBottom", "borderBottomColor", "borderBottomLeftRadius", "borderBottomRightRadius", "borderBottomStyle", "borderBottomWidth", "borderCollapse", "borderColor", "borderEndEndRadius", "borderEndStartRadius", "borderImage", "borderImageOutset", "borderImageRepeat", "borderImageSlice", "borderImageSource", "borderImageWidth", "borderInline", "borderInlineColor", "borderInlineEnd", "borderInlineEndColor", "borderInlineEndStyle", "borderInlineEndWidth", "borderInlineStart", "borderInlineStartColor", "borderInlineStartStyle", "borderInlineStartWidth", "borderInlineStyle", "borderInlineWidth", "borderLeft", "borderLeftColor", "borderLeftStyle", "borderLeftWidth", "borderRadius", "borderRight", "borderRightColor", "borderRightStyle", "borderRightWidth", "borderSpacing", "borderStartEndRadius", "borderStartStartRadius", "borderStyle", "borderTop", "borderTopColor", "borderTopLeftRadius", "borderTopRightRadius", "borderTopStyle", "borderTopWidth", "borderWidth", "bottom", "boxDecorationBreak", "boxShadow", "boxSizing", "breakAfter", "breakBefore", "breakInside", "bufferedRendering", "captionSide", "caretAnimation", "caretColor", "clear", "clip", "clipPath", "clipRule", "color", "colorInterpolation", "colorInterpolationFilters", "colorRendering", "colorScheme", "columnCount", "columnFill", "columnGap", "columnRule", "columnRuleColor", "columnRuleStyle", "columnRuleWidth", "columnSpan", "columnWidth", "columns", "contain", "containIntrinsicBlockSize", "containIntrinsicHeight", "containIntrinsicInlineSize", "containIntrinsicSize", "containIntrinsicWidth", "container", "containerName", "containerType", "content", "contentVisibility", "cornerBlockEndShape", "cornerBlockStartShape", "cornerBottomLeftShape", "cornerBottomRightShape", "cornerBottomShape", "cornerEndEndShape", "cornerEndStartShape", "cornerInlineEndShape", "cornerInlineStartShape", "cornerLeftShape", "cornerRightShape", "cornerShape", "cornerStartEndShape", "cornerStartStartShape", "cornerTopLeftShape", "cornerTopRightShape", "cornerTopShape", "counterIncrement", "counterReset", "counterSet", "cursor", "cx", "cy", "d", "descentOverride", "direction", "display", "dominantBaseline", "dynamicRangeLimit", "emptyCells", "fallback", "fieldSizing", "fill", "fillOpacity", "fillRule", "filter", "flex", "flexBasis", "flexDirection", "flexFlow", "flexGrow", "flexShrink", "flexWrap", "float", "floodColor", "floodOpacity", "font", "fontDisplay", "fontFamily", "fontFeatureSettings", "fontKerning", "fontOpticalSizing", "fontPalette", "fontSize", "fontSizeAdjust", "fontStretch", "fontStyle", "fontSynthesis", "fontSynthesisSmallCaps", "fontSynthesisStyle", "fontSynthesisWeight", "fontVariant", "fontVariantAlternates", "fontVariantCaps", "fontVariantEastAsian", "fontVariantEmoji", "fontVariantLigatures", "fontVariantNumeric", "fontVariantPosition", "fontVariationSettings", "fontWeight", "forcedColorAdjust", "gap", "grid", "gridArea", "gridAutoColumns", "gridAutoFlow", "gridAutoRows", "gridColumn", "gridColumnEnd", "gridColumnGap", "gridColumnStart", "gridGap", "gridRow", "gridRowEnd", "gridRowGap", "gridRowStart", "gridTemplate", "gridTemplateAreas", "gridTemplateColumns", "gridTemplateRows", "height", "hyphenateCharacter", "hyphenateLimitChars", "hyphens", "imageOrientation", "imageRendering", "inherits", "initialLetter", "initialValue", "inlineSize", "inset", "insetBlock", "insetBlockEnd", "insetBlockStart", "insetInline", "insetInlineEnd", "insetInlineStart", "interactivity", "interpolateSize", "isolation", "justifyContent", "justifyItems", "justifySelf", "left", "letterSpacing", "lightingColor", "lineBreak", "lineGapOverride", "lineHeight", "listStyle", "listStyleImage", "listStylePosition", "listStyleType", "margin", "marginBlock", "marginBlockEnd", "marginBlockStart", "marginBottom", "marginInline", "marginInlineEnd", "marginInlineStart", "marginLeft", "marginRight", "marginTop", "marker", "markerEnd", "markerMid", "markerStart", "mask", "maskClip", "maskComposite", "maskImage", "maskMode", "maskOrigin", "maskPosition", "maskRepeat", "maskSize", "maskType", "mathDepth", "mathShift", "mathStyle", "maxBlockSize", "maxHeight", "maxInlineSize", "maxWidth", "minBlockSize", "minHeight", "minInlineSize", "minWidth", "mixBlendMode", "navigation", "negative", "objectFit", "objectPosition", "objectViewBox", "offset", "offsetAnchor", "offsetDistance", "offsetPath", "offsetPosition", "offsetRotate", "opacity", "order", "orphans", "outline", "outlineColor", "outlineOffset", "outlineStyle", "outlineWidth", "overflow", "overflowAnchor", "overflowBlock", "overflowClipMargin", "overflowInline", "overflowWrap", "overflowX", "overflowY", "overlay", "overrideColors", "overscrollBehavior", "overscrollBehaviorBlock", "overscrollBehaviorInline", "overscrollBehaviorX", "overscrollBehaviorY", "pad", "padding", "paddingBlock", "paddingBlockEnd", "paddingBlockStart", "paddingBottom", "paddingInline", "paddingInlineEnd", "paddingInlineStart", "paddingLeft", "paddingRight", "paddingTop", "page", "pageBreakAfter", "pageBreakBefore", "pageBreakInside", "pageOrientation", "paintOrder", "perspective", "perspectiveOrigin", "placeContent", "placeItems", "placeSelf", "pointerEvents", "position", "positionAnchor", "positionArea", "positionTry", "positionTryFallbacks", "positionTryOrder", "positionVisibility", "prefix", "printColorAdjust", "quotes", "r", "range", "readingFlow", "readingOrder", "resize", "result", "right", "rotate", "rowGap", "rubyAlign", "rubyPosition", "rx", "ry", "scale", "scrollBehavior", "scrollInitialTarget", "scrollMargin", "scrollMarginBlock", "scrollMarginBlockEnd", "scrollMarginBlockStart", "scrollMarginBottom", "scrollMarginInline", "scrollMarginInlineEnd", "scrollMarginInlineStart", "scrollMarginLeft", "scrollMarginRight", "scrollMarginTop", "scrollMarkerGroup", "scrollPadding", "scrollPaddingBlock", "scrollPaddingBlockEnd", "scrollPaddingBlockStart", "scrollPaddingBottom", "scrollPaddingInline", "scrollPaddingInlineEnd", "scrollPaddingInlineStart", "scrollPaddingLeft", "scrollPaddingRight", "scrollPaddingTop", "scrollSnapAlign", "scrollSnapStop", "scrollSnapType", "scrollTargetGroup", "scrollTimeline", "scrollTimelineAxis", "scrollTimelineName", "scrollbarColor", "scrollbarGutter", "scrollbarWidth", "shapeImageThreshold", "shapeMargin", "shapeOutside", "shapeRendering", "size", "sizeAdjust", "speak", "speakAs", "src", "stopColor", "stopOpacity", "stroke", "strokeDasharray", "strokeDashoffset", "strokeLinecap", "strokeLinejoin", "strokeMiterlimit", "strokeOpacity", "strokeWidth", "suffix", "symbols", "syntax", "system", "tabSize", "tableLayout", "textAlign", "textAlignLast", "textAnchor", "textAutospace", "textBox", "textBoxEdge", "textBoxTrim", "textCombineUpright", "textDecoration", "textDecorationColor", "textDecorationLine", "textDecorationSkipInk", "textDecorationStyle", "textDecorationThickness", "textEmphasis", "textEmphasisColor", "textEmphasisPosition", "textEmphasisStyle", "textIndent", "textOrientation", "textOverflow", "textRendering", "textShadow", "textSizeAdjust", "textSpacingTrim", "textTransform", "textUnderlineOffset", "textUnderlinePosition", "textWrap", "textWrapMode", "textWrapStyle", "timelineScope", "top", "touchAction", "transform", "transformBox", "transformOrigin", "transformStyle", "transition", "transitionBehavior", "transitionDelay", "transitionDuration", "transitionProperty", "transitionTimingFunction", "translate", "types", "unicodeBidi", "unicodeRange", "userSelect", "vectorEffect", "verticalAlign", "viewTimeline", "viewTimelineAxis", "viewTimelineInset", "viewTimelineName", "viewTransitionClass", "viewTransitionGroup", "viewTransitionName", "visibility", "webkitAlignContent", "webkitAlignItems", "webkitAlignSelf", "webkitAnimation", "webkitAnimationDelay", "webkitAnimationDirection", "webkitAnimationDuration", "webkitAnimationFillMode", "webkitAnimationIterationCount", "webkitAnimationName", "webkitAnimationPlayState", "webkitAnimationTimingFunction", "webkitAppRegion", "webkitAppearance", "webkitBackfaceVisibility", "webkitBackgroundClip", "webkitBackgroundOrigin", "webkitBackgroundSize", "webkitBorderAfter", "webkitBorderAfterColor", "webkitBorderAfterStyle", "webkitBorderAfterWidth", "webkitBorderBefore", "webkitBorderBeforeColor", "webkitBorderBeforeStyle", "webkitBorderBeforeWidth", "webkitBorderBottomLeftRadius", "webkitBorderBottomRightRadius", "webkitBorderEnd", "webkitBorderEndColor", "webkitBorderEndStyle", "webkitBorderEndWidth", "webkitBorderHorizontalSpacing", "webkitBorderImage", "webkitBorderRadius", "webkitBorderStart", "webkitBorderStartColor", "webkitBorderStartStyle", "webkitBorderStartWidth", "webkitBorderTopLeftRadius", "webkitBorderTopRightRadius", "webkitBorderVerticalSpacing", "webkitBoxAlign", "webkitBoxDecorationBreak", "webkitBoxDirection", "webkitBoxFlex", "webkitBoxOrdinalGroup", "webkitBoxOrient", "webkitBoxPack", "webkitBoxReflect", "webkitBoxShadow", "webkitBoxSizing", "webkitClipPath", "webkitColumnBreakAfter", "webkitColumnBreakBefore", "webkitColumnBreakInside", "webkitColumnCount", "webkitColumnGap", "webkitColumnRule", "webkitColumnRuleColor", "webkitColumnRuleStyle", "webkitColumnRuleWidth", "webkitColumnSpan", "webkitColumnWidth", "webkitColumns", "webkitFilter", "webkitFlex", "webkitFlexBasis", "webkitFlexDirection", "webkitFlexFlow", "webkitFlexGrow", "webkitFlexShrink", "webkitFlexWrap", "webkitFontFeatureSettings", "webkitFontSmoothing", "webkitHyphenateCharacter", "webkitJustifyContent", "webkitLineBreak", "webkitLineClamp", "webkitLocale", "webkitLogicalHeight", "webkitLogicalWidth", "webkitMarginAfter", "webkitMarginBefore", "webkitMarginEnd", "webkitMarginStart", "webkitMask", "webkitMaskBoxImage", "webkitMaskBoxImageOutset", "webkitMaskBoxImageRepeat", "webkitMaskBoxImageSlice", "webkitMaskBoxImageSource", "webkitMaskBoxImageWidth", "webkitMaskClip", "webkitMaskComposite", "webkitMaskImage", "webkitMaskOrigin", "webkitMaskPosition", "webkitMaskPositionX", "webkitMaskPositionY", "webkitMaskRepeat", "webkitMaskSize", "webkitMaxLogicalHeight", "webkitMaxLogicalWidth", "webkitMinLogicalHeight", "webkitMinLogicalWidth", "webkitOpacity", "webkitOrder", "webkitPaddingAfter", "webkitPaddingBefore", "webkitPaddingEnd", "webkitPaddingStart", "webkitPerspective", "webkitPerspectiveOrigin", "webkitPerspectiveOriginX", "webkitPerspectiveOriginY", "webkitPrintColorAdjust", "webkitRtlOrdering", "webkitRubyPosition", "webkitShapeImageThreshold", "webkitShapeMargin", "webkitShapeOutside", "webkitTapHighlightColor", "webkitTextCombine", "webkitTextDecorationsInEffect", "webkitTextEmphasis", "webkitTextEmphasisColor", "webkitTextEmphasisPosition", "webkitTextEmphasisStyle", "webkitTextFillColor", "webkitTextOrientation", "webkitTextSecurity", "webkitTextSizeAdjust", "webkitTextStroke", "webkitTextStrokeColor", "webkitTextStrokeWidth", "webkitTransform", "webkitTransformOrigin", "webkitTransformOriginX", "webkitTransformOriginY", "webkitTransformOriginZ", "webkitTransformStyle", "webkitTransition", "webkitTransitionDelay", "webkitTransitionDuration", "webkitTransitionProperty", "webkitTransitionTimingFunction", "webkitUserDrag", "webkitUserModify", "webkitUserSelect", "webkitWritingMode", "whiteSpace", "whiteSpaceCollapse", "widows", "width", "willChange", "wordBreak", "wordSpacing", "wordWrap", "writingMode", "x", "y", "zIndex", "zoom"] + + allStyleProps.forEach(prop => { + if (prop === "translate") return; + + const type = cssValueType(prop); + + 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.`); + } + if(value === "auto") { + this.style[prop] = value + return this + } + this.style[prop] = value + unit; + return this; + }; + break; + + case "string": + HTMLElement.prototype[prop] = function(value) { + this.style[prop] = value; + return this; + }; + break; + } + }); +} + +extendHTMLElementWithStyleSetters(); + +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.`); + 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.`); + 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.`); + 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.`); + 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.`); + + switch(value) { + case "6xl": + value = "3.75"; unit = "rem" + break; + + case "5xl": + value = "3"; unit = "rem" + break; + + case "4xl": + value = "2.25"; unit = "rem" + break; + + case "3xl": + value = "1.875"; unit = "rem" + break; + + case "2xl": + value = "1.5"; unit = "rem" + break; + + case "xl": + value = "1.25"; unit = "rem" + break; + + case "l": + value = "1.125"; unit = "rem" + break; + + case "s": + value = "0.875"; unit = "rem" + break; + + case "xs": + value = "0.75"; unit = "rem" + break; + + default: + break; + } + this.style.fontSize = value + unit + 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") { + if (typeof value !== 'number' || isNaN(value)) + throw new Error(`Invalid value: ${value}. Expected a number.`); + checkPositionType(this) + this.style.left = value + unit + return this +} + +HTMLElement.prototype.y = function(value, unit = "px") { + if (typeof value !== 'number' || isNaN(value)) + throw new Error(`Invalid value: ${value}. Expected a number.`); + checkPositionType(this) + this.style.top = value + unit + return this +} + +HTMLElement.prototype.xRight = function(value, unit = "px") { + if (typeof value !== 'number' || isNaN(value)) + throw new Error(`Invalid value: ${value}. Expected a number.`); + checkPositionType(this) + this.style.right = value + unit + return this +} + +HTMLElement.prototype.yBottom = function(value, unit = "px") { + if (typeof value !== 'number' || isNaN(value)) + throw new Error(`Invalid value: ${value}. Expected a number.`); + checkPositionType(this) + this.style.bottom = value + unit + return this +} + +HTMLElement.prototype.backgroundImage = function (...values) { + const formatted = values + .map(v => { + if(v.includes("/") && !v.includes("gradient")) { + v = "url(" + v + ")" + } + return String(v).trim(); + }) + .join(", "); + + this.style.backgroundImage = formatted; + return this; +}; + +HTMLElement.prototype.center = function () { + this.style.transform = "translate(-50%, -50%)" + return this; +}; + +HTMLElement.prototype.centerX = function () { + this.style.transform = "translateX(-50%)" + return this; +}; + +HTMLElement.prototype.centerY = function () { + this.style.transform = "translateY(-50%)" + return this; +}; + +HTMLElement.prototype.alignVertical = function (value) { + const direction = getComputedStyle(this).flexDirection; + if(!direction) { + throw new Error("alignVertical can be only be used on HStacks or VStacks!") + } + + if (direction === "column" || direction === "column-reverse") { + this.style.justifyContent = value; + } else { + this.style.alignItems = value; + } + return this +} + +HTMLElement.prototype.alignHorizontal = function (value) { + const direction = getComputedStyle(this).flexDirection; + if(!direction) { + throw new Error("alignHorizontal can be only be used on HStacks or VStacks!") + } + + if (direction === "column" || direction === "column-reverse") { + this.style.alignItems = value; + } else { + this.style.justifyContent = value; + } + return this +} + + +/* Elements */ + +quill.setChildren = function(el, innerContent) { + if(typeof innerContent === "string") { + el.innerText = innerContent + } else if(typeof innerContent === "function") { + el.render = innerContent + } else { + throw new Error("Children of unknown type") + } +} + +window.a = function a( href, inner=href ) { + if(!href) throw new Error("quill a: missing href argument. Function: a( href, inner=href )") let link = document.createElement("a") link.setAttribute('href', href); - link.innerText = name - Registry.render(link) + quill.setChildren(link, inner) + quill.render(link) return link } @@ -654,605 +579,469 @@ window.img = function img(src, width="", height="") { } else if(height) { image.style.height = height + "px" } - Registry.render(image) + quill.render(image) return image } -window.p = function p(innerText) { - let para = document.createElement("p") - para.innerText = innerText - Registry.initReactivity(para, "innerText", innerText) - Registry.render(para) - return para +HTMLImageElement.prototype.backgroundColor = function(value) { + if (this.src.endsWith('.svg') || this.src.startsWith('data:image/svg+xml')) { + fetch(this.src).then(response => response.text()) + .then(svgText => { + const modifiedSvg = svgText.replace(/\bfill="[^"]*"/g, `fill="${value}"`); + const blob = new Blob([modifiedSvg], { type: 'image/svg+xml' }); + this.src = URL.createObjectURL(blob); + }).catch(error => { + console.error('Error updating SVG fill:', error); + }); + } else { + this.style.backgroundColor = value; + } + + return this; // Always returns the element itself + }; + +window.p = function p(innerHTML) { + let el = document.createElement("p") + if(typeof innerText === "function") { + el.render = innerHTML + } else { + el.innerHTML = innerHTML + } + el.style.margin = "0"; + quill.render(el) + return el } window.h1 = function h1(innerText) { - let header = document.createElement("h1") - header.innerText = innerText - Registry.initReactivity(header, "innerText", innerText) - Registry.render(header) - return header + let el = document.createElement("h1") + el.innerText = innerText + quill.render(el) + return el } window.h2 = function h2(innerText) { - let header = document.createElement("h2") - header.innerText = innerText - Registry.initReactivity(header, "innerText", innerText) - Registry.render(header) - return header + let el = document.createElement("h2") + el.innerText = innerText + quill.render(el) + return el } window.h3 = function h3(innerText) { - let header = document.createElement("h3") - header.innerText = innerText - Registry.initReactivity(header, "innerText", innerText) - Registry.render(header) - return header + let el = document.createElement("h3") + el.innerText = innerText + quill.render(el) + return el } window.div = function (innerText) { - let div = document.createElement("div") - div.innerText = innerText ?? "" - Registry.render(div) - return div + let el = document.createElement("div") + el.innerText = innerText ?? "" + quill.render(el) + return el } window.span = function (innerText) { - let span = document.createElement("span") - span.innerText = innerText - Registry.render(span) - return span + let el = document.createElement("span") + el.innerText = innerText + quill.render(el) + return el } -/* CUSTOM */ - -window.ForEach = function (arr, cb) { - Registry.initReactivity(window.rendering.last(), "children", arr) - arr.forEach((el, i) => { - cb(el, i) - }) +window.button = function (children = "") { + let el = document.createElement("button") + quill.setChildren(el, children) + quill.render(el) + return el } +window.form = function(cb) { + let el = document.createElement("form") + el.render = cb + quill.render(el) + return el +} + +window.input = function(placeholder, width, height) { + let el = document.createElement("input") + el.placeholder = placeholder + el.style.width = width + el.style.height = height + quill.render(el) + return el +} + +window.label = function(text) { + let el = document.createElement("label") + el.innerText = text + quill.render(el) + return el +} + +window.textarea = function(placeholder) { + let el = document.createElement("textarea") + el.placeholder = placeholder + quill.render(el) + return el +} + + +/* STACKS */ + window.VStack = function (cb = () => {}) { - let nowRendering = window.rendering.last() - if(nowRendering.innerHTML.trim() === "") { - let styles = ` - display: flex; - flex-direction: column; - ` - if(nowRendering instanceof Shadow) { - Registry.updateStyle(nowRendering.tagName.toLowerCase(), styles) - } else { - nowRendering.style.cssText += styles - } + let styles = ` + display: flex; + flex-direction: column; + ` + let nowRendering = quill.rendering[quill.rendering.length-1] + if (nowRendering.innerHTML.trim() === "" && !quill.isStack(nowRendering)) { + nowRendering.style.cssText += styles + nowRendering.classList.add("VStack") cb() return nowRendering - } else { - let div = document.createElement("div") - div.classList.add("VStack") - div.style.display = "flex" - div.style.flexDirection = "column" - div.render = cb - Registry.render(div) - return div } + + let div = document.createElement("div") + div.classList.add("VStack") + div.style.cssText += styles + div.render = cb + quill.render(div) + return div } window.HStack = function (cb = () => {}) { - let nowRendering = window.rendering.last() - if(nowRendering.innerHTML.trim() === "") { - let styles = ` - display: flex; - flex-direction: row; - ` - if(nowRendering instanceof Shadow) { - Registry.updateStyle(nowRendering.tagName.toLowerCase(), styles) - } else { - nowRendering.style.cssText += styles - } - cb() - return nowRendering - } else { - let div = document.createElement("div") - div.classList.add("HStack") - div.style.display = "flex" - div.style.flexDirection = "row" - div.render = cb - Registry.render(div) - return div + let styles = ` + display: flex; + flex-direction: row; + `; + let nowRendering = quill.rendering[quill.rendering.length - 1]; + 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 = () => {}) { - let nowRendering = window.rendering.last() - if(nowRendering.innerHTML.trim() === "") { // Parent is Empty, make it a ZStack - cb() - return nowRendering - } else { - let div = document.createElement("div") - div.classList.add("ZStack") - div.render = cb - Registry.render(div) - return div + let nowRendering = quill.rendering[quill.rendering.length - 1]; + 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 */ -window.Circle = function(text = "") { - let div = document.createElement("div") - div.innerText = text - div.style.borderRadius = "100%" - div.style.width = "20px" - div.style.height = "20px" - div.style.background = "black" - div.style.color = "white" - div.style.textAlign = "center" - Registry.render(div) - return div -} - -window.Triangle = function() { - let div = document.createElement("div") - div.style.cssText += ` - width: 20px; - height: 17.3px; - clip-path: polygon(50% 0%, 0% 100%, 100% 100%); - background: black; - ` - Registry.render(div) - return div -} - -/* PROTOTYPE FUNCTIONS */ - -Array.prototype.last = function() { - return this[this.length-1] -} -HTMLElement.prototype.addAttribute = function(name) { - this.setAttribute(name, "") -} - -HTMLElement.prototype.ownHTML = function() { - return this.startingTag() + this.endingTag() -} - -HTMLElement.prototype.startingTag = function() { - const tag = this.tagName.toLowerCase(); - let html = `<${tag}`; - - for (const attr of this.attributes) { - html += ` ${attr.name}="${attr.value}"`; - } - - html += `>`; - return html; -} - -HTMLElement.prototype.endingTag = function() { - const tag = this.tagName.toLowerCase(); - return ``; -} - -Element.prototype.render = function (...els) { - if(els.length > 0) { - this.innerHTML = "" - els.forEach((el) => { - this.appendChild(el) - }) - } - return this -} - -HTMLElement.prototype.class = function(classNames) { - this.className = classNames - return this -} - -/* PROTOTYPE STYLING */ - -function extendHTMLElementWithStyleSetters() { - allStyleProps.forEach(prop => { - if(prop === "translate") return - HTMLElement.prototype[prop] = function(value) { - this.style[prop] = value; - Registry.initReactivity(this, ["style", prop], value); - return this; - }; - }); -} -extendHTMLElementWithStyleSetters(); - -HTMLElement.prototype.padding = function(direction, value) { - if(!value) { - this.style.padding = direction; - } - - const directionName = `padding${direction.charAt(0).toUpperCase()}${direction.slice(1)}`; - if (typeof value === 'number') { - this.style[directionName] = `${value}px`; - } else { - this.style[directionName] = value; - } - Registry.initReactivity(this, ["style", directionName], value); - return this -} - - HTMLElement.prototype.paddingTop = function(value, unit = "px") { - this.style.paddingTop = value + unit - Registry.initReactivity(this, ["style", "paddingTop"], value); +window.svgMethods = function(svg) { + svg.pulse = function (duration = 600) { + this.style.transition = `transform ${duration}ms ease-in-out` + this.style.transform = "scale(1.2)" + setTimeout(() => { + this.style.transform = "scale(1)" + }, duration / 2) return this } - HTMLElement.prototype.paddingLeft = function(value, unit = "px") { - this.style.paddingLeft = value + unit - Registry.initReactivity(this, ["style", "paddingLeft"], value); + // Rotate (e.g. loading spinner) + svg.rotate = function (degrees = 360, duration = 1000) { + this.style.transition = `transform ${duration}ms linear` + this.style.transform = `rotate(${degrees}deg)` return this } - HTMLElement.prototype.paddingBottom = function(value, unit = "px") { - this.style.paddingBottom = value + unit - Registry.initReactivity(this, ["style", "paddingBottom"], value); + // Change color + svg.fill = function (color) { + this.setAttribute("fill", color) return this } - HTMLElement.prototype.paddingRight = function(value, unit = "px") { - this.style.paddingRight = value + unit - Registry.initReactivity(this, ["style", "paddingRight"], value); + svg.height = function (height) { + this.setAttribute("height", height) return this } -HTMLElement.prototype.margin = function(value, unit = "px") { - this.style.margin = value + unit - Registry.initReactivity(this, ["style", "margin"], value); - return this -} - - HTMLElement.prototype.marginTop = function(value, unit = "px") { - this.style.marginTop = value + unit - Registry.initReactivity(this, ["style", "marginTop"], value); + svg.width = function (width) { + this.setAttribute("width", width) return this } - HTMLElement.prototype.marginLeft = function(value, unit = "px") { - this.style.marginLeft = value + unit - Registry.initReactivity(this, ["style", "marginLeft"], value); + svg.stroke = function (width, color) { + this.setAttribute("stroke", color) + this.setAttribute("stroke-width", width) return this } - HTMLElement.prototype.marginBottom = function(value, unit = "px") { - this.style.marginBottom = value + unit - Registry.initReactivity(this, ["style", "marginBottom"], value); + // Toggle visibility + svg.toggle = function () { + this.style.display = this.style.display === "none" ? "" : "none" return this } - - HTMLElement.prototype.marginRight = function(value, unit = "px") { - this.style.marginRight = value + unit - Registry.initReactivity(this, ["style", "marginRight"], value); - return this - } - -HTMLElement.prototype.width = function(value, unit = "px") { - this.style.width = value + unit - Registry.initReactivity(this, ["style", "width"], value); - return this } -HTMLElement.prototype.height = function(value, unit = "px") { - this.style.height = value + unit - Registry.initReactivity(this, ["style", "height"], value); - return this +window.Rectangle = function (width = "40px", height = "40px") { + const svgNS = "http://www.w3.org/2000/svg"; + const svgEl = document.createElementNS(svgNS, "svg"); + const rectEl = document.createElementNS(svgNS, "rect"); + + // SVG size + svgEl.setAttribute("width", width); + svgEl.setAttribute("height", height); + svgEl.setAttribute("viewBox", "0 0 100 100"); + svgEl.setAttribute("preserveAspectRatio", "xMidYMid meet"); + + // Rectangle: full size, slightly rounded corners + rectEl.setAttribute("x", "15"); // 15% margin from edges + rectEl.setAttribute("y", "15"); + rectEl.setAttribute("width", "70"); // 70% of viewBox + rectEl.setAttribute("height", "70"); + // rectEl.setAttribute("rx", "8"); // rounded corners (optional) + // rectEl.setAttribute("ry", "8"); + + svgEl.appendChild(rectEl); + svgMethods(svgEl); // assuming you have this + quill.render(svgEl); + return svgEl; } -HTMLElement.prototype.fontSize = function(value, unit = "px") { - this.style.fontSize = value + unit - Registry.initReactivity(this, ["style", "fontSize"], value); - return this +window.Triangle = function (width = "40px", height = "40px") { + const svgNS = "http://www.w3.org/2000/svg" + const svgEl = document.createElementNS(svgNS, "svg") + const pathEl = document.createElementNS(svgNS, "path") + + // SVG size + svgEl.setAttribute("width", width) + svgEl.setAttribute("height", height) + svgEl.setAttribute("viewBox", "0 0 100 100") + svgEl.setAttribute("preserveAspectRatio", "xMidYMid meet") + // Right-pointing triangle (Play icon) + pathEl.setAttribute("d", "M 25 15 L 90 50 L 25 85 Z") // ◄ adjust points if needed + + svgEl.appendChild(pathEl) + svgMethods(svgEl) + quill.render(svgEl) + return svgEl } -function checkStyle(el) { - let computed = window.getComputedStyle(el).position - if(!(computed === "absolute" || computed === "fixed")) { - el.style.position = "absolute" - } -} -HTMLElement.prototype.x = function(value, unit = "px") { - if (typeof value !== 'number' || isNaN(value)) - throw new Error(`Invalid value: ${value}. Expected a number.`); - checkStyle(this) - this.style.left = value + unit - Registry.initReactivity(this, ["style", "left"], value); - return this -} - -HTMLElement.prototype.y = function(value, unit = "px") { - if (typeof value !== 'number' || isNaN(value)) - throw new Error(`Invalid value: ${value}. Expected a number.`); - checkStyle(this) - this.style.top = value + unit - Registry.initReactivity(this, ["style", "top"], value); - return this -} - -HTMLElement.prototype.xRight = function(value, unit = "px") { - if (typeof value !== 'number' || isNaN(value)) - throw new Error(`Invalid value: ${value}. Expected a number.`); - checkStyle(this) - this.style.right = value + unit - Registry.initReactivity(this, ["style", "right"], value); - return this -} - -HTMLElement.prototype.yBottom = function(value, unit = "px") { - if (typeof value !== 'number' || isNaN(value)) - throw new Error(`Invalid value: ${value}. Expected a number.`); - checkStyle(this) - this.style.bottom = value + unit - Registry.initReactivity(this, ["style", "bottom"], value); - return this -} - -HTMLElement.prototype.positionType = function (value) { - if(!(value === "absolute" || value === "relative" || value === "static" || value === "fixed" || value === "sticky")) { - console.error("HTMLElement.overlflow: must have valid overflow value!") - return; - } - this.style.position = value - Registry.initReactivity(this, ["style", "position"], value); - return this -} - -/* PROTOTYPE EVENTS */ +/* EVENTS */ HTMLElement.prototype.onAppear = function(func) { - func(this) - return this -} + func.call(this); + return this; +}; + HTMLElement.prototype.onClick = function(func) { - this.addEventListener("click", func) - return this -} + const onMouseDown = () => func.call(this, false); + const onMouseUp = () => func.call(this, true); + this._storeListener("mousedown", onMouseDown); + this._storeListener("mouseup", onMouseUp); + return this; +}; + HTMLElement.prototype.onMouseDown = function(func) { - this.addEventListener("mousedown", func) - return this -} + this._storeListener("mousedown", func); + return this; +}; + HTMLElement.prototype.onMouseUp = function(func) { - this.addEventListener("mouseup", func) - return this -} + this._storeListener("mouseup", func); + return this; +}; + HTMLElement.prototype.onRightClick = function(func) { - this.addEventListener("contextmenu", func) - return this -} + this._storeListener("contextmenu", func); + return this; +}; HTMLElement.prototype.onHover = function(cb) { - this.addEventListener("mouseover", () => cb(true)) - this.addEventListener("mouseleave", () => cb(false)) - return this -} + const onEnter = (e) => cb.call(this, true, e); + const onLeave = (e) => cb.call(this, false, e); + this._storeListener("mouseover", onEnter); + this._storeListener("mouseleave", onLeave); + return this; +}; -/* PARSE */ +HTMLElement.prototype.onFocus = function(cb) { + if (!this.matches('input, textarea, select, button')) { + throw new Error("Can't put focus event on non-form element!"); + } + const onFocus = () => cb.call(this, true); + const onBlur = () => cb.call(this, false); + this._storeListener("focus", onFocus); + this._storeListener("blur", onBlur); + return this; +}; -Registry.parseClassFields = function(classObject) { - let str = classObject.toString(); - const lines = str.split('\n'); - const fields = []; - let braceDepth = 0; // Tracks the depth of curly braces to identify when we're inside a function/method +HTMLElement.prototype.onKeyDown = function(cb) { + this._storeListener("keydown", cb); + return this; +}; - for (let line of lines) { - const trimmedLine = line.trim(); +HTMLElement.prototype.onInput = function(cb) { + if(!this.matches('input, textarea, [contenteditable=""], [contenteditable="true"]')) + throw new Error("Can't put input event on non-input element!") + this._storeListener("input", cb); + return this; +}; - // Update braceDepth based on the current line - braceDepth += (trimmedLine.match(/{/g) || []).length; - braceDepth -= (trimmedLine.match(/}/g) || []).length; +HTMLElement.prototype.onChange = function(cb) { + if(!this.matches('input, textarea, [contenteditable=""], [contenteditable="true"]')) + throw new Error("Can't put input event on non-input element!") + this._storeListener("change", cb); + return this; +}; - // Check if the line is outside any function/method (top-level within the class) - if (braceDepth === 1) { - // Attempt to match a class field declaration with or without initialization - const fieldMatch = trimmedLine.match(/^([a-zA-Z_$][0-9a-zA-Z_$]*)\s*(=|;|\n|$)/); - if (fieldMatch) { - fields.push(fieldMatch[1]); - } - } - // If we encounter the constructor, stop the parsing as we're only interested in fields above it - if (trimmedLine.startsWith('constructor')) { +HTMLElement.prototype.onSubmit = function(cb) { + if(!this.matches('form')) + throw new Error("Can't put form event on non-form element!") + this._storeListener("submit", cb); + return this; +}; + +HTMLElement.prototype.onTouch = function(cb) { + const onStart = () => cb.call(this, true); + const onEnd = () => cb.call(this, false); + const onCancel = () => cb.call(this, null); + this._storeListener("touchstart", onStart); + this._storeListener("touchend", onEnd); + this._storeListener("touchcancel", onCancel); + return this; +}; + +HTMLElement.prototype.onTap = function(cb) { + this._storeListener("touchend", cb); + return this; +}; + +/* 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. +*/ +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 fields; + return this; +}; +window.addEventListener("navigate", () => { + for(entry of navigateListeners) { + entry.el.dispatchEvent(new CustomEvent("navigate")) + } +}) + +/* +Same principle applies +*/ +queryListeners = [] +HTMLElement.prototype.onQueryChanged = function(cb) { + this._storeListener("query-changed", cb); + + let found = false + for(entry of queryListeners) { + if(entry.cb.toString() === cb.toString() && + this.nodeName === entry.el.nodeName) { + found = true + break; + } + } + if(found === false) { + queryListeners.push({el: this, cb: cb}) + } + + return this; +}; +window.addEventListener("query-changed", () => { + for(entry of queryListeners) { + entry.el.dispatchEvent(new CustomEvent("query-changed")) + } +}) + +HTMLElement.prototype.onEvent = function(name, cb) { + window._storeListener(window, name, cb); + return this; +}; + +HTMLElement.prototype._storeListener = function(type, handler, options) { + window._storeListener(this, type, handler, options) } -Registry.parseConstructor = function(classObject) { - let str = classObject.toString(); - const lines = str.split('\n'); - let modifiedLines = []; - let braceDepth = 0; - let constructorFound = false - let superCallFound = false; - let constructorEndFound = false; +window.__listeners = [] - for (let i = 0; i < lines.length; i++) { - let line = lines[i]; - const trimmedLine = line.trim(); +function _storeListener(target, type, handler, options) { + if (!target.__listeners) target.__listeners = []; - modifiedLines.push(line); + const optionsString = JSON.stringify(options); - braceDepth += (trimmedLine.match(/{/g) || []).length; - braceDepth -= (trimmedLine.match(/}/g) || []).length; + const index = target.__listeners.findIndex(listener => + listener.type === type && + listener.handler.toString() === handler.toString() && + JSON.stringify(listener.options) === optionsString + ); - if (trimmedLine.startsWith('constructor(')) { - constructorFound = true; - } + if (index === -1) { // Listener is new + target.addEventListener(type, handler, options); + target.__listeners.push({ type, handler, options }); + } else { // Listener is a duplicate, can be replaced + const old = target.__listeners[index]; + target.removeEventListener(old.type, old.handler, old.options); - if (constructorFound && trimmedLine.startsWith('super(') && !superCallFound) { - superCallFound = true; - modifiedLines.push(` window.Registry.construct(this);`); - } - - if (constructorFound && braceDepth === 1 && superCallFound && !constructorEndFound) { - modifiedLines.splice(modifiedLines.length - 1, 0, ' Object.preventExtensions(this);'); - modifiedLines.splice(modifiedLines.length - 1, 0, ' window.Registry.testInitialized(this);'); - constructorEndFound = true - } - } - - if(superCallFound) { - let modifiedStr = modifiedLines.join('\n'); - modifiedStr = '(' + modifiedStr + ')' - modifiedStr += `//# sourceURL=${classObject.prototype.constructor.name}.shadow` - return eval(modifiedStr); - } - - if(constructorFound) { - throw new Error("Quill: Constructor must have super()! " + lines[0]) - } else { - let constructorString = ` - constructor(...params) { - super(...params) - window.Registry.construct(this) - Object.preventExtensions(this); - window.Registry.testInitialized(this); - } - ` - let closingBracket = str.lastIndexOf("}"); - str = str.slice(0, closingBracket - 1) + constructorString + "\n}" - return eval('(' + str + `) //# sourceURL=${classObject.prototype.constructor.name}.shadow`); + // Replace with the new one + target.addEventListener(type, handler, options); + target.__listeners[index] = { type, handler, options }; } } -Registry.getRender = function(classObject) { - const classString = classObject.toString(); - - const regular = /render\s*\(\s*\)\s*\{/; - const arrow = /render\s*=\s*\(\s*\)\s*=>\s*\{/; - const matches = classString.match(regular) || classString.match(arrow); - - if(matches && matches.length === 1) { - return classString.substring(matches.index) - } else { - console.error("Quill: render funcion not defined properly!") +HTMLElement.prototype.removeAllListeners = function() { + if (!this.__listeners) return; + for (const { type, handler, options } of this.__listeners) { + this.removeEventListener(type, handler, options); } -} + this.__listeners = []; + return this; +}; -Registry.parseRender = class ParseRender { - str; - i = 0; - functionStack; - result; +/* ATTRIBUTES */ - /* - [ - [Function scope, value used] - ["VStack.ForEach", "form.children"], - ["VStack.ForEach.SidebarFile", "form.color"] - ["VStack.x", windowState.sidebarOut] - ] - */ - - constructor(classObject) { - this.str = Registry.getRender(classObject.toString()).replace(/\s/g, ""); - this.functionStack = "" - this.result = [] +HTMLElement.prototype.attr = function(attributes) { + if ( + typeof attributes !== "object" || + attributes === null || + Array.isArray(attributes) + ) { + throw new TypeError("attr() expects an object with key-value pairs"); } - parse() { - this.parseFunction() - return this.result + for (const [key, value] of Object.entries(attributes)) { + this.setAttribute(key, value); } - - parseFunction() { - console.log(this.str) - this.copyTo("{") - let firstEl = this.copyTo("(") - console.log(firstEl) - - if(!firstEl) { - console.log("Empty render function") - return - } - - if(firstEl.includes("Stack")) { - this.parseFunction() - } else if(firstEl.includes("ForEach")) { - let array = this.copyTo(",") - if(array.includes("this")) { - console.log(this.result) - this.result.push([this.functionStack + "ForEach", array.replace("this.", "")]) - } - this.parseFunction() - } else if(firstEl === "switch") { - - } else if(firstEl === ("if")) { - console.log("if") - } - } - - copyTo = function(char) { - this.i = this.str.indexOf(char) - let copied = this.str.substring(0, this.str.indexOf(char)); - this.str = this.str.slice(this.i + 1); // Update the string to exclude the copied part and the character - - return copied - } - - // firstParam(str, i, stack, total) { - // console.log(str[i]) - // switch(str[i]) { - // case "(": - // console.log("function") - // break; - // case "\"": - // console.log("string") - // break; - // default: - // if (!isNaN(input)) { - // console.log("Number"); - // } else { - // console.log("Variable"); - // } - // } - // } - -} - -window.register = Registry.register -window.rendering = [] - - -// const usage = []; -// const lines = renderFunctionToClassEnd.split('\n'); - -// let currentFunction = null; -// let currentFunctionChain = []; // To keep track of nested function names - -// for (const line of lines) { -// const functionMatch = line.match(/^\s*([a-zA-Z_$][0-9a-zA-Z_$]*)\s*=\s*\(\s*\)\s*=>\s*{/); -// if (functionMatch) { -// currentFunction = functionMatch[1]; -// currentFunctionChain.push(currentFunction); -// } - -// if (line.includes('this')) { -// if (currentFunction) { -// const thisUsage = line.match(/this\.[a-zA-Z_$][0-9a-zA-Z_$]*(?:\.[a-zA-Z_$][0-9a-zA-Z_$]*)*/g); -// if (thisUsage) { -// for (const usageItem of thisUsage) { -// const propertyChain = usageItem.replace('this.', ''); -// const completeChain = [...currentFunctionChain, propertyChain]; -// usage.push(completeChain); -// } -// } -// } else { -// const thisUsage = line.match(/this\.[a-zA-Z_$][0-9a-zA-Z_$]*/g); -// if (thisUsage) { -// for (const usageItem of thisUsage) { -// const propertyChain = usageItem.replace('this.', ''); -// usage.push([propertyChain]); -// } -// } -// } -// } -// } + return this; +}; diff --git a/notes.txt b/notes.txt deleted file mode 100644 index e598b22..0000000 --- a/notes.txt +++ /dev/null @@ -1,151 +0,0 @@ - - - - -Shadow.File = (param) => new class { - trippy = "asd" - - constructor() { - console.log(param) - } -} - -console.log(Shadow.File("as")) - - -ObservedObject.WindowState = () => ({ - sidebarOut: false, - children: null -}) -let windowState = ObservedObject.WindowState() -console.log(windowState) - - -Shadow(class File { - -}, "file-") - - - -3/16 -const TestClass = () => new class { - constructor() { - console.log("hey") - } -}() - -This works. Could extend shadow. This way the function and the actual code are not separate. - - -3/10 - -Ran into a problem where I can't call the same element within itself. - -There are two problems: - -1. Javascript scoping means that it tries to call the class it is inside of. -2. Quill instantiates the object when registered, to track its state - - -This is what I ended up going with - simply not using the Space() recursively and instead making a child space. - -class Space extends HTMLElement { - form = Forms.observe(window.location.pathname, this) - - contents = [ - ...this.form.children.map(form => { - switch(form.type) { - case "file": - return File() - case "space": - return ChildSpace() - case "link": - return Link() - } - }) - ] - - constructor() { - super() - console.log(this.form.path) - console.log(this.contents) - this.render(...this.contents) - } -} - - - -This was my attempt to see if an anonymous class can be used. The class functions and extends HTMLElement - so problem #2 is solved. -Problem #1 however, scoping, is not solved unless putting "window.Space()" instead of Space() here, so that it does not -attempt to access the named function value. It seems both functions and classes have this problem. Perhaps there is a -different way it could be done in Quill, like so - - - -const el = () => class extends HTMLElement { - ... -} -quill.register(el, "Space", "parchment-space") - - -However, not naming it at the top is less than desirable. - -quill("Space", class extends HTMLElement { - form = Forms.observe(window.location.pathname, this) - - contents = [ - ...this.form.children.map(form => { - switch(form.type) { - case "file": - return File() - case "space": - return ChildSpace() - case "link": - return Link() - } - }) - ] - - constructor() { - super() - console.log(this.form.path) - console.log(this.contents) - this.render(...this.contents) - } -}) - -this would probably work. Still less than ideal but maybe if we used syntax highlighting it could be alright. -How to name something without the class having access? This is the problem. I didn't try it without being an arrow function so -perhaps this would have a chance. - - - -// const Space = () => class extends HTMLElement { -// form = Forms.observe(window.location.pathname, this) - -// contents = [ -// ...this.form.children.map(form => { -// switch(form.type) { -// case "file": -// return File() -// case "space": -// return Space() -// case "link": -// return Link() -// } -// }) -// ] - -// constructor() { -// super() -// console.log(this.form.path) -// console.log(this.contents) -// this.render(...this.contents) -// } -// } - -// let instan = Space() -// customElements.define("space-", instan) -// window.Space = () => "boi" -// console.log(new instan()) - -window.register(Space, "parchment-space") \ No newline at end of file diff --git a/path.js b/path.js deleted file mode 100644 index c652ce3..0000000 --- a/path.js +++ /dev/null @@ -1,151 +0,0 @@ -class PathProcessor { - path; - hasTrailingSlash = false; - node = (typeof module !== 'undefined' && module.exports) ? true : false; - - constructor(path) { - this.path = path; - if(path === undefined) { - this.path = "" - } - } - - #removeTrailingSlash(path) { - if(path === "/") { - return path; - } - return path.endsWith("/") ? path.slice(0, -1) : path - } - - full() { - if(!this.node) return; - let path = this.path; - this.path = "" - this.join(Path.homedir(), path) - return this; - } - - web() { - if(!this.node) return; - const os = require('os') - this.path = this.path.replace(this.#removeTrailingSlash(os.homedir()), "") - if(this.path === "") { - this.path = "/" - } - return this; - } - - encode() { // Uses the built in encodeURI and also encodes certain characters that are't covered by it - this.path = encodeURI(this.path).replace(/[!'()*]/g, function(c) { - return '%' + c.charCodeAt(0).toString(16); - }); - return this; - } - - decoded() { - this.path = decodeURIComponent(this.path); - return this; - } - - parent() { - const parts = this.path.split('/').filter(Boolean); - parts.pop(); - this.path = '/' + parts.join('/'); - return this; - } - - end() { - const parts = this.path.split('/').filter(Boolean); - this.path = parts.pop() || ''; - return this; - } - - trailingSlash() { - this.path = this.path.endsWith("/") ? this.path : this.path+"/"; - this.hasTrailingSlash = true; - return this; - } - - noTrailingSlash() { - this.path = this.#removeTrailingSlash(this.path) - return this; - } - - join(...segments) { - if (this.path) { - segments.unshift(this.path); - } - - this.path = segments - .map((part, index) => { - if (index === 0) { - return part.trim().replace(/[/]*$/g, ''); - } else { - return part.trim().replace(/(^[/]*|[/]*$)/g, ''); - } - }) - .filter(Boolean) // Remove empty segments - .join('/'); - - return this; - } - - components() { - return this.path.split('/').filter(Boolean); - } - - build() { - return this.hasTrailingSlash ? this.path : this.#removeTrailingSlash(this.path) - } -} - -export default class Path { - static full(path) { - return new PathProcessor(path).full(); - } - - static web(path) { - return new PathProcessor(path).web(); - } - - static decoded(path) { - return new PathProcessor(path).decoded() - } - - static encode(path) { - return new PathProcessor(path).encode() - } - - static parent(path) { - return new PathProcessor(path).parent(); - } - - static end(path) { - return new PathProcessor(path).end(); - } - - static trailingSlash(path) { - return new PathProcessor(path).trailingSlash(); - } - - static noTrailingSlash(path) { - return new PathProcessor(path).noTrailingSlash(); - } - - static components(path) { - return new PathProcessor(path).components(); - } - - static join(...segments) { - return new PathProcessor(null).join(...segments); - } - - static homedir() { - if(typeof module === 'undefined' || !module.exports) return; - const os = require('os') - let ret = os.homedir().replace(/\\/g, '/').replace(/^[a-zA-Z]:/, ''); - return ret - } -} - -window.Path = Path; \ No newline at end of file