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

arkade

v1.0.0

Published

A toolkit to supercharge your ability to write great React apps.

Downloads

31

Readme

Arkade

Arkade (ak) is the tacklebox to React's fishing pole.

React isn't "batteries included", so Arkade is a pack of shiny new batteries.

Arkade is a collection of smallish useful components, each designed to not get-in-the-way of how you compose your apps.

Arkade includes...

  • arkade/common Reliable common components like <Icon>, <ProgressBar>, and <TabPanel>.
  • arkade/errors 3 custom error types for better DX
  • arkade/forms A suite of form components to make input a breeze
  • arkade/hooks 3 hooks: useModel, useSession, and useStorage.
  • arkade/layouts 3 flex-based layouts: <RowLayout>, <StackLayout>, and <CentralLayout>
  • arkade/media 2 media-related components, <Audio> (audio player with controls) and <CoverVideo> (dynamically sizes a video for use as a background)
  • arkade/tools 7 components for better DX and/or which have deeper functionality (such as <ScrollWatcher> and <ErrorBoundary>).
  • arkade/utils small, useful utility functions across 9 categories (browser-, download-, form-, object-, react-, social-, storage-, text-, and type-utils)
  • ...and an optional sass-based UI theme generated based on a color scheme you provide, including utility classes, stylized HTML defaults, animations, and automatic flavor classes for buttons, text, borders, and backgrounds.

Installation & setup

npm install arkade

Arkade is offered in non-transpiled, native ES6 module format, containing JSX and SCSS markup.

Being a React toolkit, Arkade requires a sibling dependency react of at least version 16.0.

To use the icons, you'll need to make sure FontAwesome CSS is included in your app bundle (or better yet, loaded on the page via a CDN).

Arkade also includes SASS, which should be transpiled to CSS at some point by your application (usually during your build step).

Crash course

Here are some example of how Arkade can get things done. Try them out!

Simple show/hide modal toggle (persists to session!)

import React from 'react'

import { useSession } from 'arkade/hooks'
import { ModalWrapper, ModalBody } from 'arkade/tools'

export const MyModalTrigger = () => {
	const [isModalShown, setIsModalShown] = useSession('myModalVisibility', false);
	
	const showModal = () => setIsModalShown(true)
	const hideModal = () => setIsModalShown(false)

	return (
		<section>
			<button className="btn btn-primary" onClick={showModal}>
				Open modal
			</button>
		
			<ModalWrapper visible={isModalShown}>
				<ModalBody onClose={hideModal}>
					Modal Content Baby
				</ModalBody>
			</ModalWrapper>
		</section>
	)
}

A sleek background video header

import React from 'react';

import { Icon } from 'arkade/common';
import { CoverVideo } from 'arkade/media';
import { CentralLayout } from 'arkade/layouts';

export const MyComponent = ({ someProp }) => {
    const videoSources = [
        { src: '/assets/splash-video.mp4', type: 'video/mp4' },
        { src: '/assets/splash-video.ogv', type: 'video/ogg' },
        { src: '/assets/splash-video.webm', type: 'video/webm' }
    ];

    return (
        <CoverVideo sources={videoSources} aspectRatio={1.66}>
            <Icon fa="plane" style={{ fontSize: '3em' }} />
            <h1>Plan your dream vacation.</h1>
            <button>Let’s Go!</button>
        </Cover>
    );
}

A simple form with validation

import React, { useState } from 'react';

import { Fieldset } from 'arkade/forms';
import { AppError, ValidationError } from 'arkade/errors';
import { isNonEmptyString } from 'arkade/utils/type-utils';

const isValidMessage = (givenMessage, formModel) => {
	if (!isNonEmptyString(givenMessage) || givenMessage.length < 10)
		throw new ValidationError('Message must a string at least 10 characters long.', givenMessage);
	if (givenMessage.toLowerCase().contains('dallas cowboys'))
		throw new ValidationError('This is an eagles town.', givenMessage);
	if (formModel.email.toLowerCase() === '[email protected]')
		throw new ValidationError(`We don't wanna hear it, Peeves.`, givenMessage);
		
	return true;
}

const isValidEmail = (email) => {
	const EMAIL_PATTERN = /^[^\s@]*@[^\s_@]+[\s]*\.[a-zA-Z]{2,}$/;
	
	if (!isNonEmptyString(givenMessage) || !EMAIL_PATTERN.test(email))
		throw new ValidationError('Please enter a valid email.', email);
		
	return true;
}

export const MyComponent = ({ someProp }) => {
	const [model, setModel] = useState({ message: null, email: null });
	
	const fields = [
		{
			modelKey: 'message',
			label: 'Your Message',
			icon: 'pencil',
			type: 'text',
			validate: isValidMessage
		},
		{
			modelKey: 'email',
			label: 'Your Email',
			type: 'email',
			icon: 'envelope',
			validate: isValidEmail
		}
	];
	
	
	return (
		<CentralLayout>
			<Fieldset
				fields={fields}
				model={model}
				onModelChange={setModel}
			/>
		</CentralLayout>
	);
}

What's In The Box

Components

from arkade/common

  • <ProgressBar />
  • <Icon />
  • <FontAwesomeIcon />
  • <ImageIcon />

from arkade/media

  • <Audio />
  • <CoverVideo />

from arkade/tools

  • <ModalBody />
  • <ModalWrapper />
  • <ErrorBoundary />
  • <Inspector />
  • <Portal />
  • <Specimen />

Errors

Custom error types for better DX

new AppError(message, contextData, ...rest)

  • Attaches .contextData to resulting error

new NetworkError(statusCode, message, ...rest)

  • Attaches .statusCode to resulting error
  • Adds .contextData string combining message and statusCode

new ValidationError(message, invalidGivenValue, ...rest)

  • Attaches .invalidGivenValue to resulting error
  • Adds .contextData string combining message with value

Utils

A few sets of utilities

Exported from arkade/utils/type-utils

  • isDefined (value)
  • isString (value)
  • isNonEmptyString (value)
  • isFunction (value)
  • isArray (value)
  • isNonEmptyArray (value)
  • isNumber (value)
  • isNumberList (value)
  • isNaN (value)
  • isNull (value)
  • isRegex (value)
  • isBoolean (value)
  • isObject (value)
  • isPrimitive (value)

Exported from arkade/utils/text-utils

  • reindent (text)
  • trim (value)
  • splitByFirst (value, splitByChar = '')
  • splitBy (value, splitByChar = '')
  • prettyPrint (content, singleLine = false)
  • lcFirst (text)
  • ucFirst (text)
  • forceCamelCase (value)
  • forceSnakeCase (value)
  • cleanTagList (tagList)
  • stripHtmlTags (html, allowTags = [], keepAttributes = false)

Exported from arkade/utils/object-utils

  • getDeep (object, path, pathSeparator = '.')
  • setDeep (object, path, replacement, pathSeparator = '.')
  • anonymizeObject(data, fields, preserveFields)
  • sortBy (list, accessor)
  • sortObjectKeys (obj)
  • sortObjectArrayValues (obj, sortAccessor)
  • memoize (func, resolver = null)
  • pick (obj = {}, keys = [])
  • getKeys (object)
  • clone (object)
  • mergeDeep (...objects)
  • equals (a, b)
  • unique (array)