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

svelte-number-spinner

v0.8.0

Published

![Number Spinner](NumberSpinner.gif)

Downloads

323

Readme

svelte-number-spinner

Number Spinner

A highly configurable number spinner component for Svelte. It's a simple input field with a number that can be controlled using the mouse or keyboard. Pressing Alt or Alt+Shift makes steps smaller or bigger. Clicking on the input field without dragging the mouse or pressing Enter or any other non-control key like -, 1, 2, 3, ... starts the normal input mode.

New since version 0.6.0

Mobile devices with touch are now also supported which needed some major rework. I had to remove the option to select between double click or simple click to start editing. Now, only simple click is possible.

Demo

Simple example using number spinners for choosing a color

Number spinner demo showing all options

Installation

npm install svelte-number-spinner

Usage

<script>
  import NumberSpinner from "svelte-number-spinner";

  let value = 50;
</script>

<NumberSpinner bind:value min=0 max=100 />

Props

| Prop | Type | Default | Description | |---------------|----------|--------------|-----------------------------------------------------| | value | Number | 0 | Input value | | min | Number | -1e12 | Minimum value | | max | Number | +1e12 | Maximum value | | step | Number | 1 | Step | | precision | Number | = step | Precision of value (should be a fraction of step) | | speed | Number | 1 | Speed of value change on mouse drag | | keyStep | Number | = step * 10 | Step for keyboard interaction | | keyStepSlow | Number | = step | Slow step for keyboard interaction | | keyStepFast | Number | = step * 100 | Fast step for keyboard interaction | | decimals | Number | 0 | Number of decimals | | format | Function | undefined | Function to format value | | parse | Function | undefined | Function to parse formatted string back to value | | horizontal | Boolean | true | Change value by dragging horizontally | | vertical | Boolean | false | Change value by dragging vertically | | circular | Boolean | false | Enable circular range (good for angles, hours, ...) | | cursor | String | undefined | Individual cursor | | class | String | undefined | Custom component class name | | mainStyle | String | undefined | Custom inline style for general appearance | | focusStyle | String | undefined | Custom inline style when focussed | | draggingStyle | String | undefined | Custom inline style when dragging | | editingStyle | String | undefined | Custom inline style when editing | | fastStyle | String | undefined | Custom inline style for fast mode | | slowStyle | String | undefined | Custom inline style for slow mode | | options | Object | {} | Set any of the above props through this object |

Prop options

If you have many number spinners that should have the same props you might want to use the options object. This sets all of the given props to the respective value.

The props in the options object are applied when mounting the component. So, changing the options later won't update the props of the number spinner. Plus, the props in the options object will not be modified by the number spinner component. So, value should typically not be part of the options.

Example:

<script>
  import NumberSpinner from "svelte-number-spinner";

  let value1 = 50;
  let value2 = 10;
  let options = {horizontal:false, vertical:true}
</script>

<NumberSpinner bind:value={value1} min=0 max=100 {options} />
<NumberSpinner bind:value={value2} min=-30 max=30 {options} />

Steps and speed

There are several props that give you control about how you can interact with the value of the number spinner.

By default, dragging the mouse 1 pixel will increase/decrease the value by step. This is usualy quite good. But if have small ranges compared to step (e.g. a range from 0 to 10 with step 1) it's a bit to sensitive to control. In this case set speed to a smaller number, e.g. 0.1.

With keyboard interaction pressing an arrow key increases/decreases the value by 10*step. In slow mode (holding down Alt) default is one step per key stroke and in fast mode (Alt + Shift) it's 100*step. You can change these steps with the props keyStep, keyStepSlow and keyStepFast.

Formatting numbers

Numbers are displayed as integer values by default. Internally they are handled with the given precision.

Use the prop decimals to display floating point numbers.

Advanced formatting using format and parse

With the number spinner component you can only control numbers. But you can format this number in any possible way giving a callback function for the prop format. In most cases you should also give a reverse function that parses the string and converts it back to the correct number. This is necessary because in edit mode people will probably enter the number as they see it.

In this example the value e.g. 100 is formatted to "$ 100" using the function addDollar(val) for formatting and removeDollar(str) for parsing it back to a simple number. In fact it returns a string but parseFloat() is done in the number spinner component so you don't have to bother about that.

<script>
  let value = 100;

  function addDollar(val) {
    return "$ " + val;
  }
  function removeDollar(str) {
    return str.replace("$", "").trim();
  }
</script>

<NumberSpinner bind:value={value} format={addDollar} parse={removeDollar}/>

Using format and parse to implement non-linear

I found that these two functions could also be used to implement non-linear ranges like exponential/logarithmic scales:

<NumberSpinner bind:value={value} step={0.01} 
  format={val => Math.pow(10, val).toFixed(1)} 
  parse={val => Math.log10(val)}
  />

Styling

Styling with custom class name

You can style the component by overriding the default styles by giving a custom class name. If you give your own class name all default styles are removed. So, best would be to take the default styles below, put it in your global css, rename the class and remove and change stuff.

It's recomended to keep the order for :focus and .fast/.slow selectors. Default styles are:

 .default {
    display: inline-block;
    box-sizing: border-box;
    font-variant-numeric: tabular-nums;
    background-color: white;
    color: black;
    width: 4em;
    height: 1.6em;
    margin: 0px;
    padding: 0.25em;
    border: 0.075em solid #0004;
    border-radius: 0.15em;
    text-align: right;
    vertical-align: baseline;
    cursor: ew-resize;
  }

  .default:focus {
    border: 0.075em solid #06f;
    outline: none; /* removes the standard focus border */
  }

  .default.fast {
    border-top-width: 0.15em;
    padding-top: 0.175em;
  }

  .default.slow {
    border-bottom-width: 0.15em;
    padding-bottom: 0.175em;
  }

  .default.dragging {
    border-color: #04c;
  }

  .default.editing {
    cursor: initial;
  }

Styling with props

If you want to replace just a few of the styles or add some more without removing the default style, it might be easier for you to use the props mainStyle, focusStyle, fastStyle, slowStyle, draggingStyle and editingStyle.

For each of them you can give a style string like "width:80px; padding-right:10px". In the example below only the font color for fast and slow mode are changed:

<script>
  import NumberSpinner from "svelte-number-spinner";
</script>

<NumberSpinner fastStyle="color:orange" slowStyle="color:purple" />

Events

| Event Name | Callback | Description | |------------|---------------------|-------------------------------------------------------------------------------------| | input | (ev) => {ev.detail} | Fires when value changes. ev.detail gives the actual value | | change | (ev) => {ev.detail} | Fires when value changes, won't fire while typing. ev.detail gives the actual value | | dragstart | (ev) => {} | Fires when dragging starts | | dragend | (ev) => {} | Fires when dragging ends | | editstart | (ev) => {} | Fires when edit mode is started | | editend | (ev) => {} | Fires when edit mode is ended | | focus | (ev) => {} | Fires when the number spinner gets the focus | | blur | (ev) => {} | Fires when the number spinner loses the focus | | keydown | (ev) => {} | Original keydown event | | keypress | (ev) => {} | Original keypress event | | keyup | (ev) => {} | Original keyup event |

<script>
  import NumberSpinner from "svelte-number-spinner";

  function handleInput(ev) {
    console.log("Value send by input event:", ev.detail);    
  }

  function handleChange(ev) {
    console.log("Value send by change event:", ev.detail);    
  }
</script>

<NumberSpinner on:input="handleInput" on:change="handleChange" />

In most cases you will probably use bind:value to react to changes of the value. This is more or less the same as listening to the change event. Use the input event if you need to get the changes while the user is typing.

Develop

npm run dev

This will build the component and start a livereload server for the example.