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

@boite-beet/ui-kit

v1.2.4

Published

Beet's UI development kit

Downloads

9

Readme

BEET UI Kit

Beet's Vue UI development kit and component library

Installation

In an existing project, open a command line at the root level and run:

yarn add @boite-beet/ui-kit

Then, in src/main.js initialize through Vue's plugin api:

// src/main.js
import BeetUI from '@boite-beet/ui-kit'

Vue.use(BeetUI)

By importing the library's styles before your own, you ensure that any overridden selectors will take precedence. In theory you can import styles from any script, but it should be noted that in our case this means they will be injected after your own styles and may override your selectors.

Basic Usage

There are two main resources you can import to your project: components and styles. All available components are exposed by the package's main export whereas all Sass stylesheets can be imported from the styles subfolder. For example:

// NavBar.vue <script>

import { DropDown } from '@boite-beet/ui-kit'

export default {
  name: 'NavBar',
  components: { DropDown }
  // ...
}
// src/styles/index.js

import '@boite-beet/ui-kit/styles/globals.scss'
import '@boite-beet/ui-kit/styles/dropdown.scss'
import './app.scss'

Components

The package's default export is the Vue install method which registers some components globally. These do not need to be imported individually, just use them as you would use the router's <RouterLink>.

Element [global]

Like Vue's built-in <component :is="DynamicComponent"/> but for HTML elements instead of Vue components. Useful for cases where you may need to dynamically change the HTML tag used to render a part of your content.

Props

| Prop | Type | Default | Description | | ---- | ------ | ------- | ------------------------------------------------------------------------------------------------------------------------------ | | is | String | 'div' | The HTML tag to use. | | tag | String | null | The same as is prop, needed for cases where Element is used with Vue's <component :is="Element"> to avoid prop conflict. |

Usage

<template>
  <element :is="dynamicTag">Sup</element>
  <!-- or -->
  <Component :is="Element" :tag="dynamicTag">Oh hey there!</Component>
</template>

<script>
export default {
  computed: {
    dynamicTag() {
      return this.condition ? 'ul' : 'div'
    }
  }
}
</script>

Icon [global]

Used to render icons that are included in the icons.svg spritesheet that is generated at build time from the SVG files found in your project's src/assets/icons folder.

Props

| Prop | Type | Default | Description | | ---- | ------ | ---------- | ------------------------------------------------------------------------------------------- | | id | String | required | The id of the icon to render. The id is based on the icon's filename in src/assets/icons. |

Usage

<template>
  <button>
    <Icon id="trash" />
    Delete
  </button>
</template>

RawHtml [global]

Used to safely inject a sanitized HTML string with additional formatting controls.

Props

| Prop | Type | Default | Description | | ----------------- | -------------- | ------- | ------------------------------------------------------------------------------------------------------------------- | | tag | String | 'div' | The tag with which the content should be wrapped. | | html | String, Object | {} | An HTML string or an object with at least one of the keys { before, after }. See details below for usage pattern. | | targetBlankLinks | Boolean | false | Automatically add target="_blank" rel="noopener" to anchor tags if true. | | preventImages | Boolean | false | Disallow img tags in content if true. | | replace | Array | [] | An array of replacements to apply. See details below for usage pattern. | | allowedTags | Array | [] | An array of strings representing tags to allow. See sanitize-html details below. | | allowedAttributes | Object | {} | An object defining allowed HTML attributes per tag. See sanitize-html details below. |

Details

html prop

If an object is passed, it should contain one or both accepted keys before and after. These determine where the content will be injected much in the same manner as CSS' ::before, ::after. This way, you can also pass your own content to the default slot and decide if the HTML should be placed before or after your content. This can be useful for titles (placing content after) and buttons/links (placing content before).

If both are passed, both will be rendered in order.

If a string is passed instead of an object, it will default to the after position.

replace prop

Allows manipulation of the HTML string before it is converted to HTML and rendered. Accepts an array of values that follow these patterns:

  • A string (:replace="['dude']") which will remove all instances of the value. Note that the string is converted to a regular expression, so all regex expressions should be escaped, such as parentheses for capture groups: 'my \(favorite\) dude'.
  • A regular expression (:replace="[/wut wut/g]") which will remove the match. Note that only the first match will be removed if the g flag is not set.
  • A tuple (array of two values) where the first value is a string or regular expression (as above) and the second is one of the following, used for replacement. See the String replace MDN docs for more detail (the values will be passed in order to String.replace).
    • A string (:replace="[[/(<br\s?\/?>){2,}/g, '<br>']]"). The example here would replace two or more consecutive <br> or <br/> or <br /> tags by a single <br>.
    • A function (:replace="[/\s(i)\s/g, ($m, $1) => ` ${$1.toUpperCase()} `]"). The example here would replace 'how i feel when it rains' with 'how I feel when it rains'.
allowedTags/allowedAttributes props

These will be merged into the sanitize-html configuration object. For details on how to configure, see the sanitize-html docs for more information.

Usage

<template>
  <RawHtml
    tag="section"
    :html="{ before: htmlContent }"
    :replace="[['what', 'wut wut in the butt']]"
    target-blank-links
    prevent-images
  >
    <RouterLink :to="{ name: 'home' }">Go Home</RouterLink>
  </RawHtml>
</template>

WrapHtml [global]

This is an alternative to RawHtml that allows you to pass the HTML string as content instead of a prop. It simply takes the slot content and passes it to RawHtml as a prop for you.

Props

The same as RawHtml except for the html prop which is replaced by the default slot's content.

Usage

<template>
  <WrapHtml tag="section" :replace="[['what', 'wut wut in the butt']]" target-blank-links prevent-images>
    {{ htmlContent }}
  </WrapHtml>
</template>

DropDown

Allows you to transition between a height of 0 and auto. Useful for dropdown menus or accordion content.

Props

| Prop | Type | Default | Description | | ------------- | ----------------------------- | ---------- | ------------------------------------------------------------------------------------------------------------------------------- | | isOpen | Boolean | required | Determines the content's visibility. Collapsed when false. | | tag | String | 'div' | The HTML tag to be used when rendering the outer element. | | contentTag | String | 'div' | The HTML tag to be used when rendering the content wrapper element. | | contentClass | String, Array, Object | [] | Additional classnames to be applied to the content wrapper element. | | transitionKey | String, Number, Array, Object | null | Similar to Vue's usage of the key prop, can be used to indicate when the height will change and transition to the new height. |

Events

| Name | Payload | Description | | -------------- | ----------- | ------------------------------------------------- | | transition-end | undefined | Is emitted when an open or close transition ends. |

Usage

// src/styles/index.js

import '@boite-beet/ui-kit/styles/globals.scss'
import '@boite-beet/ui-kit/styles/dropdown.scss' // import before your styles
import './app.scss'
<template>
  <nav class="nav">
    <ul class="nav__menu">
      <li class="nav__meta">
        <span @click="isAccountOpen = !isAccountOpen">Account</span>

        <DropDown :is-open="isAccountOpen" content-class="nav__tray">
          <RouterLink :to="{ name: 'user-home', params: { userId } }">My Account</RouterLink>
          <RouterLink :to="{ name: 'user-settings', params: { userId } }">Settings</RouterLink>
          <RouterLink :to="{ name: 'logout' }">Log out</RouterLink>
        </DropDown>
      </li>
    </ul>
  </nav>
</template>

<script>
import { DropDown } from '@boite-beet/ui-kit'

export default {
  name: 'NavBar',
  components: { DropDown },
  data() {
    return {
      userId: 'udy123',
      isAccountOpen: false
    }
  }
}
</script>

Content Components

Base content components (ContentText, ContentSplit, etc.) can be imported individually or grouped as a named export { ContentComponents } for ease of use:

<script>
import { ContentComponents } from '@boite-beet/ui-kit'

export default {
  components: { ...ContentComponents }
}
</script>

Shared props

All content components share the following props:

| Prop | Type | Default | Description | | ---------- | ------ | ------- | -------------------------------------------------------------------------------------- | | classNames | Object | {} | A map of class names you may wish to add to a component's children. See details below. |

Details

Conditional rendering

All content components will check to see if they have any content. If none is received, it will not render.

classNames prop

Each component has a specific mapping of its BEM elements which you can extend with additional class names. The root element's class can already be extended by simply passing a class attribute, as with any component. Each key in the object should correspond to a BEM element's name, so if you wish to add a modifier to content__legend for example:

<template>
  <ContentText legend="Sweet potaters" class-names="{ legend: '-dark' }" />
</template>

Each component's BEM element map is detailed below.

Accepted values are:

  • a string
  • an object
  • an array of strings, objects and/or arrays

Repeating elements (such as columns) may also accept a function to which the index is passed. The function should return one of the above values.

These elements are indicated in the BEM element maps below with parentheses ().

The following example adds -dark to all columns and applies -shift to columns whose index are odd numbers.

<template>
  <ContentText class-names="{ column: shiftOddColumns }" />
</template>

<script>
export default {
  methods: {
    shiftOddColumns(index) {
      return ['-dark', { '-shift': index % 2 }]
    }
  }
}
</script>

ContentText

Display text content in a simple layout with optional columns.

Props

| Prop | Type | Default | Description | | ------- | ------- | ------- | ----------------------------------------------------------------------------------------- | | center | Boolean | false | If the entire content should be centered. | | title | String | null | The content's main title. | | legend | String | null | The content's legend, usually smaller all-caps text that indicates the section's purpose. | | content | Array | [] | An array of strings representing columns of content. HTML is accepted. |

Slots

default

The default slot is in the footer, below the content columns. Ideal for adding a link.

Details

classNames map

{ legend, title, row, column(), footer }

column receives the index of the column.

Render structure
section.content.-text[.-center]
  h2.content__legend
  h3.content__title

  div.content__row
    v-for(index => RawHtml.content__column(index))

  footer.content__footer
    slot#default

Usage

<template>
  <ContentText v-bind="$page.section" class="section" class-names="{ column: shiftOddColumns }" centered>
    <RouterLink :to="{ name: 'home' }">Go Home</RouterLink>
  </ContentText>
</template>

<script>
import { ContentText } from '@boite-beet/ui-kit'

export default {
  components: { ContentText },
  data() {
    return {
      $page: {
        section: { title: '#', legend: '//', content: ['<p>lorem</p>', 'ipsum'] }
      }
    }
  },
  methods: {
    shiftOddColumns(index) {
      return ['-dark', { '-shift': index % 2 }]
    }
  }
}
</script>

ContentSplit

Display text content along side any other type of content, an image by default.

Props

| Prop | Type | Default | Description | | ------- | ------- | ------- | --------------------------------------------------------------------------------------- | | reverse | Boolean | false | If the split content row should be reversed, placing the media on the right side. | | title | String | null | The content's main title. | | legend | String | null | The content's legend, often smaller all-caps text that indicates the section's purpose. | | content | String | null | A string of content. HTML is accepted. | | image | String | null | The URL of the image if no media slot is provided. |

Slots

default

The default slot is below the text content. Ideal for adding a link.

media

The media slot is on the left side unless reverse is also passed. If no media slot is provided, falls back to an image.

Details

classNames map

{ legend, title, row, column(), footer }

column receives 0 if it is the media and 1 if it is the content.

Render structure
section.content.-split[.-reverse]
  div.content__column(0)
    slot#media || figure.content__image

  div.content__column(1)
    h2.content__legend
    h3.content__title
    RawHtml
    slot#default

Usage

<template>
  <!-- basic image -->
  <ContentSplit
    v-bind="$page.section"
    image="/images/happy-udy.png"
    class="home__about"
    class-names="{ legend: '-dark' }"
  />

  <!-- custom media -->
  <ContentSplit
    v-bind="$page.section"
    class="home__slider"
    class-names="{ column: isText => ({ '-pad-top': isText }) }"
    reverse>
    <template v-slot:media>
      <Slider />
    </template>

    <RouterLink :to="{ name: 'home' }">Go Home</RouterLink>
</template>

<script>
import { ContentSplit } from '@boite-beet/ui-kit'
import { Slider } from '@/components'

export default {
  components: { ContentSplit, Slider },
  data() {
    return {
      $page: {
        section: { title: '#', legend: '//', content: '<p>lorem ipsum</p>' }
      }
    }
  }
}
</script>

Helpers

camelKebab

Convert kebab-case to camel-case and vice-versa. Has two usage patterns: methods or getters.

Usage

import { camelKebab } from '@boite-beet/ui-kit'

// methods
camelKebab.toCamel('holy-moly') // holyMoly
camelKebab.toKebab('sweetBabyJesus') // sweet-baby-jesus

// getters
const eatMe = camelKebab('eat-me')
eatMe.camel // 'eatMe'
eatMe.kebab // 'eat-me'

formatInline

Format wrapping characters in text as tags, sort of like custom markdown... sort of. You can create your own formatters using the create method or use one of the predefined methods.

Note: Only supports single character matching, meaning you cannot replace **sup** with a tag for example.

Usage

To create your own formatter:

import { formatInline } from '@boite-beet/ui-kit'

// pass the character to replace as the first argument and the tag to use as second
const formatHash = formatInline.create('#', 'strong')
formatHash('I miss you #so much#') // 'I miss you <strong>so much</strong>'

// you can also override the tag if need be
formatHash('Always thinking of #you#', 'em') // 'Always thinking of <em>you</em>'

The predefined methods are:

  • bold, star, strong — Renders * as <strong>

  • italic, em, lodash, underscore — Renders _ as <em>

  • strike, strikethrough — Renders ~ as <s>

The predefined methods work in the same way as your own. If you want to match the same character but render a different tag, pass the tag as the second argument, like so:

import { formatInline } from '@boite-beet/ui-kit'

formatInline.lodash('Trouble in _paradise_', 'u') // 'Trouble in <u>paradise</u>'

keywordPropValidator

Create a Vue prop validator for String type props that checks the value against a list of strings you provide.

Usage

import { keywordPropValidator } from '@boite-beet/ui-kit'

export default {
  props: {
    position: {
      type: String,
      default: null,
      validator: keywordPropValidator('top', 'right', 'bottom', 'left')
    }
  }
}

check (type validation)

Available checks are:

  • isString

  • isNumber (NaN will return false)

  • isBoolean

  • isFunction

  • isArray

  • isObject

  • isNullOrUndefined

  • isRegExp

  • isEmpty (An empty string, array or object as well as null and undefined return true)

Usage

All checks can be used as methods or getters, for example:

import { check } from '@boite-beet/ui-kit'

// methods
const someFunc = () => null
check.isFunction(someFunc) // true
checks.isEmpty({}) // true
checks.isEmpty('') // true
checks.isEmpty(0) // false

// getters
const checkVal = check([])
checkVal.isString // false
checkVal.isArray // true
checkVal.isEmpty // true

Development

Compilation/build is done using Rollup.js.

Installation

Clone the package and install the dependencies.

git clone [email protected]:boitebeet/beet-ui-kit.git
cd beet-ui-kit
yarn

Scripts

  • build - compiles the package into the dist/ directory.
  • start - compiles the package every time the source changes.

Using local package in a project

Yarn has built in functionality that allows you to link a local package to a project. The "package" is the library that will be installed via npm and the "project" is the app/website in which you want to test it.

In the package's directory

yarn link

This only needs to be done once, the link remains available until you run yarn unlink. There is no danger or issue created by leaving the link permanently.

In your project's directory

yarn link @boite-beet/ui-kit

Now, if you run yarn start in the package and yarn start in your project, your project's development server will detect when the package has changed (compile on save) and reload.

Unlinking from your project

Once you are done working on the package and have published, it is recommended to unlink it from your project and reinstall the dependancy to verify that everything has deployed correctly.

To do this, run these commands in your project:

yarn unlink @boite-beet/ui-kit
yarn add @boite-beet/ui-kit@latest

Publishing

This requires you to be a member of the boite-beet org on npm and for you to be logged in to your npm account (using the npm login command).

Publish from master

Make sure you are in the master branch and that all your changes have been merged.

git checkout master
git merge develop

Update the version

Run the yarn version command and enter the new version as prompted. This will also create a version tag in git. Versions should follow the semver pattern of major.minor.patch

  • Patch: bugfixes and inconsequential changes
  • Minor: new features
  • Major: breaking changes

Push changes including version tags

git push --follow-tags

Publish to npm

npm publish

Merge the new package version into develop

git checkout develop
git merge master