Registering a custom Widget with SvelteCMS requires creating a plugin and an associated Svelte component. The sveltecms/plugins/checkboxes
plugin has been created as an example.
Plugin
The plugin should include the widgetTypes
key, with an array of WidgetType objects.
Example: sveltecms/plugins/checkboxes/index.ts
import type { CMSPlugin } from "sveltecms";
import CheckboxText from "./CheckboxText.svelte";
export const plugin:CMSPlugin = {
id: 'checkboxes',
widgetTypes: [
{
id: 'checkbox-text',
description: 'Replaces the standard HTML checkbox input with a text-based input that should scale.',
widget: CheckboxText,
fieldTypes: ['boolean'],
optionFields: {
falseText: {
type: 'text',
size: '1',
default: '☐',
helptext: 'Character to show when the checkbox is not checked.',
},
trueText: {
type: 'text',
size: '1',
default: '☑︎',
helptext: 'Character to show when the checkbox is not checked.',
},
fontSize: {
type: 'number',
default: 150,
helptext: 'The relative size of the checkbox text, as a percentage.',
widget: {
type: 'number',
options: {
min: 10,
max: 500,
step: 5,
}
}
},
labelBeforeCheckbox: {
type: 'boolean',
default: false,
helptext: 'Render the text label before the checkbox element in HTML markup.',
},
}
}
]
}
export default plugin
Svelte Component
Script
The Svelte component used for the Widget will receive the following properties when it is used:
cms
: The full SvelteCMS instance. Rarely needed for custom Widgets.field
: The Field object. Necessary for:disabled
andrequired
attributes of the visible input- the
<label>
for the form element
id
: The ID string of the element. Necessary for:- the
name
attribute of whatever input is bound to thevalue
- the
value
: The value of the field, which is passed to SvelteCMS as a bound property, i.e. withbind:value
.- The
value
must be bound withbind:value
to an actual element, even if it is only<input type="hidden" name="{id}">
, or form entry will be broken if submitted to an endpoint.
- The
If your widget has options defined with the optionFields
property on the WidgetType definition in the plugin, then you can use them in your Svelte component:
let opts:{property:string} = field.widget.options
HTML
The minimum HTML for a Widget should include an HTML input
within a label
, with the field’s actual label rendered in a <span>
.
The field.required
and field.disabled
properties must be implemented, and the exported value
and id
variables must be bound to an input.
<label>
<span>{field.label}</span>
<input
name="{id}"
bind:value
required={field.required}
disabled={field.disabled}
>
</label>
Example: sveltecms/plugins/checkboxes/CheckboxText.ts
<script lang="ts">
import type { WidgetField } from 'sveltecms'
export let field:WidgetField
export let id:string
export let value = field.default
//@ts-ignore
let opts:{
falseText?:string
trueText?:string
fontSize?:number
labelBeforeCheckbox?:boolean
} = field.widget.options
function toggle() { if (!field.disabled) value = !value }
</script>
<label>
<input
type="hidden"
name={id}
bind:value
required={field.required}
>
{#if opts?.labelBeforeCheckbox}
<span on:click={toggle}>{field.label}</span>
{/if}
<i style:font-size="{opts?.fontSize ?? 100}%" on:click={toggle}>
{#if value}
{opts?.trueText || ''}
{:else}
{opts?.falseText || ''}
{/if}
</i>
{#if !opts?.labelBeforeCheckbox}
<span on:click={toggle}>{field.label}</span>
{/if}
</label>
<style>
i { display:inline-block; font-style:normal; line-height:inherit; }
</style>