Last active
January 18, 2023 03:33
-
-
Save leandrohsilveira/1d36bc71ea6aebce59ac57b1e1c9effd to your computer and use it in GitHub Desktop.
Using RXJS Observables in Svelte with autosubscribe feature
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<script lang="ts"> | |
import { map } from 'rxjs'; | |
import { count$, evenCount$, oddCount$ } from './counter'; | |
import { toReadable, toWritable } from './util'; | |
let count = toWritable(count$); | |
let lastEven = toReadable(evenCount$.pipe(map(String)), 'none') | |
let lastOdd = toReadable(oddCount$.pipe(map(String)), 'none') | |
</script> | |
<div class="counter"> | |
<button on:click={() => ($count -= 1)} aria-label="Decrease the counter by one"> | |
<svg aria-hidden="true" viewBox="0 0 1 1"> | |
<path d="M0,0.5 L1,0.5" /> | |
</svg> | |
</button> | |
<div class="counter-viewport"> | |
<div class="counter-digits"> | |
<strong>{Math.floor($count)}</strong> | |
</div> | |
</div> | |
<button on:click={() => ($count += 1)} aria-label="Increase the counter by one"> | |
<svg aria-hidden="true" viewBox="0 0 1 1"> | |
<path d="M0,0.5 L1,0.5 M0.5,0 L0.5,1" /> | |
</svg> | |
</button> | |
</div> | |
Last even: {$lastEven} | |
Last odd: {$lastOdd} | |
<style> | |
.counter { | |
display: flex; | |
border-top: 1px solid rgba(0, 0, 0, 0.1); | |
border-bottom: 1px solid rgba(0, 0, 0, 0.1); | |
margin: 1rem 0; | |
} | |
.counter button { | |
width: 2em; | |
padding: 0; | |
display: flex; | |
align-items: center; | |
justify-content: center; | |
border: 0; | |
background-color: transparent; | |
touch-action: manipulation; | |
color: var(--text-color); | |
font-size: 2rem; | |
} | |
.counter button:hover { | |
background-color: var(--secondary-color); | |
} | |
svg { | |
width: 25%; | |
height: 25%; | |
} | |
path { | |
vector-effect: non-scaling-stroke; | |
stroke-width: 2px; | |
stroke: var(--text-color); | |
} | |
.counter-viewport { | |
width: 8em; | |
height: 4em; | |
overflow: hidden; | |
text-align: center; | |
position: relative; | |
} | |
.counter-viewport strong { | |
position: absolute; | |
display: flex; | |
width: 100%; | |
height: 100%; | |
font-weight: 400; | |
color: var(--accent-color); | |
font-size: 4rem; | |
align-items: center; | |
justify-content: center; | |
} | |
.counter-digits { | |
position: absolute; | |
width: 100%; | |
height: 100%; | |
} | |
</style> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import { BehaviorSubject, filter } from 'rxjs'; | |
export const count$ = new BehaviorSubject(0); | |
export const evenCount$ = count$.pipe(filter((value) => value % 2 === 0)); | |
export const oddCount$ = count$.pipe(filter((value) => value % 2 !== 0)); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import { Observable, type Subject } from 'rxjs'; | |
import { get, readable, type Readable, type Writable } from 'svelte/store'; | |
export function toReadable<T>(observable: Observable<T>, initialValue?: T): Readable<T> { | |
return readable<T>(initialValue, (next) => { | |
const subscription = observable.subscribe({ next }); | |
return () => subscription.unsubscribe(); | |
}); | |
} | |
export function toWritable<T>(subject: Subject<T>, initialValue?: T): Writable<T> { | |
const readable = toReadable(subject, initialValue); | |
return { | |
...readable, | |
set(value) { | |
subject.next(value); | |
}, | |
update(updater) { | |
subject.next(updater(get(readable))); | |
} | |
}; | |
} | |
export function fromReadable<T>(readable: Readable<T>): Observable<T> { | |
return new Observable((observer) => readable.subscribe((value) => observer.next(value))); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment