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

@blackpixel/framer-focusengine

v1.4.0

Published

Simulate the grid focus behavior seen on streaming media players like Apple TV and Roku.

Downloads

10

Readme

FocusEngine Framer Module

license PRs Welcome Maintenance

The FocusEngine module allows you to simulate the grid focus behavior seen on streaming media players like Apple TV and Roku. Use the keyboard, RemoteLayer, or another mechanism to direct focus around your prototype’s canvas.

Once initialized, any visible layer can be brought into focus, even if it’s off screen. This permits the activation of off-screen menus. Visual appearance of focused elements can be customized.

Installation

NPM Installation

$ cd /your/framer/project
$ npm i @blackpixel/framer-focusengine

Manual installation

Copy or save the FocusEngine.coffee file into your project's modules folder.

Adding It to Your Project

In your Framer project add the following:

# If you manually installed
fe = require "FocusEngine"
# else
fe = require "@blackpixel/framer-focusengine"

API

Customize focused and unfocused states

fe.focusStyle.scale = <number>
fe.focusStyle.shadowX = <number>
fe.focusStyle.shadowY = <number>
fe.focusStyle.shadowColor = <string> (hex or rgba)
fe.focusStyle.shadowBlur = <number>
fe.focusStyle.shadowSpread = <number>

fe.unfocusStyle.shadowX = <number>
fe.unfocusStyle.shadowY = <number>
fe.unfocusStyle.shadowColor = <string> (hex or rgba)
fe.unfocusStyle.shadowBlur = <number>
fe.unfocusStyle.shadowSpread = <number>

(Unfocused scale is always assumed to be the layer’s original scale. This need not be 1. You may get better visual results by drawing your layer slightly larger than needed and setting its initial scale to something less than 1.)

Customize state switch duration

fe.time = <number>

Collect layers that will participate into an array

myFocusableLayers = [layerA, layerB, layerC]

Initialize the engine with your array

fe.initialize(myFocusableLayers)

Add a layer created post-initialization

fe.addLayer(layerD)

Optionally attach changeFocus() to keyboard events

document.addEventListener "keydown", (event) ->
	keyCode = event.which
	switch keyCode
		when 13 then fe.changeFocus("select")
		when 37 then fe.changeFocus("left")
		when 38 then fe.changeFocus("up")
		when 39 then fe.changeFocus("right")
		when 40 then fe.changeFocus("down")
		else null

Place initial focus

fe.placeFocus(layerA)

focusPrevious() is available to use in conjunction with FlowComponent's showPrevious()

fe.focusPrevious()

(Note that focus cannot be placed on a layer whose visibility, or whose ancestor’s visibility, is false. You may need to delay calling focusPrevious() until the FlowComponent’s transition is ended, perhaps by using .onTransitionEnd.)

Layers can trigger behavior upon receiving or losing focus, or being selected

layerA.on "focus", ->
layerA.on "unfocus", ->
layerA.on "selected", ->

Shortcuts are also available:

layerA.onFocus ->
layerA.onUnfocus ->
layerA.onSelected ->

Integration with RemoteLayer

RemoteLayer = require "RemoteLayer"
myRemote = new RemoteLayer
	clickAction: -> fe.changeFocus("select")
	swipeUpAction: -> fe.changeFocus("up")
	swipeDownAction: -> fe.changeFocus("down")
	swipeLeftAction: -> fe.changeFocus("left")
	swipeRightAction: -> fe.changeFocus("right")

Check the currently focused layer

print fe.focus

Check whether a layer has focus

print layerA.focus

Overriding focus logic

Sometimes you will want to change focus in a way that doesn't make exact geometric sense. For example, when switching from a large header row to a smaller secondary row, you may prefer the first cell in the secondary row receive focus. Or, you may want to provide a way for focus to "loop around" at a row's end. These kinds of functions are possible through overrides.

Set a layer's overrides using the overrides object:

layerA.overrides =
	up: <layer>
	down: <layer>
	left: <layer>
	right: <layer>

It is not necessary to set all four overrides; but only for those directions which require custom behavior. Now, shifting focus from layerA will always land on the direction-specified target -- no matter what FocusEngine thinks should happen.

Obviously, you can create very counterintuitive behaviors this way. Use with care!

If a layer has custom overrides, or has been initialized with FocusEngine, you may check any of its current overrides:

print layerA.overrides?.up

The ? permits the check to fail gracefully on layers which have no overrides.

Enable debug mode to log focus changes

fe.debug = true

Example project

Download the example to try it for yourself.

Known issues

Attempting to perform a placeFocus() call as FocusEngine is changing its own focus will fail. (The call is discarded.) If you need to override FocusEngine's logic, use the overrides feature or add a slight delay to ensure the call is respected.

layerA.on "unfocus", ->
	Utils.delay 0.1, ->
		fe.placeFocus(layerB)

Website: blackpixel.com  ·  GitHub: @bpxl-labs  ·  Twitter: @blackpixel  ·  Medium: @bpxl-craft