juris
Version:
JavaScript Unified Reactive Interface Solution - Transforms web development through comprehensive object-first architecture that makes reactivity an intentional choice rather than automatic behavior
1 lines • 45.5 kB
JavaScript
!function () { "use strict"; function e(e) { return "string" == typeof e && e.trim().length > 0 && !e.includes("..") } function t(e) { return e.split(".").filter(Boolean) } function n(e, t) { if (e === t) return !0; if (null == e || null == t) return !1; if (typeof e != typeof t) return !1; if ("object" == typeof e) { if (Array.isArray(e) !== Array.isArray(t)) return !1; const s = Object.keys(e), r = Object.keys(t); if (s.length !== r.length) return !1; for (let i of s) if (!r.includes(i) || !n(e[i], t[i])) return !1; return !0 } return !1 } class s { constructor(e = {}, t = []) { this.state = { ...e }, this.middleware = [...t], this.subscribers = new Map, this.externalSubscribers = new Map, this.currentTracking = null, this.isUpdating = !1, this.updateQueue = [], this.batchTimeout = null, this.batchUpdateInProgress = !1, this.maxBatchSize = 50, this.batchDelayMs = 0, this.batchingEnabled = !0, this.initialState = JSON.parse(JSON.stringify(e)) } reset(e = []) { const t = {}; e.forEach((e => { const n = this.getState(e); null !== n && (t[e] = n) })), this.state = {}, Object.entries(this.initialState).forEach((([e, t]) => { this.setState(e, JSON.parse(JSON.stringify(t))) })), Object.entries(t).forEach((([e, t]) => { this.setState(e, t) })) } getState(n, s = null) { if (!e(n)) return console.warn("Invalid state path:", n), s; this.currentTracking && this.currentTracking.add(n); const r = t(n); let i = this.state; for (const e of r) { if (null == i || void 0 === i[e]) return s; i = i[e] } return i } setState(t, n, s = {}) { e(t) ? this._hasCircularUpdate(t) || (this.batchingEnabled && this.batchDelayMs > 0 ? this._queueUpdate(t, n, s) : this._setStateImmediate(t, n, s)) : console.warn("Invalid state path:", t) } _setStateImmediate(e, s, r = {}) { const i = this.getState(e); let a = s; for (const t of this.middleware) try { const n = t({ path: e, oldValue: i, newValue: a, context: r, state: this.state }); void 0 !== n && (a = n) } catch (e) { console.error("Middleware error:", e) } if (n(i, a)) return; const o = t(e); let c = this.state; for (let e = 0; e < o.length - 1; e++) { const t = o[e]; null != c[t] && "object" == typeof c[t] || (c[t] = {}), c = c[t] } c[o[o.length - 1]] = a, this.isUpdating || (this.isUpdating = !0, this.currentlyUpdating || (this.currentlyUpdating = new Set), this.currentlyUpdating.add(e), this._notifySubscribers(e, a, i), this._notifyExternalSubscribers(e, a, i), this.currentlyUpdating.delete(e), this.isUpdating = !1) } _processBatchedUpdates() { if (this.batchUpdateInProgress || 0 === this.updateQueue.length) return; this.batchUpdateInProgress = !0, this.batchTimeout && (clearTimeout(this.batchTimeout), this.batchTimeout = null); const e = Math.min(this.maxBatchSize, this.updateQueue.length), t = this.updateQueue.splice(0, e); try { const e = new Map; t.forEach((t => { e.set(t.path, t) })); const n = new Set; e.forEach((e => { this._setStateImmediate(e.path, e.value, e.context), n.add(e.path) })), console.log(`Batched ${t.length} updates into ${e.size} unique state changes`) } catch (e) { console.error("Error processing batched updates:", e) } finally { this.batchUpdateInProgress = !1, this.updateQueue.length > 0 && setTimeout((() => this._processBatchedUpdates()), 0) } } configureBatching(e = {}) { this.maxBatchSize = e.maxBatchSize || this.maxBatchSize, this.batchDelayMs = void 0 !== e.batchDelayMs ? e.batchDelayMs : this.batchDelayMs, void 0 !== e.enabled && (this.batchingEnabled = e.enabled), console.log(`Batching configured: enabled=${this.batchingEnabled}, delay=${this.batchDelayMs}ms, maxSize=${this.maxBatchSize}`) } getBatchStatus() { return { enabled: this.batchingEnabled, queueLength: this.updateQueue.length, inProgress: this.batchUpdateInProgress, hasTimeout: !!this.batchTimeout, delayMs: this.batchDelayMs, maxBatchSize: this.maxBatchSize } } _queueUpdate(e, t, n) { if (this.updateQueue.push({ path: e, value: t, context: n, timestamp: Date.now() }), this.updateQueue.length > 2 * this.maxBatchSize) return console.warn("Update queue is getting large, processing immediately"), void this._processBatchedUpdates(); this.batchTimeout || (this.batchTimeout = setTimeout((() => { this._processBatchedUpdates() }), this.batchDelayMs)) } subscribe(e, t, n = !0) { this.externalSubscribers.has(e) || this.externalSubscribers.set(e, new Set); const s = { callback: t, hierarchical: n }; return this.externalSubscribers.get(e).add(s), () => { const t = this.externalSubscribers.get(e); t && (t.delete(s), 0 === t.size && this.externalSubscribers.delete(e)) } } subscribeExact(e, t) { return this.subscribe(e, t, !1) } subscribeInternal(e, t) { return this.subscribers.has(e) || this.subscribers.set(e, new Set), this.subscribers.get(e).add(t), () => { const n = this.subscribers.get(e); n && (n.delete(t), 0 === n.size && this.subscribers.delete(e)) } } _notifySubscribers(e, n, s) { this._triggerPathSubscribers(e); const r = t(e); for (let e = r.length - 1; e > 0; e--) { const t = r.slice(0, e).join("."); this._triggerPathSubscribers(t) } const i = e ? e + "." : ""; new Set([...this.subscribers.keys(), ...this.externalSubscribers.keys()]).forEach((t => { t.startsWith(i) && t !== e && this._triggerPathSubscribers(t) })) } _notifyExternalSubscribers(e, t, n) { this.externalSubscribers.forEach(((s, r) => { s.forEach((s => { const { callback: i, hierarchical: a } = s; let o = !1; if (a ? (e === r || e.startsWith(r + ".")) && (o = !0) : e === r && (o = !0), o) try { i(t, n, e) } catch (e) { console.error("External subscriber error:", e) } })) })) } _triggerPathSubscribers(e) { const t = this.subscribers.get(e); if (t) { new Set(t).forEach((e => { try { const t = this.currentTracking, n = new Set; this.currentTracking = n, e(), this.currentTracking = t, n.forEach((t => { const n = this.subscribers.get(t); n && n.has(e) || this.subscribeInternal(t, e) })) } catch (e) { console.error("Subscriber error:", e), this.currentTracking = oldTracking } })) } } _hasCircularUpdate(e) { return this.currentlyUpdating || (this.currentlyUpdating = new Set), !!this.currentlyUpdating.has(e) && (console.warn(`Circular dependency detected for path: ${e}`), !0) } startTracking() { const e = new Set; return this.currentTracking = e, e } endTracking() { const e = this.currentTracking; return this.currentTracking = null, e || new Set } } class r { constructor(e) { this.juris = e, this.components = new Map, this.instances = new Map, this.context = {}, this.initQueue = new Set, this.lifecycleHooks = new Map } register(e, t, n = {}) { this.components.set(e, { fn: t, options: n }), n.autoInit && this.initQueue.add(e) } initialize(e, t = {}) { const n = this.components.get(e); if (!n) return console.warn(`Headless component '${e}' not found`), null; try { const s = this.juris.createHeadlessContext(), r = n.fn(t, s); if (!r || "object" != typeof r) return console.warn(`Headless component '${e}' must return an object`), null; if (this.instances.set(e, r), r.hooks && this.lifecycleHooks.set(e, r.hooks), r.api && (this.context[e] = r.api, this.juris.headlessAPIs || (this.juris.headlessAPIs = {}), this.juris.headlessAPIs[e] = r.api, this.juris._updateComponentContexts()), r.hooks?.onRegister) try { r.hooks.onRegister() } catch (t) { console.error(`Error in onRegister for headless component '${e}':`, t) } return r } catch (t) { return console.error(`Error initializing headless component '${e}':`, t), null } } initializeQueued() { this.initQueue.forEach((e => { if (!this.instances.has(e)) { const t = this.components.get(e); this.initialize(e, t.options || {}) } })), this.initQueue.clear() } getInstance(e) { return this.instances.get(e) } getAPI(e) { return this.context[e] } getAllAPIs() { return { ...this.context } } reinitialize(e, t = {}) { if (this.instances.has(e)) { const t = this.instances.get(e); if (t.hooks?.onUnregister) try { t.hooks.onUnregister() } catch (t) { console.error(`Error in onUnregister for '${e}':`, t) } } return this.context[e] && delete this.context[e], this.juris.headlessAPIs?.[e] && delete this.juris.headlessAPIs[e], this.instances.delete(e), this.lifecycleHooks.delete(e), this.initialize(e, t) } cleanup() { this.instances.forEach(((e, t) => { if (e.hooks?.onUnregister) try { e.hooks.onUnregister() } catch (e) { console.error(`Error in onUnregister for '${t}':`, e) } })), this.instances.clear(), this.context = {}, this.lifecycleHooks.clear(), this.juris.headlessAPIs && (this.juris.headlessAPIs = {}) } getStatus() { return { registered: Array.from(this.components.keys()), initialized: Array.from(this.instances.keys()), queued: Array.from(this.initQueue), apis: Object.keys(this.context) } } } class i { constructor(e) { this.juris = e, this.components = new Map, this.instances = new WeakMap, this.componentCounters = new Map, this.componentStates = new WeakMap } register(e, t) { this.components.set(e, t) } create(e, t = {}) { const n = this.components.get(e); if (!n) return console.error(`Component '${e}' not found`), null; try { this.componentCounters.has(e) || this.componentCounters.set(e, 0); const s = this.componentCounters.get(e) + 1; this.componentCounters.set(e, s); const r = `${e}_${s}`, i = new Set, a = this.juris.createContext(); a.newState = (e, t) => { const n = `__local.${r}.${e}`; this.juris.stateManager.getState(n, Symbol("not-found")) === Symbol("not-found") && this.juris.stateManager.setState(n, t), i.add(n); return [() => this.juris.stateManager.getState(n, t), e => this.juris.stateManager.setState(n, e)] }; const o = n(t, a); if (o && "object" == typeof o) { if (o.onMount || o.onUpdate || o.onUnmount || "function" == typeof o.render && (void 0 !== o.onMount || void 0 !== o.onUpdate || void 0 !== o.onUnmount)) return this._createLifecycleComponent(o, e, t, i); if ("function" == typeof o.render && !o.onMount && !o.onUpdate && !o.onUnmount) { const t = o.render(); console.log(`Render function for '${e}' returned:`, t); const n = this.juris.domRenderer.render(t); return n && i.size > 0 && this.componentStates.set(n, i), n } const n = Object.keys(o); if (1 === n.length) { const e = n[0]; if ("string" == typeof e && e.length > 0) { const e = this.juris.domRenderer.render(o); return e && i.size > 0 && this.componentStates.set(e, i), e } } } console.warn(`Component '${e}' returned unexpected structure, attempting to render:`, o); const c = this.juris.domRenderer.render(o); return c && i.size > 0 && this.componentStates.set(c, i), c } catch (t) { return console.error(`Error creating component '${e}':`, t), this._createErrorElement(t) } } _isVDOMStructure(e) { if (!e || "object" != typeof e) return !1; const t = Object.keys(e); if (1 !== t.length) return !1; const n = t[0]; return "string" == typeof n && (this.juris.componentManager.components.has(n) || /^[a-zA-Z][a-zA-Z0-9-]*$/.test(n)) } _createLifecycleComponent(e, t, n, s) { const r = { name: t, props: n, hooks: e.hooks || {}, api: e.api || {}, render: e.render }, i = this.juris.domRenderer.render(r.render()); return i && (this.instances.set(i, r), s && s.size > 0 && this.componentStates.set(i, s), r.hooks.onMount && setTimeout((() => { if (i.isConnected) try { r.hooks.onMount() } catch (e) { console.error(`onMount error in ${t}:`, e) } }), 0)), i } updateInstance1(e, t) { const s = this.instances.get(e); if (!s) return; const r = s.props; if (n(r, t)) console.log(`Skipping re-render for ${s.name} - props unchanged`); else { if (s.props = t, s.hooks.onUpdate) try { s.hooks.onUpdate(r, t) } catch (e) { console.error(`onUpdate error in ${s.name}:`, e) } try { const t = s.render(); this.juris.domRenderer.updateElementContent(e, t) } catch (e) { console.error(`Re-render error in ${s.name}:`, e) } } } cleanup(e) { const t = this.instances.get(e); if (t && t.hooks.onUnmount) try { t.hooks.onUnmount() } catch (e) { console.error(`onUnmount error in ${t.name}:`, e) } const n = this.componentStates.get(e); n && (n.forEach((e => { const t = e.split("."); let n = this.juris.stateManager.state; for (let e = 0; e < t.length - 1; e++) { if (!n[t[e]]) return; n = n[t[e]] } delete n[t[t.length - 1]] })), this.componentStates.delete(e)), this.instances.delete(e) } _createErrorElement(e) { const t = document.createElement("div"); return t.style.cssText = "color: red; border: 1px solid red; padding: 8px; background: #ffe6e6;", t.textContent = `Component Error: ${e.message}`, t } } class a { constructor(e) { this.juris = e, this.subscriptions = new WeakMap, this.eventMap = { ondoubleclick: "dblclick", onmousedown: "mousedown", onmouseup: "mouseup", onmouseover: "mouseover", onmouseout: "mouseout", onmousemove: "mousemove", onkeydown: "keydown", onkeyup: "keyup", onkeypress: "keypress", onfocus: "focus", onblur: "blur", onchange: "change", oninput: "input", onsubmit: "submit", onload: "load", onresize: "resize", onscroll: "scroll" }, this.elementCache = new Map, this.recyclePool = new Map, this.renderQueue = [], this.isRendering = !1, this.scheduledRender = null, this.batchSize = 20, this.recyclePoolSize = 100, this.renderMode = "fine-grained", this.failureCount = 0, this.maxFailures = 3, this.renderStats = { totalUpdates: 0, skippedUpdates: 0, lastReset: Date.now() } } getRenderStats() { const e = (Date.now() - this.renderStats.lastReset) / 1e3, t = this.renderStats.totalUpdates > 0 ? (this.renderStats.skippedUpdates / this.renderStats.totalUpdates * 100).toFixed(1) : 0; return { totalUpdates: this.renderStats.totalUpdates, skippedUpdates: this.renderStats.skippedUpdates, skipRate: `${t}%`, duration: `${e.toFixed(1)}s` } } resetRenderStats() { this.renderStats = { totalUpdates: 0, skippedUpdates: 0, lastReset: Date.now() } } setRenderMode(e) { "fine-grained" === e || "batch" === e ? (this.renderMode = e, console.log(`Juris: Render mode set to '${e}'`), "fine-grained" === e ? console.log(" → Using direct DOM updates (more compatible)") : console.log(" → Using VDOM-style reconciliation (higher performance)")) : console.warn(`Invalid render mode '${e}'. Use 'fine-grained' or 'batch'`) } getRenderMode() { return this.renderMode } isFineGrained() { return "fine-grained" === this.renderMode } isBatchMode() { return "batch" === this.renderMode } setLegacyMode(e) { console.warn("setLegacyMode() is deprecated. Use setRenderMode() instead."), this.setRenderMode(e ? "fine-grained" : "batch") } isLegacyMode() { return console.warn("isLegacyMode() is deprecated. Use isFineGrained() instead."), this.isFineGrained() } render(e) { if (!e || "object" != typeof e) return null; if (Array.isArray(e)) { const t = document.createDocumentFragment(); return e.forEach((e => { const n = this.render(e); n && t.appendChild(n) })), t } const t = Object.keys(e)[0], n = e[t] || {}; if (this.juris.componentManager.components.has(t)) { const e = this.juris.stateManager.currentTracking; this.juris.stateManager.currentTracking = null; const s = this.juris.componentManager.create(t, n); return this.juris.stateManager.currentTracking = e, s } if ("string" != typeof t || 0 === t.length) return console.error("Invalid tagName:", t, "from vnode:", e), null; if ("fine-grained" === this.renderMode) return this._createElementFineGrained(t, n); try { const e = n.key || this._generateKey(t, n), s = this.elementCache.get(e); return s && this._canReuseElement(s, t, n) ? (this._updateElementProperties(s, n), s) : this._createElementOptimized(t, n, e) } catch (e) { return console.warn("Batch rendering failed, falling back to fine-grained mode:", e.message), this.failureCount++, this.failureCount >= this.maxFailures && (console.log("Too many batch failures, switching to fine-grained mode permanently"), this.renderMode = "fine-grained"), this._createElementFineGrained(t, n) } } _createElementFineGrained(e, t) { if ("string" != typeof e) return console.error("Invalid tagName in _createElementFineGrained:", e), null; const n = document.createElement(e), s = [], r = []; return Object.keys(t).forEach((e => { const i = t[e]; "children" === e ? this._handleChildrenFineGrained(n, i, s) : "text" === e ? this._handleText(n, i, s) : "style" === e ? this._handleStyleFineGrained(n, i, s) : e.startsWith("on") ? this._handleEvent(n, e, i, r) : "function" == typeof i ? this._handleReactiveAttribute(n, e, i, s) : "key" !== e && this._setStaticAttribute(n, e, i) })), (s.length > 0 || r.length > 0) && this.subscriptions.set(n, { subscriptions: s, eventListeners: r }), n } _handleChildrenFineGrained(e, t, s) { if ("function" == typeof t) { let r = null, i = !1; const a = () => { try { const s = t(); if (i && n(s, r)) return; "ignore" !== s && (this._updateChildrenFineGrained(e, s), r = s, i = !0) } catch (e) { console.error("Error in children function:", e) } }; this._createReactiveUpdate(e, a, s) } else this._updateChildrenFineGrained(e, t) } _updateChildrenFineGrained(e, t) { if ("ignore" === t) return; Array.from(e.children).forEach((e => { this.cleanup(e) })), e.textContent = ""; const n = document.createDocumentFragment(); if (Array.isArray(t)) t.forEach((e => { const t = this.render(e); t && n.appendChild(t) })); else if (t) { const e = this.render(t); e && n.appendChild(e) } n.hasChildNodes() && e.appendChild(n) } _handleStyleFineGrained(e, t, s) { if ("function" == typeof t) { let r = null, i = !1; const a = () => { const s = t(); i && n(s, r) || "object" == typeof s && (Object.assign(e.style, s), r = { ...s }, i = !0) }; this._createReactiveUpdate(e, a, s) } else "object" == typeof t && Object.assign(e.style, t) } _createElementOptimized(e, t, n) { let s = this._getRecycledElement(e); s || (s = document.createElement(e)), n && (this.elementCache.set(n, s), s._jurisKey = n); const r = [], i = []; return this._processProperties(s, t, r, i), (r.length > 0 || i.length > 0) && this.subscriptions.set(s, { subscriptions: r, eventListeners: i }), s } _processProperties(e, t, n, s) { Object.keys(t).forEach((r => { const i = t[r]; "children" === r ? this._handleChildrenOptimized(e, i, n) : "text" === r ? this._handleText(e, i, n) : "innerHTML" === r ? "function" == typeof i ? this._handleReactiveAttribute(e, r, i, n) : e.innerHTML = i : "style" === r ? this._handleStyle(e, i, n) : r.startsWith("on") ? this._handleEvent(e, r, i, s) : "function" == typeof i ? this._handleReactiveAttribute(e, r, i, n) : "key" !== r && this._setStaticAttribute(e, r, i) })) } _handleChildrenOptimized(e, t, n) { if ("function" == typeof t) { let s = null, r = [], i = !0; const a = () => { try { const n = t(); if ("ignore" !== n && !this._childrenEqual(s, n)) if (i) try { r = this._reconcileChildren(e, r, n), s = n } catch (t) { console.warn("Reconciliation failed, falling back to safe rendering:", t.message), i = !1, this._updateChildrenSafe(e, n), s = n } else this._updateChildrenSafe(e, n), s = n } catch (t) { console.error("Error in children function:", t), i = !1; try { this._updateChildrenSafe(e, []) } catch (e) { console.error("Even safe fallback failed:", e) } } }; this._createReactiveUpdate(e, a, n); try { const n = t(); r = this._reconcileChildren(e, [], n), s = n } catch (n) { console.warn("Initial reconciliation failed, using safe method:", n.message), i = !1; const r = t(); this._updateChildrenSafe(e, r), s = r } } else try { this._reconcileChildren(e, [], t) } catch (n) { console.warn("Static reconciliation failed, using safe method:", n.message), this._updateChildrenSafe(e, t) } } _updateChildrenSafe(e, t) { if ("ignore" === t) return; Array.from(e.children).forEach((e => { try { this.cleanup(e) } catch (e) { console.warn("Error cleaning up child:", e) } })), e.textContent = ""; const n = document.createDocumentFragment(); if (Array.isArray(t)) t.forEach((t => { try { const s = this.render(t); s && s !== e && n.appendChild(s) } catch (e) { console.warn("Error rendering child:", e) } })); else if (t) try { const s = this.render(t); s && s !== e && n.appendChild(s) } catch (e) { console.warn("Error rendering single child:", e) } try { n.hasChildNodes() && e.appendChild(n) } catch (t) { console.error("Failed to append fragment, trying individual children:", t), Array.from(n.children).forEach((t => { try { t && t !== e && e.appendChild(t) } catch (e) { console.warn("Failed to append individual child:", e) } })) } } _reconcileChildren(e, t, n) { Array.isArray(n) || (n = n ? [n] : []); const s = [], r = document.createDocumentFragment(), i = new Map; t.forEach(((e, t) => { const n = e._jurisKey || `auto-${t}`; i.set(n, e) })); const a = new Set; n.forEach(((t, n) => { if (!t || "object" != typeof t) return; const o = Object.keys(t)[0], c = t[o] || {}, h = c.key || this._generateKey(o, c, n), l = i.get(h); if (l && !a.has(l) && this._canReuseElement(l, o, c) && !this._wouldCreateCircularReference(e, l)) l.parentNode && l.parentNode.removeChild(l), this._updateElementProperties(l, c), s.push(l), r.appendChild(l), a.add(l), i.delete(h); else { const n = this.render(t); n && !this._wouldCreateCircularReference(e, n) && (n._jurisKey = h, s.push(n), r.appendChild(n)) } })), i.forEach((e => { a.has(e) || this._recycleElement(e) })); try { e.textContent = "", r.hasChildNodes() && e.appendChild(r) } catch (t) { console.error("Error in reconcileChildren:", t), e.textContent = "", s.forEach((t => { try { t && !this._wouldCreateCircularReference(e, t) && e.appendChild(t) } catch (e) { console.warn("Failed to append child, skipping:", e) } })) } return s } _wouldCreateCircularReference(e, t) { if (!e || !t) return !1; if (e === t) return !0; try { let n = e.parentNode; for (; n;) { if (n === t) return !0; n = n.parentNode } if (t.contains && t.contains(e)) return !0; if (t.children) for (let n of t.children) if (this._wouldCreateCircularReference(e, n)) return !0 } catch (e) { return console.warn("Error checking circular reference, assuming unsafe:", e), !0 } return !1 } _canReuseElement(e, t, n) { return e.tagName.toLowerCase() === t.toLowerCase() } _updateElementProperties(e, t) { Object.keys(t).forEach((n => { if ("key" === n || "children" === n || "text" === n || "style" === n) return; const s = t[n]; "function" != typeof s && this._setStaticAttribute(e, n, s) })) } _childrenEqual(e, t) { return !1 } _generateKey(e, t, n = null) { if (t.key) return t.key; const s = [e];["id", "className", "text"].forEach((e => { t[e] && "function" != typeof t[e] && s.push(`${e}:${t[e]}`) })), null !== n && s.push(`idx:${n}`); const r = this._hashProps(t); return s.push(`hash:${r}`), s.join("|") } _hashProps(e) { const t = JSON.stringify(e, ((e, t) => "function" == typeof t ? "[function]" : t)); let n = 0; for (let e = 0; e < t.length; e++) { n = (n << 5) - n + t.charCodeAt(e), n &= n } return Math.abs(n).toString(36) } _getRecycledElement(e) { const t = this.recyclePool.get(e); if (t && t.length > 0) { const e = t.pop(); return this._resetElement(e), e } return null } _recycleElement(e) { if (!e || !e.tagName) return; const t = e.tagName.toLowerCase(); e.parentNode && e.parentNode.removeChild(e), this.recyclePool.has(t) || this.recyclePool.set(t, []); const n = this.recyclePool.get(t); n.length < this.recyclePoolSize && (this.cleanup(e), this._resetElement(e), n.push(e)) } _resetElement(e) { e.textContent = "", e.className = "", e.removeAttribute("style"); const t = ["id", "data-juris-key"]; Array.from(e.attributes).forEach((n => { t.includes(n.name) || e.removeAttribute(n.name) })) } _handleText(e, t, n) { if ("function" == typeof t) { let s = null, r = !1; const i = () => { const n = t(); r && n === s || (e.textContent = n, s = n, r = !0) }; this._createReactiveUpdate(e, i, n) } else e.textContent = t } _handleStyle(e, t, s) { if ("function" == typeof t) { let r = null, i = !1; this._createReactiveUpdate(e, (() => { const s = t(); if (i && n(s, r)) return; const a = this._styleObjectToCssText(s); e.style.cssText = a, r = { ...s }, i = !0 }), s); const a = t(), o = this._styleObjectToCssText(a); e.style.cssText = o, r = { ...a }, i = !0 } else if ("object" == typeof t) { const n = {}, r = {}; if (Object.keys(t).forEach((e => { "function" == typeof t[e] ? n[e] = t[e] : r[e] = t[e] })), Object.assign(e.style, r), Object.keys(n).length > 0) { const t = {}, r = {}; this._createReactiveUpdate(e, (() => { const s = {}; let i = !1; Object.keys(n).forEach((e => { const a = n[e](); r[e] && a === t[e] || (s[e] = a, t[e] = a, r[e] = !0, i = !0) })), i && Object.assign(e.style, s) }), s), Object.keys(n).forEach((s => { const i = n[s](); e.style[s] = i, t[s] = i, r[s] = !0 })) } } } _styleObjectsEqual(e, t) { if (e === t) return !0; if (!e || !t) return !1; const n = Object.keys(e), s = Object.keys(t); if (n.length !== s.length) return !1; for (let s of n) if (e[s] !== t[s]) return !1; return !0 } _styleObjectToCssText(e) { return e && "object" == typeof e ? Object.entries(e).map((([e, t]) => `${e.replace(/[A-Z]/g, (e => `-${e.toLowerCase()}`))}: ${t}`)).join("; ") : "" } _handleEvent(e, t, n, s) { if ("onclick" === t) { e.style.touchAction = "manipulation", e.style.webkitTapHighlightColor = "transparent", e.style.webkitTouchCallout = "none", e.addEventListener("click", n), s.push({ eventName: "click", handler: n }); let t = 0, r = !1, i = 0, a = 0; const o = e => { t = Date.now(), r = !1, e.touches && e.touches[0] && (i = e.touches[0].clientX, a = e.touches[0].clientY) }, c = e => { if (e.touches && e.touches[0]) { const t = Math.abs(e.touches[0].clientX - i), n = Math.abs(e.touches[0].clientY - a); (t > 10 || n > 10) && (r = !0) } }, h = e => { const s = Date.now() - t; !r && s < 300 && (e.preventDefault(), e.stopPropagation(), n(e)) }; e.addEventListener("touchstart", o, { passive: !0 }), e.addEventListener("touchmove", c, { passive: !0 }), e.addEventListener("touchend", h, { passive: !1 }), s.push({ eventName: "touchstart", handler: o }), s.push({ eventName: "touchmove", handler: c }), s.push({ eventName: "touchend", handler: h }) } else { const r = this.eventMap[t.toLowerCase()] || t.slice(2).toLowerCase(); e.addEventListener(r, n), s.push({ eventName: r, handler: n }) } } _handleReactiveAttribute(e, t, s, r) { let i = null, a = !1; this._createReactiveUpdate(e, (() => { const r = s(); a && n(r, i) || (this._setStaticAttribute(e, t, r), i = r, a = !0) }), r) } _setStaticAttribute(e, t, n) { if ("children" !== t && "key" !== t) { if ("function" == typeof n) return "value" !== t || "INPUT" !== e.tagName && "TEXTAREA" !== e.tagName && "SELECT" !== e.tagName ? void console.warn(`Function value for attribute '${t}' should be handled reactively`) : void (e.value = n()); if ("className" === t) e.className = n; else if ("htmlFor" === t) e.setAttribute("for", n); else if ("tabIndex" === t) e.tabIndex = n; else if (t.startsWith("data-") || t.startsWith("aria-")) e.setAttribute(t, n); else if (t in e && "function" != typeof e[t]) try { const s = Object.getOwnPropertyDescriptor(e, t) || Object.getOwnPropertyDescriptor(Object.getPrototypeOf(e), t); s && !1 === s.writable ? e.setAttribute(t, n) : e[t] = n } catch (s) { e.setAttribute(t, n) } else e.setAttribute(t, n) } } _createReactiveUpdate(e, t, n) { const s = this.juris.stateManager.startTracking(), r = this.juris.stateManager.currentTracking; this.juris.stateManager.currentTracking = s; try { t() } catch (e) { console.error("Error capturing dependencies:", e) } finally { this.juris.stateManager.currentTracking = r } s.forEach((e => { const s = this.juris.stateManager.subscribeInternal(e, t); n.push(s) })) } _updateChildren(e, t) { if ("ignore" !== t) try { if (Array.isArray(t)) { const n = Array.from(e.children); this._reconcileChildren(e, n, t) } else { const n = t ? [t] : [], s = Array.from(e.children); this._reconcileChildren(e, s, n) } } catch (n) { console.warn("Reconciliation failed in _updateChildren, using safe fallback:", n.message), this._updateChildrenSafe(e, t) } } updateElementContent(e, t) { this._updateChildren(e, [t]) } cleanup(e) { this.juris.componentManager.cleanup(e); const t = this.subscriptions.get(e); t && (t.subscriptions && t.subscriptions.forEach((e => { try { e() } catch (e) { console.warn("Error during subscription cleanup:", e) } })), t.eventListeners && t.eventListeners.forEach((({ eventName: t, handler: n }) => { try { e.removeEventListener(t, n) } catch (e) { console.warn("Error during event listener cleanup:", e) } })), this.subscriptions.delete(e)), e._jurisKey && this.elementCache.delete(e._jurisKey); try { Array.from(e.children || []).forEach((e => { try { this.cleanup(e) } catch (e) { console.warn("Error cleaning up child element:", e) } })) } catch (e) { console.warn("Error during children cleanup:", e) } if (e.removeAttribute) try { e.removeAttribute("data-juris-enhanced"), e.removeAttribute("data-juris-component"), e.removeAttribute("data-juris-key") } catch (e) { } } } class o { constructor(e) { this.juris = e, this.observers = new Map, this.enhancedElements = new WeakSet, this.enhancementRules = new Map, this.containerEnhancements = new WeakMap, this.options = { debounceMs: 5, batchUpdates: !0, observeSubtree: !0, observeChildList: !0 }, this.pendingEnhancements = new Set, this.enhancementTimer = null } enhance(e, t, n = {}) { const s = { ...this.options, ...n }; return this._hasSelectorsCategory(t) ? this._enhanceWithSelectors(e, t, s) : (this.enhancementRules.set(e, { definition: t, config: s, type: "simple" }), this._enhanceExistingElements(e, t, s), !1 !== s.observeNewElements && this._setupMutationObserver(e, t, s), () => this._unenhance(e)) } _hasSelectorsCategory(e) { if (e && "object" == typeof e && e.selectors) return !0; if ("function" == typeof e) try { const t = e(this.juris.createContext()); return t && "object" == typeof t && t.selectors } catch (e) { return !1 } return !1 } _enhanceWithSelectors(e, t, n) { return this.enhancementRules.set(e, { definition: t, config: n, type: "selectors" }), this._enhanceExistingContainers(e, t, n), !1 !== n.observeNewElements && this._setupSelectorsObserver(e, t, n), () => this._unenhanceSelectors(e) } _enhanceExistingContainers(e, t, n) { document.querySelectorAll(e).forEach((e => { this._enhanceContainer(e, t, n) })) } _enhanceContainer(e, t, n) { if (!this.enhancedElements.has(e)) try { this.enhancedElements.add(e), e.setAttribute("data-juris-enhanced-container", Date.now()); let s = t; if ("function" == typeof t) { s = t(this.juris.createContext(e)) } if (!s || !s.selectors) return void console.warn('Selectors enhancement must have a "selectors" property'); const r = new Map; this.containerEnhancements.set(e, r), this._applyContainerProperties(e, s), Object.entries(s.selectors).forEach((([t, s]) => { this._enhanceSelector(e, t, s, r, n) })) } catch (t) { console.error("Error enhancing container:", t), this.enhancedElements.delete(e) } } _applyContainerProperties(e, t) { const n = { ...t }; delete n.selectors, Object.keys(n).length > 0 && this._applyEnhancements(e, n) } _enhanceSelector(e, t, n, s, r) { const i = e.querySelectorAll(t), a = new Set; i.forEach((s => { this.enhancedElements.has(s) || (this._enhanceSelectorElement(s, n, e, t), a.add(s)) })), s.set(t, { definition: n, enhancedElements: a }) } _enhanceSelectorElement(e, t, n, s) { try { this.enhancedElements.add(e), e.setAttribute("data-juris-enhanced-selector", Date.now()); let n = t; if ("function" == typeof t) { if (n = t(this.juris.createContext(e)), !n || "object" != typeof n) return console.warn(`Selector '${s}' function must return a definition object`), void this.enhancedElements.delete(e) } const r = this._processElementAwareFunctions(e, n); this._applyEnhancements(e, r) } catch (t) { console.error("Error enhancing selector element:", t), this.enhancedElements.delete(e) } } _processElementAwareFunctions(e, t) { const n = {}; return Object.entries(t).forEach((([t, s]) => { if ("function" == typeof s) if (t.startsWith("on")) n[t] = s; else if (s.length > 0) try { const r = s(this.juris.createContext(e)); r && "object" == typeof r ? n[t] = r : (console.warn(`Element-aware function for '${t}' should return an object`), n[t] = s) } catch (e) { console.warn(`Error processing element-aware function '${t}':`, e), n[t] = s } else n[t] = s; else n[t] = s })), n } _setupSelectorsObserver(e, t, n) { const s = `selectors_${e}`; if (this.observers.has(s)) return; const r = new MutationObserver((s => { n.debounceMs > 0 ? this._debouncedProcessSelectorsMutations(s, e, t, n) : this._processSelectorsMutations(s, e, t, n) })), i = { childList: n.observeChildList, subtree: n.observeSubtree }; r.observe(document.body, i), this.observers.set(s, r) } _processSelectorsMutations(e, t, n, s) { e.forEach((e => { "childList" === e.type && e.addedNodes.forEach((e => { e.nodeType === Node.ELEMENT_NODE && this._handleNewNodeForSelectors(e, t, n, s) })) })) } _handleNewNodeForSelectors(e, t, n, s) { if (e.matches && e.matches(t) && this._enhanceContainer(e, n, s), e.querySelectorAll) { e.querySelectorAll(t).forEach((e => { this._enhanceContainer(e, n, s) })) } this._enhanceNewElementsInContainers(e) } _enhanceNewElementsInContainers(e) { document.querySelectorAll("[data-juris-enhanced-container]").forEach((t => { if (!t.contains(e)) return; const n = this.containerEnhancements.get(t); n && n.forEach(((n, s) => { const { definition: r, enhancedElements: i } = n; if (e.matches && e.matches(s) && (this._enhanceSelectorElement(e, r, t, s), i.add(e)), e.querySelectorAll) { e.querySelectorAll(s).forEach((e => { this.enhancedElements.has(e) || (this._enhanceSelectorElement(e, r, t, s), i.add(e)) })) } })) })) } _debouncedProcessSelectorsMutations(e, t, n, s) { e.forEach((e => { "childList" === e.type && e.addedNodes.forEach((e => { e.nodeType === Node.ELEMENT_NODE && this.pendingEnhancements.add({ node: e, containerSelector: t, definition: n, config: s, type: "selectors", timestamp: Date.now() }) })) })), this.enhancementTimer && clearTimeout(this.enhancementTimer), this.enhancementTimer = setTimeout((() => { this._processPendingEnhancements(), this.enhancementTimer = null }), s.debounceMs) } _unenhanceSelectors(e) { const t = `selectors_${e}`, n = this.observers.get(t); n && (n.disconnect(), this.observers.delete(t)), this.enhancementRules.delete(e); document.querySelectorAll(`${e}[data-juris-enhanced-container]`).forEach((e => { this._cleanupContainer(e) })) } _cleanupContainer(e) { const t = this.containerEnhancements.get(e); t && (t.forEach((e => { e.enhancedElements.forEach((e => { this._cleanupElement(e) })) })), this.containerEnhancements.delete(e)), this._cleanupElement(e), e.removeAttribute("data-juris-enhanced-container") } _enhanceExistingElements(e, t, n) { const s = document.querySelectorAll(e); n.batchUpdates && s.length > 1 ? this._batchEnhanceElements(Array.from(s), t, n) : s.forEach((e => this._enhanceElement(e, t, n))) } _batchEnhanceElements(e, t, n) { e.filter((e => !this.enhancedElements.has(e))).forEach((e => this._enhanceElement(e, t, n))) } _enhanceElement(e, t, n) { if (!this.enhancedElements.has(e)) try { this.enhancedElements.add(e), e.setAttribute("data-juris-enhanced", Date.now()); let s = t; if ("function" == typeof t) { if (s = t(this.juris.createContext(e)), !s || "object" != typeof s) return console.warn("Enhancement function must return a definition object"), void this.enhancedElements.delete(e) } if (this._applyEnhancements(e, s), n.onEnhanced) { const t = this.juris.createContext(e); n.onEnhanced(e, t) } } catch (t) { console.error("Error enhancing element:", t), this.enhancedElements.delete(e) } } _applyEnhancements(e, t) { const n = [], s = [], r = this.juris.domRenderer; Object.keys(t).forEach((i => { const a = t[i]; try { "children" === i ? this._handleChildren(e, a, n, r) : "text" === i ? r._handleText(e, a, n) : "innerHTML" === i ? this._handleInnerHTML(e, a, n, r) : "style" === i ? r._handleStyle(e, a, n) : i.startsWith("on") ? r._handleEvent(e, i, a, s) : "function" == typeof a ? r._handleReactiveAttribute(e, i, a, n) : r._setStaticAttribute(e, i, a) } catch (e) { console.error(`Error processing enhancement property '${i}':`, e) } })), (n.length > 0 || s.length > 0) && this.juris.domRenderer.subscriptions.set(e, { subscriptions: n, eventListeners: s }) } _handleChildren(e, t, n, s) { s.isFineGrained() ? s._handleChildrenFineGrained(e, t, n) : s._handleChildrenOptimized(e, t, n) } _handleInnerHTML(e, t, n, s) { "function" == typeof t ? s._handleReactiveAttribute(e, "innerHTML", t, n) : e.innerHTML = t } _setupMutationObserver(e, t, n) { if (this.observers.has(e)) return; const s = new MutationObserver((s => { n.debounceMs > 0 ? this._debouncedProcessMutations(s, e, t, n) : this._processMutations(s, e, t, n) })), r = { childList: n.observeChildList, subtree: n.observeSubtree }; s.observe(document.body, r), this.observers.set(e, s) } _processMutations(e, t, n, s) { e.forEach((e => { "childList" === e.type && e.addedNodes.forEach((e => { e.nodeType === Node.ELEMENT_NODE && this._enhanceNewNode(e, t, n, s) })) })) } _enhanceNewNode(e, t, n, s) { if (e.matches && e.matches(t) && this._enhanceElement(e, n, s), e.querySelectorAll) { e.querySelectorAll(t).forEach((e => { this._enhanceElement(e, n, s) })) } } _debouncedProcessMutations(e, t, n, s) { e.forEach((e => { "childList" === e.type && e.addedNodes.forEach((e => { e.nodeType === Node.ELEMENT_NODE && this.pendingEnhancements.add({ node: e, selector: t, definition: n, config: s, timestamp: Date.now() }) })) })), this.enhancementTimer && clearTimeout(this.enhancementTimer), this.enhancementTimer = setTimeout((() => { this._processPendingEnhancements(), this.enhancementTimer = null }), s.debounceMs) } _processPendingEnhancements() { const e = Array.from(this.pendingEnhancements); this.pendingEnhancements.clear(), e.forEach((({ node: e, selector: t, definition: n, config: s, containerSelector: r, type: i }) => { try { "selectors" === i ? this._handleNewNodeForSelectors(e, r, n, s) : this._enhanceNewNode(e, t, n, s) } catch (e) { console.error("Error processing pending enhancement:", e) } })) } _unenhance(e) { const t = this.observers.get(e); t && (t.disconnect(), this.observers.delete(e)), this.enhancementRules.delete(e); document.querySelectorAll(`${e}[data-juris-enhanced]`).forEach((e => { this._cleanupElement(e) })) } _cleanupElement(e) { this.juris.domRenderer.cleanup(e), this.enhancedElements.delete(e), e.removeAttribute("data-juris-enhanced"), e.removeAttribute("data-juris-enhanced-selector") } configure(e) { Object.assign(this.options, e) } configureRenderOptimization(e = {}) { void 0 !== e.enableLogging && (this.renderOptimization = this.renderOptimization || {}, this.renderOptimization.enableLogging = e.enableLogging), console.log("Render optimization configured:", this.renderOptimization) } getStats() { const e = document.querySelectorAll("[data-juris-enhanced]").length, t = document.querySelectorAll("[data-juris-enhanced-container]").length, n = document.querySelectorAll("[data-juris-enhanced-selector]").length; return { enhancementRules: this.enhancementRules.size, activeObservers: this.observers.size, pendingEnhancements: this.pendingEnhancements.size, enhancedElements: e, enhancedContainers: t, enhancedSelectors: n, totalEnhanced: e + n } } destroy() { this.observers.forEach((e => e.disconnect())), this.observers.clear(), this.enhancementRules.clear(), this.enhancementTimer && (clearTimeout(this.enhancementTimer), this.enhancementTimer = null); document.querySelectorAll("[data-juris-enhanced], [data-juris-enhanced-selector]").forEach((e => { this._cleanupElement(e) })); document.querySelectorAll("[data-juris-enhanced-container]").forEach((e => { this._cleanupContainer(e) })), this.pendingEnhancements.clear() } } class c { constructor(e = {}) { this.services = e.services || {}, this.layout = e.layout, this.stateManager = new s(e.states || {}, e.middleware || []), this.headlessManager = new r(this), this.componentManager = new i(this), this.domRenderer = new a(this), this.domEnhancer = new o(this), e.headlessComponents && Object.entries(e.headlessComponents).forEach((([e, t]) => { "function" == typeof t ? this.headlessManager.register(e, t) : this.headlessManager.register(e, t.fn, t.options) })), this.headlessManager.initializeQueued(), "fine-grained" === e.renderMode ? this.domRenderer.setRenderMode("fine-grained") : "batch" === e.renderMode && this.domRenderer.setRenderMode("batch"), !0 === e.legacyMode && (console.warn('legacyMode is deprecated. Use renderMode: "fine-grained" instead.'), this.domRenderer.setRenderMode("fine-grained")), e.components && Object.entries(e.components).forEach((([e, t]) => { this.componentManager.register(e, t) })) } init() { } createHeadlessContext(e = null) { const t = { getState: (e, t) => this.stateManager.getState(e, t), setState: (e, t, n) => this.stateManager.setState(e, t, n), subscribe: (e, t) => this.stateManager.subscribe(e, t), services: this.services, ...this.services || {}, headless: this.headlessManager.context, ...this.headlessAPIs || {}, components: { register: (e, t) => this.componentManager.register(e, t), registerHeadless: (e, t, n) => this.headlessManager.register(e, t, n), get: e => this.componentManager.components.get(e), getHeadless: e => this.headlessManager.getInstance(e), initHeadless: (e, t) => this.headlessManager.initialize(e, t), reinitHeadless: (e, t) => this.headlessManager.reinitialize(e, t) }, utils: { render: e => this.render(e), cleanup: () => this.cleanup(), forceRender: () => this.render(), getHeadlessStatus: () => this.headlessManager.getStatus() }, juris: this }; return e && (t.element = e), t } createContext(e = null) { const t = { getState: (e, t) => this.stateManager.getState(e, t), setState: (e, t, n) => this.stateManager.setState(e, t, n), subscribe: (e, t) => this.stateManager.subscribe(e, t), services: this.services, ...this.services || {}, ...this.headlessAPIs || {}, headless: this.headlessManager.context, components: { register: (e, t) => this.componentManager.register(e, t), registerHeadless: (e, t, n) => this.headlessManager.register(e, t, n), get: e => this.componentManager.components.get(e), getHeadless: e => this.headlessManager.getInstance(e), initHeadless: (e, t) => this.headlessManager.initialize(e, t), reinitHeadless: (e, t) => this.headlessManager.reinitialize(e, t), getHeadlessAPI: e => this.headlessManager.getAPI(e), getAllHeadlessAPIs: () => this.headlessManager.getAllAPIs() }, utils: { render: e => this.render(e), cleanup: () => this.cleanup(), forceRender: () => this.render(), setRenderMode: e => this.setRenderMode(e), getRenderMode: () => this.getRenderMode(), isFineGrained: () => this.isFineGrained(), isBatchMode: () => this.isBatchMode(), getHeadlessStatus: () => this.headlessManager.getStatus() }, juris: this }; return e && (t.element = e), t } getState(e, t) { return this.stateManager.getState(e, t) } setState(e, t, n) { return this.stateManager.setState(e, t, n) } subscribe(e, t, n = !0) { return this.stateManager.subscribe(e, t, n) } subscribeExact(e, t) { return this.stateManager.subscribeExact(e, t) } registerComponent(e, t) { return this.componentManager.register(e, t) } registerHeadlessComponent(e, t, n) { return this.headlessManager.register(e, t, n) } getComponent(e) { return this.componentManager.components.get(e) } getHeadlessComponent(e) { return this.headlessManager.getInstance(e) } initializeHeadlessComponent(e, t) { return this.headlessManager.initialize(e, t) } setRenderMode(e) { this.domRenderer.setRenderMode(e) } getRenderMode() { return this.domRenderer.getRenderMode() } isFineGrained() { return this.domRenderer.isFineGrained() } isBatchMode() { return this.domRenderer.isBatchMode() } enableLegacyMode() { console.warn('enableLegacyMode() is deprecated. Use setRenderMode("fine-grained") instead.'), this.setRenderMode("fine-grained") } disableLegacyMode() { console.warn('disableLegacyMode() is deprecated. Use setRenderMode("batch") instead.'), this.setRenderMode("batch") } _updateComponentContexts() { this.headlessAPIs } registerAndInitHeadless(e, t, n = {}) { return this.headlessManager.register(e, t, n), this.headlessManager.initialize(e, n) } getHeadlessStatus() { return this.headlessManager.getStatus() } objectToHtml(e) { return this.domRenderer.render(e) } render(e = "#app") { const t = "string" == typeof e ? document.querySelector(e) : e; if (t) { Array.from(t.children).forEach((e => { this.domRenderer.cleanup(e) })), t.innerHTML = "", this.headlessManager.initializeQueued(); try { if (!this.layout) return void (t.innerHTML = "<p>No layout configured</p>"); const e = this.domRenderer.render(this.layout); e && t.appendChild(e) } catch (e) { console.error("Render error:", e), this._renderError(t, e) } } else console.error("Container not found:", e) } _renderError(e, t) { const n = document.createElement("div"); n.style.cssText = "color: red; border: 2px solid red; padding: 16px; margin: 8px; background: #ffe6e6;", n.innerHTML = `\n <h3>Render Error</h3>\n <p><strong>Message:</strong> ${t.message}</p>\n <pre style="background: #f5f5f5; padding: 8px; overflow: auto;">${t.stack || ""}</pre>\n `, e.appendChild(n) } enhance(e, t, n) { return this.domEnhancer.enhance(e, t, n) } configureEnhancement(e) { return this.domEnhancer.configure(e) } getEnhancementStats() { return this.domEnhancer.getStats() } cleanup() { this.headlessManager.cleanup() } destroy() { this.cleanup(), this.domEnhancer.destroy(), this.stateManager.subscribers.clear(), this.stateManager.externalSubscribers.clear(), this.componentManager.components.clear(), this.headlessManager.components.clear() } } "undefined" != typeof window && (window.Juris = c, window.deepEquals = n), "undefined" != typeof module && module.exports && (module.exports = c, module.exports.deepEquals = n) }();