@loadbare/app 0.11.0 → 0.12.0
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/build/assemble.d.ts.map +1 -1
- package/dist/build/assemble.js +5 -1
- package/dist/build/assemble.js.map +1 -1
- package/dist/core/lb-constants.d.ts +2 -0
- package/dist/core/lb-constants.d.ts.map +1 -1
- package/dist/core/lb-constants.js +8 -0
- package/dist/core/lb-constants.js.map +1 -1
- package/dist/core/lb-types.d.ts +11 -0
- package/dist/core/lb-types.d.ts.map +1 -1
- package/dist/core/lb-types.js.map +1 -1
- package/dist/hub/lb-apply.d.ts +7 -1
- package/dist/hub/lb-apply.d.ts.map +1 -1
- package/dist/hub/lb-apply.js +106 -3
- package/dist/hub/lb-apply.js.map +1 -1
- package/dist/hub/lb-hub.browser.d.ts.map +1 -1
- package/dist/hub/lb-hub.browser.js +116 -31
- package/dist/hub/lb-hub.browser.js.map +1 -1
- package/dist/server/lb-server.d.ts.map +1 -1
- package/dist/server/lb-server.js +17 -0
- package/dist/server/lb-server.js.map +1 -1
- package/docs/TECHREF-1.0.md +101 -9
- package/docs/comparison.md +5 -1
- package/docs/reference/chrome.md +15 -0
- package/docs/reference/custom-elements.md +62 -0
- package/docs/reference/data-binding.md +36 -0
- package/docs/reference/page-files.md +30 -2
- package/package.json +1 -1
- package/skills/loadbare-app/SKILL.md +58 -4
- package/skills/loadbare-app/references/TECHREF-1.0.md +101 -9
- package/skills/loadbare-app/references/chrome.md +15 -0
- package/skills/loadbare-app/references/custom-elements.md +62 -0
- package/skills/loadbare-app/references/data-binding.md +36 -0
- package/skills/loadbare-app/references/page-files.md +30 -2
package/dist/hub/lb-apply.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"lb-apply.js","sourceRoot":"","sources":["../../hub/lb-apply.ts"],"names":[],"mappings":"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","sourcesContent":["/// <reference lib=\"dom\" />\n\n/**\n * Landing — see docs/reference/data-binding.md.\n *\n * The hub lands a response item's rows on every element whose `lb-query`\n * names its query. The item says the query's kind and key, so the markup\n * says neither:\n *\n * kind row template the hub\n * row no lands the row on the element itself\n * row yes lands one live row\n * rows yes lands one live row per row\n * rows no lands nothing\n *\n * Filling a live row and filling an element a `row` lands on are the same\n * operation, and the only difference is how much of the page the root\n * covers.\n *\n * A condition is the one other thing landing moves. An element whose\n * `lb-show` column is off stands in the document inside a template, and\n * landing reaches in there as it reaches everywhere else, so a branch that\n * returns is already current. Nothing but landing reaches in.\n */\n\nimport {\n ATTR_COLUMN,\n ATTR_COLUMN_VALUE,\n ATTR_KEY_VALUE,\n ATTR_QUERY,\n ATTR_QUERY_ROW_COUNT,\n ATTR_ROW_LIVE,\n ATTR_SHOW,\n KIND_ROW,\n LIVE_ROW,\n} from \"../core/lb-constants.js\";\nimport {\n isPatch,\n type ResponseItem,\n type Row,\n type RowsHost,\n type RowsResult,\n} from \"../core/lb-types.js\";\n\n/** The template holding an absent branch — see ATTR_SHOW. */\nconst PARKED = `template[${ATTR_SHOW}]`;\n\n/** A DocumentFragment's nodeType. Tier 3 has no `Node` global to read it from. */\nconst FRAGMENT_NODE = 11;\n\n/** The input types whose state is not their `value`, or cannot be set. */\nconst UNLANDED_INPUTS = [\"checkbox\", \"radio\", \"file\"];\n\n/** A control's value, whether it is native or a custom element. */\nexport interface Control extends Element {\n value: string;\n}\n\n/**\n * A native control whose state is its `value`: a `<select>`, a\n * `<textarea>`, or an `<input>` of any type but checkbox, radio and file.\n *\n * Told apart by tag name and type rather than by class, so it holds for an\n * element from any document.\n */\nfunction isNativeControl(el: Element): boolean {\n if (el.localName === \"select\" || el.localName === \"textarea\") return true;\n return (\n el.localName === \"input\" &&\n !UNLANDED_INPUTS.includes((el as HTMLInputElement).type)\n );\n}\n\n/**\n * A form-associated custom element with a `value` property. HTML marks one\n * with `static formAssociated = true` on its class, and a control has a value.\n */\nexport function isFormAssociated(el: Element): boolean {\n const ctor = el.constructor as { formAssociated?: unknown };\n return ctor.formAssociated === true && \"value\" in el;\n}\n\n/**\n * A control: an `<input>`, `<select>` or `<textarea>`, or a form-associated\n * custom element with a `value` property. Landing and gathering draw the\n * same line, so a value read back is the one that landed there.\n */\nexport function isControl(el: Element): el is Control {\n return isNativeControl(el) || isFormAssociated(el);\n}\n\n/**\n * Set an element from a column. A control's `value` is set. A custom element\n * that is not a control keeps its content, which the builder placed there\n * from its element file, and renders the stamp instead. Any other element's\n * text content is set. Every one carries the value as `lb-column-value`.\n */\nfunction land(el: Element, value: unknown): void {\n // Untouched, whatever the server sent: the browser decides what a\n // non-string looks like. See Row in core/lb-types.ts.\n if (value === null || value === undefined) {\n if (isControl(el)) el.value = \"\";\n else if (!el.localName.includes(\"-\") && el.localName !== \"input\") {\n el.textContent = \"\";\n }\n el.removeAttribute(ATTR_COLUMN_VALUE);\n return;\n }\n if (isControl(el)) {\n el.value = value as string;\n } else if (el.localName === \"input\") {\n console.warn(\n `lb-hub: a value does not land on <input type=\"${(el as HTMLInputElement).type}\">, ignoring`,\n el,\n );\n return;\n } else if (!el.localName.includes(\"-\")) {\n el.textContent = value as string;\n }\n el.setAttribute(ATTR_COLUMN_VALUE, value as string);\n}\n\n/**\n * Whether an element under `root` belongs to root's query, rather than to a\n * query nested inside it.\n *\n * A descendant is root's unless something between it and root carries\n * `lb-query`. The element's own `lb-query` does not count: it names what the\n * element holds, and the row it reads from is its ancestors'. So a picker\n * carrying `lb-query` and `lb-column` is set from the row around it. Root's\n * own attribute does not count either: root is what is being filled.\n *\n * Root may be the content of a template holding an absent branch. The walk\n * up from an element inside it stops at the top of that content, which has\n * no parent, and the template it stands for was in scope already.\n */\nfunction inScope(root: Element | DocumentFragment, el: Element): boolean {\n for (let node = el.parentElement; node && node !== root;) {\n if (node.hasAttribute(ATTR_QUERY)) return false;\n node = node.parentElement;\n }\n return true;\n}\n\n/**\n * Root if it matches, then every descendant in root's query that does.\n * Gathering finds columns through here. It does not reach into an absent\n * branch, so a live row is read back from the places a row lands that are\n * showing.\n */\nexport function within(root: Element, selector: string): Element[] {\n const found: Element[] = root.matches(selector) ? [root] : [];\n for (const el of root.querySelectorAll(selector)) {\n if (inScope(root, el)) found.push(el);\n }\n return found;\n}\n\n/**\n * Every descendant in root's query that matches, absent branches included.\n *\n * `querySelectorAll` does not enter template content, so an element that is\n * off would otherwise miss everything landed while it was away, and return\n * stale or with its rows empty. A template holding one is in root's query by\n * the ordinary rule, and its content is searched as if it stood there.\n */\nfunction below(root: Element | DocumentFragment, selector: string): Element[] {\n const found: Element[] = [];\n for (const el of root.querySelectorAll(selector)) {\n if (inScope(root, el)) found.push(el);\n }\n for (const parked of root.querySelectorAll(PARKED)) {\n if (inScope(root, parked)) {\n found.push(...below((parked as HTMLTemplateElement).content, selector));\n }\n }\n return found;\n}\n\n/**\n * Every element in root that matches, absent branches included. A query is\n * looked up this way before any row is known, so nothing is filtered out.\n */\nfunction everywhere(root: ParentNode, selector: string): Element[] {\n const found = [...root.querySelectorAll(selector)];\n for (const parked of root.querySelectorAll(PARKED)) {\n const content = (parked as HTMLTemplateElement).content;\n found.push(...everywhere(content, selector));\n }\n return found;\n}\n\n/**\n * Put an element in the document or take it out, as its `lb-show` column\n * says.\n *\n * Off is inside a template that stands where the element stood, carrying the\n * same `lb-show`. The element is moved rather than rebuilt, so a custom\n * element keeps its instance and a control keeps what was typed into it. On\n * moves it back and the template goes.\n *\n * Landing reaches into that template, so both it and the element it holds\n * arrive here. The template decides; the element it holds, whose parent is\n * the template's content, is left to it.\n */\nfunction present(el: Element, on: boolean): void {\n if (el.localName === \"template\") {\n const branch = (el as HTMLTemplateElement).content.firstElementChild;\n if (on && branch) el.replaceWith(branch);\n return;\n }\n if (on || el.parentNode?.nodeType === FRAGMENT_NODE) return;\n const parked = el.ownerDocument.createElement(\"template\");\n parked.setAttribute(ATTR_SHOW, el.getAttribute(ATTR_SHOW)!);\n el.replaceWith(parked);\n parked.content.append(el);\n}\n\n/**\n * Fill from one row: every `lb-column` and `lb-show` in root's query.\n *\n * A live row is its own row, so its root counts when it carries\n * `lb-column`: `<option>`'s content model is text, so an option row has to\n * be the column it displays. An element a `row` lands on is not its own\n * ancestor, so its own `lb-column` reads from the row around it and is left\n * alone here.\n */\nexport function applyRow(root: Element, row: Row, liveRow = false): void {\n for (const [column, value] of Object.entries(row)) {\n const selector = `[${ATTR_COLUMN}=\"${column}\"]`;\n const columns = below(root, selector);\n if (liveRow && root.matches(selector)) columns.unshift(root);\n for (const el of columns) land(el, value);\n // Only null and false are off. A string is never read, so \"false\" is on,\n // and the query spells a condition as a boolean or a null.\n //\n // Never the root's own: a row template's root carries none, and the\n // element a row lands on reads its condition from the row around it.\n const on = value !== null && value !== false;\n for (const el of below(root, `[${ATTR_SHOW}=\"${column}\"]`)) {\n present(el, on);\n }\n }\n}\n\n/**\n * The row template: the first `<template>` among the element's descendants,\n * outside any nested `lb-query`. A template holding an absent branch is not a\n * row template: rows land before the row template, so one inside the first\n * live row comes first in document order.\n */\nexport function templateIn(el: Element): HTMLTemplateElement | null {\n const template = within(el, `template:not([${ATTR_SHOW}])`).find(\n (t) => t !== el,\n );\n return (template as HTMLTemplateElement | undefined) ?? null;\n}\n\n/**\n * The live rows of the element's query, in document order. A row of a nested\n * query is that query's. An element a `row` query landed on carries a key and\n * is not a live row, so a `row` shown in a table's head or foot is not one of\n * the table's rows.\n */\nfunction liveRows(el: Element): Element[] {\n return [...el.querySelectorAll(LIVE_ROW)].filter((row) => inScope(el, row));\n}\n\n/**\n * The live rows already showing, by the key each carries. Two live rows with\n * one key are a mistake nothing downstream can recover from: only one of them\n * would ever be matched, and the other would stay until the page goes.\n */\nfunction showing(el: Element): Map<string, Element> {\n const rows = new Map<string, Element>();\n for (const row of liveRows(el)) {\n const key = row.getAttribute(ATTR_KEY_VALUE)!;\n if (rows.has(key)) {\n console.error(\n `lb-hub: <${el.localName}> shows two rows with the key '${key}'`,\n );\n }\n rows.set(key, row);\n }\n return rows;\n}\n\n/**\n * Land rows through a row template.\n *\n * All rows decide membership and order: every row is placed in the order\n * given, and a row whose key did not arrive is gone. A patch disturbs only\n * what it names — a row it did not mention keeps its contents and its\n * position.\n *\n * A custom element that carries `lbPlaceRow` decides where a row goes,\n * because only it knows whether it sorts or groups. Without it a row lands\n * immediately before the template, so rows accumulate in the order they\n * arrive and the template stays put as the insertion marker.\n */\nexport function applyRows(\n el: Element,\n template: HTMLTemplateElement,\n keyColumn: string,\n result: RowsResult,\n): void {\n const shown = showing(el);\n const host = el as Element & RowsHost;\n const whole = !isPatch(result);\n const landed = new Set<string>();\n\n const place = (row: Element, data: Row): void => {\n if (host.lbPlaceRow) host.lbPlaceRow(row, data, template);\n else template.parentElement!.insertBefore(row, template);\n };\n\n const upsert = (data: Row): void => {\n if (data[keyColumn] === undefined) {\n console.error(\n `lb-hub: a row for <${el.localName}> has no '${keyColumn}' column`,\n );\n return;\n }\n // The key is stored on the row as an attribute and read back from\n // there, so it is compared as the string the attribute holds.\n const key = String(data[keyColumn]);\n if (landed.has(key)) {\n console.error(\n `lb-hub: two rows for <${el.localName}> have the key '${key}'; ` +\n `the last one shows`,\n );\n }\n landed.add(key);\n let row = shown.get(key);\n const fresh = row === undefined;\n if (!row) {\n // Imported rather than cloned: template content belongs to a document\n // with no custom element definitions, so a clone would not upgrade\n // until inserted, and a form-associated control would be filled as if\n // it were not one.\n row = el.ownerDocument.importNode(\n template.content.firstElementChild!,\n true,\n );\n row.setAttribute(ATTR_ROW_LIVE, \"\");\n row.setAttribute(ATTR_KEY_VALUE, key);\n shown.set(key, row);\n }\n // Fill before insertion. The attributes are already there when the row\n // upgrades, which is the same thing that makes a first landing and a\n // refresh one operation everywhere else.\n applyRow(row, data, true);\n if (fresh || whole) place(row, data);\n };\n\n if (Array.isArray(result)) {\n for (const data of result) upsert(data);\n for (const [key, row] of shown) if (!landed.has(key)) row.remove();\n } else {\n for (const data of result.rows ?? []) upsert(data);\n for (const key of result.drop ?? []) shown.get(String(key))?.remove();\n }\n\n // Counted from the DOM rather than from either branch above, so all rows\n // and a patch report the same fact the same way. Only here is the count\n // known: the server answers with rows and says nothing about how many\n // survived reconciliation.\n el.setAttribute(ATTR_QUERY_ROW_COUNT, String(liveRows(el).length));\n\n // Derived scaffolding — a section heading, an <optgroup> — goes when its\n // last row does, and only the custom element knows it exists.\n host.lbRowsLanded?.();\n}\n\n/** Land one response item on one element that names its query. */\nfunction landItem(el: Element, item: ResponseItem): void {\n const template = templateIn(el);\n if (item.kind === KIND_ROW) {\n const row = item.row ?? {};\n if (template) {\n applyRows(el, template, item.key, [row]);\n return;\n }\n applyRow(el, row);\n const key = row[item.key];\n if (key !== undefined && key !== null) {\n el.setAttribute(ATTR_KEY_VALUE, String(key));\n }\n return;\n }\n // A `rows` query with no row template lands nothing: an insert form names\n // the query it adds to, and shows none of its rows.\n if (!template) return;\n const result = item.patch ?? item.rows ?? [];\n applyRows(el, template, item.key, result);\n}\n\n/**\n * Land response items. Every answer arrives through here.\n *\n * `quiet` names queries that may have nowhere to land without a warning: the\n * hub's own `lb-url` lands wherever a chrome or page names it, and nowhere\n * otherwise.\n */\nexport function applyResponse(\n root: ParentNode,\n items: ResponseItem[],\n quiet: readonly string[] = [],\n): void {\n for (const item of items) {\n const targets = everywhere(root, `[${ATTR_QUERY}=\"${item.query}\"]`);\n if (targets.length === 0) {\n if (!quiet.includes(item.query)) {\n console.warn(`lb-hub: nothing names '${item.query}', skipping`);\n }\n continue;\n }\n for (const el of targets) landItem(el, item);\n }\n}\n"]}
|
|
1
|
+
{"version":3,"file":"lb-apply.js","sourceRoot":"","sources":["../../hub/lb-apply.ts"],"names":[],"mappings":"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","sourcesContent":["/// <reference lib=\"dom\" />\n\n/**\n * Landing — see docs/reference/data-binding.md.\n *\n * The hub lands a response item's rows on every element whose `lb-query`\n * names its query. The item says the query's kind and key, so the markup\n * says neither:\n *\n * kind row template the hub\n * row no lands the row on the element itself\n * row yes lands one live row\n * rows yes lands one live row per row\n * rows no lands nothing\n *\n * Filling a live row and filling an element a `row` lands on are the same\n * operation, and the only difference is how much of the page the root\n * covers.\n *\n * An answer is kept after it lands. An element that names a query and\n * arrives after that query's answer — a picker in a new live row, a ghost\n * row a custom element built — is filled from the kept answer at the end of\n * the next landing, so a query need not land again, and need not land after\n * the one whose rows hold it, just to fill what is new. A custom element\n * shipped inside an absent branch has not upgraded, so it is filled again\n * once it has, and places its rows itself.\n *\n * A condition is the one other thing landing moves. An element whose\n * `lb-show` column is off stands in the document inside a template, and\n * landing reaches in there as it reaches everywhere else, so a branch that\n * returns is already current. Nothing but landing reaches in.\n */\n\nimport {\n ATTR_COLUMN,\n ATTR_COLUMN_VALUE,\n ATTR_KEY_VALUE,\n ATTR_QUERY,\n ATTR_QUERY_ROW_COUNT,\n ATTR_ROW_LIVE,\n ATTR_SHOW,\n KIND_ROW,\n LIVE_ROW,\n SHOW_NOT,\n} from \"../core/lb-constants.js\";\nimport {\n isPatch,\n type Patch,\n type ResponseItem,\n type Row,\n type RowsHost,\n type RowsResult,\n} from \"../core/lb-types.js\";\n\n/** The template holding an absent branch — see ATTR_SHOW. */\nconst PARKED = `template[${ATTR_SHOW}]`;\n\n/** A DocumentFragment's nodeType. Tier 3 has no `Node` global to read it from. */\nconst FRAGMENT_NODE = 11;\n\n/** The input types whose state is not their `value`, or cannot be set. */\nconst UNLANDED_INPUTS = [\"checkbox\", \"radio\", \"file\"];\n\n/** A control's value, whether it is native or a custom element. */\nexport interface Control extends Element {\n value: string;\n}\n\n/**\n * A native control whose state is its `value`: a `<select>`, a\n * `<textarea>`, or an `<input>` of any type but checkbox, radio and file.\n *\n * Told apart by tag name and type rather than by class, so it holds for an\n * element from any document.\n */\nfunction isNativeControl(el: Element): boolean {\n if (el.localName === \"select\" || el.localName === \"textarea\") return true;\n return (\n el.localName === \"input\" &&\n !UNLANDED_INPUTS.includes((el as HTMLInputElement).type)\n );\n}\n\n/**\n * A form-associated custom element with a `value` property. HTML marks one\n * with `static formAssociated = true` on its class, and a control has a value.\n */\nexport function isFormAssociated(el: Element): boolean {\n const ctor = el.constructor as { formAssociated?: unknown };\n return ctor.formAssociated === true && \"value\" in el;\n}\n\n/**\n * A control: an `<input>`, `<select>` or `<textarea>`, or a form-associated\n * custom element with a `value` property. Landing and gathering draw the\n * same line, so a value read back is the one that landed there.\n */\nexport function isControl(el: Element): el is Control {\n return isNativeControl(el) || isFormAssociated(el);\n}\n\n/**\n * Set an element from a column. A control's `value` is set. A custom element\n * that is not a control keeps its content, which the builder placed there\n * from its element file, and renders the stamp instead. Any other element's\n * text content is set. Every one carries the value as `lb-column-value`.\n */\nfunction land(el: Element, value: unknown): void {\n // Untouched, whatever the server sent: the browser decides what a\n // non-string looks like. See Row in core/lb-types.ts.\n if (value === null || value === undefined) {\n if (isControl(el)) el.value = \"\";\n else if (!el.localName.includes(\"-\") && el.localName !== \"input\") {\n el.textContent = \"\";\n }\n el.removeAttribute(ATTR_COLUMN_VALUE);\n return;\n }\n if (isControl(el)) {\n el.value = value as string;\n } else if (el.localName === \"input\") {\n console.warn(\n `lb-hub: a value does not land on <input type=\"${(el as HTMLInputElement).type}\">, ignoring`,\n el,\n );\n return;\n } else if (!el.localName.includes(\"-\")) {\n el.textContent = value as string;\n }\n el.setAttribute(ATTR_COLUMN_VALUE, value as string);\n}\n\n/**\n * Whether an element under `root` belongs to root's query, rather than to a\n * query nested inside it.\n *\n * A descendant is root's unless something between it and root carries\n * `lb-query`. The element's own `lb-query` does not count: it names what the\n * element holds, and the row it reads from is its ancestors'. So a picker\n * carrying `lb-query` and `lb-column` is set from the row around it. Root's\n * own attribute does not count either: root is what is being filled.\n *\n * Root may be the content of a template holding an absent branch. The walk\n * up from an element inside it stops at the top of that content, which has\n * no parent, and the template it stands for was in scope already.\n */\nfunction inScope(root: Element | DocumentFragment, el: Element): boolean {\n for (let node = el.parentElement; node && node !== root;) {\n if (node.hasAttribute(ATTR_QUERY)) return false;\n node = node.parentElement;\n }\n return true;\n}\n\n/**\n * Root if it matches, then every descendant in root's query that does.\n * Gathering finds columns through here. It does not reach into an absent\n * branch, so a live row is read back from the places a row lands that are\n * showing.\n */\nexport function within(root: Element, selector: string): Element[] {\n const found: Element[] = root.matches(selector) ? [root] : [];\n for (const el of root.querySelectorAll(selector)) {\n if (inScope(root, el)) found.push(el);\n }\n return found;\n}\n\n/**\n * Every descendant in root's query that matches, absent branches included.\n *\n * `querySelectorAll` does not enter template content, so an element that is\n * off would otherwise miss everything landed while it was away, and return\n * stale or with its rows empty. A template holding one is in root's query by\n * the ordinary rule, and its content is searched as if it stood there.\n */\nfunction below(root: Element | DocumentFragment, selector: string): Element[] {\n const found: Element[] = [];\n for (const el of root.querySelectorAll(selector)) {\n if (inScope(root, el)) found.push(el);\n }\n for (const parked of root.querySelectorAll(PARKED)) {\n if (inScope(root, parked)) {\n found.push(...below((parked as HTMLTemplateElement).content, selector));\n }\n }\n return found;\n}\n\n/**\n * Every element in root that matches, absent branches included. A query is\n * looked up this way before any row is known, so nothing is filtered out.\n */\nfunction everywhere(root: ParentNode, selector: string): Element[] {\n const found = [...root.querySelectorAll(selector)];\n for (const parked of root.querySelectorAll(PARKED)) {\n const content = (parked as HTMLTemplateElement).content;\n found.push(...everywhere(content, selector));\n }\n return found;\n}\n\n/**\n * Put an element in the document or take it out, as its `lb-show` column\n * says.\n *\n * Off is inside a template that stands where the element stood, carrying the\n * same `lb-show`. The element is moved rather than rebuilt, so a custom\n * element keeps its instance and a control keeps what was typed into it. On\n * moves it back and the template goes.\n *\n * Landing reaches into that template, so both it and the element it holds\n * arrive here. The template decides; the element it holds, whose parent is\n * the template's content, is left to it.\n */\nfunction present(el: Element, on: boolean): void {\n if (el.localName === \"template\") {\n const branch = (el as HTMLTemplateElement).content.firstElementChild;\n if (on && branch) el.replaceWith(branch);\n return;\n }\n if (on || el.parentNode?.nodeType === FRAGMENT_NODE) return;\n const parked = el.ownerDocument.createElement(\"template\");\n parked.setAttribute(ATTR_SHOW, el.getAttribute(ATTR_SHOW)!);\n el.replaceWith(parked);\n parked.content.append(el);\n}\n\n/**\n * Fill from one row: every `lb-column` and `lb-show` in root's query.\n *\n * A live row is its own row, so its root counts when it carries\n * `lb-column`: `<option>`'s content model is text, so an option row has to\n * be the column it displays. An element a `row` lands on is not its own\n * ancestor, so its own `lb-column` reads from the row around it and is left\n * alone here.\n */\nexport function applyRow(root: Element, row: Row, liveRow = false): void {\n for (const [column, value] of Object.entries(row)) {\n const selector = `[${ATTR_COLUMN}=\"${column}\"]`;\n const columns = below(root, selector);\n if (liveRow && root.matches(selector)) columns.unshift(root);\n for (const el of columns) land(el, value);\n // Only null and false are off. A string is never read, so \"false\" is on,\n // and the query spells a condition as a boolean or a null.\n //\n // Never the root's own: a row template's root carries none, and the\n // element a row lands on reads its condition from the row around it.\n const on = value !== null && value !== false;\n for (const el of below(root, `[${ATTR_SHOW}=\"${column}\"]`)) {\n present(el, on);\n }\n for (const el of below(root, `[${ATTR_SHOW}=\"${SHOW_NOT}${column}\"]`)) {\n present(el, !on);\n }\n }\n}\n\n/**\n * The row template: the first `<template>` among the element's descendants,\n * outside any nested `lb-query`. A template holding an absent branch is not a\n * row template: rows land before the row template, so one inside the first\n * live row comes first in document order.\n */\nexport function templateIn(el: Element): HTMLTemplateElement | null {\n const template = within(el, `template:not([${ATTR_SHOW}])`).find(\n (t) => t !== el,\n );\n return (template as HTMLTemplateElement | undefined) ?? null;\n}\n\n/**\n * The live rows of the element's query, in document order. A row of a nested\n * query is that query's. An element a `row` query landed on carries a key and\n * is not a live row, so a `row` shown in a table's head or foot is not one of\n * the table's rows.\n */\nfunction liveRows(el: Element): Element[] {\n return [...el.querySelectorAll(LIVE_ROW)].filter((row) => inScope(el, row));\n}\n\n/**\n * The live rows already showing, by the key each carries. Two live rows with\n * one key are a mistake nothing downstream can recover from: only one of them\n * would ever be matched, and the other would stay until the page goes.\n */\nfunction showing(el: Element): Map<string, Element> {\n const rows = new Map<string, Element>();\n for (const row of liveRows(el)) {\n const key = row.getAttribute(ATTR_KEY_VALUE)!;\n if (rows.has(key)) {\n console.error(\n `lb-hub: <${el.localName}> shows two rows with the key '${key}'`,\n );\n }\n rows.set(key, row);\n }\n return rows;\n}\n\n/**\n * Land rows through a row template.\n *\n * All rows decide membership and order: every row is placed in the order\n * given, and a row whose key did not arrive is gone. A patch disturbs only\n * what it names — a row it did not mention keeps its contents and its\n * position.\n *\n * A custom element that carries `lbPlaceRow` decides where a row goes,\n * because only it knows whether it sorts or groups. Without it a row lands\n * immediately before the template, so rows accumulate in the order they\n * arrive and the template stays put as the insertion marker.\n */\nexport function applyRows(\n el: Element,\n template: HTMLTemplateElement,\n keyColumn: string,\n result: RowsResult,\n): void {\n const shown = showing(el);\n const host = el as Element & RowsHost;\n const whole = !isPatch(result);\n const landed = new Set<string>();\n\n const place = (row: Element, data: Row): void => {\n if (host.lbPlaceRow) host.lbPlaceRow(row, data, template);\n else template.parentElement!.insertBefore(row, template);\n };\n\n const upsert = (data: Row): void => {\n if (data[keyColumn] === undefined) {\n console.error(\n `lb-hub: a row for <${el.localName}> has no '${keyColumn}' column`,\n );\n return;\n }\n // The key is stored on the row as an attribute and read back from\n // there, so it is compared as the string the attribute holds.\n const key = String(data[keyColumn]);\n if (landed.has(key)) {\n console.error(\n `lb-hub: two rows for <${el.localName}> have the key '${key}'; ` +\n `the last one shows`,\n );\n }\n landed.add(key);\n let row = shown.get(key);\n const fresh = row === undefined;\n if (!row) {\n // Imported rather than cloned: template content belongs to a document\n // with no custom element definitions, so a clone would not upgrade\n // until inserted, and a form-associated control would be filled as if\n // it were not one.\n row = el.ownerDocument.importNode(\n template.content.firstElementChild!,\n true,\n );\n row.setAttribute(ATTR_ROW_LIVE, \"\");\n row.setAttribute(ATTR_KEY_VALUE, key);\n shown.set(key, row);\n }\n // Fill before insertion. The attributes are already there when the row\n // upgrades, which is the same thing that makes a first landing and a\n // refresh one operation everywhere else.\n applyRow(row, data, true);\n if (fresh || whole) place(row, data);\n };\n\n if (Array.isArray(result)) {\n for (const data of result) upsert(data);\n for (const [key, row] of shown) if (!landed.has(key)) row.remove();\n } else {\n for (const data of result.rows ?? []) upsert(data);\n for (const key of result.drop ?? []) shown.get(String(key))?.remove();\n }\n\n // Counted from the DOM rather than from either branch above, so all rows\n // and a patch report the same fact the same way. Only here is the count\n // known: the server answers with rows and says nothing about how many\n // survived reconciliation.\n el.setAttribute(ATTR_QUERY_ROW_COUNT, String(liveRows(el).length));\n\n // Derived scaffolding — a section heading, an <optgroup> — goes when its\n // last row does, and only the custom element knows it exists.\n host.lbRowsLanded?.();\n}\n\n/** Land one response item on one element that names its query. */\nfunction landItem(el: Element, item: ResponseItem): void {\n const template = templateIn(el);\n if (item.kind === KIND_ROW) {\n const row = item.row ?? {};\n if (template) {\n applyRows(el, template, item.key, [row]);\n return;\n }\n applyRow(el, row);\n const key = row[item.key];\n if (key !== undefined && key !== null) {\n el.setAttribute(ATTR_KEY_VALUE, String(key));\n }\n return;\n }\n // A `rows` query with no row template lands nothing: an insert form names\n // the query it adds to, and shows none of its rows.\n if (!template) return;\n const result = item.patch ?? item.rows ?? [];\n applyRows(el, template, item.key, result);\n}\n\n/**\n * What landing keeps for one root: the last whole answer to each query, and\n * every element an answer has landed on.\n */\ninterface Kept {\n answers: Map<string, ResponseItem>;\n landed: WeakSet<Element>;\n}\n\nconst kept = new WeakMap<ParentNode, Kept>();\n\nfunction keptFor(root: ParentNode): Kept {\n let found = kept.get(root);\n if (!found) {\n found = { answers: new Map(), landed: new WeakSet() };\n kept.set(root, found);\n }\n return found;\n}\n\n/**\n * Drop what landing kept for a root. The hub calls it when it replaces the\n * page, since another page's query of the same name is another query.\n */\nexport function forget(root: ParentNode): void {\n kept.delete(root);\n}\n\n/**\n * All rows after a patch, as the elements it landed on now show them: a row\n * it names takes the columns it sends and keeps its place, a new one goes\n * last, and a dropped one goes.\n */\nfunction patched(rows: Row[], key: string, patch: Patch): Row[] {\n const byKey = new Map(rows.map((row) => [String(row[key]), row]));\n for (const row of patch.rows ?? []) {\n const k = String(row[key]);\n byKey.set(k, { ...byKey.get(k), ...row });\n }\n for (const k of patch.drop ?? []) byKey.delete(String(k));\n return [...byKey.values()];\n}\n\n/**\n * Keep an answer as all of the query's rows. A patch is applied to the\n * answer already kept; with none, it is not the whole of anything, and\n * nothing is kept.\n */\nfunction keep(answers: Map<string, ResponseItem>, item: ResponseItem): void {\n if (!item.patch) {\n answers.set(item.query, item);\n return;\n }\n const before = answers.get(item.query);\n if (!before) return;\n const { patch: _, ...whole } = item;\n answers.set(item.query, {\n ...whole,\n rows: patched(before.rows ?? [], item.key, item.patch),\n });\n}\n\n/**\n * A custom element whose class is defined and has not yet run on it: one the\n * builder shipped inside an absent branch's template, where nothing upgrades.\n * It has none of the hooks landing calls, so rows that land on it are not\n * placed by it. A landing on it does not count, and once `lb-show` brings it\n * into the document and it upgrades, it is filled again from the kept answer.\n *\n * An element with no class, such as one defined by an element file alone,\n * never upgrades, and is never waiting.\n */\nfunction waiting(el: Element): boolean {\n const registry = (globalThis as { customElements?: CustomElementRegistry })\n .customElements;\n const upgraded = registry?.get(el.localName);\n return upgraded !== undefined && !(el instanceof upgraded);\n}\n\n/**\n * Fill every element that names a kept query and has had nothing land on it.\n * Filling one can build more — a live row holding a picker of its own — so\n * it goes round until a pass finds nothing new.\n */\nfunction fillArrivals(root: ParentNode, { answers, landed }: Kept): void {\n for (let filled = true; filled;) {\n filled = false;\n for (const [query, item] of answers) {\n for (const el of everywhere(root, `[${ATTR_QUERY}=\"${query}\"]`)) {\n if (landed.has(el) || waiting(el)) continue;\n landed.add(el);\n landItem(el, item);\n filled = true;\n }\n }\n }\n}\n\n/**\n * Land response items. Every answer arrives through here, and is kept for\n * `root`, so that what arrives after it is filled from it — see forget().\n *\n * `quiet` names queries that may have nowhere to land without a warning: the\n * hub's own `lb-url` lands wherever a chrome or page names it, and nowhere\n * otherwise.\n */\nexport function applyResponse(\n root: ParentNode,\n items: ResponseItem[],\n quiet: readonly string[] = [],\n): void {\n const kept = keptFor(root);\n for (const item of items) {\n keep(kept.answers, item);\n const targets = everywhere(root, `[${ATTR_QUERY}=\"${item.query}\"]`);\n if (targets.length === 0) {\n if (!quiet.includes(item.query)) {\n console.warn(`lb-hub: nothing names '${item.query}', skipping`);\n }\n continue;\n }\n for (const el of targets) {\n if (!waiting(el)) kept.landed.add(el);\n landItem(el, item);\n }\n }\n fillArrivals(root, kept);\n}\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"lb-hub.browser.d.ts","sourceRoot":"","sources":["../../hub/lb-hub.browser.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"lb-hub.browser.d.ts","sourceRoot":"","sources":["../../hub/lb-hub.browser.ts"],"names":[],"mappings":"AAkDA,OAAO,EAAE,aAAa,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC"}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
/// <reference lib="dom" />
|
|
2
|
-
import { ATTR_COLUMN, ATTR_COLUMN_VALUE, ATTR_KEY_VALUE, ATTR_PAGE, ATTR_PAGE_TITLE, ATTR_QUERY, ATTR_REQUEST, ATTR_REQUEST_ERROR, ATTR_REQUEST_PENDING, ATTR_URL_LINK, ATTR_URL_PUSH, ATTR_URL_UNKNOWN, HUB_TAG_NAME, KIND_ROW, LB_ENDPOINT, LB_EVENT_NAME, LB_REQUEST_TIMEOUT_MS, LB_RESERVED_PREFIX, LIVE_ROW, REQUEST_ROW_DELETE, REQUEST_ROW_INSERT, REQUEST_ROW_UPDATE, URL_COLUMN_PAGE_LABEL, URL_COLUMN_PAGE_UNKNOWN, URL_COLUMN_PATH, URL_QUERY, } from "../core/lb-constants.js";
|
|
2
|
+
import { ATTR_COLUMN, ATTR_COLUMN_VALUE, ATTR_KEY_VALUE, ATTR_PAGE, ATTR_PAGE_TITLE, ATTR_QUERY, ATTR_REQUEST, ATTR_REQUEST_ERROR, ATTR_REQUEST_PENDING, ATTR_URL_LINK, ATTR_URL_PUSH, ATTR_URL_UNKNOWN, HUB_TAG_NAME, KIND_ROW, LB_DONE_EVENT_NAME, LB_ENDPOINT, LB_EVENT_NAME, LB_REQUEST_TIMEOUT_MS, LB_RESERVED_PREFIX, LIVE_ROW, REQUEST_ROW_DELETE, REQUEST_ROW_INSERT, REQUEST_ROW_UPDATE, URL_COLUMN_PAGE_LABEL, URL_COLUMN_PAGE_UNKNOWN, URL_COLUMN_PATH, URL_QUERY, } from "../core/lb-constants.js";
|
|
3
3
|
import { isRowRequest, nextLocation, pageNameFor, } from "../core/lb-types.js";
|
|
4
|
-
import { applyResponse, isControl, isFormAssociated, within, } from "./lb-apply.js";
|
|
4
|
+
import { applyResponse, forget, isControl, isFormAssociated, within, } from "./lb-apply.js";
|
|
5
5
|
export { applyResponse, applyRow } from "./lb-apply.js";
|
|
6
6
|
/** What each request Loadbare provides cannot be issued without. */
|
|
7
7
|
const NEEDS = {
|
|
@@ -268,6 +268,50 @@ function pending(el, on) {
|
|
|
268
268
|
el.removeAttribute("aria-busy");
|
|
269
269
|
}
|
|
270
270
|
}
|
|
271
|
+
/**
|
|
272
|
+
* Tell the element that committed how its request turned out. Raised after
|
|
273
|
+
* everything the request brought back has landed, so a listener sees the
|
|
274
|
+
* page as the answer left it, and `lb-request-pending` is already gone.
|
|
275
|
+
*/
|
|
276
|
+
function done(origin, request, landed) {
|
|
277
|
+
const detail = landed instanceof Error
|
|
278
|
+
? { request, items: [], error: landed }
|
|
279
|
+
: { request, items: landed };
|
|
280
|
+
origin?.dispatchEvent(new CustomEvent(LB_DONE_EVENT_NAME, { bubbles: true, detail }));
|
|
281
|
+
}
|
|
282
|
+
/** What can take focus, before asking whether it can be operated. */
|
|
283
|
+
const FOCUSABLE = `a[href], button, input:not([type="hidden"]), select, textarea, ` +
|
|
284
|
+
`summary, [tabindex]:not([tabindex="-1"]), ` +
|
|
285
|
+
`[contenteditable]:not([contenteditable="false"])`;
|
|
286
|
+
/**
|
|
287
|
+
* Focus the first element in `main` the user can operate: not disabled, not
|
|
288
|
+
* in a closed dialog, not inert, not hidden, and one that took the focus
|
|
289
|
+
* when asked. Nothing in a `<template>` is a candidate, so an absent
|
|
290
|
+
* `lb-show` branch is passed over. Focus already in `main` is the user's,
|
|
291
|
+
* and is left where it is.
|
|
292
|
+
*/
|
|
293
|
+
function focusFirst(main) {
|
|
294
|
+
if (main.contains(document.activeElement))
|
|
295
|
+
return;
|
|
296
|
+
for (const el of main.querySelectorAll(FOCUSABLE)) {
|
|
297
|
+
if (el.matches(":disabled"))
|
|
298
|
+
continue;
|
|
299
|
+
if (el.closest(`dialog:not([open]), [inert], [hidden]`))
|
|
300
|
+
continue;
|
|
301
|
+
if (el.checkVisibility?.() === false)
|
|
302
|
+
continue;
|
|
303
|
+
el.focus();
|
|
304
|
+
if (document.activeElement === el)
|
|
305
|
+
return;
|
|
306
|
+
}
|
|
307
|
+
}
|
|
308
|
+
/**
|
|
309
|
+
* The URL a round trip answers for: its path and its query string. An answer
|
|
310
|
+
* that returns to another is not landed.
|
|
311
|
+
*/
|
|
312
|
+
function here() {
|
|
313
|
+
return location.pathname + location.search;
|
|
314
|
+
}
|
|
271
315
|
/** A plain primary click: no other button, no modifier, not yet handled. */
|
|
272
316
|
function isPlainClick(e) {
|
|
273
317
|
return (e.button === 0 &&
|
|
@@ -298,6 +342,12 @@ class LbHub extends HTMLElement {
|
|
|
298
342
|
* request says which page it came from, on the path below the endpoint.
|
|
299
343
|
*/
|
|
300
344
|
page = "";
|
|
345
|
+
/**
|
|
346
|
+
* Set when a page is entered, and cleared once its queries have landed
|
|
347
|
+
* and focus has gone to its first control. A change of query parm on the
|
|
348
|
+
* same page does not set it: the user is where they chose to be.
|
|
349
|
+
*/
|
|
350
|
+
entering = false;
|
|
301
351
|
connectedCallback() {
|
|
302
352
|
this.main = this.querySelector("main");
|
|
303
353
|
// Completed in the capture phase, on the way down, so every ancestor
|
|
@@ -315,7 +365,7 @@ class LbHub extends HTMLElement {
|
|
|
315
365
|
// itself, since the event bubbles).
|
|
316
366
|
const origin = e.target ?? undefined;
|
|
317
367
|
if (request.query?.startsWith(LB_RESERVED_PREFIX)) {
|
|
318
|
-
this.answer(request, origin);
|
|
368
|
+
void this.answer(request, origin);
|
|
319
369
|
return;
|
|
320
370
|
}
|
|
321
371
|
void this.send(request, origin);
|
|
@@ -399,22 +449,31 @@ class LbHub extends HTMLElement {
|
|
|
399
449
|
* there, in the same round trip.
|
|
400
450
|
*/
|
|
401
451
|
async send(request, origin) {
|
|
402
|
-
const
|
|
403
|
-
const items = await this.roundTrip(page, request, origin);
|
|
404
|
-
if (items
|
|
405
|
-
return;
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
452
|
+
const at = here();
|
|
453
|
+
const items = await this.roundTrip(this.page, request, origin);
|
|
454
|
+
if (items instanceof Error)
|
|
455
|
+
return done(origin, request, items);
|
|
456
|
+
let landed = [];
|
|
457
|
+
// The server answered for the URL the request was sent from. A user who
|
|
458
|
+
// moved while it was in flight, to another page or to other parms, is
|
|
459
|
+
// looking at something it says nothing about, and on a URL that is not
|
|
460
|
+
// the server's to change. The write still happened.
|
|
461
|
+
if (here() === at) {
|
|
462
|
+
const url = items.find((item) => item.query === URL_QUERY);
|
|
463
|
+
const load = items.filter((item) => item !== url);
|
|
464
|
+
landed = load;
|
|
465
|
+
if (url === undefined)
|
|
466
|
+
applyResponse(this, load);
|
|
467
|
+
else
|
|
468
|
+
landed = await this.follow(url, load, origin);
|
|
469
|
+
}
|
|
412
470
|
insertedFrom.get(request)?.reset();
|
|
471
|
+
done(origin, request, landed);
|
|
413
472
|
}
|
|
414
473
|
/**
|
|
415
474
|
* One round trip for a page: a request, or with none a page load. The
|
|
416
475
|
* element that issued it carries `lb-request-pending` while it is in
|
|
417
|
-
* flight, and `lb-request-error` when it fails.
|
|
476
|
+
* flight, and `lb-request-error` when it fails. The error on failure.
|
|
418
477
|
*/
|
|
419
478
|
async roundTrip(page, request, origin) {
|
|
420
479
|
pending(origin, true);
|
|
@@ -424,7 +483,7 @@ class LbHub extends HTMLElement {
|
|
|
424
483
|
catch (err) {
|
|
425
484
|
console.error(`lb-hub: request failed for '${page}'`, err);
|
|
426
485
|
origin?.setAttribute(ATTR_REQUEST_ERROR, "");
|
|
427
|
-
return
|
|
486
|
+
return err instanceof Error ? err : new Error(String(err));
|
|
428
487
|
}
|
|
429
488
|
finally {
|
|
430
489
|
pending(origin, false);
|
|
@@ -434,15 +493,16 @@ class LbHub extends HTMLElement {
|
|
|
434
493
|
* Answer a request for a query the hub serves, with no round trip. The
|
|
435
494
|
* hub serves `lb-url`, and updates it.
|
|
436
495
|
*/
|
|
437
|
-
answer(request, origin) {
|
|
496
|
+
async answer(request, origin) {
|
|
438
497
|
if (request.query !== URL_QUERY || request.name !== REQUEST_ROW_UPDATE) {
|
|
439
|
-
|
|
440
|
-
`the hub answers, ignoring
|
|
441
|
-
|
|
498
|
+
const message = `lb-hub: '${request.name}' for '${request.query}' is not a request ` +
|
|
499
|
+
`the hub answers, ignoring`;
|
|
500
|
+
console.error(message);
|
|
501
|
+
return done(origin, request, new Error(message));
|
|
442
502
|
}
|
|
443
503
|
const pushed = origin?.hasAttribute(ATTR_URL_PUSH) ?? false;
|
|
444
|
-
|
|
445
|
-
|
|
504
|
+
const moved = this.moveTo(request.values ?? {}, pushed);
|
|
505
|
+
done(origin, request, moved ? await this.navigate(origin) : []);
|
|
446
506
|
}
|
|
447
507
|
/**
|
|
448
508
|
* Write a row for `lb-url` into the URL. A new page pushes a history
|
|
@@ -465,18 +525,20 @@ class LbHub extends HTMLElement {
|
|
|
465
525
|
* without marking the element that issued the request: its write
|
|
466
526
|
* succeeded, and an error would invite sending it twice.
|
|
467
527
|
*
|
|
468
|
-
* `
|
|
469
|
-
*
|
|
528
|
+
* What landed: the `lb-url` item and the load, however it arrived. A load
|
|
529
|
+
* asked for again that fails is not the request's failure.
|
|
470
530
|
*/
|
|
471
|
-
async follow(
|
|
472
|
-
if (pageNameFor(location.pathname) !== page)
|
|
473
|
-
return;
|
|
531
|
+
async follow(item, load, origin) {
|
|
474
532
|
this.moveTo(item.row ?? {}, origin?.hasAttribute(ATTR_URL_PUSH) ?? false);
|
|
475
|
-
if (load.length === 0)
|
|
476
|
-
|
|
533
|
+
if (load.length === 0) {
|
|
534
|
+
const again = await this.navigate();
|
|
535
|
+
return again instanceof Error ? [item] : [item, ...again];
|
|
536
|
+
}
|
|
477
537
|
const template = this.arrive();
|
|
478
538
|
if (template)
|
|
479
539
|
applyResponse(this, load);
|
|
540
|
+
this.entered();
|
|
541
|
+
return template ? [item, ...load] : [item];
|
|
480
542
|
}
|
|
481
543
|
/**
|
|
482
544
|
* Load the page at the URL the browser is showing. Every way of arriving
|
|
@@ -489,13 +551,33 @@ class LbHub extends HTMLElement {
|
|
|
489
551
|
*
|
|
490
552
|
* `origin` is the element whose request changed the URL, if one did, and
|
|
491
553
|
* carries the round trip's pending and error state.
|
|
554
|
+
*
|
|
555
|
+
* What landed, or the error when the round trip failed. A load that
|
|
556
|
+
* returns after the URL has moved again lands nothing: the load for where
|
|
557
|
+
* the browser is now is already on its way, and may be here.
|
|
492
558
|
*/
|
|
493
559
|
async navigate(origin) {
|
|
494
560
|
const template = this.arrive();
|
|
495
561
|
if (!template)
|
|
496
|
-
return;
|
|
562
|
+
return [];
|
|
563
|
+
const at = here();
|
|
497
564
|
const items = await this.roundTrip(this.page, undefined, origin);
|
|
498
|
-
|
|
565
|
+
if (here() !== at)
|
|
566
|
+
return items instanceof Error ? items : [];
|
|
567
|
+
const landed = items instanceof Error ? [] : items;
|
|
568
|
+
applyResponse(this, landed);
|
|
569
|
+
this.entered();
|
|
570
|
+
return items instanceof Error ? items : landed;
|
|
571
|
+
}
|
|
572
|
+
/**
|
|
573
|
+
* A page that was entered has landed its queries, so its first control
|
|
574
|
+
* exists: a row cloned, a branch shown, a picker's options in place.
|
|
575
|
+
*/
|
|
576
|
+
entered() {
|
|
577
|
+
if (!this.entering)
|
|
578
|
+
return;
|
|
579
|
+
this.entering = false;
|
|
580
|
+
focusFirst(this.main);
|
|
499
581
|
}
|
|
500
582
|
/**
|
|
501
583
|
* Show the page the path names, and land `lb-url`. Null when no page's
|
|
@@ -507,8 +589,11 @@ class LbHub extends HTMLElement {
|
|
|
507
589
|
if (template && page !== this.page) {
|
|
508
590
|
this.page = page;
|
|
509
591
|
// The template is already in the document, so the page's markup goes
|
|
510
|
-
// in before its data arrives rather than leaving <main> empty.
|
|
592
|
+
// in before its data arrives rather than leaving <main> empty. What
|
|
593
|
+
// the last page's queries answered goes with it.
|
|
511
594
|
this.main.replaceChildren(template.content.cloneNode(true));
|
|
595
|
+
forget(this);
|
|
596
|
+
this.entering = true;
|
|
512
597
|
}
|
|
513
598
|
this.landUrl(template ? titleOf(template, page) : null);
|
|
514
599
|
// An app that ships `<body hidden>` (docs/reference/chrome.md) stays
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"lb-hub.browser.js","sourceRoot":"","sources":["../../hub/lb-hub.browser.ts"],"names":[],"mappings":"AAAA,2BAA2B;AAE3B,OAAO,EACL,WAAW,EACX,iBAAiB,EACjB,cAAc,EACd,SAAS,EACT,eAAe,EACf,UAAU,EACV,YAAY,EACZ,kBAAkB,EAClB,oBAAoB,EACpB,aAAa,EACb,aAAa,EACb,gBAAgB,EAChB,YAAY,EACZ,QAAQ,EACR,WAAW,EACX,aAAa,EACb,qBAAqB,EACrB,kBAAkB,EAClB,QAAQ,EACR,kBAAkB,EAClB,kBAAkB,EAClB,kBAAkB,EAClB,qBAAqB,EACrB,uBAAuB,EACvB,eAAe,EACf,SAAS,GACV,MAAM,yBAAyB,CAAC;AACjC,OAAO,EACL,YAAY,EACZ,YAAY,EACZ,WAAW,GAKZ,MAAM,qBAAqB,CAAC;AAC7B,OAAO,EACL,aAAa,EACb,SAAS,EACT,gBAAgB,EAChB,MAAM,GAEP,MAAM,eAAe,CAAC;AAEvB,OAAO,EAAE,aAAa,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AAExD,oEAAoE;AACpE,MAAM,KAAK,GAAkD;IAC3D,CAAC,kBAAkB,CAAC,EAAE,CAAC,OAAO,EAAE,QAAQ,CAAC;IACzC,CAAC,kBAAkB,CAAC,EAAE,CAAC,OAAO,EAAE,KAAK,EAAE,QAAQ,CAAC;IAChD,CAAC,kBAAkB,CAAC,EAAE,CAAC,OAAO,EAAE,KAAK,CAAC;CACvC,CAAC;AAEF,2EAA2E;AAC3E,SAAS,OAAO,CAAC,EAAW;IAC1B,OAAO,EAAE,CAAC,aAAa,EAAE,OAAO,CAAC,IAAI,UAAU,GAAG,CAAC,IAAI,IAAI,CAAC;AAC9D,CAAC;AAED,4CAA4C;AAC5C,SAAS,SAAS,CAAC,EAAW;IAC5B,OAAO,EAAE,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC;AAC9B,CAAC;AAED;;;GAGG;AACH,SAAS,OAAO,CAAC,EAAW,EAAE,KAAc;IAC1C,qEAAqE;IACrE,MAAM,GAAG,GAAG,EAAE,CAAC,OAAO,CAAC,QAAQ,CAAC;QAC9B,CAAC,CAAC,EAAE;QACJ,CAAC,CAAC,EAAE,CAAC,aAAa,EAAE,OAAO,CAAC,IAAI,cAAc,GAAG,CAAC,CAAC;IACrD,IAAI,CAAC,GAAG;QAAE,OAAO,SAAS,CAAC;IAC3B,yEAAyE;IACzE,0DAA0D;IAC1D,MAAM,OAAO,GAAG,GAAG,CAAC,OAAO,CAAC,QAAQ,CAAC;QACnC,CAAC,CAAC,OAAO,CAAC,GAAG,CAAC,KAAK,KAAK;QACxB,CAAC,CAAC,GAAG,KAAK,KAAK,CAAC;IAClB,OAAO,OAAO,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,YAAY,CAAC,cAAc,CAAC,IAAI,SAAS,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC;AAC/E,CAAC;AAED;;;;GAIG;AACH,SAAS,UAAU,CAAC,IAAqB;IACvC,OAAO,CAAC,GAAI,IAAI,CAAC,QAAyC,CAAC,CAAC;AAC9D,CAAC;AAED;;;GAGG;AACH,SAAS,WAAW,CAAC,EAAW;IAC9B,MAAM,KAAK,GAAI,EAAyB,CAAC,IAAI,CAAC;IAC9C,OAAO,KAAK,IAAK,KAAiB,CAAC,SAAS,KAAK,MAAM;QACrD,CAAC,CAAE,KAAyB;QAC5B,CAAC,CAAC,IAAI,CAAC;AACX,CAAC;AAWD;;;;;;;;;;;GAWG;AACH,SAAS,QAAQ,CAAC,EAAW;IAC3B,IAAI,EAAE,CAAC,YAAY,CAAC,WAAW,CAAC;QAAE,OAAO,EAAE,QAAQ,EAAE,CAAC,EAAE,CAAC,EAAE,IAAI,EAAE,EAAE,EAAE,CAAC;IACtE,IAAI,EAAE,CAAC,SAAS,KAAK,MAAM,EAAE,CAAC;QAC5B,MAAM,IAAI,GAAG,EAAqB,CAAC;QACnC,OAAO,EAAE,QAAQ,EAAE,UAAU,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC;IAC1D,CAAC;IACD,MAAM,IAAI,GAAG,SAAS,CAAC,EAAE,CAAC,CAAC;IAC3B,IAAI,IAAI;QAAE,OAAO,EAAE,QAAQ,EAAE,MAAM,CAAC,IAAI,EAAE,IAAI,WAAW,GAAG,CAAC,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC;IAC5E,MAAM,IAAI,GAAG,WAAW,CAAC,EAAE,CAAC,CAAC;IAC7B,IAAI,IAAI;QAAE,OAAO,EAAE,QAAQ,EAAE,UAAU,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC;IAClE,OAAO,IAAI,CAAC;AACd,CAAC;AAED,oEAAoE;AACpE,SAAS,MAAM,CAAC,KAAmB;IAIjC,MAAM,QAAQ,GAAc,EAAE,CAAC;IAC/B,MAAM,MAAM,GAA2B,EAAE,CAAC;IAC1C,KAAK,MAAM,EAAE,IAAI,KAAK,EAAE,QAAQ,IAAI,EAAE,EAAE,CAAC;QACvC,MAAM,MAAM,GAAG,EAAE,CAAC,YAAY,CAAC,WAAW,CAAC,CAAC;QAC5C,IAAI,MAAM,KAAK,IAAI,IAAI,CAAC,SAAS,CAAC,EAAE,CAAC;YAAE,SAAS;QAChD,MAAM,MAAM,GAAG,OAAO,CAAC,EAAE,CAAC,CAAC;QAC3B,IAAI,MAAM,IAAI,MAAM,KAAK,KAAM,CAAC,IAAI,IAAI,KAAM,CAAC,IAAI,CAAC,QAAQ,CAAC,MAAM,CAAC,EAAE,CAAC;YACrE,SAAS;QACX,CAAC;QACD,QAAQ,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;QAClB,MAAM,CAAC,MAAM,CAAC,GAAG,EAAE,CAAC,KAAK,CAAC;IAC5B,CAAC;IACD,OAAO,EAAE,QAAQ,EAAE,MAAM,EAAE,CAAC;AAC9B,CAAC;AAED,yEAAyE;AACzE,MAAM,YAAY,GAAG,IAAI,OAAO,EAA+B,CAAC;AAEhE;;;;;;GAMG;AACH,SAAS,QAAQ,CAAC,OAA+B,EAAE,EAAW;IAC5D,IAAI,CAAC,OAAO,EAAE,IAAI,EAAE,CAAC;QACnB,OAAO,CAAC,IAAI,CAAC,4CAA4C,EAAE,OAAO,CAAC,CAAC;QACpE,OAAO,KAAK,CAAC;IACf,CAAC;IACD,MAAM,EAAE,IAAI,EAAE,GAAG,OAAO,CAAC;IACzB,IAAI,IAAI,CAAC,UAAU,CAAC,kBAAkB,CAAC,IAAI,CAAC,YAAY,CAAC,IAAI,CAAC,EAAE,CAAC;QAC/D,OAAO,CAAC,KAAK,CACX,YAAY,IAAI,kBAAkB,kBAAkB,iBAAiB;YACnE,qCAAqC,CACxC,CAAC;QACF,OAAO,KAAK,CAAC;IACf,CAAC;IAED,MAAM,KAAK,GAAG,QAAQ,CAAC,EAAE,CAAC,CAAC;IAC3B,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,GAAG,MAAM,CAAC,KAAK,CAAC,CAAC;IAC3C,IAAI,OAAO,CAAC,MAAM,KAAK,SAAS,IAAI,QAAQ,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QACxD,OAAO,CAAC,MAAM,GAAG,MAAM,CAAC;IAC1B,CAAC;IAED,2EAA2E;IAC3E,2CAA2C;IAC3C,MAAM,OAAO,GAAG,IAAI,GAAG,CAAC,QAAQ,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC;IAC/C,IAAI,OAAO,CAAC,IAAI,GAAG,CAAC,EAAE,CAAC;QACrB,OAAO,CAAC,KAAK,CACX,YAAY,IAAI,sDAAsD,EACtE,EAAE,CACH,CAAC;QACF,OAAO,KAAK,CAAC;IACf,CAAC;IACD,MAAM,IAAI,GAAG,QAAQ,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC;IAC/B,MAAM,KAAK,GAAG,QAAQ,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC,CAAE,CAAC,CAAC,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC;IACnE,IAAI,KAAK,EAAE,CAAC;QACV,OAAO,CAAC,KAAK,KAAK,KAAK,CAAC,YAAY,CAAC,UAAU,CAAE,CAAC;QAClD,MAAM,GAAG,GAAG,OAAO,CAAC,IAAI,EAAE,KAAK,CAAC,CAAC;QACjC,IAAI,GAAG,KAAK,SAAS;YAAE,OAAO,CAAC,GAAG,KAAK,GAAG,CAAC;IAC7C,CAAC;IAED,IAAI,IAAI,KAAK,kBAAkB,IAAI,KAAK,EAAE,IAAI,EAAE,CAAC;QAC/C,YAAY,CAAC,GAAG,CAAC,OAAO,EAAE,KAAK,CAAC,IAAI,CAAC,CAAC;IACxC,CAAC;IAED,MAAM,KAAK,GAAG,KAAK,CAAC,IAAI,CAAC,CAAC;IAC1B,IAAI,KAAK,EAAE,CAAC;QACV,MAAM,OAAO,GAAG,KAAK,CAAC,MAAM,CAC1B,CAAC,KAAK,EAAE,EAAE,CACR,OAAO,CAAC,KAAK,CAAC,KAAK,SAAS;YAC5B,CAAC,KAAK,KAAK,QAAQ,IAAI,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC,MAAO,CAAC,CAAC,MAAM,KAAK,CAAC,CAAC,CACpE,CAAC;QACF,IAAI,OAAO,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YACvB,OAAO,CAAC,KAAK,CACX,YAAY,IAAI,WAAW,EAAE,CAAC,SAAS,WAAW;gBAChD,GAAG,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,YAAY,EACnC,EAAE,CACH,CAAC;YACF,OAAO,KAAK,CAAC;QACf,CAAC;IACH,CAAC;IACD,OAAO,IAAI,CAAC;AACd,CAAC;AAED;;;GAGG;AACH,SAAS,MAAM,CAAC,EAAW;IACzB,IAAI,EAAE,CAAC,YAAY,CAAC,oBAAoB,CAAC;QAAE,OAAO;IAClD,MAAM,MAAM,GAAe,EAAE,IAAI,EAAE,EAAE,CAAC,YAAY,CAAC,YAAY,CAAE,EAAE,CAAC;IACpE,EAAE,CAAC,aAAa,CAAC,IAAI,WAAW,CAAC,aAAa,EAAE,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC,CAAC,CAAC;AAC9E,CAAC;AAED,+EAA+E;AAC/E,SAAS,cAAc,CAAC,EAAW;IACjC,MAAM,IAAI,GAAI,EAAuB,CAAC,IAAc,CAAC;IACrD,MAAM,OAAO,GACX,CAAC,EAAE,CAAC,SAAS,KAAK,QAAQ,IAAI,IAAI,KAAK,QAAQ,CAAC;QAChD,CAAC,EAAE,CAAC,SAAS,KAAK,OAAO,IAAI,CAAC,IAAI,KAAK,QAAQ,IAAI,IAAI,KAAK,OAAO,CAAC,CAAC,CAAC;IACxE,OAAO,OAAO,IAAI,WAAW,CAAC,EAAE,CAAC,KAAK,IAAI,CAAC;AAC7C,CAAC;AAED;;;;GAIG;AACH,MAAM,WAAW,GAAG;IAClB,SAAS;IACT,QAAQ;IACR,0BAA0B;IAC1B,QAAQ;IACR,UAAU;IACV,OAAO;IACP,SAAS;IACT,QAAQ;IACR,OAAO;IACP,iBAAiB;IACjB,iBAAiB;IACjB,aAAa;CACd,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AAEb;;;;GAIG;AACH,SAAS,MAAM,CAAC,MAAe,EAAE,EAAW;IAC1C,KAAK,IAAI,IAAI,GAAmB,MAAM,EAAE,IAAI,IAAI,IAAI,KAAK,EAAE,GAAG,CAAC;QAC7D,IAAI,IAAI,CAAC,OAAO,CAAC,WAAW,CAAC,IAAI,gBAAgB,CAAC,IAAI,CAAC;YAAE,OAAO,KAAK,CAAC;QACtE,IAAI,GAAG,IAAI,CAAC,aAAa,CAAC;IAC5B,CAAC;IACD,OAAO,IAAI,CAAC;AACd,CAAC;AAED,2DAA2D;AAC3D,SAAS,OAAO,CAAC,QAAoC,EAAE,IAAY;IACjE,OAAO,QAAQ,EAAE,YAAY,CAAC,eAAe,CAAC,IAAI,IAAI,CAAC;AACzD,CAAC;AAED;;;;GAIG;AACH,SAAS,WAAW,CAAC,IAAY;IAC/B,MAAM,KAAK,GAA0B,EAAE,CAAC;IACxC,KAAK,MAAM,EAAE,IAAI,QAAQ,CAAC,gBAAgB,CAAC,YAAY,SAAS,GAAG,CAAC,EAAE,CAAC;QACrE,IAAI,EAAE,CAAC,YAAY,CAAC,SAAS,CAAC,KAAK,IAAI,EAAE,CAAC;YACxC,KAAK,CAAC,IAAI,CAAC,EAAyB,CAAC,CAAC;QACxC,CAAC;IACH,CAAC;IACD,IAAI,KAAK,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QACrB,OAAO,CAAC,KAAK,CACX,WAAW,KAAK,CAAC,MAAM,gBAAgB,SAAS,KAAK,IAAI,KAAK;YAC5D,iBAAiB,CACpB,CAAC;IACJ,CAAC;IACD,OAAO,KAAK,CAAC,CAAC,CAAC,IAAI,IAAI,CAAC;AAC1B,CAAC;AAED;;;;;;;;GAQG;AACH,KAAK,UAAU,UAAU,CACvB,IAAY,EACZ,OAAoB;IAEpB,MAAM,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,kBAAkB,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;IAC/D,MAAM,GAAG,GAAG,GAAG,WAAW,IAAI,IAAI,GAAG,QAAQ,CAAC,MAAM,EAAE,CAAC;IACvD,MAAM,UAAU,GAAG,IAAI,eAAe,EAAE,CAAC;IACzC,MAAM,OAAO,GAAG,UAAU,CAAC,GAAG,EAAE,CAAC,UAAU,CAAC,KAAK,EAAE,EAAE,qBAAqB,CAAC,CAAC;IAC5E,IAAI,CAAC;QACH,4DAA4D;QAC5D,MAAM,GAAG,GAAG,MAAM,KAAK,CAAC,GAAG,EAAE;YAC3B,MAAM,EAAE,MAAM;YACd,OAAO,EAAE,EAAE,cAAc,EAAE,kBAAkB,EAAE;YAC/C,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,OAAO,IAAI,EAAE,CAAC;YACnC,MAAM,EAAE,UAAU,CAAC,MAAM;SAC1B,CAAC,CAAC;QACH,IAAI,CAAC,GAAG,CAAC,EAAE,EAAE,CAAC;YACZ,MAAM,IAAI,KAAK,CAAC,4BAA4B,GAAG,CAAC,MAAM,QAAQ,GAAG,EAAE,CAAC,CAAC;QACvE,CAAC;QACD,OAAO,CAAC,MAAM,GAAG,CAAC,IAAI,EAAE,CAAgB,CAAC;IAC3C,CAAC;YAAS,CAAC;QACT,YAAY,CAAC,OAAO,CAAC,CAAC;IACxB,CAAC;AACH,CAAC;AAED,uDAAuD;AACvD,SAAS,OAAO,CAAC,EAAuB,EAAE,EAAW;IACnD,IAAI,CAAC,EAAE;QAAE,OAAO;IAChB,IAAI,EAAE,EAAE,CAAC;QACP,EAAE,CAAC,eAAe,CAAC,kBAAkB,CAAC,CAAC;QACvC,EAAE,CAAC,YAAY,CAAC,oBAAoB,EAAE,EAAE,CAAC,CAAC;QAC1C,EAAE,CAAC,YAAY,CAAC,WAAW,EAAE,MAAM,CAAC,CAAC;IACvC,CAAC;SAAM,CAAC;QACN,EAAE,CAAC,eAAe,CAAC,oBAAoB,CAAC,CAAC;QACzC,EAAE,CAAC,eAAe,CAAC,WAAW,CAAC,CAAC;IAClC,CAAC;AACH,CAAC;AAED,4EAA4E;AAC5E,SAAS,YAAY,CAAC,CAAa;IACjC,OAAO,CACL,CAAC,CAAC,MAAM,KAAK,CAAC;QACd,CAAC,CAAC,CAAC,gBAAgB;QACnB,CAAC,CAAC,CAAC,OAAO;QACV,CAAC,CAAC,CAAC,OAAO;QACV,CAAC,CAAC,CAAC,QAAQ;QACX,CAAC,CAAC,CAAC,MAAM,CACV,CAAC;AACJ,CAAC;AAED,2EAA2E;AAC3E,SAAS,OAAO,CAAC,GAAQ;IACvB,MAAM,GAAG,GAAG,IAAI,GAAG,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC;IACnC,MAAM,IAAI,GAAG,YAAY,CAAC,WAAW,CAAC,GAAG,CAAC,QAAQ,CAAC,EAAE,GAAG,CAAC,YAAY,EAAE,GAAG,CAAC,CAAC;IAC5E,MAAM,IAAI,GAAG,GAAG,CAAC,eAAe,CAAC,CAAC;IAClC,IAAI,OAAO,IAAI,KAAK,QAAQ;QAAE,GAAG,CAAC,QAAQ,GAAG,IAAI,CAAC;IAClD,GAAG,CAAC,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,QAAQ,EAAE,CAAC;IACnC,OAAO,EAAE,GAAG,EAAE,KAAK,EAAE,IAAI,CAAC,KAAK,EAAE,CAAC;AACpC,CAAC;AAED;;;GAGG;AACH,MAAM,KAAM,SAAQ,WAAW;IACrB,IAAI,CAAe;IAE3B;;;OAGG;IACK,IAAI,GAAG,EAAE,CAAC;IAElB,iBAAiB;QACf,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC,aAAa,CAAC,MAAM,CAAE,CAAC;QAExC,qEAAqE;QACrE,yEAAyE;QACzE,oEAAoE;QACpE,IAAI,CAAC,gBAAgB,CACnB,aAAa,EACb,CAAC,CAAQ,EAAE,EAAE;YACX,MAAM,MAAM,GAAG,CAAC,CAAC,MAAiB,CAAC;YACnC,MAAM,OAAO,GAAI,CAA6B,CAAC,MAAM,CAAC;YACtD,IAAI,CAAC,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;gBAAE,CAAC,CAAC,eAAe,EAAE,CAAC;QACtD,CAAC,EACD,EAAE,OAAO,EAAE,IAAI,EAAE,CAClB,CAAC;QAEF,IAAI,CAAC,gBAAgB,CAAC,aAAa,EAAE,CAAC,CAAQ,EAAE,EAAE;YAChD,MAAM,OAAO,GAAI,CAA6B,CAAC,MAAM,CAAC;YACtD,oEAAoE;YACpE,oCAAoC;YACpC,MAAM,MAAM,GAAI,CAAC,CAAC,MAAyB,IAAI,SAAS,CAAC;YACzD,IAAI,OAAO,CAAC,KAAK,EAAE,UAAU,CAAC,kBAAkB,CAAC,EAAE,CAAC;gBAClD,IAAI,CAAC,MAAM,CAAC,OAAO,EAAE,MAAM,CAAC,CAAC;gBAC7B,OAAO;YACT,CAAC;YACD,KAAK,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,MAAM,CAAC,CAAC;QAClC,CAAC,CAAC,CAAC;QAEH,wEAAwE;QACxE,kDAAkD;QAClD,IAAI,CAAC,gBAAgB,CAAC,QAAQ,EAAE,CAAC,CAAc,EAAE,EAAE;YACjD,MAAM,IAAI,GAAG,CAAC,CAAC,MAAwB,CAAC;YACxC,IAAI,CAAC,IAAI;gBAAE,OAAO;YAClB,MAAM,SAAS,GAAG,CAAC,CAAC,SAAS,CAAC;YAC9B,MAAM,EAAE,GAAG,SAAS,EAAE,YAAY,CAAC,YAAY,CAAC;gBAC9C,CAAC,CAAC,SAAS;gBACX,CAAC,CAAC,IAAI,CAAC,YAAY,CAAC,YAAY,CAAC;oBAC/B,CAAC,CAAC,IAAI;oBACN,CAAC,CAAC,IAAI,CAAC;YACX,IAAI,CAAC,EAAE;gBAAE,OAAO;YAChB,CAAC,CAAC,cAAc,EAAE,CAAC;YACnB,MAAM,CAAC,EAAE,CAAC,CAAC;QACb,CAAC,CAAC,CAAC;QAEH,uEAAuE;QACvE,qEAAqE;QACrE,mEAAmE;QACnE,IAAI,CAAC,gBAAgB,CAAC,OAAO,EAAE,CAAC,CAAQ,EAAE,EAAE;YAC1C,IAAI,CAAC,CAAC,gBAAgB;gBAAE,OAAO;YAC/B,KAAK,MAAM,EAAE,IAAI,UAAU,CAAC,CAAC,CAAC,MAAyB,CAAC,EAAE,CAAC;gBACzD,EAAE,CAAC,eAAe,CAAC,iBAAiB,CAAC,CAAC;YACxC,CAAC;QACH,CAAC,CAAC,CAAC;QAEH,+BAA+B;QAC/B,IAAI,CAAC,gBAAgB,CAAC,QAAQ,EAAE,CAAC,CAAQ,EAAE,EAAE;YAC3C,MAAM,EAAE,GAAG,CAAC,CAAC,MAAwB,CAAC;YACtC,IAAI,CAAC,EAAE,IAAI,CAAC,EAAE,CAAC,YAAY,CAAC,YAAY,CAAC,IAAI,CAAC,SAAS,CAAC,EAAE,CAAC;gBAAE,OAAO;YACpE,MAAM,CAAC,EAAE,CAAC,CAAC;QACb,CAAC,CAAC,CAAC;QAEH,yEAAyE;QACzE,oEAAoE;QACpE,oDAAoD;QACpD,IAAI,CAAC,gBAAgB,CAAC,OAAO,EAAE,CAAC,CAAa,EAAE,EAAE;YAC/C,MAAM,MAAM,GAAG,CAAC,CAAC,MAAwB,CAAC;YAC1C,MAAM,EAAE,GAAG,MAAM,EAAE,OAAO,CAAC,IAAI,YAAY,GAAG,CAAC,CAAC;YAChD,IAAI,CAAC,MAAM,IAAI,CAAC,EAAE,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC,EAAE,CAAC;gBAAE,OAAO;YACjD,IAAI,EAAE,CAAC,SAAS,KAAK,MAAM,IAAI,SAAS,CAAC,EAAE,CAAC,IAAI,cAAc,CAAC,EAAE,CAAC,EAAE,CAAC;gBACnE,OAAO;YACT,CAAC;YACD,IAAI,CAAC,MAAM,CAAC,MAAM,EAAE,EAAE,CAAC;gBAAE,OAAO;YAChC,CAAC,CAAC,cAAc,EAAE,CAAC;YACnB,MAAM,CAAC,EAAE,CAAC,CAAC;QACb,CAAC,CAAC,CAAC;QAEH,oEAAoE;QACpE,oEAAoE;QACpE,qEAAqE;QACrE,+CAA+C;QAC/C,IAAI,CAAC,gBAAgB,CAAC,OAAO,EAAE,CAAC,CAAa,EAAE,EAAE;YAC/C,MAAM,IAAI,GAAI,CAAC,CAAC,MAAyB,EAAE,OAAO,CAAC,KAAK,aAAa,GAAG,CAAC,CAAC;YAC1E,IAAI,CAAC,IAAI,IAAI,CAAC,YAAY,CAAC,CAAC,CAAC;gBAAE,OAAO;YACtC,CAAC,CAAC,cAAc,EAAE,CAAC;YACnB,MAAM,IAAI,GAAG,IAAI,GAAG,CAAE,IAA0B,CAAC,IAAI,CAAC,CAAC;YACvD,MAAM,GAAG,GAAQ,EAAE,CAAC;YACpB,KAAK,MAAM,IAAI,IAAI,IAAI,eAAe,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC;gBAC/D,GAAG,CAAC,IAAI,CAAC,GAAG,EAAE,CAAC;YACjB,CAAC;YACD,KAAK,MAAM,CAAC,IAAI,EAAE,KAAK,CAAC,IAAI,IAAI,CAAC,YAAY;gBAAE,GAAG,CAAC,IAAI,CAAC,GAAG,KAAK,CAAC;YACjE,GAAG,CAAC,eAAe,CAAC,GAAG,IAAI,CAAC,QAAQ,CAAC;YACrC,IAAI,CAAC,MAAM,CAAC,GAAG,EAAE,IAAI,CAAC,CAAC;YACvB,KAAK,IAAI,CAAC,QAAQ,EAAE,CAAC;QACvB,CAAC,CAAC,CAAC;QAEH,gBAAgB,CAAC,UAAU,EAAE,GAAG,EAAE,CAAC,KAAK,IAAI,CAAC,QAAQ,EAAE,CAAC,CAAC;QAEzD,KAAK,IAAI,CAAC,QAAQ,EAAE,CAAC;IACvB,CAAC;IAED;;;;OAIG;IACK,KAAK,CAAC,IAAI,CAAC,OAAmB,EAAE,MAAgB;QACtD,MAAM,IAAI,GAAG,IAAI,CAAC,IAAI,CAAC;QACvB,MAAM,KAAK,GAAG,MAAM,IAAI,CAAC,SAAS,CAAC,IAAI,EAAE,OAAO,EAAE,MAAM,CAAC,CAAC;QAC1D,IAAI,KAAK,KAAK,IAAI;YAAE,OAAO;QAC3B,MAAM,GAAG,GAAG,KAAK,CAAC,IAAI,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,KAAK,KAAK,SAAS,CAAC,CAAC;QAC3D,MAAM,IAAI,GAAG,KAAK,CAAC,MAAM,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,KAAK,GAAG,CAAC,CAAC;QAClD,IAAI,GAAG,KAAK,SAAS;YAAE,aAAa,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC;;YAC5C,MAAM,IAAI,CAAC,MAAM,CAAC,IAAI,EAAE,GAAG,EAAE,IAAI,EAAE,MAAM,CAAC,CAAC;QAChD,YAAY,CAAC,GAAG,CAAC,OAAO,CAAC,EAAE,KAAK,EAAE,CAAC;IACrC,CAAC;IAED;;;;OAIG;IACK,KAAK,CAAC,SAAS,CACrB,IAAY,EACZ,OAA+B,EAC/B,MAA2B;QAE3B,OAAO,CAAC,MAAM,EAAE,IAAI,CAAC,CAAC;QACtB,IAAI,CAAC;YACH,OAAO,MAAM,UAAU,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC;QACzC,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,OAAO,CAAC,KAAK,CAAC,+BAA+B,IAAI,GAAG,EAAE,GAAG,CAAC,CAAC;YAC3D,MAAM,EAAE,YAAY,CAAC,kBAAkB,EAAE,EAAE,CAAC,CAAC;YAC7C,OAAO,IAAI,CAAC;QACd,CAAC;gBAAS,CAAC;YACT,OAAO,CAAC,MAAM,EAAE,KAAK,CAAC,CAAC;QACzB,CAAC;IACH,CAAC;IAED;;;OAGG;IACK,MAAM,CAAC,OAAmB,EAAE,MAAgB;QAClD,IAAI,OAAO,CAAC,KAAK,KAAK,SAAS,IAAI,OAAO,CAAC,IAAI,KAAK,kBAAkB,EAAE,CAAC;YACvE,OAAO,CAAC,KAAK,CACX,YAAY,OAAO,CAAC,IAAI,UAAU,OAAO,CAAC,KAAK,qBAAqB;gBAClE,2BAA2B,CAC9B,CAAC;YACF,OAAO;QACT,CAAC;QACD,MAAM,MAAM,GAAG,MAAM,EAAE,YAAY,CAAC,aAAa,CAAC,IAAI,KAAK,CAAC;QAC5D,IAAI,IAAI,CAAC,MAAM,CAAC,OAAO,CAAC,MAAM,IAAI,EAAE,EAAE,MAAM,CAAC;YAAE,KAAK,IAAI,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC;IAC5E,CAAC;IAED;;;;OAIG;IACK,MAAM,CAAC,GAAQ,EAAE,IAAa;QACpC,MAAM,EAAE,GAAG,EAAE,KAAK,EAAE,GAAG,OAAO,CAAC,GAAG,CAAC,CAAC;QACpC,IAAI,GAAG,CAAC,IAAI,KAAK,QAAQ,CAAC,IAAI;YAAE,OAAO,KAAK,CAAC;QAC7C,IAAI,KAAK,IAAI,IAAI;YAAE,OAAO,CAAC,SAAS,CAAC,IAAI,EAAE,EAAE,EAAE,GAAG,CAAC,CAAC;;YAC/C,OAAO,CAAC,YAAY,CAAC,IAAI,EAAE,EAAE,EAAE,GAAG,CAAC,CAAC;QACzC,OAAO,IAAI,CAAC;IACd,CAAC;IAED;;;;;;;;OAQG;IACK,KAAK,CAAC,MAAM,CAClB,IAAY,EACZ,IAAkB,EAClB,IAAoB,EACpB,MAAgB;QAEhB,IAAI,WAAW,CAAC,QAAQ,CAAC,QAAQ,CAAC,KAAK,IAAI;YAAE,OAAO;QACpD,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,IAAI,EAAE,EAAE,MAAM,EAAE,YAAY,CAAC,aAAa,CAAC,IAAI,KAAK,CAAC,CAAC;QAC1E,IAAI,IAAI,CAAC,MAAM,KAAK,CAAC;YAAE,OAAO,IAAI,CAAC,QAAQ,EAAE,CAAC;QAC9C,MAAM,QAAQ,GAAG,IAAI,CAAC,MAAM,EAAE,CAAC;QAC/B,IAAI,QAAQ;YAAE,aAAa,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC;IAC1C,CAAC;IAED;;;;;;;;;;;OAWG;IACK,KAAK,CAAC,QAAQ,CAAC,MAAgB;QACrC,MAAM,QAAQ,GAAG,IAAI,CAAC,MAAM,EAAE,CAAC;QAC/B,IAAI,CAAC,QAAQ;YAAE,OAAO;QACtB,MAAM,KAAK,GAAG,MAAM,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,IAAI,EAAE,SAAS,EAAE,MAAM,CAAC,CAAC;QACjE,aAAa,CAAC,IAAI,EAAE,KAAK,IAAI,EAAE,CAAC,CAAC;IACnC,CAAC;IAED;;;OAGG;IACK,MAAM;QACZ,MAAM,IAAI,GAAG,WAAW,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC;QAC5C,MAAM,QAAQ,GAAG,WAAW,CAAC,IAAI,CAAC,CAAC;QACnC,IAAI,QAAQ,IAAI,IAAI,KAAK,IAAI,CAAC,IAAI,EAAE,CAAC;YACnC,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC;YACjB,qEAAqE;YACrE,+DAA+D;YAC/D,IAAI,CAAC,IAAI,CAAC,eAAe,CAAC,QAAQ,CAAC,OAAO,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC,CAAC;QAC9D,CAAC;QACD,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC,CAAC,OAAO,CAAC,QAAQ,EAAE,IAAI,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC;QACxD,qEAAqE;QACrE,uDAAuD;QACvD,QAAQ,CAAC,IAAI,CAAC,MAAM,GAAG,KAAK,CAAC;QAC7B,IAAI,CAAC,QAAQ,EAAE,CAAC;YACd,OAAO,CAAC,KAAK,CAAC,wBAAwB,IAAI,GAAG,CAAC,CAAC;YAC/C,MAAM,MAAM,GAAG,IAAI,CAAC,aAAa,CAAC,UAAU,gBAAgB,GAAG,CAAC,CAAC;YACjE,IAAI,MAAM,IAAI,CAAE,MAA4B,CAAC,IAAI,EAAE,CAAC;gBACjD,MAA4B,CAAC,SAAS,EAAE,CAAC;YAC5C,CAAC;QACH,CAAC;QACD,OAAO,QAAQ,CAAC;IAClB,CAAC;IAED;;;;;;;;;;OAUG;IACK,OAAO,CAAC,KAAoB;QAClC,IAAI,KAAK,KAAK,IAAI;YAAE,QAAQ,CAAC,KAAK,GAAG,KAAK,CAAC;QAC3C,MAAM,MAAM,GAAG,IAAI,CAAC,gBAAgB,CAAC,IAAI,UAAU,KAAK,SAAS,IAAI,CAAC,CAAC;QACvE,IAAI,MAAM,CAAC,MAAM,KAAK,CAAC;YAAE,OAAO;QAChC,MAAM,GAAG,GAAQ,EAAE,CAAC;QACpB,KAAK,MAAM,KAAK,IAAI,MAAM,EAAE,CAAC;YAC3B,KAAK,MAAM,EAAE,IAAI,MAAM,CAAC,KAAK,EAAE,IAAI,WAAW,GAAG,CAAC,EAAE,CAAC;gBACnD,IAAI,EAAE,KAAK,KAAK;oBAAE,SAAS;gBAC3B,GAAG,CAAC,EAAE,CAAC,YAAY,CAAC,WAAW,CAAE,CAAC,GAAG,EAAE,CAAC;YAC1C,CAAC;QACH,CAAC;QACD,KAAK,MAAM,CAAC,IAAI,EAAE,KAAK,CAAC,IAAI,IAAI,eAAe,CAAC,QAAQ,CAAC,MAAM,CAAC,EAAE,CAAC;YACjE,GAAG,CAAC,IAAI,CAAC,GAAG,KAAK,CAAC;QACpB,CAAC;QACD,GAAG,CAAC,eAAe,CAAC,GAAG,QAAQ,CAAC,QAAQ,CAAC;QACzC,GAAG,CAAC,qBAAqB,CAAC,GAAG,KAAK,CAAC;QACnC,GAAG,CAAC,uBAAuB,CAAC,GAAG,KAAK,KAAK,IAAI,CAAC;QAC9C,aAAa,CAAC,IAAI,EAAE;YAClB,EAAE,KAAK,EAAE,SAAS,EAAE,IAAI,EAAE,QAAQ,EAAE,GAAG,EAAE,eAAe,EAAE,GAAG,EAAE;SAChE,CAAC,CAAC;IACL,CAAC;CACF;AAED,cAAc,CAAC,MAAM,CAAC,YAAY,EAAE,KAAK,CAAC,CAAC","sourcesContent":["/// <reference lib=\"dom\" />\n\nimport {\n ATTR_COLUMN,\n ATTR_COLUMN_VALUE,\n ATTR_KEY_VALUE,\n ATTR_PAGE,\n ATTR_PAGE_TITLE,\n ATTR_QUERY,\n ATTR_REQUEST,\n ATTR_REQUEST_ERROR,\n ATTR_REQUEST_PENDING,\n ATTR_URL_LINK,\n ATTR_URL_PUSH,\n ATTR_URL_UNKNOWN,\n HUB_TAG_NAME,\n KIND_ROW,\n LB_ENDPOINT,\n LB_EVENT_NAME,\n LB_REQUEST_TIMEOUT_MS,\n LB_RESERVED_PREFIX,\n LIVE_ROW,\n REQUEST_ROW_DELETE,\n REQUEST_ROW_INSERT,\n REQUEST_ROW_UPDATE,\n URL_COLUMN_PAGE_LABEL,\n URL_COLUMN_PAGE_UNKNOWN,\n URL_COLUMN_PATH,\n URL_QUERY,\n} from \"../core/lb-constants.js\";\nimport {\n isRowRequest,\n nextLocation,\n pageNameFor,\n type HubRequest,\n type HubResponse,\n type ResponseItem,\n type Row,\n} from \"../core/lb-types.js\";\nimport {\n applyResponse,\n isControl,\n isFormAssociated,\n within,\n type Control,\n} from \"./lb-apply.js\";\n\nexport { applyResponse, applyRow } from \"./lb-apply.js\";\n\n/** What each request Loadbare provides cannot be issued without. */\nconst NEEDS: Record<string, readonly (keyof HubRequest)[]> = {\n [REQUEST_ROW_INSERT]: [\"query\", \"values\"],\n [REQUEST_ROW_UPDATE]: [\"query\", \"key\", \"values\"],\n [REQUEST_ROW_DELETE]: [\"query\", \"key\"],\n};\n\n/** The nearest ancestor carrying `lb-query`. An element is not its own. */\nfunction queryOf(el: Element): Element | null {\n return el.parentElement?.closest(`[${ATTR_QUERY}]`) ?? null;\n}\n\n/** The live row an element is, or is in. */\nfunction liveRowOf(el: Element): Element | null {\n return el.closest(LIVE_ROW);\n}\n\n/**\n * The key of the nearest ancestor row, when that row is of `query`: a live\n * row whose query it is, or the element a `row` of it landed on.\n */\nfunction keyFrom(el: Element, query: Element): string | undefined {\n // A live row is its own row; any other element's row is an ancestor.\n const row = el.matches(LIVE_ROW)\n ? el\n : el.parentElement?.closest(`[${ATTR_KEY_VALUE}]`);\n if (!row) return undefined;\n // A live row's key is its outer query's, even when the row names a query\n // of its own. Any other element's key is its own query's.\n const ofQuery = row.matches(LIVE_ROW)\n ? queryOf(row) === query\n : row === query;\n return ofQuery ? (row.getAttribute(ATTR_KEY_VALUE) ?? undefined) : undefined;\n}\n\n/**\n * Every control whose form owner is `form`: HTML's own list, which holds a\n * control nested in the form or joined to it by the `form` attribute, and a\n * form-associated custom element as well as a native control.\n */\nfunction controlsOf(form: HTMLFormElement): Element[] {\n return [...(form.elements as unknown as Iterable<Element>)];\n}\n\n/**\n * The form owner of an element that has one, as HTML reports it on the\n * element's `form` property.\n */\nfunction formOwnerOf(el: Element): HTMLFormElement | null {\n const owner = (el as { form?: unknown }).form;\n return owner && (owner as Element).localName === \"form\"\n ? (owner as HTMLFormElement)\n : null;\n}\n\n/** The group a request gathers from. */\ninterface Group {\n controls: Element[];\n /** Set when the group is a form, so a successful insert resets it. */\n form?: HTMLFormElement;\n /** What the group is: the form or the live row. */\n root: Element;\n}\n\n/**\n * The controls a request gathers — see docs/reference/data-binding.md,\n * \"Gathering\":\n *\n * 1. the element carrying `lb-request` has `lb-column`: it alone;\n * 2. the element is a `<form>`: the controls whose form owner it is;\n * 3. the element is in a live row: the controls in that live row;\n * 4. otherwise: the controls whose form owner is the element's.\n *\n * A control whose nearest `lb-query` is inside the group belongs to a query\n * nested in it, and is skipped.\n */\nfunction groupFor(el: Element): Group | null {\n if (el.hasAttribute(ATTR_COLUMN)) return { controls: [el], root: el };\n if (el.localName === \"form\") {\n const form = el as HTMLFormElement;\n return { controls: controlsOf(form), form, root: form };\n }\n const live = liveRowOf(el);\n if (live) return { controls: within(live, `[${ATTR_COLUMN}]`), root: live };\n const form = formOwnerOf(el);\n if (form) return { controls: controlsOf(form), form, root: form };\n return null;\n}\n\n/** The gathered controls, with their values under their columns. */\nfunction gather(group: Group | null): {\n controls: Control[];\n values: Record<string, string>;\n} {\n const controls: Control[] = [];\n const values: Record<string, string> = {};\n for (const el of group?.controls ?? []) {\n const column = el.getAttribute(ATTR_COLUMN);\n if (column === null || !isControl(el)) continue;\n const nested = queryOf(el);\n if (nested && nested !== group!.root && group!.root.contains(nested)) {\n continue;\n }\n controls.push(el);\n values[column] = el.value;\n }\n return { controls, values };\n}\n\n/** The form each insert gathered from, until its round trip succeeds. */\nconst insertedFrom = new WeakMap<HubRequest, HTMLFormElement>();\n\n/**\n * Complete a request from where its element sits. Every request passes\n * through here, whoever issued it; a field it already carries is its\n * issuer's to decide and is left as it is.\n *\n * False when the request cannot be issued, having said why.\n */\nfunction complete(request: HubRequest | undefined, el: Element): boolean {\n if (!request?.name) {\n console.warn(`lb-hub: a request without a name, ignoring`, request);\n return false;\n }\n const { name } = request;\n if (name.startsWith(LB_RESERVED_PREFIX) && !isRowRequest(name)) {\n console.error(\n `lb-hub: '${name}' begins with '${LB_RESERVED_PREFIX}' but names no ` +\n `request Loadbare provides, ignoring`,\n );\n return false;\n }\n\n const group = groupFor(el);\n const { controls, values } = gather(group);\n if (request.values === undefined && controls.length > 0) {\n request.values = values;\n }\n\n // The request is for the nearest `lb-query` of what it gathered, or of the\n // element itself when it gathered nothing.\n const queries = new Set(controls.map(queryOf));\n if (queries.size > 1) {\n console.error(\n `lb-hub: '${name}' gathered controls of more than one query, not sent`,\n el,\n );\n return false;\n }\n const from = controls[0] ?? el;\n const query = controls.length > 0 ? [...queries][0]! : queryOf(el);\n if (query) {\n request.query ??= query.getAttribute(ATTR_QUERY)!;\n const key = keyFrom(from, query);\n if (key !== undefined) request.key ??= key;\n }\n\n if (name === REQUEST_ROW_INSERT && group?.form) {\n insertedFrom.set(request, group.form);\n }\n\n const needs = NEEDS[name];\n if (needs) {\n const missing = needs.filter(\n (field) =>\n request[field] === undefined ||\n (field === \"values\" && Object.keys(request.values!).length === 0),\n );\n if (missing.length > 0) {\n console.error(\n `lb-hub: '${name}' from <${el.localName}> has no ` +\n `${missing.join(\", \")}, not sent`,\n el,\n );\n return false;\n }\n }\n return true;\n}\n\n/**\n * Commit: dispatch the request an element names, for the hub to complete. A\n * commit on an element whose round trip is in flight is ignored.\n */\nfunction commit(el: Element): void {\n if (el.hasAttribute(ATTR_REQUEST_PENDING)) return;\n const detail: HubRequest = { name: el.getAttribute(ATTR_REQUEST)! };\n el.dispatchEvent(new CustomEvent(LB_EVENT_NAME, { bubbles: true, detail }));\n}\n\n/** A submit button with a form owner commits with its form, never on click. */\nfunction isSubmitButton(el: Element): boolean {\n const type = (el as HTMLInputElement).type as string;\n const submits =\n (el.localName === \"button\" && type === \"submit\") ||\n (el.localName === \"input\" && (type === \"submit\" || type === \"image\"));\n return submits && formOwnerOf(el) !== null;\n}\n\n/**\n * HTML's interactive content: elements a click already means something to.\n * HTML forbids nesting them inside `<a>` or `<button>` so a click means one\n * thing, and the hub draws the same line.\n */\nconst INTERACTIVE = [\n \"a[href]\",\n \"button\",\n \"input:not([type=hidden])\",\n \"select\",\n \"textarea\",\n \"label\",\n \"details\",\n \"iframe\",\n \"embed\",\n \"audio[controls]\",\n \"video[controls]\",\n \"img[usemap]\",\n].join(\", \");\n\n/**\n * Whether a click on `target` is the click of `el`, the element carrying\n * `lb-request` above it: no interactive content lies between them. A click on\n * a control, link or button inside `el` belongs to that element.\n */\nfunction clicks(target: Element, el: Element): boolean {\n for (let node: Element | null = target; node && node !== el;) {\n if (node.matches(INTERACTIVE) || isFormAssociated(node)) return false;\n node = node.parentElement;\n }\n return true;\n}\n\n/** The page file's title, or its stub when it has none. */\nfunction titleOf(template: HTMLTemplateElement | null, page: string): string {\n return template?.getAttribute(ATTR_PAGE_TITLE) || page;\n}\n\n/**\n * The `<template>` a page ships in. The builder guarantees one per stub\n * (build/locations.ts refuses two page files sharing one), so a second match\n * here means the document was assembled by something else.\n */\nfunction pageHostFor(page: string): HTMLTemplateElement | null {\n const hosts: HTMLTemplateElement[] = [];\n for (const el of document.querySelectorAll(`template[${ATTR_PAGE}]`)) {\n if (el.getAttribute(ATTR_PAGE) === page) {\n hosts.push(el as HTMLTemplateElement);\n }\n }\n if (hosts.length > 1) {\n console.error(\n `lb-hub: ${hosts.length} pages carry ${ATTR_PAGE}=\"${page}\", ` +\n `using the first`,\n );\n }\n return hosts[0] ?? null;\n}\n\n/**\n * One round trip against the client-side deadline. Throws on a non-ok\n * response, a network failure or a timeout, so a caller can tell a failed\n * request from an empty answer.\n *\n * The stub names the path below the endpoint and the query string the\n * browser is showing rides after it verbatim, so every round trip reaches\n * the server with the query parms in hand.\n */\nasync function fetchItems(\n page: string,\n request?: HubRequest,\n): Promise<HubResponse> {\n const path = page.split(\"/\").map(encodeURIComponent).join(\"/\");\n const url = `${LB_ENDPOINT}/${path}${location.search}`;\n const controller = new AbortController();\n const timeout = setTimeout(() => controller.abort(), LB_REQUEST_TIMEOUT_MS);\n try {\n // An empty body is how the hub asks for the page's queries.\n const res = await fetch(url, {\n method: \"POST\",\n headers: { \"content-type\": \"application/json\" },\n body: JSON.stringify(request ?? {}),\n signal: controller.signal,\n });\n if (!res.ok) {\n throw new Error(`lb-hub: server responded ${res.status} for ${url}`);\n }\n return (await res.json()) as HubResponse;\n } finally {\n clearTimeout(timeout);\n }\n}\n\n/** An element's round trip is in flight, or is not. */\nfunction pending(el: Element | undefined, on: boolean): void {\n if (!el) return;\n if (on) {\n el.removeAttribute(ATTR_REQUEST_ERROR);\n el.setAttribute(ATTR_REQUEST_PENDING, \"\");\n el.setAttribute(\"aria-busy\", \"true\");\n } else {\n el.removeAttribute(ATTR_REQUEST_PENDING);\n el.removeAttribute(\"aria-busy\");\n }\n}\n\n/** A plain primary click: no other button, no modifier, not yet handled. */\nfunction isPlainClick(e: MouseEvent): boolean {\n return (\n e.button === 0 &&\n !e.defaultPrevented &&\n !e.metaKey &&\n !e.ctrlKey &&\n !e.shiftKey &&\n !e.altKey\n );\n}\n\n/** The URL a row for `lb-url` leads to, by the rule the server follows. */\nfunction nextUrl(row: Row): { url: URL; moved: boolean } {\n const url = new URL(location.href);\n const next = nextLocation(pageNameFor(url.pathname), url.searchParams, row);\n const path = row[URL_COLUMN_PATH];\n if (typeof path === \"string\") url.pathname = path;\n url.search = next.parms.toString();\n return { url, moved: next.moved };\n}\n\n/**\n * The hub is a singleton outside <main>. It survives every page change,\n * so it needs no id to disambiguate it.\n */\nclass LbHub extends HTMLElement {\n private main!: HTMLElement;\n\n /**\n * The stub of the page in <main>. A page declares its own requests, so a\n * request says which page it came from, on the path below the endpoint.\n */\n private page = \"\";\n\n connectedCallback() {\n this.main = this.querySelector(\"main\")!;\n\n // Completed in the capture phase, on the way down, so every ancestor\n // that sees the request on its way back up sees it whole. A request that\n // cannot be issued is stopped here, before anything sees it at all.\n this.addEventListener(\n LB_EVENT_NAME,\n (e: Event) => {\n const origin = e.target as Element;\n const request = (e as CustomEvent<HubRequest>).detail;\n if (!complete(request, origin)) e.stopPropagation();\n },\n { capture: true },\n );\n\n this.addEventListener(LB_EVENT_NAME, (e: Event) => {\n const request = (e as CustomEvent<HubRequest>).detail;\n // The element that issued the request, not e.currentTarget (the hub\n // itself, since the event bubbles).\n const origin = (e.target as Element | null) ?? undefined;\n if (request.query?.startsWith(LB_RESERVED_PREFIX)) {\n this.answer(request, origin);\n return;\n }\n void this.send(request, origin);\n });\n\n // A form commits on submit. The submitter's own lb-request replaces the\n // form's, the way `formaction` replaces `action`.\n this.addEventListener(\"submit\", (e: SubmitEvent) => {\n const form = e.target as Element | null;\n if (!form) return;\n const submitter = e.submitter;\n const el = submitter?.hasAttribute(ATTR_REQUEST)\n ? submitter\n : form.hasAttribute(ATTR_REQUEST)\n ? form\n : null;\n if (!el) return;\n e.preventDefault();\n commit(el);\n });\n\n // A reset returns a form's controls to their defaults, so none of them\n // shows what landed any longer. The browser resets the controls; the\n // hub drops its own stamp from the same controls a submit gathers.\n this.addEventListener(\"reset\", (e: Event) => {\n if (e.defaultPrevented) return;\n for (const el of controlsOf(e.target as HTMLFormElement)) {\n el.removeAttribute(ATTR_COLUMN_VALUE);\n }\n });\n\n // A control commits on change.\n this.addEventListener(\"change\", (e: Event) => {\n const el = e.target as Element | null;\n if (!el || !el.hasAttribute(ATTR_REQUEST) || !isControl(el)) return;\n commit(el);\n });\n\n // Anything else commits on click. A form commits on submit, a control on\n // change, and a submit button with its form. A click on interactive\n // content inside the element is that content's own.\n this.addEventListener(\"click\", (e: MouseEvent) => {\n const target = e.target as Element | null;\n const el = target?.closest(`[${ATTR_REQUEST}]`);\n if (!target || !el || !this.contains(el)) return;\n if (el.localName === \"form\" || isControl(el) || isSubmitButton(el)) {\n return;\n }\n if (!clicks(target, el)) return;\n e.preventDefault();\n commit(el);\n });\n\n // A link that opted in. Everything else is a real link, and so is a\n // click that opens a new tab or window. The link's URL is a row for\n // lb-url: its path, its query parms, and every other parm emptied. A\n // link pushes a history entry, as a link does.\n this.addEventListener(\"click\", (e: MouseEvent) => {\n const link = (e.target as Element | null)?.closest(`a[${ATTR_URL_LINK}]`);\n if (!link || !isPlainClick(e)) return;\n e.preventDefault();\n const href = new URL((link as HTMLAnchorElement).href);\n const row: Row = {};\n for (const name of new URLSearchParams(location.search).keys()) {\n row[name] = \"\";\n }\n for (const [name, value] of href.searchParams) row[name] = value;\n row[URL_COLUMN_PATH] = href.pathname;\n this.moveTo(row, true);\n void this.navigate();\n });\n\n addEventListener(\"popstate\", () => void this.navigate());\n\n void this.navigate();\n }\n\n /**\n * Send a request to the server and land its answer. An answer naming\n * `lb-url` moves the URL first; the server has already loaded the page\n * there, in the same round trip.\n */\n private async send(request: HubRequest, origin?: Element): Promise<void> {\n const page = this.page;\n const items = await this.roundTrip(page, request, origin);\n if (items === null) return;\n const url = items.find((item) => item.query === URL_QUERY);\n const load = items.filter((item) => item !== url);\n if (url === undefined) applyResponse(this, load);\n else await this.follow(page, url, load, origin);\n insertedFrom.get(request)?.reset();\n }\n\n /**\n * One round trip for a page: a request, or with none a page load. The\n * element that issued it carries `lb-request-pending` while it is in\n * flight, and `lb-request-error` when it fails. Null on failure.\n */\n private async roundTrip(\n page: string,\n request: HubRequest | undefined,\n origin: Element | undefined,\n ): Promise<HubResponse | null> {\n pending(origin, true);\n try {\n return await fetchItems(page, request);\n } catch (err) {\n console.error(`lb-hub: request failed for '${page}'`, err);\n origin?.setAttribute(ATTR_REQUEST_ERROR, \"\");\n return null;\n } finally {\n pending(origin, false);\n }\n }\n\n /**\n * Answer a request for a query the hub serves, with no round trip. The\n * hub serves `lb-url`, and updates it.\n */\n private answer(request: HubRequest, origin?: Element): void {\n if (request.query !== URL_QUERY || request.name !== REQUEST_ROW_UPDATE) {\n console.error(\n `lb-hub: '${request.name}' for '${request.query}' is not a request ` +\n `the hub answers, ignoring`,\n );\n return;\n }\n const pushed = origin?.hasAttribute(ATTR_URL_PUSH) ?? false;\n if (this.moveTo(request.values ?? {}, pushed)) void this.navigate(origin);\n }\n\n /**\n * Write a row for `lb-url` into the URL. A new page pushes a history\n * entry, and so does `push`; a change of query parms replaces the entry.\n * False when the URL is already the row's.\n */\n private moveTo(row: Row, push: boolean): boolean {\n const { url, moved } = nextUrl(row);\n if (url.href === location.href) return false;\n if (moved || push) history.pushState(null, \"\", url);\n else history.replaceState(null, \"\", url);\n return true;\n }\n\n /**\n * A server answer named `lb-url`: write the URL, then land the page the\n * server loaded there. A load that did not come back is asked for again,\n * without marking the element that issued the request: its write\n * succeeded, and an error would invite sending it twice.\n *\n * `page` is where the request was sent from. A user who left it while the\n * request was in flight is on a URL that is not the server's to change.\n */\n private async follow(\n page: string,\n item: ResponseItem,\n load: ResponseItem[],\n origin?: Element,\n ): Promise<void> {\n if (pageNameFor(location.pathname) !== page) return;\n this.moveTo(item.row ?? {}, origin?.hasAttribute(ATTR_URL_PUSH) ?? false);\n if (load.length === 0) return this.navigate();\n const template = this.arrive();\n if (template) applyResponse(this, load);\n }\n\n /**\n * Load the page at the URL the browser is showing. Every way of arriving\n * comes through here — a cold load, a link, Back, a new query parm — so\n * each is the same page load and a URL always shows the same thing.\n *\n * Entering a page is the one operation that replaces what <main> holds.\n * Staying on it, with only the query parms changed, keeps what it has: the\n * queries re-run and land by key, so rows that come back keep their place.\n *\n * `origin` is the element whose request changed the URL, if one did, and\n * carries the round trip's pending and error state.\n */\n private async navigate(origin?: Element): Promise<void> {\n const template = this.arrive();\n if (!template) return;\n const items = await this.roundTrip(this.page, undefined, origin);\n applyResponse(this, items ?? []);\n }\n\n /**\n * Show the page the path names, and land `lb-url`. Null when no page's\n * stub matches the path.\n */\n private arrive(): HTMLTemplateElement | null {\n const page = pageNameFor(location.pathname);\n const template = pageHostFor(page);\n if (template && page !== this.page) {\n this.page = page;\n // The template is already in the document, so the page's markup goes\n // in before its data arrives rather than leaving <main> empty.\n this.main.replaceChildren(template.content.cloneNode(true));\n }\n this.landUrl(template ? titleOf(template, page) : null);\n // An app that ships `<body hidden>` (docs/reference/chrome.md) stays\n // invisible until there is something coherent to show.\n document.body.hidden = false;\n if (!template) {\n console.error(`lb-hub: no page for '${page}'`);\n const dialog = this.querySelector(`dialog[${ATTR_URL_UNKNOWN}]`);\n if (dialog && !(dialog as HTMLDialogElement).open) {\n (dialog as HTMLDialogElement).showModal();\n }\n }\n return template;\n }\n\n /**\n * The hub's own query: one row, keyed by the path, whose other columns are\n * the query parms.\n *\n * The one exception to landing. A row sets the columns it names and\n * leaves the rest as they were, and a URL names only the parms it carries.\n * So the row also names, as empty, every column an element under\n * `lb-query=\"lb-url\"` shows: a control then shows what the address bar\n * says after Back as well as after a reload, and never a parm the URL has\n * dropped.\n */\n private landUrl(label: string | null): void {\n if (label !== null) document.title = label;\n const scopes = this.querySelectorAll(`[${ATTR_QUERY}=\"${URL_QUERY}\"]`);\n if (scopes.length === 0) return;\n const row: Row = {};\n for (const scope of scopes) {\n for (const el of within(scope, `[${ATTR_COLUMN}]`)) {\n if (el === scope) continue;\n row[el.getAttribute(ATTR_COLUMN)!] = \"\";\n }\n }\n for (const [name, value] of new URLSearchParams(location.search)) {\n row[name] = value;\n }\n row[URL_COLUMN_PATH] = location.pathname;\n row[URL_COLUMN_PAGE_LABEL] = label;\n row[URL_COLUMN_PAGE_UNKNOWN] = label === null;\n applyResponse(this, [\n { query: URL_QUERY, kind: KIND_ROW, key: URL_COLUMN_PATH, row },\n ]);\n }\n}\n\ncustomElements.define(HUB_TAG_NAME, LbHub);\n"]}
|
|
1
|
+
{"version":3,"file":"lb-hub.browser.js","sourceRoot":"","sources":["../../hub/lb-hub.browser.ts"],"names":[],"mappings":"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","sourcesContent":["/// <reference lib=\"dom\" />\n\nimport {\n ATTR_COLUMN,\n ATTR_COLUMN_VALUE,\n ATTR_KEY_VALUE,\n ATTR_PAGE,\n ATTR_PAGE_TITLE,\n ATTR_QUERY,\n ATTR_REQUEST,\n ATTR_REQUEST_ERROR,\n ATTR_REQUEST_PENDING,\n ATTR_URL_LINK,\n ATTR_URL_PUSH,\n ATTR_URL_UNKNOWN,\n HUB_TAG_NAME,\n KIND_ROW,\n LB_DONE_EVENT_NAME,\n LB_ENDPOINT,\n LB_EVENT_NAME,\n LB_REQUEST_TIMEOUT_MS,\n LB_RESERVED_PREFIX,\n LIVE_ROW,\n REQUEST_ROW_DELETE,\n REQUEST_ROW_INSERT,\n REQUEST_ROW_UPDATE,\n URL_COLUMN_PAGE_LABEL,\n URL_COLUMN_PAGE_UNKNOWN,\n URL_COLUMN_PATH,\n URL_QUERY,\n} from \"../core/lb-constants.js\";\nimport {\n isRowRequest,\n nextLocation,\n pageNameFor,\n type HubRequest,\n type HubRequestDone,\n type HubResponse,\n type ResponseItem,\n type Row,\n} from \"../core/lb-types.js\";\nimport {\n applyResponse,\n forget,\n isControl,\n isFormAssociated,\n within,\n type Control,\n} from \"./lb-apply.js\";\n\nexport { applyResponse, applyRow } from \"./lb-apply.js\";\n\n/** What each request Loadbare provides cannot be issued without. */\nconst NEEDS: Record<string, readonly (keyof HubRequest)[]> = {\n [REQUEST_ROW_INSERT]: [\"query\", \"values\"],\n [REQUEST_ROW_UPDATE]: [\"query\", \"key\", \"values\"],\n [REQUEST_ROW_DELETE]: [\"query\", \"key\"],\n};\n\n/** The nearest ancestor carrying `lb-query`. An element is not its own. */\nfunction queryOf(el: Element): Element | null {\n return el.parentElement?.closest(`[${ATTR_QUERY}]`) ?? null;\n}\n\n/** The live row an element is, or is in. */\nfunction liveRowOf(el: Element): Element | null {\n return el.closest(LIVE_ROW);\n}\n\n/**\n * The key of the nearest ancestor row, when that row is of `query`: a live\n * row whose query it is, or the element a `row` of it landed on.\n */\nfunction keyFrom(el: Element, query: Element): string | undefined {\n // A live row is its own row; any other element's row is an ancestor.\n const row = el.matches(LIVE_ROW)\n ? el\n : el.parentElement?.closest(`[${ATTR_KEY_VALUE}]`);\n if (!row) return undefined;\n // A live row's key is its outer query's, even when the row names a query\n // of its own. Any other element's key is its own query's.\n const ofQuery = row.matches(LIVE_ROW)\n ? queryOf(row) === query\n : row === query;\n return ofQuery ? (row.getAttribute(ATTR_KEY_VALUE) ?? undefined) : undefined;\n}\n\n/**\n * Every control whose form owner is `form`: HTML's own list, which holds a\n * control nested in the form or joined to it by the `form` attribute, and a\n * form-associated custom element as well as a native control.\n */\nfunction controlsOf(form: HTMLFormElement): Element[] {\n return [...(form.elements as unknown as Iterable<Element>)];\n}\n\n/**\n * The form owner of an element that has one, as HTML reports it on the\n * element's `form` property.\n */\nfunction formOwnerOf(el: Element): HTMLFormElement | null {\n const owner = (el as { form?: unknown }).form;\n return owner && (owner as Element).localName === \"form\"\n ? (owner as HTMLFormElement)\n : null;\n}\n\n/** The group a request gathers from. */\ninterface Group {\n controls: Element[];\n /** Set when the group is a form, so a successful insert resets it. */\n form?: HTMLFormElement;\n /** What the group is: the form or the live row. */\n root: Element;\n}\n\n/**\n * The controls a request gathers — see docs/reference/data-binding.md,\n * \"Gathering\":\n *\n * 1. the element carrying `lb-request` has `lb-column`: it alone;\n * 2. the element is a `<form>`: the controls whose form owner it is;\n * 3. the element is in a live row: the controls in that live row;\n * 4. otherwise: the controls whose form owner is the element's.\n *\n * A control whose nearest `lb-query` is inside the group belongs to a query\n * nested in it, and is skipped.\n */\nfunction groupFor(el: Element): Group | null {\n if (el.hasAttribute(ATTR_COLUMN)) return { controls: [el], root: el };\n if (el.localName === \"form\") {\n const form = el as HTMLFormElement;\n return { controls: controlsOf(form), form, root: form };\n }\n const live = liveRowOf(el);\n if (live) return { controls: within(live, `[${ATTR_COLUMN}]`), root: live };\n const form = formOwnerOf(el);\n if (form) return { controls: controlsOf(form), form, root: form };\n return null;\n}\n\n/** The gathered controls, with their values under their columns. */\nfunction gather(group: Group | null): {\n controls: Control[];\n values: Record<string, string>;\n} {\n const controls: Control[] = [];\n const values: Record<string, string> = {};\n for (const el of group?.controls ?? []) {\n const column = el.getAttribute(ATTR_COLUMN);\n if (column === null || !isControl(el)) continue;\n const nested = queryOf(el);\n if (nested && nested !== group!.root && group!.root.contains(nested)) {\n continue;\n }\n controls.push(el);\n values[column] = el.value;\n }\n return { controls, values };\n}\n\n/** The form each insert gathered from, until its round trip succeeds. */\nconst insertedFrom = new WeakMap<HubRequest, HTMLFormElement>();\n\n/**\n * Complete a request from where its element sits. Every request passes\n * through here, whoever issued it; a field it already carries is its\n * issuer's to decide and is left as it is.\n *\n * False when the request cannot be issued, having said why.\n */\nfunction complete(request: HubRequest | undefined, el: Element): boolean {\n if (!request?.name) {\n console.warn(`lb-hub: a request without a name, ignoring`, request);\n return false;\n }\n const { name } = request;\n if (name.startsWith(LB_RESERVED_PREFIX) && !isRowRequest(name)) {\n console.error(\n `lb-hub: '${name}' begins with '${LB_RESERVED_PREFIX}' but names no ` +\n `request Loadbare provides, ignoring`,\n );\n return false;\n }\n\n const group = groupFor(el);\n const { controls, values } = gather(group);\n if (request.values === undefined && controls.length > 0) {\n request.values = values;\n }\n\n // The request is for the nearest `lb-query` of what it gathered, or of the\n // element itself when it gathered nothing.\n const queries = new Set(controls.map(queryOf));\n if (queries.size > 1) {\n console.error(\n `lb-hub: '${name}' gathered controls of more than one query, not sent`,\n el,\n );\n return false;\n }\n const from = controls[0] ?? el;\n const query = controls.length > 0 ? [...queries][0]! : queryOf(el);\n if (query) {\n request.query ??= query.getAttribute(ATTR_QUERY)!;\n const key = keyFrom(from, query);\n if (key !== undefined) request.key ??= key;\n }\n\n if (name === REQUEST_ROW_INSERT && group?.form) {\n insertedFrom.set(request, group.form);\n }\n\n const needs = NEEDS[name];\n if (needs) {\n const missing = needs.filter(\n (field) =>\n request[field] === undefined ||\n (field === \"values\" && Object.keys(request.values!).length === 0),\n );\n if (missing.length > 0) {\n console.error(\n `lb-hub: '${name}' from <${el.localName}> has no ` +\n `${missing.join(\", \")}, not sent`,\n el,\n );\n return false;\n }\n }\n return true;\n}\n\n/**\n * Commit: dispatch the request an element names, for the hub to complete. A\n * commit on an element whose round trip is in flight is ignored.\n */\nfunction commit(el: Element): void {\n if (el.hasAttribute(ATTR_REQUEST_PENDING)) return;\n const detail: HubRequest = { name: el.getAttribute(ATTR_REQUEST)! };\n el.dispatchEvent(new CustomEvent(LB_EVENT_NAME, { bubbles: true, detail }));\n}\n\n/** A submit button with a form owner commits with its form, never on click. */\nfunction isSubmitButton(el: Element): boolean {\n const type = (el as HTMLInputElement).type as string;\n const submits =\n (el.localName === \"button\" && type === \"submit\") ||\n (el.localName === \"input\" && (type === \"submit\" || type === \"image\"));\n return submits && formOwnerOf(el) !== null;\n}\n\n/**\n * HTML's interactive content: elements a click already means something to.\n * HTML forbids nesting them inside `<a>` or `<button>` so a click means one\n * thing, and the hub draws the same line.\n */\nconst INTERACTIVE = [\n \"a[href]\",\n \"button\",\n \"input:not([type=hidden])\",\n \"select\",\n \"textarea\",\n \"label\",\n \"details\",\n \"iframe\",\n \"embed\",\n \"audio[controls]\",\n \"video[controls]\",\n \"img[usemap]\",\n].join(\", \");\n\n/**\n * Whether a click on `target` is the click of `el`, the element carrying\n * `lb-request` above it: no interactive content lies between them. A click on\n * a control, link or button inside `el` belongs to that element.\n */\nfunction clicks(target: Element, el: Element): boolean {\n for (let node: Element | null = target; node && node !== el;) {\n if (node.matches(INTERACTIVE) || isFormAssociated(node)) return false;\n node = node.parentElement;\n }\n return true;\n}\n\n/** The page file's title, or its stub when it has none. */\nfunction titleOf(template: HTMLTemplateElement | null, page: string): string {\n return template?.getAttribute(ATTR_PAGE_TITLE) || page;\n}\n\n/**\n * The `<template>` a page ships in. The builder guarantees one per stub\n * (build/locations.ts refuses two page files sharing one), so a second match\n * here means the document was assembled by something else.\n */\nfunction pageHostFor(page: string): HTMLTemplateElement | null {\n const hosts: HTMLTemplateElement[] = [];\n for (const el of document.querySelectorAll(`template[${ATTR_PAGE}]`)) {\n if (el.getAttribute(ATTR_PAGE) === page) {\n hosts.push(el as HTMLTemplateElement);\n }\n }\n if (hosts.length > 1) {\n console.error(\n `lb-hub: ${hosts.length} pages carry ${ATTR_PAGE}=\"${page}\", ` +\n `using the first`,\n );\n }\n return hosts[0] ?? null;\n}\n\n/**\n * One round trip against the client-side deadline. Throws on a non-ok\n * response, a network failure or a timeout, so a caller can tell a failed\n * request from an empty answer.\n *\n * The stub names the path below the endpoint and the query string the\n * browser is showing rides after it verbatim, so every round trip reaches\n * the server with the query parms in hand.\n */\nasync function fetchItems(\n page: string,\n request?: HubRequest,\n): Promise<HubResponse> {\n const path = page.split(\"/\").map(encodeURIComponent).join(\"/\");\n const url = `${LB_ENDPOINT}/${path}${location.search}`;\n const controller = new AbortController();\n const timeout = setTimeout(() => controller.abort(), LB_REQUEST_TIMEOUT_MS);\n try {\n // An empty body is how the hub asks for the page's queries.\n const res = await fetch(url, {\n method: \"POST\",\n headers: { \"content-type\": \"application/json\" },\n body: JSON.stringify(request ?? {}),\n signal: controller.signal,\n });\n if (!res.ok) {\n throw new Error(`lb-hub: server responded ${res.status} for ${url}`);\n }\n return (await res.json()) as HubResponse;\n } finally {\n clearTimeout(timeout);\n }\n}\n\n/** An element's round trip is in flight, or is not. */\nfunction pending(el: Element | undefined, on: boolean): void {\n if (!el) return;\n if (on) {\n el.removeAttribute(ATTR_REQUEST_ERROR);\n el.setAttribute(ATTR_REQUEST_PENDING, \"\");\n el.setAttribute(\"aria-busy\", \"true\");\n } else {\n el.removeAttribute(ATTR_REQUEST_PENDING);\n el.removeAttribute(\"aria-busy\");\n }\n}\n\n/**\n * Tell the element that committed how its request turned out. Raised after\n * everything the request brought back has landed, so a listener sees the\n * page as the answer left it, and `lb-request-pending` is already gone.\n */\nfunction done(\n origin: Element | undefined,\n request: HubRequest,\n landed: ResponseItem[] | Error,\n): void {\n const detail: HubRequestDone =\n landed instanceof Error\n ? { request, items: [], error: landed }\n : { request, items: landed };\n origin?.dispatchEvent(\n new CustomEvent(LB_DONE_EVENT_NAME, { bubbles: true, detail }),\n );\n}\n\n/** What can take focus, before asking whether it can be operated. */\nconst FOCUSABLE =\n `a[href], button, input:not([type=\"hidden\"]), select, textarea, ` +\n `summary, [tabindex]:not([tabindex=\"-1\"]), ` +\n `[contenteditable]:not([contenteditable=\"false\"])`;\n\n/**\n * Focus the first element in `main` the user can operate: not disabled, not\n * in a closed dialog, not inert, not hidden, and one that took the focus\n * when asked. Nothing in a `<template>` is a candidate, so an absent\n * `lb-show` branch is passed over. Focus already in `main` is the user's,\n * and is left where it is.\n */\nfunction focusFirst(main: HTMLElement): void {\n if (main.contains(document.activeElement)) return;\n for (const el of main.querySelectorAll<HTMLElement>(FOCUSABLE)) {\n if (el.matches(\":disabled\")) continue;\n if (el.closest(`dialog:not([open]), [inert], [hidden]`)) continue;\n if (el.checkVisibility?.() === false) continue;\n el.focus();\n if (document.activeElement === el) return;\n }\n}\n\n/**\n * The URL a round trip answers for: its path and its query string. An answer\n * that returns to another is not landed.\n */\nfunction here(): string {\n return location.pathname + location.search;\n}\n\n/** A plain primary click: no other button, no modifier, not yet handled. */\nfunction isPlainClick(e: MouseEvent): boolean {\n return (\n e.button === 0 &&\n !e.defaultPrevented &&\n !e.metaKey &&\n !e.ctrlKey &&\n !e.shiftKey &&\n !e.altKey\n );\n}\n\n/** The URL a row for `lb-url` leads to, by the rule the server follows. */\nfunction nextUrl(row: Row): { url: URL; moved: boolean } {\n const url = new URL(location.href);\n const next = nextLocation(pageNameFor(url.pathname), url.searchParams, row);\n const path = row[URL_COLUMN_PATH];\n if (typeof path === \"string\") url.pathname = path;\n url.search = next.parms.toString();\n return { url, moved: next.moved };\n}\n\n/**\n * The hub is a singleton outside <main>. It survives every page change,\n * so it needs no id to disambiguate it.\n */\nclass LbHub extends HTMLElement {\n private main!: HTMLElement;\n\n /**\n * The stub of the page in <main>. A page declares its own requests, so a\n * request says which page it came from, on the path below the endpoint.\n */\n private page = \"\";\n\n /**\n * Set when a page is entered, and cleared once its queries have landed\n * and focus has gone to its first control. A change of query parm on the\n * same page does not set it: the user is where they chose to be.\n */\n private entering = false;\n\n connectedCallback() {\n this.main = this.querySelector(\"main\")!;\n\n // Completed in the capture phase, on the way down, so every ancestor\n // that sees the request on its way back up sees it whole. A request that\n // cannot be issued is stopped here, before anything sees it at all.\n this.addEventListener(\n LB_EVENT_NAME,\n (e: Event) => {\n const origin = e.target as Element;\n const request = (e as CustomEvent<HubRequest>).detail;\n if (!complete(request, origin)) e.stopPropagation();\n },\n { capture: true },\n );\n\n this.addEventListener(LB_EVENT_NAME, (e: Event) => {\n const request = (e as CustomEvent<HubRequest>).detail;\n // The element that issued the request, not e.currentTarget (the hub\n // itself, since the event bubbles).\n const origin = (e.target as Element | null) ?? undefined;\n if (request.query?.startsWith(LB_RESERVED_PREFIX)) {\n void this.answer(request, origin);\n return;\n }\n void this.send(request, origin);\n });\n\n // A form commits on submit. The submitter's own lb-request replaces the\n // form's, the way `formaction` replaces `action`.\n this.addEventListener(\"submit\", (e: SubmitEvent) => {\n const form = e.target as Element | null;\n if (!form) return;\n const submitter = e.submitter;\n const el = submitter?.hasAttribute(ATTR_REQUEST)\n ? submitter\n : form.hasAttribute(ATTR_REQUEST)\n ? form\n : null;\n if (!el) return;\n e.preventDefault();\n commit(el);\n });\n\n // A reset returns a form's controls to their defaults, so none of them\n // shows what landed any longer. The browser resets the controls; the\n // hub drops its own stamp from the same controls a submit gathers.\n this.addEventListener(\"reset\", (e: Event) => {\n if (e.defaultPrevented) return;\n for (const el of controlsOf(e.target as HTMLFormElement)) {\n el.removeAttribute(ATTR_COLUMN_VALUE);\n }\n });\n\n // A control commits on change.\n this.addEventListener(\"change\", (e: Event) => {\n const el = e.target as Element | null;\n if (!el || !el.hasAttribute(ATTR_REQUEST) || !isControl(el)) return;\n commit(el);\n });\n\n // Anything else commits on click. A form commits on submit, a control on\n // change, and a submit button with its form. A click on interactive\n // content inside the element is that content's own.\n this.addEventListener(\"click\", (e: MouseEvent) => {\n const target = e.target as Element | null;\n const el = target?.closest(`[${ATTR_REQUEST}]`);\n if (!target || !el || !this.contains(el)) return;\n if (el.localName === \"form\" || isControl(el) || isSubmitButton(el)) {\n return;\n }\n if (!clicks(target, el)) return;\n e.preventDefault();\n commit(el);\n });\n\n // A link that opted in. Everything else is a real link, and so is a\n // click that opens a new tab or window. The link's URL is a row for\n // lb-url: its path, its query parms, and every other parm emptied. A\n // link pushes a history entry, as a link does.\n this.addEventListener(\"click\", (e: MouseEvent) => {\n const link = (e.target as Element | null)?.closest(`a[${ATTR_URL_LINK}]`);\n if (!link || !isPlainClick(e)) return;\n e.preventDefault();\n const href = new URL((link as HTMLAnchorElement).href);\n const row: Row = {};\n for (const name of new URLSearchParams(location.search).keys()) {\n row[name] = \"\";\n }\n for (const [name, value] of href.searchParams) row[name] = value;\n row[URL_COLUMN_PATH] = href.pathname;\n this.moveTo(row, true);\n void this.navigate();\n });\n\n addEventListener(\"popstate\", () => void this.navigate());\n\n void this.navigate();\n }\n\n /**\n * Send a request to the server and land its answer. An answer naming\n * `lb-url` moves the URL first; the server has already loaded the page\n * there, in the same round trip.\n */\n private async send(request: HubRequest, origin?: Element): Promise<void> {\n const at = here();\n const items = await this.roundTrip(this.page, request, origin);\n if (items instanceof Error) return done(origin, request, items);\n let landed: ResponseItem[] = [];\n // The server answered for the URL the request was sent from. A user who\n // moved while it was in flight, to another page or to other parms, is\n // looking at something it says nothing about, and on a URL that is not\n // the server's to change. The write still happened.\n if (here() === at) {\n const url = items.find((item) => item.query === URL_QUERY);\n const load = items.filter((item) => item !== url);\n landed = load;\n if (url === undefined) applyResponse(this, load);\n else landed = await this.follow(url, load, origin);\n }\n insertedFrom.get(request)?.reset();\n done(origin, request, landed);\n }\n\n /**\n * One round trip for a page: a request, or with none a page load. The\n * element that issued it carries `lb-request-pending` while it is in\n * flight, and `lb-request-error` when it fails. The error on failure.\n */\n private async roundTrip(\n page: string,\n request: HubRequest | undefined,\n origin: Element | undefined,\n ): Promise<HubResponse | Error> {\n pending(origin, true);\n try {\n return await fetchItems(page, request);\n } catch (err) {\n console.error(`lb-hub: request failed for '${page}'`, err);\n origin?.setAttribute(ATTR_REQUEST_ERROR, \"\");\n return err instanceof Error ? err : new Error(String(err));\n } finally {\n pending(origin, false);\n }\n }\n\n /**\n * Answer a request for a query the hub serves, with no round trip. The\n * hub serves `lb-url`, and updates it.\n */\n private async answer(request: HubRequest, origin?: Element): Promise<void> {\n if (request.query !== URL_QUERY || request.name !== REQUEST_ROW_UPDATE) {\n const message =\n `lb-hub: '${request.name}' for '${request.query}' is not a request ` +\n `the hub answers, ignoring`;\n console.error(message);\n return done(origin, request, new Error(message));\n }\n const pushed = origin?.hasAttribute(ATTR_URL_PUSH) ?? false;\n const moved = this.moveTo(request.values ?? {}, pushed);\n done(origin, request, moved ? await this.navigate(origin) : []);\n }\n\n /**\n * Write a row for `lb-url` into the URL. A new page pushes a history\n * entry, and so does `push`; a change of query parms replaces the entry.\n * False when the URL is already the row's.\n */\n private moveTo(row: Row, push: boolean): boolean {\n const { url, moved } = nextUrl(row);\n if (url.href === location.href) return false;\n if (moved || push) history.pushState(null, \"\", url);\n else history.replaceState(null, \"\", url);\n return true;\n }\n\n /**\n * A server answer named `lb-url`: write the URL, then land the page the\n * server loaded there. A load that did not come back is asked for again,\n * without marking the element that issued the request: its write\n * succeeded, and an error would invite sending it twice.\n *\n * What landed: the `lb-url` item and the load, however it arrived. A load\n * asked for again that fails is not the request's failure.\n */\n private async follow(\n item: ResponseItem,\n load: ResponseItem[],\n origin?: Element,\n ): Promise<ResponseItem[]> {\n this.moveTo(item.row ?? {}, origin?.hasAttribute(ATTR_URL_PUSH) ?? false);\n if (load.length === 0) {\n const again = await this.navigate();\n return again instanceof Error ? [item] : [item, ...again];\n }\n const template = this.arrive();\n if (template) applyResponse(this, load);\n this.entered();\n return template ? [item, ...load] : [item];\n }\n\n /**\n * Load the page at the URL the browser is showing. Every way of arriving\n * comes through here — a cold load, a link, Back, a new query parm — so\n * each is the same page load and a URL always shows the same thing.\n *\n * Entering a page is the one operation that replaces what <main> holds.\n * Staying on it, with only the query parms changed, keeps what it has: the\n * queries re-run and land by key, so rows that come back keep their place.\n *\n * `origin` is the element whose request changed the URL, if one did, and\n * carries the round trip's pending and error state.\n *\n * What landed, or the error when the round trip failed. A load that\n * returns after the URL has moved again lands nothing: the load for where\n * the browser is now is already on its way, and may be here.\n */\n private async navigate(origin?: Element): Promise<ResponseItem[] | Error> {\n const template = this.arrive();\n if (!template) return [];\n const at = here();\n const items = await this.roundTrip(this.page, undefined, origin);\n if (here() !== at) return items instanceof Error ? items : [];\n const landed = items instanceof Error ? [] : items;\n applyResponse(this, landed);\n this.entered();\n return items instanceof Error ? items : landed;\n }\n\n /**\n * A page that was entered has landed its queries, so its first control\n * exists: a row cloned, a branch shown, a picker's options in place.\n */\n private entered(): void {\n if (!this.entering) return;\n this.entering = false;\n focusFirst(this.main);\n }\n\n /**\n * Show the page the path names, and land `lb-url`. Null when no page's\n * stub matches the path.\n */\n private arrive(): HTMLTemplateElement | null {\n const page = pageNameFor(location.pathname);\n const template = pageHostFor(page);\n if (template && page !== this.page) {\n this.page = page;\n // The template is already in the document, so the page's markup goes\n // in before its data arrives rather than leaving <main> empty. What\n // the last page's queries answered goes with it.\n this.main.replaceChildren(template.content.cloneNode(true));\n forget(this);\n this.entering = true;\n }\n this.landUrl(template ? titleOf(template, page) : null);\n // An app that ships `<body hidden>` (docs/reference/chrome.md) stays\n // invisible until there is something coherent to show.\n document.body.hidden = false;\n if (!template) {\n console.error(`lb-hub: no page for '${page}'`);\n const dialog = this.querySelector(`dialog[${ATTR_URL_UNKNOWN}]`);\n if (dialog && !(dialog as HTMLDialogElement).open) {\n (dialog as HTMLDialogElement).showModal();\n }\n }\n return template;\n }\n\n /**\n * The hub's own query: one row, keyed by the path, whose other columns are\n * the query parms.\n *\n * The one exception to landing. A row sets the columns it names and\n * leaves the rest as they were, and a URL names only the parms it carries.\n * So the row also names, as empty, every column an element under\n * `lb-query=\"lb-url\"` shows: a control then shows what the address bar\n * says after Back as well as after a reload, and never a parm the URL has\n * dropped.\n */\n private landUrl(label: string | null): void {\n if (label !== null) document.title = label;\n const scopes = this.querySelectorAll(`[${ATTR_QUERY}=\"${URL_QUERY}\"]`);\n if (scopes.length === 0) return;\n const row: Row = {};\n for (const scope of scopes) {\n for (const el of within(scope, `[${ATTR_COLUMN}]`)) {\n if (el === scope) continue;\n row[el.getAttribute(ATTR_COLUMN)!] = \"\";\n }\n }\n for (const [name, value] of new URLSearchParams(location.search)) {\n row[name] = value;\n }\n row[URL_COLUMN_PATH] = location.pathname;\n row[URL_COLUMN_PAGE_LABEL] = label;\n row[URL_COLUMN_PAGE_UNKNOWN] = label === null;\n applyResponse(this, [\n { query: URL_QUERY, kind: KIND_ROW, key: URL_COLUMN_PATH, row },\n ]);\n }\n}\n\ncustomElements.define(HUB_TAG_NAME, LbHub);\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"lb-server.d.ts","sourceRoot":"","sources":["../../server/lb-server.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"lb-server.d.ts","sourceRoot":"","sources":["../../server/lb-server.ts"],"names":[],"mappings":"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"}
|