Comparing version 0.3.2 to 0.4.0
1820
dist/jaxs.js
@@ -1,578 +0,626 @@ | ||
var __defProp = Object.defineProperty; | ||
var __export = (target, all) => { | ||
for (var name in all) | ||
__defProp(target, name, { | ||
get: all[name], | ||
enumerable: true, | ||
configurable: true, | ||
set: (newValue) => all[name] = () => newValue | ||
}); | ||
}; | ||
// src/rendering/dom/create.ts | ||
var setAttributesOnElement = (element, attributes) => { | ||
for (const key in attributes) { | ||
if (key === "__self") | ||
continue; | ||
if (key === "value") { | ||
element.value = attributes[key]; | ||
} else { | ||
element.setAttribute(key, attributes[key]); | ||
} | ||
const tt = (e, t) => t.createElement(e), et = (e, t) => { | ||
for (const s in t) { | ||
if (s === "__self") continue; | ||
const n = t[s].toString(); | ||
s === "value" ? e.value = n : e.setAttribute(s, n); | ||
} | ||
}; | ||
var setEventsOnElement = (element, events, publish) => { | ||
const eventMaps = {}; | ||
for (const domEvent in events) { | ||
const eventName = events[domEvent]; | ||
const listener = (event) => publish(eventName, event); | ||
element.addEventListener(domEvent, listener); | ||
eventMaps[domEvent] = { | ||
domEvent, | ||
busEvent: eventName, | ||
listener | ||
}, st = (e, t, s) => { | ||
const n = {}; | ||
for (const r in t) { | ||
const o = t[r], a = (h) => s(o, h); | ||
e.addEventListener(r, a), n[r] = { | ||
domEvent: r, | ||
busEvent: o, | ||
listener: a | ||
}; | ||
} | ||
element.eventMaps = eventMaps; | ||
}; | ||
var createNode = (type, document) => { | ||
return document.createElement(type); | ||
}; | ||
var createTextNode = (value, document) => { | ||
return document.createTextNode(value); | ||
}; | ||
var createDecoratedNode = (type, attributes, events, renderKit) => { | ||
const dom = createNode(type, renderKit.document); | ||
setAttributesOnElement(dom, attributes); | ||
setEventsOnElement(dom, events, renderKit.publish); | ||
return dom; | ||
}; | ||
// src/rendering/dom/attributesAndEvents.ts | ||
var separateAttrsAndEvents = (combined, defaultValue = "") => { | ||
const attributes = {}; | ||
const events = {}; | ||
for (const key in combined) { | ||
const value = combined[key]; | ||
if (key.match(/^on.+/i)) { | ||
const eventKey = key.slice(2).toLowerCase(); | ||
events[eventKey] = value; | ||
e.eventMaps = n; | ||
}, nt = (e, t, s, n) => { | ||
const r = tt(e, n.document); | ||
return et(r, t), st(r, s, n.publish), r; | ||
}, N = "http://www.w3.org/2000/svg", rt = (e) => e === "svg", ot = (e, t, s) => { | ||
const n = s.createElementNS(N, e); | ||
for (const r in t) | ||
r === "__self" || r === "xmlns" || n.setAttributeNS(null, r, t[r].toString()); | ||
return n; | ||
}, it = (e) => e.namespaceURI === N, at = (e, t) => t.createTextNode(e); | ||
class ct { | ||
constructor(t) { | ||
this.value = t.toString(), this.isSvg = !1; | ||
} | ||
render(t) { | ||
const s = at(this.value, t.document); | ||
return s.__jsx = "TextNode", [s]; | ||
} | ||
} | ||
const ut = (e) => typeof e == "string" || typeof e == "number", ht = (e) => new ct(e), lt = (e) => ut(e) ? ht(e) : e, dt = (e) => (t) => (t && (t.isSvg = t.isSvg || e), t), pt = (e, t) => mt(e).map(lt).flat().map(dt(t)), mt = (e) => Array.isArray(e) ? e.flat() : e ? [e] : [], j = (e, t = {}) => e || t.children || [], bt = (e, t = "") => { | ||
const s = {}, n = {}; | ||
for (const r in e) { | ||
const o = e[r]; | ||
if (r.match(/^on.+/i)) { | ||
const a = r.slice(2).toLowerCase(); | ||
n[a] = o ? o.toString() : ""; | ||
} else { | ||
attributes[key] = normalizeValueForKey(combined, key, defaultValue); | ||
if (o === !1) continue; | ||
r === "__source" ? s.__source = e.__source : s[r] = ft(r, o, t); | ||
} | ||
} | ||
return { | ||
attributes, | ||
events | ||
attributes: s, | ||
events: n | ||
}; | ||
}; | ||
var normalizeValueForKey = (object, key, defaultValue = "") => { | ||
if (object[key] === undefined) | ||
return defaultValue; | ||
return object[key]; | ||
}; | ||
// src/rendering/dom/svg.ts | ||
var namespace = "http://www.w3.org/2000/svg"; | ||
var isSvgTag = (tagType) => tagType === "svg"; | ||
var isSvg = (element) => element.namespaceURI === namespace; | ||
var createSvgNode = (type, attributes, renderKit) => { | ||
const { document } = renderKit; | ||
const node = document.createElementNS(namespace, type); | ||
for (const key in attributes) { | ||
if (key === "__self" || key === "xmlns") | ||
continue; | ||
node.setAttributeNS(null, key, attributes[key]); | ||
}, ft = (e, t, s = "") => t == null ? s : t.toString(), vt = (e, t) => { | ||
const s = e || {}, n = j(t, s); | ||
return s.children = s.children || n, s; | ||
}, k = (e, t, s = []) => e.reduce(gt(t), s).flat(), gt = (e) => (t, s) => s ? Array.isArray(s) ? k(s, e, t) : (s.render(e).forEach((n) => t.push(n)), t) : t; | ||
class O { | ||
constructor(t, s = !1) { | ||
this.collection = pt(t, s), this.isSvg = s; | ||
} | ||
return node; | ||
}; | ||
// src/rendering/templates/text.ts | ||
class TextTemplate { | ||
value; | ||
constructor(content) { | ||
this.value = content.toString(); | ||
render(t, s) { | ||
this.parentElement = s; | ||
const n = this.generateDom(t); | ||
return this.attachToParent(n), n; | ||
} | ||
render(renderKit) { | ||
const textNode = createTextNode(this.value, renderKit.document); | ||
if (!textNode) | ||
return []; | ||
textNode.__jsx = "TextNode"; | ||
return [textNode]; | ||
generateDom(t) { | ||
return k(this.collection, t); | ||
} | ||
attachToParent(t) { | ||
if (this.parentElement === void 0) return; | ||
const s = this.parentElement; | ||
t.forEach((n) => s.appendChild(n)); | ||
} | ||
} | ||
// src/rendering/templates/children.ts | ||
var ensureArray = (children) => { | ||
if (Array.isArray(children)) { | ||
return children.flat(); | ||
class yt { | ||
constructor(t, s) { | ||
this.type = t, this.attributes = s; | ||
} | ||
if (!children) { | ||
return []; | ||
generate() { | ||
return this.attributes.key || this.sourceKey() || this.createKeyFromAttributes(); | ||
} | ||
return [children]; | ||
}; | ||
var recursiveRender = (children, renderKit, rendered = []) => children.reduce(renderReducer(renderKit), rendered).flat(); | ||
var renderReducer = (renderKit) => (aggregate, view) => { | ||
if (!view) | ||
return aggregate; | ||
if (Array.isArray(view)) { | ||
const dom = recursiveRender(view, renderKit, aggregate); | ||
return dom; | ||
sourceKey() { | ||
if (this.attributes.__source) { | ||
const { fileName: t, lineNumber: s, columnNumber: n } = this.attributes.__source; | ||
return `${t}:${s}:${n}`; | ||
} | ||
} | ||
view.render(renderKit).forEach((template) => aggregate.push(template)); | ||
return aggregate; | ||
}; | ||
var replaceTextNodes = (child) => { | ||
if (isTextNode(child)) { | ||
return textNode(child); | ||
createKeyFromAttributes() { | ||
const t = this.attributes.id ? `#${this.attributes.id}` : "", s = this.attributes.type ? `[type=${this.attributes.type}]` : "", n = this.attributes.name ? `[name=${this.attributes.name}]` : ""; | ||
return `${this.type}${t}${s}${n}`; | ||
} | ||
return child; | ||
} | ||
class Et { | ||
constructor(t, s, n = [], r = !1) { | ||
this.type = t; | ||
const { events: o, attributes: a } = bt(s); | ||
this.events = o, this.attributes = a, this.isSvg = r || rt(this.type), this.children = new O(n, this.isSvg); | ||
} | ||
render(t) { | ||
const s = this.generateDom(t); | ||
return s ? (this.children.render(t, s), [s]) : []; | ||
} | ||
generateDom(t) { | ||
return this.isSvg ? this.generateSvgDom(t) : this.generateHtmlDom(t); | ||
} | ||
generateHtmlDom(t) { | ||
const s = nt( | ||
this.type, | ||
this.attributes, | ||
this.events, | ||
t | ||
); | ||
return s.__jsx = this.jsxKey(), s; | ||
} | ||
generateSvgDom(t) { | ||
const s = ot(this.type, this.attributes, t.document); | ||
return s.__jsx = this.jsxKey(), s; | ||
} | ||
jsxKey() { | ||
return new yt(this.type, this.attributes).generate(); | ||
} | ||
} | ||
const xt = (e, t, ...s) => typeof e == "string" ? new Et(e, t, s) : e(vt(t, s)); | ||
xt.fragment = (e, t) => { | ||
const s = j(t, e); | ||
return new O(s); | ||
}; | ||
var isTextNode = (child) => { | ||
return typeof child === "string" || typeof child === "number"; | ||
}; | ||
var textNode = (content) => { | ||
return new TextTemplate(content); | ||
}; | ||
var withSvgFlag = (isSvg2) => (template) => { | ||
template && (template.isSvg = template.isSvg || isSvg2); | ||
return template; | ||
}; | ||
class Children { | ||
collection; | ||
parentElement; | ||
isSvg; | ||
constructor(jsxChildren, isSvg2 = false) { | ||
this.collection = ensureArray(jsxChildren); | ||
this.collection = this.collection.map(replaceTextNodes); | ||
this.collection = this.collection.flat(); | ||
this.collection = this.collection.map(withSvgFlag(isSvg2)); | ||
this.isSvg = isSvg2; | ||
class At { | ||
constructor(t, s, n) { | ||
this.template = t, this.selector = s, this.renderKit = n, this.dom = []; | ||
} | ||
render(renderKit, parentElement) { | ||
this.parentElement = parentElement; | ||
const dom = this.generateDom(renderKit); | ||
this.attachToParent(dom); | ||
return dom; | ||
renderAndAttach(t) { | ||
this.parentElement = this.getParentElement(), this.dom = this.render({ ...t, parent: this.parentElement }), this.parentElement && this.attach(); | ||
} | ||
generateDom(renderKit) { | ||
return recursiveRender(this.collection, renderKit); | ||
render(t) { | ||
return this.template.render(t); | ||
} | ||
attachToParent(dom) { | ||
if (this.parentElement === undefined) | ||
return; | ||
const parent = this.parentElement; | ||
dom.forEach((node) => parent.appendChild(node)); | ||
attach() { | ||
this.parentElement && (this.parentElement.innerHTML = ""), this.dom.forEach((t) => { | ||
this.parentElement && this.parentElement.appendChild(t); | ||
}); | ||
} | ||
getParentElement() { | ||
return this.renderKit.document.querySelector(this.selector); | ||
} | ||
} | ||
// src/rendering/templates/tag.ts | ||
class Tag { | ||
type; | ||
events; | ||
attributes; | ||
children; | ||
isSvg; | ||
constructor(tagType, combinedAttributes, children2, isSvg2 = false) { | ||
this.type = tagType; | ||
const { events, attributes } = separateAttrsAndEvents(combinedAttributes); | ||
this.events = events; | ||
this.attributes = attributes; | ||
this.isSvg = isSvg2 || isSvgTag(this.type); | ||
this.children = new Children(children2, this.isSvg); | ||
const St = (e, t, s) => { | ||
const n = new At(e, t, s); | ||
return n.renderAndAttach(s), n; | ||
}, $ = "go-to-href", m = "navigation:location-change", M = "navigation:route-change", _t = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProperty({ | ||
__proto__: null, | ||
linkNavigationEvent: $, | ||
locationChangeEvent: m, | ||
routeChangeEvent: M | ||
}, Symbol.toStringTag, { value: "Module" })), F = (e) => { | ||
e.createRecord("route", { | ||
host: "", | ||
path: "", | ||
query: {} | ||
}); | ||
}, T = (e) => { | ||
const t = e.closest("[href]"); | ||
return t && t.getAttribute("href") || ""; | ||
}, D = (e, { publish: t, window: s }) => { | ||
s.history.pushState(null, "", e), t(m, null); | ||
}, z = (e, t) => { | ||
if (!e || !e.target) return; | ||
e.preventDefault(); | ||
const s = T(e.target); | ||
D(s, t); | ||
}, L = (e) => e.replace(/^\?/, "").split("&").reduce((t, s) => { | ||
if (!s) return t; | ||
const n = s.split("="); | ||
return t[n[0]] = n[1], t; | ||
}, {}), P = (e, t) => { | ||
const { state: s, publish: n, window: r } = t, { host: o, pathname: a, search: h } = r.location, i = a, d = L(h), u = { | ||
host: o, | ||
path: i, | ||
query: d | ||
}; | ||
s.store("route").update(u), n(M, u); | ||
}, U = (e) => { | ||
const { subscribe: t } = e; | ||
t($, z); | ||
}, B = (e) => { | ||
const { publish: t, subscribe: s, state: n, window: r } = e; | ||
F(n), r.addEventListener("popstate", () => t(m, null)), s(m, P); | ||
}, K = (e) => { | ||
setTimeout(() => e.publish(m, null), 0); | ||
}, V = (e) => { | ||
B(e), U(e), K(e); | ||
}, wt = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProperty({ | ||
__proto__: null, | ||
publishLocation: K, | ||
startNavigation: V, | ||
subscribeToHistoryChange: B, | ||
subscribeToNavigation: U | ||
}, Symbol.toStringTag, { value: "Module" })); | ||
class R { | ||
constructor({ window: t, document: s, publish: n, subscribe: r, bus: o, state: a, renderKit: h }) { | ||
this.window = t, this.document = s, this.publish = n, this.subscribe = r, this.bus = o, this.state = a, this.renderKit = h, this.roots = []; | ||
} | ||
render(renderKit) { | ||
const dom = this.generateDom(renderKit); | ||
if (!dom) | ||
return []; | ||
this.children.render(renderKit, dom); | ||
return [dom]; | ||
render(t, s) { | ||
const n = St(t, s, this.renderKit); | ||
return this.roots.push(n), n; | ||
} | ||
generateDom(renderKit) { | ||
if (this.isSvg) { | ||
return this.generateSvnDom(renderKit); | ||
} else { | ||
return this.generateHtmlDom(renderKit); | ||
} | ||
startNavigation() { | ||
V(this); | ||
} | ||
generateHtmlDom(renderKit) { | ||
const node = createDecoratedNode(this.type, this.attributes, this.events, renderKit); | ||
node.__jsx = this.key(); | ||
return node; | ||
} | ||
const pe = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProperty({ | ||
__proto__: null, | ||
App: R | ||
}, Symbol.toStringTag, { value: "Module" })); | ||
class J { | ||
constructor() { | ||
this.lookup = {}; | ||
} | ||
generateSvnDom(renderKit) { | ||
const node = createSvgNode(this.type, this.attributes, renderKit); | ||
node.__jsx = this.key(); | ||
return node; | ||
add(t, s, n) { | ||
this.ensureArrayFor(t); | ||
const r = { | ||
listener: s, | ||
index: n, | ||
matcher: t | ||
}; | ||
return this.lookup[t].push(r), () => this.remove(r); | ||
} | ||
key() { | ||
return this.attributes.key || this.source() || this.createKey(); | ||
remove(t) { | ||
this.lookup[t.matcher] && (this.lookup[t.matcher] = this.lookup[t.matcher].reduce((s, n) => (n !== t && s.push(n), s), [])); | ||
} | ||
source() { | ||
if (this.attributes.__source) { | ||
const { fileName, lineNumber, columnNumber } = this.attributes.__source; | ||
return `${fileName}:${lineNumber}:${columnNumber}`; | ||
} | ||
matches(t) { | ||
return this.lookup[t] || []; | ||
} | ||
createKey() { | ||
const id = this.attributes.id ? `#${this.attributes.id}` : ""; | ||
const type = this.attributes.type ? `[type=${this.attributes.type}]` : ""; | ||
const name = this.attributes.name ? `[name=${this.attributes.name}]` : ""; | ||
return `${this.type}${id}${type}${name}`; | ||
ensureArrayFor(t) { | ||
this.lookup[t] || (this.lookup[t] = []); | ||
} | ||
} | ||
// src/jsx.js | ||
var ensureChildrenArray = (maybeChildren, attributes) => maybeChildren || attributes.children || []; | ||
var packageAttributes = (maybeAttributes, maybeChildren) => { | ||
const attributes = maybeAttributes || {}; | ||
const children3 = ensureChildrenArray(maybeChildren, attributes); | ||
attributes.children = attributes.children || children3; | ||
return attributes; | ||
}; | ||
var jsx = (type, attributes, ...children3) => { | ||
if (typeof type === "string") { | ||
return new Tag(type, attributes, children3); | ||
class q { | ||
constructor() { | ||
this.lookup = []; | ||
} | ||
return type(packageAttributes(attributes, children3)); | ||
}; | ||
jsx.fragment = (attributes, maybeChildren) => { | ||
const children3 = ensureChildrenArray(maybeChildren, attributes); | ||
return new Children(children3); | ||
}; | ||
var jsx_default = jsx; | ||
// src/rendering/templates/root.ts | ||
class Root { | ||
template; | ||
selector; | ||
renderKit; | ||
dom; | ||
parentElement; | ||
constructor(template, selector, renderKit) { | ||
this.template = template; | ||
this.selector = selector; | ||
this.renderKit = renderKit; | ||
this.dom = []; | ||
this.parentElement = null; | ||
add(t, s, n) { | ||
const r = { | ||
listener: s, | ||
index: n, | ||
matcher: t | ||
}; | ||
return this.lookup.push(r), () => this.remove(r); | ||
} | ||
renderAndAttach(renderKit) { | ||
this.parentElement = this.getParentElement(); | ||
this.dom = this.render({ ...renderKit, parent: this.parentElement }); | ||
if (this.parentElement) { | ||
this.attach(); | ||
} | ||
remove(t) { | ||
this.lookup = this.lookup.reduce((s, n) => (n !== t && s.push(n), s), []); | ||
} | ||
render(renderKit) { | ||
return this.template.render(renderKit); | ||
matches(t) { | ||
return this.lookup.filter( | ||
(s) => s.matcher.test(t) | ||
); | ||
} | ||
attach() { | ||
this.parentElement && (this.parentElement.innerHTML = ""); | ||
this.dom.forEach((element) => { | ||
this.parentElement && this.parentElement.appendChild(element); | ||
} | ||
class H { | ||
constructor() { | ||
this.exactSubscriptions = new J(), this.fuzzySubscriptions = new q(), this.currentIndex = 0; | ||
} | ||
subscribe(t, s) { | ||
let n; | ||
return typeof t == "string" ? n = this.exactSubscriptions.add( | ||
t, | ||
s, | ||
this.currentIndex | ||
) : n = this.fuzzySubscriptions.add( | ||
t, | ||
s, | ||
this.currentIndex | ||
), this.currentIndex += 1, n; | ||
} | ||
publish(t, s) { | ||
[ | ||
...this.exactSubscriptions.matches(t), | ||
...this.fuzzySubscriptions.matches(t) | ||
].sort((r, o) => r.index - o.index).forEach((r) => { | ||
r.listener(s, this.listenerOptions(t)); | ||
}); | ||
} | ||
getParentElement() { | ||
return this.renderKit.document.querySelector(this.selector); | ||
addListenerOptions(t) { | ||
this.options = t; | ||
} | ||
listenerOptions(t) { | ||
return { | ||
eventName: t, | ||
...this.options, | ||
publish: this.publish.bind(this) | ||
}; | ||
} | ||
} | ||
var render = (template, selector, renderKit) => { | ||
const root = new Root(template, selector, renderKit); | ||
root.renderAndAttach(renderKit); | ||
return root; | ||
}; | ||
// src/state/testingTypes.js | ||
var isBoolean = (value) => typeof value === "boolean"; | ||
var isNumber = (value) => typeof value === "number"; | ||
var isString = (value) => typeof value === "string"; | ||
var isArray = (value) => Array.isArray(value); | ||
var isObject = (value) => value !== null && !isArray(value) && typeof value === "object"; | ||
// src/state/equality.js | ||
var areElementEqual = (oldValue, newValue) => oldValue === newValue; | ||
var keyLengthSame = (oldValue, newValue) => Object.keys(oldValue).length === Object.keys(newValue).length; | ||
var areObjectsEqual = (oldValue, newValue) => { | ||
if (!(isObject(oldValue) && isObject(newValue))) | ||
return false; | ||
if (!keyLengthSame(oldValue, newValue)) | ||
return false; | ||
Object.keys(oldValue).every((key) => { | ||
const oldInnerValue = oldValue[key]; | ||
const newInnerValue = newValue[key]; | ||
return areEqual(oldInnerValue, newInnerValue); | ||
}); | ||
}; | ||
var areArraysEqual = (oldValue, newValue) => { | ||
if (!(isArray(oldValue) && isArray(newValue))) | ||
return false; | ||
if (oldValue.length !== newValue.length) | ||
return false; | ||
oldValue.every((oldInnerValue, index) => { | ||
const newInnerValue = newValue[index]; | ||
return areEqual(oldInnerValue, newInnerValue); | ||
}); | ||
}; | ||
var areEqual = (oldValue, newValue) => { | ||
if (isObject(oldValue)) | ||
return areObjectsEqual(oldValue, newValue); | ||
if (isArray(oldValue)) | ||
return areArraysEqual(oldValue, newValue); | ||
return areElementEqual(oldValue, newValue); | ||
}; | ||
// src/state/stores.js | ||
class GeneralStore { | ||
nullEvent = {}; | ||
constructor({ name, value, parent }) { | ||
this.name = name; | ||
this.value = value; | ||
this.parent = parent; | ||
this.initialState = value; | ||
const I = () => { | ||
const e = new H(); | ||
return { | ||
bus: e, | ||
publish: (n, r) => e.publish(n, r), | ||
subscribe: (n, r) => e.subscribe(n, r) | ||
}; | ||
}, me = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProperty({ | ||
__proto__: null, | ||
ExactSubscriptions: J, | ||
FuzzySubscriptions: q, | ||
JaxsBus: H, | ||
createBus: I | ||
}, Symbol.toStringTag, { value: "Module" })), f = (e) => Array.isArray(e), g = (e) => e !== null && !f(e) && typeof e == "object", Nt = (e, t) => e === t, jt = (e, t) => Object.keys(e).length === Object.keys(t).length, kt = (e, t) => !(g(e) && g(t)) || !jt(e, t) ? !1 : Object.keys(e).every((s) => { | ||
const n = e[s], r = t[s]; | ||
return E(n, r); | ||
}), Ot = (e, t) => !(f(e) && f(t)) || e.length !== t.length ? !1 : e.every((s, n) => { | ||
const r = t[n]; | ||
return E(s, r); | ||
}), E = (e, t) => g(e) ? kt(e, t) : f(e) ? Ot(e, t) : Nt(e, t); | ||
class b { | ||
constructor(t) { | ||
this.store = t; | ||
} | ||
update(newValue) { | ||
if (this.isEqual(newValue)) | ||
return; | ||
this.value = newValue; | ||
return this.parent.publish(this.event()); | ||
update(t) { | ||
this.store.update(t); | ||
} | ||
reset() { | ||
this.update(this.initialState); | ||
this.store.update(this.store.initialState); | ||
} | ||
isEqual(newValue) { | ||
return areElementEqual(this.value, newValue); | ||
get value() { | ||
return this.store.value; | ||
} | ||
event() { | ||
return { | ||
name: this.name, | ||
value: this.value | ||
addUpdaterFunction(t, s) { | ||
this.constructor.prototype[t] = (...n) => { | ||
const r = s(this.value, ...n); | ||
this.update(r); | ||
}; | ||
} | ||
addUpdaterFunctions(t) { | ||
for (const s in t) | ||
this.addUpdaterFunction(s, t[s]); | ||
} | ||
} | ||
class BooleanStore extends GeneralStore { | ||
toggle() { | ||
this.update(!this.value); | ||
class x extends b { | ||
push(t) { | ||
const s = [...this.value, t]; | ||
this.update(s); | ||
} | ||
pop() { | ||
const t = [...this.value], s = t.pop(); | ||
return this.update(t), s; | ||
} | ||
unshift(t) { | ||
const s = [t, ...this.value]; | ||
this.update(s); | ||
} | ||
shift() { | ||
const t = [...this.value], s = t.shift(); | ||
return this.update(t), s; | ||
} | ||
addSorter(t, s) { | ||
this[t] = () => { | ||
this.sortBy(s); | ||
}; | ||
} | ||
sortBy(t) { | ||
const s = [...this.value]; | ||
s.sort(t), this.update(s); | ||
} | ||
insertAt(t, s) { | ||
const n = [...this.value]; | ||
n.splice(t, 0, s), this.update(n); | ||
} | ||
} | ||
class NumericStore extends GeneralStore { | ||
class y { | ||
constructor(t) { | ||
this.name = t.name, this.parent = t.parent, this._value = t.value, this.initialState = structuredClone(t.value), this.updater = new b(this); | ||
} | ||
get value() { | ||
return this._value; | ||
} | ||
set value(t) { | ||
throw new Error("Cannot set value directly. Use an updater!"); | ||
} | ||
update(t) { | ||
if (typeof t == "function") { | ||
const s = this.getUpdatedValue(t); | ||
this.updateValue(s); | ||
} else | ||
this.updateValue(t); | ||
} | ||
updateValue(t) { | ||
E(this._value, t) || (this._value = t, this.parent.notify(this.name)); | ||
} | ||
getUpdatedValue(t) { | ||
return t(this.value); | ||
} | ||
addUpdaters(t) { | ||
this.updater.addUpdaterFunctions(t); | ||
} | ||
addUpdater(t, s) { | ||
this.updater.addUpdaterFunction(t, s); | ||
} | ||
addSorter(t, s) { | ||
this.updater instanceof x && this.updater.addSorter(t, s); | ||
} | ||
} | ||
class StringStore extends GeneralStore { | ||
} | ||
class ListStore extends GeneralStore { | ||
isEqual(newValue) { | ||
return areArraysEqual(this.value, newValue); | ||
class Q extends b { | ||
toggle() { | ||
const t = !this.value; | ||
this.update(t); | ||
} | ||
push(newValue) { | ||
const value = [...this.value, newValue]; | ||
this.update(value); | ||
setTrue() { | ||
this.update(!0); | ||
} | ||
setFalse() { | ||
this.update(!1); | ||
} | ||
} | ||
class RecordStore extends GeneralStore { | ||
isEqual(newValue) { | ||
return areObjectsEqual(this.value, newValue); | ||
class W extends b { | ||
updateAttribute(t, s) { | ||
const n = { ...this.value }; | ||
n[t] = s, this.update(n); | ||
} | ||
} | ||
// src/state.js | ||
var eventPrefix = "state-change"; | ||
var eventName = (name) => `${eventPrefix}:${name}`; | ||
class State { | ||
constructor(publish) { | ||
this.publisher = publish; | ||
this.stores = {}; | ||
this.events = []; | ||
this.transacting = false; | ||
const A = "state"; | ||
class G { | ||
constructor(t) { | ||
this.publisher = t, this.stores = {}, this.eventNamePrefix = A, this.notifications = /* @__PURE__ */ new Set(), this.inTransaction = !1; | ||
} | ||
create(name, value) { | ||
const StoreClass = this.storeTypeFor(value); | ||
const store = new StoreClass({ name, value, parent: this }); | ||
this.addStore(name, store); | ||
create(t, s) { | ||
const n = new y({ | ||
name: t, | ||
parent: this, | ||
value: s | ||
}); | ||
return this.stores[t] = n, n; | ||
} | ||
add(store) { | ||
const name = store.name; | ||
this.addStore(name, store); | ||
createBoolean(t, s) { | ||
const n = this.create(t, s); | ||
return n.updater = new Q(n), n; | ||
} | ||
getStore(name) { | ||
return this.stores[name]; | ||
createRecord(t, s) { | ||
const n = this.create(t, s); | ||
return n.updater = new W(n), n; | ||
} | ||
addStore(name, store) { | ||
this.stores[name] = store; | ||
this[name] = store; | ||
createList(t, s) { | ||
const n = this.create(t, s); | ||
return n.updater = new x(n), n; | ||
} | ||
storeTypeFor(value) { | ||
if (isArray(value)) | ||
return ListStore; | ||
if (isObject(value)) | ||
return RecordStore; | ||
if (isNumber(value)) | ||
return NumericStore; | ||
if (isBoolean(value)) | ||
return BooleanStore; | ||
if (isString(value)) | ||
return StringStore; | ||
return GeneralStore; | ||
store(t) { | ||
return this.stores[t] || new y({ | ||
name: t, | ||
parent: this, | ||
value: void 0 | ||
}); | ||
} | ||
publish(event) { | ||
this.events.push(event); | ||
if (!this.transacting) | ||
this.publishAll(); | ||
get(t) { | ||
return this.store(t).value; | ||
} | ||
getAll(t) { | ||
return t.reduce((s, n) => (s[n] = this.get(n), s), {}); | ||
} | ||
notify(t) { | ||
this.inTransaction ? this.notifications.add(t) : this.publish(t); | ||
} | ||
update(t, s) { | ||
this.store(t).update(s); | ||
} | ||
transaction(t) { | ||
this.inTransaction = !0, t(this.stores), this.inTransaction = !1, this.publishAll(); | ||
} | ||
publishAll() { | ||
const publishedStores = []; | ||
this.events.reverse().forEach((event) => { | ||
const { name, value } = event; | ||
if (!publishedStores.includes(name)) { | ||
publishedStores.push(name); | ||
this.publisher(`${eventPrefix}:${name}`, value); | ||
} | ||
this.notifications.forEach((t) => { | ||
this.publish(t); | ||
}), this.notifications.clear(); | ||
} | ||
publish(t) { | ||
this.publisher(this.event(t), { | ||
state: this, | ||
store: this.store(t) | ||
}); | ||
this.events = []; | ||
} | ||
transaction(setter) { | ||
this.transacting = true; | ||
setter(this); | ||
this.transacting = false; | ||
this.publishAll(); | ||
event(t) { | ||
return `${this.eventNamePrefix}:${t}`; | ||
} | ||
value() { | ||
return Object.keys(this.stores).reduce((valueObject, key) => { | ||
valueObject[key] = this.stores[key].value; | ||
return valueObject; | ||
}, {}); | ||
} | ||
const X = (e) => new G(e), be = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProperty({ | ||
__proto__: null, | ||
BooleanUpdater: Q, | ||
JaxsState: G, | ||
JaxsStore: y, | ||
JaxsStoreUpdater: b, | ||
ListUpdater: x, | ||
ObjectUpdater: W, | ||
createState: X, | ||
eventName: A | ||
}, Symbol.toStringTag, { value: "Module" })); | ||
class $t { | ||
constructor(t) { | ||
this.setupDomEnvironment(t); | ||
} | ||
setup() { | ||
return this.setupBus(), this.setupState(), this.addBusOptions(), this.setRenderKit(), new R({ | ||
window: this.window, | ||
document: this.document, | ||
publish: this.publish, | ||
subscribe: this.subscribe, | ||
bus: this.bus, | ||
state: this.state, | ||
renderKit: this.renderKit | ||
}); | ||
} | ||
setupDomEnvironment(t) { | ||
t.window ? (this.window = t.window, this.document = this.window.document) : t.document ? (this.window = t.document.defaultView, this.document = t.document) : (this.window = window, this.document = document); | ||
} | ||
setupBus() { | ||
const { publish: t, subscribe: s, bus: n } = I(); | ||
this.publish = t, this.subscribe = s, this.bus = n; | ||
} | ||
setupState() { | ||
this.state = X(this.publish); | ||
} | ||
addBusOptions() { | ||
this.bus.addListenerOptions({ | ||
state: this.state, | ||
document: this.document, | ||
window: this.window | ||
}); | ||
} | ||
setRenderKit() { | ||
this.renderKit = { | ||
publish: this.publish, | ||
subscribe: this.subscribe, | ||
state: this.state, | ||
document: this.document, | ||
window: this.window | ||
}; | ||
} | ||
} | ||
// src/types.ts | ||
var ChangeInstructions; | ||
(function(ChangeInstructions2) { | ||
ChangeInstructions2[ChangeInstructions2["removeNode"] = 0] = "removeNode"; | ||
ChangeInstructions2[ChangeInstructions2["insertNode"] = 1] = "insertNode"; | ||
ChangeInstructions2[ChangeInstructions2["replaceNode"] = 2] = "replaceNode"; | ||
ChangeInstructions2[ChangeInstructions2["removeAttribute"] = 3] = "removeAttribute"; | ||
ChangeInstructions2[ChangeInstructions2["addAttribute"] = 4] = "addAttribute"; | ||
ChangeInstructions2[ChangeInstructions2["updateAttribute"] = 5] = "updateAttribute"; | ||
ChangeInstructions2[ChangeInstructions2["removeEvent"] = 6] = "removeEvent"; | ||
ChangeInstructions2[ChangeInstructions2["addEvent"] = 7] = "addEvent"; | ||
ChangeInstructions2[ChangeInstructions2["updateEvent"] = 8] = "updateEvent"; | ||
ChangeInstructions2[ChangeInstructions2["changeValue"] = 9] = "changeValue"; | ||
ChangeInstructions2[ChangeInstructions2["changeText"] = 10] = "changeText"; | ||
})(ChangeInstructions || (ChangeInstructions = {})); | ||
// src/rendering/change/instructions/generate.ts | ||
var changeText = (source, target) => ({ | ||
source, | ||
target, | ||
type: ChangeInstructions.changeText, | ||
const fe = (e = {}) => { | ||
const s = new $t(e).setup(); | ||
return s.startNavigation(), s; | ||
}; | ||
var c = /* @__PURE__ */ ((e) => (e[e.removeNode = 0] = "removeNode", e[e.insertNode = 1] = "insertNode", e[e.replaceNode = 2] = "replaceNode", e[e.removeAttribute = 3] = "removeAttribute", e[e.addAttribute = 4] = "addAttribute", e[e.updateAttribute = 5] = "updateAttribute", e[e.removeEvent = 6] = "removeEvent", e[e.addEvent = 7] = "addEvent", e[e.updateEvent = 8] = "updateEvent", e[e.changeValue = 9] = "changeValue", e[e.changeText = 10] = "changeText", e))(c || {}); | ||
const ve = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProperty({ | ||
__proto__: null, | ||
ChangeInstructionTypes: c | ||
}, Symbol.toStringTag, { value: "Module" })), Mt = (e, t) => ({ | ||
source: e, | ||
target: t, | ||
type: c.changeText, | ||
data: {} | ||
}); | ||
var replaceNode = (source, target) => ({ | ||
source, | ||
target, | ||
type: ChangeInstructions.replaceNode, | ||
}), Ft = (e, t) => ({ | ||
source: e, | ||
target: t, | ||
type: c.replaceNode, | ||
data: {} | ||
}); | ||
var removeAttribute = (source, target, data) => ({ | ||
source, | ||
target, | ||
data, | ||
type: ChangeInstructions.removeAttribute | ||
}); | ||
var addAttribute = (source, target, data) => ({ | ||
source, | ||
target, | ||
data, | ||
type: ChangeInstructions.addAttribute | ||
}); | ||
var updateAttribute = (source, target, data) => ({ | ||
source, | ||
target, | ||
data, | ||
type: ChangeInstructions.updateAttribute | ||
}); | ||
var removeEvent = (source, target, data) => ({ | ||
source, | ||
target, | ||
data, | ||
type: ChangeInstructions.removeEvent | ||
}); | ||
var addEvent = (source, target, data) => ({ | ||
source, | ||
target, | ||
data, | ||
type: ChangeInstructions.addEvent | ||
}); | ||
var updateEvent = (source, target, data) => ({ | ||
source, | ||
target, | ||
data, | ||
type: ChangeInstructions.updateEvent | ||
}); | ||
var removeNode = (source) => ({ | ||
source, | ||
target: source, | ||
type: ChangeInstructions.removeNode, | ||
}), Tt = (e, t, s) => ({ | ||
source: e, | ||
target: t, | ||
data: s, | ||
type: c.removeAttribute | ||
}), Dt = (e, t, s) => ({ | ||
source: e, | ||
target: t, | ||
data: s, | ||
type: c.addAttribute | ||
}), zt = (e, t, s) => ({ | ||
source: e, | ||
target: t, | ||
data: s, | ||
type: c.updateAttribute | ||
}), Lt = (e, t, s) => ({ | ||
source: e, | ||
target: t, | ||
data: s, | ||
type: c.removeEvent | ||
}), Pt = (e, t, s) => ({ | ||
source: e, | ||
target: t, | ||
data: s, | ||
type: c.addEvent | ||
}), Ut = (e, t, s) => ({ | ||
source: e, | ||
target: t, | ||
data: s, | ||
type: c.updateEvent | ||
}), S = (e) => ({ | ||
source: e, | ||
target: e, | ||
// for type crap only | ||
type: c.removeNode, | ||
data: {} | ||
}); | ||
var insertNode = (target, data) => ({ | ||
target, | ||
source: target, | ||
type: ChangeInstructions.insertNode, | ||
data | ||
}); | ||
var changeValue = (source, target, data) => ({ | ||
source, | ||
target, | ||
type: ChangeInstructions.changeValue, | ||
data | ||
}); | ||
// src/rendering/change/instructions/idMap.js | ||
var nullMatch = { index: -1 }; | ||
class IdMap { | ||
}), v = (e, t) => ({ | ||
target: e, | ||
source: e, | ||
// for type crap only | ||
type: c.insertNode, | ||
data: t | ||
}), Bt = (e, t, s) => ({ | ||
source: e, | ||
target: t, | ||
type: c.changeValue, | ||
data: s | ||
}), Kt = (e, t) => e.type > t.type ? 1 : e.type < t.type ? -1 : 0, _ = { index: -1 }; | ||
class Vt { | ||
constructor() { | ||
this.map = {}; | ||
} | ||
populate(list) { | ||
list.forEach((element, i) => { | ||
const id = element.__jsx; | ||
if (id) { | ||
this.map[id] = this.map[id] || []; | ||
this.map[id].push({ | ||
element, | ||
index: i | ||
}); | ||
} | ||
populate(t) { | ||
t.forEach((s, n) => { | ||
const r = s.__jsx; | ||
r && (this.map[r] = this.map[r] || [], this.map[r].push({ | ||
element: s, | ||
index: n | ||
})); | ||
}); | ||
} | ||
pullMatch(element) { | ||
const id = element && element.__jsx; | ||
if (!id) | ||
return nullMatch; | ||
if (!(this.map[id] && this.map[id].length)) | ||
return nullMatch; | ||
return this.map[id].shift(); | ||
pullMatch(t) { | ||
const s = t && t.__jsx; | ||
return !s || !(this.map[s] && this.map[s].length) ? _ : this.map[s].shift(); | ||
} | ||
clear(element) { | ||
const id = element && element.__jsx; | ||
if (!(id && this.map[id] && this.map[id].length)) | ||
return; | ||
const matches = this.map[id]; | ||
this.map[id] = matches.reduce((collection, possibleMatch) => { | ||
if (possibleMatch.element !== element) | ||
collection.push(possibleMatch); | ||
return collection; | ||
}, []); | ||
clear(t) { | ||
const s = t && t.__jsx; | ||
if (!(s && this.map[s] && this.map[s].length)) return; | ||
const n = this.map[s]; | ||
this.map[s] = n.reduce((r, o) => (o.element !== t && r.push(o), r), []); | ||
} | ||
check(element) { | ||
const id = element && element.__jsx; | ||
if (!(id && this.map[id])) | ||
return false; | ||
return this.map[id].length > 0; | ||
check(t) { | ||
const s = t && t.__jsx; | ||
return s && this.map[s] ? this.map[s].length > 0 : !1; | ||
} | ||
@@ -583,575 +631,249 @@ remaining() { | ||
} | ||
var createIdMap = (list) => { | ||
const map = new IdMap; | ||
map.populate(list); | ||
return map; | ||
}; | ||
// src/rendering/change/instructions/attributes.ts | ||
var compileForAttributes = (source, target, isSvg2 = false) => { | ||
const instructions = []; | ||
const sourceAttributes = source.attributes; | ||
const sourceLength = sourceAttributes.length; | ||
const targetAttributes = target.attributes; | ||
const targetLength = targetAttributes.length; | ||
let index; | ||
let innerIndex; | ||
let matchingAttribute; | ||
for (index = 0;index < sourceLength; index++) { | ||
matchingAttribute = null; | ||
const sourceAttribute = sourceAttributes.item(index); | ||
if (!sourceAttribute) | ||
continue; | ||
for (innerIndex = 0;innerIndex < targetLength; innerIndex++) { | ||
const targetAttribute = targetAttributes.item(innerIndex); | ||
if (!targetAttribute) | ||
continue; | ||
if (sourceAttribute.name == targetAttribute.name) { | ||
matchingAttribute = targetAttribute; | ||
break; | ||
const w = (e) => { | ||
const t = new Vt(); | ||
return t.populate(e), t; | ||
}, Y = (e, t, s = !1) => { | ||
const n = [], r = e.attributes, o = r.length, a = t.attributes, h = a.length; | ||
let i, d, u; | ||
for (i = 0; i < o; i++) { | ||
u = null; | ||
const l = r.item(i); | ||
if (l) { | ||
for (d = 0; d < h; d++) { | ||
const p = a.item(d); | ||
if (p && l.name == p.name) { | ||
u = p; | ||
break; | ||
} | ||
} | ||
u ? l.value !== u.value && n.push( | ||
zt(e, t, { | ||
name: l.name, | ||
value: u.value, | ||
isSvg: s | ||
}) | ||
) : n.push( | ||
Tt(e, t, { name: l.name, isSvg: s }) | ||
); | ||
} | ||
if (!matchingAttribute) { | ||
instructions.push(removeAttribute(source, target, { name: sourceAttribute.name, isSvg: isSvg2 })); | ||
} else if (sourceAttribute.value !== matchingAttribute.value) { | ||
instructions.push(updateAttribute(source, target, { | ||
name: sourceAttribute.name, | ||
value: matchingAttribute.value, | ||
isSvg: isSvg2 | ||
})); | ||
} | ||
} | ||
for (index = 0;index < targetLength; index++) { | ||
matchingAttribute = null; | ||
const targetAttribute = targetAttributes.item(index); | ||
if (!targetAttribute) | ||
continue; | ||
for (innerIndex = 0;innerIndex < sourceLength; innerIndex++) { | ||
const sourceAttribute = sourceAttributes.item(innerIndex); | ||
if (!sourceAttribute) | ||
continue; | ||
if (sourceAttribute.name == targetAttribute.name) { | ||
matchingAttribute = sourceAttribute; | ||
break; | ||
for (i = 0; i < h; i++) { | ||
u = null; | ||
const l = a.item(i); | ||
if (l) { | ||
for (d = 0; d < o; d++) { | ||
const p = r.item(d); | ||
if (p && p.name == l.name) { | ||
u = p; | ||
break; | ||
} | ||
} | ||
u || n.push( | ||
Dt(e, t, { | ||
name: l.name, | ||
value: l.value, | ||
isSvg: s | ||
}) | ||
); | ||
} | ||
if (!matchingAttribute) { | ||
instructions.push(addAttribute(source, target, { | ||
name: targetAttribute.name, | ||
value: targetAttribute.value, | ||
isSvg: isSvg2 | ||
})); | ||
} | ||
} | ||
return instructions; | ||
}; | ||
// src/rendering/change/instructions/events.ts | ||
var compileForEvents = (source, target) => { | ||
const instructions = []; | ||
const sourceEventMaps = source.eventMaps; | ||
const targetEventMaps = target.eventMaps; | ||
const sourceDomEvents = Object.keys(sourceEventMaps); | ||
const targetDomEvents = Object.keys(targetEventMaps); | ||
sourceDomEvents.forEach((domEvent) => { | ||
const sourceEventMap = sourceEventMaps[domEvent]; | ||
const targetEventMap = targetEventMaps[domEvent]; | ||
if (!targetEventMap) { | ||
instructions.push(removeEvent(source, target, { | ||
name: sourceEventMap.domEvent, | ||
value: sourceEventMap.listener | ||
})); | ||
} else if (targetEventMap.busEvent !== sourceEventMap.busEvent) { | ||
instructions.push(updateEvent(source, target, { | ||
name: domEvent, | ||
targetValue: targetEventMap.listener, | ||
sourceValue: sourceEventMap.listener | ||
})); | ||
} | ||
}); | ||
targetDomEvents.forEach((domEvent) => { | ||
const sourceEventMap = sourceEventMaps[domEvent]; | ||
const targetEventMap = targetEventMaps[domEvent]; | ||
if (!sourceEventMap) { | ||
instructions.push(addEvent(source, target, { | ||
name: targetEventMap.domEvent, | ||
value: targetEventMap.listener | ||
})); | ||
} | ||
}); | ||
return instructions; | ||
}; | ||
// src/rendering/change/instructions/element.ts | ||
var compileForElement = (source, target) => { | ||
const attributeInstructions = compileForAttributes(source, target); | ||
const eventInstructions = compileForEvents(source, target); | ||
const valueInstructions = compileForInputValue(source, target); | ||
return attributeInstructions.concat(eventInstructions).concat(valueInstructions); | ||
}; | ||
var compileForSvg = (source, target) => { | ||
return compileForAttributes(source, target, true); | ||
}; | ||
var compileForInputValue = (sourceElement, targetElement) => { | ||
const instructions = []; | ||
if (sourceElement.tagName !== "INPUT") { | ||
return instructions; | ||
return n; | ||
}, Rt = (e, t) => { | ||
const s = [], n = e.eventMaps, r = t.eventMaps, o = Object.keys(n), a = Object.keys(r); | ||
return o.forEach((h) => { | ||
const i = n[h], d = r[h]; | ||
d ? d.busEvent !== i.busEvent && s.push( | ||
Ut(e, t, { | ||
name: h, | ||
targetValue: d.listener, | ||
sourceValue: i.listener | ||
}) | ||
) : s.push( | ||
Lt(e, t, { | ||
name: i.domEvent, | ||
value: i.listener | ||
}) | ||
); | ||
}), a.forEach((h) => { | ||
const i = n[h], d = r[h]; | ||
i || s.push( | ||
Pt(e, t, { | ||
name: d.domEvent, | ||
value: d.listener | ||
}) | ||
); | ||
}), s; | ||
}, Jt = (e) => e.tagName !== "INPUT", qt = (e, t) => e.value === t.value, Ht = (e, t) => { | ||
if (Jt(e) || qt(e, t)) | ||
return []; | ||
const s = e, n = t; | ||
return [Bt(s, n, { name: "value", value: n.value })]; | ||
}, It = (e, t) => { | ||
const s = Y(e, t), n = Rt(e, t), r = Ht(e, t); | ||
return s.concat(n).concat(r); | ||
}, Qt = (e, t) => Y(e, t, !0), Wt = (e, t) => e.textContent !== t.textContent ? [Mt(e, t)] : [], Gt = (e, t, s) => { | ||
let n = []; | ||
if (e.nodeType === 1 && it(e)) { | ||
const r = e, o = t, a = Qt(r, o), h = s( | ||
r.childNodes, | ||
o.childNodes, | ||
r | ||
); | ||
n = a.concat(h); | ||
} else if (e.nodeType === 1) { | ||
const r = e, o = t, a = It(r, o), h = s( | ||
r.childNodes, | ||
o.childNodes, | ||
r | ||
); | ||
n = a.concat(h); | ||
} else e.nodeType === 3 && (n = Wt(e, t)); | ||
return n; | ||
}, Z = (e, t, s) => { | ||
const n = [], r = Xt(e, t), o = w(e), a = w(t), h = []; | ||
let i = 0; | ||
for (; i < r; i++) { | ||
const u = e[i], l = t[i]; | ||
if (l && a.check(l)) { | ||
const p = o.pullMatch(l); | ||
a.clear(l), p.element ? (p.index !== i && n.push( | ||
v(p.element, { | ||
parent: s, | ||
index: i | ||
}) | ||
), h.push({ | ||
source: p.element, | ||
target: l | ||
})) : u ? a.check(u) ? n.push( | ||
v(l, { parent: s, index: i }) | ||
) : (o.clear(u), n.push( | ||
Ft(u, l) | ||
)) : n.push( | ||
v(l, { parent: s, index: i }) | ||
); | ||
} else u && o.pullMatch(u).element && n.push(S(u)); | ||
} | ||
const source = sourceElement; | ||
const target = targetElement; | ||
if (source.value !== target.value) { | ||
instructions.push(changeValue(source, target, { name: "value", value: target.value })); | ||
} | ||
return instructions; | ||
}; | ||
// src/rendering/change/instructions/text.ts | ||
var compileForText = (source, target) => { | ||
if (source.textContent !== target.textContent) { | ||
return [changeText(source, target)]; | ||
} | ||
return []; | ||
}; | ||
// src/rendering/change/instructions/node.ts | ||
var NodeTypes; | ||
(function(NodeTypes2) { | ||
NodeTypes2[NodeTypes2["ElementNode"] = 1] = "ElementNode"; | ||
NodeTypes2[NodeTypes2["TextNode"] = 3] = "TextNode"; | ||
})(NodeTypes || (NodeTypes = {})); | ||
var compileForNodeGenerator = (compileForCollection) => (source, target) => { | ||
let instructions = []; | ||
if (source.nodeType === NodeTypes.ElementNode && isSvg(source)) { | ||
const sourceElement = source; | ||
const targetElement = target; | ||
const baseInstructions = compileForSvg(sourceElement, targetElement); | ||
const childrenInstructions = compileForCollection(sourceElement.childNodes, targetElement.childNodes, sourceElement); | ||
instructions = baseInstructions.concat(childrenInstructions); | ||
} else if (source.nodeType === NodeTypes.ElementNode) { | ||
const sourceElement = source; | ||
const targetElement = target; | ||
const baseInstructions = compileForElement(sourceElement, targetElement); | ||
const childrenInstructions = compileForCollection(sourceElement.childNodes, targetElement.childNodes, sourceElement); | ||
instructions = baseInstructions.concat(childrenInstructions); | ||
} else if (source.nodeType === NodeTypes.TextNode) { | ||
instructions = compileForText(source, target); | ||
} | ||
return instructions; | ||
}; | ||
// src/rendering/change/instructions/children.ts | ||
var compileChildren = (sourceList, targetList, parent) => { | ||
const baseInstructions = []; | ||
const length = largerLength(sourceList, targetList); | ||
const sourceMap = createIdMap(sourceList); | ||
const targetMap = createIdMap(targetList); | ||
const nodesPairsToDiff = []; | ||
let index = 0; | ||
for (;index < length; index++) { | ||
const source = sourceList[index]; | ||
const target = targetList[index]; | ||
if (target && targetMap.check(target)) { | ||
const matchingSource = sourceMap.pullMatch(target); | ||
targetMap.clear(target); | ||
if (matchingSource.element) { | ||
if (matchingSource.index !== index) { | ||
baseInstructions.push(insertNode(matchingSource.element, { parent, index })); | ||
} | ||
nodesPairsToDiff.push({ | ||
source: matchingSource.element, | ||
target | ||
}); | ||
} else if (source) { | ||
if (targetMap.check(source)) { | ||
baseInstructions.push(insertNode(target, { parent, index })); | ||
} else { | ||
sourceMap.clear(source); | ||
baseInstructions.push(replaceNode(source, target)); | ||
} | ||
} else { | ||
baseInstructions.push(insertNode(target, { parent, index })); | ||
} | ||
} else if (source) { | ||
const matchingSource = sourceMap.pullMatch(source); | ||
if (matchingSource.element) { | ||
baseInstructions.push(removeNode(source)); | ||
} | ||
} | ||
} | ||
sourceMap.remaining().forEach(({ element: element2 }) => { | ||
baseInstructions.push(removeNode(element2)); | ||
o.remaining().forEach(({ element: u }) => { | ||
n.push(S(u)); | ||
}); | ||
const nodeInstructions = nodesPairsToDiff.reduce((collection, { source, target }) => { | ||
return collection.concat(compileForNode(source, target)); | ||
}, []); | ||
return baseInstructions.concat(nodeInstructions).sort(instructionsSorter); | ||
}; | ||
var instructionsSorter = (left, right) => { | ||
if (left.type > right.type) | ||
return 1; | ||
if (left.type < right.type) | ||
return -1; | ||
return 0; | ||
}; | ||
var largerLength = (sourceList, targetList) => { | ||
const sourceLength = Array.from(sourceList).length; | ||
const targetLength = Array.from(targetList).length; | ||
return sourceLength > targetLength ? sourceLength : targetLength; | ||
}; | ||
var compileForNode = compileForNodeGenerator(compileChildren); | ||
// src/rendering/change.ts | ||
var change = (source, target, parent) => { | ||
const instructions = compileChildren(source, target, parent); | ||
instructions.forEach((instruction) => { | ||
performInstruction(instruction); | ||
const d = h.reduce( | ||
(u, { source: l, target: p }) => u.concat( | ||
Gt(l, p, Z) | ||
), | ||
[] | ||
); | ||
return n.concat(d).sort(Kt); | ||
}, Xt = (e, t) => { | ||
const s = e.length, n = t.length; | ||
return s > n ? s : n; | ||
}, Yt = (e, t, s) => { | ||
Z(e, t, s).forEach((r) => { | ||
Zt(r); | ||
}); | ||
}, Zt = (e) => { | ||
(he[e.type] || Ct)(e); | ||
}, Ct = (e) => { | ||
}, te = (e) => { | ||
const { source: t, target: s } = e; | ||
t.nodeValue = s.textContent; | ||
}, ee = (e) => { | ||
const { source: t } = e; | ||
t.remove(); | ||
}, se = (e) => { | ||
const { target: t, data: s } = e, { parent: n, index: r } = s, o = n.childNodes[r]; | ||
o ? o && o !== t && n.insertBefore(t, o) : n.appendChild(t); | ||
}, ne = (e) => { | ||
const { source: t, target: s } = e; | ||
t.replaceWith(s); | ||
}, re = (e) => { | ||
const { source: t, data: s } = e, { name: n, isSvg: r } = s; | ||
r ? t.removeAttributeNS(null, n) : t.removeAttribute(n); | ||
}, C = (e) => { | ||
const { source: t, data: s } = e, { name: n, value: r, isSvg: o } = s; | ||
o ? t.setAttributeNS(null, n, r) : t.setAttribute(n, r); | ||
}, oe = (e) => { | ||
C(e); | ||
}, ie = (e) => { | ||
const t = e.data, s = e.source, { name: n, value: r } = t; | ||
s.removeEventListener(n, r); | ||
}, ae = (e) => { | ||
const t = e.data, s = e.source, { name: n, value: r } = t; | ||
s.addEventListener(n, r); | ||
}, ce = (e) => { | ||
const t = e.data, s = e.source, { name: n, sourceValue: r, targetValue: o } = t; | ||
s.removeEventListener(n, r), s.addEventListener(n, o); | ||
}, ue = (e) => { | ||
const t = e.data, s = e.source, { value: n } = t; | ||
s.value = n; | ||
}, he = { | ||
[c.changeText]: te, | ||
[c.removeNode]: ee, | ||
[c.insertNode]: se, | ||
[c.replaceNode]: ne, | ||
[c.removeAttribute]: re, | ||
[c.addAttribute]: C, | ||
[c.updateAttribute]: oe, | ||
[c.removeEvent]: ie, | ||
[c.addEvent]: ae, | ||
[c.updateEvent]: ce, | ||
[c.changeValue]: ue | ||
}; | ||
var performInstruction = (instruction) => { | ||
const performer = performers[instruction.type] || noop; | ||
performer(instruction); | ||
}; | ||
var noop = (_instruction) => { | ||
}; | ||
var changeText2 = (instruction) => { | ||
const { source, target } = instruction; | ||
source.nodeValue = target.textContent; | ||
}; | ||
var removeNode2 = (instruction) => { | ||
const { source } = instruction; | ||
source.remove(); | ||
}; | ||
var insertNode2 = (instruction) => { | ||
const { target, data } = instruction; | ||
const { parent, index } = data; | ||
const sibling = parent.childNodes[index]; | ||
if (!sibling) { | ||
parent.appendChild(target); | ||
} else if (sibling && sibling !== target) { | ||
parent.insertBefore(target, sibling); | ||
class le { | ||
constructor({ Template: t, subscriptions: s, attributes: n, viewModel: r }) { | ||
this.Template = t, this.viewModel = r, this.attributes = n, this.subscriptions = s, this.dom = [], this.parentElement = null; | ||
} | ||
}; | ||
var replaceNode2 = (instruction) => { | ||
const { source, target } = instruction; | ||
source.replaceWith(target); | ||
}; | ||
var removeAttribute2 = (instruction) => { | ||
const { source, data } = instruction; | ||
const { name, isSvg: isSvg2 } = data; | ||
if (isSvg2) { | ||
source.removeAttributeNS(null, name); | ||
} else { | ||
source.removeAttribute(name); | ||
render(t) { | ||
return this.parentElement = t.parent, this.renderKit = t, this.subscribeForRerender(), this.dom = this.generateDom(t), this.dom; | ||
} | ||
}; | ||
var addAttribute2 = (instruction) => { | ||
const { source, data } = instruction; | ||
const { name, value, isSvg: isSvg2 } = data; | ||
if (isSvg2) { | ||
source.setAttributeNS(null, name, value); | ||
} else { | ||
source.setAttribute(name, value); | ||
} | ||
}; | ||
var updateAttribute2 = (instruction) => { | ||
addAttribute2(instruction); | ||
}; | ||
var removeEvent2 = (instruction) => { | ||
const data = instruction.data; | ||
const source = instruction.source; | ||
const { name, value } = data; | ||
source.removeEventListener(name, value); | ||
}; | ||
var addEvent2 = (instruction) => { | ||
const data = instruction.data; | ||
const source = instruction.source; | ||
const { name, value } = data; | ||
source.addEventListener(name, value); | ||
}; | ||
var updateEvent2 = (instruction) => { | ||
const data = instruction.data; | ||
const source = instruction.source; | ||
const { name, sourceValue, targetValue } = data; | ||
source.removeEventListener(name, sourceValue); | ||
source.addEventListener(name, targetValue); | ||
}; | ||
var changeValue2 = (instruction) => { | ||
const data = instruction.data; | ||
const source = instruction.source; | ||
const { value } = data; | ||
source.value = value; | ||
}; | ||
var performers = { | ||
[ChangeInstructions.changeText]: changeText2, | ||
[ChangeInstructions.removeNode]: removeNode2, | ||
[ChangeInstructions.insertNode]: insertNode2, | ||
[ChangeInstructions.replaceNode]: replaceNode2, | ||
[ChangeInstructions.removeAttribute]: removeAttribute2, | ||
[ChangeInstructions.addAttribute]: addAttribute2, | ||
[ChangeInstructions.updateAttribute]: updateAttribute2, | ||
[ChangeInstructions.removeEvent]: removeEvent2, | ||
[ChangeInstructions.addEvent]: addEvent2, | ||
[ChangeInstructions.updateEvent]: updateEvent2, | ||
[ChangeInstructions.changeValue]: changeValue2 | ||
}; | ||
// src/rendering/templates/bound.js | ||
var passThroughViewModel = (state2) => state2; | ||
class Bound { | ||
constructor(TemplateClass, viewModel, subscriptions, attributes2) { | ||
this.TemplateClass = TemplateClass; | ||
this.viewModel = viewModel || passThroughViewModel; | ||
this.attributes = attributes2 || {}; | ||
this.subscriptions = subscriptions; | ||
this.dom = []; | ||
} | ||
render(renderKit) { | ||
this.parentElement = renderKit.parent; | ||
this.renderKit = renderKit; | ||
this.subscribeForRerender(); | ||
this.dom = this._render(renderKit); | ||
return this.dom; | ||
} | ||
_render(renderKit) { | ||
const props = { | ||
generateDom(t) { | ||
const s = { | ||
...this.attributes, | ||
...this.viewModel(renderKit.state.value()) | ||
}; | ||
const template = this.TemplateClass(props); | ||
const dom = !template ? [] : template.render(renderKit); | ||
return dom; | ||
...this.viewModel( | ||
t.state.getAll(this.subscriptions) | ||
) | ||
}, n = this.Template(s); | ||
return n ? n.render(t) : []; | ||
} | ||
rerender() { | ||
if (!this.parentElement) { | ||
this.parentElement = this.dom[0] && this.dom[0].parentElement; | ||
if (!this.parentElement && this.dom[0]) { | ||
const s = this.dom[0].parentElement; | ||
this.parentElement = s; | ||
} | ||
const newDom = this._render(this.renderKit); | ||
change(this.dom, newDom, this.parentElement); | ||
if (this.parentElement) { | ||
this.dom = Array.from(this.parentElement.childNodes); | ||
} | ||
const t = this.generateDom(this.renderKit); | ||
Yt(this.dom, t, this.parentElement), this.parentElement && (this.dom = Array.from(this.parentElement.childNodes)); | ||
} | ||
subscribeForRerender() { | ||
this.subscriptions.forEach((storeName) => { | ||
this.renderKit.subscribe(eventName(storeName), () => this.rerender()); | ||
const { subscribe: t } = this.renderKit; | ||
this.subscriptions.forEach((s) => { | ||
t(this.eventName(s), () => this.rerender()); | ||
}); | ||
} | ||
} | ||
var bind = ({ Template, viewModel, subscriptions }) => { | ||
subscriptions = subscriptions || []; | ||
return (attributes2) => new Bound(Template, viewModel, subscriptions, attributes2); | ||
}; | ||
// src/messageBus.ts | ||
class MessageBus { | ||
listeners; | ||
options; | ||
constructor() { | ||
this.options = {}; | ||
this.listeners = {}; | ||
eventName(t) { | ||
return `${A}:${t}`; | ||
} | ||
subscribe(eventName2, listener) { | ||
this.ensureListenerCollection(eventName2); | ||
this.listeners[eventName2].push(listener); | ||
} | ||
publish(eventName2, payload) { | ||
const listeners = this.listeners[eventName2]; | ||
if (!listeners) | ||
return false; | ||
listeners.forEach((listener) => { | ||
listener(payload, this.buildListenerKit(eventName2)); | ||
}); | ||
return true; | ||
} | ||
ensureListenerCollection(eventName2) { | ||
if (this.listeners[eventName2]) | ||
return; | ||
this.listeners[eventName2] = []; | ||
} | ||
buildListenerKit(eventName2) { | ||
return { | ||
eventName: eventName2, | ||
publish: this.publish.bind(this), | ||
...this.options | ||
}; | ||
} | ||
addListenerOptions(options) { | ||
this.options = { | ||
...this.options, | ||
...options | ||
}; | ||
} | ||
} | ||
var createBus = () => { | ||
const bus = new MessageBus; | ||
const publish = bus.publish.bind(bus); | ||
const subscribe = bus.subscribe.bind(bus); | ||
return { | ||
bus, | ||
publish, | ||
subscribe | ||
}; | ||
}; | ||
// src/navigation/routeState.js | ||
var createRouteState = (state2) => { | ||
const store = new RecordStore({ | ||
name: "route", | ||
value: { | ||
host: "", | ||
path: "", | ||
query: "" | ||
}, | ||
parent: state2 | ||
}); | ||
state2.add(store); | ||
}; | ||
// src/navigation/setupHistory.js | ||
var locationChangeEvent = "locationChange"; | ||
var routeChangeEvent = "routeChange"; | ||
var extractQueryParams = (queryString) => { | ||
return queryString.replace(/^\?/, "").split("&").reduce((aggregate, pairString) => { | ||
if (!pairString) | ||
return aggregate; | ||
const pair = pairString.split("="); | ||
aggregate[pair[0]] = pair[1]; | ||
return aggregate; | ||
}, {}); | ||
}; | ||
var onLocationChange = (_payload, { publish, state: state2, window }) => { | ||
const { host, pathname, search } = window.location; | ||
const path = pathname; | ||
const query = extractQueryParams(search); | ||
state2.route.update({ | ||
host, | ||
path, | ||
query | ||
}); | ||
publish(routeChangeEvent, { host, path, query }); | ||
}; | ||
var setupHistory = (app) => { | ||
const { publish, subscribe, state: state2, window } = app; | ||
createRouteState(state2); | ||
window.addEventListener("popstate", () => publish(locationChangeEvent)); | ||
subscribe(locationChangeEvent, onLocationChange); | ||
}; | ||
// src/navigation/findHref.js | ||
var findHref = (node2) => { | ||
if (!node2 || !node2.getAttribute) | ||
return ""; | ||
while (!node2.getAttribute("href")) { | ||
node2 = node2.parentNode; | ||
if (!node2 || !node2.getAttribute) | ||
return ""; | ||
} | ||
return node2.getAttribute("href"); | ||
}; | ||
// src/navigation/setupNavigation.js | ||
var linkNavigationEvent = "goToHref"; | ||
var programmaticNavigationEvent = "navigate"; | ||
var navigate = (path, { publish, window }) => { | ||
window.history.pushState(null, "", path); | ||
publish(locationChangeEvent); | ||
}; | ||
var onLinkClick = (domEvent, { publish, window }) => { | ||
if (!domEvent || !domEvent.target) | ||
return; | ||
domEvent.preventDefault(); | ||
const href = findHref(domEvent.target); | ||
navigate(href, { publish, window }); | ||
}; | ||
var setupNavigation = (app) => { | ||
const { subscribe } = app; | ||
subscribe(linkNavigationEvent, onLinkClick); | ||
subscribe(programmaticNavigationEvent, navigate); | ||
}; | ||
// src/app.ts | ||
var setupBus = (app) => { | ||
const { publish, subscribe, bus } = createBus(); | ||
app.publish = publish; | ||
app.subscribe = subscribe; | ||
app.bus = bus; | ||
}; | ||
var setupState = (app) => { | ||
const state3 = new State(app.publish); | ||
app.state = state3; | ||
}; | ||
var connectBusToState = (app) => { | ||
const { bus } = app; | ||
bus.addListenerOptions({ | ||
state: app.state, | ||
document: app.document, | ||
window: app.window | ||
}); | ||
}; | ||
var setupRenderKit = (app) => { | ||
app.renderKit = { | ||
publish: app.publish, | ||
subscribe: app.subscribe, | ||
state: app.state, | ||
document: app.document, | ||
window: app.window | ||
}; | ||
}; | ||
var triggerRoute = (app) => { | ||
const publish = app.publish; | ||
setTimeout(() => { | ||
publish(locationChangeEvent, null); | ||
}, 0); | ||
}; | ||
var addRender = (app) => { | ||
app.render = (template, selector) => { | ||
return render(template, selector, app.renderKit); | ||
}; | ||
}; | ||
var setupDomEnvironment = (app, domEnvironment) => { | ||
const { window, document } = domEnvironment; | ||
if (window) { | ||
app.window = window; | ||
app.document = window.document; | ||
} else if (document) { | ||
app.window = document.defaultView; | ||
app.document = document; | ||
} else { | ||
app.window = window; | ||
app.document = window?.document; | ||
} | ||
}; | ||
var createApp = (domEnvironment) => { | ||
const app = {}; | ||
setupDomEnvironment(app, domEnvironment || {}); | ||
setupBus(app); | ||
setupState(app); | ||
connectBusToState(app); | ||
setupRenderKit(app); | ||
setupHistory(app); | ||
setupNavigation(app); | ||
triggerRoute(app); | ||
addRender(app); | ||
return app; | ||
}; | ||
// src/navigation.ts | ||
var exports_navigation = {}; | ||
__export(exports_navigation, { | ||
setupNavigation: () => { | ||
{ | ||
return setupNavigation; | ||
} | ||
}, | ||
setupHistory: () => { | ||
{ | ||
return setupHistory; | ||
} | ||
} | ||
}); | ||
const de = (e) => e, ge = ({ | ||
Template: e, | ||
viewModel: t, | ||
subscriptions: s | ||
}) => (s = s || [], t = t || de, (n) => new le({ Template: e, viewModel: t, subscriptions: s, attributes: n })), ye = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProperty({ | ||
__proto__: null, | ||
createRouteState: F, | ||
events: _t, | ||
extractQueryParams: L, | ||
findHref: T, | ||
navigate: D, | ||
onLinkClick: z, | ||
onLocationChange: P, | ||
start: wt | ||
}, Symbol.toStringTag, { value: "Module" })); | ||
export { | ||
render, | ||
exports_navigation as navigation, | ||
jsx_default as jsx, | ||
createBus, | ||
createApp, | ||
bind, | ||
State | ||
ve as JaxsTypes, | ||
pe as appBuilding, | ||
ge as bind, | ||
fe as createApp, | ||
xt as jsx, | ||
me as messageBus, | ||
ye as navigation, | ||
be as state | ||
}; |
{ | ||
"name": "jaxs", | ||
"version": "0.3.2", | ||
"description": "Modular J/TSX application framework", | ||
"module": "src/jaxs.ts", | ||
"exports": { | ||
".": "./dist/jaxs.js", | ||
"./views": "./src/views.js" | ||
}, | ||
"private": false, | ||
"version": "0.4.0", | ||
"type": "module", | ||
"devDependencies": { | ||
"@types/bun": "latest", | ||
"@types/jsdom": "^21.1.6", | ||
"concurrently": "^8.2.2", | ||
"cypress": "^13.6.2", | ||
"jsdom": "^23.2.0", | ||
"npm": "^10.3.0", | ||
"parcel": "^2.11.0", | ||
"standard": "^17.1.0" | ||
}, | ||
"peerDependencies": { | ||
"typescript": "^5.0.0" | ||
}, | ||
"scripts": { | ||
"lint": "standard --fix", | ||
"build": "bun run bundle.ts", | ||
"serve": "bun run build && parcel serve --dist-dir=cypress/jaxs-apps/dist", | ||
"integration": "concurrently \"npm run serve\" \"npx cypress open\"", | ||
"integration:ci": "concurrently \"npm run serve\" \"npx cypress run\"" | ||
"build": "vite build && npm run build:types", | ||
"build:types": "tsc --declaration --emitDeclarationOnly lib/jaxs.ts --outfile dist/jaxs.d.ts", | ||
"test": "npm run lint; vitest run", | ||
"e2e:server": "vite dev --config ./cypress/apps/vite.config.js", | ||
"e2e": "cypress open", | ||
"e2e:ci": "cypress run", | ||
"lint": "prettier . --write" | ||
}, | ||
"targets": { | ||
"html": { | ||
"source": [ | ||
"./cypress/jaxs-apps/add-remove-root-children.html", | ||
"./cypress/jaxs-apps/add-remove-nested-children.html", | ||
"./cypress/jaxs-apps/svg.html" | ||
] | ||
"files": [ | ||
"dist" | ||
], | ||
"main": "./dist/jaxs.umd.cjs", | ||
"module": "./dist/jaxs.js", | ||
"exports": { | ||
".": { | ||
"import": "./dist/jaxs.js", | ||
"require": "./dist/jaxs.umd.cjs" | ||
} | ||
}, | ||
"standard": { | ||
"globals": [ "cy", "describe", "it", "beforeEach" ] | ||
"directories": { | ||
"lib": "lib" | ||
}, | ||
"repository": { | ||
"type": "git", | ||
"url": "git+https://github.com/baccigalupi/jaxs.git" | ||
}, | ||
"keywords": [ | ||
"client-side rendering", | ||
"JSX", | ||
"TSX" | ||
], | ||
"author": "Kane Baccigalupi", | ||
"license": "MIT", | ||
"devDependencies": { | ||
"@types/jsdom": "^21.1.7", | ||
"cypress": "^13.14.2", | ||
"jsdom": "^24.1.1", | ||
"prettier": "^3.3.3", | ||
"typescript": "^5.5.4", | ||
"vite": "^5.4.1", | ||
"vitest": "^2.0.5" | ||
} | ||
} | ||
} |
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
Found 1 instance in 1 package
No README
QualityPackage does not have a README. This may indicate a failed publish or a low quality package.
Found 1 instance in 1 package
Uses eval
Supply chain riskPackage uses dynamic code execution (e.g., eval()), which is a dangerous practice. This can prevent the code from running in certain environments and increases the risk that the code may contain exploits or malicious behavior.
Found 1 instance in 1 package
No contributors or author data
MaintenancePackage does not specify a list of contributors or an author in package.json.
Found 1 instance in 1 package
No License Found
License(Experimental) License information could not be found.
Found 1 instance in 1 package
No repository
Supply chain riskPackage does not have a linked source code repository. Without this field, a package will have no reference to the location of the source code use to generate the package.
Found 1 instance in 1 package
0
7
0
1
0
1
70877
4
1582
2
0