{ closeContextMenu(); panning = false; }} /> {#snippet contextMenuItems()} {#if contextMenuGroup} {groupLabel(contextMenuGroup)} {:else if contextMenuTargetId} {contextMenuSelection.length > 1 ? `${contextMenuSelection.length} layers selected` : contextMenuSelection[0] ? elementLabel(contextMenuSelection[0]) : 'Layer'} {:else} Canvas {/if} {#if contextMenuGroup} Copy group duplicateGroup(contextMenuGroup?.id)} > Duplicate group Cut group pasteClipboard(contextMenuGroup.id)} > Paste into group ungroupGroup(contextMenuGroup.id)} > Ungroup group requestGroupDelete(contextMenuGroup.id)} > Delete group toggleGroupFlag(contextMenuGroup, 'hidden')} > {#if contextMenuGroup.hidden} Show group {:else} Hide group {/if} toggleGroupFlag(contextMenuGroup, 'locked')} > {#if contextMenuGroup.locked} Unlock group {:else} Lock group {/if} selectGroup(contextMenuGroup.id)} > Edit group {:else if contextMenuTargetId} Copy Cut pasteClipboard( contextMenuSelection.length === 1 ? contextMenuSelection[0].groupId : undefined )} > Paste Duplicate {#if contextMenuSelection.length === 1 && contextMenuSelection[0].groupId} { const groupId = contextMenuSelection[0]?.groupId; if (groupId) selectGroup(groupId); }} > Select parent group {/if} Group selection {#if contextMenuSelection.some((element) => element.groupId)} Remove from group {/if} {#if contextMenuSelection.length === 1} = elements.length - 1} onclick={() => moveSelected(1)} > Bring forward moveSelected(-1)} > Send backward {/if} toggleSelectedFlag('hidden')}> {#if contextMenuAllHidden} Show {contextMenuSelection.length === 1 ? 'layer' : 'layers'} {:else} Hide {contextMenuSelection.length === 1 ? 'layer' : 'layers'} {/if} toggleSelectedFlag('locked')}> {#if contextMenuAllLocked} Unlock {contextMenuSelection.length === 1 ? 'layer' : 'layers'} {:else} Lock {contextMenuSelection.length === 1 ? 'layer' : 'layers'} {/if} Delete {contextMenuSelection.length === 1 ? 'layer' : 'layers'} {:else} pasteClipboard()} > Paste Add text addMedia('image')}> Add image addMedia('video')}> Add shape Add Svelte component addLayer('data')}> Add data layer addLayer('icon')}> Add icon addLayer('repeater')}> Add repeater addLayer('gauge')}> Add gauge addLayer('ticker')}> Add ticker addLayer('button')}> Add button addLayer('path')}> Add vector path addLayer('particles')}> Add particles addLayer('clock')}> Add clock addLayer('countdown')}> Add countdown addLayer('widget', 'launch-button')} > Add launch button widget addLayer('widget', 'player-card')} > Add player card widget addLayer('widget', 'avatar')}> Add player avatar widget addLayer('widget', 'recent-activity')} > Add recent activity widget Add Lottie animation { selectedIds = elements.filter((element) => !element.hidden).map((element) => element.id); }} > Select all layers {/if} {/snippet} {#if selectedFontPreviewCss} {@html ``} {/if}

Theme editor

API 2.0 {#if definition.nsfw} 18+ {/if}

{definition.name || 'Untitled theme'}

{#if recoverableDraft}
An unsaved draft from {new Date(recoverableDraft.savedAt).toLocaleString()} is available.
{/if}