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 🙏

© 2025 – Pkg Stats / Ryan Hefner

@k-int/address-plugins

v1.0.1

Published

Collection of React address forms designed for different countries

Downloads

16

Readme

address-plugins

This is a set of React plugins designed to try and make internationalisation of address forms as easy and simple as possible. It was designed to mesh with a backend inspired by the OASIS CIQ TC Standard xAL.

Installation

These are React NPM plugins, and as such, you will need to include it in you project's package.json file. Too get a form up and running is:

"@k-int/address-plugins": "^1.0.0",

To call these plugins in your code, you would then include:

import {pluginGeneric} from '@k-int/address-plugins';

and call <pluginGeneric.addressFields>, say, to use the component AddressFields for this plugin.

Motivation

When researching address forms, we came across the problem that addresses are constructed differently all over the world. The standard mentioned in the link above aims to solve this problem. However in constructing a frontend to match this kind of data model, we realised that this must be a problem that crops up a lot, and so decided to write as standalone code as possible, so that our solution can be reused in other applications.

Data Model

The particular flavour of address model our backend uses comprises of an Address, containing many AddressLines, an AddressLabel string and a CountryCode string, corresponding to an ISO 3166-2 code (Or "generic"). AddressLines contain

  • a value String
  • a type RefdataValue, taking one of the values:
- AdministrativeArea
- Country
- Department
- Thoroughfare
- Locality
- PostalCode
- PostBox
- PostOffice
- PostalCodeOrTown
- Premise

It is heavily recommended that any potential user do some reading of the standard above in order to understand what each of these can mean/be used for.

:warning: This backend setup has an important restriction, in that each address is supposed to be limited to ONE of any given type of AddressLine. The ways in which the various types can be used is expanded on in the standard. :warning:

Dealing with deletion registration

We have built this in so instead of simply omitting a field from a form on deletion, we send the field with a _delete: true flag. This may not exactly match your backend configuration for dealing with this, and so you may need to write your own interpreters for the form's output.

The plugin

Each plugin, say address-plugin-generic or address-plugin-north-america, is named for a particular "sensible" domain sharing an address format. For example the addresses of the US and Canada are similar, up to field names, and so it makes sense to bundle these together. Similarly most of the British Isles share an address format, and so there is a single plugin for those. The definition of sensible is really up to whoever is writing the particular plugin, but a good rule of thumb would be to stick within continents at the highest level, and nations at the lowest level.

A plugin shouldn't have to be smart enough to deal with hundreds of address formats, address-plugin-africa is probably too ambitious of a scope, but should be smart enough to deal with changes within a nation, you don't want 4 plugins address-plugin-foo-north, address-plugin-foo-south, address-plugin-foo-east, address-plugin-foo-west. That should be dealt with internally.

:warning: Note to developers. If you wish to develop a plugin to fit into this set, it is highly recommended that you spend some time looking at an existing plugin to see exactly what you'll have to mirror. :warning:

AddressFields

First and foremost is an AddressFields component, which returns a collection of AddressFieldsComponents, formatted in a react-flexbox-grid layout. These supply regular "field" information per entry for the given country address format, but it is expected that the calling code provides the AddressTextField, allowing for varying Form implementations (final-form etc.).

These fields will tend to stick to the field names as detailed above, so that you can expect a submitted object to look like:

address: {
  premise: "<user input>",
  thoroughfare: "<user input>",
  ...
}

and so on. There are some exceptions to this, which individual plugin READMEs should detail.

Props

AddressField takes 5 props:

  • AddressTextField
  • country
  • name
  • requiredValidator
  • savedAddress

Country In those cases where a single plugin is used for multiple different countries, the country prop will be used to call the correct field labels. For example in address-plugin-north-america passing country="Canada" will result in the AdministrativeArea field being labelled Province, and passing country="USA" will result in AdministrativeArea field being labelled State.

This happens via React-Intl's FormattedMessage component. Wherever a plugin's field names may need to change country by country, the field labels should be called in the following way:

label={<FormattedMessage  id={`ui-address-plugin-north-america.${country}.locality`}  />}

The acceptable inputs for country here should match the outputted listOfSupportedCountries.

When a country is selected, the country field should pre-populate with the chosen country's translated name. If country was explicitly passed in with the savedAddress however, that data will take precedence.

Name name will be prepended to the field names, such as "${name}.locality" etc.

For example you might want to call:

<plugin.addressFields
	name="address"
	...
/>

if these address fields sit within a larger form and you wish to group their output together together or name={"address[index]} if you need an array of them.

In these examples the output would take the shape:

address: {
	locality: "foo",
	postalCode: "bar"
}

or

address: [
	{
		locality: "foo",
		postalCode: "bar"	
	},
	...
]

RequiredValidator requiredValidator takes a function, which will be run on each field marked as required. A simple example might be

const  required = value => (
  !value ? "missing value" : undefined
);

This would then flag any required fields missing data with the text missing value on submittal.

The idea here is that if your function returns a falsy value then validation is deemed to have passed.

SavedAddress savedAddress takes an address object of the correct shape, which it will then pass to backendToFields, and finally be used line by line to fill out the initialValues for each line's Field.

AddressTextField Finally, AddressTextField is what will actually be displayed as an input box. Simplest case is

<plugin.AddressField
  AddressTextField={(props) => <input {...props}/>}
  ...
/>

You can pass a custom component here if you wish, wrapped in a final-form <Field> or otherwise.

Field labels

Right now we only have internationalised field labels for en_US, and there may be some work to do on your project's end to utilise those. The idea in future is that if you were accessing address-plugin-north-america US fields from France, that you would see "Etat" in place of "State", or if you were accessing the address-plugin-north-america Canada fields from Germany you'd see "Provinz" in place of "Province".

backendToFields

This is a function: backendToFields that the AddressFields component uses to massage the data held in savedAddress into a shape the fields can read and use as initial values for the form. It accepts addresses of the correct shape.

fieldsToBackend

This is a function: fieldsToBackend that does the opposite, takes the output from the fields, and reshapes it into something the backend will accept. In the most basic case, the plugin for "Foo" will simply take the flattened {premise: "A", locality: "B", ...} shape and translate that to

{
	countryCode: "foo",
	lines: [
		{
			type: {
				value: "Premise",
			},
			value: "A"
		},
		{
			type: {
				value: "Locality",
			},
			value: "B"
		},
	]
}

In the cases though where a field is not required, it will do the above if a field is filled, else call an address-utils function, deleteFieldIfExists, to remove any existing data. This is the part that may not be compatible with all backend setups, so extra massaging may be required.

Extra magic might occur here, but that should be covered in each address-plugin's README.

listOfSupportedCountries

This is simply an array, containing a list of countries for which this plugin supports. This list MUST contain the ISO 3166-2 codes of countries the plugin supports. For example the output for address-plugin-british-isles is ["GB-ENG", "GB-SCT", "GB-WLS", "GB-NIR"], and the output for address-plugin-north-america is ["US", "CA"]. These are used for the plugin translations (where there is a need to differ by country), e.g. "US.countryCode": "USA", and "CA.administrativeArea": "Province",

fieldOrder

This is an object, with keys corresponding to the standard addressLine types above, and values corresponding to their ordering in a written address. For example the address-plugin-british-isles fieldOrder object looks like this:

const  fieldOrder = {
	"Premise":  0,
	"Thoroughfare":  1,
	"PostalCodeOrTown":  2,
	"Locality":  3,
	"AdministrativeArea":  4,
	"PostalCode":  5,
	"Country":  6
}

The ordering should match the order you'd expect to see those fields in if you were to display the address.

We can then use this for building the address later in a ViewAddress component (FUTURE RELEASE), or potentially use it to save the order to the backend, if that's something your backend necessitates.

It's shaped like this as it seemed preferable to search for a key and return a value than to iterate over an array such as [Premise, Thoroughfare,...] and return an index.

pluginName

Finally we also export a simple String containing the plugin's name, i.e. address-plugin-north-america. This can be used to access the plugin's own translation codes inside your own project.

Address Shape

The minimum shape expected by the frontend fields is:

{
  countryCode: "GB-ENG"
  lines: [
    {
      id: "some_id",
      type: {
        value: "department"
      },
      value: "Shipping department"
    },
    ...
  ]
}

with each AddressLine being an object on the lines array, comprising of an id, a type object containing a value string, and a value string itself.

A saved address is expected to have a countryCode, in ISO 3166-2 form. The above example is the subdivided code for England, which we use here in place of the general ISO code GB for greater specification.

Known Issues

When changing an address's country format to one with more fields, everything should work as expected. However, we currently don't have a built in process to remove fields that a particular format might not include.

For example, filling out a UK address with a Town field will place that information into a postalCodeOrTown AddressLine, but then switching that address to a US one, the field will be missing from the form, but the backend data massagers do not know to remove something from postalCodeOrTown if it exists. This is not priority work for now, but shouldn't be too hard to fix.

Labelling

Labels are currently automagically included in an existing react-intl scope. This will in a future update be removed in favour of the calling implementation handling labelling itself, keeping this as a "dumb" implementation with NO external knowledge of the system above.

Other READMEs

As mentioned above, this is really a set of plugins and components, so I'll include here links to all the specific READMEs for the individual plugins/repos, and attempt to keep it up to date as new ones are added.