zero-query 0.4.9 → 0.6.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +16 -10
- package/cli/commands/build.js +4 -2
- package/cli/commands/bundle.js +113 -10
- package/cli/commands/dev/index.js +82 -0
- package/cli/commands/dev/logger.js +70 -0
- package/cli/commands/dev/overlay.js +317 -0
- package/cli/commands/dev/server.js +129 -0
- package/cli/commands/dev/validator.js +94 -0
- package/cli/commands/dev/watcher.js +114 -0
- package/cli/commands/{dev.js → dev.old.js} +8 -4
- package/cli/help.js +18 -6
- package/cli/scaffold/favicon.ico +0 -0
- package/cli/scaffold/scripts/components/about.js +14 -2
- package/cli/scaffold/scripts/components/contacts/contacts.html +5 -4
- package/cli/scaffold/scripts/components/contacts/contacts.js +17 -1
- package/cli/scaffold/scripts/components/counter.js +30 -10
- package/cli/scaffold/scripts/components/home.js +3 -3
- package/cli/scaffold/scripts/components/todos.js +6 -5
- package/dist/zquery.dist.zip +0 -0
- package/dist/zquery.js +1550 -97
- package/dist/zquery.min.js +11 -8
- package/index.d.ts +253 -14
- package/index.js +25 -8
- package/package.json +8 -2
- package/src/component.js +175 -44
- package/src/core.js +25 -18
- package/src/diff.js +280 -0
- package/src/errors.js +155 -0
- package/src/expression.js +806 -0
- package/src/http.js +18 -10
- package/src/reactive.js +29 -4
- package/src/router.js +11 -5
- package/src/ssr.js +224 -0
- package/src/store.js +24 -8
package/dist/zquery.min.js
CHANGED
|
@@ -1,17 +1,20 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* zQuery (zeroQuery) v0.
|
|
2
|
+
* zQuery (zeroQuery) v0.6.3
|
|
3
3
|
* Lightweight Frontend Library
|
|
4
4
|
* https://github.com/tonywied17/zero-query
|
|
5
5
|
* (c) 2026 Anthony Wiedman — MIT License
|
|
6
6
|
*/
|
|
7
7
|
(function(global) {
|
|
8
8
|
'use strict';
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
const
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
const
|
|
9
|
+
const ErrorCode = Object.freeze({ REACTIVE_CALLBACK: 'ZQ_REACTIVE_CALLBACK', SIGNAL_CALLBACK: 'ZQ_SIGNAL_CALLBACK', EFFECT_EXEC: 'ZQ_EFFECT_EXEC', EXPR_PARSE: 'ZQ_EXPR_PARSE', EXPR_EVAL: 'ZQ_EXPR_EVAL', EXPR_UNSAFE_ACCESS: 'ZQ_EXPR_UNSAFE_ACCESS', COMP_INVALID_NAME: 'ZQ_COMP_INVALID_NAME', COMP_NOT_FOUND: 'ZQ_COMP_NOT_FOUND', COMP_MOUNT_TARGET: 'ZQ_COMP_MOUNT_TARGET', COMP_RENDER: 'ZQ_COMP_RENDER', COMP_LIFECYCLE: 'ZQ_COMP_LIFECYCLE', COMP_RESOURCE: 'ZQ_COMP_RESOURCE', COMP_DIRECTIVE: 'ZQ_COMP_DIRECTIVE', ROUTER_LOAD: 'ZQ_ROUTER_LOAD', ROUTER_GUARD: 'ZQ_ROUTER_GUARD', ROUTER_RESOLVE: 'ZQ_ROUTER_RESOLVE', STORE_ACTION: 'ZQ_STORE_ACTION', STORE_MIDDLEWARE: 'ZQ_STORE_MIDDLEWARE', STORE_SUBSCRIBE: 'ZQ_STORE_SUBSCRIBE', HTTP_REQUEST: 'ZQ_HTTP_REQUEST', HTTP_TIMEOUT: 'ZQ_HTTP_TIMEOUT', HTTP_INTERCEPTOR: 'ZQ_HTTP_INTERCEPTOR', HTTP_PARSE: 'ZQ_HTTP_PARSE', INVALID_ARGUMENT: 'ZQ_INVALID_ARGUMENT',
|
|
10
|
+
function reactive(target, onChange, _path = '') { if (typeof target !== 'object' || target === null) return target; if (typeof onChange !== 'function') { reportError(ErrorCode.REACTIVE_CALLBACK, 'reactive() onChange must be a function', { received: typeof onChange }); onChange = () => {}; } const proxyCache = new WeakMap(); const handler = { get(obj, key) { if (key === '__isReactive') return true; if (key === '__raw') return obj; const value = obj[key]; if (typeof value === 'object' && value !== null) { if (proxyCache.has(value)) return proxyCache.get(value); const childProxy = new Proxy(value, handler); proxyCache.set(value, childProxy); return childProxy; } return value; }, set(obj, key, value) { const old = obj[key]; if (old === value) return true; obj[key] = value; try { onChange(key, value, old); } catch (err) { reportError(ErrorCode.REACTIVE_CALLBACK, `Reactive onChange threw for key "${String(key)}"`, { key, value, old }, err); } return true; }, deleteProperty(obj, key) { const old = obj[key]; delete obj[key]; try { onChange(key, undefined, old); } catch (err) { reportError(ErrorCode.REACTIVE_CALLBACK, `Reactive onChange threw for key "${String(key)}"`, { key, old }, err); } return true; } }; return new Proxy(target, handler);
|
|
11
|
+
class ZQueryCollection { constructor(elements) { this.elements = Array.isArray(elements) ? elements : [elements]; this.length = this.elements.length; this.elements.forEach((el, i) => { this[i] = el; }); } each(fn) { this.elements.forEach((el, i) => fn.call(el, i, el)); return this; } map(fn) { return this.elements.map((el, i) => fn.call(el, i, el)); } forEach(fn) { this.elements.forEach((el, i) => fn(el, i, this.elements)); return this; } first() { return this.elements[0] || null; } last() { return this.elements[this.length - 1] || null; } eq(i) { return new ZQueryCollection(this.elements[i] ? [this.elements[i]] : []); } toArray(){ return [...this.elements]; } [Symbol.iterator]() { return this.elements[Symbol.iterator](); } find(selector) { const found = []; this.elements.forEach(el => found.push(...el.querySelectorAll(selector))); return new ZQueryCollection(found); } parent() { const parents = [...new Set(this.elements.map(el => el.parentElement).filter(Boolean))]; return new ZQueryCollection(parents); } closest(selector) { return new ZQueryCollection( this.elements.map(el => el.closest(selector)).filter(Boolean) ); } children(selector) { const kids = []; this.elements.forEach(el => { kids.push(...(selector ? el.querySelectorAll(`:scope > ${selector}`) : el.children)); }); return new ZQueryCollection([...kids]); } siblings() { const sibs = []; this.elements.forEach(el => { sibs.push(...[...el.parentElement.children].filter(c => c !== el)); }); return new ZQueryCollection(sibs); } next() { return new ZQueryCollection(this.elements.map(el => el.nextElementSibling).filter(Boolean)); } prev() { return new ZQueryCollection(this.elements.map(el => el.previousElementSibling).filter(Boolean)); } filter(selector) { if (typeof selector === 'function') { return new ZQueryCollection(this.elements.filter(selector)); } return new ZQueryCollection(this.elements.filter(el => el.matches(selector))); } not(selector) { if (typeof selector === 'function') { return new ZQueryCollection(this.elements.filter((el, i) => !selector.call(el, i, el))); } return new ZQueryCollection(this.elements.filter(el => !el.matches(selector))); } has(selector) { return new ZQueryCollection(this.elements.filter(el => el.querySelector(selector))); } addClass(...names) { const classes = names.flatMap(n => n.split(/\s+/)); return this.each((_, el) => el.classList.add(...classes)); } removeClass(...names) { const classes = names.flatMap(n => n.split(/\s+/)); return this.each((_, el) => el.classList.remove(...classes)); } toggleClass(name, force) { return this.each((_, el) => el.classList.toggle(name, force)); } hasClass(name) { return this.first()?.classList.contains(name) || false; } attr(name, value) { if (value === undefined) return this.first()?.getAttribute(name); return this.each((_, el) => el.setAttribute(name, value)); } removeAttr(name) { return this.each((_, el) => el.removeAttribute(name)); } prop(name, value) { if (value === undefined) return this.first()?.[name]; return this.each((_, el) => { el[name] = value; }); } data(key, value) { if (value === undefined) { if (key === undefined) return this.first()?.dataset; const raw = this.first()?.dataset[key]; try { return JSON.parse(raw); } catch { return raw; } } return this.each((_, el) => { el.dataset[key] = typeof value === 'object' ? JSON.stringify(value) : value; }); } css(props) { if (typeof props === 'string') { return getComputedStyle(this.first())[props]; } return this.each((_, el) => Object.assign(el.style, props)); } width() { return this.first()?.getBoundingClientRect().width; } height() { return this.first()?.getBoundingClientRect().height; } offset() { const r = this.first()?.getBoundingClientRect(); return r ? { top: r.top + window.scrollY, left: r.left + window.scrollX, width: r.width, height: r.height } : null; } position() { const el = this.first(); return el ? { top: el.offsetTop, left: el.offsetLeft } : null; } html(content) { if (content === undefined) return this.first()?.innerHTML; return this.each((_, el) => { el.innerHTML = content; }); } text(content) { if (content === undefined) return this.first()?.textContent; return this.each((_, el) => { el.textContent = content; }); } val(value) { if (value === undefined) return this.first()?.value; return this.each((_, el) => { el.value = value; }); } append(content) { return this.each((_, el) => { if (typeof content === 'string') el.insertAdjacentHTML('beforeend', content); else if (content instanceof ZQueryCollection) content.each((__, c) => el.appendChild(c)); else if (content instanceof Node) el.appendChild(content); }); } prepend(content) { return this.each((_, el) => { if (typeof content === 'string') el.insertAdjacentHTML('afterbegin', content); else if (content instanceof Node) el.insertBefore(content, el.firstChild); }); } after(content) { return this.each((_, el) => { if (typeof content === 'string') el.insertAdjacentHTML('afterend', content); else if (content instanceof Node) el.parentNode.insertBefore(content, el.nextSibling); }); } before(content) { return this.each((_, el) => { if (typeof content === 'string') el.insertAdjacentHTML('beforebegin', content); else if (content instanceof Node) el.parentNode.insertBefore(content, el); }); } wrap(wrapper) { return this.each((_, el) => { const w = typeof wrapper === 'string' ? createFragment(wrapper).firstElementChild : wrapper.cloneNode(true); el.parentNode.insertBefore(w, el); w.appendChild(el); }); } remove() { return this.each((_, el) => el.remove()); } empty() { return this.each((_, el) => { el.innerHTML = ''; }); } clone(deep = true) { return new ZQueryCollection(this.elements.map(el => el.cloneNode(deep))); } replaceWith(content) { return this.each((_, el) => { if (typeof content === 'string') { el.insertAdjacentHTML('afterend', content); el.remove(); } else if (content instanceof Node) { el.parentNode.replaceChild(content, el); } }); } show(display = '') { return this.each((_, el) => { el.style.display = display; }); } hide() { return this.each((_, el) => { el.style.display = 'none'; }); } toggle(display = '') { return this.each((_, el) => { el.style.display = (el.style.display === 'none' || getComputedStyle(el).display === 'none') ? display : 'none'; }); } on(event, selectorOrHandler, handler) { const events = event.split(/\s+/); return this.each((_, el) => { events.forEach(evt => { if (typeof selectorOrHandler === 'function') { el.addEventListener(evt, selectorOrHandler); } else { el.addEventListener(evt, (e) => { const target = e.target.closest(selectorOrHandler); if (target && el.contains(target)) handler.call(target, e); }); } }); }); } off(event, handler) { const events = event.split(/\s+/); return this.each((_, el) => { events.forEach(evt => el.removeEventListener(evt, handler)); }); } one(event, handler) { return this.each((_, el) => { el.addEventListener(event, handler, { once: true }); }); } trigger(event, detail) { return this.each((_, el) => { el.dispatchEvent(new CustomEvent(event, { detail, bubbles: true, cancelable: true })); }); } click(fn) { return fn ? this.on('click', fn) : this.trigger('click'); } submit(fn) { return fn ? this.on('submit', fn) : this.trigger('submit'); } focus() { this.first()?.focus(); return this; } blur() { this.first()?.blur(); return this; } animate(props, duration = 300, easing = 'ease') { return new Promise(resolve => { const count = { done: 0 }; this.each((_, el) => { el.style.transition = `all ${duration}ms ${easing}`; requestAnimationFrame(() => { Object.assign(el.style, props); const onEnd = () => { el.removeEventListener('transitionend', onEnd); el.style.transition = ''; if (++count.done >= this.length) resolve(this); }; el.addEventListener('transitionend', onEnd); }); }); setTimeout(() => resolve(this), duration + 50); }); } fadeIn(duration = 300) { return this.css({ opacity: '0', display: '' }).animate({ opacity: '1' }, duration); } fadeOut(duration = 300) { return this.animate({ opacity: '0' }, duration).then(col => col.hide()); } slideToggle(duration = 300) { return this.each((_, el) => { if (el.style.display === 'none' || getComputedStyle(el).display === 'none') { el.style.display = ''; el.style.overflow = 'hidden'; const h = el.scrollHeight + 'px'; el.style.maxHeight = '0'; el.style.transition = `max-height ${duration}ms ease`; requestAnimationFrame(() => { el.style.maxHeight = h; }); setTimeout(() => { el.style.maxHeight = ''; el.style.overflow = ''; el.style.transition = ''; }, duration); } else { el.style.overflow = 'hidden'; el.style.maxHeight = el.scrollHeight + 'px'; el.style.transition = `max-height ${duration}ms ease`; requestAnimationFrame(() => { el.style.maxHeight = '0'; }); setTimeout(() => { el.style.display = 'none'; el.style.maxHeight = ''; el.style.overflow = ''; el.style.transition = ''; }, duration); } }); } serialize() { const form = this.first(); if (!form || form.tagName !== 'FORM') return ''; return new URLSearchParams(new FormData(form)).toString(); } serializeObject() { const form = this.first(); if (!form || form.tagName !== 'FORM') return {}; const obj = {}; new FormData(form).forEach((v, k) => { if (obj[k] !== undefined) { if (!Array.isArray(obj[k])) obj[k] = [obj[k]]; obj[k].push(v); } else { obj[k] = v; } }); return obj; }
|
|
12
|
+
const T = { NUM: 1, STR: 2, IDENT: 3, OP: 4, PUNC: 5, TMPL: 6, EOF: 7
|
|
13
|
+
function morph(rootEl, newHTML) { const template = document.createElement('template'); template.innerHTML = newHTML; const newRoot = template.content; const tempDiv = document.createElement('div'); while (newRoot.firstChild) tempDiv.appendChild(newRoot.firstChild); _morphChildren(rootEl, tempDiv);
|
|
14
|
+
const _registry = new Map(); const _instances = new Map(); const _resourceCache = new Map(); let _uid = 0;
|
|
15
|
+
class Router { constructor(config = {}) { this._el = null; const isFile = typeof location !== 'undefined' && location.protocol === 'file:'; this._mode = isFile ? 'hash' : (config.mode || 'history'); let rawBase = config.base; if (rawBase == null) { rawBase = (typeof window !== 'undefined' && window.__ZQ_BASE) || ''; if (!rawBase && typeof document !== 'undefined') { const baseEl = document.querySelector('base'); if (baseEl) { try { rawBase = new URL(baseEl.href).pathname; } catch { rawBase = baseEl.getAttribute('href') || ''; } if (rawBase === '/') rawBase = ''; } } } this._base = String(rawBase).replace(/\/+$/, ''); if (this._base && !this._base.startsWith('/')) this._base = '/' + this._base; this._routes = []; this._fallback = config.fallback || null; this._current = null; this._guards = { before: [], after: [] }; this._listeners = new Set(); this._instance = null; this._resolving = false; if (config.el) { this._el = typeof config.el === 'string' ? document.querySelector(config.el) : config.el; } if (config.routes) { config.routes.forEach(r => this.add(r)); } if (this._mode === 'hash') { window.addEventListener('hashchange', () => this._resolve()); } else { window.addEventListener('popstate', () => this._resolve()); } document.addEventListener('click', (e) => { if (e.metaKey || e.ctrlKey || e.shiftKey || e.altKey) return; const link = e.target.closest('[z-link]'); if (!link) return; if (link.getAttribute('target') === '_blank') return; e.preventDefault(); this.navigate(link.getAttribute('z-link')); }); if (this._el) { queueMicrotask(() => this._resolve()); } } add(route) { const keys = []; const pattern = route.path .replace(/:(\w+)/g, (_, key) => { keys.push(key); return '([^/]+)'; }) .replace(/\*/g, '(.*)'); const regex = new RegExp(`^${pattern}$`); this._routes.push({ ...route, _regex: regex, _keys: keys }); if (route.fallback) { const fbKeys = []; const fbPattern = route.fallback .replace(/:(\w+)/g, (_, key) => { fbKeys.push(key); return '([^/]+)'; }) .replace(/\*/g, '(.*)'); const fbRegex = new RegExp(`^${fbPattern}$`); this._routes.push({ ...route, path: route.fallback, _regex: fbRegex, _keys: fbKeys }); } return this; } remove(path) { this._routes = this._routes.filter(r => r.path !== path); return this; } navigate(path, options = {}) { const [cleanPath, fragment] = (path || '').split('#'); let normalized = this._normalizePath(cleanPath); const hash = fragment ? '#' + fragment : ''; if (this._mode === 'hash') { if (fragment) window.__zqScrollTarget = fragment; window.location.hash = '#' + normalized; } else { window.history.pushState(options.state || {}, '', this._base + normalized + hash); this._resolve(); } return this; } replace(path, options = {}) { const [cleanPath, fragment] = (path || '').split('#'); let normalized = this._normalizePath(cleanPath); const hash = fragment ? '#' + fragment : ''; if (this._mode === 'hash') { if (fragment) window.__zqScrollTarget = fragment; window.location.replace('#' + normalized); } else { window.history.replaceState(options.state || {}, '', this._base + normalized + hash); this._resolve(); } return this; } _normalizePath(path) { let p = path && path.startsWith('/') ? path : (path ? `/${path}` : '/'); if (this._base) { if (p === this._base) return '/'; if (p.startsWith(this._base + '/')) p = p.slice(this._base.length) || '/'; } return p; } resolve(path) { const normalized = path && path.startsWith('/') ? path : (path ? `/${path}` : '/'); return this._base + normalized; } back() { window.history.back(); return this; } forward() { window.history.forward(); return this; } go(n) { window.history.go(n); return this; } beforeEach(fn) { this._guards.before.push(fn); return this; } afterEach(fn) { this._guards.after.push(fn); return this; } onChange(fn) { this._listeners.add(fn); return () => this._listeners.delete(fn); } get current() { return this._current; } get base() { return this._base; } get path() { if (this._mode === 'hash') { const raw = window.location.hash.slice(1) || '/'; if (raw && !raw.startsWith('/')) { window.__zqScrollTarget = raw; const fallbackPath = (this._current && this._current.path) || '/'; window.location.replace('#' + fallbackPath); return fallbackPath; } return raw; } let pathname = window.location.pathname || '/'; if (pathname.length > 1 && pathname.endsWith('/')) { pathname = pathname.slice(0, -1); } if (this._base) { if (pathname === this._base) return '/'; if (pathname.startsWith(this._base + '/')) { return pathname.slice(this._base.length) || '/'; } } return pathname; } get query() { const search = this._mode === 'hash' ? (window.location.hash.split('?')[1] || '') : window.location.search.slice(1); return Object.fromEntries(new URLSearchParams(search)); } async _resolve() { if (this._resolving) return; this._resolving = true; try { await this.__resolve(); } finally { this._resolving = false; } } async __resolve() { const fullPath = this.path; const [pathPart, queryString] = fullPath.split('?'); const path = pathPart || '/'; const query = Object.fromEntries(new URLSearchParams(queryString || '')); let matched = null; let params = {}; for (const route of this._routes) { const m = path.match(route._regex); if (m) { matched = route; route._keys.forEach((key, i) => { params[key] = m[i + 1]; }); break; } } if (!matched && this._fallback) { matched = { component: this._fallback, path: '*', _keys: [], _regex: /.*/ }; } if (!matched) return; const to = { route: matched, params, query, path }; const from = this._current; for (const guard of this._guards.before) { try { const result = await guard(to, from); if (result === false) return; if (typeof result === 'string') { return this.navigate(result); } } catch (err) { reportError(ErrorCode.ROUTER_GUARD, 'Before-guard threw', { to, from }, err); return; } } if (matched.load) { try { await matched.load(); } catch (err) { reportError(ErrorCode.ROUTER_LOAD, `Failed to load module for route "${matched.path}"`, { path: matched.path }, err); return; } } this._current = to; if (this._el && matched.component) { if (this._instance) { this._instance.destroy(); this._instance = null; } this._el.innerHTML = ''; const props = { ...params, $route: to, $query: query, $params: params }; if (typeof matched.component === 'string') { const container = document.createElement(matched.component); this._el.appendChild(container); this._instance = mount(container, matched.component, props); } else if (typeof matched.component === 'function') { this._el.innerHTML = matched.component(to); } } for (const guard of this._guards.after) { await guard(to, from); } this._listeners.forEach(fn => fn(to, from)); } destroy() { if (this._instance) this._instance.destroy(); this._listeners.clear(); this._routes = []; this._guards = { before: [], after: [] }; }
|
|
16
|
+
class Store { constructor(config = {}) { this._subscribers = new Map(); this._wildcards = new Set(); this._actions = config.actions || {}; this._getters = config.getters || {}; this._middleware = []; this._history = []; this._debug = config.debug || false; const initial = typeof config.state === 'function' ? config.state() : { ...(config.state || {}) }; this.state = reactive(initial, (key, value, old) => { const subs = this._subscribers.get(key); if (subs) subs.forEach(fn => { try { fn(value, old, key); } catch (err) { reportError(ErrorCode.STORE_SUBSCRIBE, `Subscriber for "${key}" threw`, { key }, err); } }); this._wildcards.forEach(fn => { try { fn(key, value, old); } catch (err) { reportError(ErrorCode.STORE_SUBSCRIBE, 'Wildcard subscriber threw', { key }, err); } }); }); this.getters = {}; for (const [name, fn] of Object.entries(this._getters)) { Object.defineProperty(this.getters, name, { get: () => fn(this.state.__raw || this.state), enumerable: true }); } } dispatch(name, ...args) { const action = this._actions[name]; if (!action) { reportError(ErrorCode.STORE_ACTION, `Unknown action "${name}"`, { action: name, args }); return; } for (const mw of this._middleware) { try { const result = mw(name, args, this.state); if (result === false) return; } catch (err) { reportError(ErrorCode.STORE_MIDDLEWARE, `Middleware threw during "${name}"`, { action: name }, err); return; } } if (this._debug) { console.log(`%c[Store] ${name}`, 'color: #4CAF50; font-weight: bold;', ...args); } try { const result = action(this.state, ...args); this._history.push({ action: name, args, timestamp: Date.now() }); return result; } catch (err) { reportError(ErrorCode.STORE_ACTION, `Action "${name}" threw`, { action: name, args }, err); } } subscribe(keyOrFn, fn) { if (typeof keyOrFn === 'function') { this._wildcards.add(keyOrFn); return () => this._wildcards.delete(keyOrFn); } if (!this._subscribers.has(keyOrFn)) { this._subscribers.set(keyOrFn, new Set()); } this._subscribers.get(keyOrFn).add(fn); return () => this._subscribers.get(keyOrFn)?.delete(fn); } snapshot() { return JSON.parse(JSON.stringify(this.state.__raw || this.state)); } replaceState(newState) { const raw = this.state.__raw || this.state; for (const key of Object.keys(raw)) { delete this.state[key]; } Object.assign(this.state, newState); } use(fn) { this._middleware.push(fn); return this; } get history() { return [...this._history]; } reset(initialState) { this.replaceState(initialState); this._history = []; }
|
|
17
|
+
const _config = { baseURL: '', headers: { 'Content-Type': 'application/json' }, timeout: 30000,
|
|
15
18
|
function debounce(fn, ms = 250) { let timer; const debounced = (...args) => { clearTimeout(timer); timer = setTimeout(() => fn(...args), ms); }; debounced.cancel = () => clearTimeout(timer); return debounced;
|
|
16
|
-
function $(selector, context) { if (typeof selector === 'function') { query.ready(selector); return; } return query(selector, context);
|
|
19
|
+
function $(selector, context) { if (typeof selector === 'function') { query.ready(selector); return; } return query(selector, context);
|
|
17
20
|
})(typeof window !== 'undefined' ? window : globalThis);
|
package/index.d.ts
CHANGED
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
* Lightweight modern frontend library — jQuery-like selectors, reactive
|
|
5
5
|
* components, SPA router, state management, HTTP client & utilities.
|
|
6
6
|
*
|
|
7
|
-
* @version 0.
|
|
7
|
+
* @version 0.6.3
|
|
8
8
|
* @license MIT
|
|
9
9
|
* @see https://z-query.com/docs
|
|
10
10
|
*/
|
|
@@ -38,6 +38,11 @@ export class ZQueryCollection {
|
|
|
38
38
|
*/
|
|
39
39
|
map<T>(fn: (this: Element, index: number, element: Element) => T): T[];
|
|
40
40
|
|
|
41
|
+
/**
|
|
42
|
+
* Iterate elements with Array-style `forEach`. Returns `this` for chaining.
|
|
43
|
+
*/
|
|
44
|
+
forEach(fn: (element: Element, index: number, elements: Element[]) => void): this;
|
|
45
|
+
|
|
41
46
|
/** First raw element, or `null`. */
|
|
42
47
|
first(): Element | null;
|
|
43
48
|
|
|
@@ -384,6 +389,20 @@ interface ComponentDefinition {
|
|
|
384
389
|
/** Called when the component is destroyed. Clean up subscriptions here. */
|
|
385
390
|
destroyed?(this: ComponentInstance): void;
|
|
386
391
|
|
|
392
|
+
/**
|
|
393
|
+
* Computed properties — lazy getters derived from state.
|
|
394
|
+
* Each function receives the raw state as its argument.
|
|
395
|
+
* Access via `this.computed.name` in methods and templates.
|
|
396
|
+
*/
|
|
397
|
+
computed?: Record<string, (state: Record<string, any>) => any>;
|
|
398
|
+
|
|
399
|
+
/**
|
|
400
|
+
* Watch state keys for changes.
|
|
401
|
+
* Keys support dot-path notation (e.g. `'user.name'`).
|
|
402
|
+
* Handler receives `(newValue, oldValue)`.
|
|
403
|
+
*/
|
|
404
|
+
watch?: Record<string, ((this: ComponentInstance, newVal: any, oldVal: any) => void) | { handler: (this: ComponentInstance, newVal: any, oldVal: any) => void }>;
|
|
405
|
+
|
|
387
406
|
/** Additional keys become instance methods (bound to the instance). */
|
|
388
407
|
[method: string]: any;
|
|
389
408
|
}
|
|
@@ -414,6 +433,12 @@ interface ComponentInstance {
|
|
|
414
433
|
/** Active page id derived from route param (when using `pages` config). */
|
|
415
434
|
activePage: string;
|
|
416
435
|
|
|
436
|
+
/**
|
|
437
|
+
* Computed properties — lazy getters derived from state.
|
|
438
|
+
* Defined via `computed` in the component definition.
|
|
439
|
+
*/
|
|
440
|
+
readonly computed: Record<string, any>;
|
|
441
|
+
|
|
417
442
|
/** Merge partial state (triggers re-render). */
|
|
418
443
|
setState(partial: Record<string, any>): void;
|
|
419
444
|
|
|
@@ -491,6 +516,85 @@ interface StyleOptions {
|
|
|
491
516
|
export function style(urls: string | string[], opts?: StyleOptions): StyleHandle;
|
|
492
517
|
|
|
493
518
|
|
|
519
|
+
// ---------------------------------------------------------------------------
|
|
520
|
+
// DOM Diffing (Morphing)
|
|
521
|
+
// ---------------------------------------------------------------------------
|
|
522
|
+
|
|
523
|
+
/**
|
|
524
|
+
* Morph an existing DOM element's children to match new HTML.
|
|
525
|
+
* Only touches nodes that actually differ — preserves focus, scroll
|
|
526
|
+
* positions, video playback, and other live DOM state.
|
|
527
|
+
*
|
|
528
|
+
* Use `z-key="uniqueId"` attributes on list items for keyed reconciliation.
|
|
529
|
+
*
|
|
530
|
+
* @param rootEl The live DOM container to patch.
|
|
531
|
+
* @param newHTML The desired HTML string.
|
|
532
|
+
*/
|
|
533
|
+
export function morph(rootEl: Element, newHTML: string): void;
|
|
534
|
+
|
|
535
|
+
|
|
536
|
+
// ---------------------------------------------------------------------------
|
|
537
|
+
// Safe Expression Evaluator
|
|
538
|
+
// ---------------------------------------------------------------------------
|
|
539
|
+
|
|
540
|
+
/**
|
|
541
|
+
* CSP-safe expression evaluator. Parses and evaluates JS expressions
|
|
542
|
+
* without `eval()` or `new Function()`. Used internally by directives.
|
|
543
|
+
*
|
|
544
|
+
* @param expr Expression string.
|
|
545
|
+
* @param scope Array of scope objects checked in order for identifier resolution.
|
|
546
|
+
* @returns Evaluation result, or `undefined` on error.
|
|
547
|
+
*/
|
|
548
|
+
export function safeEval(expr: string, scope: object[]): any;
|
|
549
|
+
|
|
550
|
+
|
|
551
|
+
// ---------------------------------------------------------------------------
|
|
552
|
+
// SSR (Server-Side Rendering)
|
|
553
|
+
// ---------------------------------------------------------------------------
|
|
554
|
+
|
|
555
|
+
/** SSR application instance for server-side component rendering. */
|
|
556
|
+
interface SSRApp {
|
|
557
|
+
/** Register a component for SSR. */
|
|
558
|
+
component(name: string, definition: ComponentDefinition): SSRApp;
|
|
559
|
+
|
|
560
|
+
/**
|
|
561
|
+
* Render a component to an HTML string.
|
|
562
|
+
* @param componentName Registered component name.
|
|
563
|
+
* @param props Props to pass to the component.
|
|
564
|
+
* @param options Rendering options.
|
|
565
|
+
*/
|
|
566
|
+
renderToString(
|
|
567
|
+
componentName: string,
|
|
568
|
+
props?: Record<string, any>,
|
|
569
|
+
options?: { hydrate?: boolean },
|
|
570
|
+
): Promise<string>;
|
|
571
|
+
|
|
572
|
+
/**
|
|
573
|
+
* Render a full HTML page with a component mounted in a shell.
|
|
574
|
+
*/
|
|
575
|
+
renderPage(options: {
|
|
576
|
+
component?: string;
|
|
577
|
+
props?: Record<string, any>;
|
|
578
|
+
title?: string;
|
|
579
|
+
styles?: string[];
|
|
580
|
+
scripts?: string[];
|
|
581
|
+
lang?: string;
|
|
582
|
+
meta?: string;
|
|
583
|
+
bodyAttrs?: string;
|
|
584
|
+
}): Promise<string>;
|
|
585
|
+
}
|
|
586
|
+
|
|
587
|
+
/** Create an SSR application instance. */
|
|
588
|
+
export function createSSRApp(): SSRApp;
|
|
589
|
+
|
|
590
|
+
/**
|
|
591
|
+
* Quick one-shot render of a component definition to an HTML string.
|
|
592
|
+
* @param definition Component definition object.
|
|
593
|
+
* @param props Props to pass.
|
|
594
|
+
*/
|
|
595
|
+
export function renderToString(definition: ComponentDefinition, props?: Record<string, any>): string;
|
|
596
|
+
|
|
597
|
+
|
|
494
598
|
// ---------------------------------------------------------------------------
|
|
495
599
|
// Directive System
|
|
496
600
|
// ---------------------------------------------------------------------------
|
|
@@ -512,6 +616,11 @@ export function style(urls: string | string[], opts?: StyleOptions): StyleHandle
|
|
|
512
616
|
// n in 5 Number range → [1, 2, 3, 4, 5].
|
|
513
617
|
// (val, key) in object Object iteration → {key, value} entries.
|
|
514
618
|
//
|
|
619
|
+
// z-key="uniqueId" Keyed reconciliation for list items.
|
|
620
|
+
// Preserves DOM nodes across reorders. Use inside
|
|
621
|
+
// z-for to give each item a stable identity.
|
|
622
|
+
// Example: <li z-for="item in items" z-key="{{item.id}}">
|
|
623
|
+
//
|
|
515
624
|
// z-show="expression" Toggle `display: none` (element stays in DOM).
|
|
516
625
|
//
|
|
517
626
|
// ─── Attribute Directives ───────────────────────────────────────────────
|
|
@@ -571,6 +680,20 @@ export function style(urls: string | string[], opts?: StyleOptions): StyleHandle
|
|
|
571
680
|
// z-pre Skip all directive processing for this element
|
|
572
681
|
// and its descendants.
|
|
573
682
|
//
|
|
683
|
+
// ─── Slot System ────────────────────────────────────────────────────────
|
|
684
|
+
//
|
|
685
|
+
// <slot> Default slot — replaced with child content
|
|
686
|
+
// passed by the parent component.
|
|
687
|
+
// <slot name="header"> Named slot — replaced with child content that
|
|
688
|
+
// has a matching slot="header" attribute.
|
|
689
|
+
// <slot>fallback</slot> Fallback content shown when no slot content provided.
|
|
690
|
+
//
|
|
691
|
+
// Parent usage:
|
|
692
|
+
// <my-component>
|
|
693
|
+
// <h1 slot="header">Title</h1> (→ named slot "header")
|
|
694
|
+
// <p>Body text</p> (→ default slot)
|
|
695
|
+
// </my-component>
|
|
696
|
+
//
|
|
574
697
|
// ─── Processing Order ───────────────────────────────────────────────────
|
|
575
698
|
//
|
|
576
699
|
// 1. z-for (pre-innerHTML expansion)
|
|
@@ -1046,22 +1169,125 @@ interface EventBus {
|
|
|
1046
1169
|
export const bus: EventBus;
|
|
1047
1170
|
|
|
1048
1171
|
|
|
1172
|
+
// ---------------------------------------------------------------------------
|
|
1173
|
+
// Error Handling
|
|
1174
|
+
// ---------------------------------------------------------------------------
|
|
1175
|
+
|
|
1176
|
+
/** All structured error codes used by zQuery. */
|
|
1177
|
+
export const ErrorCode: {
|
|
1178
|
+
// Reactive
|
|
1179
|
+
readonly REACTIVE_CALLBACK: 'ZQ_REACTIVE_CALLBACK';
|
|
1180
|
+
readonly SIGNAL_CALLBACK: 'ZQ_SIGNAL_CALLBACK';
|
|
1181
|
+
readonly EFFECT_EXEC: 'ZQ_EFFECT_EXEC';
|
|
1182
|
+
|
|
1183
|
+
// Expression parser
|
|
1184
|
+
readonly EXPR_PARSE: 'ZQ_EXPR_PARSE';
|
|
1185
|
+
readonly EXPR_EVAL: 'ZQ_EXPR_EVAL';
|
|
1186
|
+
readonly EXPR_UNSAFE_ACCESS: 'ZQ_EXPR_UNSAFE_ACCESS';
|
|
1187
|
+
|
|
1188
|
+
// Component
|
|
1189
|
+
readonly COMP_INVALID_NAME: 'ZQ_COMP_INVALID_NAME';
|
|
1190
|
+
readonly COMP_NOT_FOUND: 'ZQ_COMP_NOT_FOUND';
|
|
1191
|
+
readonly COMP_MOUNT_TARGET: 'ZQ_COMP_MOUNT_TARGET';
|
|
1192
|
+
readonly COMP_RENDER: 'ZQ_COMP_RENDER';
|
|
1193
|
+
readonly COMP_LIFECYCLE: 'ZQ_COMP_LIFECYCLE';
|
|
1194
|
+
readonly COMP_RESOURCE: 'ZQ_COMP_RESOURCE';
|
|
1195
|
+
readonly COMP_DIRECTIVE: 'ZQ_COMP_DIRECTIVE';
|
|
1196
|
+
|
|
1197
|
+
// Router
|
|
1198
|
+
readonly ROUTER_LOAD: 'ZQ_ROUTER_LOAD';
|
|
1199
|
+
readonly ROUTER_GUARD: 'ZQ_ROUTER_GUARD';
|
|
1200
|
+
readonly ROUTER_RESOLVE: 'ZQ_ROUTER_RESOLVE';
|
|
1201
|
+
|
|
1202
|
+
// Store
|
|
1203
|
+
readonly STORE_ACTION: 'ZQ_STORE_ACTION';
|
|
1204
|
+
readonly STORE_MIDDLEWARE: 'ZQ_STORE_MIDDLEWARE';
|
|
1205
|
+
readonly STORE_SUBSCRIBE: 'ZQ_STORE_SUBSCRIBE';
|
|
1206
|
+
|
|
1207
|
+
// HTTP
|
|
1208
|
+
readonly HTTP_REQUEST: 'ZQ_HTTP_REQUEST';
|
|
1209
|
+
readonly HTTP_TIMEOUT: 'ZQ_HTTP_TIMEOUT';
|
|
1210
|
+
readonly HTTP_INTERCEPTOR: 'ZQ_HTTP_INTERCEPTOR';
|
|
1211
|
+
readonly HTTP_PARSE: 'ZQ_HTTP_PARSE';
|
|
1212
|
+
|
|
1213
|
+
// General
|
|
1214
|
+
readonly INVALID_ARGUMENT: 'ZQ_INVALID_ARGUMENT';
|
|
1215
|
+
};
|
|
1216
|
+
|
|
1217
|
+
/** Union of all error code string values. */
|
|
1218
|
+
export type ErrorCodeValue = typeof ErrorCode[keyof typeof ErrorCode];
|
|
1219
|
+
|
|
1220
|
+
/** Structured error class used throughout zQuery. */
|
|
1221
|
+
export class ZQueryError extends Error {
|
|
1222
|
+
readonly name: 'ZQueryError';
|
|
1223
|
+
/** Machine-readable error code (e.g. `'ZQ_COMP_RENDER'`). */
|
|
1224
|
+
readonly code: ErrorCodeValue;
|
|
1225
|
+
/** Extra contextual data (component name, expression string, etc.). */
|
|
1226
|
+
readonly context: Record<string, any>;
|
|
1227
|
+
/** Original error that caused this one, if any. */
|
|
1228
|
+
readonly cause?: Error;
|
|
1229
|
+
|
|
1230
|
+
constructor(
|
|
1231
|
+
code: ErrorCodeValue,
|
|
1232
|
+
message: string,
|
|
1233
|
+
context?: Record<string, any>,
|
|
1234
|
+
cause?: Error,
|
|
1235
|
+
);
|
|
1236
|
+
}
|
|
1237
|
+
|
|
1238
|
+
/** Error handler callback type. */
|
|
1239
|
+
export type ZQueryErrorHandler = (error: ZQueryError) => void;
|
|
1240
|
+
|
|
1241
|
+
/**
|
|
1242
|
+
* Register a global error handler. Called whenever zQuery catches an
|
|
1243
|
+
* error internally. Pass `null` to remove.
|
|
1244
|
+
*/
|
|
1245
|
+
export function onError(handler: ZQueryErrorHandler | null): void;
|
|
1246
|
+
|
|
1247
|
+
/**
|
|
1248
|
+
* Report an error through the global handler and console.
|
|
1249
|
+
* Non-throwing — used for recoverable errors in callbacks, lifecycle hooks, etc.
|
|
1250
|
+
*/
|
|
1251
|
+
export function reportError(
|
|
1252
|
+
code: ErrorCodeValue,
|
|
1253
|
+
message: string,
|
|
1254
|
+
context?: Record<string, any>,
|
|
1255
|
+
cause?: Error,
|
|
1256
|
+
): void;
|
|
1257
|
+
|
|
1258
|
+
/**
|
|
1259
|
+
* Wrap a callback so that thrown errors are caught, reported via `reportError`,
|
|
1260
|
+
* and don't crash the current execution context.
|
|
1261
|
+
*/
|
|
1262
|
+
export function guardCallback<T extends (...args: any[]) => any>(
|
|
1263
|
+
fn: T,
|
|
1264
|
+
code: ErrorCodeValue,
|
|
1265
|
+
context?: Record<string, any>,
|
|
1266
|
+
): (...args: Parameters<T>) => ReturnType<T> | undefined;
|
|
1267
|
+
|
|
1268
|
+
/**
|
|
1269
|
+
* Validate a required value is defined and of the expected type.
|
|
1270
|
+
* Throws `ZQueryError` with `INVALID_ARGUMENT` on failure.
|
|
1271
|
+
*/
|
|
1272
|
+
export function validate(value: any, name: string, expectedType?: string): void;
|
|
1273
|
+
|
|
1274
|
+
|
|
1049
1275
|
// ---------------------------------------------------------------------------
|
|
1050
1276
|
// $ — Main function & namespace
|
|
1051
1277
|
// ---------------------------------------------------------------------------
|
|
1052
1278
|
|
|
1053
1279
|
/**
|
|
1054
|
-
* Main selector / DOM-ready function.
|
|
1280
|
+
* Main selector / DOM-ready function — always returns a `ZQueryCollection` (like jQuery).
|
|
1055
1281
|
*
|
|
1056
|
-
* - `$('selector')` →
|
|
1057
|
-
* - `$('<div>…</div>')` →
|
|
1058
|
-
* - `$(element)` →
|
|
1282
|
+
* - `$('selector')` → ZQueryCollection via `querySelectorAll`
|
|
1283
|
+
* - `$('<div>…</div>')` → ZQueryCollection from created elements
|
|
1284
|
+
* - `$(element)` → ZQueryCollection wrapping the element
|
|
1059
1285
|
* - `$(fn)` → DOMContentLoaded shorthand
|
|
1060
1286
|
*/
|
|
1061
1287
|
interface ZQueryStatic {
|
|
1062
|
-
(selector: string, context?: string | Element):
|
|
1063
|
-
(element: Element):
|
|
1064
|
-
(nodeList: NodeList | HTMLCollection | Element[]):
|
|
1288
|
+
(selector: string, context?: string | Element): ZQueryCollection;
|
|
1289
|
+
(element: Element): ZQueryCollection;
|
|
1290
|
+
(nodeList: NodeList | HTMLCollection | Element[]): ZQueryCollection;
|
|
1065
1291
|
(fn: () => void): void;
|
|
1066
1292
|
|
|
1067
1293
|
// -- Collection selector -------------------------------------------------
|
|
@@ -1082,12 +1308,14 @@ interface ZQueryStatic {
|
|
|
1082
1308
|
id(id: string): Element | null;
|
|
1083
1309
|
/** `document.querySelector('.name')` */
|
|
1084
1310
|
class(name: string): Element | null;
|
|
1085
|
-
/** `document.getElementsByClassName(name)` as
|
|
1086
|
-
classes(name: string):
|
|
1087
|
-
/** `document.getElementsByTagName(name)` as
|
|
1088
|
-
tag(name: string):
|
|
1089
|
-
/**
|
|
1090
|
-
|
|
1311
|
+
/** `document.getElementsByClassName(name)` as `ZQueryCollection`. */
|
|
1312
|
+
classes(name: string): ZQueryCollection;
|
|
1313
|
+
/** `document.getElementsByTagName(name)` as `ZQueryCollection`. */
|
|
1314
|
+
tag(name: string): ZQueryCollection;
|
|
1315
|
+
/** `document.getElementsByName(name)` as `ZQueryCollection`. */
|
|
1316
|
+
name(name: string): ZQueryCollection;
|
|
1317
|
+
/** Children of `#parentId` as `ZQueryCollection`. */
|
|
1318
|
+
children(parentId: string): ZQueryCollection;
|
|
1091
1319
|
|
|
1092
1320
|
// -- Static helpers ------------------------------------------------------
|
|
1093
1321
|
/**
|
|
@@ -1117,6 +1345,7 @@ interface ZQueryStatic {
|
|
|
1117
1345
|
|
|
1118
1346
|
// -- Reactive ------------------------------------------------------------
|
|
1119
1347
|
reactive: typeof reactive;
|
|
1348
|
+
Signal: typeof Signal;
|
|
1120
1349
|
signal: typeof signal;
|
|
1121
1350
|
computed: typeof computed;
|
|
1122
1351
|
effect: typeof effect;
|
|
@@ -1130,6 +1359,8 @@ interface ZQueryStatic {
|
|
|
1130
1359
|
/** Returns all registered component definitions. */
|
|
1131
1360
|
components: typeof getRegistry;
|
|
1132
1361
|
style: typeof style;
|
|
1362
|
+
morph: typeof morph;
|
|
1363
|
+
safeEval: typeof safeEval;
|
|
1133
1364
|
|
|
1134
1365
|
// -- Router --------------------------------------------------------------
|
|
1135
1366
|
router: typeof createRouter;
|
|
@@ -1147,6 +1378,14 @@ interface ZQueryStatic {
|
|
|
1147
1378
|
patch: HttpClient['patch'];
|
|
1148
1379
|
delete: HttpClient['delete'];
|
|
1149
1380
|
|
|
1381
|
+
// -- Error Handling ------------------------------------------------------
|
|
1382
|
+
/** Register a global error handler (or pass `null` to remove). */
|
|
1383
|
+
onError: typeof onError;
|
|
1384
|
+
/** Structured error class. */
|
|
1385
|
+
ZQueryError: typeof ZQueryError;
|
|
1386
|
+
/** Frozen map of all error code constants. */
|
|
1387
|
+
ErrorCode: typeof ErrorCode;
|
|
1388
|
+
|
|
1150
1389
|
// -- Utilities -----------------------------------------------------------
|
|
1151
1390
|
debounce: typeof debounce;
|
|
1152
1391
|
throttle: typeof throttle;
|
package/index.js
CHANGED
|
@@ -10,17 +10,20 @@
|
|
|
10
10
|
*/
|
|
11
11
|
|
|
12
12
|
import { query, queryAll, ZQueryCollection } from './src/core.js';
|
|
13
|
-
import { reactive, signal, computed, effect } from './src/reactive.js';
|
|
13
|
+
import { reactive, Signal, signal, computed, effect } from './src/reactive.js';
|
|
14
14
|
import { component, mount, mountAll, getInstance, destroy, getRegistry, style } from './src/component.js';
|
|
15
15
|
import { createRouter, getRouter } from './src/router.js';
|
|
16
16
|
import { createStore, getStore } from './src/store.js';
|
|
17
17
|
import { http } from './src/http.js';
|
|
18
|
+
import { morph } from './src/diff.js';
|
|
19
|
+
import { safeEval } from './src/expression.js';
|
|
18
20
|
import {
|
|
19
21
|
debounce, throttle, pipe, once, sleep,
|
|
20
22
|
escapeHtml, html, trust, uuid, camelCase, kebabCase,
|
|
21
23
|
deepClone, deepMerge, isEqual, param, parseQuery,
|
|
22
24
|
storage, session, bus,
|
|
23
25
|
} from './src/utils.js';
|
|
26
|
+
import { ZQueryError, ErrorCode, onError, reportError } from './src/errors.js';
|
|
24
27
|
|
|
25
28
|
|
|
26
29
|
// ---------------------------------------------------------------------------
|
|
@@ -28,16 +31,16 @@ import {
|
|
|
28
31
|
// ---------------------------------------------------------------------------
|
|
29
32
|
|
|
30
33
|
/**
|
|
31
|
-
* Main selector function
|
|
34
|
+
* Main selector function — always returns a ZQueryCollection (like jQuery).
|
|
32
35
|
*
|
|
33
|
-
* $('selector') →
|
|
34
|
-
* $('<div>hello</div>') →
|
|
35
|
-
* $(element) →
|
|
36
|
+
* $('selector') → ZQueryCollection (querySelectorAll)
|
|
37
|
+
* $('<div>hello</div>') → ZQueryCollection from created elements
|
|
38
|
+
* $(element) → ZQueryCollection wrapping the element
|
|
36
39
|
* $(fn) → DOMContentLoaded shorthand
|
|
37
40
|
*
|
|
38
41
|
* @param {string|Element|NodeList|Function} selector
|
|
39
42
|
* @param {string|Element} [context]
|
|
40
|
-
* @returns {
|
|
43
|
+
* @returns {ZQueryCollection}
|
|
41
44
|
*/
|
|
42
45
|
function $(selector, context) {
|
|
43
46
|
// $(fn) → DOM ready shorthand
|
|
@@ -49,11 +52,14 @@ function $(selector, context) {
|
|
|
49
52
|
}
|
|
50
53
|
|
|
51
54
|
|
|
52
|
-
// --- Quick refs
|
|
55
|
+
// --- Quick refs (DOM selectors) --------------------------------------------
|
|
53
56
|
$.id = query.id;
|
|
54
57
|
$.class = query.class;
|
|
55
58
|
$.classes = query.classes;
|
|
56
59
|
$.tag = query.tag;
|
|
60
|
+
Object.defineProperty($, 'name', {
|
|
61
|
+
value: query.name, writable: true, configurable: true
|
|
62
|
+
});
|
|
57
63
|
$.children = query.children;
|
|
58
64
|
|
|
59
65
|
// --- Collection selector ---------------------------------------------------
|
|
@@ -82,6 +88,7 @@ $.fn = query.fn;
|
|
|
82
88
|
|
|
83
89
|
// --- Reactive primitives ---------------------------------------------------
|
|
84
90
|
$.reactive = reactive;
|
|
91
|
+
$.Signal = Signal;
|
|
85
92
|
$.signal = signal;
|
|
86
93
|
$.computed = computed;
|
|
87
94
|
$.effect = effect;
|
|
@@ -94,6 +101,8 @@ $.getInstance = getInstance;
|
|
|
94
101
|
$.destroy = destroy;
|
|
95
102
|
$.components = getRegistry;
|
|
96
103
|
$.style = style;
|
|
104
|
+
$.morph = morph;
|
|
105
|
+
$.safeEval = safeEval;
|
|
97
106
|
|
|
98
107
|
// --- Router ----------------------------------------------------------------
|
|
99
108
|
$.router = createRouter;
|
|
@@ -132,6 +141,11 @@ $.storage = storage;
|
|
|
132
141
|
$.session = session;
|
|
133
142
|
$.bus = bus;
|
|
134
143
|
|
|
144
|
+
// --- Error handling --------------------------------------------------------
|
|
145
|
+
$.onError = onError;
|
|
146
|
+
$.ZQueryError = ZQueryError;
|
|
147
|
+
$.ErrorCode = ErrorCode;
|
|
148
|
+
|
|
135
149
|
// --- Meta ------------------------------------------------------------------
|
|
136
150
|
$.version = '__VERSION__';
|
|
137
151
|
$.meta = {}; // populated at build time by CLI bundler
|
|
@@ -161,11 +175,14 @@ export {
|
|
|
161
175
|
$ as zQuery,
|
|
162
176
|
ZQueryCollection,
|
|
163
177
|
queryAll,
|
|
164
|
-
reactive, signal, computed, effect,
|
|
178
|
+
reactive, Signal, signal, computed, effect,
|
|
165
179
|
component, mount, mountAll, getInstance, destroy, getRegistry, style,
|
|
180
|
+
morph,
|
|
181
|
+
safeEval,
|
|
166
182
|
createRouter, getRouter,
|
|
167
183
|
createStore, getStore,
|
|
168
184
|
http,
|
|
185
|
+
ZQueryError, ErrorCode, onError, reportError,
|
|
169
186
|
debounce, throttle, pipe, once, sleep,
|
|
170
187
|
escapeHtml, html, trust, uuid, camelCase, kebabCase,
|
|
171
188
|
deepClone, deepMerge, isEqual, param, parseQuery,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "zero-query",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.6.3",
|
|
4
4
|
"description": "Lightweight modern frontend library — jQuery-like selectors, reactive components, SPA router, and state management with zero dependencies.",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"types": "index.d.ts",
|
|
@@ -21,7 +21,9 @@
|
|
|
21
21
|
"dev": "node cli/index.js dev zquery-website",
|
|
22
22
|
"dev-lib": "node cli/index.js build --watch",
|
|
23
23
|
"bundle": "node cli/index.js bundle",
|
|
24
|
-
"bundle:app": "node cli/index.js bundle zquery-website"
|
|
24
|
+
"bundle:app": "node cli/index.js bundle zquery-website --minimal",
|
|
25
|
+
"test": "vitest run",
|
|
26
|
+
"test:watch": "vitest"
|
|
25
27
|
},
|
|
26
28
|
"keywords": [
|
|
27
29
|
"dom",
|
|
@@ -52,5 +54,9 @@
|
|
|
52
54
|
},
|
|
53
55
|
"dependencies": {
|
|
54
56
|
"zero-http": "^0.2.3"
|
|
57
|
+
},
|
|
58
|
+
"devDependencies": {
|
|
59
|
+
"jsdom": "^28.1.0",
|
|
60
|
+
"vitest": "^4.0.18"
|
|
55
61
|
}
|
|
56
62
|
}
|