Editor Features
In blökkli the term feature means a single feature component that provides a set of editor features, for example comments, duplicate or clipboard integration. Another term would be "module" or "plugin".
Every feature can be enabled or disabled at both build time or runtime. For example, the translation
feature is only enabled when the language context indicates the user is editing translated content.
Builtin features
Most of the functionality in blökkli is also implemented as features. This allows you to completely override a feature component with your own implementation.
Anatomy of a feature component
Let's look at one of the builtin feature components:
<template>
<PluginItemAction
:title="$t('deleteButton', 'Delete')"
:disabled="state.editMode.value !== 'editing'"
multiple
key-code="Delete"
icon="delete"
:weight="-80"
@click="onClick"
/>
</template>
<script lang="ts" setup>
import { useBlokkli, defineBlokkliFeature } from '#imports'
import type { DraggableExistingBlock } from '#blokkli/types'
import { PluginItemAction } from '#blokkli/plugins'
const { state, eventBus, $t } = useBlokkli()
const { adapter } = defineBlokkliFeature({
id: 'delete',
icon: 'delete',
label: 'Delete',
requiredAdapterMethods: ['deleteBlocks'],
description: 'Provides an action to delete one or more blocks.',
})
async function onClick(items: DraggableExistingBlock[]) {
// Unselect all items.
eventBus.emit('select:end', [])
await state.mutateWithLoadingState(
adapter.deleteBlocks(items.map((v) => v.uuid)),
$t('deleteError', 'The block could not be deleted.'),
)
}
</script>
<script lang="ts">
export default {
name: 'Delete',
}
</script>
A feature component is declared using the defineBlokkliFeature()
composable. The id
, icon
and label
properties are required.
Every feature component is rendered as a child of <BlokkliProvider>
, but it can easily render its content anywhere else using <Teleport>
.
In this example, the feature makes use of the <PluginItemAction>
component. This will render a button in the block actions overlay that appears when a block is selected. It renders a single button with the given label and icon. In addition a keyboard shortcut can be provided which will trigger the @click
callback.
defineBlokkliFeature
This composable + compiler macro is used to define a feature. It is required.
dependencies: string[]
When set the feature will only be mounted if the defined dependencies (IDs of other features) are mounted.
viewports: Viewport[]
This allows you to only mount the feature for the given viewports. Possible values are 'mobile' | 'desktop'
.
requiredAdapterMethods: Methods[]
An array of adapter methods that must be implemented. For example, the comments
feature declares ['loadComments', 'addComment']
as required methods:
const { adapter } = defineBlokkliFeature({
id: 'comments',
icon: 'comment',
label: 'Comments',
requiredAdapterMethods: ['loadComments', 'addComment'],
description: 'Provides comment functionality for blocks.',
})
In the returned adapter
instance all the declared required adapter methods have been made Required
in TypeScript terms.
settings: Record<string, FeatureDefinitionSetting>
A feature can additionally declare settings. These settings are displayed in the "Settings" dialog of the editor. The settings are stored in local storage.
The returned settings
object is a computed property containing the value of the declarted settings. It works exactly the same as the block options.
const { settings } = defineBlokkliFeature({
id: 'artboard',
label: 'Artboard',
icon: 'artboard',
settings: {
persist: {
type: 'checkbox',
default: true,
label: 'Persist position and zoom',
group: 'behavior',
viewports: ['desktop'],
},
},
})
Custom features
Using the alterFeatures
config option, it's possible to extend the editor with your own feature component.
To