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.
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.
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.
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.
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.
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, anduseStackedData
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, anduseTabularData
outputs sorted and paginated rows of props ready to pass to specific column renderers. - Generating and caching data and functions, for example
useSorter
anduseFilter
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, anduseConsoleAPI
gives developers direct access to datastore data viawindow
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 filteredstates
RuntimeContext
shares the current runtime messageTimeContext
shares the state message currently selected in the shell timelinePeersContext
shares an array of currently selected peer ID strings fromuseDatastore
WebsocketContext
shares the websocket metadata object fromuseDatastore
GlobalFilterContext
shares anapplyFilters
function fromuseFilter
controlled by the global filters UI in the shellSetterContext
shares an object, cached withuseRef
to prevent causing unnecessary re-renders, containing the following functions for updating data:updateRuntime
fromuseDatastore
setCurrentState
to change the selected state message shared inTimeContext
setPeerIds
fromuseDatastore
updateData
fromuseDatastore
replaceData
fromuseDatastore
removeData
fromuseDatastore
setIsLoading
fromuseDatastore
dispatchWebsocket
fromuseDatastore
dispatchGlobalFilters
fromuseFilter
updating the filter function shared byGlobalFilterContext
globalFilters
fromuseFilter
describing the filter function shared byGlobalFilterContext
Takes an array of filterDefs
, passes these to useFilter
, and shares the results.
Exports FilterProvider
wrapper component and the following contexts:
FilterContext
: SharesapplyFilters
andfilters
fromuseFilter
and the originalfilterDefs
prop passed toFilterProvider
.FilterSetterContext
: sharesdispatchFilters
fromuseFilter
. This function remains unchanged through the React lifecycle, meaning components callinguseContext(FilterSetterContext)
won't re-render on changes to filters unless they also calluseContext(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 Tooltip
s 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.
Passed to useSorter
sorts by strings alphabetically, ascending or descending (ascending by default).
Passed to useSorter
sorts by numbers alphabetically, ascending or descending (descending by default).
These provide useFilter
with filterDef
objects coverring common cases.
Returns filter definitions for a filter controlled by a checkbox UI where a set list of items are toggled on or off.
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.