docs/frontend-system: document advanced blueprint param types
Signed-off-by: Patrik Oldsberg <poldsberg@gmail.com>
This commit is contained in:
@@ -60,6 +60,39 @@ When using `makeWithOverrides`, we no longer pass the blueprint parameters direc
|
||||
|
||||
Apart from the addition of the blueprint parameters of the first argument to the original factory function, the `makeWithOverrides` method works the same way as [extension overrides](./25-extension-overrides.md). All the same options and rules apply, including the ability to define additional inputs, override outputs, and so on. We therefore defer to the [extension overrides](./25-extension-overrides.md) documentation for more information on how to use the `makeWithOverrides` method.
|
||||
|
||||
### Creating an extension from a blueprint with advanced parameter types
|
||||
|
||||
Some blueprints may be defined with something known as "advanced parameter types". This is a feature that enables type inference and transform of the blueprint parameters, and the way that you pass the parameters look a little bit different. Rather than passing the parameters directly, they are instead passed as a callback function of the form `define => define(<params>)`.
|
||||
|
||||
An example of a blueprint that uses advanced parameter types is the `ApiBlueprint` blueprint. Using it to create a simple implementation for the `AlertApi` might look like this:
|
||||
|
||||
```ts
|
||||
const alertApiBlueprint = ApiBlueprint.make({
|
||||
params: define =>
|
||||
define({
|
||||
api: alertApiRef,
|
||||
deps: {},
|
||||
factory: () => new MyAlertApi(),
|
||||
}),
|
||||
});
|
||||
```
|
||||
|
||||
This also works with `makeWithOverrides`, where the define callback is passed as the first argument to the original factory:
|
||||
|
||||
```ts
|
||||
const alertApiBlueprint = ApiBlueprint.makeWithOverrides({
|
||||
factory(originalFactory, { config }) {
|
||||
return originalFactory(define =>
|
||||
define({
|
||||
api: alertApiRef,
|
||||
deps: {},
|
||||
factory: () => new MyAlertApi(config),
|
||||
}),
|
||||
);
|
||||
},
|
||||
});
|
||||
```
|
||||
|
||||
## Creating an extension blueprint
|
||||
|
||||
To create a new extension blueprint, you use the `createExtensionBlueprint` function. At the surface it is very similar to `createExtension`, but with a few key differences. Firstly you must provide a `kind` option, which will be the kind of all extensions created with the blueprint. See the [naming patterns section](./50-naming-patterns.md) for more information about how to select a good extension kind. Secondly, the `factory` function has a new signature where the first parameter is the blueprint parameters, and the second is the factory context. And finally, rather than returning an extension, `createExtensionBlueprint` returns a blueprint object with the `make` method and friends, which is used as is described above.
|
||||
@@ -99,6 +132,41 @@ This is of course a quite bare-bones example blueprint, but still a very real ex
|
||||
|
||||
Most of the options provided to `createExtensionBlueprint` can be overridden when using `makeWithOverrides` to create an extension from the blueprint. These overrides work the same way as [extension overrides](./25-extension-overrides.md), and we defer to that documentation for more information on how overrides work.
|
||||
|
||||
### Creating an extension blueprint with advanced parameter types
|
||||
|
||||
In some cases you may want to use inferred type parameters in the definition of the blueprint parameters. For this you need to use something known as "advanced parameter types". This is a feature that enables type inference and transform of the blueprint parameters, and the way you define the parameter type is a bit different. Rather than defining the type of the parameters as part of the factory function, you instead provide a separate `defineParams` options. This is a function that takes the parameters as a single argument, and must then return the parameters wrapped with the `createExtensionBlueprintParams` function.
|
||||
|
||||
The following is an example of how one might define a blueprint where the parameters make use of inferred types:
|
||||
|
||||
```ts
|
||||
export interface MyWidgetBlueprintParams<T> {
|
||||
defaultOptions: T;
|
||||
elementFactory(options: T): JSX.Element;
|
||||
}
|
||||
|
||||
export const MyWidgetBlueprint = createExtensionBlueprint({
|
||||
kind: 'my-widget',
|
||||
attachTo: { id: 'page:my-plugin', input: 'widgets' },
|
||||
output: [coreExtensionData.reactElement],
|
||||
defineParams<T>(params: MyWidgetBlueprintParams<T>) {
|
||||
return createExtensionBlueprintParams(params);
|
||||
},
|
||||
// Note that we no longer define the parameters type here, they are inferred from the defineParams function
|
||||
factory(params) {
|
||||
return [
|
||||
coreExtensionData.reactElement(
|
||||
<MyWidgetRenderer
|
||||
defaultOptions={params.defaultOptions}
|
||||
elementFactory={params.elementFactory}
|
||||
/>,
|
||||
),
|
||||
];
|
||||
},
|
||||
});
|
||||
```
|
||||
|
||||
If you happen to ask yourself, "why can't I just define type parameters on the factory function instead?", this is a limitation in the TypeScript type system. We could technically support that in the blueprint definition, but there would be no way for that logic to be carried forward to the blueprint `.make` and `.makeWithOverrides` methods.
|
||||
|
||||
### Blueprint-specific extension data references
|
||||
|
||||
In some cases you may want to define and provide [extension data reference](./20-extensions.md#extension-data-references) that are specific to your blueprint. In the above example we might want to forward the `title` as data for example, rather than encapsulating it into the `MyWidgetContainer` component. This gives the parent extension more flexibility in the rendering for our example widget extensions.
|
||||
|
||||
Reference in New Issue
Block a user