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

@volusion/element-proptypes

v1.5.2

Published

Wrapper around React PropTypes for adding metadata to the props

Downloads

5

Readme

Element PropTypes

This package creates a React PropTypes replacement that adds metadata to the validators, and in that way, we can do cool things like automatic form generation of block configurations and validations.

Table of Contents

Using the PropTypes

import { ElementPropTypes } from '@volusion/element-proptypes';

let props = {
  // You can declare that a prop is a specific JS primitive. By default, these
  // are all optional.
  optionalArray: ElementPropTypes.array,
  optionalBool: ElementPropTypes.bool,
  optionalNumber: ElementPropTypes.number,
  optionalString: ElementPropTypes.string,
  optionalColor: ElementPropTypes.color,
  optionalProduct: ElementPropTypes.product,
  optionalCategory: ElementPropTypes.category,
  optionalCategory: ElementPropTypes.sectionHeader,
  optionalCategory: ElementPropTypes.subHeader,
  optionalIcon: ElementPropTypes.icon,
  optionalImage: ElementPropTypes.image,
  optionalSlider: ElementPropTypes.slider,
  optionalMedia: ElementPropTypes.media,
  optionalEditorFull: ElementPropTypes.editorFull,
  optionalEditorMinimal: ElementPropTypes.editorMinimal,
  optionalReadOnly: ElementPropTypes.readOnly,

  // You can make them required too
  requiredArray: ElementPropTypes.array,
  requiredBool: ElementPropTypes.bool,
  requiredNumber: ElementPropTypes.number,
  requiredString: ElementPropTypes.string,
  requiredColor: ElementPropTypes.color,
  requiredProduct: ElementPropTypes.product,
  requiredCategory: ElementPropTypes.category,
  requiredCategory: ElementPropTypes.sectionHeader,
  requiredCategory: ElementPropTypes.subHeader,
  requiredIcon: ElementPropTypes.icon,
  requiredImage: ElementPropTypes.image,
  requiredSlider: ElementPropTypes.slider,
  requiredMedia: ElementPropTypes.media,
  requiredEditorFull: ElementPropTypes.editorFull,
  requiredEditorMinimal: ElementPropTypes.editorMinimal,

  // You can ensure that your prop is limited to specific values by treating
  // it as an enum.
  optionalEnum: ElementPropTypes.oneOf(['News', 'Photos']),

  // Or a required one
  requiredEnum: ElementPropTypes.oneOf(['News', 'Photos']).isRequired,

  // An array of a certain type
  optionalArrayOf: ElementPropTypes.arrayOf(PropTypes.number),

  // A required array of a certain type
  requiredArrayOf: ElementPropTypes.arrayOf(PropTypes.number).isRequired,

  // An object with property values of a certain type
  optionalObjectOf: ElementPropTypes.objectOf(PropTypes.number),

  // A required object with property values of a certain type
  requiredObjectOf: ElementPropTypes.objectOf(PropTypes.number).isRequired,

  // An object taking on a particular shape
  optionalObjectWithShape: ElementPropTypes.shape({
    color: ElementPropTypes.color,
    fontFamily: ElementPropTypes.string,
    fontSize: ElementPropTypes.number
  }),

  // A required object taking on a particular shape
  RequiredObjectWithShape: ElementPropTypes.shape({
    color: ElementPropTypes.color,
    fontFamily: ElementPropTypes.string,
    fontSize: ElementPropTypes.number
  }).isRequired,

  // An embeddable prop.
  Embeddable: ElementPropTypes.embeddable({
    embedType: ElementPropTypes.string,
  })
}

The previous props will generate a schema object like this when using the function extractMetadata

import { extractMetadata } from 'element-proptypes';

const meta = extractMetadata(props);

//console.log(meta)
{
  'Optional Array': {
      type: 'array'
  },
  'Optional Bool': {
      type: 'bool'
  },
  'Optional Number': {
      type: 'number'
  },
  'Optional String': {
      type: 'string'
  },
  'Optional Color': {
      type: 'color'
  },
  'Optional Product': {
      type: 'product'
  },
  'Optional Category': {
      type: 'category'
  },
  'Optional Section Header': {
      type: 'sectionHeader'
  },
  'Optional Sub Header': {
      type: 'subHeader'
  },
  'Optional Media': {
      type: 'media'
  },
  'Optional Editor Full': {
      type: 'editorFull'
  },
  'Optional Editor Minimal': {
      type: 'editorMinimal'
  },
  'Optional Read Only': {
      type: 'readOnly'
  },
  'Required Array': {
      type: 'array',
      isRequired: true
  },
  'Required Bool': {
      type: 'bool',
      isRequired: true
  },
  'Required Number': {
      type: 'number',
      isRequired: true
  },
  'Required String': {
      type: 'string',
      isRequired: true
  },
  'Required Color': {
      type: 'color',
      isRequired: true
  },
  'Required Product': {
      type: 'product',
      isRequired: true
  },
  'Required Category': {
      type: 'category',
      isRequired: true
  },
  'Required Section Header': {
      type: 'sectionHeader',
      isRequired: true
  },
  'Required Sub Header': {
      type: 'subHeader',
      isRequired: true
  },
  'Required Media': {
      type: 'media',
      isRequired: true
  },
  'Required Editor Full': {
      type: 'editorFull',
      isRequired: true
  },
  'Required Editor Minimal': {
      type: 'editorMinimal',
      isRequired: true
  },
  'Optional Enum': {
      type: 'oneOf',
      values: ['News', 'Photos']
  },
  'Required Enum': {
      type: 'oneOf',
      values: ['News', 'Photos'],
      isRequired: true
  },
  'Optional Array Of': {
      type: 'arrayOf',
      argType: {
          type: 'number'
      }
  },
  'Required Array Of': {
      type: 'arrayOf',
      argType: {
          type: 'number'
      },
      isRequired: true
  },
  'Optional Object Of': {
      type: 'objectOf',
      argType: {
          type: 'number'
      }
  },
  'Optional Object Of': {
      type: 'objectOf',
      argType: {
          type: 'number'
      }
  },
  'Required Object Of': {
      type: 'objectOf',
      argType: {
          type: 'number'
      },
      isRequired: true
  },
  'Object With Shape': {
    objMeta: {
     'Color': {
        type: 'string'
      },
      'Font Size': {
        type: 'number'
      }
    }
  },
  'Required Object With Shape': {
    objMeta: {
     'Color': {
        type: 'string'
      },
      'Font Size': {
        type: 'number'
      }
    },
    isRequired: true
  },
  'Optional Icon': {
    objMeta: {
        'Icon Name': {
            propName: 'iconName',
            type: 'string'
        },
        'Icon Prefix': {
            propName: 'iconPrefix',
            type: 'string'
        },
        'Default Filter': {
            propName: 'defaultFilter',
            type: 'string'
        },
    }
  },
  'Required Image': {
    objMeta: {
        'Icon Name': {
            propName: 'iconName',
            type: 'string'
        },
        'Icon Prefix': {
            propName: 'iconPrefix',
            type: 'string'
        },
        'Default Filter': {
            propName: 'defaultFilter',
            type: 'string'
        },
    }
    isRequired: true
  },
  'Optional Image': {
    objMeta: {
        'Uri Base': {
            propName: 'uriBase',
            type: 'string'
        },
        'Image Path': {
            propName: 'imagePath',
            type: 'string'
        },
        'Alt Text': {
            propName: 'altText',
            type: 'string'
        },
        Width: {
            propName: 'width',
            type: 'number'
        },
        Height: {
            propName: 'height',
            type: 'number'
        }
    }
  },
  'Required Image': {
    objMeta: {
        'Uri Base': {
            propName: 'uriBase',
            type: 'string'
        },
        'Image Path': {
            propName: 'imagePath',
            type: 'string'
        },
        'Alt Text': {
            propName: 'altText',
            type: 'string'
        },
        Width: {
            propName: 'width',
            type: 'number'
        },
        Height: {
            propName: 'height',
            type: 'number'
        }
    },
    isRequired: true
  },
  'Optional Slider': {
    objMeta: {
        'Label Prefix': {
            propName: 'labelPrefix',
            type: 'string'
        },
        'Label Step Size': {
            propName: 'labelStepSize',
            type: 'number'
        },
        'Label Suffix': {
            propName: 'labelSuffix',
            type: 'string'
        },
        Min: {
            propName: 'min',
            type: 'number'
        },
        Max: {
            propName: 'max',
            type: 'number'
        },
        'Step Size': {
            propName: 'stepSize',
            type: 'number'
        },
        'Selected Value': {
            propName: 'selectedValue',
            type: 'number'
        },
        'Vertical': {
            propName: 'vertical',
            type: 'bool'
        }
    }
  },
  'Required Slider': {
    objMeta: {
        'Label Prefix': {
            propName: 'labelPrefix',
            type: 'string'
        },
        'Label Step Size': {
            propName: 'labelStepSize',
            type: 'number'
        },
        'Label Suffix': {
            propName: 'labelSuffix',
            type: 'string'
        },
        Min: {
            propName: 'min',
            type: 'number'
        },
        Max: {
            propName: 'max',
            type: 'number'
        },
        'Step Size': {
            propName: 'stepSize',
            type: 'number'
        },
        'Selected Value': {
            propName: 'selectedValue',
            type: 'number'
        },
        'Vertical': {
            propName: 'vertical',
            type: 'bool'
        }
    },
    isRequired: true
  },
  'Embeddable': {
    objMeta: {
     'Embed Type': {
        type: 'string'
      },
    }
  },

}

Developing

If you are using a non-npmjs registry, then you will need to run npm config set registry https://registry.npmjs.org

npm install
npm run build

Run npm run build every time you want to compile and transpile your code.

Adding new dependencies

mv ~/.npmrc ~/.npmrc.bak # If your default reposity is not npmjs.com
npm install <dependency>
mv ~/.npmrc.bak ~/.npmrc # If your default reposity is not npmjs.com

Using the product proptype

The product proptype will launch a product picker when editing a block config in Site Designer, and store the product id when a product from the store is selected. When using the product proptype within a block, you will need to add the prop to the block configSpec

configSpec = {
    myProduct: ElementPropTypes.product
}

Using the category proptype

The category proptype will launch a category picker when editing a block config in Site Designer, and store the product id when a category from the store is selected. When using the category proptype within a block, you will need to add the prop to the block configSpec

configSpec = {
    myCategory: ElementPropTypes.category
}

Using the sectionHeader proptype

The sectionHeader proptype is not editable in Site Designer - it is included so that it can be used to format the contents of the block config edit form in Site Designer. When using the sectionHeader proptype within a block, you will need to add the prop to the block configSpec

configSpec = {
    mySectionHeader: ElementPropTypes.sectionHeader
}

You will also need to add a default value for the mySectionHeader property on the defaultProps of the object

defaultProps = {
    mySectionHeader = "The header text for this section of the block config editing form"
}

Using the subHeader proptype

The subHeader proptype is not editable in Site Designer - it is included so that there can be a header within the props below a collapsible sectionHeader. When using the subHeader proptype within a block, you will need to add the prop to the block configSpec

configSpec = {
    mySubHeader: ElementPropTypes.subHeader
}

You will also need to add a default value for the mySubHeader property on the defaultProps of the object

defaultProps = {
    mySubHeader = "The header text for this section of the block config editing form"
}

Using editor proptype

When using the editorFull and editorMinimal proptypes within a block, you will first need to add the prop to the block configSpec

configSpec = {
    myEditableText: ElementPropTypes.editorFull.isRequired
}

You will also need to add a default value for the myEditableText property on the defaultProps of the object

defaultProps = {
    myEditableText = "<p>Some text to edit</p>"
}

Lastly, in order to inject the HTML into your component you will need to pass it in using dangerouslySetInnerHTML

<div dangerouslySetInnerHTML={{ __html: this.props.myEditableText  }} />

Using the embeddable proptype

Currently, only iframe is supported as an embeddable. You must specify a block config like this one:

configSpec = {
    iFrameConfig: ElementPropTypes.embeddable({
        embedType: ElementPropTypes.string,
        url: ElementPropTypes.string,
        height: ElementPropTypes.number
    })
};

And for the default props, use something like this:

defaultProps = {
    iFrameConfig: {
        embedType: 'iframe',
        url: 'https://www.site.com',
        height: 800
    }
}

url is the site you want to load in the embedded iframe, and height is the number representing the height of the iframe.

Using the icon proptype

The icon propType will launch an icon picker in Site Designer when editing the block config.

Site Designer will populate the icon like this when an icon has been selected:

iconConfig: {
    iconName: 'cart-shopping',
    iconPrefix: 'fa',
    defaultFilter: 'shopping',
}

You can use ElementPropTypes.icon.default in your default props, which will return this:

{
    iconName: '',
    iconPrefix: '',
    defaultFilter: '',
}

And it would be used in default props like this:

defaultProps = {
    iconConfig: ElementPropTypes.icon.default
}

Using the image proptype

The image propType will launch an image picker in Site Designer when editing the block config.

Site Designer will populate the image like this when an image has been selected:

imageConfig: {
    uriBase: 'https://www.site.com',
    imagePath: 'path/to/image',
    altText: 'alt text for the image',
    width: 800,
    height: 600
}

You can use ElementPropTypes.image.default in your default props, which will return this:

{
    uriBase: '',
    imagePath: '',
    altText: '',
    width: 0,
    height: 0
}

And it would be used in default props like this:

defaultProps = {
    imageConfig: ElementPropTypes.image.default
}

Using the slider proptype

The slider propType will display an horizontal slider for picking a numeric value in Site Designer when editing the block config.

Site Designer will populate the slider like this when a value has been selected. Note the selectedValue field:

sliderConfig: {
    labelPrefix: "~",
    labelStepSize: 10,
    labelSuffix: " oz",
    min: 50,
    max: 100,
    stepSize: 5,
    selectedValue: 75,
    vertical: false
}

You can use ElementPropTypes.slider.default in your default props, which will return this:

{
    min: 0,
    max: 10,
    stepSize: 1,
    selectedValue: 0
}

And it would be used in default props like this:

defaultProps = {
    sliderConfig: ElementPropTypes.slider.default
}

The labelPrefix and labelSuffix props can be used to specify a string value that should appear before and/or after the number in your labels.

The labelStepSize prop allows you to control label step size independently of slider step size. If labelStepSize is not set, the stepSize value will be used.

The vertical prop allows you to orient the slider in a vertical direction rather than the default of horizontal.

Versioning

We use SemVer for versioning. For the versions available, see the tags on this repository.

Deployment

You do not need to manually update the package version, the following command does it for you. It uses npm np.

npm run release

Contributing

We're very excited that you're interested in contributing! At present, we are not accepting contributions for this repo, but that might change in the future. However, we are very interested in your suggestions for new PropTypes that you want to have in this package. You can make your suggestions by opening an issue. We do already have a Code of Conduct in place.

Code of Conduct

Our Code of Conduct, by way of the Contributor Covenant, can be found here.

License

© 2018 onward by Volusion MIT License