@lumston/ds-angular 0.0.1 → 0.0.3

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.
@@ -1,5 +1,5 @@
1
1
  import * as i0 from '@angular/core';
2
- import { inject, input, computed, ChangeDetectionStrategy, Component, HostListener, ViewChild, Input, TemplateRef, Directive, output, signal, effect, forwardRef, Renderer2, DestroyRef, ElementRef, model, viewChild, ViewEncapsulation, Injectable, contentChild, untracked } from '@angular/core';
2
+ import { inject, input, computed, ChangeDetectionStrategy, Component, HostListener, ViewChild, Input, TemplateRef, Directive, ElementRef, output, signal, effect, forwardRef, Renderer2, DestroyRef, model, viewChild, ViewEncapsulation, untracked, Injectable, contentChild } from '@angular/core';
3
3
  import { DomSanitizer } from '@angular/platform-browser';
4
4
  import * as i1 from '@angular/common';
5
5
  import { CommonModule, NgTemplateOutlet, DOCUMENT } from '@angular/common';
@@ -228,7 +228,10 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.2", ngImpor
228
228
 
229
229
  class ButtonComponent {
230
230
  constructor() {
231
+ this._elementRef = inject((ElementRef));
231
232
  this.sanitizer = inject(DomSanitizer);
233
+ /** Host element of this component. Pass directly as `anchorEl` to overlay components like `ls-menu`. */
234
+ this.nativeElement = this._elementRef.nativeElement;
232
235
  this.variant = input('contained', ...(ngDevMode ? [{ debugName: "variant" }] : []));
233
236
  this.color = input('primary', ...(ngDevMode ? [{ debugName: "color" }] : []));
234
237
  this.size = input('medium', ...(ngDevMode ? [{ debugName: "size" }] : []));
@@ -2524,6 +2527,505 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.2", ngImpor
2524
2527
  `, changeDetection: ChangeDetectionStrategy.OnPush, styles: [":host{display:contents}.alert{display:flex;align-items:flex-start;gap:12px;padding:12px 16px;border-radius:var(--ls-border-radius-md, 6px);font-family:var(--ls-font-family, \"Nunito\", sans-serif);font-size:14px;line-height:1.5;position:relative;width:100%;box-sizing:border-box}.alert-icon{flex-shrink:0;width:24px;height:24px;display:flex;align-items:center;justify-content:center}.alert-icon svg{width:100%;height:100%}.alert-content{flex:1;min-width:0}.alert-title{font-weight:600;margin-bottom:4px}.alert-message{padding-top:2px;font-weight:400}.alert-close{flex-shrink:0;background:none;border:none;cursor:pointer;padding:4px;border-radius:4px;color:inherit;opacity:.7;transition:opacity var(--ls-transition-duration, .3s);display:flex;align-items:center;justify-content:center}.alert-close:hover{opacity:1}.alert-default-success{background-color:var(--ls-color-success-light);border-left:4px solid var(--ls-color-success);color:var(--ls-color-success)}.alert-default-error{background-color:var(--ls-color-danger-light);border-left:4px solid var(--ls-color-danger);color:var(--ls-color-danger)}.alert-default-warning{background-color:var(--ls-color-warning-light);border-left:4px solid var(--ls-color-warning);color:var(--ls-color-warning)}.alert-default-info{background-color:var(--ls-color-info-light);border-left:4px solid var(--ls-color-info);color:var(--ls-color-info)}.alert-default-primary{background-color:var(--ls-color-primary-light);border-left:4px solid var(--ls-color-primary);color:var(--ls-color-primary)}.alert-default-secondary{background-color:var(--ls-color-secondary-light);border-left:4px solid var(--ls-color-secondary);color:var(--ls-color-secondary)}.alert-filled-success{background-color:var(--ls-color-success);color:#fff}.alert-filled-error{background-color:var(--ls-color-danger);color:#fff}.alert-filled-warning{background-color:var(--ls-color-warning);color:#fff}.alert-filled-info{background-color:var(--ls-color-info);color:#fff}.alert-filled-primary{background-color:var(--ls-color-primary);color:#fff}.alert-filled-secondary{background-color:var(--ls-color-secondary);color:#fff}.alert-outlined-success{background-color:transparent;border:1px solid var(--ls-color-success);color:var(--ls-color-success)}.alert-outlined-error{background-color:transparent;border:1px solid var(--ls-color-danger);color:var(--ls-color-danger)}.alert-outlined-warning{background-color:transparent;border:1px solid var(--ls-color-warning);color:var(--ls-color-warning)}.alert-outlined-info{background-color:transparent;border:1px solid var(--ls-color-info);color:var(--ls-color-info)}.alert-outlined-primary{background-color:transparent;border:1px solid var(--ls-color-primary);color:var(--ls-color-primary)}.alert-outlined-secondary{background-color:transparent;border:1px solid var(--ls-color-secondary);color:var(--ls-color-secondary)}.alert[style*=--alert-custom-color]{border-color:var(--alert-custom-color)}.alert-default-success[style*=--alert-custom-color],.alert-default-error[style*=--alert-custom-color],.alert-default-warning[style*=--alert-custom-color],.alert-default-info[style*=--alert-custom-color],.alert-default-primary[style*=--alert-custom-color],.alert-default-secondary[style*=--alert-custom-color]{border-left-color:var(--alert-custom-color);color:var(--alert-custom-color)}.alert-filled-success[style*=--alert-custom-color],.alert-filled-error[style*=--alert-custom-color],.alert-filled-warning[style*=--alert-custom-color],.alert-filled-info[style*=--alert-custom-color],.alert-filled-primary[style*=--alert-custom-color],.alert-filled-secondary[style*=--alert-custom-color]{background-color:var(--alert-custom-color)}.alert-outlined-success[style*=--alert-custom-color],.alert-outlined-error[style*=--alert-custom-color],.alert-outlined-warning[style*=--alert-custom-color],.alert-outlined-info[style*=--alert-custom-color],.alert-outlined-primary[style*=--alert-custom-color],.alert-outlined-secondary[style*=--alert-custom-color]{border-color:var(--alert-custom-color);color:var(--alert-custom-color)}body.dark .alert-default-success{background-color:var(--ls-color-success-dark-light);border-left-color:var(--ls-color-success);color:var(--ls-color-success)}body.dark .alert-default-error{background-color:var(--ls-color-danger-dark-light);border-left-color:var(--ls-color-danger);color:var(--ls-color-danger)}body.dark .alert-default-warning{background-color:var(--ls-color-warning-dark-light);border-left-color:var(--ls-color-warning);color:var(--ls-color-warning)}body.dark .alert-default-info{background-color:var(--ls-color-info-dark-light);border-left-color:var(--ls-color-info);color:var(--ls-color-info)}body.dark .alert-default-primary{background-color:var(--ls-color-primary-dark-light);border-left-color:var(--ls-color-primary);color:var(--ls-color-primary)}body.dark .alert-default-secondary{background-color:var(--ls-color-secondary-dark-light);border-left-color:var(--ls-color-secondary);color:var(--ls-color-secondary)}body.dark .alert-outlined-success{border-color:var(--ls-color-success);color:var(--ls-color-success)}body.dark .alert-outlined-error{border-color:var(--ls-color-danger);color:var(--ls-color-danger)}body.dark .alert-outlined-warning{border-color:var(--ls-color-warning);color:var(--ls-color-warning)}body.dark .alert-outlined-info{border-color:var(--ls-color-info);color:var(--ls-color-info)}body.dark .alert-outlined-primary{border-color:var(--ls-color-primary);color:var(--ls-color-primary)}body.dark .alert-outlined-secondary{border-color:var(--ls-color-secondary);color:var(--ls-color-secondary)}\n"] }]
2525
2528
  }], propDecorators: { severity: [{ type: i0.Input, args: [{ isSignal: true, alias: "severity", required: false }] }], variant: [{ type: i0.Input, args: [{ isSignal: true, alias: "variant", required: false }] }], closable: [{ type: i0.Input, args: [{ isSignal: true, alias: "closable", required: false }] }], icon: [{ type: i0.Input, args: [{ isSignal: true, alias: "icon", required: false }] }], iconMapping: [{ type: i0.Input, args: [{ isSignal: true, alias: "iconMapping", required: false }] }], color: [{ type: i0.Input, args: [{ isSignal: true, alias: "color", required: false }] }], alertTitle: [{ type: i0.Input, args: [{ isSignal: true, alias: "alertTitle", required: false }] }], message: [{ type: i0.Input, args: [{ isSignal: true, alias: "message", required: false }] }], onClose: [{ type: i0.Output, args: ["onClose"] }] } });
2526
2529
 
2530
+ /**
2531
+ * Renders an anchored floating menu panel attached to a trigger element.
2532
+ *
2533
+ * Supports both **controlled** and **directive-driven** open modes:
2534
+ * - **Controlled**: bind `[(open)]` and respond to `opened`/`closed` outputs.
2535
+ * - **Directive-driven**: apply `lsMenuTriggerFor` to any host element;
2536
+ * the directive calls `setAnchorEl()` and `toggle()` automatically.
2537
+ *
2538
+ * Panel position is derived from the anchor element's bounding rect combined
2539
+ * with `anchorOrigin` (attachment point on the trigger) and `transformOrigin`
2540
+ * (attachment point on the panel). Position is recomputed each time the
2541
+ * panel opens via a `setTimeout(0)` deferral to ensure the panel is measured.
2542
+ *
2543
+ * When `disablePortal` is `false` (default), the panel uses `position: fixed`
2544
+ * for viewport-relative placement. When `true`, it uses `position: absolute`.
2545
+ *
2546
+ * Keyboard: `Escape` closes the panel; `ArrowDown`/`ArrowUp` move focus
2547
+ * between enabled `[role="menuitem"]` elements inside the panel.
2548
+ *
2549
+ * @example
2550
+ * ```html
2551
+ * <!-- Controlled -->
2552
+ * <ls-menu [(open)]="isOpen" [anchorEl]="triggerEl">
2553
+ * <ls-menu-item (itemClick)="onEdit()">Edit</ls-menu-item>
2554
+ * </ls-menu>
2555
+ *
2556
+ * <!-- Directive-driven -->
2557
+ * <button [lsMenuTriggerFor]="myMenu">Open</button>
2558
+ * <ls-menu #myMenu>
2559
+ * <ls-menu-item>Delete</ls-menu-item>
2560
+ * </ls-menu>
2561
+ * ```
2562
+ */
2563
+ class MenuComponent {
2564
+ constructor() {
2565
+ this._document = inject(DOCUMENT);
2566
+ this._destroyRef = inject(DestroyRef);
2567
+ /** Controls the visibility of the menu panel. Supports two-way binding. */
2568
+ this.open = model(false, ...(ngDevMode ? [{ debugName: "open" }] : []));
2569
+ /**
2570
+ * Element used to position the menu panel.
2571
+ *
2572
+ * Accepts a native DOM element, an `ElementRef`, or any Angular component
2573
+ * that exposes a `nativeElement: HTMLElement` property (e.g. `ls-button`).
2574
+ * In templates, pass a template reference variable directly:
2575
+ * `[anchorEl]="btn"` where `#btn` is on any element or component.
2576
+ *
2577
+ * When using `lsMenuTriggerFor`, this is set automatically by the directive
2578
+ * via `setAnchorEl()`. When using controlled mode, bind directly.
2579
+ *
2580
+ * @default null
2581
+ */
2582
+ this.anchorEl = input(null, ...(ngDevMode ? [{ debugName: "anchorEl" }] : []));
2583
+ /**
2584
+ * Defines the attachment point on the anchor element.
2585
+ *
2586
+ * Combined with `transformOrigin` to compute the panel's `top`/`left`
2587
+ * position via `getBoundingClientRect()`.
2588
+ *
2589
+ * @default { vertical: 'bottom', horizontal: 'left' }
2590
+ */
2591
+ this.anchorOrigin = input({
2592
+ vertical: 'bottom',
2593
+ horizontal: 'left',
2594
+ }, ...(ngDevMode ? [{ debugName: "anchorOrigin" }] : []));
2595
+ /**
2596
+ * Defines the attachment point on the menu panel surface.
2597
+ *
2598
+ * The panel is translated so this point aligns with `anchorOrigin`.
2599
+ *
2600
+ * @default { vertical: 'top', horizontal: 'left' }
2601
+ */
2602
+ this.transformOrigin = input({
2603
+ vertical: 'top',
2604
+ horizontal: 'left',
2605
+ }, ...(ngDevMode ? [{ debugName: "transformOrigin" }] : []));
2606
+ /**
2607
+ * When `false` (default), the panel uses `position: fixed` for
2608
+ * viewport-relative placement. When `true`, uses `position: absolute`
2609
+ * and renders relative to the nearest positioned ancestor.
2610
+ *
2611
+ * @default false
2612
+ */
2613
+ this.disablePortal = input(false, ...(ngDevMode ? [{ debugName: "disablePortal" }] : []));
2614
+ /**
2615
+ * When `true`, the panel closes automatically after the user activates
2616
+ * a `ls-menu-item` (i.e., a `[role="menuitem"]` element) inside it.
2617
+ *
2618
+ * @default true
2619
+ */
2620
+ this.closeOnClick = input(true, ...(ngDevMode ? [{ debugName: "closeOnClick" }] : []));
2621
+ /**
2622
+ * Emits when the panel's opening animation completes.
2623
+ * Does NOT emit when `open` is set programmatically without animation.
2624
+ */
2625
+ this.opened = output();
2626
+ /**
2627
+ * Emits when the panel's closing animation completes and the panel
2628
+ * is fully hidden. In controlled mode, the host can use this to update
2629
+ * state after the transition finishes.
2630
+ */
2631
+ this.closed = output();
2632
+ /**
2633
+ * Emits when the user clicks the transparent backdrop behind the panel.
2634
+ * The menu closes automatically after this output emits.
2635
+ */
2636
+ this.backdropClick = output();
2637
+ this._panelRef = viewChild('panelRef', ...(ngDevMode ? [{ debugName: "_panelRef" }] : []));
2638
+ this._isAnimating = signal(false, ...(ngDevMode ? [{ debugName: "_isAnimating" }] : []));
2639
+ this._wasOpen = false;
2640
+ this._previouslyFocused = null;
2641
+ this._savedBodyOverflow = '';
2642
+ this._savedBodyPaddingRight = '';
2643
+ this._resolvedAnchorEl = signal(null, ...(ngDevMode ? [{ debugName: "_resolvedAnchorEl" }] : []));
2644
+ this._repositionHandler = () => this._computeAndApplyPosition();
2645
+ // Manages animation state, scroll lock, focus, and repositioning listeners
2646
+ // when the panel opens or closes.
2647
+ effect(() => {
2648
+ const isOpen = this.open();
2649
+ untracked(() => {
2650
+ if (isOpen) {
2651
+ this._isAnimating.set(true);
2652
+ this._previouslyFocused = this._document.activeElement;
2653
+ this._savedBodyOverflow = this._document.body.style.overflow;
2654
+ this._savedBodyPaddingRight = this._document.body.style.paddingRight;
2655
+ const scrollbarWidth = this._getScrollbarWidth();
2656
+ if (scrollbarWidth > 0) {
2657
+ this._document.body.style.paddingRight = `${scrollbarWidth}px`;
2658
+ }
2659
+ this._document.body.style.overflow = 'hidden';
2660
+ setTimeout(() => this._panelRef()?.nativeElement.focus(), 0);
2661
+ window.addEventListener('resize', this._repositionHandler);
2662
+ window.addEventListener('scroll', this._repositionHandler, true);
2663
+ this._wasOpen = true;
2664
+ }
2665
+ else if (this._wasOpen) {
2666
+ this._isAnimating.set(true);
2667
+ window.removeEventListener('resize', this._repositionHandler);
2668
+ window.removeEventListener('scroll', this._repositionHandler, true);
2669
+ this._wasOpen = false;
2670
+ }
2671
+ });
2672
+ });
2673
+ // Computes and applies panel position whenever the panel enters the DOM
2674
+ // or any positioning input changes. Using a separate effect (rather than
2675
+ // setTimeout) guarantees that Angular has already updated the viewChild
2676
+ // signal before this runs, so _panelRef() is always non-null here.
2677
+ effect(() => {
2678
+ const panel = this._panelRef()?.nativeElement;
2679
+ if (!panel)
2680
+ return;
2681
+ this._computeAndApplyPosition();
2682
+ });
2683
+ this._destroyRef.onDestroy(() => {
2684
+ window.removeEventListener('resize', this._repositionHandler);
2685
+ window.removeEventListener('scroll', this._repositionHandler, true);
2686
+ if (this._wasOpen) {
2687
+ this._document.body.style.overflow = this._savedBodyOverflow;
2688
+ this._document.body.style.paddingRight = this._savedBodyPaddingRight;
2689
+ this._previouslyFocused?.focus?.();
2690
+ }
2691
+ });
2692
+ }
2693
+ /** Toggles the panel between open and closed. */
2694
+ toggle() {
2695
+ this.open.set(!this.open());
2696
+ }
2697
+ /**
2698
+ * Sets the anchor element used for panel positioning.
2699
+ * Called automatically by `MenuTriggerDirective`.
2700
+ */
2701
+ setAnchorEl(el) {
2702
+ this._resolvedAnchorEl.set(el);
2703
+ }
2704
+ /** Closes the panel without waiting for a user interaction. */
2705
+ requestClose() {
2706
+ this.open.set(false);
2707
+ }
2708
+ onBackdropClick(event) {
2709
+ this.backdropClick.emit(event);
2710
+ this.open.set(false);
2711
+ }
2712
+ onPanelClick(event) {
2713
+ if (!this.closeOnClick())
2714
+ return;
2715
+ const target = event.target;
2716
+ if (target.closest('[role="menuitem"]') !== null) {
2717
+ this.open.set(false);
2718
+ }
2719
+ }
2720
+ onAnimationEnd() {
2721
+ this._isAnimating.set(false);
2722
+ if (this.open()) {
2723
+ this.opened.emit();
2724
+ }
2725
+ else {
2726
+ this._document.body.style.overflow = this._savedBodyOverflow;
2727
+ this._document.body.style.paddingRight = this._savedBodyPaddingRight;
2728
+ this.closed.emit();
2729
+ this._previouslyFocused?.focus?.();
2730
+ this._previouslyFocused = null;
2731
+ }
2732
+ }
2733
+ onEscape() {
2734
+ if (this.open()) {
2735
+ this.open.set(false);
2736
+ }
2737
+ }
2738
+ onArrowDown(event) {
2739
+ if (!this.open())
2740
+ return;
2741
+ event.preventDefault();
2742
+ this._moveFocus(1);
2743
+ }
2744
+ onArrowUp(event) {
2745
+ if (!this.open())
2746
+ return;
2747
+ event.preventDefault();
2748
+ this._moveFocus(-1);
2749
+ }
2750
+ _computeAndApplyPosition() {
2751
+ const rawAnchor = this.anchorEl() ?? this._resolvedAnchorEl();
2752
+ const panel = this._panelRef()?.nativeElement;
2753
+ if (!rawAnchor || !panel)
2754
+ return;
2755
+ const anchorEl = this._toHTMLElement(rawAnchor);
2756
+ if (!anchorEl)
2757
+ return;
2758
+ const anchorRect = anchorEl.getBoundingClientRect();
2759
+ const panelRect = panel.getBoundingClientRect();
2760
+ const ao = this.anchorOrigin();
2761
+ const to = this.transformOrigin();
2762
+ const anchorX = anchorRect.left +
2763
+ (ao.horizontal === 'center'
2764
+ ? anchorRect.width / 2
2765
+ : ao.horizontal === 'right'
2766
+ ? anchorRect.width
2767
+ : 0);
2768
+ const anchorY = anchorRect.top +
2769
+ (ao.vertical === 'center'
2770
+ ? anchorRect.height / 2
2771
+ : ao.vertical === 'bottom'
2772
+ ? anchorRect.height
2773
+ : 0);
2774
+ const transformX = to.horizontal === 'center'
2775
+ ? panelRect.width / 2
2776
+ : to.horizontal === 'right'
2777
+ ? panelRect.width
2778
+ : 0;
2779
+ const transformY = to.vertical === 'center'
2780
+ ? panelRect.height / 2
2781
+ : to.vertical === 'bottom'
2782
+ ? panelRect.height
2783
+ : 0;
2784
+ panel.style.setProperty('--menu-top', `${anchorY - transformY}px`);
2785
+ panel.style.setProperty('--menu-left', `${anchorX - transformX}px`);
2786
+ }
2787
+ /**
2788
+ * Resolves any supported anchor value to a plain `HTMLElement`.
2789
+ *
2790
+ * Handles: `HTMLElement`, `ElementRef<HTMLElement>`, and objects that expose
2791
+ * a `nativeElement: HTMLElement` property (e.g. `ls-button` component refs).
2792
+ */
2793
+ _toHTMLElement(anchor) {
2794
+ if (!anchor)
2795
+ return null;
2796
+ if (anchor instanceof HTMLElement)
2797
+ return anchor;
2798
+ if (typeof anchor === 'object' &&
2799
+ anchor !== null &&
2800
+ 'nativeElement' in anchor) {
2801
+ const el = anchor.nativeElement;
2802
+ return el instanceof HTMLElement ? el : null;
2803
+ }
2804
+ return null;
2805
+ }
2806
+ _moveFocus(direction) {
2807
+ const panel = this._panelRef()?.nativeElement;
2808
+ if (!panel)
2809
+ return;
2810
+ const items = Array.from(panel.querySelectorAll('[role="menuitem"]:not([aria-disabled="true"])'));
2811
+ if (items.length === 0)
2812
+ return;
2813
+ const currentIndex = items.indexOf(this._document.activeElement);
2814
+ const nextIndex = currentIndex === -1
2815
+ ? direction === 1
2816
+ ? 0
2817
+ : items.length - 1
2818
+ : (currentIndex + direction + items.length) % items.length;
2819
+ items[nextIndex]?.focus();
2820
+ }
2821
+ _getScrollbarWidth() {
2822
+ return window.innerWidth - this._document.documentElement.clientWidth;
2823
+ }
2824
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.2", ngImport: i0, type: MenuComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
2825
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.1.2", type: MenuComponent, isStandalone: true, selector: "ls-menu", inputs: { open: { classPropertyName: "open", publicName: "open", isSignal: true, isRequired: false, transformFunction: null }, anchorEl: { classPropertyName: "anchorEl", publicName: "anchorEl", isSignal: true, isRequired: false, transformFunction: null }, anchorOrigin: { classPropertyName: "anchorOrigin", publicName: "anchorOrigin", isSignal: true, isRequired: false, transformFunction: null }, transformOrigin: { classPropertyName: "transformOrigin", publicName: "transformOrigin", isSignal: true, isRequired: false, transformFunction: null }, disablePortal: { classPropertyName: "disablePortal", publicName: "disablePortal", isSignal: true, isRequired: false, transformFunction: null }, closeOnClick: { classPropertyName: "closeOnClick", publicName: "closeOnClick", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { open: "openChange", opened: "opened", closed: "closed", backdropClick: "backdropClick" }, host: { listeners: { "document:keydown.escape": "onEscape()", "document:keydown.arrowdown": "onArrowDown($event)", "document:keydown.arrowup": "onArrowUp($event)" } }, viewQueries: [{ propertyName: "_panelRef", first: true, predicate: ["panelRef"], descendants: true, isSignal: true }], ngImport: i0, template: `
2826
+ @if (open() || _isAnimating()) {
2827
+ <div class="menu-backdrop" (click)="onBackdropClick($event)"></div>
2828
+ <div
2829
+ #panelRef
2830
+ class="menu-panel"
2831
+ [class.menu-panel-inline]="disablePortal()"
2832
+ [class.menu-enter]="open() && _isAnimating()"
2833
+ [class.menu-leave]="!open() && _isAnimating()"
2834
+ role="menu"
2835
+ tabindex="-1"
2836
+ (click)="onPanelClick($event)"
2837
+ (animationend)="onAnimationEnd()">
2838
+ <ng-content />
2839
+ </div>
2840
+ }
2841
+ `, isInline: true, styles: [":host{display:contents}.menu-backdrop{position:fixed;inset:0;z-index:var(--ls-menu-z-index);background-color:transparent}.menu-panel{position:fixed;top:var(--menu-top, 0px);left:var(--menu-left, 0px);z-index:calc(var(--ls-menu-z-index) + 1);min-width:10rem;padding:.25rem 0;background-color:#fff;border-radius:var(--ls-border-radius-md);box-shadow:0 4px 24px #0000001f;outline:none}.menu-panel.menu-panel-inline{position:absolute}@keyframes menu-enter-kf{0%{opacity:0;transform:scale(.95) translateY(-4px)}to{opacity:1;transform:scale(1) translateY(0)}}@keyframes menu-leave-kf{0%{opacity:1;transform:scale(1) translateY(0)}to{opacity:0;transform:scale(.95) translateY(-4px)}}.menu-panel.menu-enter{animation:menu-enter-kf .15s ease-out forwards}.menu-panel.menu-leave{animation:menu-leave-kf .1s ease-in forwards}.menu-item{display:flex;align-items:center;width:100%;padding:.5rem 1rem;background:none;border:none;text-align:left;font-family:var(--ls-font-family);font-size:.875rem;color:#3b3f5c;cursor:pointer;transition:background-color var(--ls-transition-duration) ease}.menu-item:hover:not(:disabled){background-color:#f1f2f3}.menu-item:focus-visible{outline:2px solid var(--ls-color-primary);outline-offset:-2px;background-color:#f1f2f3}.menu-item-dense{padding-top:.25rem;padding-bottom:.25rem}.menu-item-no-gutters{padding-inline:0}.menu-item-divider{border-bottom:1px solid #e0e6ed}.menu-item-disabled{color:#888ea8;pointer-events:none;cursor:not-allowed}body.dark .menu-panel{background-color:#1b2e4b;box-shadow:0 4px 24px #0006}body.dark .menu-item{color:#e0e6ed}body.dark .menu-item:hover:not(:disabled){background-color:#253b5e}body.dark .menu-item:focus-visible{background-color:#253b5e}body.dark .menu-item-divider{border-bottom-color:#253b5e}body.dark .menu-item-disabled{color:#506690}\n"], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
2842
+ }
2843
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.2", ngImport: i0, type: MenuComponent, decorators: [{
2844
+ type: Component,
2845
+ args: [{ changeDetection: ChangeDetectionStrategy.OnPush, imports: [], selector: 'ls-menu', standalone: true, template: `
2846
+ @if (open() || _isAnimating()) {
2847
+ <div class="menu-backdrop" (click)="onBackdropClick($event)"></div>
2848
+ <div
2849
+ #panelRef
2850
+ class="menu-panel"
2851
+ [class.menu-panel-inline]="disablePortal()"
2852
+ [class.menu-enter]="open() && _isAnimating()"
2853
+ [class.menu-leave]="!open() && _isAnimating()"
2854
+ role="menu"
2855
+ tabindex="-1"
2856
+ (click)="onPanelClick($event)"
2857
+ (animationend)="onAnimationEnd()">
2858
+ <ng-content />
2859
+ </div>
2860
+ }
2861
+ `, styles: [":host{display:contents}.menu-backdrop{position:fixed;inset:0;z-index:var(--ls-menu-z-index);background-color:transparent}.menu-panel{position:fixed;top:var(--menu-top, 0px);left:var(--menu-left, 0px);z-index:calc(var(--ls-menu-z-index) + 1);min-width:10rem;padding:.25rem 0;background-color:#fff;border-radius:var(--ls-border-radius-md);box-shadow:0 4px 24px #0000001f;outline:none}.menu-panel.menu-panel-inline{position:absolute}@keyframes menu-enter-kf{0%{opacity:0;transform:scale(.95) translateY(-4px)}to{opacity:1;transform:scale(1) translateY(0)}}@keyframes menu-leave-kf{0%{opacity:1;transform:scale(1) translateY(0)}to{opacity:0;transform:scale(.95) translateY(-4px)}}.menu-panel.menu-enter{animation:menu-enter-kf .15s ease-out forwards}.menu-panel.menu-leave{animation:menu-leave-kf .1s ease-in forwards}.menu-item{display:flex;align-items:center;width:100%;padding:.5rem 1rem;background:none;border:none;text-align:left;font-family:var(--ls-font-family);font-size:.875rem;color:#3b3f5c;cursor:pointer;transition:background-color var(--ls-transition-duration) ease}.menu-item:hover:not(:disabled){background-color:#f1f2f3}.menu-item:focus-visible{outline:2px solid var(--ls-color-primary);outline-offset:-2px;background-color:#f1f2f3}.menu-item-dense{padding-top:.25rem;padding-bottom:.25rem}.menu-item-no-gutters{padding-inline:0}.menu-item-divider{border-bottom:1px solid #e0e6ed}.menu-item-disabled{color:#888ea8;pointer-events:none;cursor:not-allowed}body.dark .menu-panel{background-color:#1b2e4b;box-shadow:0 4px 24px #0006}body.dark .menu-item{color:#e0e6ed}body.dark .menu-item:hover:not(:disabled){background-color:#253b5e}body.dark .menu-item:focus-visible{background-color:#253b5e}body.dark .menu-item-divider{border-bottom-color:#253b5e}body.dark .menu-item-disabled{color:#506690}\n"] }]
2862
+ }], ctorParameters: () => [], propDecorators: { open: [{ type: i0.Input, args: [{ isSignal: true, alias: "open", required: false }] }, { type: i0.Output, args: ["openChange"] }], anchorEl: [{ type: i0.Input, args: [{ isSignal: true, alias: "anchorEl", required: false }] }], anchorOrigin: [{ type: i0.Input, args: [{ isSignal: true, alias: "anchorOrigin", required: false }] }], transformOrigin: [{ type: i0.Input, args: [{ isSignal: true, alias: "transformOrigin", required: false }] }], disablePortal: [{ type: i0.Input, args: [{ isSignal: true, alias: "disablePortal", required: false }] }], closeOnClick: [{ type: i0.Input, args: [{ isSignal: true, alias: "closeOnClick", required: false }] }], opened: [{ type: i0.Output, args: ["opened"] }], closed: [{ type: i0.Output, args: ["closed"] }], backdropClick: [{ type: i0.Output, args: ["backdropClick"] }], _panelRef: [{ type: i0.ViewChild, args: ['panelRef', { isSignal: true }] }], onEscape: [{
2863
+ type: HostListener,
2864
+ args: ['document:keydown.escape']
2865
+ }], onArrowDown: [{
2866
+ type: HostListener,
2867
+ args: ['document:keydown.arrowdown', ['$event']]
2868
+ }], onArrowUp: [{
2869
+ type: HostListener,
2870
+ args: ['document:keydown.arrowup', ['$event']]
2871
+ }] } });
2872
+
2873
+ /**
2874
+ * Interactive item rendered inside an `ls-menu` panel.
2875
+ *
2876
+ * Renders a `<button role="menuitem">` that projects its label via
2877
+ * `<ng-content>`. Visual density, gutters, and a bottom divider are
2878
+ * configurable via inputs. When `disabled` is `true`, the item is not
2879
+ * interactive and the `itemClick` output will not emit.
2880
+ *
2881
+ * @example
2882
+ * ```html
2883
+ * <ls-menu-item [dense]="true" (itemClick)="onEdit($event)">
2884
+ * Edit
2885
+ * </ls-menu-item>
2886
+ * ```
2887
+ */
2888
+ class MenuItemComponent {
2889
+ constructor() {
2890
+ /**
2891
+ * Reduces the vertical padding of the item for compact layouts.
2892
+ *
2893
+ * @default false
2894
+ */
2895
+ this.dense = input(false, ...(ngDevMode ? [{ debugName: "dense" }] : []));
2896
+ /**
2897
+ * Removes left and right padding when `true`.
2898
+ *
2899
+ * @default false
2900
+ */
2901
+ this.disableGutters = input(false, ...(ngDevMode ? [{ debugName: "disableGutters" }] : []));
2902
+ /**
2903
+ * Adds a 1px border at the bottom of the item to act as a visual divider.
2904
+ *
2905
+ * @default false
2906
+ */
2907
+ this.divider = input(false, ...(ngDevMode ? [{ debugName: "divider" }] : []));
2908
+ /**
2909
+ * Prevents interaction. Applies disabled styling, sets `aria-disabled="true"`,
2910
+ * and suppresses the `itemClick` output.
2911
+ *
2912
+ * @default false
2913
+ */
2914
+ this.disabled = input(false, ...(ngDevMode ? [{ debugName: "disabled" }] : []));
2915
+ /**
2916
+ * Emits the originating `MouseEvent` when the user activates the item.
2917
+ * Does NOT emit when `disabled` is `true`.
2918
+ */
2919
+ this.itemClick = output();
2920
+ this._itemClasses = computed(() => {
2921
+ const classes = ['menu-item'];
2922
+ if (this.dense())
2923
+ classes.push('menu-item-dense');
2924
+ if (this.disableGutters())
2925
+ classes.push('menu-item-no-gutters');
2926
+ if (this.divider())
2927
+ classes.push('menu-item-divider');
2928
+ if (this.disabled())
2929
+ classes.push('menu-item-disabled');
2930
+ return classes.join(' ');
2931
+ }, ...(ngDevMode ? [{ debugName: "_itemClasses" }] : []));
2932
+ }
2933
+ handleClick(event) {
2934
+ if (this.disabled())
2935
+ return;
2936
+ this.itemClick.emit(event);
2937
+ }
2938
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.2", ngImport: i0, type: MenuItemComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
2939
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "21.1.2", type: MenuItemComponent, isStandalone: true, selector: "ls-menu-item", inputs: { dense: { classPropertyName: "dense", publicName: "dense", isSignal: true, isRequired: false, transformFunction: null }, disableGutters: { classPropertyName: "disableGutters", publicName: "disableGutters", isSignal: true, isRequired: false, transformFunction: null }, divider: { classPropertyName: "divider", publicName: "divider", isSignal: true, isRequired: false, transformFunction: null }, disabled: { classPropertyName: "disabled", publicName: "disabled", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { itemClick: "itemClick" }, ngImport: i0, template: `
2940
+ <button
2941
+ type="button"
2942
+ [class]="_itemClasses()"
2943
+ [disabled]="disabled()"
2944
+ [attr.aria-disabled]="disabled() ? 'true' : null"
2945
+ role="menuitem"
2946
+ (click)="handleClick($event)">
2947
+ <ng-content />
2948
+ </button>
2949
+ `, isInline: true, styles: [":host{display:contents}.menu-backdrop{position:fixed;inset:0;z-index:var(--ls-menu-z-index);background-color:transparent}.menu-panel{position:fixed;top:var(--menu-top, 0px);left:var(--menu-left, 0px);z-index:calc(var(--ls-menu-z-index) + 1);min-width:10rem;padding:.25rem 0;background-color:#fff;border-radius:var(--ls-border-radius-md);box-shadow:0 4px 24px #0000001f;outline:none}.menu-panel.menu-panel-inline{position:absolute}@keyframes menu-enter-kf{0%{opacity:0;transform:scale(.95) translateY(-4px)}to{opacity:1;transform:scale(1) translateY(0)}}@keyframes menu-leave-kf{0%{opacity:1;transform:scale(1) translateY(0)}to{opacity:0;transform:scale(.95) translateY(-4px)}}.menu-panel.menu-enter{animation:menu-enter-kf .15s ease-out forwards}.menu-panel.menu-leave{animation:menu-leave-kf .1s ease-in forwards}.menu-item{display:flex;align-items:center;width:100%;padding:.5rem 1rem;background:none;border:none;text-align:left;font-family:var(--ls-font-family);font-size:.875rem;color:#3b3f5c;cursor:pointer;transition:background-color var(--ls-transition-duration) ease}.menu-item:hover:not(:disabled){background-color:#f1f2f3}.menu-item:focus-visible{outline:2px solid var(--ls-color-primary);outline-offset:-2px;background-color:#f1f2f3}.menu-item-dense{padding-top:.25rem;padding-bottom:.25rem}.menu-item-no-gutters{padding-inline:0}.menu-item-divider{border-bottom:1px solid #e0e6ed}.menu-item-disabled{color:#888ea8;pointer-events:none;cursor:not-allowed}body.dark .menu-panel{background-color:#1b2e4b;box-shadow:0 4px 24px #0006}body.dark .menu-item{color:#e0e6ed}body.dark .menu-item:hover:not(:disabled){background-color:#253b5e}body.dark .menu-item:focus-visible{background-color:#253b5e}body.dark .menu-item-divider{border-bottom-color:#253b5e}body.dark .menu-item-disabled{color:#506690}\n"], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
2950
+ }
2951
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.2", ngImport: i0, type: MenuItemComponent, decorators: [{
2952
+ type: Component,
2953
+ args: [{ changeDetection: ChangeDetectionStrategy.OnPush, imports: [], selector: 'ls-menu-item', standalone: true, template: `
2954
+ <button
2955
+ type="button"
2956
+ [class]="_itemClasses()"
2957
+ [disabled]="disabled()"
2958
+ [attr.aria-disabled]="disabled() ? 'true' : null"
2959
+ role="menuitem"
2960
+ (click)="handleClick($event)">
2961
+ <ng-content />
2962
+ </button>
2963
+ `, styles: [":host{display:contents}.menu-backdrop{position:fixed;inset:0;z-index:var(--ls-menu-z-index);background-color:transparent}.menu-panel{position:fixed;top:var(--menu-top, 0px);left:var(--menu-left, 0px);z-index:calc(var(--ls-menu-z-index) + 1);min-width:10rem;padding:.25rem 0;background-color:#fff;border-radius:var(--ls-border-radius-md);box-shadow:0 4px 24px #0000001f;outline:none}.menu-panel.menu-panel-inline{position:absolute}@keyframes menu-enter-kf{0%{opacity:0;transform:scale(.95) translateY(-4px)}to{opacity:1;transform:scale(1) translateY(0)}}@keyframes menu-leave-kf{0%{opacity:1;transform:scale(1) translateY(0)}to{opacity:0;transform:scale(.95) translateY(-4px)}}.menu-panel.menu-enter{animation:menu-enter-kf .15s ease-out forwards}.menu-panel.menu-leave{animation:menu-leave-kf .1s ease-in forwards}.menu-item{display:flex;align-items:center;width:100%;padding:.5rem 1rem;background:none;border:none;text-align:left;font-family:var(--ls-font-family);font-size:.875rem;color:#3b3f5c;cursor:pointer;transition:background-color var(--ls-transition-duration) ease}.menu-item:hover:not(:disabled){background-color:#f1f2f3}.menu-item:focus-visible{outline:2px solid var(--ls-color-primary);outline-offset:-2px;background-color:#f1f2f3}.menu-item-dense{padding-top:.25rem;padding-bottom:.25rem}.menu-item-no-gutters{padding-inline:0}.menu-item-divider{border-bottom:1px solid #e0e6ed}.menu-item-disabled{color:#888ea8;pointer-events:none;cursor:not-allowed}body.dark .menu-panel{background-color:#1b2e4b;box-shadow:0 4px 24px #0006}body.dark .menu-item{color:#e0e6ed}body.dark .menu-item:hover:not(:disabled){background-color:#253b5e}body.dark .menu-item:focus-visible{background-color:#253b5e}body.dark .menu-item-divider{border-bottom-color:#253b5e}body.dark .menu-item-disabled{color:#506690}\n"] }]
2964
+ }], propDecorators: { dense: [{ type: i0.Input, args: [{ isSignal: true, alias: "dense", required: false }] }], disableGutters: [{ type: i0.Input, args: [{ isSignal: true, alias: "disableGutters", required: false }] }], divider: [{ type: i0.Input, args: [{ isSignal: true, alias: "divider", required: false }] }], disabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "disabled", required: false }] }], itemClick: [{ type: i0.Output, args: ["itemClick"] }] } });
2965
+
2966
+ /**
2967
+ * Connects any host element to a `MenuComponent` instance, enabling
2968
+ * click-to-toggle behavior without manual open-state management.
2969
+ *
2970
+ * Sets `anchorEl` on the linked `MenuComponent` to the host element
2971
+ * before toggling visibility, so the panel is correctly positioned
2972
+ * relative to the trigger. Also applies `aria-haspopup="menu"` to the
2973
+ * host for accessibility.
2974
+ *
2975
+ * @example
2976
+ * ```html
2977
+ * <button type="button" [lsMenuTriggerFor]="myMenu">Options</button>
2978
+ * <ls-menu #myMenu>
2979
+ * <ls-menu-item>Delete</ls-menu-item>
2980
+ * </ls-menu>
2981
+ * ```
2982
+ */
2983
+ class MenuTriggerDirective {
2984
+ constructor() {
2985
+ /**
2986
+ * The `MenuComponent` instance this directive controls.
2987
+ * Assign a template reference variable of `ls-menu`.
2988
+ */
2989
+ this.lsMenuTriggerFor = input.required(...(ngDevMode ? [{ debugName: "lsMenuTriggerFor" }] : []));
2990
+ this._elementRef = inject((ElementRef));
2991
+ }
2992
+ onClick() {
2993
+ const menu = this.lsMenuTriggerFor();
2994
+ menu.setAnchorEl(this._resolveAnchorElement());
2995
+ menu.toggle();
2996
+ }
2997
+ /**
2998
+ * Resolves the first ancestor element that has a real layout box.
2999
+ *
3000
+ * Angular component hosts commonly use `:host { display: contents }`,
3001
+ * which means the element itself has no bounding box and
3002
+ * `getBoundingClientRect()` returns all zeros. This method walks down
3003
+ * through `display: contents` wrappers until it reaches the first child
3004
+ * that participates in layout, so the menu panel is positioned relative
3005
+ * to the visible trigger element rather than a phantom box.
3006
+ */
3007
+ _resolveAnchorElement() {
3008
+ let el = this._elementRef.nativeElement;
3009
+ while (el.firstElementChild && getComputedStyle(el).display === 'contents') {
3010
+ el = el.firstElementChild;
3011
+ }
3012
+ return el;
3013
+ }
3014
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.2", ngImport: i0, type: MenuTriggerDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive }); }
3015
+ static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.1.0", version: "21.1.2", type: MenuTriggerDirective, isStandalone: true, selector: "[lsMenuTriggerFor]", inputs: { lsMenuTriggerFor: { classPropertyName: "lsMenuTriggerFor", publicName: "lsMenuTriggerFor", isSignal: true, isRequired: true, transformFunction: null } }, host: { attributes: { "aria-haspopup": "menu" }, listeners: { "click": "onClick()" } }, ngImport: i0 }); }
3016
+ }
3017
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.2", ngImport: i0, type: MenuTriggerDirective, decorators: [{
3018
+ type: Directive,
3019
+ args: [{
3020
+ host: { 'aria-haspopup': 'menu' },
3021
+ selector: '[lsMenuTriggerFor]',
3022
+ standalone: true,
3023
+ }]
3024
+ }], propDecorators: { lsMenuTriggerFor: [{ type: i0.Input, args: [{ isSignal: true, alias: "lsMenuTriggerFor", required: true }] }], onClick: [{
3025
+ type: HostListener,
3026
+ args: ['click']
3027
+ }] } });
3028
+
2527
3029
  class ModalActionsComponent {
2528
3030
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.2", ngImport: i0, type: ModalActionsComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
2529
3031
  static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "21.1.2", type: ModalActionsComponent, isStandalone: true, selector: "ls-modal-actions", host: { classAttribute: "modal-actions" }, ngImport: i0, template: `<ng-content />`, isInline: true, changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
@@ -2980,20 +3482,135 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.2", ngImpor
2980
3482
  `, styles: [":host{display:contents}.popover-panel{position:fixed;top:var(--popover-top, 0);left:var(--popover-left, 0);z-index:1050;background:var(--ls-color-white, #fff);border:1px solid var(--ls-color-border, #e0e6ed);border-radius:8px;box-shadow:0 4px 16px #0000001f;padding:12px 16px;animation-duration:.15s;animation-fill-mode:both;animation-timing-function:ease-out}.popover-enter{animation-name:popoverFadeIn}.popover-exit{animation-name:popoverFadeOut}@keyframes popoverFadeIn{0%{opacity:0;transform:translateY(4px)}to{opacity:1;transform:translateY(0)}}@keyframes popoverFadeOut{0%{opacity:1;transform:translateY(0)}to{opacity:0;transform:translateY(4px)}}.popover-arrow{position:absolute;width:10px;height:10px;background:inherit;border:inherit;transform:rotate(45deg);z-index:-1}.popover-arrow-top{bottom:-6px;left:50%;margin-left:-5px;border-top:0;border-left:0}.popover-arrow-bottom{top:-6px;left:50%;margin-left:-5px;border-bottom:0;border-right:0}.popover-arrow-left{right:-6px;top:50%;margin-top:-5px;border-bottom:0;border-left:0}.popover-arrow-right{left:-6px;top:50%;margin-top:-5px;border-top:0;border-right:0}:host-context(body.dark) .popover-panel{background:#1b2e4b!important;border-color:#253b5c!important;color:#e0e6ed!important;box-shadow:0 4px 16px #00000080!important}:host-context(.dark) .popover-panel{background:#1b2e4b!important;border-color:#253b5c!important;color:#e0e6ed!important}\n"] }]
2981
3483
  }], ctorParameters: () => [], propDecorators: { placement: [{ type: i0.Input, args: [{ isSignal: true, alias: "placement", required: false }] }], showArrow: [{ type: i0.Input, args: [{ isSignal: true, alias: "showArrow", required: false }] }], offset: [{ type: i0.Input, args: [{ isSignal: true, alias: "offset", required: false }] }], autoFlip: [{ type: i0.Input, args: [{ isSignal: true, alias: "autoFlip", required: false }] }], trigger: [{ type: i0.Input, args: [{ isSignal: true, alias: "trigger", required: false }] }], isOpen: [{ type: i0.Input, args: [{ isSignal: true, alias: "isOpen", required: false }] }, { type: i0.Output, args: ["isOpenChange"] }], onOpened: [{ type: i0.Output, args: ["onOpened"] }], onHidden: [{ type: i0.Output, args: ["onHidden"] }], _panelRef: [{ type: i0.ViewChild, args: ['panelRef', { isSignal: true }] }] } });
2982
3484
 
3485
+ /**
3486
+ * Renders an accessible pagination bar for navigating a paged data set.
3487
+ *
3488
+ * Supports both **controlled** and **uncontrolled** modes:
3489
+ * - **Controlled**: provide the `page` input and update it in response to
3490
+ * the `pageChange` output. The component reflects the external value.
3491
+ * - **Uncontrolled**: omit `page`. The component manages its own active
3492
+ * page via an internal signal, initialized from `defaultPage`.
3493
+ *
3494
+ * When the total page count exceeds 5, a 5-item sliding window is rendered
3495
+ * centered on the active page. Navigation buttons are rendered inside a
3496
+ * `<nav aria-label="pagination">` landmark. Each button receives
3497
+ * `aria-current="page"` (active) or `aria-disabled="true"` (boundary/disabled)
3498
+ * as appropriate.
3499
+ *
3500
+ * @example
3501
+ * ```html
3502
+ * <!-- Uncontrolled -->
3503
+ * <ls-pagination [count]="20" (pageChange)="onPage($event)" />
3504
+ *
3505
+ * <!-- Controlled -->
3506
+ * <ls-pagination
3507
+ * [count]="20"
3508
+ * [page]="currentPage"
3509
+ * (pageChange)="currentPage = $event" />
3510
+ * ```
3511
+ */
2983
3512
  class PaginationComponent {
2984
3513
  constructor() {
3514
+ /**
3515
+ * Total number of pages in the data set.
3516
+ *
3517
+ * Must be a positive integer ≥ 1. Determines both the upper boundary for
3518
+ * navigation and the page window calculation.
3519
+ *
3520
+ * @default 1
3521
+ */
2985
3522
  this.count = input(1, ...(ngDevMode ? [{ debugName: "count" }] : []));
3523
+ /**
3524
+ * Active page index in controlled mode (1-based).
3525
+ *
3526
+ * When provided, the component reflects this value and does not maintain
3527
+ * internal page state. The host is responsible for updating this input in
3528
+ * response to `pageChange` emissions. Pass `undefined` to switch to
3529
+ * uncontrolled mode.
3530
+ *
3531
+ * @default undefined
3532
+ */
2986
3533
  this.page = input(undefined, ...(ngDevMode ? [{ debugName: "page" }] : []));
3534
+ /**
3535
+ * Initial active page used in uncontrolled mode (1-based).
3536
+ *
3537
+ * Consumed once on `ngOnInit`. Has no effect when `page` is provided.
3538
+ *
3539
+ * @default 1
3540
+ */
2987
3541
  this.defaultPage = input(1, ...(ngDevMode ? [{ debugName: "defaultPage" }] : []));
3542
+ /**
3543
+ * Color token applied to the active page item and button hover states.
3544
+ *
3545
+ * @default 'primary'
3546
+ */
2988
3547
  this.color = input('primary', ...(ngDevMode ? [{ debugName: "color" }] : []));
3548
+ /**
3549
+ * Visual rendering style of page number items and navigation buttons.
3550
+ *
3551
+ * @default 'outlined'
3552
+ */
2989
3553
  this.variant = input('outlined', ...(ngDevMode ? [{ debugName: "variant" }] : []));
3554
+ /**
3555
+ * Border-radius style applied uniformly to all buttons in the bar.
3556
+ *
3557
+ * @default 'rounded'
3558
+ */
2990
3559
  this.shape = input('rounded', ...(ngDevMode ? [{ debugName: "shape" }] : []));
3560
+ /**
3561
+ * Physical dimensions (height, font size, padding) of all buttons.
3562
+ *
3563
+ * @default 'medium'
3564
+ */
2991
3565
  this.size = input('medium', ...(ngDevMode ? [{ debugName: "size" }] : []));
3566
+ /**
3567
+ * Disables all buttons in the pagination bar.
3568
+ *
3569
+ * When `true`, every button receives `disabled` and
3570
+ * `aria-disabled="true"`. The `pageChange` output will not emit.
3571
+ *
3572
+ * @default false
3573
+ */
2992
3574
  this.disabled = input(false, ...(ngDevMode ? [{ debugName: "disabled" }] : []));
3575
+ /**
3576
+ * Renders a "go to first page" button before the previous-page button.
3577
+ *
3578
+ * The button is automatically disabled and receives `aria-disabled="true"`
3579
+ * when the active page is already the first page.
3580
+ *
3581
+ * @default false
3582
+ */
2993
3583
  this.showFirstButton = input(false, ...(ngDevMode ? [{ debugName: "showFirstButton" }] : []));
3584
+ /**
3585
+ * Renders a "go to last page" button after the next-page button.
3586
+ *
3587
+ * The button is automatically disabled and receives `aria-disabled="true"`
3588
+ * when the active page is already the last page.
3589
+ *
3590
+ * @default false
3591
+ */
2994
3592
  this.showLastButton = input(false, ...(ngDevMode ? [{ debugName: "showLastButton" }] : []));
3593
+ /**
3594
+ * Hides the previous-page navigation button.
3595
+ *
3596
+ * @default false
3597
+ */
2995
3598
  this.hidePrevButton = input(false, ...(ngDevMode ? [{ debugName: "hidePrevButton" }] : []));
3599
+ /**
3600
+ * Hides the next-page navigation button.
3601
+ *
3602
+ * @default false
3603
+ */
2996
3604
  this.hideNextButton = input(false, ...(ngDevMode ? [{ debugName: "hideNextButton" }] : []));
3605
+ /**
3606
+ * Emits the target page number (1-based) when the user activates any
3607
+ * page item or navigation button.
3608
+ *
3609
+ * Does NOT emit when `disabled` is `true` or when the user clicks a
3610
+ * boundary button that is already at its limit (first/last page).
3611
+ * In controlled mode, the host must update the `page` input in response
3612
+ * to this event to reflect the navigation in the UI.
3613
+ */
2997
3614
  this.pageChange = output();
2998
3615
  this._internalPage = signal(1, ...(ngDevMode ? [{ debugName: "_internalPage" }] : []));
2999
3616
  this.activePage = computed(() => this.page() ?? this._internalPage(), ...(ngDevMode ? [{ debugName: "activePage" }] : []));
@@ -3209,11 +3826,105 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.2", ngImpor
3209
3826
  `, styles: [":host{display:contents}.pg-icon-left{transform:rotate(90deg)}.pg-icon-right{transform:rotate(-90deg)}.pg-list{display:inline-flex;align-items:center;gap:.25rem;list-style:none;margin:0;padding:0}.pg-item{display:inline-flex;align-items:center;justify-content:center;font-weight:600;cursor:pointer;transition:all var(--ls-transition-duration) ease;border:2px solid transparent;background:none;outline:none;font-family:var(--ls-font-family);line-height:1;-webkit-user-select:none;user-select:none}.pg-item-sm{padding:.375rem .625rem;font-size:.75rem;min-width:1.75rem;height:1.75rem}.pg-item-md{padding:.5rem .875rem;font-size:.875rem;min-width:2.25rem;height:2.25rem}.pg-item-lg{padding:.625rem 1.25rem;font-size:1rem;min-width:2.75rem;height:2.75rem}.pg-item-rounded{border-radius:var(--ls-border-radius-md)}.pg-item-circular{border-radius:var(--ls-border-radius-full);padding-inline:0}.pg-item-circular.pg-item-sm{width:1.75rem}.pg-item-circular.pg-item-md{width:2.25rem}.pg-item-circular.pg-item-lg{width:2.75rem}.pg-item-disabled,.pg-item[disabled]{cursor:not-allowed;opacity:.6}.pg-item-solid-primary{background-color:var(--ls-color-white-light);color:var(--ls-color-dark)}.pg-item-solid-primary:not([disabled]):hover{background-color:var(--ls-color-primary);color:var(--ls-color-white)}.pg-item-solid-primary.pg-item-active{background-color:var(--ls-color-primary);color:var(--ls-color-white)}.pg-item-solid-secondary{background-color:var(--ls-color-white-light);color:var(--ls-color-dark)}.pg-item-solid-secondary:not([disabled]):hover{background-color:var(--ls-color-secondary);color:var(--ls-color-white)}.pg-item-solid-secondary.pg-item-active{background-color:var(--ls-color-secondary);color:var(--ls-color-white)}.pg-item-solid-default{background-color:var(--ls-color-white-light);color:var(--ls-color-dark)}.pg-item-solid-default:not([disabled]):hover{background-color:var(--ls-color-dark);color:var(--ls-color-white)}.pg-item-solid-default.pg-item-active{background-color:var(--ls-color-dark);color:var(--ls-color-white)}.pg-item-outlined-primary{background-color:transparent;border-color:var(--ls-color-white-light);color:var(--ls-color-dark)}.pg-item-outlined-primary:not([disabled]):hover{border-color:var(--ls-color-primary);color:var(--ls-color-primary)}.pg-item-outlined-primary.pg-item-active{border-color:var(--ls-color-primary);color:var(--ls-color-primary)}.pg-item-outlined-secondary{background-color:transparent;border-color:var(--ls-color-white-light);color:var(--ls-color-dark)}.pg-item-outlined-secondary:not([disabled]):hover{border-color:var(--ls-color-secondary);color:var(--ls-color-secondary)}.pg-item-outlined-secondary.pg-item-active{border-color:var(--ls-color-secondary);color:var(--ls-color-secondary)}.pg-item-outlined-default{background-color:transparent;border-color:var(--ls-color-white-light);color:var(--ls-color-dark)}.pg-item-outlined-default:not([disabled]):hover{border-color:var(--ls-color-dark);color:var(--ls-color-dark)}.pg-item-outlined-default.pg-item-active{border-color:var(--ls-color-dark);color:var(--ls-color-dark)}.pg-item-text-primary{background-color:transparent;border-color:transparent;color:var(--ls-color-white-dark)}.pg-item-text-primary:not([disabled]):hover{background-color:#4361ee1a;color:var(--ls-color-primary)}.pg-item-text-primary.pg-item-active{color:var(--ls-color-primary)}.pg-item-text-secondary{background-color:transparent;border-color:transparent;color:var(--ls-color-white-dark)}.pg-item-text-secondary:not([disabled]):hover{background-color:#805dca1a;color:var(--ls-color-secondary)}.pg-item-text-secondary.pg-item-active{color:var(--ls-color-secondary)}.pg-item-text-default{background-color:transparent;border-color:transparent;color:var(--ls-color-white-dark)}.pg-item-text-default:not([disabled]):hover{background-color:#3b3f5c1a;color:var(--ls-color-dark)}.pg-item-text-default.pg-item-active{color:var(--ls-color-dark)}body.dark .pg-item-solid-primary,body.dark .pg-item-solid-secondary,body.dark .pg-item-solid-default{background-color:#191e3a;color:var(--ls-color-white-light)}body.dark .pg-item-solid-primary:not([disabled]):hover,body.dark .pg-item-solid-primary.pg-item-active{background-color:var(--ls-color-primary);color:var(--ls-color-white-light)}body.dark .pg-item-solid-secondary:not([disabled]):hover,body.dark .pg-item-solid-secondary.pg-item-active{background-color:var(--ls-color-secondary);color:var(--ls-color-white-light)}body.dark .pg-item-solid-default:not([disabled]):hover,body.dark .pg-item-solid-default.pg-item-active{background-color:var(--ls-color-dark);color:var(--ls-color-white-light)}body.dark .pg-item-outlined-primary,body.dark .pg-item-outlined-secondary,body.dark .pg-item-outlined-default{border-color:#191e3a;color:var(--ls-color-white-light)}body.dark .pg-item-outlined-primary:not([disabled]):hover,body.dark .pg-item-outlined-primary.pg-item-active{border-color:var(--ls-color-primary);color:var(--ls-color-white-light)}body.dark .pg-item-outlined-secondary:not([disabled]):hover,body.dark .pg-item-outlined-secondary.pg-item-active{border-color:var(--ls-color-secondary);color:var(--ls-color-white-light)}body.dark .pg-item-outlined-default:not([disabled]):hover,body.dark .pg-item-outlined-default.pg-item-active{border-color:var(--ls-color-dark);color:var(--ls-color-white-light)}body.dark .pg-item-text-primary,body.dark .pg-item-text-secondary,body.dark .pg-item-text-default{color:var(--ls-color-white-dark)}body.dark .pg-item-text-primary:not([disabled]):hover,body.dark .pg-item-text-primary.pg-item-active{color:var(--ls-color-primary)}body.dark .pg-item-text-secondary:not([disabled]):hover,body.dark .pg-item-text-secondary.pg-item-active{color:var(--ls-color-secondary)}body.dark .pg-item-text-default:not([disabled]):hover,body.dark .pg-item-text-default.pg-item-active{color:var(--ls-color-white-light)}\n"] }]
3210
3827
  }], propDecorators: { count: [{ type: i0.Input, args: [{ isSignal: true, alias: "count", required: false }] }], page: [{ type: i0.Input, args: [{ isSignal: true, alias: "page", required: false }] }], defaultPage: [{ type: i0.Input, args: [{ isSignal: true, alias: "defaultPage", required: false }] }], color: [{ type: i0.Input, args: [{ isSignal: true, alias: "color", required: false }] }], variant: [{ type: i0.Input, args: [{ isSignal: true, alias: "variant", required: false }] }], shape: [{ type: i0.Input, args: [{ isSignal: true, alias: "shape", required: false }] }], size: [{ type: i0.Input, args: [{ isSignal: true, alias: "size", required: false }] }], disabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "disabled", required: false }] }], showFirstButton: [{ type: i0.Input, args: [{ isSignal: true, alias: "showFirstButton", required: false }] }], showLastButton: [{ type: i0.Input, args: [{ isSignal: true, alias: "showLastButton", required: false }] }], hidePrevButton: [{ type: i0.Input, args: [{ isSignal: true, alias: "hidePrevButton", required: false }] }], hideNextButton: [{ type: i0.Input, args: [{ isSignal: true, alias: "hideNextButton", required: false }] }], pageChange: [{ type: i0.Output, args: ["pageChange"] }] } });
3211
3828
 
3829
+ class BreadcrumbComponent {
3830
+ constructor() {
3831
+ this.items = input.required(...(ngDevMode ? [{ debugName: "items" }] : []));
3832
+ this.variant = input('default', ...(ngDevMode ? [{ debugName: "variant" }] : []));
3833
+ this.separator = input('/', ...(ngDevMode ? [{ debugName: "separator" }] : []));
3834
+ this.color = input('gray', ...(ngDevMode ? [{ debugName: "color" }] : [])); // El nuevo input de color
3835
+ // Lógica para el color dinámico
3836
+ this._colorStyle = computed(() => {
3837
+ const c = this.color();
3838
+ const value = c === 'primary' ? 'var(--ls-color-primary)' :
3839
+ c === 'secondary' ? 'var(--ls-color-secondary)' : c;
3840
+ return { '--ls-breadcrumb-main-color': value };
3841
+ }, ...(ngDevMode ? [{ debugName: "_colorStyle" }] : []));
3842
+ this._classes = computed(() => {
3843
+ return `ls-breadcrumb ls-breadcrumb--${this.variant()}`;
3844
+ }, ...(ngDevMode ? [{ debugName: "_classes" }] : []));
3845
+ this._isTemplateSeparator = computed(() => {
3846
+ return this.separator() instanceof TemplateRef;
3847
+ }, ...(ngDevMode ? [{ debugName: "_isTemplateSeparator" }] : []));
3848
+ }
3849
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.2", ngImport: i0, type: BreadcrumbComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
3850
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.1.2", type: BreadcrumbComponent, isStandalone: true, selector: "ls-breadcrumb", inputs: { items: { classPropertyName: "items", publicName: "items", isSignal: true, isRequired: true, transformFunction: null }, variant: { classPropertyName: "variant", publicName: "variant", isSignal: true, isRequired: false, transformFunction: null }, separator: { classPropertyName: "separator", publicName: "separator", isSignal: true, isRequired: false, transformFunction: null }, color: { classPropertyName: "color", publicName: "color", isSignal: true, isRequired: false, transformFunction: null } }, ngImport: i0, template: `
3851
+ <nav aria-label="Breadcrumb" [style]="_colorStyle()">
3852
+ <ol [class]="_classes()">
3853
+ @for (item of items(); track item.label; let isLast = $last) {
3854
+ <li class="ls-breadcrumb-item" [class.ls-breadcrumb-item--active]="isLast">
3855
+
3856
+ @if (item.icon) {
3857
+ <ls-icon
3858
+ [name]="$any(item.icon)"
3859
+ iconClass="ls-breadcrumb-icon" />
3860
+ }
3861
+
3862
+ @if (isLast) {
3863
+ <span aria-current="page">{{ item.label }}</span>
3864
+ } @else if (item.url) {
3865
+ <a [href]="item.url">{{ item.label }}</a>
3866
+ } @else {
3867
+ <span>{{ item.label }}</span>
3868
+ }
3869
+ </li>
3870
+
3871
+ @if (!isLast && variant() !== 'arrowed') {
3872
+ <li class="ls-breadcrumb-separator" aria-hidden="true">
3873
+ @if (_isTemplateSeparator()) {
3874
+ <ng-container *ngTemplateOutlet="$any(separator())" />
3875
+ } @else {
3876
+ {{ separator() }}
3877
+ }
3878
+ </li>
3879
+ }
3880
+ }
3881
+ </ol>
3882
+ </nav>
3883
+ `, isInline: true, styles: [":host{display:block;--ls-breadcrumb-main-color: #4361ee}.ls-breadcrumb{display:flex;align-items:center;flex-wrap:wrap;list-style:none;margin:0;padding:0;font-family:var(--ls-font-family, sans-serif);font-size:.875rem}.ls-breadcrumb-item{display:inline-flex;align-items:center;gap:.5rem;color:#6c757d}.ls-breadcrumb-item a{color:inherit;text-decoration:none!important;transition:color .2s;border:none}.ls-breadcrumb-item a:hover{text-decoration:none!important;color:var(--ls-breadcrumb-main-color)}.ls-breadcrumb-icon{width:1.15rem;height:1.15rem;display:flex;align-items:center;justify-content:center;color:currentColor}.ls-breadcrumb-icon svg{width:100%;height:100%;display:block}.ls-breadcrumb-separator{margin:0 .5rem;color:#888ea8;-webkit-user-select:none;user-select:none}.ls-breadcrumb--default .ls-breadcrumb-item--active{color:#000;font-weight:600}.ls-breadcrumb--dotted .ls-breadcrumb-separator{font-size:0;display:flex;align-items:center}.ls-breadcrumb--dotted .ls-breadcrumb-separator:before{content:\"\";width:6px;height:6px;background:var(--ls-breadcrumb-main-color);border-radius:50%;display:inline-block}.ls-breadcrumb--dotted .ls-breadcrumb-item--active{color:#000;font-weight:600}.ls-breadcrumb--arrowed{gap:0}.ls-breadcrumb--arrowed .ls-breadcrumb-item{position:relative;background:#e9ecef;padding:.5rem 1rem .5rem 1.5rem;margin-left:-10px;clip-path:polygon(calc(100% - 12px) 0%,100% 50%,calc(100% - 12px) 100%,0% 100%,12px 50%,0% 0%);filter:drop-shadow(1px 0 1px rgba(0,0,0,.08));color:#515365}.ls-breadcrumb--arrowed .ls-breadcrumb-item:first-child{margin-left:0;padding-left:.75rem;clip-path:polygon(calc(100% - 12px) 0%,100% 50%,calc(100% - 12px) 100%,0% 100%,0% 0%);border-radius:4px 0 0 4px}.ls-breadcrumb--arrowed .ls-breadcrumb-item:last-child{padding-right:1.25rem;clip-path:polygon(100% 0%,100% 100%,0% 100%,12px 50%,0% 0%);border-radius:0 4px 4px 0}.ls-breadcrumb--arrowed .ls-breadcrumb-item--active{background:var(--ls-breadcrumb-main-color)!important;color:#fff!important;z-index:10!important}.ls-breadcrumb--arrowed .ls-breadcrumb-item:nth-child(1){z-index:5}.ls-breadcrumb--arrowed .ls-breadcrumb-item:nth-child(2){z-index:4}.ls-breadcrumb--arrowed .ls-breadcrumb-item:nth-child(3){z-index:3}body.dark .ls-breadcrumb-item{color:#bfc9d4}body.dark .ls-breadcrumb--default .ls-breadcrumb-item--active,body.dark .ls-breadcrumb--dotted .ls-breadcrumb-item--active{color:#fff!important}body.dark .ls-breadcrumb--arrowed .ls-breadcrumb-item:not(.ls-breadcrumb-item--active){background:#1b2e4b!important;color:#e0e6ed!important}body.dark .ls-breadcrumb-separator{color:#3b3f5c}\n"], dependencies: [{ kind: "directive", type: NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "component", type: IconComponent, selector: "ls-icon", inputs: ["name", "iconClass"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
3884
+ }
3885
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.2", ngImport: i0, type: BreadcrumbComponent, decorators: [{
3886
+ type: Component,
3887
+ args: [{ changeDetection: ChangeDetectionStrategy.OnPush, imports: [NgTemplateOutlet, IconComponent], selector: 'ls-breadcrumb', standalone: true, template: `
3888
+ <nav aria-label="Breadcrumb" [style]="_colorStyle()">
3889
+ <ol [class]="_classes()">
3890
+ @for (item of items(); track item.label; let isLast = $last) {
3891
+ <li class="ls-breadcrumb-item" [class.ls-breadcrumb-item--active]="isLast">
3892
+
3893
+ @if (item.icon) {
3894
+ <ls-icon
3895
+ [name]="$any(item.icon)"
3896
+ iconClass="ls-breadcrumb-icon" />
3897
+ }
3898
+
3899
+ @if (isLast) {
3900
+ <span aria-current="page">{{ item.label }}</span>
3901
+ } @else if (item.url) {
3902
+ <a [href]="item.url">{{ item.label }}</a>
3903
+ } @else {
3904
+ <span>{{ item.label }}</span>
3905
+ }
3906
+ </li>
3907
+
3908
+ @if (!isLast && variant() !== 'arrowed') {
3909
+ <li class="ls-breadcrumb-separator" aria-hidden="true">
3910
+ @if (_isTemplateSeparator()) {
3911
+ <ng-container *ngTemplateOutlet="$any(separator())" />
3912
+ } @else {
3913
+ {{ separator() }}
3914
+ }
3915
+ </li>
3916
+ }
3917
+ }
3918
+ </ol>
3919
+ </nav>
3920
+ `, styles: [":host{display:block;--ls-breadcrumb-main-color: #4361ee}.ls-breadcrumb{display:flex;align-items:center;flex-wrap:wrap;list-style:none;margin:0;padding:0;font-family:var(--ls-font-family, sans-serif);font-size:.875rem}.ls-breadcrumb-item{display:inline-flex;align-items:center;gap:.5rem;color:#6c757d}.ls-breadcrumb-item a{color:inherit;text-decoration:none!important;transition:color .2s;border:none}.ls-breadcrumb-item a:hover{text-decoration:none!important;color:var(--ls-breadcrumb-main-color)}.ls-breadcrumb-icon{width:1.15rem;height:1.15rem;display:flex;align-items:center;justify-content:center;color:currentColor}.ls-breadcrumb-icon svg{width:100%;height:100%;display:block}.ls-breadcrumb-separator{margin:0 .5rem;color:#888ea8;-webkit-user-select:none;user-select:none}.ls-breadcrumb--default .ls-breadcrumb-item--active{color:#000;font-weight:600}.ls-breadcrumb--dotted .ls-breadcrumb-separator{font-size:0;display:flex;align-items:center}.ls-breadcrumb--dotted .ls-breadcrumb-separator:before{content:\"\";width:6px;height:6px;background:var(--ls-breadcrumb-main-color);border-radius:50%;display:inline-block}.ls-breadcrumb--dotted .ls-breadcrumb-item--active{color:#000;font-weight:600}.ls-breadcrumb--arrowed{gap:0}.ls-breadcrumb--arrowed .ls-breadcrumb-item{position:relative;background:#e9ecef;padding:.5rem 1rem .5rem 1.5rem;margin-left:-10px;clip-path:polygon(calc(100% - 12px) 0%,100% 50%,calc(100% - 12px) 100%,0% 100%,12px 50%,0% 0%);filter:drop-shadow(1px 0 1px rgba(0,0,0,.08));color:#515365}.ls-breadcrumb--arrowed .ls-breadcrumb-item:first-child{margin-left:0;padding-left:.75rem;clip-path:polygon(calc(100% - 12px) 0%,100% 50%,calc(100% - 12px) 100%,0% 100%,0% 0%);border-radius:4px 0 0 4px}.ls-breadcrumb--arrowed .ls-breadcrumb-item:last-child{padding-right:1.25rem;clip-path:polygon(100% 0%,100% 100%,0% 100%,12px 50%,0% 0%);border-radius:0 4px 4px 0}.ls-breadcrumb--arrowed .ls-breadcrumb-item--active{background:var(--ls-breadcrumb-main-color)!important;color:#fff!important;z-index:10!important}.ls-breadcrumb--arrowed .ls-breadcrumb-item:nth-child(1){z-index:5}.ls-breadcrumb--arrowed .ls-breadcrumb-item:nth-child(2){z-index:4}.ls-breadcrumb--arrowed .ls-breadcrumb-item:nth-child(3){z-index:3}body.dark .ls-breadcrumb-item{color:#bfc9d4}body.dark .ls-breadcrumb--default .ls-breadcrumb-item--active,body.dark .ls-breadcrumb--dotted .ls-breadcrumb-item--active{color:#fff!important}body.dark .ls-breadcrumb--arrowed .ls-breadcrumb-item:not(.ls-breadcrumb-item--active){background:#1b2e4b!important;color:#e0e6ed!important}body.dark .ls-breadcrumb-separator{color:#3b3f5c}\n"] }]
3921
+ }], propDecorators: { items: [{ type: i0.Input, args: [{ isSignal: true, alias: "items", required: true }] }], variant: [{ type: i0.Input, args: [{ isSignal: true, alias: "variant", required: false }] }], separator: [{ type: i0.Input, args: [{ isSignal: true, alias: "separator", required: false }] }], color: [{ type: i0.Input, args: [{ isSignal: true, alias: "color", required: false }] }] } });
3922
+
3212
3923
  // @lumston/ds-angular — public API surface
3213
3924
 
3214
3925
  /**
3215
3926
  * Generated bundle index. Do not edit.
3216
3927
  */
3217
3928
 
3218
- export { AlertComponent, AvatarComponent, AvatarGroupComponent, BadgeComponent, ButtonComponent, CheckboxComponent, ChipComponent, DropdownComponent, ICON_REGISTRY, IconButtonComponent, IconComponent, LinkComponent, LoaderComponent, LogoComponent, LsDropdownContentDirective, ModalActionsComponent, ModalComponent, ModalContentComponent, ModalStackService, ModalTitleComponent, PaginationComponent, PopoverComponent, ProgressBarComponent, RadioButtonComponent, SliderComponent, SwitchComponent, TagComponent, TextComponent, TooltipComponent };
3929
+ export { AlertComponent, AvatarComponent, AvatarGroupComponent, BadgeComponent, BreadcrumbComponent, ButtonComponent, CheckboxComponent, ChipComponent, DropdownComponent, ICON_REGISTRY, IconButtonComponent, IconComponent, LinkComponent, LoaderComponent, LogoComponent, LsDropdownContentDirective, MenuComponent, MenuItemComponent, MenuTriggerDirective, ModalActionsComponent, ModalComponent, ModalContentComponent, ModalStackService, ModalTitleComponent, PaginationComponent, PopoverComponent, ProgressBarComponent, RadioButtonComponent, SliderComponent, SwitchComponent, TagComponent, TextComponent, TooltipComponent };
3219
3930
  //# sourceMappingURL=lumston-ds-angular.mjs.map