@aglyn/plugins-ai 1.0.0-beta.292 → 1.0.0-beta.293

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.
Files changed (149) hide show
  1. package/package.json +17 -17
  2. package/src/lib/components/ai-site-import-job.component.js +5 -4
  3. package/src/lib/components/ai-site-import-job.component.js.map +1 -1
  4. package/src/lib/components/ai-site-import-start.component.js +3 -3
  5. package/src/lib/components/ai-site-import-start.component.js.map +1 -1
  6. package/src/lib/components/ai-site-start-card.component.d.ts +1 -1
  7. package/src/lib/components/ai-site-start-card.component.js +129 -29
  8. package/src/lib/components/ai-site-start-card.component.js.map +1 -1
  9. package/src/lib/components/ai-site-start-steps.component.d.ts +15 -3
  10. package/src/lib/components/ai-site-start-steps.component.js +42 -25
  11. package/src/lib/components/ai-site-start-steps.component.js.map +1 -1
  12. package/src/lib/components/ai-site-style-previews.d.ts +17 -0
  13. package/src/lib/components/ai-site-style-previews.js +26 -95
  14. package/src/lib/components/ai-site-style-previews.js.map +1 -1
  15. package/src/lib/declarations.server.js +22 -0
  16. package/src/lib/declarations.server.js.map +1 -1
  17. package/src/lib/jobs/ai-job-import-step.d.ts +21 -2
  18. package/src/lib/jobs/ai-job-import-step.js +179 -49
  19. package/src/lib/jobs/ai-job-import-step.js.map +1 -1
  20. package/src/lib/jobs/ai-job-layout-language.d.ts +27 -3
  21. package/src/lib/jobs/ai-job-layout-language.js +156 -113
  22. package/src/lib/jobs/ai-job-layout-language.js.map +1 -1
  23. package/src/lib/jobs/ai-job-layout-step.js +56 -17
  24. package/src/lib/jobs/ai-job-layout-step.js.map +1 -1
  25. package/src/lib/jobs/ai-job-page-language.d.ts +25 -15
  26. package/src/lib/jobs/ai-job-page-language.js +120 -66
  27. package/src/lib/jobs/ai-job-page-language.js.map +1 -1
  28. package/src/lib/jobs/ai-job-page-step.js +27 -7
  29. package/src/lib/jobs/ai-job-page-step.js.map +1 -1
  30. package/src/lib/jobs/ai-job-site-datasets.d.ts +12 -4
  31. package/src/lib/jobs/ai-job-site-datasets.js +36 -16
  32. package/src/lib/jobs/ai-job-site-datasets.js.map +1 -1
  33. package/src/lib/jobs/ai-jobs.js +6 -2
  34. package/src/lib/jobs/ai-jobs.js.map +1 -1
  35. package/src/lib/jobs/ai-layout-stock-photos.d.ts +50 -1
  36. package/src/lib/jobs/ai-layout-stock-photos.js +586 -35
  37. package/src/lib/jobs/ai-layout-stock-photos.js.map +1 -1
  38. package/src/lib/jobs/ai-site-import-compile.d.ts +147 -0
  39. package/src/lib/jobs/ai-site-import-compile.js +1143 -0
  40. package/src/lib/jobs/ai-site-import-compile.js.map +1 -0
  41. package/src/lib/jobs/ai-site-import-document.d.ts +9 -36
  42. package/src/lib/jobs/ai-site-import-document.js +23 -489
  43. package/src/lib/jobs/ai-site-import-document.js.map +1 -1
  44. package/src/lib/jobs/ai-site-import-look.d.ts +54 -7
  45. package/src/lib/jobs/ai-site-import-look.js +163 -52
  46. package/src/lib/jobs/ai-site-import-look.js.map +1 -1
  47. package/src/lib/jobs/ai-site-import-publish.d.ts +7 -1
  48. package/src/lib/jobs/ai-site-import-publish.js +19 -5
  49. package/src/lib/jobs/ai-site-import-publish.js.map +1 -1
  50. package/src/lib/jobs/ai-site-late-photos.js +4 -2
  51. package/src/lib/jobs/ai-site-late-photos.js.map +1 -1
  52. package/src/lib/jobs/ai-site-publish.d.ts +10 -1
  53. package/src/lib/jobs/ai-site-publish.js +8 -3
  54. package/src/lib/jobs/ai-site-publish.js.map +1 -1
  55. package/src/lib/jobs/fixtures/ai-stock-photo-agl4092-1029-recordings.d.ts +23 -0
  56. package/src/lib/jobs/fixtures/ai-stock-photo-agl4092-1029-recordings.js +677 -0
  57. package/src/lib/jobs/fixtures/ai-stock-photo-agl4092-1029-recordings.js.map +1 -0
  58. package/src/lib/layout-language/ai-layout-compiler.d.ts +26 -0
  59. package/src/lib/layout-language/ai-layout-compiler.js +677 -33
  60. package/src/lib/layout-language/ai-layout-compiler.js.map +1 -1
  61. package/src/lib/layout-language/ai-layout-frame-hollows.js +5 -1
  62. package/src/lib/layout-language/ai-layout-frame-hollows.js.map +1 -1
  63. package/src/lib/layout-language/ai-layout-frame-source.d.ts +196 -0
  64. package/src/lib/layout-language/ai-layout-frame-source.js +726 -0
  65. package/src/lib/layout-language/ai-layout-frame-source.js.map +1 -0
  66. package/src/lib/layout-language/ai-layout-frame.d.ts +22 -0
  67. package/src/lib/layout-language/ai-layout-frame.js +121 -29
  68. package/src/lib/layout-language/ai-layout-frame.js.map +1 -1
  69. package/src/lib/layout-language/ai-layout-language.d.ts +103 -37
  70. package/src/lib/layout-language/ai-layout-language.js +85 -120
  71. package/src/lib/layout-language/ai-layout-language.js.map +1 -1
  72. package/src/lib/model/ai-credit-estimate.d.ts +11 -7
  73. package/src/lib/model/ai-credit-estimate.js +11 -7
  74. package/src/lib/model/ai-credit-estimate.js.map +1 -1
  75. package/src/lib/model/ai-site-import.d.ts +307 -13
  76. package/src/lib/model/ai-site-import.js +227 -19
  77. package/src/lib/model/ai-site-import.js.map +1 -1
  78. package/src/lib/model/ai-site-look.d.ts +65 -1
  79. package/src/lib/model/ai-site-look.js +141 -23
  80. package/src/lib/model/ai-site-look.js.map +1 -1
  81. package/src/lib/model/ai-site-photos.d.ts +2 -0
  82. package/src/lib/model/ai-site-photos.js.map +1 -1
  83. package/src/lib/model/ai-site-start-steps.d.ts +4 -3
  84. package/src/lib/model/ai-site-start-steps.js +11 -3
  85. package/src/lib/model/ai-site-start-steps.js.map +1 -1
  86. package/src/lib/model/ai-site-start.d.ts +23 -2
  87. package/src/lib/model/ai-site-start.js +25 -3
  88. package/src/lib/model/ai-site-start.js.map +1 -1
  89. package/src/lib/providers/routing.d.ts +11 -0
  90. package/src/lib/providers/routing.js +23 -0
  91. package/src/lib/providers/routing.js.map +1 -1
  92. package/src/lib/runtime/ai-doctrine-validators.d.ts +4 -2
  93. package/src/lib/runtime/ai-doctrine-validators.js +7 -2
  94. package/src/lib/runtime/ai-doctrine-validators.js.map +1 -1
  95. package/src/lib/runtime/ai-icon-library.d.ts +4 -0
  96. package/src/lib/runtime/ai-icon-library.js +4 -0
  97. package/src/lib/runtime/ai-icon-library.js.map +1 -1
  98. package/src/lib/runtime/ai-node-tree.js +5 -1
  99. package/src/lib/runtime/ai-node-tree.js.map +1 -1
  100. package/src/lib/runtime/ai-palette.d.ts +2 -0
  101. package/src/lib/runtime/ai-palette.generated.js +19 -3
  102. package/src/lib/runtime/ai-palette.generated.js.map +1 -1
  103. package/src/lib/runtime/ai-palette.js +2 -1
  104. package/src/lib/runtime/ai-palette.js.map +1 -1
  105. package/src/lib/site-import/fixtures/site-layout-recordings.d.ts +50 -0
  106. package/src/lib/site-import/fixtures/site-layout-recordings.js +86 -0
  107. package/src/lib/site-import/fixtures/site-layout-recordings.js.map +1 -0
  108. package/src/lib/site-import/site-import-crawl.d.ts +18 -1
  109. package/src/lib/site-import/site-import-crawl.js +70 -10
  110. package/src/lib/site-import/site-import-crawl.js.map +1 -1
  111. package/src/lib/site-import/site-import-css.d.ts +110 -0
  112. package/src/lib/site-import/site-import-css.js +826 -0
  113. package/src/lib/site-import/site-import-css.js.map +1 -0
  114. package/src/lib/site-import/site-import-html.d.ts +116 -1
  115. package/src/lib/site-import/site-import-html.js +538 -46
  116. package/src/lib/site-import/site-import-html.js.map +1 -1
  117. package/src/lib/site-import/site-import-layout.d.ts +79 -0
  118. package/src/lib/site-import/site-import-layout.js +1608 -0
  119. package/src/lib/site-import/site-import-layout.js.map +1 -0
  120. package/src/lib/site-import/site-import-nav.d.ts +40 -0
  121. package/src/lib/site-import/site-import-nav.js +437 -0
  122. package/src/lib/site-import/site-import-nav.js.map +1 -0
  123. package/src/lib/site-import/site-import-page.d.ts +8 -1
  124. package/src/lib/site-import/site-import-page.js +24 -2
  125. package/src/lib/site-import/site-import-page.js.map +1 -1
  126. package/src/lib/assets/site-styles/beauty.webp +0 -0
  127. package/src/lib/assets/site-styles/blog.webp +0 -0
  128. package/src/lib/assets/site-styles/business.webp +0 -0
  129. package/src/lib/assets/site-styles/coming-soon.webp +0 -0
  130. package/src/lib/assets/site-styles/education.webp +0 -0
  131. package/src/lib/assets/site-styles/events.webp +0 -0
  132. package/src/lib/assets/site-styles/fitness.webp +0 -0
  133. package/src/lib/assets/site-styles/landing.webp +0 -0
  134. package/src/lib/assets/site-styles/music.webp +0 -0
  135. package/src/lib/assets/site-styles/nonprofit.webp +0 -0
  136. package/src/lib/assets/site-styles/personal.webp +0 -0
  137. package/src/lib/assets/site-styles/photography.webp +0 -0
  138. package/src/lib/assets/site-styles/portfolio.webp +0 -0
  139. package/src/lib/assets/site-styles/professional.webp +0 -0
  140. package/src/lib/assets/site-styles/realestate.webp +0 -0
  141. package/src/lib/assets/site-styles/restaurant.webp +0 -0
  142. package/src/lib/assets/site-styles/store.webp +0 -0
  143. package/src/lib/assets/site-styles/studio.webp +0 -0
  144. package/src/lib/assets/site-styles/trades.webp +0 -0
  145. package/src/lib/assets/site-styles/wellness.webp +0 -0
  146. package/src/lib/assets/site-styles/yoga.webp +0 -0
  147. package/src/lib/site-import/site-import-review.d.ts +0 -40
  148. package/src/lib/site-import/site-import-review.js +0 -149
  149. package/src/lib/site-import/site-import-review.js.map +0 -1
@@ -31,6 +31,10 @@ import { _ as _extends } from "@swc/helpers/_/_extends";
31
31
  'muiMegaMenu'
32
32
  ]);
33
33
  const LINK = 'muiScreenLink';
34
+ /** What a menu's entry may be: a Page Link, or a Link Container holding a name and the line under it (AGL-4108). */ const MENU_LINKS = new Set([
35
+ LINK,
36
+ 'muiLinkBox'
37
+ ]);
34
38
  /** Frames that hold content without being it: the language's, and a plain element. */ const HOLDERS = new Set([
35
39
  ...AI_LAYOUT_FRAMES,
36
40
  'div',
@@ -127,7 +131,7 @@ function inspect(map) {
127
131
  const headerIds = new Set(headers.flatMap(subtree));
128
132
  const headerMenus = [
129
133
  ...headerIds
130
- ].filter((id)=>DROPDOWNS.has(String(map[id].componentId)) && !subtree(id).some((at)=>at !== id && map[at].componentId === LINK));
134
+ ].filter((id)=>DROPDOWNS.has(String(map[id].componentId)) && !subtree(id).some((at)=>at !== id && MENU_LINKS.has(String(map[at].componentId))));
131
135
  return {
132
136
  footerColumns,
133
137
  footerHeadings,
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../../../../../libs/plugins/ai/src/lib/layout-language/ai-layout-frame-hollows.ts"],"sourcesContent":["/**\n * @license\n * Copyright 2026 Aglyn LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { AI_LAYOUT_FRAMES, aiLayoutSpans } from './ai-layout-tree'\n\n/**\n * A FRAME WITH NOTHING HOLLOW IN IT (AGL-3735).\n *\n * The live Tidewater Soap Works footer (job S0vnUzhGar, 10/11) had four\n * columns: the brand, \"Shop\" over the site's pages, \"Our shop\" over NOTHING,\n * and the store's account and policy links under no heading — the list the\n * design put under \"Our shop\" was left out, its heading and column stayed,\n * and the grid centered the columns so each sat at its own height.\n *\n * A heading with nothing under it, and a column with nothing but headings,\n * is never published. So, wherever the frame's links change — the compiler,\n * a publish taking out links to pages that were never written, a menu change\n * taking a link out — and once more on what a publish writes:\n *\n * - in the footer, a column of only a heading followed by a column of only\n * links with no heading (the Tidewater shape) becomes one column: the\n * heading over those links;\n * - then a heading with no content under it is taken out, then a column\n * holding nothing (or nothing but headings) is, and the columns left\n * reflow across the row's twelve;\n * - the footer's rows are top-aligned;\n * - in the header, a Dropdown Menu left holding no link is taken out.\n *\n * `aiLayoutFrameHollows` is the check: what is still hollow.\n *\n * Pure over a node map (`{ id: { componentId, props, sx, nodes } }`) — the\n * compiler's, a stored version's, or a publish's working copy.\n */\n\ninterface HollowNode {\n componentId?: string\n props?: Record<string, unknown>\n sx?: Record<string, unknown>\n nodes?: string[]\n [key: string]: unknown\n}\n\ntype NodeMap = Record<string, HollowNode>\n\n/** A Typography variant that heads what follows it, never content of its own. */\nconst HEADING_VARIANTS: ReadonlySet<string> = new Set(['h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'subtitle1', 'subtitle2', 'overline'])\n/** The Besigner's Dropdown Menu and Mega Menu. */\nconst DROPDOWNS: ReadonlySet<string> = new Set(['muiNavMenu', 'muiMegaMenu'])\nconst LINK = 'muiScreenLink'\n/** Frames that hold content without being it: the language's, and a plain element. */\nconst HOLDERS: ReadonlySet<string> = new Set([...AI_LAYOUT_FRAMES, 'div', 'span', 'muiGrid'])\n\nconst renders = (node: HollowNode, element: string) =>\n node.props?.['element'] === element || node.props?.['component'] === element || node.componentId === element\n\nconst isHeading = (node: HollowNode | undefined) =>\n !!node && node.componentId === 'muiTypography' && HEADING_VARIANTS.has(String(node.props?.['variant'] ?? ''))\n\n/** What is still hollow in a frame: the node ids, by kind. */\nexport interface AiLayoutFrameHollows {\n /** Footer grid columns holding nothing, or nothing but headings. */\n footerColumns: string[]\n /** Footer headings with nothing under them. */\n footerHeadings: string[]\n /** Footer rows whose columns are centered against each other rather than top-aligned. */\n footerCenteredRows: string[]\n /** Header Dropdown Menus holding no link. */\n headerMenus: string[]\n}\n\n/** A heading-only footer column and the heading-less column of links right after it, which it heads. */\ninterface HeadingOverLinks {\n heading: string\n links: string\n}\n\nfunction inspect(map: NodeMap): AiLayoutFrameHollows & { rows: string[]; merges: HeadingOverLinks[] } {\n const subtree = (id: string): string[] => {\n const out: string[] = []\n const visit = (at: string) => {\n if (!map[at] || out.includes(at)) return\n out.push(at)\n for (const child of map[at].nodes ?? []) visit(child)\n }\n visit(id)\n return out\n }\n /** The leaves under a node, in document order: what a visitor reads. */\n const leaves = (id: string) =>\n subtree(id).filter((at) => {\n const node = map[at]\n return !(node.nodes ?? []).some((child) => map[child]) && !HOLDERS.has(String(node.componentId))\n })\n const footers = Object.keys(map).filter((id) => renders(map[id], 'footer'))\n const headers = Object.keys(map).filter((id) => map[id].componentId === 'muiAppBar' || renders(map[id], 'header'))\n\n const footerIds = new Set(footers.flatMap(subtree))\n const rows = [...footerIds].filter((id) => map[id].componentId === 'muiGrid' && map[id].props?.['container'])\n const columns = rows.flatMap((row) => (map[row].nodes ?? []).filter((id) => map[id]?.componentId === 'muiGrid'))\n const footerColumns = columns.filter((id) => leaves(id).every((leaf) => isHeading(map[leaf])))\n // The Tidewater shape: a column of only a heading, then a column of only\n // links with no heading. The links are what the heading heads.\n const merges: HeadingOverLinks[] = []\n for (const row of rows) {\n const inRow = (map[row].nodes ?? []).filter((id) => map[id]?.componentId === 'muiGrid')\n inRow.forEach((id, at) => {\n const next = inRow[at + 1]\n if (!next || !footerColumns.includes(id) || !leaves(id).length) return\n const read = leaves(next)\n if (read.length && read.every((leaf) => map[leaf].componentId === LINK)) merges.push({ heading: id, links: next })\n })\n }\n // A heading is hollow when nothing but headings follow it before the next\n // heading of its own (an overline labels the heading after it, so it\n // reaches one heading further).\n const footerHeadings: string[] = []\n const flows = columns.length ? columns : footers\n for (const flow of flows) {\n if (footerColumns.includes(flow)) continue\n const read = leaves(flow)\n read.forEach((id, at) => {\n if (!isHeading(map[id])) return\n let headingsLeft = map[id].props?.['variant'] === 'overline' ? 2 : 1\n for (const next of read.slice(at + 1)) {\n if (!isHeading(map[next])) return\n if (map[next].props?.['variant'] !== 'overline') headingsLeft -= 1\n if (headingsLeft <= 0) break\n }\n footerHeadings.push(id)\n })\n }\n const footerCenteredRows = rows.filter((id) => map[id].sx?.['alignItems'] === 'center')\n const headerIds = new Set(headers.flatMap(subtree))\n const headerMenus = [...headerIds].filter(\n (id) => DROPDOWNS.has(String(map[id].componentId)) && !subtree(id).some((at) => at !== id && map[at].componentId === LINK),\n )\n return { footerColumns, footerHeadings, footerCenteredRows, headerMenus, rows, merges }\n}\n\n/** What is still hollow in a frame (AGL-3735); every list empty when nothing is. */\nexport function aiLayoutFrameHollows(nodes: Readonly<Record<string, unknown>>): AiLayoutFrameHollows {\n const { footerColumns, footerHeadings, footerCenteredRows, headerMenus } = inspect(nodes as NodeMap)\n return { footerColumns, footerHeadings, footerCenteredRows, headerMenus }\n}\n\n/** Whether a frame has anything hollow in it. */\nexport function aiLayoutFrameIsHollow(hollows: AiLayoutFrameHollows): boolean {\n return [hollows.footerColumns, hollows.footerHeadings, hollows.footerCenteredRows, hollows.headerMenus].some((ids) => ids.length > 0)\n}\n\n/** The sentences a check reports for what is hollow. */\nexport function aiLayoutFrameHollowsSaid(hollows: AiLayoutFrameHollows): string[] {\n return [\n ...(hollows.footerColumns.length ? [`${hollows.footerColumns.length} footer column(s) hold only a heading or nothing`] : []),\n ...(hollows.footerHeadings.length ? [`${hollows.footerHeadings.length} footer heading(s) have nothing under them`] : []),\n ...(hollows.footerCenteredRows.length ? ['the footer’s columns are centered, not top-aligned'] : []),\n ...(hollows.headerMenus.length ? [`${hollows.headerMenus.length} header dropdown(s) hold no link`] : []),\n ]\n}\n\n/**\n * Takes what is hollow out of a frame, IN PLACE (AGL-3735): see the file's\n * comment. Returns whether anything changed. A frame left holding nothing is\n * taken out after it, up to the row, the footer's or the header's own element.\n */\nexport function aiLayoutRepairFrameHollows(nodes: Record<string, unknown>): boolean {\n const map = nodes as NodeMap\n let changed = false\n const parentOf = (id: string) => Object.keys(map).find((at) => map[at].nodes?.includes(id)) ?? null\n const remove = (id: string) => {\n const tree = (at: string): string[] => [at, ...(map[at]?.nodes ?? []).flatMap(tree)]\n let parent = parentOf(id)\n for (const at of tree(id)) delete map[at]\n // Up the tree: a frame that held only what went is gone with it.\n let child = id\n while (parent && map[parent]) {\n const node = map[parent]\n node.nodes = (node.nodes ?? []).filter((at) => at !== child)\n const empty = !node.nodes.some((at) => map[at])\n const stops = renders(node, 'footer') || renders(node, 'header') || node.componentId === 'muiAppBar' || (node.componentId === 'muiGrid' && node.props?.['container'])\n if (!empty || stops || !HOLDERS.has(String(node.componentId))) break\n child = parent\n parent = parentOf(parent)\n delete map[child]\n }\n changed = true\n }\n for (let pass = 0; pass < 4; pass += 1) {\n const hollows = inspect(map)\n if (!aiLayoutFrameIsHollow(hollows)) break\n for (const id of hollows.footerCenteredRows) {\n map[id].sx = { ...(map[id].sx ?? {}), alignItems: 'flex-start' }\n changed = true\n }\n for (const id of hollows.headerMenus) if (map[id]) remove(id)\n const headed = new Set<string>()\n for (const merge of hollows.merges) {\n if (map[merge.heading] && map[merge.links] && headOver(map, merge)) {\n headed.add(merge.heading)\n changed = true\n }\n }\n for (const id of hollows.footerHeadings) if (map[id]) remove(id)\n for (const id of hollows.footerColumns) if (map[id] && !headed.has(id)) remove(id)\n // Every row that lost a column, however it lost it, reflows.\n for (const row of hollows.rows) if (map[row] && reflow(map, row)) changed = true\n }\n return changed\n}\n\n/**\n * A heading-only column takes in the heading-less column of links after it,\n * as one flow (heading, then links), and the links' column goes; whether it\n * changed. The row it leaves one column short reflows after.\n */\nfunction headOver(map: NodeMap, { heading, links }: HeadingOverLinks): boolean {\n const moved = (map[links].nodes ?? []).filter((id) => map[id])\n if (!moved.length) return false\n const own = (map[heading].nodes ?? []).filter((id) => map[id])\n const flow = own.length === 1 && map[own[0]].componentId === 'muiStack' ? own[0] : null\n if (flow) {\n map[flow].nodes = [...(map[flow].nodes ?? []), ...moved]\n } else {\n let id = `${heading}-flow`\n for (let n = 2; map[id]; n += 1) id = `${heading}-flow${n}`\n // The compiler's flow of a column (`compileFlow`): a stack, 2.5 apart.\n map[id] = { componentId: 'muiStack', props: { spacing: '2.5' }, nodes: [...own, ...moved] }\n map[heading].nodes = [id]\n }\n delete map[links]\n for (const node of Object.values(map)) {\n if (node.nodes?.includes(links)) node.nodes = node.nodes.filter((at) => at !== links)\n }\n return true\n}\n\n/** The columns a row has left, spread across its twelve as their widths were; whether it changed. */\nfunction reflow(map: NodeMap, row: string): boolean {\n const columns = (map[row].nodes ?? []).filter((id) => map[id]?.componentId === 'muiGrid')\n const md = columns.map((id) => /(?:^|\\s)md:(\\d+)/.exec(String(map[id].props?.['size'] ?? ''))?.[1])\n if (!columns.length || md.some((span) => !span)) return false\n // A row whose columns fill it, as many as it was drawn for, is as it was drawn.\n const drawnFor = /sm:6/.test(String(map[columns[0]].props?.['size'] ?? '')) ? 4 : 3\n if (md.reduce((sum, span) => sum + Number(span), 0) === 12 && (columns.length >= 4) === (drawnFor === 4)) return false\n const spans = columns.length === 1 ? [12] : aiLayoutSpans(md.map(Number))\n columns.forEach((id, at) => {\n map[id].props = { ...(map[id].props ?? {}), size: `${columns.length >= 4 ? 'xs:12 sm:6' : 'xs:12'} md:${spans[at]}` }\n })\n // The compiler's row spacing for that many columns (`compileRow`).\n if (map[row].props?.['spacing'] === '4' || map[row].props?.['spacing'] === '6') {\n map[row].props = { ...map[row].props, spacing: columns.length >= 3 ? '4' : '6' }\n }\n return true\n}\n\n/** A frame with what is hollow taken out (AGL-3735), as a copy; `null` when nothing was. */\nexport function aiLayoutWithoutFrameHollows<T extends Readonly<Record<string, unknown>>>(nodes: T): T | null {\n const copy: Record<string, unknown> = {}\n for (const [id, raw] of Object.entries(nodes)) {\n const node = raw as HollowNode\n copy[id] =\n node && typeof node === 'object'\n ? { ...node, ...(node.props ? { props: { ...node.props } } : {}), ...(node.sx ? { sx: { ...node.sx } } : {}), ...(node.nodes ? { nodes: [...node.nodes] } : {}) }\n : node\n }\n return aiLayoutRepairFrameHollows(copy) ? (copy as T) : null\n}\n"],"names":["AI_LAYOUT_FRAMES","aiLayoutSpans","HEADING_VARIANTS","Set","DROPDOWNS","LINK","HOLDERS","renders","node","element","props","componentId","isHeading","has","String","inspect","map","subtree","id","out","visit","at","includes","push","child","nodes","leaves","filter","some","footers","Object","keys","headers","footerIds","flatMap","rows","columns","row","footerColumns","every","leaf","merges","inRow","forEach","next","length","read","heading","links","footerHeadings","flows","flow","headingsLeft","slice","footerCenteredRows","sx","headerIds","headerMenus","aiLayoutFrameHollows","aiLayoutFrameIsHollow","hollows","ids","aiLayoutFrameHollowsSaid","aiLayoutRepairFrameHollows","changed","parentOf","find","remove","tree","parent","empty","stops","pass","alignItems","headed","merge","headOver","add","reflow","moved","own","n","spacing","values","md","exec","span","drawnFor","test","reduce","sum","Number","spans","size","aiLayoutWithoutFrameHollows","copy","raw","entries"],"mappings":"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"}
1
+ {"version":3,"sources":["../../../../../../../libs/plugins/ai/src/lib/layout-language/ai-layout-frame-hollows.ts"],"sourcesContent":["/**\n * @license\n * Copyright 2026 Aglyn LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { AI_LAYOUT_FRAMES, aiLayoutSpans } from './ai-layout-tree'\n\n/**\n * A FRAME WITH NOTHING HOLLOW IN IT (AGL-3735).\n *\n * The live Tidewater Soap Works footer (job S0vnUzhGar, 10/11) had four\n * columns: the brand, \"Shop\" over the site's pages, \"Our shop\" over NOTHING,\n * and the store's account and policy links under no heading — the list the\n * design put under \"Our shop\" was left out, its heading and column stayed,\n * and the grid centered the columns so each sat at its own height.\n *\n * A heading with nothing under it, and a column with nothing but headings,\n * is never published. So, wherever the frame's links change — the compiler,\n * a publish taking out links to pages that were never written, a menu change\n * taking a link out — and once more on what a publish writes:\n *\n * - in the footer, a column of only a heading followed by a column of only\n * links with no heading (the Tidewater shape) becomes one column: the\n * heading over those links;\n * - then a heading with no content under it is taken out, then a column\n * holding nothing (or nothing but headings) is, and the columns left\n * reflow across the row's twelve;\n * - the footer's rows are top-aligned;\n * - in the header, a Dropdown Menu left holding no link is taken out.\n *\n * `aiLayoutFrameHollows` is the check: what is still hollow.\n *\n * Pure over a node map (`{ id: { componentId, props, sx, nodes } }`) — the\n * compiler's, a stored version's, or a publish's working copy.\n */\n\ninterface HollowNode {\n componentId?: string\n props?: Record<string, unknown>\n sx?: Record<string, unknown>\n nodes?: string[]\n [key: string]: unknown\n}\n\ntype NodeMap = Record<string, HollowNode>\n\n/** A Typography variant that heads what follows it, never content of its own. */\nconst HEADING_VARIANTS: ReadonlySet<string> = new Set(['h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'subtitle1', 'subtitle2', 'overline'])\n/** The Besigner's Dropdown Menu and Mega Menu. */\nconst DROPDOWNS: ReadonlySet<string> = new Set(['muiNavMenu', 'muiMegaMenu'])\nconst LINK = 'muiScreenLink'\n/** What a menu's entry may be: a Page Link, or a Link Container holding a name and the line under it (AGL-4108). */\nconst MENU_LINKS: ReadonlySet<string> = new Set([LINK, 'muiLinkBox'])\n/** Frames that hold content without being it: the language's, and a plain element. */\nconst HOLDERS: ReadonlySet<string> = new Set([...AI_LAYOUT_FRAMES, 'div', 'span', 'muiGrid'])\n\nconst renders = (node: HollowNode, element: string) =>\n node.props?.['element'] === element || node.props?.['component'] === element || node.componentId === element\n\nconst isHeading = (node: HollowNode | undefined) =>\n !!node && node.componentId === 'muiTypography' && HEADING_VARIANTS.has(String(node.props?.['variant'] ?? ''))\n\n/** What is still hollow in a frame: the node ids, by kind. */\nexport interface AiLayoutFrameHollows {\n /** Footer grid columns holding nothing, or nothing but headings. */\n footerColumns: string[]\n /** Footer headings with nothing under them. */\n footerHeadings: string[]\n /** Footer rows whose columns are centered against each other rather than top-aligned. */\n footerCenteredRows: string[]\n /** Header Dropdown Menus holding no link. */\n headerMenus: string[]\n}\n\n/** A heading-only footer column and the heading-less column of links right after it, which it heads. */\ninterface HeadingOverLinks {\n heading: string\n links: string\n}\n\nfunction inspect(map: NodeMap): AiLayoutFrameHollows & { rows: string[]; merges: HeadingOverLinks[] } {\n const subtree = (id: string): string[] => {\n const out: string[] = []\n const visit = (at: string) => {\n if (!map[at] || out.includes(at)) return\n out.push(at)\n for (const child of map[at].nodes ?? []) visit(child)\n }\n visit(id)\n return out\n }\n /** The leaves under a node, in document order: what a visitor reads. */\n const leaves = (id: string) =>\n subtree(id).filter((at) => {\n const node = map[at]\n return !(node.nodes ?? []).some((child) => map[child]) && !HOLDERS.has(String(node.componentId))\n })\n const footers = Object.keys(map).filter((id) => renders(map[id], 'footer'))\n const headers = Object.keys(map).filter((id) => map[id].componentId === 'muiAppBar' || renders(map[id], 'header'))\n\n const footerIds = new Set(footers.flatMap(subtree))\n const rows = [...footerIds].filter((id) => map[id].componentId === 'muiGrid' && map[id].props?.['container'])\n const columns = rows.flatMap((row) => (map[row].nodes ?? []).filter((id) => map[id]?.componentId === 'muiGrid'))\n const footerColumns = columns.filter((id) => leaves(id).every((leaf) => isHeading(map[leaf])))\n // The Tidewater shape: a column of only a heading, then a column of only\n // links with no heading. The links are what the heading heads.\n const merges: HeadingOverLinks[] = []\n for (const row of rows) {\n const inRow = (map[row].nodes ?? []).filter((id) => map[id]?.componentId === 'muiGrid')\n inRow.forEach((id, at) => {\n const next = inRow[at + 1]\n if (!next || !footerColumns.includes(id) || !leaves(id).length) return\n const read = leaves(next)\n if (read.length && read.every((leaf) => map[leaf].componentId === LINK)) merges.push({ heading: id, links: next })\n })\n }\n // A heading is hollow when nothing but headings follow it before the next\n // heading of its own (an overline labels the heading after it, so it\n // reaches one heading further).\n const footerHeadings: string[] = []\n const flows = columns.length ? columns : footers\n for (const flow of flows) {\n if (footerColumns.includes(flow)) continue\n const read = leaves(flow)\n read.forEach((id, at) => {\n if (!isHeading(map[id])) return\n let headingsLeft = map[id].props?.['variant'] === 'overline' ? 2 : 1\n for (const next of read.slice(at + 1)) {\n if (!isHeading(map[next])) return\n if (map[next].props?.['variant'] !== 'overline') headingsLeft -= 1\n if (headingsLeft <= 0) break\n }\n footerHeadings.push(id)\n })\n }\n const footerCenteredRows = rows.filter((id) => map[id].sx?.['alignItems'] === 'center')\n const headerIds = new Set(headers.flatMap(subtree))\n const headerMenus = [...headerIds].filter(\n (id) => DROPDOWNS.has(String(map[id].componentId)) && !subtree(id).some((at) => at !== id && MENU_LINKS.has(String(map[at].componentId))),\n )\n return { footerColumns, footerHeadings, footerCenteredRows, headerMenus, rows, merges }\n}\n\n/** What is still hollow in a frame (AGL-3735); every list empty when nothing is. */\nexport function aiLayoutFrameHollows(nodes: Readonly<Record<string, unknown>>): AiLayoutFrameHollows {\n const { footerColumns, footerHeadings, footerCenteredRows, headerMenus } = inspect(nodes as NodeMap)\n return { footerColumns, footerHeadings, footerCenteredRows, headerMenus }\n}\n\n/** Whether a frame has anything hollow in it. */\nexport function aiLayoutFrameIsHollow(hollows: AiLayoutFrameHollows): boolean {\n return [hollows.footerColumns, hollows.footerHeadings, hollows.footerCenteredRows, hollows.headerMenus].some((ids) => ids.length > 0)\n}\n\n/** The sentences a check reports for what is hollow. */\nexport function aiLayoutFrameHollowsSaid(hollows: AiLayoutFrameHollows): string[] {\n return [\n ...(hollows.footerColumns.length ? [`${hollows.footerColumns.length} footer column(s) hold only a heading or nothing`] : []),\n ...(hollows.footerHeadings.length ? [`${hollows.footerHeadings.length} footer heading(s) have nothing under them`] : []),\n ...(hollows.footerCenteredRows.length ? ['the footer’s columns are centered, not top-aligned'] : []),\n ...(hollows.headerMenus.length ? [`${hollows.headerMenus.length} header dropdown(s) hold no link`] : []),\n ]\n}\n\n/**\n * Takes what is hollow out of a frame, IN PLACE (AGL-3735): see the file's\n * comment. Returns whether anything changed. A frame left holding nothing is\n * taken out after it, up to the row, the footer's or the header's own element.\n */\nexport function aiLayoutRepairFrameHollows(nodes: Record<string, unknown>): boolean {\n const map = nodes as NodeMap\n let changed = false\n const parentOf = (id: string) => Object.keys(map).find((at) => map[at].nodes?.includes(id)) ?? null\n const remove = (id: string) => {\n const tree = (at: string): string[] => [at, ...(map[at]?.nodes ?? []).flatMap(tree)]\n let parent = parentOf(id)\n for (const at of tree(id)) delete map[at]\n // Up the tree: a frame that held only what went is gone with it.\n let child = id\n while (parent && map[parent]) {\n const node = map[parent]\n node.nodes = (node.nodes ?? []).filter((at) => at !== child)\n const empty = !node.nodes.some((at) => map[at])\n const stops = renders(node, 'footer') || renders(node, 'header') || node.componentId === 'muiAppBar' || (node.componentId === 'muiGrid' && node.props?.['container'])\n if (!empty || stops || !HOLDERS.has(String(node.componentId))) break\n child = parent\n parent = parentOf(parent)\n delete map[child]\n }\n changed = true\n }\n for (let pass = 0; pass < 4; pass += 1) {\n const hollows = inspect(map)\n if (!aiLayoutFrameIsHollow(hollows)) break\n for (const id of hollows.footerCenteredRows) {\n map[id].sx = { ...(map[id].sx ?? {}), alignItems: 'flex-start' }\n changed = true\n }\n for (const id of hollows.headerMenus) if (map[id]) remove(id)\n const headed = new Set<string>()\n for (const merge of hollows.merges) {\n if (map[merge.heading] && map[merge.links] && headOver(map, merge)) {\n headed.add(merge.heading)\n changed = true\n }\n }\n for (const id of hollows.footerHeadings) if (map[id]) remove(id)\n for (const id of hollows.footerColumns) if (map[id] && !headed.has(id)) remove(id)\n // Every row that lost a column, however it lost it, reflows.\n for (const row of hollows.rows) if (map[row] && reflow(map, row)) changed = true\n }\n return changed\n}\n\n/**\n * A heading-only column takes in the heading-less column of links after it,\n * as one flow (heading, then links), and the links' column goes; whether it\n * changed. The row it leaves one column short reflows after.\n */\nfunction headOver(map: NodeMap, { heading, links }: HeadingOverLinks): boolean {\n const moved = (map[links].nodes ?? []).filter((id) => map[id])\n if (!moved.length) return false\n const own = (map[heading].nodes ?? []).filter((id) => map[id])\n const flow = own.length === 1 && map[own[0]].componentId === 'muiStack' ? own[0] : null\n if (flow) {\n map[flow].nodes = [...(map[flow].nodes ?? []), ...moved]\n } else {\n let id = `${heading}-flow`\n for (let n = 2; map[id]; n += 1) id = `${heading}-flow${n}`\n // The compiler's flow of a column (`compileFlow`): a stack, 2.5 apart.\n map[id] = { componentId: 'muiStack', props: { spacing: '2.5' }, nodes: [...own, ...moved] }\n map[heading].nodes = [id]\n }\n delete map[links]\n for (const node of Object.values(map)) {\n if (node.nodes?.includes(links)) node.nodes = node.nodes.filter((at) => at !== links)\n }\n return true\n}\n\n/** The columns a row has left, spread across its twelve as their widths were; whether it changed. */\nfunction reflow(map: NodeMap, row: string): boolean {\n const columns = (map[row].nodes ?? []).filter((id) => map[id]?.componentId === 'muiGrid')\n const md = columns.map((id) => /(?:^|\\s)md:(\\d+)/.exec(String(map[id].props?.['size'] ?? ''))?.[1])\n if (!columns.length || md.some((span) => !span)) return false\n // A row whose columns fill it, as many as it was drawn for, is as it was drawn.\n const drawnFor = /sm:6/.test(String(map[columns[0]].props?.['size'] ?? '')) ? 4 : 3\n if (md.reduce((sum, span) => sum + Number(span), 0) === 12 && (columns.length >= 4) === (drawnFor === 4)) return false\n const spans = columns.length === 1 ? [12] : aiLayoutSpans(md.map(Number))\n columns.forEach((id, at) => {\n map[id].props = { ...(map[id].props ?? {}), size: `${columns.length >= 4 ? 'xs:12 sm:6' : 'xs:12'} md:${spans[at]}` }\n })\n // The compiler's row spacing for that many columns (`compileRow`).\n if (map[row].props?.['spacing'] === '4' || map[row].props?.['spacing'] === '6') {\n map[row].props = { ...map[row].props, spacing: columns.length >= 3 ? '4' : '6' }\n }\n return true\n}\n\n/** A frame with what is hollow taken out (AGL-3735), as a copy; `null` when nothing was. */\nexport function aiLayoutWithoutFrameHollows<T extends Readonly<Record<string, unknown>>>(nodes: T): T | null {\n const copy: Record<string, unknown> = {}\n for (const [id, raw] of Object.entries(nodes)) {\n const node = raw as HollowNode\n copy[id] =\n node && typeof node === 'object'\n ? { ...node, ...(node.props ? { props: { ...node.props } } : {}), ...(node.sx ? { sx: { ...node.sx } } : {}), ...(node.nodes ? { nodes: [...node.nodes] } : {}) }\n : node\n }\n return aiLayoutRepairFrameHollows(copy) ? (copy as T) : null\n}\n"],"names":["AI_LAYOUT_FRAMES","aiLayoutSpans","HEADING_VARIANTS","Set","DROPDOWNS","LINK","MENU_LINKS","HOLDERS","renders","node","element","props","componentId","isHeading","has","String","inspect","map","subtree","id","out","visit","at","includes","push","child","nodes","leaves","filter","some","footers","Object","keys","headers","footerIds","flatMap","rows","columns","row","footerColumns","every","leaf","merges","inRow","forEach","next","length","read","heading","links","footerHeadings","flows","flow","headingsLeft","slice","footerCenteredRows","sx","headerIds","headerMenus","aiLayoutFrameHollows","aiLayoutFrameIsHollow","hollows","ids","aiLayoutFrameHollowsSaid","aiLayoutRepairFrameHollows","changed","parentOf","find","remove","tree","parent","empty","stops","pass","alignItems","headed","merge","headOver","add","reflow","moved","own","n","spacing","values","md","exec","span","drawnFor","test","reduce","sum","Number","spans","size","aiLayoutWithoutFrameHollows","copy","raw","entries"],"mappings":"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"}
@@ -0,0 +1,196 @@
1
+ /**
2
+ * @license
3
+ * Copyright 2026 Aglyn LLC
4
+ *
5
+ * Licensed under the Apache License, Version 2.0 (the "License");
6
+ * you may not use this file except in compliance with the License.
7
+ * You may obtain a copy of the License at
8
+ *
9
+ * http://www.apache.org/licenses/LICENSE-2.0
10
+ *
11
+ * Unless required by applicable law or agreed to in writing, software
12
+ * distributed under the License is distributed on an "AS IS" BASIS,
13
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
+ * See the License for the specific language governing permissions and
15
+ * limitations under the License.
16
+ */
17
+ import type { AiLayoutTreeBuilder } from './ai-layout-tree';
18
+ /** How a source's button is drawn: filled, outlined, or as text. */
19
+ export type AiLayoutFrameSourceStyle = 'primary' | 'secondary' | 'quiet';
20
+ /**
21
+ * Where a link of a source's header or footer goes: `page:<id>` for a page of
22
+ * the site, a path on the site (`/pricing`) for a page still to come in, or
23
+ * the source's own address (`https:`, `mailto:`, `tel:`) for anywhere else.
24
+ */
25
+ export type AiLayoutFrameSourceTo = string;
26
+ export interface AiLayoutFrameSourceLink {
27
+ label: string;
28
+ to: AiLayoutFrameSourceTo;
29
+ }
30
+ /** One entry of a menu. */
31
+ export interface AiLayoutFrameSourceEntry extends AiLayoutFrameSourceLink {
32
+ /** The line under it in a mega menu. */
33
+ text?: string;
34
+ /** Its icon, drawn on a 24-unit square. */
35
+ iconPath?: string;
36
+ /** The heading of the menu's column it sits in. */
37
+ column?: string;
38
+ }
39
+ /** A top-level item: a link, or a menu of entries under a name. */
40
+ export interface AiLayoutFrameSourceGroup {
41
+ label: string;
42
+ /** Where the name itself goes; `null` when it only opens its menu. */
43
+ to: AiLayoutFrameSourceTo | null;
44
+ /** Empty for a plain link. */
45
+ items: AiLayoutFrameSourceEntry[];
46
+ }
47
+ export interface AiLayoutFrameSourceCta extends AiLayoutFrameSourceLink {
48
+ style: AiLayoutFrameSourceStyle;
49
+ }
50
+ export interface AiLayoutFrameSourceFooter {
51
+ columns: Array<{
52
+ heading: string;
53
+ links: AiLayoutFrameSourceLink[];
54
+ }>;
55
+ /** Links outside any column and not a profile (Privacy, Terms). */
56
+ links: AiLayoutFrameSourceLink[];
57
+ /** Its lines of words outside links, as written. */
58
+ text: string[];
59
+ /** Its profiles on other sites, by network. */
60
+ social: Array<AiLayoutFrameSourceLink & {
61
+ network: string;
62
+ }>;
63
+ address: string | null;
64
+ phone: string | null;
65
+ email: string | null;
66
+ /** Its © line, word for word. */
67
+ copyright: string | null;
68
+ }
69
+ /**
70
+ * What the source's header bar sits on: the page's own ground, paper, the
71
+ * brand color, or a dark band.
72
+ */
73
+ export type AiLayoutFrameSourceGround = 'page' | 'paper' | 'brand' | 'dark';
74
+ /** A header and footer as the source builds them (AGL-4108). */
75
+ export interface AiLayoutFrameSource {
76
+ nav: AiLayoutFrameSourceGroup[];
77
+ ctas: AiLayoutFrameSourceCta[];
78
+ header: AiLayoutFrameSourceGround;
79
+ footer: AiLayoutFrameSourceFooter | null;
80
+ }
81
+ /** The most kept of each part: the reader's own limits, held again on the way in. */
82
+ export declare const AI_LAYOUT_FRAME_SOURCE_LIMITS: {
83
+ readonly groups: 12;
84
+ readonly entries: 40;
85
+ readonly ctas: 4;
86
+ readonly columns: 12;
87
+ readonly links: 60;
88
+ readonly text: 12;
89
+ readonly social: 20;
90
+ readonly label: 120;
91
+ readonly line: 300;
92
+ };
93
+ /** Whether a destination is one a link of the frame may carry. */
94
+ export declare function aiLayoutFrameSourceToAllowed(to: unknown): to is AiLayoutFrameSourceTo;
95
+ /**
96
+ * A source frame as a job carries it, read defensively: every label cut to
97
+ * its limit, every destination one a link may carry, every icon one path.
98
+ * `null` where it holds no menu item and no button to draw.
99
+ */
100
+ export declare function aiLayoutFrameSourceOf(raw: unknown): AiLayoutFrameSource | null;
101
+ /** The pages a source frame links by id, each once. */
102
+ export declare function aiLayoutFrameSourcePageIds(source: AiLayoutFrameSource): string[];
103
+ /** A link's props for where it goes: a page by its id, anywhere else by its address. */
104
+ export declare function aiLayoutFrameSourceLinkProps(to: AiLayoutFrameSourceTo): Record<string, unknown>;
105
+ /**
106
+ * The widths the header row is held to, in CSS pixels: a character of a
107
+ * label at the body size, the chevron a menu's trigger carries, the gap
108
+ * between the row's items and between its buttons, a button's padding, and
109
+ * the row's room at each breakpoint (the Container's `lg` width less its
110
+ * gutters).
111
+ */
112
+ export declare const AI_LAYOUT_HEADER_MEASURE: {
113
+ readonly char: 9;
114
+ readonly chevron: 28;
115
+ readonly gap: 24;
116
+ readonly buttonGap: 8;
117
+ readonly padding: {
118
+ readonly primary: 32;
119
+ readonly secondary: 32;
120
+ readonly quiet: 16;
121
+ };
122
+ readonly room: {
123
+ readonly md: number;
124
+ readonly lg: number;
125
+ };
126
+ /** What share of the room the row may fill: the estimate is a character's average, so it keeps a margin. */
127
+ readonly fill: 0.9;
128
+ /** A logo's width where its picture's shape is unknown. */
129
+ readonly logo: 160;
130
+ };
131
+ /** The header row's width in CSS pixels, its brand, its menu and its buttons side by side. */
132
+ export declare function aiLayoutHeaderRowWidth(input: {
133
+ brandWidth: number;
134
+ nav: ReadonlyArray<{
135
+ label: string;
136
+ menu: boolean;
137
+ }>;
138
+ ctas: ReadonlyArray<{
139
+ label: string;
140
+ style: AiLayoutFrameSourceStyle;
141
+ }>;
142
+ }): number;
143
+ /**
144
+ * The screen width the menu row shows from (AGL-4108): `md` where it fits a
145
+ * 900-pixel screen with room to spare, else `lg`; and `lg` whatever it
146
+ * measures for a row of more than five items or more than 60 characters.
147
+ * Below it the row is the phone menu's button.
148
+ */
149
+ export declare function aiLayoutNavBreakpoint(input: Parameters<typeof aiLayoutHeaderRowWidth>[0]): 'md' | 'lg';
150
+ /** A source's header row as `aiLayoutHeaderRowWidth` measures it. */
151
+ export declare function aiLayoutFrameSourceRow(source: Pick<AiLayoutFrameSource, 'nav' | 'ctas'>, brandWidth: number): Parameters<typeof aiLayoutHeaderRowWidth>[0];
152
+ /** A column of a menu: its heading, where its entries have one, and its entries. */
153
+ interface MenuColumn {
154
+ heading: string | null;
155
+ entries: AiLayoutFrameSourceEntry[];
156
+ }
157
+ /** A menu's entries in the columns the source sets them in, in order; a long unheaded run in two. */
158
+ export declare function aiLayoutMenuColumns(entries: readonly AiLayoutFrameSourceEntry[]): MenuColumn[];
159
+ /** Whether a menu is drawn as a Mega Menu: its entries carry a line under them, or sit in more than one headed column. */
160
+ export declare function aiLayoutMenuIsMega(group: Pick<AiLayoutFrameSourceGroup, 'items'>): boolean;
161
+ export interface AiLayoutSourceHeader {
162
+ /** The menu row, shown from `breakpoint` up; `null` with no item to show. */
163
+ nav: string | null;
164
+ /** The buttons beside it; `null` with none. */
165
+ ctas: string | null;
166
+ /** The phone menu's contents, in order. */
167
+ drawer: string[];
168
+ breakpoint: 'md' | 'lg';
169
+ }
170
+ /**
171
+ * The source's header drawn (AGL-4108): its menu row, its buttons and its
172
+ * phone menu. `close` is the interaction a link of the phone menu closes it
173
+ * with.
174
+ */
175
+ export declare function aiLayoutSourceHeader(tree: AiLayoutTreeBuilder, source: AiLayoutFrameSource, input: {
176
+ onBrand: boolean;
177
+ close: unknown[];
178
+ brandWidth: number;
179
+ }): AiLayoutSourceHeader;
180
+ /**
181
+ * The page a menu's own name opens, where none of its entries does: a page
182
+ * of the site, never an address elsewhere (a Squarespace folder's address
183
+ * is no page). `null` otherwise.
184
+ */
185
+ export declare function aiLayoutMenuOwnPage(group: Pick<AiLayoutFrameSourceGroup, 'to' | 'items'>): AiLayoutFrameSourceTo | null;
186
+ /** A phone number as a link that calls it: its digits, a `+` only first; `null` where it is no number. */
187
+ export declare function aiLayoutTelHref(phone: string): string | null;
188
+ /** The source's footer drawn (AGL-4108): its words and profiles beside its columns, its © line and other links under a rule. */
189
+ export declare function aiLayoutSourceFooter(tree: AiLayoutTreeBuilder, footer: AiLayoutFrameSourceFooter, input: {
190
+ name: string;
191
+ }): {
192
+ top: string | null;
193
+ bottom: string;
194
+ sx: Record<string, unknown>;
195
+ };
196
+ export {};