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

@mind-elixir/viselect

v3.1.0

Published

Simple, lightweight and modern library library for making visual DOM Selections.

Downloads

11

Readme

Installation

Via package manager

$ npm install @viselect/vanilla
# or 
$ yarn add @viselect/vanilla

Via script tags


<script src="https://cdn.jsdelivr.net/npm/@viselect/vanilla/lib/viselect.cjs.js"></script>
Via ES6 import
import SelectionArea from "https://cdn.jsdelivr.net/npm/@viselect/vanilla/lib/viselect.esm.js"

Getting started

Last but not least you'll need to add some basic styles to make your selection-area visible:

.selection-area {
    background: rgba(46, 115, 252, 0.11);
    border: 2px solid rgba(98, 155, 255, 0.81);
    border-radius: 0.1em;
}

Additionally, to not interfere with text-selection, selection-js won't prevent any default events anymore (as of v2.0.3). This however can cause problems with the actual selection ("introduced" by #99, reported in #103). If you don't care about text-selection, add the following to the container where all your selectables are located:

.container {
    user-select: none;
}

Configuration

const selection = new SelectionArea({

    // Class for the selection-area itself (the element).
    selectionAreaClass: 'selection-area',

    // Class for the selection-area container.
    selectionContainerClass: 'selection-area-container',

    // Query selector or dom-node to set up container for the selection-area element.
    container: 'body',

    // document object - if you want to use it within an embed document (or iframe).
    document: window.document,

    // Query selectors for elements which can be selected.
    selectables: [],

    // Query selectors for elements from where a selection can be started from.
    startareas: ['html'],

    // Query selectors for elements which will be used as boundaries for the selection.
    boundaries: ['html'],

    // Behaviour related options.
    behaviour: {

        // Specifies what should be done if already selected elements get selected again.
        //   invert: Invert selection for elements which were already selected
        //   keep: Keep selected elements (use clearSelection() to remove those)
        //   drop: Remove stored elements after they have been touched
        overlap: 'invert',

        // On which point an element should be selected.
        // Available modes are cover (cover the entire element), center (touch the center) or
        // the default mode is touch (just touching it).
        intersect: 'touch',

        // px, how many pixels the point should move before starting the selection (combined distance).
        // Or specifiy the threshold for each axis by passing an object like {x: <number>, y: <number>}.
        startThreshold: 10,

        // Scroll configuration.
        scrolling: {

            // On scrollable areas the number on px per frame is devided by this amount.
            // Default is 10 to provide a enjoyable scroll experience.
            speedDivider: 10,

            // Browsers handle mouse-wheel events differently, this number will be used as 
            // numerator to calculate the mount of px while scrolling manually: manualScrollSpeed / scrollSpeedDivider.
            manualSpeed: 750,

            // This property defines the virtual inset margins from the borders of the container
            // component that, when crossed by the mouse/touch, trigger the scrolling. Useful for
            // fullscreen containers.
            startScrollMargins: {x: 0, y: 0}
        }
    },

    // Features.
    features: {

        // Enable / disable touch support.
        touch: true,

        // Range selection.
        range: true,

        // Configuration in case a selectable gets just clicked.
        singleTap: {

            // Enable single-click selection (Also disables range-selection via shift + ctrl).
            allow: true,

            // 'native' (element was mouse-event target) or 'touch' (element visually touched).
            intersect: 'native'
        }
    }
});

Events

Use the on(event, cb) and off(event, cb) functions to bind / unbind event-listener.

| Event | Description | |---------------|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| | beforestart | The user tapped one of the areas within the specified boundaries. Return false to cancel selection immediatly. | | beforedrag | Same as beforestart but before the user starts selecting by dragging the mouse. Can be used to conditionally allow a selection by dragging. Return false to cancel the selection. | | start | Selection started, here you can decide if you want to keep your previously selected elements. | | move | Selection is active, user is moving the pointer around. | | stop | Selection has stopped. |

Functions

| Function | Description | |-----------------------------------------------------------------|----------------------------------------------------------------------------------------------------------------| | trigger(evt: MouseEvent / TouchEvent, silent = true): void | Manually trigger a selection. | | resolveSelectables(): void | Updates the list of selectables, useful if new elements have been added during a selection. | | clearSelection(includeStored = true): void | Clears the selection, pass false to keep previously selected elements. | | getSelection(): Element[] | Returns currently selected element. Use it in the stop event to collect selected elements. | | getSelectionArea(): HTMLElement | Returns the selection area element. | | cancel(keepEvent = false): void | Cancel the currently active selection, pass true to trigger the stop event afterwards. | | destroy(): void | Destroy the SelectionArea-instance, removes all event-listeners and the selection-area element from the DOM. | | disable(): void | Disables the selection-area temporarily. | | enable(): void | Enables the selection-area. | | select(query: SelectAllSelectors, quiet = false): Element[] | Manually select elements, if quiet is set to true this will not fire the move & stop event. |
| deselect(query: SelectAllSelectors, quiet = false): Element[] | Manually deselect elements, if quiet is set to true this will not fire the move & stop event. |

Example

selection.on('beforestart', evt => {

    // Use this event to decide whether a selection should take place or not.
    // For example if the user should be able to normally interact with input-elements you 
    // may want to prevent a selection if the user clicks such a element:
    // selection.on('beforestart', ({event}) => {
    //   return event.target.tagName !== 'INPUT'; // Returning false prevents a selection
    // });

    console.log('beforestart', evt);
}).on('beforedrag', evt => {

    // Same as 'beforestart' but before a selection via dragging happens.
    console.log('beforedrag', evt);
}).on('start', evt => {

    // A selection got initiated, you could now clear the previous selection or
    // keep it if in case of multi-selection.
    console.log('start', evt);
}).on('move', evt => {

    // Here you can update elements based on their state.
    console.log('move', evt);
}).on('stop', evt => {

    // Do something with the selected elements.
    console.log('stop', evt);
});

Event properties

Every event comes with the following properties:

{
    selection: SelectionArea // Current instance
    event: TouchEvent | MouseEvent | null // TouchEvent, MouseEvent or `null` if triggered manually
    store: {
        touched: Element[] // Touched elements
        selected: Element[] // Elements from the currently active selection (each click, drag counts as a single "selection") 
        stored: Element[] // Elements currently selected (in total, not just an instant)
        changed: {
            added: Element[] // Added elements since last change
            removed: Element[] // Removed elements since last change
        }
    }
}

Common recipes can be found under recipes.