@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/mega-menu/MegaMenu.ts","../src/mega-menu/MegaMenuColumn.ts","../src/mega-menu/MegaMenuFeature.ts"],"sourcesContent":["import { LitElement, PropertyValues, css, html, nothing } from 'lit';\nimport { customElement, property, state } from 'lit/decorators.js';\n\nimport { controlBaseStyles, fontFamilyStyles } from '../shared/styles';\nimport { MEGA_MENU_LAYOUT_EVENT, type MegaMenuLayoutEventDetail } from './MegaMenuEvents';\n\n/**\n * The rich layout of a mega-menu panel, after okta.com: an optional intro column on the left (a\n * large `heading`, a `description` and, under a divider, quick links in `slot=\"intro\"`), then the\n * link columns side by side (`st-mega-menu-column`s in the default slot), then an optional\n * featured column on the right (`featured-heading` over the `st-mega-menu-feature` cards in\n * `slot=\"featured\"`). Slot it into an `st-dropdown` with `mega` set.\n *\n * The layout follows the width it is given, not the viewport (a container query): side by side\n * when there is room; intro and featured column above/below two link columns on a medium panel;\n * everything stacked in the narrow drill-down panel `st-header` shows on a phone (where the intro\n * heading is left out — the drill-down already shows the section's name).\n *\n * `cta-label` + `cta-href` add a call-to-action pill pinned to the foot of the intro column, so the\n * column ends level with the featured cards instead of leaving an empty gap under the text.\n *\n * @slot - The link columns (`st-mega-menu-column`s, or any blocks).\n * @slot intro - Quick links under the intro text, e.g. `st-menu-item`s with an icon.\n * @slot featured - Promo cards (`st-mega-menu-feature`s), stacked.\n * @csspart inner - The grid holding every area.\n * @csspart intro - The intro column.\n * @csspart cta - The intro column's call-to-action pill.\n * @csspart columns - The grid holding the link columns.\n * @csspart featured - The featured column.\n */\n@customElement('st-mega-menu')\nexport class MegaMenu extends LitElement {\n static styles = css`\n ${controlBaseStyles}\n\n :host {\n display: block;\n container-type: inline-size;\n ${fontFamilyStyles}\n }\n\n .inner {\n display: grid;\n gap: 3rem;\n padding: 3rem 3.5rem;\n box-sizing: border-box;\n }\n\n .columns {\n display: grid;\n grid-template-columns: repeat(var(--st-mega-menu-columns, 3), minmax(0, 1fr));\n gap: 3rem;\n align-items: stretch;\n }\n\n .intro,\n .featured {\n display: flex;\n flex-direction: column;\n min-width: 0;\n }\n\n .intro-heading {\n margin: 0 0 1rem;\n font-size: 2rem;\n font-weight: 400;\n line-height: 1.15;\n color: var(--st-color-text-strong);\n }\n\n .intro-description {\n margin: 0;\n font-size: 1rem;\n line-height: 1.55;\n color: var(--st-color-text);\n }\n\n .intro-links {\n display: flex;\n flex-direction: column;\n gap: 2px;\n margin-top: 2.5rem;\n padding-top: 2rem;\n border-top: 1px solid var(--st-color-border);\n }\n\n .intro-links.no-text {\n margin-top: 0;\n padding-top: 0;\n border-top: 0;\n }\n\n /* The intro column's call to action: pinned to the foot of the column, so it lines up with the featured cards. */\n .intro-footer {\n display: flex;\n margin-top: auto;\n padding-top: 2rem;\n }\n\n .intro-cta {\n display: inline-flex;\n align-items: center;\n justify-content: center;\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: 1rem;\n font-weight: 600;\n text-decoration: none;\n }\n\n .intro-cta:hover {\n background: color-mix(in oklch, var(--st-color-accent) 88%, var(--st-color-text-strong));\n }\n\n .featured-heading {\n margin: 0 0 1rem;\n font-size: 1.125rem;\n font-weight: 500;\n line-height: 1.35;\n color: var(--st-color-text-strong);\n }\n\n .featured-items {\n display: flex;\n flex-direction: column;\n gap: 0.75rem;\n }\n\n [hidden] {\n display: none !important;\n }\n\n /* Medium panel: intro on top, two link columns, featured cards side by side underneath. */\n @container (max-width: 960px) {\n .inner {\n grid-template-columns: minmax(0, 1fr) !important;\n gap: 2rem;\n padding: 2rem;\n }\n\n .columns {\n grid-template-columns: repeat(var(--st-mega-menu-columns-md, 2), minmax(0, 1fr));\n gap: 2rem;\n }\n\n .intro-links {\n margin-top: 1.5rem;\n padding-top: 1.5rem;\n }\n\n .featured-items {\n display: grid;\n grid-template-columns: repeat(auto-fill, minmax(220px, 1fr));\n }\n }\n\n /* Narrow panel (the phone drill-down): everything stacked. */\n @container (max-width: 560px) {\n .inner {\n gap: 1.75rem;\n padding: 0.5rem 0 1.5rem;\n }\n\n .columns {\n grid-template-columns: minmax(0, 1fr);\n gap: 1.75rem;\n }\n\n .intro-heading {\n display: none;\n }\n }\n `;\n\n /** Large title of the intro column. */\n @property({ type: String })\n heading = '';\n\n /** Text under the intro title. */\n @property({ type: String })\n description = '';\n\n /** Heading over the featured cards. */\n @property({ type: String, attribute: 'featured-heading' })\n featuredHeading = '';\n\n /** Number of link columns side by side at full width. `0` (the default) uses one per slotted column. */\n @property({ type: Number })\n columns = 0;\n\n /** Label of the call-to-action pill at the foot of the intro column. Needs `cta-href`. */\n @property({ type: String, attribute: 'cta-label' })\n ctaLabel = '';\n\n /** Target of the intro column's call to action. */\n @property({ type: String, attribute: 'cta-href' })\n ctaHref = '';\n\n /** Whether the menu panel is shown. Set to `false` to hide it entirely (it keeps its slotted content). */\n @property({ type: Boolean })\n visible = true;\n\n @state() private columnCount = 1;\n @state() private hasIntroLinks = false;\n @state() private hasFeatured = false;\n\n private onColumnsSlotChange = (event: Event): void => {\n this.columnCount = Math.max(1, (event.target as HTMLSlotElement).assignedElements({ flatten: true }).length);\n };\n\n private onIntroSlotChange = (event: Event): void => {\n this.hasIntroLinks = (event.target as HTMLSlotElement).assignedElements({ flatten: true }).length > 0;\n };\n\n private onFeaturedSlotChange = (event: Event): void => {\n this.hasFeatured = (event.target as HTMLSlotElement).assignedElements({ flatten: true }).length > 0;\n };\n\n private get layout() {\n const columns = Math.min(6, Math.max(1, Math.round(this.columns) || this.columnCount));\n const hasIntroText = !!(this.heading || this.description);\n const hasCta = !!(this.ctaLabel && this.ctaHref);\n const hasIntro = hasIntroText || this.hasIntroLinks || hasCta;\n const hasFeatured = this.hasFeatured || !!this.featuredHeading;\n return { columns, hasIntroText, hasCta, hasIntro, hasFeatured, tracks: columns + (hasIntro ? 1 : 0) + (hasFeatured ? 1 : 0) };\n }\n\n private lastTracks = 0;\n\n protected updated(_changed: PropertyValues): void {\n const { tracks } = this.layout;\n if (tracks === this.lastTracks) return;\n this.lastTracks = tracks;\n this.dispatchEvent(\n new CustomEvent<MegaMenuLayoutEventDetail>(MEGA_MENU_LAYOUT_EVENT, { detail: { tracks }, bubbles: true, composed: true })\n );\n }\n\n render() {\n const { columns, hasIntroText, hasCta, hasIntro, hasFeatured } = this.layout;\n // Every column — intro, each link column, featured — gets the same share of the width.\n const tracks = [hasIntro ? 'minmax(0, 1fr)' : '', `minmax(0, ${columns}fr)`, hasFeatured ? 'minmax(0, 1fr)' : '']\n .filter(Boolean)\n .join(' ');\n return html`\n <div\n part=\"inner\"\n class=\"inner\"\n ?hidden=${!this.visible}\n style=\"grid-template-columns:${tracks};--st-mega-menu-columns:${columns};--st-mega-menu-columns-md:${Math.min(2, columns)}\"\n >\n <div part=\"intro\" class=\"intro\" ?hidden=${!hasIntro}>\n ${this.heading ? html`<p part=\"heading\" class=\"intro-heading\">${this.heading}</p>` : nothing}\n ${this.description ? html`<p part=\"description\" class=\"intro-description\">${this.description}</p>` : nothing}\n <div part=\"intro-links\" class=\"intro-links ${hasIntroText ? '' : 'no-text'}\" ?hidden=${!this.hasIntroLinks}>\n <slot name=\"intro\" @slotchange=${this.onIntroSlotChange}></slot>\n </div>\n ${hasCta\n ? html`<div part=\"cta-row\" class=\"intro-footer\"><a part=\"cta\" class=\"intro-cta\" href=${this.ctaHref}>${this.ctaLabel}</a></div>`\n : nothing}\n </div>\n <div part=\"columns\" class=\"columns\"><slot @slotchange=${this.onColumnsSlotChange}></slot></div>\n <div part=\"featured\" class=\"featured\" ?hidden=${!hasFeatured}>\n ${this.featuredHeading ? html`<p part=\"featured-heading\" class=\"featured-heading\">${this.featuredHeading}</p>` : nothing}\n <div class=\"featured-items\"><slot name=\"featured\" @slotchange=${this.onFeaturedSlotChange}></slot></div>\n </div>\n </div>\n `;\n }\n}\n","import 'iconify-icon';\nimport { LitElement, css, html, nothing, svg } from 'lit';\nimport type { TemplateResult } from 'lit';\nimport { customElement, property, state } from 'lit/decorators.js';\n\nimport { arrowUpRightIcon } from '../shared/icons';\nimport { controlBaseStyles, fontFamilyStyles } from '../shared/styles';\nimport { isCurrentPath } from '../shared/nav-path';\nimport type { MegaMenuSelectEventDetail } from './MegaMenuEvents';\n\n/** The line art of a `product` card's `decoration`, drawn in `currentColor`. */\nconst DECORATIONS: Record<'flow' | 'orbit' | 'waves' | 'ribbon', TemplateResult> = {\n flow: svg`\n <path d=\"M240 8 C 190 20, 150 70, 70 150\" fill=\"none\" stroke=\"currentColor\" stroke-linecap=\"round\" stroke-width=\"1.5\"/>\n <path d=\"M240 28 C 196 40, 162 84, 100 156\" fill=\"none\" stroke=\"currentColor\" stroke-linecap=\"round\" stroke-width=\"1.25\"/>\n <path d=\"M240 48 C 204 60, 176 98, 130 160\" fill=\"none\" stroke=\"currentColor\" stroke-linecap=\"round\" stroke-width=\"1\"/>\n <path d=\"M226 0 C 180 10, 130 52, 40 132\" fill=\"none\" stroke=\"currentColor\" stroke-linecap=\"round\" stroke-width=\"1.25\"/>\n <path d=\"M206 0 C 166 8, 112 36, 12 108\" fill=\"none\" stroke=\"currentColor\" stroke-linecap=\"round\" stroke-width=\"1\"/>\n `,\n orbit: svg`\n <circle cx=\"240\" cy=\"0\" r=\"36\" fill=\"none\" stroke=\"currentColor\" stroke-linecap=\"round\" stroke-width=\"1.5\"/>\n <circle cx=\"240\" cy=\"0\" r=\"62\" fill=\"none\" stroke=\"currentColor\" stroke-linecap=\"round\" stroke-width=\"1.25\"/>\n <circle cx=\"240\" cy=\"0\" r=\"90\" fill=\"none\" stroke=\"currentColor\" stroke-linecap=\"round\" stroke-width=\"1\"/>\n <circle cx=\"240\" cy=\"0\" r=\"120\" fill=\"none\" stroke=\"currentColor\" stroke-linecap=\"round\" stroke-width=\"1\" stroke-dasharray=\"2 6\"/>\n <circle cx=\"204\" cy=\"34\" r=\"3\" fill=\"currentColor\" stroke=\"none\"/>\n `,\n waves: svg`\n <path d=\"M0 30 C 40 6, 80 54, 120 30 S 200 6, 240 30\" fill=\"none\" stroke=\"currentColor\" stroke-linecap=\"round\" stroke-width=\"1.5\"/>\n <path d=\"M0 48 C 40 24, 80 72, 120 48 S 200 24, 240 48\" fill=\"none\" stroke=\"currentColor\" stroke-linecap=\"round\" stroke-width=\"1.25\"/>\n <path d=\"M0 66 C 40 42, 80 90, 120 66 S 200 42, 240 66\" fill=\"none\" stroke=\"currentColor\" stroke-linecap=\"round\" stroke-width=\"1\"/>\n <path d=\"M0 84 C 40 60, 80 108, 120 84 S 200 60, 240 84\" fill=\"none\" stroke=\"currentColor\" stroke-linecap=\"round\" stroke-width=\"1\"/>\n `,\n ribbon: svg`\n <path d=\"M250 20 C 170 -10, 120 90, 180 110 S 250 40, 150 20 S 40 70, -10 40\" fill=\"none\" stroke=\"currentColor\" stroke-linecap=\"round\" stroke-width=\"1.5\"/>\n <path d=\"M250 50 C 180 20, 140 110, 196 128 S 256 70, 160 52 S 60 100, -10 80\" fill=\"none\" stroke=\"currentColor\" stroke-linecap=\"round\" stroke-width=\"1\"/>\n `\n};\n\n/**\n * One column (or one group within a column) of an `st-mega-menu`: a heading, an optional line of\n * description, then its links stacked — usually `st-menu-item`s with `variant=\"link\"`. Nest\n * columns to stack several headed groups in one column, as okta.com does.\n *\n * `variant=\"card\"` puts the column on a tinted rounded tile and `variant=\"accent\"` on a solid\n * accent tile with light text; both suit a row of equal columns without intro or featured area.\n *\n * `variant=\"product\"` makes a product card for a row of products: an icon tile and a `tag` pill on a\n * top row, the heading and description, the links as rows\n * with a `→` arrow (a new-tab link keeps its `↗` icon), and a full-width `cta-label` + `cta-href`\n * button pinned to the bottom. The icon tile shows `icon` (an iconify name), or, when `icon-src` is set,\n * that image at 28px on the same tinted tile (`icon-src-dark`, if set, replaces it on the dark theme). The\n * card lifts and gets an accent border on hover or focus. Set\n * `accent` (any CSS colour) to tint it; it defaults to the theme accent. A card whose link is the\n * page being shown (see `st-header`'s `current-path`) becomes the \"You are here\" card: a 2px accent\n * border, a faint accent wash, a `currentLabel` pill and a solid button. Inside an `inline`\n * (hamburger) header panel the card does not lift.\n *\n * `decoration` (`none` default, `flow`, `orbit`, `waves` or `ribbon`) draws faint curvy line art in\n * the card's accent behind its top-right corner. It is `product`-only and sits under the content;\n * it drifts on hover or focus, but not in the `inline` panel or with reduced motion.\n *\n * `cta-label` + `cta-href` add a pill button at the bottom of any variant's column.\n *\n * The heading (when `href` is set) and the button fire a *cancelable* `mega-menu-select` event\n * (detail: `{ href }`) before navigating; a host doing client-side routing calls\n * `event.preventDefault()` on it. A link whose `href` is the page being shown (see `st-header`'s\n * `current-path`) gets `aria-current=\"page\"`.\n *\n * @slot - The column's links, or nested `st-mega-menu-column` groups.\n * @fires mega-menu-select - The heading link or the button was clicked (cancelable; detail `{ href }`).\n * @csspart top - The product card's top row (icon tile and pills).\n * @csspart icon - The product card's icon tile. With `icon-src` it holds the image (one, or two with `icon-src-dark`) at 28px, on the same tinted tile.\n * @csspart tag - The product card's tag pill.\n * @csspart current - The product card's \"You are here\" pill.\n * @csspart heading - The heading text or link.\n * @csspart description - The line under the heading.\n * @csspart items - The box holding the links.\n * @csspart cta - The pill button.\n * @csspart decoration - The decorative line art of a `product` card (`decoration` other than `none`).\n * @cssprop --st-mega-menu-column-padding - Overrides the padding of a `card`/`accent` column.\n * @cssprop --st-mega-menu-column-accent - The accent of a `product` card (default `--st-color-accent`); `accent` sets it.\n * @cssprop --st-mega-menu-column-lift - The hover/focus lift of a `product` card (default `-3px`); `st-dropdown` sets it to `0px` while `inline`.\n * @cssprop --st-mega-menu-column-deco-opacity - The resting opacity of the `decoration` line art (default `0.28`); raise or lower it per theme, e.g. on dark surfaces.\n * @cssprop --st-mega-menu-column-deco-transform - The hover/focus shift of the `decoration` line art (default `translate(-6px, 4px)`); `st-dropdown` sets it to `none` while `inline`.\n */\n@customElement('st-mega-menu-column')\nexport class MegaMenuColumn extends LitElement {\n static styles = css`\n ${controlBaseStyles}\n\n :host {\n display: flex;\n flex-direction: column;\n min-width: 0;\n box-sizing: border-box;\n --st-mega-menu-column-accent: var(--st-color-accent);\n /* Accent for text and icons: blended with the theme's strong text colour, so a dark accent\n (e.g. navy) still reads on the dark theme's surface and stays crisp on the light one. */\n --st-mega-menu-column-accent-text: color-mix(in oklch, var(--st-mega-menu-column-accent) 60%, var(--st-color-text-strong));\n ${fontFamilyStyles}\n }\n\n :host([variant='card']),\n :host([variant='accent']) {\n /* !important: a page-level reset (e.g. Tailwind Preflight) otherwise zeroes a shadow host's\n padding; override with --st-mega-menu-column-padding instead. */\n padding: var(--st-mega-menu-column-padding, 2rem 1.75rem 1.75rem) !important;\n border-radius: 20px;\n background: color-mix(in oklch, var(--st-color-text-strong) 5%, var(--st-color-surface));\n }\n\n /* The accent look, from variant=\"accent\" or from current-variant=\"accent\" while the page it links to is shown. */\n :host([variant='accent']),\n :host([current][current-variant='accent']) {\n background: var(--st-color-accent);\n color: var(--st-color-on-solid);\n /* Read by the st-menu-item links inside. */\n --st-nav-color: var(--st-color-on-solid);\n --st-nav-hover-bg: transparent;\n }\n\n .heading {\n display: inline-flex;\n align-items: center;\n gap: 6px;\n margin: 0 0 0.75rem;\n font-size: 1.125rem;\n font-weight: 500;\n line-height: 1.35;\n color: var(--st-color-text-strong);\n text-decoration: none;\n }\n\n :host([variant='card']) .heading,\n :host([variant='accent']) .heading {\n font-size: 1.375rem;\n }\n\n :host([variant='accent']) .heading,\n :host([current][current-variant='accent']) .heading {\n color: inherit;\n }\n\n a.heading:hover,\n a.heading:focus-visible {\n text-decoration: underline;\n text-underline-offset: 4px;\n }\n\n .description {\n margin: -0.25rem 0 0.75rem;\n font-size: 0.875rem;\n line-height: 1.5;\n color: var(--st-color-text-muted);\n }\n\n :host([variant='accent']) .description,\n :host([current][current-variant='accent']) .description {\n color: inherit;\n opacity: 0.85;\n }\n\n .items {\n display: flex;\n flex-direction: column;\n gap: 2px;\n }\n\n /* Nested groups stack with room between them (!important for the same page-reset reason). */\n ::slotted(st-mega-menu-column:not(:first-child)) {\n margin-top: 2rem !important;\n }\n\n .cta {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n gap: 6px;\n padding: 0.875rem 1.5rem;\n border-radius: 9999px;\n background: var(--st-color-surface);\n color: var(--st-color-text-strong);\n font-size: 1rem;\n font-weight: 500;\n text-align: center;\n text-decoration: none;\n transition: box-shadow 0.2s ease;\n }\n\n .cta-spacer {\n flex: 1;\n min-height: 1.75rem;\n }\n\n .cta:hover,\n .cta:focus-visible {\n box-shadow: 0 0 0 2px currentColor;\n }\n\n .cta-arrow {\n display: inline-block;\n }\n\n @media (prefers-reduced-motion: reduce) {\n .cta {\n transition: none;\n }\n }\n\n /* ---- variant=\"product\": a product card ---- */\n\n .edge,\n .top,\n .tile,\n .pill {\n display: none;\n }\n\n :host([variant='product']) {\n position: relative;\n overflow: hidden;\n gap: 14px;\n /* !important for the same page-reset reason as card/accent. The border is 1px; the current card's\n 2px border takes its padding from the 1px it gives up, so nothing moves. */\n padding: 24px !important;\n border: 1px solid var(--st-color-border);\n border-radius: 20px;\n background: var(--st-color-surface);\n box-shadow: 0 1px 2px var(--st-shadow-color-sm);\n transition:\n transform 0.2s ease,\n box-shadow 0.2s ease,\n border-color 0.2s ease,\n background-color 0.2s ease;\n }\n\n :host([variant='product']) .edge {\n display: block;\n position: absolute;\n top: 0;\n left: 0;\n right: 0;\n height: 3px;\n background: linear-gradient(90deg, var(--st-mega-menu-column-accent), transparent);\n pointer-events: none;\n }\n\n /* The decorative line art: behind the card's content (z-index 0), faded toward the bottom-left. */\n :host([variant='product']) .deco {\n position: absolute;\n top: 0;\n right: 0;\n width: 240px;\n height: 160px;\n z-index: 0;\n pointer-events: none;\n color: var(--st-mega-menu-column-accent);\n opacity: var(--st-mega-menu-column-deco-opacity, 0.28);\n -webkit-mask-image: radial-gradient(120% 120% at 100% 0%, #000 35%, transparent 75%);\n mask-image: radial-gradient(120% 120% at 100% 0%, #000 35%, transparent 75%);\n transition:\n transform 0.4s ease,\n opacity 0.4s ease;\n }\n\n /* Everything else in the card paints above the line art (.edge keeps its absolute position). */\n :host([variant='product']) .edge {\n z-index: 1;\n }\n\n :host([variant='product']) .top,\n :host([variant='product']) .heading,\n :host([variant='product']) .description,\n :host([variant='product']) .items,\n :host([variant='product']) .cta-spacer,\n :host([variant='product']) .cta {\n position: relative;\n z-index: 1;\n }\n\n :host([variant='product']:hover) .deco,\n :host([variant='product']:focus-within) .deco {\n opacity: 0.5;\n transform: var(--st-mega-menu-column-deco-transform, translate(-6px, 4px));\n }\n\n :host([variant='product'][current]) .deco {\n opacity: 0.42;\n }\n\n :host([variant='product']) .top {\n display: flex;\n align-items: flex-start;\n justify-content: space-between;\n gap: 8px;\n }\n\n :host([variant='product']) .tile {\n display: inline-flex;\n flex: none;\n align-items: center;\n justify-content: center;\n width: 44px;\n height: 44px;\n border-radius: 12px;\n background: color-mix(in oklch, var(--st-mega-menu-column-accent) 14%, transparent);\n color: var(--st-mega-menu-column-accent-text);\n }\n\n :host([variant='product']) .tile iconify-icon {\n display: block;\n width: 24px;\n height: 24px;\n font-size: 24px;\n }\n\n /* The image is 28px inside the 44px tile, which keeps the same tinted background as an iconify tile. No display here: the theme classes below set it. */\n :host([variant='product']) .tile img {\n flex: none;\n width: 28px;\n height: 28px;\n object-fit: contain;\n }\n\n /* Light and dark icon per the site's theme: the dark one shows on :root.dark (see --st-theme-*-display). */\n .theme-light {\n display: var(--st-theme-light-display, inline-block);\n }\n\n .theme-dark {\n display: var(--st-theme-dark-display, none);\n }\n\n :host([variant='product']) .pills {\n display: flex;\n flex-wrap: wrap;\n justify-content: flex-end;\n gap: 6px;\n margin-left: auto;\n }\n\n :host([variant='product']) .pill {\n display: inline-flex;\n align-items: center;\n height: 22px;\n padding: 0 8px;\n border-radius: 9999px;\n font-size: 11px;\n font-weight: 600;\n letter-spacing: 0.04em;\n text-transform: uppercase;\n white-space: nowrap;\n }\n\n :host([variant='product']) .pill.tag {\n display: inline-flex;\n background: color-mix(in oklch, var(--st-mega-menu-column-accent) 12%, transparent);\n color: var(--st-mega-menu-column-accent-text);\n }\n\n :host([variant='product']) .heading {\n margin: 0;\n font-size: 1.125rem;\n font-weight: 600;\n }\n\n :host([variant='product']) .description {\n margin: 0;\n }\n\n :host([variant='product']) .items.has-links {\n gap: 4px;\n padding-top: 12px;\n border-top: 1px solid var(--st-color-border);\n }\n\n /* Each link is a row: the arrow (set on the links here, drawn by st-menu-item) slides on hover in the accent. */\n :host([variant='product']) ::slotted(st-menu-item) {\n --st-menu-item-arrow: '→';\n }\n\n :host([variant='product']) ::slotted(st-menu-item:hover) {\n --st-nav-color: var(--st-mega-menu-column-accent-text);\n }\n\n :host([variant='product']) .cta {\n display: flex;\n box-sizing: border-box;\n width: 100%;\n height: 40px;\n padding: 0 1rem;\n white-space: nowrap;\n background: color-mix(in oklch, var(--st-mega-menu-column-accent) 10%, transparent);\n color: var(--st-mega-menu-column-accent-text);\n font-size: 0.875rem;\n font-weight: 600;\n transition:\n background-color 0.2s ease,\n color 0.2s ease;\n }\n\n :host([variant='product']) .cta:hover,\n :host([variant='product']) .cta:focus-visible {\n box-shadow: none;\n background: var(--st-mega-menu-column-accent);\n color: #fff;\n }\n\n :host([variant='product']) .cta:hover .cta-arrow,\n :host([variant='product']) .cta:focus-visible .cta-arrow {\n transform: translateX(2px);\n }\n\n :host([variant='product']:hover),\n :host([variant='product']:focus-within) {\n transform: translateY(var(--st-mega-menu-column-lift, -3px));\n box-shadow: 0 16px 32px -12px var(--st-shadow-color-md);\n border-color: color-mix(in oklch, var(--st-mega-menu-column-accent) 45%, var(--st-color-border));\n }\n\n /* The page being shown: no solid block, an accent border and wash, and a solid button. Declared after\n the hover rules so it keeps its border while hovered. */\n :host([variant='product'][current]) {\n padding: 23px !important;\n border: 2px solid var(--st-mega-menu-column-accent);\n background: color-mix(in oklch, var(--st-mega-menu-column-accent) 6%, var(--st-color-surface));\n }\n\n :host([variant='product'][current]) .pill.current {\n display: inline-flex;\n background: var(--st-mega-menu-column-accent);\n color: #fff;\n }\n\n :host([variant='product'][current]) .cta {\n background: var(--st-mega-menu-column-accent);\n color: #fff;\n }\n\n :host([variant='product'][current]) .cta:hover,\n :host([variant='product'][current]) .cta:focus-visible {\n background: color-mix(in oklch, var(--st-mega-menu-column-accent) 85%, #000);\n color: #fff;\n }\n\n @media (prefers-reduced-motion: reduce) {\n :host([variant='product']),\n :host([variant='product']) .cta,\n :host([variant='product']) .cta-arrow {\n transition: none;\n }\n\n :host([variant='product']:hover),\n :host([variant='product']:focus-within) {\n transform: none;\n }\n\n :host([variant='product']) .deco {\n transition: none;\n }\n\n :host([variant='product']:hover) .deco,\n :host([variant='product']:focus-within) .deco {\n transform: none;\n }\n\n :host([variant='product']) .cta:hover .cta-arrow,\n :host([variant='product']) .cta:focus-visible .cta-arrow {\n transform: none;\n }\n }\n `;\n\n @property({ type: String })\n heading = '';\n\n /** Makes the heading a link (e.g. to the section's overview page). */\n @property({ type: String })\n href = '';\n\n @property({ type: String })\n description = '';\n\n /** `plain` (default), `card` (tinted tile), `accent` (solid accent tile, light text) or `product` (a product card). */\n @property({ type: String, reflect: true })\n variant: 'plain' | 'card' | 'accent' | 'product' = 'plain';\n\n /** Text of a pill button at the bottom of the column; needs `cta-href`. */\n @property({ type: String, attribute: 'cta-label' })\n ctaLabel = '';\n\n @property({ type: String, attribute: 'cta-href' })\n ctaHref = '';\n\n /**\n * Variant the column takes while its heading or button links to the page being shown, e.g. a card\n * that turns accent on its own product page. Empty (default) keeps `variant` at all times.\n */\n @property({ type: String, attribute: 'current-variant', reflect: true })\n currentVariant: '' | 'plain' | 'card' | 'accent' = '';\n\n /** Small icon tile on a `product` card: an iconify icon name, e.g. `heroicons:book-open`. */\n @property({ type: String })\n icon = '';\n\n /** Image icon of a `product` card (28px inside the 44px tile), e.g. a product logo. Replaces the iconify `icon` when set. */\n @property({ type: String, attribute: 'icon-src' })\n iconSrc = '';\n\n /** Dark-theme variant of `icon-src`, shown on the site's dark theme (`:root.dark`) in place of it. Needs `icon-src`. */\n @property({ type: String, attribute: 'icon-src-dark' })\n iconSrcDark = '';\n\n /** Short label pill on the top row of a `product` card, e.g. `Open source`. */\n @property({ type: String })\n tag = '';\n\n /** Accent of a `product` card, any CSS colour (sets `--st-mega-menu-column-accent`). */\n @property({ type: String })\n accent = '';\n\n /**\n * Decorative curvy line art behind a `product` card's top-right corner: `flow` (lines fanning down-left),\n * `orbit` (concentric arcs), `waves` (parallel waves across the top) or `ribbon` (crossing loops).\n * `none` (default) draws nothing. Other variants ignore it.\n */\n @property({ type: String, reflect: true })\n decoration: 'none' | 'flow' | 'orbit' | 'waves' | 'ribbon' = 'none';\n\n /** \"You are here\" marker on the `product` card of the page being shown. */\n @property({ type: String, attribute: 'current-label' })\n currentLabel = 'Current';\n\n /** Page path the header is showing; set by `st-header`. A link whose href matches gets `aria-current=\"page\"`. */\n @property({ attribute: false })\n currentPath = '';\n\n /**\n * True while the column is the page being shown: while `current-variant` applies, or always for a\n * `product` card. Set by the column, never from outside.\n */\n @property({ type: Boolean, reflect: true })\n current = false;\n\n /** Whether the links slot has any links, so a `product` card draws its divider only above them. */\n @state() private hasLinks = false;\n\n private onLinksSlotChange = (event: Event): void => {\n this.hasLinks = (event.target as HTMLSlotElement).assignedElements({ flatten: true }).length > 0;\n };\n\n protected willUpdate(changed: Map<string, unknown>): void {\n if (\n changed.has('currentVariant') ||\n changed.has('variant') ||\n changed.has('currentPath') ||\n changed.has('href') ||\n changed.has('ctaHref')\n ) {\n this.current =\n (!!this.currentVariant || this.variant === 'product') &&\n (isCurrentPath(this.href, this.currentPath) || isCurrentPath(this.ctaHref, this.currentPath));\n }\n if (changed.has('accent')) {\n if (this.accent) this.style.setProperty('--st-mega-menu-column-accent', this.accent);\n else this.style.removeProperty('--st-mega-menu-column-accent');\n }\n }\n\n private select(event: MouseEvent, href: string): void {\n if (href.startsWith('http')) return;\n const selectEvent = new CustomEvent<MegaMenuSelectEventDetail>('mega-menu-select', {\n detail: { href },\n bubbles: true,\n composed: true,\n cancelable: true\n });\n this.dispatchEvent(selectEvent);\n if (selectEvent.defaultPrevented) event.preventDefault();\n }\n\n private renderHeading() {\n if (!this.heading) return nothing;\n return this.href\n ? html`<a\n part=\"heading\"\n class=\"heading\"\n href=${this.href}\n aria-current=${isCurrentPath(this.href, this.currentPath) ? 'page' : nothing}\n @click=${(event: MouseEvent) => this.select(event, this.href)}\n >${this.heading}</a\n >`\n : html`<p part=\"heading\" class=\"heading\">${this.heading}</p>`;\n }\n\n private renderDecoration() {\n if (this.variant !== 'product' || this.decoration === 'none') return nothing;\n return html`<svg\n class=\"deco\"\n part=\"decoration\"\n viewBox=\"0 0 240 160\"\n preserveAspectRatio=\"xMaxYMin meet\"\n aria-hidden=\"true\"\n focusable=\"false\"\n >${DECORATIONS[this.decoration]}</svg\n >`;\n }\n\n /** The tile's content: the `icon-src` image (light, plus the dark one when `icon-src-dark` is set), else the iconify `icon`. */\n private renderTileIcon() {\n if (this.iconSrc) {\n const light = html`<img class=\"${this.iconSrcDark ? 'theme-light' : ''}\" src=${this.iconSrc} alt=\"\" width=\"28\" height=\"28\" />`;\n if (!this.iconSrcDark) return light;\n return html`${light}<img class=\"theme-dark\" src=${this.iconSrcDark} alt=\"\" width=\"28\" height=\"28\" />`;\n }\n return html`<iconify-icon icon=${this.icon} aria-hidden=\"true\"></iconify-icon>`;\n }\n\n private renderTop() {\n if (this.variant !== 'product') return nothing;\n return html`<div part=\"top\" class=\"top\">\n ${this.iconSrc || this.icon\n ? html`<span part=\"icon\" class=\"tile ${this.iconSrc ? 'image' : ''}\">${this.renderTileIcon()}</span>`\n : nothing}\n <span class=\"pills\">\n ${this.current\n ? html`<span part=\"current\" class=\"pill current\">${this.currentLabel}</span>`\n : this.tag\n ? html`<span part=\"tag\" class=\"pill tag\">${this.tag}</span>`\n : nothing}\n </span>\n </div>`;\n }\n\n private renderCta() {\n if (!this.ctaLabel || !this.ctaHref) return nothing;\n const external = this.ctaHref.startsWith('http');\n let trailing: unknown = nothing;\n if (external) trailing = arrowUpRightIcon(14);\n else if (this.variant === 'product') trailing = html`<span class=\"cta-arrow\" aria-hidden=\"true\">→</span>`;\n return html`\n <span class=\"cta-spacer\"></span>\n <a\n part=\"cta\"\n class=\"cta\"\n href=${this.ctaHref}\n target=${external ? '_blank' : '_self'}\n rel=${external ? 'noopener noreferrer' : nothing}\n aria-current=${isCurrentPath(this.ctaHref, this.currentPath) ? 'page' : nothing}\n @click=${(event: MouseEvent) => this.select(event, this.ctaHref)}\n >${this.ctaLabel} ${trailing}</a\n >\n `;\n }\n\n render() {\n return html`\n ${this.renderDecoration()}\n ${this.variant === 'product' ? html`<span class=\"edge\" part=\"edge\" aria-hidden=\"true\"></span>` : nothing}\n ${this.renderTop()}\n ${this.renderHeading()}\n ${this.description ? html`<p part=\"description\" class=\"description\">${this.description}</p>` : nothing}\n <div part=\"items\" class=${this.hasLinks ? 'items has-links' : 'items'} role=\"group\" aria-label=${this.heading || nothing}><slot @slotchange=${this.onLinksSlotChange}></slot></div>\n ${this.renderCta()}\n `;\n }\n}\n","import { LitElement, css, html, nothing } from 'lit';\nimport { customElement, property } from 'lit/decorators.js';\n\nimport { controlBaseStyles, fontFamilyStyles } from '../shared/styles';\nimport { isCurrentPath } from '../shared/nav-path';\nimport type { MegaMenuSelectEventDetail } from './MegaMenuEvents';\n\n/**\n * A promo card for the featured column of an `st-mega-menu` (`slot=\"featured\"`). The whole card\n * is one link. Two looks, after okta.com:\n *\n * - `story` (default): a rounded image on top, then the description and an underlined\n * call-to-action line — a customer story or announcement.\n * - `overlay`: a tile with light text over `image-url` (darkened), or over an accent gradient when\n * there is no image — an optional `logo-url` top left, the title and description at the bottom.\n *\n * An `http(s)` `href` opens in a new tab unless `target` says otherwise. Any other `href` fires a\n * *cancelable* `mega-menu-select` event (detail: `{ href }`) first; a host doing client-side\n * routing calls `event.preventDefault()` on it.\n *\n * @fires mega-menu-select - The card was clicked (cancelable; detail `{ href }`).\n * @csspart card - The card link.\n * @csspart image - The image (`story`).\n * @csspart logo - The logo (`overlay`).\n * @csspart eyebrow - The small label above the title.\n * @csspart title - The title.\n * @csspart description - The description.\n * @csspart cta - The call-to-action line.\n * @cssprop --st-mega-menu-feature-from - Start colour of the `overlay` gradient (default: the accent colour).\n * @cssprop --st-mega-menu-feature-to - End colour of the `overlay` gradient.\n */\n@customElement('st-mega-menu-feature')\nexport class MegaMenuFeature extends LitElement {\n /** `focus()` on the element focuses its link, so `st-dropdown` can arrow-key to it. */\n static shadowRootOptions = { ...LitElement.shadowRootOptions, delegatesFocus: true };\n\n static styles = css`\n ${controlBaseStyles}\n\n :host {\n display: block;\n ${fontFamilyStyles}\n }\n\n .card {\n display: flex;\n flex-direction: column;\n gap: 0.75rem;\n box-sizing: border-box;\n color: var(--st-color-text-strong);\n text-decoration: none;\n }\n\n .image {\n display: block;\n width: 100%;\n aspect-ratio: 9 / 8;\n object-fit: cover;\n border-radius: 20px;\n transition: transform 0.3s ease;\n }\n\n .card:hover .image {\n transform: scale(1.015);\n }\n\n .eyebrow {\n font-size: 0.75rem;\n font-weight: 600;\n letter-spacing: 0.06em;\n text-transform: uppercase;\n color: var(--st-color-accent-text);\n }\n\n .title {\n margin: 0;\n font-size: 1.125rem;\n font-weight: 500;\n line-height: 1.3;\n }\n\n .description {\n margin: 0;\n font-size: 0.9375rem;\n line-height: 1.5;\n }\n\n .cta {\n align-self: flex-start;\n margin-top: 0.75rem;\n font-size: 0.9375rem;\n font-weight: 500;\n text-decoration: underline;\n text-underline-offset: 5px;\n text-decoration-thickness: 1px;\n }\n\n .card:hover .cta,\n .card:focus-visible .cta {\n text-decoration-thickness: 2px;\n }\n\n /* overlay */\n :host([variant='overlay']) .card {\n justify-content: flex-end;\n gap: 0.5rem;\n min-height: 15rem;\n padding: 1.75rem;\n border-radius: 20px;\n color: #fff;\n background-color: var(--st-color-accent);\n background-image:\n linear-gradient(to top, rgb(0 0 0 / 0.55), rgb(0 0 0 / 0.05)),\n var(--st-mega-menu-feature-image, linear-gradient(160deg, var(--st-mega-menu-feature-from, var(--st-color-accent)), var(--st-mega-menu-feature-to, oklch(0.25 0.12 280))));\n background-size: cover;\n background-position: center;\n transition: transform 0.2s ease;\n }\n\n :host([variant='overlay']) .card:hover {\n transform: translateY(-2px);\n }\n\n :host([variant='overlay']) .logo {\n height: 2.25rem;\n width: auto;\n max-width: 70%;\n margin-bottom: auto;\n align-self: flex-start;\n object-fit: contain;\n }\n\n :host([variant='overlay']) .title {\n font-size: 1.75rem;\n font-weight: 400;\n }\n\n :host([variant='overlay']) .eyebrow,\n :host([variant='overlay']) .cta {\n color: inherit;\n }\n\n /* tip: a light-blue card with dark text, like a tip panel on a page. */\n :host([variant='tip']) .card {\n gap: 0.5rem;\n padding: 1.25rem;\n border-radius: var(--st-radius-md);\n border: 1px solid var(--st-color-accent-border);\n background: var(--st-color-accent-subtle);\n color: var(--st-color-text);\n transition: border-color 0.2s ease;\n }\n\n :host([variant='tip']) .card:hover {\n border-color: var(--st-color-accent-muted);\n }\n\n :host([variant='tip']) .title {\n font-size: var(--st-text-lg);\n font-weight: var(--st-font-weight-semibold);\n color: var(--st-color-text-strong);\n }\n\n :host([variant='tip']) .eyebrow,\n :host([variant='tip']) .cta {\n color: var(--st-color-accent-text);\n }\n\n @media (prefers-reduced-motion: reduce) {\n .image,\n :host([variant='overlay']) .card {\n transition: none;\n }\n }\n `;\n\n /** `story` (default), `overlay` (dark, over an image or gradient) or `tip` (light blue, for a hint). */\n @property({ type: String, reflect: true })\n variant: 'story' | 'overlay' | 'tip' = 'story';\n\n @property({ type: String })\n title = '';\n\n @property({ type: String })\n description = '';\n\n /** Small label above the title, e.g. \"New\" or \"Report\". */\n @property({ type: String })\n eyebrow = '';\n\n @property({ type: String })\n href = '';\n\n /** `target` for the link. Defaults to `_blank` for an `http(s)` `href`, `_self` otherwise. */\n @property({ type: String })\n target = '';\n\n /** Image on top (`story`) or behind the text (`overlay`). */\n @property({ type: String, attribute: 'image-url' })\n imageUrl = '';\n\n @property({ type: String, attribute: 'image-alt' })\n imageAlt = '';\n\n /** Logo at the top of an `overlay` card. */\n @property({ type: String, attribute: 'logo-url' })\n logoUrl = '';\n\n @property({ type: String, attribute: 'logo-alt' })\n logoAlt = '';\n\n /** Call-to-action text at the bottom of the card; empty hides it. */\n @property({ type: String, attribute: 'cta-label' })\n ctaLabel = '';\n\n /** Page path the header is showing; set by `st-header`. A card whose `href` matches gets `aria-current=\"page\"`. */\n @property({ attribute: false })\n currentPath = '';\n\n private get isExternal(): boolean {\n return this.href.startsWith('http');\n }\n\n private onClick = (event: MouseEvent): void => {\n if (this.isExternal) return;\n const selectEvent = new CustomEvent<MegaMenuSelectEventDetail>('mega-menu-select', {\n detail: { href: this.href },\n bubbles: true,\n composed: true,\n cancelable: true\n });\n this.dispatchEvent(selectEvent);\n if (selectEvent.defaultPrevented) event.preventDefault();\n };\n\n render() {\n const target = this.target || (this.isExternal ? '_blank' : '_self');\n const overlay = this.variant === 'overlay';\n const style = overlay && this.imageUrl ? `--st-mega-menu-feature-image:url(${JSON.stringify(this.imageUrl)})` : '';\n return html`\n <a\n part=\"card\"\n class=\"card\"\n style=${style}\n href=${this.href || nothing}\n target=${target}\n rel=${target === '_blank' ? 'noopener noreferrer' : nothing}\n aria-current=${isCurrentPath(this.href, this.currentPath) ? 'page' : nothing}\n @click=${this.onClick}\n >\n ${overlay && this.logoUrl ? html`<img part=\"logo\" class=\"logo\" src=${this.logoUrl} alt=${this.logoAlt} />` : nothing}\n ${!overlay && this.imageUrl\n ? html`<img part=\"image\" class=\"image\" src=${this.imageUrl} alt=${this.imageAlt} loading=\"lazy\" />`\n : nothing}\n ${this.eyebrow ? html`<span part=\"eyebrow\" class=\"eyebrow\">${this.eyebrow}</span>` : nothing}\n ${this.title ? html`<p part=\"title\" class=\"title\">${this.title}</p>` : nothing}\n ${this.description ? html`<p part=\"description\" class=\"description\">${this.description}</p>` : nothing}\n ${this.ctaLabel ? html`<span part=\"cta\" class=\"cta\">${this.ctaLabel}</span>` : nothing}\n </a>\n `;\n }\n}\n"],"mappings":"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","names":["LitElement","css","html","nothing","customElement","property","state","LitElement","nothing","html","css","property","state","customElement","LitElement","css","html","nothing","customElement","property","LitElement","html","nothing","css","property","customElement"]}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import {
|
|
2
2
|
fontFamilyStyles
|
|
3
|
-
} from "./chunk-
|
|
3
|
+
} from "./chunk-NXUS2CH7.js";
|
|
4
4
|
import {
|
|
5
5
|
__decorateClass
|
|
6
6
|
} from "./chunk-EUXUH3YW.js";
|
|
@@ -130,4 +130,4 @@ AttentionPanel = __decorateClass([
|
|
|
130
130
|
export {
|
|
131
131
|
AttentionPanel
|
|
132
132
|
};
|
|
133
|
-
//# sourceMappingURL=chunk-
|
|
133
|
+
//# sourceMappingURL=chunk-NABSRUXG.js.map
|
|
@@ -1,10 +1,13 @@
|
|
|
1
|
+
import {
|
|
2
|
+
isCurrentPath
|
|
3
|
+
} from "./chunk-UKIVLF7S.js";
|
|
1
4
|
import {
|
|
2
5
|
arrowUpRightIcon
|
|
3
6
|
} from "./chunk-WTD2YIAA.js";
|
|
4
7
|
import {
|
|
5
8
|
controlBaseStyles,
|
|
6
9
|
fontFamilyStyles
|
|
7
|
-
} from "./chunk-
|
|
10
|
+
} from "./chunk-NXUS2CH7.js";
|
|
8
11
|
import {
|
|
9
12
|
__decorateClass
|
|
10
13
|
} from "./chunk-EUXUH3YW.js";
|
|
@@ -20,6 +23,7 @@ var MenuItem = class extends LitElement {
|
|
|
20
23
|
this.description = "";
|
|
21
24
|
this.badge = "";
|
|
22
25
|
this.active = false;
|
|
26
|
+
this.currentPath = "";
|
|
23
27
|
this.compact = false;
|
|
24
28
|
this.showDescription = true;
|
|
25
29
|
this.target = "_self";
|
|
@@ -43,11 +47,12 @@ var MenuItem = class extends LitElement {
|
|
|
43
47
|
render() {
|
|
44
48
|
const showDescription = !!this.description && this.showDescription;
|
|
45
49
|
const link = this.variant === "link";
|
|
50
|
+
const current = isCurrentPath(this.href, this.currentPath);
|
|
46
51
|
const classes = [
|
|
47
52
|
"menu-item",
|
|
48
53
|
link ? "link" : "",
|
|
49
54
|
this.variant === "bar" ? "bar" : "",
|
|
50
|
-
this.active ? "active" : "",
|
|
55
|
+
this.active || current ? "active" : "",
|
|
51
56
|
this.compact ? "compact" : "",
|
|
52
57
|
showDescription ? "" : "no-description"
|
|
53
58
|
].filter(Boolean).join(" ");
|
|
@@ -59,6 +64,7 @@ var MenuItem = class extends LitElement {
|
|
|
59
64
|
href=${this.href}
|
|
60
65
|
target=${this.target}
|
|
61
66
|
rel=${this.target === "_blank" ? "noopener noreferrer" : nothing}
|
|
67
|
+
aria-current=${current ? "page" : nothing}
|
|
62
68
|
@click=${this.onClick}
|
|
63
69
|
>
|
|
64
70
|
<span
|
|
@@ -151,10 +157,11 @@ MenuItem.styles = css`
|
|
|
151
157
|
transition-duration: 0.1s;
|
|
152
158
|
}
|
|
153
159
|
|
|
160
|
+
/* The current page: an underline, the one indicator the header uses. No fill and no side bar. The
|
|
161
|
+
header sets --st-nav-active-line to follow its own text colour on a hero. */
|
|
154
162
|
.menu-item.active {
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
border-left: 4px solid var(--st-color-accent);
|
|
163
|
+
color: var(--st-nav-color, var(--st-color-accent-text));
|
|
164
|
+
box-shadow: inset 0 -2px 0 var(--st-nav-active-line, var(--st-color-accent));
|
|
158
165
|
}
|
|
159
166
|
|
|
160
167
|
.menu-item-icon {
|
|
@@ -267,6 +274,34 @@ MenuItem.styles = css`
|
|
|
267
274
|
transform: none;
|
|
268
275
|
}
|
|
269
276
|
|
|
277
|
+
/* The row arrow of a product card (st-mega-menu-column variant="product" sets --st-menu-item-arrow).
|
|
278
|
+
Nothing is drawn by default, and never on a link that opens a new tab (its ↗ icon sits in the title). */
|
|
279
|
+
.menu-item.link::after {
|
|
280
|
+
content: var(--st-menu-item-arrow, none);
|
|
281
|
+
flex: none;
|
|
282
|
+
transition: transform 0.2s ease;
|
|
283
|
+
}
|
|
284
|
+
|
|
285
|
+
.menu-item.link[target='_blank']::after {
|
|
286
|
+
content: none;
|
|
287
|
+
}
|
|
288
|
+
|
|
289
|
+
.menu-item.link:hover::after,
|
|
290
|
+
.menu-item.link:focus-visible::after {
|
|
291
|
+
transform: translateX(2px);
|
|
292
|
+
}
|
|
293
|
+
|
|
294
|
+
@media (prefers-reduced-motion: reduce) {
|
|
295
|
+
.menu-item.link::after {
|
|
296
|
+
transition: none;
|
|
297
|
+
}
|
|
298
|
+
|
|
299
|
+
.menu-item.link:hover::after,
|
|
300
|
+
.menu-item.link:focus-visible::after {
|
|
301
|
+
transform: none;
|
|
302
|
+
}
|
|
303
|
+
}
|
|
304
|
+
|
|
270
305
|
.menu-item.link.active {
|
|
271
306
|
border-left: 0;
|
|
272
307
|
background: transparent;
|
|
@@ -366,6 +401,9 @@ __decorateClass([
|
|
|
366
401
|
__decorateClass([
|
|
367
402
|
property({ type: Boolean, reflect: true })
|
|
368
403
|
], MenuItem.prototype, "active", 2);
|
|
404
|
+
__decorateClass([
|
|
405
|
+
property({ attribute: false })
|
|
406
|
+
], MenuItem.prototype, "currentPath", 2);
|
|
369
407
|
__decorateClass([
|
|
370
408
|
property({ type: Boolean, reflect: true })
|
|
371
409
|
], MenuItem.prototype, "compact", 2);
|
|
@@ -391,4 +429,4 @@ MenuItem = __decorateClass([
|
|
|
391
429
|
export {
|
|
392
430
|
MenuItem
|
|
393
431
|
};
|
|
394
|
-
//# sourceMappingURL=chunk-
|
|
432
|
+
//# sourceMappingURL=chunk-NXKDZWS7.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/menu-item/MenuItem.ts"],"sourcesContent":["import { LitElement, css, html, nothing } from 'lit';\nimport { customElement, property, state } from 'lit/decorators.js';\n\nimport { arrowUpRightIcon } from '../shared/icons';\nimport { controlBaseStyles, fontFamilyStyles } from '../shared/styles';\nimport { isCurrentPath } from '../shared/nav-path';\nimport type { MenuItemSelectEventDetail } from './MenuItemEvents';\n\n/**\n * A single flat nav row — icon (`slot=\"icon\"`) + title + badge on one line, an optional\n * description below — as opposed to `st-menu-grid-item`'s card for a multi-column grid. Effects\n * are CSS: nudges right and scales to 1.01 on hover / 0.99 while pressed, the icon tilts on hover,\n * the badge pops in, the description fades in. Colors come from the suite theme rather than\n * per-item utility classes.\n *\n * Renders a real `<a href>` but fires a *cancelable* `menu-item-select` event (detail: `{ href }`)\n * before navigating — a host doing client-side routing calls `event.preventDefault()` on it.\n *\n * It is the current page (`aria-current=\"page\"`, shown as active) when `active` is set, or when the\n * `href` matches `currentPath`, which an enclosing `st-header` sets from its `current-path`.\n *\n * @slot icon - The row's icon, sized to `icon-size` (16px, or 14px when `compact`).\n * @cssprop --st-menu-item-icon-size - Width and height of the slotted icon; `icon-size` sets it.\n * @cssprop --st-menu-item-arrow - A trailing glyph (e.g. `'→'`) drawn after a `link` variant's title; none by default, and not drawn on a link that opens a new tab.\n */\n@customElement('st-menu-item')\nexport class MenuItem extends LitElement {\n /** `focus()` on the element focuses its link, so `st-dropdown` can arrow-key between items. */\n static shadowRootOptions = { ...LitElement.shadowRootOptions, delegatesFocus: true };\n\n static styles = css`\n ${controlBaseStyles}\n\n :host {\n display: block;\n ${fontFamilyStyles}\n }\n\n @keyframes st-menu-item-badge-pop {\n from {\n transform: scale(0);\n }\n 70% {\n transform: scale(1.12);\n }\n to {\n transform: scale(1);\n }\n }\n\n @keyframes st-menu-item-fade-in {\n from {\n opacity: 0;\n }\n to {\n opacity: 1;\n }\n }\n\n .menu-item {\n display: flex;\n align-items: flex-start;\n gap: 12px;\n padding: 12px 16px;\n font-size: 0.875rem;\n text-decoration: none;\n /* --st-nav-*: set by a host bar (st-header's transparent state) to recolour its nav items. */\n color: var(--st-nav-color, var(--st-color-text));\n border-radius: 6px;\n /* The source's 'all 0.15s', minus visibility: animating the visibility this link inherits\n from a dropdown panel kept it unfocusable for a frame after the panel opened. */\n transition-property: background-color, color, padding, transform, border-color;\n transition-duration: 0.15s;\n transition-timing-function: ease;\n box-sizing: border-box;\n }\n\n /* The source's hover nudge (x: 4px) is done with padding, not a transform: a transform would\n spill past a scrolling panel's edge (st-source-bar's menus) and show a horizontal scrollbar.\n Keyboard focus gets the same treatment as hover. */\n .menu-item:hover,\n .menu-item:focus-visible {\n background: var(--st-nav-hover-bg, var(--st-color-hover));\n color: var(--st-nav-color, var(--st-color-text-strong));\n padding-left: 20px;\n transition-duration: 0.1s;\n }\n\n .menu-item.compact:hover,\n .menu-item.compact:focus-visible {\n padding-left: 16px;\n }\n\n .menu-item:active {\n transform: scale(0.99);\n transition-duration: 0.1s;\n }\n\n /* The current page: an underline, the one indicator the header uses. No fill and no side bar. The\n header sets --st-nav-active-line to follow its own text colour on a hero. */\n .menu-item.active {\n color: var(--st-nav-color, var(--st-color-accent-text));\n box-shadow: inset 0 -2px 0 var(--st-nav-active-line, var(--st-color-accent));\n }\n\n .menu-item-icon {\n display: flex;\n flex-shrink: 0;\n margin-top: 2px;\n transition: transform 0.2s ease;\n }\n\n .menu-item-icon:hover {\n transform: rotate(5deg);\n }\n\n .menu-item-icon[hidden] {\n display: none;\n }\n\n .menu-item-icon ::slotted(*) {\n width: var(--st-menu-item-icon-size, 16px);\n height: var(--st-menu-item-icon-size, 16px);\n }\n\n .menu-item-content {\n flex: 1;\n min-width: 0;\n }\n\n .menu-item-header {\n display: flex;\n align-items: center;\n justify-content: space-between;\n gap: 8px;\n }\n\n .menu-item-title {\n font-weight: 500;\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n }\n\n .menu-item-badge {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n min-width: 20px;\n height: 20px;\n padding: 0 6px;\n font-size: 0.75rem;\n font-weight: 500;\n border-radius: 9999px;\n flex-shrink: 0;\n background: var(--st-color-accent-subtle);\n color: var(--st-color-accent-text);\n animation: st-menu-item-badge-pop 0.35s ease-out;\n }\n\n .menu-item-description {\n display: -webkit-box;\n margin: 4px 0 0;\n font-size: 0.75rem;\n color: var(--st-color-text-muted);\n -webkit-box-orient: vertical;\n overflow: hidden;\n line-height: 1.4;\n animation: st-menu-item-fade-in 0.2s ease;\n }\n\n .menu-item.compact {\n padding: 8px 12px;\n gap: 8px;\n }\n\n .menu-item.compact .menu-item-icon ::slotted(*) {\n width: var(--st-menu-item-icon-size, 14px);\n height: var(--st-menu-item-icon-size, 14px);\n }\n\n .menu-item.compact .menu-item-title {\n font-size: 0.75rem;\n }\n\n .menu-item.compact .menu-item-description {\n font-size: 0.75rem;\n }\n\n /* link: a plain text link (okta.com mega-menu columns) — no box, no nudge, the badge right\n after the title, long titles wrap. */\n .menu-item.link {\n padding: 7px 0;\n gap: 10px;\n font-size: 0.9375rem;\n color: var(--st-nav-color, var(--st-color-text));\n }\n\n .menu-item.link:hover,\n .menu-item.link:focus-visible {\n padding-left: 0;\n background: transparent;\n color: var(--st-nav-color, var(--st-color-text-strong));\n }\n\n .menu-item.link:hover .menu-item-title,\n .menu-item.link:focus-visible .menu-item-title {\n text-decoration: underline;\n text-underline-offset: 4px;\n }\n\n .menu-item.link:active {\n transform: none;\n }\n\n /* The row arrow of a product card (st-mega-menu-column variant=\"product\" sets --st-menu-item-arrow).\n Nothing is drawn by default, and never on a link that opens a new tab (its ↗ icon sits in the title). */\n .menu-item.link::after {\n content: var(--st-menu-item-arrow, none);\n flex: none;\n transition: transform 0.2s ease;\n }\n\n .menu-item.link[target='_blank']::after {\n content: none;\n }\n\n .menu-item.link:hover::after,\n .menu-item.link:focus-visible::after {\n transform: translateX(2px);\n }\n\n @media (prefers-reduced-motion: reduce) {\n .menu-item.link::after {\n transition: none;\n }\n\n .menu-item.link:hover::after,\n .menu-item.link:focus-visible::after {\n transform: none;\n }\n }\n\n .menu-item.link.active {\n border-left: 0;\n background: transparent;\n font-weight: 600;\n }\n\n .menu-item.link .menu-item-header {\n justify-content: flex-start;\n }\n\n .menu-item.link .menu-item-title {\n white-space: normal;\n font-weight: 400;\n }\n\n .menu-item.link .menu-item-description {\n margin-top: 2px;\n font-size: 0.8125rem;\n }\n\n /* bar: a top-level item in a header bar next to mega st-dropdowns (e.g. \"Dashboard\" beside\n \"Masters ▼\") — the same pill, size and active look as their triggers, so the row reads as\n one set. Wins over compact (declared after it). */\n .menu-item.bar {\n align-items: center;\n min-height: 40px;\n padding: 12px;\n gap: 8px;\n border-radius: 9999px;\n white-space: nowrap;\n }\n\n /* Hover fills like a mega trigger opening on hover. */\n .menu-item.bar:hover,\n .menu-item.bar:focus-visible {\n padding-left: 12px;\n background: var(--st-color-accent);\n color: var(--st-color-on-solid);\n }\n\n .menu-item.bar.active {\n border-left: 0;\n }\n\n .menu-item.bar .menu-item-icon {\n margin-top: 0;\n }\n\n .menu-item.bar .menu-item-title {\n font-size: 0.875rem;\n font-weight: 400;\n }\n\n .external {\n display: inline-flex;\n margin-left: 3px;\n vertical-align: 0.05em;\n }\n\n .menu-item.no-description {\n align-items: center;\n }\n\n .menu-item.no-description .menu-item-icon {\n margin-top: 0;\n }\n\n @media (prefers-reduced-motion: reduce) {\n .menu-item,\n .menu-item-icon {\n transition: none;\n }\n\n .menu-item:active,\n .menu-item-icon:hover {\n transform: none;\n }\n\n .menu-item-badge,\n .menu-item-description {\n animation: none;\n }\n }\n `;\n\n @property({ type: String })\n title = '';\n\n @property({ type: String })\n href = '';\n\n @property({ type: String })\n description = '';\n\n /** Small trailing label, e.g. a count or \"New\"/\"Beta\" — omit for none. */\n @property({ type: String })\n badge = '';\n\n /** Highlights this row as the current page (source: `isActive`). */\n @property({ type: Boolean, reflect: true })\n active = false;\n\n /** Page path the header is showing; set by `st-header` (from its `current-path`), so this row can compare its `href` with it. */\n @property({ attribute: false })\n currentPath = '';\n\n @property({ type: Boolean, reflect: true })\n compact = false;\n\n /** Suppresses the description even when `description` is set (source: `showDescription`, default `true`). */\n @property({ type: Boolean, attribute: 'show-description' })\n showDescription = true;\n\n /** `target` for the `<a>` (source default `_self`). */\n @property({ type: String })\n target = '_self';\n\n /** `default` (a row with a hover box), `link` (a plain text link, as in `st-mega-menu-column`;\n * marked with an arrow when it opens a new tab) or `bar` (a top-level item in a header bar,\n * shaped like a mega `st-dropdown`'s trigger pill so it lines up with the dropdowns beside it). */\n @property({ type: String, reflect: true })\n variant: 'default' | 'link' | 'bar' = 'default';\n\n /** Size of the slotted icon, any CSS length (e.g. `36px`); empty keeps 16px (14px when `compact`). */\n @property({ type: String, attribute: 'icon-size' })\n iconSize = '';\n\n /** Whether `slot=\"icon\"` has content, so an omitted icon leaves no empty box. */\n @state() private hasIcon = false;\n\n private onIconSlotChange = (event: Event): void => {\n this.hasIcon = (event.target as HTMLSlotElement).assignedNodes({ flatten: true }).length > 0;\n };\n\n private onClick = (event: MouseEvent): void => {\n const selectEvent = new CustomEvent<MenuItemSelectEventDetail>('menu-item-select', {\n detail: { href: this.href },\n bubbles: true,\n composed: true,\n cancelable: true\n });\n this.dispatchEvent(selectEvent);\n if (selectEvent.defaultPrevented) event.preventDefault();\n };\n\n render() {\n const showDescription = !!this.description && this.showDescription;\n const link = this.variant === 'link';\n const current = isCurrentPath(this.href, this.currentPath);\n const classes = [\n 'menu-item',\n link ? 'link' : '',\n this.variant === 'bar' ? 'bar' : '',\n this.active || current ? 'active' : '',\n this.compact ? 'compact' : '',\n showDescription ? '' : 'no-description'\n ]\n .filter(Boolean)\n .join(' ');\n const external = link && this.target === '_blank';\n return html`\n <a\n part=\"item\"\n class=${classes}\n href=${this.href}\n target=${this.target}\n rel=${this.target === '_blank' ? 'noopener noreferrer' : nothing}\n aria-current=${current ? 'page' : nothing}\n @click=${this.onClick}\n >\n <span\n class=\"menu-item-icon\"\n part=\"icon\"\n ?hidden=${!this.hasIcon}\n style=${this.iconSize ? `--st-menu-item-icon-size: ${this.iconSize}` : nothing}\n ><slot name=\"icon\" @slotchange=${this.onIconSlotChange}></slot\n ></span>\n <span class=\"menu-item-content\" part=\"content\">\n <span class=\"menu-item-header\" part=\"header\">\n <span part=\"title\" class=\"menu-item-title\"\n >${this.title}${external ? html`<span class=\"external\">${arrowUpRightIcon(11)}</span>` : nothing}</span\n >\n ${this.badge ? html`<span part=\"badge\" class=\"menu-item-badge\">${this.badge}</span>` : nothing}\n </span>\n ${showDescription ? html`<p part=\"description\" class=\"menu-item-description\">${this.description}</p>` : nothing}\n </span>\n </a>\n `;\n }\n}\n"],"mappings":"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","names":[]}
|
|
@@ -11,6 +11,18 @@ var buttonResetStyles = css`
|
|
|
11
11
|
font: inherit;
|
|
12
12
|
cursor: pointer;
|
|
13
13
|
`;
|
|
14
|
+
var ctaPillStyles = css`
|
|
15
|
+
display: inline-flex;
|
|
16
|
+
align-items: center;
|
|
17
|
+
justify-content: center;
|
|
18
|
+
gap: var(--st-space-8);
|
|
19
|
+
box-sizing: border-box;
|
|
20
|
+
min-height: var(--st-cta-pill-min-height, 52px);
|
|
21
|
+
padding: 0 var(--st-space-28);
|
|
22
|
+
border-radius: 9999px;
|
|
23
|
+
font-weight: var(--st-font-weight-semibold);
|
|
24
|
+
text-decoration: none;
|
|
25
|
+
`;
|
|
14
26
|
var ctaButtonStyles = css`
|
|
15
27
|
border: 0;
|
|
16
28
|
border-radius: var(--st-button-radius);
|
|
@@ -115,6 +127,7 @@ var BREAKPOINT_MOBILE = 500;
|
|
|
115
127
|
export {
|
|
116
128
|
truncateStyles,
|
|
117
129
|
buttonResetStyles,
|
|
130
|
+
ctaPillStyles,
|
|
118
131
|
ctaButtonStyles,
|
|
119
132
|
ctaButtonDisabledStyles,
|
|
120
133
|
ctaButtonFillStyles,
|
|
@@ -135,4 +148,4 @@ export {
|
|
|
135
148
|
BREAKPOINT_TABLET,
|
|
136
149
|
BREAKPOINT_MOBILE
|
|
137
150
|
};
|
|
138
|
-
//# sourceMappingURL=chunk-
|
|
151
|
+
//# sourceMappingURL=chunk-NXUS2CH7.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/shared/styles.ts"],"sourcesContent":["import { css } from 'lit';\n\n/**\n * Reusable `css` fragments shared across component `static styles` blocks.\n *\n * Lit's `css` tag allows interpolating another `CSSResult` anywhere inside a\n * template, including mid-rule — `${fragment}` below expands to raw CSS\n * text, so these compose into a component's own selectors without forcing a\n * shared class name or touching `render()`. Each component keeps its own\n * selectors; only the duplicated property lists move here. Layout details\n * that genuinely vary per component (padding, gap, font-size, ...) stay\n * local, declared after a fragment so the cascade lets them override it.\n *\n * Add a fragment here only once a pattern is byte-identical (or near enough\n * that the deltas are better expressed as local overrides) across 3+\n * components — see `packages/suite-components/README.md#shared-style-fragments`.\n */\n\n/** Truncates overflowing text to a single line with an ellipsis. */\nexport const truncateStyles = css`\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n`;\n\n/**\n * Base for an unstyled, click-through interactive element (icon buttons,\n * menu triggers, link-like buttons) before component-specific padding,\n * font-size, and color are layered on.\n */\nexport const buttonResetStyles = css`\n border: 0;\n background: transparent;\n font: inherit;\n cursor: pointer;\n`;\n\n/**\n * The pill CTA shape (`buttonStyle=\"pill\"`): fully rounded, centred label, `min-height` 52px for a\n * main CTA (hero, banner). A component can set `--st-cta-pill-min-height: 44px` for smaller CTAs.\n * Fill, colour, border and padding stay local (they differ between primary and secondary).\n */\nexport const ctaPillStyles = css`\n display: inline-flex;\n align-items: center;\n justify-content: center;\n gap: var(--st-space-8);\n box-sizing: border-box;\n min-height: var(--st-cta-pill-min-height, 52px);\n padding: 0 var(--st-space-28);\n border-radius: 9999px;\n font-weight: var(--st-font-weight-semibold);\n text-decoration: none;\n`;\n\n/**\n * The dark-filled primary-action button look (wizard Next/Generate/Run/Save,\n * active toggle buttons, ...). Pair with `ctaButtonDisabledStyles` on the\n * same selector's `:disabled` state.\n */\nexport const ctaButtonStyles = css`\n border: 0;\n border-radius: var(--st-button-radius);\n background: var(--st-button-primary-bg);\n color: var(--st-button-primary-color);\n font-weight: var(--st-button-font-weight);\n cursor: pointer;\n`;\n\nexport const ctaButtonDisabledStyles = css`\n background: var(--st-color-subtle);\n cursor: not-allowed;\n`;\n\n/**\n * Just the fill (background + color) from `ctaButtonStyles`, for selectors\n * that only need to swap an already-bordered/sized button into the CTA look\n * on an active/pressed/selected state (`[aria-pressed='true']`, `.active`,\n * ...) rather than defining the button from scratch.\n */\nexport const ctaButtonFillStyles = css`\n background: var(--st-button-primary-bg);\n color: var(--st-button-primary-color);\n`;\n\n/** Floating menu/dropdown panel chrome (user menu, language menu, ...). */\nexport const dropdownPanelStyles = css`\n position: absolute;\n top: 38px;\n right: 0;\n background: var(--st-color-surface);\n border: 1px solid var(--st-color-border);\n border-radius: var(--st-radius-sm);\n box-shadow: 0 4px 16px var(--st-shadow-color-sm);\n z-index: 30;\n overflow: hidden;\n`;\n\n/** \"No results\" / \"Nothing here.\" empty-state text. Padding stays local. */\nexport const emptyStateStyles = css`\n text-align: center;\n color: var(--st-color-text-muted);\n font-size: var(--st-text-base);\n`;\n\n/** Bordered, rounded shell wrapping a data table (browse/list views). */\nexport const tableShellStyles = css`\n background: var(--st-color-surface);\n border: 1px solid var(--st-color-border);\n border-radius: var(--st-radius-md);\n overflow: hidden;\n`;\n\n/** A single bordered result row with a name (truncated) + trailing link. */\nexport const resultRowStyles = css`\n display: flex;\n align-items: center;\n gap: var(--st-space-12);\n padding: var(--st-space-12) var(--st-space-14);\n border: 1px solid var(--st-color-border);\n border-radius: var(--st-radius-sm);\n`;\n\nexport const resultNameStyles = css`\n flex: 1;\n min-width: 120px;\n font-size: var(--st-text-base);\n font-weight: var(--st-font-weight-medium);\n ${truncateStyles}\n`;\n\nexport const resultLinkStyles = css`\n font-size: var(--st-text-sm);\n font-weight: var(--st-font-weight-semibold);\n color: var(--st-color-accent-text);\n`;\n\n/**\n * Uppercase, letter-spaced section/field \"eyebrow\" label (card headings,\n * table headers, field labels, ...). Font-size stays local since it varies\n * (11–12px) by context.\n */\nexport const eyebrowLabelStyles = css`\n font-weight: var(--st-font-weight-bold);\n color: var(--st-color-text-muted);\n text-transform: uppercase;\n letter-spacing: var(--st-tracking-wide);\n`;\n\n/** Top border separating stacked rows in a list/table (folder rows, data rows, table rows, ...). */\nexport const rowDividerStyles = css`\n border-top: 1px solid var(--st-color-divider);\n`;\n\n/**\n * Bordered, rounded surface shell for a card/tile/panel (as opposed to\n * `tableShellStyles`, which additionally clips overflow for tabular content).\n * Padding, gap, and cursor stay local since they vary by component.\n */\nexport const cardShellStyles = css`\n background: var(--st-color-surface);\n border: 1px solid var(--st-color-border);\n border-radius: var(--st-radius-md);\n`;\n\n/** A card/tile/row's bold primary name line (folder tiles/rows, template cards, ...). */\nexport const itemNameStyles = css`\n font-size: var(--st-text-base);\n font-weight: var(--st-font-weight-semibold);\n color: var(--st-color-text-strong);\n`;\n\n/** A card/tile/row's muted secondary caption line, paired with `itemNameStyles`. */\nexport const itemCaptionStyles = css`\n font-size: var(--st-text-xs);\n color: var(--st-color-text-muted);\n`;\n\n/**\n * Whole rules (not a property list) every component's stylesheet starts\n * with: routes keyboard focus rings and native checkbox/radio tint through\n * `--st-focus-ring` / `--st-checkbox-color`, whose defaults (`auto`) keep\n * the browser's own look until a host app themes them.\n */\nexport const controlBaseStyles = css`\n :is(button, a, input, select, textarea, [tabindex]):focus-visible {\n outline: var(--st-focus-ring);\n outline-offset: var(--st-focus-ring-offset);\n }\n\n input[type='checkbox'],\n input[type='radio'] {\n accent-color: var(--st-checkbox-color);\n }\n`;\n\n/** Default font stack, used by nearly every component. */\nexport const fontFamilyStyles = css`\n font-family: var(--st-font-family);\n`;\n\n/**\n * Font stack for page-root/chrome components (`st-template-hub`, the admin\n * and configuration pages, `st-app-header`, ...). Identical to\n * `fontFamilyStyles` now that `--st-font-family` always resolves via\n * `theme.css` (no per-usage fallback) — kept as a separate export so those\n * call sites stay semantically distinct if the two ever need to diverge\n * again.\n */\nexport const rootFontFamilyStyles = css`\n font-family: var(--st-font-family);\n`;\n\n/** Canonical responsive breakpoints (px). Interpolate as `${BREAKPOINT_TABLET}px`. */\nexport const BREAKPOINT_TABLET = 900;\nexport const BREAKPOINT_MOBILE = 500;\n"],"mappings":";AAAA,SAAS,WAAW;AAmBb,IAAM,iBAAiB;AAAA;AAAA;AAAA;AAAA;AAWvB,IAAM,oBAAoB;AAAA;AAAA;AAAA;AAAA;AAAA;AAY1B,IAAM,gBAAgB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAkBtB,IAAM,kBAAkB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AASxB,IAAM,0BAA0B;AAAA;AAAA;AAAA;AAWhC,IAAM,sBAAsB;AAAA;AAAA;AAAA;AAM5B,IAAM,sBAAsB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAa5B,IAAM,mBAAmB;AAAA;AAAA;AAAA;AAAA;AAOzB,IAAM,mBAAmB;AAAA;AAAA;AAAA;AAAA;AAAA;AAQzB,IAAM,kBAAkB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AASxB,IAAM,mBAAmB;AAAA;AAAA;AAAA;AAAA;AAAA,IAK5B,cAAc;AAAA;AAGX,IAAM,mBAAmB;AAAA;AAAA;AAAA;AAAA;AAWzB,IAAM,qBAAqB;AAAA;AAAA;AAAA;AAAA;AAAA;AAQ3B,IAAM,mBAAmB;AAAA;AAAA;AASzB,IAAM,kBAAkB;AAAA;AAAA;AAAA;AAAA;AAOxB,IAAM,iBAAiB;AAAA;AAAA;AAAA;AAAA;AAOvB,IAAM,oBAAoB;AAAA;AAAA;AAAA;AAW1B,IAAM,oBAAoB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAa1B,IAAM,mBAAmB;AAAA;AAAA;AAYzB,IAAM,uBAAuB;AAAA;AAAA;AAK7B,IAAM,oBAAoB;AAC1B,IAAM,oBAAoB;","names":[]}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import {
|
|
2
2
|
controlBaseStyles,
|
|
3
3
|
rootFontFamilyStyles
|
|
4
|
-
} from "./chunk-
|
|
4
|
+
} from "./chunk-NXUS2CH7.js";
|
|
5
5
|
import {
|
|
6
6
|
__decorateClass
|
|
7
7
|
} from "./chunk-EUXUH3YW.js";
|
|
@@ -16,10 +16,12 @@ var Footer = class extends LitElement {
|
|
|
16
16
|
this.inverted = false;
|
|
17
17
|
this.companyName = "";
|
|
18
18
|
this.copyright = "";
|
|
19
|
+
this.legalNote = "";
|
|
19
20
|
this.poweredBy = "";
|
|
20
21
|
this.poweredByLink = "";
|
|
21
22
|
this.version = "";
|
|
22
23
|
this.imageSrc = "";
|
|
24
|
+
this.imageAlt = "";
|
|
23
25
|
this.description = "";
|
|
24
26
|
this.columns = [];
|
|
25
27
|
this.socialLinks = [];
|
|
@@ -27,6 +29,10 @@ var Footer = class extends LitElement {
|
|
|
27
29
|
get isSite() {
|
|
28
30
|
return !!(this.columns.length || this.socialLinks.length || this.description || this.imageSrc);
|
|
29
31
|
}
|
|
32
|
+
/** The columns to show, each with only its visible links; a column left with no links is dropped. */
|
|
33
|
+
get visibleColumns() {
|
|
34
|
+
return this.columns.filter((column) => column.visible !== false).map((column) => ({ ...column, links: column.links.filter((link) => link.visible !== false) })).filter((column) => column.links.length > 0);
|
|
35
|
+
}
|
|
30
36
|
get resolvedCopyright() {
|
|
31
37
|
if (this.copyright) return this.copyright;
|
|
32
38
|
if (this.companyName) return `\xA9 ${(/* @__PURE__ */ new Date()).getFullYear()} ${this.companyName}`;
|
|
@@ -61,19 +67,19 @@ var Footer = class extends LitElement {
|
|
|
61
67
|
<div class="grid">
|
|
62
68
|
<div class="brand" part="brand">
|
|
63
69
|
${this.imageSrc || this.companyName ? html`<div class="logo">
|
|
64
|
-
${this.imageSrc ? html`<img class="logo-img" src=${this.imageSrc} alt=${this.
|
|
70
|
+
${this.imageSrc ? html`<img class="logo-img" part="logo" src=${this.imageSrc} alt=${this.imageAlt || (this.companyName ? `${this.companyName} home` : "Home")} />` : nothing}
|
|
65
71
|
${this.companyName ? html`<span>${this.companyName}</span>` : nothing}
|
|
66
72
|
</div>` : nothing}
|
|
67
73
|
${this.description ? html`<p class="description">${this.description}</p>` : nothing}
|
|
68
74
|
${this.socialLinks.length ? html`<div class="social">
|
|
69
75
|
${this.socialLinks.map(
|
|
70
|
-
(social) => html`<a part="social" class="social-link" href=${social.href} target="_blank" rel="noopener noreferrer" aria-label=${social.icon}>
|
|
76
|
+
(social) => html`<a part="social" class="social-link" href=${social.href} target="_blank" rel="noopener noreferrer" aria-label=${social.label || social.icon}>
|
|
71
77
|
<iconify-icon icon=${social.icon} width="24" height="24"></iconify-icon>
|
|
72
78
|
</a>`
|
|
73
79
|
)}
|
|
74
80
|
</div>` : nothing}
|
|
75
81
|
</div>
|
|
76
|
-
${this.
|
|
82
|
+
${this.visibleColumns.map(
|
|
77
83
|
(column) => html`<div class="column" part="column">
|
|
78
84
|
<h4 class="column-title">${column.title}</h4>
|
|
79
85
|
<div class="links">${column.links.map((link) => this.renderLink(link))}</div>
|
|
@@ -82,17 +88,23 @@ var Footer = class extends LitElement {
|
|
|
82
88
|
</div>
|
|
83
89
|
<div class="bottom" part="bottom">
|
|
84
90
|
<div class="bottom-text">
|
|
85
|
-
|
|
91
|
+
${this.renderCopyright()}
|
|
86
92
|
${this.version ? html`<span part="version">v${this.version}</span>` : nothing} ${this.renderPoweredBy()}
|
|
87
93
|
</div>
|
|
88
94
|
</div>
|
|
89
95
|
</div>
|
|
90
96
|
`;
|
|
91
97
|
}
|
|
98
|
+
renderCopyright() {
|
|
99
|
+
return html`<div class="copyright-line">
|
|
100
|
+
<span part="copyright">${this.resolvedCopyright}</span>
|
|
101
|
+
${this.legalNote ? html`<span part="legal">${this.legalNote}</span>` : nothing}
|
|
102
|
+
</div>`;
|
|
103
|
+
}
|
|
92
104
|
render() {
|
|
93
105
|
if (this.isSite) return this.renderSite();
|
|
94
106
|
return html`
|
|
95
|
-
|
|
107
|
+
${this.renderCopyright()}
|
|
96
108
|
${this.version ? html`<span part="version">v${this.version}</span>` : nothing} ${this.renderPoweredBy()}
|
|
97
109
|
`;
|
|
98
110
|
}
|
|
@@ -111,7 +123,9 @@ Footer.styles = css`
|
|
|
111
123
|
* specificity — so a page that resets margin/padding/border on every element (e.g. Tailwind
|
|
112
124
|
* Preflight, which every app but Template Hub loads) silently zeroes this footer's padding
|
|
113
125
|
* and top border unless these two win the conflict outright via !important. */
|
|
114
|
-
padding
|
|
126
|
+
/* The bottom padding also clears a visible cookie banner (st-cookie-consent publishes its height
|
|
127
|
+
* as --st-cookie-banner-height on <html>; 0 when there is no banner). */
|
|
128
|
+
padding: var(--st-space-16) var(--st-space-28) calc(var(--st-space-16) + var(--st-cookie-banner-height, 0px)) !important;
|
|
115
129
|
border-top: 1px solid var(--st-color-border) !important;
|
|
116
130
|
color: var(--st-color-text-muted);
|
|
117
131
|
font-size: var(--st-text-xs);
|
|
@@ -137,7 +151,7 @@ Footer.styles = css`
|
|
|
137
151
|
/* Site layout */
|
|
138
152
|
:host([site]) {
|
|
139
153
|
display: block;
|
|
140
|
-
padding: 64px var(--st-space-28) 32px !important;
|
|
154
|
+
padding: 64px var(--st-space-28) calc(32px + var(--st-cookie-banner-height, 0px)) !important;
|
|
141
155
|
font-size: var(--st-text-sm);
|
|
142
156
|
}
|
|
143
157
|
|
|
@@ -186,7 +200,9 @@ Footer.styles = css`
|
|
|
186
200
|
}
|
|
187
201
|
|
|
188
202
|
.social-link,
|
|
189
|
-
.link
|
|
203
|
+
.link,
|
|
204
|
+
.powered-by {
|
|
205
|
+
position: relative;
|
|
190
206
|
color: inherit;
|
|
191
207
|
text-decoration: none;
|
|
192
208
|
transition: color 0.2s ease;
|
|
@@ -197,6 +213,19 @@ Footer.styles = css`
|
|
|
197
213
|
color: var(--st-color-text-strong);
|
|
198
214
|
}
|
|
199
215
|
|
|
216
|
+
/* Touch target: the visible icon or text keeps its size; a 44px hit area (WCAG 2.5.5) sits over it. */
|
|
217
|
+
.social-link::after,
|
|
218
|
+
.link::after,
|
|
219
|
+
.powered-by::after {
|
|
220
|
+
content: '';
|
|
221
|
+
position: absolute;
|
|
222
|
+
top: 50%;
|
|
223
|
+
left: 50%;
|
|
224
|
+
width: max(100%, 44px);
|
|
225
|
+
height: 44px;
|
|
226
|
+
transform: translate(-50%, -50%);
|
|
227
|
+
}
|
|
228
|
+
|
|
200
229
|
.column-title {
|
|
201
230
|
margin: 0 0 24px;
|
|
202
231
|
font-size: var(--st-text-xs);
|
|
@@ -209,6 +238,7 @@ Footer.styles = css`
|
|
|
209
238
|
.links {
|
|
210
239
|
display: flex;
|
|
211
240
|
flex-direction: column;
|
|
241
|
+
align-items: flex-start;
|
|
212
242
|
gap: 16px;
|
|
213
243
|
}
|
|
214
244
|
|
|
@@ -224,10 +254,19 @@ Footer.styles = css`
|
|
|
224
254
|
gap: 4px;
|
|
225
255
|
}
|
|
226
256
|
|
|
257
|
+
.copyright-line {
|
|
258
|
+
display: flex;
|
|
259
|
+
flex-wrap: wrap;
|
|
260
|
+
column-gap: 16px;
|
|
261
|
+
row-gap: 4px;
|
|
262
|
+
}
|
|
263
|
+
|
|
264
|
+
/* No opacity here: it blended the text into the background and fell below WCAG AA (about 3.6:1
|
|
265
|
+
on a light footer). The link takes the footer's colour, text-muted (5.1:1 on white) or
|
|
266
|
+
on-solid on an inverted footer. */
|
|
227
267
|
.bottom-text .powered-by {
|
|
228
268
|
font-size: 0.85em;
|
|
229
269
|
font-weight: inherit;
|
|
230
|
-
opacity: 0.8;
|
|
231
270
|
}
|
|
232
271
|
|
|
233
272
|
@media (max-width: 1024px) {
|
|
@@ -268,6 +307,9 @@ __decorateClass([
|
|
|
268
307
|
__decorateClass([
|
|
269
308
|
property({ type: String })
|
|
270
309
|
], Footer.prototype, "copyright", 2);
|
|
310
|
+
__decorateClass([
|
|
311
|
+
property({ type: String, attribute: "legal-note" })
|
|
312
|
+
], Footer.prototype, "legalNote", 2);
|
|
271
313
|
__decorateClass([
|
|
272
314
|
property({ type: String, attribute: "powered-by" })
|
|
273
315
|
], Footer.prototype, "poweredBy", 2);
|
|
@@ -280,6 +322,9 @@ __decorateClass([
|
|
|
280
322
|
__decorateClass([
|
|
281
323
|
property({ type: String, attribute: "image-src" })
|
|
282
324
|
], Footer.prototype, "imageSrc", 2);
|
|
325
|
+
__decorateClass([
|
|
326
|
+
property({ type: String, attribute: "image-alt" })
|
|
327
|
+
], Footer.prototype, "imageAlt", 2);
|
|
283
328
|
__decorateClass([
|
|
284
329
|
property({ type: String })
|
|
285
330
|
], Footer.prototype, "description", 2);
|
|
@@ -296,4 +341,4 @@ Footer = __decorateClass([
|
|
|
296
341
|
export {
|
|
297
342
|
Footer
|
|
298
343
|
};
|
|
299
|
-
//# sourceMappingURL=chunk-
|
|
344
|
+
//# sourceMappingURL=chunk-OCPGOLVF.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/footer/Footer.ts"],"sourcesContent":["import { LitElement, PropertyValues, css, html, nothing } from 'lit';\nimport { customElement, property } from 'lit/decorators.js';\nimport 'iconify-icon';\n\nimport { controlBaseStyles, rootFontFamilyStyles } from '../shared/styles';\n\nexport interface FooterLink {\n label: string;\n href: string;\n /** `false` leaves the link out of the footer. Omit, or `true`, to show it. */\n visible?: boolean;\n}\n\nexport interface FooterColumn {\n title: string;\n links: FooterLink[];\n /** `false` leaves the whole column out. A column whose links are all hidden is left out too. */\n visible?: boolean;\n}\n\nexport interface FooterSocialLink {\n /** Iconify icon name, e.g. `mdi:github`. */\n icon: string;\n href: string;\n /** Accessible name of the icon link (e.g. \"Sankhyatronics on LinkedIn\"). Falls back to `icon`. */\n label?: string;\n}\n\n/** Fired when an internal footer link is activated — cancelable, so an SPA can `preventDefault()` and route instead. */\nexport interface FooterLinkEventDetail {\n href: string;\n}\n\n/**\n * The footer, in two layouts:\n *\n * - **Bar** (default): a copyright line plus an optional \"powered by\" link — what the suite's\n * authenticated apps use.\n * - **Site**: when `columns`, `socialLinks`, `description` or `imageSrc` is set, the footer becomes a\n * marketing-site footer — brand (logo/company name, description, social icons), link columns and a\n * bottom bar with the copyright and \"powered by\".\n *\n * Fires a cancelable `footer-link` event (detail `{ href }`) when an internal link is clicked.\n */\n@customElement('st-footer')\nexport class Footer extends LitElement {\n static styles = css`\n ${controlBaseStyles}\n\n :host {\n display: flex;\n align-items: center;\n justify-content: space-between;\n gap: var(--st-space-16);\n flex-wrap: wrap;\n /* !important on padding/border-top only: a shadow host's own :host rule always loses to ANY\n * rule the consuming page has for the same property on that element, regardless of\n * specificity — so a page that resets margin/padding/border on every element (e.g. Tailwind\n * Preflight, which every app but Template Hub loads) silently zeroes this footer's padding\n * and top border unless these two win the conflict outright via !important. */\n /* The bottom padding also clears a visible cookie banner (st-cookie-consent publishes its height\n * as --st-cookie-banner-height on <html>; 0 when there is no banner). */\n padding: var(--st-space-16) var(--st-space-28) calc(var(--st-space-16) + var(--st-cookie-banner-height, 0px)) !important;\n border-top: 1px solid var(--st-color-border) !important;\n color: var(--st-color-text-muted);\n font-size: var(--st-text-xs);\n ${rootFontFamilyStyles}\n }\n\n .powered-by {\n color: inherit;\n text-decoration: none;\n font-weight: var(--st-font-weight-semibold);\n }\n\n .powered-by:hover {\n color: var(--st-color-text-strong);\n }\n\n :host([inverted]) {\n background: var(--st-color-text-strong);\n color: var(--st-color-on-solid);\n border-top-color: transparent !important;\n }\n\n /* Site layout */\n :host([site]) {\n display: block;\n padding: 64px var(--st-space-28) calc(32px + var(--st-cookie-banner-height, 0px)) !important;\n font-size: var(--st-text-sm);\n }\n\n .site {\n max-width: 1200px;\n margin: 0 auto;\n }\n\n .grid {\n display: grid;\n grid-template-columns: 2fr repeat(3, 1fr);\n gap: 64px;\n margin-bottom: 64px;\n }\n\n .brand {\n display: flex;\n flex-direction: column;\n gap: 16px;\n }\n\n .logo {\n display: flex;\n align-items: center;\n gap: 8px;\n font-size: 1.25rem;\n font-weight: 700;\n color: var(--st-color-text-strong);\n }\n\n .logo-img {\n height: 32px;\n width: auto;\n }\n\n .description {\n margin: 0;\n max-width: 300px;\n line-height: 1.6;\n }\n\n .social {\n display: flex;\n gap: 16px;\n margin-top: 16px;\n }\n\n .social-link,\n .link,\n .powered-by {\n position: relative;\n color: inherit;\n text-decoration: none;\n transition: color 0.2s ease;\n }\n\n .social-link:hover,\n .link:hover {\n color: var(--st-color-text-strong);\n }\n\n /* Touch target: the visible icon or text keeps its size; a 44px hit area (WCAG 2.5.5) sits over it. */\n .social-link::after,\n .link::after,\n .powered-by::after {\n content: '';\n position: absolute;\n top: 50%;\n left: 50%;\n width: max(100%, 44px);\n height: 44px;\n transform: translate(-50%, -50%);\n }\n\n .column-title {\n margin: 0 0 24px;\n font-size: var(--st-text-xs);\n font-weight: var(--st-font-weight-semibold);\n color: var(--st-color-text-strong);\n text-transform: uppercase;\n letter-spacing: 0.05em;\n }\n\n .links {\n display: flex;\n flex-direction: column;\n align-items: flex-start;\n gap: 16px;\n }\n\n .bottom {\n padding-top: 32px;\n border-top: 1px solid var(--st-color-border);\n font-size: var(--st-text-xs);\n }\n\n .bottom-text {\n display: flex;\n flex-direction: column;\n gap: 4px;\n }\n\n .copyright-line {\n display: flex;\n flex-wrap: wrap;\n column-gap: 16px;\n row-gap: 4px;\n }\n\n /* No opacity here: it blended the text into the background and fell below WCAG AA (about 3.6:1\n on a light footer). The link takes the footer's colour, text-muted (5.1:1 on white) or\n on-solid on an inverted footer. */\n .bottom-text .powered-by {\n font-size: 0.85em;\n font-weight: inherit;\n }\n\n @media (max-width: 1024px) {\n .grid {\n grid-template-columns: repeat(3, 1fr);\n gap: 48px;\n }\n }\n\n @media (max-width: 768px) {\n .grid {\n grid-template-columns: 1fr;\n gap: 40px;\n }\n\n .bottom {\n text-align: center;\n }\n }\n\n :host([site][inverted]) .logo,\n :host([site][inverted]) .column-title,\n :host([site][inverted]) .social-link:hover,\n :host([site][inverted]) .link:hover {\n color: var(--st-color-on-solid);\n }\n\n :host([site][inverted]) .bottom {\n border-top-color: color-mix(in oklch, var(--st-color-on-solid) 20%, var(--st-color-text-strong));\n }\n `;\n\n /** Inverts the footer's color roles (light-on-dark instead of dark-on-light) — matches the\n * source component's `inverted` (from its shared `BaseProps`), same as `st-header`'s. */\n @property({ type: Boolean, reflect: true })\n inverted = false;\n\n /** Used to build the default `copyright` line (`© {year} {companyName}`) when `copyright` isn't set explicitly. */\n @property({ type: String, attribute: 'company-name' })\n companyName = '';\n\n /** Overrides the default computed copyright line entirely. */\n @property({ type: String })\n copyright = '';\n\n /** Legal line (e.g. a trademark notice) shown beside the copyright. Empty hides it. */\n @property({ type: String, attribute: 'legal-note' })\n legalNote = '';\n\n @property({ type: String, attribute: 'powered-by' })\n poweredBy = '';\n\n @property({ type: String, attribute: 'powered-by-link' })\n poweredByLink = '';\n\n /** App version, rendered as `v{version}` after the copyright line — for apps that show their own\n * version in the footer rather than the header title. */\n @property({ type: String })\n version = '';\n\n /** Logo shown in the brand block (site layout). */\n @property({ type: String, attribute: 'image-src' })\n imageSrc = '';\n\n /** Alt text of the logo. Default: the company name plus \"home\", or \"Home\" without one. */\n @property({ type: String, attribute: 'image-alt' })\n imageAlt = '';\n\n /** Short blurb under the logo (site layout). */\n @property({ type: String })\n description = '';\n\n /** Link columns (site layout). */\n @property({ attribute: false })\n columns: FooterColumn[] = [];\n\n /** Social icon links under the description (site layout). */\n @property({ attribute: false })\n socialLinks: FooterSocialLink[] = [];\n\n private get isSite(): boolean {\n return !!(this.columns.length || this.socialLinks.length || this.description || this.imageSrc);\n }\n\n /** The columns to show, each with only its visible links; a column left with no links is dropped. */\n private get visibleColumns(): FooterColumn[] {\n return this.columns\n .filter(column => column.visible !== false)\n .map(column => ({ ...column, links: column.links.filter(link => link.visible !== false) }))\n .filter(column => column.links.length > 0);\n }\n\n private get resolvedCopyright(): string {\n if (this.copyright) return this.copyright;\n if (this.companyName) return `© ${new Date().getFullYear()} ${this.companyName}`;\n return `© ${new Date().getFullYear()}`;\n }\n\n protected willUpdate(changed: PropertyValues): void {\n if (changed.size) this.toggleAttribute('site', this.isSite);\n }\n\n private onLinkClick(event: MouseEvent, href: string): void {\n const select = new CustomEvent<FooterLinkEventDetail>('footer-link', {\n detail: { href },\n bubbles: true,\n composed: true,\n cancelable: true\n });\n this.dispatchEvent(select);\n if (select.defaultPrevented) event.preventDefault();\n }\n\n private renderLink(link: FooterLink) {\n return /^https?:/i.test(link.href)\n ? html`<a part=\"link\" class=\"link\" href=${link.href} target=\"_blank\" rel=\"noopener noreferrer\">${link.label}</a>`\n : html`<a part=\"link\" class=\"link\" href=${link.href} @click=${(event: MouseEvent) => this.onLinkClick(event, link.href)}>${link.label}</a>`;\n }\n\n private renderPoweredBy() {\n return this.poweredBy\n ? html`\n <a part=\"powered-by\" class=\"powered-by\" href=${this.poweredByLink || '#'} target=\"_blank\" rel=\"noopener noreferrer\">\n ${this.poweredBy}\n </a>\n `\n : nothing;\n }\n\n private renderSite() {\n return html`\n <div class=\"site\" part=\"site\">\n <div class=\"grid\">\n <div class=\"brand\" part=\"brand\">\n ${this.imageSrc || this.companyName\n ? html`<div class=\"logo\">\n ${this.imageSrc ? html`<img class=\"logo-img\" part=\"logo\" src=${this.imageSrc} alt=${this.imageAlt || (this.companyName ? `${this.companyName} home` : 'Home')} />` : nothing}\n ${this.companyName ? html`<span>${this.companyName}</span>` : nothing}\n </div>`\n : nothing}\n ${this.description ? html`<p class=\"description\">${this.description}</p>` : nothing}\n ${this.socialLinks.length\n ? html`<div class=\"social\">\n ${this.socialLinks.map(\n social => html`<a part=\"social\" class=\"social-link\" href=${social.href} target=\"_blank\" rel=\"noopener noreferrer\" aria-label=${social.label || social.icon}>\n <iconify-icon icon=${social.icon} width=\"24\" height=\"24\"></iconify-icon>\n </a>`\n )}\n </div>`\n : nothing}\n </div>\n ${this.visibleColumns.map(\n column => html`<div class=\"column\" part=\"column\">\n <h4 class=\"column-title\">${column.title}</h4>\n <div class=\"links\">${column.links.map(link => this.renderLink(link))}</div>\n </div>`\n )}\n </div>\n <div class=\"bottom\" part=\"bottom\">\n <div class=\"bottom-text\">\n ${this.renderCopyright()}\n ${this.version ? html`<span part=\"version\">v${this.version}</span>` : nothing} ${this.renderPoweredBy()}\n </div>\n </div>\n </div>\n `;\n }\n\n private renderCopyright() {\n return html`<div class=\"copyright-line\">\n <span part=\"copyright\">${this.resolvedCopyright}</span>\n ${this.legalNote ? html`<span part=\"legal\">${this.legalNote}</span>` : nothing}\n </div>`;\n }\n\n render() {\n if (this.isSite) return this.renderSite();\n return html`\n ${this.renderCopyright()}\n ${this.version ? html`<span part=\"version\">v${this.version}</span>` : nothing} ${this.renderPoweredBy()}\n `;\n }\n}\n"],"mappings":"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","names":[]}
|