npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

ng2-if-media

v1.0.0

Published

Angular 2+ module making media queries and responsive design easy.

Downloads

20

Readme

Dependency Status devDependency Status Downloads Licence Known Vulnerabilities

ng2-if-media

A flexible directive/service module for handling media types and queries in Angular 2+, inspired by include-media.

Server rendering (Universal) compatible.

ng2-if-media

Installation

npm install --save ng2-if-media

import { IfMediaModule } from 'ng2-if-media';

const mediaConfig = {
  breakpoints: {
    tablet: {
      value: '768px',
      param: 'width'
    },
    budgetHeight: {
      value: '480px',
      param: 'height'
    },
    widescreen: {
      value: '1280px',
      param: 'width'
    },
    print: {
      media: 'print'
    },
    landscape: '(orientation: landscape)'
  },
  vendorBreakpoints: ['bootstrap'],  // include 3rd party namespace
  throttle: 100
};

@NgModule({
  imports: [IfMediaModule.withConfig(mediaConfig)]
})

Features

ng2-if-media allows using preconfigured breakpoints with <, >, = logical operators, enabling expressive and readable control over your responsive web-application UI. Window resize updates are handled automatically during the component lifetime with a configurable throttle timer.

<div *ifMedia="<tablet">I will appear below tablet width!</div>
<!-- (max-width: 767px) -->

<div *ifMedia=">=tablet and landscape">Tablets and above in landscape mode!</div>
<!-- (min-width: 768px) and (orientation: landscape) -->

<div *ifMedia="<=tablet, landscape">Tablets and below OR landscape mode!</div>
<!-- (max-width: 768px), (orientation: landscape) -->

<div *ifMedia="print">You will see this on paper IRL.</div>
<!-- (only) print -->

Directive

When used as an attribute directive, ng2-if-media works just like ngIf by showing or hiding elements based on the active media query. It's therefore compatible with the void state of native Angular 4+ animation engine.

<nav class="desktop-nav" *ifMedia=">mobile">
  ...
</nav>

<nav class="burger-nav" *ifMedia="<=mobile">
  <ul>
    <li>About Us</li>
    <li>About You</li>
    <li>About Them</li>
  </ul>
</nav>
<ul>
  <li *ifMedia=">tablet">
    <h1>This is a story...<h1>
    <p>of a man with many devices.</p>
    <audioPlayer play="runningman">
  </li>
  <li *ifMedia="<=tablet and >phone">
    <h1>And his struggle...</h1>
    <p>to find the smoothest scaling experience ever...</p>
  </li>
  <li *ifMedia="<=phone">
    <h1>Where every pixel...</h1>
    <p>has a standalone component.</p>
    <img src="lovecraftianhorror.jpg">
  </li>
</ul>

Following CSS, abstractions can be combined with the and keyword or comma separated and treated as independent junctions. You can also use width values directly or create breakpoints for other properties in the config.

<span *ifMedia="<576px, >widescreen">
  I go high or I go low.
</span>

<loFiWidget *ifMedia="<=budgetHeight and landscape">
  I exist to create a great customer experience for the glorious "landscape" of budget phone users!
</loFiWidget>

Service

Sometimes you need more granularity than just showing and hiding some HTML. ng2-if-media is also available as a service to simplify working with matchMedia API and related window events using the same methodology and configuration as the directive.

import { IfMediaService } from 'ng2-if-media';

export class AppComponent implements OnDestroy {
  mediaContainer;

  constructor(private mediaService: IfMediaService) {
    this.mediaContainer = this.mediaService.register(this);
  }

  ngOnDestroy() {
    this.mediaContainer.deregister();
  }
}

onChange

The onChange method provides the functional jackhammer for media specific application logic, where the media expression result is passed to the callback as an optional parameter.

// component.html
<a routerLink="/register">{{ message }}</a>

// component.ts
const messageSmall = 'Tap to win great stuff!';
const messageBig = 'Click here to win the greatest prizes of all time in history!';
this.mediaContainer.onChange('<768px', (match) => { this.message = match ? messageSmall : messageBig });

The callback is executed once for every time the media expression result is flipped, allowing some advanced usage.

// component.html
<h1>Spin to win!</h1>
<strong>x{{orientationFlipCounter}}!</strong>

// component.ts
this.mediaContainer.onChange('landscape', () => { this.orientationFlipCounter++; });

when

when method executes its callback only once for every time the media expression evaluates to true.

this.mediaContainer.when('landscape', () => {
  alert('Switching back to portrait is $2.24 monthly. - Comcast');
})

To make things practically simple, you can pass an object of properties to change in the current component this context instead.

// component.html
<p>{{text}}</p>

// component.ts
text: string = 'Default message';
this.mediaContainer.when({
  '<=phone': { 'text': 'Text for phones' },
  '>phone and <desktop': { 'text': 'Longer text for some other devices' },
  '>=desktop': { 'text': 'Funny retro-viral message for Wizards in 8bit|4K' }
})

Configuration

By default, ng2-if-media has no abstract configuration and you can use it freely with direct values (eg. <=640px) or 3rd party presets. Since project requirements can get very specific, supplying your own custom breakpoints is the most expected usecase.

You can either create flexible breakpoints that utilize <, >, = logical operators (with precision), specify media types and append static suffixes:

breakpoints: {
  vga: {
    value: '640px',
    param: 'width',
    media: 'screen',
    suffix: '(aspect-ratio: 4/3)'
  },
  retina2: {
    value: '2dppx',
    param: 'resolution',
    precision: 0.01
  }
}

Or handle any other usecase with static string expressions (which cannot use operators):

breakpoints: {
  landscape: '(orientation: landscape)',
  iPhone5: 'screen and (min-width: 320px) and (max-width: 568px) and (-webkit-min-device-pixel-ratio: 2)'
}

Presets

Presets are available for 3rd party methodologies (currently for Bootstrap 4) and optionally extend the custom configuration. Resize update throttle timer is also configurable (default 100).

Note: Bootstrap methodology is incompatible with logical operators, due to xs and sm being the same 576px breakpoint with opposite orientation. The namespace is only available as static expressions, just like in Bootstrap itself.

breakpoints: { ... },
vendorBreakpoints: ['bootstrap'],
throttle: 16.7

Building from code

$ git clone [email protected]:salsita/ng2-if-media.git
$ cd ng2-if-media
$ npm i

The module library code is in src/ng2-if-media/neg-if-media.module.ts.

$ npm run lint   # to lint the code
$ npm test       # to run the tests
$ npm run build  # to build

Licence

MIT License

Copyright (c) 2017 Salsita Software

Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.


Created with :muscle: in Salsita!