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

react-attached-properties

v0.0.4

Published

A React pattern that can be applied to elements that are in a Container-/-Content relationship to attach information to nested elements that is needed and understood by the container.

Downloads

10

Readme

react-attached-properties: A React Pattern

AttachedProperties is a pattern that can be applied to elements that are in a Container-/-Content relationship to attach information to nested elements that is needed and understood by the container; the pattern's core idea is that it directly associates the information with the nested element, in a readable and self-documenting way, and without the need to write excessive markup.

The pattern can help to reduce the need for wrapper components that would otherwise be necessairy to convey the information in a more conventional approach.

It is inspired by the mechanism of the same name that is available in all XAML-based user-interface technologies like WPF and Silverlight. View the examples below to see how it looks in jsx code.

The react-attached-properties library provides utility functions for creating and retrieving attached properties, provides a mechanism to avoid property name clashes, and a mechanism to clear attached properties (which is needed lest some child component propagates those properties unwittingly to its own children); but this library is by no means a prerequisite for using the pattern: You can apply AttachedProperties in any vanilla React project with just a few lines of code without needing to add react-attached-properties to your dependencies. Using this library however allows you to reduce boiler-plate code, offers a uniform way to define and retrieve attached properties, and spares you the hassle to deal with obvious (and not-so-obvious) pitfalls.

how it looks

Solved problem: provide row and column placement of elements in a Grid component

<Grid rows={3} columns={3}>
    <Red {...Grid.row(3)} {...Grid.column(2)} />
    <Blue {...Grid.row(1)} {...Grid.column(1)} />
    <Green {...Grid.row(2)} {...Grid.column(3)} />
</Grid>

Solved problem: selectively add dropdown closing behavior to content elements in a generic Dropdown component

<DropdownButton>
    <p>
        It was a dark and stormy night...
    </p>
    <FancyBorder>
        <Button>
            Open some flyout
        </Button>
        <Button {...DropdownButton.closeOnClick()}>
            Option #Foo
        </Button>
        <Button {...DropdownButton.closeOnClick()}>
            Option #Bar
        </Button>
        <Button>
            Show more...
        </Button>
    </FancyBorder>
</DropdownButton>

Solved problem: earmark content elements to be placed in the header and footer areas of a Modal component, instead of in the body

<Modal>
    <h2 {...Modal.isHeader()}>
        You have unsaved changes
    </h2>
    <p>
        You are leaving the current view.
        Please decide if you want to save your changes now, discard them,
        or cancel the operation and stay on the current view.
    </p>
    <Button {...Modal.isFooter()}>
        Save changes and leave view.
    </Button>
    <Button {...Modal.isFooter()}>
        Discard changes and leave view.
    </Button>
    <Button {...Modal.isFooter()}>
        Cancel and stay on view
    </Button>
</Modal>

implementation

  • (1.) Import the AttachedProperty class at the top of your component.
  • (2.) Declare and create a new attached property constant for each property you want to support.
  • (3.) Add property setters to your component for each property you want to support.
// 1.
import { AttachedProperty } from 'react-attached-properties';
import React from 'react';

// 2.
const attachedRow = new AttachedProperty('row');
const attachedColumn = new AttachedProperty('column');

const MyGrid = (props) => {
    // ...
};

// 3.
attachedRow.createSetter(MyGrid);
attachedColumn.createSetter(MyGrid);

export { MyGrid };
  • (4.) When your component is rendered: iterate over children (either shallow i.e. you inspect only the immediate children, or deep i.e. you inspect recursively children of children, depending on your use case, see examples for both variants).
  • (5.) For each inspected child: retrieve each attached property value you want to support.
  • (6.) Process each child according to the retrieved values; remember that strings can be among the children; they don't have properties and cannot be cloned. We can check for strings with React.isValidElement. If you have retrieved an attached property value you do not need to check for string because only valid react elements (i.e. not a string) can have properties.
  • (7.) Clear any attached property value
<div className="my-grid">
{
    // 4.
    React.Children.map(children, (child) => {
        // 5.
        const row = attachedRow.from(child) || 0;
        const column = attachedColumn.from(child) || 0;

        // 6.
        const placement = `cell-${column}-${row}`;

        return (
            <div className={placement}>
            {
                // 6.
                React.isValidElement(child) ?
                    // 7.
                    React.cloneElement(child, {...attachedRow.clear(), ...attachedColumn.clear()}) : child
            }
            </div>
        );
    })
}
</div>

notes on syntax

The spread operator syntax is well supported by jsx although it might be unfamiliar if you haven't seen it used before. The rest of the pattern is just a plain old dot notation function call to a function that happens to be exposed on the component itself. The object that is returned has a property with a guaranteed unique property name. With attached properties that don't require an input value you could therefore separate the function call from the property spread like this:

const isHeader = Modal.isHeader();
const isFooter = Modal.isFooter();

<h2 {...isHeader} />
<p>Lorem Ipsum</P>
<Button {...isFooter} />
<Button {...isFooter} />
<Button {...isFooter} />

how to conditionally set an attached property

To conditionally set a property you can use the following syntax:

<Button {...placeButtonsInFooter ? Modal.isFooter() : null} />