jq79 0.4.15 → 0.4.17
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 +20 -1
- package/dist/jq79.cjs +12 -12
- package/dist/jq79.cjs.map +1 -1
- package/dist/jq79.d.ts +19 -2
- package/dist/jq79.global.js +12 -12
- package/dist/jq79.global.js.map +1 -1
- package/dist/jq79.js +12 -12
- package/dist/jq79.js.map +1 -1
- package/package.json +1 -1
- package/src/jq79.ts +117 -9
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "jq79",
|
|
3
|
-
"version": "0.4.
|
|
3
|
+
"version": "0.4.17",
|
|
4
4
|
"description": "Mini reactive component library: single-file components, Svelte-style setup scripts, fine-grained proxy reactivity. Single-file build, zero dependencies.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"reactive",
|
package/src/jq79.ts
CHANGED
|
@@ -7,6 +7,14 @@ import { transformSetupScript, transformFactoryScript, parsePropsPattern, parseF
|
|
|
7
7
|
|
|
8
8
|
export { $, $$, $create } from "./dom"
|
|
9
9
|
export { $reactive } from "./reactive"
|
|
10
|
+
|
|
11
|
+
// the package version, substituted at build time (tsup/vitest `define`, read
|
|
12
|
+
// from package.json - releases bump it there and nowhere else). The typeof
|
|
13
|
+
// guard is what keeps the raw source runnable: tests and any bundler that
|
|
14
|
+
// doesn't define it see a bare identifier, not a ReferenceError
|
|
15
|
+
declare const __JQ79_VERSION__: string
|
|
16
|
+
const VERSION = typeof __JQ79_VERSION__ === "string" ? __JQ79_VERSION__ : "0.0.0-dev"
|
|
17
|
+
|
|
10
18
|
type TemplateNode = {
|
|
11
19
|
tag: string
|
|
12
20
|
attrs: Record<string, string>
|
|
@@ -1460,9 +1468,11 @@ const componentPartsFrom = (elements: Element[], hashSource: string): ComponentP
|
|
|
1460
1468
|
return { template, scripts, styles }
|
|
1461
1469
|
}
|
|
1462
1470
|
|
|
1463
|
-
// loads .html URLs as components, delegating anything else to native import()
|
|
1471
|
+
// loads .html URLs as components, delegating anything else to native import().
|
|
1472
|
+
// Goes to fetchComponent rather than Component79.fetch because an import wants
|
|
1473
|
+
// the component, not the chainable handle the public entry point returns
|
|
1464
1474
|
const importResource = (url: string): Promise<any> =>
|
|
1465
|
-
/\.html?([?#]|$)/.test(url) ?
|
|
1475
|
+
/\.html?([?#]|$)/.test(url) ? fetchComponent(url) : import(url)
|
|
1466
1476
|
|
|
1467
1477
|
// ---------------------------------------------------------------------------
|
|
1468
1478
|
// naming scripts for devtools
|
|
@@ -1773,6 +1783,10 @@ const fetchComponent = async (url: string): Promise<Component79> => {
|
|
|
1773
1783
|
// jq79.detach() // detach, keeping state - mount() re-attaches
|
|
1774
1784
|
// .destroy() // dispose effects and remove styles
|
|
1775
1785
|
export class Component79 {
|
|
1786
|
+
// the version of jq79 this class came from, so a page can tell which build it
|
|
1787
|
+
// loaded (a CDN <script> pins nothing on its own)
|
|
1788
|
+
static readonly version: string = VERSION
|
|
1789
|
+
|
|
1776
1790
|
template: TemplateNode[]
|
|
1777
1791
|
scripts: TagBlock[]
|
|
1778
1792
|
styles: TagBlock[]
|
|
@@ -1903,13 +1917,23 @@ export class Component79 {
|
|
|
1903
1917
|
return true
|
|
1904
1918
|
}
|
|
1905
1919
|
|
|
1906
|
-
|
|
1907
|
-
|
|
1908
|
-
//
|
|
1909
|
-
//
|
|
1910
|
-
//
|
|
1911
|
-
|
|
1912
|
-
|
|
1920
|
+
// downloads and parses a component, handing back a PendingComponent79: a
|
|
1921
|
+
// handle that can be mounted right away, and that awaits to this component -
|
|
1922
|
+
// so both of these are the whole program
|
|
1923
|
+
//
|
|
1924
|
+
// Component79.fetch("./app.html").mount("main")
|
|
1925
|
+
// const app = await Component79.fetch("./app.html")
|
|
1926
|
+
static fetch(url: string): PendingComponent79 {
|
|
1927
|
+
if (Array.isArray(url)) throw new TypeError("Component79.fetch takes one URL; use fetchAll for an array")
|
|
1928
|
+
return new PendingComponent79(fetchComponent(url))
|
|
1929
|
+
}
|
|
1930
|
+
|
|
1931
|
+
// fetches them all at once and resolves to the components in the same order,
|
|
1932
|
+
// so one await destructures them - and, like Promise.all, the first failure
|
|
1933
|
+
// rejects the whole thing. A plain promise, not a handle: mounting a *list*
|
|
1934
|
+
// of components has no single meaning
|
|
1935
|
+
static fetchAll(urls: string[]): Promise<Component79[]> {
|
|
1936
|
+
return Promise.all(urls.map(fetchComponent))
|
|
1913
1937
|
}
|
|
1914
1938
|
|
|
1915
1939
|
// subscribes to this instance's $emit events, on top of the DOM CustomEvent
|
|
@@ -2175,6 +2199,90 @@ export class Component79 {
|
|
|
2175
2199
|
}
|
|
2176
2200
|
}
|
|
2177
2201
|
|
|
2202
|
+
// what Component79.fetch() hands back: a component that hasn't arrived yet.
|
|
2203
|
+
//
|
|
2204
|
+
// Every method queues onto the fetch and returns the handle, so a whole page
|
|
2205
|
+
// is one expression and the calls run in the order they were written:
|
|
2206
|
+
//
|
|
2207
|
+
// C79.fetch("./app.html").on("save", persist).mount("main", { user })
|
|
2208
|
+
//
|
|
2209
|
+
// It is also thenable, resolving to the Component79 itself - which is what
|
|
2210
|
+
// keeps `await Component79.fetch(url)` (and importResource, and a handle
|
|
2211
|
+
// dropped into Promise.all) working exactly as before. Queued calls keep the
|
|
2212
|
+
// resolved value, so awaiting a chain gives the mounted component.
|
|
2213
|
+
//
|
|
2214
|
+
// The catch: mount() here returns the handle, not the component - there is no
|
|
2215
|
+
// component yet to return. That's why the whole lifecycle is on the handle and
|
|
2216
|
+
// not just mount(): nobody should have to await merely to destroy something.
|
|
2217
|
+
export class PendingComponent79 {
|
|
2218
|
+
// the fetch with every queued call chained onto it, each passing the
|
|
2219
|
+
// component through - so `chain` always settles to the component, however
|
|
2220
|
+
// many calls were queued, and a failure anywhere rejects the rest
|
|
2221
|
+
private chain: Promise<Component79>
|
|
2222
|
+
|
|
2223
|
+
constructor(component: Promise<Component79>) {
|
|
2224
|
+
this.chain = component
|
|
2225
|
+
}
|
|
2226
|
+
|
|
2227
|
+
private queue(action: (component: Component79) => void): this {
|
|
2228
|
+
this.chain = this.chain.then(component => {
|
|
2229
|
+
action(component)
|
|
2230
|
+
return component
|
|
2231
|
+
})
|
|
2232
|
+
return this
|
|
2233
|
+
}
|
|
2234
|
+
|
|
2235
|
+
then<TResult1 = Component79, TResult2 = never>(
|
|
2236
|
+
onfulfilled?: ((value: Component79) => TResult1 | PromiseLike<TResult1>) | null,
|
|
2237
|
+
onrejected?: ((reason: any) => TResult2 | PromiseLike<TResult2>) | null,
|
|
2238
|
+
): Promise<TResult1 | TResult2> {
|
|
2239
|
+
return this.chain.then(onfulfilled, onrejected)
|
|
2240
|
+
}
|
|
2241
|
+
|
|
2242
|
+
// a chain nobody awaits reports a failed fetch as an unhandled rejection,
|
|
2243
|
+
// like any dropped promise chain - these are for callers who'd rather handle
|
|
2244
|
+
// it. catch() returns a promise, not a handle: the chain ends here
|
|
2245
|
+
catch<TResult = never>(onrejected?: ((reason: any) => TResult | PromiseLike<TResult>) | null): Promise<Component79 | TResult> {
|
|
2246
|
+
return this.chain.catch(onrejected)
|
|
2247
|
+
}
|
|
2248
|
+
|
|
2249
|
+
finally(onfinally?: (() => void) | null): Promise<Component79> {
|
|
2250
|
+
return this.chain.finally(onfinally)
|
|
2251
|
+
}
|
|
2252
|
+
|
|
2253
|
+
mount(parent: Element | ShadowRoot | DocumentFragment | string, data?: Record<string, any>): this {
|
|
2254
|
+
return this.queue(component => component.mount(parent, data))
|
|
2255
|
+
}
|
|
2256
|
+
|
|
2257
|
+
mountShadow(parent: Element | ShadowRoot | DocumentFragment | string, data?: Record<string, any>): this {
|
|
2258
|
+
return this.queue(component => component.mountShadow(parent, data))
|
|
2259
|
+
}
|
|
2260
|
+
|
|
2261
|
+
render(data: Record<string, any> = {}): this {
|
|
2262
|
+
return this.queue(component => component.render(data))
|
|
2263
|
+
}
|
|
2264
|
+
|
|
2265
|
+
renderShadow(data: Record<string, any> = {}): this {
|
|
2266
|
+
return this.queue(component => component.renderShadow(data))
|
|
2267
|
+
}
|
|
2268
|
+
|
|
2269
|
+
on(eventName: string, listener: EmitListener): this {
|
|
2270
|
+
return this.queue(component => component.on(eventName, listener))
|
|
2271
|
+
}
|
|
2272
|
+
|
|
2273
|
+
off(eventName: string, listener: EmitListener): this {
|
|
2274
|
+
return this.queue(component => component.off(eventName, listener))
|
|
2275
|
+
}
|
|
2276
|
+
|
|
2277
|
+
detach(): this {
|
|
2278
|
+
return this.queue(component => component.detach())
|
|
2279
|
+
}
|
|
2280
|
+
|
|
2281
|
+
destroy(): this {
|
|
2282
|
+
return this.queue(component => component.destroy())
|
|
2283
|
+
}
|
|
2284
|
+
}
|
|
2285
|
+
|
|
2178
2286
|
export { Component79 as C79 }
|
|
2179
2287
|
|
|
2180
2288
|
export const parseComponent = (component: string): Component79 => new Component79(component)
|