Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
32 commits
Select commit Hold shift + click to select a range
2d211ab
adds ScrollerLottie
SudevKiyadaTR Sep 26, 2025
fc17d3b
fix linting and formatting
SudevKiyadaTR Sep 26, 2025
f3375f0
fix TS issues
SudevKiyadaTR Oct 3, 2025
a20a027
docs
SudevKiyadaTR Oct 13, 2025
867155c
type files refactoring/cleaning
MinamiFunakoshiTR Dec 1, 2025
916344d
cleanup, refactors
MinamiFunakoshiTR Dec 1, 2025
88451b6
simplify mouse events
MinamiFunakoshiTR Dec 1, 2025
87749bf
clean up event listener destroy redundancy
MinamiFunakoshiTR Dec 1, 2025
a4e4d66
gets rid of Block for SREP support
MinamiFunakoshiTR Dec 1, 2025
746c08e
deletes debug font
MinamiFunakoshiTR Dec 1, 2025
2c37cc8
deletes container width prop
MinamiFunakoshiTR Dec 1, 2025
7a10bd3
renames to Lottie
MinamiFunakoshiTR Dec 3, 2025
675860a
updates marker screenshot
MinamiFunakoshiTR Dec 3, 2025
4f2d8d9
updated docs
MinamiFunakoshiTR Dec 3, 2025
252b2ca
clean up LottieForeground
MinamiFunakoshiTR Dec 3, 2025
24efc40
tweaks
MinamiFunakoshiTR Dec 3, 2025
d01a0bb
Merge pull request #376 from reuters-graphics/mf-lottie
SudevKiyadaTR Dec 4, 2025
4089964
Convert .lottie to .zip
SudevKiyadaTR Dec 4, 2025
bdfff3b
adds windowResize event listener
SudevKiyadaTR Dec 4, 2025
8414c10
docs
SudevKiyadaTR Dec 4, 2025
92e72ce
resolve linting errors
SudevKiyadaTR Dec 4, 2025
1a5fcef
expose width and height
SudevKiyadaTR Dec 5, 2025
ce69a48
docs
SudevKiyadaTR Dec 10, 2025
8ba4784
makes story args reactive
SudevKiyadaTR Jan 12, 2026
f156926
removes wasm integration
SudevKiyadaTR Jan 12, 2026
fe3e79b
Merge pull request #378 from reuters-graphics/sk-lottie-test
SudevKiyadaTR Jan 12, 2026
8f225a7
tweaks height for ScrollerBase example
SudevKiyadaTR Jan 12, 2026
1e58b1b
fix linting
SudevKiyadaTR Jan 12, 2026
e8995cf
updates transitionSpeed for videoPercentage reactivity
SudevKiyadaTR Jan 12, 2026
528c62e
solves #380
SudevKiyadaTR Jan 12, 2026
2acb2bd
cleanup
SudevKiyadaTR Jan 12, 2026
c803927
Merge branch 'main' into sudev-scroller-lottie
SudevKiyadaTR Jan 12, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,7 @@
"dependencies": {
"@fortawesome/free-regular-svg-icons": "^6.7.2",
"@fortawesome/free-solid-svg-icons": "^6.7.2",
"@lottiefiles/dotlottie-web": "^0.52.2",
"@reuters-graphics/svelte-markdown": "^0.0.3",
"@sveltejs/kit": "^2.0.0",
"dayjs": "^1.11.13",
Expand Down
8 changes: 8 additions & 0 deletions pnpm-lock.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

11 changes: 11 additions & 0 deletions src/components/@types/global.ts
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,17 @@ export type ScrollerVideoForegroundPosition =
| 'center left'
| 'center right';

export type LottieForegroundPosition =
| 'top center'
| 'top left'
| 'top right'
| 'bottom center'
| 'bottom left'
| 'bottom right'
| 'center center'
| 'center left'
| 'center right';

// Complete ScrollerVideo instance interface
export interface ScrollerVideoInstance {
// Properties
Expand Down
269 changes: 269 additions & 0 deletions src/components/Lottie/Debug.svelte
Original file line number Diff line number Diff line change
@@ -0,0 +1,269 @@
<script lang="ts">
const { componentState } = $props();

let isMoving = $state(false);
let preventDetails = $state(false);
let position = $state({ x: 8, y: 8 });

function onMouseDown(e: MouseEvent) {
isMoving = true;
e.preventDefault();
}

function onMouseMove(e: MouseEvent) {
if (isMoving) {
position = {
x: position.x + e.movementX,
y: position.y + e.movementY,
};
preventDetails = true;
}
e.preventDefault();
}

function onMouseUp(e: MouseEvent) {
if (isMoving) {
isMoving = false;
setTimeout(() => {
preventDetails = false;
}, 5);
e.stopImmediatePropagation();
}
e.preventDefault();
}

function onClick(e: MouseEvent) {
if (preventDetails) {
e.preventDefault();
}
isMoving = false;
}
</script>

<svelte:window onmousemove={onMouseMove} />

<div
style="position: absolute; top: {position.y}px; left: {position.x}px; z-index: 5; user-select: none;"
role="region"
>
<details class="debug-info" open>
<summary
class="text-xxs font-sans font-bold title"
style="grid-column: span 2;"
onmousedown={onMouseDown}
onmouseup={onMouseUp}
onclick={onClick}
>
CONSOLE
</summary>
<div class="state-debug">
<!-- -->
<p>Progress:</p>
<div style="display: flex; flex-direction: column; gap: 4px;">
<p class="state-value">{componentState.progress}</p>
<div id="video-progress-bar">
<div
style="width: {componentState.progress * 100}%; height: 100%;"
></div>
</div>
</div>
<!-- -->
<p>Duration:</p>
<p class="state-value">
{componentState.duration}s
</p>
<!-- -->
{#if componentState.segment}
<p>Segment:</p>
<p class="state-value">
{componentState.segment[0]} -- {componentState.segment[1]}
</p>
{/if}
<!-- -->
<p>Current frame:</p>
<p class="state-value">
{componentState.currentFrame}/{componentState.totalFrames}
</p>
<!-- -->
<p>Speed:</p>
<p class="state-value">
{componentState.speed}
</p>
<!-- -->
<p>Autoplay:</p>
<p class="state-value">
<span class="tag">{componentState.autoplay}</span>
</p>
<!-- -->
<p>Loop:</p>
<p class="state-value">
<span class="tag">{componentState.loop}</span>
{componentState.loop ? `(Loop count: ${componentState.loopCount})` : ''}
</p>
<!-- -->
<p>Mode:</p>
<p class="state-value">
<span class="tag">{componentState.mode}</span>
</p>
<!-- -->
<p>Layout:</p>
<p class="state-value">
{JSON.stringify(componentState.layout)}
</p>
<!-- -->
{#if Object.keys(componentState.allMarkers).length}
<p>All markers:</p>
<p class="state-value">
{componentState.allMarkers}
</p>
{/if}
<!-- -->
{#if componentState.marker}
<p>Active marker:</p>
<p class="state-value">
{componentState.marker}
</p>
{/if}
<!-- -->
{#if componentState.allThemes.length}
<p>All themes:</p>
<p class="state-value">
{componentState.allThemes.join(', ')}
</p>
{/if}
{#if componentState.activeThemeId}
<p>Active theme ID:</p>
<p class="state-value">
{componentState.activeThemeId}
</p>
{/if}
<!-- -->
<p>isPaused:</p>
<p class="state-value">
<span class="tag">{componentState.isPaused}</span>
</p>
<!-- -->
<p>isPlaying:</p>
<p class="state-value">
<span class="tag">{componentState.isPlaying}</span>
</p>
<!-- -->
<p>isStopped:</p>
<p class="state-value">
<span class="tag">{componentState.isStopped}</span>
</p>
<!-- -->
<p>isLoaded:</p>
<p class="state-value">
<span class="tag">{componentState.isLoaded}</span>
</p>
<!-- -->
<p>isFrozen:</p>
<p class="state-value">
<span class="tag">{componentState.isFrozen}</span>
</p>
</div>
</details>
</div>

<style lang="scss">
.debug-info {
position: absolute;
top: 0;
left: 0;
background-color: rgba(0, 0, 0, 1);
z-index: 3;
margin: 0;
width: 50vmin;
min-width: 50vmin;
padding: 8px;
border-radius: 8px;
overflow: auto;
resize: horizontal;
opacity: 0.6;
transition: opacity 0.3s ease;
filter: drop-shadow(0 0 16px rgba(0, 0, 0, 0.5));

@media (prefers-reduced-motion: no-preference) {
interpolate-size: allow-keywords;
}

&::details-content {
opacity: 0;
block-size: 0;
overflow-y: clip;
transition:
content-visibility 0.4s allow-discrete,
opacity 0.4s,
block-size 0.4s cubic-bezier(0.87, 0, 0.13, 1);
}

&[open]::details-content {
opacity: 1;
block-size: auto;
}

.title {
width: 100%;
font-family: var(--theme-font-family-monospace);
color: white;
margin: 0;
}

* {
user-select: none;
}
}

.debug-info[open] {
opacity: 1;
}

div.state-debug {
display: grid;
width: 100%;
padding: 8px 8px 16px 8px;
grid-template-columns: 20vmin 1fr;
align-items: center;
gap: 0.75rem 0.25rem;
background-color: #1e1e1e;
border-radius: 4px;
margin-top: 8px;
}

p {
font-size: var(--theme-font-size-xxs);
font-family: var(--theme-font-family-monospace);
padding: 0;
margin: 0;
color: rgba(255, 255, 255, 0.7);
overflow-wrap: anywhere;
line-height: 100%;
font-variant: tabular-nums;
}

.state-value {
color: white;
}

#video-progress-bar {
width: 100%;
background-color: rgba(255, 255, 255, 0.2);
height: 2px;
border-radius: 50px;
// margin: auto;

div {
background-color: white;
border-radius: 50px;
}
}

.tag {
padding: 0.1rem 0.2rem;
border-radius: 4px;
background-color: rgba(255, 255, 255, 0.2);
text-transform: uppercase;
font-weight: 500;
}
</style>
Loading