Skip to content

Latest commit

 

History

History

sdk

sdk @libp2p/observer-sdk

This package contains the core React hooks and components on which libp2p Observer widgets are built. It is also used for other libp2p Observer UIs such as the catalogue and shell.

1. Usage

1.1 Including the SDK in a widget

To create a libp2p Observer data visualisation widget, use the create-widget script. This sets up a new repository including this package alongside Webpack and Storybook configuration, setting the widget up to be compatible with libp2p Observer Cataloguesand to run inside the libp2p Observer Shell.

1.2 Including the SDK in any other project

The following is intended for use cases where create-widget does not apply. It may be skipped if using create-widget, as this configured automatically by that script.

1.2.1 Recommended dependency type

To use this package as a base for other types of UI, choose the type of dependency which this package should be depending on based on whether the project is standalone:

  • If the project is intended to run alongside or inside the libp2p Observer Catalogue, include this package as a peer dependency, so that only one version of this package and its dependencies can be included in the build, and also as a dev dependency, so that it is available locally during development for use (for example, for use with Storybook and Jest).
  • If the project is standalone and independent of the catalogue, for example if it is alternative to or fork of the libp2p Catalogue, include this package as an ordinary dependency.

1.2.2 Webpack config

This package exports font files, it is recommended to use file-loader with a test matching at least the otf extension.

Configuration including the following is recommended, as it covers fonts as well as other useful file types including sample binary files in the samples package and the markdown files and PNG images used in standard libp2p widgets:

return {
  module: {
    rules: [
      {
        // Exports these as raw text
        test: /\.md$/,
        loader: 'raw-loader',
      },
      {
        // Bundles these as files and exports URIs
        test: /\.(png|woff|woff2|eot|ttf|otf|svg|mock)$/,
        loader: 'file-loader',
      },
    ],
  }
}

Config including rules like these is automatically generated by the create-widget script.

Exports by type

This package exports React Hooks, React Components (which include context providers), theming including fonts and utility functions. Some familiarity or experience with React Hooks is recommended.

These custom react hooks contain JavaScript logic that uses React hooks and follows the rules of hooks but does not directly render a component.

See the hooks directory readme for API documentation of each exported hook.

To give a broad overview, uses of custom hooks in the SDK include:

  • Data management. For example, useDatastore handles the central management of all libp2p Introspection messages and metadata held in memory.
  • Shaping data for specific uses. For example, usePooledData creates pooled tallies of data usable for histograms and metrics, and useStackedData stacks data cumulatively ready for use drawing area charts and stacked bar charts.
  • Producing props use by visualisation components, for example useAreaChart generates path co-ordinates ready to pass to SVG or Canvas components, and useTabularData outputs sorted and paginated rows of props ready to pass to specific column renderers.
  • Generating and caching data and functions, for example useSorter and useFilter generate functions for sorting and filtering data and update them as the user selects different options.
  • Manipulating the DOM directly after rendering, for example useCanvas handles canvas animations frame-by-frame, and useConsoleAPI gives developers direct access to datastore data via window and console.

These components make values available anywhere deeper in an application. They use React's createContext and context.Provider components to share values with any child component that imports the context object and passes it as an argument to React's useContext hook. See the useContext documentation for more details.

Any change to a context value causes a re-render, so care is taken to minimise changes to values shared this way.

Takes data from useDatastore, applies global filters, removes data later than the current timeline position and shares the resulting data with child components and hooks.

Exports DataProvider wrapper component and the following contexts:

  • DataContext shares an array of filtered states
  • RuntimeContext shares the current runtime message
  • TimeContext shares the state message currently selected in the shell timeline
  • PeersContext shares an array of currently selected peer ID strings from useDatastore
  • WebsocketContext shares the websocket metadata object from useDatastore
  • GlobalFilterContext shares an applyFilters function from useFilter controlled by the global filters UI in the shell
  • SetterContext shares an object, cached with useRef to prevent causing unnecessary re-renders, containing the following functions for updating data:
    • updateRuntime from useDatastore
    • setCurrentState to change the selected state message shared in TimeContext
    • setPeerIds from useDatastore
    • updateData from useDatastore
    • replaceData from useDatastore
    • removeData from useDatastore
    • setIsLoading from useDatastore
    • dispatchWebsocket from useDatastore
    • dispatchGlobalFilters from useFilter updating the filter function shared by GlobalFilterContext
    • globalFilters from useFilter describing the filter function shared by GlobalFilterContext

Takes an array of filterDefs, passes these to useFilter, and shares the results.

Exports FilterProvider wrapper component and the following contexts:

  • FilterContext: Shares applyFilters and filters from useFilter and the original filterDefs prop passed to FilterProvider.
  • FilterSetterContext: shares dispatchFilters from useFilter. This function remains unchanged through the React lifecycle, meaning components calling useContext(FilterSetterContext) won't re-render on changes to filters unless they also call useContext(FilterContext)

Renders a <div> that inherits most styling from its parent and passes that <div> a ref from useRef, then shares that ref. This allows children to make comparisons against a common ancestor: for example, it can be used to provide Tooltips with a boundary to not overflow.

Exports RootNodeProvider wrapper component and a context RootNodeContext that shares the ref of RootNodeProvider's parent <div>.

Takes a theme object as a prop (or, uses the default SDK theme), initialises any global styles, and shares it using Styled Components's ThemeProvider context, making it available as a prop within Styled Components tagged template literals.

See Styled Components theming documentation for more details.

These provide useSorter with getSorter props coverring common cases.

getStringSorter

Passed to useSorter sorts by strings alphabetically, ascending or descending (ascending by default).

getNumericSorter

Passed to useSorter sorts by numbers alphabetically, ascending or descending (descending by default).

These provide useFilter with filterDef objects coverring common cases.

getListFilter

Returns filter definitions for a filter controlled by a checkbox UI where a set list of items are toggled on or off.

getRangeFilter

Returns filter definitions for a filter controlled by a range slider UI where values are filtered if they do not fall between the two selected points.

Running npm run storybook:sdk in the libp2p Observer root directory launches a storybook instance demonstrating several of these components and their interactions with other child components and simple data.

All components have complete propType objects specifying the type of props they consume and which are required. These propTypes definitions are checked automatically by lint.