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

@mvarble/viewport-utilities

v1.0.12

Published

A bunch of utilities for interfacing with the viewport.js API

Downloads

5

Readme

viewport-utilities

A bunch of utilities for interfacing with the viewport.js API.

API

relativeMousePosition

[x, y] = relativeMousePosition(event)

This function calculates the bounding rectangle of the event target and calculates the mouse position relative to this. If the isDrag attribute from createDrag is present in the event, event.isDrag.target is used instead of event.target.

singleClick

singleclick$ = mousedown$.compose(singleClick)

This is a xstream operator that takes a stream of mousedown events and returns a stream of click events that happened within 50ms and 3 pixels of each mousedown. The intention of this is to separate usual click events from those returned by createDrag.

createDrag

drag$ = mousedown$.compose(createDrag)

This is a xstream operator that takes a stream of mousedown events and returns a stream of streams that match the following diagram.

mousedown: |-----x-------------------x------------->

        (createDrag)

mousemove: |-x-------x--x-x----x------------------->
mouseup:   |----------------o-------------o-------->

output:    |-----x-------------------x------------->
                   \                   \
                    --x--x-x-o-|        -----|

Note that every stream starts with a mousedown event, and ends with the mouseup event. The streams will always output mousemove and mouseup events from the document, not the DOM element that the mousedown events corresponded to. However, each of these events will have an isDrag attribute which will point to the reference of the original mousedown event. Also, these streams are not provided as arguments of the operator; they are just in the diagram for explanation.

Note in the example above, we have that the output streams will be empty if no mousemove occurs between 'mousedown' and 'mouseup' events. The rationale behind this is that:

  1. Clicks are not drags
  2. Every nonempty drag starts with a 'mousemove'.
  3. Every nonempty drag ends with a 'mouseup'.

renderBox

renderBox(context, frame, options)

This function will use the provided context to perform an imperative render to the canvas with said context. The render will display a rectangle with vertices having coordinates [-1, -1] and [1, 1] with respect to frame. By providing an object options with options.fill and options.stroke, this will decide whether to do the respective operations in the render. The options object is optional, and it is assumed of its attributes both are true.

withWindow

NewComponent = withWindow(FrameComponent, options)

By providing a component FrameComponent that is managing a frame using the withState API, this will return a new component which wraps the oldState into an object of the form:

{
  type: 'root',
  width: w,
  height: h,
  children: [
    { type: 'window', worldMatrix: [...] },
    oldState
  ],
}

This object will be such that its first child frame has a world matrix such that [-1, -1] and [1, 1] are the bottom-left and top-right coordinates of the canvas, respectively. Moreover, this component will merge reducers into the state stream of FrameComponent that trigger resize calculations and allow for navigating its frame within the window.

The returned NewComponent will be such that there is a new source, a stream of desired dimensions [w, h] of the component. The resize will be calculated such that the child frame will be scaled uniformly in both dimensions with a scale that requires the least amount of distortion in accomodating the new dimension ratio w/h.

The options object sets the keys of the sources/sinks NewComponent necessarily uses. Its keys are the following:

  • state: This is the desired key of the withState source/sinks. By default, it is 'state'.
  • dimensions: This is the desired source key of the stream of desired dimensions. By default, it is 'dimensions'.
  • frameSource: This is the desired source key of the mounted FrameSource instance is required for delivering mouse intent for panning/resizing the child frame. By default, it is 'frameSource'.

resizeFrame

newFrame = resizeFrame(frame, width, height)

This will take a state frame of the form of withWindow and return newFrame, accomodated to the new dimensions width and height. This is used in the reducer of the component returned by said wrapper.

changeZoom

newFrame = changeZoom(event, frame)

This will take a wheel event event and a state frame of the form of withWindow and return newFrame, in which frame.children[1] has been scaled according to the direction of the wheel move. This is used in the reducer of the component returned by said wrapper.

parentDims

dimensions$ = element$.compose(parentDims)

This is a xstream operator that takes a stream of DOM elements and returns a stream of [offsetWidth, offsetHeight] dimensions corresponding to the parent of the element in the stream. The initial dimensions are returned with the delivery of the element of the stream element$; thereafter, window resize events will pipe to this stream only when the dimensions have changed. To this end, you may think of this as a flattened stream of streams of the form

|---[initialWidth, initialHeight]----[newWidth, newHeight]--[newWidth, newHeight]--->

Warning. If you declare the canvas size dependent on this stream (and make your imperative render function resize accordingly) and the parent does not have fixed sizing, you may cause an indefinite loop of

parent dimensions change → parentDims update → canvas dimensions change → parent dimensions change → ...

so tread lightly with setting the parent's dimensions in some fixed way (say, with CSS vw and vh).