@sankhyatronics/sankhya-cms 0.1.5 → 0.1.6

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.
@@ -5,8 +5,9 @@ import { LitElement } from 'lit';
5
5
  * Cycles through its slotted children, one visible at a time, with optional autoplay, arrows and
6
6
  * dot indicators. The incoming slide slides in from the travel direction (CSS keyframes in place
7
7
  * of the source's framer-motion spring), or fades in with `transition="fade"`. Autoplay pauses
8
- * while hovered or focused and stops when the element is disconnected; a paused slide keeps the
9
- * time it had left.
8
+ * while hovered (unless `pause-on-hover` is turned off, e.g. for a full-screen hero the pointer
9
+ * nearly always rests on) or focused, and stops when the element is disconnected; a paused slide
10
+ * keeps the time it had left.
10
11
  *
11
12
  * `indicator-style="tabs"` replaces the dots with a row of labelled tabs along the bottom, each
12
13
  * with a progress bar that fills while its slide is showing, plus a pause button — the tabbed hero
@@ -25,6 +26,9 @@ declare class Carousel extends LitElement {
25
26
  autoPlay: boolean;
26
27
  /** Autoplay delay in milliseconds. */
27
28
  interval: number;
29
+ /** Pause autoplay while the pointer is over the carousel. Turn off for a hero that fills the
30
+ * screen; the tabs' pause button and keyboard focus still pause it. */
31
+ pauseOnHover: boolean;
28
32
  showArrows: boolean;
29
33
  showIndicators: boolean;
30
34
  /** `dots` (default) or `tabs`: labelled tabs with progress bars along the bottom. */
@@ -52,6 +56,7 @@ declare class Carousel extends LitElement {
52
56
  /** Applies a pause-state change, freezing or resuming the timer (and the tab progress bar). */
53
57
  private hold;
54
58
  private pause;
59
+ private pauseOnEnter;
55
60
  private resume;
56
61
  private togglePlay;
57
62
  private get slides();
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  Carousel
3
- } from "../chunk-47RPYNFG.js";
3
+ } from "../chunk-HPIQSECE.js";
4
4
  import "../chunk-3VE6VFJ4.js";
5
5
  import "../chunk-RHAOQ6K4.js";
6
6
  import "../chunk-EUXUH3YW.js";
@@ -17,6 +17,7 @@ var Carousel = class extends LitElement {
17
17
  super(...arguments);
18
18
  this.autoPlay = true;
19
19
  this.interval = 5e3;
20
+ this.pauseOnHover = true;
20
21
  this.showArrows = true;
21
22
  this.showIndicators = true;
22
23
  this.indicatorStyle = "dots";
@@ -32,19 +33,22 @@ var Carousel = class extends LitElement {
32
33
  this.remaining = 0;
33
34
  this.startedAt = 0;
34
35
  this.pause = () => this.hold(() => this.paused = true);
36
+ this.pauseOnEnter = () => {
37
+ if (this.pauseOnHover) this.pause();
38
+ };
35
39
  this.resume = () => this.hold(() => this.paused = false);
36
40
  this.togglePlay = () => this.hold(() => this.userPaused = !this.userPaused);
37
41
  }
38
42
  connectedCallback() {
39
43
  super.connectedCallback();
40
- this.addEventListener("mouseenter", this.pause);
44
+ this.addEventListener("mouseenter", this.pauseOnEnter);
41
45
  this.addEventListener("mouseleave", this.resume);
42
46
  this.addEventListener("focusin", this.pause);
43
47
  this.addEventListener("focusout", this.resume);
44
48
  }
45
49
  disconnectedCallback() {
46
50
  this.stopTimer();
47
- this.removeEventListener("mouseenter", this.pause);
51
+ this.removeEventListener("mouseenter", this.pauseOnEnter);
48
52
  this.removeEventListener("mouseleave", this.resume);
49
53
  this.removeEventListener("focusin", this.pause);
50
54
  this.removeEventListener("focusout", this.resume);
@@ -490,6 +494,9 @@ __decorateClass([
490
494
  __decorateClass([
491
495
  property({ type: Number })
492
496
  ], Carousel.prototype, "interval", 2);
497
+ __decorateClass([
498
+ property({ type: Boolean, attribute: "pause-on-hover" })
499
+ ], Carousel.prototype, "pauseOnHover", 2);
493
500
  __decorateClass([
494
501
  property({ type: Boolean, attribute: "show-arrows" })
495
502
  ], Carousel.prototype, "showArrows", 2);
@@ -524,4 +531,4 @@ Carousel = __decorateClass([
524
531
  export {
525
532
  Carousel
526
533
  };
527
- //# sourceMappingURL=chunk-47RPYNFG.js.map
534
+ //# sourceMappingURL=chunk-HPIQSECE.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/carousel/Carousel.ts"],"sourcesContent":["import { LitElement, css, html, nothing } from 'lit';\nimport { customElement, property, state } from 'lit/decorators.js';\n\nimport { buttonResetStyles, controlBaseStyles } from '../shared/styles';\nimport { reducedMotionStyles } from '../shared/section-styles';\nimport type { CarouselChangeEventDetail } from './CarouselEvents';\n\n/**\n * Cycles through its slotted children, one visible at a time, with optional autoplay, arrows and\n * dot indicators. The incoming slide slides in from the travel direction (CSS keyframes in place\n * of the source's framer-motion spring), or fades in with `transition=\"fade\"`. Autoplay pauses\n * while hovered (unless `pause-on-hover` is turned off, e.g. for a full-screen hero the pointer\n * nearly always rests on) or focused, and stops when the element is disconnected; a paused slide\n * keeps the time it had left.\n *\n * `indicator-style=\"tabs\"` replaces the dots with a row of labelled tabs along the bottom, each\n * with a progress bar that fills while its slide is showing, plus a pause button — the tabbed hero\n * carousel layout (put `st-hero`s in it). Tab labels come from `tab-labels`, else each slide's\n * `data-tab-label` attribute, else its `title`.\n *\n * @fires carousel-change - Detail `{ index }`, when the visible slide changes.\n * @cssprop --st-carousel-tab-color - Tab text and progress colour (default: light, for slides with a dark image).\n * @cssprop --st-carousel-tabs-space - Room kept free under each slide's content for the tabs (default `6rem`).\n * @csspart tabs - The tab row.\n * @csspart tab - One tab button.\n * @csspart progress - A tab's progress bar.\n */\n@customElement('st-carousel')\nexport class Carousel extends LitElement {\n static styles = css`\n ${controlBaseStyles}\n\n :host {\n display: block;\n position: relative;\n width: 100%;\n overflow: hidden;\n }\n\n ::slotted(*) {\n display: none !important;\n }\n\n ::slotted([data-st-active]) {\n display: block !important;\n animation: st-carousel-in-next 0.4s ease both;\n }\n\n :host([data-direction='prev']) ::slotted([data-st-active]) {\n animation-name: st-carousel-in-prev;\n }\n\n :host([transition='fade']) ::slotted([data-st-active]),\n :host([transition='fade'][data-direction]) ::slotted([data-st-active]) {\n animation: st-carousel-fade 0.7s ease both;\n }\n\n @keyframes st-carousel-in-next {\n from {\n transform: translateX(10%);\n opacity: 0;\n }\n to {\n transform: none;\n opacity: 1;\n }\n }\n\n @keyframes st-carousel-in-prev {\n from {\n transform: translateX(-10%);\n opacity: 0;\n }\n to {\n transform: none;\n opacity: 1;\n }\n }\n\n @keyframes st-carousel-fade {\n from {\n opacity: 0;\n }\n to {\n opacity: 1;\n }\n }\n\n .nav {\n ${buttonResetStyles}\n position: absolute;\n top: 50%;\n transform: translateY(-50%);\n z-index: 10;\n display: flex;\n align-items: center;\n justify-content: center;\n width: var(--st-size-38);\n height: var(--st-size-38);\n border-radius: var(--st-radius-circle);\n border: 1px solid var(--st-color-border);\n background: var(--st-color-surface);\n color: var(--st-color-text-strong);\n font-size: var(--st-text-xl);\n opacity: 0.8;\n transition:\n opacity 0.3s ease,\n transform 0.3s ease;\n }\n\n .nav:hover {\n opacity: 1;\n transform: translateY(-50%) scale(1.1);\n }\n\n .prev {\n left: var(--st-space-12);\n }\n\n .next {\n right: var(--st-space-12);\n }\n\n .indicators {\n position: absolute;\n bottom: var(--st-space-24);\n left: 50%;\n transform: translateX(-50%);\n z-index: 10;\n display: flex;\n gap: var(--st-space-12);\n }\n\n .dot {\n ${buttonResetStyles}\n width: var(--st-space-12);\n height: var(--st-space-12);\n padding: 0;\n border-radius: var(--st-radius-circle);\n background: var(--st-color-border-strong);\n transition:\n background 0.3s ease,\n transform 0.3s ease;\n }\n\n .dot:hover {\n background: var(--st-color-text-muted);\n }\n\n .dot.active {\n background: var(--st-color-text-strong);\n transform: scale(1.2);\n }\n\n /* ---- indicator-style=\"tabs\" ---- */\n\n :host([indicator-style='tabs']) ::slotted(*) {\n padding-bottom: var(--st-carousel-tabs-space, 6rem);\n }\n\n .tabs {\n position: absolute;\n left: 0;\n right: 0;\n bottom: 0;\n z-index: 10;\n color: var(--st-carousel-tab-color, var(--st-color-on-solid));\n }\n\n .tabs-inner {\n display: flex;\n align-items: flex-start;\n gap: var(--st-space-24);\n max-width: var(--st-cms-container-max);\n margin: 0 auto;\n box-sizing: border-box;\n padding: 0 var(--st-space-24) var(--st-space-24);\n }\n\n .tablist {\n flex: 1;\n display: grid;\n grid-auto-flow: column;\n grid-auto-columns: minmax(0, 1fr);\n gap: var(--st-space-24);\n }\n\n .tab {\n ${buttonResetStyles}\n display: flex;\n flex-direction: column;\n gap: var(--st-space-12);\n padding: var(--st-space-12) 0;\n color: inherit;\n text-align: left;\n font-size: var(--st-text-base);\n font-weight: var(--st-font-weight-semibold);\n line-height: 1.3;\n opacity: 0.7;\n transition: opacity 0.2s ease;\n }\n\n .tab:hover,\n .tab.active {\n opacity: 1;\n }\n\n .tab:focus-visible,\n .play:focus-visible {\n outline: 2px solid currentColor;\n outline-offset: 4px;\n }\n\n .progress {\n position: relative;\n display: block;\n height: 3px;\n border-radius: 2px;\n overflow: hidden;\n background: color-mix(in oklch, currentColor 30%, transparent);\n }\n\n .fill {\n position: absolute;\n inset: 0;\n background: currentColor;\n transform: scaleX(0);\n transform-origin: left center;\n }\n\n .tab.active .fill {\n transform: scaleX(1);\n }\n\n .tab.active.running .fill {\n animation: st-carousel-progress var(--st-carousel-interval, 5000ms) linear both;\n }\n\n :host([data-paused]) .tab.active.running .fill {\n animation-play-state: paused;\n }\n\n @keyframes st-carousel-progress {\n from {\n transform: scaleX(0);\n }\n to {\n transform: scaleX(1);\n }\n }\n\n .play {\n ${buttonResetStyles}\n flex: none;\n display: inline-flex;\n align-items: center;\n justify-content: center;\n width: var(--st-size-32);\n height: var(--st-size-32);\n margin-top: var(--st-space-4);\n border-radius: var(--st-radius-circle);\n color: inherit;\n box-shadow: inset 0 0 0 1.5px color-mix(in oklch, currentColor 60%, transparent);\n }\n\n .play:hover {\n background: color-mix(in oklch, currentColor 15%, transparent);\n }\n\n .tab-current {\n display: none;\n }\n\n @media (max-width: 768px) {\n .tablist {\n gap: var(--st-space-8);\n }\n\n .tab-label {\n display: none;\n }\n\n .tab-current {\n display: block;\n margin: 0 0 var(--st-space-4);\n font-size: var(--st-text-base);\n font-weight: var(--st-font-weight-semibold);\n }\n\n .tabs-inner {\n flex-wrap: wrap;\n align-items: center;\n }\n }\n\n @media (min-width: 1024px) {\n .tabs-inner {\n padding: 0 var(--st-space-32) var(--st-space-32);\n }\n }\n\n ${reducedMotionStyles}\n @media (prefers-reduced-motion: reduce) {\n ::slotted([data-st-active]) {\n animation: none;\n }\n .tab.active.running .fill {\n animation: none;\n }\n }\n `;\n\n @property({ type: Boolean, attribute: 'auto-play' })\n autoPlay = true;\n\n /** Autoplay delay in milliseconds. */\n @property({ type: Number })\n interval = 5000;\n\n /** Pause autoplay while the pointer is over the carousel. Turn off for a hero that fills the\n * screen; the tabs' pause button and keyboard focus still pause it. */\n @property({ type: Boolean, attribute: 'pause-on-hover' })\n pauseOnHover = true;\n\n @property({ type: Boolean, attribute: 'show-arrows' })\n showArrows = true;\n\n @property({ type: Boolean, attribute: 'show-indicators' })\n showIndicators = true;\n\n /** `dots` (default) or `tabs`: labelled tabs with progress bars along the bottom. */\n @property({ type: String, reflect: true, attribute: 'indicator-style' })\n indicatorStyle: 'dots' | 'tabs' = 'dots';\n\n /** `slide` (default) or `fade`. */\n @property({ type: String, reflect: true })\n transition: 'slide' | 'fade' = 'slide';\n\n /** Tab labels, one per slide, for `indicator-style=\"tabs\"`. Missing entries fall back to the slide's `data-tab-label`, then its `title`. */\n @property({ attribute: false })\n tabLabels: string[] = [];\n\n @state() private index = 0;\n @state() private count = 0;\n @state() private slideLabels: string[] = [];\n /** Paused with the pause button; stays paused until the button is pressed again. */\n @state() private userPaused = false;\n /** Paused while hovered or focused. */\n private paused = false;\n private timer?: ReturnType<typeof setTimeout>;\n /** Time left on the current slide, so a pause resumes where it stopped. */\n private remaining = 0;\n private startedAt = 0;\n\n connectedCallback() {\n super.connectedCallback();\n this.addEventListener('mouseenter', this.pauseOnEnter);\n this.addEventListener('mouseleave', this.resume);\n this.addEventListener('focusin', this.pause);\n this.addEventListener('focusout', this.resume);\n }\n\n disconnectedCallback() {\n this.stopTimer();\n this.removeEventListener('mouseenter', this.pauseOnEnter);\n this.removeEventListener('mouseleave', this.resume);\n this.removeEventListener('focusin', this.pause);\n this.removeEventListener('focusout', this.resume);\n super.disconnectedCallback();\n }\n\n protected willUpdate(changed: Map<string, unknown>) {\n if (changed.has('interval')) this.style.setProperty('--st-carousel-interval', `${this.interval}ms`);\n }\n\n protected updated(changed: Map<string, unknown>) {\n if (changed.has('index') || changed.has('count') || changed.has('indicatorStyle') || changed.has('tabLabels')) this.syncSlides();\n if (changed.has('autoPlay') || changed.has('interval') || changed.has('count')) this.restartTimer();\n }\n\n private get halted(): boolean {\n return this.paused || this.userPaused;\n }\n\n /** Applies a pause-state change, freezing or resuming the timer (and the tab progress bar). */\n private hold(update: () => void) {\n const was = this.halted;\n update();\n const now = this.halted;\n if (was === now) return;\n this.toggleAttribute('data-paused', now);\n if (now) {\n if (this.timer !== undefined) this.remaining -= performance.now() - this.startedAt;\n this.stopTimer();\n } else {\n this.startTimer();\n }\n }\n\n private pause = () => this.hold(() => (this.paused = true));\n\n private pauseOnEnter = () => {\n if (this.pauseOnHover) this.pause();\n };\n\n private resume = () => this.hold(() => (this.paused = false));\n\n private togglePlay = () => this.hold(() => (this.userPaused = !this.userPaused));\n\n private get slides(): Element[] {\n return this.shadowRoot?.querySelector('slot')?.assignedElements({ flatten: true }) ?? [];\n }\n\n private labelFor(i: number): string {\n return this.tabLabels[i] || this.slideLabels[i] || `Slide ${i + 1}`;\n }\n\n private syncSlides() {\n const tabs = this.indicatorStyle === 'tabs';\n this.slides.forEach((el, i) => {\n el.toggleAttribute('data-st-active', i === this.index);\n if (tabs) {\n el.setAttribute('role', 'tabpanel');\n el.setAttribute('aria-label', this.labelFor(i));\n } else if (el.getAttribute('role') === 'tabpanel') {\n el.removeAttribute('role');\n el.removeAttribute('aria-label');\n }\n });\n }\n\n private onSlotChange() {\n const slides = this.slides;\n this.count = slides.length;\n this.slideLabels = slides.map(el => (el as HTMLElement).dataset.tabLabel || (el as HTMLElement).title || '');\n if (this.index >= this.count) this.index = 0;\n this.syncSlides();\n }\n\n private stopTimer() {\n if (this.timer !== undefined) clearTimeout(this.timer);\n this.timer = undefined;\n }\n\n private startTimer() {\n this.stopTimer();\n if (!this.autoPlay || this.count < 2 || this.halted) return;\n this.startedAt = performance.now();\n this.timer = setTimeout(() => this.go(this.index + 1, 'next'), Math.max(0, this.remaining));\n }\n\n private restartTimer() {\n this.remaining = this.interval;\n this.startTimer();\n }\n\n private go(target: number, direction: 'next' | 'prev') {\n if (this.count === 0) return;\n this.setAttribute('data-direction', direction);\n this.index = (target + this.count) % this.count;\n this.dispatchEvent(\n new CustomEvent<CarouselChangeEventDetail>('carousel-change', {\n detail: { index: this.index },\n bubbles: true,\n composed: true,\n }),\n );\n this.restartTimer();\n }\n\n private onTabKeydown(event: KeyboardEvent) {\n const step = { ArrowRight: 1, ArrowLeft: -1 }[event.key];\n let target: number | undefined;\n if (step !== undefined) target = this.index + step;\n else if (event.key === 'Home') target = 0;\n else if (event.key === 'End') target = this.count - 1;\n if (target === undefined) return;\n event.preventDefault();\n this.go(target, step === -1 || target < this.index ? 'prev' : 'next');\n void this.updateComplete.then(() => this.renderRoot.querySelector<HTMLElement>('.tab.active')?.focus());\n }\n\n private renderTabs() {\n const running = this.autoPlay && this.count > 1;\n return html`<div class=\"tabs\" part=\"tabs\">\n <div class=\"tabs-inner\">\n <p class=\"tab-current\" aria-hidden=\"true\">${this.labelFor(this.index)}</p>\n <div class=\"tablist\" role=\"tablist\" aria-label=\"Slides\" @keydown=${this.onTabKeydown}>\n ${Array.from({ length: this.count }, (_, i) => {\n const active = i === this.index;\n return html`\n <button\n part=\"tab\"\n type=\"button\"\n role=\"tab\"\n class=\"tab ${active ? 'active' : ''} ${running ? 'running' : ''}\"\n aria-selected=${active ? 'true' : 'false'}\n tabindex=${active ? 0 : -1}\n @click=${() => active || this.go(i, i > this.index ? 'next' : 'prev')}\n >\n <span class=\"progress\" part=\"progress\"><span class=\"fill\"></span></span>\n <span class=\"tab-label\">${this.labelFor(i)}</span>\n </button>\n `;\n })}\n </div>\n ${running\n ? html`<button\n part=\"play-button\"\n type=\"button\"\n class=\"play\"\n aria-label=${this.userPaused ? 'Play slides' : 'Pause slides'}\n @click=${this.togglePlay}\n >\n ${this.userPaused\n ? html`<svg width=\"12\" height=\"12\" viewBox=\"0 0 12 12\" aria-hidden=\"true\"><path d=\"M3 1.5v9l7.5-4.5z\" fill=\"currentColor\" /></svg>`\n : html`<svg width=\"12\" height=\"12\" viewBox=\"0 0 12 12\" aria-hidden=\"true\"><path d=\"M2.5 1.5h2.5v9H2.5zM7 1.5h2.5v9H7z\" fill=\"currentColor\" /></svg>`}\n </button>`\n : nothing}\n </div>\n </div>`;\n }\n\n private renderDots() {\n return html`<div class=\"indicators\" part=\"indicators\">\n ${Array.from(\n { length: this.count },\n (_, i) => html`\n <button\n part=\"dot\"\n class=\"dot ${i === this.index ? 'active' : ''}\"\n aria-label=\"Go to slide ${i + 1}\"\n aria-current=${i === this.index ? 'true' : 'false'}\n @click=${() => this.go(i, i > this.index ? 'next' : 'prev')}\n ></button>\n `,\n )}\n </div>`;\n }\n\n render() {\n const multiple = this.count > 1;\n return html`\n <slot @slotchange=${this.onSlotChange}></slot>\n ${this.showArrows && multiple\n ? html`\n <button part=\"nav-button prev\" class=\"nav prev\" aria-label=\"Previous Slide\" @click=${() => this.go(this.index - 1, 'prev')}>&#10094;</button>\n <button part=\"nav-button next\" class=\"nav next\" aria-label=\"Next Slide\" @click=${() => this.go(this.index + 1, 'next')}>&#10095;</button>\n `\n : nothing}\n ${this.showIndicators && multiple ? (this.indicatorStyle === 'tabs' ? this.renderTabs() : this.renderDots()) : nothing}\n `;\n }\n}\n"],"mappings":"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A;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,QA2Df,iBAAiB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,QA6CjB,iBAAiB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,QAsDjB,iBAAiB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,QAgEjB,iBAAiB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,MAiDnB,mBAAmB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAYvB;AAAA,EADC,SAAS,EAAE,MAAM,SAAS,WAAW,YAAY,CAAC;AAAA,GA5RxC,SA6RX;AAIA;AAAA,EADC,SAAS,EAAE,MAAM,OAAO,CAAC;AAAA,GAhSf,SAiSX;AAKA;AAAA,EADC,SAAS,EAAE,MAAM,SAAS,WAAW,iBAAiB,CAAC;AAAA,GArS7C,SAsSX;AAGA;AAAA,EADC,SAAS,EAAE,MAAM,SAAS,WAAW,cAAc,CAAC;AAAA,GAxS1C,SAySX;AAGA;AAAA,EADC,SAAS,EAAE,MAAM,SAAS,WAAW,kBAAkB,CAAC;AAAA,GA3S9C,SA4SX;AAIA;AAAA,EADC,SAAS,EAAE,MAAM,QAAQ,SAAS,MAAM,WAAW,kBAAkB,CAAC;AAAA,GA/S5D,SAgTX;AAIA;AAAA,EADC,SAAS,EAAE,MAAM,QAAQ,SAAS,KAAK,CAAC;AAAA,GAnT9B,SAoTX;AAIA;AAAA,EADC,SAAS,EAAE,WAAW,MAAM,CAAC;AAAA,GAvTnB,SAwTX;AAEiB;AAAA,EAAhB,MAAM;AAAA,GA1TI,SA0TM;AACA;AAAA,EAAhB,MAAM;AAAA,GA3TI,SA2TM;AACA;AAAA,EAAhB,MAAM;AAAA,GA5TI,SA4TM;AAEA;AAAA,EAAhB,MAAM;AAAA,GA9TI,SA8TM;AA9TN,WAAN;AAAA,EADN,cAAc,aAAa;AAAA,GACf;","names":[]}
@@ -45,6 +45,7 @@ var MenuItem = class extends LitElement {
45
45
  const classes = [
46
46
  "menu-item",
47
47
  link ? "link" : "",
48
+ this.variant === "bar" ? "bar" : "",
48
49
  this.active ? "active" : "",
49
50
  this.compact ? "compact" : "",
50
51
  showDescription ? "" : "no-description"
@@ -279,6 +280,36 @@ MenuItem.styles = css`
279
280
  font-size: 0.8125rem;
280
281
  }
281
282
 
283
+ /* bar: a top-level item in a header bar next to mega st-dropdowns (e.g. "Dashboard" beside
284
+ "Masters ▼") — the same pill, size and active look as their triggers, so the row reads as
285
+ one set. Wins over compact (declared after it). */
286
+ .menu-item.bar {
287
+ align-items: center;
288
+ min-height: 40px;
289
+ padding: 12px;
290
+ gap: 8px;
291
+ border-radius: 9999px;
292
+ white-space: nowrap;
293
+ }
294
+
295
+ .menu-item.bar:hover,
296
+ .menu-item.bar:focus-visible {
297
+ padding-left: 12px;
298
+ }
299
+
300
+ .menu-item.bar.active {
301
+ border-left: 0;
302
+ }
303
+
304
+ .menu-item.bar .menu-item-icon {
305
+ margin-top: 0;
306
+ }
307
+
308
+ .menu-item.bar .menu-item-title {
309
+ font-size: 0.875rem;
310
+ font-weight: 400;
311
+ }
312
+
282
313
  .external {
283
314
  display: inline-flex;
284
315
  margin-left: 3px;
@@ -347,4 +378,4 @@ MenuItem = __decorateClass([
347
378
  export {
348
379
  MenuItem
349
380
  };
350
- //# sourceMappingURL=chunk-KHPJ5FAJ.js.map
381
+ //# sourceMappingURL=chunk-URC5XBTL.js.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/menu-item/MenuItem.ts"],"sourcesContent":["import { LitElement, css, html, nothing } from 'lit';\r\nimport { customElement, property, state } from 'lit/decorators.js';\r\n\r\nimport { arrowUpRightIcon } from '../shared/icons';\r\nimport { controlBaseStyles, fontFamilyStyles } from '../shared/styles';\r\nimport type { MenuItemSelectEventDetail } from './MenuItemEvents';\r\n\r\n/**\r\n * A single flat nav row — icon (`slot=\"icon\"`) + title + badge on one line, an optional\r\n * description below — as opposed to `st-menu-grid-item`'s card for a multi-column grid. A 1:1\r\n * port of `SankhyaUI`'s React `MenuItem` (`SankhyaCMS/SankhyaUI/src/components/Menu`): same\r\n * markup and CSS, with its `motion` effects redone in CSS — nudges right and scales to 1.01 on\r\n * hover / 0.99 while pressed, the icon tilts on hover, the badge pops in, the description fades\r\n * in. Colors come from the suite theme rather than per-item utility classes.\r\n *\r\n * Renders a real `<a href>` but fires a *cancelable* `menu-item-select` event (detail: `{ href }`)\r\n * before navigating — a host doing client-side routing calls `event.preventDefault()` on it (the\r\n * source used react-router's `Link` here; the suite apps have no router).\r\n */\r\n@customElement('st-menu-item')\r\nexport class MenuItem extends LitElement {\r\n /** `focus()` on the element focuses its link, so `st-dropdown` can arrow-key between items. */\r\n static shadowRootOptions = { ...LitElement.shadowRootOptions, delegatesFocus: true };\r\n\r\n static styles = css`\r\n ${controlBaseStyles}\r\n\r\n :host {\r\n display: block;\r\n ${fontFamilyStyles}\r\n }\r\n\r\n @keyframes st-menu-item-badge-pop {\r\n from {\r\n transform: scale(0);\r\n }\r\n 70% {\r\n transform: scale(1.12);\r\n }\r\n to {\r\n transform: scale(1);\r\n }\r\n }\r\n\r\n @keyframes st-menu-item-fade-in {\r\n from {\r\n opacity: 0;\r\n }\r\n to {\r\n opacity: 1;\r\n }\r\n }\r\n\r\n .menu-item {\r\n display: flex;\r\n align-items: flex-start;\r\n gap: 12px;\r\n padding: 12px 16px;\r\n font-size: 0.875rem;\r\n text-decoration: none;\r\n /* --st-nav-*: set by a host bar (st-header's transparent state) to recolour its nav items. */\r\n color: var(--st-nav-color, var(--st-color-text));\r\n border-radius: 6px;\r\n /* The source's 'all 0.15s', minus visibility: animating the visibility this link inherits\r\n from a dropdown panel kept it unfocusable for a frame after the panel opened. */\r\n transition-property: background-color, color, padding, transform, border-color;\r\n transition-duration: 0.15s;\r\n transition-timing-function: ease;\r\n box-sizing: border-box;\r\n }\r\n\r\n /* The source's hover nudge (x: 4px) is done with padding, not a transform: a transform would\r\n spill past a scrolling panel's edge (st-source-bar's menus) and show a horizontal scrollbar.\r\n Keyboard focus gets the same treatment as hover. */\r\n .menu-item:hover,\r\n .menu-item:focus-visible {\r\n background: var(--st-nav-hover-bg, var(--st-color-hover));\r\n color: var(--st-nav-color, var(--st-color-text-strong));\r\n padding-left: 20px;\r\n transition-duration: 0.1s;\r\n }\r\n\r\n .menu-item.compact:hover,\r\n .menu-item.compact:focus-visible {\r\n padding-left: 16px;\r\n }\r\n\r\n .menu-item:active {\r\n transform: scale(0.99);\r\n transition-duration: 0.1s;\r\n }\r\n\r\n .menu-item.active {\r\n background-color: var(--st-color-accent-subtle);\r\n color: var(--st-color-accent-text);\r\n border-left: 4px solid var(--st-color-accent);\r\n }\r\n\r\n .menu-item-icon {\r\n display: flex;\r\n flex-shrink: 0;\r\n margin-top: 2px;\r\n transition: transform 0.2s ease;\r\n }\r\n\r\n .menu-item-icon:hover {\r\n transform: rotate(5deg);\r\n }\r\n\r\n .menu-item-icon[hidden] {\r\n display: none;\r\n }\r\n\r\n .menu-item-icon ::slotted(*) {\r\n width: 16px;\r\n height: 16px;\r\n }\r\n\r\n .menu-item-content {\r\n flex: 1;\r\n min-width: 0;\r\n }\r\n\r\n .menu-item-header {\r\n display: flex;\r\n align-items: center;\r\n justify-content: space-between;\r\n gap: 8px;\r\n }\r\n\r\n .menu-item-title {\r\n font-weight: 500;\r\n overflow: hidden;\r\n text-overflow: ellipsis;\r\n white-space: nowrap;\r\n }\r\n\r\n .menu-item-badge {\r\n display: inline-flex;\r\n align-items: center;\r\n justify-content: center;\r\n min-width: 20px;\r\n height: 20px;\r\n padding: 0 6px;\r\n font-size: 0.75rem;\r\n font-weight: 500;\r\n border-radius: 9999px;\r\n flex-shrink: 0;\r\n background: var(--st-color-accent-subtle);\r\n color: var(--st-color-accent-text);\r\n animation: st-menu-item-badge-pop 0.35s ease-out;\r\n }\r\n\r\n .menu-item-description {\r\n display: -webkit-box;\r\n margin: 4px 0 0;\r\n font-size: 0.75rem;\r\n color: var(--st-color-text-muted);\r\n -webkit-box-orient: vertical;\r\n overflow: hidden;\r\n line-height: 1.4;\r\n animation: st-menu-item-fade-in 0.2s ease;\r\n }\r\n\r\n .menu-item.compact {\r\n padding: 8px 12px;\r\n gap: 8px;\r\n }\r\n\r\n .menu-item.compact .menu-item-icon ::slotted(*) {\r\n width: 14px;\r\n height: 14px;\r\n }\r\n\r\n .menu-item.compact .menu-item-title {\r\n font-size: 0.75rem;\r\n }\r\n\r\n .menu-item.compact .menu-item-description {\r\n font-size: 0.75rem;\r\n }\r\n\r\n /* link: a plain text link (okta.com mega-menu columns) — no box, no nudge, the badge right\r\n after the title, long titles wrap. */\r\n .menu-item.link {\r\n padding: 7px 0;\r\n gap: 10px;\r\n font-size: 0.9375rem;\r\n color: var(--st-nav-color, var(--st-color-text));\r\n }\r\n\r\n .menu-item.link:hover,\r\n .menu-item.link:focus-visible {\r\n padding-left: 0;\r\n background: transparent;\r\n color: var(--st-nav-color, var(--st-color-text-strong));\r\n }\r\n\r\n .menu-item.link:hover .menu-item-title,\r\n .menu-item.link:focus-visible .menu-item-title {\r\n text-decoration: underline;\r\n text-underline-offset: 4px;\r\n }\r\n\r\n .menu-item.link:active {\r\n transform: none;\r\n }\r\n\r\n .menu-item.link.active {\r\n border-left: 0;\r\n background: transparent;\r\n font-weight: 600;\r\n }\r\n\r\n .menu-item.link .menu-item-header {\r\n justify-content: flex-start;\r\n }\r\n\r\n .menu-item.link .menu-item-title {\r\n white-space: normal;\r\n font-weight: 400;\r\n }\r\n\r\n .menu-item.link .menu-item-description {\r\n margin-top: 2px;\r\n font-size: 0.8125rem;\r\n }\r\n\r\n .external {\r\n display: inline-flex;\r\n margin-left: 3px;\r\n vertical-align: 0.05em;\r\n }\r\n\r\n .menu-item.no-description {\r\n align-items: center;\r\n }\r\n\r\n .menu-item.no-description .menu-item-icon {\r\n margin-top: 0;\r\n }\r\n\r\n @media (prefers-reduced-motion: reduce) {\r\n .menu-item,\r\n .menu-item-icon {\r\n transition: none;\r\n }\r\n\r\n .menu-item:active,\r\n .menu-item-icon:hover {\r\n transform: none;\r\n }\r\n\r\n .menu-item-badge,\r\n .menu-item-description {\r\n animation: none;\r\n }\r\n }\r\n `;\r\n\r\n @property({ type: String })\r\n title = '';\r\n\r\n @property({ type: String })\r\n href = '';\r\n\r\n @property({ type: String })\r\n description = '';\r\n\r\n /** Small trailing label, e.g. a count or \"New\"/\"Beta\" — omit for none. */\r\n @property({ type: String })\r\n badge = '';\r\n\r\n /** Highlights this row as the current page (source: `isActive`). */\r\n @property({ type: Boolean, reflect: true })\r\n active = false;\r\n\r\n @property({ type: Boolean, reflect: true })\r\n compact = false;\r\n\r\n /** Suppresses the description even when `description` is set (source: `showDescription`, default `true`). */\r\n @property({ type: Boolean, attribute: 'show-description' })\r\n showDescription = true;\r\n\r\n /** `target` for the `<a>` (source default `_self`). */\r\n @property({ type: String })\r\n target = '_self';\r\n\r\n /** `default` (a row with a hover box) or `link` (a plain text link, as in `st-mega-menu-column`;\r\n * marked with an arrow when it opens a new tab). */\r\n @property({ type: String, reflect: true })\r\n variant: 'default' | 'link' = 'default';\r\n\r\n /** Whether `slot=\"icon\"` has content, so an omitted icon leaves no empty box. */\r\n @state() private hasIcon = false;\r\n\r\n private onIconSlotChange = (event: Event): void => {\r\n this.hasIcon = (event.target as HTMLSlotElement).assignedNodes({ flatten: true }).length > 0;\r\n };\r\n\r\n private onClick = (event: MouseEvent): void => {\r\n const selectEvent = new CustomEvent<MenuItemSelectEventDetail>('menu-item-select', {\r\n detail: { href: this.href },\r\n bubbles: true,\r\n composed: true,\r\n cancelable: true\r\n });\r\n this.dispatchEvent(selectEvent);\r\n if (selectEvent.defaultPrevented) event.preventDefault();\r\n };\r\n\r\n render() {\r\n const showDescription = !!this.description && this.showDescription;\r\n const link = this.variant === 'link';\r\n const classes = [\r\n 'menu-item',\r\n link ? 'link' : '',\r\n this.active ? 'active' : '',\r\n this.compact ? 'compact' : '',\r\n showDescription ? '' : 'no-description'\r\n ]\r\n .filter(Boolean)\r\n .join(' ');\r\n const external = link && this.target === '_blank';\r\n return html`\r\n <a\r\n part=\"item\"\r\n class=${classes}\r\n href=${this.href}\r\n target=${this.target}\r\n rel=${this.target === '_blank' ? 'noopener noreferrer' : nothing}\r\n @click=${this.onClick}\r\n >\r\n <span class=\"menu-item-icon\" part=\"icon\" ?hidden=${!this.hasIcon}><slot name=\"icon\" @slotchange=${this.onIconSlotChange}></slot></span>\r\n <span class=\"menu-item-content\" part=\"content\">\r\n <span class=\"menu-item-header\" part=\"header\">\r\n <span part=\"title\" class=\"menu-item-title\"\r\n >${this.title}${external ? html`<span class=\"external\">${arrowUpRightIcon(11)}</span>` : nothing}</span\r\n >\r\n ${this.badge ? html`<span part=\"badge\" class=\"menu-item-badge\">${this.badge}</span>` : nothing}\r\n </span>\r\n ${showDescription ? html`<p part=\"description\" class=\"menu-item-description\">${this.description}</p>` : nothing}\r\n </span>\r\n </a>\r\n `;\r\n }\r\n}\r\n"],"mappings":"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","names":[]}
1
+ {"version":3,"sources":["../src/menu-item/MenuItem.ts"],"sourcesContent":["import { LitElement, css, html, nothing } from 'lit';\r\nimport { customElement, property, state } from 'lit/decorators.js';\r\n\r\nimport { arrowUpRightIcon } from '../shared/icons';\r\nimport { controlBaseStyles, fontFamilyStyles } from '../shared/styles';\r\nimport type { MenuItemSelectEventDetail } from './MenuItemEvents';\r\n\r\n/**\r\n * A single flat nav row — icon (`slot=\"icon\"`) + title + badge on one line, an optional\r\n * description below — as opposed to `st-menu-grid-item`'s card for a multi-column grid. A 1:1\r\n * port of `SankhyaUI`'s React `MenuItem` (`SankhyaCMS/SankhyaUI/src/components/Menu`): same\r\n * markup and CSS, with its `motion` effects redone in CSS — nudges right and scales to 1.01 on\r\n * hover / 0.99 while pressed, the icon tilts on hover, the badge pops in, the description fades\r\n * in. Colors come from the suite theme rather than per-item utility classes.\r\n *\r\n * Renders a real `<a href>` but fires a *cancelable* `menu-item-select` event (detail: `{ href }`)\r\n * before navigating — a host doing client-side routing calls `event.preventDefault()` on it (the\r\n * source used react-router's `Link` here; the suite apps have no router).\r\n */\r\n@customElement('st-menu-item')\r\nexport class MenuItem extends LitElement {\r\n /** `focus()` on the element focuses its link, so `st-dropdown` can arrow-key between items. */\r\n static shadowRootOptions = { ...LitElement.shadowRootOptions, delegatesFocus: true };\r\n\r\n static styles = css`\r\n ${controlBaseStyles}\r\n\r\n :host {\r\n display: block;\r\n ${fontFamilyStyles}\r\n }\r\n\r\n @keyframes st-menu-item-badge-pop {\r\n from {\r\n transform: scale(0);\r\n }\r\n 70% {\r\n transform: scale(1.12);\r\n }\r\n to {\r\n transform: scale(1);\r\n }\r\n }\r\n\r\n @keyframes st-menu-item-fade-in {\r\n from {\r\n opacity: 0;\r\n }\r\n to {\r\n opacity: 1;\r\n }\r\n }\r\n\r\n .menu-item {\r\n display: flex;\r\n align-items: flex-start;\r\n gap: 12px;\r\n padding: 12px 16px;\r\n font-size: 0.875rem;\r\n text-decoration: none;\r\n /* --st-nav-*: set by a host bar (st-header's transparent state) to recolour its nav items. */\r\n color: var(--st-nav-color, var(--st-color-text));\r\n border-radius: 6px;\r\n /* The source's 'all 0.15s', minus visibility: animating the visibility this link inherits\r\n from a dropdown panel kept it unfocusable for a frame after the panel opened. */\r\n transition-property: background-color, color, padding, transform, border-color;\r\n transition-duration: 0.15s;\r\n transition-timing-function: ease;\r\n box-sizing: border-box;\r\n }\r\n\r\n /* The source's hover nudge (x: 4px) is done with padding, not a transform: a transform would\r\n spill past a scrolling panel's edge (st-source-bar's menus) and show a horizontal scrollbar.\r\n Keyboard focus gets the same treatment as hover. */\r\n .menu-item:hover,\r\n .menu-item:focus-visible {\r\n background: var(--st-nav-hover-bg, var(--st-color-hover));\r\n color: var(--st-nav-color, var(--st-color-text-strong));\r\n padding-left: 20px;\r\n transition-duration: 0.1s;\r\n }\r\n\r\n .menu-item.compact:hover,\r\n .menu-item.compact:focus-visible {\r\n padding-left: 16px;\r\n }\r\n\r\n .menu-item:active {\r\n transform: scale(0.99);\r\n transition-duration: 0.1s;\r\n }\r\n\r\n .menu-item.active {\r\n background-color: var(--st-color-accent-subtle);\r\n color: var(--st-color-accent-text);\r\n border-left: 4px solid var(--st-color-accent);\r\n }\r\n\r\n .menu-item-icon {\r\n display: flex;\r\n flex-shrink: 0;\r\n margin-top: 2px;\r\n transition: transform 0.2s ease;\r\n }\r\n\r\n .menu-item-icon:hover {\r\n transform: rotate(5deg);\r\n }\r\n\r\n .menu-item-icon[hidden] {\r\n display: none;\r\n }\r\n\r\n .menu-item-icon ::slotted(*) {\r\n width: 16px;\r\n height: 16px;\r\n }\r\n\r\n .menu-item-content {\r\n flex: 1;\r\n min-width: 0;\r\n }\r\n\r\n .menu-item-header {\r\n display: flex;\r\n align-items: center;\r\n justify-content: space-between;\r\n gap: 8px;\r\n }\r\n\r\n .menu-item-title {\r\n font-weight: 500;\r\n overflow: hidden;\r\n text-overflow: ellipsis;\r\n white-space: nowrap;\r\n }\r\n\r\n .menu-item-badge {\r\n display: inline-flex;\r\n align-items: center;\r\n justify-content: center;\r\n min-width: 20px;\r\n height: 20px;\r\n padding: 0 6px;\r\n font-size: 0.75rem;\r\n font-weight: 500;\r\n border-radius: 9999px;\r\n flex-shrink: 0;\r\n background: var(--st-color-accent-subtle);\r\n color: var(--st-color-accent-text);\r\n animation: st-menu-item-badge-pop 0.35s ease-out;\r\n }\r\n\r\n .menu-item-description {\r\n display: -webkit-box;\r\n margin: 4px 0 0;\r\n font-size: 0.75rem;\r\n color: var(--st-color-text-muted);\r\n -webkit-box-orient: vertical;\r\n overflow: hidden;\r\n line-height: 1.4;\r\n animation: st-menu-item-fade-in 0.2s ease;\r\n }\r\n\r\n .menu-item.compact {\r\n padding: 8px 12px;\r\n gap: 8px;\r\n }\r\n\r\n .menu-item.compact .menu-item-icon ::slotted(*) {\r\n width: 14px;\r\n height: 14px;\r\n }\r\n\r\n .menu-item.compact .menu-item-title {\r\n font-size: 0.75rem;\r\n }\r\n\r\n .menu-item.compact .menu-item-description {\r\n font-size: 0.75rem;\r\n }\r\n\r\n /* link: a plain text link (okta.com mega-menu columns) — no box, no nudge, the badge right\r\n after the title, long titles wrap. */\r\n .menu-item.link {\r\n padding: 7px 0;\r\n gap: 10px;\r\n font-size: 0.9375rem;\r\n color: var(--st-nav-color, var(--st-color-text));\r\n }\r\n\r\n .menu-item.link:hover,\r\n .menu-item.link:focus-visible {\r\n padding-left: 0;\r\n background: transparent;\r\n color: var(--st-nav-color, var(--st-color-text-strong));\r\n }\r\n\r\n .menu-item.link:hover .menu-item-title,\r\n .menu-item.link:focus-visible .menu-item-title {\r\n text-decoration: underline;\r\n text-underline-offset: 4px;\r\n }\r\n\r\n .menu-item.link:active {\r\n transform: none;\r\n }\r\n\r\n .menu-item.link.active {\r\n border-left: 0;\r\n background: transparent;\r\n font-weight: 600;\r\n }\r\n\r\n .menu-item.link .menu-item-header {\r\n justify-content: flex-start;\r\n }\r\n\r\n .menu-item.link .menu-item-title {\r\n white-space: normal;\r\n font-weight: 400;\r\n }\r\n\r\n .menu-item.link .menu-item-description {\r\n margin-top: 2px;\r\n font-size: 0.8125rem;\r\n }\r\n\r\n /* bar: a top-level item in a header bar next to mega st-dropdowns (e.g. \"Dashboard\" beside\r\n \"Masters ▼\") — the same pill, size and active look as their triggers, so the row reads as\r\n one set. Wins over compact (declared after it). */\r\n .menu-item.bar {\r\n align-items: center;\r\n min-height: 40px;\r\n padding: 12px;\r\n gap: 8px;\r\n border-radius: 9999px;\r\n white-space: nowrap;\r\n }\r\n\r\n .menu-item.bar:hover,\r\n .menu-item.bar:focus-visible {\r\n padding-left: 12px;\r\n }\r\n\r\n .menu-item.bar.active {\r\n border-left: 0;\r\n }\r\n\r\n .menu-item.bar .menu-item-icon {\r\n margin-top: 0;\r\n }\r\n\r\n .menu-item.bar .menu-item-title {\r\n font-size: 0.875rem;\r\n font-weight: 400;\r\n }\r\n\r\n .external {\r\n display: inline-flex;\r\n margin-left: 3px;\r\n vertical-align: 0.05em;\r\n }\r\n\r\n .menu-item.no-description {\r\n align-items: center;\r\n }\r\n\r\n .menu-item.no-description .menu-item-icon {\r\n margin-top: 0;\r\n }\r\n\r\n @media (prefers-reduced-motion: reduce) {\r\n .menu-item,\r\n .menu-item-icon {\r\n transition: none;\r\n }\r\n\r\n .menu-item:active,\r\n .menu-item-icon:hover {\r\n transform: none;\r\n }\r\n\r\n .menu-item-badge,\r\n .menu-item-description {\r\n animation: none;\r\n }\r\n }\r\n `;\r\n\r\n @property({ type: String })\r\n title = '';\r\n\r\n @property({ type: String })\r\n href = '';\r\n\r\n @property({ type: String })\r\n description = '';\r\n\r\n /** Small trailing label, e.g. a count or \"New\"/\"Beta\" — omit for none. */\r\n @property({ type: String })\r\n badge = '';\r\n\r\n /** Highlights this row as the current page (source: `isActive`). */\r\n @property({ type: Boolean, reflect: true })\r\n active = false;\r\n\r\n @property({ type: Boolean, reflect: true })\r\n compact = false;\r\n\r\n /** Suppresses the description even when `description` is set (source: `showDescription`, default `true`). */\r\n @property({ type: Boolean, attribute: 'show-description' })\r\n showDescription = true;\r\n\r\n /** `target` for the `<a>` (source default `_self`). */\r\n @property({ type: String })\r\n target = '_self';\r\n\r\n /** `default` (a row with a hover box), `link` (a plain text link, as in `st-mega-menu-column`;\r\n * marked with an arrow when it opens a new tab) or `bar` (a top-level item in a header bar,\r\n * shaped like a mega `st-dropdown`'s trigger pill so it lines up with the dropdowns beside it). */\r\n @property({ type: String, reflect: true })\r\n variant: 'default' | 'link' | 'bar' = 'default';\r\n\r\n /** Whether `slot=\"icon\"` has content, so an omitted icon leaves no empty box. */\r\n @state() private hasIcon = false;\r\n\r\n private onIconSlotChange = (event: Event): void => {\r\n this.hasIcon = (event.target as HTMLSlotElement).assignedNodes({ flatten: true }).length > 0;\r\n };\r\n\r\n private onClick = (event: MouseEvent): void => {\r\n const selectEvent = new CustomEvent<MenuItemSelectEventDetail>('menu-item-select', {\r\n detail: { href: this.href },\r\n bubbles: true,\r\n composed: true,\r\n cancelable: true\r\n });\r\n this.dispatchEvent(selectEvent);\r\n if (selectEvent.defaultPrevented) event.preventDefault();\r\n };\r\n\r\n render() {\r\n const showDescription = !!this.description && this.showDescription;\r\n const link = this.variant === 'link';\r\n const classes = [\r\n 'menu-item',\r\n link ? 'link' : '',\r\n this.variant === 'bar' ? 'bar' : '',\r\n this.active ? 'active' : '',\r\n this.compact ? 'compact' : '',\r\n showDescription ? '' : 'no-description'\r\n ]\r\n .filter(Boolean)\r\n .join(' ');\r\n const external = link && this.target === '_blank';\r\n return html`\r\n <a\r\n part=\"item\"\r\n class=${classes}\r\n href=${this.href}\r\n target=${this.target}\r\n rel=${this.target === '_blank' ? 'noopener noreferrer' : nothing}\r\n @click=${this.onClick}\r\n >\r\n <span class=\"menu-item-icon\" part=\"icon\" ?hidden=${!this.hasIcon}><slot name=\"icon\" @slotchange=${this.onIconSlotChange}></slot></span>\r\n <span class=\"menu-item-content\" part=\"content\">\r\n <span class=\"menu-item-header\" part=\"header\">\r\n <span part=\"title\" class=\"menu-item-title\"\r\n >${this.title}${external ? html`<span class=\"external\">${arrowUpRightIcon(11)}</span>` : nothing}</span\r\n >\r\n ${this.badge ? html`<span part=\"badge\" class=\"menu-item-badge\">${this.badge}</span>` : nothing}\r\n </span>\r\n ${showDescription ? html`<p part=\"description\" class=\"menu-item-description\">${this.description}</p>` : nothing}\r\n </span>\r\n </a>\r\n `;\r\n }\r\n}\r\n"],"mappings":"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","names":[]}
@@ -1,3 +1,6 @@
1
+ import {
2
+ chevronIcon
3
+ } from "./chunk-PB7ZPPLP.js";
1
4
  import {
2
5
  invertedSectionTextStyles,
3
6
  reducedMotionStyles,
@@ -5,9 +8,6 @@ import {
5
8
  sectionSubtitleStyles,
6
9
  sectionTitleStyles
7
10
  } from "./chunk-3VE6VFJ4.js";
8
- import {
9
- chevronIcon
10
- } from "./chunk-PB7ZPPLP.js";
11
11
  import {
12
12
  buttonResetStyles,
13
13
  cardShellStyles,
@@ -508,4 +508,4 @@ Testimonials = __decorateClass([
508
508
  export {
509
509
  Testimonials
510
510
  };
511
- //# sourceMappingURL=chunk-IDBEZY2O.js.map
511
+ //# sourceMappingURL=chunk-ZRXYWH6C.js.map
package/dist/index.js CHANGED
@@ -3,7 +3,7 @@ import {
3
3
  } from "./chunk-6H262SG6.js";
4
4
  import {
5
5
  Testimonials
6
- } from "./chunk-IDBEZY2O.js";
6
+ } from "./chunk-ZRXYWH6C.js";
7
7
  import {
8
8
  MenuGrid
9
9
  } from "./chunk-VYON56QO.js";
@@ -12,7 +12,7 @@ import {
12
12
  } from "./chunk-4HKSA5UT.js";
13
13
  import {
14
14
  MenuItem
15
- } from "./chunk-KHPJ5FAJ.js";
15
+ } from "./chunk-URC5XBTL.js";
16
16
  import {
17
17
  PromoBanner
18
18
  } from "./chunk-HGJT24UG.js";
@@ -22,6 +22,9 @@ import {
22
22
  import {
23
23
  Select
24
24
  } from "./chunk-TLHG33MM.js";
25
+ import {
26
+ Footer
27
+ } from "./chunk-CDC4P77V.js";
25
28
  import {
26
29
  FeatureItem,
27
30
  FeaturesSection
@@ -30,14 +33,11 @@ import {
30
33
  Header
31
34
  } from "./chunk-5KHI36M5.js";
32
35
  import {
33
- FeatureSplit
34
- } from "./chunk-VRRBMOUP.js";
36
+ IconButton
37
+ } from "./chunk-XXPBFHWR.js";
35
38
  import {
36
39
  Hero
37
40
  } from "./chunk-K4ZICRZL.js";
38
- import {
39
- IconButton
40
- } from "./chunk-XXPBFHWR.js";
41
41
  import {
42
42
  ItemsAccordion
43
43
  } from "./chunk-EMVHNAID.js";
@@ -46,22 +46,18 @@ import {
46
46
  MegaMenuColumn,
47
47
  MegaMenuFeature
48
48
  } from "./chunk-HGTC3LCW.js";
49
- import {
50
- Carousel
51
- } from "./chunk-47RPYNFG.js";
52
49
  import {
53
50
  BentoGrid
54
51
  } from "./chunk-2JGWWXEI.js";
55
52
  import {
56
53
  Card
57
54
  } from "./chunk-7PSYCTEN.js";
55
+ import {
56
+ Carousel
57
+ } from "./chunk-HPIQSECE.js";
58
58
  import {
59
59
  ContentBlock
60
60
  } from "./chunk-UVNBZD7R.js";
61
- import {
62
- Markdown
63
- } from "./chunk-3JU3R22O.js";
64
- import "./chunk-3VE6VFJ4.js";
65
61
  import {
66
62
  CookieConsent
67
63
  } from "./chunk-MW43OS47.js";
@@ -70,8 +66,12 @@ import {
70
66
  } from "./chunk-5MTPMXAQ.js";
71
67
  import "./chunk-PB7ZPPLP.js";
72
68
  import {
73
- Footer
74
- } from "./chunk-CDC4P77V.js";
69
+ FeatureSplit
70
+ } from "./chunk-VRRBMOUP.js";
71
+ import {
72
+ Markdown
73
+ } from "./chunk-3JU3R22O.js";
74
+ import "./chunk-3VE6VFJ4.js";
75
75
  import "./chunk-RHAOQ6K4.js";
76
76
  import "./chunk-EUXUH3YW.js";
77
77
  export {
@@ -36,9 +36,10 @@ declare class MenuItem extends LitElement {
36
36
  showDescription: boolean;
37
37
  /** `target` for the `<a>` (source default `_self`). */
38
38
  target: string;
39
- /** `default` (a row with a hover box) or `link` (a plain text link, as in `st-mega-menu-column`;
40
- * marked with an arrow when it opens a new tab). */
41
- variant: 'default' | 'link';
39
+ /** `default` (a row with a hover box), `link` (a plain text link, as in `st-mega-menu-column`;
40
+ * marked with an arrow when it opens a new tab) or `bar` (a top-level item in a header bar,
41
+ * shaped like a mega `st-dropdown`'s trigger pill so it lines up with the dropdowns beside it). */
42
+ variant: 'default' | 'link' | 'bar';
42
43
  /** Whether `slot="icon"` has content, so an omitted icon leaves no empty box. */
43
44
  private hasIcon;
44
45
  private onIconSlotChange;
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  MenuItem
3
- } from "../chunk-KHPJ5FAJ.js";
3
+ } from "../chunk-URC5XBTL.js";
4
4
  import "../chunk-PB7ZPPLP.js";
5
5
  import "../chunk-RHAOQ6K4.js";
6
6
  import "../chunk-EUXUH3YW.js";
@@ -1,8 +1,8 @@
1
1
  import {
2
2
  Testimonials
3
- } from "../chunk-IDBEZY2O.js";
4
- import "../chunk-3VE6VFJ4.js";
3
+ } from "../chunk-ZRXYWH6C.js";
5
4
  import "../chunk-PB7ZPPLP.js";
5
+ import "../chunk-3VE6VFJ4.js";
6
6
  import "../chunk-RHAOQ6K4.js";
7
7
  import "../chunk-EUXUH3YW.js";
8
8
  export {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@sankhyatronics/sankhya-cms",
3
- "version": "0.1.5",
3
+ "version": "0.1.6",
4
4
  "repository": {
5
5
  "type": "git",
6
6
  "url": "https://github.com/sankhyatronics/SankhyaCMS.git",
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/carousel/Carousel.ts"],"sourcesContent":["import { LitElement, css, html, nothing } from 'lit';\nimport { customElement, property, state } from 'lit/decorators.js';\n\nimport { buttonResetStyles, controlBaseStyles } from '../shared/styles';\nimport { reducedMotionStyles } from '../shared/section-styles';\nimport type { CarouselChangeEventDetail } from './CarouselEvents';\n\n/**\n * Cycles through its slotted children, one visible at a time, with optional autoplay, arrows and\n * dot indicators. The incoming slide slides in from the travel direction (CSS keyframes in place\n * of the source's framer-motion spring), or fades in with `transition=\"fade\"`. Autoplay pauses\n * while hovered or focused and stops when the element is disconnected; a paused slide keeps the\n * time it had left.\n *\n * `indicator-style=\"tabs\"` replaces the dots with a row of labelled tabs along the bottom, each\n * with a progress bar that fills while its slide is showing, plus a pause button — the tabbed hero\n * carousel layout (put `st-hero`s in it). Tab labels come from `tab-labels`, else each slide's\n * `data-tab-label` attribute, else its `title`.\n *\n * @fires carousel-change - Detail `{ index }`, when the visible slide changes.\n * @cssprop --st-carousel-tab-color - Tab text and progress colour (default: light, for slides with a dark image).\n * @cssprop --st-carousel-tabs-space - Room kept free under each slide's content for the tabs (default `6rem`).\n * @csspart tabs - The tab row.\n * @csspart tab - One tab button.\n * @csspart progress - A tab's progress bar.\n */\n@customElement('st-carousel')\nexport class Carousel extends LitElement {\n static styles = css`\n ${controlBaseStyles}\n\n :host {\n display: block;\n position: relative;\n width: 100%;\n overflow: hidden;\n }\n\n ::slotted(*) {\n display: none !important;\n }\n\n ::slotted([data-st-active]) {\n display: block !important;\n animation: st-carousel-in-next 0.4s ease both;\n }\n\n :host([data-direction='prev']) ::slotted([data-st-active]) {\n animation-name: st-carousel-in-prev;\n }\n\n :host([transition='fade']) ::slotted([data-st-active]),\n :host([transition='fade'][data-direction]) ::slotted([data-st-active]) {\n animation: st-carousel-fade 0.7s ease both;\n }\n\n @keyframes st-carousel-in-next {\n from {\n transform: translateX(10%);\n opacity: 0;\n }\n to {\n transform: none;\n opacity: 1;\n }\n }\n\n @keyframes st-carousel-in-prev {\n from {\n transform: translateX(-10%);\n opacity: 0;\n }\n to {\n transform: none;\n opacity: 1;\n }\n }\n\n @keyframes st-carousel-fade {\n from {\n opacity: 0;\n }\n to {\n opacity: 1;\n }\n }\n\n .nav {\n ${buttonResetStyles}\n position: absolute;\n top: 50%;\n transform: translateY(-50%);\n z-index: 10;\n display: flex;\n align-items: center;\n justify-content: center;\n width: var(--st-size-38);\n height: var(--st-size-38);\n border-radius: var(--st-radius-circle);\n border: 1px solid var(--st-color-border);\n background: var(--st-color-surface);\n color: var(--st-color-text-strong);\n font-size: var(--st-text-xl);\n opacity: 0.8;\n transition:\n opacity 0.3s ease,\n transform 0.3s ease;\n }\n\n .nav:hover {\n opacity: 1;\n transform: translateY(-50%) scale(1.1);\n }\n\n .prev {\n left: var(--st-space-12);\n }\n\n .next {\n right: var(--st-space-12);\n }\n\n .indicators {\n position: absolute;\n bottom: var(--st-space-24);\n left: 50%;\n transform: translateX(-50%);\n z-index: 10;\n display: flex;\n gap: var(--st-space-12);\n }\n\n .dot {\n ${buttonResetStyles}\n width: var(--st-space-12);\n height: var(--st-space-12);\n padding: 0;\n border-radius: var(--st-radius-circle);\n background: var(--st-color-border-strong);\n transition:\n background 0.3s ease,\n transform 0.3s ease;\n }\n\n .dot:hover {\n background: var(--st-color-text-muted);\n }\n\n .dot.active {\n background: var(--st-color-text-strong);\n transform: scale(1.2);\n }\n\n /* ---- indicator-style=\"tabs\" ---- */\n\n :host([indicator-style='tabs']) ::slotted(*) {\n padding-bottom: var(--st-carousel-tabs-space, 6rem);\n }\n\n .tabs {\n position: absolute;\n left: 0;\n right: 0;\n bottom: 0;\n z-index: 10;\n color: var(--st-carousel-tab-color, var(--st-color-on-solid));\n }\n\n .tabs-inner {\n display: flex;\n align-items: flex-start;\n gap: var(--st-space-24);\n max-width: var(--st-cms-container-max);\n margin: 0 auto;\n box-sizing: border-box;\n padding: 0 var(--st-space-24) var(--st-space-24);\n }\n\n .tablist {\n flex: 1;\n display: grid;\n grid-auto-flow: column;\n grid-auto-columns: minmax(0, 1fr);\n gap: var(--st-space-24);\n }\n\n .tab {\n ${buttonResetStyles}\n display: flex;\n flex-direction: column;\n gap: var(--st-space-12);\n padding: var(--st-space-12) 0;\n color: inherit;\n text-align: left;\n font-size: var(--st-text-base);\n font-weight: var(--st-font-weight-semibold);\n line-height: 1.3;\n opacity: 0.7;\n transition: opacity 0.2s ease;\n }\n\n .tab:hover,\n .tab.active {\n opacity: 1;\n }\n\n .tab:focus-visible,\n .play:focus-visible {\n outline: 2px solid currentColor;\n outline-offset: 4px;\n }\n\n .progress {\n position: relative;\n display: block;\n height: 3px;\n border-radius: 2px;\n overflow: hidden;\n background: color-mix(in oklch, currentColor 30%, transparent);\n }\n\n .fill {\n position: absolute;\n inset: 0;\n background: currentColor;\n transform: scaleX(0);\n transform-origin: left center;\n }\n\n .tab.active .fill {\n transform: scaleX(1);\n }\n\n .tab.active.running .fill {\n animation: st-carousel-progress var(--st-carousel-interval, 5000ms) linear both;\n }\n\n :host([data-paused]) .tab.active.running .fill {\n animation-play-state: paused;\n }\n\n @keyframes st-carousel-progress {\n from {\n transform: scaleX(0);\n }\n to {\n transform: scaleX(1);\n }\n }\n\n .play {\n ${buttonResetStyles}\n flex: none;\n display: inline-flex;\n align-items: center;\n justify-content: center;\n width: var(--st-size-32);\n height: var(--st-size-32);\n margin-top: var(--st-space-4);\n border-radius: var(--st-radius-circle);\n color: inherit;\n box-shadow: inset 0 0 0 1.5px color-mix(in oklch, currentColor 60%, transparent);\n }\n\n .play:hover {\n background: color-mix(in oklch, currentColor 15%, transparent);\n }\n\n .tab-current {\n display: none;\n }\n\n @media (max-width: 768px) {\n .tablist {\n gap: var(--st-space-8);\n }\n\n .tab-label {\n display: none;\n }\n\n .tab-current {\n display: block;\n margin: 0 0 var(--st-space-4);\n font-size: var(--st-text-base);\n font-weight: var(--st-font-weight-semibold);\n }\n\n .tabs-inner {\n flex-wrap: wrap;\n align-items: center;\n }\n }\n\n @media (min-width: 1024px) {\n .tabs-inner {\n padding: 0 var(--st-space-32) var(--st-space-32);\n }\n }\n\n ${reducedMotionStyles}\n @media (prefers-reduced-motion: reduce) {\n ::slotted([data-st-active]) {\n animation: none;\n }\n .tab.active.running .fill {\n animation: none;\n }\n }\n `;\n\n @property({ type: Boolean, attribute: 'auto-play' })\n autoPlay = true;\n\n /** Autoplay delay in milliseconds. */\n @property({ type: Number })\n interval = 5000;\n\n @property({ type: Boolean, attribute: 'show-arrows' })\n showArrows = true;\n\n @property({ type: Boolean, attribute: 'show-indicators' })\n showIndicators = true;\n\n /** `dots` (default) or `tabs`: labelled tabs with progress bars along the bottom. */\n @property({ type: String, reflect: true, attribute: 'indicator-style' })\n indicatorStyle: 'dots' | 'tabs' = 'dots';\n\n /** `slide` (default) or `fade`. */\n @property({ type: String, reflect: true })\n transition: 'slide' | 'fade' = 'slide';\n\n /** Tab labels, one per slide, for `indicator-style=\"tabs\"`. Missing entries fall back to the slide's `data-tab-label`, then its `title`. */\n @property({ attribute: false })\n tabLabels: string[] = [];\n\n @state() private index = 0;\n @state() private count = 0;\n @state() private slideLabels: string[] = [];\n /** Paused with the pause button; stays paused until the button is pressed again. */\n @state() private userPaused = false;\n /** Paused while hovered or focused. */\n private paused = false;\n private timer?: ReturnType<typeof setTimeout>;\n /** Time left on the current slide, so a pause resumes where it stopped. */\n private remaining = 0;\n private startedAt = 0;\n\n connectedCallback() {\n super.connectedCallback();\n this.addEventListener('mouseenter', this.pause);\n this.addEventListener('mouseleave', this.resume);\n this.addEventListener('focusin', this.pause);\n this.addEventListener('focusout', this.resume);\n }\n\n disconnectedCallback() {\n this.stopTimer();\n this.removeEventListener('mouseenter', this.pause);\n this.removeEventListener('mouseleave', this.resume);\n this.removeEventListener('focusin', this.pause);\n this.removeEventListener('focusout', this.resume);\n super.disconnectedCallback();\n }\n\n protected willUpdate(changed: Map<string, unknown>) {\n if (changed.has('interval')) this.style.setProperty('--st-carousel-interval', `${this.interval}ms`);\n }\n\n protected updated(changed: Map<string, unknown>) {\n if (changed.has('index') || changed.has('count') || changed.has('indicatorStyle') || changed.has('tabLabels')) this.syncSlides();\n if (changed.has('autoPlay') || changed.has('interval') || changed.has('count')) this.restartTimer();\n }\n\n private get halted(): boolean {\n return this.paused || this.userPaused;\n }\n\n /** Applies a pause-state change, freezing or resuming the timer (and the tab progress bar). */\n private hold(update: () => void) {\n const was = this.halted;\n update();\n const now = this.halted;\n if (was === now) return;\n this.toggleAttribute('data-paused', now);\n if (now) {\n if (this.timer !== undefined) this.remaining -= performance.now() - this.startedAt;\n this.stopTimer();\n } else {\n this.startTimer();\n }\n }\n\n private pause = () => this.hold(() => (this.paused = true));\n\n private resume = () => this.hold(() => (this.paused = false));\n\n private togglePlay = () => this.hold(() => (this.userPaused = !this.userPaused));\n\n private get slides(): Element[] {\n return this.shadowRoot?.querySelector('slot')?.assignedElements({ flatten: true }) ?? [];\n }\n\n private labelFor(i: number): string {\n return this.tabLabels[i] || this.slideLabels[i] || `Slide ${i + 1}`;\n }\n\n private syncSlides() {\n const tabs = this.indicatorStyle === 'tabs';\n this.slides.forEach((el, i) => {\n el.toggleAttribute('data-st-active', i === this.index);\n if (tabs) {\n el.setAttribute('role', 'tabpanel');\n el.setAttribute('aria-label', this.labelFor(i));\n } else if (el.getAttribute('role') === 'tabpanel') {\n el.removeAttribute('role');\n el.removeAttribute('aria-label');\n }\n });\n }\n\n private onSlotChange() {\n const slides = this.slides;\n this.count = slides.length;\n this.slideLabels = slides.map(el => (el as HTMLElement).dataset.tabLabel || (el as HTMLElement).title || '');\n if (this.index >= this.count) this.index = 0;\n this.syncSlides();\n }\n\n private stopTimer() {\n if (this.timer !== undefined) clearTimeout(this.timer);\n this.timer = undefined;\n }\n\n private startTimer() {\n this.stopTimer();\n if (!this.autoPlay || this.count < 2 || this.halted) return;\n this.startedAt = performance.now();\n this.timer = setTimeout(() => this.go(this.index + 1, 'next'), Math.max(0, this.remaining));\n }\n\n private restartTimer() {\n this.remaining = this.interval;\n this.startTimer();\n }\n\n private go(target: number, direction: 'next' | 'prev') {\n if (this.count === 0) return;\n this.setAttribute('data-direction', direction);\n this.index = (target + this.count) % this.count;\n this.dispatchEvent(\n new CustomEvent<CarouselChangeEventDetail>('carousel-change', {\n detail: { index: this.index },\n bubbles: true,\n composed: true,\n }),\n );\n this.restartTimer();\n }\n\n private onTabKeydown(event: KeyboardEvent) {\n const step = { ArrowRight: 1, ArrowLeft: -1 }[event.key];\n let target: number | undefined;\n if (step !== undefined) target = this.index + step;\n else if (event.key === 'Home') target = 0;\n else if (event.key === 'End') target = this.count - 1;\n if (target === undefined) return;\n event.preventDefault();\n this.go(target, step === -1 || target < this.index ? 'prev' : 'next');\n void this.updateComplete.then(() => this.renderRoot.querySelector<HTMLElement>('.tab.active')?.focus());\n }\n\n private renderTabs() {\n const running = this.autoPlay && this.count > 1;\n return html`<div class=\"tabs\" part=\"tabs\">\n <div class=\"tabs-inner\">\n <p class=\"tab-current\" aria-hidden=\"true\">${this.labelFor(this.index)}</p>\n <div class=\"tablist\" role=\"tablist\" aria-label=\"Slides\" @keydown=${this.onTabKeydown}>\n ${Array.from({ length: this.count }, (_, i) => {\n const active = i === this.index;\n return html`\n <button\n part=\"tab\"\n type=\"button\"\n role=\"tab\"\n class=\"tab ${active ? 'active' : ''} ${running ? 'running' : ''}\"\n aria-selected=${active ? 'true' : 'false'}\n tabindex=${active ? 0 : -1}\n @click=${() => active || this.go(i, i > this.index ? 'next' : 'prev')}\n >\n <span class=\"progress\" part=\"progress\"><span class=\"fill\"></span></span>\n <span class=\"tab-label\">${this.labelFor(i)}</span>\n </button>\n `;\n })}\n </div>\n ${running\n ? html`<button\n part=\"play-button\"\n type=\"button\"\n class=\"play\"\n aria-label=${this.userPaused ? 'Play slides' : 'Pause slides'}\n @click=${this.togglePlay}\n >\n ${this.userPaused\n ? html`<svg width=\"12\" height=\"12\" viewBox=\"0 0 12 12\" aria-hidden=\"true\"><path d=\"M3 1.5v9l7.5-4.5z\" fill=\"currentColor\" /></svg>`\n : html`<svg width=\"12\" height=\"12\" viewBox=\"0 0 12 12\" aria-hidden=\"true\"><path d=\"M2.5 1.5h2.5v9H2.5zM7 1.5h2.5v9H7z\" fill=\"currentColor\" /></svg>`}\n </button>`\n : nothing}\n </div>\n </div>`;\n }\n\n private renderDots() {\n return html`<div class=\"indicators\" part=\"indicators\">\n ${Array.from(\n { length: this.count },\n (_, i) => html`\n <button\n part=\"dot\"\n class=\"dot ${i === this.index ? 'active' : ''}\"\n aria-label=\"Go to slide ${i + 1}\"\n aria-current=${i === this.index ? 'true' : 'false'}\n @click=${() => this.go(i, i > this.index ? 'next' : 'prev')}\n ></button>\n `,\n )}\n </div>`;\n }\n\n render() {\n const multiple = this.count > 1;\n return html`\n <slot @slotchange=${this.onSlotChange}></slot>\n ${this.showArrows && multiple\n ? html`\n <button part=\"nav-button prev\" class=\"nav prev\" aria-label=\"Previous Slide\" @click=${() => this.go(this.index - 1, 'prev')}>&#10094;</button>\n <button part=\"nav-button next\" class=\"nav next\" aria-label=\"Next Slide\" @click=${() => this.go(this.index + 1, 'next')}>&#10095;</button>\n `\n : nothing}\n ${this.showIndicators && multiple ? (this.indicatorStyle === 'tabs' ? this.renderTabs() : this.renderDots()) : nothing}\n `;\n }\n}\n"],"mappings":"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AAA;AAAA;AAAA;AAAA;AAAA;AAAA,QA2Df,iBAAiB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,QA6CjB,iBAAiB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,QAsDjB,iBAAiB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,QAgEjB,iBAAiB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,MAiDnB,mBAAmB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAYvB;AAAA,EADC,SAAS,EAAE,MAAM,SAAS,WAAW,YAAY,CAAC;AAAA,GA5RxC,SA6RX;AAIA;AAAA,EADC,SAAS,EAAE,MAAM,OAAO,CAAC;AAAA,GAhSf,SAiSX;AAGA;AAAA,EADC,SAAS,EAAE,MAAM,SAAS,WAAW,cAAc,CAAC;AAAA,GAnS1C,SAoSX;AAGA;AAAA,EADC,SAAS,EAAE,MAAM,SAAS,WAAW,kBAAkB,CAAC;AAAA,GAtS9C,SAuSX;AAIA;AAAA,EADC,SAAS,EAAE,MAAM,QAAQ,SAAS,MAAM,WAAW,kBAAkB,CAAC;AAAA,GA1S5D,SA2SX;AAIA;AAAA,EADC,SAAS,EAAE,MAAM,QAAQ,SAAS,KAAK,CAAC;AAAA,GA9S9B,SA+SX;AAIA;AAAA,EADC,SAAS,EAAE,WAAW,MAAM,CAAC;AAAA,GAlTnB,SAmTX;AAEiB;AAAA,EAAhB,MAAM;AAAA,GArTI,SAqTM;AACA;AAAA,EAAhB,MAAM;AAAA,GAtTI,SAsTM;AACA;AAAA,EAAhB,MAAM;AAAA,GAvTI,SAuTM;AAEA;AAAA,EAAhB,MAAM;AAAA,GAzTI,SAyTM;AAzTN,WAAN;AAAA,EADN,cAAc,aAAa;AAAA,GACf;","names":[]}