Skip to content

Commit 8c9361f

Browse files
committed
refactor: ♻️ add tiktok embed
1 parent 71aa9ec commit 8c9361f

File tree

5 files changed

+212
-1
lines changed

5 files changed

+212
-1
lines changed

.vscode/settings.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,5 +4,6 @@
44
"source.organizeImports": "explicit"
55
},
66
"git.enableSmartCommit": true,
7-
"git.postCommitCommand": "sync"
7+
"git.postCommitCommand": "sync",
8+
"cSpell.words": ["tiktok"]
89
}

apps/web/src/routes/+page.md

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
SoundCloud,
1616
Spotify,
1717
StackBlitz,
18+
TikTok,
1819
Toot,
1920
Tweet,
2021
Vimeo,
@@ -142,6 +143,7 @@ or open a [PR](https://github.com/spences10/sveltekit-embed/pulls).
142143
- [SoundCloud](#soundcloud)
143144
- [Spotify](#spotify)
144145
- [StackBlitz](#stackblitz)
146+
- [TikTok](#tiktok)
145147
- [Toot](#toot)
146148
- [Tweet](#tweet)
147149
- [Vimeo](#vimeo)
@@ -559,6 +561,57 @@ Output:
559561
hideNavigation
560562
/>
561563

564+
## TikTok
565+
566+
Props:
567+
568+
```ts
569+
tiktokId: string;
570+
width?: string = '100%';
571+
height?: string = '600px';
572+
controls?: boolean = true;
573+
progress_bar?: boolean = true;
574+
play_button?: boolean = true;
575+
volume_control?: boolean = true;
576+
fullscreen_button?: boolean = true;
577+
timestamp?: boolean = true;
578+
loop?: boolean = false;
579+
autoplay?: boolean = false;
580+
music_info?: boolean = false;
581+
description?: boolean = false;
582+
rel?: boolean = true;
583+
native_context_menu?: boolean = true;
584+
closed_caption?: boolean = true;
585+
disable_observer?: boolean = false;
586+
```
587+
588+
Usage:
589+
590+
```html
591+
<TikTok
592+
tiktokId="6718335390845095173"
593+
width="100%"
594+
height="600px"
595+
autoplay="{false}"
596+
loop="{true}"
597+
music_info="{true}"
598+
description="{true}"
599+
/>
600+
```
601+
602+
Output:
603+
604+
<TikTok
605+
disable_observer={$disable_observer_store}
606+
tiktokId="6718335390845095173"
607+
width="100%"
608+
height="600px"
609+
autoplay={false}
610+
loop={true}
611+
music_info={true}
612+
description={true}
613+
/>
614+
562615
## Toot
563616

564617
Props:
Lines changed: 88 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,88 @@
1+
<script lang="ts">
2+
import GeneralObserver from './general-observer.svelte';
3+
4+
interface Props {
5+
tiktokId: string;
6+
width?: string;
7+
height?: string;
8+
controls?: boolean;
9+
progress_bar?: boolean;
10+
play_button?: boolean;
11+
volume_control?: boolean;
12+
fullscreen_button?: boolean;
13+
timestamp?: boolean;
14+
loop?: boolean;
15+
autoplay?: boolean;
16+
music_info?: boolean;
17+
description?: boolean;
18+
rel?: boolean;
19+
native_context_menu?: boolean;
20+
closed_caption?: boolean;
21+
disable_observer?: boolean;
22+
}
23+
24+
let {
25+
tiktokId,
26+
width = '100%',
27+
height = '600px',
28+
controls = true,
29+
progress_bar = true,
30+
play_button = true,
31+
volume_control = true,
32+
fullscreen_button = true,
33+
timestamp = true,
34+
loop = false,
35+
autoplay = false,
36+
music_info = false,
37+
description = false,
38+
rel = true,
39+
native_context_menu = true,
40+
closed_caption = true,
41+
disable_observer = false,
42+
}: Props = $props();
43+
44+
const query_params = new URLSearchParams({
45+
controls: controls ? '1' : '0',
46+
progress_bar: progress_bar ? '1' : '0',
47+
play_button: play_button ? '1' : '0',
48+
volume_control: volume_control ? '1' : '0',
49+
fullscreen_button: fullscreen_button ? '1' : '0',
50+
timestamp: timestamp ? '1' : '0',
51+
loop: loop ? '1' : '0',
52+
autoplay: autoplay ? '1' : '0',
53+
music_info: music_info ? '1' : '0',
54+
description: description ? '1' : '0',
55+
rel: rel ? '1' : '0',
56+
native_context_menu: native_context_menu ? '1' : '0',
57+
closed_caption: closed_caption ? '1' : '0',
58+
});
59+
60+
const src = `https://www.tiktok.com/player/v1/${tiktokId}?${query_params.toString()}`;
61+
</script>
62+
63+
<GeneralObserver {disable_observer}>
64+
<div
65+
class="tiktok-sveltekit-embed"
66+
style={`
67+
position: relative;
68+
width: ${width};
69+
height: ${height};
70+
`}
71+
>
72+
<iframe
73+
data-testid="tiktok-embed"
74+
title={`tiktok-${tiktokId}`}
75+
{src}
76+
frameborder="0"
77+
scrolling="no"
78+
allow="encrypted-media; picture-in-picture; fullscreen"
79+
style={`
80+
position: absolute;
81+
top: 0;
82+
left: 0;
83+
width: 100%;
84+
height: 100%;
85+
`}
86+
></iframe>
87+
</div>
88+
</GeneralObserver>
Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
import TikTok from '$lib/components/tiktok.svelte';
2+
import { cleanup, render } from '@testing-library/svelte/svelte5';
3+
import { afterEach, describe, expect, it } from 'vitest';
4+
5+
describe('TikTok', () => {
6+
afterEach(cleanup);
7+
8+
it('mounts with default props', async () => {
9+
const { container } = render(TikTok, {
10+
tiktokId: '6718335390845095173',
11+
});
12+
expect(container).toBeTruthy();
13+
});
14+
15+
it('renders iframe with correct src', async () => {
16+
const tiktokId = '6718335390845095173';
17+
const { getByTestId } = render(TikTok, {
18+
tiktokId,
19+
disable_observer: true,
20+
});
21+
const iframe = getByTestId('tiktok-embed');
22+
const expected_src = `https://www.tiktok.com/player/v1/${tiktokId}?controls=1&progress_bar=1&play_button=1&volume_control=1&fullscreen_button=1&timestamp=1&loop=0&autoplay=0&music_info=0&description=0&rel=1&native_context_menu=1&closed_caption=1`;
23+
expect(iframe.getAttribute('src')).toBe(expected_src);
24+
});
25+
26+
it('mounts with custom height and width', async () => {
27+
const { container } = render(TikTok, {
28+
tiktokId: '6718335390845095173',
29+
height: '400px',
30+
width: '50%',
31+
disable_observer: true,
32+
});
33+
const div = container.querySelector('.tiktok-sveltekit-embed');
34+
35+
expect(div?.getAttribute('style')).toContain('height: 400px');
36+
expect(div?.getAttribute('style')).toContain('width: 50%');
37+
});
38+
39+
it('renders with custom options', async () => {
40+
const tiktokId = '6718335390845095173';
41+
const { getByTestId } = render(TikTok, {
42+
tiktokId,
43+
controls: false,
44+
loop: true,
45+
autoplay: true,
46+
music_info: true,
47+
description: true,
48+
disable_observer: true,
49+
});
50+
const iframe = getByTestId('tiktok-embed');
51+
const src = iframe.getAttribute('src');
52+
53+
expect(src).toContain('controls=0');
54+
expect(src).toContain('loop=1');
55+
expect(src).toContain('autoplay=1');
56+
expect(src).toContain('music_info=1');
57+
expect(src).toContain('description=1');
58+
});
59+
60+
it('renders with a GeneralObserver', async () => {
61+
const { getByTestId } = render(TikTok, {
62+
tiktokId: '6718335390845095173',
63+
disable_observer: false,
64+
});
65+
const general_observer = getByTestId('general-observer');
66+
expect(general_observer).toBeTruthy();
67+
});
68+
});

packages/sveltekit-embed/src/lib/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ export { default as Slides } from './components/slides.svelte';
1212
export { default as SoundCloud } from './components/sound-cloud.svelte';
1313
export { default as Spotify } from './components/spotify.svelte';
1414
export { default as StackBlitz } from './components/stackblitz.svelte';
15+
export { default as TikTok } from './components/tiktok.svelte';
1516
export { default as Toot } from './components/toot.svelte';
1617
export { default as Tweet } from './components/tweet.svelte';
1718
export { default as Vimeo } from './components/vimeo.svelte';

0 commit comments

Comments
 (0)