Skip to content

Censkh/pluggable-react

Repository files navigation

pluggable-react

Create React components that can be overridden globally or via context. Useful for design systems, white-label apps, and dependency injection of UI.

Installation

npm install pluggable-react react

Usage

1. Create a pluggable component

Use createPluggable to define a component with a default implementation that can be swapped out. The first argument is a unique id used to look up overrides in the registry:

import { createPluggable } from "pluggable-react";

const DefaultButton = ({ label, onClick }: { label: string; onClick?: () => void }) => (
  <button type="button" onClick={onClick}>{label}</button>
);

export const Button = createPluggable("MyApp.Button", DefaultButton);
// Button.id === "MyApp.Button"

2. Override via context

Wrap your tree with PluggableComponentRegistry and pass a map of component ids to replacement components. Any usage of Button under that provider will render your custom component instead.

Because pluggable components toString() to their id, you can use the component itself as the key:

import { PluggableComponentRegistry } from "pluggable-react";
import { Button } from "./Button";

const CustomButton = (props: any) => (
  <button className="custom" {...props}>{props.label}</button>
);

function App() {
  return (
    <PluggableComponentRegistry components={{ [Button]: CustomButton }}>
      <Button label="Click me" />
    </PluggableComponentRegistry>
  );
}

You can also use the id string: components={{ "MyApp.Button": CustomButton }}.

Overrides are merged with any parent registry, so you can override only some components at different levels of the tree.

3. Override globally (imperative)

Pluggable components expose a .replace() method so you can set a single global override without context:

import { Button } from "./Button";

Button.replace((props) => <button className="global-override">{props.label}</button>);

// Later: revert to default
Button.replace(null);

Context overrides take precedence over the static override; the static override is used when no context override is provided.

API

Export Description
createPluggable(id, DefaultComponent) Returns a pluggable component with .id, .replace(), displayName, and toString() (returns id, so you can use [Button]: CustomButton).
PluggableComponentRegistry Provider that accepts a components map of id → component to override within its subtree.
usePluggableComponentFromRegistry(idOrComponent) Hook that returns the override for the given id string or pluggable component from the nearest registry, or undefined.
PluggableComponentRegistryContext React context used by the registry (for advanced use).

Requirements

  • React 18+
  • TypeScript (optional; types are included)

License

MIT

About

No description, website, or topics provided.

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors