@loadbare/app 0.11.0 → 0.13.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 +61 -1
- package/dist/build/assemble.js.map +1 -1
- package/dist/build/cli.js +2 -1
- package/dist/build/cli.js.map +1 -1
- package/dist/build/elements.d.ts +9 -1
- package/dist/build/elements.d.ts.map +1 -1
- package/dist/build/elements.js +50 -0
- package/dist/build/elements.js.map +1 -1
- package/dist/build/origins.d.ts +2 -0
- package/dist/build/origins.d.ts.map +1 -1
- package/dist/build/origins.js +1 -1
- package/dist/build/origins.js.map +1 -1
- package/dist/core/lb-constants.d.ts +26 -1
- package/dist/core/lb-constants.d.ts.map +1 -1
- package/dist/core/lb-constants.js +79 -0
- package/dist/core/lb-constants.js.map +1 -1
- package/dist/core/lb-types.d.ts +58 -18
- package/dist/core/lb-types.d.ts.map +1 -1
- package/dist/core/lb-types.js +74 -11
- package/dist/core/lb-types.js.map +1 -1
- package/dist/hub/lb-apply.d.ts +44 -16
- package/dist/hub/lb-apply.d.ts.map +1 -1
- package/dist/hub/lb-apply.js +694 -49
- 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 +168 -36
- package/dist/hub/lb-hub.browser.js.map +1 -1
- package/dist/server/lb-express.d.ts +6 -4
- package/dist/server/lb-express.d.ts.map +1 -1
- package/dist/server/lb-express.js +32 -14
- package/dist/server/lb-express.js.map +1 -1
- package/dist/server/lb-server.d.ts +49 -10
- package/dist/server/lb-server.d.ts.map +1 -1
- package/dist/server/lb-server.js +87 -28
- package/dist/server/lb-server.js.map +1 -1
- package/docs/TECHREF-1.0.md +364 -72
- package/docs/comparison.md +16 -10
- package/docs/possible-ideas.md +188 -0
- package/docs/reference/chrome.md +22 -1
- package/docs/reference/custom-elements.md +90 -29
- package/docs/reference/data-binding.md +132 -7
- package/docs/reference/page-files.md +48 -11
- package/docs/reference/server.md +4 -0
- package/docs/reference/widgets.md +94 -24
- package/docs/roadmap.md +10 -6
- package/docs/testing.md +21 -10
- package/package.json +2 -3
- package/skills/loadbare-app/SKILL.md +85 -12
- package/skills/loadbare-app/references/TECHREF-1.0.md +364 -72
- package/skills/loadbare-app/references/chrome.md +22 -1
- package/skills/loadbare-app/references/custom-elements.md +90 -29
- package/skills/loadbare-app/references/data-binding.md +132 -7
- package/skills/loadbare-app/references/page-files.md +48 -11
- package/skills/loadbare-app/references/server.md +4 -0
- package/skills/loadbare-app/references/widgets.md +94 -24
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 `rows` query is placed by its order: the one the URL carries for it, or\n * the one the server declared, or, with neither, the order its rows arrived\n * in. Groups are built from the markup's group templates as the order breaks,\n * and every change to a list — a row created, changed, moved or leaving, a\n * group appearing or leaving — is one a stylesheet can see.\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 AGGREGATES,\n ATTR_COLUMN,\n ATTR_COLUMN_VALUE,\n ATTR_COUNT,\n ATTR_GROUP,\n ATTR_GROUP_COLUMN,\n ATTR_GROUP_LEAVING,\n ATTR_GROUP_LIVE,\n ATTR_GROUP_VALUE,\n ATTR_KEY_VALUE,\n ATTR_MAX,\n ATTR_MIN,\n ATTR_QUERY,\n ATTR_QUERY_ROW_COUNT,\n ATTR_ROW_CHANGED,\n ATTR_ROW_CREATED,\n ATTR_ROW_LEAVING,\n ATTR_ROW_LIVE,\n ATTR_ROW_MOVED,\n ATTR_ROW_REQUESTED,\n ATTR_SHOW,\n ATTR_SUM,\n KIND_ROW,\n LIVE_GROUP,\n LIVE_ROW,\n REQUESTED_CHANGED,\n REQUESTED_CREATED,\n REQUESTED_MOVED,\n SHOW_NOT,\n} from \"../core/lb-constants.js\";\nimport {\n compareRows,\n compareValues,\n isPatch,\n parseOrder,\n type OrderTerm,\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/** An Element's nodeType, for the same reason. */\nconst ELEMENT_NODE = 1;\n\n/** A row or a group on its way out. */\nconst LEAVING = `[${ATTR_ROW_LEAVING}], [${ATTR_GROUP_LEAVING}]`;\n\n/**\n * What a group's heading and aggregates stop at: the rows and groups inside\n * it, live or leaving, which are filled from rows of their own.\n */\nconst SCAFFOLD_STOP = `${LIVE_ROW}, ${LIVE_GROUP}, ${LEAVING}`;\n\n/** An element carrying any aggregate. */\nconst AGGREGATE = AGGREGATES.map((name) => `[${name}]`).join(\", \");\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(\n root: Element | DocumentFragment,\n el: Element,\n stop?: string,\n): boolean {\n if (stop && el !== root && el.matches(stop)) return false;\n for (let node = el.parentElement; node && node !== root;) {\n if (node.hasAttribute(ATTR_QUERY)) return false;\n if (stop && node.matches(stop)) 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(\n root: Element | DocumentFragment,\n selector: string,\n stop?: string,\n): Element[] {\n const found: Element[] = [];\n for (const el of root.querySelectorAll(selector)) {\n if (inScope(root, el, stop)) found.push(el);\n }\n for (const parked of root.querySelectorAll(PARKED)) {\n if (inScope(root, parked, stop)) {\n found.push(\n ...below((parked as HTMLTemplateElement).content, selector, stop),\n );\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(\n root: Element,\n row: Row,\n liveRow = false,\n stop?: string,\n): void {\n for (const [column, value] of Object.entries(row)) {\n const selector = `[${ATTR_COLUMN}=\"${column}\"]`;\n const columns = below(root, selector, stop);\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}\"]`, stop)) {\n present(el, on);\n }\n for (const el of below(\n root,\n `[${ATTR_SHOW}=\"${SHOW_NOT}${column}\"]`,\n stop,\n )) {\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 * One group the hub built from a group template: the nodes its clone put in\n * the document, and the clone of the nested template, which is where its\n * contents go. The root of a list is a group with no nodes, whose slot is the\n * markup's own first template.\n */\ninterface Group {\n /** The column the group breaks on and its value there, as one string. */\n id: string;\n /** Every node the clone put in the document, the slot among them or not. */\n nodes: ChildNode[];\n /** The nested template's clone: contents land immediately before it. */\n slot: HTMLTemplateElement;\n /** The next level's groups, in order, when this is not the innermost. */\n children: Group[];\n /** The live rows, in order, when this is the innermost level. */\n rows: Element[];\n /** Whether its nodes have gone into the document yet. */\n placed: boolean;\n}\n\n/**\n * What the hub keeps about one element's rows between landings: the\n * templates the markup wrote, each live row's columns, and the groups built\n * from them.\n */\ninterface List {\n /** The markup's first template: a group template, or the row template. */\n top: HTMLTemplateElement;\n /** The group templates, outermost first. Empty when the list has none. */\n levels: HTMLTemplateElement[];\n /** The innermost template, which every live row is cloned from. */\n rowTemplate: HTMLTemplateElement;\n /** Every live row's columns, as landed so far. */\n data: Map<Element, Row>;\n /** The group each live row sits in. */\n groupOf: WeakMap<Element, Group>;\n root: Group;\n}\n\nconst lists = new WeakMap<Element, List>();\n\n/** Elements already told their group templates outrun their order. */\nconst warned = new WeakSet<Element>();\n\n/**\n * The template a group's contents go in front of: the first `<template>` in\n * the content outside any nested `lb-query`, and not one holding an absent\n * branch.\n */\nfunction slotIn(root: Element | DocumentFragment): HTMLTemplateElement | null {\n for (const t of root.querySelectorAll(`template:not([${ATTR_SHOW}])`)) {\n if (inScope(root, t)) return t as HTMLTemplateElement;\n }\n return null;\n}\n\n/**\n * The list an element holds, found from its first template the first time\n * rows land on it, and kept after that: once groups exist, their slots are\n * templates too, and they come first in the document.\n */\nfunction listFor(el: Element, template: HTMLTemplateElement): List | null {\n const found = lists.get(el);\n if (found) return found;\n const levels: HTMLTemplateElement[] = [];\n let at = template;\n while (at.hasAttribute(ATTR_GROUP)) {\n levels.push(at);\n const next = slotIn(at.content);\n if (!next) {\n console.error(\n `lb-hub: a group template in <${el.localName}> holds no nested ` +\n `template for its contents`,\n );\n return null;\n }\n at = next;\n }\n const list: List = {\n top: template,\n levels,\n rowTemplate: at,\n data: new Map(),\n groupOf: new WeakMap(),\n root: {\n id: \"\",\n nodes: [],\n slot: template,\n children: [],\n rows: [],\n placed: true,\n },\n };\n // Live rows already in the markup, as a page rendered ahead of its data\n // ships them, are the list's from the start, in the order they stand.\n if (levels.length === 0) {\n for (const row of liveRows(el)) {\n list.data.set(row, {});\n list.groupOf.set(row, list.root);\n list.root.rows.push(row);\n }\n }\n lists.set(el, list);\n return list;\n}\n\n/** The live rows of a group and everything under it, in order. */\nfunction rowsUnder(group: Group): Element[] {\n return group.children.length > 0\n ? group.children.flatMap(rowsUnder)\n : group.rows;\n}\n\n/** A group's identity among its siblings: its column and its value there. */\nfunction groupId(column: string, value: unknown): string {\n return `${column}\\u0000${JSON.stringify(value ?? null)}`;\n}\n\n/**\n * Make an attribute's change one a stylesheet sees, even when it is removed\n * and added again in one landing: the style is computed between the two.\n */\nfunction restamp(el: Element, name: string, on: boolean, value = \"\"): void {\n const had = el.hasAttribute(name);\n if (had) el.removeAttribute(name);\n if (!on) return;\n if (had)\n void el.ownerDocument.defaultView?.getComputedStyle(el).animationName;\n el.setAttribute(name, value);\n}\n\n/**\n * Take nodes out of the document once whatever their stylesheet started on\n * them has finished: at once when nothing is running. Asking for the running\n * animations computes the style, so an animation keyed to the leaving stamp\n * just set is among them.\n */\nfunction depart(nodes: ChildNode[]): void {\n const running: Animation[] = [];\n for (const node of nodes) {\n if (node.nodeType !== ELEMENT_NODE) continue;\n const el = node as Element & { getAnimations?: Element[\"getAnimations\"] };\n running.push(...(el.getAnimations?.({ subtree: true }) ?? []));\n }\n const go = (): void => {\n for (const node of nodes) node.remove();\n };\n if (running.length === 0) go();\n else void Promise.allSettled(running.map((a) => a.finished)).then(go);\n}\n\n/** Mark an element as leaving: no longer live, and taking no input. */\nfunction leaving(el: Element, live: string, stamp: string): void {\n el.removeAttribute(live);\n el.removeAttribute(ATTR_ROW_REQUESTED);\n el.setAttribute(stamp, \"\");\n el.setAttribute(\"inert\", \"\");\n}\n\n/** A live row the answer took away: it leaves, and the list forgets it. */\nfunction leaveRow(list: List, row: Element): void {\n list.data.delete(row);\n const group = list.groupOf.get(row);\n if (group) group.rows = group.rows.filter((r) => r !== row);\n leaving(row, ATTR_ROW_LIVE, ATTR_ROW_LEAVING);\n depart([row]);\n}\n\n/** A group with no rows left, and every group inside it, leave. */\nfunction leaveGroup(group: Group): void {\n for (const child of group.children) leaveGroup(child);\n for (const node of group.nodes) {\n if (node.nodeType === ELEMENT_NODE) {\n leaving(node as Element, ATTR_GROUP_LIVE, ATTR_GROUP_LEAVING);\n }\n }\n depart(group.nodes);\n}\n\n/** A new group, cloned from the group template for its level and stamped. */\nfunction makeGroup(\n doc: Document,\n template: HTMLTemplateElement,\n id: string,\n term: OrderTerm | undefined,\n value: unknown,\n): Group {\n // Imported rather than cloned, for the reason a live row is.\n const fragment = doc.importNode(template.content, true);\n const slot = slotIn(fragment)!;\n const nodes = [...fragment.childNodes];\n for (const node of nodes) {\n if (node.nodeType !== ELEMENT_NODE || node === slot) continue;\n const el = node as Element;\n el.setAttribute(ATTR_GROUP_LIVE, \"\");\n if (term) el.setAttribute(ATTR_GROUP_COLUMN, term.column);\n if (value === null || value === undefined) {\n el.removeAttribute(ATTR_GROUP_VALUE);\n } else {\n el.setAttribute(ATTR_GROUP_VALUE, String(value));\n }\n }\n return { id, nodes, slot, children: [], rows: [], placed: false };\n}\n\n/**\n * Which entries of a sequence of old positions keep their place: the run\n * already in order that keeps the most rows whose values did not change,\n * and then the most rows. Everything else moves, so the row that moves is the\n * one whose values put it somewhere else, never a neighbour it passed, and a\n * list landed again unchanged moves nothing. -1 is a row with no old\n * position here.\n */\nfunction inPlace(positions: number[], changed: boolean[]): Set<number> {\n // Heaviest increasing run, by a running maximum over old positions. An\n // unchanged row outweighs every changed row together.\n const size = positions.length;\n const heavy = size + 1;\n // Indexed by old position, which may run past the rows placed now: rows\n // that left the group in this landing kept theirs.\n const span = Math.max(0, ...positions) + 1;\n const tree: { weight: number; at: number }[] = Array.from(\n { length: span + 1 },\n () => ({ weight: 0, at: -1 }),\n );\n const best: number[] = new Array(size).fill(0);\n const before: number[] = new Array(size).fill(-1);\n let top = { weight: 0, at: -1 };\n for (let i = 0; i < size; i++) {\n const p = positions[i]!;\n if (p < 0) continue;\n let prior = { weight: 0, at: -1 };\n for (let k = p; k > 0; k -= k & -k) {\n if (tree[k]!.weight > prior.weight) prior = tree[k]!;\n }\n best[i] = prior.weight + (changed[i] ? 1 : heavy);\n before[i] = prior.at;\n const here = { weight: best[i]!, at: i };\n for (let k = p + 1; k <= span; k += k & -k) {\n if (here.weight > tree[k]!.weight) tree[k] = here;\n }\n if (here.weight > top.weight) top = here;\n }\n const keep = new Set<number>();\n for (let i = top.at; i >= 0; i = before[i]!) keep.add(i);\n return keep;\n}\n\n/**\n * Put a row in front of `ref`. A row already in the document leaves a copy\n * of itself behind, leaving, and is moved rather than taken out and put\n * back, where the browser can, so the control the user is in keeps focus.\n */\nfunction moveRow(row: Element, ref: ChildNode, moved: Set<Element>): void {\n const parent = ref.parentNode as\n (ParentNode & { moveBefore?(node: Node, child: Node | null): void }) | null;\n if (!parent) return;\n if (row.parentNode) {\n const copy = row.cloneNode(true) as Element;\n copy.removeAttribute(ATTR_ROW_CREATED);\n copy.removeAttribute(ATTR_ROW_CHANGED);\n copy.removeAttribute(ATTR_ROW_MOVED);\n leaving(copy, ATTR_ROW_LIVE, ATTR_ROW_LEAVING);\n row.parentNode.insertBefore(copy, row);\n moved.add(row);\n if (parent.moveBefore && row.isConnected && ref.isConnected) {\n try {\n parent.moveBefore(row, ref);\n depart([copy]);\n return;\n } catch {\n // Fall back to inserting, which the browser always allows.\n }\n }\n parent.insertBefore(row, ref);\n depart([copy]);\n return;\n }\n parent.insertBefore(row, ref);\n}\n\n/**\n * Place a list's live rows in the order given: groups made where the order\n * breaks and gone where it no longer does, and each row moved only when it\n * is out of place. Groups never move. Their order follows the leading terms,\n * so it changes only when the order does, and then every group at that level\n * is made again.\n */\nfunction arrange(\n list: List,\n doc: Document,\n desired: Element[],\n terms: OrderTerm[],\n changed: ReadonlySet<Element>,\n): Set<Element> {\n const moved = new Set<Element>();\n const retired: Group[] = [];\n\n const placeRows = (group: Group, rows: Element[]): void => {\n const was = new Map<Element, number>();\n group.rows.forEach((row, i) => {\n if (list.groupOf.get(row) === group && list.data.has(row))\n was.set(row, i);\n });\n const keep = inPlace(\n rows.map((row) => was.get(row) ?? -1),\n rows.map((row) => changed.has(row)),\n );\n let ref: ChildNode = group.slot;\n for (let i = rows.length - 1; i >= 0; i--) {\n const row = rows[i]!;\n if (!keep.has(i)) moveRow(row, ref, moved);\n ref = row;\n }\n group.rows = rows;\n for (const row of rows) list.groupOf.set(row, group);\n };\n\n const visit = (parent: Group, level: number, rows: Element[]): void => {\n if (level === list.levels.length) {\n placeRows(parent, rows);\n return;\n }\n const term = terms[level];\n const runs: { id: string; value: unknown; rows: Element[] }[] = [];\n for (const row of rows) {\n const value = term ? list.data.get(row)![term.column] : null;\n const id = groupId(term?.column ?? \"\", value);\n const last = runs.at(-1);\n if (last?.id === id) last.rows.push(row);\n else runs.push({ id, value, rows: [row] });\n }\n\n // Groups a level keeps must still be in the order the runs are in.\n // When they are not, the order changed, and every one is made again.\n const at = new Map(runs.map((run, i) => [run.id, i]));\n let last = -1;\n let kept = true;\n for (const child of parent.children) {\n const i = at.get(child.id);\n if (i === undefined) continue;\n if (i < last) kept = false;\n last = i;\n }\n const existing = new Map(\n kept ? parent.children.map((child) => [child.id, child]) : [],\n );\n const next = runs.map(\n (run) =>\n existing.get(run.id) ??\n makeGroup(doc, list.levels[level]!, run.id, term, run.value),\n );\n for (const child of parent.children) {\n if (!next.includes(child)) retired.push(child);\n }\n\n let ref: ChildNode = parent.slot;\n for (let i = next.length - 1; i >= 0; i--) {\n const group = next[i]!;\n if (!group.placed) {\n for (const node of group.nodes) ref.parentNode!.insertBefore(node, ref);\n group.placed = true;\n }\n ref = group.nodes[0] ?? group.slot;\n }\n parent.children = next;\n runs.forEach((run, i) => visit(next[i]!, level + 1, run.rows));\n };\n\n visit(list.root, 0, desired);\n // Only now, when every row that was in them has gone to its new place.\n for (const group of retired) leaveGroup(group);\n return moved;\n}\n\n/** A decimal: the digits as one integer, and how many of them are decimals. */\ninterface Decimal {\n digits: bigint;\n scale: number;\n}\n\n/** A plain decimal number, as JSON or Postgres writes one. */\nconst DECIMAL = /^[+-]?\\d+(\\.\\d+)?$/;\n\nfunction decimalOf(value: unknown): Decimal | null {\n const text = typeof value === \"number\" ? String(value) : value;\n if (typeof text !== \"string\" || !DECIMAL.test(text.trim())) return null;\n const [whole, fraction = \"\"] = text.trim().split(\".\");\n return { digits: BigInt(whole! + fraction), scale: fraction.length };\n}\n\nfunction rescale(d: Decimal, scale: number): bigint {\n return d.digits * 10n ** BigInt(scale - d.scale);\n}\n\nfunction decimalText(digits: bigint, scale: number): string {\n const negative = digits < 0n;\n const text = (negative ? -digits : digits)\n .toString()\n .padStart(scale + 1, \"0\");\n const whole = text.slice(0, text.length - scale);\n const fraction = scale > 0 ? `.${text.slice(text.length - scale)}` : \"\";\n return `${negative ? \"-\" : \"\"}${whole}${fraction}`;\n}\n\n/** Aggregates already warned about, so a bad value is reported once. */\nconst reported = new Set<string>();\n\n/**\n * One aggregate over rows. A sum and an average are exact, carried as\n * decimals with as many places as the most precise value, and an average\n * keeps up to two places more. Null and empty values are left out, as SQL\n * leaves them out; a value that is not a number is left out and reported.\n */\nfunction aggregateOf(name: string, column: string, rows: Row[]): unknown {\n if (name === ATTR_COUNT) return rows.length;\n const values = rows\n .map((row) => row[column])\n .filter((v) => v !== null && v !== undefined && v !== \"\");\n if (values.length === 0) return null;\n if (name === ATTR_MIN || name === ATTR_MAX) {\n const sign = name === ATTR_MIN ? 1 : -1;\n return values.reduce((a, b) => (sign * compareValues(b, a) < 0 ? b : a));\n }\n const decimals: Decimal[] = [];\n for (const value of values) {\n const d = decimalOf(value);\n if (d) decimals.push(d);\n else if (!reported.has(`${name}:${column}`)) {\n reported.add(`${name}:${column}`);\n console.warn(\n `lb-hub: ${name}=\"${column}\" left out ${JSON.stringify(value)}, ` +\n `which is not a number`,\n );\n }\n }\n if (decimals.length === 0) return null;\n const scale = Math.max(...decimals.map((d) => d.scale));\n const sum = decimals.reduce((total, d) => total + rescale(d, scale), 0n);\n if (name === ATTR_SUM) return decimalText(sum, scale);\n // An average, rounded half away from zero at two places past the values',\n // which are then dropped while they are zeros.\n const scaled = sum * 100n;\n const n = BigInt(decimals.length);\n const sign = scaled < 0n ? -1n : 1n;\n let text = decimalText((2n * scaled + sign * n) / (2n * n), scale + 2);\n for (let i = 0; i < 2 && text.endsWith(\"0\"); i++) text = text.slice(0, -1);\n return text.endsWith(\".\") ? text.slice(0, -1) : text;\n}\n\n/**\n * Set every aggregate in `root` from rows: the root itself when `self`, and\n * every element below it that is not inside a row or a group of its own.\n */\nfunction aggregate(root: Element, rows: Row[], self: boolean): void {\n const found = below(root, AGGREGATE, SCAFFOLD_STOP);\n if (self && root.matches(AGGREGATE)) found.unshift(root);\n for (const el of found) {\n const name = AGGREGATES.find((a) => el.hasAttribute(a))!;\n land(el, aggregateOf(name, el.getAttribute(name) ?? \"\", rows));\n }\n}\n\n/**\n * Fill each group's heading from its first row, and set each group's\n * aggregates from its rows, all the way down.\n */\nfunction finish(list: List, group: Group): void {\n for (const child of group.children) finish(list, child);\n const rows = rowsUnder(group);\n const data = rows.map((row) => list.data.get(row)!);\n for (const node of group.nodes) {\n if (node.nodeType !== ELEMENT_NODE || node === group.slot) continue;\n const el = node as Element;\n // A heading's own column is filled, as a live row's is, unless it holds\n // the group's contents, which filling it would replace.\n if (data[0]) {\n applyRow(el, data[0], !el.contains(group.slot), SCAFFOLD_STOP);\n }\n aggregate(el, data, true);\n }\n}\n\n/** The order to place rows by, or none when it cannot be read. */\nfunction termsOf(el: Element, order: string | undefined): OrderTerm[] {\n try {\n return parseOrder(order ?? \"\");\n } catch (err) {\n console.error(`lb-hub: <${el.localName}> ${(err as Error).message}`);\n return [];\n }\n}\n\n/** Whether a row's columns as landed differ from what they were. */\nfunction differs(before: Row | undefined, after: Row): boolean {\n if (!before) return false;\n return Object.entries(after).some(\n ([column, value]) =>\n JSON.stringify(before[column]) !== JSON.stringify(value),\n );\n}\n\n/** How a list of rows lands: in what order, and whether a request asked. */\nexport interface RowsOptions {\n /** The order to place rows by, as an order's text. */\n order?: string;\n /** The landing answers a request from this page. */\n requested?: boolean;\n}\n\n/**\n * Land rows through a row template.\n *\n * All rows decide membership: a row whose key did not arrive leaves. A patch\n * disturbs only what it names — a row it did not mention keeps its contents,\n * and keeps its place unless a row the patch named now sorts around it.\n *\n * Every live row is placed by the order. With none, all rows show in the\n * order they arrived, and a patch's new rows go last. A row moves only when\n * the order put it somewhere else, so landing the same rows again moves\n * nothing.\n */\nexport function applyRows(\n el: Element,\n template: HTMLTemplateElement,\n keyColumn: string,\n result: RowsResult,\n options: RowsOptions = {},\n): void {\n const list = listFor(el, template);\n if (!list) return;\n const shown = showing(el);\n const host = el as Element & RowsHost;\n const whole = !isPatch(result);\n const landed = new Map<string, Element>();\n const touched = new Map<Element, { fresh: boolean; changed: boolean }>();\n\n // What a request did is said by this landing alone.\n for (const row of shown.values()) row.removeAttribute(ATTR_ROW_REQUESTED);\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 landed.delete(key);\n }\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 list.rowTemplate.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 landed.set(key, row);\n const before = list.data.get(row);\n const prior = touched.get(row);\n touched.set(row, {\n fresh: prior?.fresh ?? fresh,\n changed: (prior?.changed ?? false) || differs(before, data),\n });\n list.data.set(row, { ...before, ...data });\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 };\n\n if (Array.isArray(result)) {\n for (const data of result) upsert(data);\n for (const [key, row] of shown) {\n if (!landed.has(key)) leaveRow(list, row);\n }\n } else {\n for (const data of result.rows ?? []) upsert(data);\n for (const key of result.drop ?? []) {\n const row = shown.get(String(key));\n if (row) leaveRow(list, row);\n }\n }\n\n const terms = termsOf(el, options.order);\n if (list.levels.length > terms.length && !warned.has(el)) {\n warned.add(el);\n console.warn(\n `lb-hub: <${el.localName}> has ${list.levels.length} group ` +\n `template(s) and an order of ${terms.length} term(s); a level with ` +\n `no term shows its rows as one group`,\n );\n }\n\n // Before sorting: the order the rows arrived in for all rows, and for a\n // patch the order already showing, with what is new after it. A sort keeps\n // rows that compare equal in this order.\n const live = new Set(list.data.keys());\n let base: Element[];\n if (whole) {\n base = [...landed.values()].filter((row) => live.has(row));\n } else {\n base = rowsUnder(list.root).filter((row) => live.has(row));\n const seen = new Set(base);\n for (const row of landed.values()) {\n if (!seen.has(row) && live.has(row)) base.push(row);\n }\n }\n const desired =\n terms.length === 0\n ? base\n : base\n .map((row, i) => ({ row, i, data: list.data.get(row)! }))\n .sort((a, b) => compareRows(a.data, b.data, terms) || a.i - b.i)\n .map(({ row }) => row);\n\n const moved = arrange(\n list,\n el.ownerDocument,\n desired,\n terms,\n new Set([...touched].filter(([, t]) => t.changed).map(([row]) => row)),\n );\n\n for (const [row, { fresh, changed }] of touched) {\n if (!list.data.has(row)) continue;\n const went = moved.has(row);\n restamp(row, ATTR_ROW_CREATED, fresh);\n restamp(row, ATTR_ROW_CHANGED, changed);\n restamp(row, ATTR_ROW_MOVED, went);\n const requested = went\n ? REQUESTED_MOVED\n : fresh\n ? REQUESTED_CREATED\n : changed\n ? REQUESTED_CHANGED\n : null;\n if (options.requested && requested) {\n row.setAttribute(ATTR_ROW_REQUESTED, requested);\n }\n }\n for (const row of moved) {\n if (!touched.has(row)) restamp(row, ATTR_ROW_MOVED, true);\n }\n\n finish(list, list.root);\n aggregate(\n el,\n rowsUnder(list.root).map((row) => list.data.get(row)!),\n false,\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 host.lbRowsLanded?.();\n}\n\n/** Land one response item on one element that names its query. */\nfunction landItem(\n el: Element,\n item: ResponseItem,\n options: RowsOptions = {},\n): void {\n const template = lists.get(el)?.top ?? templateIn(el);\n if (item.kind === KIND_ROW) {\n const row = item.row ?? {};\n if (template) {\n applyRows(el, template, item.key, [row], options);\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, options);\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 /** Where the user's order for a query comes from, as last handed in. */\n orderFor?: (query: string) => string | undefined;\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/** The answer kept for a query, as all of its rows. */\nexport function keptAnswer(\n root: ParentNode,\n query: string,\n): ResponseItem | undefined {\n return kept.get(root)?.answers.get(query);\n}\n\n/** The order a query's rows are placed by: the user's, else the server's. */\nfunction orderOf(state: Kept, item: ResponseItem): string | undefined {\n return state.orderFor?.(item.query) ?? item.order;\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, state: Kept): void {\n const { answers, landed } = state;\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) || el.closest(LEAVING)) continue;\n landed.add(el);\n landItem(el, item, { order: orderOf(state, item) });\n filled = true;\n }\n }\n }\n}\n\n/** How response items land. */\nexport interface LandOptions {\n /**\n * Queries that may have nowhere to land without a warning: the hub's own\n * `lb-url` lands wherever a chrome or page names it, and nowhere otherwise.\n */\n quiet?: readonly string[];\n /** The user's order for a query, which replaces the server's. */\n orderFor?: (query: string) => string | undefined;\n /** The items answer a request from this page. */\n requested?: boolean;\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 */\nexport function applyResponse(\n root: ParentNode,\n items: ResponseItem[],\n options: LandOptions = {},\n): void {\n const state = keptFor(root);\n if (options.orderFor) state.orderFor = options.orderFor;\n for (const item of items) {\n keep(state.answers, item);\n const targets = everywhere(root, `[${ATTR_QUERY}=\"${item.query}\"]`).filter(\n (el) => !el.closest(LEAVING),\n );\n if (targets.length === 0) {\n if (!options.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)) state.landed.add(el);\n landItem(el, item, {\n order: orderOf(state, item),\n requested: options.requested,\n });\n }\n }\n fillArrivals(root, state);\n}\n\n/**\n * Land a query's kept answer again, as all of its rows: what the hub does\n * when the user's order for it changes and the rows themselves have not.\n * False when no answer is kept.\n */\nexport function reland(root: ParentNode, query: string): boolean {\n const item = keptAnswer(root, query);\n if (!item) return false;\n applyResponse(root, [item]);\n return true;\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":"AAuDA,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";
|
|
3
|
-
import { isRowRequest, nextLocation, pageNameFor, } from "../core/lb-types.js";
|
|
4
|
-
import { applyResponse, isControl, isFormAssociated, within, } from "./lb-apply.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, ORDER_PARM_PREFIX, 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
|
+
import { isRowRequest, nextLocation, orderParm, pageNameFor, } from "../core/lb-types.js";
|
|
4
|
+
import { applyResponse, forget, isControl, isFormAssociated, keptAnswer, reland, 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 &&
|
|
@@ -277,6 +321,12 @@ function isPlainClick(e) {
|
|
|
277
321
|
!e.shiftKey &&
|
|
278
322
|
!e.altKey);
|
|
279
323
|
}
|
|
324
|
+
/** The user's order for a query, from the parm the URL carries for it. */
|
|
325
|
+
function orderFor(query) {
|
|
326
|
+
return new URLSearchParams(location.search).get(orderParm(query)) ?? undefined;
|
|
327
|
+
}
|
|
328
|
+
/** How everything the hub lands is landed: placed by the user's order. */
|
|
329
|
+
const LANDING = { orderFor };
|
|
280
330
|
/** The URL a row for `lb-url` leads to, by the rule the server follows. */
|
|
281
331
|
function nextUrl(row) {
|
|
282
332
|
const url = new URL(location.href);
|
|
@@ -298,6 +348,12 @@ class LbHub extends HTMLElement {
|
|
|
298
348
|
* request says which page it came from, on the path below the endpoint.
|
|
299
349
|
*/
|
|
300
350
|
page = "";
|
|
351
|
+
/**
|
|
352
|
+
* Set when a page is entered, and cleared once its queries have landed
|
|
353
|
+
* and focus has gone to its first control. A change of query parm on the
|
|
354
|
+
* same page does not set it: the user is where they chose to be.
|
|
355
|
+
*/
|
|
356
|
+
entering = false;
|
|
301
357
|
connectedCallback() {
|
|
302
358
|
this.main = this.querySelector("main");
|
|
303
359
|
// Completed in the capture phase, on the way down, so every ancestor
|
|
@@ -315,7 +371,7 @@ class LbHub extends HTMLElement {
|
|
|
315
371
|
// itself, since the event bubbles).
|
|
316
372
|
const origin = e.target ?? undefined;
|
|
317
373
|
if (request.query?.startsWith(LB_RESERVED_PREFIX)) {
|
|
318
|
-
this.answer(request, origin);
|
|
374
|
+
void this.answer(request, origin);
|
|
319
375
|
return;
|
|
320
376
|
}
|
|
321
377
|
void this.send(request, origin);
|
|
@@ -399,22 +455,32 @@ class LbHub extends HTMLElement {
|
|
|
399
455
|
* there, in the same round trip.
|
|
400
456
|
*/
|
|
401
457
|
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
|
-
|
|
458
|
+
const at = here();
|
|
459
|
+
const items = await this.roundTrip(this.page, request, origin);
|
|
460
|
+
if (items instanceof Error)
|
|
461
|
+
return done(origin, request, items);
|
|
462
|
+
let landed = [];
|
|
463
|
+
// The server answered for the URL the request was sent from. A user who
|
|
464
|
+
// moved while it was in flight, to another page or to other parms, is
|
|
465
|
+
// looking at something it says nothing about, and on a URL that is not
|
|
466
|
+
// the server's to change. The write still happened.
|
|
467
|
+
if (here() === at) {
|
|
468
|
+
const url = items.find((item) => item.query === URL_QUERY);
|
|
469
|
+
const load = items.filter((item) => item !== url);
|
|
470
|
+
landed = load;
|
|
471
|
+
if (url === undefined) {
|
|
472
|
+
applyResponse(this, load, { ...LANDING, requested: true });
|
|
473
|
+
}
|
|
474
|
+
else
|
|
475
|
+
landed = await this.follow(url, load, origin);
|
|
476
|
+
}
|
|
412
477
|
insertedFrom.get(request)?.reset();
|
|
478
|
+
done(origin, request, landed);
|
|
413
479
|
}
|
|
414
480
|
/**
|
|
415
481
|
* One round trip for a page: a request, or with none a page load. The
|
|
416
482
|
* element that issued it carries `lb-request-pending` while it is in
|
|
417
|
-
* flight, and `lb-request-error` when it fails.
|
|
483
|
+
* flight, and `lb-request-error` when it fails. The error on failure.
|
|
418
484
|
*/
|
|
419
485
|
async roundTrip(page, request, origin) {
|
|
420
486
|
pending(origin, true);
|
|
@@ -424,7 +490,7 @@ class LbHub extends HTMLElement {
|
|
|
424
490
|
catch (err) {
|
|
425
491
|
console.error(`lb-hub: request failed for '${page}'`, err);
|
|
426
492
|
origin?.setAttribute(ATTR_REQUEST_ERROR, "");
|
|
427
|
-
return
|
|
493
|
+
return err instanceof Error ? err : new Error(String(err));
|
|
428
494
|
}
|
|
429
495
|
finally {
|
|
430
496
|
pending(origin, false);
|
|
@@ -434,15 +500,49 @@ class LbHub extends HTMLElement {
|
|
|
434
500
|
* Answer a request for a query the hub serves, with no round trip. The
|
|
435
501
|
* hub serves `lb-url`, and updates it.
|
|
436
502
|
*/
|
|
437
|
-
answer(request, origin) {
|
|
503
|
+
async answer(request, origin) {
|
|
438
504
|
if (request.query !== URL_QUERY || request.name !== REQUEST_ROW_UPDATE) {
|
|
439
|
-
|
|
440
|
-
`the hub answers, ignoring
|
|
441
|
-
|
|
505
|
+
const message = `lb-hub: '${request.name}' for '${request.query}' is not a request ` +
|
|
506
|
+
`the hub answers, ignoring`;
|
|
507
|
+
console.error(message);
|
|
508
|
+
return done(origin, request, new Error(message));
|
|
442
509
|
}
|
|
443
510
|
const pushed = origin?.hasAttribute(ATTR_URL_PUSH) ?? false;
|
|
444
|
-
|
|
445
|
-
|
|
511
|
+
const was = new URL(location.href);
|
|
512
|
+
if (!this.moveTo(request.values ?? {}, pushed)) {
|
|
513
|
+
return done(origin, request, []);
|
|
514
|
+
}
|
|
515
|
+
if (this.sortHere(was))
|
|
516
|
+
return done(origin, request, []);
|
|
517
|
+
done(origin, request, await this.navigate(origin));
|
|
518
|
+
}
|
|
519
|
+
/**
|
|
520
|
+
* A change of URL that only changed the user's order for queries the hub
|
|
521
|
+
* sorts itself: the rows are already here, so they are placed again with
|
|
522
|
+
* no round trip. False when anything else changed, or a query whose order
|
|
523
|
+
* changed reads the parm itself, and the page must load.
|
|
524
|
+
*/
|
|
525
|
+
sortHere(was) {
|
|
526
|
+
if (was.pathname !== location.pathname)
|
|
527
|
+
return false;
|
|
528
|
+
const now = new URLSearchParams(location.search);
|
|
529
|
+
const names = new Set([...was.searchParams.keys(), ...now.keys()]);
|
|
530
|
+
const queries = [];
|
|
531
|
+
for (const name of names) {
|
|
532
|
+
if (was.searchParams.get(name) === now.get(name))
|
|
533
|
+
continue;
|
|
534
|
+
if (!name.startsWith(ORDER_PARM_PREFIX))
|
|
535
|
+
return false;
|
|
536
|
+
const query = name.slice(ORDER_PARM_PREFIX.length);
|
|
537
|
+
const item = keptAnswer(this, query);
|
|
538
|
+
if (!item || item.serverSortedByUrl)
|
|
539
|
+
return false;
|
|
540
|
+
queries.push(query);
|
|
541
|
+
}
|
|
542
|
+
this.arrive();
|
|
543
|
+
for (const query of queries)
|
|
544
|
+
reland(this, query);
|
|
545
|
+
return true;
|
|
446
546
|
}
|
|
447
547
|
/**
|
|
448
548
|
* Write a row for `lb-url` into the URL. A new page pushes a history
|
|
@@ -465,18 +565,20 @@ class LbHub extends HTMLElement {
|
|
|
465
565
|
* without marking the element that issued the request: its write
|
|
466
566
|
* succeeded, and an error would invite sending it twice.
|
|
467
567
|
*
|
|
468
|
-
* `
|
|
469
|
-
*
|
|
568
|
+
* What landed: the `lb-url` item and the load, however it arrived. A load
|
|
569
|
+
* asked for again that fails is not the request's failure.
|
|
470
570
|
*/
|
|
471
|
-
async follow(
|
|
472
|
-
if (pageNameFor(location.pathname) !== page)
|
|
473
|
-
return;
|
|
571
|
+
async follow(item, load, origin) {
|
|
474
572
|
this.moveTo(item.row ?? {}, origin?.hasAttribute(ATTR_URL_PUSH) ?? false);
|
|
475
|
-
if (load.length === 0)
|
|
476
|
-
|
|
573
|
+
if (load.length === 0) {
|
|
574
|
+
const again = await this.navigate();
|
|
575
|
+
return again instanceof Error ? [item] : [item, ...again];
|
|
576
|
+
}
|
|
477
577
|
const template = this.arrive();
|
|
478
578
|
if (template)
|
|
479
|
-
applyResponse(this, load);
|
|
579
|
+
applyResponse(this, load, LANDING);
|
|
580
|
+
this.entered();
|
|
581
|
+
return template ? [item, ...load] : [item];
|
|
480
582
|
}
|
|
481
583
|
/**
|
|
482
584
|
* Load the page at the URL the browser is showing. Every way of arriving
|
|
@@ -489,13 +591,42 @@ class LbHub extends HTMLElement {
|
|
|
489
591
|
*
|
|
490
592
|
* `origin` is the element whose request changed the URL, if one did, and
|
|
491
593
|
* carries the round trip's pending and error state.
|
|
594
|
+
*
|
|
595
|
+
* What landed, or the error when the round trip failed. A load that
|
|
596
|
+
* returns after the URL has moved again lands nothing: the load for where
|
|
597
|
+
* the browser is now is already on its way, and may be here.
|
|
492
598
|
*/
|
|
493
599
|
async navigate(origin) {
|
|
494
600
|
const template = this.arrive();
|
|
495
601
|
if (!template)
|
|
496
|
-
return;
|
|
602
|
+
return [];
|
|
603
|
+
const at = here();
|
|
497
604
|
const items = await this.roundTrip(this.page, undefined, origin);
|
|
498
|
-
|
|
605
|
+
if (here() !== at)
|
|
606
|
+
return items instanceof Error ? items : [];
|
|
607
|
+
if (items instanceof Error) {
|
|
608
|
+
this.entered();
|
|
609
|
+
return items;
|
|
610
|
+
}
|
|
611
|
+
// Entering the page moved the URL, as an application restoring what the
|
|
612
|
+
// user last had on screen does: the server loaded the page there.
|
|
613
|
+
const url = items.find((item) => item.query === URL_QUERY);
|
|
614
|
+
if (url) {
|
|
615
|
+
return this.follow(url, items.filter((item) => item !== url), origin);
|
|
616
|
+
}
|
|
617
|
+
applyResponse(this, items, LANDING);
|
|
618
|
+
this.entered();
|
|
619
|
+
return items;
|
|
620
|
+
}
|
|
621
|
+
/**
|
|
622
|
+
* A page that was entered has landed its queries, so its first control
|
|
623
|
+
* exists: a row cloned, a branch shown, a picker's options in place.
|
|
624
|
+
*/
|
|
625
|
+
entered() {
|
|
626
|
+
if (!this.entering)
|
|
627
|
+
return;
|
|
628
|
+
this.entering = false;
|
|
629
|
+
focusFirst(this.main);
|
|
499
630
|
}
|
|
500
631
|
/**
|
|
501
632
|
* Show the page the path names, and land `lb-url`. Null when no page's
|
|
@@ -507,8 +638,11 @@ class LbHub extends HTMLElement {
|
|
|
507
638
|
if (template && page !== this.page) {
|
|
508
639
|
this.page = page;
|
|
509
640
|
// The template is already in the document, so the page's markup goes
|
|
510
|
-
// in before its data arrives rather than leaving <main> empty.
|
|
641
|
+
// in before its data arrives rather than leaving <main> empty. What
|
|
642
|
+
// the last page's queries answered goes with it.
|
|
511
643
|
this.main.replaceChildren(template.content.cloneNode(true));
|
|
644
|
+
forget(this);
|
|
645
|
+
this.entering = true;
|
|
512
646
|
}
|
|
513
647
|
this.landUrl(template ? titleOf(template, page) : null);
|
|
514
648
|
// An app that ships `<body hidden>` (docs/reference/chrome.md) stays
|
|
@@ -554,9 +688,7 @@ class LbHub extends HTMLElement {
|
|
|
554
688
|
row[URL_COLUMN_PATH] = location.pathname;
|
|
555
689
|
row[URL_COLUMN_PAGE_LABEL] = label;
|
|
556
690
|
row[URL_COLUMN_PAGE_UNKNOWN] = label === null;
|
|
557
|
-
applyResponse(this, [
|
|
558
|
-
{ query: URL_QUERY, kind: KIND_ROW, key: URL_COLUMN_PATH, row },
|
|
559
|
-
]);
|
|
691
|
+
applyResponse(this, [{ query: URL_QUERY, kind: KIND_ROW, key: URL_COLUMN_PATH, row }], LANDING);
|
|
560
692
|
}
|
|
561
693
|
}
|
|
562
694
|
customElements.define(HUB_TAG_NAME, LbHub);
|