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