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

@spscommerce/items-experience

v1.4.1

Published

The Items Experience is a collection of UI components that interact with Assortment's Items API. Using these components in multiple frontend projects will ensure a consistent user experience across SPS applications.

Downloads

473

Readme

Items Experience

The Items Experience is a collection of UI components that interact with Assortment's Items API. Using these components in multiple frontend projects will ensure a consistent user experience across SPS applications.

"Earthshaking"

-- @omnipitous

Contents

Installation

Install the package:

pnpm add @spscommerce/items-experience

The package is hosted publicly on the NPM registry, so no extra configuration or permissions are required for installing.

This package requires some Peer Dependencies that should also be installed (refer to package.json for versions):

  • @sps-woodland/content-row
  • @sps-woodland/core
  • @sps-woodland/file-upload
  • @sps-woodland/illustrations
  • @sps-woodland/key-value-set
  • @sps-woodland/page-title
  • @sps-woodland/product-bar
  • @sps-woodland/tokens
  • @sps-woodland/zero-state
  • @spscommerce/ds-react
  • @spscommerce/utils
  • @spscommerce/asst-api
  • @spscommerce/form-presets-api
  • @spscommerce/items-api
  • react
  • react-dom
  • react-query
  • react-router-dom (optional)

Basic Setup

Items Experience was built to be used with React Router (version 6.4 or later), but is compatible with any routing setup.

All routing options require some initial basic setup, which includes:

  • Setting up a context provider
  • Setting up API providers

Routing can be setup after the basic setup.

Context Provider

All components from Items Experience must exist within the context of ItemsExperienceBasicContextProvider.

ItemsExperienceBasicContextProvider provides common data and functions from the host app:

type ItemsExperienceBasicContextProps = {
  /**
   * Provided by `useGrowlers` from `@spscommerce/ds-react`
   */
  createGrowler: (config: GrowlerConfig) => void;
  /**
   * Allows form-presets to be saved for your application
   */
  formPresetDetails: {
    appName: string;
    advancedSearchDefaultsFormName: string;
    selectedColumnsFormName: string;
  };
  /**
   * Options for advanced search.  Currently only includes standard attributes.
   */
  advancedSearchOptions: {
    /**
     * An array of standard attributes that will be used in advanced search.
     */
    standardAttributes: Attribute[];
  };
  /**
   * Optional array of available attributes to be used in searches.
   */
  availableAttributeList?: string[];
  /**
   * Config options for the Items Index page
   */
  itemsIndexConfig: {
    /**
     * An array of unique attributes.
     * Affects available columns.
     */
    uniqueAttributes: string[];
    /**
     * Boolean flag to enable Stage Item feature.
     * Affects column chooser.
     */
    isStageItemEnabled: boolean;
    /**
     * Boolean flag to enable MSIS feature.
     * Affects column chooser.
     */
    isMsisUiEnabled: boolean;
    /**
     * Boolean flag to enable Media Item feature.
     */
    enableMediaItem: boolean;
    /**
     * Optional boolean to show the "Add Item" button.
     * Defaults to false.
     */
    showAddItemsBtn?: boolean;
    /**
     * Array of columns that are initially selected.
     */
    columnsInitiallySelected: ColumnType[];
    /**
     * Array of columns that are initially unselected.
     */
    columnsInitiallyUnselected: ColumnType[];
    /**
     * Optional boolean to hide Status column.
     * Defaults to false.
     */
    hideStatusColumn?: boolean;
  };
  /**
   * An optional {@link QueryClient} can be passed to Items Experience.
   *
   * Note: The {@link QueryCache} will be replaced.
   *
   * It is not recommended to pass a `QueryClient` to Items Experience unless greater control is required, such as disabling retries during testing.
   * Items Experience will create its own `QueryClient`.
   */
  queryClient?: QueryClient;
  /**
   * Your application, including Items Experience pages
   */
  children: React.ReactNode;
};

API Provider Setup

In addition to context providers, Items Experience requires a valid user token to make network requests. All page components will wait until a valid token has been provided before rendering to ensure there are no race conditions.

Items Experience exports a function to set the token, updateApiProviders:

import { updateApiProviders } from "@spscommerce/items-experience";

updateApiProviders(env, "user_token");

Draft Notification Setup

The forms in this package save drafts to mitigate the loss of unsaved work done by the end user. Although optional, it is recommended that the user is notified when a draft is saved. To do this, Items Experience exports triggerDraftNotifications() which must be called after every rout change.

If you are using React-Router, setup may look like this:

import { useLocation } from "react-router-dom";
import { triggerDraftNotifications } from "@spscommerce/items-experience";

export function Component() {
  // Get the current location from react-router
  const location = useLocation();

  // Call `triggerDraftNotifications` any time `location` changes
  useEffect(() => {
    triggerDraftNotifications();
  }, [location]);

  return ...
}

Routing

Items Experience consists of multiple pages, and therefore requires a routing solution. Simple routing configuration can be done with React Router, but Items Experience can also be configured to work with any router.

React Router

If your application uses React Router version 6.4, then setup can be much simpler. Items Experience exports a RouteObject that can be added to your app's existing RouteObject at any level. It uses relative routing to automatically configure navigation between pages.

ItemsExperienceBasicContextProvider and updateApiProviders are still required for setup, but ItemsExperienceUrlContextProvider is not because routing is handled automatically.

import { itemsExperienceRouteObject } from "@spscommerce/items-experience/react-router";

const router = createHashRouter([
  {
    path: "/",
    element: <Navigate to="a" />,
  },
  {
    path: "/a",
    element: <A />,
  },
  {
    path: "/b",
    element: <B />,
  },
  {
    path: "/items",
    element: <Outlet />,
    children: [itemsExperienceRouteObject()],
  },
]);

Optional parameters can be provided to itemsExperienceRouteObject, which allow Items Experience to link to external pages:

{
  errorsIndexLocation?: string;
  errorsByItemLocation?: string;
  imageSettingsLocation?: string;
  exportsConfigLocation?: string;
}

Please see src/App.tsx for a full example.

Using Your Own Router

This package exports each page as a single component so they can be used in your project's routing system. Each page component can exist under the URL of your choice within your project, but those URLs must be provided to ItemsExperienceUrlContextProps to enable navigation between pages.

ItemsExperienceUrlContextProvider provides routing data and functions from the host app. This component allows Items Experience components to integrate with your application's router:

type ItemsExperienceUrlContextProps = {
  /**
   * Your application, including Items Experience pages
   */
  children: React.ReactNode;
  /**
   * URL data and functions.
   */
  value: {
    /**
     * Path parameters for the current route
     */
    urlParams: Record<string, string | undefined>;
    /**
     * Search parameters for the current route
     */
    urlSearchParams: URLSearchParams;
    /**
     * Function to set search parameters.  Used for url state.
     * @param params Search parameters to set
     * @param replace Should the new parameters replace the current parameters (ie. not add to location history)
     * @returns void
     */
    setUrlSearchParams: (params: URLSearchParams, replace: boolean) => void;
    /**
     * A function to navigate to different url's
     * @param location The location to navigate to
     * @returns void
     */
    navigateTo: (location: string) => void;
    /**
     * Object containing strings that specify the url location of each page when routing is handled by the host app.
     * These locations allow Items Experience pages to link to each other.
     *
     * Required locations have a corresponding page component exported by Items Experience.
     * For example:
     * ```
     * // Corresponds with `errorDetailsLocation`
     * import { ErrorDetailsPage } from '@spscommerce/items-experience'
     * ```
     *
     * Optional locations link to pages that are external to Items Experience.
     * Typically, these will not be used by teams other than Assortment.
     */
    locations: {
      /**
       * Errors Index location.
       * This location is external to Items Experience and is optional.
       */
      errorsIndexLocation?: string;
      /**
       * Error Details location.
       */
      errorDetailsLocation: string;
      /**
       * Errors by Item location.
       * This location is external to Items Experience and is optional.
       */
      errorsByItemLocation?: string;
      /**
       * Imports Index location.
       */
      importsIndexLocation: string;
      /**
       * Imports Create Template location.
       */
      importsCreateTemplateLocation: string;
      /**
       * Items Index location.
       */
      itemsIndexLocation: string;
      /**
       * Item Details location.
       */
      itemDetailsLocation: string;
      /**
       * Advanced Search Defaults location.
       */
      advSearchDefaultsLocation: string;
      /**
       * Image Settings location.
       * This location is external to Items Experience and is optional.
       */
      imageSettingsLocation?: string;
      /**
       * Exports Configuration location.
       * This location is external to Items Experience and is optional.
       */
      exportsConfigLocation?: string;
    };
  };
};

Items Experience exports the following page components in each category:

  • Preferences
    • AdvancedSearchDefaultsPage
  • Errors
    • ErrorDetailsPage
  • Imports
    • ImportsCreateTemplatePage
    • ImportsIndexPage
  • Items
    • ItemsIndexPage
    • ItemDetailsPage

Some pages expect URL path parameters (ItemsExperienceUrlContextProps.value.urlParams) and are required to function as expected:

  • ErrorDetailsPage expects itemInfoId
    • ex. errors/detail/:itemInfoId
  • ItemsDetail expects id
    • ex. items/detail/:id

When Items Experience pages link to each other, these path parameters will be automatically be appended to the locations provided in ItemsExperienceUrlContextProps.value.locations. The host app needs to provide the path parameters to ItemsExperienceUrlContextProvider because Items Experience components do not have direct access to the router.

Contributing

When contributing, please keep in mind that this is a public package that is used by multiple teams. Breaking changes need to be documented (see Pull Requests and Deployment for details).

Installation

This project is part of the Assortment UI workspace and uses pnpm for package management.

Install dependencies:

pnpm i

Project Structure

lib

The lib folder contains the code that will be exported. It has two sub-folders: core and react-router. These sub-folder correspond to the two entrypoints of the package.

  • core contains the base components the Items Experience, without any routing.

  • react-router contains the react-router adapter, which is a RouteObject that can be dropped into an existing react router config

src

The src folder contains an example application that uses the Items Experience with the react-router adapter.

Running the example project:

pnpm dev

Testing

This project is set up for unit tests and end-to-end tests.

Unit Tests

This project uses Vitest with React Testing Library for unit tests. These tests will have a *.test.(ts|tsx) file extension.

Running tests in watch mode:

pnpm test

Running tests with an explorer UI:

pnpm test:ui

End-to-end Tests

This project uses Playwright for end-to-end tests. These tests will exist under the e2e folder and will have a *.spec.ts file extension.

Running tests:

pnpm test:e2e

Playwright also features a UI for step by step debugging.

Running the Playwright UI:

pnpm test:e2e-ui

Storybook

This project uses Storybook to help with development.

Running Storybook:

pnpm storybook

Pull Requests and Deployment

This projects uses Microsoft's beachball to manage semantic versioning.

Pull Requests

When opening a pull request, the build pipeline will check if a changefile is included. The build will fail if no changefile is found. To create a changefile, run the beachball:change script. The cli will ask a few questions and then generate a changefile.

When generating a changefile, the type of change must be specified:

  • Patch - bug fixes; no backwards incompatible changes.
  • Minor - small feature; backwards compatible changes.
  • None - this change does not affect the published package in any way.
  • Major - major feature; breaking changes.

Deployment

The project is not automatically deployed when a Pull Request is merged. The project must be deployed manually by running the Items Experience Publish pipeline.

When this pipeline is run, it will run the following on the main branch:

  • check lint
  • check formatting
  • run tests
  • build
  • check for changefiles
  • increment package version, delete changefiles, commit to main
  • publish the package to NPM

Rotating NPM keys

The key required to publish the package can only be valid for a maximum of 365 days. When the key expires, it must be replaced with a newly generated key. A newly key can be generated on NPM, using the spsc_asst account.

Scripts

  • dev: run the example project
  • test: run unit tests in watch mode
  • test:ui: run unit tests with the explorer UI
  • test:ci: run unit tests in CI
  • test:e2e: run the playwright e2e tests
  • test:e2e-ui: run the playwright e2e test explorer and debugger
  • lint:lib: lint the lib folder
  • lint:src: lint the src folder
  • prettier:check: check that all files are formatted correctly
  • storybook: run storybook
  • build-storybook: build deployable storybook files (not necessary to run storybook locally)
  • beachball:change: generate a changefile (at least one changefile is required for a pull request)
  • beachball:check: check that a changefile accompanies changes that are not in main (used by CI)
  • beachball:publish: publish the package (used by CI)