ps-helix 6.0.0 → 6.0.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +6 -6
- package/fesm2022/ps-helix.mjs +277 -50
- package/fesm2022/ps-helix.mjs.map +1 -1
- package/package.json +1 -1
- package/src/lib/styles/tokens/effects.tokens.css +39 -38
- package/types/ps-helix.d.ts +83 -14
package/fesm2022/ps-helix.mjs
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import * as i0 from '@angular/core';
|
|
2
|
-
import { input, output, computed, ChangeDetectionStrategy, Component, model, inject, ElementRef, signal, PLATFORM_ID, ViewEncapsulation, InjectionToken, viewChild, effect, Injectable, DestroyRef, Directive,
|
|
2
|
+
import { input, output, computed, ChangeDetectionStrategy, Component, model, inject, ElementRef, signal, PLATFORM_ID, ViewEncapsulation, InjectionToken, viewChild, effect, Injectable, DestroyRef, Directive, ViewContainerRef, ChangeDetectorRef, ViewChild, Injector, afterNextRender, HostListener, Renderer2, contentChild, linkedSignal, EventEmitter, Output, Input, contentChildren } from '@angular/core';
|
|
3
3
|
import * as i1 from '@angular/common';
|
|
4
4
|
import { CommonModule, DOCUMENT, isPlatformBrowser, NgTemplateOutlet } from '@angular/common';
|
|
5
5
|
import { NG_VALUE_ACCESSOR, FormsModule } from '@angular/forms';
|
|
@@ -1516,6 +1516,112 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.4", ngImpor
|
|
|
1516
1516
|
}]
|
|
1517
1517
|
}], ctorParameters: () => [], propDecorators: { pshClickOutside: [{ type: i0.Output, args: ["pshClickOutside"] }] } });
|
|
1518
1518
|
|
|
1519
|
+
/**
|
|
1520
|
+
* Teleports a `TemplateRef` into a single body-level overlay layer so popover
|
|
1521
|
+
* panels (select / dropdown / menu…) escape any ancestor `overflow`, `transform`
|
|
1522
|
+
* or stacking context and can layer above modals.
|
|
1523
|
+
*
|
|
1524
|
+
* A lightweight, CDK-free "manual portal": the embedded view is created from the
|
|
1525
|
+
* consumer's `ViewContainerRef` (so it stays in that component's change-detection
|
|
1526
|
+
* tree and keeps its bindings reactive), then its root nodes are moved into the
|
|
1527
|
+
* shared `.psh-overlay-layer`. The layer is `position: fixed; inset: 0;
|
|
1528
|
+
* pointer-events: none` at `z-index: var(--z-index-overlay)`; panels re-enable
|
|
1529
|
+
* pointer events. The layer is created lazily and removed once empty.
|
|
1530
|
+
*/
|
|
1531
|
+
class PshPortalService {
|
|
1532
|
+
constructor() {
|
|
1533
|
+
this.document = inject(DOCUMENT);
|
|
1534
|
+
this.layer = null;
|
|
1535
|
+
this.count = 0;
|
|
1536
|
+
}
|
|
1537
|
+
/** Teleports `tpl` into the overlay layer and returns a handle to control it. */
|
|
1538
|
+
attach(tpl, vcr) {
|
|
1539
|
+
const layer = this.ensureLayer();
|
|
1540
|
+
const viewRef = vcr.createEmbeddedView(tpl);
|
|
1541
|
+
viewRef.detectChanges();
|
|
1542
|
+
const nodes = viewRef.rootNodes;
|
|
1543
|
+
const panel = (nodes.find((n) => n instanceof HTMLElement) ??
|
|
1544
|
+
nodes[0]);
|
|
1545
|
+
nodes.forEach(node => layer.appendChild(node));
|
|
1546
|
+
this.count++;
|
|
1547
|
+
return {
|
|
1548
|
+
panel,
|
|
1549
|
+
position: (anchor, side, gap) => this.position(panel, anchor, side, gap),
|
|
1550
|
+
positionByPlacement: (anchor, placement, gap) => this.positionByPlacement(panel, anchor, placement, gap),
|
|
1551
|
+
detach: () => this.detach(viewRef),
|
|
1552
|
+
};
|
|
1553
|
+
}
|
|
1554
|
+
position(panel, anchor, side, gap) {
|
|
1555
|
+
const view = this.document.defaultView;
|
|
1556
|
+
if (!view)
|
|
1557
|
+
return;
|
|
1558
|
+
const rect = anchor.getBoundingClientRect();
|
|
1559
|
+
const style = panel.style;
|
|
1560
|
+
style.position = 'fixed';
|
|
1561
|
+
style.left = `${rect.left}px`;
|
|
1562
|
+
style.width = `${rect.width}px`;
|
|
1563
|
+
if (side === 'top') {
|
|
1564
|
+
const height = panel.offsetHeight;
|
|
1565
|
+
style.top = `${Math.max(gap, rect.top - height - gap)}px`;
|
|
1566
|
+
style.maxHeight = `${Math.max(0, rect.top - gap * 2)}px`;
|
|
1567
|
+
}
|
|
1568
|
+
else {
|
|
1569
|
+
style.top = `${rect.bottom + gap}px`;
|
|
1570
|
+
style.maxHeight = `${Math.max(0, view.innerHeight - rect.bottom - gap * 2)}px`;
|
|
1571
|
+
}
|
|
1572
|
+
}
|
|
1573
|
+
positionByPlacement(panel, anchor, placement, gap) {
|
|
1574
|
+
const view = this.document.defaultView;
|
|
1575
|
+
if (!view)
|
|
1576
|
+
return;
|
|
1577
|
+
const rect = anchor.getBoundingClientRect();
|
|
1578
|
+
const [side, align] = placement.split('-');
|
|
1579
|
+
const style = panel.style;
|
|
1580
|
+
style.position = 'fixed';
|
|
1581
|
+
if (side === 'top') {
|
|
1582
|
+
const height = panel.offsetHeight;
|
|
1583
|
+
style.top = `${Math.max(gap, rect.top - height - gap)}px`;
|
|
1584
|
+
style.maxHeight = `${Math.max(0, rect.top - gap * 2)}px`;
|
|
1585
|
+
}
|
|
1586
|
+
else {
|
|
1587
|
+
style.top = `${rect.bottom + gap}px`;
|
|
1588
|
+
style.maxHeight = `${Math.max(0, view.innerHeight - rect.bottom - gap * 2)}px`;
|
|
1589
|
+
}
|
|
1590
|
+
// Content-sized menu: anchor the start/end edge to the trigger.
|
|
1591
|
+
if (align === 'end') {
|
|
1592
|
+
style.left = `${Math.max(0, rect.right - panel.offsetWidth)}px`;
|
|
1593
|
+
}
|
|
1594
|
+
else {
|
|
1595
|
+
style.left = `${rect.left}px`;
|
|
1596
|
+
}
|
|
1597
|
+
}
|
|
1598
|
+
detach(viewRef) {
|
|
1599
|
+
viewRef.destroy();
|
|
1600
|
+
this.count = Math.max(0, this.count - 1);
|
|
1601
|
+
if (this.count === 0 && this.layer) {
|
|
1602
|
+
this.layer.remove();
|
|
1603
|
+
this.layer = null;
|
|
1604
|
+
}
|
|
1605
|
+
}
|
|
1606
|
+
ensureLayer() {
|
|
1607
|
+
if (this.layer)
|
|
1608
|
+
return this.layer;
|
|
1609
|
+
const layer = this.document.createElement('div');
|
|
1610
|
+
layer.className = 'psh-overlay-layer';
|
|
1611
|
+
layer.style.cssText =
|
|
1612
|
+
'position:fixed;inset:0;z-index:var(--z-index-overlay);pointer-events:none;';
|
|
1613
|
+
this.document.body.appendChild(layer);
|
|
1614
|
+
this.layer = layer;
|
|
1615
|
+
return layer;
|
|
1616
|
+
}
|
|
1617
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.4", ngImport: i0, type: PshPortalService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
|
|
1618
|
+
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "22.0.4", ngImport: i0, type: PshPortalService, providedIn: 'root' }); }
|
|
1619
|
+
}
|
|
1620
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.4", ngImport: i0, type: PshPortalService, decorators: [{
|
|
1621
|
+
type: Injectable,
|
|
1622
|
+
args: [{ providedIn: 'root' }]
|
|
1623
|
+
}] });
|
|
1624
|
+
|
|
1519
1625
|
class PshDropdownComponent {
|
|
1520
1626
|
getState() {
|
|
1521
1627
|
if (this.disabled())
|
|
@@ -1528,7 +1634,14 @@ class PshDropdownComponent {
|
|
|
1528
1634
|
this.elementRef = inject(ElementRef);
|
|
1529
1635
|
this.isBrowser = isPlatformBrowser(inject(PLATFORM_ID));
|
|
1530
1636
|
this.overlayPosition = inject(PshOverlayPositionService);
|
|
1531
|
-
this.
|
|
1637
|
+
this.portal = inject(PshPortalService);
|
|
1638
|
+
this.viewContainer = inject(ViewContainerRef);
|
|
1639
|
+
// The menu is teleported to a body-level overlay layer on open so it escapes
|
|
1640
|
+
// any ancestor overflow / stacking context (a modal body, a scrollable card…).
|
|
1641
|
+
this.menuTpl = viewChild('menuTpl', /* @ts-ignore */
|
|
1642
|
+
...(ngDevMode ? [{ debugName: "menuTpl" }] : /* istanbul ignore next */ []));
|
|
1643
|
+
this.portalRef = null;
|
|
1644
|
+
this.repositionHandler = () => this.reposition();
|
|
1532
1645
|
// Regular inputs
|
|
1533
1646
|
this.appearance = input('filled', /* @ts-ignore */
|
|
1534
1647
|
...(ngDevMode ? [{ debugName: "appearance" }] : /* istanbul ignore next */ []));
|
|
@@ -1584,33 +1697,54 @@ class PshDropdownComponent {
|
|
|
1584
1697
|
...(ngDevMode ? [{ debugName: "computedAriaLabel" }] : /* istanbul ignore next */ []));
|
|
1585
1698
|
this.state = computed(() => this.getState(), /* @ts-ignore */
|
|
1586
1699
|
...(ngDevMode ? [{ debugName: "state" }] : /* istanbul ignore next */ []));
|
|
1587
|
-
// Close on outside click
|
|
1700
|
+
// Close on outside click. Clicks inside the menu are stopped at the menu
|
|
1701
|
+
// (stopPropagation); as a safety net for the teleported panel we also ignore
|
|
1702
|
+
// clicks whose target is inside it here.
|
|
1588
1703
|
const clickOutside = inject(PshClickOutsideDirective);
|
|
1589
|
-
const sub = clickOutside.pshClickOutside.subscribe(
|
|
1590
|
-
|
|
1591
|
-
|
|
1592
|
-
|
|
1593
|
-
|
|
1594
|
-
|
|
1595
|
-
|
|
1596
|
-
|
|
1597
|
-
|
|
1598
|
-
this.resolvedPlacement.set(this.placement());
|
|
1599
|
-
}
|
|
1704
|
+
const sub = clickOutside.pshClickOutside.subscribe(event => {
|
|
1705
|
+
const target = event.target;
|
|
1706
|
+
if (target && this.portalRef?.panel.contains(target))
|
|
1707
|
+
return;
|
|
1708
|
+
this.close();
|
|
1709
|
+
});
|
|
1710
|
+
inject(DestroyRef).onDestroy(() => {
|
|
1711
|
+
sub.unsubscribe();
|
|
1712
|
+
this.closePanel();
|
|
1600
1713
|
});
|
|
1601
1714
|
}
|
|
1715
|
+
openPanel() {
|
|
1716
|
+
if (!this.isBrowser || this.portalRef)
|
|
1717
|
+
return;
|
|
1718
|
+
const tpl = this.menuTpl();
|
|
1719
|
+
if (!tpl)
|
|
1720
|
+
return;
|
|
1721
|
+
this.portalRef = this.portal.attach(tpl, this.viewContainer);
|
|
1722
|
+
this.reposition();
|
|
1723
|
+
const view = this.elementRef.nativeElement.ownerDocument.defaultView;
|
|
1724
|
+
view?.addEventListener('scroll', this.repositionHandler, true);
|
|
1725
|
+
view?.addEventListener('resize', this.repositionHandler);
|
|
1726
|
+
}
|
|
1727
|
+
closePanel() {
|
|
1728
|
+
const view = this.elementRef.nativeElement.ownerDocument.defaultView;
|
|
1729
|
+
view?.removeEventListener('scroll', this.repositionHandler, true);
|
|
1730
|
+
view?.removeEventListener('resize', this.repositionHandler);
|
|
1731
|
+
this.portalRef?.detach();
|
|
1732
|
+
this.portalRef = null;
|
|
1733
|
+
this.resolvedPlacement.set(this.placement());
|
|
1734
|
+
}
|
|
1602
1735
|
reposition() {
|
|
1603
|
-
if (!this.
|
|
1736
|
+
if (!this.portalRef)
|
|
1604
1737
|
return;
|
|
1605
1738
|
const host = this.elementRef.nativeElement;
|
|
1606
1739
|
const trigger = host.querySelector('.dropdown-trigger');
|
|
1607
|
-
const menu = host.querySelector('.dropdown-menu');
|
|
1608
1740
|
if (!trigger)
|
|
1609
1741
|
return;
|
|
1610
|
-
this.
|
|
1611
|
-
overlayHeight:
|
|
1612
|
-
overlayWidth:
|
|
1613
|
-
})
|
|
1742
|
+
const placement = this.overlayPosition.flipPlacement(trigger, this.placement(), {
|
|
1743
|
+
overlayHeight: this.portalRef.panel.offsetHeight,
|
|
1744
|
+
overlayWidth: this.portalRef.panel.offsetWidth,
|
|
1745
|
+
});
|
|
1746
|
+
this.resolvedPlacement.set(placement);
|
|
1747
|
+
this.portalRef.positionByPlacement(trigger, placement, 4);
|
|
1614
1748
|
}
|
|
1615
1749
|
toggleDropdown() {
|
|
1616
1750
|
if (!this.disabled()) {
|
|
@@ -1619,9 +1753,11 @@ class PshDropdownComponent {
|
|
|
1619
1753
|
if (this.isOpen()) {
|
|
1620
1754
|
this.focusedItemIndex.set(0);
|
|
1621
1755
|
this.opened.emit();
|
|
1756
|
+
this.openPanel();
|
|
1622
1757
|
}
|
|
1623
1758
|
else {
|
|
1624
1759
|
this.focusedItemIndex.set(-1);
|
|
1760
|
+
this.closePanel();
|
|
1625
1761
|
this.closed.emit();
|
|
1626
1762
|
}
|
|
1627
1763
|
}
|
|
@@ -1637,6 +1773,7 @@ class PshDropdownComponent {
|
|
|
1637
1773
|
if (this.isOpen()) {
|
|
1638
1774
|
this.isOpenSignal.set(false);
|
|
1639
1775
|
this.focusedItemIndex.set(-1);
|
|
1776
|
+
this.closePanel();
|
|
1640
1777
|
this.closed.emit();
|
|
1641
1778
|
}
|
|
1642
1779
|
}
|
|
@@ -1771,17 +1908,17 @@ class PshDropdownComponent {
|
|
|
1771
1908
|
}
|
|
1772
1909
|
focusItemAtIndex(index) {
|
|
1773
1910
|
setTimeout(() => {
|
|
1774
|
-
const item = this.
|
|
1911
|
+
const item = this.portalRef?.panel.querySelector(`[data-dropdown-item-index="${index}"]`);
|
|
1775
1912
|
item?.focus();
|
|
1776
1913
|
});
|
|
1777
1914
|
}
|
|
1778
1915
|
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.4", ngImport: i0, type: PshDropdownComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
|
|
1779
|
-
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.0.4", type: PshDropdownComponent, isStandalone: true, selector: "psh-dropdown", inputs: { appearance: { classPropertyName: "appearance", publicName: "appearance", isSignal: true, isRequired: false, transformFunction: null }, variant: { classPropertyName: "variant", publicName: "variant", isSignal: true, isRequired: false, transformFunction: null }, size: { classPropertyName: "size", publicName: "size", isSignal: true, isRequired: false, transformFunction: null }, placement: { classPropertyName: "placement", publicName: "placement", isSignal: true, isRequired: false, transformFunction: null }, items: { classPropertyName: "items", publicName: "items", isSignal: true, isRequired: false, transformFunction: null }, label: { classPropertyName: "label", publicName: "label", isSignal: true, isRequired: false, transformFunction: null }, icon: { classPropertyName: "icon", publicName: "icon", isSignal: true, isRequired: false, transformFunction: null }, ariaLabel: { classPropertyName: "ariaLabel", publicName: "ariaLabel", isSignal: true, isRequired: false, transformFunction: null }, iconOnly: { classPropertyName: "iconOnly", publicName: "iconOnly", isSignal: true, isRequired: false, transformFunction: null }, iconOnlyText: { classPropertyName: "iconOnlyText", publicName: "iconOnlyText", isSignal: true, isRequired: false, transformFunction: null }, disabled: { classPropertyName: "disabled", publicName: "disabled", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { disabled: "disabledChange", selected: "selected", opened: "opened", closed: "closed" }, hostDirectives: [{ directive: PshClickOutsideDirective }], ngImport: i0, template: "<div\r\n class=\"dropdown-container\"\r\n [class]=\"size()\"\r\n [class.open]=\"isOpen()\"\r\n [class.disabled]=\"disabled()\"\r\n [class.icon-only]=\"isIconOnly()\"\r\n [attr.data-state]=\"state()\"\r\n>\r\n <button\r\n class=\"dropdown-trigger\"\r\n [class]=\"appearance()\"\r\n [class.primary]=\"variant() === 'primary'\"\r\n [class.secondary]=\"variant() === 'secondary'\"\r\n [class.success]=\"variant() === 'success'\"\r\n [class.warning]=\"variant() === 'warning'\"\r\n [class.danger]=\"variant() === 'danger'\"\r\n (click)=\"toggleDropdown()\"\r\n (keydown)=\"handleTriggerKeyDown($event)\"\r\n [attr.aria-expanded]=\"isOpen()\"\r\n [attr.aria-disabled]=\"disabled()\"\r\n [attr.aria-label]=\"computedAriaLabel()\"\r\n [attr.aria-haspopup]=\"'menu'\"\r\n type=\"button\"\r\n [disabled]=\"disabled()\"\r\n >\r\n <span class=\"trigger-content\">\r\n @if (isIconOnly()) {\r\n <i class=\"ph ph-{{ icon() }}\" aria-hidden=\"true\"></i>\r\n } @else {\r\n @if (icon()) {\r\n <i class=\"ph ph-{{ icon() }}\" aria-hidden=\"true\"></i>\r\n }\r\n <ng-content select=\"[dropdown-trigger]\">\r\n @if (label()) {\r\n {{ label() }}\r\n }\r\n </ng-content>\r\n <i\r\n class=\"ph ph-caret-down trigger-arrow\"\r\n [class.open]=\"isOpen()\"\r\n aria-hidden=\"true\"\r\n ></i>\r\n }\r\n </span>\r\n </button>\r\n\r\n @if (isOpen()) {\r\n <!-- stopPropagation only (keeps clicks inside the menu from closing it); not a user interaction. -->\r\n <!-- eslint-disable-next-line @angular-eslint/template/click-events-have-key-events, @angular-eslint/template/interactive-supports-focus -->\r\n <div\r\n class=\"dropdown-menu\"\r\n [class]=\"resolvedPlacement()\"\r\n role=\"menu\"\r\n (click)=\"$event.stopPropagation()\"\r\n >\r\n <ng-content select=\"[dropdown-menu]\">\r\n @for (item of items(); track item.value; let i = $index) {\r\n <button\r\n type=\"button\"\r\n class=\"dropdown-item\"\r\n [class.disabled]=\"item.disabled\"\r\n [class.active]=\"selectedItem() === item\"\r\n [attr.data-dropdown-item-index]=\"i\"\r\n (click)=\"selectItem(item)\"\r\n (keydown)=\"handleItemKeyDown($event, item, i)\"\r\n role=\"menuitem\"\r\n [attr.aria-disabled]=\"item.disabled\"\r\n [disabled]=\"item.disabled\"\r\n [attr.tabindex]=\"item.disabled ? -1 : 0\"\r\n >\r\n @if (item.icon) {\r\n <i class=\"ph ph-{{ item.icon }}\" aria-hidden=\"true\"></i>\r\n }\r\n <span class=\"item-label\">{{ item.content }}</span>\r\n </button>\r\n }\r\n </ng-content>\r\n </div>\r\n }\r\n</div>", styles: [".dropdown-container{position:relative;display:inline-block}.dropdown-trigger{display:inline-flex;align-items:center;justify-content:center;height:var(--height-input-md);padding:0 var(--spacing-lg);border:none;border-radius:var(--border-radius);font-weight:var(--font-weight-medium);font-size:var(--font-size-base);font-family:var(--font-family);line-height:var(--line-height-normal);cursor:pointer;transition:all var(--animation-duration-fast) var(--animation-easing-smooth);min-width:7.5rem;background:transparent;position:relative;overflow:hidden;white-space:nowrap;text-overflow:ellipsis}.trigger-content{display:flex;align-items:center;gap:var(--spacing-sm);position:relative;z-index:1;line-height:1}.trigger-arrow{transition:transform var(--animation-duration-fast) var(--animation-easing-smooth);margin-left:var(--spacing-sm)}.trigger-arrow.open{transform:rotate(180deg)}.dropdown-trigger.primary{color:var(--primary-color)}.dropdown-trigger.secondary{color:var(--secondary-color)}.dropdown-trigger.success{color:var(--success-color)}.dropdown-trigger.warning{color:var(--warning-color)}.dropdown-trigger.danger{color:var(--danger-color)}.dropdown-trigger.filled{background-color:currentColor}.dropdown-trigger.filled.primary{background:var(--primary-gradient);color:var(--text-on-primary)}.dropdown-trigger.filled.primary .trigger-content{color:var(--text-on-primary)}.dropdown-trigger.filled.secondary .trigger-content{color:var(--text-on-secondary)}.dropdown-trigger.filled.success .trigger-content{color:var(--text-on-success)}.dropdown-trigger.filled.warning .trigger-content{color:var(--text-on-warning)}.dropdown-trigger.filled.danger .trigger-content{color:var(--text-on-danger)}.dropdown-trigger.filled.primary:hover:not(.disabled){background:var(--primary-gradient-hover)}.dropdown-trigger.filled.secondary:hover:not(.disabled){background-color:var(--secondary-color-light)}.dropdown-trigger.filled.success:hover:not(.disabled){background-color:var(--green-400)}.dropdown-trigger.filled.warning:hover:not(.disabled){background-color:var(--orange-400)}.dropdown-trigger.filled.danger:hover:not(.disabled){background-color:var(--red-400)}.dropdown-trigger.outline{background:transparent;border:var(--border-width-2) solid currentColor}.dropdown-trigger.outline .trigger-content{color:inherit}.dropdown-trigger.outline:hover:not(.disabled){background:currentColor}.dropdown-trigger.outline.primary:hover:not(.disabled) .trigger-content{color:var(--text-on-primary)}.dropdown-trigger.outline.secondary:hover:not(.disabled) .trigger-content{color:var(--text-on-secondary)}.dropdown-trigger.outline.success:hover:not(.disabled) .trigger-content{color:var(--text-on-success)}.dropdown-trigger.outline.warning:hover:not(.disabled) .trigger-content{color:var(--text-on-warning)}.dropdown-trigger.outline.danger:hover:not(.disabled) .trigger-content{color:var(--text-on-danger)}.dropdown-trigger.text{background:transparent}.dropdown-trigger.text:hover:not(.disabled){background:var(--surface-hover)}.dropdown-container.small .dropdown-trigger{height:var(--height-input-sm);padding:0 var(--spacing-md);font-size:var(--font-size-sm);min-width:6rem}.dropdown-container.large .dropdown-trigger{height:var(--height-input-lg);padding:0 var(--spacing-lg);font-size:var(--font-size-lg);min-width:8.75rem}.dropdown-container.icon-only .dropdown-trigger{min-width:0;width:var(--height-input-md);padding:0}.dropdown-container.icon-only.small .dropdown-trigger{width:var(--height-input-sm);padding:0;min-width:0}.dropdown-container.icon-only.large .dropdown-trigger{width:var(--height-input-lg);padding:0;min-width:0}.dropdown-container.icon-only .trigger-content{gap:0;justify-content:center}.dropdown-container.icon-only .trigger-content i{margin:0}.dropdown-menu{position:absolute;min-width:12.5rem;background:var(--surface-card);border:var(--border-width-1) solid var(--surface-border);border-radius:var(--border-radius);box-shadow:var(--shadow-lg);z-index:var(--z-index-dropdown);margin-top:var(--spacing-xs);animation:fadeIn var(--animation-duration-fast) var(--animation-easing-smooth);overflow:hidden}.dropdown-menu ::ng-deep [dropdown-menu]{background:transparent;padding:0;margin:0}.dropdown-menu ::ng-deep .dropdown-item{display:flex;align-items:center;gap:var(--spacing-sm);width:100%;padding:var(--spacing-sm) var(--spacing-md);border:none;background:transparent;color:var(--text-color);font-family:var(--font-family);font-size:var(--font-size-base);text-align:left;cursor:pointer;transition:all var(--animation-duration-fast) var(--animation-easing-smooth)}.dropdown-menu ::ng-deep .dropdown-item:hover:not(.disabled){background:var(--surface-hover)}.dropdown-menu ::ng-deep .dropdown-item.active{color:var(--primary-color);background:rgba(var(--primary-color-rgb),.1)}.dropdown-menu ::ng-deep .dropdown-item.disabled{opacity:.6;cursor:not-allowed}.dropdown-menu ::ng-deep .dropdown-item i{font-size:var(--icon-size-md);color:inherit}.dropdown-menu.bottom-start{top:100%;left:0}.dropdown-menu.bottom-end{top:100%;right:0}.dropdown-menu.top-start{bottom:100%;left:0}.dropdown-menu.top-end{bottom:100%;right:0}.dropdown-item{display:flex;align-items:center;gap:var(--spacing-sm);width:100%;padding:var(--spacing-sm) var(--spacing-md);border:none;background:transparent;color:var(--text-color);font-family:var(--font-family);font-size:var(--font-size-base);text-align:left;cursor:pointer;transition:all var(--animation-duration-fast) var(--animation-easing-smooth)}.dropdown-item:hover:not(.disabled){background:var(--surface-hover)}.dropdown-item.active{color:var(--primary-color);background:rgba(var(--primary-color-rgb),.1)}.dropdown-item.disabled{opacity:.6;cursor:not-allowed}.item-check{margin-left:auto;color:var(--primary-color)}.dropdown-trigger:focus-visible{outline:none;box-shadow:0 0 0 var(--focus-ring-width) var(--focus-ring-color)}.dropdown-trigger:active:not(.disabled){transform:translateY(.0625rem)}.dropdown-container.disabled{opacity:.6;cursor:not-allowed}.dropdown-container.disabled .dropdown-trigger{pointer-events:none}@keyframes fadeIn{0%{opacity:0;transform:translateY(calc(-1 * var(--animation-distance-sm)))}to{opacity:1;transform:translateY(0)}}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
|
|
1916
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.0.4", type: PshDropdownComponent, isStandalone: true, selector: "psh-dropdown", inputs: { appearance: { classPropertyName: "appearance", publicName: "appearance", isSignal: true, isRequired: false, transformFunction: null }, variant: { classPropertyName: "variant", publicName: "variant", isSignal: true, isRequired: false, transformFunction: null }, size: { classPropertyName: "size", publicName: "size", isSignal: true, isRequired: false, transformFunction: null }, placement: { classPropertyName: "placement", publicName: "placement", isSignal: true, isRequired: false, transformFunction: null }, items: { classPropertyName: "items", publicName: "items", isSignal: true, isRequired: false, transformFunction: null }, label: { classPropertyName: "label", publicName: "label", isSignal: true, isRequired: false, transformFunction: null }, icon: { classPropertyName: "icon", publicName: "icon", isSignal: true, isRequired: false, transformFunction: null }, ariaLabel: { classPropertyName: "ariaLabel", publicName: "ariaLabel", isSignal: true, isRequired: false, transformFunction: null }, iconOnly: { classPropertyName: "iconOnly", publicName: "iconOnly", isSignal: true, isRequired: false, transformFunction: null }, iconOnlyText: { classPropertyName: "iconOnlyText", publicName: "iconOnlyText", isSignal: true, isRequired: false, transformFunction: null }, disabled: { classPropertyName: "disabled", publicName: "disabled", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { disabled: "disabledChange", selected: "selected", opened: "opened", closed: "closed" }, viewQueries: [{ propertyName: "menuTpl", first: true, predicate: ["menuTpl"], descendants: true, isSignal: true }], hostDirectives: [{ directive: PshClickOutsideDirective }], ngImport: i0, template: "<div\r\n class=\"dropdown-container\"\r\n [class]=\"size()\"\r\n [class.open]=\"isOpen()\"\r\n [class.disabled]=\"disabled()\"\r\n [class.icon-only]=\"isIconOnly()\"\r\n [attr.data-state]=\"state()\"\r\n>\r\n <button\r\n class=\"dropdown-trigger\"\r\n [class]=\"appearance()\"\r\n [class.primary]=\"variant() === 'primary'\"\r\n [class.secondary]=\"variant() === 'secondary'\"\r\n [class.success]=\"variant() === 'success'\"\r\n [class.warning]=\"variant() === 'warning'\"\r\n [class.danger]=\"variant() === 'danger'\"\r\n (click)=\"toggleDropdown()\"\r\n (keydown)=\"handleTriggerKeyDown($event)\"\r\n [attr.aria-expanded]=\"isOpen()\"\r\n [attr.aria-disabled]=\"disabled()\"\r\n [attr.aria-label]=\"computedAriaLabel()\"\r\n [attr.aria-haspopup]=\"'menu'\"\r\n type=\"button\"\r\n [disabled]=\"disabled()\"\r\n >\r\n <span class=\"trigger-content\">\r\n @if (isIconOnly()) {\r\n <i class=\"ph ph-{{ icon() }}\" aria-hidden=\"true\"></i>\r\n } @else {\r\n @if (icon()) {\r\n <i class=\"ph ph-{{ icon() }}\" aria-hidden=\"true\"></i>\r\n }\r\n <ng-content select=\"[dropdown-trigger]\">\r\n @if (label()) {\r\n {{ label() }}\r\n }\r\n </ng-content>\r\n <i\r\n class=\"ph ph-caret-down trigger-arrow\"\r\n [class.open]=\"isOpen()\"\r\n aria-hidden=\"true\"\r\n ></i>\r\n }\r\n </span>\r\n </button>\r\n\r\n <ng-template #menuTpl>\r\n <!-- stopPropagation only (keeps clicks inside the menu from closing it); not a user interaction. -->\r\n <!-- eslint-disable-next-line @angular-eslint/template/click-events-have-key-events, @angular-eslint/template/interactive-supports-focus -->\r\n <div\r\n class=\"dropdown-menu\"\r\n [class]=\"resolvedPlacement()\"\r\n role=\"menu\"\r\n (click)=\"$event.stopPropagation()\"\r\n >\r\n <ng-content select=\"[dropdown-menu]\">\r\n @for (item of items(); track item.value; let i = $index) {\r\n <button\r\n type=\"button\"\r\n class=\"dropdown-item\"\r\n [class.disabled]=\"item.disabled\"\r\n [class.active]=\"selectedItem() === item\"\r\n [attr.data-dropdown-item-index]=\"i\"\r\n (click)=\"selectItem(item)\"\r\n (keydown)=\"handleItemKeyDown($event, item, i)\"\r\n role=\"menuitem\"\r\n [attr.aria-disabled]=\"item.disabled\"\r\n [disabled]=\"item.disabled\"\r\n [attr.tabindex]=\"item.disabled ? -1 : 0\"\r\n >\r\n @if (item.icon) {\r\n <i class=\"ph ph-{{ item.icon }}\" aria-hidden=\"true\"></i>\r\n }\r\n <span class=\"item-label\">{{ item.content }}</span>\r\n </button>\r\n }\r\n </ng-content>\r\n </div>\r\n </ng-template>\r\n</div>", styles: [".dropdown-container{position:relative;display:inline-block}.dropdown-trigger{display:inline-flex;align-items:center;justify-content:center;height:var(--height-input-md);padding:0 var(--spacing-lg);border:none;border-radius:var(--border-radius);font-weight:var(--font-weight-medium);font-size:var(--font-size-base);font-family:var(--font-family);line-height:var(--line-height-normal);cursor:pointer;transition:all var(--animation-duration-fast) var(--animation-easing-smooth);min-width:7.5rem;background:transparent;position:relative;overflow:hidden;white-space:nowrap;text-overflow:ellipsis}.trigger-content{display:flex;align-items:center;gap:var(--spacing-sm);position:relative;z-index:1;line-height:1}.trigger-arrow{transition:transform var(--animation-duration-fast) var(--animation-easing-smooth);margin-left:var(--spacing-sm)}.trigger-arrow.open{transform:rotate(180deg)}.dropdown-trigger.primary{color:var(--primary-color)}.dropdown-trigger.secondary{color:var(--secondary-color)}.dropdown-trigger.success{color:var(--success-color)}.dropdown-trigger.warning{color:var(--warning-color)}.dropdown-trigger.danger{color:var(--danger-color)}.dropdown-trigger.filled{background-color:currentColor}.dropdown-trigger.filled.primary{background:var(--primary-gradient);color:var(--text-on-primary)}.dropdown-trigger.filled.primary .trigger-content{color:var(--text-on-primary)}.dropdown-trigger.filled.secondary .trigger-content{color:var(--text-on-secondary)}.dropdown-trigger.filled.success .trigger-content{color:var(--text-on-success)}.dropdown-trigger.filled.warning .trigger-content{color:var(--text-on-warning)}.dropdown-trigger.filled.danger .trigger-content{color:var(--text-on-danger)}.dropdown-trigger.filled.primary:hover:not(.disabled){background:var(--primary-gradient-hover)}.dropdown-trigger.filled.secondary:hover:not(.disabled){background-color:var(--secondary-color-light)}.dropdown-trigger.filled.success:hover:not(.disabled){background-color:var(--green-400)}.dropdown-trigger.filled.warning:hover:not(.disabled){background-color:var(--orange-400)}.dropdown-trigger.filled.danger:hover:not(.disabled){background-color:var(--red-400)}.dropdown-trigger.outline{background:transparent;border:var(--border-width-2) solid currentColor}.dropdown-trigger.outline .trigger-content{color:inherit}.dropdown-trigger.outline:hover:not(.disabled){background:currentColor}.dropdown-trigger.outline.primary:hover:not(.disabled) .trigger-content{color:var(--text-on-primary)}.dropdown-trigger.outline.secondary:hover:not(.disabled) .trigger-content{color:var(--text-on-secondary)}.dropdown-trigger.outline.success:hover:not(.disabled) .trigger-content{color:var(--text-on-success)}.dropdown-trigger.outline.warning:hover:not(.disabled) .trigger-content{color:var(--text-on-warning)}.dropdown-trigger.outline.danger:hover:not(.disabled) .trigger-content{color:var(--text-on-danger)}.dropdown-trigger.text{background:transparent}.dropdown-trigger.text:hover:not(.disabled){background:var(--surface-hover)}.dropdown-container.small .dropdown-trigger{height:var(--height-input-sm);padding:0 var(--spacing-md);font-size:var(--font-size-sm);min-width:6rem}.dropdown-container.large .dropdown-trigger{height:var(--height-input-lg);padding:0 var(--spacing-lg);font-size:var(--font-size-lg);min-width:8.75rem}.dropdown-container.icon-only .dropdown-trigger{min-width:0;width:var(--height-input-md);padding:0}.dropdown-container.icon-only.small .dropdown-trigger{width:var(--height-input-sm);padding:0;min-width:0}.dropdown-container.icon-only.large .dropdown-trigger{width:var(--height-input-lg);padding:0;min-width:0}.dropdown-container.icon-only .trigger-content{gap:0;justify-content:center}.dropdown-container.icon-only .trigger-content i{margin:0}.dropdown-menu{min-width:12.5rem;background:var(--surface-card);border:var(--border-width-1) solid var(--surface-border);border-radius:var(--border-radius);box-shadow:var(--shadow-lg);pointer-events:auto;animation:fadeIn var(--animation-duration-fast) var(--animation-easing-smooth);overflow:hidden}.dropdown-menu ::ng-deep [dropdown-menu]{background:transparent;padding:0;margin:0}.dropdown-menu ::ng-deep .dropdown-item{display:flex;align-items:center;gap:var(--spacing-sm);width:100%;padding:var(--spacing-sm) var(--spacing-md);border:none;background:transparent;color:var(--text-color);font-family:var(--font-family);font-size:var(--font-size-base);text-align:left;cursor:pointer;transition:all var(--animation-duration-fast) var(--animation-easing-smooth)}.dropdown-menu ::ng-deep .dropdown-item:hover:not(.disabled){background:var(--surface-hover)}.dropdown-menu ::ng-deep .dropdown-item.active{color:var(--primary-color);background:rgba(var(--primary-color-rgb),.1)}.dropdown-menu ::ng-deep .dropdown-item.disabled{opacity:.6;cursor:not-allowed}.dropdown-menu ::ng-deep .dropdown-item i{font-size:var(--icon-size-md);color:inherit}.dropdown-item{display:flex;align-items:center;gap:var(--spacing-sm);width:100%;padding:var(--spacing-sm) var(--spacing-md);border:none;background:transparent;color:var(--text-color);font-family:var(--font-family);font-size:var(--font-size-base);text-align:left;cursor:pointer;transition:all var(--animation-duration-fast) var(--animation-easing-smooth)}.dropdown-item:hover:not(.disabled){background:var(--surface-hover)}.dropdown-item.active{color:var(--primary-color);background:rgba(var(--primary-color-rgb),.1)}.dropdown-item.disabled{opacity:.6;cursor:not-allowed}.item-check{margin-left:auto;color:var(--primary-color)}.dropdown-trigger:focus-visible{outline:none;box-shadow:0 0 0 var(--focus-ring-width) var(--focus-ring-color)}.dropdown-trigger:active:not(.disabled){transform:translateY(.0625rem)}.dropdown-container.disabled{opacity:.6;cursor:not-allowed}.dropdown-container.disabled .dropdown-trigger{pointer-events:none}@keyframes fadeIn{0%{opacity:0;transform:translateY(calc(-1 * var(--animation-distance-sm)))}to{opacity:1;transform:translateY(0)}}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
|
|
1780
1917
|
}
|
|
1781
1918
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.4", ngImport: i0, type: PshDropdownComponent, decorators: [{
|
|
1782
1919
|
type: Component,
|
|
1783
|
-
args: [{ selector: 'psh-dropdown', imports: [CommonModule], changeDetection: ChangeDetectionStrategy.OnPush, hostDirectives: [PshClickOutsideDirective], template: "<div\r\n class=\"dropdown-container\"\r\n [class]=\"size()\"\r\n [class.open]=\"isOpen()\"\r\n [class.disabled]=\"disabled()\"\r\n [class.icon-only]=\"isIconOnly()\"\r\n [attr.data-state]=\"state()\"\r\n>\r\n <button\r\n class=\"dropdown-trigger\"\r\n [class]=\"appearance()\"\r\n [class.primary]=\"variant() === 'primary'\"\r\n [class.secondary]=\"variant() === 'secondary'\"\r\n [class.success]=\"variant() === 'success'\"\r\n [class.warning]=\"variant() === 'warning'\"\r\n [class.danger]=\"variant() === 'danger'\"\r\n (click)=\"toggleDropdown()\"\r\n (keydown)=\"handleTriggerKeyDown($event)\"\r\n [attr.aria-expanded]=\"isOpen()\"\r\n [attr.aria-disabled]=\"disabled()\"\r\n [attr.aria-label]=\"computedAriaLabel()\"\r\n [attr.aria-haspopup]=\"'menu'\"\r\n type=\"button\"\r\n [disabled]=\"disabled()\"\r\n >\r\n <span class=\"trigger-content\">\r\n @if (isIconOnly()) {\r\n <i class=\"ph ph-{{ icon() }}\" aria-hidden=\"true\"></i>\r\n } @else {\r\n @if (icon()) {\r\n <i class=\"ph ph-{{ icon() }}\" aria-hidden=\"true\"></i>\r\n }\r\n <ng-content select=\"[dropdown-trigger]\">\r\n @if (label()) {\r\n {{ label() }}\r\n }\r\n </ng-content>\r\n <i\r\n class=\"ph ph-caret-down trigger-arrow\"\r\n [class.open]=\"isOpen()\"\r\n aria-hidden=\"true\"\r\n ></i>\r\n }\r\n </span>\r\n </button>\r\n\r\n
|
|
1784
|
-
}], ctorParameters: () => [], propDecorators: { appearance: [{ type: i0.Input, args: [{ isSignal: true, alias: "appearance", required: false }] }], variant: [{ type: i0.Input, args: [{ isSignal: true, alias: "variant", required: false }] }], size: [{ type: i0.Input, args: [{ isSignal: true, alias: "size", required: false }] }], placement: [{ type: i0.Input, args: [{ isSignal: true, alias: "placement", required: false }] }], items: [{ type: i0.Input, args: [{ isSignal: true, alias: "items", required: false }] }], label: [{ type: i0.Input, args: [{ isSignal: true, alias: "label", required: false }] }], icon: [{ type: i0.Input, args: [{ isSignal: true, alias: "icon", required: false }] }], ariaLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "ariaLabel", required: false }] }], iconOnly: [{ type: i0.Input, args: [{ isSignal: true, alias: "iconOnly", required: false }] }], iconOnlyText: [{ type: i0.Input, args: [{ isSignal: true, alias: "iconOnlyText", required: false }] }], disabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "disabled", required: false }] }, { type: i0.Output, args: ["disabledChange"] }], selected: [{ type: i0.Output, args: ["selected"] }], opened: [{ type: i0.Output, args: ["opened"] }], closed: [{ type: i0.Output, args: ["closed"] }] } });
|
|
1920
|
+
args: [{ selector: 'psh-dropdown', imports: [CommonModule], changeDetection: ChangeDetectionStrategy.OnPush, hostDirectives: [PshClickOutsideDirective], template: "<div\r\n class=\"dropdown-container\"\r\n [class]=\"size()\"\r\n [class.open]=\"isOpen()\"\r\n [class.disabled]=\"disabled()\"\r\n [class.icon-only]=\"isIconOnly()\"\r\n [attr.data-state]=\"state()\"\r\n>\r\n <button\r\n class=\"dropdown-trigger\"\r\n [class]=\"appearance()\"\r\n [class.primary]=\"variant() === 'primary'\"\r\n [class.secondary]=\"variant() === 'secondary'\"\r\n [class.success]=\"variant() === 'success'\"\r\n [class.warning]=\"variant() === 'warning'\"\r\n [class.danger]=\"variant() === 'danger'\"\r\n (click)=\"toggleDropdown()\"\r\n (keydown)=\"handleTriggerKeyDown($event)\"\r\n [attr.aria-expanded]=\"isOpen()\"\r\n [attr.aria-disabled]=\"disabled()\"\r\n [attr.aria-label]=\"computedAriaLabel()\"\r\n [attr.aria-haspopup]=\"'menu'\"\r\n type=\"button\"\r\n [disabled]=\"disabled()\"\r\n >\r\n <span class=\"trigger-content\">\r\n @if (isIconOnly()) {\r\n <i class=\"ph ph-{{ icon() }}\" aria-hidden=\"true\"></i>\r\n } @else {\r\n @if (icon()) {\r\n <i class=\"ph ph-{{ icon() }}\" aria-hidden=\"true\"></i>\r\n }\r\n <ng-content select=\"[dropdown-trigger]\">\r\n @if (label()) {\r\n {{ label() }}\r\n }\r\n </ng-content>\r\n <i\r\n class=\"ph ph-caret-down trigger-arrow\"\r\n [class.open]=\"isOpen()\"\r\n aria-hidden=\"true\"\r\n ></i>\r\n }\r\n </span>\r\n </button>\r\n\r\n <ng-template #menuTpl>\r\n <!-- stopPropagation only (keeps clicks inside the menu from closing it); not a user interaction. -->\r\n <!-- eslint-disable-next-line @angular-eslint/template/click-events-have-key-events, @angular-eslint/template/interactive-supports-focus -->\r\n <div\r\n class=\"dropdown-menu\"\r\n [class]=\"resolvedPlacement()\"\r\n role=\"menu\"\r\n (click)=\"$event.stopPropagation()\"\r\n >\r\n <ng-content select=\"[dropdown-menu]\">\r\n @for (item of items(); track item.value; let i = $index) {\r\n <button\r\n type=\"button\"\r\n class=\"dropdown-item\"\r\n [class.disabled]=\"item.disabled\"\r\n [class.active]=\"selectedItem() === item\"\r\n [attr.data-dropdown-item-index]=\"i\"\r\n (click)=\"selectItem(item)\"\r\n (keydown)=\"handleItemKeyDown($event, item, i)\"\r\n role=\"menuitem\"\r\n [attr.aria-disabled]=\"item.disabled\"\r\n [disabled]=\"item.disabled\"\r\n [attr.tabindex]=\"item.disabled ? -1 : 0\"\r\n >\r\n @if (item.icon) {\r\n <i class=\"ph ph-{{ item.icon }}\" aria-hidden=\"true\"></i>\r\n }\r\n <span class=\"item-label\">{{ item.content }}</span>\r\n </button>\r\n }\r\n </ng-content>\r\n </div>\r\n </ng-template>\r\n</div>", styles: [".dropdown-container{position:relative;display:inline-block}.dropdown-trigger{display:inline-flex;align-items:center;justify-content:center;height:var(--height-input-md);padding:0 var(--spacing-lg);border:none;border-radius:var(--border-radius);font-weight:var(--font-weight-medium);font-size:var(--font-size-base);font-family:var(--font-family);line-height:var(--line-height-normal);cursor:pointer;transition:all var(--animation-duration-fast) var(--animation-easing-smooth);min-width:7.5rem;background:transparent;position:relative;overflow:hidden;white-space:nowrap;text-overflow:ellipsis}.trigger-content{display:flex;align-items:center;gap:var(--spacing-sm);position:relative;z-index:1;line-height:1}.trigger-arrow{transition:transform var(--animation-duration-fast) var(--animation-easing-smooth);margin-left:var(--spacing-sm)}.trigger-arrow.open{transform:rotate(180deg)}.dropdown-trigger.primary{color:var(--primary-color)}.dropdown-trigger.secondary{color:var(--secondary-color)}.dropdown-trigger.success{color:var(--success-color)}.dropdown-trigger.warning{color:var(--warning-color)}.dropdown-trigger.danger{color:var(--danger-color)}.dropdown-trigger.filled{background-color:currentColor}.dropdown-trigger.filled.primary{background:var(--primary-gradient);color:var(--text-on-primary)}.dropdown-trigger.filled.primary .trigger-content{color:var(--text-on-primary)}.dropdown-trigger.filled.secondary .trigger-content{color:var(--text-on-secondary)}.dropdown-trigger.filled.success .trigger-content{color:var(--text-on-success)}.dropdown-trigger.filled.warning .trigger-content{color:var(--text-on-warning)}.dropdown-trigger.filled.danger .trigger-content{color:var(--text-on-danger)}.dropdown-trigger.filled.primary:hover:not(.disabled){background:var(--primary-gradient-hover)}.dropdown-trigger.filled.secondary:hover:not(.disabled){background-color:var(--secondary-color-light)}.dropdown-trigger.filled.success:hover:not(.disabled){background-color:var(--green-400)}.dropdown-trigger.filled.warning:hover:not(.disabled){background-color:var(--orange-400)}.dropdown-trigger.filled.danger:hover:not(.disabled){background-color:var(--red-400)}.dropdown-trigger.outline{background:transparent;border:var(--border-width-2) solid currentColor}.dropdown-trigger.outline .trigger-content{color:inherit}.dropdown-trigger.outline:hover:not(.disabled){background:currentColor}.dropdown-trigger.outline.primary:hover:not(.disabled) .trigger-content{color:var(--text-on-primary)}.dropdown-trigger.outline.secondary:hover:not(.disabled) .trigger-content{color:var(--text-on-secondary)}.dropdown-trigger.outline.success:hover:not(.disabled) .trigger-content{color:var(--text-on-success)}.dropdown-trigger.outline.warning:hover:not(.disabled) .trigger-content{color:var(--text-on-warning)}.dropdown-trigger.outline.danger:hover:not(.disabled) .trigger-content{color:var(--text-on-danger)}.dropdown-trigger.text{background:transparent}.dropdown-trigger.text:hover:not(.disabled){background:var(--surface-hover)}.dropdown-container.small .dropdown-trigger{height:var(--height-input-sm);padding:0 var(--spacing-md);font-size:var(--font-size-sm);min-width:6rem}.dropdown-container.large .dropdown-trigger{height:var(--height-input-lg);padding:0 var(--spacing-lg);font-size:var(--font-size-lg);min-width:8.75rem}.dropdown-container.icon-only .dropdown-trigger{min-width:0;width:var(--height-input-md);padding:0}.dropdown-container.icon-only.small .dropdown-trigger{width:var(--height-input-sm);padding:0;min-width:0}.dropdown-container.icon-only.large .dropdown-trigger{width:var(--height-input-lg);padding:0;min-width:0}.dropdown-container.icon-only .trigger-content{gap:0;justify-content:center}.dropdown-container.icon-only .trigger-content i{margin:0}.dropdown-menu{min-width:12.5rem;background:var(--surface-card);border:var(--border-width-1) solid var(--surface-border);border-radius:var(--border-radius);box-shadow:var(--shadow-lg);pointer-events:auto;animation:fadeIn var(--animation-duration-fast) var(--animation-easing-smooth);overflow:hidden}.dropdown-menu ::ng-deep [dropdown-menu]{background:transparent;padding:0;margin:0}.dropdown-menu ::ng-deep .dropdown-item{display:flex;align-items:center;gap:var(--spacing-sm);width:100%;padding:var(--spacing-sm) var(--spacing-md);border:none;background:transparent;color:var(--text-color);font-family:var(--font-family);font-size:var(--font-size-base);text-align:left;cursor:pointer;transition:all var(--animation-duration-fast) var(--animation-easing-smooth)}.dropdown-menu ::ng-deep .dropdown-item:hover:not(.disabled){background:var(--surface-hover)}.dropdown-menu ::ng-deep .dropdown-item.active{color:var(--primary-color);background:rgba(var(--primary-color-rgb),.1)}.dropdown-menu ::ng-deep .dropdown-item.disabled{opacity:.6;cursor:not-allowed}.dropdown-menu ::ng-deep .dropdown-item i{font-size:var(--icon-size-md);color:inherit}.dropdown-item{display:flex;align-items:center;gap:var(--spacing-sm);width:100%;padding:var(--spacing-sm) var(--spacing-md);border:none;background:transparent;color:var(--text-color);font-family:var(--font-family);font-size:var(--font-size-base);text-align:left;cursor:pointer;transition:all var(--animation-duration-fast) var(--animation-easing-smooth)}.dropdown-item:hover:not(.disabled){background:var(--surface-hover)}.dropdown-item.active{color:var(--primary-color);background:rgba(var(--primary-color-rgb),.1)}.dropdown-item.disabled{opacity:.6;cursor:not-allowed}.item-check{margin-left:auto;color:var(--primary-color)}.dropdown-trigger:focus-visible{outline:none;box-shadow:0 0 0 var(--focus-ring-width) var(--focus-ring-color)}.dropdown-trigger:active:not(.disabled){transform:translateY(.0625rem)}.dropdown-container.disabled{opacity:.6;cursor:not-allowed}.dropdown-container.disabled .dropdown-trigger{pointer-events:none}@keyframes fadeIn{0%{opacity:0;transform:translateY(calc(-1 * var(--animation-distance-sm)))}to{opacity:1;transform:translateY(0)}}\n"] }]
|
|
1921
|
+
}], ctorParameters: () => [], propDecorators: { menuTpl: [{ type: i0.ViewChild, args: ['menuTpl', { isSignal: true }] }], appearance: [{ type: i0.Input, args: [{ isSignal: true, alias: "appearance", required: false }] }], variant: [{ type: i0.Input, args: [{ isSignal: true, alias: "variant", required: false }] }], size: [{ type: i0.Input, args: [{ isSignal: true, alias: "size", required: false }] }], placement: [{ type: i0.Input, args: [{ isSignal: true, alias: "placement", required: false }] }], items: [{ type: i0.Input, args: [{ isSignal: true, alias: "items", required: false }] }], label: [{ type: i0.Input, args: [{ isSignal: true, alias: "label", required: false }] }], icon: [{ type: i0.Input, args: [{ isSignal: true, alias: "icon", required: false }] }], ariaLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "ariaLabel", required: false }] }], iconOnly: [{ type: i0.Input, args: [{ isSignal: true, alias: "iconOnly", required: false }] }], iconOnlyText: [{ type: i0.Input, args: [{ isSignal: true, alias: "iconOnlyText", required: false }] }], disabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "disabled", required: false }] }, { type: i0.Output, args: ["disabledChange"] }], selected: [{ type: i0.Output, args: ["selected"] }], opened: [{ type: i0.Output, args: ["opened"] }], closed: [{ type: i0.Output, args: ["closed"] }] } });
|
|
1785
1922
|
|
|
1786
1923
|
const INPUT_LABELS = {
|
|
1787
1924
|
showPassword: 'Afficher le mot de passe',
|
|
@@ -1809,6 +1946,16 @@ class PshInputComponent {
|
|
|
1809
1946
|
this.elementRef = inject(ElementRef);
|
|
1810
1947
|
this.cdr = inject(ChangeDetectorRef);
|
|
1811
1948
|
this.destroyRef = inject(DestroyRef);
|
|
1949
|
+
this.portal = inject(PshPortalService);
|
|
1950
|
+
this.viewContainer = inject(ViewContainerRef);
|
|
1951
|
+
this.overlayPosition = inject(PshOverlayPositionService);
|
|
1952
|
+
// The autocomplete suggestions are teleported to a body-level overlay layer so
|
|
1953
|
+
// they escape any ancestor overflow / stacking context (a modal body, a
|
|
1954
|
+
// scrollable card…) instead of being clipped.
|
|
1955
|
+
this.suggestionsTpl = viewChild('suggestionsTpl', /* @ts-ignore */
|
|
1956
|
+
...(ngDevMode ? [{ debugName: "suggestionsTpl" }] : /* istanbul ignore next */ []));
|
|
1957
|
+
this.portalRef = null;
|
|
1958
|
+
this.repositionHandler = () => this.reposition();
|
|
1812
1959
|
this.inputId = `psh-input-${PshInputComponent.nextId++}`;
|
|
1813
1960
|
this.value = model('', /* @ts-ignore */
|
|
1814
1961
|
...(ngDevMode ? [{ debugName: "value" }] : /* istanbul ignore next */ []));
|
|
@@ -1898,7 +2045,49 @@ class PshInputComponent {
|
|
|
1898
2045
|
clearTimeout(this.blurTimeoutId);
|
|
1899
2046
|
if (this.debounceTimeoutId)
|
|
1900
2047
|
clearTimeout(this.debounceTimeoutId);
|
|
2048
|
+
this.closePanel();
|
|
2049
|
+
});
|
|
2050
|
+
}
|
|
2051
|
+
/** Attaches / detaches / repositions the teleported suggestions panel to match visibility. */
|
|
2052
|
+
syncPanel() {
|
|
2053
|
+
if (this.showSuggestions()) {
|
|
2054
|
+
if (this.portalRef)
|
|
2055
|
+
this.reposition();
|
|
2056
|
+
else
|
|
2057
|
+
this.openPanel();
|
|
2058
|
+
}
|
|
2059
|
+
else if (this.portalRef) {
|
|
2060
|
+
this.closePanel();
|
|
2061
|
+
}
|
|
2062
|
+
}
|
|
2063
|
+
openPanel() {
|
|
2064
|
+
const tpl = this.suggestionsTpl();
|
|
2065
|
+
if (!tpl || this.portalRef)
|
|
2066
|
+
return;
|
|
2067
|
+
this.portalRef = this.portal.attach(tpl, this.viewContainer);
|
|
2068
|
+
this.reposition();
|
|
2069
|
+
const view = this.elementRef.nativeElement.ownerDocument.defaultView;
|
|
2070
|
+
// Capture phase so inner (e.g. modal body) scrolls keep the panel aligned.
|
|
2071
|
+
view?.addEventListener('scroll', this.repositionHandler, true);
|
|
2072
|
+
view?.addEventListener('resize', this.repositionHandler);
|
|
2073
|
+
}
|
|
2074
|
+
closePanel() {
|
|
2075
|
+
const view = this.elementRef.nativeElement.ownerDocument.defaultView;
|
|
2076
|
+
view?.removeEventListener('scroll', this.repositionHandler, true);
|
|
2077
|
+
view?.removeEventListener('resize', this.repositionHandler);
|
|
2078
|
+
this.portalRef?.detach();
|
|
2079
|
+
this.portalRef = null;
|
|
2080
|
+
}
|
|
2081
|
+
reposition() {
|
|
2082
|
+
if (!this.portalRef)
|
|
2083
|
+
return;
|
|
2084
|
+
const anchor = this.elementRef.nativeElement.querySelector('.input-wrapper');
|
|
2085
|
+
if (!anchor)
|
|
2086
|
+
return;
|
|
2087
|
+
const side = this.overlayPosition.flipSide(anchor, 'bottom', {
|
|
2088
|
+
overlayHeight: this.portalRef.panel.offsetHeight,
|
|
1901
2089
|
});
|
|
2090
|
+
this.portalRef.position(anchor, side, 4);
|
|
1902
2091
|
}
|
|
1903
2092
|
writeValue(value) {
|
|
1904
2093
|
const safeValue = typeof value === 'string' ? value : '';
|
|
@@ -1936,6 +2125,7 @@ class PshInputComponent {
|
|
|
1936
2125
|
this.blurTimeoutId = setTimeout(() => {
|
|
1937
2126
|
this.suggestionsVisible.set(false);
|
|
1938
2127
|
this.focusedSuggestionIndex.set(-1);
|
|
2128
|
+
this.syncPanel();
|
|
1939
2129
|
this.blurTimeoutId = null;
|
|
1940
2130
|
}, 200);
|
|
1941
2131
|
}
|
|
@@ -1966,6 +2156,7 @@ class PshInputComponent {
|
|
|
1966
2156
|
event.preventDefault();
|
|
1967
2157
|
this.suggestionsVisible.set(false);
|
|
1968
2158
|
this.focusedSuggestionIndex.set(-1);
|
|
2159
|
+
this.syncPanel();
|
|
1969
2160
|
break;
|
|
1970
2161
|
}
|
|
1971
2162
|
}
|
|
@@ -1975,6 +2166,7 @@ class PshInputComponent {
|
|
|
1975
2166
|
this.suggestionSelect.emit(suggestion);
|
|
1976
2167
|
this.suggestionsVisible.set(false);
|
|
1977
2168
|
this.focusedSuggestionIndex.set(-1);
|
|
2169
|
+
this.syncPanel();
|
|
1978
2170
|
}
|
|
1979
2171
|
togglePasswordVisibility() {
|
|
1980
2172
|
this.passwordVisibleSignal.update(v => !v);
|
|
@@ -2009,12 +2201,14 @@ class PshInputComponent {
|
|
|
2009
2201
|
}
|
|
2010
2202
|
this.filteredSuggestionsSignal.set(results);
|
|
2011
2203
|
this.suggestionsVisible.set(results.length > 0);
|
|
2204
|
+
this.syncPanel();
|
|
2012
2205
|
}
|
|
2013
2206
|
catch (error) {
|
|
2014
2207
|
// Fail gracefully (hide stale suggestions) but surface the error so a
|
|
2015
2208
|
// failing provider is not silently swallowed during development.
|
|
2016
2209
|
this.filteredSuggestionsSignal.set([]);
|
|
2017
2210
|
this.suggestionsVisible.set(false);
|
|
2211
|
+
this.syncPanel();
|
|
2018
2212
|
console.error('[psh-input] Suggestion provider failed:', error);
|
|
2019
2213
|
}
|
|
2020
2214
|
}
|
|
@@ -2025,7 +2219,7 @@ class PshInputComponent {
|
|
|
2025
2219
|
useExisting: PshInputComponent,
|
|
2026
2220
|
multi: true
|
|
2027
2221
|
}
|
|
2028
|
-
], ngImport: i0, template: "<div class=\"input-container\">\r\n @if (showLabel()) {\r\n <!-- label[for] delegates focus to its control natively; the click handler is a convenience. -->\r\n <!-- eslint-disable-next-line @angular-eslint/template/click-events-have-key-events, @angular-eslint/template/interactive-supports-focus -->\r\n <label\r\n class=\"input-label\"\r\n [for]=\"inputId\"\r\n (click)=\"focusSelect()\"\r\n [class.required]=\"required()\"\r\n >\r\n <ng-content select=\"[input-label]\"></ng-content>\r\n @if (!hasLabelContent()) {\r\n {{ label() }}\r\n }\r\n </label>\r\n }\r\n\r\n <div class=\"input-wrapper\">\r\n @if (iconStart()) {\r\n <i class=\"ph ph-{{ iconStart() }}\" aria-hidden=\"true\"></i>\r\n }\r\n\r\n <input\r\n [id]=\"inputId\"\r\n [type]=\"effectiveType()\"\r\n [attr.placeholder]=\"placeholder()\"\r\n [attr.aria-label]=\"computedAriaLabel()\"\r\n [attr.aria-invalid]=\"!!error()\"\r\n [attr.aria-required]=\"required()\"\r\n [attr.aria-describedby]=\"error() ? 'error-message' : success() ? 'success-message' : hint() ? 'hint-message' : null\"\r\n [disabled]=\"disabled()\"\r\n [readonly]=\"readonly()\"\r\n [required]=\"required()\"\r\n [value]=\"value()\"\r\n (input)=\"handleInput($event)\"\r\n (keydown)=\"handleKeydown($event)\"\r\n (focus)=\"handleFocus()\"\r\n (blur)=\"handleBlur()\"\r\n [attr.data-state]=\"state()\"\r\n />\r\n\r\n @if (iconEnd()) {\r\n <i class=\"ph ph-{{ iconEnd() }}\" aria-hidden=\"true\"></i>\r\n }\r\n\r\n @if (type() === 'password') {\r\n <button\r\n type=\"button\"\r\n class=\"password-toggle\"\r\n (click)=\"togglePasswordVisibility()\"\r\n [attr.aria-label]=\"passwordToggleLabel()\"\r\n [disabled]=\"disabled() || readonly()\"\r\n >\r\n <i \r\n [class]=\"'ph ph-' + (passwordVisible() ? 'eye-slash' : 'eye')\"\r\n aria-hidden=\"true\"\r\n ></i>\r\n </button>\r\n }\r\n\r\n @if (loading()) {\r\n <div class=\"input-loader\" aria-hidden=\"true\">\r\n <div class=\"loader\"></div>\r\n </div>\r\n }\r\n\r\n
|
|
2222
|
+
], viewQueries: [{ propertyName: "suggestionsTpl", first: true, predicate: ["suggestionsTpl"], descendants: true, isSignal: true }], ngImport: i0, template: "<div class=\"input-container\">\r\n @if (showLabel()) {\r\n <!-- label[for] delegates focus to its control natively; the click handler is a convenience. -->\r\n <!-- eslint-disable-next-line @angular-eslint/template/click-events-have-key-events, @angular-eslint/template/interactive-supports-focus -->\r\n <label\r\n class=\"input-label\"\r\n [for]=\"inputId\"\r\n (click)=\"focusSelect()\"\r\n [class.required]=\"required()\"\r\n >\r\n <ng-content select=\"[input-label]\"></ng-content>\r\n @if (!hasLabelContent()) {\r\n {{ label() }}\r\n }\r\n </label>\r\n }\r\n\r\n <div class=\"input-wrapper\">\r\n @if (iconStart()) {\r\n <i class=\"ph ph-{{ iconStart() }}\" aria-hidden=\"true\"></i>\r\n }\r\n\r\n <input\r\n [id]=\"inputId\"\r\n [type]=\"effectiveType()\"\r\n [attr.placeholder]=\"placeholder()\"\r\n [attr.aria-label]=\"computedAriaLabel()\"\r\n [attr.aria-invalid]=\"!!error()\"\r\n [attr.aria-required]=\"required()\"\r\n [attr.aria-describedby]=\"error() ? 'error-message' : success() ? 'success-message' : hint() ? 'hint-message' : null\"\r\n [disabled]=\"disabled()\"\r\n [readonly]=\"readonly()\"\r\n [required]=\"required()\"\r\n [value]=\"value()\"\r\n (input)=\"handleInput($event)\"\r\n (keydown)=\"handleKeydown($event)\"\r\n (focus)=\"handleFocus()\"\r\n (blur)=\"handleBlur()\"\r\n [attr.data-state]=\"state()\"\r\n />\r\n\r\n @if (iconEnd()) {\r\n <i class=\"ph ph-{{ iconEnd() }}\" aria-hidden=\"true\"></i>\r\n }\r\n\r\n @if (type() === 'password') {\r\n <button\r\n type=\"button\"\r\n class=\"password-toggle\"\r\n (click)=\"togglePasswordVisibility()\"\r\n [attr.aria-label]=\"passwordToggleLabel()\"\r\n [disabled]=\"disabled() || readonly()\"\r\n >\r\n <i \r\n [class]=\"'ph ph-' + (passwordVisible() ? 'eye-slash' : 'eye')\"\r\n aria-hidden=\"true\"\r\n ></i>\r\n </button>\r\n }\r\n\r\n @if (loading()) {\r\n <div class=\"input-loader\" aria-hidden=\"true\">\r\n <div class=\"loader\"></div>\r\n </div>\r\n }\r\n\r\n <ng-template #suggestionsTpl>\r\n <div class=\"suggestions-list\" role=\"listbox\">\r\n @for (suggestion of filteredSuggestions(); track suggestion; let i = $index) {\r\n <!-- option in a listbox: keyboard is handled by the input (arrow keys + focusedSuggestionIndex). -->\r\n <!-- eslint-disable-next-line @angular-eslint/template/click-events-have-key-events, @angular-eslint/template/interactive-supports-focus -->\r\n <div\r\n class=\"suggestion-item\"\r\n [class.focused]=\"i === focusedSuggestionIndex()\"\r\n role=\"option\"\r\n [attr.aria-selected]=\"i === focusedSuggestionIndex()\"\r\n (click)=\"handleSuggestionClick(suggestion)\"\r\n (mouseenter)=\"focusedSuggestionIndex.set(i)\"\r\n >\r\n {{ suggestion }}\r\n </div>\r\n }\r\n </div>\r\n </ng-template>\r\n </div>\r\n\r\n @if (error()) {\r\n <div id=\"error-message\" class=\"input-error\" role=\"alert\">\r\n <ng-content select=\"[input-error]\">\r\n {{ error() }}\r\n </ng-content>\r\n </div>\r\n } @else if (success()) {\r\n <div id=\"success-message\" class=\"input-success\" role=\"status\">\r\n <ng-content select=\"[input-success]\">\r\n {{ success() }}\r\n </ng-content>\r\n </div>\r\n } @else if (hint()) {\r\n <div id=\"hint-message\" class=\"input-hint\">\r\n <ng-content select=\"[input-hint]\">\r\n {{ hint() }}\r\n </ng-content>\r\n </div>\r\n }\r\n</div>", styles: [":host{display:block;width:100%;max-width:18.75rem;transition:all var(--animation-duration-default) var(--animation-easing-default)}:host.full-width{max-width:none}.input-container{position:relative;width:100%;display:flex;flex-direction:column;gap:var(--form-field-gap)}.input-label{display:block;color:var(--text-color);font-size:.875rem;font-weight:500;width:100%;cursor:pointer}.input-label.required:after{content:\"*\";color:var(--danger-color);margin-left:.125rem}.input-wrapper{position:relative;display:flex;align-items:center;width:100%}input{width:100%;height:2.5rem;padding:0 1rem;font-family:inherit;font-size:1rem;color:var(--text-color);background:var(--surface-0);border:.125rem solid var(--surface-border);border-radius:var(--border-radius);transition:all var(--animation-duration-default) var(--animation-easing-default)}input:hover:not(:disabled):not(:focus){border-color:var(--primary-color)}input::placeholder{color:var(--text-color-tertiary);opacity:1}input:focus{outline:none;border-color:var(--primary-color);box-shadow:0 0 0 .125rem var(--focus-ring-color)}:host.outlined input{background:transparent}:host.filled input{background:var(--surface-ground);border:.125rem solid var(--surface-border)}:host.filled input:hover:not(:disabled):not(:focus){background:var(--surface-hover)}:host.filled input:focus{background:var(--surface-0)}:host.error input{border-color:var(--danger-color)}:host.error input:focus{box-shadow:0 0 0 .125rem var(--focus-ring-error)}:host.success input{border-color:var(--success-color)}:host.success input:focus{box-shadow:0 0 0 .125rem var(--focus-ring-success)}:host.disabled input{background:var(--surface-ground);cursor:not-allowed;opacity:var(--opacity-disabled)}:host.readonly input{background:var(--surface-ground);cursor:default}:host.small input{height:2rem;font-size:.875rem}:host.large input{height:3rem;font-size:1.125rem}:host.has-start-icon input{padding-left:2.75rem}:host.has-end-icon input{padding-right:2.75rem}.input-wrapper i{position:absolute;top:50%;transform:translateY(-50%);font-size:1.25rem;color:var(--text-color-secondary);pointer-events:none;z-index:2}.input-wrapper i:first-of-type{padding-left:1rem}.input-wrapper i:last-of-type{padding-right:1rem}.password-toggle{position:absolute;right:.5rem;top:50%;transform:translateY(-50%);width:2rem;height:2rem;background:transparent;border:none;color:var(--text-color-secondary);cursor:pointer;padding:0;border-radius:var(--border-radius);display:flex;align-items:center;justify-content:center;transition:all .2s ease;z-index:3}.password-toggle:hover:not(:disabled){background:var(--surface-hover);color:var(--text-color)}.password-toggle i{position:static;transform:none;pointer-events:auto}.input-loader{position:absolute;right:1rem;top:50%;transform:translateY(-50%);z-index:3}.loader{width:1rem;height:1rem;border:.125rem solid var(--surface-border);border-top-color:var(--primary-color);border-radius:50%;animation:spin .8s linear infinite}.suggestions-list{pointer-events:auto;background:var(--surface-0);border:.0625rem solid var(--surface-border);border-radius:var(--border-radius);box-shadow:var(--shadow-lg);overflow-y:auto}.suggestion-item{padding:.5rem 1rem;cursor:pointer;color:var(--text-color)}.suggestion-item:hover,.suggestion-item.focused{background:var(--surface-hover);color:var(--primary-color)}.input-error,.input-success,.input-hint{font-size:.875rem}.input-error{color:var(--danger-color)}.input-success{color:var(--success-color)}.input-hint{color:var(--text-color-secondary)}@keyframes spin{to{transform:rotate(360deg)}}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
|
|
2029
2223
|
}
|
|
2030
2224
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.4", ngImport: i0, type: PshInputComponent, decorators: [{
|
|
2031
2225
|
type: Component,
|
|
@@ -2049,8 +2243,8 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.4", ngImpor
|
|
|
2049
2243
|
'[class.has-end-icon]': '!!iconEnd() || type() === "password"',
|
|
2050
2244
|
'[class.outlined]': 'variant() === "outlined"',
|
|
2051
2245
|
'[class.filled]': 'variant() === "filled"',
|
|
2052
|
-
}, template: "<div class=\"input-container\">\r\n @if (showLabel()) {\r\n <!-- label[for] delegates focus to its control natively; the click handler is a convenience. -->\r\n <!-- eslint-disable-next-line @angular-eslint/template/click-events-have-key-events, @angular-eslint/template/interactive-supports-focus -->\r\n <label\r\n class=\"input-label\"\r\n [for]=\"inputId\"\r\n (click)=\"focusSelect()\"\r\n [class.required]=\"required()\"\r\n >\r\n <ng-content select=\"[input-label]\"></ng-content>\r\n @if (!hasLabelContent()) {\r\n {{ label() }}\r\n }\r\n </label>\r\n }\r\n\r\n <div class=\"input-wrapper\">\r\n @if (iconStart()) {\r\n <i class=\"ph ph-{{ iconStart() }}\" aria-hidden=\"true\"></i>\r\n }\r\n\r\n <input\r\n [id]=\"inputId\"\r\n [type]=\"effectiveType()\"\r\n [attr.placeholder]=\"placeholder()\"\r\n [attr.aria-label]=\"computedAriaLabel()\"\r\n [attr.aria-invalid]=\"!!error()\"\r\n [attr.aria-required]=\"required()\"\r\n [attr.aria-describedby]=\"error() ? 'error-message' : success() ? 'success-message' : hint() ? 'hint-message' : null\"\r\n [disabled]=\"disabled()\"\r\n [readonly]=\"readonly()\"\r\n [required]=\"required()\"\r\n [value]=\"value()\"\r\n (input)=\"handleInput($event)\"\r\n (keydown)=\"handleKeydown($event)\"\r\n (focus)=\"handleFocus()\"\r\n (blur)=\"handleBlur()\"\r\n [attr.data-state]=\"state()\"\r\n />\r\n\r\n @if (iconEnd()) {\r\n <i class=\"ph ph-{{ iconEnd() }}\" aria-hidden=\"true\"></i>\r\n }\r\n\r\n @if (type() === 'password') {\r\n <button\r\n type=\"button\"\r\n class=\"password-toggle\"\r\n (click)=\"togglePasswordVisibility()\"\r\n [attr.aria-label]=\"passwordToggleLabel()\"\r\n [disabled]=\"disabled() || readonly()\"\r\n >\r\n <i \r\n [class]=\"'ph ph-' + (passwordVisible() ? 'eye-slash' : 'eye')\"\r\n aria-hidden=\"true\"\r\n ></i>\r\n </button>\r\n }\r\n\r\n @if (loading()) {\r\n <div class=\"input-loader\" aria-hidden=\"true\">\r\n <div class=\"loader\"></div>\r\n </div>\r\n }\r\n\r\n
|
|
2053
|
-
}], ctorParameters: () => [], propDecorators: { value: [{ type: i0.Input, args: [{ isSignal: true, alias: "value", required: false }] }, { type: i0.Output, args: ["valueChange"] }], disabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "disabled", required: false }] }, { type: i0.Output, args: ["disabledChange"] }], readonly: [{ type: i0.Input, args: [{ isSignal: true, alias: "readonly", required: false }] }, { type: i0.Output, args: ["readonlyChange"] }], loading: [{ type: i0.Input, args: [{ isSignal: true, alias: "loading", required: false }] }, { type: i0.Output, args: ["loadingChange"] }], touched: [{ type: i0.Input, args: [{ isSignal: true, alias: "touched", required: false }] }, { type: i0.Output, args: ["touchedChange"] }], variant: [{ type: i0.Input, args: [{ isSignal: true, alias: "variant", required: false }] }], size: [{ type: i0.Input, args: [{ isSignal: true, alias: "size", required: false }] }], fullWidth: [{ type: i0.Input, args: [{ isSignal: true, alias: "fullWidth", required: false }] }], required: [{ type: i0.Input, args: [{ isSignal: true, alias: "required", required: false }] }], showLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "showLabel", required: false }] }], type: [{ type: i0.Input, args: [{ isSignal: true, alias: "type", required: false }] }], placeholder: [{ type: i0.Input, args: [{ isSignal: true, alias: "placeholder", required: false }] }], label: [{ type: i0.Input, args: [{ isSignal: true, alias: "label", required: false }] }], ariaLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "ariaLabel", required: false }] }], iconStart: [{ type: i0.Input, args: [{ isSignal: true, alias: "iconStart", required: false }] }], iconEnd: [{ type: i0.Input, args: [{ isSignal: true, alias: "iconEnd", required: false }] }], error: [{ type: i0.Input, args: [{ isSignal: true, alias: "error", required: false }] }], success: [{ type: i0.Input, args: [{ isSignal: true, alias: "success", required: false }] }], hint: [{ type: i0.Input, args: [{ isSignal: true, alias: "hint", required: false }] }], suggestions: [{ type: i0.Input, args: [{ isSignal: true, alias: "suggestions", required: false }] }], autocompleteConfig: [{ type: i0.Input, args: [{ isSignal: true, alias: "autocompleteConfig", required: false }] }], inputFocus: [{ type: i0.Output, args: ["inputFocus"] }], inputBlur: [{ type: i0.Output, args: ["inputBlur"] }], suggestionSelect: [{ type: i0.Output, args: ["suggestionSelect"] }] } });
|
|
2246
|
+
}, template: "<div class=\"input-container\">\r\n @if (showLabel()) {\r\n <!-- label[for] delegates focus to its control natively; the click handler is a convenience. -->\r\n <!-- eslint-disable-next-line @angular-eslint/template/click-events-have-key-events, @angular-eslint/template/interactive-supports-focus -->\r\n <label\r\n class=\"input-label\"\r\n [for]=\"inputId\"\r\n (click)=\"focusSelect()\"\r\n [class.required]=\"required()\"\r\n >\r\n <ng-content select=\"[input-label]\"></ng-content>\r\n @if (!hasLabelContent()) {\r\n {{ label() }}\r\n }\r\n </label>\r\n }\r\n\r\n <div class=\"input-wrapper\">\r\n @if (iconStart()) {\r\n <i class=\"ph ph-{{ iconStart() }}\" aria-hidden=\"true\"></i>\r\n }\r\n\r\n <input\r\n [id]=\"inputId\"\r\n [type]=\"effectiveType()\"\r\n [attr.placeholder]=\"placeholder()\"\r\n [attr.aria-label]=\"computedAriaLabel()\"\r\n [attr.aria-invalid]=\"!!error()\"\r\n [attr.aria-required]=\"required()\"\r\n [attr.aria-describedby]=\"error() ? 'error-message' : success() ? 'success-message' : hint() ? 'hint-message' : null\"\r\n [disabled]=\"disabled()\"\r\n [readonly]=\"readonly()\"\r\n [required]=\"required()\"\r\n [value]=\"value()\"\r\n (input)=\"handleInput($event)\"\r\n (keydown)=\"handleKeydown($event)\"\r\n (focus)=\"handleFocus()\"\r\n (blur)=\"handleBlur()\"\r\n [attr.data-state]=\"state()\"\r\n />\r\n\r\n @if (iconEnd()) {\r\n <i class=\"ph ph-{{ iconEnd() }}\" aria-hidden=\"true\"></i>\r\n }\r\n\r\n @if (type() === 'password') {\r\n <button\r\n type=\"button\"\r\n class=\"password-toggle\"\r\n (click)=\"togglePasswordVisibility()\"\r\n [attr.aria-label]=\"passwordToggleLabel()\"\r\n [disabled]=\"disabled() || readonly()\"\r\n >\r\n <i \r\n [class]=\"'ph ph-' + (passwordVisible() ? 'eye-slash' : 'eye')\"\r\n aria-hidden=\"true\"\r\n ></i>\r\n </button>\r\n }\r\n\r\n @if (loading()) {\r\n <div class=\"input-loader\" aria-hidden=\"true\">\r\n <div class=\"loader\"></div>\r\n </div>\r\n }\r\n\r\n <ng-template #suggestionsTpl>\r\n <div class=\"suggestions-list\" role=\"listbox\">\r\n @for (suggestion of filteredSuggestions(); track suggestion; let i = $index) {\r\n <!-- option in a listbox: keyboard is handled by the input (arrow keys + focusedSuggestionIndex). -->\r\n <!-- eslint-disable-next-line @angular-eslint/template/click-events-have-key-events, @angular-eslint/template/interactive-supports-focus -->\r\n <div\r\n class=\"suggestion-item\"\r\n [class.focused]=\"i === focusedSuggestionIndex()\"\r\n role=\"option\"\r\n [attr.aria-selected]=\"i === focusedSuggestionIndex()\"\r\n (click)=\"handleSuggestionClick(suggestion)\"\r\n (mouseenter)=\"focusedSuggestionIndex.set(i)\"\r\n >\r\n {{ suggestion }}\r\n </div>\r\n }\r\n </div>\r\n </ng-template>\r\n </div>\r\n\r\n @if (error()) {\r\n <div id=\"error-message\" class=\"input-error\" role=\"alert\">\r\n <ng-content select=\"[input-error]\">\r\n {{ error() }}\r\n </ng-content>\r\n </div>\r\n } @else if (success()) {\r\n <div id=\"success-message\" class=\"input-success\" role=\"status\">\r\n <ng-content select=\"[input-success]\">\r\n {{ success() }}\r\n </ng-content>\r\n </div>\r\n } @else if (hint()) {\r\n <div id=\"hint-message\" class=\"input-hint\">\r\n <ng-content select=\"[input-hint]\">\r\n {{ hint() }}\r\n </ng-content>\r\n </div>\r\n }\r\n</div>", styles: [":host{display:block;width:100%;max-width:18.75rem;transition:all var(--animation-duration-default) var(--animation-easing-default)}:host.full-width{max-width:none}.input-container{position:relative;width:100%;display:flex;flex-direction:column;gap:var(--form-field-gap)}.input-label{display:block;color:var(--text-color);font-size:.875rem;font-weight:500;width:100%;cursor:pointer}.input-label.required:after{content:\"*\";color:var(--danger-color);margin-left:.125rem}.input-wrapper{position:relative;display:flex;align-items:center;width:100%}input{width:100%;height:2.5rem;padding:0 1rem;font-family:inherit;font-size:1rem;color:var(--text-color);background:var(--surface-0);border:.125rem solid var(--surface-border);border-radius:var(--border-radius);transition:all var(--animation-duration-default) var(--animation-easing-default)}input:hover:not(:disabled):not(:focus){border-color:var(--primary-color)}input::placeholder{color:var(--text-color-tertiary);opacity:1}input:focus{outline:none;border-color:var(--primary-color);box-shadow:0 0 0 .125rem var(--focus-ring-color)}:host.outlined input{background:transparent}:host.filled input{background:var(--surface-ground);border:.125rem solid var(--surface-border)}:host.filled input:hover:not(:disabled):not(:focus){background:var(--surface-hover)}:host.filled input:focus{background:var(--surface-0)}:host.error input{border-color:var(--danger-color)}:host.error input:focus{box-shadow:0 0 0 .125rem var(--focus-ring-error)}:host.success input{border-color:var(--success-color)}:host.success input:focus{box-shadow:0 0 0 .125rem var(--focus-ring-success)}:host.disabled input{background:var(--surface-ground);cursor:not-allowed;opacity:var(--opacity-disabled)}:host.readonly input{background:var(--surface-ground);cursor:default}:host.small input{height:2rem;font-size:.875rem}:host.large input{height:3rem;font-size:1.125rem}:host.has-start-icon input{padding-left:2.75rem}:host.has-end-icon input{padding-right:2.75rem}.input-wrapper i{position:absolute;top:50%;transform:translateY(-50%);font-size:1.25rem;color:var(--text-color-secondary);pointer-events:none;z-index:2}.input-wrapper i:first-of-type{padding-left:1rem}.input-wrapper i:last-of-type{padding-right:1rem}.password-toggle{position:absolute;right:.5rem;top:50%;transform:translateY(-50%);width:2rem;height:2rem;background:transparent;border:none;color:var(--text-color-secondary);cursor:pointer;padding:0;border-radius:var(--border-radius);display:flex;align-items:center;justify-content:center;transition:all .2s ease;z-index:3}.password-toggle:hover:not(:disabled){background:var(--surface-hover);color:var(--text-color)}.password-toggle i{position:static;transform:none;pointer-events:auto}.input-loader{position:absolute;right:1rem;top:50%;transform:translateY(-50%);z-index:3}.loader{width:1rem;height:1rem;border:.125rem solid var(--surface-border);border-top-color:var(--primary-color);border-radius:50%;animation:spin .8s linear infinite}.suggestions-list{pointer-events:auto;background:var(--surface-0);border:.0625rem solid var(--surface-border);border-radius:var(--border-radius);box-shadow:var(--shadow-lg);overflow-y:auto}.suggestion-item{padding:.5rem 1rem;cursor:pointer;color:var(--text-color)}.suggestion-item:hover,.suggestion-item.focused{background:var(--surface-hover);color:var(--primary-color)}.input-error,.input-success,.input-hint{font-size:.875rem}.input-error{color:var(--danger-color)}.input-success{color:var(--success-color)}.input-hint{color:var(--text-color-secondary)}@keyframes spin{to{transform:rotate(360deg)}}\n"] }]
|
|
2247
|
+
}], ctorParameters: () => [], propDecorators: { suggestionsTpl: [{ type: i0.ViewChild, args: ['suggestionsTpl', { isSignal: true }] }], value: [{ type: i0.Input, args: [{ isSignal: true, alias: "value", required: false }] }, { type: i0.Output, args: ["valueChange"] }], disabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "disabled", required: false }] }, { type: i0.Output, args: ["disabledChange"] }], readonly: [{ type: i0.Input, args: [{ isSignal: true, alias: "readonly", required: false }] }, { type: i0.Output, args: ["readonlyChange"] }], loading: [{ type: i0.Input, args: [{ isSignal: true, alias: "loading", required: false }] }, { type: i0.Output, args: ["loadingChange"] }], touched: [{ type: i0.Input, args: [{ isSignal: true, alias: "touched", required: false }] }, { type: i0.Output, args: ["touchedChange"] }], variant: [{ type: i0.Input, args: [{ isSignal: true, alias: "variant", required: false }] }], size: [{ type: i0.Input, args: [{ isSignal: true, alias: "size", required: false }] }], fullWidth: [{ type: i0.Input, args: [{ isSignal: true, alias: "fullWidth", required: false }] }], required: [{ type: i0.Input, args: [{ isSignal: true, alias: "required", required: false }] }], showLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "showLabel", required: false }] }], type: [{ type: i0.Input, args: [{ isSignal: true, alias: "type", required: false }] }], placeholder: [{ type: i0.Input, args: [{ isSignal: true, alias: "placeholder", required: false }] }], label: [{ type: i0.Input, args: [{ isSignal: true, alias: "label", required: false }] }], ariaLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "ariaLabel", required: false }] }], iconStart: [{ type: i0.Input, args: [{ isSignal: true, alias: "iconStart", required: false }] }], iconEnd: [{ type: i0.Input, args: [{ isSignal: true, alias: "iconEnd", required: false }] }], error: [{ type: i0.Input, args: [{ isSignal: true, alias: "error", required: false }] }], success: [{ type: i0.Input, args: [{ isSignal: true, alias: "success", required: false }] }], hint: [{ type: i0.Input, args: [{ isSignal: true, alias: "hint", required: false }] }], suggestions: [{ type: i0.Input, args: [{ isSignal: true, alias: "suggestions", required: false }] }], autocompleteConfig: [{ type: i0.Input, args: [{ isSignal: true, alias: "autocompleteConfig", required: false }] }], inputFocus: [{ type: i0.Output, args: ["inputFocus"] }], inputBlur: [{ type: i0.Output, args: ["inputBlur"] }], suggestionSelect: [{ type: i0.Output, args: ["suggestionSelect"] }] } });
|
|
2054
2248
|
|
|
2055
2249
|
const TEXTAREA_LABELS = {
|
|
2056
2250
|
characterCountSuffix: 'caractères',
|
|
@@ -3734,7 +3928,14 @@ class PshSelectComponent {
|
|
|
3734
3928
|
this.elementRef = inject(ElementRef);
|
|
3735
3929
|
this.destroyRef = inject(DestroyRef);
|
|
3736
3930
|
this.overlayPosition = inject(PshOverlayPositionService);
|
|
3737
|
-
this.
|
|
3931
|
+
this.portal = inject(PshPortalService);
|
|
3932
|
+
this.viewContainer = inject(ViewContainerRef);
|
|
3933
|
+
// The options panel, teleported to a body-level overlay layer on open so it
|
|
3934
|
+
// escapes any ancestor overflow / stacking context (e.g. a modal body).
|
|
3935
|
+
this.panelTpl = viewChild('panelTpl', /* @ts-ignore */
|
|
3936
|
+
...(ngDevMode ? [{ debugName: "panelTpl" }] : /* istanbul ignore next */ []));
|
|
3937
|
+
this.portalRef = null;
|
|
3938
|
+
this.repositionHandler = () => this.reposition();
|
|
3738
3939
|
// Side the panel actually opens on, after viewport collision/flip.
|
|
3739
3940
|
this.resolvedSide = signal('bottom', /* @ts-ignore */
|
|
3740
3941
|
...(ngDevMode ? [{ debugName: "resolvedSide" }] : /* istanbul ignore next */ []));
|
|
@@ -3888,34 +4089,58 @@ class PshSelectComponent {
|
|
|
3888
4089
|
...(ngDevMode ? [{ debugName: "filteredOptions" }] : /* istanbul ignore next */ []));
|
|
3889
4090
|
this.onChange = () => { };
|
|
3890
4091
|
this.onTouched = () => { };
|
|
3891
|
-
// Close on outside click via the shared click-outside primitive.
|
|
4092
|
+
// Close on outside click via the shared click-outside primitive. The options
|
|
4093
|
+
// panel is teleported to the body (outside the host), so a click inside it
|
|
4094
|
+
// must NOT count as "outside" — otherwise selecting an option would close the
|
|
4095
|
+
// panel before select() runs.
|
|
3892
4096
|
const clickOutside = inject(PshClickOutsideDirective);
|
|
3893
|
-
const sub = clickOutside.pshClickOutside.subscribe(
|
|
3894
|
-
if (this.isOpen())
|
|
3895
|
-
|
|
4097
|
+
const sub = clickOutside.pshClickOutside.subscribe(event => {
|
|
4098
|
+
if (!this.isOpen())
|
|
4099
|
+
return;
|
|
4100
|
+
const target = event.target;
|
|
4101
|
+
if (target && this.portalRef?.panel.contains(target))
|
|
4102
|
+
return;
|
|
4103
|
+
this.close();
|
|
3896
4104
|
});
|
|
3897
|
-
this.destroyRef.onDestroy(() =>
|
|
3898
|
-
|
|
3899
|
-
|
|
3900
|
-
if (this.isOpen()) {
|
|
3901
|
-
afterNextRender(() => this.reposition(), { injector: this.injector });
|
|
3902
|
-
}
|
|
3903
|
-
else {
|
|
3904
|
-
this.resolvedSide.set('bottom');
|
|
3905
|
-
}
|
|
4105
|
+
this.destroyRef.onDestroy(() => {
|
|
4106
|
+
sub.unsubscribe();
|
|
4107
|
+
this.closePanel();
|
|
3906
4108
|
});
|
|
3907
4109
|
}
|
|
4110
|
+
/** Teleports the options panel to the body-level overlay layer and positions it. */
|
|
4111
|
+
openPanel() {
|
|
4112
|
+
if (this.portalRef)
|
|
4113
|
+
return;
|
|
4114
|
+
const tpl = this.panelTpl();
|
|
4115
|
+
if (!tpl)
|
|
4116
|
+
return;
|
|
4117
|
+
this.portalRef = this.portal.attach(tpl, this.viewContainer);
|
|
4118
|
+
this.reposition();
|
|
4119
|
+
const view = this.elementRef.nativeElement.ownerDocument.defaultView;
|
|
4120
|
+
// Capture phase so inner (e.g. modal body) scrolls keep the panel aligned.
|
|
4121
|
+
view?.addEventListener('scroll', this.repositionHandler, true);
|
|
4122
|
+
view?.addEventListener('resize', this.repositionHandler);
|
|
4123
|
+
}
|
|
4124
|
+
closePanel() {
|
|
4125
|
+
const view = this.elementRef.nativeElement.ownerDocument.defaultView;
|
|
4126
|
+
view?.removeEventListener('scroll', this.repositionHandler, true);
|
|
4127
|
+
view?.removeEventListener('resize', this.repositionHandler);
|
|
4128
|
+
this.portalRef?.detach();
|
|
4129
|
+
this.portalRef = null;
|
|
4130
|
+
this.resolvedSide.set('bottom');
|
|
4131
|
+
}
|
|
3908
4132
|
reposition() {
|
|
3909
|
-
if (!this.
|
|
4133
|
+
if (!this.portalRef)
|
|
3910
4134
|
return;
|
|
3911
4135
|
const host = this.elementRef.nativeElement;
|
|
3912
4136
|
const trigger = host.querySelector('.select-trigger');
|
|
3913
|
-
const panel = host.querySelector('.select-dropdown');
|
|
3914
4137
|
if (!trigger)
|
|
3915
4138
|
return;
|
|
3916
|
-
this.
|
|
3917
|
-
overlayHeight: panel
|
|
3918
|
-
})
|
|
4139
|
+
const side = this.overlayPosition.flipSide(trigger, 'bottom', {
|
|
4140
|
+
overlayHeight: this.portalRef.panel.offsetHeight,
|
|
4141
|
+
});
|
|
4142
|
+
this.resolvedSide.set(side);
|
|
4143
|
+
this.portalRef.position(trigger, side, 8);
|
|
3919
4144
|
}
|
|
3920
4145
|
writeValue(value) {
|
|
3921
4146
|
this.value.set(value);
|
|
@@ -3932,6 +4157,7 @@ class PshSelectComponent {
|
|
|
3932
4157
|
else {
|
|
3933
4158
|
this.isOpenSignal.set(true);
|
|
3934
4159
|
this.opened.emit();
|
|
4160
|
+
this.openPanel();
|
|
3935
4161
|
}
|
|
3936
4162
|
}
|
|
3937
4163
|
close() {
|
|
@@ -3940,6 +4166,7 @@ class PshSelectComponent {
|
|
|
3940
4166
|
this.isOpenSignal.set(false);
|
|
3941
4167
|
this.searchTermSignal.set('');
|
|
3942
4168
|
this.focusedIndex.set(-1);
|
|
4169
|
+
this.closePanel();
|
|
3943
4170
|
this.closed.emit();
|
|
3944
4171
|
}
|
|
3945
4172
|
select(option, groupDisabled = false) {
|
|
@@ -4100,7 +4327,7 @@ class PshSelectComponent {
|
|
|
4100
4327
|
useExisting: PshSelectComponent,
|
|
4101
4328
|
multi: true
|
|
4102
4329
|
}
|
|
4103
|
-
], hostDirectives: [{ directive: PshClickOutsideDirective }], ngImport: i0, template: "<div class=\"select-container\">\r\n @if (label()) {\r\n <!-- label[for] delegates focus to its control natively; the click handler is a convenience. -->\r\n <!-- eslint-disable-next-line @angular-eslint/template/click-events-have-key-events, @angular-eslint/template/interactive-supports-focus -->\r\n <label class=\"select-label\" [attr.for]=\"selectId\" (click)=\"focusSelect()\" [class.required]=\"required()\">\r\n {{ label() }}\r\n @if (required()) { <span class=\"required-mark\">*</span> }\r\n </label>\r\n }\r\n\r\n <div class=\"select-trigger-wrapper\">\r\n <div class=\"select-trigger\"\r\n role=\"combobox\"\r\n [id]=\"selectId\"\r\n [attr.aria-expanded]=\"isOpen()\"\r\n [attr.aria-haspopup]=\"'listbox'\"\r\n [attr.aria-controls]=\"selectId + '-listbox'\"\r\n [attr.aria-activedescendant]=\"activeDescendant()\"\r\n [attr.aria-label]=\"computedAriaLabel()\"\r\n [attr.aria-invalid]=\"!!error()\"\r\n [attr.aria-required]=\"required()\"\r\n [attr.aria-disabled]=\"disabled()\"\r\n [attr.aria-busy]=\"loading()\"\r\n [attr.aria-describedby]=\"describedBy()\"\r\n [attr.tabindex]=\"disabled() || loading() ? -1 : 0\"\r\n (keydown)=\"handleKeydown($event)\"\r\n (click)=\"toggle()\">\r\n <div class=\"select-value\">\r\n <span [class.placeholder]=\"!hasValue()\">\r\n {{ selectedLabel() }}\r\n </span>\r\n </div>\r\n <div class=\"select-actions\">\r\n @if (clearable() && hasValue() && !disabled()) {\r\n <button class=\"select-clear\" (click)=\"clear($event)\">\r\n <i class=\"ph ph-x\"></i>\r\n </button>\r\n }\r\n @if (loading()) {\r\n <div class=\"select-loader-trigger\"></div>\r\n } @else {\r\n <i class=\"ph ph-caret-down select-arrow\"></i>\r\n }\r\n </div>\r\n </div>\r\n\r\n @if (isOpen()) {\r\n <div class=\"select-dropdown\" [class.open-top]=\"resolvedSide() === 'top'\">\r\n @if (searchable()) {\r\n <div class=\"select-search\">\r\n <i class=\"ph ph-magnifying-glass select-search-icon\"></i>\r\n <input type=\"text\"\r\n [placeholder]=\"searchConfig().placeholder\"\r\n [value]=\"searchTerm()\"\r\n (input)=\"onSearch($event)\"\r\n (click)=\"$event.stopPropagation()\">\r\n </div>\r\n }\r\n <div class=\"select-options\"\r\n role=\"listbox\"\r\n [id]=\"selectId + '-listbox'\"\r\n [attr.aria-multiselectable]=\"multiple() || null\"\r\n (scroll)=\"onScroll($event)\">\r\n @for (item of filteredOptions(); track getOptionKey(item)) {\r\n @if (isOptionGroup(item)) {\r\n <div class=\"select-group\" role=\"group\" [attr.aria-label]=\"item.label\">\r\n <div class=\"select-group-label\">{{ item.label }}</div>\r\n @for (opt of item.options; track opt.label) {\r\n <!-- option in a listbox: keyboard is handled at the widget level (arrows + aria-activedescendant). -->\r\n <!-- eslint-disable-next-line @angular-eslint/template/click-events-have-key-events -->\r\n <div class=\"select-option\"\r\n role=\"option\"\r\n [id]=\"selectId + '-' + opt.value\"\r\n [attr.aria-selected]=\"isSelected(opt)\"\r\n [attr.aria-disabled]=\"(item.disabled || opt.disabled) ? true : null\"\r\n [attr.tabindex]=\"(item.disabled || opt.disabled) ? -1 : null\"\r\n [class.selected]=\"isSelected(opt)\"\r\n [class.disabled]=\"item.disabled || opt.disabled\"\r\n [class.focused]=\"getFlatIndex(opt) === focusedIndex()\"\r\n (click)=\"select(opt, !!item.disabled)\">\r\n @if (opt.icon) { <i [class]=\"'ph ph-' + opt.icon\" aria-hidden=\"true\"></i> }\r\n <div class=\"select-option-content\">\r\n <span class=\"select-option-label\">{{ opt.label }}</span>\r\n @if (opt.description) { <span class=\"select-option-description\">{{ opt.description }}</span> }\r\n </div>\r\n </div>\r\n }\r\n </div>\r\n } @else {\r\n <!-- option in a listbox: keyboard is handled at the widget level (arrows + aria-activedescendant). -->\r\n <!-- eslint-disable-next-line @angular-eslint/template/click-events-have-key-events -->\r\n <div class=\"select-option\"\r\n role=\"option\"\r\n [id]=\"selectId + '-' + item.value\"\r\n [attr.aria-selected]=\"isSelected(item)\"\r\n [attr.aria-disabled]=\"item.disabled ? true : null\"\r\n [attr.tabindex]=\"item.disabled ? -1 : null\"\r\n [class.selected]=\"isSelected(item)\"\r\n [class.disabled]=\"item.disabled\"\r\n [class.focused]=\"getFlatIndex(item) === focusedIndex()\"\r\n (click)=\"select(item)\">\r\n @if (item.icon) { <i [class]=\"'ph ph-' + item.icon\" aria-hidden=\"true\"></i> }\r\n <div class=\"select-option-content\">\r\n <span class=\"select-option-label\">{{ item.label }}</span>\r\n @if (item.description) { <span class=\"select-option-description\">{{ item.description }}</span> }\r\n </div>\r\n </div>\r\n }\r\n } @empty {\r\n <div class=\"select-no-results\">Aucun r\u00E9sultat</div>\r\n }\r\n </div>\r\n </div>\r\n }\r\n </div>\r\n\r\n @if (error()) {\r\n <div id=\"error-message\" class=\"select-error-message\" role=\"alert\">{{ error() }}</div>\r\n } @else if (success()) {\r\n <div id=\"success-message\" class=\"select-success-message\" role=\"status\">{{ success() }}</div>\r\n } @else if (hint()) {\r\n <div id=\"hint-message\" class=\"select-hint\">{{ hint() }}</div>\r\n }\r\n</div>\r\n", styles: [":host{display:block;width:100%;max-width:18.75rem}:host.full-width{max-width:none}.select-container{width:100%;display:flex;flex-direction:column;gap:var(--form-field-gap)}.select-trigger-wrapper{position:relative}.select-label{display:block;color:var(--text-color);font-size:.875rem;font-weight:500;cursor:pointer}.select-trigger{display:flex;align-items:center;justify-content:space-between;width:100%;height:2.5rem;padding:0 1rem;background:var(--surface-0);border:.125rem solid var(--surface-border);border-radius:var(--border-radius);cursor:pointer;box-sizing:border-box}.select-trigger:focus{border-color:var(--primary-color);outline:none;box-shadow:0 0 0 .125rem var(--focus-ring-color)}:host.error .select-trigger{border-color:var(--danger-color)}:host.error .select-trigger:focus{box-shadow:0 0 0 .125rem var(--focus-ring-error)}:host.success .select-trigger{border-color:var(--success-color)}:host.success .select-trigger:focus{box-shadow:0 0 0 .125rem var(--focus-ring-success)}:host.disabled .select-trigger{background:var(--surface-ground);cursor:not-allowed;opacity:var(--opacity-disabled)}:host.filled .select-trigger{background:var(--surface-ground);border:.125rem solid var(--surface-border)}:host.filled .select-trigger:hover:not([disabled]):not(:focus){background:var(--surface-hover)}.select-value{flex:1;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.select-actions{display:flex;align-items:center;gap:.5rem;flex-shrink:0}.select-clear{background:none;border:none;cursor:pointer;padding:0;color:var(--text-color-secondary);display:flex}.select-clear:hover{color:var(--danger-color)}.select-loader-trigger{width:1rem;height:1rem;border:2px solid var(--surface-border);border-top-color:var(--primary-color);border-radius:50%;animation:spin .8s linear infinite}.select-arrow{transition:transform .2s;font-size:1rem;color:var(--text-color-secondary)}:host[aria-expanded=true] .select-arrow{transform:rotate(180deg)}.select-dropdown.open-top{top:auto;bottom:calc(100% + .25rem)}.select-dropdown{position:absolute;top:calc(100% + .25rem);left:0;right:0;z-index:var(--z-index-dropdown);background:var(--surface-0);border:.125rem solid var(--surface-border);border-radius:var(--border-radius);box-shadow:var(--shadow-lg)}.select-search{position:relative;padding:.5rem;border-bottom:.0625rem solid var(--surface-border)}.select-search-icon{position:absolute;left:1.25rem;top:50%;transform:translateY(-50%);color:var(--text-color-secondary);font-size:.875rem;pointer-events:none}.select-search input{width:100%;height:2rem;padding:0 .75rem 0 2rem;background:var(--surface-ground);border:.0625rem solid var(--surface-border);border-radius:var(--border-radius);color:var(--text-color);font-size:.875rem;outline:none;box-sizing:border-box;transition:border-color .15s}.select-search input::placeholder{color:var(--text-color-secondary)}.select-search input:focus{border-color:var(--primary-color)}.select-options{max-height:15rem;overflow-y:auto}.select-group-label{padding:.5rem 1rem;font-size:.75rem;font-weight:600;color:var(--text-color-secondary);background:var(--surface-ground)}.select-option{padding:.625rem 1rem;cursor:pointer;display:flex;align-items:flex-start;gap:.5rem}.select-option:hover{background:var(--surface-hover)}.select-option.selected{background:rgba(var(--primary-color-rgb),.1);color:var(--primary-color);font-weight:500}.select-option.focused{background:var(--surface-hover)}.select-option.disabled{opacity:var(--opacity-disabled);cursor:not-allowed}.select-option i{flex-shrink:0;line-height:1.4}.select-option-content{flex:1;min-width:0;display:flex;flex-direction:column;gap:.125rem}.select-option-label{min-width:0}.select-option-description{font-size:.75rem;color:var(--text-color-secondary)}.select-error-message,.select-success-message,.select-hint{font-size:.875rem}.select-error-message{color:var(--danger-color)}.select-success-message{color:var(--success-color)}.select-hint{color:var(--text-color-secondary)}:host.small .select-trigger{text-overflow:ellipsis;height:2rem;font-size:.875rem}:host.large .select-trigger{text-overflow:ellipsis;height:3rem;font-size:1.125rem}@keyframes spin{to{transform:rotate(360deg)}}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "ngmodule", type: FormsModule }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
|
|
4330
|
+
], viewQueries: [{ propertyName: "panelTpl", first: true, predicate: ["panelTpl"], descendants: true, isSignal: true }], hostDirectives: [{ directive: PshClickOutsideDirective }], ngImport: i0, template: "<div class=\"select-container\">\r\n @if (label()) {\r\n <!-- label[for] delegates focus to its control natively; the click handler is a convenience. -->\r\n <!-- eslint-disable-next-line @angular-eslint/template/click-events-have-key-events, @angular-eslint/template/interactive-supports-focus -->\r\n <label class=\"select-label\" [attr.for]=\"selectId\" (click)=\"focusSelect()\" [class.required]=\"required()\">\r\n {{ label() }}\r\n @if (required()) { <span class=\"required-mark\">*</span> }\r\n </label>\r\n }\r\n\r\n <div class=\"select-trigger-wrapper\">\r\n <div class=\"select-trigger\"\r\n role=\"combobox\"\r\n [id]=\"selectId\"\r\n [attr.aria-expanded]=\"isOpen()\"\r\n [attr.aria-haspopup]=\"'listbox'\"\r\n [attr.aria-controls]=\"selectId + '-listbox'\"\r\n [attr.aria-activedescendant]=\"activeDescendant()\"\r\n [attr.aria-label]=\"computedAriaLabel()\"\r\n [attr.aria-invalid]=\"!!error()\"\r\n [attr.aria-required]=\"required()\"\r\n [attr.aria-disabled]=\"disabled()\"\r\n [attr.aria-busy]=\"loading()\"\r\n [attr.aria-describedby]=\"describedBy()\"\r\n [attr.tabindex]=\"disabled() || loading() ? -1 : 0\"\r\n (keydown)=\"handleKeydown($event)\"\r\n (click)=\"toggle()\">\r\n <div class=\"select-value\">\r\n <span [class.placeholder]=\"!hasValue()\">\r\n {{ selectedLabel() }}\r\n </span>\r\n </div>\r\n <div class=\"select-actions\">\r\n @if (clearable() && hasValue() && !disabled()) {\r\n <button class=\"select-clear\" (click)=\"clear($event)\">\r\n <i class=\"ph ph-x\"></i>\r\n </button>\r\n }\r\n @if (loading()) {\r\n <div class=\"select-loader-trigger\"></div>\r\n } @else {\r\n <i class=\"ph ph-caret-down select-arrow\"></i>\r\n }\r\n </div>\r\n </div>\r\n\r\n <ng-template #panelTpl>\r\n <div class=\"select-dropdown\" [class.open-top]=\"resolvedSide() === 'top'\">\r\n @if (searchable()) {\r\n <div class=\"select-search\">\r\n <i class=\"ph ph-magnifying-glass select-search-icon\"></i>\r\n <input type=\"text\"\r\n [placeholder]=\"searchConfig().placeholder\"\r\n [value]=\"searchTerm()\"\r\n (input)=\"onSearch($event)\"\r\n (click)=\"$event.stopPropagation()\">\r\n </div>\r\n }\r\n <div class=\"select-options\"\r\n role=\"listbox\"\r\n [id]=\"selectId + '-listbox'\"\r\n [attr.aria-multiselectable]=\"multiple() || null\"\r\n (scroll)=\"onScroll($event)\">\r\n @for (item of filteredOptions(); track getOptionKey(item)) {\r\n @if (isOptionGroup(item)) {\r\n <div class=\"select-group\" role=\"group\" [attr.aria-label]=\"item.label\">\r\n <div class=\"select-group-label\">{{ item.label }}</div>\r\n @for (opt of item.options; track opt.label) {\r\n <!-- option in a listbox: keyboard is handled at the widget level (arrows + aria-activedescendant). -->\r\n <!-- eslint-disable-next-line @angular-eslint/template/click-events-have-key-events -->\r\n <div class=\"select-option\"\r\n role=\"option\"\r\n [id]=\"selectId + '-' + opt.value\"\r\n [attr.aria-selected]=\"isSelected(opt)\"\r\n [attr.aria-disabled]=\"(item.disabled || opt.disabled) ? true : null\"\r\n [attr.tabindex]=\"(item.disabled || opt.disabled) ? -1 : null\"\r\n [class.selected]=\"isSelected(opt)\"\r\n [class.disabled]=\"item.disabled || opt.disabled\"\r\n [class.focused]=\"getFlatIndex(opt) === focusedIndex()\"\r\n (click)=\"select(opt, !!item.disabled)\">\r\n @if (opt.icon) { <i [class]=\"'ph ph-' + opt.icon\" aria-hidden=\"true\"></i> }\r\n <div class=\"select-option-content\">\r\n <span class=\"select-option-label\">{{ opt.label }}</span>\r\n @if (opt.description) { <span class=\"select-option-description\">{{ opt.description }}</span> }\r\n </div>\r\n </div>\r\n }\r\n </div>\r\n } @else {\r\n <!-- option in a listbox: keyboard is handled at the widget level (arrows + aria-activedescendant). -->\r\n <!-- eslint-disable-next-line @angular-eslint/template/click-events-have-key-events -->\r\n <div class=\"select-option\"\r\n role=\"option\"\r\n [id]=\"selectId + '-' + item.value\"\r\n [attr.aria-selected]=\"isSelected(item)\"\r\n [attr.aria-disabled]=\"item.disabled ? true : null\"\r\n [attr.tabindex]=\"item.disabled ? -1 : null\"\r\n [class.selected]=\"isSelected(item)\"\r\n [class.disabled]=\"item.disabled\"\r\n [class.focused]=\"getFlatIndex(item) === focusedIndex()\"\r\n (click)=\"select(item)\">\r\n @if (item.icon) { <i [class]=\"'ph ph-' + item.icon\" aria-hidden=\"true\"></i> }\r\n <div class=\"select-option-content\">\r\n <span class=\"select-option-label\">{{ item.label }}</span>\r\n @if (item.description) { <span class=\"select-option-description\">{{ item.description }}</span> }\r\n </div>\r\n </div>\r\n }\r\n } @empty {\r\n <div class=\"select-no-results\">Aucun r\u00E9sultat</div>\r\n }\r\n </div>\r\n </div>\r\n </ng-template>\r\n </div>\r\n\r\n @if (error()) {\r\n <div id=\"error-message\" class=\"select-error-message\" role=\"alert\">{{ error() }}</div>\r\n } @else if (success()) {\r\n <div id=\"success-message\" class=\"select-success-message\" role=\"status\">{{ success() }}</div>\r\n } @else if (hint()) {\r\n <div id=\"hint-message\" class=\"select-hint\">{{ hint() }}</div>\r\n }\r\n</div>\r\n", styles: [":host{display:block;width:100%;max-width:18.75rem}:host.full-width{max-width:none}.select-container{width:100%;display:flex;flex-direction:column;gap:var(--form-field-gap)}.select-trigger-wrapper{position:relative}.select-label{display:block;color:var(--text-color);font-size:.875rem;font-weight:500;cursor:pointer}.select-trigger{display:flex;align-items:center;justify-content:space-between;width:100%;height:2.5rem;padding:0 1rem;background:var(--surface-0);border:.125rem solid var(--surface-border);border-radius:var(--border-radius);cursor:pointer;box-sizing:border-box}.select-trigger:focus{border-color:var(--primary-color);outline:none;box-shadow:0 0 0 .125rem var(--focus-ring-color)}:host.error .select-trigger{border-color:var(--danger-color)}:host.error .select-trigger:focus{box-shadow:0 0 0 .125rem var(--focus-ring-error)}:host.success .select-trigger{border-color:var(--success-color)}:host.success .select-trigger:focus{box-shadow:0 0 0 .125rem var(--focus-ring-success)}:host.disabled .select-trigger{background:var(--surface-ground);cursor:not-allowed;opacity:var(--opacity-disabled)}:host.filled .select-trigger{background:var(--surface-ground);border:.125rem solid var(--surface-border)}:host.filled .select-trigger:hover:not([disabled]):not(:focus){background:var(--surface-hover)}.select-value{flex:1;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.select-actions{display:flex;align-items:center;gap:.5rem;flex-shrink:0}.select-clear{background:none;border:none;cursor:pointer;padding:0;color:var(--text-color-secondary);display:flex}.select-clear:hover{color:var(--danger-color)}.select-loader-trigger{width:1rem;height:1rem;border:2px solid var(--surface-border);border-top-color:var(--primary-color);border-radius:50%;animation:spin .8s linear infinite}.select-arrow{transition:transform .2s;font-size:1rem;color:var(--text-color-secondary)}:host[aria-expanded=true] .select-arrow{transform:rotate(180deg)}.select-dropdown{display:flex;flex-direction:column;overflow:hidden;pointer-events:auto;background:var(--surface-0);border:.125rem solid var(--surface-border);border-radius:var(--border-radius);box-shadow:var(--shadow-lg)}.select-search{position:relative;flex-shrink:0;padding:.5rem;border-bottom:.0625rem solid var(--surface-border)}.select-search-icon{position:absolute;left:1.25rem;top:50%;transform:translateY(-50%);color:var(--text-color-secondary);font-size:.875rem;pointer-events:none}.select-search input{width:100%;height:2rem;padding:0 .75rem 0 2rem;background:var(--surface-ground);border:.0625rem solid var(--surface-border);border-radius:var(--border-radius);color:var(--text-color);font-size:.875rem;outline:none;box-sizing:border-box;transition:border-color .15s}.select-search input::placeholder{color:var(--text-color-secondary)}.select-search input:focus{border-color:var(--primary-color)}.select-options{flex:0 1 auto;max-height:15rem;overflow-y:auto}.select-group-label{padding:.5rem 1rem;font-size:.75rem;font-weight:600;color:var(--text-color-secondary);background:var(--surface-ground)}.select-option{padding:.625rem 1rem;cursor:pointer;display:flex;align-items:flex-start;gap:.5rem}.select-option:hover{background:var(--surface-hover)}.select-option.selected{background:rgba(var(--primary-color-rgb),.1);color:var(--primary-color);font-weight:500}.select-option.focused{background:var(--surface-hover)}.select-option.disabled{opacity:var(--opacity-disabled);cursor:not-allowed}.select-option i{flex-shrink:0;line-height:1.4}.select-option-content{flex:1;min-width:0;display:flex;flex-direction:column;gap:.125rem}.select-option-label{min-width:0}.select-option-description{font-size:.75rem;color:var(--text-color-secondary)}.select-error-message,.select-success-message,.select-hint{font-size:.875rem}.select-error-message{color:var(--danger-color)}.select-success-message{color:var(--success-color)}.select-hint{color:var(--text-color-secondary)}:host.small .select-trigger{text-overflow:ellipsis;height:2rem;font-size:.875rem}:host.large .select-trigger{text-overflow:ellipsis;height:3rem;font-size:1.125rem}@keyframes spin{to{transform:rotate(360deg)}}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "ngmodule", type: FormsModule }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
|
|
4104
4331
|
}
|
|
4105
4332
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.4", ngImport: i0, type: PshSelectComponent, decorators: [{
|
|
4106
4333
|
type: Component,
|
|
@@ -4122,8 +4349,8 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.4", ngImpor
|
|
|
4122
4349
|
'[class.loading]': 'loading()',
|
|
4123
4350
|
'[attr.aria-expanded]': 'isOpen().toString()',
|
|
4124
4351
|
'[attr.data-state]': 'state()'
|
|
4125
|
-
}, template: "<div class=\"select-container\">\r\n @if (label()) {\r\n <!-- label[for] delegates focus to its control natively; the click handler is a convenience. -->\r\n <!-- eslint-disable-next-line @angular-eslint/template/click-events-have-key-events, @angular-eslint/template/interactive-supports-focus -->\r\n <label class=\"select-label\" [attr.for]=\"selectId\" (click)=\"focusSelect()\" [class.required]=\"required()\">\r\n {{ label() }}\r\n @if (required()) { <span class=\"required-mark\">*</span> }\r\n </label>\r\n }\r\n\r\n <div class=\"select-trigger-wrapper\">\r\n <div class=\"select-trigger\"\r\n role=\"combobox\"\r\n [id]=\"selectId\"\r\n [attr.aria-expanded]=\"isOpen()\"\r\n [attr.aria-haspopup]=\"'listbox'\"\r\n [attr.aria-controls]=\"selectId + '-listbox'\"\r\n [attr.aria-activedescendant]=\"activeDescendant()\"\r\n [attr.aria-label]=\"computedAriaLabel()\"\r\n [attr.aria-invalid]=\"!!error()\"\r\n [attr.aria-required]=\"required()\"\r\n [attr.aria-disabled]=\"disabled()\"\r\n [attr.aria-busy]=\"loading()\"\r\n [attr.aria-describedby]=\"describedBy()\"\r\n [attr.tabindex]=\"disabled() || loading() ? -1 : 0\"\r\n (keydown)=\"handleKeydown($event)\"\r\n (click)=\"toggle()\">\r\n <div class=\"select-value\">\r\n <span [class.placeholder]=\"!hasValue()\">\r\n {{ selectedLabel() }}\r\n </span>\r\n </div>\r\n <div class=\"select-actions\">\r\n @if (clearable() && hasValue() && !disabled()) {\r\n <button class=\"select-clear\" (click)=\"clear($event)\">\r\n <i class=\"ph ph-x\"></i>\r\n </button>\r\n }\r\n @if (loading()) {\r\n <div class=\"select-loader-trigger\"></div>\r\n } @else {\r\n <i class=\"ph ph-caret-down select-arrow\"></i>\r\n }\r\n </div>\r\n </div>\r\n\r\n @if (isOpen()) {\r\n <div class=\"select-dropdown\" [class.open-top]=\"resolvedSide() === 'top'\">\r\n @if (searchable()) {\r\n <div class=\"select-search\">\r\n <i class=\"ph ph-magnifying-glass select-search-icon\"></i>\r\n <input type=\"text\"\r\n [placeholder]=\"searchConfig().placeholder\"\r\n [value]=\"searchTerm()\"\r\n (input)=\"onSearch($event)\"\r\n (click)=\"$event.stopPropagation()\">\r\n </div>\r\n }\r\n <div class=\"select-options\"\r\n role=\"listbox\"\r\n [id]=\"selectId + '-listbox'\"\r\n [attr.aria-multiselectable]=\"multiple() || null\"\r\n (scroll)=\"onScroll($event)\">\r\n @for (item of filteredOptions(); track getOptionKey(item)) {\r\n @if (isOptionGroup(item)) {\r\n <div class=\"select-group\" role=\"group\" [attr.aria-label]=\"item.label\">\r\n <div class=\"select-group-label\">{{ item.label }}</div>\r\n @for (opt of item.options; track opt.label) {\r\n <!-- option in a listbox: keyboard is handled at the widget level (arrows + aria-activedescendant). -->\r\n <!-- eslint-disable-next-line @angular-eslint/template/click-events-have-key-events -->\r\n <div class=\"select-option\"\r\n role=\"option\"\r\n [id]=\"selectId + '-' + opt.value\"\r\n [attr.aria-selected]=\"isSelected(opt)\"\r\n [attr.aria-disabled]=\"(item.disabled || opt.disabled) ? true : null\"\r\n [attr.tabindex]=\"(item.disabled || opt.disabled) ? -1 : null\"\r\n [class.selected]=\"isSelected(opt)\"\r\n [class.disabled]=\"item.disabled || opt.disabled\"\r\n [class.focused]=\"getFlatIndex(opt) === focusedIndex()\"\r\n (click)=\"select(opt, !!item.disabled)\">\r\n @if (opt.icon) { <i [class]=\"'ph ph-' + opt.icon\" aria-hidden=\"true\"></i> }\r\n <div class=\"select-option-content\">\r\n <span class=\"select-option-label\">{{ opt.label }}</span>\r\n @if (opt.description) { <span class=\"select-option-description\">{{ opt.description }}</span> }\r\n </div>\r\n </div>\r\n }\r\n </div>\r\n } @else {\r\n <!-- option in a listbox: keyboard is handled at the widget level (arrows + aria-activedescendant). -->\r\n <!-- eslint-disable-next-line @angular-eslint/template/click-events-have-key-events -->\r\n <div class=\"select-option\"\r\n role=\"option\"\r\n [id]=\"selectId + '-' + item.value\"\r\n [attr.aria-selected]=\"isSelected(item)\"\r\n [attr.aria-disabled]=\"item.disabled ? true : null\"\r\n [attr.tabindex]=\"item.disabled ? -1 : null\"\r\n [class.selected]=\"isSelected(item)\"\r\n [class.disabled]=\"item.disabled\"\r\n [class.focused]=\"getFlatIndex(item) === focusedIndex()\"\r\n (click)=\"select(item)\">\r\n @if (item.icon) { <i [class]=\"'ph ph-' + item.icon\" aria-hidden=\"true\"></i> }\r\n <div class=\"select-option-content\">\r\n <span class=\"select-option-label\">{{ item.label }}</span>\r\n @if (item.description) { <span class=\"select-option-description\">{{ item.description }}</span> }\r\n </div>\r\n </div>\r\n }\r\n } @empty {\r\n <div class=\"select-no-results\">Aucun r\u00E9sultat</div>\r\n }\r\n </div>\r\n </div>\r\n }\r\n </div>\r\n\r\n @if (error()) {\r\n <div id=\"error-message\" class=\"select-error-message\" role=\"alert\">{{ error() }}</div>\r\n } @else if (success()) {\r\n <div id=\"success-message\" class=\"select-success-message\" role=\"status\">{{ success() }}</div>\r\n } @else if (hint()) {\r\n <div id=\"hint-message\" class=\"select-hint\">{{ hint() }}</div>\r\n }\r\n</div>\r\n", styles: [":host{display:block;width:100%;max-width:18.75rem}:host.full-width{max-width:none}.select-container{width:100%;display:flex;flex-direction:column;gap:var(--form-field-gap)}.select-trigger-wrapper{position:relative}.select-label{display:block;color:var(--text-color);font-size:.875rem;font-weight:500;cursor:pointer}.select-trigger{display:flex;align-items:center;justify-content:space-between;width:100%;height:2.5rem;padding:0 1rem;background:var(--surface-0);border:.125rem solid var(--surface-border);border-radius:var(--border-radius);cursor:pointer;box-sizing:border-box}.select-trigger:focus{border-color:var(--primary-color);outline:none;box-shadow:0 0 0 .125rem var(--focus-ring-color)}:host.error .select-trigger{border-color:var(--danger-color)}:host.error .select-trigger:focus{box-shadow:0 0 0 .125rem var(--focus-ring-error)}:host.success .select-trigger{border-color:var(--success-color)}:host.success .select-trigger:focus{box-shadow:0 0 0 .125rem var(--focus-ring-success)}:host.disabled .select-trigger{background:var(--surface-ground);cursor:not-allowed;opacity:var(--opacity-disabled)}:host.filled .select-trigger{background:var(--surface-ground);border:.125rem solid var(--surface-border)}:host.filled .select-trigger:hover:not([disabled]):not(:focus){background:var(--surface-hover)}.select-value{flex:1;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.select-actions{display:flex;align-items:center;gap:.5rem;flex-shrink:0}.select-clear{background:none;border:none;cursor:pointer;padding:0;color:var(--text-color-secondary);display:flex}.select-clear:hover{color:var(--danger-color)}.select-loader-trigger{width:1rem;height:1rem;border:2px solid var(--surface-border);border-top-color:var(--primary-color);border-radius:50%;animation:spin .8s linear infinite}.select-arrow{transition:transform .2s;font-size:1rem;color:var(--text-color-secondary)}:host[aria-expanded=true] .select-arrow{transform:rotate(180deg)}.select-dropdown.open-top{top:auto;bottom:calc(100% + .25rem)}.select-dropdown{position:absolute;top:calc(100% + .25rem);left:0;right:0;z-index:var(--z-index-dropdown);background:var(--surface-0);border:.125rem solid var(--surface-border);border-radius:var(--border-radius);box-shadow:var(--shadow-lg)}.select-search{position:relative;padding:.5rem;border-bottom:.0625rem solid var(--surface-border)}.select-search-icon{position:absolute;left:1.25rem;top:50%;transform:translateY(-50%);color:var(--text-color-secondary);font-size:.875rem;pointer-events:none}.select-search input{width:100%;height:2rem;padding:0 .75rem 0 2rem;background:var(--surface-ground);border:.0625rem solid var(--surface-border);border-radius:var(--border-radius);color:var(--text-color);font-size:.875rem;outline:none;box-sizing:border-box;transition:border-color .15s}.select-search input::placeholder{color:var(--text-color-secondary)}.select-search input:focus{border-color:var(--primary-color)}.select-options{max-height:15rem;overflow-y:auto}.select-group-label{padding:.5rem 1rem;font-size:.75rem;font-weight:600;color:var(--text-color-secondary);background:var(--surface-ground)}.select-option{padding:.625rem 1rem;cursor:pointer;display:flex;align-items:flex-start;gap:.5rem}.select-option:hover{background:var(--surface-hover)}.select-option.selected{background:rgba(var(--primary-color-rgb),.1);color:var(--primary-color);font-weight:500}.select-option.focused{background:var(--surface-hover)}.select-option.disabled{opacity:var(--opacity-disabled);cursor:not-allowed}.select-option i{flex-shrink:0;line-height:1.4}.select-option-content{flex:1;min-width:0;display:flex;flex-direction:column;gap:.125rem}.select-option-label{min-width:0}.select-option-description{font-size:.75rem;color:var(--text-color-secondary)}.select-error-message,.select-success-message,.select-hint{font-size:.875rem}.select-error-message{color:var(--danger-color)}.select-success-message{color:var(--success-color)}.select-hint{color:var(--text-color-secondary)}:host.small .select-trigger{text-overflow:ellipsis;height:2rem;font-size:.875rem}:host.large .select-trigger{text-overflow:ellipsis;height:3rem;font-size:1.125rem}@keyframes spin{to{transform:rotate(360deg)}}\n"] }]
|
|
4126
|
-
}], ctorParameters: () => [], propDecorators: { value: [{ type: i0.Input, args: [{ isSignal: true, alias: "value", required: false }] }, { type: i0.Output, args: ["valueChange"] }], disabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "disabled", required: false }] }, { type: i0.Output, args: ["disabledChange"] }], touched: [{ type: i0.Input, args: [{ isSignal: true, alias: "touched", required: false }] }, { type: i0.Output, args: ["touchedChange"] }], size: [{ type: i0.Input, args: [{ isSignal: true, alias: "size", required: false }] }], variant: [{ type: i0.Input, args: [{ isSignal: true, alias: "variant", required: false }] }], searchable: [{ type: i0.Input, args: [{ isSignal: true, alias: "searchable", required: false }] }], multiple: [{ type: i0.Input, args: [{ isSignal: true, alias: "multiple", required: false }] }], clearable: [{ type: i0.Input, args: [{ isSignal: true, alias: "clearable", required: false }] }], loading: [{ type: i0.Input, args: [{ isSignal: true, alias: "loading", required: false }] }], fullWidth: [{ type: i0.Input, args: [{ isSignal: true, alias: "fullWidth", required: false }] }], required: [{ type: i0.Input, args: [{ isSignal: true, alias: "required", required: false }] }], options: [{ type: i0.Input, args: [{ isSignal: true, alias: "options", required: false }] }], label: [{ type: i0.Input, args: [{ isSignal: true, alias: "label", required: false }] }], placeholder: [{ type: i0.Input, args: [{ isSignal: true, alias: "placeholder", required: false }] }], multiplePlaceholder: [{ type: i0.Input, args: [{ isSignal: true, alias: "multiplePlaceholder", required: false }] }], error: [{ type: i0.Input, args: [{ isSignal: true, alias: "error", required: false }] }], success: [{ type: i0.Input, args: [{ isSignal: true, alias: "success", required: false }] }], hint: [{ type: i0.Input, args: [{ isSignal: true, alias: "hint", required: false }] }], ariaLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "ariaLabel", required: false }] }], maxSelections: [{ type: i0.Input, args: [{ isSignal: true, alias: "maxSelections", required: false }] }], minSelections: [{ type: i0.Input, args: [{ isSignal: true, alias: "minSelections", required: false }] }], compareWith: [{ type: i0.Input, args: [{ isSignal: true, alias: "compareWith", required: false }] }], searchConfig: [{ type: i0.Input, args: [{ isSignal: true, alias: "searchConfig", required: false }] }], opened: [{ type: i0.Output, args: ["opened"] }], closed: [{ type: i0.Output, args: ["closed"] }], searched: [{ type: i0.Output, args: ["searched"] }], scrollEnd: [{ type: i0.Output, args: ["scrollEnd"] }] } });
|
|
4352
|
+
}, template: "<div class=\"select-container\">\r\n @if (label()) {\r\n <!-- label[for] delegates focus to its control natively; the click handler is a convenience. -->\r\n <!-- eslint-disable-next-line @angular-eslint/template/click-events-have-key-events, @angular-eslint/template/interactive-supports-focus -->\r\n <label class=\"select-label\" [attr.for]=\"selectId\" (click)=\"focusSelect()\" [class.required]=\"required()\">\r\n {{ label() }}\r\n @if (required()) { <span class=\"required-mark\">*</span> }\r\n </label>\r\n }\r\n\r\n <div class=\"select-trigger-wrapper\">\r\n <div class=\"select-trigger\"\r\n role=\"combobox\"\r\n [id]=\"selectId\"\r\n [attr.aria-expanded]=\"isOpen()\"\r\n [attr.aria-haspopup]=\"'listbox'\"\r\n [attr.aria-controls]=\"selectId + '-listbox'\"\r\n [attr.aria-activedescendant]=\"activeDescendant()\"\r\n [attr.aria-label]=\"computedAriaLabel()\"\r\n [attr.aria-invalid]=\"!!error()\"\r\n [attr.aria-required]=\"required()\"\r\n [attr.aria-disabled]=\"disabled()\"\r\n [attr.aria-busy]=\"loading()\"\r\n [attr.aria-describedby]=\"describedBy()\"\r\n [attr.tabindex]=\"disabled() || loading() ? -1 : 0\"\r\n (keydown)=\"handleKeydown($event)\"\r\n (click)=\"toggle()\">\r\n <div class=\"select-value\">\r\n <span [class.placeholder]=\"!hasValue()\">\r\n {{ selectedLabel() }}\r\n </span>\r\n </div>\r\n <div class=\"select-actions\">\r\n @if (clearable() && hasValue() && !disabled()) {\r\n <button class=\"select-clear\" (click)=\"clear($event)\">\r\n <i class=\"ph ph-x\"></i>\r\n </button>\r\n }\r\n @if (loading()) {\r\n <div class=\"select-loader-trigger\"></div>\r\n } @else {\r\n <i class=\"ph ph-caret-down select-arrow\"></i>\r\n }\r\n </div>\r\n </div>\r\n\r\n <ng-template #panelTpl>\r\n <div class=\"select-dropdown\" [class.open-top]=\"resolvedSide() === 'top'\">\r\n @if (searchable()) {\r\n <div class=\"select-search\">\r\n <i class=\"ph ph-magnifying-glass select-search-icon\"></i>\r\n <input type=\"text\"\r\n [placeholder]=\"searchConfig().placeholder\"\r\n [value]=\"searchTerm()\"\r\n (input)=\"onSearch($event)\"\r\n (click)=\"$event.stopPropagation()\">\r\n </div>\r\n }\r\n <div class=\"select-options\"\r\n role=\"listbox\"\r\n [id]=\"selectId + '-listbox'\"\r\n [attr.aria-multiselectable]=\"multiple() || null\"\r\n (scroll)=\"onScroll($event)\">\r\n @for (item of filteredOptions(); track getOptionKey(item)) {\r\n @if (isOptionGroup(item)) {\r\n <div class=\"select-group\" role=\"group\" [attr.aria-label]=\"item.label\">\r\n <div class=\"select-group-label\">{{ item.label }}</div>\r\n @for (opt of item.options; track opt.label) {\r\n <!-- option in a listbox: keyboard is handled at the widget level (arrows + aria-activedescendant). -->\r\n <!-- eslint-disable-next-line @angular-eslint/template/click-events-have-key-events -->\r\n <div class=\"select-option\"\r\n role=\"option\"\r\n [id]=\"selectId + '-' + opt.value\"\r\n [attr.aria-selected]=\"isSelected(opt)\"\r\n [attr.aria-disabled]=\"(item.disabled || opt.disabled) ? true : null\"\r\n [attr.tabindex]=\"(item.disabled || opt.disabled) ? -1 : null\"\r\n [class.selected]=\"isSelected(opt)\"\r\n [class.disabled]=\"item.disabled || opt.disabled\"\r\n [class.focused]=\"getFlatIndex(opt) === focusedIndex()\"\r\n (click)=\"select(opt, !!item.disabled)\">\r\n @if (opt.icon) { <i [class]=\"'ph ph-' + opt.icon\" aria-hidden=\"true\"></i> }\r\n <div class=\"select-option-content\">\r\n <span class=\"select-option-label\">{{ opt.label }}</span>\r\n @if (opt.description) { <span class=\"select-option-description\">{{ opt.description }}</span> }\r\n </div>\r\n </div>\r\n }\r\n </div>\r\n } @else {\r\n <!-- option in a listbox: keyboard is handled at the widget level (arrows + aria-activedescendant). -->\r\n <!-- eslint-disable-next-line @angular-eslint/template/click-events-have-key-events -->\r\n <div class=\"select-option\"\r\n role=\"option\"\r\n [id]=\"selectId + '-' + item.value\"\r\n [attr.aria-selected]=\"isSelected(item)\"\r\n [attr.aria-disabled]=\"item.disabled ? true : null\"\r\n [attr.tabindex]=\"item.disabled ? -1 : null\"\r\n [class.selected]=\"isSelected(item)\"\r\n [class.disabled]=\"item.disabled\"\r\n [class.focused]=\"getFlatIndex(item) === focusedIndex()\"\r\n (click)=\"select(item)\">\r\n @if (item.icon) { <i [class]=\"'ph ph-' + item.icon\" aria-hidden=\"true\"></i> }\r\n <div class=\"select-option-content\">\r\n <span class=\"select-option-label\">{{ item.label }}</span>\r\n @if (item.description) { <span class=\"select-option-description\">{{ item.description }}</span> }\r\n </div>\r\n </div>\r\n }\r\n } @empty {\r\n <div class=\"select-no-results\">Aucun r\u00E9sultat</div>\r\n }\r\n </div>\r\n </div>\r\n </ng-template>\r\n </div>\r\n\r\n @if (error()) {\r\n <div id=\"error-message\" class=\"select-error-message\" role=\"alert\">{{ error() }}</div>\r\n } @else if (success()) {\r\n <div id=\"success-message\" class=\"select-success-message\" role=\"status\">{{ success() }}</div>\r\n } @else if (hint()) {\r\n <div id=\"hint-message\" class=\"select-hint\">{{ hint() }}</div>\r\n }\r\n</div>\r\n", styles: [":host{display:block;width:100%;max-width:18.75rem}:host.full-width{max-width:none}.select-container{width:100%;display:flex;flex-direction:column;gap:var(--form-field-gap)}.select-trigger-wrapper{position:relative}.select-label{display:block;color:var(--text-color);font-size:.875rem;font-weight:500;cursor:pointer}.select-trigger{display:flex;align-items:center;justify-content:space-between;width:100%;height:2.5rem;padding:0 1rem;background:var(--surface-0);border:.125rem solid var(--surface-border);border-radius:var(--border-radius);cursor:pointer;box-sizing:border-box}.select-trigger:focus{border-color:var(--primary-color);outline:none;box-shadow:0 0 0 .125rem var(--focus-ring-color)}:host.error .select-trigger{border-color:var(--danger-color)}:host.error .select-trigger:focus{box-shadow:0 0 0 .125rem var(--focus-ring-error)}:host.success .select-trigger{border-color:var(--success-color)}:host.success .select-trigger:focus{box-shadow:0 0 0 .125rem var(--focus-ring-success)}:host.disabled .select-trigger{background:var(--surface-ground);cursor:not-allowed;opacity:var(--opacity-disabled)}:host.filled .select-trigger{background:var(--surface-ground);border:.125rem solid var(--surface-border)}:host.filled .select-trigger:hover:not([disabled]):not(:focus){background:var(--surface-hover)}.select-value{flex:1;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.select-actions{display:flex;align-items:center;gap:.5rem;flex-shrink:0}.select-clear{background:none;border:none;cursor:pointer;padding:0;color:var(--text-color-secondary);display:flex}.select-clear:hover{color:var(--danger-color)}.select-loader-trigger{width:1rem;height:1rem;border:2px solid var(--surface-border);border-top-color:var(--primary-color);border-radius:50%;animation:spin .8s linear infinite}.select-arrow{transition:transform .2s;font-size:1rem;color:var(--text-color-secondary)}:host[aria-expanded=true] .select-arrow{transform:rotate(180deg)}.select-dropdown{display:flex;flex-direction:column;overflow:hidden;pointer-events:auto;background:var(--surface-0);border:.125rem solid var(--surface-border);border-radius:var(--border-radius);box-shadow:var(--shadow-lg)}.select-search{position:relative;flex-shrink:0;padding:.5rem;border-bottom:.0625rem solid var(--surface-border)}.select-search-icon{position:absolute;left:1.25rem;top:50%;transform:translateY(-50%);color:var(--text-color-secondary);font-size:.875rem;pointer-events:none}.select-search input{width:100%;height:2rem;padding:0 .75rem 0 2rem;background:var(--surface-ground);border:.0625rem solid var(--surface-border);border-radius:var(--border-radius);color:var(--text-color);font-size:.875rem;outline:none;box-sizing:border-box;transition:border-color .15s}.select-search input::placeholder{color:var(--text-color-secondary)}.select-search input:focus{border-color:var(--primary-color)}.select-options{flex:0 1 auto;max-height:15rem;overflow-y:auto}.select-group-label{padding:.5rem 1rem;font-size:.75rem;font-weight:600;color:var(--text-color-secondary);background:var(--surface-ground)}.select-option{padding:.625rem 1rem;cursor:pointer;display:flex;align-items:flex-start;gap:.5rem}.select-option:hover{background:var(--surface-hover)}.select-option.selected{background:rgba(var(--primary-color-rgb),.1);color:var(--primary-color);font-weight:500}.select-option.focused{background:var(--surface-hover)}.select-option.disabled{opacity:var(--opacity-disabled);cursor:not-allowed}.select-option i{flex-shrink:0;line-height:1.4}.select-option-content{flex:1;min-width:0;display:flex;flex-direction:column;gap:.125rem}.select-option-label{min-width:0}.select-option-description{font-size:.75rem;color:var(--text-color-secondary)}.select-error-message,.select-success-message,.select-hint{font-size:.875rem}.select-error-message{color:var(--danger-color)}.select-success-message{color:var(--success-color)}.select-hint{color:var(--text-color-secondary)}:host.small .select-trigger{text-overflow:ellipsis;height:2rem;font-size:.875rem}:host.large .select-trigger{text-overflow:ellipsis;height:3rem;font-size:1.125rem}@keyframes spin{to{transform:rotate(360deg)}}\n"] }]
|
|
4353
|
+
}], ctorParameters: () => [], propDecorators: { panelTpl: [{ type: i0.ViewChild, args: ['panelTpl', { isSignal: true }] }], value: [{ type: i0.Input, args: [{ isSignal: true, alias: "value", required: false }] }, { type: i0.Output, args: ["valueChange"] }], disabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "disabled", required: false }] }, { type: i0.Output, args: ["disabledChange"] }], touched: [{ type: i0.Input, args: [{ isSignal: true, alias: "touched", required: false }] }, { type: i0.Output, args: ["touchedChange"] }], size: [{ type: i0.Input, args: [{ isSignal: true, alias: "size", required: false }] }], variant: [{ type: i0.Input, args: [{ isSignal: true, alias: "variant", required: false }] }], searchable: [{ type: i0.Input, args: [{ isSignal: true, alias: "searchable", required: false }] }], multiple: [{ type: i0.Input, args: [{ isSignal: true, alias: "multiple", required: false }] }], clearable: [{ type: i0.Input, args: [{ isSignal: true, alias: "clearable", required: false }] }], loading: [{ type: i0.Input, args: [{ isSignal: true, alias: "loading", required: false }] }], fullWidth: [{ type: i0.Input, args: [{ isSignal: true, alias: "fullWidth", required: false }] }], required: [{ type: i0.Input, args: [{ isSignal: true, alias: "required", required: false }] }], options: [{ type: i0.Input, args: [{ isSignal: true, alias: "options", required: false }] }], label: [{ type: i0.Input, args: [{ isSignal: true, alias: "label", required: false }] }], placeholder: [{ type: i0.Input, args: [{ isSignal: true, alias: "placeholder", required: false }] }], multiplePlaceholder: [{ type: i0.Input, args: [{ isSignal: true, alias: "multiplePlaceholder", required: false }] }], error: [{ type: i0.Input, args: [{ isSignal: true, alias: "error", required: false }] }], success: [{ type: i0.Input, args: [{ isSignal: true, alias: "success", required: false }] }], hint: [{ type: i0.Input, args: [{ isSignal: true, alias: "hint", required: false }] }], ariaLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "ariaLabel", required: false }] }], maxSelections: [{ type: i0.Input, args: [{ isSignal: true, alias: "maxSelections", required: false }] }], minSelections: [{ type: i0.Input, args: [{ isSignal: true, alias: "minSelections", required: false }] }], compareWith: [{ type: i0.Input, args: [{ isSignal: true, alias: "compareWith", required: false }] }], searchConfig: [{ type: i0.Input, args: [{ isSignal: true, alias: "searchConfig", required: false }] }], opened: [{ type: i0.Output, args: ["opened"] }], closed: [{ type: i0.Output, args: ["closed"] }], searched: [{ type: i0.Output, args: ["searched"] }], scrollEnd: [{ type: i0.Output, args: ["scrollEnd"] }] } });
|
|
4127
4354
|
|
|
4128
4355
|
const SIDEBAR_CONFIG = new InjectionToken('SIDEBAR_CONFIG', {
|
|
4129
4356
|
factory: () => ({
|
|
@@ -6153,5 +6380,5 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.4", ngImpor
|
|
|
6153
6380
|
* Generated bundle index. Do not edit.
|
|
6154
6381
|
*/
|
|
6155
6382
|
|
|
6156
|
-
export { CHECKBOX_CONFIG, CUSTOMER_CONTEXT_SERVICE, INPUT_LABELS, MODAL_CONFIG, ModalService, NgxTranslateProvider, PAGINATION_CONFIG, PROGRESSBAR_CONFIG, PSH_THEME_OPTIONS, PshAlertComponent, PshAvatarComponent, PshBadgeComponent, PshButtonComponent, PshCardComponent, PshCheckboxComponent, PshClickOutsideDirective, PshCollapseComponent, PshDropdownComponent, PshFlowStepComponent, PshFocusTrapDirective, PshHorizontalCardComponent, PshInfoCardComponent, PshInputComponent, PshLiveAnnouncerService, PshMenuComponent, PshModalComponent, PshOverlayPositionService, PshOverlayService, PshPaginationComponent, PshProgressbarComponent, PshRadioComponent, PshSelectComponent, PshSidebarComponent, PshSpinLoaderComponent, PshStatCardComponent, PshStateFlowIndicatorComponent, PshStepComponent, PshStepperComponent, PshSwitchComponent, PshTabBarComponent, PshTabComponent, PshTableComponent, PshTabsComponent, PshTagComponent, PshTextareaComponent, PshToastComponent, PshToastService, PshTooltipComponent, RADIO_CONFIG, RADIO_STYLES, SIDEBAR_CONFIG, SPINLOADER_CONFIG, STATE_FLOW_INDICATOR_CONFIG, STEPPER_CONFIG, SWITCH_CONFIG, ScrollService, TABLE_CONFIG, TABS_CONFIG, TAB_BAR_CONFIG, TAG_CONFIG, TEXTAREA_LABELS, TOAST_CONFIG, TOOLTIP_CONFIG, TRANSLATION_PROVIDER, ThemeService, ToastComponent, ToastService, provideTranslation };
|
|
6383
|
+
export { CHECKBOX_CONFIG, CUSTOMER_CONTEXT_SERVICE, INPUT_LABELS, MODAL_CONFIG, ModalService, NgxTranslateProvider, PAGINATION_CONFIG, PROGRESSBAR_CONFIG, PSH_THEME_OPTIONS, PshAlertComponent, PshAvatarComponent, PshBadgeComponent, PshButtonComponent, PshCardComponent, PshCheckboxComponent, PshClickOutsideDirective, PshCollapseComponent, PshDropdownComponent, PshFlowStepComponent, PshFocusTrapDirective, PshHorizontalCardComponent, PshInfoCardComponent, PshInputComponent, PshLiveAnnouncerService, PshMenuComponent, PshModalComponent, PshOverlayPositionService, PshOverlayService, PshPaginationComponent, PshPortalService, PshProgressbarComponent, PshRadioComponent, PshSelectComponent, PshSidebarComponent, PshSpinLoaderComponent, PshStatCardComponent, PshStateFlowIndicatorComponent, PshStepComponent, PshStepperComponent, PshSwitchComponent, PshTabBarComponent, PshTabComponent, PshTableComponent, PshTabsComponent, PshTagComponent, PshTextareaComponent, PshToastComponent, PshToastService, PshTooltipComponent, RADIO_CONFIG, RADIO_STYLES, SIDEBAR_CONFIG, SPINLOADER_CONFIG, STATE_FLOW_INDICATOR_CONFIG, STEPPER_CONFIG, SWITCH_CONFIG, ScrollService, TABLE_CONFIG, TABS_CONFIG, TAB_BAR_CONFIG, TAG_CONFIG, TEXTAREA_LABELS, TOAST_CONFIG, TOOLTIP_CONFIG, TRANSLATION_PROVIDER, ThemeService, ToastComponent, ToastService, provideTranslation };
|
|
6157
6384
|
//# sourceMappingURL=ps-helix.mjs.map
|