fix: resize object opacity, context menu visibility

This commit is contained in:
HorizonCode committed 2026-10-29 16:18:20 +01:00
1 parent c02b26e8ae
commit fbfa3aa54c
1 file changed
+63 -57
+63 -57
View File
@@ -350,7 +350,10 @@
onpointerdown={beginMarquee} onpointerdown={beginMarquee}
oncontextmenu={(event) => { oncontextmenu={(event) => {
if (!interactive || event.target !== event.currentTarget) return; if (!interactive || event.target !== event.currentTarget) return;
event.preventDefault(); // 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); oncontext?.(undefined, event);
}} }}
> >
@@ -363,7 +366,7 @@
class:cursor-move={interactive && !element.locked} class:cursor-move={interactive && !element.locked}
class:cursor-default={interactive && element.locked} class:cursor-default={interactive && element.locked}
style="left:{element.x}px;top:{element.y}px;width:{element.width}px;height:{element.height}px;transform:rotate({element.rotation ?? style="left:{element.x}px;top:{element.y}px;width:{element.width}px;height:{element.height}px;transform:rotate({element.rotation ??
0}deg);opacity:{element.opacity ?? 1};touch-action:none;outline:{selected 0}deg);touch-action:none;outline:{selected
? `${selectedIds.length > 1 ? 1 : 2}px solid #ff006e` ? `${selectedIds.length > 1 ? 1 : 2}px solid #ff006e`
: 'none'};outline-offset:2px;" : 'none'};outline-offset:2px;"
role={interactive ? 'button' : undefined} role={interactive ? 'button' : undefined}
@@ -372,7 +375,7 @@
onpointerdown={(event) => beginDrag(event, element)} onpointerdown={(event) => beginDrag(event, element)}
oncontextmenu={(event) => { oncontextmenu={(event) => {
if (!interactive) return; if (!interactive) return;
event.preventDefault(); // Let the event bubble so the editor's ContextMenu.Trigger can open.
oncontext?.(element.id, event); oncontext?.(element.id, event);
}} }}
onkeydown={(event) => { onkeydown={(event) => {
@@ -382,61 +385,64 @@
} }
}} }}
> >
{#if element.type === 'text'} <!-- Opacity lives on the content wrapper so selection chrome stays fully opaque. -->
<div <div class="h-full w-full" style="opacity:{element.opacity ?? 1};">
class="h-full w-full overflow-hidden" {#if element.type === 'text'}
style="display:flex;align-items:{element.verticalAlign === 'center' <div
? 'center' class="h-full w-full overflow-hidden"
: element.verticalAlign === 'bottom' style="display:flex;align-items:{element.verticalAlign === 'center'
? 'flex-end' ? 'center'
: 'flex-start'};justify-content:{element.align === 'center' : element.verticalAlign === 'bottom'
? 'center' ? 'flex-end'
: element.align === 'right' : 'flex-start'};justify-content:{element.align === 'center'
? 'flex-end' ? 'center'
: 'flex-start'};text-align:{element.align ?? 'left'};" : element.align === 'right'
> ? 'flex-end'
<span : 'flex-start'};text-align:{element.align ?? 'left'};"
style="font-family:{fontStack(element.fontFamily)};font-size:{element.fontSize ??
28}px;font-weight:{element.fontWeight ?? 600};color:{element.color ??
'#ffffff'};line-height:{element.lineHeight ??
1.2};letter-spacing:{element.letterSpacing ??
0}px;white-space:pre-wrap;overflow-wrap:anywhere;"
> >
{element.text} <span
</span> style="font-family:{fontStack(element.fontFamily)};font-size:{element.fontSize ??
</div> 28}px;font-weight:{element.fontWeight ?? 600};color:{element.color ??
{:else if element.type === 'image'} '#ffffff'};line-height:{element.lineHeight ??
<img 1.2};letter-spacing:{element.letterSpacing ??
class="pointer-events-none h-full w-full" 0}px;white-space:pre-wrap;overflow-wrap:anywhere;"
src={assetUrl(element.src)} >
alt="" {element.text}
draggable="false" </span>
style="object-fit:{element.fit ?? 'cover'};border-radius:{element.radius ?? 0}px;" </div>
/> {:else if element.type === 'image'}
{:else if element.type === 'video'} <img
<video class="pointer-events-none h-full w-full"
class="pointer-events-none h-full w-full" src={assetUrl(element.src)}
use:themeMediaSource={assetUrl(element.src)} alt=""
use:themeVideoLifecycle draggable="false"
autoplay style="object-fit:{element.fit ?? 'cover'};border-radius:{element.radius ?? 0}px;"
loop />
muted={element.muted !== false} {:else if element.type === 'video'}
use:applyMuted={element.muted !== false} <video
playsinline class="pointer-events-none h-full w-full"
disablepictureinpicture use:themeMediaSource={assetUrl(element.src)}
aria-hidden="true" use:themeVideoLifecycle
style="object-fit:{element.fit ?? 'cover'};border-radius:{element.radius ?? 0}px;" autoplay
></video> loop
{:else} muted={element.muted !== false}
<div use:applyMuted={element.muted !== false}
class="h-full w-full" playsinline
style="background:{element.fill ?? '#ff006e'};border-radius:{element.shape === 'ellipse' disablepictureinpicture
? '50%' aria-hidden="true"
: `${element.radius ?? 16}px`};border:{element.borderWidth style="object-fit:{element.fit ?? 'cover'};border-radius:{element.radius ?? 0}px;"
? `${element.borderWidth}px solid ${element.borderColor ?? '#ffffff'}` ></video>
: 'none'};" {:else}
></div> <div
{/if} class="h-full w-full"
style="background:{element.fill ?? '#ff006e'};border-radius:{element.shape === 'ellipse'
? '50%'
: `${element.radius ?? 16}px`};border:{element.borderWidth
? `${element.borderWidth}px solid ${element.borderColor ?? '#ffffff'}`
: 'none'};"
></div>
{/if}
</div>
{#if singleSelected && !element.locked} {#if singleSelected && !element.locked}
{#each resizeDirections as direction (direction)} {#each resizeDirections as direction (direction)}