@sankhyatronics/sankhya-cms 0.1.18 → 0.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/custom-elements.json +11634 -3153
- package/dist/attention-panel/index.js +2 -2
- package/dist/bar-chart/index.js +2 -2
- package/dist/bento-grid/index.d.ts +33 -1
- package/dist/bento-grid/index.js +4 -3
- package/dist/booking/index.d.ts +309 -0
- package/dist/booking/index.js +20 -0
- package/dist/booking/index.js.map +1 -0
- package/dist/card/index.d.ts +3 -4
- package/dist/card/index.js +2 -2
- package/dist/carousel/index.d.ts +20 -6
- package/dist/carousel/index.js +3 -3
- package/dist/chip/index.js +2 -2
- package/dist/{chunk-JQY2G4QK.js → chunk-2GTR37PU.js} +2 -2
- package/dist/chunk-2GTR37PU.js.map +1 -0
- package/dist/{chunk-FLY7TNRT.js → chunk-2HMOX253.js} +128 -25
- package/dist/chunk-2HMOX253.js.map +1 -0
- package/dist/{chunk-DH53HZPB.js → chunk-37KFBKPD.js} +32 -4
- package/dist/chunk-37KFBKPD.js.map +1 -0
- package/dist/{chunk-ALI26WOB.js → chunk-4XPKKYVZ.js} +54 -15
- package/dist/chunk-4XPKKYVZ.js.map +1 -0
- package/dist/chunk-535QAZ6A.js +236 -0
- package/dist/chunk-535QAZ6A.js.map +1 -0
- package/dist/{chunk-AKJQ345O.js → chunk-5AWGZQWU.js} +2 -2
- package/dist/chunk-6OZKZG5J.js +300 -0
- package/dist/chunk-6OZKZG5J.js.map +1 -0
- package/dist/chunk-AYNT7G3J.js +805 -0
- package/dist/chunk-AYNT7G3J.js.map +1 -0
- package/dist/chunk-BEWX3E6P.js +32 -0
- package/dist/chunk-BEWX3E6P.js.map +1 -0
- package/dist/chunk-CZUGPKXV.js +275 -0
- package/dist/chunk-CZUGPKXV.js.map +1 -0
- package/dist/{chunk-LEXZKGQX.js → chunk-DJFWZOZM.js} +107 -11
- package/dist/chunk-DJFWZOZM.js.map +1 -0
- package/dist/chunk-DPANTC3O.js +1714 -0
- package/dist/chunk-DPANTC3O.js.map +1 -0
- package/dist/chunk-EKZFFY45.js +426 -0
- package/dist/chunk-EKZFFY45.js.map +1 -0
- package/dist/chunk-ER7MCPDV.js +7 -0
- package/dist/chunk-ER7MCPDV.js.map +1 -0
- package/dist/chunk-EW2RK5Y6.js +383 -0
- package/dist/chunk-EW2RK5Y6.js.map +1 -0
- package/dist/{chunk-BLQV2YMO.js → chunk-EZOKT7NJ.js} +2 -2
- package/dist/chunk-FF2LWEF3.js +386 -0
- package/dist/chunk-FF2LWEF3.js.map +1 -0
- package/dist/chunk-FOUK3NHR.js +7 -0
- package/dist/chunk-FOUK3NHR.js.map +1 -0
- package/dist/chunk-GB4NGCZI.js +181 -0
- package/dist/chunk-GB4NGCZI.js.map +1 -0
- package/dist/{chunk-7NLZND6Q.js → chunk-GOFSMD6W.js} +35 -11
- package/dist/chunk-GOFSMD6W.js.map +1 -0
- package/dist/{chunk-6D6ROU7X.js → chunk-IGMVF3KK.js} +2 -2
- package/dist/{chunk-INMSEYT6.js → chunk-IVPVYVWG.js} +2 -2
- package/dist/chunk-JURCF4OD.js +381 -0
- package/dist/chunk-JURCF4OD.js.map +1 -0
- package/dist/{chunk-FZ36KL73.js → chunk-KZ7PMFWS.js} +11 -1
- package/dist/chunk-KZ7PMFWS.js.map +1 -0
- package/dist/{chunk-EMCQBT3S.js → chunk-LO6TZBGD.js} +129 -35
- package/dist/chunk-LO6TZBGD.js.map +1 -0
- package/dist/chunk-MFRGAT6D.js +860 -0
- package/dist/chunk-MFRGAT6D.js.map +1 -0
- package/dist/chunk-MIBVQXRU.js +1098 -0
- package/dist/chunk-MIBVQXRU.js.map +1 -0
- package/dist/{chunk-35TX3AOA.js → chunk-NABSRUXG.js} +2 -2
- package/dist/{chunk-R5G6KFTJ.js → chunk-NXKDZWS7.js} +44 -6
- package/dist/chunk-NXKDZWS7.js.map +1 -0
- package/dist/{chunk-KMU6ABQF.js → chunk-NXUS2CH7.js} +14 -1
- package/dist/chunk-NXUS2CH7.js.map +1 -0
- package/dist/{chunk-GJO3RGOB.js → chunk-OCPGOLVF.js} +56 -11
- package/dist/chunk-OCPGOLVF.js.map +1 -0
- package/dist/chunk-OEOE6IFY.js +628 -0
- package/dist/chunk-OEOE6IFY.js.map +1 -0
- package/dist/{chunk-SMLR736E.js → chunk-PV6OCXXN.js} +2 -2
- package/dist/chunk-PV6OCXXN.js.map +1 -0
- package/dist/chunk-Q66CJO3P.js +534 -0
- package/dist/chunk-Q66CJO3P.js.map +1 -0
- package/dist/{chunk-MG2VTZA4.js → chunk-QS3ANOWN.js} +2 -2
- package/dist/{chunk-ZN4LIKVG.js → chunk-QSJ543V2.js} +2 -2
- package/dist/chunk-QSJ543V2.js.map +1 -0
- package/dist/{chunk-FML6AG2V.js → chunk-RANC3OI6.js} +2 -2
- package/dist/chunk-T4BIN37Q.js +32 -0
- package/dist/chunk-T4BIN37Q.js.map +1 -0
- package/dist/{chunk-YVTFQHVY.js → chunk-TEAZZPDQ.js} +2 -2
- package/dist/chunk-TJK55CJ2.js +49 -0
- package/dist/chunk-TJK55CJ2.js.map +1 -0
- package/dist/chunk-UKIVLF7S.js +32 -0
- package/dist/chunk-UKIVLF7S.js.map +1 -0
- package/dist/chunk-V4R7PYP5.js +905 -0
- package/dist/chunk-V4R7PYP5.js.map +1 -0
- package/dist/{chunk-AG2COC64.js → chunk-VVYQ2DDS.js} +2 -2
- package/dist/chunk-WAMOAAMN.js +16 -0
- package/dist/chunk-WAMOAAMN.js.map +1 -0
- package/dist/chunk-WAYHHL4J.js +1234 -0
- package/dist/chunk-WAYHHL4J.js.map +1 -0
- package/dist/{chunk-YQ42EBK5.js → chunk-WH6HE6SY.js} +10 -4
- package/dist/chunk-WH6HE6SY.js.map +1 -0
- package/dist/chunk-XP6DI3VY.js +180 -0
- package/dist/chunk-XP6DI3VY.js.map +1 -0
- package/dist/{chunk-5EBWMPJS.js → chunk-XS6LNTSH.js} +76 -14
- package/dist/chunk-XS6LNTSH.js.map +1 -0
- package/dist/{chunk-WT4OATGP.js → chunk-ZKFCDVB4.js} +16 -7
- package/dist/chunk-ZKFCDVB4.js.map +1 -0
- package/dist/cms-theme.css +29 -0
- package/dist/contact-form/index.d.ts +220 -0
- package/dist/contact-form/index.js +16 -0
- package/dist/contact-form/index.js.map +1 -0
- package/dist/content-block/index.d.ts +39 -4
- package/dist/content-block/index.js +8 -4
- package/dist/cookie-consent/index.d.ts +60 -12
- package/dist/cookie-consent/index.js +3 -2
- package/dist/date-tile/index.js +2 -2
- package/dist/dropdown/index.d.ts +29 -11
- package/dist/dropdown/index.js +4 -2
- package/dist/feature-split/index.d.ts +6 -1
- package/dist/feature-split/index.js +5 -4
- package/dist/features-section/index.d.ts +53 -9
- package/dist/features-section/index.js +6 -5
- package/dist/flow/index.d.ts +35 -0
- package/dist/flow/index.js +9 -0
- package/dist/flow/index.js.map +1 -0
- package/dist/footer/index.d.ts +13 -0
- package/dist/footer/index.js +2 -2
- package/dist/header/index.d.ts +135 -16
- package/dist/header/index.js +3 -2
- package/dist/hero/index.d.ts +92 -8
- package/dist/hero/index.js +6 -3
- package/dist/icon-button/index.d.ts +7 -7
- package/dist/icon-button/index.js +2 -2
- package/dist/index.d.ts +12 -3
- package/dist/index.js +121 -47
- package/dist/items-accordion/index.d.ts +9 -0
- package/dist/items-accordion/index.js +4 -3
- package/dist/kpi-card/index.js +2 -2
- package/dist/markdown/index.d.ts +19 -2
- package/dist/markdown/index.js +3 -2
- package/dist/mega-menu/index.d.ts +95 -7
- package/dist/mega-menu/index.js +7 -2
- package/dist/menu-grid/index.d.ts +2 -3
- package/dist/menu-grid/index.js +2 -2
- package/dist/menu-grid-item/index.d.ts +6 -8
- package/dist/menu-grid-item/index.js +2 -2
- package/dist/menu-item/index.d.ts +11 -7
- package/dist/menu-item/index.js +3 -2
- package/dist/plan-cards/index.d.ts +69 -0
- package/dist/plan-cards/index.js +13 -0
- package/dist/plan-cards/index.js.map +1 -0
- package/dist/product-nav/index.d.ts +127 -0
- package/dist/product-nav/index.js +11 -0
- package/dist/product-nav/index.js.map +1 -0
- package/dist/promo-banner/index.d.ts +42 -4
- package/dist/promo-banner/index.js +6 -3
- package/dist/quote-dialog/index.d.ts +174 -0
- package/dist/quote-dialog/index.js +22 -0
- package/dist/quote-dialog/index.js.map +1 -0
- package/dist/schema/index.d.ts +11 -0
- package/dist/schema/index.js +9 -0
- package/dist/schema/index.js.map +1 -1
- package/dist/screenshot-tour/index.d.ts +54 -0
- package/dist/screenshot-tour/index.js +9 -0
- package/dist/screenshot-tour/index.js.map +1 -0
- package/dist/section/index.d.ts +3 -0
- package/dist/section/index.js +3 -3
- package/dist/segmented-control/index.js +2 -2
- package/dist/select/index.js +2 -2
- package/dist/shared/styles.d.ts +7 -1
- package/dist/shared/styles.js +3 -1
- package/dist/stats/index.js +2 -2
- package/dist/steps/index.d.ts +45 -0
- package/dist/steps/index.js +11 -0
- package/dist/steps/index.js.map +1 -0
- package/dist/tag-strip/index.d.ts +33 -0
- package/dist/tag-strip/index.js +9 -0
- package/dist/tag-strip/index.js.map +1 -0
- package/dist/testimonials/index.d.ts +9 -1
- package/dist/testimonials/index.js +3 -3
- package/dist/tooltip/index.js +2 -2
- package/package.json +38 -2
- package/dist/chunk-5EBWMPJS.js.map +0 -1
- package/dist/chunk-76AVBQUA.js +0 -252
- package/dist/chunk-76AVBQUA.js.map +0 -1
- package/dist/chunk-7NLZND6Q.js.map +0 -1
- package/dist/chunk-ALI26WOB.js.map +0 -1
- package/dist/chunk-BMHMNXIA.js +0 -158
- package/dist/chunk-BMHMNXIA.js.map +0 -1
- package/dist/chunk-DH53HZPB.js.map +0 -1
- package/dist/chunk-EMCQBT3S.js.map +0 -1
- package/dist/chunk-FLY7TNRT.js.map +0 -1
- package/dist/chunk-FZ36KL73.js.map +0 -1
- package/dist/chunk-GJO3RGOB.js.map +0 -1
- package/dist/chunk-J6EO4R73.js +0 -633
- package/dist/chunk-J6EO4R73.js.map +0 -1
- package/dist/chunk-JKBWZLG4.js +0 -348
- package/dist/chunk-JKBWZLG4.js.map +0 -1
- package/dist/chunk-JQY2G4QK.js.map +0 -1
- package/dist/chunk-KMU6ABQF.js.map +0 -1
- package/dist/chunk-LEXZKGQX.js.map +0 -1
- package/dist/chunk-MSSH3HFK.js +0 -205
- package/dist/chunk-MSSH3HFK.js.map +0 -1
- package/dist/chunk-R5G6KFTJ.js.map +0 -1
- package/dist/chunk-SMLR736E.js.map +0 -1
- package/dist/chunk-VWS53WY4.js +0 -157
- package/dist/chunk-VWS53WY4.js.map +0 -1
- package/dist/chunk-WT4OATGP.js.map +0 -1
- package/dist/chunk-XWB4CKDU.js +0 -708
- package/dist/chunk-XWB4CKDU.js.map +0 -1
- package/dist/chunk-YQ42EBK5.js.map +0 -1
- package/dist/chunk-ZN4LIKVG.js.map +0 -1
- /package/dist/{chunk-AKJQ345O.js.map → chunk-5AWGZQWU.js.map} +0 -0
- /package/dist/{chunk-BLQV2YMO.js.map → chunk-EZOKT7NJ.js.map} +0 -0
- /package/dist/{chunk-6D6ROU7X.js.map → chunk-IGMVF3KK.js.map} +0 -0
- /package/dist/{chunk-INMSEYT6.js.map → chunk-IVPVYVWG.js.map} +0 -0
- /package/dist/{chunk-35TX3AOA.js.map → chunk-NABSRUXG.js.map} +0 -0
- /package/dist/{chunk-MG2VTZA4.js.map → chunk-QS3ANOWN.js.map} +0 -0
- /package/dist/{chunk-FML6AG2V.js.map → chunk-RANC3OI6.js.map} +0 -0
- /package/dist/{chunk-YVTFQHVY.js.map → chunk-TEAZZPDQ.js.map} +0 -0
- /package/dist/{chunk-AG2COC64.js.map → chunk-VVYQ2DDS.js.map} +0 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/header/Header.ts"],"sourcesContent":["import { LitElement, css, html, nothing } from 'lit';\nimport { customElement, property, state } from 'lit/decorators.js';\n\nimport { chevronIcon, closeIcon, menuIcon } from '../shared/icons';\nimport { setModalOpen } from '../shared/modal-state';\nimport { BREAKPOINT_TABLET, buttonResetStyles, controlBaseStyles, dropdownPanelStyles, rootFontFamilyStyles } from '../shared/styles';\nimport type { LanguageChangedEventDetail } from './HeaderEvents';\n\n/** The nav elements that take the header's `currentPath`: their own link is current, or (dropdowns) one inside is. */\nconst NAV_SELECTOR = 'st-menu-item, st-mega-menu-column, st-mega-menu-feature, st-dropdown';\n\n/** Height of the bar in context mode. The context trigger counts as passed once its bottom is above this line. */\nconst CONTEXT_BAR_HEIGHT = 64;\n\n/** What a keyboard user can tab to. */\nconst FOCUSABLE_SELECTOR =\n 'a[href], button:not([disabled]), input:not([disabled]), select:not([disabled]), textarea:not([disabled]), [tabindex]:not([tabindex=\"-1\"])';\n\n/** Whether an element is laid out and not hidden by `visibility` (on itself or an ancestor). */\nfunction isRendered(el: Element): boolean {\n if (el.getClientRects().length === 0) return false;\n const check = (el as Element & { checkVisibility?: (options?: { visibilityProperty?: boolean }) => boolean }).checkVisibility;\n return check ? check.call(el, { visibilityProperty: true }) : true;\n}\n\n/**\n * The focusable elements at and below `roots` that are rendered, in document order. Looks into open\n * shadow roots and follows each `<slot>` to the elements it shows, so slotted content counts where it lands.\n */\nfunction renderedFocusables(roots: Element[]): HTMLElement[] {\n const found = new Set<HTMLElement>();\n const visit = (el: Element): void => {\n if (el instanceof HTMLSlotElement) {\n for (const assigned of el.assignedElements({ flatten: true })) visit(assigned);\n return;\n }\n if (el.matches(FOCUSABLE_SELECTOR) && isRendered(el)) found.add(el as HTMLElement);\n const children = el.shadowRoot ? el.shadowRoot.children : el.children;\n for (const child of Array.from(children)) visit(child);\n };\n roots.forEach(visit);\n return [...found];\n}\n\n/** The focused element, looking through open shadow roots (`document.activeElement` stops at the host). */\nfunction deepActiveElement(): Element | null {\n let el: Element | null = document.activeElement;\n while (el?.shadowRoot?.activeElement) el = el.shadowRoot.activeElement;\n return el;\n}\n\n/** How long the header keeps looking for a `context-trigger` element the page has not rendered yet. */\nconst CONTEXT_TRIGGER_TIMEOUT_MS = 5000;\n\n/** Set on `<html>` while the header's drawer (the mobile menu or a site-menu request) is open. The cookie banner steps aside for it. */\nconst DRAWER_OPEN_ATTRIBUTE = 'data-st-drawer-open';\n\n/**\n * The app-shell header bar — brand (image + title, or title alone) on the left, a `slot=\"menu\"`\n * for primary nav (e.g. `st-dropdown`/`st-menu-grid` mega-menus, or plain links) taking the\n * middle, and a `slot=\"utility\"` for account/app-switcher/theme controls on the right. `title` is\n * the primary brand prop; `brand-image-url` is optional. For a fixed nav-links/user-menu header,\n * use `st-app-header` instead.\n *\n * The nav link for the page being shown is marked: `current-path` (e.g. `/t-pilot`) is compared\n * with each `st-menu-item`/`st-mega-menu-column`/`st-mega-menu-feature` `href` (and a mega column's\n * `cta-href`). A link is current when it equals the path, or, for a non-root href, when the path is\n * beneath it; `/` is current only on `/`. The current link gets `aria-current=\"page\"`, and an\n * `st-dropdown` containing one is highlighted as active. Without `current-path` the header uses\n * `location.pathname`, re-checked on `popstate`; a single-page app should set `current-path`\n * on each navigation (the React `Header` does this from the router).\n *\n * Layout: the menu starts 4rem after the brand, the utility\n * controls sit after a vertical divider, and below `BREAKPOINT_TABLET` (900px) `menu`/`utility`\n * collapse behind a hamburger toggle into a full-screen layer under the\n * toggle (closes on Escape or a click inside it), where the menu's `st-dropdown`s are switched to\n * `inline` so they open in the flow — the same two slotted elements just get repositioned by CSS\n * (`.mobile-panel`'s `display: contents` at desktop width vs. a real fixed-position box below\n * `BREAKPOINT_TABLET`), rather than the slots being duplicated in the template, since a shadow\n * root can only ever assign a given light-DOM child to the *first* slot of a given name.\n *\n * An optional `slot=\"brand-extra\"` sits right after the brand (e.g. an edition badge such as\n * \"🇮🇳 India Edition\"); unlike `menu`/`utility` it stays in the bar at every width.\n *\n * Also carries an optional built-in language switcher (`languages`/`currentLanguageCode`, fires\n * `language-change`). Hidden entirely when `languages` has fewer than two entries.\n * This component has no translation logic itself; the consuming app owns what a language `code`\n * means and which content it re-renders in response.\n *\n * Context mode (opt-in): set `context-trigger` to a CSS selector for a page element (typically the\n * hero) and give the header a `slot=\"context\"` child (e.g. an `st-product-nav` with `embedded` and\n * `scroll-spy`). Once the trigger element has scrolled up past the bar, the bar swaps its menu for\n * the slotted context content. Scrolling back above the trigger restores the menu. Both rows share the\n * same 64px box, so the header never changes height, and the bar is solid while the context row shows,\n * even when `transparent`. With no `context-trigger`, or no `slot=\"context\"` content, the header is\n * unchanged. An open mobile menu closes when the context row takes over. `context-active` reflects the\n * state; `header-context-change` fires on every switch (detail `{ active }`).\n *\n * In context mode, the slotted product nav's site-menu button (`product-nav-site-menu`) opens this\n * header's site menu over the bar, at every width. The bar keeps its state: the context row stays\n * visible underneath (made inert), and only the drawer, its close button and a backdrop (above 768px)\n * are shown on top. `st-cookie-consent` steps aside while the drawer is open (see `setModalOpen`). Esc,\n * the close button, a click outside the bar, or activating a link in the drawer closes it and returns\n * focus to that button.\n *\n * On a narrow screen the open drawer covers the whole viewport and locks page scroll. It sets\n * `data-st-drawer-open` on `<html>`, holds keyboard focus (Tab wraps, Esc closes, focus returns to the\n * toggle), and shows the brand and, with `cta-label` + `cta-href`, a primary call to action above the\n * menu, which sits before the theme toggle on desktop.\n *\n * @slot menu - Primary navigation.\n * @slot context - Product sub-nav shown in place of the menu in context mode (see above). Its children get `inert` while the context row is hidden or a site-menu drawer is open.\n * @slot utility - Account, app-switcher and theme controls, after the divider.\n * @slot brand-extra - Shown right after the brand at every width (e.g. an edition badge).\n * @slot menu-icon - Replaces the hamburger on the narrow-screen toggle (the built-in glyph when empty).\n * @slot close-icon - Replaces the close (X) on the toggle while the menu is open (the built-in glyph when empty).\n * @cssprop --st-header-toggle-icon-size - Width and height of a slotted toggle icon (default 20px, the built-in glyph's size).\n * @fires header-context-change - Fired when the bar switches to or from the context row. Detail: `{ active: boolean }`. Bubbles, composed.\n * @csspart mobile-panel - The menu and utility panel (the full-screen layer under the hamburger below 900px, and the site menu in context mode).\n */\n@customElement('st-header')\nexport class Header extends LitElement {\n static styles = css`\n ${controlBaseStyles}\n\n :host {\n display: flex;\n align-items: center;\n /* The containing block of an st-dropdown[mega] panel, which spans the bar. */\n position: relative;\n /* Spacing between brand, menu and utility controls is the rows' own margins, not a\n flex gap. */\n gap: 0;\n /* !important on the box-model properties only: a shadow host's own :host rule always loses\n * to ANY rule the consuming page has for the same property on that element, regardless of\n * specificity (see st-footer's own padding/border-top for the same fix). Without\n * box-sizing: border-box pinned here, a page that also sets its own padding on this host\n * (e.g. a p-2 utility class) adds that padding on TOP of the fixed 64px height instead of\n * being absorbed inside it — which is exactly what happens in Template Hub, the one app that\n * doesn't load Tailwind Preflight (Preflight's own box-sizing: border-box reset is what\n * silently keeps every other app's header at the intended 64px). */\n box-sizing: border-box !important;\n padding: 0 2rem !important;\n height: 64px !important;\n background: var(--st-color-surface);\n border-bottom: 1px solid var(--st-color-border) !important;\n ${rootFontFamilyStyles}\n color: var(--st-color-text-strong);\n }\n\n :host([sticky]) {\n position: sticky;\n top: 0;\n z-index: 100;\n }\n\n /* Toggle icons: a host's slotted icon, else the built-in glyph; only the current state's shows. */\n .toggle slot {\n display: contents;\n }\n\n .toggle slot[hidden] {\n display: none;\n }\n\n .toggle ::slotted(*) {\n flex: none;\n width: var(--st-header-toggle-icon-size, 20px);\n height: var(--st-header-toggle-icon-size, 20px);\n }\n\n :host([inverted]) {\n background: var(--st-color-text-strong);\n color: var(--st-color-on-solid);\n border-bottom-color: transparent;\n }\n\n :host([sticky]),\n :host([transparent]),\n :host([hide-on-scroll]) {\n transition:\n background-color 0.3s ease,\n color 0.3s ease,\n box-shadow 0.3s ease,\n border-color 0.3s ease,\n transform 0.3s ease;\n }\n\n /* Once the page has scrolled, a sticky/fixed header lifts off the content. */\n :host([scrolled][sticky]),\n :host([scrolled][transparent]),\n :host([scrolled][hide-on-scroll]) {\n box-shadow: 0 4px 16px var(--st-shadow-color-md);\n border-bottom-color: transparent !important;\n }\n\n /* transparent: fixed over the top of the page (e.g. a dark hero), see-through until scrolled. */\n :host([transparent]) {\n position: fixed;\n top: 0;\n left: 0;\n right: 0;\n z-index: 100;\n }\n\n :host([transparent]:not([scrolled]):not([mobile-open])) {\n background: transparent;\n border-bottom-color: transparent !important;\n color: var(--st-header-transparent-color, var(--st-color-on-solid));\n /* Read by st-menu-item / st-dropdown triggers in the bar (their panels reset them). */\n --st-nav-color: var(--st-header-transparent-color, var(--st-color-on-solid));\n --st-nav-hover-bg: color-mix(in oklch, currentColor 14%, transparent);\n /* The current-page underline follows the bar's text colour here, since the accent may not read on a hero. */\n --st-nav-active-line: currentColor;\n }\n\n :host([transparent]:not([scrolled]):not([mobile-open])) .utility-row {\n border-left-color: color-mix(in oklch, currentColor 35%, transparent);\n }\n\n :host([transparent]:not([scrolled]):not([mobile-open])) .lang-trigger {\n color: inherit;\n }\n\n :host([transparent]:not([scrolled]):not([mobile-open])) .lang-trigger:hover,\n :host([transparent]:not([scrolled]):not([mobile-open])) .toggle:hover {\n background: color-mix(in oklch, currentColor 14%, transparent);\n }\n\n /* hide-on-scroll: slides away while scrolling down, back as soon as the user scrolls up. */\n :host([hide-on-scroll]:not([sticky]):not([transparent])) {\n position: sticky;\n top: 0;\n z-index: 100;\n }\n\n :host([scroll-hidden]:not([mobile-open])) {\n transform: translateY(-100%);\n box-shadow: none;\n }\n\n .brand {\n display: flex;\n align-items: center;\n gap: var(--st-space-10);\n flex: none;\n text-decoration: none;\n color: inherit;\n }\n\n .brand-mark {\n width: var(--st-size-28);\n height: var(--st-size-28);\n border-radius: var(--st-radius-sm);\n flex: none;\n object-fit: contain;\n }\n\n .brand-title {\n font-size: var(--st-text-xl);\n font-weight: var(--st-font-weight-bold);\n letter-spacing: var(--st-tracking-tight);\n white-space: nowrap;\n }\n\n /* Optional slot=\"brand-extra\" (e.g. an edition badge) right after the brand. Outside the\n mobile panel, so it stays beside the logo at every width; no box at all when empty. */\n .brand-extra {\n display: flex;\n align-items: center;\n gap: var(--st-space-8);\n flex: none;\n margin-left: var(--st-space-10);\n white-space: nowrap;\n }\n\n .brand-extra.empty {\n display: none;\n }\n\n /* Desktop: a transparent pass-through so .menu-row/.utility-row lay out directly as :host's\n own flex children. Mobile (see below) turns this into the actual overlay box. */\n .mobile-panel {\n display: contents;\n }\n\n /* Desktop layout: the menu starts 4rem after the brand and takes the\n free width; the utility controls sit after a vertical divider. Between 901px and 1200px the\n gaps tighten so the menu still fits down to the 900px hamburger breakpoint. */\n .menu-row {\n flex: 1;\n display: flex;\n align-items: center;\n gap: 1.5rem;\n min-width: 0;\n margin-left: 4rem;\n }\n\n .utility-row {\n flex: none;\n display: flex;\n align-items: center;\n gap: 1rem;\n margin-left: 1.5rem;\n padding-left: 1.5rem;\n border-left: 1px solid var(--st-color-border);\n }\n\n :host([inverted]) .utility-row {\n border-left-color: currentColor;\n }\n\n .utility-row.empty {\n display: none;\n }\n\n @media (max-width: 1200px) {\n :host {\n padding: 0 1rem !important;\n }\n\n .menu-row {\n margin-left: 0.5rem;\n }\n\n .utility-row {\n margin-left: 0.5rem;\n padding-left: 0.5rem;\n }\n }\n\n .toggle {\n display: none;\n align-items: center;\n justify-content: center;\n flex: none;\n position: relative;\n z-index: 1002;\n /* A 44px touch target; the glyph inside keeps its 20px size. */\n width: 44px;\n height: 44px;\n margin-left: auto;\n padding: 0.5rem;\n border: 0;\n border-radius: var(--st-radius-sm);\n background: transparent;\n color: inherit;\n cursor: pointer;\n }\n\n .toggle:hover {\n background: var(--st-color-hover);\n }\n\n .lang-menu {\n position: relative;\n flex: none;\n }\n\n .lang-trigger {\n ${buttonResetStyles}\n display: flex;\n align-items: center;\n gap: var(--st-space-4);\n height: var(--st-size-32);\n padding: 0 var(--st-space-8);\n border-radius: var(--st-radius-sm);\n font-size: var(--st-text-base);\n font-weight: var(--st-font-weight-semibold);\n color: var(--st-color-text-muted);\n }\n\n .lang-trigger:hover {\n background: var(--st-color-hover);\n color: var(--st-color-text-strong);\n }\n\n .lang-dropdown {\n ${dropdownPanelStyles}\n min-width: 140px;\n }\n\n .lang-option {\n ${buttonResetStyles}\n display: block;\n width: 100%;\n padding: var(--st-space-10) var(--st-space-14);\n font-size: var(--st-text-base);\n font-weight: var(--st-font-weight-semibold);\n text-align: left;\n color: inherit;\n }\n\n .lang-option:hover {\n background: var(--st-color-hover);\n }\n\n .lang-option.active {\n color: var(--st-color-accent-text);\n }\n\n /* Primary call to action in the utility row, before the theme toggle. Solid accent, so it reads on both themes. */\n .cta {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n flex: none;\n box-sizing: border-box;\n min-height: 44px;\n padding: 0 1.25rem;\n border-radius: 9999px;\n background: var(--st-color-accent);\n color: var(--st-color-on-solid);\n font-size: var(--st-text-base);\n font-weight: var(--st-font-weight-semibold);\n text-decoration: none;\n white-space: nowrap;\n }\n\n .cta:hover {\n background: color-mix(in oklch, var(--st-color-accent) 88%, var(--st-color-text-strong));\n }\n\n /* Hamburger layout: a full-screen layer under the toggle, menu above\n the utility controls, the menu's dropdowns opening in the flow (see syncInlineDropdowns). */\n @media (max-width: ${BREAKPOINT_TABLET}px) {\n :host {\n padding: 0 1rem !important;\n }\n\n .mobile-panel {\n display: none;\n }\n\n .toggle {\n display: inline-flex;\n }\n\n :host([mobile-open]) .mobile-panel {\n display: flex;\n flex-direction: column;\n gap: 2rem;\n position: fixed;\n inset: 0;\n background: var(--st-color-surface);\n padding: 0 1.5rem 2rem;\n overflow-y: auto;\n overscroll-behavior: contain;\n z-index: 1001;\n }\n\n :host([mobile-open]) .menu-row,\n :host([mobile-open]) .utility-row {\n flex-direction: column;\n align-items: stretch;\n gap: 1.5rem;\n margin-left: 0;\n }\n\n :host([mobile-open]) .utility-row {\n padding: 1.5rem 0 0;\n border-left: 0;\n border-top: 1px solid var(--st-color-border);\n }\n\n /* Apps usually slot one flex-row wrapper per slot; stack its items as the source does. */\n :host([mobile-open]) ::slotted([slot='menu']),\n :host([mobile-open]) ::slotted([slot='utility']) {\n flex-direction: column !important;\n align-items: stretch !important;\n margin: 0 !important;\n }\n }\n\n /* The same collapsed layout, switched on by script when the menu no longer fits the bar at\n desktop width (see evaluateFit) — without it the menu spills over the utility controls. A site-menu\n request (see openSiteMenu) switches it on the same way at every width. */\n :host([compact]) .mobile-panel {\n display: none;\n }\n\n :host([compact]) .toggle {\n display: inline-flex;\n }\n\n :host([compact][mobile-open]) .mobile-panel {\n display: flex;\n flex-direction: column;\n gap: 2rem;\n position: fixed;\n inset: 0;\n background: var(--st-color-surface);\n padding: 0 1.5rem 2rem;\n overflow-y: auto;\n overscroll-behavior: contain;\n z-index: 1001;\n }\n\n :host([compact][mobile-open]) .menu-row,\n :host([compact][mobile-open]) .utility-row {\n flex-direction: column;\n align-items: stretch;\n gap: 1.5rem;\n margin-left: 0;\n }\n\n :host([compact][mobile-open]) .utility-row {\n padding: 1.5rem 0 0;\n border-left: 0;\n border-top: 1px solid var(--st-color-border);\n }\n\n :host([compact][mobile-open]) ::slotted([slot='menu']),\n :host([compact][mobile-open]) ::slotted([slot='utility']) {\n flex-direction: column !important;\n align-items: stretch !important;\n margin: 0 !important;\n }\n\n /* Context mode. Without context content both layers are transparent wrappers (display: contents),\n so the header lays out exactly as before. With it, layer A (the site header) and layer B (the\n context row) share one grid cell, and the inactive one fades out and is hidden. */\n .layers,\n .layers .layer {\n display: contents;\n }\n\n .layers .layer-b {\n display: none;\n }\n\n /* A context-trigger bar is sticky by itself (a transparent one keeps its own fixed positioning). */\n :host([context-trigger]:not([transparent])) {\n position: sticky;\n top: 0;\n z-index: 100;\n }\n\n .layers.stacked {\n display: grid;\n flex: 1 1 auto;\n min-width: 0;\n height: 100%;\n }\n\n .layers.stacked .layer {\n grid-area: 1 / 1;\n display: flex;\n align-items: center;\n min-width: 0;\n height: 100%;\n opacity: 1;\n visibility: visible;\n /* Outgoing layer: fades out, and its visibility only drops once the fade has finished. */\n transition:\n opacity 180ms ease,\n visibility 0s linear 180ms;\n }\n\n /* Incoming layer: visible at once, then fades in. */\n .layers.stacked .layer.is-on {\n transition:\n opacity 180ms ease,\n visibility 0s linear 0s;\n }\n\n .layers.stacked .layer:not(.is-on) {\n opacity: 0;\n visibility: hidden;\n pointer-events: none;\n }\n\n /* Site-menu request (see openSiteMenu): layer A keeps only what the drawer needs. Its bar row is hidden\n by visibility, and its opacity is 1, since a faded ancestor would fade the drawer too. The drawer, the\n toggle (the close control) and the backdrop are shown again. Layer B stays visible underneath. */\n .layers.stacked .layer-a.drawer-only {\n opacity: 1;\n visibility: hidden;\n pointer-events: none;\n transition: none;\n }\n\n .layers.stacked .layer-a.drawer-only .mobile-panel,\n .layers.stacked .layer-a.drawer-only .toggle,\n .layers.stacked .layer-a.drawer-only .site-menu-backdrop {\n visibility: visible;\n pointer-events: auto;\n }\n\n .layers.stacked .layer-b {\n align-items: center;\n }\n\n .layers.stacked .layer-b slot {\n display: contents;\n }\n\n .layers.stacked .layer-b ::slotted(*) {\n flex: 1 1 auto;\n min-width: 0;\n }\n\n /* The context bar is solid, even when the header is transparent over a hero. */\n :host([context-active]) {\n background: var(--st-color-surface) !important;\n border-bottom-color: var(--st-color-border) !important;\n color: var(--st-color-text-strong) !important;\n }\n\n /* Site-menu request (see openSiteMenu). The drawer's top row carries the brand, aligned with the bar's\n 64px row, so the toggle sits beside it. The drawer is a right-side panel over a backdrop above 768px;\n below that it stays the full-screen drawer. Only a request uses these rules, not normal mobile use. */\n .drawer-head {\n display: none;\n }\n\n /* The drawer's own top row: the brand, on the bar's row. Pulled back to the bar's 1rem edge, where the toggle sits. */\n :host([mobile-open]) .drawer-head {\n display: flex;\n align-items: center;\n flex: none;\n height: 64px;\n min-width: 0;\n margin: 0 -0.5rem;\n }\n\n :host([site-menu-request][compact][mobile-open]) .mobile-panel {\n padding: 0 1.5rem 2rem;\n }\n\n .site-menu-backdrop {\n display: none;\n }\n\n @media (min-width: 769px) {\n :host([site-menu-request][compact][mobile-open]) .mobile-panel {\n inset: 0 0 0 auto;\n width: min(400px, 100vw);\n height: 100%;\n box-shadow: -8px 0 24px var(--st-shadow-color-md);\n animation: st-header-slide-in 200ms ease;\n }\n\n :host([site-menu-request]) .site-menu-backdrop {\n display: block;\n position: fixed;\n inset: 0;\n z-index: 1000;\n background: rgba(1, 29, 65, 0.45);\n }\n }\n\n @keyframes st-header-slide-in {\n from {\n transform: translateX(100%);\n }\n to {\n transform: none;\n }\n }\n\n @media (prefers-reduced-motion: reduce) {\n .layers.stacked .layer {\n transition: none !important;\n }\n }\n\n @media (prefers-reduced-motion: reduce) {\n :host,\n .mobile-panel {\n animation: none !important;\n transition: none !important;\n }\n }\n `;\n\n @property({ type: String })\n title = '';\n\n /** Optional logo image URL, shown before `title`. Omitted entirely when empty — none of this suite's apps has one today. Matches the source component's `imageSrc` (renamed here to pair with `title`/`logoHref`, since this component's only image use is the brand mark). */\n @property({ type: String, attribute: 'brand-image-url' })\n brandImageUrl = '';\n\n /** Path of the page being shown (e.g. `/t-pilot`). Marks the matching nav link as current; falls back to `location.pathname` when empty. */\n @property({ type: String, attribute: 'current-path' })\n currentPath = '';\n\n /** `alt` text for the brand image — matches the source component's `altText` (default `'Logo'`). */\n @property({ type: String, attribute: 'alt-text' })\n altText = 'Logo';\n\n /** Wraps the brand in an `<a>` when set (e.g. `/`); a plain non-link `<div>` otherwise. */\n @property({ type: String })\n logoHref = '';\n\n /** `target` for the brand `<a>` — matches the source component's `logoTarget` (default `_self`). No effect when `logoHref` isn't set. */\n @property({ type: String, attribute: 'logo-target' })\n logoTarget = '_self';\n\n /** Extra class(es) appended to the brand link/div — matches the source component's `logoClassName`. */\n @property({ type: String, attribute: 'logo-class-name' })\n logoClassName = '';\n\n /** Inverts the header's color roles (light-on-dark instead of dark-on-light) — matches the\n * source component's `inverted` (from its shared `BaseProps`). */\n @property({ type: Boolean, reflect: true })\n inverted = false;\n\n @property({ type: Boolean, reflect: true })\n sticky = false;\n\n /**\n * Fixes the header over the top of the page and makes it see-through, with light text\n * (`--st-header-transparent-color`), until the page scrolls past `scroll-threshold` — for a\n * header laid over a dark hero. It then takes its normal background and a shadow. The page\n * content starts under it, so the first section should leave room for the 64px bar.\n */\n @property({ type: Boolean, reflect: true })\n transparent = false;\n\n /** Slides the header out of view while the page scrolls down and back in when it scrolls up. */\n @property({ type: Boolean, reflect: true, attribute: 'hide-on-scroll' })\n hideOnScroll = false;\n\n /** Scroll distance in px after which the header counts as `scrolled`. */\n @property({ type: Number, attribute: 'scroll-threshold' })\n scrollThreshold = 8;\n\n /** True once the page has scrolled past `scroll-threshold`; reflected so pages can style `st-header[scrolled]`. Set by the header, never from outside. */\n @property({ type: Boolean, reflect: true })\n scrolled = false;\n\n /** True while `hide-on-scroll` has slid the header away. Set by the header, never from outside. */\n @property({ type: Boolean, reflect: true, attribute: 'scroll-hidden' })\n scrollHidden = false;\n\n private lastScrollY = 0;\n private scrollFrame = 0;\n\n /** The `<html>` overflow and padding to restore when the drawer closes; null while the page is not locked. */\n private drawerScrollLock: { overflow: string; paddingRight: string } | null = null;\n\n private onScroll = (): void => {\n if (this.scrollFrame) return;\n this.scrollFrame = requestAnimationFrame(() => {\n this.scrollFrame = 0;\n const y = Math.max(0, window.scrollY);\n this.scrolled = y > this.scrollThreshold;\n if (this.hideOnScroll) {\n const delta = y - this.lastScrollY;\n // Ignore tiny jitters; never hide while still at the top of the page or with the menu open.\n if (Math.abs(delta) > 4) this.scrollHidden = delta > 0 && y > this.offsetHeight && !this.mobileOpen;\n } else {\n this.scrollHidden = false;\n }\n this.lastScrollY = y;\n });\n };\n\n /**\n * Language switcher options, e.g. `[{ code: 'en', label: 'English' }, ...]` — hidden entirely\n * when empty or when only one language is offered (same convention as `st-app-header`'s\n * `languages`, which this reuses verbatim). This component has no translation logic itself —\n * selecting an option fires `language-change` (detail: `{ code }`), and the consuming app owns\n * what `code` actually means and which content it re-renders.\n */\n @property({ attribute: false })\n languages: { code: string; label: string }[] = [];\n\n @property({ type: String, attribute: 'current-language-code' })\n currentLanguageCode = '';\n\n @property({ type: String, attribute: 'language-menu-label' })\n languageMenuLabel = 'Language';\n\n /** Internal open/closed state for the mobile nav overlay, reflected to an attribute purely so\n * the `:host([mobile-open])` CSS selector above can react to it — not meant to be set from\n * outside. */\n @property({ type: Boolean, reflect: true, attribute: 'mobile-open' })\n mobileOpen = false;\n\n /** True while the menu doesn't fit the bar at the current width: the header then shows the same\n * hamburger layout it uses on a narrow screen. Set by `evaluateFit`, never from outside. */\n @property({ type: Boolean, reflect: true })\n compact = false;\n\n /** Label of an optional primary call to action in the utility row, before the theme toggle. Hidden when empty (also needs `cta-href`). */\n @property({ type: String, attribute: 'cta-label' })\n ctaLabel = '';\n\n /** Target of the call to action. Hidden when empty (also needs `cta-label`). */\n @property({ type: String, attribute: 'cta-href' })\n ctaHref = '';\n\n @state() private languageMenuOpen = false;\n\n /** Whether `slot=\"utility\"` has content — an empty utility row (and its divider) is hidden. */\n @state() private hasUtility = false;\n\n /** Whether `slot=\"brand-extra\"` has content — an empty one takes no room beside the brand. */\n @state() private hasBrandExtra = false;\n\n /**\n * CSS selector of a page element (e.g. `#hero`). Once it has scrolled up past the bar, the bar\n * shows the context row instead of its menu. Empty (the default) turns context mode off. The\n * selector is re-queried for up to 5s if the element is not rendered yet, and again whenever it changes.\n */\n @property({ type: String, attribute: 'context-trigger' })\n contextTrigger = '';\n\n /** True while the page is past the trigger, so the context row shows. A site-menu drawer opened over it leaves it showing. Set by the header from the trigger's position, never from outside. */\n @property({ type: Boolean, reflect: true, attribute: 'context-active' })\n contextActive = false;\n\n /** Whether `slot=\"context\"` has content. */\n @state() private hasContext = false;\n\n /** True while a site-menu request from the slotted product nav has its drawer open over the bar (see openSiteMenu). */\n @state() private siteMenuRequested = false;\n\n /** The product nav's site-menu button that asked for the menu; focus returns to it when the menu closes. */\n private siteMenuTrigger: HTMLElement | null = null;\n\n /** Whether the trigger element has scrolled up past the bar. */\n private pastTrigger = false;\n\n private triggerObserver?: IntersectionObserver;\n\n private triggerMutations?: MutationObserver;\n\n private triggerTimer = 0;\n\n private resizeObserver?: ResizeObserver;\n\n /** Matches below BREAKPOINT_TABLET, where the hamburger layout is always on. */\n private narrowQuery?: MediaQueryList;\n\n /** The dropdowns this header switched to `inline` — only these are switched back, so a caller's\n * own `inline` setting is left alone. */\n private inlinedDropdowns = new Set<HTMLElement & { inline: boolean; open: boolean }>();\n\n /** While the hamburger layout is on, the dropdowns in the header open in the flow of the\n * full-screen panel instead of floating over it (the touch-device layout). */\n private syncInlineDropdowns = (): void => {\n const collapsed = this.compact || !!this.narrowQuery?.matches;\n const dropdowns = Array.from(this.querySelectorAll('st-dropdown')) as (HTMLElement & { inline: boolean; open: boolean })[];\n if (collapsed) {\n for (const dropdown of dropdowns) {\n if (dropdown.inline) continue;\n dropdown.inline = true;\n this.inlinedDropdowns.add(dropdown);\n }\n } else {\n for (const dropdown of this.inlinedDropdowns) dropdown.inline = false;\n this.inlinedDropdowns.clear();\n }\n };\n\n private onBrandExtraSlotChange = (event: Event): void => {\n this.hasBrandExtra = (event.target as HTMLSlotElement).assignedElements({ flatten: true }).length > 0;\n this.evaluateFit();\n };\n\n private onUtilitySlotChange = (event: Event): void => {\n this.hasUtility = (event.target as HTMLSlotElement).assignedElements({ flatten: true }).length > 0;\n this.evaluateFit();\n };\n\n private onMenuSlotChange = (): void => {\n this.evaluateFit();\n this.syncInlineDropdowns();\n this.syncCurrentPath();\n };\n\n /** Hands the current page path to every nav element under the header, which marks its own link current. */\n private syncCurrentPath = (): void => {\n const path = this.currentPath || window.location.pathname;\n // requestUpdate: a dropdown's `current` also depends on links added to its panel later, which\n // the path alone would not re-check.\n for (const el of this.querySelectorAll<HTMLElement & { currentPath: string; requestUpdate(): void }>(NAV_SELECTOR)) {\n el.currentPath = path;\n el.requestUpdate();\n }\n };\n\n /** Runs when the light DOM changes: a late-rendered dropdown or nav item needs the same state as the rest. */\n private onLightDomChange = (): void => {\n this.syncInlineDropdowns();\n this.syncCurrentPath();\n };\n\n /** Re-watches the trigger when `context-trigger` changes (before render, so state changes don't re-render twice). */\n protected willUpdate(changed: Map<string, unknown>): void {\n if (changed.has('contextTrigger')) this.startContextTrigger();\n }\n\n protected updated(changed: Map<string, unknown>): void {\n // Scopes the site-menu drawer styles (right-side panel above 768px) to a site-menu request only.\n this.toggleAttribute('site-menu-request', this.siteMenuRequested);\n this.syncContextSlot();\n this.syncSiteMenuOpen();\n if (changed.has('currentPath')) this.syncCurrentPath();\n if (changed.has('compact')) this.syncInlineDropdowns();\n if (changed.has('mobileOpen')) this.syncDrawerOpen();\n if (changed.has('mobileOpen') && !this.mobileOpen) {\n // A mega dropdown's drill-down panel would otherwise still cover the menu next time it opens.\n for (const dropdown of this.inlinedDropdowns) dropdown.open = false;\n // Esc, the toggle, a click outside the bar or a link in the drawer all close it; a site-menu request ends here too.\n this.endSiteMenu(true);\n }\n }\n\n /**\n * Keeps the page in step with the drawer: `<html data-st-drawer-open>` (which the cookie banner reads) and\n * a scroll lock. The lock gives back the scrollbar's width, so the page does not shift sideways. Opening\n * moves focus to the first item in the drawer; a site-menu request focuses its close button instead.\n */\n private syncDrawerOpen(): void {\n const root = document.documentElement;\n root.toggleAttribute(DRAWER_OPEN_ATTRIBUTE, this.mobileOpen);\n if (!this.mobileOpen) {\n this.unlockScroll();\n return;\n }\n if (!this.drawerScrollLock) {\n const scrollbarWidth = window.innerWidth - root.clientWidth;\n this.drawerScrollLock = { overflow: root.style.overflow, paddingRight: root.style.paddingRight };\n root.style.overflow = 'hidden';\n if (scrollbarWidth > 0) root.style.paddingRight = `${scrollbarWidth}px`;\n }\n if (!this.siteMenuRequested) void this.updateComplete.then(() => this.drawerFocusables()[0]?.focus({ preventScroll: true }));\n }\n\n private unlockScroll(): void {\n if (!this.drawerScrollLock) return;\n const root = document.documentElement;\n root.style.overflow = this.drawerScrollLock.overflow;\n root.style.paddingRight = this.drawerScrollLock.paddingRight;\n this.drawerScrollLock = null;\n }\n\n /** What a keyboard user can reach in the open drawer, in order: its own items, then the toggle that closes it. */\n private drawerFocusables(): HTMLElement[] {\n const panel = this.renderRoot.querySelector<HTMLElement>('.mobile-panel');\n const toggle = this.renderRoot.querySelector<HTMLElement>('.toggle');\n return renderedFocusables([panel, toggle].filter((el): el is HTMLElement => el !== null));\n }\n\n /** Keeps Tab and Shift+Tab inside the open drawer, wrapping at either end (and pulling in focus that has left it). */\n private trapDrawerFocus(event: KeyboardEvent): void {\n const items = this.drawerFocusables();\n if (items.length === 0) return;\n const first = items[0];\n const last = items[items.length - 1];\n const active = deepActiveElement();\n const inside = active !== null && items.includes(active as HTMLElement);\n if (event.shiftKey) {\n if (!inside || active === first) {\n event.preventDefault();\n last.focus({ preventScroll: true });\n }\n } else if (!inside || active === last) {\n event.preventDefault();\n first.focus({ preventScroll: true });\n }\n }\n\n /**\n * Closes the drawer and returns focus to its toggle. A site-menu request returns focus to the product\n * nav's button instead (see endSiteMenu).\n */\n private closeDrawer(): void {\n if (!this.mobileOpen) return;\n this.mobileOpen = false;\n if (!this.siteMenuRequested) this.renderRoot.querySelector<HTMLElement>('.toggle')?.focus({ preventScroll: true });\n }\n\n /** The bar width at which the menu last overflowed — the bar only expands again once it is\n * clearly wider than this, so it can't flip back and forth right at the threshold. */\n private collapsedAtWidth = 0;\n\n /** Collapses to the hamburger layout when the slotted menu overflows its row, and expands again\n * once there is room. The collapsed layout hides the menu, so the room it needs can't be\n * measured then; the width remembered when it collapsed stands in for it. */\n private evaluateFit = (): void => {\n // A site-menu request forces the collapsed layout until it ends (see openSiteMenu).\n if (this.siteMenuRequested) return;\n const width = this.clientWidth;\n if (this.compact) {\n if (width > this.collapsedAtWidth + 24) {\n this.compact = false;\n this.mobileOpen = false;\n void this.updateComplete.then(this.evaluateFit);\n }\n return;\n }\n if (this.menuOverflows()) {\n this.collapsedAtWidth = width;\n this.compact = true;\n }\n };\n\n /** Whether the visible menu items reach past the right edge of the menu row. Measured from the\n * items' own boxes (the slotted elements and their direct children), not the row's scrollWidth:\n * a closed dropdown's absolutely positioned panel also counts towards scrollWidth, which would\n * report overflow at any width. */\n private menuOverflows(): boolean {\n const row = this.renderRoot.querySelector<HTMLElement>('.menu-row');\n const slot = this.renderRoot.querySelector<HTMLSlotElement>('slot[name=\"menu\"]');\n if (!row || !slot) return false;\n const limit = row.getBoundingClientRect().right + 1;\n let right = 0;\n for (const el of slot.assignedElements({ flatten: true })) {\n for (const box of [el, ...Array.from(el.children)]) {\n const rect = box.getBoundingClientRect();\n if (rect.width > 0) right = Math.max(right, rect.right);\n }\n }\n return right > limit;\n }\n\n protected firstUpdated(): void {\n this.resizeObserver = new ResizeObserver(this.evaluateFit);\n this.resizeObserver.observe(this);\n this.evaluateFit();\n this.syncInlineDropdowns();\n this.syncCurrentPath();\n }\n\n connectedCallback(): void {\n super.connectedCallback();\n window.addEventListener('keydown', this.onKeyDown);\n window.addEventListener('click', this.closeLanguageMenuOnOutsideClick);\n window.addEventListener('click', this.closeSiteMenuOnOutsideClick);\n this.addEventListener('product-nav-site-menu', this.onSiteMenuRequest);\n window.addEventListener('scroll', this.onScroll, { passive: true });\n window.addEventListener('popstate', this.syncCurrentPath);\n this.onScroll();\n this.narrowQuery = window.matchMedia(`(max-width: ${BREAKPOINT_TABLET}px)`);\n this.narrowQuery.addEventListener('change', this.syncInlineDropdowns);\n // Menus often render their dropdowns after the header (e.g. once the user's role loads),\n // deeper than a slotchange reports.\n this.lightDomObserver = new MutationObserver(this.onLightDomChange);\n this.lightDomObserver.observe(this, { childList: true, subtree: true });\n this.startContextTrigger();\n }\n\n private lightDomObserver?: MutationObserver;\n\n disconnectedCallback(): void {\n this.lightDomObserver?.disconnect();\n this.stopContextTrigger();\n setModalOpen(this, false);\n document.documentElement.removeAttribute(DRAWER_OPEN_ATTRIBUTE);\n this.unlockScroll();\n this.narrowQuery?.removeEventListener('change', this.syncInlineDropdowns);\n this.resizeObserver?.disconnect();\n window.removeEventListener('keydown', this.onKeyDown);\n window.removeEventListener('click', this.closeLanguageMenuOnOutsideClick);\n window.removeEventListener('click', this.closeSiteMenuOnOutsideClick);\n this.removeEventListener('product-nav-site-menu', this.onSiteMenuRequest);\n window.removeEventListener('scroll', this.onScroll);\n window.removeEventListener('popstate', this.syncCurrentPath);\n if (this.scrollFrame) cancelAnimationFrame(this.scrollFrame);\n this.scrollFrame = 0;\n super.disconnectedCallback();\n }\n\n /** Esc closes the open drawer; Tab is held inside it while it is open. */\n private onKeyDown = (event: KeyboardEvent): void => {\n if (this.mobileOpen) {\n if (event.key === 'Escape') this.closeDrawer();\n else if (event.key === 'Tab') this.trapDrawerFocus(event);\n }\n if (this.languageMenuOpen && event.key === 'Escape') this.languageMenuOpen = false;\n };\n\n private closeLanguageMenuOnOutsideClick = (event: Event): void => {\n if (this.languageMenuOpen && !event.composedPath().includes(this)) this.languageMenuOpen = false;\n };\n\n /** A click outside the bar closes a site menu opened from the product nav. */\n private closeSiteMenuOnOutsideClick = (event: Event): void => {\n if (this.siteMenuRequested && !event.composedPath().includes(this)) this.endSiteMenu(true);\n };\n\n /** The product nav's site-menu button asked for the site menu (context mode only). */\n private onSiteMenuRequest = (event: Event): void => {\n if (!this.stacked) return;\n const trigger = (event as CustomEvent<{ trigger?: HTMLElement }>).detail?.trigger ?? null;\n this.openSiteMenu(trigger);\n };\n\n /**\n * Opens the site menu as a drawer over the bar, which keeps its state underneath (see render). The\n * drawer is the collapsed layout, so `compact` is forced on at every width, the page's modal flag is\n * set, and focus moves to the drawer's close button.\n */\n private openSiteMenu(trigger: HTMLElement | null): void {\n this.siteMenuTrigger = trigger;\n this.siteMenuRequested = true;\n this.compact = true;\n this.mobileOpen = true;\n setModalOpen(this, true);\n void this.updateComplete.then(() => this.renderRoot.querySelector<HTMLElement>('.toggle')?.focus({ preventScroll: true }));\n }\n\n /**\n * Ends a site-menu request: the drawer closes, and the layout goes back to what the bar's own fit\n * gives. Focus returns to the product nav's button when asked and the context row is shown.\n */\n private endSiteMenu(restoreFocus: boolean): void {\n if (!this.siteMenuRequested) return;\n const trigger = this.siteMenuTrigger;\n this.siteMenuTrigger = null;\n this.siteMenuRequested = false;\n setModalOpen(this, false);\n this.mobileOpen = false;\n this.compact = false;\n void this.updateComplete.then(() => {\n this.evaluateFit();\n if (restoreFocus && this.contextActive && trigger?.isConnected) trigger.focus({ preventScroll: true });\n });\n }\n\n /** Keeps the slotted product nav's `site-menu-open` in step with the header's site menu. */\n private syncSiteMenuOpen(): void {\n // The product nav may sit inside a wrapper of the slot (e.g. a display: contents div), so look inside each slotted element.\n for (const el of this.contextSlotElements()) {\n const nav = el.localName === 'st-product-nav' ? el : el.querySelector('st-product-nav');\n if (nav) (nav as HTMLElement & { siteMenuOpen: boolean }).siteMenuOpen = this.siteMenuRequested;\n }\n }\n\n /** Whether the bar has a context row: a trigger is set and `slot=\"context\"` has content. */\n private get stacked(): boolean {\n return !!this.contextTrigger && this.hasContext;\n }\n\n /** Layer B (the context row) is inert while it is hidden, and while a site-menu drawer is open over the bar. */\n private get layerBInert(): boolean {\n return !this.contextActive || this.siteMenuRequested;\n }\n\n /** Starts watching the trigger element, retrying for a few seconds while the page has not rendered it. */\n private startContextTrigger(): void {\n this.stopContextTrigger();\n this.pastTrigger = false;\n if (this.contextTrigger && typeof IntersectionObserver !== 'undefined' && !this.observeContextTrigger()) {\n this.triggerMutations = new MutationObserver(() => {\n if (this.observeContextTrigger()) this.stopTriggerRetry();\n });\n this.triggerMutations.observe(document.documentElement, { childList: true, subtree: true });\n this.triggerTimer = window.setTimeout(() => this.stopTriggerRetry(), CONTEXT_TRIGGER_TIMEOUT_MS);\n }\n this.updateContextActive();\n }\n\n /** Observes the trigger element if the page has it now. An invalid selector counts as not found. */\n private observeContextTrigger(): boolean {\n let element: Element | null = null;\n try {\n element = document.querySelector(this.contextTrigger);\n } catch {\n element = null;\n }\n if (!element) return false;\n this.triggerObserver?.disconnect();\n this.triggerObserver = new IntersectionObserver(this.onTriggerIntersect, {\n rootMargin: `-${CONTEXT_BAR_HEIGHT}px 0px 0px 0px`,\n threshold: 0,\n });\n this.triggerObserver.observe(element);\n return true;\n }\n\n private onTriggerIntersect = (entries: IntersectionObserverEntry[]): void => {\n const entry = entries[entries.length - 1];\n if (!entry) return;\n // The page replaced the trigger (e.g. a route change): look for the new element.\n if (!entry.target.isConnected) {\n this.startContextTrigger();\n return;\n }\n // Passed: no longer under the bar, and its bottom is above the bar's line.\n this.pastTrigger = !entry.isIntersecting && entry.boundingClientRect.bottom <= CONTEXT_BAR_HEIGHT;\n this.updateContextActive();\n };\n\n private stopTriggerRetry(): void {\n this.triggerMutations?.disconnect();\n this.triggerMutations = undefined;\n window.clearTimeout(this.triggerTimer);\n this.triggerTimer = 0;\n }\n\n private stopContextTrigger(): void {\n this.stopTriggerRetry();\n this.triggerObserver?.disconnect();\n this.triggerObserver = undefined;\n }\n\n private updateContextActive(): void {\n const next = this.stacked && this.pastTrigger;\n if (next !== this.contextActive) this.setContextActive(next);\n }\n\n private setContextActive(next: boolean): void {\n const focused = this.focusedLayer();\n // The mobile menu belongs to layer A, so it closes when the context row takes over (and so does a site-menu request).\n if (next) {\n this.mobileOpen = false;\n this.endSiteMenu(false);\n }\n this.contextActive = next;\n this.dispatchEvent(\n new CustomEvent<{ active: boolean }>('header-context-change', { detail: { active: next }, bubbles: true, composed: true })\n );\n // The layer being hidden is made inert in the coming render, which drops focus. Move it across.\n if (focused === (next ? 'a' : 'b')) {\n void this.updateComplete.then(() => this.focusLayer(next ? 'b' : 'a'));\n }\n }\n\n /** Which layer holds the focus right now, if any. */\n private focusedLayer(): 'a' | 'b' | null {\n const inner = (this.renderRoot as ShadowRoot).activeElement;\n if (inner) return this.renderRoot.querySelector('.layer-b')?.contains(inner) ? 'b' : 'a';\n const active = document.activeElement;\n if (!active || active === this || !this.contains(active)) return null;\n // Light-DOM focus is in layer B only when it is inside the context slot's content.\n return this.contextSlotElements().some(el => el.contains(active)) ? 'b' : 'a';\n }\n\n /** Focuses the first control of the layer that is shown: the brand link or toggle (layer A), or the first rendered control of the context content (layer B). */\n private focusLayer(layer: 'a' | 'b'): void {\n if (layer === 'a') {\n this.layerAFocusTarget()?.focus({ preventScroll: true });\n return;\n }\n this.layerBFocusTarget()?.focus({ preventScroll: true });\n }\n\n /** The first rendered control of the context row: the slotted product nav's brand link. */\n private layerBFocusTarget(): HTMLElement | null {\n return renderedFocusables(this.contextSlotElements())[0] ?? null;\n }\n\n private layerAFocusTarget(): HTMLElement | null {\n const candidates = [\n ...this.renderRoot.querySelectorAll<HTMLElement>('.layer-a a.brand, .layer-a .toggle'),\n ...this.querySelectorAll<HTMLElement>('a[href], button'),\n ];\n return candidates.find(el => !el.closest('[slot=\"context\"]') && el.getClientRects().length > 0) ?? null;\n }\n\n private contextSlotElements(): Element[] {\n const slot = this.renderRoot.querySelector<HTMLSlotElement>('slot[name=\"context\"]');\n return slot ? slot.assignedElements({ flatten: true }) : [];\n }\n\n /** The slotted context content is inert while layer B is inert (see layerBInert). */\n private syncContextSlot(): void {\n for (const el of this.contextSlotElements()) el.toggleAttribute('inert', this.layerBInert);\n }\n\n private onContextSlotChange = (event: Event): void => {\n this.hasContext = (event.target as HTMLSlotElement).assignedElements({ flatten: true }).length > 0;\n this.syncSiteMenuOpen();\n this.updateContextActive();\n };\n\n /** The primary call to action (`cta-label` + `cta-href`), before the theme toggle. */\n private renderCta() {\n if (!this.ctaLabel || !this.ctaHref) return nothing;\n return html`<a part=\"cta\" class=\"cta\" href=${this.ctaHref}>${this.ctaLabel}</a>`;\n }\n\n private renderLanguageMenu() {\n if (this.languages.length < 2) return nothing;\n const current = this.languages.find((lang) => lang.code === this.currentLanguageCode);\n return html`\n <div class=\"lang-menu\" part=\"language-menu\">\n <button\n part=\"language-menu-trigger\"\n type=\"button\"\n class=\"lang-trigger\"\n aria-label=${this.languageMenuLabel}\n aria-expanded=${this.languageMenuOpen}\n @click=${(event: Event) => {\n event.stopPropagation();\n this.languageMenuOpen = !this.languageMenuOpen;\n }}\n >\n <span part=\"language-menu-current\">${current?.label ?? this.languageMenuLabel}</span>\n ${chevronIcon('down', 10)}\n </button>\n ${this.languageMenuOpen\n ? html`\n <div part=\"language-dropdown\" class=\"lang-dropdown\">\n ${this.languages.map(\n (lang) => html`\n <button\n part=\"language-option\"\n type=\"button\"\n class=\"lang-option ${lang.code === this.currentLanguageCode ? 'active' : ''}\"\n aria-current=${lang.code === this.currentLanguageCode}\n @click=${() => this.onLanguageSelect(lang.code)}\n >\n ${lang.label}\n </button>\n `\n )}\n </div>\n `\n : nothing}\n </div>\n `;\n }\n\n private onLanguageSelect(code: string): void {\n this.languageMenuOpen = false;\n if (code === this.currentLanguageCode) return;\n this.dispatchEvent(new CustomEvent<LanguageChangedEventDetail>('language-change', { detail: { code }, bubbles: true, composed: true }));\n }\n\n /** The header's brand link. Inert while a site-menu request is open, when the drawer shows its own copy (`drawer-head`). */\n private renderBrand(inert = false) {\n const content = html`\n ${this.brandImageUrl ? html`<img part=\"brand-mark\" class=\"brand-mark\" src=${this.brandImageUrl} alt=${this.altText} /> ` : nothing}\n <span part=\"brand-title\" class=\"brand-title\">${this.title}</span>\n `;\n // A logo link needs an accessible name. With an image, that is `alt-text` (or \"Home\"); with only\n // text, the visible title already names it, so no aria-label (it would override the text).\n const label = this.brandImageUrl ? this.altText || 'Home' : this.title ? nothing : 'Home';\n return this.logoHref\n ? html`<a part=\"brand\" class=\"brand ${this.logoClassName}\" href=${this.logoHref} target=${this.logoTarget} aria-label=${label} ?inert=${inert}>${content}</a>`\n : html`<div part=\"brand\" class=\"brand ${this.logoClassName}\" ?inert=${inert}>${content}</div>`;\n }\n\n render() {\n const showContext = this.contextActive;\n // A site-menu drawer over the bar: layer A shows only the drawer (see .drawer-only), and layer B stays as it is.\n const drawerOnly = this.siteMenuRequested;\n return html`\n <div class=\"layers ${this.stacked ? 'stacked' : ''}\">\n <div class=\"layer layer-a ${showContext ? '' : 'is-on'} ${drawerOnly ? 'drawer-only' : ''}\" ?inert=${showContext && !drawerOnly}>\n ${this.renderBrand(this.mobileOpen)}\n <div class=\"brand-extra ${this.hasBrandExtra ? '' : 'empty'}\" part=\"brand-extra\"><slot name=\"brand-extra\" @slotchange=${this.onBrandExtraSlotChange}></slot></div>\n\n <div\n id=\"drawer\"\n class=\"mobile-panel\"\n part=\"mobile-panel\"\n role=${this.mobileOpen ? 'dialog' : nothing}\n aria-modal=${this.mobileOpen ? 'true' : nothing}\n aria-label=${this.mobileOpen ? 'Site menu' : nothing}\n @click=${() => this.closeDrawer()}\n >\n ${this.brandImageUrl || this.title ? html`<div class=\"drawer-head\" part=\"drawer-head\">${this.renderBrand()}</div>` : nothing}\n <nav class=\"menu-row\" part=\"menu-row\" aria-label=\"Main\"><slot name=\"menu\" @slotchange=${this.onMenuSlotChange}></slot></nav>\n <div class=\"utility-row ${this.hasUtility || this.languages.length >= 2 || this.ctaLabel ? '' : 'empty'}\" part=\"utility-row\">\n ${this.renderLanguageMenu()}${this.renderCta()}<slot name=\"utility\" @slotchange=${this.onUtilitySlotChange}></slot>\n </div>\n </div>\n\n ${this.siteMenuRequested\n ? html`<div class=\"site-menu-backdrop\" part=\"site-menu-backdrop\" @click=${() => this.closeDrawer()}></div>`\n : nothing}\n\n <button\n part=\"toggle\"\n type=\"button\"\n class=\"toggle\"\n aria-label=${this.mobileOpen ? 'Close menu' : 'Open menu'}\n aria-expanded=${this.mobileOpen}\n aria-controls=\"drawer\"\n @click=${() => (this.mobileOpen ? this.closeDrawer() : (this.mobileOpen = true))}\n >\n <slot name=\"menu-icon\" ?hidden=${this.mobileOpen}>${menuIcon()}</slot>\n <slot name=\"close-icon\" ?hidden=${!this.mobileOpen}>${closeIcon()}</slot>\n </button>\n </div>\n\n <div class=\"layer layer-b ${showContext ? 'is-on' : ''}\" ?inert=${this.layerBInert}>\n <slot name=\"context\" @slotchange=${this.onContextSlotChange}></slot>\n </div>\n </div>\n `;\n }\n}\n"],"mappings":"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AA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,QAsNpB,iBAAiB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,QAkBjB,mBAAmB;AAAA;AAAA;AAAA;AAAA;AAAA,QAKnB,iBAAiB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,yBA0CA,iBAAiB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AA4PxC;AAAA,EADC,SAAS,EAAE,MAAM,OAAO,CAAC;AAAA,GA3iBf,OA4iBX;AAIA;AAAA,EADC,SAAS,EAAE,MAAM,QAAQ,WAAW,kBAAkB,CAAC;AAAA,GA/iB7C,OAgjBX;AAIA;AAAA,EADC,SAAS,EAAE,MAAM,QAAQ,WAAW,eAAe,CAAC;AAAA,GAnjB1C,OAojBX;AAIA;AAAA,EADC,SAAS,EAAE,MAAM,QAAQ,WAAW,WAAW,CAAC;AAAA,GAvjBtC,OAwjBX;AAIA;AAAA,EADC,SAAS,EAAE,MAAM,OAAO,CAAC;AAAA,GA3jBf,OA4jBX;AAIA;AAAA,EADC,SAAS,EAAE,MAAM,QAAQ,WAAW,cAAc,CAAC;AAAA,GA/jBzC,OAgkBX;AAIA;AAAA,EADC,SAAS,EAAE,MAAM,QAAQ,WAAW,kBAAkB,CAAC;AAAA,GAnkB7C,OAokBX;AAKA;AAAA,EADC,SAAS,EAAE,MAAM,SAAS,SAAS,KAAK,CAAC;AAAA,GAxkB/B,OAykBX;AAGA;AAAA,EADC,SAAS,EAAE,MAAM,SAAS,SAAS,KAAK,CAAC;AAAA,GA3kB/B,OA4kBX;AASA;AAAA,EADC,SAAS,EAAE,MAAM,SAAS,SAAS,KAAK,CAAC;AAAA,GAplB/B,OAqlBX;AAIA;AAAA,EADC,SAAS,EAAE,MAAM,SAAS,SAAS,MAAM,WAAW,iBAAiB,CAAC;AAAA,GAxlB5D,OAylBX;AAIA;AAAA,EADC,SAAS,EAAE,MAAM,QAAQ,WAAW,mBAAmB,CAAC;AAAA,GA5lB9C,OA6lBX;AAIA;AAAA,EADC,SAAS,EAAE,MAAM,SAAS,SAAS,KAAK,CAAC;AAAA,GAhmB/B,OAimBX;AAIA;AAAA,EADC,SAAS,EAAE,MAAM,SAAS,SAAS,MAAM,WAAW,gBAAgB,CAAC;AAAA,GApmB3D,OAqmBX;AAiCA;AAAA,EADC,SAAS,EAAE,WAAW,MAAM,CAAC;AAAA,GAroBnB,OAsoBX;AAGA;AAAA,EADC,SAAS,EAAE,MAAM,QAAQ,WAAW,wBAAwB,CAAC;AAAA,GAxoBnD,OAyoBX;AAGA;AAAA,EADC,SAAS,EAAE,MAAM,QAAQ,WAAW,sBAAsB,CAAC;AAAA,GA3oBjD,OA4oBX;AAMA;AAAA,EADC,SAAS,EAAE,MAAM,SAAS,SAAS,MAAM,WAAW,cAAc,CAAC;AAAA,GAjpBzD,OAkpBX;AAKA;AAAA,EADC,SAAS,EAAE,MAAM,SAAS,SAAS,KAAK,CAAC;AAAA,GAtpB/B,OAupBX;AAIA;AAAA,EADC,SAAS,EAAE,MAAM,QAAQ,WAAW,YAAY,CAAC;AAAA,GA1pBvC,OA2pBX;AAIA;AAAA,EADC,SAAS,EAAE,MAAM,QAAQ,WAAW,WAAW,CAAC;AAAA,GA9pBtC,OA+pBX;AAEiB;AAAA,EAAhB,MAAM;AAAA,GAjqBI,OAiqBM;AAGA;AAAA,EAAhB,MAAM;AAAA,GApqBI,OAoqBM;AAGA;AAAA,EAAhB,MAAM;AAAA,GAvqBI,OAuqBM;AAQjB;AAAA,EADC,SAAS,EAAE,MAAM,QAAQ,WAAW,kBAAkB,CAAC;AAAA,GA9qB7C,OA+qBX;AAIA;AAAA,EADC,SAAS,EAAE,MAAM,SAAS,SAAS,MAAM,WAAW,iBAAiB,CAAC;AAAA,GAlrB5D,OAmrBX;AAGiB;AAAA,EAAhB,MAAM;AAAA,GAtrBI,OAsrBM;AAGA;AAAA,EAAhB,MAAM;AAAA,GAzrBI,OAyrBM;AAzrBN,SAAN;AAAA,EADN,cAAc,WAAW;AAAA,GACb;","names":[]}
|
|
@@ -2,13 +2,13 @@ import {
|
|
|
2
2
|
buttonResetStyles,
|
|
3
3
|
controlBaseStyles,
|
|
4
4
|
rootFontFamilyStyles
|
|
5
|
-
} from "./chunk-
|
|
5
|
+
} from "./chunk-NXUS2CH7.js";
|
|
6
6
|
import {
|
|
7
7
|
__decorateClass
|
|
8
8
|
} from "./chunk-EUXUH3YW.js";
|
|
9
9
|
|
|
10
10
|
// src/icon-button/IconButton.ts
|
|
11
|
-
import { LitElement, css, html } from "lit";
|
|
11
|
+
import { LitElement, css, html, nothing } from "lit";
|
|
12
12
|
import { customElement, property } from "lit/decorators.js";
|
|
13
13
|
var IconButton = class extends LitElement {
|
|
14
14
|
constructor() {
|
|
@@ -18,7 +18,13 @@ var IconButton = class extends LitElement {
|
|
|
18
18
|
}
|
|
19
19
|
render() {
|
|
20
20
|
return html`
|
|
21
|
-
<button
|
|
21
|
+
<button
|
|
22
|
+
part="button"
|
|
23
|
+
type="button"
|
|
24
|
+
aria-label=${this.label || nothing}
|
|
25
|
+
title=${this.label || nothing}
|
|
26
|
+
?disabled=${this.disabled}
|
|
27
|
+
>
|
|
22
28
|
<slot></slot>
|
|
23
29
|
</button>
|
|
24
30
|
`;
|
|
@@ -67,4 +73,4 @@ IconButton = __decorateClass([
|
|
|
67
73
|
export {
|
|
68
74
|
IconButton
|
|
69
75
|
};
|
|
70
|
-
//# sourceMappingURL=chunk-
|
|
76
|
+
//# sourceMappingURL=chunk-WH6HE6SY.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/icon-button/IconButton.ts"],"sourcesContent":["import { LitElement, css, html, nothing } from 'lit';\nimport { customElement, property } from 'lit/decorators.js';\n\nimport { buttonResetStyles, controlBaseStyles, rootFontFamilyStyles } from '../shared/styles';\n\n/**\n * A small, icon-only action button. The icon is default-slotted content (the package has no icon\n * library dependency), the same convention as `st-dropdown`/`st-menu-grid-item`'s `slot=\"icon\"`.\n *\n * Fires a plain native `click` — no custom event, since a caller just wants an ordinary button.\n */\n@customElement('st-icon-button')\nexport class IconButton extends LitElement {\n static styles = css`\n ${controlBaseStyles}\n\n :host {\n display: inline-flex;\n ${rootFontFamilyStyles}\n }\n\n button {\n ${buttonResetStyles}\n display: inline-flex;\n align-items: center;\n justify-content: center;\n width: var(--st-size-32);\n height: var(--st-size-32);\n border-radius: var(--st-radius-sm);\n color: var(--st-color-text-muted);\n }\n\n button:hover {\n background: var(--st-color-hover);\n color: var(--st-color-text-strong);\n }\n\n :host([disabled]) button {\n color: var(--st-color-text-muted);\n cursor: not-allowed;\n pointer-events: none;\n }\n `;\n\n /**\n * Accessible name, set as the button's `aria-label` and its `title` (tooltip). Required for a\n * control with no visible text. Matches the source component's `ariaLabel` (renamed: modern\n * browsers already expose a native `ariaLabel` reflected property on every `Element`, so reusing\n * that exact name as a Lit reactive property would shadow it).\n */\n @property({ type: String })\n label = '';\n\n @property({ type: Boolean, reflect: true })\n disabled = false;\n\n render() {\n return html`\n <button\n part=\"button\"\n type=\"button\"\n aria-label=${this.label || nothing}\n title=${this.label || nothing}\n ?disabled=${this.disabled}\n >\n <slot></slot>\n </button>\n `;\n }\n}\n"],"mappings":";;;;;;;;;;AAAA,SAAS,YAAY,KAAK,MAAM,eAAe;AAC/C,SAAS,eAAe,gBAAgB;AAWjC,IAAM,aAAN,cAAyB,WAAW;AAAA,EAApC;AAAA;AAuCL,iBAAQ;AAGR,oBAAW;AAAA;AAAA,EAEX,SAAS;AACP,WAAO;AAAA;AAAA;AAAA;AAAA,qBAIU,KAAK,SAAS,OAAO;AAAA,gBAC1B,KAAK,SAAS,OAAO;AAAA,oBACjB,KAAK,QAAQ;AAAA;AAAA;AAAA;AAAA;AAAA,EAK/B;AACF;AAzDa,WACJ,SAAS;AAAA,MACZ,iBAAiB;AAAA;AAAA;AAAA;AAAA,QAIf,oBAAoB;AAAA;AAAA;AAAA;AAAA,QAIpB,iBAAiB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AA6BvB;AAAA,EADC,SAAS,EAAE,MAAM,OAAO,CAAC;AAAA,GAtCf,WAuCX;AAGA;AAAA,EADC,SAAS,EAAE,MAAM,SAAS,SAAS,KAAK,CAAC;AAAA,GAzC/B,WA0CX;AA1CW,aAAN;AAAA,EADN,cAAc,gBAAgB;AAAA,GAClB;","names":[]}
|
|
@@ -0,0 +1,180 @@
|
|
|
1
|
+
import {
|
|
2
|
+
controlBaseStyles,
|
|
3
|
+
fontFamilyStyles
|
|
4
|
+
} from "./chunk-NXUS2CH7.js";
|
|
5
|
+
import {
|
|
6
|
+
__decorateClass
|
|
7
|
+
} from "./chunk-EUXUH3YW.js";
|
|
8
|
+
|
|
9
|
+
// src/tag-strip/TagStrip.ts
|
|
10
|
+
import { LitElement, css, html, nothing } from "lit";
|
|
11
|
+
import { customElement, property } from "lit/decorators.js";
|
|
12
|
+
var TagStrip = class extends LitElement {
|
|
13
|
+
constructor() {
|
|
14
|
+
super(...arguments);
|
|
15
|
+
this.label = "";
|
|
16
|
+
this.heading = "";
|
|
17
|
+
this.items = [];
|
|
18
|
+
this.inverted = false;
|
|
19
|
+
this.variant = "default";
|
|
20
|
+
}
|
|
21
|
+
render() {
|
|
22
|
+
return html`
|
|
23
|
+
<div class="strip" part="strip">
|
|
24
|
+
${this.label || this.heading ? html`<p class="label" part="label">${this.label || this.heading}</p>` : nothing}
|
|
25
|
+
<ul class="items" part="items">
|
|
26
|
+
${this.items.map((item) => html`<li class="item" part="item">${item}</li>`)}
|
|
27
|
+
</ul>
|
|
28
|
+
</div>
|
|
29
|
+
`;
|
|
30
|
+
}
|
|
31
|
+
};
|
|
32
|
+
TagStrip.styles = css`
|
|
33
|
+
${controlBaseStyles}
|
|
34
|
+
/* fontFamilyStyles is a bare declaration: it must sit inside a rule, or it swallows the next one. */
|
|
35
|
+
:host {
|
|
36
|
+
${fontFamilyStyles}
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
:host {
|
|
40
|
+
display: block;
|
|
41
|
+
box-sizing: border-box;
|
|
42
|
+
/* !important: a page-level reset (e.g. Tailwind Preflight) otherwise zeroes a shadow host's
|
|
43
|
+
padding; override with --st-tag-strip-padding instead. */
|
|
44
|
+
padding: var(--st-tag-strip-padding, var(--st-space-24)) var(--st-space-24) !important;
|
|
45
|
+
background: var(--st-color-page);
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
:host([inverted]) {
|
|
49
|
+
background: var(--st-cms-band-dark-bg);
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
/* variant="spread": no band behind the card (it sits on the page), with the same 24px side gutter
|
|
53
|
+
at every width. */
|
|
54
|
+
:host([variant='spread']) {
|
|
55
|
+
width: 100%;
|
|
56
|
+
background: transparent;
|
|
57
|
+
padding: var(--st-tag-strip-padding, var(--st-space-24)) var(--st-space-24) !important;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
.strip {
|
|
61
|
+
display: flex;
|
|
62
|
+
flex-wrap: wrap;
|
|
63
|
+
align-items: center;
|
|
64
|
+
gap: var(--st-space-16) var(--st-space-32);
|
|
65
|
+
box-sizing: border-box;
|
|
66
|
+
max-width: var(--st-cms-container-max);
|
|
67
|
+
margin: 0 auto;
|
|
68
|
+
padding: var(--st-space-20) var(--st-space-28, 28px);
|
|
69
|
+
border: 1px solid var(--st-color-border);
|
|
70
|
+
border-radius: var(--st-radius-lg);
|
|
71
|
+
background: var(--st-color-surface);
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
:host([inverted]) .strip {
|
|
75
|
+
background: transparent;
|
|
76
|
+
border-color: color-mix(in oklch, var(--st-cms-band-dark-color) 22%, transparent);
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
.label {
|
|
80
|
+
margin: 0;
|
|
81
|
+
flex-shrink: 0;
|
|
82
|
+
font-size: var(--st-text-sm);
|
|
83
|
+
font-weight: var(--st-font-weight-bold);
|
|
84
|
+
letter-spacing: var(--st-tracking-wider);
|
|
85
|
+
text-transform: uppercase;
|
|
86
|
+
color: var(--st-color-text-muted);
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
:host([inverted]) .label {
|
|
90
|
+
color: color-mix(in oklch, var(--st-cms-band-dark-color) 75%, transparent);
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
.items {
|
|
94
|
+
display: flex;
|
|
95
|
+
flex-wrap: wrap;
|
|
96
|
+
flex: 1 1 auto;
|
|
97
|
+
gap: var(--st-space-12) var(--st-space-28, 28px);
|
|
98
|
+
margin: 0;
|
|
99
|
+
padding: 0;
|
|
100
|
+
list-style: none;
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
.item {
|
|
104
|
+
margin: 0;
|
|
105
|
+
font-size: var(--st-text-lg);
|
|
106
|
+
font-weight: var(--st-font-weight-bold);
|
|
107
|
+
color: var(--st-color-text-strong);
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
:host([inverted]) .item {
|
|
111
|
+
color: var(--st-cms-band-dark-color);
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
/* variant="spread": a white card with the label on the left and the items pushed to the right,
|
|
115
|
+
on the content width. */
|
|
116
|
+
:host([variant='spread']) .strip {
|
|
117
|
+
justify-content: space-between;
|
|
118
|
+
padding: 20px 28px;
|
|
119
|
+
border-radius: 12px;
|
|
120
|
+
border-color: var(--st-cms-primary-100, #e4ebff);
|
|
121
|
+
background: var(--st-color-surface);
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
:host([variant='spread']) .label {
|
|
125
|
+
font-size: 12px;
|
|
126
|
+
font-weight: 600;
|
|
127
|
+
letter-spacing: 0.05em;
|
|
128
|
+
color: var(--st-cms-text, var(--st-cms-navy-2, #03346b));
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
:host([variant='spread']) .items {
|
|
132
|
+
flex: 1 1 auto;
|
|
133
|
+
justify-content: flex-end;
|
|
134
|
+
gap: 12px 28px;
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
:host([variant='spread']) .item {
|
|
138
|
+
font-weight: 600;
|
|
139
|
+
color: var(--st-cms-text-strong, var(--st-cms-navy, #011d41));
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
@media (max-width: 600px) {
|
|
143
|
+
.strip {
|
|
144
|
+
flex-direction: column;
|
|
145
|
+
align-items: flex-start;
|
|
146
|
+
padding: var(--st-space-16) var(--st-space-20);
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
:host([variant='spread']) .strip {
|
|
150
|
+
padding: 16px 20px;
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
:host([variant='spread']) .items {
|
|
154
|
+
justify-content: flex-start;
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
`;
|
|
158
|
+
__decorateClass([
|
|
159
|
+
property({ type: String })
|
|
160
|
+
], TagStrip.prototype, "label", 2);
|
|
161
|
+
__decorateClass([
|
|
162
|
+
property({ type: String })
|
|
163
|
+
], TagStrip.prototype, "heading", 2);
|
|
164
|
+
__decorateClass([
|
|
165
|
+
property({ attribute: false })
|
|
166
|
+
], TagStrip.prototype, "items", 2);
|
|
167
|
+
__decorateClass([
|
|
168
|
+
property({ type: Boolean, reflect: true })
|
|
169
|
+
], TagStrip.prototype, "inverted", 2);
|
|
170
|
+
__decorateClass([
|
|
171
|
+
property({ type: String, reflect: true })
|
|
172
|
+
], TagStrip.prototype, "variant", 2);
|
|
173
|
+
TagStrip = __decorateClass([
|
|
174
|
+
customElement("st-tag-strip")
|
|
175
|
+
], TagStrip);
|
|
176
|
+
|
|
177
|
+
export {
|
|
178
|
+
TagStrip
|
|
179
|
+
};
|
|
180
|
+
//# sourceMappingURL=chunk-XP6DI3VY.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/tag-strip/TagStrip.ts"],"sourcesContent":["import { LitElement, css, html, nothing } from 'lit';\nimport { customElement, property } from 'lit/decorators.js';\n\nimport { controlBaseStyles, fontFamilyStyles } from '../shared/styles';\n\n/**\n * A single bordered band: a small uppercase label on the left and a run of bold items beside it\n * (e.g. \"Supported platforms: AWS · Azure · GCP\"). Items wrap onto new lines on narrow screens.\n * `inverted` puts the band on the dark band (`--st-cms-band-dark-bg`).\n *\n * @cssprop --st-tag-strip-padding - Overrides the block's padding.\n * @csspart strip - The bordered band.\n * @csspart label - The uppercase label.\n * @csspart items - The list of items.\n * @csspart item - Each item (an `li`).\n */\n@customElement('st-tag-strip')\nexport class TagStrip extends LitElement {\n static styles = css`\n ${controlBaseStyles}\n /* fontFamilyStyles is a bare declaration: it must sit inside a rule, or it swallows the next one. */\n :host {\n ${fontFamilyStyles}\n }\n\n :host {\n display: block;\n box-sizing: border-box;\n /* !important: a page-level reset (e.g. Tailwind Preflight) otherwise zeroes a shadow host's\n padding; override with --st-tag-strip-padding instead. */\n padding: var(--st-tag-strip-padding, var(--st-space-24)) var(--st-space-24) !important;\n background: var(--st-color-page);\n }\n\n :host([inverted]) {\n background: var(--st-cms-band-dark-bg);\n }\n\n /* variant=\"spread\": no band behind the card (it sits on the page), with the same 24px side gutter\n at every width. */\n :host([variant='spread']) {\n width: 100%;\n background: transparent;\n padding: var(--st-tag-strip-padding, var(--st-space-24)) var(--st-space-24) !important;\n }\n\n .strip {\n display: flex;\n flex-wrap: wrap;\n align-items: center;\n gap: var(--st-space-16) var(--st-space-32);\n box-sizing: border-box;\n max-width: var(--st-cms-container-max);\n margin: 0 auto;\n padding: var(--st-space-20) var(--st-space-28, 28px);\n border: 1px solid var(--st-color-border);\n border-radius: var(--st-radius-lg);\n background: var(--st-color-surface);\n }\n\n :host([inverted]) .strip {\n background: transparent;\n border-color: color-mix(in oklch, var(--st-cms-band-dark-color) 22%, transparent);\n }\n\n .label {\n margin: 0;\n flex-shrink: 0;\n font-size: var(--st-text-sm);\n font-weight: var(--st-font-weight-bold);\n letter-spacing: var(--st-tracking-wider);\n text-transform: uppercase;\n color: var(--st-color-text-muted);\n }\n\n :host([inverted]) .label {\n color: color-mix(in oklch, var(--st-cms-band-dark-color) 75%, transparent);\n }\n\n .items {\n display: flex;\n flex-wrap: wrap;\n flex: 1 1 auto;\n gap: var(--st-space-12) var(--st-space-28, 28px);\n margin: 0;\n padding: 0;\n list-style: none;\n }\n\n .item {\n margin: 0;\n font-size: var(--st-text-lg);\n font-weight: var(--st-font-weight-bold);\n color: var(--st-color-text-strong);\n }\n\n :host([inverted]) .item {\n color: var(--st-cms-band-dark-color);\n }\n\n /* variant=\"spread\": a white card with the label on the left and the items pushed to the right,\n on the content width. */\n :host([variant='spread']) .strip {\n justify-content: space-between;\n padding: 20px 28px;\n border-radius: 12px;\n border-color: var(--st-cms-primary-100, #e4ebff);\n background: var(--st-color-surface);\n }\n\n :host([variant='spread']) .label {\n font-size: 12px;\n font-weight: 600;\n letter-spacing: 0.05em;\n color: var(--st-cms-text, var(--st-cms-navy-2, #03346b));\n }\n\n :host([variant='spread']) .items {\n flex: 1 1 auto;\n justify-content: flex-end;\n gap: 12px 28px;\n }\n\n :host([variant='spread']) .item {\n font-weight: 600;\n color: var(--st-cms-text-strong, var(--st-cms-navy, #011d41));\n }\n\n @media (max-width: 600px) {\n .strip {\n flex-direction: column;\n align-items: flex-start;\n padding: var(--st-space-16) var(--st-space-20);\n }\n\n :host([variant='spread']) .strip {\n padding: 16px 20px;\n }\n\n :host([variant='spread']) .items {\n justify-content: flex-start;\n }\n }\n `;\n\n /** Small uppercase label at the start of the band. Omit it for items alone. */\n @property({ type: String })\n label = '';\n\n /**\n * The same label as `label`, under a name the page JSON can use: the site renderer drops a node's\n * `label` key (it is the node's own name), so JSON sets `heading`. Shown when `label` is empty.\n */\n @property({ type: String })\n heading = '';\n\n /** The items, shown in order. */\n @property({ attribute: false })\n items: string[] = [];\n\n /** Puts the band on the dark band (`--st-cms-band-dark-bg`), which stays dark in the dark theme. */\n @property({ type: Boolean, reflect: true })\n inverted = false;\n\n /** `default` is the bordered band; `spread` is a white card with the label left and the items right (`label` shown). */\n @property({ type: String, reflect: true })\n variant: 'default' | 'spread' = 'default';\n\n render() {\n return html`\n <div class=\"strip\" part=\"strip\">\n ${this.label || this.heading ? html`<p class=\"label\" part=\"label\">${this.label || this.heading}</p>` : nothing}\n <ul class=\"items\" part=\"items\">\n ${this.items.map(item => html`<li class=\"item\" part=\"item\">${item}</li>`)}\n </ul>\n </div>\n `;\n }\n}\n"],"mappings":";;;;;;;;;AAAA,SAAS,YAAY,KAAK,MAAM,eAAe;AAC/C,SAAS,eAAe,gBAAgB;AAgBjC,IAAM,WAAN,cAAuB,WAAW;AAAA,EAAlC;AAAA;AAkIL,iBAAQ;AAOR,mBAAU;AAIV,iBAAkB,CAAC;AAInB,oBAAW;AAIX,mBAAgC;AAAA;AAAA,EAEhC,SAAS;AACP,WAAO;AAAA;AAAA,UAED,KAAK,SAAS,KAAK,UAAU,qCAAqC,KAAK,SAAS,KAAK,OAAO,SAAS,OAAO;AAAA;AAAA,YAE1G,KAAK,MAAM,IAAI,UAAQ,oCAAoC,IAAI,OAAO,CAAC;AAAA;AAAA;AAAA;AAAA,EAIjF;AACF;AAjKa,SACJ,SAAS;AAAA,MACZ,iBAAiB;AAAA;AAAA;AAAA,QAGf,gBAAgB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AA6HtB;AAAA,EADC,SAAS,EAAE,MAAM,OAAO,CAAC;AAAA,GAjIf,SAkIX;AAOA;AAAA,EADC,SAAS,EAAE,MAAM,OAAO,CAAC;AAAA,GAxIf,SAyIX;AAIA;AAAA,EADC,SAAS,EAAE,WAAW,MAAM,CAAC;AAAA,GA5InB,SA6IX;AAIA;AAAA,EADC,SAAS,EAAE,MAAM,SAAS,SAAS,KAAK,CAAC;AAAA,GAhJ/B,SAiJX;AAIA;AAAA,EADC,SAAS,EAAE,MAAM,QAAQ,SAAS,KAAK,CAAC;AAAA,GApJ9B,SAqJX;AArJW,WAAN;AAAA,EADN,cAAc,cAAc;AAAA,GAChB;","names":[]}
|
|
@@ -1,7 +1,10 @@
|
|
|
1
|
+
import {
|
|
2
|
+
renderMarkdown
|
|
3
|
+
} from "./chunk-TJK55CJ2.js";
|
|
1
4
|
import {
|
|
2
5
|
controlBaseStyles,
|
|
3
6
|
fontFamilyStyles
|
|
4
|
-
} from "./chunk-
|
|
7
|
+
} from "./chunk-NXUS2CH7.js";
|
|
5
8
|
import {
|
|
6
9
|
__decorateClass
|
|
7
10
|
} from "./chunk-EUXUH3YW.js";
|
|
@@ -10,13 +13,12 @@ import {
|
|
|
10
13
|
import { LitElement, css, html, nothing } from "lit";
|
|
11
14
|
import { customElement, property, state } from "lit/decorators.js";
|
|
12
15
|
import { unsafeHTML } from "lit/directives/unsafe-html.js";
|
|
13
|
-
import DOMPurify from "dompurify";
|
|
14
|
-
import { marked } from "marked";
|
|
15
16
|
var Markdown = class extends LitElement {
|
|
16
17
|
constructor() {
|
|
17
18
|
super(...arguments);
|
|
18
19
|
this.content = "";
|
|
19
20
|
this.src = "";
|
|
21
|
+
this.listStyle = "default";
|
|
20
22
|
this.fetched = "";
|
|
21
23
|
this.loading = false;
|
|
22
24
|
this.error = null;
|
|
@@ -63,8 +65,7 @@ var Markdown = class extends LitElement {
|
|
|
63
65
|
if (this.error) return html`<div part="error">Error loading content.</div>`;
|
|
64
66
|
const source = this.src ? this.fetched : this.content;
|
|
65
67
|
if (!source) return nothing;
|
|
66
|
-
|
|
67
|
-
return html`<div part="body">${unsafeHTML(rendered)}</div>`;
|
|
68
|
+
return html`<div part="body">${unsafeHTML(renderMarkdown(source))}</div>`;
|
|
68
69
|
}
|
|
69
70
|
};
|
|
70
71
|
Markdown.styles = css`
|
|
@@ -76,6 +77,29 @@ Markdown.styles = css`
|
|
|
76
77
|
line-height: 1.7;
|
|
77
78
|
}
|
|
78
79
|
|
|
80
|
+
/* list-style="check": unordered items get a check mark instead of a bullet. */
|
|
81
|
+
:host([list-style='check']) ul {
|
|
82
|
+
list-style: none;
|
|
83
|
+
padding-left: 0;
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
:host([list-style='check']) ul > li {
|
|
87
|
+
position: relative;
|
|
88
|
+
padding-left: 32px;
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
:host([list-style='check']) ul > li::before {
|
|
92
|
+
content: '';
|
|
93
|
+
position: absolute;
|
|
94
|
+
left: 0;
|
|
95
|
+
top: 0.3em;
|
|
96
|
+
width: 20px;
|
|
97
|
+
height: 20px;
|
|
98
|
+
background-color: var(--st-markdown-list-check-color, var(--st-cms-navy));
|
|
99
|
+
-webkit-mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath d='M20 6 9 17l-5-5' fill='none' stroke='black' stroke-width='3' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E") center / contain no-repeat;
|
|
100
|
+
mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath d='M20 6 9 17l-5-5' fill='none' stroke='black' stroke-width='3' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E") center / contain no-repeat;
|
|
101
|
+
}
|
|
102
|
+
|
|
79
103
|
:host > div > :first-child {
|
|
80
104
|
margin-top: 0;
|
|
81
105
|
}
|
|
@@ -149,23 +173,58 @@ Markdown.styles = css`
|
|
|
149
173
|
padding: var(--st-space-8) var(--st-space-12);
|
|
150
174
|
}
|
|
151
175
|
|
|
152
|
-
|
|
176
|
+
/* Inline code: a chip tinted from the surrounding text colour, so it reads on light and inverted
|
|
177
|
+
(dark) containers alike. */
|
|
153
178
|
code {
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
179
|
+
font-family: var(--st-markdown-code-font, ui-monospace, SFMono-Regular, Menlo, Consolas, monospace);
|
|
180
|
+
font-size: 0.875em;
|
|
181
|
+
padding: 0.1em 0.4em;
|
|
182
|
+
border-radius: 6px;
|
|
183
|
+
background: color-mix(in srgb, currentColor 12%, transparent);
|
|
184
|
+
overflow-wrap: anywhere;
|
|
160
185
|
}
|
|
161
186
|
|
|
187
|
+
/* Code blocks: always a dark navy panel with light text (white-on-light-grey was unreadable). The
|
|
188
|
+
token colours are all at least 4.5:1 on #011d41 and on #03346b. Long lines scroll inside the block. */
|
|
162
189
|
pre {
|
|
163
|
-
|
|
190
|
+
margin: 0 0 var(--st-space-24);
|
|
191
|
+
padding: 20px;
|
|
164
192
|
overflow-x: auto;
|
|
193
|
+
border: 1px solid var(--st-markdown-code-border, rgb(228 235 255 / 0.14));
|
|
194
|
+
border-radius: 12px;
|
|
195
|
+
background: var(--st-markdown-code-bg, #011d41);
|
|
196
|
+
color: var(--st-markdown-code-color, #e4ebff);
|
|
197
|
+
font-size: 14px;
|
|
198
|
+
line-height: 1.6;
|
|
199
|
+
tab-size: 2;
|
|
165
200
|
}
|
|
166
201
|
|
|
167
202
|
pre code {
|
|
203
|
+
display: block;
|
|
168
204
|
padding: 0;
|
|
205
|
+
border-radius: 0;
|
|
206
|
+
background: none;
|
|
207
|
+
font-size: 14px;
|
|
208
|
+
color: inherit;
|
|
209
|
+
white-space: pre;
|
|
210
|
+
overflow-wrap: normal;
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
pre .tok-key {
|
|
214
|
+
color: var(--st-markdown-code-key, #8eaffe);
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
pre .tok-string {
|
|
218
|
+
color: var(--st-markdown-code-string, #49cce0);
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
pre .tok-number,
|
|
222
|
+
pre .tok-literal {
|
|
223
|
+
color: var(--st-markdown-code-number, #fbbf77);
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
pre .tok-punct {
|
|
227
|
+
color: var(--st-markdown-code-punct, #c9d7fe);
|
|
169
228
|
}
|
|
170
229
|
`;
|
|
171
230
|
__decorateClass([
|
|
@@ -174,6 +233,9 @@ __decorateClass([
|
|
|
174
233
|
__decorateClass([
|
|
175
234
|
property({ type: String })
|
|
176
235
|
], Markdown.prototype, "src", 2);
|
|
236
|
+
__decorateClass([
|
|
237
|
+
property({ type: String, reflect: true, attribute: "list-style" })
|
|
238
|
+
], Markdown.prototype, "listStyle", 2);
|
|
177
239
|
__decorateClass([
|
|
178
240
|
state()
|
|
179
241
|
], Markdown.prototype, "fetched", 2);
|
|
@@ -190,4 +252,4 @@ Markdown = __decorateClass([
|
|
|
190
252
|
export {
|
|
191
253
|
Markdown
|
|
192
254
|
};
|
|
193
|
-
//# sourceMappingURL=chunk-
|
|
255
|
+
//# sourceMappingURL=chunk-XS6LNTSH.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/markdown/Markdown.ts"],"sourcesContent":["import { LitElement, css, html, nothing } from 'lit';\nimport { customElement, property, state } from 'lit/decorators.js';\nimport { unsafeHTML } from 'lit/directives/unsafe-html.js';\n\nimport { controlBaseStyles, fontFamilyStyles } from '../shared/styles';\nimport { renderMarkdown } from '../shared/markdown';\nimport type { MarkdownErrorEventDetail } from './MarkdownEvents';\n\n/**\n * Renders Markdown (GFM, single newlines become `<br>`) from either an inline `content` string or\n * a `src` URL it fetches. Output is sanitized with DOMPurify. `src` wins over `content` when both are set.\n * While a fetch is pending it shows \"Loading content...\"; on failure \"Error loading content.\" and\n * a `markdown-error` event (detail: `{ error }`).\n *\n * Text color is inherited from the parent so inverted containers just work.\n *\n * `list-style=\"check\"` replaces the bullets of unordered lists with a check mark, in the colour of\n * `--st-markdown-list-check-color` (navy by default).\n *\n * Code blocks are a dark navy panel (14px monospace, 20px padding, 12px corners) that scrolls\n * sideways only when a line is wider than the block; ```json fences get syntax colours. Inline\n * `code` is a chip tinted from the surrounding text colour.\n *\n * @cssprop --st-markdown-list-check-color - Colour of the check marks (`list-style=\"check\"`).\n * @cssprop --st-markdown-code-bg - Code block background (default `#011d41`).\n * @cssprop --st-markdown-code-color - Code block text (default `#e4ebff`).\n * @cssprop --st-markdown-code-border - Code block hairline (default `#e4ebff` at 14%).\n * @cssprop --st-markdown-code-key - JSON keys (default `#8eaffe`).\n * @cssprop --st-markdown-code-string - JSON strings (default `#49cce0`).\n * @cssprop --st-markdown-code-number - JSON numbers, `true`, `false`, `null` (default `#fbbf77`).\n * @cssprop --st-markdown-code-punct - JSON punctuation (default `#c9d7fe`).\n */\n@customElement('st-markdown')\nexport class Markdown extends LitElement {\n static styles = css`\n ${controlBaseStyles}\n\n :host {\n display: block;\n ${fontFamilyStyles}\n line-height: 1.7;\n }\n\n /* list-style=\"check\": unordered items get a check mark instead of a bullet. */\n :host([list-style='check']) ul {\n list-style: none;\n padding-left: 0;\n }\n\n :host([list-style='check']) ul > li {\n position: relative;\n padding-left: 32px;\n }\n\n :host([list-style='check']) ul > li::before {\n content: '';\n position: absolute;\n left: 0;\n top: 0.3em;\n width: 20px;\n height: 20px;\n background-color: var(--st-markdown-list-check-color, var(--st-cms-navy));\n -webkit-mask: url(\"data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath d='M20 6 9 17l-5-5' fill='none' stroke='black' stroke-width='3' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E\") center / contain no-repeat;\n mask: url(\"data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath d='M20 6 9 17l-5-5' fill='none' stroke='black' stroke-width='3' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E\") center / contain no-repeat;\n }\n\n :host > div > :first-child {\n margin-top: 0;\n }\n\n h1,\n h2,\n h3,\n h4 {\n color: inherit;\n font-weight: var(--st-font-weight-bold);\n line-height: 1.3;\n }\n\n h2 {\n font-size: var(--st-text-2xl);\n margin: var(--st-space-48) 0 var(--st-space-24);\n }\n\n h3 {\n font-size: var(--st-text-xl);\n font-weight: var(--st-font-weight-semibold);\n margin: var(--st-space-32) 0 var(--st-space-16);\n }\n\n p {\n margin: 0 0 var(--st-space-24);\n }\n\n ul,\n ol {\n margin: 0 0 var(--st-space-24);\n padding-left: var(--st-space-24);\n }\n\n li {\n margin-bottom: var(--st-space-8);\n }\n\n a {\n color: inherit;\n text-decoration: underline;\n text-underline-offset: 4px;\n }\n\n a:hover {\n color: var(--st-color-text-strong);\n }\n\n img {\n max-width: 100%;\n height: auto;\n border-radius: var(--st-radius-sm);\n margin: var(--st-space-32) 0;\n }\n\n blockquote {\n border-left: 4px solid var(--st-color-border);\n margin: var(--st-space-32) 0;\n padding-left: var(--st-space-24);\n font-style: italic;\n }\n\n table {\n border-collapse: collapse;\n margin: 0 0 var(--st-space-24);\n }\n\n th,\n td {\n border: 1px solid var(--st-color-border);\n padding: var(--st-space-8) var(--st-space-12);\n }\n\n /* Inline code: a chip tinted from the surrounding text colour, so it reads on light and inverted\n (dark) containers alike. */\n code {\n font-family: var(--st-markdown-code-font, ui-monospace, SFMono-Regular, Menlo, Consolas, monospace);\n font-size: 0.875em;\n padding: 0.1em 0.4em;\n border-radius: 6px;\n background: color-mix(in srgb, currentColor 12%, transparent);\n overflow-wrap: anywhere;\n }\n\n /* Code blocks: always a dark navy panel with light text (white-on-light-grey was unreadable). The\n token colours are all at least 4.5:1 on #011d41 and on #03346b. Long lines scroll inside the block. */\n pre {\n margin: 0 0 var(--st-space-24);\n padding: 20px;\n overflow-x: auto;\n border: 1px solid var(--st-markdown-code-border, rgb(228 235 255 / 0.14));\n border-radius: 12px;\n background: var(--st-markdown-code-bg, #011d41);\n color: var(--st-markdown-code-color, #e4ebff);\n font-size: 14px;\n line-height: 1.6;\n tab-size: 2;\n }\n\n pre code {\n display: block;\n padding: 0;\n border-radius: 0;\n background: none;\n font-size: 14px;\n color: inherit;\n white-space: pre;\n overflow-wrap: normal;\n }\n\n pre .tok-key {\n color: var(--st-markdown-code-key, #8eaffe);\n }\n\n pre .tok-string {\n color: var(--st-markdown-code-string, #49cce0);\n }\n\n pre .tok-number,\n pre .tok-literal {\n color: var(--st-markdown-code-number, #fbbf77);\n }\n\n pre .tok-punct {\n color: var(--st-markdown-code-punct, #c9d7fe);\n }\n `;\n\n /** Inline Markdown source. Ignored when `src` is set. */\n @property({ type: String })\n content = '';\n\n /** URL of a Markdown file to fetch. */\n @property({ type: String })\n src = '';\n\n /** `default` keeps bullets; `check` shows a check mark on each unordered item. */\n @property({ type: String, reflect: true, attribute: 'list-style' })\n listStyle: 'default' | 'check' = 'default';\n\n @state() private fetched = '';\n @state() private loading = false;\n @state() private error: Error | null = null;\n\n private abort?: AbortController;\n\n willUpdate(changed: Map<string, unknown>): void {\n if (changed.has('src')) void this.load();\n }\n\n disconnectedCallback(): void {\n this.abort?.abort();\n super.disconnectedCallback();\n }\n\n private async load(): Promise<void> {\n this.abort?.abort();\n this.fetched = '';\n this.error = null;\n if (!this.src) {\n this.loading = false;\n return;\n }\n const controller = new AbortController();\n this.abort = controller;\n this.loading = true;\n try {\n const response = await fetch(this.src, { signal: controller.signal });\n if (!response.ok) throw new Error(`Failed to fetch markdown: ${response.statusText}`);\n const text = await response.text();\n if (controller.signal.aborted) return;\n this.fetched = text;\n } catch (err) {\n if (controller.signal.aborted) return;\n this.error = err instanceof Error ? err : new Error('Unknown error fetching markdown');\n this.dispatchEvent(\n new CustomEvent<MarkdownErrorEventDetail>('markdown-error', {\n detail: { error: this.error },\n bubbles: true,\n composed: true\n })\n );\n }\n this.loading = false;\n }\n\n render() {\n if (this.loading) return html`<div part=\"loading\">Loading content...</div>`;\n if (this.error) return html`<div part=\"error\">Error loading content.</div>`;\n const source = this.src ? this.fetched : this.content;\n if (!source) return nothing;\n return html`<div part=\"body\">${unsafeHTML(renderMarkdown(source))}</div>`;\n }\n}\n"],"mappings":"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","names":[]}
|