diff --git a/.gitignore b/.gitignore index 8f4c558..679eb7f 100644 --- a/.gitignore +++ b/.gitignore @@ -40,3 +40,4 @@ testem.log /.chrome /.git yarn.lock +/examples/.vscode/settings.json diff --git a/examples/package.json b/examples/package.json index b0f8007..daf0b4c 100644 --- a/examples/package.json +++ b/examples/package.json @@ -21,7 +21,7 @@ "@angular/platform-browser-dynamic": "~9.1.6", "@angular/router": "~9.1.6", "core-js": "^3.6.5", - "ngx-responsive": "9.0.2-beta", + "ngx-responsive": "./../dist", "rxjs": "~6.5.5", "tslib": "^1.11.2", "zone.js": "~0.10.3" diff --git a/examples/src/app/app.component.html b/examples/src/app/app.component.html index 2b6eea5..a65f482 100644 --- a/examples/src/app/app.component.html +++ b/examples/src/app/app.component.html @@ -17,11 +17,19 @@

Angular blog

+
HELLO XL
HELLO LG
HELLO MD
HELLO SM
HELLO XS
+ +
HELLO XL PATTERN
+
HELLO LG PATTERN
+
HELLO MD PATTERN
+
HELLO SM PATTERN
+
HELLO XS PATTERN
+ diff --git a/examples/src/app/app.component.ts b/examples/src/app/app.component.ts index 055f8c5..a38d25a 100644 --- a/examples/src/app/app.component.ts +++ b/examples/src/app/app.component.ts @@ -2,7 +2,7 @@ import { Component } from '@angular/core'; import { IeInfoRx, ResponsiveSizeInfoRx, OrientationInfoRx, DeviceStandardInfoRx, DeviceInfoRx, - UserAgentInfoRx, BrowserInfoRx, + UserAgentInfoRx, BrowserInfoRx, IResponsivePattern, } from 'ngx-responsive'; // tslint:disable-next-line:ordered-imports import { OnInit, OnDestroy } from '@angular/core'; @@ -13,6 +13,21 @@ import { Subscription } from 'rxjs'; styleUrls: ['./app.component.scss'] }) export class AppComponent implements OnInit, OnDestroy { + public readonly xsPattern: IResponsivePattern = { + bootstrap: 'xs' + }; + public readonly smPattern: IResponsivePattern = { + bootstrap: 'sm' + }; + public readonly mdPattern: IResponsivePattern = { + bootstrap: 'md' + }; + public readonly lgPattern: IResponsivePattern = { + bootstrap: 'lg' + }; + public readonly xlPattern: IResponsivePattern = { + bootstrap: 'xl' + }; private _subscriptions: Subscription[] = []; constructor( public ieInfoRx: IeInfoRx, diff --git a/examples/src/app/app.module.ts b/examples/src/app/app.module.ts index 6a411e7..15f7644 100644 --- a/examples/src/app/app.module.ts +++ b/examples/src/app/app.module.ts @@ -23,6 +23,7 @@ const config: IResponsiveConfig = { imports: [ BrowserModule, CommonModule, + AppRoutingModule, ResponsiveModule.forRoot(config) ], providers: [], diff --git a/package.json b/package.json index 79a6c69..fe1ce20 100644 --- a/package.json +++ b/package.json @@ -111,6 +111,7 @@ "jest-preset-angular": "^8.0.0", "ts-loader": "^6.2.1", "rimraf": "2.6.2", + "rxjs": "~6.5.5", "tsickle": "^0.38.1", "ts-node": "~8.10.1", "tslint": "~6.1.2", diff --git a/src/@core/constants/user-agent.constants.ts b/src/@core/constants/user-agent.constants.ts index aee5f6e..2c3d71a 100644 --- a/src/@core/constants/user-agent.constants.ts +++ b/src/@core/constants/user-agent.constants.ts @@ -4,11 +4,12 @@ * * @license MIT */ +import { IUserAgent } from "../interfaces"; -export const USER_AGENT = { +export const USER_AGENT: IUserAgent = { device: null, browser: null, - pixelratio: null, + pixelRatio: null, ie_version: { name: null, state: null diff --git a/src/@core/interfaces/responsive.interfaces.ts b/src/@core/interfaces/responsive.interfaces.ts index fe98f75..c630321 100644 --- a/src/@core/interfaces/responsive.interfaces.ts +++ b/src/@core/interfaces/responsive.interfaces.ts @@ -1,19 +1,21 @@ +import { TBootstraps, TBrowserNames, TDevices, TOrientations, TPixelRatios, TStandards, TIE_VERSIONS, TSizes } from "../types"; + export interface IResponsivePattern { - bootstrap?: string | string[]; - browser?: string | string[]; - device?: string | string[]; - pixelratio?: string | string[]; - orientation?: string | string[]; - standard?: string | string[]; - ie?: string | string[]; - sizes?: number; + bootstrap?: TBootstraps | TBootstraps[]; + browser?: TBrowserNames | TBrowserNames[]; + device?: TDevices | TDevices[]; + pixelRatio?: TPixelRatios | TPixelRatios[]; + orientation?: TOrientations | TOrientations[]; + standard?: TStandards | TStandards[]; + ie?: TIE_VERSIONS | TIE_VERSIONS[]; + sizes?: number | TSizes; } export interface IResponsiveSubscriptions { bootstrap?: boolean; browser?: boolean; device?: boolean; - pixelratio?: boolean; + pixelRatio?: boolean; orientation?: boolean; standard?: boolean; ie?: boolean; diff --git a/src/@core/interfaces/user-agent.interfaces.ts b/src/@core/interfaces/user-agent.interfaces.ts index 11b5655..c7a0154 100644 --- a/src/@core/interfaces/user-agent.interfaces.ts +++ b/src/@core/interfaces/user-agent.interfaces.ts @@ -5,43 +5,57 @@ * @license MIT */ +import { + TBrowserNames, + TDevices, + TGameDevices, + TIE_VERSIONS, + TLinuxOS, + TMobileDevices, + TosSystems, + TPixelRatios, + TSmartTv, + TTabletDevices, + TWindowsOS +} from "../types"; + /** * @export IUserAgent */ export interface IUserAgent { - device: string; - browser: string; - pixelratio: string; + device: TDevices; + browser: TBrowserNames; + pixelRatio: TPixelRatios; ie_version: { - name: string; + name: TIE_VERSIONS; state: boolean; }; game_device: { - name: string; + name: TGameDevices; state: boolean; }; smart_tv: { - name: string; + name: TSmartTv; state: boolean; }; desktop: { - name: string; + name: TosSystems; state: boolean; }; tablet: { - name: string; + name: TTabletDevices; state: boolean; }; mobile: { - name: string; + name: TMobileDevices; state: boolean; }; window_os: { - name: string; + name: TWindowsOS; state: boolean; }; linux_os: { - name: string; + name: TLinuxOS; state: boolean; }; bot: boolean; diff --git a/src/@core/providers/platform-service/platform.service.ts b/src/@core/providers/platform-service/platform.service.ts index b4c6e62..d23270e 100644 --- a/src/@core/providers/platform-service/platform.service.ts +++ b/src/@core/providers/platform-service/platform.service.ts @@ -1,24 +1,24 @@ import { Inject, PLATFORM_ID, Injectable } from '@angular/core'; -import { ResponsiveConfig } from '../responsive-config/responsive-config'; import { isPlatformBrowser, isPlatformServer } from '@angular/common'; +import { ResponsiveConfig } from '../responsive-config/responsive-config'; + @Injectable() export class PlatformService { + public readonly isServer: boolean; + public readonly isBrowser: boolean; - isServer: boolean; - isBrowser: boolean; - - constructor( - @Inject(PLATFORM_ID) private readonly _platformId, - @Inject(ResponsiveConfig) private responsiveConfig: ResponsiveConfig - ) { - this.isServer = isPlatformServer(_platformId); - this.isBrowser = isPlatformBrowser(_platformId); - } + constructor( + @Inject(PLATFORM_ID) private readonly _platformId, + @Inject(ResponsiveConfig) private readonly _responsiveConfig: ResponsiveConfig + ) { + this.isServer = isPlatformServer(this._platformId); + this.isBrowser = isPlatformBrowser(this._platformId); + } - public isEnabledForPlatform() { - return this.isBrowser || this.responsiveConfig.config.renderOnServer; - } -} \ No newline at end of file + public isEnabledForPlatform() { + return this.isBrowser || this._responsiveConfig.config.renderOnServer; + } +} diff --git a/src/@core/providers/responsive-base/responsive-base.ts b/src/@core/providers/responsive-base/responsive-base.ts index 88bf990..f92765c 100644 --- a/src/@core/providers/responsive-base/responsive-base.ts +++ b/src/@core/providers/responsive-base/responsive-base.ts @@ -11,12 +11,14 @@ import { OnInit, OnDestroy, ChangeDetectorRef, + Directive, } from '@angular/core'; import { Subscription } from 'rxjs'; import { IResponsiveSubscriptions } from '../../interfaces'; import { ResponsiveState } from '../responsive-state/responsive-state'; import { PlatformService } from '../platform-service/platform.service'; +@Directive() export abstract class RESPONSIVE_BASE implements OnInit, OnDestroy { private _noRepeat = 0; @@ -39,7 +41,7 @@ export abstract class RESPONSIVE_BASE implements OnInit, OnDestroy { bootstrap: false, browser: false, device: false, - pixelratio: false, + pixelRatio: false, orientation: false, standard: false, ie: false, @@ -76,7 +78,7 @@ export abstract class RESPONSIVE_BASE implements OnInit, OnDestroy { this.set_active_subscriptions.browser = true; break; case 'pixelratio': - this.set_active_subscriptions.pixelratio = true; + this.set_active_subscriptions.pixelRatio = true; break; case 'ie': this.set_active_subscriptions.ie = true; @@ -100,7 +102,6 @@ export abstract class RESPONSIVE_BASE implements OnInit, OnDestroy { this._subscription_Bootstrap = this._responsiveState.elemento$.subscribe(this.updateView.bind(this)); } - if (this.set_active_subscriptions.browser) { this._subscription_Browser = this._responsiveState.browser$.subscribe(this.updateView.bind(this)); } @@ -108,7 +109,7 @@ export abstract class RESPONSIVE_BASE implements OnInit, OnDestroy { this._subscription_Device = this._responsiveState.device$.subscribe(this.updateView.bind(this)); } - if (this.set_active_subscriptions.pixelratio) { + if (this.set_active_subscriptions.pixelRatio) { this._subscription_Pixel_Ratio = this._responsiveState.pixel$.subscribe(this.updateView.bind(this)); } @@ -144,7 +145,7 @@ export abstract class RESPONSIVE_BASE implements OnInit, OnDestroy { this._subscription_Device.unsubscribe(); } - if (this.set_active_subscriptions.pixelratio) { + if (this.set_active_subscriptions.pixelRatio) { this._subscription_Pixel_Ratio.unsubscribe(); } diff --git a/src/@core/providers/responsive-state/responsive-state.ts b/src/@core/providers/responsive-state/responsive-state.ts index 09a1268..7a9fae5 100644 --- a/src/@core/providers/responsive-state/responsive-state.ts +++ b/src/@core/providers/responsive-state/responsive-state.ts @@ -19,28 +19,28 @@ import { USER_AGENT, REG_IE_VERSIONS, TABLET, WINDOWS_OS, LINUX_OS, MOBILE, IE_VERSIONS } from '../../constants'; +import { IUserAgent } from '../../interfaces'; import { - TLinuxOS, TWindowsOS, TTablet, TMobile, - TosSystems, TSmartTv, TGameDevices + TLinuxOS, TWindowsOS, TTabletDevices, TMobileDevices, + TosSystems, TSmartTv, TGameDevices, TBootstraps, TBrowserNames, TDevices, TPixelRatios, TOrientations, TStandards, TIE_VERSIONS, TSizes } from '../../types'; import { ResponsiveConfig } from '../responsive-config/responsive-config'; import { PlatformService } from '../platform-service/platform.service'; @Injectable() export class ResponsiveState { - - public _windows: Object = {}; - public _window: any = null; - - public elemento$: Observable; - public ancho$: Observable; - public browser$: Observable; - public pixel$: Observable; - public device$: Observable; - public orientation$: Observable; - public standard$: Observable; - public ieVersion$: Observable; - public userAgent$: Observable; + public _windows: { [name: string]: ResponsiveWindowDirective } = {}; + public _window: Window; + + public elemento$: Observable; + public ancho$: Observable; + public browser$: Observable; + public pixel$: Observable; + public device$: Observable; + public orientation$: Observable; + public standard$: Observable; + public ieVersion$: Observable; + public userAgent$: Observable; private _screenWidth: number = null; private _screenHeight: number = null; @@ -59,14 +59,14 @@ export class ResponsiveState { this._screenHeight = (this.isEnabledForPlatform) ? this._window.screen.height : 0; this._userAgent = (this.isEnabledForPlatform) ? this._window.navigator.userAgent.toLowerCase() : null; - if(this.isEnabledForPlatform) { - + if (this.isEnabledForPlatform) { const _resize$ = combineLatest( - fromEvent(this._window, 'resize').pipe( - debounceTime(this._responsiveConfig.config.debounceTime), - defaultIfEmpty(), - startWith(this.getWidth('window')) - ), + fromEvent(this._window, 'resize') + .pipe( + debounceTime(this._responsiveConfig.config.debounceTime), + defaultIfEmpty(), + startWith(this.getWidth('window')) + ), this._forceRefresh$ ).pipe( debounceTime(this._responsiveConfig.config.debounceTime) @@ -74,26 +74,26 @@ export class ResponsiveState { const _pixelRatio$ = fromEvent(this._window, 'onload') .pipe( - defaultIfEmpty(), - startWith(this.getDevicePixelRatio()) + defaultIfEmpty(), + startWith(this.getDevicePixelRatio()) ); const _device$ = fromEvent(this._window, 'onload') .pipe( - defaultIfEmpty(), - startWith(this.getUserAgent()) + defaultIfEmpty(), + startWith(this.getUserAgent()) ); const _userAgent$ = fromEvent(this._window, 'onload') .pipe( - defaultIfEmpty(), - startWith(this.userAgentData()) + defaultIfEmpty(), + startWith(this.userAgentData()) ); const _orientation$ = fromEvent(this._window, 'orientationchange') .pipe( - defaultIfEmpty(), - startWith(this.getOrientation()) + defaultIfEmpty(), + startWith(this.getOrientation()) ); this.elemento$ = _resize$.pipe(map(this.sizeOperations.bind(this))); @@ -146,7 +146,7 @@ export class ResponsiveState { * @name getWidth * @param windowName */ - public getWidth(windowName: string = null): any { + public getWidth(windowName: string = null): number { if (this._windows !== null && this.isEnabledForPlatform) { if (windowName && this._windows[windowName]) { return this._windows[windowName].getWidth(); @@ -163,10 +163,12 @@ export class ResponsiveState { public getDevicePixelRatio(): any { let ratio = 1; if (this.isEnabledForPlatform) { - if (typeof this._window.screen.systemXDPI !== 'undefined' && - typeof this._window.screen.logicalXDPI !== 'undefined' && - this._window.screen.systemXDPI > this._window.screen.logicalXDPI) { - ratio = this._window.screen.systemXDPI / this._window.screen.logicalXDPI; + const screen = this._window.screen as any; + + if (typeof screen.systemXDPI !== 'undefined' && + typeof screen.logicalXDPI !== 'undefined' && + screen.systemXDPI > screen.logicalXDPI) { + ratio = screen.systemXDPI / screen.logicalXDPI; } else if (typeof this._window.devicePixelRatio !== 'undefined') { ratio = this._window.devicePixelRatio; } @@ -184,18 +186,21 @@ export class ResponsiveState { /** * @name sizeObserver */ - public sizeObserver(): any { + public sizeObserver(): number { return (this._windows !== null && this.isEnabledForPlatform) ? this.getWidth('window') : 0; } /** * @name sizeOperations */ - public sizeOperations(): any { - let _sizes = null; + public sizeOperations(): TBootstraps { + let _sizes: TBootstraps = null; + const _breackpoints = this._responsiveConfig.config.breakPoints; + if (this._windows !== null && this.isEnabledForPlatform && _breackpoints !== null) { const _width = this.getWidth('window'); + if (_breackpoints.xl.min <= _width) { _sizes = 'xl'; } else if (_breackpoints.lg.max >= _width && _breackpoints.lg.min <= _width) { @@ -208,14 +213,16 @@ export class ResponsiveState { _sizes = 'xs'; } } + return _sizes; } /** * @name sizeOperations */ - public pixelRatio(): any { - let _pixelRatio = null; + public pixelRatio(): TPixelRatios { + let _pixelRatio: TPixelRatios = null; + if (this.isEnabledForPlatform && this._screenWidth !== 0 && this._screenHeight !== 0) { if (this.testIs4k()) { _pixelRatio = '4k'; @@ -225,6 +232,7 @@ export class ResponsiveState { _pixelRatio = '1x'; } } + return _pixelRatio; } @@ -241,7 +249,7 @@ export class ResponsiveState { /** * @name orientationDevice */ - public orientationDevice(): any { + public orientationDevice(): TOrientations { let _orientationDevice = null; if (this.isEnabledForPlatform) { if (this.isMobile() || this.isTablet()) { @@ -260,14 +268,14 @@ export class ResponsiveState { /** * @name getUserAgent */ - public getUserAgent(): any { + public getUserAgent(): string { return (this.isEnabledForPlatform) ? this._window.navigator.userAgent.toLowerCase() : null; } /** * @name userAgentData */ - public userAgentData(): any { + public userAgentData(): IUserAgent { if (this._window === null) { return USER_AGENT; } @@ -283,37 +291,37 @@ export class ResponsiveState { return { device: this.deviceDetection(), browser: this.browserName(), - pixelratio: this.pixelRatio(), + pixelRatio: this.pixelRatio(), ie_version: { - name: (_ieVersionState) ? this.ieVersionDetect() : DEFAULT_USER_AGENT_VALUE, + name: (_ieVersionState) ? this.ieVersionDetect() : null, state: _ieVersionState }, game_device: { - name: (_isGameDevice) ? this.gameDevices() : DEFAULT_USER_AGENT_VALUE, + name: (_isGameDevice) ? this.gameDevices() : null, state: _isGameDevice }, smart_tv: { - name: (_isSMART) ? this.smartTv() : DEFAULT_USER_AGENT_VALUE, + name: (_isSMART) ? this.smartTv() : null, state: _isSMART }, desktop: { - name: (_isDesktop) ? this.desktop() : DEFAULT_USER_AGENT_VALUE, + name: (_isDesktop) ? this.desktop() : null, state: _isDesktop }, tablet: { - name: (_isTablet) ? this.tablet() : DEFAULT_USER_AGENT_VALUE, + name: (_isTablet) ? this.tablet() : null, state: _isTablet }, mobile: { - name: (_isMobile) ? this.mobile() : DEFAULT_USER_AGENT_VALUE, + name: (_isMobile) ? this.mobile() : null, state: _isMobile }, window_os: { - name: (_isWindows) ? this.windows() : DEFAULT_USER_AGENT_VALUE, + name: (_isWindows) ? this.windows() : null, state: _isWindows }, linux_os: { - name: (_isLinux) ? this.linux() : DEFAULT_USER_AGENT_VALUE, + name: (_isLinux) ? this.linux() : null, state: _isLinux }, bot: this.isBot() @@ -323,7 +331,7 @@ export class ResponsiveState { /** * @name deviceDetection */ - public deviceDetection(): any { + public deviceDetection(): TDevices { if (this.isEnabledForPlatform) { if (this.isMobile()) { return 'mobile'; @@ -335,13 +343,14 @@ export class ResponsiveState { return 'desktop'; } } + return null; } /** * @name standardDevices */ - public standardDevices(): any { + public standardDevices(): TStandards { if (this.isEnabledForPlatform) { if (REG_MOBILES.IPHONE.REG.test(this._userAgent)) { return 'iphone'; @@ -355,13 +364,14 @@ export class ResponsiveState { return 'windows phone'; } } + return null; } /** * @name ieVersionDetect */ - public ieVersionDetect(): any { + public ieVersionDetect(): TIE_VERSIONS { if (this.isEnabledForPlatform) { const _userAgent = this.getUserAgent(); const msie = _userAgent.indexOf('msie '); @@ -392,14 +402,15 @@ export class ResponsiveState { return IE_VERSIONS.IE_12; } } + return null; } /** * @name browserName */ - public browserName(): any { - let _browserName = null; + public browserName(): TBrowserNames { + let _browserName: TBrowserNames = null; if (this.isEnabledForPlatform) { if (REG_SORT_NAMES.WEBKIT.REG.test(this._userAgent) && REG_SORT_NAMES.CHROME.REG.test(this._userAgent) && !REG_BROWSERS.IE.REG.test(this._userAgent)) { @@ -487,7 +498,7 @@ export class ResponsiveState { /** * @name tablet */ - public tablet(): TTablet { + public tablet(): TTabletDevices { let _tablet = null; if (this._userAgent !== null) { if (REG_TABLETS.IPAD.REG.test(this._userAgent)) { @@ -506,7 +517,7 @@ export class ResponsiveState { /** * @name mobile */ - public mobile(): TMobile { + public mobile(): TMobileDevices { let _mobile = null; if (this._userAgent !== null) { for (let _reg in REG_MOBILES) { diff --git a/src/@core/types/bootstraps.types.ts b/src/@core/types/bootstraps.types.ts new file mode 100644 index 0000000..41cf004 --- /dev/null +++ b/src/@core/types/bootstraps.types.ts @@ -0,0 +1,48 @@ +/** + * @name bootstrap.types + * @description Bootstrap types in ngx-responsive + * + * @license MIT + */ + +/** + * @type + * @name TXs + * @export TXs + */ +export type TXs = 'xs'; + +/** + * @type + * @name TSm + * @export TSm + */ +export type TSm = 'sm'; + + /** + * @type + * @name TMd + * @export TMd + */ +export type TMd = 'md'; + +/** + * @type + * @name TLg + * @export TLg + */ +export type TLg = 'lg'; + + /** + * @type + * @name TXl + * @export TXl + */ +export type TXl = 'xl'; + +/** + * @type + * @name TBootstraps + * @export TBootstraps + */ +export type TBootstraps = TXs | TSm | TMd | TLg | TXl; diff --git a/src/@core/types/devices.types.ts b/src/@core/types/devices.types.ts new file mode 100644 index 0000000..9f3758a --- /dev/null +++ b/src/@core/types/devices.types.ts @@ -0,0 +1,41 @@ +/** + * @name device.types + * @description Device types in ngx-responsive + * + * @license MIT + */ + +/** + * @type + * @name TMobile + * @export TMobile + */ +export type TMobile = 'mobile'; + +/** + * @type + * @name TTablet + * @export TTablet + */ +export type TTablet = 'tablet'; + + /** + * @type + * @name TSmartTV + * @export TSmartTV + */ +export type TSmartTV = 'smarttv'; + +/** + * @type + * @name TDesktop + * @export TDesktop + */ +export type TDesktop = 'desktop'; + +/** + * @type + * @name TDevices + * @export TDevices + */ +export type TDevices = TMobile | TTablet | TSmartTV | TDesktop; diff --git a/src/@core/types/index.ts b/src/@core/types/index.ts index 46d1f9f..36e6fbf 100644 --- a/src/@core/types/index.ts +++ b/src/@core/types/index.ts @@ -6,11 +6,17 @@ */ export * from './linux.types'; export * from './windows.types'; -export * from './mobile.types'; -export * from './tablet.types'; +export * from './mobile-devices.types'; +export * from './tablet-devices.types'; export * from './os-systems.types'; export * from './game-devices.types'; export * from './smart-tv.types'; export * from './bot.types'; export * from './browser-names.types'; export * from './ie-versions.types'; +export * from './devices.types'; +export * from './bootstraps.types'; +export * from './pixel-ratio.types'; +export * from './orientations.types'; +export * from './standards.types'; +export * from './sizes.types'; diff --git a/src/@core/types/mobile.types.ts b/src/@core/types/mobile-devices.types.ts similarity index 80% rename from src/@core/types/mobile.types.ts rename to src/@core/types/mobile-devices.types.ts index f549cd9..3bf69c0 100644 --- a/src/@core/types/mobile.types.ts +++ b/src/@core/types/mobile-devices.types.ts @@ -43,8 +43,8 @@ export type TGenericMobile = 'Generic Mobile'; /** * @type - * @name TMobile - * @export TMobile + * @name TMobileDevices + * @export TMobileDevices */ -export type TMobile = TIphone | TAndroid | TWindowsPhone | TBlackberry | TGenericMobile | null; +export type TMobileDevices = TIphone | TAndroid | TWindowsPhone | TBlackberry | TGenericMobile | null; diff --git a/src/@core/types/orientations.types.ts b/src/@core/types/orientations.types.ts new file mode 100644 index 0000000..bac88ce --- /dev/null +++ b/src/@core/types/orientations.types.ts @@ -0,0 +1,27 @@ +/** + * @name orientation.types + * @description Orientation types in ngx-responsive + * + * @license MIT + */ + +/** + * @type + * @name TLandscape + * @export TLandscape + */ +export type TLandscape = 'landscape'; + +/** + * @type + * @name TPortrait + * @export TPortrait + */ +export type TPortrait = 'portrait'; + +/** + * @type + * @name TOrientations + * @export TOrientations + */ +export type TOrientations = TLandscape | TPortrait; diff --git a/src/@core/types/pixel-ratio.types.ts b/src/@core/types/pixel-ratio.types.ts new file mode 100644 index 0000000..99feba3 --- /dev/null +++ b/src/@core/types/pixel-ratio.types.ts @@ -0,0 +1,34 @@ +/** + * @name pixelratio.types + * @description Pixel-ratio types in ngx-responsive + * + * @license MIT + */ + +/** + * @type + * @name T1x + * @export T1x + */ +export type T1x = '1x'; + +/** + * @type + * @name TRetina + * @export TRetina + */ +export type TRetina = 'retina'; + +/** + * @type + * @name T4k + * @export T4k + */ +export type T4k = '4k'; + +/** + * @type + * @name TPixelRatios + * @export TPixelRatios + */ +export type TPixelRatios = T1x | TRetina | T4k; diff --git a/src/@core/types/sizes.types.ts b/src/@core/types/sizes.types.ts new file mode 100644 index 0000000..31cdcf8 --- /dev/null +++ b/src/@core/types/sizes.types.ts @@ -0,0 +1,17 @@ +/** + * @name sizes.types + * @description Sizes types in ngx-responsive + * + * @license MIT + */ + +/** + * @type + * @name TSizes + * @export TSizes + */ +export type TSizes = { + min?: number; + max?: number; + window?: string; +}; diff --git a/src/@core/types/standards.types.ts b/src/@core/types/standards.types.ts new file mode 100644 index 0000000..c4b5253 --- /dev/null +++ b/src/@core/types/standards.types.ts @@ -0,0 +1,48 @@ +/** + * @name standard.types + * @description Standard types in ngx-responsive + * + * @license MIT + */ + +/** + * @type + * @name TIphoneStandard + * @export TIphoneStandard + */ +export type TIphoneStandard = 'iphone'; + +/** + * @type + * @name TIpadStandard + * @export TIpadStandard + */ +export type TIpadStandard = 'ipad'; + +/** + * @type + * @name TAndroidMobile + * @export TAndroidMobile + */ + export type TAndroidMobile = 'android mobile'; + +/** +* @type +* @name TAndroidTablet +* @export TAndroidTablet +*/ +export type TAndroidTablet = 'android tablet'; + +/** + * @type + * @name TWindowsPhoneStandard + * @export TWindowsPhoneStandard + */ +export type TWindowsPhoneStandard = 'windows phone'; + +/** + * @type + * @name TStandards + * @export TStandards + */ +export type TStandards = TIphoneStandard | TIpadStandard | TAndroidMobile | TAndroidTablet | TWindowsPhoneStandard; diff --git a/src/@core/types/tablet.types.ts b/src/@core/types/tablet-devices.types.ts similarity index 64% rename from src/@core/types/tablet.types.ts rename to src/@core/types/tablet-devices.types.ts index daa4784..b4f1a38 100644 --- a/src/@core/types/tablet.types.ts +++ b/src/@core/types/tablet-devices.types.ts @@ -4,7 +4,7 @@ * * @license MIT */ -import { TAndroid, TWindowsPhone } from './mobile.types'; +import { TAndroid, TWindowsPhone } from './mobile-devices.types'; /** * @type * @name TIpad @@ -28,8 +28,8 @@ export type TGenericTablet = 'Generic Tablet'; /** * @type - * @name TTablet - * @export TTablet + * @name TTabletDevices + * @export TTabletDevices */ -export type TTablet = TIpad | TAndroid | TWindowsPhone | TKindle | TGenericTablet | null; +export type TTabletDevices = TIpad | TAndroid | TWindowsPhone | TKindle | TGenericTablet | null; diff --git a/src/@directives/responsive-window/responsive-window.ts b/src/@directives/responsive-window/responsive-window.ts index 40f9d7d..25d7e58 100644 --- a/src/@directives/responsive-window/responsive-window.ts +++ b/src/@directives/responsive-window/responsive-window.ts @@ -67,13 +67,13 @@ export class ResponsiveWindowDirective implements OnInit, OnDestroy, DoCheck { } } - public getWidth() { + public getWidth(): number { return (this._isEnabledForPlatform) ? this.element.offsetWidth : 0; } public getCurrentBreakpoint(): string { const width: number = this.getWidth(); - // console.error("getCurrentBreakpoint", width) + if (this._responsiveConfig.config.breakPoints.xl.min <= width) { return 'xl'; } else if (this._responsiveConfig.config.breakPoints.lg.max >= width && this._responsiveConfig.config.breakPoints.lg.min <= width) { @@ -87,7 +87,6 @@ export class ResponsiveWindowDirective implements OnInit, OnDestroy, DoCheck { } } - private _ifValueChanged(oldValue: any, newValue: any): boolean { if (oldValue === newValue) { return false; diff --git a/src/@directives/responsive/responsive.ts b/src/@directives/responsive/responsive.ts index 9b82586..e0478d0 100644 --- a/src/@directives/responsive/responsive.ts +++ b/src/@directives/responsive/responsive.ts @@ -9,25 +9,27 @@ import { PLATFORM_ID, Inject } from '@angular/core'; import { isPlatformBrowser } from '@angular/common'; import { Subscription } from 'rxjs'; -import { IResponsivePattern, IResponsiveSubscriptions } from '../../@core'; +import { IResponsivePattern, IResponsiveSubscriptions, TBootstraps, TBrowserNames, TDevices, TIE_VERSIONS, TOrientations, TPixelRatios, TSizes, TStandards } from '../../@core'; import { ResponsiveState } from '../../@core/providers/responsive-state/responsive-state'; import { ResponsiveWindowDirective } from "../responsive-window/responsive-window"; import { PlatformService } from '../../@core/providers/platform-service/platform.service'; -@Directive( - { - selector: '[responsive]' - }) +@Directive({ + selector: '[responsive]' +}) export class ResponsiveDirective implements OnDestroy { - - private _config: string | string[]; - @Input() set responsive(config: string | string[]) { + @Input() + public set responsive(config: IResponsivePattern) { this._config = config; + this.init_responsive(); } - get config(): string | string[]{ + + public get config(): IResponsivePattern { return this._config; } + + private _config: IResponsivePattern; // @Input() responsiveContainer: ResponsiveWindowDirective; private _responsiveContainer:ResponsiveWindowDirective; @@ -49,15 +51,16 @@ export class ResponsiveDirective implements OnDestroy { private _windows = null; private _window = null; private _isEnabledForPlatform: boolean = null; + public set_values: IResponsivePattern = { - bootstrap: '', - browser: '', - device: '', - pixelratio: '', - orientation: '', - standard: '', - ie: '', - sizes: 0 + bootstrap: null, + browser: null, + device: null, + pixelRatio: null, + orientation: null, + standard: null, + ie: null, + sizes: null }; private set_active_subscriptions: IResponsiveSubscriptions = @@ -65,7 +68,7 @@ export class ResponsiveDirective implements OnDestroy { bootstrap: false, browser: false, device: false, - pixelratio: false, + pixelRatio: false, orientation: false, standard: false, ie: false, @@ -76,7 +79,7 @@ export class ResponsiveDirective implements OnDestroy { bootstrap: false, browser: false, device: false, - pixelratio: false, + pixelRatio: false, orientation: false, standard: false, ie: false, @@ -130,7 +133,8 @@ export class ResponsiveDirective implements OnDestroy { } public init_responsive(): void { - const config: any = this.config; + const config = this.config; + if (this.isJSON(config)) { if (!!config.bootstrap && this._bootstrapNoRepeat === 0) { this._bootstrap_user_param = (Array.isArray(config.bootstrap) ? config.bootstrap : [config.bootstrap]); @@ -157,10 +161,10 @@ export class ResponsiveDirective implements OnDestroy { this._browserNoRepeat = 1; this.set_active_subscriptions.browser = true; } - if (!!config.pixelratio && this._pixelratioNoRepeat === 0) { - this._pixelratio_user_param = (Array.isArray(config.pixelratio) ? config.pixelratio : [config.pixelratio]); + if (!!config.pixelRatio && this._pixelratioNoRepeat === 0) { + this._pixelratio_user_param = (Array.isArray(config.pixelRatio) ? config.pixelRatio : [config.pixelRatio]); this._pixelratioNoRepeat = 1; - this.set_active_subscriptions.pixelratio = true; + this.set_active_subscriptions.pixelRatio = true; } if (!!config.ie && this._ieNoRepeat === 0) { this._ie_user_param = (Array.isArray(config.ie) ? config.ie : [config.ie]); @@ -168,13 +172,25 @@ export class ResponsiveDirective implements OnDestroy { this.set_active_subscriptions.ie = true; } if (!!config.sizes && this._sizesNoRepeat === 0) { - const _min = config.sizes.min || 0; - const _max = config.sizes.max || Number.MAX_VALUE; - const _win = config.sizes.window; + let _min: number; + let _max: number; + let _win: string; + + if (typeof config.sizes === 'number') { + _min = 0; + _max = (config.sizes as number) || Number.MAX_VALUE; + } else { + const sizes = config.sizes as TSizes; + + _min = sizes.min || 0; + _max = sizes.max || Number.MAX_VALUE; + _win = sizes.window; + } + if (_win !== undefined) { this._sizes_window = _win; } - // this._sizes_container = value.sizes.container; + this._sizes_user_param = [_min, _max]; this._sizesNoRepeat = 1; this.set_active_subscriptions.sizes = true; @@ -206,7 +222,7 @@ export class ResponsiveDirective implements OnDestroy { this._subscription_Device = this._responsiveState.device$.subscribe(this.updateDevice.bind(this)); } - if (this.set_active_subscriptions.pixelratio) { + if (this.set_active_subscriptions.pixelRatio) { this._subscription_Pixel_Ratio = this._responsiveState.pixel$.subscribe(this.updatePixelRatio.bind(this)); } @@ -228,45 +244,61 @@ export class ResponsiveDirective implements OnDestroy { } } - private updateBootstrap(value: string): void { + private updateBootstrap(value: TBootstraps): void { const _update = this._ifValueChanged(this._noRepeatBootstrapName, value); + if (_update) { this.set_values.bootstrap = value; } + this.updateEvent(this.set_values.bootstrap, 'bootstrap'); } - private updateBrowser(value: string): void { + + private updateBrowser(value: TBrowserNames): void { this.set_values.browser = value; + this.updateEvent(this.set_values.browser, 'browser'); } - private updateDevice(value: string): void { + + private updateDevice(value: TDevices): void { this.set_values.device = value; + this.updateEvent(this.set_values.device, 'device'); } - private updatePixelRatio(value: string): void { - this.set_values.pixelratio = value; - this.updateEvent(this.set_values.pixelratio, 'pixelratio'); + + private updatePixelRatio(value: TPixelRatios): void { + this.set_values.pixelRatio = value; + + this.updateEvent(this.set_values.pixelRatio, 'pixelratio'); } - private updateOrientation(value: string): void { + + private updateOrientation(value: TOrientations): void { this.set_values.orientation = value; + this.updateEvent(this.set_values.orientation, 'orientation'); } - private updateStandard(value: string): void { + + private updateStandard(value: TStandards): void { this.set_values.standard = value; + this.updateEvent(this.set_values.standard, 'standard'); } - private updateIEversion(value: string): void { + + private updateIEversion(value: TIE_VERSIONS): void { this.set_values.ie = value; + this.updateEvent(this.set_values.ie, 'ie'); } - private updateSizes(value: number): void { - if(this.responsiveContainer){ + + private updateSizes(value: number | TSizes): void { + if (this.responsiveContainer){ this.set_values.sizes = this._isEnabledForPlatform ? this.responsiveContainer.getWidth() : 0; - }else if (this._sizes_window){ + } else if (this._sizes_window){ this.set_values.sizes = this._responsiveState.getWidth(this._sizes_window); - }else{ + } else{ this.set_values.sizes = value; } + this.updateEvent(this.set_values.sizes, 'sizes'); } @@ -385,7 +417,7 @@ export class ResponsiveDirective implements OnDestroy { this._subscription_Device.unsubscribe(); } - if (this.set_active_subscriptions.pixelratio) { + if (this.set_active_subscriptions.pixelRatio) { this._subscription_Pixel_Ratio.unsubscribe(); } diff --git a/src/@directives/useragent/useragent-info.directive.ts b/src/@directives/useragent/useragent-info.directive.ts index 9fe7d2f..97d7543 100644 --- a/src/@directives/useragent/useragent-info.directive.ts +++ b/src/@directives/useragent/useragent-info.directive.ts @@ -4,31 +4,41 @@ * * @license MIT */ -import { Output, EventEmitter, Directive, OnInit, OnDestroy, ChangeDetectorRef} from '@angular/core'; +import { Output, EventEmitter, Directive, OnInit, OnDestroy, ChangeDetectorRef, Inject } from '@angular/core'; + +import { IUserAgent } from '../../@core/interfaces'; import { ResponsiveState } from '../../@core/providers/responsive-state/responsive-state'; -import { UserAgentInfo } from './useragent-info'; import { PlatformService } from '../../@core/providers/platform-service/platform.service'; -@Directive( -{ +import { UserAgentInfo } from '../../@directives/useragent/useragent-info'; + +@Directive({ selector: 'user-agent-info' }) export class UserAgentInfoDirective extends UserAgentInfo implements OnInit, OnDestroy { - @Output() info: EventEmitter = new EventEmitter(); + @Output() + public readonly info: EventEmitter = new EventEmitter(); + constructor( - public _responsiveState: ResponsiveState, - public cd: ChangeDetectorRef, - platformService: PlatformService - ) { super(_responsiveState, platformService); } + protected readonly responsiveState: ResponsiveState, + @Inject(PlatformService) protected readonly platformService: PlatformService, + private readonly _cd: ChangeDetectorRef + ) { + super(responsiveState, platformService); + } + public ngOnInit(): void { this.connect(); } + public ngOnDestroy(): void { this.disconnect(); } - protected _emitUserAgent ( value: any ): void { - this.info.emit( value ); - this.cd.markForCheck(); + + protected emitUserAgent(userAgent: IUserAgent): void { + this.info.next(userAgent); + + this._cd.markForCheck(); } } diff --git a/src/@directives/useragent/useragent-info.rx.ts b/src/@directives/useragent/useragent-info.rx.ts index ce8c5a7..0bb99b9 100644 --- a/src/@directives/useragent/useragent-info.rx.ts +++ b/src/@directives/useragent/useragent-info.rx.ts @@ -5,14 +5,19 @@ * @license MIT */ import { Injectable} from '@angular/core'; -import { PLATFORM_ID, Inject } from '@angular/core'; +import { Inject } from '@angular/core'; + import { ResponsiveState } from '../../@core/providers/responsive-state/responsive-state'; -import { UserAgentInfo } from './useragent-info'; +import { PlatformService } from '../../@core/providers/platform-service/platform.service'; + +import { UserAgentInfo } from '../../@directives/useragent/useragent-info'; @Injectable() -export class UserAgentInfoRx extends UserAgentInfo { +export class UserAgentInfoRx extends UserAgentInfo { constructor( - public _responsiveState: ResponsiveState, - @Inject(PLATFORM_ID) protected _platformId - ) { super(_responsiveState, _platformId); } + protected readonly responsiveState: ResponsiveState, + @Inject(PlatformService) protected readonly platformService: PlatformService + ) { + super(responsiveState, platformService); + } } diff --git a/src/@directives/useragent/useragent-info.ts b/src/@directives/useragent/useragent-info.ts index fc32aa1..3d20fbd 100644 --- a/src/@directives/useragent/useragent-info.ts +++ b/src/@directives/useragent/useragent-info.ts @@ -4,42 +4,53 @@ * * @license MIT */ -import { PLATFORM_ID, Inject } from '@angular/core'; -import { isPlatformBrowser } from '@angular/common'; -import { distinctUntilChanged } from 'rxjs/operators'; import { Subscription } from 'rxjs'; import { ReplaySubject } from 'rxjs'; import { Observable } from 'rxjs'; +import { distinctUntilChanged } from 'rxjs/operators'; + +import { IUserAgent } from '../../@core/interfaces'; import { ResponsiveState } from '../../@core/providers/responsive-state/responsive-state'; +import { PlatformService } from '../../@core/providers/platform-service/platform.service'; export abstract class UserAgentInfo { - public replaySubject$: ReplaySubject = new ReplaySubject(); - private _isBrowser: boolean = null; - private _subscription: Subscription; - constructor(public _responsiveState: ResponsiveState, - @Inject(PLATFORM_ID) protected _platformId - ) { - this._isBrowser = isPlatformBrowser(this._platformId); + public get getUserAgent(): ReplaySubject { + return this._replaySubject$; + } + + private readonly _replaySubject$: ReplaySubject = new ReplaySubject(); + + private get _isBrowser(): boolean { + return this.platformService.isBrowser; } - public connect(): Observable { + + private _subscription: Subscription; + + constructor( + protected readonly responsiveState: ResponsiveState, + protected readonly platformService: PlatformService + ) {} + + public connect(): Observable { if (this._isBrowser) { - this._subscription = this._responsiveState.userAgent$.pipe(distinctUntilChanged()) - .subscribe((data) => { - this._emitUserAgent(data); - }); + this._subscription = this.responsiveState.userAgent$ + .pipe(distinctUntilChanged()) + .subscribe(data => { + this.emitUserAgent(data); + }); } - return this.replaySubject$.asObservable(); + + return this._replaySubject$.asObservable(); } + public disconnect(): void { if (this._isBrowser) { this._subscription.unsubscribe(); } } - get getUserAgent(): Observable { - return this.replaySubject$.asObservable(); - } - protected _emitUserAgent(value: any): void { - this.replaySubject$.next(value); + + protected emitUserAgent(value: IUserAgent): void { + this._replaySubject$.next(value); } }