@aglyn/plugins-mui 1.0.0-beta.143

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 (177) hide show
  1. package/LICENSE +201 -0
  2. package/README.md +22 -0
  3. package/package.json +47 -0
  4. package/src/index.d.ts +21 -0
  5. package/src/index.js +22 -0
  6. package/src/index.js.map +1 -0
  7. package/src/lib/components/accordion.d.ts +96 -0
  8. package/src/lib/components/accordion.js +392 -0
  9. package/src/lib/components/accordion.js.map +1 -0
  10. package/src/lib/components/app-bar.d.ts +32 -0
  11. package/src/lib/components/app-bar.js +86 -0
  12. package/src/lib/components/app-bar.js.map +1 -0
  13. package/src/lib/components/blocks.d.ts +46 -0
  14. package/src/lib/components/blocks.js +1007 -0
  15. package/src/lib/components/blocks.js.map +1 -0
  16. package/src/lib/components/box.d.ts +47 -0
  17. package/src/lib/components/box.js +125 -0
  18. package/src/lib/components/box.js.map +1 -0
  19. package/src/lib/components/breadcrumbs.d.ts +44 -0
  20. package/src/lib/components/breadcrumbs.js +172 -0
  21. package/src/lib/components/breadcrumbs.js.map +1 -0
  22. package/src/lib/components/button.d.ts +89 -0
  23. package/src/lib/components/button.js +272 -0
  24. package/src/lib/components/button.js.map +1 -0
  25. package/src/lib/components/card.d.ts +61 -0
  26. package/src/lib/components/card.js +336 -0
  27. package/src/lib/components/card.js.map +1 -0
  28. package/src/lib/components/collection.d.ts +514 -0
  29. package/src/lib/components/collection.js +2999 -0
  30. package/src/lib/components/collection.js.map +1 -0
  31. package/src/lib/components/container.d.ts +42 -0
  32. package/src/lib/components/container.js +169 -0
  33. package/src/lib/components/container.js.map +1 -0
  34. package/src/lib/components/custom-html.d.ts +78 -0
  35. package/src/lib/components/custom-html.js +219 -0
  36. package/src/lib/components/custom-html.js.map +1 -0
  37. package/src/lib/components/data-table.d.ts +57 -0
  38. package/src/lib/components/data-table.js +216 -0
  39. package/src/lib/components/data-table.js.map +1 -0
  40. package/src/lib/components/document-root.d.ts +77 -0
  41. package/src/lib/components/document-root.js +118 -0
  42. package/src/lib/components/document-root.js.map +1 -0
  43. package/src/lib/components/drawer.d.ts +93 -0
  44. package/src/lib/components/drawer.js +566 -0
  45. package/src/lib/components/drawer.js.map +1 -0
  46. package/src/lib/components/function-controls.d.ts +66 -0
  47. package/src/lib/components/function-controls.js +207 -0
  48. package/src/lib/components/function-controls.js.map +1 -0
  49. package/src/lib/components/function-scope.d.ts +110 -0
  50. package/src/lib/components/function-scope.js +478 -0
  51. package/src/lib/components/function-scope.js.map +1 -0
  52. package/src/lib/components/function-widget.d.ts +75 -0
  53. package/src/lib/components/function-widget.js +307 -0
  54. package/src/lib/components/function-widget.js.map +1 -0
  55. package/src/lib/components/grid.d.ts +91 -0
  56. package/src/lib/components/grid.js +322 -0
  57. package/src/lib/components/grid.js.map +1 -0
  58. package/src/lib/components/icon.d.ts +54 -0
  59. package/src/lib/components/icon.js +163 -0
  60. package/src/lib/components/icon.js.map +1 -0
  61. package/src/lib/components/image-list.d.ts +58 -0
  62. package/src/lib/components/image-list.js +336 -0
  63. package/src/lib/components/image-list.js.map +1 -0
  64. package/src/lib/components/image.d.ts +154 -0
  65. package/src/lib/components/image.js +451 -0
  66. package/src/lib/components/image.js.map +1 -0
  67. package/src/lib/components/inline-text.d.ts +74 -0
  68. package/src/lib/components/inline-text.js +407 -0
  69. package/src/lib/components/inline-text.js.map +1 -0
  70. package/src/lib/components/language-switcher.d.ts +35 -0
  71. package/src/lib/components/language-switcher.js +179 -0
  72. package/src/lib/components/language-switcher.js.map +1 -0
  73. package/src/lib/components/layout-slot.d.ts +68 -0
  74. package/src/lib/components/layout-slot.js +192 -0
  75. package/src/lib/components/layout-slot.js.map +1 -0
  76. package/src/lib/components/link-box-accessible-name.d.ts +79 -0
  77. package/src/lib/components/link-box-accessible-name.js +158 -0
  78. package/src/lib/components/link-box-accessible-name.js.map +1 -0
  79. package/src/lib/components/link-box.d.ts +66 -0
  80. package/src/lib/components/link-box.js +212 -0
  81. package/src/lib/components/link-box.js.map +1 -0
  82. package/src/lib/components/list-item-text.d.ts +22 -0
  83. package/src/lib/components/list-item-text.js +86 -0
  84. package/src/lib/components/list-item-text.js.map +1 -0
  85. package/src/lib/components/list-item.d.ts +32 -0
  86. package/src/lib/components/list-item.js +127 -0
  87. package/src/lib/components/list-item.js.map +1 -0
  88. package/src/lib/components/list.d.ts +34 -0
  89. package/src/lib/components/list.js +108 -0
  90. package/src/lib/components/list.js.map +1 -0
  91. package/src/lib/components/markdown.d.ts +129 -0
  92. package/src/lib/components/markdown.js +853 -0
  93. package/src/lib/components/markdown.js.map +1 -0
  94. package/src/lib/components/nav-menu.d.ts +68 -0
  95. package/src/lib/components/nav-menu.js +683 -0
  96. package/src/lib/components/nav-menu.js.map +1 -0
  97. package/src/lib/components/pagination.d.ts +59 -0
  98. package/src/lib/components/pagination.js +243 -0
  99. package/src/lib/components/pagination.js.map +1 -0
  100. package/src/lib/components/paper.d.ts +47 -0
  101. package/src/lib/components/paper.js +202 -0
  102. package/src/lib/components/paper.js.map +1 -0
  103. package/src/lib/components/plugin-frame.d.ts +64 -0
  104. package/src/lib/components/plugin-frame.js +335 -0
  105. package/src/lib/components/plugin-frame.js.map +1 -0
  106. package/src/lib/components/plugin.d.ts +95 -0
  107. package/src/lib/components/plugin.js +304 -0
  108. package/src/lib/components/plugin.js.map +1 -0
  109. package/src/lib/components/product.d.ts +40 -0
  110. package/src/lib/components/product.js +287 -0
  111. package/src/lib/components/product.js.map +1 -0
  112. package/src/lib/components/reusable-instance.d.ts +57 -0
  113. package/src/lib/components/reusable-instance.js +126 -0
  114. package/src/lib/components/reusable-instance.js.map +1 -0
  115. package/src/lib/components/screen-link.d.ts +85 -0
  116. package/src/lib/components/screen-link.js +324 -0
  117. package/src/lib/components/screen-link.js.map +1 -0
  118. package/src/lib/components/search-box.d.ts +41 -0
  119. package/src/lib/components/search-box.js +125 -0
  120. package/src/lib/components/search-box.js.map +1 -0
  121. package/src/lib/components/section.d.ts +56 -0
  122. package/src/lib/components/section.js +132 -0
  123. package/src/lib/components/section.js.map +1 -0
  124. package/src/lib/components/stack.d.ts +55 -0
  125. package/src/lib/components/stack.js +309 -0
  126. package/src/lib/components/stack.js.map +1 -0
  127. package/src/lib/components/tabs.d.ts +288 -0
  128. package/src/lib/components/tabs.js +788 -0
  129. package/src/lib/components/tabs.js.map +1 -0
  130. package/src/lib/components/theme-mode-switcher.d.ts +38 -0
  131. package/src/lib/components/theme-mode-switcher.js +168 -0
  132. package/src/lib/components/theme-mode-switcher.js.map +1 -0
  133. package/src/lib/components/toolbar.d.ts +37 -0
  134. package/src/lib/components/toolbar.js +117 -0
  135. package/src/lib/components/toolbar.js.map +1 -0
  136. package/src/lib/components/typography.d.ts +33 -0
  137. package/src/lib/components/typography.js +433 -0
  138. package/src/lib/components/typography.js.map +1 -0
  139. package/src/lib/components/video-lightbox-controls.d.ts +131 -0
  140. package/src/lib/components/video-lightbox-controls.js +536 -0
  141. package/src/lib/components/video-lightbox-controls.js.map +1 -0
  142. package/src/lib/components/video-lightbox.d.ts +60 -0
  143. package/src/lib/components/video-lightbox.js +247 -0
  144. package/src/lib/components/video-lightbox.js.map +1 -0
  145. package/src/lib/components/video-playback-beacon.d.ts +80 -0
  146. package/src/lib/components/video-playback-beacon.js +128 -0
  147. package/src/lib/components/video-playback-beacon.js.map +1 -0
  148. package/src/lib/components/video-player-frame.d.ts +58 -0
  149. package/src/lib/components/video-player-frame.js +51 -0
  150. package/src/lib/components/video-player-frame.js.map +1 -0
  151. package/src/lib/components/video.d.ts +220 -0
  152. package/src/lib/components/video.js +874 -0
  153. package/src/lib/components/video.js.map +1 -0
  154. package/src/lib/constants/bundle-common.d.ts +17 -0
  155. package/src/lib/constants/bundle-common.js +18 -0
  156. package/src/lib/constants/bundle-common.js.map +1 -0
  157. package/src/lib/constants/field-presets.d.ts +93 -0
  158. package/src/lib/constants/field-presets.js +248 -0
  159. package/src/lib/constants/field-presets.js.map +1 -0
  160. package/src/lib/plugin.d.ts +80 -0
  161. package/src/lib/plugin.js +599 -0
  162. package/src/lib/plugin.js.map +1 -0
  163. package/src/lib/utils/author-html-label.d.ts +73 -0
  164. package/src/lib/utils/author-html-label.js +89 -0
  165. package/src/lib/utils/author-html-label.js.map +1 -0
  166. package/src/lib/utils/drop-cleared-props.d.ts +18 -0
  167. package/src/lib/utils/drop-cleared-props.js +74 -0
  168. package/src/lib/utils/drop-cleared-props.js.map +1 -0
  169. package/src/lib/utils/element-picker.d.ts +99 -0
  170. package/src/lib/utils/element-picker.js +140 -0
  171. package/src/lib/utils/element-picker.js.map +1 -0
  172. package/src/lib/utils/generate-preset-id.d.ts +19 -0
  173. package/src/lib/utils/generate-preset-id.js +25 -0
  174. package/src/lib/utils/generate-preset-id.js.map +1 -0
  175. package/src/lib/utils/link-target-props.d.ts +53 -0
  176. package/src/lib/utils/link-target-props.js +53 -0
  177. package/src/lib/utils/link-target-props.js.map +1 -0
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../../../../../libs/plugins/mui/src/lib/components/tabs.tsx"],"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 * as Aglyn from '@aglyn/aglyn'\nimport { mdiTab, mdiViewCarousel } from '@aglyn/shared-data-mdi'\nimport { AppLink } from '@aglyn/shared-ui-jsx'\nimport Box from '@mui/material/Box'\nimport MuiTab from '@mui/material/Tab'\nimport MuiTabs from '@mui/material/Tabs'\nimport Typography from '@mui/material/Typography'\nimport type { SxProps } from '@mui/material/styles'\nimport {\n createContext,\n forwardRef,\n type ReactNode,\n useContext,\n useState,\n} from 'react'\nimport { BUNDLE_ID } from '../constants/bundle-common'\nimport { dropClearedProps } from '../utils/drop-cleared-props'\nimport { generatePresetId } from '../utils/generate-preset-id'\n\n// Component ids are persisted in screen documents; never rename.\nexport const TABS_ID: Aglyn.ComponentId = 'muiTabs'\nexport const TAB_PANEL_ID: Aglyn.ComponentId = 'muiTabPanel'\n\n/**\n * How many tabs in a strip can carry a screen link (AGL-1312). The strip is\n * authored as a free-form label list, so the links have to be flat props —\n * one per position — and a flat prop needs a name that exists up front.\n *\n * Eight is well past any usable navigation row (the marketing content-tabs\n * row is three) and costs nothing at render: the attributes panel only shows\n * a link picker for a tab that actually exists, so a two-tab strip shows two.\n */\nexport const TAB_LINK_SLOTS = 8\n\n/** Prop name carrying the link of the 1-based `position`-th tab. */\nexport function tabLinkProp(position: number): string {\n return `tabLink${position}`\n}\n\n/**\n * The per-tab screen links, `tabLink1`…`tabLink8`. Declared as a mapped type\n * rather than an index signature: an index signature on the props interface\n * would force `sx`, `children` and the rest to conform to it.\n */\nexport type TabLinkProps = Partial<\n Record<\n | 'tabLink1'\n | 'tabLink2'\n | 'tabLink3'\n | 'tabLink4'\n | 'tabLink5'\n | 'tabLink6'\n | 'tabLink7'\n | 'tabLink8',\n string\n >\n>\n\nexport interface TabsElementProps extends TabLinkProps {\n /** Tab labels, one per line (commas also accepted). */\n labels?: string\n /**\n * The LABEL of the tab the strip opens on (AGL-3164). Unset opens the\n * first tab, which is what every Tabs already in the wild does.\n *\n * A label rather than a position, because a position is a silent lie the\n * moment the list is edited: it keeps pointing at \"the second tab\" after\n * the author reorders or renames, and nothing on screen says the wrong\n * panel is now the one that opens. A label that no longer exists simply\n * does not match, and the strip falls back to the first tab.\n *\n * See {@link openingTabIndex} for the whole rule, and `deferLazyPanelNodes`\n * in tenant-runtime for the server side of it — the two must agree or the\n * page ships the wrong panel's markup.\n */\n opensOn?: string\n /** Accessible name of the strip; also names the nav landmark in link mode. */\n ariaLabel?: string\n orientation?: 'horizontal' | 'vertical'\n variant?: 'standard' | 'scrollable' | 'fullWidth'\n /** Centres a standard strip; MUI ignores it when scrollable. */\n centered?: boolean\n textColor?: 'primary' | 'secondary' | 'inherit'\n indicatorColor?: 'primary' | 'secondary'\n /**\n * Render every panel into the SSR output up front instead of building each\n * panel the first time its tab is opened (AGL-1283 option 3).\n *\n * Mount-on-first-selection is the DEFAULT: `/pricing` shipped eight copies\n * of a 50-row table so desktop visitors could see none of them, and any\n * large tab set pays the same tax silently. The trade is that an unopened\n * panel's content is then not in the page source — not indexable, not\n * findable — so this switch exists for the panels where that matters:\n * content that appears nowhere else on the page and must reach crawlers.\n */\n ssrPanels?: boolean\n /**\n * Legacy opt-in from when eager panels were the default (AGL-1283).\n * Lazy mounting is now the default, so this is accepted from existing\n * documents but no longer consulted — `ssrPanels` is the one switch.\n * Still destructured so an authored value never leaks onto the DOM.\n */\n lazyPanels?: boolean\n /**\n * Authored node styles, handed over by the renderer rather than typed into\n * an attribute — the merge below reads it, so it belongs on the public\n * interface. Leaving it undeclared (AGL-1284 added the reads, not the\n * declaration) meant no typed caller could pass one, including the specs\n * that exist to prove an authored `sx` survives (AGL-1323).\n */\n sx?: SxProps\n children?: ReactNode\n}\n\nexport interface TabPanelElementProps {\n /** Which tab reveals this panel; must match one of the Tabs labels. */\n label?: string\n /**\n * Set by the server when this panel's children were withheld from the page\n * payload (AGL-1285, `deferLazyPanelNodes`) — never authored, and there is\n * deliberately no attribute for it.\n *\n * It must be destructured off the prop bag either way: everything else on\n * this element is spread straight onto a `Box`, so leaving it in produced a\n * React \"does not recognize the prop\" warning for every deferred panel.\n *\n * It also drives the loading state. A withheld panel that the reader has\n * just opened has no children yet and is indistinguishable from a panel that\n * is genuinely empty, and the fetch behind it is a full server compose —\n * 3.8s cold when measured. This flag is what lets the panel say so.\n *\n * It clears itself: the patch from `/api/screen/nodes` carries the ORIGINAL\n * panel nodes, which never had the marker, so the moment the real children\n * arrive this is gone and the placeholder with it (AGL-1287).\n */\n aglynDeferred?: boolean\n /** Authored node styles, merged over the panel's own — see Tabs' `sx`. */\n sx?: SxProps\n children?: ReactNode\n}\n\n/**\n * Splits the authored label list. Newline-separated is the documented\n * form; commas are accepted because a one-line \"A, B, C\" is what people\n * type first.\n */\nexport function parseLabels(value: unknown): string[] {\n if (value == null) return []\n return String(value)\n .split(/[\\n,]/)\n .map((label) => label.trim())\n .filter(Boolean)\n}\n\n/** Stable DOM id fragment for the tab ⇄ panel aria wiring. */\nexport function labelSlug(label: string): string {\n return (\n label\n .toLowerCase()\n .replace(/[^a-z0-9]+/g, '-')\n .replace(/^-|-$/g, '') || 'tab'\n )\n}\n\n/** Case/whitespace-insensitive: authors don't retype labels exactly. */\nexport function labelsMatch(a: unknown, b: unknown): boolean {\n return (\n String(a ?? '').trim().toLowerCase() ===\n String(b ?? '').trim().toLowerCase()\n )\n}\n\n/**\n * Which tab the strip opens on, by index into the parsed label list.\n *\n * Two rules, in order:\n *\n * 1. the tab the author NAMED in `opensOn` (AGL-3164), matched by label with\n * the same case/whitespace tolerance panels are matched with;\n * 2. otherwise the landing tab — the first one WITHOUT a screen link, which\n * is how a navigation row says \"this is the page you are on\" (AGL-1312),\n * and which is tab 0 on a strip with no links at all, i.e. exactly what\n * this element did before the attribute existed.\n *\n * The named tab is refused when it carries a screen link: a linked tab\n * navigates instead of revealing a panel (AGL-1312), so it is not a tab the\n * strip can rest on, and opening on it would show the indicator over a panel\n * nobody can see. It falls back rather than rendering nothing.\n *\n * Never returns -1. `landing` is -1 when EVERY tab navigates — the strip\n * shows no indicator there, but callers still read a label with this index.\n */\nexport function openingTabIndex(\n labels: readonly string[],\n opensOn?: unknown,\n linkIds: readonly (string | undefined)[] = [],\n): number {\n const named = labels.findIndex(\n (label, index) => !linkIds[index] && labelsMatch(label, opensOn),\n )\n if (named >= 0) return named\n const landing = labels.findIndex((_label, index) => !linkIds[index])\n return landing < 0 ? 0 : landing\n}\n\ninterface TabsContextValue {\n activeLabel: string\n /** True on the besigner canvas, where every panel is shown at once. */\n showAll: boolean\n /** Panels render nothing until first selected (AGL-1283). */\n lazyPanels: boolean\n /** Labels opened at least once — a lazily mounted panel stays mounted. */\n opened: ReadonlySet<string>\n /**\n * True when at least one tab carries a screen link (AGL-1312), which makes\n * the whole row navigation rather than a tab list — see the a11y note on\n * `TabsElement`. Panels drop `role=\"tabpanel\"` in that mode: a tabpanel\n * with no tablist to belong to is orphaned ARIA.\n */\n navMode: boolean\n}\n\nexport const TabsContext = createContext<TabsContextValue | undefined>(\n undefined,\n)\n\n/**\n * Tabs (https://mui.com/material-ui/react-tabs/).\n *\n * The strip is authored on the container as a label list, and each Tab\n * Panel child names the label it belongs to. It does **not** slice its\n * React children by index: the node renderer hands every component a\n * single `Branch` fragment rather than one element per child node\n * (`libs/aglyn-node-renderer`), so an index-based split would silently\n * put all the content behind the first tab. Matching by label also\n * survives reordering panels in the hierarchy.\n *\n * The strip renders from the author's own list, so it is complete in the\n * SSR output — no registration pass, no empty-then-filled flash, and it\n * still reads as a tab list with JavaScript disabled.\n *\n * ## Link mode (AGL-1312)\n *\n * Any tab may carry a screen link (`tabLink1`…`tabLink8`, by position). A\n * tab that has one renders as a real anchor — navigable, crawlable,\n * middle-clickable — because the row it exists for (Blog | Changelog |\n * Newsroom) is navigation ACROSS screens, which a panel switcher can only\n * fake with empty panels or a hand-styled row of buttons. The anchor is an\n * `AppLink`, never a bare `href`: a raw href full-reloads the SPA.\n *\n * A tab WITHOUT a link keeps today's behavior exactly, and mixed rows work\n * — the marketing pattern IS a mixed row, since the tab for the page you\n * are already on must not link to itself. That unlinked tab is also how the\n * author says which page this copy of the row is on: the strip lands on it,\n * so the same three-tab row placed on three screens shows the indicator in\n * the right place on each, with no \"selected tab\" attribute to keep in sync\n * — `opensOn` below is for panel rows and gives way to this one.\n *\n * ## Which tab opens (AGL-3164)\n *\n * `opensOn` names it, by LABEL. Unset opens the first tab, which is what\n * every Tabs authored before the attribute existed does; a label that no\n * longer matches opens the first tab too, rather than nothing. The rule\n * lives in {@link openingTabIndex} and is mirrored server-side by\n * `deferLazyPanelNodes` (tenant-runtime), which decides which panel's nodes\n * reach the page at all — so the tab that opens is the one that was\n * rendered, and the page does not paint one panel and swap to another.\n *\n * **Accessibility.** The row is a `tablist` only while NOTHING in it\n * navigates. As soon as one tab carries a link the whole strip is marked up\n * as navigation: a `nav` landmark, no `role=\"tab\"`, no `aria-selected`, and\n * no roving tab stop (every link is its own tab stop, as in any nav). The\n * alternative — an `<a href>` wearing `role=\"tab\"` — tells assistive tech\n * the activation will reveal a panel when it actually loads a page, and a\n * tablist whose children are not tabs is invalid either way. The tab for\n * the current screen is marked `aria-current=\"page\"`; tabs that still\n * switch panels stay buttons and keep their `aria-controls`, which is an\n * accurate disclosure relationship on its own. The half-applied version of\n * this — links inside a tablist, or panels still claiming `role=\"tabpanel\"`\n * with no tablist above them — is what this deliberately avoids.\n */\nconst TabsElement = forwardRef<HTMLDivElement, TabsElementProps>(\n (rawProps, ref) => {\n // Cleared props dropped up front (AGL-1451). The four selects below\n // already coalesce their own value, but `rest` is spread onto the root\n // and the per-tab link props are read out of it, so a `null` from the\n // field's ✕ (AGL-1226) must not survive this far.\n const props = dropClearedProps(rawProps)\n const {\n labels,\n ariaLabel,\n orientation,\n variant,\n centered,\n textColor,\n indicatorColor,\n ssrPanels,\n lazyPanels,\n opensOn,\n children,\n ...rest\n } = props\n const { editorInert, suppressNavigation } = Aglyn.useScreenLink(undefined)\n // Read the routing map directly rather than calling `useScreenLink` per\n // tab: the number of tabs changes with the label list, and a hook per\n // list item is a rules-of-hooks violation waiting for the author to add\n // a fourth tab.\n const { screens } = useContext(Aglyn.ScreenLinkContext)\n // Screen ids by tab position, lifted out of `rest` so they can never\n // reach the DOM as unknown attributes (the nav-menu does the same with\n // its legacy trigger prop).\n const linkIds: (string | undefined)[] = []\n for (let slot = 1; slot <= TAB_LINK_SLOTS; slot += 1) {\n const key = tabLinkProp(slot)\n const value = (rest as Record<string, unknown>)[key]\n linkIds.push(typeof value === 'string' && value ? value : undefined)\n delete (rest as Record<string, unknown>)[key]\n }\n const parsed = parseLabels(labels)\n // Authored links decide the mode, NOT resolved hrefs: the canvas and\n // preview suppress navigation, and they must still show the element the\n // page will actually ship (the same rule Screen Link follows).\n const navMode = parsed.some((_label, index) => !!linkIds[index])\n /**\n * The tab a navigation row LANDS on is the one with no link: the row is\n * placed on every screen it names, and on each of those the tab for that\n * screen is left unlinked, because a page that links to itself helps\n * nobody. So \"first tab with no link\" is how the author says \"this is\n * the page you are on\" — without a second attribute, and without this\n * element having to know the current route.\n *\n * `-1` means every tab navigates: nothing is current, and the strip\n * shows no indicator rather than inventing one under the first tab.\n * With no links at all this is 0, i.e. exactly today's behavior.\n */\n const landing = parsed.findIndex((_label, index) => !linkIds[index])\n // Which tab this strip opens on (AGL-3164): the one the author named,\n // and otherwise `landing` — so an unset attribute, or one naming a label\n // that has since been renamed away, behaves exactly as it always did.\n const opening = openingTabIndex(parsed, opensOn, linkIds)\n const [active, setActive] = useState(opening)\n // Once a lazy panel has been opened it stays mounted: re-tabbing between\n // two plans should not re-render 50 rows each time, and anything the\n // reader typed or scrolled inside a panel survives a round trip.\n //\n // Seeded with the OPENING label, because that panel is open from the\n // start without anyone clicking it. Leaving it out unmounted the opening\n // panel the moment the reader moved away — visibly inconsistent with\n // every other panel they had visited, and caught by the round-trip test.\n const [opened, setOpened] = useState<ReadonlySet<string>>(() => {\n const first = parsed[opening]\n return new Set<string>(first === undefined ? [] : [first])\n })\n // A label removed from the list must not leave the strip pointing at\n // a tab that no longer exists — MUI warns and drops the indicator.\n //\n // On the besigner canvas the authored attribute is read every render\n // instead of the state seeded at mount: `onChange` is inert there, so\n // nothing else can have moved the selection, and a canvas that kept\n // showing the tab that was open when the element mounted would make\n // \"Opens on\" look like it had done nothing.\n const chosen = editorInert ? opening : active < parsed.length ? active : 0\n // A tab that navigates is never the selected one; if the author has just\n // given the open tab a link, fall back to one that still has a panel.\n const activeIndex = linkIds[chosen] && landing >= 0 ? landing : chosen\n const resolvedVariant = variant || 'standard'\n const vertical = orientation === 'vertical'\n const stripLabel = ariaLabel || 'Tabs'\n\n const strip = (\n <MuiTabs\n // No indicator when every tab navigates: there is no selection to\n // show, and marking one anyway would point at the wrong page.\n value={parsed.length && landing >= 0 ? activeIndex : false}\n onChange={\n editorInert\n ? undefined\n : (_event, next: number) => {\n // A navigating tab must not move the selection on its way\n // out: the indicator would jump to a tab whose panel is\n // empty while the next page is still loading.\n if (linkIds[next]) return\n setActive(next)\n const label = parsed[next]\n if (label !== undefined) {\n setOpened((prev) =>\n prev.has(label) ? prev : new Set(prev).add(label),\n )\n }\n }\n }\n orientation={vertical ? 'vertical' : 'horizontal'}\n variant={resolvedVariant}\n // MUI ignores `centered` on a scrollable strip and warns in dev.\n centered={resolvedVariant === 'standard' ? !!centered : undefined}\n textColor={textColor || 'primary'}\n indicatorColor={indicatorColor || 'primary'}\n // Link mode is navigation, so the root becomes the `nav` landmark\n // and the inner flex row gives up `role=\"tablist\"`. The accessible\n // name moves with it: MUI puts `aria-label` on the list, which in\n // this mode is a plain div and cannot carry the landmark's name.\n {...(navMode\n ? {\n component: 'nav',\n slotProps: {\n root: { 'aria-label': stripLabel },\n list: { role: undefined },\n },\n }\n : { 'aria-label': stripLabel })}\n >\n {parsed.map((label, index) => {\n const slug = labelSlug(label)\n const key = `${slug}-${index}`\n if (!navMode) {\n return (\n <MuiTab\n key={key}\n label={label}\n id={`tab-${slug}`}\n aria-controls={`tabpanel-${slug}`}\n />\n )\n }\n // Suppressed navigation (canvas, preview) keeps the item in the\n // row but without an href, so a click cannot leave the editor.\n const href = suppressNavigation\n ? undefined\n : Aglyn.resolveScreenHref(screens, linkIds[index])\n // An authored target that the routing map does not have: the\n // screen was unpublished or deleted out from under this row\n // (AGL-1893). Computed from the MAP, never from `href`, so a\n // canvas or preview render — where nothing has an href on purpose\n // — does not paint every working link as dead.\n const broken = Aglyn.isScreenLinkBroken(screens, linkIds[index])\n return (\n <MuiTab\n key={key}\n label={label}\n id={`tab-${slug}`}\n // Only a tab that still reveals a panel controls anything.\n aria-controls={linkIds[index] ? undefined : `tabpanel-${slug}`}\n {...(href\n ? { component: AppLink, componentVariant: 'naked', href }\n : null)}\n /**\n * A tab whose screen is gone stops being a control (AGL-1893).\n *\n * It used to render as a bare `<button>` indistinguishable\n * from its working neighbours: no href, no `aria-controls`,\n * and `onChange` returns early on it because the AUTHORED id\n * is still there — so it looked live, announced live, and did\n * nothing at all. Live on `/changelog` and `/newsroom` for two\n * days without anything anywhere saying so.\n *\n * Disabled rather than hidden, on purpose:\n *\n * - the routing map differs between the render that produced\n * an ISR page and the render that hydrates it, and AGL-1268\n * settled that a node's ELEMENT must not depend on it —\n * removing the tab would make the strip's DOM shape depend\n * on it, which is strictly worse than an attribute;\n * - `MuiTabs` addresses its children by index, so dropping one\n * silently repoints `value` at the wrong tab;\n * - the failure directions are not symmetric. A wrongly\n * disabled tab is a dimmed label; a wrongly hidden one is\n * navigation that vanished from a customer's site with no\n * trace of why.\n *\n * Falling through to panel behaviour instead — the other\n * option AGL-1893 weighed — is not available to this element:\n * the node renderer hands it ONE `Branch` fragment rather than\n * per-panel children, so a Tabs container cannot know whether\n * a panel with this label exists, and on the real `/changelog`\n * shape it does not.\n *\n * `landing`, `opening`, `activeIndex`, `aria-controls` and the\n * `onChange` guard all still read the AUTHORED id, unchanged.\n * They must: `deferLazyPanelNodes` computes the opening label\n * server-side from the raw `tabLink{n}` props and has no\n * routing map to resolve ids with, so a client that resolved\n * differently would keep a panel the server withheld.\n */\n disabled={broken && !editorInert ? true : undefined}\n // On the canvas the tab stays live: the author has to be able\n // to select the node to repair it. It carries the ring and the\n // explanation instead.\n {...Aglyn.brokenScreenLinkProps(broken, !!editorInert)}\n sx={\n broken && editorInert\n ? Aglyn.BROKEN_SCREEN_LINK_SX\n : undefined\n }\n // MUI writes these before spreading the rest, so passing them\n // undefined is what removes them (see the a11y note above).\n role={undefined}\n aria-selected={undefined}\n aria-current={\n landing >= 0 && index === activeIndex ? 'page' : undefined\n }\n // Undo the roving tab stop: in a nav every item is reachable\n // with Tab, and MUI's arrow-key handler already stands down\n // because it only moves between `role=\"tab\"` siblings.\n tabIndex={undefined}\n />\n )\n })}\n </MuiTabs>\n )\n\n return (\n <TabsContext.Provider\n value={{\n activeLabel: parsed[activeIndex] ?? '',\n // Every panel at once on the canvas: a hidden panel cannot be\n // selected or styled, the same reason Accordion force-expands.\n showAll: !!editorInert,\n // Lazy is the default (AGL-1283 option 3); `ssrPanels` is the SEO\n // escape hatch. The legacy `lazyPanels` opt-in is subsumed: `true`\n // now means what the default means, and a stored `false` was only\n // ever the old default, never an author's intent.\n lazyPanels: !ssrPanels,\n opened,\n navMode,\n }}\n >\n <Box\n ref={ref}\n {...rest}\n // MERGE, never replace. `sx` written after `{...rest}` silently\n // discarded whatever the author set on the node — every Tabs on\n // every site rendered with default MUI styling and no way to\n // change it, with nothing in the editor to suggest the value had\n // been dropped (AGL-1284). Vertical orientation still needs the\n // flex row, so it goes first and the author can override it.\n sx={[\n { display: vertical ? 'flex' : undefined },\n ...(Array.isArray(rest.sx) ? rest.sx : [rest.sx]),\n ]}\n >\n {strip}\n {children}\n </Box>\n </TabsContext.Provider>\n )\n },\n)\nTabsElement.displayName = 'AglynTabs'\n\n/**\n * One tab's content. Outside a Tabs container it renders plainly rather\n * than disappearing — a panel dragged out of its tabs would otherwise\n * vanish from the canvas with no explanation.\n */\nexport const TabPanelElement = forwardRef<\n HTMLDivElement,\n TabPanelElementProps\n>((props, ref) => {\n const { label, aglynDeferred, children, ...rest } = props\n const context = useContext(TabsContext)\n const selected = !context || labelsMatch(label, context.activeLabel)\n const visible = selected || !!context?.showAll\n /**\n * With `lazyPanels`, an unopened panel renders its wrapper but not its\n * children — the wrapper stays so the `aria-controls` target and the\n * tab ⇄ panel wiring still resolve, and so nothing about the accessible\n * structure depends on whether the reader has clicked yet.\n *\n * `opened` is checked as well as `selected` because a panel that has been\n * visited stays mounted; only the never-opened ones are skipped.\n */\n const mounted =\n !context ||\n !context.lazyPanels ||\n context.showAll ||\n selected ||\n context.opened.has(String(label ?? ''))\n\n /**\n * In link mode the strip is a nav, not a tablist (AGL-1312), so a panel\n * has no tablist to belong to and drops the tab-pattern ARIA rather than\n * claiming half of it. The id stays — the button that still reveals this\n * panel points `aria-controls` at it, which is a valid relationship on\n * its own — and an orphan panel (dragged out of its Tabs, no context)\n * keeps today's markup untouched.\n */\n const navMode = !!context?.navMode\n\n return (\n <Box\n ref={ref}\n role={navMode ? undefined : 'tabpanel'}\n hidden={!visible}\n id={`tabpanel-${labelSlug(String(label ?? ''))}`}\n aria-labelledby={\n navMode ? undefined : `tab-${labelSlug(String(label ?? ''))}`\n }\n {...rest}\n // Same merge bug as the Tabs container (AGL-1284): the author's `sx`\n // was dropped, so a panel could not even have its padding changed.\n // Order matters — the default padding is first so the author can\n // override it, and the hide rule is LAST so an authored `display`\n // can never force a deselected panel back on screen.\n sx={[\n { p: 2 },\n ...(Array.isArray(rest.sx) ? rest.sx : [rest.sx]),\n ...(visible ? [] : [{ display: 'none' }]),\n ]}\n >\n {context?.showAll && !selected ? (\n // Canvas only: says which tab this content belongs to, so a\n // stack of panels is readable and a label typo is obvious.\n <Typography\n variant=\"caption\"\n color=\"text.secondary\"\n sx={{ display: 'block', mb: 0.5 }}\n >\n {label ? `Tab: ${label}` : 'Tab: (no label set)'}\n </Typography>\n ) : null}\n {mounted ? (\n aglynDeferred && visible ? (\n // Opened, but its nodes are still in flight (AGL-1287). Only while\n // VISIBLE — a deferred panel nobody has opened must stay silent, or\n // every unopened tab would render a spinner into the page.\n //\n // Deliberately not a skeleton of the content: a withheld subtree can\n // be a 50-row table or a paragraph, and this component has no way to\n // know which, so a shaped skeleton would be a guess that flashes\n // wrong. `role=\"status\"` announces it to a screen reader, which\n // otherwise gets a panel that is silently empty for seconds.\n <Typography\n role=\"status\"\n variant=\"body2\"\n color=\"text.secondary\"\n sx={{ display: 'block', py: 2 }}\n >\n {'Loading…'}\n </Typography>\n ) : (\n children\n )\n ) : null}\n </Box>\n )\n})\nTabPanelElement.displayName = 'AglynTabPanel'\n\n/** `centered` is a standard-strip-only prop; MUI warns when scrollable. */\nconst STANDARD_ONLY = { when: 'variant', is: 'scrollable', notMatch: true }\n\n/**\n * Shows a per-tab link picker only once the label list has that many tabs,\n * so a three-tab strip offers three pickers rather than eight.\n *\n * Expressed as a serialisable `pattern` rather than an `is` predicate:\n * conditions travel with the component schema, and a function in there is a\n * live grenade the day a schema is cloned or sent across a boundary. An\n * \"item\" is a run without a separator that holds something visible, and a\n * separator run swallows blank lines, so it counts exactly what\n * `parseLabels` counts.\n */\nexport function atLeastLabels(count: number): Record<string, unknown> {\n if (count <= 1) return { when: 'labels', isNotEmpty: true }\n const item = '[^\\\\n,]*\\\\S[^\\\\n,]*'\n const separator = '[\\\\n,][\\\\s,]*'\n return {\n when: 'labels',\n pattern: `(?:${item}${separator}){${count - 1}}${item}`,\n }\n}\n\n/**\n * The \"Opens on\" field's `resolveProps`: its answers are the element's OWN\n * tab labels, read from the sibling `labels` field as they are typed\n * (AGL-3164).\n *\n * A picker rather than a typed index or a typed label. An index goes on\n * meaning \"the second tab\" after a reorder, with nothing on screen to say\n * the wrong panel now opens; a typed label breaks on a rename and on every\n * typo in between. Choosing from the list the author has just written is the\n * only form of this control someone who does not write code can get right,\n * which is the whole reason it exists instead of the tabs being reordered by\n * hand to obtain a behavior.\n *\n * The answers follow the label list as it is edited because the field's\n * `condition` names `labels`: data-driven-forms subscribes a conditional\n * field to its condition's trigger fields, and that subscription is what\n * re-runs this.\n *\n * A stored label the list no longer holds is offered back as its own option,\n * named as gone. The element itself already falls back to the first tab, so\n * the page is never broken by one; but a picker that rendered BLANK would\n * read as \"not set\", and the author would never learn that the choice they\n * made has stopped being honoured — the same reason a Screen picker names a\n * target the host no longer has (AGL-1893).\n */\nexport function opensOnFieldProps(\n _props: unknown,\n field: { input?: { value?: unknown } },\n formOptions?: {\n getFieldState?: (name: string) => { value?: unknown } | undefined\n getState?: () => { values?: Record<string, unknown> } | undefined\n },\n): { options: { value: string; label: string }[] } {\n // The registered field first, the form's values as the fallback: a field\n // that has not registered yet has no state, and the values are there from\n // the first render.\n const authored =\n formOptions?.getFieldState?.('labels')?.value ??\n formOptions?.getState?.()?.values?.['labels']\n const options = parseLabels(authored).map((label) => ({\n value: label,\n label,\n }))\n const stored = field?.input?.value\n if (\n typeof stored === 'string' &&\n stored.trim() &&\n !options.some((option) => labelsMatch(option.value, stored))\n ) {\n options.push({ value: stored, label: `${stored} (no longer a tab)` })\n }\n return { options }\n}\n\n/** \"1st\", \"2nd\", \"3rd\", … for the link fields' own descriptions. */\nfunction ordinal(position: number): string {\n const suffix =\n position % 10 === 1 && position !== 11\n ? 'st'\n : position % 10 === 2 && position !== 12\n ? 'nd'\n : position % 10 === 3 && position !== 13\n ? 'rd'\n : 'th'\n return `${position}${suffix}`\n}\n\n/**\n * One Screen picker per tab position (AGL-1312), the same field the Screen\n * Link element uses — so a tab's target is chosen from the host's screens\n * and survives a slug rename, and the attributes panel needs no new UI.\n *\n * Deliberately NOT paired with a \"link mode\" switch: a mode select would\n * need its default to persist, and an `''` option value cannot (AGL-1191 —\n * the form strips it before save). Carrying a link IS the mode, per tab,\n * which is also what makes a mixed row expressible at all.\n */\nconst TAB_LINK_FIELDS: Aglyn.AglynAttributeSchema[] = Array.from(\n { length: TAB_LINK_SLOTS },\n (_unused, index) => {\n const position = index + 1\n return {\n name: tabLinkProp(position),\n label: `Tab ${position} link`,\n description:\n `Screen the ${ordinal(position)} tab navigates to. A tab with a ` +\n 'link is a real link — it can be opened in a new tab and search ' +\n 'engines follow it — and it no longer switches panels. Leave it ' +\n 'unset for a tab that just reveals its own panel, including the ' +\n 'tab for the page this row is already on.',\n component: Aglyn.FieldComponentType.SCREEN_SELECT,\n condition: atLeastLabels(position),\n }\n },\n)\n\nexport const tabsSchema: Aglyn.ComponentSchema<TabsElementProps> = {\n $id: TABS_ID,\n pluginId: BUNDLE_ID,\n displayName: 'Tabs',\n description:\n 'Tab strip whose Tab Panel children each name the tab that reveals ' +\n 'them.',\n category: Aglyn.ComponentCategory.NAVIGATION,\n icon: { path: mdiTab.path, sx: { color: '#2196f3' } },\n restrictChildren: [\n Aglyn.LinealDirectiveFlag.LIMIT_TO,\n { components: [TAB_PANEL_ID] },\n ],\n attributes: [\n {\n name: 'labels',\n label: 'Tabs',\n description:\n 'One tab label per line. Each Tab Panel below shows under the ' +\n 'tab whose label it names.',\n component: Aglyn.FieldComponentType.TEXTAREA,\n },\n ...TAB_LINK_FIELDS,\n {\n name: 'opensOn',\n label: 'Opens on',\n description:\n 'The tab a visitor lands on. Leave it unset and the first tab ' +\n 'opens, as it always has. Pick from the tabs above rather than ' +\n 'reordering them — the strip is the design, and which tab opens ' +\n 'is not. If the tab named here is later renamed or removed, the ' +\n 'first tab opens again.',\n component: Aglyn.FieldComponentType.SELECT,\n // Nothing to choose on a one-tab strip — and naming `labels` is also\n // what keeps the answers following the list (see opensOnFieldProps).\n condition: atLeastLabels(2),\n resolveProps: opensOnFieldProps,\n // The corner ✕ is the way back to \"the first tab\": no option could\n // carry that meaning, since an `''` value is stripped before save\n // (AGL-1191) and every other value names a real tab.\n clearable: true,\n },\n {\n name: 'orientation',\n label: 'Orientation',\n description:\n 'Vertical puts the strip beside the panels instead of above them.',\n component: Aglyn.FieldComponentType.SELECT,\n // Real sentinels throughout this schema rather than deletions\n // (AGL-1451): each \"(default)\" here names MUI's OWN value for that\n // prop — horizontal, standard, primary — so the option is a real\n // choice an author may want to pin, not a synonym for \"unset\".\n // Spelled `''` they could not persist at all (AGL-1191): picking\n // Horizontal on a vertical strip silently reverted to vertical.\n options: [\n { value: 'horizontal', label: 'Horizontal (default)' },\n { value: 'vertical', label: 'Vertical' },\n ],\n },\n {\n name: 'variant',\n label: 'Variant',\n description:\n 'Scrollable keeps long strips usable on small screens; full width ' +\n 'divides the available space evenly.',\n component: Aglyn.FieldComponentType.SELECT,\n options: [\n { value: 'standard', label: 'Standard (default)' },\n { value: 'scrollable', label: 'Scrollable' },\n { value: 'fullWidth', label: 'Full width' },\n ],\n },\n {\n name: 'ssrPanels',\n label: 'Keep every panel in the page source',\n description:\n 'Panels are normally built the first time their tab is opened, ' +\n 'which keeps big tab sets light. Turn this on when panel content ' +\n 'appears nowhere else on the page and search engines must be able ' +\n 'to read it — every panel is then rendered into the page source ' +\n 'up front, which can make a large tab set much heavier.',\n component: Aglyn.FieldComponentType.SWITCH,\n },\n {\n name: 'centered',\n label: 'Centered?',\n description: 'Centers the tabs in the strip.',\n component: Aglyn.FieldComponentType.SWITCH,\n // MUI ignores centered on a scrollable strip and warns in dev.\n condition: STANDARD_ONLY,\n },\n {\n name: 'textColor',\n label: 'Text color',\n description: 'Theme color of the tab labels.',\n component: Aglyn.FieldComponentType.SELECT,\n options: [\n { value: 'primary', label: 'Primary (default)' },\n { value: 'secondary', label: 'Secondary' },\n { value: 'inherit', label: 'Inherit' },\n ],\n },\n {\n name: 'indicatorColor',\n label: 'Indicator color',\n description: 'Theme color of the underline marking the active tab.',\n component: Aglyn.FieldComponentType.SELECT,\n options: [\n { value: 'primary', label: 'Primary (default)' },\n { value: 'secondary', label: 'Secondary' },\n ],\n },\n {\n name: 'ariaLabel',\n label: 'Accessible label',\n description:\n 'Names the row for screen readers. Default \"Tabs\". Give a row ' +\n 'whose tabs link to other screens its own name — it becomes a ' +\n 'navigation landmark, and two landmarks called the same thing are ' +\n 'no help to anyone.',\n component: Aglyn.FieldComponentType.TEXT_FIELD,\n },\n ],\n}\n\nexport const tabPanelSchema: Aglyn.ComponentSchema<TabPanelElementProps> = {\n $id: TAB_PANEL_ID,\n pluginId: BUNDLE_ID,\n displayName: 'Tab Panel',\n description: 'The content shown under one tab.',\n category: Aglyn.ComponentCategory.NAVIGATION,\n icon: { path: mdiViewCarousel.path, sx: { color: '#2196f3' } },\n attributes: [\n {\n name: 'label',\n label: 'Shows under tab',\n description:\n \"The tab label this panel belongs to — type it exactly as it \" +\n 'appears in the Tabs list above (capitalisation is ignored).',\n component: Aglyn.FieldComponentType.TEXT_FIELD,\n },\n ],\n}\n\nconst tabPanel = (label: string, body: string) => ({\n $id: null,\n componentId: TAB_PANEL_ID,\n pluginId: BUNDLE_ID,\n props: { label },\n nodes: [\n {\n $id: null,\n componentId: 'muiTypography',\n pluginId: BUNDLE_ID,\n props: { variant: 'body2', children: body },\n },\n ],\n})\n\nexport const tabsPresets: Aglyn.PresetSchema[] = [\n {\n // Labels and panels ship already matched: the one place this element\n // can be misconfigured is never hit on the common path.\n $id: generatePresetId(TABS_ID),\n type: Aglyn.NodeType.PRESET,\n displayName: 'Tabs',\n pluginId: BUNDLE_ID,\n description: 'Three tabs with matching panels, ready to edit',\n category: Aglyn.ComponentCategory.NAVIGATION,\n icon: tabsSchema.icon,\n data: {\n $id: null,\n componentId: TABS_ID,\n pluginId: BUNDLE_ID,\n props: { labels: 'Overview\\nDetails\\nFAQ' },\n nodes: [\n tabPanel('Overview', 'What this is, in a sentence or two.'),\n tabPanel('Details', 'The specifics that back up the overview.'),\n tabPanel('FAQ', 'The questions people actually ask.'),\n ],\n },\n },\n {\n $id: generatePresetId(TAB_PANEL_ID),\n type: Aglyn.NodeType.PRESET,\n displayName: 'Tab Panel',\n pluginId: BUNDLE_ID,\n description: 'One more panel to add to an existing Tabs element',\n category: Aglyn.ComponentCategory.NAVIGATION,\n icon: tabPanelSchema.icon,\n data: tabPanel('', 'Name the tab this panel belongs to.'),\n },\n]\n\nexport default TabsElement\n"],"names":["Aglyn","mdiTab","mdiViewCarousel","AppLink","Box","MuiTab","MuiTabs","Typography","createContext","forwardRef","useContext","useState","BUNDLE_ID","dropClearedProps","generatePresetId","TABS_ID","TAB_PANEL_ID","TAB_LINK_SLOTS","tabLinkProp","position","parseLabels","value","String","split","map","label","trim","filter","Boolean","labelSlug","toLowerCase","replace","labelsMatch","a","b","openingTabIndex","labels","opensOn","linkIds","named","findIndex","index","landing","_label","TabsContext","undefined","TabsElement","rawProps","ref","parsed","props","ariaLabel","orientation","variant","centered","textColor","indicatorColor","ssrPanels","lazyPanels","children","rest","editorInert","suppressNavigation","useScreenLink","screens","ScreenLinkContext","slot","key","push","navMode","some","opening","active","setActive","opened","setOpened","first","Set","chosen","length","activeIndex","resolvedVariant","vertical","stripLabel","strip","onChange","_event","next","prev","has","add","component","slotProps","root","list","role","slug","id","aria-controls","href","resolveScreenHref","broken","isScreenLinkBroken","componentVariant","disabled","brokenScreenLinkProps","sx","BROKEN_SCREEN_LINK_SX","aria-selected","aria-current","tabIndex","Provider","activeLabel","showAll","display","Array","isArray","displayName","TabPanelElement","aglynDeferred","context","selected","visible","mounted","hidden","aria-labelledby","p","color","mb","py","STANDARD_ONLY","when","is","notMatch","atLeastLabels","count","isNotEmpty","item","separator","pattern","opensOnFieldProps","_props","field","formOptions","authored","getFieldState","getState","values","options","stored","input","option","ordinal","suffix","TAB_LINK_FIELDS","from","_unused","name","description","FieldComponentType","SCREEN_SELECT","condition","tabsSchema","$id","pluginId","category","ComponentCategory","NAVIGATION","icon","path","restrictChildren","LinealDirectiveFlag","LIMIT_TO","components","attributes","TEXTAREA","SELECT","resolveProps","clearable","SWITCH","TEXT_FIELD","tabPanelSchema","tabPanel","body","componentId","nodes","tabsPresets","type","NodeType","PRESET","data"],"mappings":"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"}
@@ -0,0 +1,38 @@
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 * as Aglyn from '@aglyn/aglyn';
18
+ export declare const ID: Aglyn.ComponentId;
19
+ export interface ThemeModeSwitcherProps {
20
+ /** 'icon' cycles light→dark→system on click; 'toggle' shows all three. */
21
+ variant?: 'icon' | 'toggle';
22
+ }
23
+ /**
24
+ * Visitor-facing light/dark override (AGL-337): drives the shared
25
+ * cookie-backed theme mode state the HostThemeProvider already resolves,
26
+ * so the choice persists across visits and pages. The icon variant
27
+ * cycles light → dark → device default; the toggle variant shows the
28
+ * three choices explicitly.
29
+ *
30
+ * A site whose theme has its dark scheme switched off renders light whatever
31
+ * this control says, so on a published page it renders nothing rather than a
32
+ * switch that flips only its own icon (AGL-2676). The static besigner canvas
33
+ * keeps it visible so the author can still place and style it.
34
+ */
35
+ declare const ThemeModeSwitcher: import("react").ForwardRefExoticComponent<ThemeModeSwitcherProps & import("react").RefAttributes<HTMLElement>>;
36
+ export declare const schema: Aglyn.ComponentSchema<ThemeModeSwitcherProps>;
37
+ export declare const presets: Aglyn.PresetSchema[];
38
+ export default ThemeModeSwitcher;
@@ -0,0 +1,168 @@
1
+ import { _ as _extends } from "@swc/helpers/_/_extends";
2
+ import { _ as _object_without_properties_loose } from "@swc/helpers/_/_object_without_properties_loose";
3
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
4
+ /**
5
+ * @license
6
+ * Copyright 2026 Aglyn LLC
7
+ *
8
+ * Licensed under the Apache License, Version 2.0 (the "License");
9
+ * you may not use this file except in compliance with the License.
10
+ * You may obtain a copy of the License at
11
+ *
12
+ * http://www.apache.org/licenses/LICENSE-2.0
13
+ *
14
+ * Unless required by applicable law or agreed to in writing, software
15
+ * distributed under the License is distributed on an "AS IS" BASIS,
16
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17
+ * See the License for the specific language governing permissions and
18
+ * limitations under the License.
19
+ */ import * as Aglyn from "@aglyn/aglyn";
20
+ import { mdiThemeLightDark, mdiWeatherNight, mdiWhiteBalanceSunny } from "@aglyn/shared-data-mdi";
21
+ import { MdiIcon } from "@aglyn/shared-ui-jsx";
22
+ import { useThemeMode } from "@aglyn/shared-ui-theme";
23
+ import IconButton from "@mui/material/IconButton";
24
+ import ToggleButton from "@mui/material/ToggleButton";
25
+ import ToggleButtonGroup from "@mui/material/ToggleButtonGroup";
26
+ import Tooltip from "@mui/material/Tooltip";
27
+ import { forwardRef, useContext } from "react";
28
+ import { BUNDLE_ID } from "../constants/bundle-common.js";
29
+ import { generatePresetId } from "../utils/generate-preset-id.js";
30
+ // Component ids are persisted in screen documents; never rename.
31
+ export const ID = 'themeModeSwitcher';
32
+ /**
33
+ * Visitor-facing light/dark override (AGL-337): drives the shared
34
+ * cookie-backed theme mode state the HostThemeProvider already resolves,
35
+ * so the choice persists across visits and pages. The icon variant
36
+ * cycles light → dark → device default; the toggle variant shows the
37
+ * three choices explicitly.
38
+ *
39
+ * A site whose theme has its dark scheme switched off renders light whatever
40
+ * this control says, so on a published page it renders nothing rather than a
41
+ * switch that flips only its own icon (AGL-2676). The static besigner canvas
42
+ * keeps it visible so the author can still place and style it.
43
+ */ const ThemeModeSwitcher = /*#__PURE__*/ forwardRef((props, ref)=>{
44
+ const { variant } = props, rest = _object_without_properties_loose(props, [
45
+ "variant"
46
+ ]);
47
+ const [, toggleThemeMode, cookieMode, canGoDark] = useThemeMode();
48
+ const { editorInert } = useContext(Aglyn.ScreenLinkContext);
49
+ if (canGoDark === false && !editorInert) return null;
50
+ if (variant === 'toggle') {
51
+ return /*#__PURE__*/ _jsxs(ToggleButtonGroup, _extends({
52
+ ref: ref,
53
+ size: "small",
54
+ exclusive: true,
55
+ value: cookieMode != null ? cookieMode : 'system',
56
+ onChange: (event, value)=>value && toggleThemeMode(event, value),
57
+ "aria-label": "Color theme"
58
+ }, rest, {
59
+ children: [
60
+ /*#__PURE__*/ _jsx(ToggleButton, {
61
+ value: "light",
62
+ "aria-label": "Light",
63
+ children: /*#__PURE__*/ _jsx(MdiIcon, {
64
+ path: mdiWhiteBalanceSunny.path,
65
+ fontSize: "small"
66
+ })
67
+ }),
68
+ /*#__PURE__*/ _jsx(ToggleButton, {
69
+ value: "system",
70
+ "aria-label": "Device default",
71
+ children: /*#__PURE__*/ _jsx(MdiIcon, {
72
+ path: mdiThemeLightDark.path,
73
+ fontSize: "small"
74
+ })
75
+ }),
76
+ /*#__PURE__*/ _jsx(ToggleButton, {
77
+ value: "dark",
78
+ "aria-label": "Dark",
79
+ children: /*#__PURE__*/ _jsx(MdiIcon, {
80
+ path: mdiWeatherNight.path,
81
+ fontSize: "small"
82
+ })
83
+ })
84
+ ]
85
+ }));
86
+ }
87
+ return /*#__PURE__*/ _jsx(Tooltip, {
88
+ title: `Theme: ${cookieMode != null ? cookieMode : 'device default'}`,
89
+ children: /*#__PURE__*/ _jsx(IconButton, _extends({
90
+ ref: ref,
91
+ onClick: (event)=>toggleThemeMode(event),
92
+ "aria-label": "Toggle color theme",
93
+ color: "inherit"
94
+ }, rest, {
95
+ children: /*#__PURE__*/ _jsx(MdiIcon, {
96
+ // Key off the visitor's SELECTION, not the resolved mode: with
97
+ // 'device default' chosen, `mode` still resolves to light or dark,
98
+ // so the button showed a sun/moon and the system state was
99
+ // invisible — you couldn't tell it apart from an explicit choice.
100
+ // Same mapping the toggle variant uses.
101
+ path: cookieMode === 'dark' ? mdiWeatherNight.path : cookieMode === 'light' ? mdiWhiteBalanceSunny.path : mdiThemeLightDark.path,
102
+ fontSize: "small"
103
+ })
104
+ }))
105
+ });
106
+ });
107
+ ThemeModeSwitcher.displayName = 'AglynThemeModeSwitcher';
108
+ export const schema = {
109
+ $id: ID,
110
+ pluginId: BUNDLE_ID,
111
+ displayName: 'Theme mode switcher',
112
+ description: 'Lets visitors override the site theme with light, dark, or device default. Hidden on published pages while the theme has its dark scheme switched off.',
113
+ category: Aglyn.ComponentCategory.INPUT,
114
+ icon: {
115
+ path: mdiThemeLightDark.path,
116
+ sx: {
117
+ color: '#7b1fa2'
118
+ }
119
+ },
120
+ flags: {
121
+ selfClosing: Aglyn.FEATURE_FLAG.ENABLED
122
+ },
123
+ attributes: [
124
+ {
125
+ name: 'variant',
126
+ label: 'Variant',
127
+ description: 'Icon button cycles modes on click; toggle shows light / device / dark.',
128
+ component: Aglyn.FieldComponentType.SELECT,
129
+ options: [
130
+ {
131
+ value: 'icon',
132
+ label: 'Icon button'
133
+ },
134
+ {
135
+ value: 'toggle',
136
+ label: 'Toggle group'
137
+ }
138
+ ]
139
+ }
140
+ ]
141
+ };
142
+ export const presets = [
143
+ {
144
+ $id: generatePresetId(ID),
145
+ type: Aglyn.NodeType.PRESET,
146
+ displayName: 'Theme mode switcher',
147
+ pluginId: BUNDLE_ID,
148
+ description: 'Visitor light/dark/system override button',
149
+ category: Aglyn.ComponentCategory.INPUT,
150
+ icon: {
151
+ path: mdiThemeLightDark.path,
152
+ sx: {
153
+ color: '#7b1fa2'
154
+ }
155
+ },
156
+ data: {
157
+ $id: null,
158
+ componentId: ID,
159
+ pluginId: BUNDLE_ID,
160
+ props: {
161
+ variant: 'icon'
162
+ }
163
+ }
164
+ }
165
+ ];
166
+ export default ThemeModeSwitcher;
167
+
168
+ //# sourceMappingURL=theme-mode-switcher.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../../../../../libs/plugins/mui/src/lib/components/theme-mode-switcher.tsx"],"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 * as Aglyn from '@aglyn/aglyn'\nimport {\n mdiThemeLightDark,\n mdiWeatherNight,\n mdiWhiteBalanceSunny,\n} from '@aglyn/shared-data-mdi'\nimport { MdiIcon } from '@aglyn/shared-ui-jsx'\nimport { useThemeMode } from '@aglyn/shared-ui-theme'\nimport IconButton from '@mui/material/IconButton'\nimport ToggleButton from '@mui/material/ToggleButton'\nimport ToggleButtonGroup from '@mui/material/ToggleButtonGroup'\nimport Tooltip from '@mui/material/Tooltip'\nimport { forwardRef, useContext } from 'react'\nimport { BUNDLE_ID } from '../constants/bundle-common'\nimport { generatePresetId } from '../utils/generate-preset-id'\n\n// Component ids are persisted in screen documents; never rename.\nexport const ID: Aglyn.ComponentId = 'themeModeSwitcher'\n\nexport interface ThemeModeSwitcherProps {\n /** 'icon' cycles light→dark→system on click; 'toggle' shows all three. */\n variant?: 'icon' | 'toggle'\n}\n\n/**\n * Visitor-facing light/dark override (AGL-337): drives the shared\n * cookie-backed theme mode state the HostThemeProvider already resolves,\n * so the choice persists across visits and pages. The icon variant\n * cycles light → dark → device default; the toggle variant shows the\n * three choices explicitly.\n *\n * A site whose theme has its dark scheme switched off renders light whatever\n * this control says, so on a published page it renders nothing rather than a\n * switch that flips only its own icon (AGL-2676). The static besigner canvas\n * keeps it visible so the author can still place and style it.\n */\nconst ThemeModeSwitcher = forwardRef<HTMLElement, ThemeModeSwitcherProps>(\n (props, ref) => {\n const { variant, ...rest } = props\n const [, toggleThemeMode, cookieMode, canGoDark] = useThemeMode()\n const { editorInert } = useContext(Aglyn.ScreenLinkContext)\n\n if (canGoDark === false && !editorInert) return null\n\n if (variant === 'toggle') {\n return (\n <ToggleButtonGroup\n ref={ref as any}\n size=\"small\"\n exclusive\n value={cookieMode ?? 'system'}\n onChange={(event, value) =>\n value && toggleThemeMode(event as any, value)\n }\n aria-label=\"Color theme\"\n {...rest}\n >\n <ToggleButton value=\"light\" aria-label=\"Light\">\n <MdiIcon path={mdiWhiteBalanceSunny.path} fontSize=\"small\" />\n </ToggleButton>\n <ToggleButton value=\"system\" aria-label=\"Device default\">\n <MdiIcon path={mdiThemeLightDark.path} fontSize=\"small\" />\n </ToggleButton>\n <ToggleButton value=\"dark\" aria-label=\"Dark\">\n <MdiIcon path={mdiWeatherNight.path} fontSize=\"small\" />\n </ToggleButton>\n </ToggleButtonGroup>\n )\n }\n\n return (\n <Tooltip title={`Theme: ${cookieMode ?? 'device default'}`}>\n <IconButton\n ref={ref as any}\n onClick={(event) => toggleThemeMode(event)}\n aria-label=\"Toggle color theme\"\n color=\"inherit\"\n {...rest}\n >\n <MdiIcon\n // Key off the visitor's SELECTION, not the resolved mode: with\n // 'device default' chosen, `mode` still resolves to light or dark,\n // so the button showed a sun/moon and the system state was\n // invisible — you couldn't tell it apart from an explicit choice.\n // Same mapping the toggle variant uses.\n path={\n cookieMode === 'dark'\n ? mdiWeatherNight.path\n : cookieMode === 'light'\n ? mdiWhiteBalanceSunny.path\n : mdiThemeLightDark.path\n }\n fontSize=\"small\"\n />\n </IconButton>\n </Tooltip>\n )\n },\n)\nThemeModeSwitcher.displayName = 'AglynThemeModeSwitcher'\n\nexport const schema: Aglyn.ComponentSchema<ThemeModeSwitcherProps> = {\n $id: ID,\n pluginId: BUNDLE_ID,\n displayName: 'Theme mode switcher',\n description:\n 'Lets visitors override the site theme with light, dark, or device default. Hidden on published pages while the theme has its dark scheme switched off.',\n category: Aglyn.ComponentCategory.INPUT,\n icon: { path: mdiThemeLightDark.path, sx: { color: '#7b1fa2' } },\n flags: { selfClosing: Aglyn.FEATURE_FLAG.ENABLED },\n attributes: [\n {\n name: 'variant',\n label: 'Variant',\n description:\n 'Icon button cycles modes on click; toggle shows light / device / dark.',\n component: Aglyn.FieldComponentType.SELECT,\n options: [\n { value: 'icon', label: 'Icon button' },\n { value: 'toggle', label: 'Toggle group' },\n ],\n },\n ],\n}\n\nexport const presets: Aglyn.PresetSchema[] = [\n {\n $id: generatePresetId(ID),\n type: Aglyn.NodeType.PRESET,\n displayName: 'Theme mode switcher',\n pluginId: BUNDLE_ID,\n description: 'Visitor light/dark/system override button',\n category: Aglyn.ComponentCategory.INPUT,\n icon: { path: mdiThemeLightDark.path, sx: { color: '#7b1fa2' } },\n data: {\n $id: null,\n componentId: ID,\n pluginId: BUNDLE_ID,\n props: { variant: 'icon' },\n },\n },\n]\n\nexport default ThemeModeSwitcher\n"],"names":["Aglyn","mdiThemeLightDark","mdiWeatherNight","mdiWhiteBalanceSunny","MdiIcon","useThemeMode","IconButton","ToggleButton","ToggleButtonGroup","Tooltip","forwardRef","useContext","BUNDLE_ID","generatePresetId","ID","ThemeModeSwitcher","props","ref","variant","rest","toggleThemeMode","cookieMode","canGoDark","editorInert","ScreenLinkContext","size","exclusive","value","onChange","event","aria-label","path","fontSize","title","onClick","color","displayName","schema","$id","pluginId","description","category","ComponentCategory","INPUT","icon","sx","flags","selfClosing","FEATURE_FLAG","ENABLED","attributes","name","label","component","FieldComponentType","SELECT","options","presets","type","NodeType","PRESET","data","componentId"],"mappings":"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"}
@@ -0,0 +1,37 @@
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 * as Aglyn from '@aglyn/aglyn';
18
+ import { type ToolbarProps } from '@mui/material/Toolbar';
19
+ /**
20
+ * MUI's Toolbar behind the cleared-prop guard (AGL-1451).
21
+ *
22
+ * This was the one component in the AGL-1451 set where `''` reached MUI
23
+ * untouched, so it carried the AGL-1435 defect exactly: MUI's Toolbar
24
+ * destructures `variant = 'regular'` and then applies its height from
25
+ * `ownerState.variant === 'regular' && theme.mixins.toolbar`. `''` is not
26
+ * `undefined`, so the default never fires, and it is falsy, so neither the
27
+ * `regular` nor the `dense` branch matches — the toolbar renders with NO
28
+ * min-height at all and the app bar collapses to its content. Nothing
29
+ * throws and the editor looks fine.
30
+ *
31
+ * `createElement` rather than JSX keeps this a `.ts` file.
32
+ */
33
+ declare const Toolbar: import("react").ForwardRefExoticComponent<Omit<ToolbarProps, "ref"> & import("react").RefAttributes<HTMLDivElement>>;
34
+ export declare const ID: Aglyn.ComponentId;
35
+ export declare const schema: Aglyn.ComponentSchema<ToolbarProps>;
36
+ export declare const presets: Aglyn.PresetSchema[];
37
+ export default Toolbar;
@@ -0,0 +1,117 @@
1
+ import { _ as _extends } from "@swc/helpers/_/_extends";
2
+ /**
3
+ * @license
4
+ * Copyright 2026 Aglyn LLC
5
+ *
6
+ * Licensed under the Apache License, Version 2.0 (the "License");
7
+ * you may not use this file except in compliance with the License.
8
+ * You may obtain a copy of the License at
9
+ *
10
+ * http://www.apache.org/licenses/LICENSE-2.0
11
+ *
12
+ * Unless required by applicable law or agreed to in writing, software
13
+ * distributed under the License is distributed on an "AS IS" BASIS,
14
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15
+ * See the License for the specific language governing permissions and
16
+ * limitations under the License.
17
+ */ import * as Aglyn from "@aglyn/aglyn";
18
+ import { mdiBorderInside } from "@aglyn/shared-data-mdi";
19
+ import MuiToolbar from "@mui/material/Toolbar";
20
+ import { createElement, forwardRef } from "react";
21
+ import { BUNDLE_ID } from "../constants/bundle-common.js";
22
+ import { FIELD_DISABLE_GUTTERS } from "../constants/field-presets.js";
23
+ import { applySemanticElement, semanticElementAttribute, semanticElementLabelAttribute } from "../utils/element-picker.js";
24
+ import { dropClearedProps } from "../utils/drop-cleared-props.js";
25
+ import { generatePresetId } from "../utils/generate-preset-id.js";
26
+ /**
27
+ * MUI's Toolbar behind the cleared-prop guard (AGL-1451).
28
+ *
29
+ * This was the one component in the AGL-1451 set where `''` reached MUI
30
+ * untouched, so it carried the AGL-1435 defect exactly: MUI's Toolbar
31
+ * destructures `variant = 'regular'` and then applies its height from
32
+ * `ownerState.variant === 'regular' && theme.mixins.toolbar`. `''` is not
33
+ * `undefined`, so the default never fires, and it is falsy, so neither the
34
+ * `regular` nor the `dense` branch matches — the toolbar renders with NO
35
+ * min-height at all and the app bar collapses to its content. Nothing
36
+ * throws and the editor looks fine.
37
+ *
38
+ * `createElement` rather than JSX keeps this a `.ts` file.
39
+ */ const Toolbar = forwardRef((props, ref)=>createElement(MuiToolbar, _extends({}, applySemanticElement(dropClearedProps(props)), {
40
+ ref
41
+ })));
42
+ Toolbar.displayName = 'AglynToolbar';
43
+ // Component ids are persisted in screen documents; keep the legacy ids.
44
+ export const ID = 'muiToolbar';
45
+ export const schema = {
46
+ $id: ID,
47
+ pluginId: BUNDLE_ID,
48
+ displayName: 'Toolbar Content',
49
+ description: 'The content row inside an App Bar — brand, links, actions.',
50
+ category: Aglyn.ComponentCategory.NAVIGATION,
51
+ icon: {
52
+ path: mdiBorderInside.path,
53
+ sx: {
54
+ color: '#2196f3'
55
+ }
56
+ },
57
+ restrictParent: [
58
+ Aglyn.LinealDirectiveFlag.LIMIT_TO,
59
+ {
60
+ components: [
61
+ 'muiAppBar'
62
+ ],
63
+ plugins: [
64
+ BUNDLE_ID
65
+ ]
66
+ }
67
+ ],
68
+ attributes: [
69
+ semanticElementAttribute('this row'),
70
+ semanticElementLabelAttribute(),
71
+ FIELD_DISABLE_GUTTERS,
72
+ {
73
+ name: 'variant',
74
+ description: 'Regular is the standard bar height; dense compacts it. Clearing ' + 'the field falls back to Regular, which is MUI’s own default.',
75
+ component: Aglyn.FieldComponentType.SELECT,
76
+ label: 'Variant',
77
+ // No "Default" option: MUI has exactly two toolbar heights and
78
+ // `regular` IS the default, so "Default" was a second name for a
79
+ // choice already in the list — carrying the `''` value that rendered
80
+ // a toolbar with no min-height at all (AGL-1451). Deleted rather
81
+ // than given a sentinel for that reason; every value here is real
82
+ // and persistable.
83
+ options: [
84
+ {
85
+ value: 'dense',
86
+ label: 'Dense'
87
+ },
88
+ {
89
+ value: 'regular',
90
+ label: 'Regular (default)'
91
+ }
92
+ ]
93
+ }
94
+ ]
95
+ };
96
+ export const presets = [
97
+ {
98
+ $id: generatePresetId(ID),
99
+ type: Aglyn.NodeType.PRESET,
100
+ displayName: 'Toolbar Content',
101
+ icon: {
102
+ path: mdiBorderInside.path,
103
+ sx: {
104
+ color: '#2196f3'
105
+ }
106
+ },
107
+ category: Aglyn.ComponentCategory.NAVIGATION,
108
+ data: {
109
+ $id: null,
110
+ componentId: ID,
111
+ pluginId: BUNDLE_ID
112
+ }
113
+ }
114
+ ];
115
+ export default Toolbar;
116
+
117
+ //# sourceMappingURL=toolbar.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../../../../../libs/plugins/mui/src/lib/components/toolbar.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 * as Aglyn from '@aglyn/aglyn'\nimport {\n mdiBorderInside,\n} from '@aglyn/shared-data-mdi'\nimport MuiToolbar, { type ToolbarProps } from '@mui/material/Toolbar'\nimport { createElement, forwardRef } from 'react'\nimport { BUNDLE_ID } from '../constants/bundle-common'\nimport { FIELD_DISABLE_GUTTERS } from '../constants/field-presets'\nimport {\n applySemanticElement,\n semanticElementAttribute,\n semanticElementLabelAttribute,\n} from '../utils/element-picker'\nimport { dropClearedProps } from '../utils/drop-cleared-props'\nimport { generatePresetId } from '../utils/generate-preset-id'\n\n/**\n * MUI's Toolbar behind the cleared-prop guard (AGL-1451).\n *\n * This was the one component in the AGL-1451 set where `''` reached MUI\n * untouched, so it carried the AGL-1435 defect exactly: MUI's Toolbar\n * destructures `variant = 'regular'` and then applies its height from\n * `ownerState.variant === 'regular' && theme.mixins.toolbar`. `''` is not\n * `undefined`, so the default never fires, and it is falsy, so neither the\n * `regular` nor the `dense` branch matches — the toolbar renders with NO\n * min-height at all and the app bar collapses to its content. Nothing\n * throws and the editor looks fine.\n *\n * `createElement` rather than JSX keeps this a `.ts` file.\n */\nconst Toolbar = forwardRef<HTMLDivElement, ToolbarProps>((props, ref) =>\n createElement(MuiToolbar, {\n ...applySemanticElement(dropClearedProps(props) as Record<string, unknown>),\n ref,\n }),\n)\nToolbar.displayName = 'AglynToolbar'\n\n// Component ids are persisted in screen documents; keep the legacy ids.\nexport const ID: Aglyn.ComponentId = 'muiToolbar'\n\nexport const schema: Aglyn.ComponentSchema<ToolbarProps> = {\n $id: ID,\n pluginId: BUNDLE_ID,\n displayName: 'Toolbar Content',\n description: 'The content row inside an App Bar — brand, links, actions.',\n category: Aglyn.ComponentCategory.NAVIGATION,\n icon: {\n path: mdiBorderInside.path,\n sx: { color: '#2196f3' },\n },\n restrictParent: [\n Aglyn.LinealDirectiveFlag.LIMIT_TO,\n { components: ['muiAppBar'], plugins: [BUNDLE_ID] },\n ],\n attributes: [\n semanticElementAttribute('this row'),\n semanticElementLabelAttribute(),\n FIELD_DISABLE_GUTTERS,\n {\n name: 'variant',\n description:\n 'Regular is the standard bar height; dense compacts it. Clearing ' +\n 'the field falls back to Regular, which is MUI’s own default.',\n component: Aglyn.FieldComponentType.SELECT,\n label: 'Variant',\n // No \"Default\" option: MUI has exactly two toolbar heights and\n // `regular` IS the default, so \"Default\" was a second name for a\n // choice already in the list — carrying the `''` value that rendered\n // a toolbar with no min-height at all (AGL-1451). Deleted rather\n // than given a sentinel for that reason; every value here is real\n // and persistable.\n options: [\n { value: 'dense', label: 'Dense' },\n { value: 'regular', label: 'Regular (default)' },\n ],\n },\n ],\n}\n\nexport const presets: Aglyn.PresetSchema[] = [\n {\n $id: generatePresetId(ID),\n type: Aglyn.NodeType.PRESET,\n displayName: 'Toolbar Content',\n icon: {\n path: mdiBorderInside.path,\n sx: { color: '#2196f3' },\n },\n category: Aglyn.ComponentCategory.NAVIGATION,\n data: {\n $id: null,\n componentId: ID,\n pluginId: BUNDLE_ID,\n },\n },\n]\n\nexport default Toolbar\n"],"names":["Aglyn","mdiBorderInside","MuiToolbar","createElement","forwardRef","BUNDLE_ID","FIELD_DISABLE_GUTTERS","applySemanticElement","semanticElementAttribute","semanticElementLabelAttribute","dropClearedProps","generatePresetId","Toolbar","props","ref","displayName","ID","schema","$id","pluginId","description","category","ComponentCategory","NAVIGATION","icon","path","sx","color","restrictParent","LinealDirectiveFlag","LIMIT_TO","components","plugins","attributes","name","component","FieldComponentType","SELECT","label","options","value","presets","type","NodeType","PRESET","data","componentId"],"mappings":";AAAA;;;;;;;;;;;;;;;CAeC,GAED,YAAYA,WAAW,eAAc;AACrC,SACEC,eAAe,QACV,yBAAwB;AAC/B,OAAOC,gBAAuC,wBAAuB;AACrE,SAASC,aAAa,EAAEC,UAAU,QAAQ,QAAO;AACjD,SAASC,SAAS,QAAQ,gCAA4B;AACtD,SAASC,qBAAqB,QAAQ,gCAA4B;AAClE,SACEC,oBAAoB,EACpBC,wBAAwB,EACxBC,6BAA6B,QACxB,6BAAyB;AAChC,SAASC,gBAAgB,QAAQ,iCAA6B;AAC9D,SAASC,gBAAgB,QAAQ,iCAA6B;AAE9D;;;;;;;;;;;;;CAaC,GACD,MAAMC,UAAUR,WAAyC,CAACS,OAAOC,MAC/DX,cAAcD,YAAY,aACrBK,qBAAqBG,iBAAiBG;QACzCC;;AAGJF,QAAQG,WAAW,GAAG;AAEtB,wEAAwE;AACxE,OAAO,MAAMC,KAAwB,aAAY;AAEjD,OAAO,MAAMC,SAA8C;IACzDC,KAAKF;IACLG,UAAUd;IACVU,aAAa;IACbK,aAAa;IACbC,UAAUrB,MAAMsB,iBAAiB,CAACC,UAAU;IAC5CC,MAAM;QACJC,MAAMxB,gBAAgBwB,IAAI;QAC1BC,IAAI;YAAEC,OAAO;QAAU;IACzB;IACAC,gBAAgB;QACd5B,MAAM6B,mBAAmB,CAACC,QAAQ;QAClC;YAAEC,YAAY;gBAAC;aAAY;YAAEC,SAAS;gBAAC3B;aAAU;QAAC;KACnD;IACD4B,YAAY;QACVzB,yBAAyB;QACzBC;QACAH;QACA;YACE4B,MAAM;YACNd,aACE,qEACA;YACFe,WAAWnC,MAAMoC,kBAAkB,CAACC,MAAM;YAC1CC,OAAO;YACP,+DAA+D;YAC/D,iEAAiE;YACjE,qEAAqE;YACrE,iEAAiE;YACjE,kEAAkE;YAClE,mBAAmB;YACnBC,SAAS;gBACP;oBAAEC,OAAO;oBAASF,OAAO;gBAAQ;gBACjC;oBAAEE,OAAO;oBAAWF,OAAO;gBAAoB;aAChD;QACH;KACD;AACH,EAAC;AAED,OAAO,MAAMG,UAAgC;IAC3C;QACEvB,KAAKP,iBAAiBK;QACtB0B,MAAM1C,MAAM2C,QAAQ,CAACC,MAAM;QAC3B7B,aAAa;QACbS,MAAM;YACJC,MAAMxB,gBAAgBwB,IAAI;YAC1BC,IAAI;gBAAEC,OAAO;YAAU;QACzB;QACAN,UAAUrB,MAAMsB,iBAAiB,CAACC,UAAU;QAC5CsB,MAAM;YACJ3B,KAAK;YACL4B,aAAa9B;YACbG,UAAUd;QACZ;IACF;CACD,CAAA;AAED,eAAeO,QAAO"}
@@ -0,0 +1,33 @@
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 * as Aglyn from '@aglyn/aglyn';
18
+ export declare const ID: Aglyn.ComponentId;
19
+ export declare const typographyVariants: {
20
+ value: string;
21
+ label: string;
22
+ icon: {
23
+ path: string;
24
+ };
25
+ }[];
26
+ export declare const schema: Aglyn.ComponentSchema;
27
+ export declare const presets: Aglyn.PresetSchema[];
28
+ declare const AglynTypography: import("react").ForwardRefExoticComponent<Omit<import("@mui/material").TypographyOwnProps & import("@mui/material/OverridableComponent").CommonProps & Omit<import("react").DetailedHTMLProps<import("react").HTMLAttributes<HTMLSpanElement>, HTMLSpanElement>, "color" | "sx" | "children" | "style" | "className" | "classes" | "variant" | "align" | "noWrap" | "gutterBottom" | "variantMapping"> & {
29
+ component?: React.ElementType | undefined;
30
+ } & {
31
+ html?: string;
32
+ }, "ref"> & import("react").RefAttributes<HTMLElement>>;
33
+ export default AglynTypography;