{ if (!interactive || event.target !== event.currentTarget) return; // The surrounding bits-ui ContextMenu.Trigger opens on the bubbling // contextmenu event and prevents the native menu itself. Calling // preventDefault() here makes the trigger treat the event as handled // (it bails when defaultPrevented is set), leaving no menu at all. oncontext?.(undefined, event); }} > {#snippet maskedLayer(element: ThemeV2Element, depth: number)} {@const masks = maskedAncestors(element)} {#if depth < masks.length}
{@render maskedLayer(element, depth + 1)}
{:else} {@render layerContent(element)} {/if} {/snippet} {#snippet layerContent(element: ThemeV2Element)} {@const selected = isSelected(element.id)} {@const singleSelected = selected && selectedIds.length === 1} {@const elementLocked = isElementLocked(element)}
beginDrag(event, element)} onclick={() => triggerInteraction(element, 'click')} onpointerenter={() => { triggerInteraction(element, 'hover'); showGroupHover(element); }} onpointerleave={() => { triggerInteraction(element, 'leave'); if (interactive) scheduleHoverHide(); }} oncontextmenu={(event) => { if (!interactive) return; // Let the event bubble so the editor's ContextMenu.Trigger can open. oncontext?.(element.id, event); }} ondblclick={(event) => { if (!interactive || !element.groupId) return; event.preventDefault(); event.stopPropagation(); onselectgroup?.(element.groupId); }} onkeydown={(event) => { if (interactive && (event.key === 'Enter' || event.key === ' ')) { event.preventDefault(); selectElement(element.id, modifierPressed(event)); } else if ( !interactive && element.interactive && (event.key === 'Enter' || event.key === ' ') ) { event.preventDefault(); triggerInteraction(element, 'click'); } }} >
{#if element.type === 'text' || element.type === 'data'}
{element.type === 'data' ? dataValue(element) : interpolateThemeText(element.text, variables)}
{:else if element.type === 'image'} {#if element.tint}
{:else} {/if} {:else if element.type === 'video'} {:else if element.type === 'svelte'} {:else if element.type === 'shape'} {#if element.shape === 'arc'} {@const arc = arcGeometry(element)} {@const gradientVector = themeSvgGradientVector(element.gradientAngle ?? 135)} {#if element.fillMode === 'gradient'} {/if} {:else}
{/if} {:else if element.type === 'icon'}
{:else if element.type === 'repeater'}
{#each Array(repeaterTiles(element).total) as _, index (index)} {#if element.source === 'image' && element.src} {:else} {/if} {/each}
{:else if element.type === 'gauge'} {#if element.mode === 'ring'}
{#if gaugeLabel(element)} {gaugeLabel(element)} {/if}
{:else}
{#if gaugeLabel(element)} {gaugeLabel(element)} {/if}
{/if} {:else if element.type === 'ticker'}
{#each [0, 1] as copy (copy)} {interpolateThemeText(element.text, variables)} {/each}
{:else if element.type === 'lottie'} {#key element.src} {/key} {:else if element.type === 'button'} {:else if element.type === 'path'} {@const gradientVector = themeSvgGradientVector(element.gradientAngle ?? 135)} {#if element.fillMode === 'gradient'} {/if} {:else if element.type === 'particles'}
{#each themeParticleSeeds(element) as seed, index (index)} {/each}
{:else if element.type === 'clock'} {@const now = clockNow} {#if element.mode === 'analog'} {@const hands = analogHands(now)} {#each Array(12) as _, index (index)} {/each} {#if element.showSeconds !== false} {/if} {:else}
{#if element.label} {element.label} {/if} {themeClockTime(element, now)} {#if element.showDate} {themeClockDate(now)} {/if}
{/if} {:else if element.type === 'countdown'}
{themeCountdownText(element, clockNow)}
{/if}
{#if singleSelected && !elementLocked} {#each resizeDirections as direction (direction)} beginResize(event, element, direction)} role="presentation" > {/each} {element.type} {/if} {#if selected && selectedIds.length > 1} selected {/if}
{/snippet} {#each visibleElements as element (element.id)} {@render maskedLayer(element, 0)} {/each} {#if hoverGroupFrame} {@const hover = hoverGroupFrame} {@const breadcrumb = themeGroupPath(groups, hover.group.id)} {#if hover.group.id !== selectedGroupId} `${corner.x},${corner.y}`).join(' ')} fill="var(--primary)" fill-opacity="0.02" stroke="var(--primary)" stroke-opacity="0.8" stroke-width="1" stroke-dasharray="5 4" /> {/if} {#if hover.group.id !== selectedGroupId || breadcrumb.length > 1}
event.stopPropagation()} oncontextmenu={(event) => { if (!interactive) return; // Let the event bubble so the editor's ContextMenu.Trigger opens. const target = event.target instanceof Element ? event.target.closest('[data-group-id]') : null; oncontextgroup?.(target?.dataset.groupId ?? hover.group.id, event); }} > {#each breadcrumb as group, index (group.id)} {#if index > 0} {/if} {/each}
{/if} {/if} {#if groupFrame} {@const frame = groupFrame} `${corner.x},${corner.y}`).join(' ')} fill="var(--primary)" fill-opacity="0.06" stroke="var(--primary)" stroke-width="1.5" stroke-dasharray={frame.locked ? '6 4' : undefined} /> {#if !frame.locked} {/if} {#if !frame.locked} {#each frame.corners as corner, index (index)} {/each} {/if} {/if} {#if snapGuides.x !== undefined}
{/if} {#if snapGuides.y !== undefined}
{/if} {#if marquee}
{/if}