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

vue-combo-blocks

v2.1.1

Published

Provides all the building blocks needed for accessible autocomplete, combobox, or typeahead component.

Downloads

1,534

Readme

Vue Combo Blocks 🧱

Provides all the building blocks needed for accessible autocomplete, combobox, or typeahead component.

A very Downshift like autocomplete solution for Vue

Downshift for Vue.js

size gzip size downloads

The problem

You want to build an autocomplete/combobox component, and it needs to be accessible, lightweight and you don't really want extra dependencies or styling you would not use, or you'd have to hack around to to make it your own.

The solution

This library provides you the state and the controls for your combobox. You provide the elements and styles to build the thing you need.

Installation

For vue 3.x use npm i vue-combo-blocks For vue 2.x use npm i vue-combo-blocks@vue2

Usage

Try it out in codesandbox

<template>
  <vue-combo-blocks
    v-model="selected"
    :itemToString="itemToString"
    :items="filteredList"
    @input-value-change="updateList"
    v-slot:default="{
      getInputProps,
      getInputEventListeners,
      hoveredIndex,
      isOpen,
      getMenuProps,
      getMenuEventListeners,
      getItemProps,
      getItemEventListeners,
      getComboboxProps,
      reset,
    }"
  >
    <div v-bind="getComboboxProps()">
      <button @click="reset">reset</button>
      <input
        v-bind="getInputProps()"
        v-on="getInputEventListeners()"
        placeholder="Search"
      />
      <ul
        v-show="isOpen"
        v-bind="getMenuProps()"
        v-on="getMenuEventListeners()"
      >
        <li
          v-for="(item, index) in filteredList"
          :key="item.id"
          :style="{
            backgroundColor: hoveredIndex === index ? 'lightgray' : 'white',
            fontWeight: selected === item ? 'bold' : 'normal',
          }"
          v-bind="getItemProps({ item, index })"
          v-on="getItemEventListeners({ item, index })"
        >
          {{ item.value }}
        </li>
      </ul>
    </div>
  </vue-combo-blocks>
</template>

<script>
import VueComboBlocks from 'vue-combo-blocks';

// This list could come from an external api
const list = [
  { value: 'Gretsch', id: '1' },
  { value: 'Ludwig', id: '2' },
  { value: 'Mapex', id: '3' },
  { value: 'Pearl', id: '4' },
  { value: 'Sonor', id: '5' },
  { value: 'Tama', id: '6' },
  { value: 'Zildjian', id: '7' },
];
export default {
  components: {
    VueComboBlocks,
  },
  data() {
    return {
      selected: null,
      filteredList: list,
    };
  },
  methods: {
    itemToString(item) {
      return item ? item.value : '';
    },
    // This could be a call to an api that returns the options
    updateList(text) {
      this.filteredList = list.filter((item) =>
        item.value.toLowerCase().includes(text.toLowerCase()),
      );
    },
  },
};
</script>

Props

| Name | Type | Default | description | | ------------------------------ | ------------------------------------------------- | -------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | items | Array | required | | | itemToString | Function | (item) => (item ? String(item) : '') | | | modelValue (value in Vue2) | Any | null | Sets the selected item. Prop part of v-model | | stateReducer | Function(state: object, actionAndChanges: object) | optional | Very handy feature that gives you a complete control of the vue-combo-blocks state. Read more about it in the State Reducer section | | scrollIntoView | Boolean | true | Controls whether or not the hovered item is scrolled into view when navigating with up and down keys. Note: the menu (ul) element must be positioned either relative or absolute for it to work | | circular | Boolean | true | Controls what happens when navigation with arrow keys and list bottom or top is reached | | inputId | String | generated ID | Used for aria attributes and the id prop of the element (input) | | labelId | String | generated ID | Used for aria attributes and the id prop of the element (label) | | menuId | String | generated ID | Used for aria attributes and the id prop of the element (ul) | | getItemId | Function(index) | optional | defaults to a function that generates an ID based on the index |

Events

Emitted events return 2 parameters. First is the new value, and second is the state change type.

| Name | Type | Description | | ---------------------- | ---------------------------------------------------------------- | -------------------------------------------------------- | | select | selectedItem: Any, type: stateChangeType | Emitted when the item is selected | | change | selectedItem: Any, type: stateChangeType | Emitted when the selected item changes | | input-value-change | inputValue: String, type: stateChangeType | Emitted when the input value changes | | is-open-change | isOpen: Boolean, type: stateChangeType | Emitted when the isOpen value changes | | hovered-index-change | hoveredIndex: Number, type: stateChangeType | Emitted when the hoveredIndex value changes | | state-change | state:Object, type: stateChangeType | Emitted when the state changes. Contains all the changes |

Default Slot & returned props

Default slot's scope contains: prop getters, event listeners, component state and actions.

Prop getters

Bind the prop getters to their elements with v-bind and event listeners with v-on. You can add your own event listeners to these elements too and any other props needed.

<input v-bind="getInputProps()" v-on="getInputEventListeners()" />

| Name | Type | Description | | ------------------ | --------------------------------------------------------- | --------------------------------------------------------------------------------------------------------- | | getComboboxProps | function() | returns the props you should apply to an element that wraps the input element that you render. | | getInputProps | function() | returns the props you should apply to the input element that you render. | | getLabelProps | function() | returns the props you should apply to the label element that you render. | | getItemProps | function({ item: any, index: number, disabled: boolean }) | returns the props you should apply to any menu item elements you render. item property is required! | | getMenuProps | function() | returns the props you should apply to the ul element (or root of your menu) that you render. |

Event listeners

| Name | Type | Description | | ------------------------ | --------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------- | | getInputEventListeners | function({ blur?: (e: Event) => void, input?: (e: Event) => void, keydown?: (e: Event) => void, keyup?: (e: Event) => void }) | Bind these to the input element. | | getItemEventListeners | function({ item: any, index?: number, disabled?: boolean, mousemove?: (e: Event) => void, mousedown?: (e: Event) => void, click?: (e: Event) => void }) | Bind these to the li element. item property is required! | | getMenuEventListeners | function({ mouseleave?: (e: Event) => void, mousedown?: (e: Event) => void }) | Bind these to the ul element. |

Custom Event Listeners

(New in 1.1.0)

You can add custom event listers with default event listeners. Your custom event listener will run before vue-combo-blocks internal event listener:

<vue-combo-blocks
  v-slot:default="{
    getInputProps,
    getInputEventListeners,
  }"
>
  <input v-bind="getInputProps()" v-on="getInputEventListeners()" @input="myInput" />
</vue-combo-blocks>

You can also override, or just prevent the default event by providing you custom event listener as an argument:

<vue-combo-blocks
  v-slot:default="{
    getInputProps,
    getInputEventListeners,
  }"
>
    <input v-bind="getInputProps()" v-on="getInputEventListeners({ input: myInput })" />
  </vue-combo-blocks>

State

| Name | Type | Description | | ------------ | ------- | --------------------------- | | isOpen | Boolean | the list open state | | selectedItem | Any | the currently selected item | | hoveredIndex | Number | the currently hovered item | | inputValue | String | the value in the input |

Actions

| Name | Type | Description | | ------------- | ---------------------------- | --------------------------------------------------- | | reset | function() | Clears the selected item, and reset the input value | | select | function(item: any) | Selects an item | | setInputValue | function(inputValue: string) | Sets the input value | | openMenu | function() | Opens the menu | | closeMenu | function() | Closes the menu |

State Reducer

function(state: object, actionAndChanges: object This function is called each time vue-combo-blocks sets its internal state. It gives you the current state and the state that will be set, and you return the state that you want to set.

  • state: The full current state of vue-combo-blocks.
  • actionAndChanges: Object that contains the action type, props needed to return a new state based on that type and the changes suggested by the vue-combo-blocks default reducer. About the type property you can learn more about in the stateChangeTypes section.

In this example, we want to keep the menu open after the item is selected, and keep the input value empty

<template>
  <vue-combo-blocks :stateReducer="stateReducer" ****>
    ****
  </vue-combo-blocks>
</template>
  methods: {
    stateReducer(oldState, { changes, type }) {
      switch (type) {
        case VueComboBlocks.stateChangeTypes.InputKeyUpEnter:
        case VueComboBlocks.stateChangeTypes.ItemClick:
          return {
            ...changes,
            isOpen: true,
            inputValue: '',
          };
        default:
          return changes;
      }
    },
  }

stateChangeTypes

The list of all possible values this type property can take is defined in this file and is as follows:

  • VueComboBlocks.stateChangeTypes.InputKeyDownArrowDown
  • VueComboBlocks.stateChangeTypes.InputKeyDownArrowUp
  • VueComboBlocks.stateChangeTypes.InputKeyDownTab
  • VueComboBlocks.stateChangeTypes.InputKeyUpEscape
  • VueComboBlocks.stateChangeTypes.InputKeyUpEnter
  • VueComboBlocks.stateChangeTypes.InputChange
  • VueComboBlocks.stateChangeTypes.InputBlur
  • VueComboBlocks.stateChangeTypes.MenuMouseLeave
  • VueComboBlocks.stateChangeTypes.ItemMouseMove
  • VueComboBlocks.stateChangeTypes.ItemClick
  • VueComboBlocks.stateChangeTypes.FunctionOpenMenu
  • VueComboBlocks.stateChangeTypes.FunctionCloseMenu
  • VueComboBlocks.stateChangeTypes.FunctionSelectItem
  • VueComboBlocks.stateChangeTypes.FunctionSetInputValue
  • VueComboBlocks.stateChangeTypes.FunctionReset
  • VueComboBlocks.stateChangeTypes.ControlledPropUpdatedSelectedItem