primeng-shadowdom-directives
Version:
Directives that make PrimeNG plays nicely with ShadowDOM
446 lines (433 loc) • 22 kB
JavaScript
import * as i0 from '@angular/core';
import { PLATFORM_ID, Directive, Host, Self, Optional, Inject, NgModule } from '@angular/core';
import { isPlatformBrowser } from '@angular/common';
import * as i1 from 'primeng/menu';
import { DomHandler } from 'primeng/dom';
import * as i1$1 from 'primeng/overlaypanel';
import * as i1$2 from 'primeng/inputmask';
import * as i1$3 from 'primeng/slidemenu';
import * as i1$4 from 'primeng/splitbutton';
import * as i1$5 from 'primeng/tieredmenu';
import * as i1$6 from 'primeng/calendar';
class psdMenuDirective {
constructor(hostEl, platformId) {
this.hostEl = hostEl;
this.platformId = platformId;
hostEl.bindDocumentClickListener = () => {
if (!hostEl.documentClickListener && isPlatformBrowser(platformId)) {
const documentTarget = hostEl.el
? hostEl.el.nativeElement.ownerDocument
: 'document';
hostEl.documentClickListener = hostEl.renderer.listen(documentTarget, 'click', (event) => {
const isOutsideContainer = hostEl.containerViewChild?.nativeElement &&
!hostEl.containerViewChild.nativeElement.contains(event.target.shadowRoot
? event.target.shadowRoot.activeElement
: event.target);
const isOutsideTarget = !(hostEl.target &&
(hostEl.target === event.target ||
hostEl.target.contains(event.target)));
if (!hostEl.popup && isOutsideContainer && isOutsideTarget) {
hostEl.onListBlur(event);
}
if (hostEl.preventDocumentDefault &&
hostEl.overlayVisible &&
isOutsideContainer &&
isOutsideTarget) {
hostEl.hide();
hostEl.preventDocumentDefault = false;
}
});
}
};
}
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: psdMenuDirective, deps: [{ token: i1.Menu, host: true, optional: true, self: true }, { token: PLATFORM_ID }], target: i0.ɵɵFactoryTarget.Directive }); }
static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "17.3.12", type: psdMenuDirective, selector: "[psdMenu]", ngImport: i0 }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: psdMenuDirective, decorators: [{
type: Directive,
args: [{
selector: '[psdMenu]',
}]
}], ctorParameters: () => [{ type: i1.Menu, decorators: [{
type: Host
}, {
type: Self
}, {
type: Optional
}] }, { type: undefined, decorators: [{
type: Inject,
args: [PLATFORM_ID]
}] }] });
class psdOverlayPanelDirective {
constructor(hostEl, zone) {
this.hostEl = hostEl;
this.zone = zone;
hostEl.bindDocumentClickListener = () => {
if (!hostEl.documentClickListener && hostEl.dismissable) {
this.zone.runOutsideAngular(() => {
let documentEvent = DomHandler.isIOS() ? 'touchstart' : 'click';
const documentTarget = hostEl.el ? hostEl.el.nativeElement.ownerDocument : 'document';
hostEl.documentClickListener = hostEl.renderer.listen(documentTarget, documentEvent, (event) => {
const path = event.path || (event.composedPath && event.composedPath());
const target = event.target.shadowRoot ? path[0] : event.target;
if (!hostEl.container?.contains(target) && hostEl.target !== target && !hostEl.target.contains(target) && !hostEl.selfClick) {
this.zone.run(() => {
hostEl.hide();
});
}
hostEl.selfClick = false;
hostEl.cd.markForCheck();
});
});
}
};
}
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: psdOverlayPanelDirective, deps: [{ token: i1$1.OverlayPanel, host: true, optional: true, self: true }, { token: i0.NgZone }], target: i0.ɵɵFactoryTarget.Directive }); }
static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "17.3.12", type: psdOverlayPanelDirective, selector: "[psdOverlayPanel]", ngImport: i0 }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: psdOverlayPanelDirective, decorators: [{
type: Directive,
args: [{
selector: '[psdOverlayPanel]',
}]
}], ctorParameters: () => [{ type: i1$1.OverlayPanel, decorators: [{
type: Host
}, {
type: Self
}, {
type: Optional
}] }, { type: i0.NgZone }] });
/*
In angular 15, primeNg uses document from inject, but the logic is still same
*/
class psdInputMaskDirective {
constructor(hostEl) {
this.hostEl = hostEl;
// @ts-ignore
hostEl.caret = (first, last) => {
let range, begin, end;
if (!hostEl.inputViewChild?.nativeElement.offsetParent ||
hostEl.inputViewChild.nativeElement !==
hostEl.inputViewChild.nativeElement.getRootNode().activeElement) {
return;
}
if (typeof first == 'number') {
begin = first;
end = typeof last === 'number' ? last : begin;
if (hostEl.inputViewChild.nativeElement.setSelectionRange) {
hostEl.inputViewChild.nativeElement.setSelectionRange(begin, end);
}
else if (hostEl.inputViewChild.nativeElement['createTextRange']) {
range = hostEl.inputViewChild.nativeElement['createTextRange']();
range.collapse(true);
range.moveEnd('character', end);
range.moveStart('character', begin);
range.select();
}
}
else {
if (hostEl.inputViewChild.nativeElement.setSelectionRange) {
begin = hostEl.inputViewChild.nativeElement.selectionStart;
end = hostEl.inputViewChild.nativeElement.selectionEnd;
}
else if (document['selection'] &&
document['selection'].createRange) {
range = document['selection'].createRange();
begin = 0 - range.duplicate().moveStart('character', -100000);
end = begin + range.text.length;
}
return { begin: begin, end: end };
}
};
}
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: psdInputMaskDirective, deps: [{ token: i1$2.InputMask, host: true, optional: true, self: true }], target: i0.ɵɵFactoryTarget.Directive }); }
static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "17.3.12", type: psdInputMaskDirective, selector: "[psdInputMask]", ngImport: i0 }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: psdInputMaskDirective, decorators: [{
type: Directive,
args: [{
selector: '[psdInputMask]',
}]
}], ctorParameters: () => [{ type: i1$2.InputMask, decorators: [{
type: Host
}, {
type: Self
}, {
type: Optional
}] }] });
class psdSlideMenuDirective {
constructor(hostEl, platformId) {
this.hostEl = hostEl;
this.platformId = platformId;
hostEl.bindOutsideClickListener = () => {
if (isPlatformBrowser(platformId)) {
if (!hostEl.outsideClickListener) {
hostEl.outsideClickListener = hostEl.renderer.listen(document, 'click', (event) => {
const path = event.path || (event.composedPath && event.composedPath());
const target = event.target.shadowRoot ? path[0] : event.target;
const isOutsideContainer = hostEl.containerViewChild &&
!hostEl.containerViewChild.nativeElement.contains(target);
const isOutsideTarget = hostEl.popup
? !(hostEl.target &&
(hostEl.target === target || hostEl.target.contains(target)))
: true;
if (hostEl.popup) {
if (isOutsideContainer && isOutsideTarget) {
hostEl.onMenuBlur();
hostEl.hide();
}
}
else {
if (isOutsideContainer && isOutsideTarget && hostEl.focused) {
hostEl.onMenuBlur();
}
}
});
}
}
};
}
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: psdSlideMenuDirective, deps: [{ token: i1$3.SlideMenu, host: true, optional: true, self: true }, { token: PLATFORM_ID }], target: i0.ɵɵFactoryTarget.Directive }); }
static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "17.3.12", type: psdSlideMenuDirective, selector: "[psdSlideMenu]", ngImport: i0 }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: psdSlideMenuDirective, decorators: [{
type: Directive,
args: [{
selector: '[psdSlideMenu]',
}]
}], ctorParameters: () => [{ type: i1$3.SlideMenu, decorators: [{
type: Host
}, {
type: Self
}, {
type: Optional
}] }, { type: undefined, decorators: [{
type: Inject,
args: [PLATFORM_ID]
}] }] });
class psdSplitButtonDirective {
constructor(hostEl, platformId) {
this.hostEl = hostEl;
this.platformId = platformId;
hostEl.onDropdownButtonClick = (event) => {
hostEl.onDropdownClick.emit(event);
hostEl.menu?.toggle({
currentTarget: hostEl.containerViewChild?.nativeElement,
relativeAlign: hostEl.appendTo == null,
});
hostEl.isExpanded.set(hostEl.menu?.visible);
};
}
ngAfterViewInit() {
const menu = this.hostEl.menu;
menu.bindOutsideClickListener = () => {
if (isPlatformBrowser(this.platformId)) {
if (!menu.outsideClickListener) {
menu.outsideClickListener = menu.renderer.listen(document, 'click', (event) => {
const path = event.path || (event.composedPath && event.composedPath());
const target = event.target.shadowRoot ? path[0] : event.target;
const isOutsideContainer = menu.containerViewChild &&
!menu.containerViewChild.nativeElement.contains(target);
const isOutsideTarget = menu.popup
? !(menu.target &&
(menu.target === target || menu.target.contains(target)))
: true;
if (isOutsideContainer && isOutsideTarget) {
menu.hide();
}
});
}
}
};
}
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: psdSplitButtonDirective, deps: [{ token: i1$4.SplitButton, host: true, optional: true, self: true }, { token: PLATFORM_ID }], target: i0.ɵɵFactoryTarget.Directive }); }
static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "17.3.12", type: psdSplitButtonDirective, selector: "[psdSplitButton]", ngImport: i0 }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: psdSplitButtonDirective, decorators: [{
type: Directive,
args: [{
selector: '[psdSplitButton]',
}]
}], ctorParameters: () => [{ type: i1$4.SplitButton, decorators: [{
type: Host
}, {
type: Self
}, {
type: Optional
}] }, { type: undefined, decorators: [{
type: Inject,
args: [PLATFORM_ID]
}] }] });
class psdTieredMenuDirective {
constructor(hostEl, platformId) {
this.hostEl = hostEl;
this.platformId = platformId;
hostEl.bindOutsideClickListener = () => {
if (isPlatformBrowser(platformId)) {
if (!hostEl.outsideClickListener) {
hostEl.outsideClickListener = hostEl.renderer.listen(document, 'click', (event) => {
const path = event.path || (event.composedPath && event.composedPath());
const target = event.target.shadowRoot ? path[0] : event.target;
const isOutsideContainer = hostEl.containerViewChild &&
!hostEl.containerViewChild.nativeElement.contains(target);
const isOutsideTarget = hostEl.popup
? !(hostEl.target &&
(hostEl.target === target || hostEl.target.contains(target)))
: true;
if (isOutsideContainer && isOutsideTarget) {
hostEl.hide();
}
});
}
}
};
}
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: psdTieredMenuDirective, deps: [{ token: i1$5.TieredMenu, host: true, optional: true, self: true }, { token: PLATFORM_ID }], target: i0.ɵɵFactoryTarget.Directive }); }
static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "17.3.12", type: psdTieredMenuDirective, selector: "[psdTieredMenu]", ngImport: i0 }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: psdTieredMenuDirective, decorators: [{
type: Directive,
args: [{
selector: '[psdTieredMenu]',
}]
}], ctorParameters: () => [{ type: i1$5.TieredMenu, decorators: [{
type: Host
}, {
type: Self
}, {
type: Optional
}] }, { type: undefined, decorators: [{
type: Inject,
args: [PLATFORM_ID]
}] }] });
/**
* Though delete the following line, there's no error thrown in the console
* but the directive doesn't work as expected, value is not updated in the input field after selection
* so we need to keep it
*/
class psdCalendarDirective {
constructor(hostEl) {
this.hostEl = hostEl;
hostEl.isOutsideClicked = (event) => {
const path = event.path || (event.composedPath && event.composedPath());
const target = event.target.shadowRoot ? path[0] : event.target;
return !(this.hostEl.el.nativeElement.isSameNode(target) || this.hostEl.el.nativeElement.contains(target) || (this.hostEl.overlay && this.hostEl.overlay.contains(target)));
};
}
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: psdCalendarDirective, deps: [{ token: i1$6.Calendar, host: true, optional: true, self: true }], target: i0.ɵɵFactoryTarget.Directive }); }
static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "17.3.12", type: psdCalendarDirective, selector: "[psdCalendar]", ngImport: i0 }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: psdCalendarDirective, decorators: [{
type: Directive,
args: [{
selector: '[psdCalendar]', // psd = PRIMENG ShadowDOM Directive
}]
}], ctorParameters: () => [{ type: i1$6.Calendar, decorators: [{
type: Host
}, {
type: Self
}, {
type: Optional
}] }] });
DomHandler.getScrollableParents = (element) => {
let scrollableParents = [];
if (element) {
let parents = DomHandler.getParents(element).filter((item) => !(item instanceof ShadowRoot));
const overflowRegex = /(auto|scroll)/;
const overflowCheck = (node) => {
let styleDeclaration = window['getComputedStyle'](node, null);
return (overflowRegex.test(styleDeclaration.getPropertyValue('overflow')) ||
overflowRegex.test(styleDeclaration.getPropertyValue('overflowX')) ||
overflowRegex.test(styleDeclaration.getPropertyValue('overflowY')));
};
for (let parent of parents) {
let scrollSelectors = parent.nodeType === 1 && parent.dataset['scrollselectors'];
if (scrollSelectors) {
let selectors = scrollSelectors.split(',');
for (let selector of selectors) {
let el = DomHandler.findSingle(parent, selector);
if (el && overflowCheck(el)) {
scrollableParents.push(el);
}
}
}
if (parent.nodeType !== 9 && overflowCheck(parent)) {
scrollableParents.push(parent);
}
}
}
return scrollableParents;
};
class PrimeNGShadowDOMDirective {
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: PrimeNGShadowDOMDirective, deps: [], target: i0.ɵɵFactoryTarget.NgModule }); }
static { this.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "17.3.12", ngImport: i0, type: PrimeNGShadowDOMDirective, declarations: [psdMenuDirective,
psdOverlayPanelDirective,
psdInputMaskDirective,
psdSlideMenuDirective,
psdSplitButtonDirective,
psdTieredMenuDirective,
psdCalendarDirective], exports: [psdMenuDirective,
psdOverlayPanelDirective,
psdInputMaskDirective,
psdSlideMenuDirective,
psdSplitButtonDirective,
psdTieredMenuDirective,
psdCalendarDirective] }); }
static { this.ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: PrimeNGShadowDOMDirective }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: PrimeNGShadowDOMDirective, decorators: [{
type: NgModule,
args: [{
declarations: [
psdMenuDirective,
psdOverlayPanelDirective,
psdInputMaskDirective,
psdSlideMenuDirective,
psdSplitButtonDirective,
psdTieredMenuDirective,
psdCalendarDirective,
],
exports: [
psdMenuDirective,
psdOverlayPanelDirective,
psdInputMaskDirective,
psdSlideMenuDirective,
psdSplitButtonDirective,
psdTieredMenuDirective,
psdCalendarDirective,
],
}]
}] });
function ensureResizableColumn(dt, shadowRoot) {
dt.destroyStyleElement = () => {
if (dt.styleElement) {
if (shadowRoot instanceof ShadowRoot) {
shadowRoot.removeChild(dt.styleElement);
}
else {
document.head.removeChild(dt.styleElement);
}
dt.styleElement = null;
}
};
dt.createStyleElement = () => {
dt.styleElement = document.createElement('style');
dt.styleElement.type = 'text/css';
DomHandler.setAttribute(dt.styleElement, 'nonce', dt.config?.csp()?.nonce);
if (shadowRoot instanceof ShadowRoot) {
// Use the component's shadow root instead of document.head
shadowRoot.appendChild(dt.styleElement);
}
else {
document.head.appendChild(dt.styleElement);
}
};
}
/*
* Public API Surface of primeng-shadowdom-directives
*/
/**
* Generated bundle index. Do not edit.
*/
export { PrimeNGShadowDOMDirective, ensureResizableColumn, psdCalendarDirective, psdInputMaskDirective, psdMenuDirective, psdOverlayPanelDirective, psdSlideMenuDirective, psdSplitButtonDirective, psdTieredMenuDirective };
//# sourceMappingURL=primeng-shadowdom-directives.mjs.map