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

@billow/vue-utilities

v1.0.2

Published

Useful set of utilities for Vue apps. Under continuous development.

Downloads

8

Readme

Vue Utiities, by Billow

Made with Vue Does not contain tree nuts Built with Love

A useful set of utilities designed specifically for Vue apps. Includes the following features:

  • Handy set of filters.
  • Simple model class for your Vuex stores. Need a full-fledged ORM? Try vue-orm.
  • Dot-notation-based mutation helpers for Vuex.
  • Passport, a basic local-storage-based OAuth client manager, for general use with a password grant client. Need to authenticate with third-parties? Try vue-authenticate
  • Factories: auto-register components (static or lazy) and Vuex stores (supports sync-helpers and nested mutations).
  • FormData (as well as a type-safe counterpart that converts non-files to a JSON payload that your backend will need to translate when compiling a request).
  • String, Object and Array helpers.

💡 WIP: These docs are a work in progress, and may be moved to a dedicated site at a later stage.

Filters

abbreviateCount

Shorten long numbers into their abbreviated counter-parts.

(input, precision = 1)

2500 | abbreviateCount // 2.5k
25000 | abbreviateCount // 25k
250000 | abbreviateCount // 250k
2510000 | abbreviateCount // 2.5m
2510000 | abbreviateCount(2) // 2.51m

accounting

Format numbers in accounting format, using declarative rules. Uses accounting-big.

(currency = 'R', precision = 2, thousandsSeparator = ',', precisionSeparator = '.', format = '%s %v')

2000 | accounting // R 2,000.00
2000 | accounting('$') // $ 2,000.00
15982.115 | accounting('R', 3) // R 15,982.115
2000 | accounting('R', 2, ' ') // R 2 000.00
2000 | accounting('€', 2, '.', ',') // € 2.000,00
2000 | accounting('CAD', 2, ',', '.', '%v %s') // 2,000.00 CAD

calendar

Formats date objects using a calendar format. Uses moment.calendar internally.

(sameElse = 'D MMMM Y', utc = false)

date | calendar
date | calendar('DD/MM/YYYY')
date | calendar('DD/MM/YYYY', true) // uses a UTC offset

convertBreaks

Convert line breaks to HTML breaks

<div v-html="$options.filters.nl2br(multilineString)"></div>

currency

Format numbers as currency using the native toLocaleString. Uses the number if not using Intl-based formatting (which requires three currency symbol characters).

(currency = 'R', locale = 'en-GB', minimumFractionDigits = 2, maximumFractionDigits = 2)

2000 | currency // R 2,000.00
2000 | currency('$') // $ 2,000.00
123456.789 | currency('₹', 'en-IN') // ₹ 1,23,456.79

Note: This filter is a mix-match between Intl.NumberFormat and manual currency-symbol concatenation. Unfortunately, the spec for Intl uses a non-standard format for South African currencies (1 000,00 as opposed to 1,000.00). If you’d prefer to use the Intl spec for formatting currencies, simply provide the three-digit currency code instead of the symbol and the applicable locale. If this route is taken, all rules related to Intl.NumberFormat apply.

2000 | currency('ZAR', 'en-ZA')
2000 | currency('ZAR')

date

Format a date using moment.format.

format = 'Y-MM-DD', utc = false

date | date
date | date('DD/MM/YYYY')
date | date('DD/MM/YYYY', true) // uses a UTC offset

filesize

Given a filesize in bytes, format the size.

base = 2, exponent = -1

38889823 | filesize // 37.09 MB
38889823 | filesize(2, 3) // 0.04 GB

format

Format a string by replacing placeholders (in :placeholder or {placeholder} format, by default) within it.

(format|object), where the argument is the format string and the input is the object from which data is obtained, or vice-versa.

user | format('{name} has role of :role') // Mike has a role of member
':name has role of {role}' | format(user) // Mike has a role of member

Where:

user = {
  name: 'Mike',
  role: 'member'
}

If you’d like to use custom container formats, you can specify them in the second argument as an array of strings:

'(name) has a role of *role' | format({ name: 'Mike', role: 'admin }, ['(|)', '*'])

Each format may be separated by a pipe if you’d like to surround the entire placeholder. Either side of the pipe may have many characters as needed. Where a pipe is not specified, the entire string will be used for the left of the placeholder.

fromNow

Return a date in human-friendly format.

(suffix = true, utc = false)

'2018-09-10' | fromNow // in 4 months
'2018-05-24 07:24:00' | fromNow // 4 minutes ago
'2018-05-24 07:24:00' | fromNow(false) // 4 minutes
'2018-05-24 07:24:00' | fromNow(false, false) // uses a UTC offset

get

Using dot-notation, get the value of the key/path provided from an object. If the key does not exist, the path will be printed instead, failing which a fallback can be set.

(path, fallback = undefined)

user | get('profile.avatar.url') // https://test.test/img.jpg
user | get('profile.avatar.nothing') // profile.avatar.nothing
user | get('profile.avatar.nothing', 'Not set') // Not set

Where:

let user = {
  profile: {
    avatar: {
      url: 'https://test.test/img.jpg'
    }
  }
}

lcfirst

Return the input with the first character in lower case.

'Howzit' | lcfirst // howzit

lcwords

Return the input with the first character in lower case.

'No Howzit' | lcfirst // no howzit

log

Log the input to the console.

something.to.log | log

number

Similar to the currency filter, but without the currency symbol. The currency filter relies on the number filter for locale-based formatting.

(minimumFractionDigits = 2, maximumFractionDigits = 2, locale = 'en-GB')

2000 | number // 2,000.00
2000.211 | number(3) // 2,000.211
2000.21109 | number(3, 5) // 2,000.21109
12345678.7891 | number(3, 5, 'en-IN') // 1,23,456.7891

or

Similar to using the logical-or (a || b, where a is falsy for example), only or uses a stricter truthy-check, unless loose is true.

(fallback, loose = false)

undefined | or('n/a')
null | or('n/a')
'' | or('n/a')

0 | or('n/a') // 0
0 | or('n/a', true) // n/a
false | or('n/a') // false
false | or('n/a', true) // n/a

ordinal

Return the ordinal of the input.

1 | ordinal // 1st
2 | ordinal // 2nd
3 | ordinal // 3rd
4 | ordinal // 4th

plain

Convert HTML to plain text.

<div>body | plain</div>
<!-- In laoreet exercitation? Accusantium, pede? Nascetur, [...] -->
export default {
  data: () => ({
    body: '<p>In laoreet exercitation? Accusantium, pede? <br><br>' +
      'Nascetur, aspernatur pretium feugiat, nullam rerum suscipit pulvinar' +
      'dignissimos nulla sint, rerum dolorum fames hac.</p>'
  })
}

plural

Pluralise a word when the input is a number greater than 1. Arguments are swappable.

(count|singular), where the argument is the singular word and the input is the count, or vice-versa.

1 | plural('apple') // apple
2 | plural('apple') // apples
1 | plural('fish') // fish
2 | plural('fish') // fish

'apple' | plural(1)
'apple' | plural(2)
'fish' | plural(1)
'fish' | plural(2)

replace

Pass the input string to a String.prototype.replace.

(string, replace)

'foo bar' | replace('foo', 'boo') // boo bar
'A123E' | replace(/\d/, '*') // A*23E
'A123E' | replace(/\d/g, '*') // A***E

toFixed

Convert the input to a number and apply fixed precision

(precision = 2)

"2.983726" | toFixed // 2.98

truncate

Truncate the input to the nearest word or character, using the specified omission character.

(length = 20, omitWith = '…', useWordBoundary = true)

'Error gravida dis phasellus deleniti, nostrud.' | truncate
// Error gravida dis…

'Error gravida dis phasellus deleniti, nostrud.' | truncate(15)
// Error gravida…

'Error gravida dis phasellus deleniti, nostrud.' | truncate(15, '[…]')
// Error gravida[…]

'Error gravida dis phasellus deleniti, nostrud.' | truncate(15, '[…]', false)
// Error gravida d[…]

ucfirst

Return the input with the first character in upper case.

'howzit' | ucfirst // Howzit

ucwords

Return the input with the first character in upper case.

'no howzit' | lcfirst // No Howzit

yesNo

A friendly way to display boolean values.

(yes = 'yes', no = 'no')

true | yesNo // yes
false | yesNo // no
true | yesNo('yep', 'nope') // yep
false | yesNo('yep', 'nope') // nope

Model class

Often-times you’ll be setting data in your state based on a server-response, such as a user. A simple model class is provided to add some functionality atop this data, making it easier to work with in general.

The basic construct of a model is as follows (note the export notation – this is achieved with the StoreFactory):

// store/models/user.js
import { Model } from '@billow/vue-utilities/vuex/model'

export class User extends Model {
  constructor(payload = null) {
    super(payload || {
      name: '',
      email: ''
    })
  }
}

Here, we have a User class that extends Model, providing it with additional functionality, such as tracking whether or not the model is dirty (has been changed) or converting it to FormData.

Now, we use the model in our state:

// store/modules/user.js
import { User } from '../models/user'

export let state = {
  user: new User
}

Models are aware of their clean/dirty state. To turn this off, simply construct the model with a null payload, and turn off history by setting the second argument to true.

new User(null, true)

Hydration

Models are also hydratable, either through the hydrate method, or the constructor:

Constructor (most efficient)

Create a new instance of the model, hydrating it with the provided payload, effectively resetting the original state.

export let mutations = {
  setUser: (state, payload) => state.user = new User(payload)
}

The hydrate method

Hydrate the model instance with the provided payload, optionally resetting the original state.

export let mutations = {
  setUser: (state, payload) => state.user.hydrate(payload) // sets the original state to the payload
  setUser: (state, payload) => state.user.hydrate(payload, false) // retains the original state
}

Checking the state of the model

To determine if a model is dirty, simply use the isDirty getter on the model instance:

// User.vue
<template>
  <p>User has unsaved changes: {{ user.isDirty | yesNo }}</p>
</template>

<script>
import { mapState } from 'vuex'

export default {
  computed: mapState('user', ['user'])
}
</script>

Check if tracking is enabled

You can also check if the model is tracking it’s state using the noHistory getter on the instance. Alternatively, you can check if originals have been set using the hasOriginals getter.

Reset the model state

If a model is dirty, you can reset it to the payload that was passed in the constructor or through the hydrate method. To do this, simply call the reset method on the model instance. If there are no originals, then nothing will happen.

Cloning a model

Though meant to be used internally, feel free to clone the model with the clone method on the instance. This will return a fully-qualified clone of the model, however it will not be reactive unless it is set to something that Vuex can observe.

Model transformations

Note: This feature may change in the future to use only dot-notation (see below), or will at least support it over and above the syntax below. If the current syntax is removed, it will only be removed in a major release.

Sometimes, you’ll find yourself in the position where you have a subkey of type Object in your model, but you want that subkey’s value to be of type Number for the purposes of API compatibility. For example, let’s say you have the following data in a model:

{
  name: 'Mike',
  email: '[email protected]',
  country: {
    id: 1,
    name: 'South Africa'
  }
}

When this payload goes up to your API, you might want to only pass the ID of the country. This is where transformations come in – they allow you to easily grab parts of the model and move them to the root, optionally using a custom key to replace it.

There are two types of transformations you can make. The first type simply hoists the value you're looking for in a subkey to the root of the model. For example:

return user.transform({
  country: 'id'
})

This tells the model to return only the id under the country key, whilst retaining the key name, yielding:

{
  name: 'Mike',
  email: '[email protected]',
  country: 1
}

All well and good, but what if you need to rename the key to country_id? This is where the second type of transformation comes in. By passing an array with two parameters that resemble the current and new key names (or an object resembling the current key and the new key pair), we can rename the key easily:

return user.transform({
  country: ['id', 'country_id'] // or
  // country: { id: 'country_id' }
})

These both yield:

{
  name: 'Mike',
  email: '[email protected]',
  country_id: 1
}

Hoist by dot-notation

Because models support dot-notation out of the the box (see the methods below for this), we can further expand on our transformations by hoisting a deeply nested key’s value and optionally renaming it:

return user.transform({ country: 'profile.country.id' })
return user.transform({ country: { 'profile.country.id': 'country_id' } })

This will yield the same result as before, only we’re now working with a country object inside a the user’s profile.

Using dot-notation

As mentioned, models use dot-notation out of the box. With this strategy, we can easily get, pick and omit data from a model.

get

Get a piece of data from the model, with an optional fallback if the data is falsy.

<p>{{ user.get('profile.country.name') }}</p>
<p>{{ user.get('profile.country.name', 'Unknown') }}</p>

Tip: Use the get filter when you’re not working with a model.

pick

Return a limited set of data that your API may require.

return user.pick(['name', 'email'])

Yielding:

{
  name: 'Mike',
  email: '[email protected]',
}

omit

In the same vein, omit data that you don’t need:

return user.omit(['profile'])

Which yields the same thing.

Conversions

You can convert a model to string, form-data and JSON-based-form-data using the built-in helper methods:

return user.toString()
return user.toFormData()
return user.toJsonFormData('data')

In the first case, the model’s enumerable props are simply sent off to JSON.stringify and returned.

In the latter two cases, the first converts the model to a standard FormData object, and the second converts it to a type-safe version of FormData, where anything that is not a file gets added to a single key in JSON format. Your backend will need to parse this out when parsing compiling the incoming request. For more information, there’s a nice little article on it (see the middleware example for Laravel).

Mutation Helpers

API Client

Passport

Component and Store Factories

Array, Object and String Utilities