Plugin options
Every first-party plugin can be tuned: which presets a filter offers, which aspect ratios a crop allows, whether a watermark is locked. Options follow two rules:
- They tune behaviour and constrain edits. They never carry pixel data. A custom filter is written to the edit log as
preset: 'custom'with its matrix, stickers and fonts are assets, so a render never depends on options and the parity guarantee holds. - Constraints are enforced on both sides when you ask for it. By default options only shape the tools. Set
enforce: trueon a plugin (orlock: trueon the watermark) and every edit log that breaks the constraints is rejected withOPTION_VIOLATION, even from a modified client. Pass the same options tocreateRendereron your server for the guarantee to hold;render()then throwsOPTION_VIOLATIONfor such a log.
With enforce, a constraint applies to the state an operation produces, not only to the fields it names. A resize.set without fit that starts a new target gets contain, so contain must be in fits. With resize.max, a target must name both width and height: with one side, the core derives the other from the aspect ratio of the image as it reaches the resize stage, and that side has no bound. annotate.fill: false and the palette cover the fill of a path and the background of a text as well as the fill of a rectangle or an ellipse.
Two ways to configure
Compose plugins yourself with configure():
import { defaultPlugins, filterPlugin, cropPlugin } from '@sealpixel/plugins';
const plugins = defaultPlugins.map((p) => {
if (p.id === 'filter')
return filterPlugin.configure({
presets: ['grayscale', 'sepia', { name: 'brand', label: 'Brand', matrix: BRAND_MATRIX }],
defaultStrength: 0.8,
});
if (p.id === 'crop') return cropPlugin.configure({ aspects: [{ label: 'crop.aspect.square', value: 1 }], enforce: true });
return p;
});
editor.plugins = plugins;Or pass a pluginOptions map and let the editor apply it to the default plugins:
<sealpixel-editor plugin-options='{"filter":{"presets":["grayscale","sepia"]},"crop":{"rotation":false}}'></sealpixel-editor><SealpixelEditor src={file} pluginOptions={{ filter: { presets: ['grayscale', 'sepia'] }, crop: { rotation: false } }} /><SealpixelEditor :src="file" :plugin-options="{ filter: { presets: ['grayscale', 'sepia'] }, crop: { rotation: false } }" /><SealpixelEditor {src} pluginOptions={{ filter: { presets: ['grayscale', 'sepia'] }, crop: { rotation: false } }} /><SealpixelEditor src="/photo.jpg" pluginOptions={{ filter: { presets: ['grayscale', 'sepia'] }, crop: { rotation: false } }} />createRenderer({
plugins: defaultPlugins,
pluginOptions: { filter: { presets: ['grayscale', 'sepia'] }, crop: { rotation: false } },
});Unknown keys, unknown plugin ids and values outside the schema throw at configuration time. The map wins over a hand-configured plugin with the same id.
A configuration that the plugin would reject later also throws at configuration time, with the key that is wrong:
- A
finetune.rangesentry must stay inside the op range of its parameter (gamma0.1..10,exposure-3..3, the others -1..1). A slider past it writes values that no edit log parser accepts. - With
enforce, every default must pass the constraints:finetune.defaultsonly for offeredcontrolsand inside their ranges,fill.defaultin thepalette, the watermark defaults (withanchorbr,scale0.2 andopacity0.6 when not set) inanchors,scaleRangeandopacityRange, theannotate.defaultStrokeinwidthRangeand thepalette, and eachresize.presetsentry insidemax.
Without this, the editor would dispatch a default operation that its own options reject when an image loads, and the defaults of the other plugins would not apply either.
Try it
The filter offers two built-in presets and one custom matrix; the crop is square only, without rotation. Edit the JSON below the editor.
Round avatars
cropPlugin.configure({ shape: 'circle', reset: false, enforce: true });shape: 'circle' fixes the aspect to 1, shows a round mask in the crop gizmo and writes mask: 'circle' into the crop operation. The core keeps only the inscribed circle with an anti-aliased edge and makes the outside transparent, identically in the browser and on the server; PNG and WebP exports keep the transparency, JPEG flattens onto the background colour. Because the mask lives in the edit log, a saved log renders the same everywhere without knowing the option. reset: false removes the "Reset crop" button (and, with enforce, rejects crop.reset), so a signup flow cannot lose its round shape; with reset allowed, resetting a circle crop restores a full round crop instead of dropping the mask.
The frame at the edge of a rotated image
cropPlugin.configure({ outside: 'allow' });The crop rectangle lives in the bounding box of the rotated image, which is larger than the image, so at an angle a frame can reach area the image does not cover; fill paints it. With the default outside: 'forbid' the crop tool keeps the frame on the picture: a handle drag stops at the turned image's edge and slides along it, and a rotation that would carry the frame off the image shrinks it about its centre. allow lets the frame reach the box, for a passe-partout or a tilted print on a coloured background. The option shapes the UI only; the log carries rect and rotation either way, and a host that writes them itself decides for itself.
Defaults become operations
Options such as filter.defaultPreset, finetune.defaults, crop.defaultAspect, fill.default and watermark.defaults.source are applied when a source loads with an empty edit log. The editor dispatches the corresponding operations, so the defaults are visible in the log and travel with it. A saved log is never altered.
Locked watermark
watermarkPlugin.configure({
lock: true,
defaults: { source: { kind: 'text', text: '© ACME', font: 'font.roboto', color: [1, 1, 1, 1] }, anchor: 'br', opacity: 0.5 },
});With lock, the tool shows the watermark as fixed, every watermark.set that deviates and every watermark.clear is rejected, and export or a server render fail while the watermark is missing or altered. Register the same options on the server for the guarantee to hold.
anchors, text, image, scaleRange and opacityRange shape the tool. Like the options of the other plugins, they reject operations only with enforce: true. The lock applies with or without enforce.
Reference
The options reference lists every option with type, default and description, generated from the schemas.
Third-party plugins
definePlugin({ options: { schema, defaults, describe }, validate, validateDocument, initialOps }) gives your plugin the same surface. See Writing a plugin.