@energycap/components 0.39.16 → 0.39.17-ECAP-23124-menu-item-divider-improvements.20240523-1134
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/esm2020/lib/controls/combobox/combobox.component.mjs +32 -40
- package/esm2020/lib/controls/menu/menu.component.mjs +67 -39
- package/fesm2015/energycap-components.mjs +1020 -1000
- package/fesm2015/energycap-components.mjs.map +1 -1
- package/fesm2020/energycap-components.mjs +1009 -990
- package/fesm2020/energycap-components.mjs.map +1 -1
- package/lib/controls/combobox/combobox.component.d.ts +5 -0
- package/lib/controls/menu/menu.component.d.ts +26 -11
- package/package.json +1 -1
@@ -1479,205 +1479,229 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.9", ngImpor
|
|
1479
1479
|
}] } });
|
1480
1480
|
|
1481
1481
|
/**
|
1482
|
-
*
|
1483
|
-
*
|
1484
|
-
* @export
|
1482
|
+
* Service to help with interfacing with the window object
|
1483
|
+
* and navigating around the application (going outside of the Angular 2+ router)
|
1485
1484
|
*/
|
1486
|
-
class
|
1485
|
+
class WindowService {
|
1487
1486
|
/**
|
1488
|
-
*
|
1489
|
-
*
|
1490
|
-
*
|
1491
|
-
*
|
1492
|
-
*
|
1487
|
+
* Tracks if there are any unsaved changes that the user could lose.
|
1488
|
+
*
|
1489
|
+
* It is set up as `get` only because it is set with `addNavigateAwayPrompt`.
|
1490
|
+
*
|
1491
|
+
* This also includes adding a prompt to the window itself (in addition to
|
1492
|
+
* working with the `CanDeactivateUnsavedChanges` guard) to cover page reloads
|
1493
|
+
* which do not trigger router events.
|
1493
1494
|
*/
|
1494
|
-
|
1495
|
-
this.
|
1496
|
-
|
1497
|
-
|
1498
|
-
|
1495
|
+
get hasUnsavedChanges() {
|
1496
|
+
return this._hasUnsavedChanges;
|
1497
|
+
}
|
1498
|
+
/**
|
1499
|
+
* Expose the innerWidth on the window global. Protects against errors when code
|
1500
|
+
* is running on a non-browser platform.
|
1501
|
+
*/
|
1502
|
+
get innerWidth() {
|
1503
|
+
return window ? window.innerWidth : undefined;
|
1504
|
+
}
|
1505
|
+
constructor(router, activatedRoute) {
|
1506
|
+
this.router = router;
|
1507
|
+
this.activatedRoute = activatedRoute;
|
1508
|
+
this._hasUnsavedChanges = false;
|
1499
1509
|
/**
|
1500
|
-
*
|
1510
|
+
* Function called when the window `beforeunload` event is fired.
|
1511
|
+
*
|
1512
|
+
* A reference to the function that was passed to `window.addEventListener`
|
1513
|
+
* must be retained for `window.removeEventListener` to function properly.
|
1514
|
+
*
|
1515
|
+
* Some browsers require the event's `returnValue` to be set to show the confirmation
|
1516
|
+
* dialog.
|
1517
|
+
* @see https://developer.mozilla.org/en-US/docs/Web/API/Window/beforeunload_event
|
1501
1518
|
*/
|
1502
|
-
this.
|
1519
|
+
this.beforeUnloadFunction = (event) => {
|
1520
|
+
// Cancel the event as stated by the standard.
|
1521
|
+
event.preventDefault();
|
1522
|
+
// Chrome requires returnValue to be set.
|
1523
|
+
event.returnValue = '';
|
1524
|
+
};
|
1525
|
+
if (window) {
|
1526
|
+
this.resized = fromEvent(window, 'resize');
|
1527
|
+
}
|
1503
1528
|
}
|
1504
1529
|
/**
|
1505
|
-
*
|
1506
|
-
* @see https://angular.io/guide/lifecycle-hooks
|
1530
|
+
* Navigates to the previous page the user had visited
|
1507
1531
|
*/
|
1508
|
-
|
1509
|
-
|
1532
|
+
goBack() {
|
1533
|
+
window.history.back();
|
1510
1534
|
}
|
1511
|
-
/**
|
1512
|
-
*
|
1513
|
-
* @see https://angular.io/guide/lifecycle-hooks
|
1535
|
+
/**An abstraction around the browsers window history length.
|
1536
|
+
* Returns zero if unable to access or running outside a browser context
|
1514
1537
|
*/
|
1515
|
-
|
1516
|
-
|
1538
|
+
getHistoryLength() {
|
1539
|
+
return window?.history?.length || 0;
|
1517
1540
|
}
|
1518
1541
|
/**
|
1519
|
-
*
|
1542
|
+
* Navigate to any url you know the path to
|
1543
|
+
* @param url The URL to navigate to
|
1520
1544
|
*
|
1521
|
-
* @
|
1545
|
+
* @deprecated For legacy support only; use `router.navigateByUrl` instead
|
1522
1546
|
*/
|
1523
|
-
|
1524
|
-
|
1525
|
-
if (
|
1526
|
-
|
1527
|
-
|
1547
|
+
async navigateToUrl(url) {
|
1548
|
+
try {
|
1549
|
+
if (url.indexOf('/app/') === 0) {
|
1550
|
+
await this.router.navigateByUrl(url.substring(5));
|
1551
|
+
}
|
1552
|
+
else {
|
1553
|
+
await this.router.navigateByUrl(url);
|
1528
1554
|
}
|
1529
1555
|
}
|
1530
|
-
|
1531
|
-
|
1532
|
-
|
1533
|
-
|
1534
|
-
|
1535
|
-
if (!this.popperRef) {
|
1536
|
-
// Add the popper template as an embedded view since PopperJS
|
1537
|
-
// manipulates DOM elements.
|
1538
|
-
this.popupViewRef = this.viewContainer.createEmbeddedView(this.popup);
|
1539
|
-
// Since popper needs real DOM elements, grab the first non-comment
|
1540
|
-
// DOM element to use as our anchor.
|
1541
|
-
let anchorElement = this.popupViewRef.rootNodes.find(elem => { return elem.nodeName !== "#text"; });
|
1542
|
-
// Use the parents elements as our DOM elements to Popper
|
1543
|
-
this.popperRef = new Popper(this.templateViewRef.rootNodes[0], anchorElement, this.popperOptions);
|
1544
|
-
PopupContainerDirective.GlobalPopupRef = this;
|
1545
|
-
this.popperStatusChange.emit('visible');
|
1556
|
+
catch (e) {
|
1557
|
+
// If the router throws we will try to navigate to the fully qualified url as a last ditch effort.
|
1558
|
+
// This can happen if we missed a link that needs to be converted to ng5 or our ng1Href directive
|
1559
|
+
// didn't handle a link correctly
|
1560
|
+
window.location.href = url;
|
1546
1561
|
}
|
1547
1562
|
}
|
1548
1563
|
/**
|
1549
|
-
*
|
1550
|
-
*
|
1551
|
-
* @memberof PopupContainerDirective
|
1564
|
+
* Adds a `beforeunload` function to the window to alert the user that there are about to leave
|
1565
|
+
* the current page and ask if they'd like to leave or stay
|
1552
1566
|
*/
|
1553
|
-
|
1554
|
-
|
1555
|
-
|
1556
|
-
this.globalCloseSubscription = undefined;
|
1557
|
-
}
|
1558
|
-
if (this.popperRef && this.popupViewRef) {
|
1559
|
-
this.popupViewRef.destroy();
|
1560
|
-
this.popperRef.destroy();
|
1561
|
-
this.popperRef = undefined;
|
1562
|
-
this.popperStatusChange.emit('hidden');
|
1563
|
-
}
|
1567
|
+
addNavigateAwayPrompt() {
|
1568
|
+
this._hasUnsavedChanges = true;
|
1569
|
+
window.addEventListener("beforeunload", this.beforeUnloadFunction);
|
1564
1570
|
}
|
1565
1571
|
/**
|
1566
|
-
*
|
1572
|
+
* Removes the `beforeunload` function added to the window
|
1567
1573
|
*/
|
1568
|
-
|
1569
|
-
|
1570
|
-
|
1571
|
-
}
|
1572
|
-
}
|
1573
|
-
fixPosition(minWidthNone, appendToBody = false) {
|
1574
|
-
if (this.popperRef && this.popperRef['reference'] && this.popperRef['popper']) {
|
1575
|
-
let popupEl = this.popperRef['popper'];
|
1576
|
-
// Reset width style previously assigned because the content may have
|
1577
|
-
// changed and the auto width would be different
|
1578
|
-
this.renderer.removeStyle(popupEl, 'width');
|
1579
|
-
this.renderer.setStyle(popupEl, 'position', 'fixed');
|
1580
|
-
if (appendToBody) {
|
1581
|
-
const bodyEl = this.document.querySelector('body');
|
1582
|
-
const popupParent = this.renderer.parentNode(popupEl);
|
1583
|
-
if (popupParent !== bodyEl) {
|
1584
|
-
this.renderer.appendChild(bodyEl, popupEl);
|
1585
|
-
}
|
1586
|
-
}
|
1587
|
-
let toggleEl = this.popperRef['reference'];
|
1588
|
-
let width = popupEl.offsetWidth;
|
1589
|
-
let boundaries = popupEl.getBoundingClientRect();
|
1590
|
-
let left = boundaries.left;
|
1591
|
-
let coords = toggleEl.getBoundingClientRect();
|
1592
|
-
// Set the top of our menu to the bottom of the toggle element
|
1593
|
-
let top = coords.bottom;
|
1594
|
-
if (this.popperOptions && this.popperOptions.placement) {
|
1595
|
-
if (this.popperOptions.placement === 'bottom-start' || this.popperOptions.placement === 'top-start') {
|
1596
|
-
left = coords.left;
|
1597
|
-
}
|
1598
|
-
else {
|
1599
|
-
left = coords.right - ((minWidthNone || width > coords.width) ? width : coords.width);
|
1600
|
-
}
|
1601
|
-
}
|
1602
|
-
// if it won't fit (with 10px space before hitting the window edge), flip it
|
1603
|
-
if (boundaries.height + top + 10 > window.innerHeight) {
|
1604
|
-
top = coords.top - boundaries.height;
|
1605
|
-
}
|
1606
|
-
this.renderer.setStyle(popupEl, 'transform', 'none');
|
1607
|
-
this.renderer.setStyle(popupEl, 'left', left + 'px');
|
1608
|
-
this.renderer.setStyle(popupEl, 'top', top + 'px');
|
1609
|
-
this.renderer.setStyle(popupEl, 'width', width + 'px');
|
1610
|
-
if (!minWidthNone) {
|
1611
|
-
this.renderer.setStyle(popupEl, 'min-width', coords.width + 'px');
|
1612
|
-
}
|
1613
|
-
}
|
1574
|
+
removeNavigateAwayPrompt() {
|
1575
|
+
this._hasUnsavedChanges = false;
|
1576
|
+
window.removeEventListener("beforeunload", this.beforeUnloadFunction);
|
1614
1577
|
}
|
1615
|
-
}
|
1616
|
-
/**
|
1617
|
-
* Global reference to the currently displayed popup; only
|
1618
|
-
* one popup directive can be in `show` state at a given time.
|
1619
|
-
*
|
1620
|
-
* @memberof PopupContainerDirective
|
1621
|
-
*/
|
1622
|
-
PopupContainerDirective.GlobalPopupRef = undefined;
|
1623
|
-
PopupContainerDirective.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.2.9", ngImport: i0, type: PopupContainerDirective, deps: [{ token: i0.TemplateRef }, { token: i0.ViewContainerRef }, { token: DOCUMENT }, { token: i0.Renderer2 }], target: i0.ɵɵFactoryTarget.Directive });
|
1624
|
-
PopupContainerDirective.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "15.2.9", type: PopupContainerDirective, selector: "[ecPopup]", inputs: { popup: ["ecPopup", "popup"], popperOptions: ["options", "popperOptions"] }, ngImport: i0 });
|
1625
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.9", ngImport: i0, type: PopupContainerDirective, decorators: [{
|
1626
|
-
type: Directive,
|
1627
|
-
args: [{ selector: '[ecPopup]' }]
|
1628
|
-
}], ctorParameters: function () { return [{ type: i0.TemplateRef }, { type: i0.ViewContainerRef }, { type: undefined, decorators: [{
|
1629
|
-
type: Inject,
|
1630
|
-
args: [DOCUMENT]
|
1631
|
-
}] }, { type: i0.Renderer2 }]; }, propDecorators: { popup: [{
|
1632
|
-
type: Input,
|
1633
|
-
args: ['ecPopup']
|
1634
|
-
}], popperOptions: [{
|
1635
|
-
type: Input,
|
1636
|
-
args: ['options']
|
1637
|
-
}] } });
|
1638
|
-
|
1639
|
-
class ScrollService {
|
1640
|
-
constructor() { }
|
1641
1578
|
/**
|
1642
|
-
*
|
1643
|
-
* the container to bring the target into view.
|
1579
|
+
* Send data to another window.
|
1644
1580
|
*
|
1645
|
-
*
|
1646
|
-
*
|
1647
|
-
*
|
1648
|
-
*
|
1649
|
-
*
|
1581
|
+
* __SECURITY RISK__ - Always use a specific target origin. Failing to provide a specific target origin can allow
|
1582
|
+
* malicious sites to receive the message.
|
1583
|
+
*
|
1584
|
+
* @param targetWindow - Window to send the message to
|
1585
|
+
* @param message - Data to send
|
1586
|
+
* @param targetOrigin - What the URI of the target window must be for the message to be sent.
|
1587
|
+
* If sending data to another EnergyCAP window, this should always be `window.location.origin` to ensure
|
1588
|
+
* that only instances of EnergyCAP app receive the message.
|
1650
1589
|
*/
|
1651
|
-
|
1652
|
-
|
1653
|
-
if (!scrollContainer) {
|
1654
|
-
return;
|
1655
|
-
}
|
1656
|
-
let targetElement = scrollContainer.querySelector(targetElementSelector);
|
1657
|
-
if (!targetElement) {
|
1658
|
-
return;
|
1659
|
-
}
|
1660
|
-
let targetRect = targetElement.getBoundingClientRect();
|
1661
|
-
let containerRect = scrollContainer.getBoundingClientRect();
|
1662
|
-
// Only scroll if the target is outside of the view bounds of the container
|
1663
|
-
if (targetRect.bottom > containerRect.bottom || targetRect.top < containerRect.top) {
|
1664
|
-
scrollContainer.scrollTop =
|
1665
|
-
(targetRect.top - containerRect.top) + scrollContainer.scrollTop - topPadding;
|
1666
|
-
}
|
1590
|
+
postMessage(targetWindow, message, targetOrigin) {
|
1591
|
+
targetWindow.postMessage(message, targetOrigin);
|
1667
1592
|
}
|
1668
1593
|
/**
|
1669
|
-
*
|
1670
|
-
* @param
|
1594
|
+
* Open a new window
|
1595
|
+
* @param url - The URL of the resource to be loaded
|
1671
1596
|
*/
|
1672
|
-
|
1673
|
-
|
1674
|
-
|
1675
|
-
|
1676
|
-
|
1677
|
-
|
1678
|
-
|
1679
|
-
|
1680
|
-
|
1597
|
+
openNew(url) {
|
1598
|
+
window.open(url, '_blank');
|
1599
|
+
}
|
1600
|
+
/**
|
1601
|
+
* A wrapper around the router for changing the query params for the current url
|
1602
|
+
* without creating a new history entry or removing any existing query parameters.
|
1603
|
+
* The provided params are updated if they already exist or added to the url if they don't
|
1604
|
+
*
|
1605
|
+
* @returns a promise that resolves to true if the navigation succeeds, false if something (like a guard) blocks it.
|
1606
|
+
* In normal use, the navigation should succeed unless we use query params to block access to a route the user is already on
|
1607
|
+
*/
|
1608
|
+
async modifyHistoryQueryParamsSubset(queryParams) {
|
1609
|
+
return this.router.navigate([], {
|
1610
|
+
relativeTo: this.activatedRoute,
|
1611
|
+
replaceUrl: true,
|
1612
|
+
queryParams: queryParams,
|
1613
|
+
queryParamsHandling: 'merge',
|
1614
|
+
});
|
1615
|
+
}
|
1616
|
+
/**A wrapper around the default javascript confirm dialog to allow us to unit test dependent code.
|
1617
|
+
* Of course eventually we'd like to have pretty confirmations for everything, but in some cases it wasn't worth the extra time
|
1618
|
+
* so we're using this instead.
|
1619
|
+
*/
|
1620
|
+
confirm(prompt) {
|
1621
|
+
return Promise.resolve(confirm(prompt));
|
1622
|
+
}
|
1623
|
+
/**
|
1624
|
+
* Close the current window or a window instance if one is provided
|
1625
|
+
* @param windowInstance - Window to close (optional)
|
1626
|
+
*/
|
1627
|
+
closeWindow(windowInstance) {
|
1628
|
+
if (windowInstance) {
|
1629
|
+
windowInstance.close();
|
1630
|
+
}
|
1631
|
+
else {
|
1632
|
+
window.close();
|
1633
|
+
}
|
1634
|
+
}
|
1635
|
+
getLocation() {
|
1636
|
+
return window.location.pathname + window.location.hash;
|
1637
|
+
}
|
1638
|
+
/** Get the current value of the full url, including protocol, host and path */
|
1639
|
+
getFullUrl() {
|
1640
|
+
return window.location.href;
|
1641
|
+
}
|
1642
|
+
/** Get the current value of the base url, including protocol, domain and port (if explicitly specified) */
|
1643
|
+
getBaseUrl() {
|
1644
|
+
return window.location.origin;
|
1645
|
+
}
|
1646
|
+
/**
|
1647
|
+
* Reloads the browser window.
|
1648
|
+
* NOT RECOMMENDED. Seek other options for reloading content within Angular before resorting to this.
|
1649
|
+
*/
|
1650
|
+
reloadWindow() {
|
1651
|
+
window.location.reload();
|
1652
|
+
}
|
1653
|
+
}
|
1654
|
+
WindowService.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.2.9", ngImport: i0, type: WindowService, deps: [{ token: i1$2.Router }, { token: i1$2.ActivatedRoute }], target: i0.ɵɵFactoryTarget.Injectable });
|
1655
|
+
WindowService.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "15.2.9", ngImport: i0, type: WindowService, providedIn: 'root' });
|
1656
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.9", ngImport: i0, type: WindowService, decorators: [{
|
1657
|
+
type: Injectable,
|
1658
|
+
args: [{
|
1659
|
+
providedIn: 'root'
|
1660
|
+
}]
|
1661
|
+
}], ctorParameters: function () { return [{ type: i1$2.Router }, { type: i1$2.ActivatedRoute }]; } });
|
1662
|
+
|
1663
|
+
class ScrollService {
|
1664
|
+
constructor() { }
|
1665
|
+
/**
|
1666
|
+
* Given a container and the target element to scroll to, we will set the scroll top on
|
1667
|
+
* the container to bring the target into view.
|
1668
|
+
*
|
1669
|
+
* @param scrollContainerSelector A valid CSS selector string for the scroll container.
|
1670
|
+
* @param targetElementSelector A valid CSS selector string for the target element.
|
1671
|
+
* @param topPadding The amount of space to leave above the target
|
1672
|
+
* to keep it from being pinned to the top of the scrollContainer. Defaults
|
1673
|
+
* to 32px, the default height of a menu item.
|
1674
|
+
*/
|
1675
|
+
scrollToItem(scrollContainerSelector, targetElementSelector, topPadding = 32) {
|
1676
|
+
let scrollContainer = document.querySelector(scrollContainerSelector);
|
1677
|
+
if (!scrollContainer) {
|
1678
|
+
return;
|
1679
|
+
}
|
1680
|
+
let targetElement = scrollContainer.querySelector(targetElementSelector);
|
1681
|
+
if (!targetElement) {
|
1682
|
+
return;
|
1683
|
+
}
|
1684
|
+
let targetRect = targetElement.getBoundingClientRect();
|
1685
|
+
let containerRect = scrollContainer.getBoundingClientRect();
|
1686
|
+
// Only scroll if the target is outside of the view bounds of the container
|
1687
|
+
if (targetRect.bottom > containerRect.bottom || targetRect.top < containerRect.top) {
|
1688
|
+
scrollContainer.scrollTop =
|
1689
|
+
(targetRect.top - containerRect.top) + scrollContainer.scrollTop - topPadding;
|
1690
|
+
}
|
1691
|
+
}
|
1692
|
+
/**
|
1693
|
+
* Return the value of the scrollTop property for an HTMLElement that matches the selector
|
1694
|
+
* @param scrollContainerSelector A valid CSS selector
|
1695
|
+
*/
|
1696
|
+
getCurrentScrollPosition(scrollContainerSelector) {
|
1697
|
+
let scrollContainer = document.querySelector(scrollContainerSelector);
|
1698
|
+
if (scrollContainer) {
|
1699
|
+
return scrollContainer.scrollTop;
|
1700
|
+
}
|
1701
|
+
else {
|
1702
|
+
console.error(`Scroll container '${scrollContainerSelector}' does not exist.`);
|
1703
|
+
return 0;
|
1704
|
+
}
|
1681
1705
|
}
|
1682
1706
|
/**
|
1683
1707
|
* Set the scrollTop of an HTMLElement that matches the selector to a specific position
|
@@ -1723,922 +1747,926 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.9", ngImpor
|
|
1723
1747
|
}]
|
1724
1748
|
}], ctorParameters: function () { return []; } });
|
1725
1749
|
|
1726
|
-
|
1727
|
-
const textboxValidation = (validatorParams) => {
|
1728
|
-
return (control) => {
|
1729
|
-
let validators = [];
|
1730
|
-
// Innocent until proven guilty
|
1731
|
-
validatorParams.valid = true;
|
1732
|
-
if (validatorParams.required) {
|
1733
|
-
validators.push(Validators.required);
|
1734
|
-
}
|
1735
|
-
if (validatorParams.minLength !== undefined) {
|
1736
|
-
validators.push(Validators.minLength(validatorParams.minLength));
|
1737
|
-
}
|
1738
|
-
if (validatorParams.maxLength !== undefined) {
|
1739
|
-
validators.push(Validators.maxLength(validatorParams.maxLength));
|
1740
|
-
}
|
1741
|
-
if (validatorParams.pattern !== undefined) {
|
1742
|
-
validators.push(Validators.pattern(validatorParams.pattern));
|
1743
|
-
}
|
1744
|
-
validators.forEach(validator => {
|
1745
|
-
let validationResult = validator(control);
|
1746
|
-
if (validationResult) {
|
1747
|
-
validatorParams.valid = false;
|
1748
|
-
}
|
1749
|
-
});
|
1750
|
-
if (validatorParams.valid) {
|
1751
|
-
return null;
|
1752
|
-
}
|
1753
|
-
else {
|
1754
|
-
return {
|
1755
|
-
textbox: validatorParams
|
1756
|
-
};
|
1757
|
-
}
|
1758
|
-
};
|
1759
|
-
};
|
1760
|
-
const phoneNumberValidationPattern = '^\\s*(?:\\+?(\\d{1,3}))?[-. (]*(\\d{3})[-. )]*(\\d{3})[-. ]*(\\d{4})(?: *x(\\d+))?\\s*$';
|
1761
|
-
const urlValidationPattern = '([A-Za-z])+(:\/\/)+[^\\s]*';
|
1762
|
-
class TextboxComponent extends FormControlBase {
|
1763
|
-
constructor(validationMessageService, formGroupHelper, translate) {
|
1764
|
-
super(validationMessageService, formGroupHelper);
|
1765
|
-
this.validationMessageService = validationMessageService;
|
1766
|
-
this.formGroupHelper = formGroupHelper;
|
1767
|
-
this.translate = translate;
|
1768
|
-
/**
|
1769
|
-
* Set the value of the input's autocomplete attribute
|
1770
|
-
*/
|
1771
|
-
this.autocomplete = 'off';
|
1772
|
-
/**
|
1773
|
-
* The textbox type
|
1774
|
-
*/
|
1775
|
-
this.type = "text";
|
1776
|
-
/**
|
1777
|
-
* The value of the rows attribute for a textarea. Only applies to multi-line type
|
1778
|
-
*/
|
1779
|
-
this.rows = 3;
|
1780
|
-
/**
|
1781
|
-
* If set to true, we will select all text within the input if
|
1782
|
-
* autofocus is also set to true
|
1783
|
-
*/
|
1784
|
-
this.selectOnAutofocus = false;
|
1785
|
-
/**
|
1786
|
-
* If set to true, we will upper case on focus out
|
1787
|
-
*/
|
1788
|
-
this.upperCase = false;
|
1789
|
-
/**
|
1790
|
-
* Validation pattern for the input. This is determined on the input type specified
|
1791
|
-
*/
|
1792
|
-
this.validationPattern = '';
|
1793
|
-
}
|
1794
|
-
ngOnChanges(changes) {
|
1795
|
-
super.ngOnChanges(changes);
|
1796
|
-
}
|
1750
|
+
class NavItemActiveDirective {
|
1797
1751
|
/**
|
1798
|
-
*
|
1752
|
+
* Determines whether the directive will try to make an exact match on the url or not
|
1753
|
+
* If false, the directive will add the active class if the first part of the url matches
|
1754
|
+
* the active route.
|
1755
|
+
* see: https://angular.io/api/router/Router#isactive
|
1799
1756
|
*/
|
1800
|
-
|
1801
|
-
|
1802
|
-
|
1803
|
-
if (this.type === 'tel') {
|
1804
|
-
this.validationPattern = phoneNumberValidationPattern;
|
1805
|
-
}
|
1806
|
-
else if (this.type === 'url') {
|
1807
|
-
this.validationPattern = urlValidationPattern;
|
1757
|
+
set exact(value) {
|
1758
|
+
if (value === undefined) {
|
1759
|
+
this._exact = true;
|
1808
1760
|
}
|
1809
|
-
|
1810
|
-
this.
|
1811
|
-
.subscribe((translated) => {
|
1812
|
-
this.placeholder = translated;
|
1813
|
-
});
|
1761
|
+
else {
|
1762
|
+
this._exact = value;
|
1814
1763
|
}
|
1764
|
+
this.update();
|
1815
1765
|
}
|
1816
1766
|
/**
|
1817
|
-
* The
|
1767
|
+
* The url of the NavItem to check for activeness. Convert the item url into a
|
1768
|
+
* UrlTree relative to the ActivatedRoute so router#isActive works even with relative urls.
|
1769
|
+
* See Angular's [routerLink](https://github.com/angular/angular/blob/8282e15c2becbe42a49befa07d6407247e8243d8/packages/router/src/directives/router_link.ts#L249)
|
1770
|
+
* and [routerLinkActive](https://github.com/angular/angular/blob/8282e15c2becbe42a49befa07d6407247e8243d8/packages/router/src/directives/router_link_active.ts#L139)
|
1771
|
+
* for a similiar implementation.
|
1818
1772
|
*/
|
1819
|
-
|
1820
|
-
if (
|
1821
|
-
this.
|
1773
|
+
set url(value) {
|
1774
|
+
if (value !== null && value !== undefined) {
|
1775
|
+
this._url = this.router.createUrlTree([value], { relativeTo: this.route, queryParams: this.queryParams });
|
1776
|
+
this.update();
|
1822
1777
|
}
|
1823
1778
|
}
|
1824
|
-
|
1825
|
-
|
1826
|
-
|
1827
|
-
|
1828
|
-
|
1829
|
-
|
1830
|
-
|
1831
|
-
|
1832
|
-
|
1833
|
-
|
1779
|
+
constructor(router, el, renderer, route) {
|
1780
|
+
this.router = router;
|
1781
|
+
this.el = el;
|
1782
|
+
this.renderer = renderer;
|
1783
|
+
this.route = route;
|
1784
|
+
this._exact = true;
|
1785
|
+
/** Emits when the url becomes active */
|
1786
|
+
this.routerLinkActivated = new EventEmitter();
|
1787
|
+
/** Subject that emits when component is destroyed to unsubscribe from any subscriptions */
|
1788
|
+
this.destroyed = new Subject();
|
1834
1789
|
}
|
1835
|
-
/**
|
1836
|
-
|
1837
|
-
|
1838
|
-
|
1839
|
-
|
1840
|
-
if (this.upperCase && this.formModel.value) {
|
1841
|
-
this.formModel.setValue(this.formModel.value.toUpperCase().trim());
|
1842
|
-
}
|
1790
|
+
/** Check if url is active on NavigationEnd events */
|
1791
|
+
ngOnInit() {
|
1792
|
+
this.router.events.pipe(takeUntil(this.destroyed), filter(e => e instanceof NavigationEnd)).subscribe(() => {
|
1793
|
+
this.update();
|
1794
|
+
});
|
1843
1795
|
}
|
1844
|
-
|
1845
|
-
|
1846
|
-
TextboxComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "15.2.9", type: TextboxComponent, selector: "ec-textbox", inputs: { autocomplete: "autocomplete", type: "type", placeholder: "placeholder", maxlength: "maxlength", minlength: "minlength", rows: "rows", selectOnAutofocus: "selectOnAutofocus", upperCase: "upperCase" }, viewQueries: [{ propertyName: "inputElement", first: true, predicate: ["textboxInput"], descendants: true }], usesInheritance: true, usesOnChanges: true, ngImport: i0, template: "<div class=\"control control-label-{{labelPosition}}\"\r\n [ngClass]=\"{'is-readonly': readonly}\">\r\n\r\n <label *ngIf=\"label\">\r\n <span>{{label | translate}}</span>\r\n <span *ngIf=\"validationErrors.length > 0 && formModel.touched && formModel.invalid\"> {{validationErrors |\r\n translate}}</span>\r\n <ec-help-popover id=\"{{id}}_helpPopover\"\r\n *ngIf=\"helpPopover\"\r\n class=\"d-inline-block my-n3 mx-n1\"\r\n text=\"{{helpPopover | translate}}\"\r\n contentPosition=\"{{helpPopoverPosition}}\">\r\n </ec-help-popover>\r\n </label>\r\n\r\n <div class=\"input-wrapper control-input\">\r\n <input *ngIf=\"type !== 'multi_line'\"\r\n #textboxInput\r\n email=\"{{type === 'email' ? true : false}}\"\r\n pattern=\"{{validationPattern}}\"\r\n type=\"{{type}}\"\r\n tabindex=\"{{tabindex}}\"\r\n title=\"{{tooltip}}\"\r\n [attr.id]=\"inputId\"\r\n [attr.autocomplete]=\"autocomplete\"\r\n [attr.placeholder]=\"placeholder\"\r\n [attr.maxlength]=\"maxlength\"\r\n [attr.minlength]=\"minlength\"\r\n [attr.required]=\"required ? required : null\"\r\n [formControl]=\"formModel\"\r\n [ngClass]=\"{'is-empty': !formModel?.value, 'is-pending': pending, 'is-uppercase': upperCase}\"\r\n (focusout)=\"focusOutEvent()\"\r\n [attr.cdkFocusInitial]=\"autofocus || null\">\r\n\r\n <textarea *ngIf=\"type === 'multi_line'\"\r\n [attr.rows]=\"rows\"\r\n #textboxInput\r\n tabindex=\"{{tabindex}}\"\r\n [attr.id]=\"inputId\"\r\n [attr.placeholder]=\"placeholder\"\r\n [attr.maxlength]=\"maxlength\"\r\n [attr.minlength]=\"minlength\"\r\n [attr.required]=\"required ? required : null\"\r\n [formControl]=\"formModel\"\r\n [ngClass]=\"{'is-empty': formModel?.value === '', 'is-pending': pending}\"\r\n [attr.cdkFocusInitial]=\"autofocus || null\">\r\n </textarea>\r\n\r\n <i class=\"ec-icon icon-required\"></i>\r\n <i class=\"ec-icon icon-invalid\"></i>\r\n <i class=\"ec-icon icon-loading\"></i>\r\n </div>\r\n</div>", styles: [":host{color:var(--ec-form-control-color);font-size:var(--ec-form-control-font-size);display:block;margin-bottom:1rem;width:100%}:host :host-context(.form-condensed){margin-bottom:.5rem}:host .control{width:100%;display:flex;flex-direction:column}:host .control.control-label-bottom{flex-direction:column-reverse}:host .control.control-label-left{flex-direction:row}:host .control.control-label-left label{margin-right:.25rem}:host .control.control-label-right{flex-direction:row-reverse}:host .control.control-label-right label{margin-left:.25rem}:host .control.control-label-left,:host .control.control-label-right{align-items:center}:host .control.control-label-left label,:host .control.control-label-right label{flex:1 1;margin-top:0;margin-bottom:0}:host .control.control-label-left .control-input,:host .control.control-label-right .control-input{flex:2 2}:host .control.is-readonly input,:host .control.is-readonly select,:host .control.is-readonly textarea{border-color:var(--ec-form-control-border-color-readonly);background-color:var(--ec-form-control-background-color-readonly);background-clip:border-box;background-image:none;color:var(--ec-form-control-color-readonly);opacity:1;-webkit-user-select:none;user-select:none;pointer-events:none;overflow:hidden;white-space:nowrap}:host .control.invalid .textbox-group-input ::ng-deep .control input.ng-invalid,:host .control.invalid .textbox-group-input ::ng-deep .control input.ng-valid{background-color:var(--ec-form-control-background-color-invalid);border-color:var(--ec-form-control-border-color-invalid);background-repeat:no-repeat;background-position:.5rem center;background-size:1rem,1rem;padding-left:1.75rem;background-image:none}:host .control.invalid .textbox-group-input ::ng-deep .control input.ng-invalid:focus,:host .control.invalid .textbox-group-input ::ng-deep .control input.ng-valid:focus{border-color:var(--ec-form-control-background-color-invalid)}:host .control.invalid .textbox-group-input ::ng-deep .control input.ng-invalid~.icon-invalid,:host .control.invalid .textbox-group-input ::ng-deep .control input.ng-valid~.icon-invalid{display:inline-flex;position:absolute;left:.5rem;top:.5rem;z-index:1}:host .control.invalid .textbox-group-input ::ng-deep .control input.ng-invalid~.icon-required,:host .control.invalid .textbox-group-input ::ng-deep .control input.ng-valid~.icon-required{display:none}:host .control.invalid:not(.open) .textbox-group-btn-right ::ng-deep button{background-color:var(--ec-form-control-background-color-invalid)}:host .control.invalid:not(.open) .textbox-group-btn-right ::ng-deep button:not(:focus){border-color:var(--ec-form-control-border-color-invalid)}:host .textbox-group{display:flex;position:relative}:host textarea:focus,:host input:focus,:host select:focus{outline:none}:host label{color:var(--ec-form-control-label-color, var(--ec-color-secondary-dark));display:block;font-size:var(--ec-font-size-label);line-height:1;margin:calc(var(--ec-font-size-label) / 2) 0}:host input{background-color:var(--ec-form-control-background-color);border:1px solid var(--ec-form-control-border-color);border-radius:var(--ec-border-radius);background-image:none;background-clip:padding-box;width:100%;line-height:1.25rem;padding:.3125rem .5rem;height:2rem}:host input::selection{background-color:var(--ec-form-control-background-color-selection);color:var(--ec-form-control-color-selection)}:host input::-webkit-input-placeholder{color:var(--ec-form-control-color-placeholder)}:host input::-moz-placeholder{color:var(--ec-form-control-color-placeholder);opacity:1}:host input:-ms-input-placeholder{color:var(--ec-form-control-color-placeholder)}:host input:-moz-placeholder{color:var(--ec-form-control-color-placeholder);opacity:1}:host input~.icon-required,:host input~.icon-invalid{color:var(--ec-form-control-border-color-invalid)}:host input:required.is-empty{background-repeat:no-repeat;background-position:.5rem center;background-size:1rem,1rem;padding-left:1.75rem;background-image:none}:host input:required.is-empty~.icon-required{display:inline-flex;position:absolute;left:.5rem;top:.5rem;z-index:1}:host input.ng-invalid.ng-touched{background-color:var(--ec-form-control-background-color-invalid);border-color:var(--ec-form-control-border-color-invalid);background-repeat:no-repeat;background-position:.5rem center;background-size:1rem,1rem;padding-left:1.75rem;background-image:none}:host input.ng-invalid.ng-touched:focus{border-color:var(--ec-form-control-background-color-invalid)}:host input.ng-invalid.ng-touched~.icon-invalid{display:inline-flex;position:absolute;left:.5rem;top:.5rem;z-index:1}:host input.ng-invalid.ng-touched~.icon-required{display:none}:host input.is-pending.ng-valid,:host input.is-pending.ng-invalid,:host input.is-pending.ng-pending{background-image:\"\";background-repeat:no-repeat;background-position:.5rem center;background-size:1rem,1rem;padding-left:1.75rem}:host input.is-pending.ng-valid~.icon-loading,:host input.is-pending.ng-invalid~.icon-loading,:host input.is-pending.ng-pending~.icon-loading{display:inline-flex;position:absolute;left:.5rem;top:.5rem;z-index:1}:host input.is-pending.ng-valid~.icon-required,:host input.is-pending.ng-valid~.icon-invalid,:host input.is-pending.ng-invalid~.icon-required,:host input.is-pending.ng-invalid~.icon-invalid,:host input.is-pending.ng-pending~.icon-required,:host input.is-pending.ng-pending~.icon-invalid{display:none}:host input:focus,:host input:focus.is-empty{border-color:var(--ec-form-control-border-color-focus);box-shadow:var(--ec-form-control-box-shadow-focus);position:relative;z-index:1}:host input:disabled{background-color:var(--ec-form-control-background-color-disabled);border-color:var(--ec-form-control-border-color-disabled);color:var(--ec-form-control-color-disabled);opacity:var(--ec-form-control-opacity-disabled)}:host input:disabled:required,:host input:disabled:required.is-empty{background-image:none;padding-left:.5rem;background-color:var(--ec-form-control-background-color-disabled);border-color:var(--ec-form-control-border-color-disabled)}:host input:disabled:required+.icon-required,:host input:disabled:required.is-empty+.icon-required{display:none}:host input.is-uppercase:not(.is-empty){text-transform:uppercase}:host textarea{background-color:var(--ec-form-control-background-color);border:1px solid var(--ec-form-control-border-color);border-radius:var(--ec-border-radius);background-image:none;background-clip:padding-box;width:100%;line-height:1.25rem;padding:.3125rem .5rem;height:auto;resize:none;display:block}:host textarea::selection{background-color:var(--ec-form-control-background-color-selection);color:var(--ec-form-control-color-selection)}:host textarea::-webkit-input-placeholder{color:var(--ec-form-control-color-placeholder)}:host textarea::-moz-placeholder{color:var(--ec-form-control-color-placeholder);opacity:1}:host textarea:-ms-input-placeholder{color:var(--ec-form-control-color-placeholder)}:host textarea:-moz-placeholder{color:var(--ec-form-control-color-placeholder);opacity:1}:host textarea~.icon-required,:host textarea~.icon-invalid{color:var(--ec-form-control-border-color-invalid)}:host textarea:required.is-empty{background-repeat:no-repeat;background-position:.5rem .5rem;background-size:1rem,1rem;padding-left:1.75rem;background-image:none}:host textarea:required.is-empty~.icon-required{display:inline-flex;position:absolute;left:.5rem;top:.5rem;z-index:1}:host textarea.ng-invalid.ng-touched{background-color:var(--ec-form-control-background-color-invalid);border-color:var(--ec-form-control-border-color-invalid);background-repeat:no-repeat;background-position:.5rem .5rem;background-size:1rem,1rem;padding-left:1.75rem;background-image:none}:host textarea.ng-invalid.ng-touched:focus{border-color:var(--ec-form-control-background-color-invalid)}:host textarea.ng-invalid.ng-touched~.icon-invalid{display:inline-flex;position:absolute;left:.5rem;top:.5rem;z-index:1}:host textarea.ng-invalid.ng-touched~.icon-required{display:none}:host textarea.is-pending.ng-valid,:host textarea.is-pending.ng-invalid,:host textarea.is-pending.ng-pending{background-image:\"\";background-repeat:no-repeat;background-position:.5rem .5rem;background-size:1rem,1rem;padding-left:1.75rem}:host textarea.is-pending.ng-valid~.icon-loading,:host textarea.is-pending.ng-invalid~.icon-loading,:host textarea.is-pending.ng-pending~.icon-loading{display:inline-flex;position:absolute;left:.5rem;top:.5rem;z-index:1}:host textarea.is-pending.ng-valid~.icon-required,:host textarea.is-pending.ng-valid~.icon-invalid,:host textarea.is-pending.ng-invalid~.icon-required,:host textarea.is-pending.ng-invalid~.icon-invalid,:host textarea.is-pending.ng-pending~.icon-required,:host textarea.is-pending.ng-pending~.icon-invalid{display:none}:host textarea:focus,:host textarea:focus.is-empty{border-color:var(--ec-form-control-border-color-focus);box-shadow:var(--ec-form-control-box-shadow-focus);position:relative;z-index:1}:host textarea:disabled{background-color:var(--ec-form-control-background-color-disabled);border-color:var(--ec-form-control-border-color-disabled);color:var(--ec-form-control-color-disabled);opacity:var(--ec-form-control-opacity-disabled)}:host textarea:disabled:required,:host textarea:disabled:required.is-empty{background-image:none;padding-left:.5rem;background-color:var(--ec-form-control-background-color-disabled);border-color:var(--ec-form-control-border-color-disabled)}:host textarea:disabled:required+.icon-required,:host textarea:disabled:required.is-empty+.icon-required{display:none}:host textarea.is-uppercase:not(.is-empty){text-transform:uppercase}.input-wrapper{position:relative}.input-wrapper>.ec-icon{display:none}:host(.textbox-group-input:not(:last-child)){flex:1 1 0%;width:1px}:host(.textbox-group-input:not(:last-child)) .control{margin-bottom:0}:host(.textbox-group-input:not(:last-child)) .control.is-readonly input{border-right-width:1px}:host(.textbox-group-input:not(:last-child)) input{border-top-right-radius:0;border-bottom-right-radius:0;border-right-width:0}:host(.textbox-group-input:not(:last-child)) input:focus{position:relative;z-index:1;border-right-width:1px}:host(.text-truncate) input{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}:host(.is-monospace) input,:host(.is-monospace) textarea,:host-context(.is-monospace) input,:host-context(.is-monospace) textarea{font-family:var(--ec-font-family-monospace)}\n"], dependencies: [{ kind: "directive", type: i1.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: i1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i4.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i4.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i4.RequiredValidator, selector: ":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]", inputs: ["required"] }, { kind: "directive", type: i4.MinLengthValidator, selector: "[minlength][formControlName],[minlength][formControl],[minlength][ngModel]", inputs: ["minlength"] }, { kind: "directive", type: i4.MaxLengthValidator, selector: "[maxlength][formControlName],[maxlength][formControl],[maxlength][ngModel]", inputs: ["maxlength"] }, { kind: "directive", type: i4.PatternValidator, selector: "[pattern][formControlName],[pattern][formControl],[pattern][ngModel]", inputs: ["pattern"] }, { kind: "directive", type: i4.EmailValidator, selector: "[email][formControlName],[email][formControl],[email][ngModel]", inputs: ["email"] }, { kind: "directive", type: i4.FormControlDirective, selector: "[formControl]", inputs: ["formControl", "disabled", "ngModel"], outputs: ["ngModelChange"], exportAs: ["ngForm"] }, { kind: "component", type: HelpPopoverComponent, selector: "ec-help-popover", inputs: ["id", "text", "contentPosition", "maxWidth"] }, { kind: "pipe", type: i2.TranslatePipe, name: "translate" }] });
|
1847
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.9", ngImport: i0, type: TextboxComponent, decorators: [{
|
1848
|
-
type: Component,
|
1849
|
-
args: [{ selector: 'ec-textbox', template: "<div class=\"control control-label-{{labelPosition}}\"\r\n [ngClass]=\"{'is-readonly': readonly}\">\r\n\r\n <label *ngIf=\"label\">\r\n <span>{{label | translate}}</span>\r\n <span *ngIf=\"validationErrors.length > 0 && formModel.touched && formModel.invalid\"> {{validationErrors |\r\n translate}}</span>\r\n <ec-help-popover id=\"{{id}}_helpPopover\"\r\n *ngIf=\"helpPopover\"\r\n class=\"d-inline-block my-n3 mx-n1\"\r\n text=\"{{helpPopover | translate}}\"\r\n contentPosition=\"{{helpPopoverPosition}}\">\r\n </ec-help-popover>\r\n </label>\r\n\r\n <div class=\"input-wrapper control-input\">\r\n <input *ngIf=\"type !== 'multi_line'\"\r\n #textboxInput\r\n email=\"{{type === 'email' ? true : false}}\"\r\n pattern=\"{{validationPattern}}\"\r\n type=\"{{type}}\"\r\n tabindex=\"{{tabindex}}\"\r\n title=\"{{tooltip}}\"\r\n [attr.id]=\"inputId\"\r\n [attr.autocomplete]=\"autocomplete\"\r\n [attr.placeholder]=\"placeholder\"\r\n [attr.maxlength]=\"maxlength\"\r\n [attr.minlength]=\"minlength\"\r\n [attr.required]=\"required ? required : null\"\r\n [formControl]=\"formModel\"\r\n [ngClass]=\"{'is-empty': !formModel?.value, 'is-pending': pending, 'is-uppercase': upperCase}\"\r\n (focusout)=\"focusOutEvent()\"\r\n [attr.cdkFocusInitial]=\"autofocus || null\">\r\n\r\n <textarea *ngIf=\"type === 'multi_line'\"\r\n [attr.rows]=\"rows\"\r\n #textboxInput\r\n tabindex=\"{{tabindex}}\"\r\n [attr.id]=\"inputId\"\r\n [attr.placeholder]=\"placeholder\"\r\n [attr.maxlength]=\"maxlength\"\r\n [attr.minlength]=\"minlength\"\r\n [attr.required]=\"required ? required : null\"\r\n [formControl]=\"formModel\"\r\n [ngClass]=\"{'is-empty': formModel?.value === '', 'is-pending': pending}\"\r\n [attr.cdkFocusInitial]=\"autofocus || null\">\r\n </textarea>\r\n\r\n <i class=\"ec-icon icon-required\"></i>\r\n <i class=\"ec-icon icon-invalid\"></i>\r\n <i class=\"ec-icon icon-loading\"></i>\r\n </div>\r\n</div>", styles: [":host{color:var(--ec-form-control-color);font-size:var(--ec-form-control-font-size);display:block;margin-bottom:1rem;width:100%}:host :host-context(.form-condensed){margin-bottom:.5rem}:host .control{width:100%;display:flex;flex-direction:column}:host .control.control-label-bottom{flex-direction:column-reverse}:host .control.control-label-left{flex-direction:row}:host .control.control-label-left label{margin-right:.25rem}:host .control.control-label-right{flex-direction:row-reverse}:host .control.control-label-right label{margin-left:.25rem}:host .control.control-label-left,:host .control.control-label-right{align-items:center}:host .control.control-label-left label,:host .control.control-label-right label{flex:1 1;margin-top:0;margin-bottom:0}:host .control.control-label-left .control-input,:host .control.control-label-right .control-input{flex:2 2}:host .control.is-readonly input,:host .control.is-readonly select,:host .control.is-readonly textarea{border-color:var(--ec-form-control-border-color-readonly);background-color:var(--ec-form-control-background-color-readonly);background-clip:border-box;background-image:none;color:var(--ec-form-control-color-readonly);opacity:1;-webkit-user-select:none;user-select:none;pointer-events:none;overflow:hidden;white-space:nowrap}:host .control.invalid .textbox-group-input ::ng-deep .control input.ng-invalid,:host .control.invalid .textbox-group-input ::ng-deep .control input.ng-valid{background-color:var(--ec-form-control-background-color-invalid);border-color:var(--ec-form-control-border-color-invalid);background-repeat:no-repeat;background-position:.5rem center;background-size:1rem,1rem;padding-left:1.75rem;background-image:none}:host .control.invalid .textbox-group-input ::ng-deep .control input.ng-invalid:focus,:host .control.invalid .textbox-group-input ::ng-deep .control input.ng-valid:focus{border-color:var(--ec-form-control-background-color-invalid)}:host .control.invalid .textbox-group-input ::ng-deep .control input.ng-invalid~.icon-invalid,:host .control.invalid .textbox-group-input ::ng-deep .control input.ng-valid~.icon-invalid{display:inline-flex;position:absolute;left:.5rem;top:.5rem;z-index:1}:host .control.invalid .textbox-group-input ::ng-deep .control input.ng-invalid~.icon-required,:host .control.invalid .textbox-group-input ::ng-deep .control input.ng-valid~.icon-required{display:none}:host .control.invalid:not(.open) .textbox-group-btn-right ::ng-deep button{background-color:var(--ec-form-control-background-color-invalid)}:host .control.invalid:not(.open) .textbox-group-btn-right ::ng-deep button:not(:focus){border-color:var(--ec-form-control-border-color-invalid)}:host .textbox-group{display:flex;position:relative}:host textarea:focus,:host input:focus,:host select:focus{outline:none}:host label{color:var(--ec-form-control-label-color, var(--ec-color-secondary-dark));display:block;font-size:var(--ec-font-size-label);line-height:1;margin:calc(var(--ec-font-size-label) / 2) 0}:host input{background-color:var(--ec-form-control-background-color);border:1px solid var(--ec-form-control-border-color);border-radius:var(--ec-border-radius);background-image:none;background-clip:padding-box;width:100%;line-height:1.25rem;padding:.3125rem .5rem;height:2rem}:host input::selection{background-color:var(--ec-form-control-background-color-selection);color:var(--ec-form-control-color-selection)}:host input::-webkit-input-placeholder{color:var(--ec-form-control-color-placeholder)}:host input::-moz-placeholder{color:var(--ec-form-control-color-placeholder);opacity:1}:host input:-ms-input-placeholder{color:var(--ec-form-control-color-placeholder)}:host input:-moz-placeholder{color:var(--ec-form-control-color-placeholder);opacity:1}:host input~.icon-required,:host input~.icon-invalid{color:var(--ec-form-control-border-color-invalid)}:host input:required.is-empty{background-repeat:no-repeat;background-position:.5rem center;background-size:1rem,1rem;padding-left:1.75rem;background-image:none}:host input:required.is-empty~.icon-required{display:inline-flex;position:absolute;left:.5rem;top:.5rem;z-index:1}:host input.ng-invalid.ng-touched{background-color:var(--ec-form-control-background-color-invalid);border-color:var(--ec-form-control-border-color-invalid);background-repeat:no-repeat;background-position:.5rem center;background-size:1rem,1rem;padding-left:1.75rem;background-image:none}:host input.ng-invalid.ng-touched:focus{border-color:var(--ec-form-control-background-color-invalid)}:host input.ng-invalid.ng-touched~.icon-invalid{display:inline-flex;position:absolute;left:.5rem;top:.5rem;z-index:1}:host input.ng-invalid.ng-touched~.icon-required{display:none}:host input.is-pending.ng-valid,:host input.is-pending.ng-invalid,:host input.is-pending.ng-pending{background-image:\"\";background-repeat:no-repeat;background-position:.5rem center;background-size:1rem,1rem;padding-left:1.75rem}:host input.is-pending.ng-valid~.icon-loading,:host input.is-pending.ng-invalid~.icon-loading,:host input.is-pending.ng-pending~.icon-loading{display:inline-flex;position:absolute;left:.5rem;top:.5rem;z-index:1}:host input.is-pending.ng-valid~.icon-required,:host input.is-pending.ng-valid~.icon-invalid,:host input.is-pending.ng-invalid~.icon-required,:host input.is-pending.ng-invalid~.icon-invalid,:host input.is-pending.ng-pending~.icon-required,:host input.is-pending.ng-pending~.icon-invalid{display:none}:host input:focus,:host input:focus.is-empty{border-color:var(--ec-form-control-border-color-focus);box-shadow:var(--ec-form-control-box-shadow-focus);position:relative;z-index:1}:host input:disabled{background-color:var(--ec-form-control-background-color-disabled);border-color:var(--ec-form-control-border-color-disabled);color:var(--ec-form-control-color-disabled);opacity:var(--ec-form-control-opacity-disabled)}:host input:disabled:required,:host input:disabled:required.is-empty{background-image:none;padding-left:.5rem;background-color:var(--ec-form-control-background-color-disabled);border-color:var(--ec-form-control-border-color-disabled)}:host input:disabled:required+.icon-required,:host input:disabled:required.is-empty+.icon-required{display:none}:host input.is-uppercase:not(.is-empty){text-transform:uppercase}:host textarea{background-color:var(--ec-form-control-background-color);border:1px solid var(--ec-form-control-border-color);border-radius:var(--ec-border-radius);background-image:none;background-clip:padding-box;width:100%;line-height:1.25rem;padding:.3125rem .5rem;height:auto;resize:none;display:block}:host textarea::selection{background-color:var(--ec-form-control-background-color-selection);color:var(--ec-form-control-color-selection)}:host textarea::-webkit-input-placeholder{color:var(--ec-form-control-color-placeholder)}:host textarea::-moz-placeholder{color:var(--ec-form-control-color-placeholder);opacity:1}:host textarea:-ms-input-placeholder{color:var(--ec-form-control-color-placeholder)}:host textarea:-moz-placeholder{color:var(--ec-form-control-color-placeholder);opacity:1}:host textarea~.icon-required,:host textarea~.icon-invalid{color:var(--ec-form-control-border-color-invalid)}:host textarea:required.is-empty{background-repeat:no-repeat;background-position:.5rem .5rem;background-size:1rem,1rem;padding-left:1.75rem;background-image:none}:host textarea:required.is-empty~.icon-required{display:inline-flex;position:absolute;left:.5rem;top:.5rem;z-index:1}:host textarea.ng-invalid.ng-touched{background-color:var(--ec-form-control-background-color-invalid);border-color:var(--ec-form-control-border-color-invalid);background-repeat:no-repeat;background-position:.5rem .5rem;background-size:1rem,1rem;padding-left:1.75rem;background-image:none}:host textarea.ng-invalid.ng-touched:focus{border-color:var(--ec-form-control-background-color-invalid)}:host textarea.ng-invalid.ng-touched~.icon-invalid{display:inline-flex;position:absolute;left:.5rem;top:.5rem;z-index:1}:host textarea.ng-invalid.ng-touched~.icon-required{display:none}:host textarea.is-pending.ng-valid,:host textarea.is-pending.ng-invalid,:host textarea.is-pending.ng-pending{background-image:\"\";background-repeat:no-repeat;background-position:.5rem .5rem;background-size:1rem,1rem;padding-left:1.75rem}:host textarea.is-pending.ng-valid~.icon-loading,:host textarea.is-pending.ng-invalid~.icon-loading,:host textarea.is-pending.ng-pending~.icon-loading{display:inline-flex;position:absolute;left:.5rem;top:.5rem;z-index:1}:host textarea.is-pending.ng-valid~.icon-required,:host textarea.is-pending.ng-valid~.icon-invalid,:host textarea.is-pending.ng-invalid~.icon-required,:host textarea.is-pending.ng-invalid~.icon-invalid,:host textarea.is-pending.ng-pending~.icon-required,:host textarea.is-pending.ng-pending~.icon-invalid{display:none}:host textarea:focus,:host textarea:focus.is-empty{border-color:var(--ec-form-control-border-color-focus);box-shadow:var(--ec-form-control-box-shadow-focus);position:relative;z-index:1}:host textarea:disabled{background-color:var(--ec-form-control-background-color-disabled);border-color:var(--ec-form-control-border-color-disabled);color:var(--ec-form-control-color-disabled);opacity:var(--ec-form-control-opacity-disabled)}:host textarea:disabled:required,:host textarea:disabled:required.is-empty{background-image:none;padding-left:.5rem;background-color:var(--ec-form-control-background-color-disabled);border-color:var(--ec-form-control-border-color-disabled)}:host textarea:disabled:required+.icon-required,:host textarea:disabled:required.is-empty+.icon-required{display:none}:host textarea.is-uppercase:not(.is-empty){text-transform:uppercase}.input-wrapper{position:relative}.input-wrapper>.ec-icon{display:none}:host(.textbox-group-input:not(:last-child)){flex:1 1 0%;width:1px}:host(.textbox-group-input:not(:last-child)) .control{margin-bottom:0}:host(.textbox-group-input:not(:last-child)) .control.is-readonly input{border-right-width:1px}:host(.textbox-group-input:not(:last-child)) input{border-top-right-radius:0;border-bottom-right-radius:0;border-right-width:0}:host(.textbox-group-input:not(:last-child)) input:focus{position:relative;z-index:1;border-right-width:1px}:host(.text-truncate) input{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}:host(.is-monospace) input,:host(.is-monospace) textarea,:host-context(.is-monospace) input,:host-context(.is-monospace) textarea{font-family:var(--ec-font-family-monospace)}\n"] }]
|
1850
|
-
}], ctorParameters: function () { return [{ type: ValidationMessageService }, { type: FormGroupHelper }, { type: i2.TranslateService }]; }, propDecorators: { autocomplete: [{
|
1851
|
-
type: Input
|
1852
|
-
}], type: [{
|
1853
|
-
type: Input
|
1854
|
-
}], placeholder: [{
|
1855
|
-
type: Input
|
1856
|
-
}], maxlength: [{
|
1857
|
-
type: Input
|
1858
|
-
}], minlength: [{
|
1859
|
-
type: Input
|
1860
|
-
}], rows: [{
|
1861
|
-
type: Input
|
1862
|
-
}], selectOnAutofocus: [{
|
1863
|
-
type: Input
|
1864
|
-
}], upperCase: [{
|
1865
|
-
type: Input
|
1866
|
-
}], inputElement: [{
|
1867
|
-
type: ViewChild,
|
1868
|
-
args: ['textboxInput']
|
1869
|
-
}] } });
|
1870
|
-
|
1871
|
-
/** Exposes the markup and styles that represent the spinner. No inputs or outputs defined because it is just a visual component*/
|
1872
|
-
class SpinnerComponent {
|
1873
|
-
}
|
1874
|
-
SpinnerComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.2.9", ngImport: i0, type: SpinnerComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
1875
|
-
SpinnerComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "15.2.9", type: SpinnerComponent, selector: "ec-spinner", ngImport: i0, template: "<div class=\"spinner\">\r\n <span class=\"spinner-dot\"></span>\r\n <span class=\"spinner-dot\"></span>\r\n <span class=\"spinner-dot\"></span>\r\n <span class=\"spinner-dot\"></span>\r\n</div>", styles: ["@keyframes sk-bouncedelay{0%,80%,to{opacity:0}40%{opacity:1}}.spinner{display:flex}.spinner-dot{width:.75rem;height:.75rem;background-color:var(--ec-color-interactive);animation:sk-bouncedelay 1.7s infinite ease-in-out both;margin-right:.25rem}.spinner-dot:nth-child(1){animation-delay:-.6s}.spinner-dot:nth-child(2){animation-delay:-.4s}.spinner-dot:nth-child(3){animation-delay:-.2s}:host(.spinner-small) .spinner-dot{width:.5rem;height:.5rem;background-color:var(--ec-color-interactive);animation:sk-bouncedelay 1.7s infinite ease-in-out both;margin-right:.1666666667rem}:host(.spinner-small) .spinner-dot:nth-child(1){animation-delay:-.6s}:host(.spinner-small) .spinner-dot:nth-child(2){animation-delay:-.4s}:host(.spinner-small) .spinner-dot:nth-child(3){animation-delay:-.2s}\n"] });
|
1876
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.9", ngImport: i0, type: SpinnerComponent, decorators: [{
|
1877
|
-
type: Component,
|
1878
|
-
args: [{ selector: 'ec-spinner', template: "<div class=\"spinner\">\r\n <span class=\"spinner-dot\"></span>\r\n <span class=\"spinner-dot\"></span>\r\n <span class=\"spinner-dot\"></span>\r\n <span class=\"spinner-dot\"></span>\r\n</div>", styles: ["@keyframes sk-bouncedelay{0%,80%,to{opacity:0}40%{opacity:1}}.spinner{display:flex}.spinner-dot{width:.75rem;height:.75rem;background-color:var(--ec-color-interactive);animation:sk-bouncedelay 1.7s infinite ease-in-out both;margin-right:.25rem}.spinner-dot:nth-child(1){animation-delay:-.6s}.spinner-dot:nth-child(2){animation-delay:-.4s}.spinner-dot:nth-child(3){animation-delay:-.2s}:host(.spinner-small) .spinner-dot{width:.5rem;height:.5rem;background-color:var(--ec-color-interactive);animation:sk-bouncedelay 1.7s infinite ease-in-out both;margin-right:.1666666667rem}:host(.spinner-small) .spinner-dot:nth-child(1){animation-delay:-.6s}:host(.spinner-small) .spinner-dot:nth-child(2){animation-delay:-.4s}:host(.spinner-small) .spinner-dot:nth-child(3){animation-delay:-.2s}\n"] }]
|
1879
|
-
}] });
|
1880
|
-
|
1881
|
-
class Overlay {
|
1882
|
-
constructor(status, message) {
|
1883
|
-
this.status = 'hasData';
|
1884
|
-
this.message = '';
|
1885
|
-
this.setStatus(status, message);
|
1886
|
-
}
|
1887
|
-
setStatus(status, message, action, noDataTemplate, overlayClassList) {
|
1888
|
-
this.status = status;
|
1889
|
-
this.message = message || '';
|
1890
|
-
this.action = action || undefined;
|
1891
|
-
this.noDataTemplate = noDataTemplate || undefined;
|
1892
|
-
this.overlayClassList = overlayClassList || '';
|
1893
|
-
}
|
1894
|
-
}
|
1895
|
-
/**
|
1896
|
-
* Wraps content in order to show pending, error, and no data states with an optional message/noDataTemplate
|
1897
|
-
*/
|
1898
|
-
class ViewOverlayComponent {
|
1899
|
-
constructor() {
|
1900
|
-
this.status = 'hasData';
|
1901
|
-
}
|
1902
|
-
setStatus(status, message, action, noDataTemplate) {
|
1903
|
-
this.status = status;
|
1904
|
-
this.message = message || '';
|
1905
|
-
this.action = action || undefined;
|
1906
|
-
this.noDataTemplate = noDataTemplate || undefined;
|
1796
|
+
ngOnDestroy() {
|
1797
|
+
this.destroyed.next();
|
1798
|
+
this.destroyed.unsubscribe();
|
1907
1799
|
}
|
1908
|
-
|
1909
|
-
|
1910
|
-
|
1800
|
+
/** If url is active apply the defined class to the element, otherwise remove it */
|
1801
|
+
update() {
|
1802
|
+
if (this._url && this.classValue) {
|
1803
|
+
if (this.router.isActive(this._url, { matrixParams: 'ignored', queryParams: this._exact ? 'exact' : 'subset', paths: this._exact ? 'exact' : 'subset', fragment: 'ignored' })) {
|
1804
|
+
this.renderer.addClass(this.el.nativeElement, this.classValue);
|
1805
|
+
this.routerLinkActivated.emit(new Event('routerLinkActivated'));
|
1806
|
+
}
|
1807
|
+
else {
|
1808
|
+
this.renderer.removeClass(this.el.nativeElement, this.classValue);
|
1809
|
+
}
|
1911
1810
|
}
|
1912
1811
|
}
|
1913
1812
|
}
|
1914
|
-
|
1915
|
-
|
1916
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.9", ngImport: i0, type:
|
1917
|
-
type:
|
1918
|
-
args: [{
|
1919
|
-
|
1920
|
-
|
1921
|
-
|
1922
|
-
type: Input
|
1923
|
-
|
1924
|
-
|
1925
|
-
|
1926
|
-
|
1927
|
-
}],
|
1928
|
-
type: Input
|
1929
|
-
|
1930
|
-
|
1813
|
+
NavItemActiveDirective.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.2.9", ngImport: i0, type: NavItemActiveDirective, deps: [{ token: i1$2.Router }, { token: i0.ElementRef }, { token: i0.Renderer2 }, { token: i1$2.ActivatedRoute }], target: i0.ɵɵFactoryTarget.Directive });
|
1814
|
+
NavItemActiveDirective.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "15.2.9", type: NavItemActiveDirective, selector: "[ecNavItemActive]", inputs: { classValue: ["ecNavItemActive", "classValue"], exact: ["ecNavItemActiveExactMatch", "exact"], queryParams: ["ecNavItemActiveQueryParams", "queryParams"], url: ["ecNavItemActiveUrl", "url"] }, outputs: { routerLinkActivated: "routerLinkActivated" }, ngImport: i0 });
|
1815
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.9", ngImport: i0, type: NavItemActiveDirective, decorators: [{
|
1816
|
+
type: Directive,
|
1817
|
+
args: [{
|
1818
|
+
selector: '[ecNavItemActive]'
|
1819
|
+
}]
|
1820
|
+
}], ctorParameters: function () { return [{ type: i1$2.Router }, { type: i0.ElementRef }, { type: i0.Renderer2 }, { type: i1$2.ActivatedRoute }]; }, propDecorators: { classValue: [{
|
1821
|
+
type: Input,
|
1822
|
+
args: ['ecNavItemActive']
|
1823
|
+
}], exact: [{
|
1824
|
+
type: Input,
|
1825
|
+
args: ['ecNavItemActiveExactMatch']
|
1826
|
+
}], queryParams: [{
|
1827
|
+
type: Input,
|
1828
|
+
args: ['ecNavItemActiveQueryParams']
|
1829
|
+
}], url: [{
|
1830
|
+
type: Input,
|
1831
|
+
args: ['ecNavItemActiveUrl']
|
1832
|
+
}], routerLinkActivated: [{
|
1833
|
+
type: Output
|
1931
1834
|
}] } });
|
1932
1835
|
|
1836
|
+
;
|
1837
|
+
const menuAnimationSpeed = 350;
|
1933
1838
|
/**
|
1934
|
-
*
|
1935
|
-
*
|
1839
|
+
* Primitive Menu component that encapsulates known templates
|
1840
|
+
*
|
1841
|
+
* @export
|
1936
1842
|
*/
|
1937
|
-
class
|
1843
|
+
class MenuComponent {
|
1938
1844
|
/**
|
1939
|
-
*
|
1940
|
-
*
|
1941
|
-
* It is set up as `get` only because it is set with `addNavigateAwayPrompt`.
|
1942
|
-
*
|
1943
|
-
* This also includes adding a prompt to the window itself (in addition to
|
1944
|
-
* working with the `CanDeactivateUnsavedChanges` guard) to cover page reloads
|
1945
|
-
* which do not trigger router events.
|
1845
|
+
* Helper function to return a flat list of all selectable items in the provided menu items. Filters out headings and divided-sections.
|
1846
|
+
* This makes it much easier to keep track of currently highlighted items for keyboard navigation.
|
1946
1847
|
*/
|
1947
|
-
|
1948
|
-
return
|
1848
|
+
static getSelectableItems(items) {
|
1849
|
+
return items.reduce((selectableItems, item) => {
|
1850
|
+
if (item.display !== 'heading' && item.display !== 'divided-section') {
|
1851
|
+
selectableItems.push(item);
|
1852
|
+
}
|
1853
|
+
else if (item.items) {
|
1854
|
+
selectableItems.push(...item.items.filter(childItem => childItem.display !== 'heading' && childItem.display !== 'divided-section'));
|
1855
|
+
}
|
1856
|
+
return selectableItems;
|
1857
|
+
}, []);
|
1949
1858
|
}
|
1950
1859
|
/**
|
1951
|
-
*
|
1952
|
-
* is
|
1860
|
+
* Returns an ID for the provided item based on its index in the provided items array. This mimics the behavior of the MenuComponent's
|
1861
|
+
* generated IDs for items that don't have provided IDs. This is used in MenuComponent and ComboboxComponent to scroll to specific items.
|
1862
|
+
* NOTE: If the items array does not match what is displayed in the menu, this function will not return the correct ID.
|
1863
|
+
*
|
1864
|
+
* Returns null if the not found
|
1865
|
+
* @param items The MenuItems array to search through.
|
1866
|
+
* @param item The item to generate the ID for.
|
1867
|
+
* @param menuComponentId Used to prefix the generated ID. This should be the ID of the menu component the item is present in.
|
1868
|
+
* @memberof MenuComponent
|
1953
1869
|
*/
|
1954
|
-
|
1955
|
-
|
1870
|
+
static getIndexedItemId(items, item, menuComponentId) {
|
1871
|
+
if (item) {
|
1872
|
+
for (let i = 0; i < items.length; i++) {
|
1873
|
+
const itemInList = items[i];
|
1874
|
+
if (itemInList.label === item.label) {
|
1875
|
+
return `${menuComponentId}_item${i}`;
|
1876
|
+
}
|
1877
|
+
// If the item is a heading or divided section, check its children
|
1878
|
+
if (itemInList.items && (itemInList.display === 'heading' || itemInList.display === 'divided-section')) {
|
1879
|
+
for (let j = 0; j < itemInList.items.length; j++) {
|
1880
|
+
const childItem = itemInList.items[j];
|
1881
|
+
// Fall back to checking only the label if the item doesn't have an id
|
1882
|
+
if (childItem.label === item.label) {
|
1883
|
+
return `${menuComponentId}_item${i}-${j}`;
|
1884
|
+
}
|
1885
|
+
}
|
1886
|
+
}
|
1887
|
+
}
|
1888
|
+
}
|
1889
|
+
return null;
|
1956
1890
|
}
|
1957
|
-
constructor(
|
1958
|
-
this.
|
1959
|
-
this.
|
1960
|
-
this.
|
1891
|
+
constructor(el, renderer, windowService, scrollService) {
|
1892
|
+
this.el = el;
|
1893
|
+
this.renderer = renderer;
|
1894
|
+
this.windowService = windowService;
|
1895
|
+
this.scrollService = scrollService;
|
1961
1896
|
/**
|
1962
|
-
*
|
1897
|
+
* Array of items to display
|
1963
1898
|
*
|
1964
|
-
*
|
1965
|
-
|
1899
|
+
* @memberof MenuComponent
|
1900
|
+
*/
|
1901
|
+
this.items = [];
|
1902
|
+
/**
|
1903
|
+
* Selected item; annotates the item
|
1904
|
+
* when displayed with 'selected' class
|
1966
1905
|
*
|
1967
|
-
*
|
1968
|
-
* dialog.
|
1969
|
-
* @see https://developer.mozilla.org/en-US/docs/Web/API/Window/beforeunload_event
|
1906
|
+
* @memberof MenuComponent
|
1970
1907
|
*/
|
1971
|
-
this.
|
1972
|
-
|
1973
|
-
|
1974
|
-
|
1975
|
-
|
1976
|
-
|
1977
|
-
|
1978
|
-
|
1979
|
-
|
1980
|
-
|
1981
|
-
|
1982
|
-
|
1983
|
-
|
1984
|
-
|
1985
|
-
|
1908
|
+
this.selected = null;
|
1909
|
+
/**
|
1910
|
+
* Display template
|
1911
|
+
*
|
1912
|
+
* @memberof MenuComponent
|
1913
|
+
*/
|
1914
|
+
this.templateType = 'label';
|
1915
|
+
/**
|
1916
|
+
* Show message when there are no items
|
1917
|
+
*/
|
1918
|
+
this.showNoItems = false;
|
1919
|
+
/**
|
1920
|
+
* Text to show when menu is empty and showNoItems is true
|
1921
|
+
*/
|
1922
|
+
this.noDataText = 'NoItems_TC';
|
1923
|
+
/**
|
1924
|
+
* Controls whether keyboard navigation is enabled
|
1925
|
+
*/
|
1926
|
+
this.enableKeyNav = false;
|
1927
|
+
/**
|
1928
|
+
* Item currently highlighted by keyboard navigation
|
1929
|
+
*/
|
1930
|
+
this.highlightedItem = null;
|
1931
|
+
/**
|
1932
|
+
* Tells the menu to maintain the selected/lastSelected item. Turning this off is useful for
|
1933
|
+
* action type menus that are displayed on the screen at all times and you do not
|
1934
|
+
* want the item to be selected when clicked.
|
1935
|
+
*/
|
1936
|
+
this.maintainSelectedItem = true;
|
1937
|
+
/**
|
1938
|
+
* Will prevent text-wrapping of menu items and truncate instead. Also turns on a tooltip for the menu item. Default: false;
|
1939
|
+
*/
|
1940
|
+
this.truncateItems = false;
|
1941
|
+
/**
|
1942
|
+
* When true, the space for the icon is preserved for menu items that do not have icons.
|
1943
|
+
* Only applicable for iconAndLabel menus.
|
1944
|
+
*/
|
1945
|
+
this.preserveIconSpace = false;
|
1946
|
+
/**
|
1947
|
+
* Emitted when `selected` is changed. Emits the referenced object.
|
1948
|
+
*
|
1949
|
+
* @memberof MenuComponent
|
1950
|
+
*/
|
1951
|
+
this.selectedChanged = new EventEmitter();
|
1952
|
+
/**
|
1953
|
+
* Emitted when the menu has a parent and back is clicked
|
1954
|
+
* @memberof MenuComponent
|
1955
|
+
*/
|
1956
|
+
this.menuClosed = new EventEmitter();
|
1957
|
+
/**
|
1958
|
+
* Index of the item currently highlighted using keyboard nav
|
1959
|
+
*/
|
1960
|
+
this.highlightedItemIndex = -1;
|
1961
|
+
/**
|
1962
|
+
* Last item this.selected was set to via selectItem().
|
1963
|
+
* This isn't necessarily the same as this.selected, because this.selected is an input property
|
1964
|
+
* and could have been changed by a consumer through some means other than selectItem().
|
1965
|
+
* This allows us to prevent double-calls to selectItem() with the same input.
|
1966
|
+
*/
|
1967
|
+
this.lastSelected = null;
|
1968
|
+
/**
|
1969
|
+
* Flattened array of all selectable items in the menu. Makes it easier to keep track of the currently highlighted item for keyboard navigation.
|
1970
|
+
*/
|
1971
|
+
this.selectableItems = [];
|
1986
1972
|
}
|
1987
|
-
|
1988
|
-
|
1989
|
-
|
1990
|
-
|
1991
|
-
return window?.history?.length || 0;
|
1973
|
+
ngOnChanges(changes) {
|
1974
|
+
if (changes.items && this.items) {
|
1975
|
+
this.selectableItems = MenuComponent.getSelectableItems(this.items);
|
1976
|
+
}
|
1992
1977
|
}
|
1993
1978
|
/**
|
1994
|
-
*
|
1995
|
-
*
|
1979
|
+
* Sets & displays the interalized template based on
|
1980
|
+
* the set template.
|
1981
|
+
* @see { @link https://angular.io/guide/lifecycle-hooks|Angular Lifecycle Hooks}
|
1996
1982
|
*
|
1997
|
-
* @
|
1983
|
+
* @memberof MenuComponent
|
1998
1984
|
*/
|
1999
|
-
|
2000
|
-
|
2001
|
-
|
2002
|
-
|
2003
|
-
|
2004
|
-
|
2005
|
-
|
2006
|
-
|
1985
|
+
ngAfterContentInit() {
|
1986
|
+
switch (this.templateType) {
|
1987
|
+
case ("label"):
|
1988
|
+
this.internalizedTemplate = this.iconAndLabelTemplate;
|
1989
|
+
break;
|
1990
|
+
case ("iconAndLabel"):
|
1991
|
+
this.internalizedTemplate = this.iconAndLabelTemplate;
|
1992
|
+
break;
|
1993
|
+
case ("checkAndLabel"):
|
1994
|
+
this.internalizedTemplate = this.checkAndLabelTemplate;
|
1995
|
+
break;
|
1996
|
+
case ("iconLabelCaption"):
|
1997
|
+
this.internalizedTemplate = this.iconLabelCaptionTemplate;
|
1998
|
+
break;
|
1999
|
+
default:
|
2000
|
+
throw new Error(`Invalid templateType for MenuComponent. Please use either: 'label', 'iconAndLabel' or 'checkAndLabel'`);
|
2007
2001
|
}
|
2008
|
-
|
2009
|
-
|
2010
|
-
|
2011
|
-
// didn't handle a link correctly
|
2012
|
-
window.location.href = url;
|
2002
|
+
//if the consumer provided a menuItemTemplate, override the internalizedTemplate with that.
|
2003
|
+
if (this.customMenuTemplate) {
|
2004
|
+
this.internalizedTemplate = this.customMenuTemplate;
|
2013
2005
|
}
|
2006
|
+
if (this.id) {
|
2007
|
+
this.attrId = this.id;
|
2008
|
+
}
|
2009
|
+
this.setItemIds();
|
2010
|
+
if (this.highlightedItem && this.selectableItems.length) {
|
2011
|
+
this.highlightedItemIndex = this.selectableItems.findIndex(item => { return this.highlightedItem === item; });
|
2012
|
+
}
|
2013
|
+
this.addKeydownListener();
|
2014
2014
|
}
|
2015
|
-
|
2016
|
-
|
2017
|
-
|
2018
|
-
|
2019
|
-
|
2020
|
-
this._hasUnsavedChanges = true;
|
2021
|
-
window.addEventListener("beforeunload", this.beforeUnloadFunction);
|
2022
|
-
}
|
2023
|
-
/**
|
2024
|
-
* Removes the `beforeunload` function added to the window
|
2025
|
-
*/
|
2026
|
-
removeNavigateAwayPrompt() {
|
2027
|
-
this._hasUnsavedChanges = false;
|
2028
|
-
window.removeEventListener("beforeunload", this.beforeUnloadFunction);
|
2029
|
-
}
|
2030
|
-
/**
|
2031
|
-
* Send data to another window.
|
2032
|
-
*
|
2033
|
-
* __SECURITY RISK__ - Always use a specific target origin. Failing to provide a specific target origin can allow
|
2034
|
-
* malicious sites to receive the message.
|
2035
|
-
*
|
2036
|
-
* @param targetWindow - Window to send the message to
|
2037
|
-
* @param message - Data to send
|
2038
|
-
* @param targetOrigin - What the URI of the target window must be for the message to be sent.
|
2039
|
-
* If sending data to another EnergyCAP window, this should always be `window.location.origin` to ensure
|
2040
|
-
* that only instances of EnergyCAP app receive the message.
|
2041
|
-
*/
|
2042
|
-
postMessage(targetWindow, message, targetOrigin) {
|
2043
|
-
targetWindow.postMessage(message, targetOrigin);
|
2044
|
-
}
|
2045
|
-
/**
|
2046
|
-
* Open a new window
|
2047
|
-
* @param url - The URL of the resource to be loaded
|
2048
|
-
*/
|
2049
|
-
openNew(url) {
|
2050
|
-
window.open(url, '_blank');
|
2015
|
+
ngOnDestroy() {
|
2016
|
+
// Remove the listener when the component is destroyed
|
2017
|
+
if (this.removeKeydownListener) {
|
2018
|
+
this.removeKeydownListener();
|
2019
|
+
}
|
2051
2020
|
}
|
2052
2021
|
/**
|
2053
|
-
*
|
2054
|
-
*
|
2055
|
-
* The provided params are updated if they already exist or added to the url if they don't
|
2022
|
+
* When a menu item is selected, open a child menu if the item has items, call
|
2023
|
+
* the item's click method if defined, or emit the selected item.
|
2056
2024
|
*
|
2057
|
-
* @
|
2058
|
-
*
|
2059
|
-
*/
|
2060
|
-
async modifyHistoryQueryParamsSubset(queryParams) {
|
2061
|
-
return this.router.navigate([], {
|
2062
|
-
relativeTo: this.activatedRoute,
|
2063
|
-
replaceUrl: true,
|
2064
|
-
queryParams: queryParams,
|
2065
|
-
queryParamsHandling: 'merge',
|
2066
|
-
});
|
2067
|
-
}
|
2068
|
-
/**A wrapper around the default javascript confirm dialog to allow us to unit test dependent code.
|
2069
|
-
* Of course eventually we'd like to have pretty confirmations for everything, but in some cases it wasn't worth the extra time
|
2070
|
-
* so we're using this instead.
|
2025
|
+
* @param item The selected item
|
2026
|
+
* @memberof MenuComponent
|
2071
2027
|
*/
|
2072
|
-
|
2073
|
-
|
2028
|
+
selectItem(event, item, isKeyEvent) {
|
2029
|
+
event.stopPropagation();
|
2030
|
+
//In the case that the user clicks an item, selectItem() will be called from the click handler
|
2031
|
+
//and through onRouterLinkActivated. Only one of these will make it through this if statement
|
2032
|
+
//because the first one will set this.lastSelected = item.
|
2033
|
+
if (!item.disabled && !item.readonly && this.lastSelected !== item) {
|
2034
|
+
if (!item.url) {
|
2035
|
+
if (item.onClick) {
|
2036
|
+
item.onClick(item, false);
|
2037
|
+
}
|
2038
|
+
if (item.items && item.display !== 'heading' && item.display !== 'divided-section') {
|
2039
|
+
this.toggleChildMenu(true);
|
2040
|
+
}
|
2041
|
+
else {
|
2042
|
+
this.onSelection(item);
|
2043
|
+
}
|
2044
|
+
// We need to manually handle the url navigation if the keyboard was used
|
2045
|
+
}
|
2046
|
+
else if (isKeyEvent || event.target?.tagName === 'LI') {
|
2047
|
+
if (item.target) {
|
2048
|
+
window.open(item.url, item.target);
|
2049
|
+
}
|
2050
|
+
else {
|
2051
|
+
this.windowService.navigateToUrl(item.url);
|
2052
|
+
}
|
2053
|
+
// Emit so upstream components know an item was selected
|
2054
|
+
this.onSelection(item);
|
2055
|
+
}
|
2056
|
+
else {
|
2057
|
+
this.onSelection(item);
|
2058
|
+
}
|
2059
|
+
if (this.maintainSelectedItem) {
|
2060
|
+
this.selected = item;
|
2061
|
+
this.lastSelected = item;
|
2062
|
+
}
|
2063
|
+
else {
|
2064
|
+
this.selected = null;
|
2065
|
+
this.lastSelected = null;
|
2066
|
+
}
|
2067
|
+
}
|
2074
2068
|
}
|
2075
2069
|
/**
|
2076
|
-
* Close the current
|
2077
|
-
* @
|
2070
|
+
* Close the current menu and open the parent menu
|
2071
|
+
* @memberof MenuComponent
|
2078
2072
|
*/
|
2079
|
-
|
2080
|
-
|
2081
|
-
|
2082
|
-
|
2083
|
-
else {
|
2084
|
-
window.close();
|
2073
|
+
back(event) {
|
2074
|
+
event.stopPropagation();
|
2075
|
+
if (this.parent && this.parent.onClick) {
|
2076
|
+
this.parent.onClick(null, true);
|
2085
2077
|
}
|
2086
|
-
|
2087
|
-
getLocation() {
|
2088
|
-
return window.location.pathname + window.location.hash;
|
2089
|
-
}
|
2090
|
-
/** Get the current value of the full url, including protocol, host and path */
|
2091
|
-
getFullUrl() {
|
2092
|
-
return window.location.href;
|
2093
|
-
}
|
2094
|
-
/** Get the current value of the base url, including protocol, domain and port (if explicitly specified) */
|
2095
|
-
getBaseUrl() {
|
2096
|
-
return window.location.origin;
|
2078
|
+
this.menuClosed.emit();
|
2097
2079
|
}
|
2098
2080
|
/**
|
2099
|
-
*
|
2100
|
-
*
|
2081
|
+
* Emit the selected item
|
2082
|
+
* @param item The selected item
|
2101
2083
|
*/
|
2102
|
-
|
2103
|
-
|
2084
|
+
onSelection(item) {
|
2085
|
+
if (item.display !== 'heading') {
|
2086
|
+
this.selectedChanged.emit(item);
|
2087
|
+
}
|
2104
2088
|
}
|
2105
|
-
}
|
2106
|
-
WindowService.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.2.9", ngImport: i0, type: WindowService, deps: [{ token: i1$2.Router }, { token: i1$2.ActivatedRoute }], target: i0.ɵɵFactoryTarget.Injectable });
|
2107
|
-
WindowService.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "15.2.9", ngImport: i0, type: WindowService, providedIn: 'root' });
|
2108
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.9", ngImport: i0, type: WindowService, decorators: [{
|
2109
|
-
type: Injectable,
|
2110
|
-
args: [{
|
2111
|
-
providedIn: 'root'
|
2112
|
-
}]
|
2113
|
-
}], ctorParameters: function () { return [{ type: i1$2.Router }, { type: i1$2.ActivatedRoute }]; } });
|
2114
|
-
|
2115
|
-
class NavItemActiveDirective {
|
2116
2089
|
/**
|
2117
|
-
*
|
2118
|
-
*
|
2119
|
-
*
|
2120
|
-
* see: https://angular.io/api/router/Router#isactive
|
2090
|
+
* Open or close the child menu. When the child menu closes, the selected
|
2091
|
+
* item is reset.
|
2092
|
+
* @memberof MenuComponent
|
2121
2093
|
*/
|
2122
|
-
|
2123
|
-
|
2124
|
-
|
2094
|
+
toggleChildMenu(open) {
|
2095
|
+
let navEl = this.el.nativeElement.querySelector('nav');
|
2096
|
+
if (open) {
|
2097
|
+
// Remove the listener on the parent menu when a child menu is opened
|
2098
|
+
// This is to avoid interference between the parent and child menus
|
2099
|
+
if (this.removeKeydownListener) {
|
2100
|
+
this.removeKeydownListener();
|
2101
|
+
}
|
2102
|
+
let height = navEl.offsetHeight;
|
2103
|
+
let width = navEl.offsetWidth;
|
2104
|
+
// In order to animate the child menu, we need to set height on the nav element
|
2105
|
+
// so we can absolutely position the two menus and maintain the current menu's height
|
2106
|
+
this.renderer.setStyle(navEl, 'height', `${height}px`);
|
2107
|
+
this.renderer.setStyle(navEl, 'width', `${width}px`);
|
2108
|
+
this.renderer.addClass(this.el.nativeElement, 'open');
|
2109
|
+
setTimeout(() => {
|
2110
|
+
this.renderer.addClass(this.el.nativeElement, 'open-active');
|
2111
|
+
});
|
2125
2112
|
}
|
2126
2113
|
else {
|
2127
|
-
|
2114
|
+
// Re-add the listener once the child menu closes
|
2115
|
+
this.addKeydownListener();
|
2116
|
+
this.renderer.removeClass(this.el.nativeElement, 'open-active');
|
2117
|
+
setTimeout(() => {
|
2118
|
+
this.renderer.removeClass(this.el.nativeElement, 'open');
|
2119
|
+
// Reset the nav element's height to auto
|
2120
|
+
this.renderer.setStyle(navEl, 'height', '100%');
|
2121
|
+
this.selected = null;
|
2122
|
+
}, menuAnimationSpeed);
|
2128
2123
|
}
|
2129
|
-
this.update();
|
2130
2124
|
}
|
2131
2125
|
/**
|
2132
|
-
*
|
2133
|
-
* UrlTree relative to the ActivatedRoute so router#isActive works even with relative urls.
|
2134
|
-
* See Angular's [routerLink](https://github.com/angular/angular/blob/8282e15c2becbe42a49befa07d6407247e8243d8/packages/router/src/directives/router_link.ts#L249)
|
2135
|
-
* and [routerLinkActive](https://github.com/angular/angular/blob/8282e15c2becbe42a49befa07d6407247e8243d8/packages/router/src/directives/router_link_active.ts#L139)
|
2136
|
-
* for a similiar implementation.
|
2126
|
+
* Handle key presses to navigate the menu
|
2137
2127
|
*/
|
2138
|
-
|
2139
|
-
if (
|
2140
|
-
|
2141
|
-
|
2142
|
-
|
2143
|
-
|
2144
|
-
|
2145
|
-
|
2146
|
-
|
2147
|
-
|
2148
|
-
|
2149
|
-
|
2150
|
-
|
2151
|
-
|
2152
|
-
|
2153
|
-
|
2154
|
-
|
2155
|
-
|
2156
|
-
|
2157
|
-
|
2158
|
-
|
2159
|
-
|
2128
|
+
keyNavigate(event) {
|
2129
|
+
if (this.enableKeyNav && event.target === this.dropdownToggleButton?.nativeElement) {
|
2130
|
+
switch (event.key) {
|
2131
|
+
case 'ArrowUp':
|
2132
|
+
case 'Up':
|
2133
|
+
case 'ArrowDown':
|
2134
|
+
case 'Down':
|
2135
|
+
event.stopPropagation();
|
2136
|
+
event.preventDefault();
|
2137
|
+
this.moveHighlightedUpOrDown(event);
|
2138
|
+
break;
|
2139
|
+
case 'ArrowRight':
|
2140
|
+
case 'Right':
|
2141
|
+
event.stopPropagation();
|
2142
|
+
event.preventDefault();
|
2143
|
+
// Select the item if it has child items
|
2144
|
+
if (this.highlightedItem && this.highlightedItem.items) {
|
2145
|
+
this.selectItem(event, this.highlightedItem, true);
|
2146
|
+
}
|
2147
|
+
break;
|
2148
|
+
case 'ArrowLeft':
|
2149
|
+
case 'Left':
|
2150
|
+
event.stopPropagation();
|
2151
|
+
event.preventDefault();
|
2152
|
+
// Close the menu if it is a child menu
|
2153
|
+
if (this.parent) {
|
2154
|
+
this.back(event);
|
2155
|
+
}
|
2156
|
+
break;
|
2157
|
+
case ' ':
|
2158
|
+
case 'Spacebar':
|
2159
|
+
case 'Enter':
|
2160
|
+
// Prevent 'enter' from doing whatever it does on the currently focused element
|
2161
|
+
event.preventDefault();
|
2162
|
+
if (this.highlightedItemIndex > -1 && this.highlightedItem) {
|
2163
|
+
this.selectItem(event, this.highlightedItem, true);
|
2164
|
+
// If the header is highlighted
|
2165
|
+
}
|
2166
|
+
else if (this.highlightedItemIndex === -1) {
|
2167
|
+
// Close the menu if it's a child
|
2168
|
+
if (this.parent) {
|
2169
|
+
this.back(event);
|
2170
|
+
}
|
2171
|
+
}
|
2172
|
+
break;
|
2173
|
+
default:
|
2174
|
+
return;
|
2175
|
+
}
|
2176
|
+
}
|
2160
2177
|
}
|
2161
|
-
|
2162
|
-
|
2163
|
-
|
2178
|
+
/**
|
2179
|
+
* Scroll to the item currently marked as 'is-selected'. Wait a tick for the
|
2180
|
+
* NgClassDirecitve or NavItemActiveDirective to respond to the model changes
|
2181
|
+
* and update the view.
|
2182
|
+
*/
|
2183
|
+
scrollToSelectedItem() {
|
2184
|
+
window.setTimeout(() => {
|
2185
|
+
const linkSelector = `li.is-selected`;
|
2186
|
+
this.scrollService.scrollToItem(`#${this.id}_list`, linkSelector);
|
2187
|
+
});
|
2164
2188
|
}
|
2165
|
-
|
2166
|
-
|
2167
|
-
|
2168
|
-
|
2169
|
-
|
2170
|
-
|
2171
|
-
|
2172
|
-
|
2173
|
-
|
2174
|
-
|
2189
|
+
moveHighlightedUpOrDown(event) {
|
2190
|
+
switch (event.key) {
|
2191
|
+
case 'ArrowUp':
|
2192
|
+
case 'Up':
|
2193
|
+
if (this.highlightedItemIndex > -1) {
|
2194
|
+
this.highlightedItemIndex--;
|
2195
|
+
}
|
2196
|
+
break;
|
2197
|
+
case 'ArrowDown':
|
2198
|
+
case 'Down':
|
2199
|
+
if (this.highlightedItemIndex < this.selectableItems.length - 1) {
|
2200
|
+
this.highlightedItemIndex++;
|
2201
|
+
}
|
2202
|
+
break;
|
2203
|
+
default:
|
2204
|
+
return;
|
2205
|
+
}
|
2206
|
+
if (this.highlightedItemIndex > -1) {
|
2207
|
+
// Store the item at the current highlight index
|
2208
|
+
this.highlightedItem = this.selectableItems[this.highlightedItemIndex];
|
2209
|
+
}
|
2210
|
+
else {
|
2211
|
+
this.highlightedItem = null;
|
2212
|
+
}
|
2213
|
+
this.scrollToHighlightedItem();
|
2214
|
+
}
|
2215
|
+
/**
|
2216
|
+
* Scroll to the specified menu item.
|
2217
|
+
* If no item is provided, it will scroll to the first item.
|
2218
|
+
*
|
2219
|
+
* @param item The menu item to scroll to.
|
2220
|
+
* @memberof MenuComponent
|
2221
|
+
*/
|
2222
|
+
scrollMenu(item) {
|
2223
|
+
if (this.items.length > 0 && this.id) {
|
2224
|
+
item = item ? item : this.items[0];
|
2225
|
+
let itemId = item.id ? item.id : MenuComponent.getIndexedItemId(this.items, item, this.id);
|
2226
|
+
this.scrollService.scrollItemCentered(`#${this.id}_list`, `#${itemId}`);
|
2227
|
+
}
|
2228
|
+
}
|
2229
|
+
scrollToHighlightedItem() {
|
2230
|
+
this.scrollMenu(this.highlightedItem);
|
2231
|
+
}
|
2232
|
+
addKeydownListener() {
|
2233
|
+
// Only attempt to add the listener if keyboard nav is enabled
|
2234
|
+
if (this.enableKeyNav) {
|
2235
|
+
// renderer.listen adds the listener and returns a function to remove it from the renderer.
|
2236
|
+
// The listener remains active until this function is called.
|
2237
|
+
this.removeKeydownListener = this.renderer.listen('document', 'keydown', (event) => this.keyNavigate(event));
|
2238
|
+
}
|
2239
|
+
}
|
2240
|
+
/**
|
2241
|
+
* Sets the menu item ids using its index if item doesn't already have one
|
2242
|
+
*/
|
2243
|
+
setItemIds() {
|
2244
|
+
if (this.items) {
|
2245
|
+
this.items.forEach((item, index) => {
|
2246
|
+
item.id = item.id ? item.id : this.id + '_item' + index;
|
2247
|
+
});
|
2175
2248
|
}
|
2176
2249
|
}
|
2177
2250
|
}
|
2178
|
-
|
2179
|
-
NavItemActiveDirective.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "15.2.9", type: NavItemActiveDirective, selector: "[ecNavItemActive]", inputs: { classValue: ["ecNavItemActive", "classValue"], exact: ["ecNavItemActiveExactMatch", "exact"], queryParams: ["ecNavItemActiveQueryParams", "queryParams"], url: ["ecNavItemActiveUrl", "url"] }, outputs: { routerLinkActivated: "routerLinkActivated" }, ngImport: i0 });
|
2180
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.9", ngImport: i0, type:
|
2181
|
-
type:
|
2182
|
-
args: [{
|
2183
|
-
|
2184
|
-
|
2185
|
-
|
2186
|
-
type:
|
2187
|
-
args: ['
|
2188
|
-
}],
|
2189
|
-
type: Input
|
2190
|
-
|
2191
|
-
|
2192
|
-
|
2193
|
-
|
2194
|
-
}],
|
2195
|
-
type: Input
|
2196
|
-
|
2197
|
-
|
2251
|
+
MenuComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.2.9", ngImport: i0, type: MenuComponent, deps: [{ token: i0.ElementRef }, { token: i0.Renderer2 }, { token: WindowService }, { token: ScrollService }], target: i0.ɵɵFactoryTarget.Component });
|
2252
|
+
MenuComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "15.2.9", type: MenuComponent, selector: "ec-menu", inputs: { id: "id", items: "items", selected: "selected", parent: "parent", templateType: "templateType", customMenuTemplate: "customMenuTemplate", title: "title", showNoItems: "showNoItems", noDataText: "noDataText", enableKeyNav: "enableKeyNav", highlightedItem: "highlightedItem", maintainSelectedItem: "maintainSelectedItem", truncateItems: "truncateItems", preserveIconSpace: "preserveIconSpace", dropdownToggleButton: "dropdownToggleButton" }, outputs: { selectedChanged: "selectedChanged", menuClosed: "menuClosed" }, host: { properties: { "attr.id": "this.attrId" } }, viewQueries: [{ propertyName: "labelTemplate", first: true, predicate: ["label"], descendants: true, static: true }, { propertyName: "iconAndLabelTemplate", first: true, predicate: ["iconAndLabel"], descendants: true, static: true }, { propertyName: "checkAndLabelTemplate", first: true, predicate: ["checkAndLabel"], descendants: true, static: true }, { propertyName: "iconLabelCaptionTemplate", first: true, predicate: ["iconLabelCaption"], descendants: true, static: true }], usesOnChanges: true, ngImport: i0, template: "<nav>\r\n <div class=\"parent\"\r\n [class.no-data]=\"showNoItems && (!items || items.length === 0)\">\r\n <header id=\"{{id}}_header\"\r\n class=\"text-heading-3 p-1\"\r\n [class.is-selected]=\"highlightedItemIndex === -1\"\r\n *ngIf=\"parent\"\r\n (click)=\"back($event)\">\r\n <div class=\"item-wrapper\">\r\n <i class=\"ec-icon icon-angle-down rotate-90 flex-shrink\"></i>\r\n <span class=\"label text-truncate flex-grow\">{{parent?.label}}</span>\r\n </div>\r\n </header>\r\n\r\n <ul id=\"{{id}}_list\"\r\n class=\"py-1\">\r\n <ng-container *ngFor=\"let item of items; index as i\">\r\n <ng-container *ngTemplateOutlet=\"itemTemplate; context: {$implicit: item, index: i}\"></ng-container>\r\n\r\n <!-- Show child items under parent item if the item is a heading or divided-section -->\r\n <ng-container *ngIf=\"item.items?.length && (item.display === 'heading' || item.display === 'divided-section')\">\r\n <ng-container *ngFor=\"let childItem of item.items; index as j; first as isFirst; last as isLast\"\r\n [ngTemplateOutlet]=\"itemTemplate\"\r\n [ngTemplateOutletContext]=\"{$implicit: childItem, index: i + '-' + j, isDividedSectionChild: item.display === 'divided-section', isFirst: isFirst, isLast: isLast}\">\r\n </ng-container>\r\n </ng-container>\r\n </ng-container>\r\n </ul>\r\n\r\n <p class=\"no-data-message\">{{noDataText | translate}}</p>\r\n </div>\r\n\r\n <!-- Child menu (Rendered to the right) -->\r\n <ec-menu *ngIf=\"selected?.items && selected?.display !== 'heading' && selected?.display !== 'divided-section'\"\r\n id=\"{{id}}_child\"\r\n class=\"child\"\r\n [parent]=\"selected\"\r\n [items]=\"selected?.items\"\r\n [showNoItems]=\"true\"\r\n [templateType]=\"templateType\"\r\n [enableKeyNav]=\"true\"\r\n [truncateItems]=\"truncateItems\"\r\n (selectedChanged)=\"onSelection($event)\"\r\n (menuClosed)=\"toggleChildMenu(false)\">\r\n </ec-menu>\r\n</nav>\r\n\r\n<ng-template #itemTemplate\r\n let-item\r\n let-i=\"index\"\r\n let-isDividedSectionChild=\"isDividedSectionChild\"\r\n let-isFirst=\"isFirst\"\r\n let-isLast=\"isLast\">\r\n <li *ngIf=\"!(item.hideIfNoItems && !item.items?.length) && item.display !== 'divided-section'\"\r\n id=\"{{item.id || id + '_item' + i}}\"\r\n class=\"{{item.display || 'item'}} {{item.classList}}\"\r\n [class.divider-top]=\"item.display === 'divider-top' || (isDividedSectionChild && isFirst)\"\r\n [class.divider]=\"item.display === 'divider' || (isDividedSectionChild && isLast)\"\r\n [attr.disabled]=\"item.disabled\"\r\n [hidden]=\"item.hidden\"\r\n ecNavItemActive=\"is-selected\"\r\n [ecNavItemActiveQueryParams]=\"item.queryParams\"\r\n [ecNavItemActiveUrl]=\"item.url\"\r\n [ecNavItemActiveExactMatch]='item.isActiveExactMatch'\r\n (routerLinkActivated)=\"selectItem($event, item)\"\r\n [ngClass]=\"{'is-highlighted':(selected === item && item?.display !== 'heading') || highlightedItem === item, 'is-link': item.url, 'is-disabled': item.disabled, 'is-readonly': item.readonly, 'is-checked': item.checked, 'text-heading-3': item?.display === 'heading'}\"\r\n (click)=\"selectItem($event, item)\">\r\n\r\n <a *ngIf=\"item.url && !item.externalLink\"\r\n id=\"{{item.id}}_link\"\r\n title=\"{{truncateItems ? item.label : ''}}\"\r\n class=\"item-wrapper\"\r\n [routerLink]=\"item.url\"\r\n [queryParams]=\"item.queryParams || null\"\r\n target=\"{{item.target || '_self'}}\">\r\n <ng-container *ngTemplateOutlet=\"internalizedTemplate; context: {$implicit: item}\"></ng-container>\r\n </a>\r\n\r\n <a *ngIf=\"item.url && item.externalLink\"\r\n id=\"{{item.id}}_link\"\r\n title=\"{{truncateItems ? item.label : ''}}\"\r\n class=\"item-wrapper\"\r\n href=\"{{item.url}}\"\r\n target=\"{{item.target || '_self'}}\">\r\n <ng-container *ngTemplateOutlet=\"internalizedTemplate; context: {$implicit: item}\"></ng-container>\r\n </a>\r\n\r\n <div *ngIf=\"!item.url\"\r\n title=\"{{truncateItems ? item.label : ''}}\"\r\n class=\"item-wrapper\">\r\n <ng-container *ngTemplateOutlet=\"internalizedTemplate; context: {$implicit: item}\"></ng-container>\r\n </div>\r\n </li>\r\n</ng-template>\r\n\r\n<!-- 'label' Item Template -->\r\n<ng-template #label\r\n let-item>\r\n <span id=\"{{item.id}}_label\"\r\n class=\"label\"\r\n [class.text-truncate]=\"truncateItems\">{{item.label}}</span>\r\n\r\n <i class=\"ec-icon icon-angle-down rotate-270\"\r\n *ngIf=\"item?.items && item.display !== 'heading' && item.display !== 'divided-section'\"></i>\r\n</ng-template>\r\n\r\n<!-- 'checkAndLabel' Item Template -->\r\n<ng-template #checkAndLabel\r\n let-item>\r\n\r\n <i class=\"ec-icon icon-check ec-icon-sm\"\r\n *ngIf=\"item.display !== 'heading'\"></i>\r\n\r\n <i class=\"ec-icon {{item.icon}} ml-2\"\r\n *ngIf=\"item.icon\"></i>\r\n\r\n <span id=\"{{item.id}}_label\"\r\n class=\"label\"\r\n [class.text-truncate]=\"truncateItems\">{{item.label}}</span>\r\n\r\n <i class=\"ec-icon icon-angle-down rotate-270\"\r\n *ngIf=\"item?.items && item.display !== 'heading' && item.display !== 'divided-section'\"></i>\r\n</ng-template>\r\n\r\n<!-- 'iconAndLabel' Item Template -->\r\n<ng-template #iconAndLabel\r\n let-item>\r\n <!-- If menuItem.icon exists and is not blank, show the icon in the menu -->\r\n <i class=\"ec-icon {{item.icon}}\"\r\n *ngIf=\"(item.icon && item.icon !== '') || preserveIconSpace\"></i>\r\n\r\n <span id=\"{{item.id}}_label\"\r\n class=\"label\"\r\n [class.text-truncate]=\"truncateItems\">{{item.label}}</span>\r\n\r\n <i class=\"ec-icon icon-angle-down rotate-270\"\r\n *ngIf=\"item?.items && item.display !== 'heading' && item.display !== 'divided-section'\"></i>\r\n</ng-template>\r\n\r\n<ng-template #iconLabelCaption\r\n let-item>\r\n <i class=\"ec-icon {{item.icon}}\"\r\n *ngIf=\"(item.icon && item.icon !== '') || preserveIconSpace\"></i>\r\n <div *ngIf=\"item.display !== 'heading'\"\r\n class=\"label flex-grow\">\r\n <div id=\"{{item.id}}_label\"\r\n class=\"text-body-1\"\r\n [class.text-truncate]=\"truncateItems\">{{item.label}}</div>\r\n <div id=\"{{item.id}}_caption\"\r\n *ngIf=\"item.caption\"\r\n class=\"text-caption-1\"\r\n [class.text-truncate]=\"truncateItems\">{{item.caption}}</div>\r\n </div>\r\n <h3 *ngIf=\"item.display === 'heading'\"\r\n class=\"flex-grow text-heading-3 align-self-center\"\r\n [class.text-truncate]=\"truncateItems\">{{item.label}}</h3>\r\n <i class=\"ec-icon icon-angle-down rotate-270 align-self-center\"\r\n *ngIf=\"item?.items && item.display !== 'heading' && item.display !== 'divided-section'\"></i>\r\n</ng-template>", styles: ["@keyframes spin{0%{transform:rotate(0)}to{transform:rotate(1turn)}}:host{display:block;font-size:var(--ec-menu-font-size, var(--ec-font-size-action));font-weight:400;background-color:var(--ec-menu-background-color, var(--ec-background-color))}:host.open>nav>.parent,:host.open>nav>.child{position:absolute;left:0;top:0;right:0;height:100%;transition:transform .25s ease}:host.open>nav>.parent{transform:translate(0)}:host.open>nav>.child{transform:translate(100%)}:host.open-active>nav>.parent{transform:translate(-100%)}:host.open-active>nav>.child{transform:translate(0)}:host(.bg-transparent){background-color:transparent}:host-context(.is-always-open){height:100%}:host-context(.is-always-open) .item-wrapper{padding-left:1rem;padding-right:1rem}nav{display:flex;position:relative;height:100%;overflow:hidden}.parent{display:flex;flex-direction:column;flex:auto;position:relative;max-width:100%}.parent>header{cursor:pointer}.parent>header.is-selected .item-wrapper,.parent>header.is-highlighted .item-wrapper{background-color:var(--ec-background-color-selected)}.parent>header:hover .item-wrapper{background-color:var(--ec-background-color-hover)}.parent.no-data ul{display:none}.parent.no-data .no-data-message{display:block}ul{padding:0;margin:0;list-style:none;flex:auto;height:100%;overflow-y:auto}ul li{cursor:pointer;padding:0 .25rem}ul li a{color:inherit;border-bottom:0;text-decoration:none}ul li.is-selected .item-wrapper,ul li.is-highlighted .item-wrapper{background-color:var(--ec-background-color-selected)}ul li:hover .item-wrapper{background-color:var(--ec-background-color-hover)}ul li:focus .item-wrapper{outline:none;background-color:var(--ec-color-disabled-dark);position:relative;z-index:1}ul li.is-disabled .item-wrapper{color:var(--ec-color-disabled-dark);opacity:var(--ec-form-control-opacity-disabled)}ul li.is-disabled,ul li.is-readonly{cursor:default}ul li.is-disabled .item-wrapper,ul li.is-readonly .item-wrapper{background-color:transparent;color:inherit}ul li.is-checked .icon-check{opacity:1}ul li.heading{cursor:default}ul li.heading .item-wrapper{background-color:transparent}ul li.heading:not(:first-child){margin-top:.5rem}ul li.divider:not(:last-child){border-bottom:1px solid var(--ec-border-color);padding-bottom:.25rem;margin-bottom:.25rem}ul li.divider-top:not(:first-child):not(.divider + .divider-top){border-top:1px solid var(--ec-border-color);padding-top:.25rem;margin-top:.25rem}ul li.indent-1 .item-wrapper{padding-left:1.5rem}ul li.indent-2 .item-wrapper{padding-left:2.5rem}ul li.indent-3 .item-wrapper{padding-left:3.5rem}.item-wrapper{cursor:inherit;line-height:1.25rem;min-height:1.75rem;padding:.25rem .5rem;border-radius:var(--ec-border-radius);display:flex;color:inherit}.item-wrapper .label{margin-right:auto}.item-wrapper .label+.ec-icon{margin-left:.5rem}.item-wrapper .ec-icon{margin-top:calc((1.25rem - var(--ec-font-size-icon)) / 2);flex:none}.item-wrapper .ec-icon+.label{margin-left:.5rem}.item-wrapper .ec-icon-sm{margin-top:calc((1.25rem - calc(var(--ec-font-size-icon) * .75)) / 2)}.item-wrapper .icon-check{opacity:0}.no-data-message{display:none;text-align:center;padding:1rem;color:var(--ec-color-hint-dark);margin-bottom:0;font-size:var(--ec-font-size-body)}:host-context(ec-tree) ul{overflow-x:hidden}:host-context(ec-tree) li.is-selected,:host-context(ec-tree) li.is-highlighted{font-weight:700;color:var(--ec-menu-color-highlighted, inherit)}:host-context(ec-tree) li.is-selected:not(:hover),:host-context(ec-tree) li.is-highlighted:not(:hover){background-color:transparent}\n"], dependencies: [{ kind: "directive", type: i1.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: i1.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i1.NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "directive", type: i1$2.RouterLink, selector: "[routerLink]", inputs: ["target", "queryParams", "fragment", "queryParamsHandling", "state", "relativeTo", "preserveFragment", "skipLocationChange", "replaceUrl", "routerLink"] }, { kind: "directive", type: NavItemActiveDirective, selector: "[ecNavItemActive]", inputs: ["ecNavItemActive", "ecNavItemActiveExactMatch", "ecNavItemActiveQueryParams", "ecNavItemActiveUrl"], outputs: ["routerLinkActivated"] }, { kind: "component", type: MenuComponent, selector: "ec-menu", inputs: ["id", "items", "selected", "parent", "templateType", "customMenuTemplate", "title", "showNoItems", "noDataText", "enableKeyNav", "highlightedItem", "maintainSelectedItem", "truncateItems", "preserveIconSpace", "dropdownToggleButton"], outputs: ["selectedChanged", "menuClosed"] }, { kind: "pipe", type: i2.TranslatePipe, name: "translate" }] });
|
2253
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.9", ngImport: i0, type: MenuComponent, decorators: [{
|
2254
|
+
type: Component,
|
2255
|
+
args: [{ selector: 'ec-menu', template: "<nav>\r\n <div class=\"parent\"\r\n [class.no-data]=\"showNoItems && (!items || items.length === 0)\">\r\n <header id=\"{{id}}_header\"\r\n class=\"text-heading-3 p-1\"\r\n [class.is-selected]=\"highlightedItemIndex === -1\"\r\n *ngIf=\"parent\"\r\n (click)=\"back($event)\">\r\n <div class=\"item-wrapper\">\r\n <i class=\"ec-icon icon-angle-down rotate-90 flex-shrink\"></i>\r\n <span class=\"label text-truncate flex-grow\">{{parent?.label}}</span>\r\n </div>\r\n </header>\r\n\r\n <ul id=\"{{id}}_list\"\r\n class=\"py-1\">\r\n <ng-container *ngFor=\"let item of items; index as i\">\r\n <ng-container *ngTemplateOutlet=\"itemTemplate; context: {$implicit: item, index: i}\"></ng-container>\r\n\r\n <!-- Show child items under parent item if the item is a heading or divided-section -->\r\n <ng-container *ngIf=\"item.items?.length && (item.display === 'heading' || item.display === 'divided-section')\">\r\n <ng-container *ngFor=\"let childItem of item.items; index as j; first as isFirst; last as isLast\"\r\n [ngTemplateOutlet]=\"itemTemplate\"\r\n [ngTemplateOutletContext]=\"{$implicit: childItem, index: i + '-' + j, isDividedSectionChild: item.display === 'divided-section', isFirst: isFirst, isLast: isLast}\">\r\n </ng-container>\r\n </ng-container>\r\n </ng-container>\r\n </ul>\r\n\r\n <p class=\"no-data-message\">{{noDataText | translate}}</p>\r\n </div>\r\n\r\n <!-- Child menu (Rendered to the right) -->\r\n <ec-menu *ngIf=\"selected?.items && selected?.display !== 'heading' && selected?.display !== 'divided-section'\"\r\n id=\"{{id}}_child\"\r\n class=\"child\"\r\n [parent]=\"selected\"\r\n [items]=\"selected?.items\"\r\n [showNoItems]=\"true\"\r\n [templateType]=\"templateType\"\r\n [enableKeyNav]=\"true\"\r\n [truncateItems]=\"truncateItems\"\r\n (selectedChanged)=\"onSelection($event)\"\r\n (menuClosed)=\"toggleChildMenu(false)\">\r\n </ec-menu>\r\n</nav>\r\n\r\n<ng-template #itemTemplate\r\n let-item\r\n let-i=\"index\"\r\n let-isDividedSectionChild=\"isDividedSectionChild\"\r\n let-isFirst=\"isFirst\"\r\n let-isLast=\"isLast\">\r\n <li *ngIf=\"!(item.hideIfNoItems && !item.items?.length) && item.display !== 'divided-section'\"\r\n id=\"{{item.id || id + '_item' + i}}\"\r\n class=\"{{item.display || 'item'}} {{item.classList}}\"\r\n [class.divider-top]=\"item.display === 'divider-top' || (isDividedSectionChild && isFirst)\"\r\n [class.divider]=\"item.display === 'divider' || (isDividedSectionChild && isLast)\"\r\n [attr.disabled]=\"item.disabled\"\r\n [hidden]=\"item.hidden\"\r\n ecNavItemActive=\"is-selected\"\r\n [ecNavItemActiveQueryParams]=\"item.queryParams\"\r\n [ecNavItemActiveUrl]=\"item.url\"\r\n [ecNavItemActiveExactMatch]='item.isActiveExactMatch'\r\n (routerLinkActivated)=\"selectItem($event, item)\"\r\n [ngClass]=\"{'is-highlighted':(selected === item && item?.display !== 'heading') || highlightedItem === item, 'is-link': item.url, 'is-disabled': item.disabled, 'is-readonly': item.readonly, 'is-checked': item.checked, 'text-heading-3': item?.display === 'heading'}\"\r\n (click)=\"selectItem($event, item)\">\r\n\r\n <a *ngIf=\"item.url && !item.externalLink\"\r\n id=\"{{item.id}}_link\"\r\n title=\"{{truncateItems ? item.label : ''}}\"\r\n class=\"item-wrapper\"\r\n [routerLink]=\"item.url\"\r\n [queryParams]=\"item.queryParams || null\"\r\n target=\"{{item.target || '_self'}}\">\r\n <ng-container *ngTemplateOutlet=\"internalizedTemplate; context: {$implicit: item}\"></ng-container>\r\n </a>\r\n\r\n <a *ngIf=\"item.url && item.externalLink\"\r\n id=\"{{item.id}}_link\"\r\n title=\"{{truncateItems ? item.label : ''}}\"\r\n class=\"item-wrapper\"\r\n href=\"{{item.url}}\"\r\n target=\"{{item.target || '_self'}}\">\r\n <ng-container *ngTemplateOutlet=\"internalizedTemplate; context: {$implicit: item}\"></ng-container>\r\n </a>\r\n\r\n <div *ngIf=\"!item.url\"\r\n title=\"{{truncateItems ? item.label : ''}}\"\r\n class=\"item-wrapper\">\r\n <ng-container *ngTemplateOutlet=\"internalizedTemplate; context: {$implicit: item}\"></ng-container>\r\n </div>\r\n </li>\r\n</ng-template>\r\n\r\n<!-- 'label' Item Template -->\r\n<ng-template #label\r\n let-item>\r\n <span id=\"{{item.id}}_label\"\r\n class=\"label\"\r\n [class.text-truncate]=\"truncateItems\">{{item.label}}</span>\r\n\r\n <i class=\"ec-icon icon-angle-down rotate-270\"\r\n *ngIf=\"item?.items && item.display !== 'heading' && item.display !== 'divided-section'\"></i>\r\n</ng-template>\r\n\r\n<!-- 'checkAndLabel' Item Template -->\r\n<ng-template #checkAndLabel\r\n let-item>\r\n\r\n <i class=\"ec-icon icon-check ec-icon-sm\"\r\n *ngIf=\"item.display !== 'heading'\"></i>\r\n\r\n <i class=\"ec-icon {{item.icon}} ml-2\"\r\n *ngIf=\"item.icon\"></i>\r\n\r\n <span id=\"{{item.id}}_label\"\r\n class=\"label\"\r\n [class.text-truncate]=\"truncateItems\">{{item.label}}</span>\r\n\r\n <i class=\"ec-icon icon-angle-down rotate-270\"\r\n *ngIf=\"item?.items && item.display !== 'heading' && item.display !== 'divided-section'\"></i>\r\n</ng-template>\r\n\r\n<!-- 'iconAndLabel' Item Template -->\r\n<ng-template #iconAndLabel\r\n let-item>\r\n <!-- If menuItem.icon exists and is not blank, show the icon in the menu -->\r\n <i class=\"ec-icon {{item.icon}}\"\r\n *ngIf=\"(item.icon && item.icon !== '') || preserveIconSpace\"></i>\r\n\r\n <span id=\"{{item.id}}_label\"\r\n class=\"label\"\r\n [class.text-truncate]=\"truncateItems\">{{item.label}}</span>\r\n\r\n <i class=\"ec-icon icon-angle-down rotate-270\"\r\n *ngIf=\"item?.items && item.display !== 'heading' && item.display !== 'divided-section'\"></i>\r\n</ng-template>\r\n\r\n<ng-template #iconLabelCaption\r\n let-item>\r\n <i class=\"ec-icon {{item.icon}}\"\r\n *ngIf=\"(item.icon && item.icon !== '') || preserveIconSpace\"></i>\r\n <div *ngIf=\"item.display !== 'heading'\"\r\n class=\"label flex-grow\">\r\n <div id=\"{{item.id}}_label\"\r\n class=\"text-body-1\"\r\n [class.text-truncate]=\"truncateItems\">{{item.label}}</div>\r\n <div id=\"{{item.id}}_caption\"\r\n *ngIf=\"item.caption\"\r\n class=\"text-caption-1\"\r\n [class.text-truncate]=\"truncateItems\">{{item.caption}}</div>\r\n </div>\r\n <h3 *ngIf=\"item.display === 'heading'\"\r\n class=\"flex-grow text-heading-3 align-self-center\"\r\n [class.text-truncate]=\"truncateItems\">{{item.label}}</h3>\r\n <i class=\"ec-icon icon-angle-down rotate-270 align-self-center\"\r\n *ngIf=\"item?.items && item.display !== 'heading' && item.display !== 'divided-section'\"></i>\r\n</ng-template>", styles: ["@keyframes spin{0%{transform:rotate(0)}to{transform:rotate(1turn)}}:host{display:block;font-size:var(--ec-menu-font-size, var(--ec-font-size-action));font-weight:400;background-color:var(--ec-menu-background-color, var(--ec-background-color))}:host.open>nav>.parent,:host.open>nav>.child{position:absolute;left:0;top:0;right:0;height:100%;transition:transform .25s ease}:host.open>nav>.parent{transform:translate(0)}:host.open>nav>.child{transform:translate(100%)}:host.open-active>nav>.parent{transform:translate(-100%)}:host.open-active>nav>.child{transform:translate(0)}:host(.bg-transparent){background-color:transparent}:host-context(.is-always-open){height:100%}:host-context(.is-always-open) .item-wrapper{padding-left:1rem;padding-right:1rem}nav{display:flex;position:relative;height:100%;overflow:hidden}.parent{display:flex;flex-direction:column;flex:auto;position:relative;max-width:100%}.parent>header{cursor:pointer}.parent>header.is-selected .item-wrapper,.parent>header.is-highlighted .item-wrapper{background-color:var(--ec-background-color-selected)}.parent>header:hover .item-wrapper{background-color:var(--ec-background-color-hover)}.parent.no-data ul{display:none}.parent.no-data .no-data-message{display:block}ul{padding:0;margin:0;list-style:none;flex:auto;height:100%;overflow-y:auto}ul li{cursor:pointer;padding:0 .25rem}ul li a{color:inherit;border-bottom:0;text-decoration:none}ul li.is-selected .item-wrapper,ul li.is-highlighted .item-wrapper{background-color:var(--ec-background-color-selected)}ul li:hover .item-wrapper{background-color:var(--ec-background-color-hover)}ul li:focus .item-wrapper{outline:none;background-color:var(--ec-color-disabled-dark);position:relative;z-index:1}ul li.is-disabled .item-wrapper{color:var(--ec-color-disabled-dark);opacity:var(--ec-form-control-opacity-disabled)}ul li.is-disabled,ul li.is-readonly{cursor:default}ul li.is-disabled .item-wrapper,ul li.is-readonly .item-wrapper{background-color:transparent;color:inherit}ul li.is-checked .icon-check{opacity:1}ul li.heading{cursor:default}ul li.heading .item-wrapper{background-color:transparent}ul li.heading:not(:first-child){margin-top:.5rem}ul li.divider:not(:last-child){border-bottom:1px solid var(--ec-border-color);padding-bottom:.25rem;margin-bottom:.25rem}ul li.divider-top:not(:first-child):not(.divider + .divider-top){border-top:1px solid var(--ec-border-color);padding-top:.25rem;margin-top:.25rem}ul li.indent-1 .item-wrapper{padding-left:1.5rem}ul li.indent-2 .item-wrapper{padding-left:2.5rem}ul li.indent-3 .item-wrapper{padding-left:3.5rem}.item-wrapper{cursor:inherit;line-height:1.25rem;min-height:1.75rem;padding:.25rem .5rem;border-radius:var(--ec-border-radius);display:flex;color:inherit}.item-wrapper .label{margin-right:auto}.item-wrapper .label+.ec-icon{margin-left:.5rem}.item-wrapper .ec-icon{margin-top:calc((1.25rem - var(--ec-font-size-icon)) / 2);flex:none}.item-wrapper .ec-icon+.label{margin-left:.5rem}.item-wrapper .ec-icon-sm{margin-top:calc((1.25rem - calc(var(--ec-font-size-icon) * .75)) / 2)}.item-wrapper .icon-check{opacity:0}.no-data-message{display:none;text-align:center;padding:1rem;color:var(--ec-color-hint-dark);margin-bottom:0;font-size:var(--ec-font-size-body)}:host-context(ec-tree) ul{overflow-x:hidden}:host-context(ec-tree) li.is-selected,:host-context(ec-tree) li.is-highlighted{font-weight:700;color:var(--ec-menu-color-highlighted, inherit)}:host-context(ec-tree) li.is-selected:not(:hover),:host-context(ec-tree) li.is-highlighted:not(:hover){background-color:transparent}\n"] }]
|
2256
|
+
}], ctorParameters: function () { return [{ type: i0.ElementRef }, { type: i0.Renderer2 }, { type: WindowService }, { type: ScrollService }]; }, propDecorators: { id: [{
|
2257
|
+
type: Input
|
2258
|
+
}], attrId: [{
|
2259
|
+
type: HostBinding,
|
2260
|
+
args: ['attr.id']
|
2261
|
+
}], items: [{
|
2262
|
+
type: Input
|
2263
|
+
}], selected: [{
|
2264
|
+
type: Input
|
2265
|
+
}], parent: [{
|
2266
|
+
type: Input
|
2267
|
+
}], templateType: [{
|
2268
|
+
type: Input
|
2269
|
+
}], customMenuTemplate: [{
|
2270
|
+
type: Input
|
2271
|
+
}], title: [{
|
2272
|
+
type: Input
|
2273
|
+
}], showNoItems: [{
|
2274
|
+
type: Input
|
2275
|
+
}], noDataText: [{
|
2276
|
+
type: Input
|
2277
|
+
}], enableKeyNav: [{
|
2278
|
+
type: Input
|
2279
|
+
}], highlightedItem: [{
|
2280
|
+
type: Input
|
2281
|
+
}], maintainSelectedItem: [{
|
2282
|
+
type: Input
|
2283
|
+
}], truncateItems: [{
|
2284
|
+
type: Input
|
2285
|
+
}], preserveIconSpace: [{
|
2286
|
+
type: Input
|
2287
|
+
}], dropdownToggleButton: [{
|
2288
|
+
type: Input
|
2289
|
+
}], selectedChanged: [{
|
2290
|
+
type: Output
|
2291
|
+
}], menuClosed: [{
|
2198
2292
|
type: Output
|
2293
|
+
}], labelTemplate: [{
|
2294
|
+
type: ViewChild,
|
2295
|
+
args: ['label', { static: true }]
|
2296
|
+
}], iconAndLabelTemplate: [{
|
2297
|
+
type: ViewChild,
|
2298
|
+
args: ['iconAndLabel', { static: true }]
|
2299
|
+
}], checkAndLabelTemplate: [{
|
2300
|
+
type: ViewChild,
|
2301
|
+
args: ['checkAndLabel', { static: true }]
|
2302
|
+
}], iconLabelCaptionTemplate: [{
|
2303
|
+
type: ViewChild,
|
2304
|
+
args: ['iconLabelCaption', { static: true }]
|
2199
2305
|
}] } });
|
2200
2306
|
|
2201
|
-
;
|
2202
|
-
const menuAnimationSpeed = 350;
|
2203
2307
|
/**
|
2204
|
-
* Primitive
|
2308
|
+
* Primitive directive that popups a container using PopperJS
|
2205
2309
|
*
|
2206
2310
|
* @export
|
2207
2311
|
*/
|
2208
|
-
class
|
2209
|
-
|
2210
|
-
|
2312
|
+
class PopupContainerDirective {
|
2313
|
+
/**
|
2314
|
+
* Creates an instance of PopupContainerDirective.
|
2315
|
+
* @param templateRef Reference to the popup template
|
2316
|
+
* @param viewContainer Reference to the view container
|
2317
|
+
* @param document Reference to Document
|
2318
|
+
* @memberof PopupContainerDirective
|
2319
|
+
*/
|
2320
|
+
constructor(templateRef, viewContainer, document, renderer) {
|
2321
|
+
this.templateRef = templateRef;
|
2322
|
+
this.viewContainer = viewContainer;
|
2323
|
+
this.document = document;
|
2211
2324
|
this.renderer = renderer;
|
2212
|
-
this.windowService = windowService;
|
2213
|
-
this.scrollService = scrollService;
|
2214
|
-
/**
|
2215
|
-
* Array of items to display
|
2216
|
-
*
|
2217
|
-
* @memberof MenuComponent
|
2218
|
-
*/
|
2219
|
-
this.items = [];
|
2220
|
-
/**
|
2221
|
-
* Selected item; annotates the item
|
2222
|
-
* when displayed with 'selected' class
|
2223
|
-
*
|
2224
|
-
* @memberof MenuComponent
|
2225
|
-
*/
|
2226
|
-
this.selected = null;
|
2227
|
-
/**
|
2228
|
-
* Display template
|
2229
|
-
*
|
2230
|
-
* @memberof MenuComponent
|
2231
|
-
*/
|
2232
|
-
this.templateType = 'label';
|
2233
|
-
/**
|
2234
|
-
* Show message when there are no items
|
2235
|
-
*/
|
2236
|
-
this.showNoItems = false;
|
2237
|
-
/**
|
2238
|
-
* Text to show when menu is empty and showNoItems is true
|
2239
|
-
*/
|
2240
|
-
this.noDataText = 'NoItems_TC';
|
2241
2325
|
/**
|
2242
|
-
*
|
2243
|
-
*/
|
2244
|
-
this.enableKeyNav = false;
|
2245
|
-
/**
|
2246
|
-
* Item currently highlighted by keyboard navigation
|
2247
|
-
*/
|
2248
|
-
this.highlightedItem = null;
|
2249
|
-
/**
|
2250
|
-
* Tells the menu to maintain the selected/lastSelected item. Turning this off is useful for
|
2251
|
-
* action type menus that are displayed on the screen at all times and you do not
|
2252
|
-
* want the item to be selected when clicked.
|
2253
|
-
*/
|
2254
|
-
this.maintainSelectedItem = true;
|
2255
|
-
/**
|
2256
|
-
* Will prevent text-wrapping of menu items and truncate instead. Also turns on a tooltip for the menu item. Default: false;
|
2257
|
-
*/
|
2258
|
-
this.truncateItems = false;
|
2259
|
-
/**
|
2260
|
-
* When true, the space for the icon is preserved for menu items that do not have icons.
|
2261
|
-
* Only applicable for iconAndLabel menus.
|
2262
|
-
*/
|
2263
|
-
this.preserveIconSpace = false;
|
2264
|
-
/**
|
2265
|
-
* Emitted when `selected` is changed. Emits the referenced object.
|
2266
|
-
*
|
2267
|
-
* @memberof MenuComponent
|
2268
|
-
*/
|
2269
|
-
this.selectedChanged = new EventEmitter();
|
2270
|
-
/**
|
2271
|
-
* Emitted when the menu has a parent and back is clicked
|
2272
|
-
* @memberof MenuComponent
|
2273
|
-
*/
|
2274
|
-
this.menuClosed = new EventEmitter();
|
2275
|
-
/**
|
2276
|
-
* Index of the item currently highlighted using keyboard nav
|
2277
|
-
*/
|
2278
|
-
this.highlightedItemIndex = -1;
|
2279
|
-
/**
|
2280
|
-
* Last item this.selected was set to via selectItem().
|
2281
|
-
* This isn't necessarily the same as this.selected, because this.selected is an input property
|
2282
|
-
* and could have been changed by a consumer through some means other than selectItem().
|
2283
|
-
* This allows us to prevent double-calls to selectItem() with the same input.
|
2326
|
+
* Emit the {@link PopupStatus} when it changes
|
2284
2327
|
*/
|
2285
|
-
this.
|
2328
|
+
this.popperStatusChange = new EventEmitter();
|
2286
2329
|
}
|
2287
2330
|
/**
|
2288
|
-
*
|
2289
|
-
*
|
2290
|
-
|
2331
|
+
* Angular onInit lifecycle hook
|
2332
|
+
* @see https://angular.io/guide/lifecycle-hooks
|
2333
|
+
*/
|
2334
|
+
ngOnInit() {
|
2335
|
+
this.templateViewRef = this.viewContainer.createEmbeddedView(this.templateRef);
|
2336
|
+
}
|
2337
|
+
/**
|
2338
|
+
* Angular onDestroy lifecycle hook. Close and delete references. Unsubscribe observables
|
2339
|
+
* @see https://angular.io/guide/lifecycle-hooks
|
2340
|
+
*/
|
2341
|
+
ngOnDestroy() {
|
2342
|
+
this.hide();
|
2343
|
+
}
|
2344
|
+
/**
|
2345
|
+
* Displays the templateRef as a popup
|
2291
2346
|
*
|
2292
|
-
* @memberof
|
2347
|
+
* @memberof PopupContainerDirective
|
2293
2348
|
*/
|
2294
|
-
|
2295
|
-
|
2296
|
-
|
2297
|
-
|
2298
|
-
|
2299
|
-
|
2300
|
-
this.internalizedTemplate = this.iconAndLabelTemplate;
|
2301
|
-
break;
|
2302
|
-
case ("checkAndLabel"):
|
2303
|
-
this.internalizedTemplate = this.checkAndLabelTemplate;
|
2304
|
-
break;
|
2305
|
-
case ("iconLabelCaption"):
|
2306
|
-
this.internalizedTemplate = this.iconLabelCaptionTemplate;
|
2307
|
-
break;
|
2308
|
-
default:
|
2309
|
-
throw new Error(`Invalid templateType for MenuComponent. Please use either: 'label', 'iconAndLabel' or 'checkAndLabel'`);
|
2310
|
-
}
|
2311
|
-
//if the consumer provided a menuItemTemplate, override the internalizedTemplate with that.
|
2312
|
-
if (this.customMenuTemplate) {
|
2313
|
-
this.internalizedTemplate = this.customMenuTemplate;
|
2349
|
+
show() {
|
2350
|
+
if (PopupContainerDirective.GlobalPopupRef) {
|
2351
|
+
if (PopupContainerDirective.GlobalPopupRef != this) {
|
2352
|
+
PopupContainerDirective.GlobalPopupRef.hide();
|
2353
|
+
PopupContainerDirective.GlobalPopupRef = undefined;
|
2354
|
+
}
|
2314
2355
|
}
|
2315
|
-
if (this.
|
2316
|
-
this.
|
2356
|
+
if (!this.globalCloseSubscription) {
|
2357
|
+
this.globalCloseSubscription = fromEvent(this.document.body, "click").subscribe((event) => {
|
2358
|
+
this.hide();
|
2359
|
+
});
|
2317
2360
|
}
|
2318
|
-
this.
|
2319
|
-
|
2320
|
-
|
2361
|
+
if (!this.popperRef) {
|
2362
|
+
// Add the popper template as an embedded view since PopperJS
|
2363
|
+
// manipulates DOM elements.
|
2364
|
+
this.popupViewRef = this.viewContainer.createEmbeddedView(this.popup);
|
2365
|
+
// Since popper needs real DOM elements, grab the first non-comment
|
2366
|
+
// DOM element to use as our anchor.
|
2367
|
+
let anchorElement = this.popupViewRef.rootNodes.find(elem => { return elem.nodeName !== "#text"; });
|
2368
|
+
// Use the parents elements as our DOM elements to Popper
|
2369
|
+
this.popperRef = new Popper(this.templateViewRef.rootNodes[0], anchorElement, this.popperOptions);
|
2370
|
+
PopupContainerDirective.GlobalPopupRef = this;
|
2371
|
+
this.popperStatusChange.emit('visible');
|
2321
2372
|
}
|
2322
|
-
this.addKeydownListener();
|
2323
2373
|
}
|
2324
|
-
|
2325
|
-
|
2326
|
-
|
2327
|
-
|
2374
|
+
/**
|
2375
|
+
* Hides the templateRef
|
2376
|
+
*
|
2377
|
+
* @memberof PopupContainerDirective
|
2378
|
+
*/
|
2379
|
+
hide() {
|
2380
|
+
if (this.globalCloseSubscription) {
|
2381
|
+
this.globalCloseSubscription.unsubscribe();
|
2382
|
+
this.globalCloseSubscription = undefined;
|
2383
|
+
}
|
2384
|
+
if (this.popperRef && this.popupViewRef) {
|
2385
|
+
this.popupViewRef.destroy();
|
2386
|
+
this.popperRef.destroy();
|
2387
|
+
this.popperRef = undefined;
|
2388
|
+
this.popperStatusChange.emit('hidden');
|
2328
2389
|
}
|
2329
2390
|
}
|
2330
2391
|
/**
|
2331
|
-
*
|
2332
|
-
* the item's click method if defined, or emit the selected item.
|
2333
|
-
*
|
2334
|
-
* @param item The selected item
|
2335
|
-
* @memberof MenuComponent
|
2392
|
+
* Updates the popup container position
|
2336
2393
|
*/
|
2337
|
-
|
2338
|
-
|
2339
|
-
|
2340
|
-
|
2341
|
-
|
2342
|
-
|
2343
|
-
|
2344
|
-
|
2345
|
-
|
2346
|
-
|
2347
|
-
|
2348
|
-
|
2349
|
-
|
2350
|
-
|
2351
|
-
|
2394
|
+
update() {
|
2395
|
+
if (this.popperRef) {
|
2396
|
+
this.popperRef.update();
|
2397
|
+
}
|
2398
|
+
}
|
2399
|
+
fixPosition(minWidthNone, appendToBody = false) {
|
2400
|
+
if (this.popperRef && this.popperRef['reference'] && this.popperRef['popper']) {
|
2401
|
+
let popupEl = this.popperRef['popper'];
|
2402
|
+
// Reset width style previously assigned because the content may have
|
2403
|
+
// changed and the auto width would be different
|
2404
|
+
this.renderer.removeStyle(popupEl, 'width');
|
2405
|
+
this.renderer.setStyle(popupEl, 'position', 'fixed');
|
2406
|
+
if (appendToBody) {
|
2407
|
+
const bodyEl = this.document.querySelector('body');
|
2408
|
+
const popupParent = this.renderer.parentNode(popupEl);
|
2409
|
+
if (popupParent !== bodyEl) {
|
2410
|
+
this.renderer.appendChild(bodyEl, popupEl);
|
2352
2411
|
}
|
2353
|
-
// We need to manually handle the url navigation if the keyboard was used
|
2354
2412
|
}
|
2355
|
-
|
2356
|
-
|
2357
|
-
|
2413
|
+
let toggleEl = this.popperRef['reference'];
|
2414
|
+
let width = popupEl.offsetWidth;
|
2415
|
+
let boundaries = popupEl.getBoundingClientRect();
|
2416
|
+
let left = boundaries.left;
|
2417
|
+
let coords = toggleEl.getBoundingClientRect();
|
2418
|
+
// Set the top of our menu to the bottom of the toggle element
|
2419
|
+
let top = coords.bottom;
|
2420
|
+
if (this.popperOptions && this.popperOptions.placement) {
|
2421
|
+
if (this.popperOptions.placement === 'bottom-start' || this.popperOptions.placement === 'top-start') {
|
2422
|
+
left = coords.left;
|
2358
2423
|
}
|
2359
2424
|
else {
|
2360
|
-
|
2425
|
+
left = coords.right - ((minWidthNone || width > coords.width) ? width : coords.width);
|
2361
2426
|
}
|
2362
|
-
// Emit so upstream components know an item was selected
|
2363
|
-
this.onSelection(item);
|
2364
|
-
}
|
2365
|
-
else {
|
2366
|
-
this.onSelection(item);
|
2367
2427
|
}
|
2368
|
-
if (
|
2369
|
-
|
2370
|
-
|
2428
|
+
// if it won't fit (with 10px space before hitting the window edge), flip it
|
2429
|
+
if (boundaries.height + top + 10 > window.innerHeight) {
|
2430
|
+
top = coords.top - boundaries.height;
|
2371
2431
|
}
|
2372
|
-
|
2373
|
-
|
2374
|
-
|
2432
|
+
this.renderer.setStyle(popupEl, 'transform', 'none');
|
2433
|
+
this.renderer.setStyle(popupEl, 'left', left + 'px');
|
2434
|
+
this.renderer.setStyle(popupEl, 'top', top + 'px');
|
2435
|
+
this.renderer.setStyle(popupEl, 'width', width + 'px');
|
2436
|
+
if (!minWidthNone) {
|
2437
|
+
this.renderer.setStyle(popupEl, 'min-width', coords.width + 'px');
|
2375
2438
|
}
|
2376
2439
|
}
|
2377
2440
|
}
|
2378
|
-
|
2379
|
-
|
2380
|
-
|
2381
|
-
|
2382
|
-
|
2383
|
-
|
2384
|
-
|
2385
|
-
|
2441
|
+
}
|
2442
|
+
/**
|
2443
|
+
* Global reference to the currently displayed popup; only
|
2444
|
+
* one popup directive can be in `show` state at a given time.
|
2445
|
+
*
|
2446
|
+
* @memberof PopupContainerDirective
|
2447
|
+
*/
|
2448
|
+
PopupContainerDirective.GlobalPopupRef = undefined;
|
2449
|
+
PopupContainerDirective.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.2.9", ngImport: i0, type: PopupContainerDirective, deps: [{ token: i0.TemplateRef }, { token: i0.ViewContainerRef }, { token: DOCUMENT }, { token: i0.Renderer2 }], target: i0.ɵɵFactoryTarget.Directive });
|
2450
|
+
PopupContainerDirective.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "15.2.9", type: PopupContainerDirective, selector: "[ecPopup]", inputs: { popup: ["ecPopup", "popup"], popperOptions: ["options", "popperOptions"] }, ngImport: i0 });
|
2451
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.9", ngImport: i0, type: PopupContainerDirective, decorators: [{
|
2452
|
+
type: Directive,
|
2453
|
+
args: [{ selector: '[ecPopup]' }]
|
2454
|
+
}], ctorParameters: function () { return [{ type: i0.TemplateRef }, { type: i0.ViewContainerRef }, { type: undefined, decorators: [{
|
2455
|
+
type: Inject,
|
2456
|
+
args: [DOCUMENT]
|
2457
|
+
}] }, { type: i0.Renderer2 }]; }, propDecorators: { popup: [{
|
2458
|
+
type: Input,
|
2459
|
+
args: ['ecPopup']
|
2460
|
+
}], popperOptions: [{
|
2461
|
+
type: Input,
|
2462
|
+
args: ['options']
|
2463
|
+
}] } });
|
2464
|
+
|
2465
|
+
/** Advanced validation for textbox form controls */
|
2466
|
+
const textboxValidation = (validatorParams) => {
|
2467
|
+
return (control) => {
|
2468
|
+
let validators = [];
|
2469
|
+
// Innocent until proven guilty
|
2470
|
+
validatorParams.valid = true;
|
2471
|
+
if (validatorParams.required) {
|
2472
|
+
validators.push(Validators.required);
|
2386
2473
|
}
|
2387
|
-
|
2388
|
-
|
2389
|
-
/**
|
2390
|
-
* Emit the selected item
|
2391
|
-
* @param item The selected item
|
2392
|
-
*/
|
2393
|
-
onSelection(item) {
|
2394
|
-
if (item.display !== 'heading') {
|
2395
|
-
this.selectedChanged.emit(item);
|
2474
|
+
if (validatorParams.minLength !== undefined) {
|
2475
|
+
validators.push(Validators.minLength(validatorParams.minLength));
|
2396
2476
|
}
|
2397
|
-
|
2398
|
-
|
2399
|
-
* Open or close the child menu. When the child menu closes, the selected
|
2400
|
-
* item is reset.
|
2401
|
-
* @memberof MenuComponent
|
2402
|
-
*/
|
2403
|
-
toggleChildMenu(open) {
|
2404
|
-
let navEl = this.el.nativeElement.querySelector('nav');
|
2405
|
-
if (open) {
|
2406
|
-
// Remove the listener on the parent menu when a child menu is opened
|
2407
|
-
// This is to avoid interference between the parent and child menus
|
2408
|
-
if (this.removeKeydownListener) {
|
2409
|
-
this.removeKeydownListener();
|
2410
|
-
}
|
2411
|
-
let height = navEl.offsetHeight;
|
2412
|
-
let width = navEl.offsetWidth;
|
2413
|
-
// In order to animate the child menu, we need to set height on the nav element
|
2414
|
-
// so we can absolutely position the two menus and maintain the current menu's height
|
2415
|
-
this.renderer.setStyle(navEl, 'height', `${height}px`);
|
2416
|
-
this.renderer.setStyle(navEl, 'width', `${width}px`);
|
2417
|
-
this.renderer.addClass(this.el.nativeElement, 'open');
|
2418
|
-
setTimeout(() => {
|
2419
|
-
this.renderer.addClass(this.el.nativeElement, 'open-active');
|
2420
|
-
});
|
2477
|
+
if (validatorParams.maxLength !== undefined) {
|
2478
|
+
validators.push(Validators.maxLength(validatorParams.maxLength));
|
2421
2479
|
}
|
2422
|
-
|
2423
|
-
|
2424
|
-
this.addKeydownListener();
|
2425
|
-
this.renderer.removeClass(this.el.nativeElement, 'open-active');
|
2426
|
-
setTimeout(() => {
|
2427
|
-
this.renderer.removeClass(this.el.nativeElement, 'open');
|
2428
|
-
// Reset the nav element's height to auto
|
2429
|
-
this.renderer.setStyle(navEl, 'height', '100%');
|
2430
|
-
this.selected = null;
|
2431
|
-
}, menuAnimationSpeed);
|
2480
|
+
if (validatorParams.pattern !== undefined) {
|
2481
|
+
validators.push(Validators.pattern(validatorParams.pattern));
|
2432
2482
|
}
|
2433
|
-
|
2434
|
-
|
2435
|
-
|
2436
|
-
|
2437
|
-
keyNavigate(event) {
|
2438
|
-
if (this.enableKeyNav && event.target === this.dropdownToggleButton?.nativeElement) {
|
2439
|
-
switch (event.key) {
|
2440
|
-
case 'ArrowUp':
|
2441
|
-
case 'Up':
|
2442
|
-
case 'ArrowDown':
|
2443
|
-
case 'Down':
|
2444
|
-
event.stopPropagation();
|
2445
|
-
event.preventDefault();
|
2446
|
-
this.moveHighlightedUpOrDown(event);
|
2447
|
-
break;
|
2448
|
-
case 'ArrowRight':
|
2449
|
-
case 'Right':
|
2450
|
-
event.stopPropagation();
|
2451
|
-
event.preventDefault();
|
2452
|
-
// Select the item if it has child items
|
2453
|
-
if (this.highlightedItem && this.highlightedItem.items) {
|
2454
|
-
this.selectItem(event, this.highlightedItem, true);
|
2455
|
-
}
|
2456
|
-
break;
|
2457
|
-
case 'ArrowLeft':
|
2458
|
-
case 'Left':
|
2459
|
-
event.stopPropagation();
|
2460
|
-
event.preventDefault();
|
2461
|
-
// Close the menu if it is a child menu
|
2462
|
-
if (this.parent) {
|
2463
|
-
this.back(event);
|
2464
|
-
}
|
2465
|
-
break;
|
2466
|
-
case ' ':
|
2467
|
-
case 'Spacebar':
|
2468
|
-
case 'Enter':
|
2469
|
-
// Prevent 'enter' from doing whatever it does on the currently focused element
|
2470
|
-
event.preventDefault();
|
2471
|
-
if (this.highlightedItemIndex > -1 && this.highlightedItem) {
|
2472
|
-
this.selectItem(event, this.highlightedItem, true);
|
2473
|
-
// If the header is highlighted
|
2474
|
-
}
|
2475
|
-
else if (this.highlightedItemIndex === -1) {
|
2476
|
-
// Close the menu if it's a child
|
2477
|
-
if (this.parent) {
|
2478
|
-
this.back(event);
|
2479
|
-
}
|
2480
|
-
}
|
2481
|
-
break;
|
2482
|
-
default:
|
2483
|
-
return;
|
2483
|
+
validators.forEach(validator => {
|
2484
|
+
let validationResult = validator(control);
|
2485
|
+
if (validationResult) {
|
2486
|
+
validatorParams.valid = false;
|
2484
2487
|
}
|
2488
|
+
});
|
2489
|
+
if (validatorParams.valid) {
|
2490
|
+
return null;
|
2491
|
+
}
|
2492
|
+
else {
|
2493
|
+
return {
|
2494
|
+
textbox: validatorParams
|
2495
|
+
};
|
2485
2496
|
}
|
2497
|
+
};
|
2498
|
+
};
|
2499
|
+
const phoneNumberValidationPattern = '^\\s*(?:\\+?(\\d{1,3}))?[-. (]*(\\d{3})[-. )]*(\\d{3})[-. ]*(\\d{4})(?: *x(\\d+))?\\s*$';
|
2500
|
+
const urlValidationPattern = '([A-Za-z])+(:\/\/)+[^\\s]*';
|
2501
|
+
class TextboxComponent extends FormControlBase {
|
2502
|
+
constructor(validationMessageService, formGroupHelper, translate) {
|
2503
|
+
super(validationMessageService, formGroupHelper);
|
2504
|
+
this.validationMessageService = validationMessageService;
|
2505
|
+
this.formGroupHelper = formGroupHelper;
|
2506
|
+
this.translate = translate;
|
2507
|
+
/**
|
2508
|
+
* Set the value of the input's autocomplete attribute
|
2509
|
+
*/
|
2510
|
+
this.autocomplete = 'off';
|
2511
|
+
/**
|
2512
|
+
* The textbox type
|
2513
|
+
*/
|
2514
|
+
this.type = "text";
|
2515
|
+
/**
|
2516
|
+
* The value of the rows attribute for a textarea. Only applies to multi-line type
|
2517
|
+
*/
|
2518
|
+
this.rows = 3;
|
2519
|
+
/**
|
2520
|
+
* If set to true, we will select all text within the input if
|
2521
|
+
* autofocus is also set to true
|
2522
|
+
*/
|
2523
|
+
this.selectOnAutofocus = false;
|
2524
|
+
/**
|
2525
|
+
* If set to true, we will upper case on focus out
|
2526
|
+
*/
|
2527
|
+
this.upperCase = false;
|
2528
|
+
/**
|
2529
|
+
* Validation pattern for the input. This is determined on the input type specified
|
2530
|
+
*/
|
2531
|
+
this.validationPattern = '';
|
2532
|
+
}
|
2533
|
+
ngOnChanges(changes) {
|
2534
|
+
super.ngOnChanges(changes);
|
2486
2535
|
}
|
2487
2536
|
/**
|
2488
|
-
*
|
2489
|
-
* NgClassDirecitve or NavItemActiveDirective to respond to the model changes
|
2490
|
-
* and update the view.
|
2537
|
+
* The angular onInit lifecycle hook
|
2491
2538
|
*/
|
2492
|
-
|
2493
|
-
|
2494
|
-
|
2495
|
-
|
2496
|
-
|
2497
|
-
}
|
2498
|
-
moveHighlightedUpOrDown(event) {
|
2499
|
-
switch (event.key) {
|
2500
|
-
case 'ArrowUp':
|
2501
|
-
case 'Up':
|
2502
|
-
if (this.highlightedItemIndex > -1) {
|
2503
|
-
this.highlightedItemIndex--;
|
2504
|
-
// Skip any in-menu heading items
|
2505
|
-
if (this.highlightedItemIndex > -1 && this.items[this.highlightedItemIndex].display === 'heading') {
|
2506
|
-
this.highlightedItemIndex--;
|
2507
|
-
}
|
2508
|
-
}
|
2509
|
-
break;
|
2510
|
-
case 'ArrowDown':
|
2511
|
-
case 'Down':
|
2512
|
-
if (this.highlightedItemIndex < this.items.length - 1) {
|
2513
|
-
this.highlightedItemIndex++;
|
2514
|
-
// Skip any in-menu heading items
|
2515
|
-
if (this.highlightedItemIndex < this.items.length - 1 && this.items[this.highlightedItemIndex].display === 'heading') {
|
2516
|
-
this.highlightedItemIndex++;
|
2517
|
-
}
|
2518
|
-
}
|
2519
|
-
break;
|
2520
|
-
default:
|
2521
|
-
return;
|
2539
|
+
ngOnInit() {
|
2540
|
+
super.ngOnInit();
|
2541
|
+
this.validationPattern = '';
|
2542
|
+
if (this.type === 'tel') {
|
2543
|
+
this.validationPattern = phoneNumberValidationPattern;
|
2522
2544
|
}
|
2523
|
-
if (this.
|
2524
|
-
|
2525
|
-
this.highlightedItem = this.items[this.highlightedItemIndex];
|
2545
|
+
else if (this.type === 'url') {
|
2546
|
+
this.validationPattern = urlValidationPattern;
|
2526
2547
|
}
|
2527
|
-
|
2528
|
-
this.
|
2548
|
+
if (this.placeholder) {
|
2549
|
+
this.translate.get(this.placeholder)
|
2550
|
+
.subscribe((translated) => {
|
2551
|
+
this.placeholder = translated;
|
2552
|
+
});
|
2529
2553
|
}
|
2530
|
-
this.scrollToHighlightedItem();
|
2531
2554
|
}
|
2532
2555
|
/**
|
2533
|
-
*
|
2534
|
-
* If no item is provided, it will scroll to the first item.
|
2535
|
-
*
|
2536
|
-
* @param item The menu item to scroll to.
|
2537
|
-
* @memberof MenuComponent
|
2556
|
+
* The angular afterViewInit lifecycle hook
|
2538
2557
|
*/
|
2539
|
-
|
2540
|
-
if (this.
|
2541
|
-
|
2542
|
-
let itemIndex = this.findItemIndex(item);
|
2543
|
-
if (this.id) {
|
2544
|
-
let itemSelector = item.id ? `#${item.id}` : `#${this.id}_item${itemIndex}`;
|
2545
|
-
this.scrollService.scrollItemCentered(`#${this.id}_list`, itemSelector);
|
2546
|
-
}
|
2558
|
+
ngAfterViewInit() {
|
2559
|
+
if (this.autofocus) {
|
2560
|
+
this.setFocus(this.selectOnAutofocus);
|
2547
2561
|
}
|
2548
2562
|
}
|
2549
|
-
scrollToHighlightedItem() {
|
2550
|
-
this.scrollMenu(this.highlightedItem);
|
2551
|
-
}
|
2552
2563
|
/**
|
2553
|
-
*
|
2554
|
-
*
|
2555
|
-
*
|
2556
|
-
* @param itemToFind The matching item to find in the items array.
|
2557
|
-
* @memberof MenuComponent
|
2564
|
+
* Function to set focus on an input programmatically after the page
|
2565
|
+
* had been rendered. The highlight text flag will select the text
|
2566
|
+
* within the input if passed in and true
|
2558
2567
|
*/
|
2559
|
-
|
2560
|
-
|
2561
|
-
|
2562
|
-
|
2563
|
-
});
|
2564
|
-
}
|
2565
|
-
else {
|
2566
|
-
return -1;
|
2567
|
-
}
|
2568
|
-
}
|
2569
|
-
addKeydownListener() {
|
2570
|
-
// Only attempt to add the listener if keyboard nav is enabled
|
2571
|
-
if (this.enableKeyNav) {
|
2572
|
-
// renderer.listen adds the listener and returns a function to remove it from the renderer.
|
2573
|
-
// The listener remains active until this function is called.
|
2574
|
-
this.removeKeydownListener = this.renderer.listen('document', 'keydown', (event) => this.keyNavigate(event));
|
2568
|
+
setFocus(highlightText) {
|
2569
|
+
this.inputElement.nativeElement.focus();
|
2570
|
+
if (highlightText) {
|
2571
|
+
this.inputElement.nativeElement.select();
|
2575
2572
|
}
|
2576
2573
|
}
|
2577
2574
|
/**
|
2578
|
-
|
2579
|
-
|
2580
|
-
|
2581
|
-
|
2582
|
-
|
2583
|
-
|
2584
|
-
});
|
2575
|
+
* Focus out event handler
|
2576
|
+
* will upper case and trim value if upperCase is true (this is what we do on the apis)
|
2577
|
+
*/
|
2578
|
+
focusOutEvent() {
|
2579
|
+
if (this.upperCase && this.formModel.value) {
|
2580
|
+
this.formModel.setValue(this.formModel.value.toUpperCase().trim());
|
2585
2581
|
}
|
2586
2582
|
}
|
2587
2583
|
}
|
2588
|
-
|
2589
|
-
MenuComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "15.2.9", type: MenuComponent, selector: "ec-menu", inputs: { id: "id", items: "items", selected: "selected", parent: "parent", templateType: "templateType", customMenuTemplate: "customMenuTemplate", title: "title", showNoItems: "showNoItems", noDataText: "noDataText", enableKeyNav: "enableKeyNav", highlightedItem: "highlightedItem", maintainSelectedItem: "maintainSelectedItem", truncateItems: "truncateItems", preserveIconSpace: "preserveIconSpace", dropdownToggleButton: "dropdownToggleButton" }, outputs: { selectedChanged: "selectedChanged", menuClosed: "menuClosed" }, host: { properties: { "attr.id": "this.attrId" } }, viewQueries: [{ propertyName: "labelTemplate", first: true, predicate: ["label"], descendants: true, static: true }, { propertyName: "iconAndLabelTemplate", first: true, predicate: ["iconAndLabel"], descendants: true, static: true }, { propertyName: "checkAndLabelTemplate", first: true, predicate: ["checkAndLabel"], descendants: true, static: true }, { propertyName: "iconLabelCaptionTemplate", first: true, predicate: ["iconLabelCaption"], descendants: true, static: true }], ngImport: i0, template: "<nav>\r\n <div class=\"parent\"\r\n [class.no-data]=\"showNoItems && (!items || items.length === 0)\">\r\n <header id=\"{{id}}_header\"\r\n class=\"text-heading-3 p-1\"\r\n [class.is-selected]=\"highlightedItemIndex === -1\"\r\n *ngIf=\"parent\"\r\n (click)=\"back($event)\">\r\n <div class=\"item-wrapper\">\r\n <i class=\"ec-icon icon-angle-down rotate-90 flex-shrink\"></i>\r\n <span class=\"label text-truncate flex-grow\">{{parent?.label}}</span>\r\n </div>\r\n </header>\r\n\r\n <ul id=\"{{id}}_list\"\r\n class=\"py-1\">\r\n <li *ngFor=\"let item of items; index as i\"\r\n id=\"{{item.id || id + '_item' + i}}\"\r\n class=\"{{item.display || 'item'}} {{item.classList}}\"\r\n [attr.disabled]=\"item.disabled\"\r\n [hidden]=\"item.hidden\"\r\n ecNavItemActive=\"is-selected\"\r\n [ecNavItemActiveQueryParams]=\"item.queryParams\"\r\n [ecNavItemActiveUrl]=\"item.url\"\r\n [ecNavItemActiveExactMatch]='item.isActiveExactMatch'\r\n (routerLinkActivated)=\"selectItem($event, item)\"\r\n [ngClass]=\"{'is-highlighted':(selected === item && item?.display !== 'heading') || highlightedItem === item, 'is-link': item.url, 'is-disabled': item.disabled, 'is-readonly': item.readonly, 'is-checked': item.checked, 'text-heading-3': item?.display === 'heading'}\"\r\n (click)=\"selectItem($event, item)\">\r\n\r\n <a *ngIf=\"item.url && !item.externalLink\"\r\n id=\"{{item.id}}_link\"\r\n title=\"{{truncateItems ? item.label : ''}}\"\r\n class=\"item-wrapper\"\r\n [routerLink]=\"item.url\"\r\n [queryParams]=\"item.queryParams || null\"\r\n target=\"{{item.target || '_self'}}\">\r\n\r\n <ng-container *ngTemplateOutlet=\"internalizedTemplate; context: {$implicit: item}\"></ng-container>\r\n </a>\r\n\r\n <a *ngIf=\"item.url && item.externalLink\"\r\n id=\"{{item.id}}_link\"\r\n title=\"{{truncateItems ? item.label : ''}}\"\r\n class=\"item-wrapper\"\r\n href=\"{{item.url}}\"\r\n target=\"{{item.target || '_self'}}\">\r\n\r\n <ng-container *ngTemplateOutlet=\"internalizedTemplate; context: {$implicit: item}\"></ng-container>\r\n </a>\r\n\r\n <div *ngIf=\"!item.url\"\r\n title=\"{{truncateItems ? item.label : ''}}\"\r\n class=\"item-wrapper\">\r\n <ng-container *ngTemplateOutlet=\"internalizedTemplate; context: {$implicit: item}\"></ng-container>\r\n </div>\r\n </li>\r\n </ul>\r\n\r\n <p class=\"no-data-message\">{{noDataText | translate}}</p>\r\n </div>\r\n\r\n <!-- Child menu (Rendered to the right) -->\r\n <ec-menu *ngIf=\"selected?.items\"\r\n id=\"{{id}}_child\"\r\n class=\"child\"\r\n [parent]=\"selected\"\r\n [items]=\"selected?.items\"\r\n [showNoItems]=\"true\"\r\n [templateType]=\"templateType\"\r\n [enableKeyNav]=\"true\"\r\n [truncateItems]=\"truncateItems\"\r\n (selectedChanged)=\"onSelection($event)\"\r\n (menuClosed)=\"toggleChildMenu(false)\">\r\n </ec-menu>\r\n</nav>\r\n\r\n<!-- 'label' Item Template -->\r\n<ng-template #label\r\n let-item>\r\n <span id=\"{{item.id}}_label\"\r\n class=\"label\"\r\n [class.text-truncate]=\"truncateItems\">{{item.label}}</span>\r\n\r\n <i class=\"ec-icon icon-angle-down rotate-270\"\r\n *ngIf=\"item?.items\"></i>\r\n</ng-template>\r\n\r\n<!-- 'checkAndLabel' Item Template -->\r\n<ng-template #checkAndLabel\r\n let-item>\r\n\r\n <i class=\"ec-icon icon-check ec-icon-sm\"\r\n *ngIf=\"item.display !== 'heading'\"></i>\r\n\r\n <i class=\"ec-icon {{item.icon}} ml-2\"\r\n *ngIf=\"item.icon\"></i>\r\n\r\n <span id=\"{{item.id}}_label\"\r\n class=\"label\"\r\n [class.text-truncate]=\"truncateItems\">{{item.label}}</span>\r\n\r\n <i class=\"ec-icon icon-angle-down rotate-270\"\r\n *ngIf=\"item?.items\"></i>\r\n</ng-template>\r\n\r\n<!-- 'iconAndLabel' Item Template -->\r\n<ng-template #iconAndLabel\r\n let-item>\r\n <!-- If menuItem.icon exists and is not blank, show the icon in the menu -->\r\n <i class=\"ec-icon {{item.icon}}\"\r\n *ngIf=\"(item.icon && item.icon !== '') || preserveIconSpace\"></i>\r\n\r\n <span id=\"{{item.id}}_label\"\r\n class=\"label\"\r\n [class.text-truncate]=\"truncateItems\">{{item.label}}</span>\r\n\r\n <i class=\"ec-icon icon-angle-down rotate-270\"\r\n *ngIf=\"item?.items\"></i>\r\n</ng-template>\r\n\r\n<ng-template #iconLabelCaption\r\n let-item>\r\n <i class=\"ec-icon {{item.icon}}\"\r\n *ngIf=\"(item.icon && item.icon !== '') || preserveIconSpace\"></i>\r\n <div *ngIf=\"item.display !== 'heading'\"\r\n class=\"label flex-grow\">\r\n <div id=\"{{item.id}}_label\"\r\n class=\"text-body-1\"\r\n [class.text-truncate]=\"truncateItems\">{{item.label}}</div>\r\n <div id=\"{{item.id}}_caption\"\r\n *ngIf=\"item.caption\"\r\n class=\"text-caption-1\"\r\n [class.text-truncate]=\"truncateItems\">{{item.caption}}</div>\r\n </div>\r\n <h3 *ngIf=\"item.display === 'heading'\"\r\n class=\"flex-grow text-heading-3 align-self-center\"\r\n [class.text-truncate]=\"truncateItems\">{{item.label}}</h3>\r\n <i class=\"ec-icon icon-angle-down rotate-270 align-self-center\"\r\n *ngIf=\"item?.items\"></i>\r\n</ng-template>", styles: ["@keyframes spin{0%{transform:rotate(0)}to{transform:rotate(1turn)}}:host{display:block;font-size:var(--ec-menu-font-size, var(--ec-font-size-action));font-weight:400;background-color:var(--ec-menu-background-color, var(--ec-background-color))}:host.open>nav>.parent,:host.open>nav>.child{position:absolute;left:0;top:0;right:0;height:100%;transition:transform .25s ease}:host.open>nav>.parent{transform:translate(0)}:host.open>nav>.child{transform:translate(100%)}:host.open-active>nav>.parent{transform:translate(-100%)}:host.open-active>nav>.child{transform:translate(0)}:host(.bg-transparent){background-color:transparent}:host-context(.is-always-open){height:100%}:host-context(.is-always-open) .item-wrapper{padding-left:1rem;padding-right:1rem}nav{display:flex;position:relative;height:100%;overflow:hidden}.parent{display:flex;flex-direction:column;flex:auto;position:relative;max-width:100%}.parent>header{cursor:pointer}.parent>header.is-selected .item-wrapper,.parent>header.is-highlighted .item-wrapper{background-color:var(--ec-background-color-selected)}.parent>header:hover .item-wrapper{background-color:var(--ec-background-color-hover)}.parent.no-data ul{display:none}.parent.no-data .no-data-message{display:block}ul{padding:0;margin:0;list-style:none;flex:auto;height:100%;overflow-y:auto}ul li{cursor:pointer;padding:0 .25rem}ul li a{color:inherit;border-bottom:0;text-decoration:none}ul li.is-selected .item-wrapper,ul li.is-highlighted .item-wrapper{background-color:var(--ec-background-color-selected)}ul li:hover .item-wrapper{background-color:var(--ec-background-color-hover)}ul li:focus .item-wrapper{outline:none;background-color:var(--ec-color-disabled-dark);position:relative;z-index:1}ul li.is-disabled .item-wrapper{color:var(--ec-color-disabled-dark);opacity:var(--ec-form-control-opacity-disabled)}ul li.is-disabled,ul li.is-readonly{cursor:default}ul li.is-disabled .item-wrapper,ul li.is-readonly .item-wrapper{background-color:transparent;color:inherit}ul li.is-checked .icon-check{opacity:1}ul li.heading{cursor:default}ul li.heading .item-wrapper{background-color:transparent}ul li.heading:not(:first-child){margin-top:.5rem}ul li.divider{border-bottom:1px solid var(--ec-border-color);padding-bottom:.25rem;margin-bottom:.25rem}ul li.indent-1 .item-wrapper{padding-left:1.5rem}ul li.indent-2 .item-wrapper{padding-left:2.5rem}ul li.indent-3 .item-wrapper{padding-left:3.5rem}.item-wrapper{cursor:inherit;line-height:1.25rem;min-height:1.75rem;padding:.25rem .5rem;border-radius:var(--ec-border-radius);display:flex;color:inherit}.item-wrapper .label{margin-right:auto}.item-wrapper .label+.ec-icon{margin-left:.5rem}.item-wrapper .ec-icon{margin-top:calc((1.25rem - var(--ec-font-size-icon)) / 2);flex:none}.item-wrapper .ec-icon+.label{margin-left:.5rem}.item-wrapper .ec-icon-sm{margin-top:calc((1.25rem - calc(var(--ec-font-size-icon) * .75)) / 2)}.item-wrapper .icon-check{opacity:0}.no-data-message{display:none;text-align:center;padding:1rem;color:var(--ec-color-hint-dark);margin-bottom:0;font-size:var(--ec-font-size-body)}:host-context(ec-tree) ul{overflow-x:hidden}:host-context(ec-tree) li.is-selected,:host-context(ec-tree) li.is-highlighted{font-weight:700;color:var(--ec-menu-color-highlighted, inherit)}:host-context(ec-tree) li.is-selected:not(:hover),:host-context(ec-tree) li.is-highlighted:not(:hover){background-color:transparent}\n"], dependencies: [{ kind: "directive", type: i1.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: i1.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i1.NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "directive", type: i1$2.RouterLink, selector: "[routerLink]", inputs: ["target", "queryParams", "fragment", "queryParamsHandling", "state", "relativeTo", "preserveFragment", "skipLocationChange", "replaceUrl", "routerLink"] }, { kind: "directive", type: NavItemActiveDirective, selector: "[ecNavItemActive]", inputs: ["ecNavItemActive", "ecNavItemActiveExactMatch", "ecNavItemActiveQueryParams", "ecNavItemActiveUrl"], outputs: ["routerLinkActivated"] }, { kind: "component", type: MenuComponent, selector: "ec-menu", inputs: ["id", "items", "selected", "parent", "templateType", "customMenuTemplate", "title", "showNoItems", "noDataText", "enableKeyNav", "highlightedItem", "maintainSelectedItem", "truncateItems", "preserveIconSpace", "dropdownToggleButton"], outputs: ["selectedChanged", "menuClosed"] }, { kind: "pipe", type: i2.TranslatePipe, name: "translate" }] });
|
2590
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.9", ngImport: i0, type:
|
2584
|
+
TextboxComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.2.9", ngImport: i0, type: TextboxComponent, deps: [{ token: ValidationMessageService }, { token: FormGroupHelper }, { token: i2.TranslateService }], target: i0.ɵɵFactoryTarget.Component });
|
2585
|
+
TextboxComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "15.2.9", type: TextboxComponent, selector: "ec-textbox", inputs: { autocomplete: "autocomplete", type: "type", placeholder: "placeholder", maxlength: "maxlength", minlength: "minlength", rows: "rows", selectOnAutofocus: "selectOnAutofocus", upperCase: "upperCase" }, viewQueries: [{ propertyName: "inputElement", first: true, predicate: ["textboxInput"], descendants: true }], usesInheritance: true, usesOnChanges: true, ngImport: i0, template: "<div class=\"control control-label-{{labelPosition}}\"\r\n [ngClass]=\"{'is-readonly': readonly}\">\r\n\r\n <label *ngIf=\"label\">\r\n <span>{{label | translate}}</span>\r\n <span *ngIf=\"validationErrors.length > 0 && formModel.touched && formModel.invalid\"> {{validationErrors |\r\n translate}}</span>\r\n <ec-help-popover id=\"{{id}}_helpPopover\"\r\n *ngIf=\"helpPopover\"\r\n class=\"d-inline-block my-n3 mx-n1\"\r\n text=\"{{helpPopover | translate}}\"\r\n contentPosition=\"{{helpPopoverPosition}}\">\r\n </ec-help-popover>\r\n </label>\r\n\r\n <div class=\"input-wrapper control-input\">\r\n <input *ngIf=\"type !== 'multi_line'\"\r\n #textboxInput\r\n email=\"{{type === 'email' ? true : false}}\"\r\n pattern=\"{{validationPattern}}\"\r\n type=\"{{type}}\"\r\n tabindex=\"{{tabindex}}\"\r\n title=\"{{tooltip}}\"\r\n [attr.id]=\"inputId\"\r\n [attr.autocomplete]=\"autocomplete\"\r\n [attr.placeholder]=\"placeholder\"\r\n [attr.maxlength]=\"maxlength\"\r\n [attr.minlength]=\"minlength\"\r\n [attr.required]=\"required ? required : null\"\r\n [formControl]=\"formModel\"\r\n [ngClass]=\"{'is-empty': !formModel?.value, 'is-pending': pending, 'is-uppercase': upperCase}\"\r\n (focusout)=\"focusOutEvent()\"\r\n [attr.cdkFocusInitial]=\"autofocus || null\">\r\n\r\n <textarea *ngIf=\"type === 'multi_line'\"\r\n [attr.rows]=\"rows\"\r\n #textboxInput\r\n tabindex=\"{{tabindex}}\"\r\n [attr.id]=\"inputId\"\r\n [attr.placeholder]=\"placeholder\"\r\n [attr.maxlength]=\"maxlength\"\r\n [attr.minlength]=\"minlength\"\r\n [attr.required]=\"required ? required : null\"\r\n [formControl]=\"formModel\"\r\n [ngClass]=\"{'is-empty': formModel?.value === '', 'is-pending': pending}\"\r\n [attr.cdkFocusInitial]=\"autofocus || null\">\r\n </textarea>\r\n\r\n <i class=\"ec-icon icon-required\"></i>\r\n <i class=\"ec-icon icon-invalid\"></i>\r\n <i class=\"ec-icon icon-loading\"></i>\r\n </div>\r\n</div>", styles: [":host{color:var(--ec-form-control-color);font-size:var(--ec-form-control-font-size);display:block;margin-bottom:1rem;width:100%}:host :host-context(.form-condensed){margin-bottom:.5rem}:host .control{width:100%;display:flex;flex-direction:column}:host .control.control-label-bottom{flex-direction:column-reverse}:host .control.control-label-left{flex-direction:row}:host .control.control-label-left label{margin-right:.25rem}:host .control.control-label-right{flex-direction:row-reverse}:host .control.control-label-right label{margin-left:.25rem}:host .control.control-label-left,:host .control.control-label-right{align-items:center}:host .control.control-label-left label,:host .control.control-label-right label{flex:1 1;margin-top:0;margin-bottom:0}:host .control.control-label-left .control-input,:host .control.control-label-right .control-input{flex:2 2}:host .control.is-readonly input,:host .control.is-readonly select,:host .control.is-readonly textarea{border-color:var(--ec-form-control-border-color-readonly);background-color:var(--ec-form-control-background-color-readonly);background-clip:border-box;background-image:none;color:var(--ec-form-control-color-readonly);opacity:1;-webkit-user-select:none;user-select:none;pointer-events:none;overflow:hidden;white-space:nowrap}:host .control.invalid .textbox-group-input ::ng-deep .control input.ng-invalid,:host .control.invalid .textbox-group-input ::ng-deep .control input.ng-valid{background-color:var(--ec-form-control-background-color-invalid);border-color:var(--ec-form-control-border-color-invalid);background-repeat:no-repeat;background-position:.5rem center;background-size:1rem,1rem;padding-left:1.75rem;background-image:none}:host .control.invalid .textbox-group-input ::ng-deep .control input.ng-invalid:focus,:host .control.invalid .textbox-group-input ::ng-deep .control input.ng-valid:focus{border-color:var(--ec-form-control-background-color-invalid)}:host .control.invalid .textbox-group-input ::ng-deep .control input.ng-invalid~.icon-invalid,:host .control.invalid .textbox-group-input ::ng-deep .control input.ng-valid~.icon-invalid{display:inline-flex;position:absolute;left:.5rem;top:.5rem;z-index:1}:host .control.invalid .textbox-group-input ::ng-deep .control input.ng-invalid~.icon-required,:host .control.invalid .textbox-group-input ::ng-deep .control input.ng-valid~.icon-required{display:none}:host .control.invalid:not(.open) .textbox-group-btn-right ::ng-deep button{background-color:var(--ec-form-control-background-color-invalid)}:host .control.invalid:not(.open) .textbox-group-btn-right ::ng-deep button:not(:focus){border-color:var(--ec-form-control-border-color-invalid)}:host .textbox-group{display:flex;position:relative}:host textarea:focus,:host input:focus,:host select:focus{outline:none}:host label{color:var(--ec-form-control-label-color, var(--ec-color-secondary-dark));display:block;font-size:var(--ec-font-size-label);line-height:1;margin:calc(var(--ec-font-size-label) / 2) 0}:host input{background-color:var(--ec-form-control-background-color);border:1px solid var(--ec-form-control-border-color);border-radius:var(--ec-border-radius);background-image:none;background-clip:padding-box;width:100%;line-height:1.25rem;padding:.3125rem .5rem;height:2rem}:host input::selection{background-color:var(--ec-form-control-background-color-selection);color:var(--ec-form-control-color-selection)}:host input::-webkit-input-placeholder{color:var(--ec-form-control-color-placeholder)}:host input::-moz-placeholder{color:var(--ec-form-control-color-placeholder);opacity:1}:host input:-ms-input-placeholder{color:var(--ec-form-control-color-placeholder)}:host input:-moz-placeholder{color:var(--ec-form-control-color-placeholder);opacity:1}:host input~.icon-required,:host input~.icon-invalid{color:var(--ec-form-control-border-color-invalid)}:host input:required.is-empty{background-repeat:no-repeat;background-position:.5rem center;background-size:1rem,1rem;padding-left:1.75rem;background-image:none}:host input:required.is-empty~.icon-required{display:inline-flex;position:absolute;left:.5rem;top:.5rem;z-index:1}:host input.ng-invalid.ng-touched{background-color:var(--ec-form-control-background-color-invalid);border-color:var(--ec-form-control-border-color-invalid);background-repeat:no-repeat;background-position:.5rem center;background-size:1rem,1rem;padding-left:1.75rem;background-image:none}:host input.ng-invalid.ng-touched:focus{border-color:var(--ec-form-control-background-color-invalid)}:host input.ng-invalid.ng-touched~.icon-invalid{display:inline-flex;position:absolute;left:.5rem;top:.5rem;z-index:1}:host input.ng-invalid.ng-touched~.icon-required{display:none}:host input.is-pending.ng-valid,:host input.is-pending.ng-invalid,:host input.is-pending.ng-pending{background-image:\"\";background-repeat:no-repeat;background-position:.5rem center;background-size:1rem,1rem;padding-left:1.75rem}:host input.is-pending.ng-valid~.icon-loading,:host input.is-pending.ng-invalid~.icon-loading,:host input.is-pending.ng-pending~.icon-loading{display:inline-flex;position:absolute;left:.5rem;top:.5rem;z-index:1}:host input.is-pending.ng-valid~.icon-required,:host input.is-pending.ng-valid~.icon-invalid,:host input.is-pending.ng-invalid~.icon-required,:host input.is-pending.ng-invalid~.icon-invalid,:host input.is-pending.ng-pending~.icon-required,:host input.is-pending.ng-pending~.icon-invalid{display:none}:host input:focus,:host input:focus.is-empty{border-color:var(--ec-form-control-border-color-focus);box-shadow:var(--ec-form-control-box-shadow-focus);position:relative;z-index:1}:host input:disabled{background-color:var(--ec-form-control-background-color-disabled);border-color:var(--ec-form-control-border-color-disabled);color:var(--ec-form-control-color-disabled);opacity:var(--ec-form-control-opacity-disabled)}:host input:disabled:required,:host input:disabled:required.is-empty{background-image:none;padding-left:.5rem;background-color:var(--ec-form-control-background-color-disabled);border-color:var(--ec-form-control-border-color-disabled)}:host input:disabled:required+.icon-required,:host input:disabled:required.is-empty+.icon-required{display:none}:host input.is-uppercase:not(.is-empty){text-transform:uppercase}:host textarea{background-color:var(--ec-form-control-background-color);border:1px solid var(--ec-form-control-border-color);border-radius:var(--ec-border-radius);background-image:none;background-clip:padding-box;width:100%;line-height:1.25rem;padding:.3125rem .5rem;height:auto;resize:none;display:block}:host textarea::selection{background-color:var(--ec-form-control-background-color-selection);color:var(--ec-form-control-color-selection)}:host textarea::-webkit-input-placeholder{color:var(--ec-form-control-color-placeholder)}:host textarea::-moz-placeholder{color:var(--ec-form-control-color-placeholder);opacity:1}:host textarea:-ms-input-placeholder{color:var(--ec-form-control-color-placeholder)}:host textarea:-moz-placeholder{color:var(--ec-form-control-color-placeholder);opacity:1}:host textarea~.icon-required,:host textarea~.icon-invalid{color:var(--ec-form-control-border-color-invalid)}:host textarea:required.is-empty{background-repeat:no-repeat;background-position:.5rem .5rem;background-size:1rem,1rem;padding-left:1.75rem;background-image:none}:host textarea:required.is-empty~.icon-required{display:inline-flex;position:absolute;left:.5rem;top:.5rem;z-index:1}:host textarea.ng-invalid.ng-touched{background-color:var(--ec-form-control-background-color-invalid);border-color:var(--ec-form-control-border-color-invalid);background-repeat:no-repeat;background-position:.5rem .5rem;background-size:1rem,1rem;padding-left:1.75rem;background-image:none}:host textarea.ng-invalid.ng-touched:focus{border-color:var(--ec-form-control-background-color-invalid)}:host textarea.ng-invalid.ng-touched~.icon-invalid{display:inline-flex;position:absolute;left:.5rem;top:.5rem;z-index:1}:host textarea.ng-invalid.ng-touched~.icon-required{display:none}:host textarea.is-pending.ng-valid,:host textarea.is-pending.ng-invalid,:host textarea.is-pending.ng-pending{background-image:\"\";background-repeat:no-repeat;background-position:.5rem .5rem;background-size:1rem,1rem;padding-left:1.75rem}:host textarea.is-pending.ng-valid~.icon-loading,:host textarea.is-pending.ng-invalid~.icon-loading,:host textarea.is-pending.ng-pending~.icon-loading{display:inline-flex;position:absolute;left:.5rem;top:.5rem;z-index:1}:host textarea.is-pending.ng-valid~.icon-required,:host textarea.is-pending.ng-valid~.icon-invalid,:host textarea.is-pending.ng-invalid~.icon-required,:host textarea.is-pending.ng-invalid~.icon-invalid,:host textarea.is-pending.ng-pending~.icon-required,:host textarea.is-pending.ng-pending~.icon-invalid{display:none}:host textarea:focus,:host textarea:focus.is-empty{border-color:var(--ec-form-control-border-color-focus);box-shadow:var(--ec-form-control-box-shadow-focus);position:relative;z-index:1}:host textarea:disabled{background-color:var(--ec-form-control-background-color-disabled);border-color:var(--ec-form-control-border-color-disabled);color:var(--ec-form-control-color-disabled);opacity:var(--ec-form-control-opacity-disabled)}:host textarea:disabled:required,:host textarea:disabled:required.is-empty{background-image:none;padding-left:.5rem;background-color:var(--ec-form-control-background-color-disabled);border-color:var(--ec-form-control-border-color-disabled)}:host textarea:disabled:required+.icon-required,:host textarea:disabled:required.is-empty+.icon-required{display:none}:host textarea.is-uppercase:not(.is-empty){text-transform:uppercase}.input-wrapper{position:relative}.input-wrapper>.ec-icon{display:none}:host(.textbox-group-input:not(:last-child)){flex:1 1 0%;width:1px}:host(.textbox-group-input:not(:last-child)) .control{margin-bottom:0}:host(.textbox-group-input:not(:last-child)) .control.is-readonly input{border-right-width:1px}:host(.textbox-group-input:not(:last-child)) input{border-top-right-radius:0;border-bottom-right-radius:0;border-right-width:0}:host(.textbox-group-input:not(:last-child)) input:focus{position:relative;z-index:1;border-right-width:1px}:host(.text-truncate) input{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}:host(.is-monospace) input,:host(.is-monospace) textarea,:host-context(.is-monospace) input,:host-context(.is-monospace) textarea{font-family:var(--ec-font-family-monospace)}\n"], dependencies: [{ kind: "directive", type: i1.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: i1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i4.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i4.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i4.RequiredValidator, selector: ":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]", inputs: ["required"] }, { kind: "directive", type: i4.MinLengthValidator, selector: "[minlength][formControlName],[minlength][formControl],[minlength][ngModel]", inputs: ["minlength"] }, { kind: "directive", type: i4.MaxLengthValidator, selector: "[maxlength][formControlName],[maxlength][formControl],[maxlength][ngModel]", inputs: ["maxlength"] }, { kind: "directive", type: i4.PatternValidator, selector: "[pattern][formControlName],[pattern][formControl],[pattern][ngModel]", inputs: ["pattern"] }, { kind: "directive", type: i4.EmailValidator, selector: "[email][formControlName],[email][formControl],[email][ngModel]", inputs: ["email"] }, { kind: "directive", type: i4.FormControlDirective, selector: "[formControl]", inputs: ["formControl", "disabled", "ngModel"], outputs: ["ngModelChange"], exportAs: ["ngForm"] }, { kind: "component", type: HelpPopoverComponent, selector: "ec-help-popover", inputs: ["id", "text", "contentPosition", "maxWidth"] }, { kind: "pipe", type: i2.TranslatePipe, name: "translate" }] });
|
2586
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.9", ngImport: i0, type: TextboxComponent, decorators: [{
|
2591
2587
|
type: Component,
|
2592
|
-
args: [{ selector: 'ec-menu', template: "<nav>\r\n <div class=\"parent\"\r\n [class.no-data]=\"showNoItems && (!items || items.length === 0)\">\r\n <header id=\"{{id}}_header\"\r\n class=\"text-heading-3 p-1\"\r\n [class.is-selected]=\"highlightedItemIndex === -1\"\r\n *ngIf=\"parent\"\r\n (click)=\"back($event)\">\r\n <div class=\"item-wrapper\">\r\n <i class=\"ec-icon icon-angle-down rotate-90 flex-shrink\"></i>\r\n <span class=\"label text-truncate flex-grow\">{{parent?.label}}</span>\r\n </div>\r\n </header>\r\n\r\n <ul id=\"{{id}}_list\"\r\n class=\"py-1\">\r\n <li *ngFor=\"let item of items; index as i\"\r\n id=\"{{item.id || id + '_item' + i}}\"\r\n class=\"{{item.display || 'item'}} {{item.classList}}\"\r\n [attr.disabled]=\"item.disabled\"\r\n [hidden]=\"item.hidden\"\r\n ecNavItemActive=\"is-selected\"\r\n [ecNavItemActiveQueryParams]=\"item.queryParams\"\r\n [ecNavItemActiveUrl]=\"item.url\"\r\n [ecNavItemActiveExactMatch]='item.isActiveExactMatch'\r\n (routerLinkActivated)=\"selectItem($event, item)\"\r\n [ngClass]=\"{'is-highlighted':(selected === item && item?.display !== 'heading') || highlightedItem === item, 'is-link': item.url, 'is-disabled': item.disabled, 'is-readonly': item.readonly, 'is-checked': item.checked, 'text-heading-3': item?.display === 'heading'}\"\r\n (click)=\"selectItem($event, item)\">\r\n\r\n <a *ngIf=\"item.url && !item.externalLink\"\r\n id=\"{{item.id}}_link\"\r\n title=\"{{truncateItems ? item.label : ''}}\"\r\n class=\"item-wrapper\"\r\n [routerLink]=\"item.url\"\r\n [queryParams]=\"item.queryParams || null\"\r\n target=\"{{item.target || '_self'}}\">\r\n\r\n <ng-container *ngTemplateOutlet=\"internalizedTemplate; context: {$implicit: item}\"></ng-container>\r\n </a>\r\n\r\n <a *ngIf=\"item.url && item.externalLink\"\r\n id=\"{{item.id}}_link\"\r\n title=\"{{truncateItems ? item.label : ''}}\"\r\n class=\"item-wrapper\"\r\n href=\"{{item.url}}\"\r\n target=\"{{item.target || '_self'}}\">\r\n\r\n <ng-container *ngTemplateOutlet=\"internalizedTemplate; context: {$implicit: item}\"></ng-container>\r\n </a>\r\n\r\n <div *ngIf=\"!item.url\"\r\n title=\"{{truncateItems ? item.label : ''}}\"\r\n class=\"item-wrapper\">\r\n <ng-container *ngTemplateOutlet=\"internalizedTemplate; context: {$implicit: item}\"></ng-container>\r\n </div>\r\n </li>\r\n </ul>\r\n\r\n <p class=\"no-data-message\">{{noDataText | translate}}</p>\r\n </div>\r\n\r\n <!-- Child menu (Rendered to the right) -->\r\n <ec-menu *ngIf=\"selected?.items\"\r\n id=\"{{id}}_child\"\r\n class=\"child\"\r\n [parent]=\"selected\"\r\n [items]=\"selected?.items\"\r\n [showNoItems]=\"true\"\r\n [templateType]=\"templateType\"\r\n [enableKeyNav]=\"true\"\r\n [truncateItems]=\"truncateItems\"\r\n (selectedChanged)=\"onSelection($event)\"\r\n (menuClosed)=\"toggleChildMenu(false)\">\r\n </ec-menu>\r\n</nav>\r\n\r\n<!-- 'label' Item Template -->\r\n<ng-template #label\r\n let-item>\r\n <span id=\"{{item.id}}_label\"\r\n class=\"label\"\r\n [class.text-truncate]=\"truncateItems\">{{item.label}}</span>\r\n\r\n <i class=\"ec-icon icon-angle-down rotate-270\"\r\n *ngIf=\"item?.items\"></i>\r\n</ng-template>\r\n\r\n<!-- 'checkAndLabel' Item Template -->\r\n<ng-template #checkAndLabel\r\n let-item>\r\n\r\n <i class=\"ec-icon icon-check ec-icon-sm\"\r\n *ngIf=\"item.display !== 'heading'\"></i>\r\n\r\n <i class=\"ec-icon {{item.icon}} ml-2\"\r\n *ngIf=\"item.icon\"></i>\r\n\r\n <span id=\"{{item.id}}_label\"\r\n class=\"label\"\r\n [class.text-truncate]=\"truncateItems\">{{item.label}}</span>\r\n\r\n <i class=\"ec-icon icon-angle-down rotate-270\"\r\n *ngIf=\"item?.items\"></i>\r\n</ng-template>\r\n\r\n<!-- 'iconAndLabel' Item Template -->\r\n<ng-template #iconAndLabel\r\n let-item>\r\n <!-- If menuItem.icon exists and is not blank, show the icon in the menu -->\r\n <i class=\"ec-icon {{item.icon}}\"\r\n *ngIf=\"(item.icon && item.icon !== '') || preserveIconSpace\"></i>\r\n\r\n <span id=\"{{item.id}}_label\"\r\n class=\"label\"\r\n [class.text-truncate]=\"truncateItems\">{{item.label}}</span>\r\n\r\n <i class=\"ec-icon icon-angle-down rotate-270\"\r\n *ngIf=\"item?.items\"></i>\r\n</ng-template>\r\n\r\n<ng-template #iconLabelCaption\r\n let-item>\r\n <i class=\"ec-icon {{item.icon}}\"\r\n *ngIf=\"(item.icon && item.icon !== '') || preserveIconSpace\"></i>\r\n <div *ngIf=\"item.display !== 'heading'\"\r\n class=\"label flex-grow\">\r\n <div id=\"{{item.id}}_label\"\r\n class=\"text-body-1\"\r\n [class.text-truncate]=\"truncateItems\">{{item.label}}</div>\r\n <div id=\"{{item.id}}_caption\"\r\n *ngIf=\"item.caption\"\r\n class=\"text-caption-1\"\r\n [class.text-truncate]=\"truncateItems\">{{item.caption}}</div>\r\n </div>\r\n <h3 *ngIf=\"item.display === 'heading'\"\r\n class=\"flex-grow text-heading-3 align-self-center\"\r\n [class.text-truncate]=\"truncateItems\">{{item.label}}</h3>\r\n <i class=\"ec-icon icon-angle-down rotate-270 align-self-center\"\r\n *ngIf=\"item?.items\"></i>\r\n</ng-template>", styles: ["@keyframes spin{0%{transform:rotate(0)}to{transform:rotate(1turn)}}:host{display:block;font-size:var(--ec-menu-font-size, var(--ec-font-size-action));font-weight:400;background-color:var(--ec-menu-background-color, var(--ec-background-color))}:host.open>nav>.parent,:host.open>nav>.child{position:absolute;left:0;top:0;right:0;height:100%;transition:transform .25s ease}:host.open>nav>.parent{transform:translate(0)}:host.open>nav>.child{transform:translate(100%)}:host.open-active>nav>.parent{transform:translate(-100%)}:host.open-active>nav>.child{transform:translate(0)}:host(.bg-transparent){background-color:transparent}:host-context(.is-always-open){height:100%}:host-context(.is-always-open) .item-wrapper{padding-left:1rem;padding-right:1rem}nav{display:flex;position:relative;height:100%;overflow:hidden}.parent{display:flex;flex-direction:column;flex:auto;position:relative;max-width:100%}.parent>header{cursor:pointer}.parent>header.is-selected .item-wrapper,.parent>header.is-highlighted .item-wrapper{background-color:var(--ec-background-color-selected)}.parent>header:hover .item-wrapper{background-color:var(--ec-background-color-hover)}.parent.no-data ul{display:none}.parent.no-data .no-data-message{display:block}ul{padding:0;margin:0;list-style:none;flex:auto;height:100%;overflow-y:auto}ul li{cursor:pointer;padding:0 .25rem}ul li a{color:inherit;border-bottom:0;text-decoration:none}ul li.is-selected .item-wrapper,ul li.is-highlighted .item-wrapper{background-color:var(--ec-background-color-selected)}ul li:hover .item-wrapper{background-color:var(--ec-background-color-hover)}ul li:focus .item-wrapper{outline:none;background-color:var(--ec-color-disabled-dark);position:relative;z-index:1}ul li.is-disabled .item-wrapper{color:var(--ec-color-disabled-dark);opacity:var(--ec-form-control-opacity-disabled)}ul li.is-disabled,ul li.is-readonly{cursor:default}ul li.is-disabled .item-wrapper,ul li.is-readonly .item-wrapper{background-color:transparent;color:inherit}ul li.is-checked .icon-check{opacity:1}ul li.heading{cursor:default}ul li.heading .item-wrapper{background-color:transparent}ul li.heading:not(:first-child){margin-top:.5rem}ul li.divider{border-bottom:1px solid var(--ec-border-color);padding-bottom:.25rem;margin-bottom:.25rem}ul li.indent-1 .item-wrapper{padding-left:1.5rem}ul li.indent-2 .item-wrapper{padding-left:2.5rem}ul li.indent-3 .item-wrapper{padding-left:3.5rem}.item-wrapper{cursor:inherit;line-height:1.25rem;min-height:1.75rem;padding:.25rem .5rem;border-radius:var(--ec-border-radius);display:flex;color:inherit}.item-wrapper .label{margin-right:auto}.item-wrapper .label+.ec-icon{margin-left:.5rem}.item-wrapper .ec-icon{margin-top:calc((1.25rem - var(--ec-font-size-icon)) / 2);flex:none}.item-wrapper .ec-icon+.label{margin-left:.5rem}.item-wrapper .ec-icon-sm{margin-top:calc((1.25rem - calc(var(--ec-font-size-icon) * .75)) / 2)}.item-wrapper .icon-check{opacity:0}.no-data-message{display:none;text-align:center;padding:1rem;color:var(--ec-color-hint-dark);margin-bottom:0;font-size:var(--ec-font-size-body)}:host-context(ec-tree) ul{overflow-x:hidden}:host-context(ec-tree) li.is-selected,:host-context(ec-tree) li.is-highlighted{font-weight:700;color:var(--ec-menu-color-highlighted, inherit)}:host-context(ec-tree) li.is-selected:not(:hover),:host-context(ec-tree) li.is-highlighted:not(:hover){background-color:transparent}\n"] }]
|
2593
|
-
}], ctorParameters: function () { return [{ type:
|
2594
|
-
type: Input
|
2595
|
-
}], attrId: [{
|
2596
|
-
type: HostBinding,
|
2597
|
-
args: ['attr.id']
|
2598
|
-
}], items: [{
|
2588
|
+
args: [{ selector: 'ec-textbox', template: "<div class=\"control control-label-{{labelPosition}}\"\r\n [ngClass]=\"{'is-readonly': readonly}\">\r\n\r\n <label *ngIf=\"label\">\r\n <span>{{label | translate}}</span>\r\n <span *ngIf=\"validationErrors.length > 0 && formModel.touched && formModel.invalid\"> {{validationErrors |\r\n translate}}</span>\r\n <ec-help-popover id=\"{{id}}_helpPopover\"\r\n *ngIf=\"helpPopover\"\r\n class=\"d-inline-block my-n3 mx-n1\"\r\n text=\"{{helpPopover | translate}}\"\r\n contentPosition=\"{{helpPopoverPosition}}\">\r\n </ec-help-popover>\r\n </label>\r\n\r\n <div class=\"input-wrapper control-input\">\r\n <input *ngIf=\"type !== 'multi_line'\"\r\n #textboxInput\r\n email=\"{{type === 'email' ? true : false}}\"\r\n pattern=\"{{validationPattern}}\"\r\n type=\"{{type}}\"\r\n tabindex=\"{{tabindex}}\"\r\n title=\"{{tooltip}}\"\r\n [attr.id]=\"inputId\"\r\n [attr.autocomplete]=\"autocomplete\"\r\n [attr.placeholder]=\"placeholder\"\r\n [attr.maxlength]=\"maxlength\"\r\n [attr.minlength]=\"minlength\"\r\n [attr.required]=\"required ? required : null\"\r\n [formControl]=\"formModel\"\r\n [ngClass]=\"{'is-empty': !formModel?.value, 'is-pending': pending, 'is-uppercase': upperCase}\"\r\n (focusout)=\"focusOutEvent()\"\r\n [attr.cdkFocusInitial]=\"autofocus || null\">\r\n\r\n <textarea *ngIf=\"type === 'multi_line'\"\r\n [attr.rows]=\"rows\"\r\n #textboxInput\r\n tabindex=\"{{tabindex}}\"\r\n [attr.id]=\"inputId\"\r\n [attr.placeholder]=\"placeholder\"\r\n [attr.maxlength]=\"maxlength\"\r\n [attr.minlength]=\"minlength\"\r\n [attr.required]=\"required ? required : null\"\r\n [formControl]=\"formModel\"\r\n [ngClass]=\"{'is-empty': formModel?.value === '', 'is-pending': pending}\"\r\n [attr.cdkFocusInitial]=\"autofocus || null\">\r\n </textarea>\r\n\r\n <i class=\"ec-icon icon-required\"></i>\r\n <i class=\"ec-icon icon-invalid\"></i>\r\n <i class=\"ec-icon icon-loading\"></i>\r\n </div>\r\n</div>", styles: [":host{color:var(--ec-form-control-color);font-size:var(--ec-form-control-font-size);display:block;margin-bottom:1rem;width:100%}:host :host-context(.form-condensed){margin-bottom:.5rem}:host .control{width:100%;display:flex;flex-direction:column}:host .control.control-label-bottom{flex-direction:column-reverse}:host .control.control-label-left{flex-direction:row}:host .control.control-label-left label{margin-right:.25rem}:host .control.control-label-right{flex-direction:row-reverse}:host .control.control-label-right label{margin-left:.25rem}:host .control.control-label-left,:host .control.control-label-right{align-items:center}:host .control.control-label-left label,:host .control.control-label-right label{flex:1 1;margin-top:0;margin-bottom:0}:host .control.control-label-left .control-input,:host .control.control-label-right .control-input{flex:2 2}:host .control.is-readonly input,:host .control.is-readonly select,:host .control.is-readonly textarea{border-color:var(--ec-form-control-border-color-readonly);background-color:var(--ec-form-control-background-color-readonly);background-clip:border-box;background-image:none;color:var(--ec-form-control-color-readonly);opacity:1;-webkit-user-select:none;user-select:none;pointer-events:none;overflow:hidden;white-space:nowrap}:host .control.invalid .textbox-group-input ::ng-deep .control input.ng-invalid,:host .control.invalid .textbox-group-input ::ng-deep .control input.ng-valid{background-color:var(--ec-form-control-background-color-invalid);border-color:var(--ec-form-control-border-color-invalid);background-repeat:no-repeat;background-position:.5rem center;background-size:1rem,1rem;padding-left:1.75rem;background-image:none}:host .control.invalid .textbox-group-input ::ng-deep .control input.ng-invalid:focus,:host .control.invalid .textbox-group-input ::ng-deep .control input.ng-valid:focus{border-color:var(--ec-form-control-background-color-invalid)}:host .control.invalid .textbox-group-input ::ng-deep .control input.ng-invalid~.icon-invalid,:host .control.invalid .textbox-group-input ::ng-deep .control input.ng-valid~.icon-invalid{display:inline-flex;position:absolute;left:.5rem;top:.5rem;z-index:1}:host .control.invalid .textbox-group-input ::ng-deep .control input.ng-invalid~.icon-required,:host .control.invalid .textbox-group-input ::ng-deep .control input.ng-valid~.icon-required{display:none}:host .control.invalid:not(.open) .textbox-group-btn-right ::ng-deep button{background-color:var(--ec-form-control-background-color-invalid)}:host .control.invalid:not(.open) .textbox-group-btn-right ::ng-deep button:not(:focus){border-color:var(--ec-form-control-border-color-invalid)}:host .textbox-group{display:flex;position:relative}:host textarea:focus,:host input:focus,:host select:focus{outline:none}:host label{color:var(--ec-form-control-label-color, var(--ec-color-secondary-dark));display:block;font-size:var(--ec-font-size-label);line-height:1;margin:calc(var(--ec-font-size-label) / 2) 0}:host input{background-color:var(--ec-form-control-background-color);border:1px solid var(--ec-form-control-border-color);border-radius:var(--ec-border-radius);background-image:none;background-clip:padding-box;width:100%;line-height:1.25rem;padding:.3125rem .5rem;height:2rem}:host input::selection{background-color:var(--ec-form-control-background-color-selection);color:var(--ec-form-control-color-selection)}:host input::-webkit-input-placeholder{color:var(--ec-form-control-color-placeholder)}:host input::-moz-placeholder{color:var(--ec-form-control-color-placeholder);opacity:1}:host input:-ms-input-placeholder{color:var(--ec-form-control-color-placeholder)}:host input:-moz-placeholder{color:var(--ec-form-control-color-placeholder);opacity:1}:host input~.icon-required,:host input~.icon-invalid{color:var(--ec-form-control-border-color-invalid)}:host input:required.is-empty{background-repeat:no-repeat;background-position:.5rem center;background-size:1rem,1rem;padding-left:1.75rem;background-image:none}:host input:required.is-empty~.icon-required{display:inline-flex;position:absolute;left:.5rem;top:.5rem;z-index:1}:host input.ng-invalid.ng-touched{background-color:var(--ec-form-control-background-color-invalid);border-color:var(--ec-form-control-border-color-invalid);background-repeat:no-repeat;background-position:.5rem center;background-size:1rem,1rem;padding-left:1.75rem;background-image:none}:host input.ng-invalid.ng-touched:focus{border-color:var(--ec-form-control-background-color-invalid)}:host input.ng-invalid.ng-touched~.icon-invalid{display:inline-flex;position:absolute;left:.5rem;top:.5rem;z-index:1}:host input.ng-invalid.ng-touched~.icon-required{display:none}:host input.is-pending.ng-valid,:host input.is-pending.ng-invalid,:host input.is-pending.ng-pending{background-image:\"\";background-repeat:no-repeat;background-position:.5rem center;background-size:1rem,1rem;padding-left:1.75rem}:host input.is-pending.ng-valid~.icon-loading,:host input.is-pending.ng-invalid~.icon-loading,:host input.is-pending.ng-pending~.icon-loading{display:inline-flex;position:absolute;left:.5rem;top:.5rem;z-index:1}:host input.is-pending.ng-valid~.icon-required,:host input.is-pending.ng-valid~.icon-invalid,:host input.is-pending.ng-invalid~.icon-required,:host input.is-pending.ng-invalid~.icon-invalid,:host input.is-pending.ng-pending~.icon-required,:host input.is-pending.ng-pending~.icon-invalid{display:none}:host input:focus,:host input:focus.is-empty{border-color:var(--ec-form-control-border-color-focus);box-shadow:var(--ec-form-control-box-shadow-focus);position:relative;z-index:1}:host input:disabled{background-color:var(--ec-form-control-background-color-disabled);border-color:var(--ec-form-control-border-color-disabled);color:var(--ec-form-control-color-disabled);opacity:var(--ec-form-control-opacity-disabled)}:host input:disabled:required,:host input:disabled:required.is-empty{background-image:none;padding-left:.5rem;background-color:var(--ec-form-control-background-color-disabled);border-color:var(--ec-form-control-border-color-disabled)}:host input:disabled:required+.icon-required,:host input:disabled:required.is-empty+.icon-required{display:none}:host input.is-uppercase:not(.is-empty){text-transform:uppercase}:host textarea{background-color:var(--ec-form-control-background-color);border:1px solid var(--ec-form-control-border-color);border-radius:var(--ec-border-radius);background-image:none;background-clip:padding-box;width:100%;line-height:1.25rem;padding:.3125rem .5rem;height:auto;resize:none;display:block}:host textarea::selection{background-color:var(--ec-form-control-background-color-selection);color:var(--ec-form-control-color-selection)}:host textarea::-webkit-input-placeholder{color:var(--ec-form-control-color-placeholder)}:host textarea::-moz-placeholder{color:var(--ec-form-control-color-placeholder);opacity:1}:host textarea:-ms-input-placeholder{color:var(--ec-form-control-color-placeholder)}:host textarea:-moz-placeholder{color:var(--ec-form-control-color-placeholder);opacity:1}:host textarea~.icon-required,:host textarea~.icon-invalid{color:var(--ec-form-control-border-color-invalid)}:host textarea:required.is-empty{background-repeat:no-repeat;background-position:.5rem .5rem;background-size:1rem,1rem;padding-left:1.75rem;background-image:none}:host textarea:required.is-empty~.icon-required{display:inline-flex;position:absolute;left:.5rem;top:.5rem;z-index:1}:host textarea.ng-invalid.ng-touched{background-color:var(--ec-form-control-background-color-invalid);border-color:var(--ec-form-control-border-color-invalid);background-repeat:no-repeat;background-position:.5rem .5rem;background-size:1rem,1rem;padding-left:1.75rem;background-image:none}:host textarea.ng-invalid.ng-touched:focus{border-color:var(--ec-form-control-background-color-invalid)}:host textarea.ng-invalid.ng-touched~.icon-invalid{display:inline-flex;position:absolute;left:.5rem;top:.5rem;z-index:1}:host textarea.ng-invalid.ng-touched~.icon-required{display:none}:host textarea.is-pending.ng-valid,:host textarea.is-pending.ng-invalid,:host textarea.is-pending.ng-pending{background-image:\"\";background-repeat:no-repeat;background-position:.5rem .5rem;background-size:1rem,1rem;padding-left:1.75rem}:host textarea.is-pending.ng-valid~.icon-loading,:host textarea.is-pending.ng-invalid~.icon-loading,:host textarea.is-pending.ng-pending~.icon-loading{display:inline-flex;position:absolute;left:.5rem;top:.5rem;z-index:1}:host textarea.is-pending.ng-valid~.icon-required,:host textarea.is-pending.ng-valid~.icon-invalid,:host textarea.is-pending.ng-invalid~.icon-required,:host textarea.is-pending.ng-invalid~.icon-invalid,:host textarea.is-pending.ng-pending~.icon-required,:host textarea.is-pending.ng-pending~.icon-invalid{display:none}:host textarea:focus,:host textarea:focus.is-empty{border-color:var(--ec-form-control-border-color-focus);box-shadow:var(--ec-form-control-box-shadow-focus);position:relative;z-index:1}:host textarea:disabled{background-color:var(--ec-form-control-background-color-disabled);border-color:var(--ec-form-control-border-color-disabled);color:var(--ec-form-control-color-disabled);opacity:var(--ec-form-control-opacity-disabled)}:host textarea:disabled:required,:host textarea:disabled:required.is-empty{background-image:none;padding-left:.5rem;background-color:var(--ec-form-control-background-color-disabled);border-color:var(--ec-form-control-border-color-disabled)}:host textarea:disabled:required+.icon-required,:host textarea:disabled:required.is-empty+.icon-required{display:none}:host textarea.is-uppercase:not(.is-empty){text-transform:uppercase}.input-wrapper{position:relative}.input-wrapper>.ec-icon{display:none}:host(.textbox-group-input:not(:last-child)){flex:1 1 0%;width:1px}:host(.textbox-group-input:not(:last-child)) .control{margin-bottom:0}:host(.textbox-group-input:not(:last-child)) .control.is-readonly input{border-right-width:1px}:host(.textbox-group-input:not(:last-child)) input{border-top-right-radius:0;border-bottom-right-radius:0;border-right-width:0}:host(.textbox-group-input:not(:last-child)) input:focus{position:relative;z-index:1;border-right-width:1px}:host(.text-truncate) input{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}:host(.is-monospace) input,:host(.is-monospace) textarea,:host-context(.is-monospace) input,:host-context(.is-monospace) textarea{font-family:var(--ec-font-family-monospace)}\n"] }]
|
2589
|
+
}], ctorParameters: function () { return [{ type: ValidationMessageService }, { type: FormGroupHelper }, { type: i2.TranslateService }]; }, propDecorators: { autocomplete: [{
|
2599
2590
|
type: Input
|
2600
|
-
}],
|
2591
|
+
}], type: [{
|
2601
2592
|
type: Input
|
2602
|
-
}],
|
2593
|
+
}], placeholder: [{
|
2603
2594
|
type: Input
|
2604
|
-
}],
|
2595
|
+
}], maxlength: [{
|
2605
2596
|
type: Input
|
2606
|
-
}],
|
2597
|
+
}], minlength: [{
|
2607
2598
|
type: Input
|
2608
|
-
}],
|
2599
|
+
}], rows: [{
|
2609
2600
|
type: Input
|
2610
|
-
}],
|
2601
|
+
}], selectOnAutofocus: [{
|
2611
2602
|
type: Input
|
2612
|
-
}],
|
2603
|
+
}], upperCase: [{
|
2613
2604
|
type: Input
|
2614
|
-
}],
|
2605
|
+
}], inputElement: [{
|
2606
|
+
type: ViewChild,
|
2607
|
+
args: ['textboxInput']
|
2608
|
+
}] } });
|
2609
|
+
|
2610
|
+
/** Exposes the markup and styles that represent the spinner. No inputs or outputs defined because it is just a visual component*/
|
2611
|
+
class SpinnerComponent {
|
2612
|
+
}
|
2613
|
+
SpinnerComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.2.9", ngImport: i0, type: SpinnerComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
2614
|
+
SpinnerComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "15.2.9", type: SpinnerComponent, selector: "ec-spinner", ngImport: i0, template: "<div class=\"spinner\">\r\n <span class=\"spinner-dot\"></span>\r\n <span class=\"spinner-dot\"></span>\r\n <span class=\"spinner-dot\"></span>\r\n <span class=\"spinner-dot\"></span>\r\n</div>", styles: ["@keyframes sk-bouncedelay{0%,80%,to{opacity:0}40%{opacity:1}}.spinner{display:flex}.spinner-dot{width:.75rem;height:.75rem;background-color:var(--ec-color-interactive);animation:sk-bouncedelay 1.7s infinite ease-in-out both;margin-right:.25rem}.spinner-dot:nth-child(1){animation-delay:-.6s}.spinner-dot:nth-child(2){animation-delay:-.4s}.spinner-dot:nth-child(3){animation-delay:-.2s}:host(.spinner-small) .spinner-dot{width:.5rem;height:.5rem;background-color:var(--ec-color-interactive);animation:sk-bouncedelay 1.7s infinite ease-in-out both;margin-right:.1666666667rem}:host(.spinner-small) .spinner-dot:nth-child(1){animation-delay:-.6s}:host(.spinner-small) .spinner-dot:nth-child(2){animation-delay:-.4s}:host(.spinner-small) .spinner-dot:nth-child(3){animation-delay:-.2s}\n"] });
|
2615
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.9", ngImport: i0, type: SpinnerComponent, decorators: [{
|
2616
|
+
type: Component,
|
2617
|
+
args: [{ selector: 'ec-spinner', template: "<div class=\"spinner\">\r\n <span class=\"spinner-dot\"></span>\r\n <span class=\"spinner-dot\"></span>\r\n <span class=\"spinner-dot\"></span>\r\n <span class=\"spinner-dot\"></span>\r\n</div>", styles: ["@keyframes sk-bouncedelay{0%,80%,to{opacity:0}40%{opacity:1}}.spinner{display:flex}.spinner-dot{width:.75rem;height:.75rem;background-color:var(--ec-color-interactive);animation:sk-bouncedelay 1.7s infinite ease-in-out both;margin-right:.25rem}.spinner-dot:nth-child(1){animation-delay:-.6s}.spinner-dot:nth-child(2){animation-delay:-.4s}.spinner-dot:nth-child(3){animation-delay:-.2s}:host(.spinner-small) .spinner-dot{width:.5rem;height:.5rem;background-color:var(--ec-color-interactive);animation:sk-bouncedelay 1.7s infinite ease-in-out both;margin-right:.1666666667rem}:host(.spinner-small) .spinner-dot:nth-child(1){animation-delay:-.6s}:host(.spinner-small) .spinner-dot:nth-child(2){animation-delay:-.4s}:host(.spinner-small) .spinner-dot:nth-child(3){animation-delay:-.2s}\n"] }]
|
2618
|
+
}] });
|
2619
|
+
|
2620
|
+
class Overlay {
|
2621
|
+
constructor(status, message) {
|
2622
|
+
this.status = 'hasData';
|
2623
|
+
this.message = '';
|
2624
|
+
this.setStatus(status, message);
|
2625
|
+
}
|
2626
|
+
setStatus(status, message, action, noDataTemplate, overlayClassList) {
|
2627
|
+
this.status = status;
|
2628
|
+
this.message = message || '';
|
2629
|
+
this.action = action || undefined;
|
2630
|
+
this.noDataTemplate = noDataTemplate || undefined;
|
2631
|
+
this.overlayClassList = overlayClassList || '';
|
2632
|
+
}
|
2633
|
+
}
|
2634
|
+
/**
|
2635
|
+
* Wraps content in order to show pending, error, and no data states with an optional message/noDataTemplate
|
2636
|
+
*/
|
2637
|
+
class ViewOverlayComponent {
|
2638
|
+
constructor() {
|
2639
|
+
this.status = 'hasData';
|
2640
|
+
}
|
2641
|
+
setStatus(status, message, action, noDataTemplate) {
|
2642
|
+
this.status = status;
|
2643
|
+
this.message = message || '';
|
2644
|
+
this.action = action || undefined;
|
2645
|
+
this.noDataTemplate = noDataTemplate || undefined;
|
2646
|
+
}
|
2647
|
+
actionClicked(event) {
|
2648
|
+
if (this.action && this.action.onClick) {
|
2649
|
+
this.action.onClick(event);
|
2650
|
+
}
|
2651
|
+
}
|
2652
|
+
}
|
2653
|
+
ViewOverlayComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.2.9", ngImport: i0, type: ViewOverlayComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
2654
|
+
ViewOverlayComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "15.2.9", type: ViewOverlayComponent, selector: "[ecOverlay]", inputs: { status: "status", message: "message", action: "action", noDataTemplate: "noDataTemplate", displayAsMask: "displayAsMask", overlayClassList: "overlayClassList" }, ngImport: i0, template: "<!-- Transcluded Content -->\r\n<ng-content *ngIf=\"displayAsMask || (!displayAsMask && status === 'hasData')\"></ng-content>\r\n<!--Used by GI tests to know the overlay status whether we use ngIf or mask version. No visual impact-->\r\n<span [hidden]=\"true\"\r\n\t class=\"overlay-status-{{status}}\"></span>\r\n<!-- Overlay goes last so it is rendered on top of preceding content due to source order -->\r\n<div *ngIf=\"status !== 'hasData'\"\r\n\t class=\"overlay flex-grow {{overlayClassList}}\"\r\n\t [ngClass]=\"{'not-mask': !displayAsMask,\r\n\t\t\t\t'overlay-error': status === 'error',\r\n\t\t\t\t'overlay-nodata': status === 'noData',\r\n\t\t\t\t'overlay-pending': status === 'pending'}\">\r\n\r\n\t<!--Pending Spinner-->\r\n\t<ec-spinner [hidden]=\"status !== 'pending'\"></ec-spinner>\r\n\r\n\t<ng-template [ngIf]=\"status === 'noData' && noDataTemplate\">\r\n\t\t<ng-container *ngTemplateOutlet=\"noDataTemplate\"></ng-container>\r\n\t</ng-template>\r\n\r\n\t<ng-container *ngIf=\"(status === 'noData' && !noDataTemplate) || status !== 'noData'\">\r\n\t\t<!--Status Message-->\r\n\t\t<div id=\"statusMessage\"\r\n\t\t\t class=\"message\"\r\n\t\t\t *ngIf=\"message\"\r\n\t\t\t [ngClass]=\"{'error': status === 'error', 'mt-1': status === 'pending'}\"\r\n\t\t\t [innerHtml]=\"message | translate\">\r\n\t\t</div>\r\n\r\n\t\t<!-- Action -->\r\n\t\t<ec-button type=\"common\"\r\n\t\t\t\t class=\"mt-3\"\r\n\t\t\t\t *ngIf=\"action?.onClick\"\r\n\t\t\t\t [icon]=\"action?.icon\"\r\n\t\t\t\t (clicked)=\"actionClicked($event)\"\r\n\t\t\t\t [label]=\"action?.label\"\r\n\t\t\t\t [hidden]=\"status === 'pending'\">\r\n\t\t</ec-button>\r\n\t</ng-container>\r\n\r\n</div>", styles: [":host{position:relative}:host(.bg-body)>.overlay{background-color:var(--ec-background-color-body)}:host(.bg-body).is-translucent>.overlay{background-color:var(--ec-background-color-overlay)}:host(.bg-content)>.overlay{background-color:var(--ec-background-color)}:host(.bg-content).is-translucent>.overlay{background-color:var(--ec-background-color-overlay)}.overlay{align-items:center;background-color:var(--ec-overlay-background-color, var(--ec-background-color));display:flex;flex-direction:column;justify-content:center;padding:3rem 4rem;z-index:var(--ec-z-index-overlay);position:absolute;inset:0}.overlay.not-mask{position:relative;min-height:100%}.message{color:var(--ec-color-secondary-dark);font-size:var(--ec-font-size-title)}.message.error{color:var(--ec-color-danger);font-size:var(--ec-font-size-title)}\n"], dependencies: [{ kind: "directive", type: i1.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: i1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i1.NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "component", type: ButtonComponent, selector: "ec-button", inputs: ["id", "disabled", "icon", "label", "badge", "tabindex", "type", "pending", "pendingIcon", "customTemplate", "isSubmit", "autofocus"], outputs: ["clicked"] }, { kind: "component", type: SpinnerComponent, selector: "ec-spinner" }, { kind: "pipe", type: i2.TranslatePipe, name: "translate" }] });
|
2655
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.9", ngImport: i0, type: ViewOverlayComponent, decorators: [{
|
2656
|
+
type: Component,
|
2657
|
+
args: [{ selector: '[ecOverlay]', template: "<!-- Transcluded Content -->\r\n<ng-content *ngIf=\"displayAsMask || (!displayAsMask && status === 'hasData')\"></ng-content>\r\n<!--Used by GI tests to know the overlay status whether we use ngIf or mask version. No visual impact-->\r\n<span [hidden]=\"true\"\r\n\t class=\"overlay-status-{{status}}\"></span>\r\n<!-- Overlay goes last so it is rendered on top of preceding content due to source order -->\r\n<div *ngIf=\"status !== 'hasData'\"\r\n\t class=\"overlay flex-grow {{overlayClassList}}\"\r\n\t [ngClass]=\"{'not-mask': !displayAsMask,\r\n\t\t\t\t'overlay-error': status === 'error',\r\n\t\t\t\t'overlay-nodata': status === 'noData',\r\n\t\t\t\t'overlay-pending': status === 'pending'}\">\r\n\r\n\t<!--Pending Spinner-->\r\n\t<ec-spinner [hidden]=\"status !== 'pending'\"></ec-spinner>\r\n\r\n\t<ng-template [ngIf]=\"status === 'noData' && noDataTemplate\">\r\n\t\t<ng-container *ngTemplateOutlet=\"noDataTemplate\"></ng-container>\r\n\t</ng-template>\r\n\r\n\t<ng-container *ngIf=\"(status === 'noData' && !noDataTemplate) || status !== 'noData'\">\r\n\t\t<!--Status Message-->\r\n\t\t<div id=\"statusMessage\"\r\n\t\t\t class=\"message\"\r\n\t\t\t *ngIf=\"message\"\r\n\t\t\t [ngClass]=\"{'error': status === 'error', 'mt-1': status === 'pending'}\"\r\n\t\t\t [innerHtml]=\"message | translate\">\r\n\t\t</div>\r\n\r\n\t\t<!-- Action -->\r\n\t\t<ec-button type=\"common\"\r\n\t\t\t\t class=\"mt-3\"\r\n\t\t\t\t *ngIf=\"action?.onClick\"\r\n\t\t\t\t [icon]=\"action?.icon\"\r\n\t\t\t\t (clicked)=\"actionClicked($event)\"\r\n\t\t\t\t [label]=\"action?.label\"\r\n\t\t\t\t [hidden]=\"status === 'pending'\">\r\n\t\t</ec-button>\r\n\t</ng-container>\r\n\r\n</div>", styles: [":host{position:relative}:host(.bg-body)>.overlay{background-color:var(--ec-background-color-body)}:host(.bg-body).is-translucent>.overlay{background-color:var(--ec-background-color-overlay)}:host(.bg-content)>.overlay{background-color:var(--ec-background-color)}:host(.bg-content).is-translucent>.overlay{background-color:var(--ec-background-color-overlay)}.overlay{align-items:center;background-color:var(--ec-overlay-background-color, var(--ec-background-color));display:flex;flex-direction:column;justify-content:center;padding:3rem 4rem;z-index:var(--ec-z-index-overlay);position:absolute;inset:0}.overlay.not-mask{position:relative;min-height:100%}.message{color:var(--ec-color-secondary-dark);font-size:var(--ec-font-size-title)}.message.error{color:var(--ec-color-danger);font-size:var(--ec-font-size-title)}\n"] }]
|
2658
|
+
}], propDecorators: { status: [{
|
2615
2659
|
type: Input
|
2616
|
-
}],
|
2660
|
+
}], message: [{
|
2617
2661
|
type: Input
|
2618
|
-
}],
|
2662
|
+
}], action: [{
|
2619
2663
|
type: Input
|
2620
|
-
}],
|
2664
|
+
}], noDataTemplate: [{
|
2621
2665
|
type: Input
|
2622
|
-
}],
|
2666
|
+
}], displayAsMask: [{
|
2623
2667
|
type: Input
|
2624
|
-
}],
|
2668
|
+
}], overlayClassList: [{
|
2625
2669
|
type: Input
|
2626
|
-
}], selectedChanged: [{
|
2627
|
-
type: Output
|
2628
|
-
}], menuClosed: [{
|
2629
|
-
type: Output
|
2630
|
-
}], labelTemplate: [{
|
2631
|
-
type: ViewChild,
|
2632
|
-
args: ['label', { static: true }]
|
2633
|
-
}], iconAndLabelTemplate: [{
|
2634
|
-
type: ViewChild,
|
2635
|
-
args: ['iconAndLabel', { static: true }]
|
2636
|
-
}], checkAndLabelTemplate: [{
|
2637
|
-
type: ViewChild,
|
2638
|
-
args: ['checkAndLabel', { static: true }]
|
2639
|
-
}], iconLabelCaptionTemplate: [{
|
2640
|
-
type: ViewChild,
|
2641
|
-
args: ['iconLabelCaption', { static: true }]
|
2642
2670
|
}] } });
|
2643
2671
|
|
2644
2672
|
/**
|
@@ -2794,6 +2822,11 @@ class ComboboxComponent extends FormControlBase {
|
|
2794
2822
|
* Number of filtered options to display in the footer. Excludes headings.
|
2795
2823
|
*/
|
2796
2824
|
this.filteredOptionCount = 0;
|
2825
|
+
/**
|
2826
|
+
* Flat list of selectable items in the combobox.
|
2827
|
+
* Does not include headings or divider-section items.
|
2828
|
+
*/
|
2829
|
+
this.selectableItems = [];
|
2797
2830
|
/**
|
2798
2831
|
* Index of the currently-selected options
|
2799
2832
|
*/
|
@@ -2930,13 +2963,14 @@ class ComboboxComponent extends FormControlBase {
|
|
2930
2963
|
*/
|
2931
2964
|
resetOptions(options) {
|
2932
2965
|
this.filteredOptions = options || this.options;
|
2966
|
+
this.selectableItems = MenuComponent.getSelectableItems(this.filteredOptions);
|
2933
2967
|
// do not count headings
|
2934
|
-
this.filteredOptionCount = this.filteredOptions?.filter(o => o.display !== 'heading').length || 0;
|
2968
|
+
this.filteredOptionCount = this.filteredOptions?.filter(o => o.display !== 'heading' && o.display !== 'divided-section').length || 0;
|
2935
2969
|
//if they have no search term, don't try to select anything so they can clear the box out by hitting enter
|
2936
2970
|
//if they have a search term and the options changed, select an option from the menu so they will get it automatically if they hit enter
|
2937
2971
|
if (this.textboxFormModel.value !== '') {
|
2938
|
-
this.selectedItemIndex = this.findDefaultSelectionIndex(this.
|
2939
|
-
this.selectedItem = this.
|
2972
|
+
this.selectedItemIndex = this.findDefaultSelectionIndex(this.selectableItems, this.textboxFormModel.value);
|
2973
|
+
this.selectedItem = this.selectableItems[this.selectedItemIndex] || null;
|
2940
2974
|
this.scrollMenu(this.selectedItemIndex);
|
2941
2975
|
}
|
2942
2976
|
else {
|
@@ -3130,18 +3164,11 @@ class ComboboxComponent extends FormControlBase {
|
|
3130
3164
|
if (this.selectedItemIndex === -1 && this.addNewButton && !this.addNewButton.nativeElement.hidden && !this.addNewSelected) {
|
3131
3165
|
this.addNewSelected = true;
|
3132
3166
|
}
|
3133
|
-
else if (this.selectedItemIndex < this.
|
3167
|
+
else if (this.selectedItemIndex < this.selectableItems.length - 1) {
|
3168
|
+
this.selectedItemIndex++;
|
3134
3169
|
if (this.addNewSelected) {
|
3135
3170
|
this.addNewSelected = false;
|
3136
3171
|
}
|
3137
|
-
//if the last item is a heading and we are on the second last item, we shouldn't increment the selectedItemIndex because that would select the heading
|
3138
|
-
if (!(this.selectedItemIndex == this.filteredOptions.length - 2 && this.filteredOptions[this.selectedItemIndex + 1].display === 'heading')) {
|
3139
|
-
this.selectedItemIndex++;
|
3140
|
-
// Skip any in-menu heading items
|
3141
|
-
if (this.selectedItemIndex < this.filteredOptions.length - 1 && this.filteredOptions[this.selectedItemIndex].display === 'heading') {
|
3142
|
-
this.selectedItemIndex++;
|
3143
|
-
}
|
3144
|
-
}
|
3145
3172
|
}
|
3146
3173
|
break;
|
3147
3174
|
case "ArrowUp":
|
@@ -3150,30 +3177,16 @@ class ComboboxComponent extends FormControlBase {
|
|
3150
3177
|
this.addNewSelected = false;
|
3151
3178
|
}
|
3152
3179
|
else if (this.selectedItemIndex > -1) {
|
3153
|
-
if (this.selectedItemIndex === 0 && this.addNewButton && !this.addNewButton.nativeElement.hidden) {
|
3154
|
-
this.addNewSelected = true;
|
3155
|
-
}
|
3156
3180
|
this.selectedItemIndex--;
|
3157
|
-
|
3158
|
-
|
3159
|
-
this.selectedItemIndex--;
|
3160
|
-
//if the selectedItemIndex is -1, that means the very first item was a heading and we just skipped over it.
|
3161
|
-
if (this.selectedItemIndex == -1) {
|
3162
|
-
//if there is an add new button we should select it. otherwise we should lock them at index 1 (right before the heading)
|
3163
|
-
if (this.addNewButton && !this.addNewButton.nativeElement.hidden) {
|
3164
|
-
this.addNewSelected = true;
|
3165
|
-
}
|
3166
|
-
else {
|
3167
|
-
this.selectedItemIndex = 1;
|
3168
|
-
}
|
3169
|
-
}
|
3181
|
+
if (this.selectedItemIndex === -1 && this.addNewButton && !this.addNewButton.nativeElement.hidden) {
|
3182
|
+
this.addNewSelected = true;
|
3170
3183
|
}
|
3171
3184
|
}
|
3172
3185
|
break;
|
3173
3186
|
default:
|
3174
3187
|
return;
|
3175
3188
|
}
|
3176
|
-
this.selectedItem = this.
|
3189
|
+
this.selectedItem = this.selectableItems[this.selectedItemIndex];
|
3177
3190
|
if (this.menuStatus === 'hidden') {
|
3178
3191
|
this.setFormModelValue(this.selectedItem);
|
3179
3192
|
}
|
@@ -3192,10 +3205,16 @@ class ComboboxComponent extends FormControlBase {
|
|
3192
3205
|
filterOptionsArray(filterText) {
|
3193
3206
|
let searchText = filterText.toLowerCase();
|
3194
3207
|
if (filterText && filterText !== '') {
|
3195
|
-
|
3196
|
-
|
3197
|
-
|
3198
|
-
|
3208
|
+
const matchesSearch = (item) => item.label.toLowerCase().indexOf(searchText) >= 0 || (item.caption && item.caption.toLowerCase().indexOf(searchText) >= 0);
|
3209
|
+
return this.options.reduce((filteredItems, item) => {
|
3210
|
+
if (!item.items?.length && matchesSearch(item)) {
|
3211
|
+
filteredItems.push(item);
|
3212
|
+
}
|
3213
|
+
else if (item.items?.length && (item.display === 'heading' || item.display === 'divided-section')) {
|
3214
|
+
filteredItems.push({ ...item, items: item.items.filter(matchesSearch) });
|
3215
|
+
}
|
3216
|
+
return filteredItems;
|
3217
|
+
}, []);
|
3199
3218
|
}
|
3200
3219
|
else {
|
3201
3220
|
return this.options;
|
@@ -3212,7 +3231,7 @@ class ComboboxComponent extends FormControlBase {
|
|
3212
3231
|
findSelectedItemIndex(item) {
|
3213
3232
|
let itemToFind = item ? item : this.selectedItem;
|
3214
3233
|
if (itemToFind) {
|
3215
|
-
return this.
|
3234
|
+
return this.selectableItems.findIndex(item => {
|
3216
3235
|
if (item.id && itemToFind.id) {
|
3217
3236
|
return item.label === itemToFind.label && item.id === itemToFind.id;
|
3218
3237
|
}
|
@@ -3238,7 +3257,7 @@ class ComboboxComponent extends FormControlBase {
|
|
3238
3257
|
this.textboxFormModel.setValue(data.selectedLabel || data.label);
|
3239
3258
|
this.selectedItemIndex = this.findSelectedItemIndex(data);
|
3240
3259
|
if (this.selectedItemIndex >= 0) {
|
3241
|
-
this.selectedItem = this.
|
3260
|
+
this.selectedItem = this.selectableItems[this.selectedItemIndex];
|
3242
3261
|
}
|
3243
3262
|
}
|
3244
3263
|
else {
|
@@ -3259,10 +3278,10 @@ class ComboboxComponent extends FormControlBase {
|
|
3259
3278
|
if (this.selectedItemIndex > -1 && this.selectedItem) {
|
3260
3279
|
// The menu component will automatically generate ids for the menu items if they dont have them,
|
3261
3280
|
// so they need to be accounted for here since the combobox doesn't know about those ids
|
3262
|
-
let
|
3281
|
+
let itemId = this.selectedItem.id ? this.selectedItem.id : MenuComponent.getIndexedItemId(this.filteredOptions, this.selectedItem, `${this.id}_menu`);
|
3263
3282
|
//trigger the scrolling after a tick to allow the menu to be up to date (and pending mask cleared) before measuring
|
3264
3283
|
setTimeout(() => {
|
3265
|
-
this.scrollService.scrollItemCentered(`#${this.id}_menu_list`,
|
3284
|
+
this.scrollService.scrollItemCentered(`#${this.id}_menu_list`, `#${itemId}`);
|
3266
3285
|
}, 0);
|
3267
3286
|
}
|
3268
3287
|
else {
|
@@ -3428,10 +3447,10 @@ class ComboboxComponent extends FormControlBase {
|
|
3428
3447
|
findDefaultSelectionIndex(options, searchText) {
|
3429
3448
|
let index = -1;
|
3430
3449
|
if (options && options.length) {
|
3431
|
-
index = options.findIndex(option => option != null
|
3450
|
+
index = options.findIndex(option => option != null);
|
3432
3451
|
if (searchText) {
|
3433
3452
|
searchText = searchText.toLowerCase().trim();
|
3434
|
-
let exactMatchIndex = options.findIndex(option => option.label.toLowerCase() == searchText
|
3453
|
+
let exactMatchIndex = options.findIndex(option => option.label.toLowerCase() == searchText);
|
3435
3454
|
if (exactMatchIndex >= 0) {
|
3436
3455
|
index = exactMatchIndex;
|
3437
3456
|
}
|