Skip to content

Latest commit

 

History

History

Folders and files

NameName
Last commit message
Last commit date

parent directory

..
 
 
 
 
 
 
 
 
 
 
 
 
 
 

README.md

Person block plugin

One or more profile cards with cropped avatars, biography, role, and social links.

Install and register

npm install @shelamkoff/rector @shelamkoff/cropper
import { createEditor } from '@shelamkoff/rector'
import { Person } from '@shelamkoff/rector/plugins/person'

const editor = createEditor({
  holder: document.querySelector('#editor'),
  plugins: [new Person()],
})

The registered block type is person. The class is also exported by the complete @shelamkoff/rector/plugins preset and can be loaded through @shelamkoff/rector/plugins/async.

Data

{
  "persons": [{
    "avatar": "https://cdn.example/ada.jpg",
    "name": "Ada",
    "role": "Author",
    "bio": "",
    "links": [{ "type": "website", "url": "https://example.com" }]
  }]
}

Field reference

Field Required Meaning and constraints
persons yes Non-empty array of profile cards. The saved order is the display order.
persons[].avatar yes Empty string or canonical media URL. Cropping and uploading replace this value.
persons[].name yes Profile name string. A profile with both an empty name and empty avatar is treated as empty by the editor.
persons[].role, persons[].bio yes Role and biography strings; empty values are allowed.
persons[].links yes Array of social links; it may be empty. Every item needs a string type and a canonical link-policy url.

All fields are present in normalized saved data even when their values are empty. Unknown application fields are not part of the contract and should be stored outside the block.

The active profile tab is view state, not document data: save() persists all profiles in their current order but does not persist which tab was open. Tab switching therefore remains available in read-only mode so a reader can inspect every profile; it does not create a history entry. Adding, removing, reordering, or editing profiles is disabled in read-only mode.

Callback avatar URLs must pass the shared media URL policy. The editor plugin requires @shelamkoff/cropper. The multi-card renderer requires @shelamkoff/carousel.

Configuration

Every built-in block plugin accepts two style ownership options: injectStyles?: boolean defaults to true; set it to false when the host bundles that plugin's CSS. css?: string adds one host-provided stylesheet URL after the plugin default, or acts as the replacement URL when default injection is disabled.

uploadFile?: (file: File, context: { signal: AbortSignal }) => Promise<{ url: string }> uploads the cropped avatar as avatar.webp and must stop work when the supplied signal is aborted. Without it, the cropped avatar is embedded in persons[].avatar as a data URL, which increases document size. socialResolvers?: Array<{ test: RegExp | ((url: string) => boolean); type: string; icon?: string }> extends social-link icon resolution.

Capabilities

Multiple profiles; tab reordering; avatar crop/upload; social links; read-only profile navigation; deterministic dialog cleanup.

Undo, lifecycle, and styles

User actions exposed by the plugin enter the command pipeline through the supplied context.mutate() capability, so each completed action is one undo/redo step. The editor reference-counts the plugin's declared stylesheet URLs. Removing a block calls its cleanup hook; removing the editor calls destroy() for every remaining block and then releases shared plugin resources.

Do not remove the editor holder without first calling editor.destroy().

Document output

Use the matching renderer from @shelamkoff/rector/renderer/renderers/person. The VitePress guide documents configuration, commands and history, extension contracts, document migrations, styling, security, and lifecycle in a sequential form.