feature-plugin

Feature Plugin System

Provides a user-friendly facade for enabling optional features that extend Stately's functionality. Feature plugins wrap extension points with a simple .enable() API and handle lazy loading of heavy dependencies.

For details on the lower level extension apis, refer to the ExtensionPoint interface.

Remarks

User-Facing Plugin API

Feature plugins sit above the extension system and provides:

  • Simple .enable() API for users
  • Lazy loading of heavy components
  • Dependency management between plugins
  • lazyComponent for consuming lazy components

For Users

Examples

import { codemirror } from '@statelyjs/stately/plugins';

// Enable with defaults
codemirror.enable();

// Or with options
codemirror.enable({
  themes: ['github', 'vscode'],
  languages: ['json', 'yaml', 'sql'],
});

For Plugin Authors

import { createFeaturePlugin } from '@statelyjs/ui/feature-plugin';
import { addStringModes } from './extensions';

export const myPlugin = createFeaturePlugin({
  id: 'myPlugin',
  component: () => import('./heavy-component'),
  setup: (ctx, options) => {
    addStringModes.extend(state => ({
      component: state.mode === 'custom' ? ctx.Component : state.component,
    }));
  },
});

Interfaces

FeatureComponentProps

Defined in: packages/ui/src/feature-plugin.tsx:343

Expand

Props for the FeatureComponent wrapper.

Type Parameters

TProps

TProps extends JSX.IntrinsicAttributes

Properties

fallback?

optional fallback: ReactNode

Defined in: packages/ui/src/feature-plugin.tsx:358

Fallback to show while the component is loading.

Default
null
notEnabled?

optional notEnabled: ReactNode

Defined in: packages/ui/src/feature-plugin.tsx:364

Content to show if the plugin is not enabled.

Default
null
plugin

plugin: FeaturePlugin<any, TProps>

Defined in: packages/ui/src/feature-plugin.tsx:347

The feature plugin to render the component from.

props

props: TProps

Defined in: packages/ui/src/feature-plugin.tsx:352

Props to pass to the lazy-loaded component.


FeaturePlugin

Defined in: packages/ui/src/feature-plugin.tsx:147

A feature plugin instance with .enable(), .lazyComponent, and other APIs.

Type Parameters

TOptions

TOptions

Options accepted by .enable()

TComponentProps

TComponentProps

Props type for the lazy-loaded component

TExtras

TExtras extends object = never

Extras object, initialized via FeaturePluginConfig.defaultExtras or .setup().

Properties

extras

extras: TExtras

Defined in: packages/ui/src/feature-plugin.tsx:211

Get the extras from FeaturePluginConfig.defaultExtras or .setup(). Returns undefined if not enabled.

id

readonly id: string

Defined in: packages/ui/src/feature-plugin.tsx:151

Unique identifier for this plugin.

lazyComponent

lazyComponent: LazyExoticComponent<ComponentType<TComponentProps>> | null

Defined in: packages/ui/src/feature-plugin.tsx:199

Getter to access the lazy-loaded component.

Returns null if the plugin hasn't been enabled. The component is wrapped with React.lazy() for automatic code splitting.

Returns

The lazy component or null if not enabled

Example
function MyEditor(props) {
  const CodeMirror = codemirror.lazyComponent;

  if (!CodeMirror) {
    return <div>CodeMirror not enabled</div>;
  }

  return (
    <Suspense fallback={<Spinner />}>
      <CodeMirror {...props} />
    </Suspense>
  );
}

Methods

enable()

enable(options?): void

Defined in: packages/ui/src/feature-plugin.tsx:167

Enable the plugin with optional configuration.

This should be called once at application startup, before rendering. Calling multiple times is safe (subsequent calls are no-ops).

Parameters
options?

TOptions

Plugin-specific configuration options

Returns

void

Example
// In your app entry point
codemirror.enable({ themes: ['github'] });
getOptions()

getOptions(): TOptions | undefined

Defined in: packages/ui/src/feature-plugin.tsx:205

Get the options that were passed to .enable(). Returns undefined if not enabled.

Returns

TOptions | undefined

isEnabled()

isEnabled(): boolean

Defined in: packages/ui/src/feature-plugin.tsx:172

Check if the plugin has been enabled.

Returns

boolean


FeaturePluginConfig

Defined in: packages/ui/src/feature-plugin.tsx:84

Configuration for creating a feature plugin.

Type Parameters

TOptions

TOptions

Options accepted by .enable()

TComponentProps

TComponentProps

Props type for the lazy-loaded component

TExtras

TExtras extends object = never

Additional properties to expose on the plugin object

Properties

component()?

optional component: () => Promise<{ default: ComponentType<TComponentProps>; }>

Defined in: packages/ui/src/feature-plugin.tsx:102

Dynamic import for the heavy component. Only loaded when the plugin is enabled and the component is rendered.

Returns

Promise<{ default: ComponentType<TComponentProps>; }>

Example
component: () => import('@uiw/react-codemirror'),
defaultExtras

defaultExtras: TExtras

Defined in: packages/ui/src/feature-plugin.tsx:137

Default extras if .enable() is never called.

defaults?

optional defaults: Partial<TOptions>

Defined in: packages/ui/src/feature-plugin.tsx:132

Default options applied when .enable() is called without arguments.

id

id: string

Defined in: packages/ui/src/feature-plugin.tsx:91

Unique identifier for this plugin.

Examples
'codemirror'
'markdown-editor'
setup()

setup: (ctx, options) => TExtras | undefined

Defined in: packages/ui/src/feature-plugin.tsx:127

Setup function called once when .enable() is invoked. Use this to register extensions, configure behavior, etc.

Optionally return an object with additional properties (extras) that will be spread onto the plugin object, making them accessible as plugin.extraName.

Parameters
ctx

FeaturePluginContext<TComponentProps>

Plugin context with lazy component and state

options

TOptions

Options passed to .enable()

Returns

TExtras | undefined

Optional extras object to merge into the plugin

Example
setup: (ctx, options) => {
  // Register extensions...

  // Return extras that become plugin properties
  return {
    ToggledEditor: (props) => <MyToggled {...options} {...props} />,
  };
},

FeaturePluginContext

Defined in: packages/ui/src/feature-plugin.tsx:64

Context passed to the setup function during plugin initialization.

Type Parameters

TComponentProps

TComponentProps

The component type that will be lazy loaded

Properties

Component

Component: LazyExoticComponent<ComponentType<TComponentProps>> | null

Defined in: packages/ui/src/feature-plugin.tsx:69

The lazy-wrapped component, ready for use in React. This is null until .enable() is called.

isEnabled

isEnabled: boolean

Defined in: packages/ui/src/feature-plugin.tsx:74

Whether the plugin has been enabled.

Functions

createFeaturePlugin()

createFeaturePlugin<TOptions, TComponentProps, TExtras>(config): FeaturePlugin<TOptions, TComponentProps, TExtras>

Defined in: packages/ui/src/feature-plugin.tsx:277

Type Parameters

TOptions

TOptions = void

TComponentProps

TComponentProps = unknown

TExtras

TExtras extends object = never

Parameters

config

FeaturePluginConfig<TOptions, TComponentProps, TExtras>

Returns

FeaturePlugin<TOptions, TComponentProps, TExtras>


FeatureComponent()

FeatureComponent<TProps>(__namedParameters): ReactNode

Defined in: packages/ui/src/feature-plugin.tsx:380

Wrapper component that handles Suspense and enabled checks for feature plugins.

Type Parameters

TProps

TProps extends IntrinsicAttributes

Parameters

__namedParameters

FeatureComponentProps<TProps>

Returns

ReactNode

Example

<FeatureComponent
  plugin={codemirror}
  props={{ value, onChange }}
  fallback={<Spinner />}
  notEnabled={<div>Enable CodeMirror to use this feature</div>}
/>