@llui/dom 0.0.26 → 0.0.27
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/dist/dom-env.d.ts
CHANGED
|
@@ -57,12 +57,14 @@ export interface DomEnv {
|
|
|
57
57
|
* runtimes where no real document exists (detached linkedom, empty
|
|
58
58
|
* shadow root, etc.) can safely return `null` here.
|
|
59
59
|
*
|
|
60
|
-
*
|
|
61
|
-
*
|
|
62
|
-
*
|
|
63
|
-
*
|
|
60
|
+
* Required — making this mandatory on the interface means a custom
|
|
61
|
+
* env that forgets to wire up selector resolution fails compile
|
|
62
|
+
* instead of silently falling back to `globalThis.document` at
|
|
63
|
+
* render time (which would crash under Cloudflare Workers + other
|
|
64
|
+
* strict-isolate runtimes). The three first-party envs
|
|
65
|
+
* (`browserEnv`, `jsdomEnv`, `linkedomEnv`) all implement it.
|
|
64
66
|
*/
|
|
65
|
-
querySelector
|
|
67
|
+
querySelector(selector: string): Element | null;
|
|
66
68
|
}
|
|
67
69
|
/**
|
|
68
70
|
* Wrap the browser globals as a `DomEnv`. Used as the default env for
|
package/dist/dom-env.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"dom-env.d.ts","sourceRoot":"","sources":["../src/dom-env.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,MAAM,WAAW,MAAM;IAErB,aAAa,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAA;IACnC,eAAe,CAAC,EAAE,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,OAAO,CAAA;IACjD,cAAc,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CAAA;IAClC,aAAa,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAA;IACpC,sBAAsB,IAAI,gBAAgB,CAAA;IAC1C;;;;;OAKG;IACH,WAAW,IAAI,KAAK,CAAA;IAKpB,QAAQ,CAAC,OAAO,EAAE,OAAO,OAAO,CAAA;IAChC,QAAQ,CAAC,IAAI,EAAE,OAAO,IAAI,CAAA;IAC1B,QAAQ,CAAC,IAAI,EAAE,OAAO,IAAI,CAAA;IAC1B,QAAQ,CAAC,OAAO,EAAE,OAAO,OAAO,CAAA;IAChC,QAAQ,CAAC,gBAAgB,EAAE,OAAO,gBAAgB,CAAA;IAClD,QAAQ,CAAC,WAAW,EAAE,OAAO,WAAW,CAAA;IACxC,QAAQ,CAAC,mBAAmB,EAAE,OAAO,mBAAmB,CAAA;IACxD,QAAQ,CAAC,UAAU,EAAE,OAAO,UAAU,CAAA;IAGtC,QAAQ,CAAC,UAAU,EAAE,OAAO,UAAU,CAAA;IAEtC;;;;;OAKG;IACH,iBAAiB,CAAC,IAAI,EAAE,MAAM,GAAG,gBAAgB,CAAA;IAEjD
|
|
1
|
+
{"version":3,"file":"dom-env.d.ts","sourceRoot":"","sources":["../src/dom-env.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,MAAM,WAAW,MAAM;IAErB,aAAa,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAA;IACnC,eAAe,CAAC,EAAE,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,OAAO,CAAA;IACjD,cAAc,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CAAA;IAClC,aAAa,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAA;IACpC,sBAAsB,IAAI,gBAAgB,CAAA;IAC1C;;;;;OAKG;IACH,WAAW,IAAI,KAAK,CAAA;IAKpB,QAAQ,CAAC,OAAO,EAAE,OAAO,OAAO,CAAA;IAChC,QAAQ,CAAC,IAAI,EAAE,OAAO,IAAI,CAAA;IAC1B,QAAQ,CAAC,IAAI,EAAE,OAAO,IAAI,CAAA;IAC1B,QAAQ,CAAC,OAAO,EAAE,OAAO,OAAO,CAAA;IAChC,QAAQ,CAAC,gBAAgB,EAAE,OAAO,gBAAgB,CAAA;IAClD,QAAQ,CAAC,WAAW,EAAE,OAAO,WAAW,CAAA;IACxC,QAAQ,CAAC,mBAAmB,EAAE,OAAO,mBAAmB,CAAA;IACxD,QAAQ,CAAC,UAAU,EAAE,OAAO,UAAU,CAAA;IAGtC,QAAQ,CAAC,UAAU,EAAE,OAAO,UAAU,CAAA;IAEtC;;;;;OAKG;IACH,iBAAiB,CAAC,IAAI,EAAE,MAAM,GAAG,gBAAgB,CAAA;IAEjD;;;;;;;;;;;;;;;OAeG;IACH,aAAa,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,GAAG,IAAI,CAAA;CAQhD;AAED;;;;;;;;;;;;;GAaG;AACH,wBAAgB,UAAU,IAAI,MAAM,CA8CnC"}
|
package/dist/dom-env.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"dom-env.js","sourceRoot":"","sources":["../src/dom-env.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"dom-env.js","sourceRoot":"","sources":["../src/dom-env.ts"],"names":[],"mappings":"AAqFA;;;;;;;;;;;;;GAaG;AACH,MAAM,UAAU,UAAU;IACxB,8DAA8D;IAC9D,mEAAmE;IACnE,0DAA0D;IAC1D,OAAO;QACL,aAAa,EAAE,CAAC,GAAG,EAAE,EAAE,CAAC,QAAQ,CAAC,aAAa,CAAC,GAAG,CAAC;QACnD,eAAe,EAAE,CAAC,EAAE,EAAE,GAAG,EAAE,EAAE,CAAC,QAAQ,CAAC,eAAe,CAAC,EAAE,EAAE,GAAG,CAAC;QAC/D,cAAc,EAAE,CAAC,IAAI,EAAE,EAAE,CAAC,QAAQ,CAAC,cAAc,CAAC,IAAI,CAAC;QACvD,aAAa,EAAE,CAAC,IAAI,EAAE,EAAE,CAAC,QAAQ,CAAC,aAAa,CAAC,IAAI,CAAC;QACrD,sBAAsB,EAAE,GAAG,EAAE,CAAC,QAAQ,CAAC,sBAAsB,EAAE;QAC/D,WAAW,EAAE,GAAG,EAAE,CAAC,QAAQ,CAAC,WAAW,EAAE;QACzC,IAAI,OAAO;YACT,OAAO,OAAO,CAAA;QAChB,CAAC;QACD,IAAI,IAAI;YACN,OAAO,IAAI,CAAA;QACb,CAAC;QACD,IAAI,IAAI;YACN,OAAO,IAAI,CAAA;QACb,CAAC;QACD,IAAI,OAAO;YACT,OAAO,OAAO,CAAA;QAChB,CAAC;QACD,IAAI,gBAAgB;YAClB,OAAO,gBAAgB,CAAA;QACzB,CAAC;QACD,IAAI,WAAW;YACb,OAAO,WAAW,CAAA;QACpB,CAAC;QACD,IAAI,mBAAmB;YACrB,OAAO,mBAAmB,CAAA;QAC5B,CAAC;QACD,IAAI,UAAU;YACZ,OAAO,UAAU,CAAA;QACnB,CAAC;QACD,IAAI,UAAU;YACZ,OAAO,UAAU,CAAA;QACnB,CAAC;QACD,iBAAiB,EAAE,CAAC,IAAI,EAAE,EAAE;YAC1B,MAAM,QAAQ,GAAG,QAAQ,CAAC,aAAa,CAAC,UAAU,CAAC,CAAA;YACnD,QAAQ,CAAC,SAAS,GAAG,IAAI,CAAA;YACzB,OAAO,QAAQ,CAAC,OAAO,CAAA;QACzB,CAAC;QACD,aAAa,EAAE,CAAC,QAAQ,EAAE,EAAE,CAAC,QAAQ,CAAC,aAAa,CAAC,QAAQ,CAAC;QAC7D,SAAS,EAAE,IAAI;KAChB,CAAA;AACH,CAAC","sourcesContent":["/**\n * Minimal DOM surface that `@llui/dom`'s internals depend on. Passed to\n * `mountApp` / `hydrateApp` / `renderToString` as a context object so\n * the runtime never reaches for `globalThis.document` directly.\n *\n * Why an injected shape instead of a global shim:\n *\n * 1. **Bundler-friendly.** A Cloudflare Worker that imports\n * `@llui/dom/ssr/linkedom` reaches only linkedom via its module\n * graph. No `await import('jsdom')` appears in reachable source,\n * so rollup doesn't inline the 9 MiB jsdom bundle.\n * 2. **Concurrency-safe.** Two `renderToString` calls can pass\n * different envs; no process-level singleton to collide on.\n * 3. **Strict-isolate safe.** No `globalThis[key] = ...` mutation —\n * Cloudflare workerd and Deno strict modes forbid it.\n *\n * The surface is deliberately narrow: exactly the methods and\n * constructors the runtime touches. Grep `document\\.` /\n * `instanceof (HTMLElement|Element|...)` inside `@llui/dom/src` for\n * the exhaustive set.\n */\nexport interface DomEnv {\n // ── Factories ────────────────────────────────────────────────────\n createElement(tag: string): Element\n createElementNS(ns: string, tag: string): Element\n createTextNode(text: string): Text\n createComment(text: string): Comment\n createDocumentFragment(): DocumentFragment\n /**\n * Used by `each()`'s fast clear/bulk-remove paths to delete a range\n * of siblings in one call. SSR adapters that don't need those paths\n * (jsdom + linkedom both do) can stub — the runtime tolerates a\n * missing range during SSR render, which never hits the bulk paths.\n */\n createRange(): Range\n\n // ── Node / element constructors ─────────────────────────────────\n // Exposed for `instanceof` checks in binding targeting + for any\n // rare site that needs to construct a node type directly.\n readonly Element: typeof Element\n readonly Node: typeof Node\n readonly Text: typeof Text\n readonly Comment: typeof Comment\n readonly DocumentFragment: typeof DocumentFragment\n readonly HTMLElement: typeof HTMLElement\n readonly HTMLTemplateElement: typeof HTMLTemplateElement\n readonly ShadowRoot: typeof ShadowRoot\n\n // ── Event constructor ───────────────────────────────────────────\n readonly MouseEvent: typeof MouseEvent\n\n /**\n * Parse an HTML fragment string into a `DocumentFragment`. Used by\n * `unsafeHtml()`. Browsers and jsdom parse via template-element\n * innerHTML; linkedom has its own fragment parser. Adapter chooses\n * the right mechanism.\n */\n parseHtmlFragment(html: string): DocumentFragment\n\n /**\n * Resolve a CSS selector against the env's root document. Used by\n * `portal()` to locate its target when `opts.target` is a string.\n *\n * Returns `null` when the selector doesn't match — portal callers\n * treat a null target as a no-op (render nothing), so adapters on\n * runtimes where no real document exists (detached linkedom, empty\n * shadow root, etc.) can safely return `null` here.\n *\n * Required — making this mandatory on the interface means a custom\n * env that forgets to wire up selector resolution fails compile\n * instead of silently falling back to `globalThis.document` at\n * render time (which would crash under Cloudflare Workers + other\n * strict-isolate runtimes). The three first-party envs\n * (`browserEnv`, `jsdomEnv`, `linkedomEnv`) all implement it.\n */\n querySelector(selector: string): Element | null\n\n /**\n * @internal Lets hot-path code (e.g. `el-split.ts`'s template-clone)\n * skip env indirection when the env wraps the browser globals. Only\n * set by `browserEnv()`.\n */\n readonly isBrowser?: boolean\n}\n\n/**\n * Wrap the browser globals as a `DomEnv`. Used as the default env for\n * `mountApp` / `hydrateApp` on the client.\n *\n * The returned object delegates to `globalThis.document` / `globalThis.X`\n * lazily — evaluating `browserEnv()` on a server process before a DOM\n * exists is safe because the delegation only dereferences the globals\n * when a method is actually called.\n *\n * Never mutates `globalThis`. A process with no browser globals that\n * invokes one of the factory methods gets a `TypeError` / `ReferenceError`\n * at the call site — which is correct: you're trying to build DOM on a\n * runtime that has no DOM.\n */\nexport function browserEnv(): DomEnv {\n // Evaluate globals lazily through getters so module-load on a\n // DOM-less process doesn't throw. Hot client code is still cheap —\n // V8/SpiderMonkey inline the getter after the first call.\n return {\n createElement: (tag) => document.createElement(tag),\n createElementNS: (ns, tag) => document.createElementNS(ns, tag),\n createTextNode: (text) => document.createTextNode(text),\n createComment: (text) => document.createComment(text),\n createDocumentFragment: () => document.createDocumentFragment(),\n createRange: () => document.createRange(),\n get Element() {\n return Element\n },\n get Node() {\n return Node\n },\n get Text() {\n return Text\n },\n get Comment() {\n return Comment\n },\n get DocumentFragment() {\n return DocumentFragment\n },\n get HTMLElement() {\n return HTMLElement\n },\n get HTMLTemplateElement() {\n return HTMLTemplateElement\n },\n get ShadowRoot() {\n return ShadowRoot\n },\n get MouseEvent() {\n return MouseEvent\n },\n parseHtmlFragment: (html) => {\n const template = document.createElement('template')\n template.innerHTML = html\n return template.content\n },\n querySelector: (selector) => document.querySelector(selector),\n isBrowser: true,\n }\n}\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"portal.d.ts","sourceRoot":"","sources":["../../src/primitives/portal.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,aAAa,CAAA;AAIhD,wBAAgB,MAAM,CAAC,IAAI,EAAE,aAAa,GAAG,IAAI,EAAE,
|
|
1
|
+
{"version":3,"file":"portal.d.ts","sourceRoot":"","sources":["../../src/primitives/portal.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,aAAa,CAAA;AAIhD,wBAAgB,MAAM,CAAC,IAAI,EAAE,aAAa,GAAG,IAAI,EAAE,CAuClD"}
|
|
@@ -3,26 +3,12 @@ import { createLifetime, addDisposer } from '../lifetime.js';
|
|
|
3
3
|
export function portal(opts) {
|
|
4
4
|
const ctx = getRenderContext('portal');
|
|
5
5
|
const parentLifetime = ctx.rootLifetime;
|
|
6
|
-
//
|
|
7
|
-
//
|
|
8
|
-
//
|
|
9
|
-
//
|
|
10
|
-
//
|
|
11
|
-
|
|
12
|
-
// we return [] instead of throwing. Portal is a client concept; SSR
|
|
13
|
-
// silently skipping the resolution is the right "no-op" behavior.
|
|
14
|
-
let target = null;
|
|
15
|
-
if (typeof opts.target === 'string') {
|
|
16
|
-
if (ctx.dom.querySelector) {
|
|
17
|
-
target = ctx.dom.querySelector(opts.target);
|
|
18
|
-
}
|
|
19
|
-
else if (typeof document !== 'undefined') {
|
|
20
|
-
target = document.querySelector(opts.target);
|
|
21
|
-
}
|
|
22
|
-
}
|
|
23
|
-
else {
|
|
24
|
-
target = opts.target;
|
|
25
|
-
}
|
|
6
|
+
// `DomEnv.querySelector` is a required method — see dom-env.ts.
|
|
7
|
+
// Custom envs that don't implement it fail TS compile; at runtime
|
|
8
|
+
// every LLui-shipped env resolves against its own document, which
|
|
9
|
+
// keeps portal safe on both client and SSR (returns `null` →
|
|
10
|
+
// no-op when the target is unreachable).
|
|
11
|
+
const target = typeof opts.target === 'string' ? ctx.dom.querySelector(opts.target) : opts.target;
|
|
26
12
|
if (!target) {
|
|
27
13
|
return [];
|
|
28
14
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"portal.js","sourceRoot":"","sources":["../../src/primitives/portal.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,gBAAgB,EAAE,gBAAgB,EAAE,kBAAkB,EAAE,MAAM,sBAAsB,CAAA;AAC7F,OAAO,EAAE,cAAc,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAA;AAE5D,MAAM,UAAU,MAAM,CAAC,IAAmB;IACxC,MAAM,GAAG,GAAG,gBAAgB,CAAC,QAAQ,CAAC,CAAA;IACtC,MAAM,cAAc,GAAG,GAAG,CAAC,YAAY,CAAA;IAEvC,
|
|
1
|
+
{"version":3,"file":"portal.js","sourceRoot":"","sources":["../../src/primitives/portal.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,gBAAgB,EAAE,gBAAgB,EAAE,kBAAkB,EAAE,MAAM,sBAAsB,CAAA;AAC7F,OAAO,EAAE,cAAc,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAA;AAE5D,MAAM,UAAU,MAAM,CAAC,IAAmB;IACxC,MAAM,GAAG,GAAG,gBAAgB,CAAC,QAAQ,CAAC,CAAA;IACtC,MAAM,cAAc,GAAG,GAAG,CAAC,YAAY,CAAA;IAEvC,gEAAgE;IAChE,kEAAkE;IAClE,kEAAkE;IAClE,6DAA6D;IAC7D,yCAAyC;IACzC,MAAM,MAAM,GAAG,OAAO,IAAI,CAAC,MAAM,KAAK,QAAQ,CAAC,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC,aAAa,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,MAAM,CAAA;IAEjG,IAAI,CAAC,MAAM,EAAE,CAAC;QACZ,OAAO,EAAE,CAAA;IACX,CAAC;IAED,MAAM,WAAW,GAAG,cAAc,CAAC,cAAc,CAAC,CAAA;IAClD,WAAW,CAAC,KAAK,GAAG,QAAQ,CAAA;IAC5B,MAAM,QAAQ,GAAG,EAAE,GAAG,GAAG,EAAE,YAAY,EAAE,WAAW,EAAE,SAAS,EAAE,MAAiB,EAAE,CAAA;IACpF,gBAAgB,CAAC,QAAQ,CAAC,CAAA;IAC1B,MAAM,KAAK,GAAG,IAAI,CAAC,MAAM,EAAE,CAAA;IAC3B,kBAAkB,EAAE,CAAA;IACpB,yBAAyB;IACzB,gBAAgB,CAAC,GAAG,CAAC,CAAA;IAErB,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;QACzB,MAAM,CAAC,WAAW,CAAC,IAAI,CAAC,CAAA;IAC1B,CAAC;IAED,qDAAqD;IACrD,WAAW,CAAC,WAAW,EAAE,GAAG,EAAE;QAC5B,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;YACzB,IAAI,IAAI,CAAC,UAAU,KAAK,MAAM,EAAE,CAAC;gBAC/B,MAAM,CAAC,WAAW,CAAC,IAAI,CAAC,CAAA;YAC1B,CAAC;QACH,CAAC;IACH,CAAC,CAAC,CAAA;IAEF,sEAAsE;IACtE,OAAO,EAAE,CAAA;AACX,CAAC","sourcesContent":["import type { PortalOptions } from '../types.js'\nimport { getRenderContext, setRenderContext, clearRenderContext } from '../render-context.js'\nimport { createLifetime, addDisposer } from '../lifetime.js'\n\nexport function portal(opts: PortalOptions): Node[] {\n const ctx = getRenderContext('portal')\n const parentLifetime = ctx.rootLifetime\n\n // `DomEnv.querySelector` is a required method — see dom-env.ts.\n // Custom envs that don't implement it fail TS compile; at runtime\n // every LLui-shipped env resolves against its own document, which\n // keeps portal safe on both client and SSR (returns `null` →\n // no-op when the target is unreachable).\n const target = typeof opts.target === 'string' ? ctx.dom.querySelector(opts.target) : opts.target\n\n if (!target) {\n return []\n }\n\n const portalScope = createLifetime(parentLifetime)\n portalScope._kind = 'portal'\n const buildCtx = { ...ctx, rootLifetime: portalScope, container: target as Element }\n setRenderContext(buildCtx)\n const nodes = opts.render()\n clearRenderContext()\n // Restore parent context\n setRenderContext(ctx)\n\n for (const node of nodes) {\n target.appendChild(node)\n }\n\n // On scope disposal, remove portal nodes from target\n addDisposer(portalScope, () => {\n for (const node of nodes) {\n if (node.parentNode === target) {\n target.removeChild(node)\n }\n }\n })\n\n // Portal returns nothing to the parent DOM — nodes live in the target\n return []\n}\n"]}
|