react-rx 1.0.0 → 2.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.idea/compiler.xml +1 -1
- package/.idea/inspectionProfiles/Project_Default.xml +1 -0
- package/.idea/markdown.xml +9 -0
- package/.idea/misc.xml +0 -6
- package/dist/cjs/displayName.js +1 -1
- package/dist/cjs/useAsObservable.js +9 -17
- package/dist/cjs/useObservable.js +25 -30
- package/dist/cjs/withPropsStream.js +5 -1
- package/dist/es2015/useAsObservable.js +10 -18
- package/dist/es2015/useObservable.js +24 -31
- package/dist/esm/displayName.js +1 -1
- package/dist/esm/useAsObservable.js +10 -18
- package/dist/esm/useObservable.js +26 -31
- package/package.json +6 -4
- package/src/useAsObservable.ts +13 -18
- package/src/useObservable.ts +39 -34
- package/.idea/workspace.xml +0 -226
- package/jest.config.js +0 -5
- package/website/.babelrc +0 -21
- package/website/.prettierrc +0 -7
- package/website/README.mdx +0 -1
- package/website/package.json +0 -84
- package/website/src/@types/babel.d.ts +0 -4
- package/website/src/@types/mdx.d.ts +0 -11
- package/website/src/@types/react-css-burger.d.ts +0 -4
- package/website/src/App.tsx +0 -68
- package/website/src/components/Header.tsx +0 -118
- package/website/src/components/Link.tsx +0 -18
- package/website/src/components/LoadPage.tsx +0 -60
- package/website/src/components/Sidebar.tsx +0 -88
- package/website/src/components/logos/Github.tsx +0 -10
- package/website/src/components/logos/React.tsx +0 -27
- package/website/src/components/logos/ReactRxLogo.tsx +0 -39
- package/website/src/components/logos/RxJs.tsx +0 -69
- package/website/src/components/repl/Checkerboard.tsx +0 -25
- package/website/src/components/repl/CodeBlock.tsx +0 -147
- package/website/src/components/repl/CodeMirror.tsx +0 -37
- package/website/src/components/repl/CodeMirrorMode.tsx +0 -67
- package/website/src/components/repl/EvalCode.tsx +0 -55
- package/website/src/components/repl/Prelude.tsx +0 -50
- package/website/src/components/repl/ShowError.tsx +0 -27
- package/website/src/components/repl/codemirror-lib.ts +0 -8
- package/website/src/components/repl/codemirror-theme.css +0 -131
- package/website/src/components/repl/compile/babel.ts +0 -21
- package/website/src/components/repl/eval/evalCallback.ts +0 -27
- package/website/src/components/repl/eval/evalCode.ts +0 -7
- package/website/src/components/repl/eval/evalExpression.ts +0 -4
- package/website/src/components/repl/eval/evalReactDomRender.ts +0 -23
- package/website/src/components/repl/index.ts +0 -1
- package/website/src/components/repl/runMode.ts +0 -42
- package/website/src/datastores/location.ts +0 -14
- package/website/src/datastores/page.ts +0 -11
- package/website/src/datastores/pageTransition.ts +0 -97
- package/website/src/entries/main.css +0 -2
- package/website/src/entries/main.tsx +0 -6
- package/website/src/examples/FizzBuzz/FizzBuzzExample.tsx +0 -39
- package/website/src/examples/FizzBuzz/index.tsx +0 -9
- package/website/src/examples/_utils/globalScope.ts +0 -45
- package/website/src/examples/animation/AnimationExample.tsx +0 -152
- package/website/src/examples/animation/easings.ts +0 -0
- package/website/src/examples/animation/index.tsx +0 -15
- package/website/src/examples/context/Context.example.jsx +0 -67
- package/website/src/examples/context/index.tsx +0 -9
- package/website/src/examples/errors/Errors.example.jsx +0 -69
- package/website/src/examples/errors/index.tsx +0 -9
- package/website/src/examples/event-handlers/EventHandlersExample.tsx +0 -48
- package/website/src/examples/event-handlers/index.tsx +0 -9
- package/website/src/examples/fetch/FetchExample.jsx +0 -43
- package/website/src/examples/fetch/a.txt +0 -1
- package/website/src/examples/fetch/b.txt +0 -1
- package/website/src/examples/fetch/index.tsx +0 -9
- package/website/src/examples/form-data/FormDataExample.jsx +0 -119
- package/website/src/examples/form-data/index.tsx +0 -12
- package/website/src/examples/form-data/storage.ts +0 -27
- package/website/src/examples/forward-ref/ForwardRefExample.tsx +0 -55
- package/website/src/examples/forward-ref/index.tsx +0 -9
- package/website/src/examples/hello-world/HelloWorld.example.jsx +0 -6
- package/website/src/examples/hello-world/index.tsx +0 -9
- package/website/src/examples/hooks-interop/HooksInterop.example.tsx +0 -42
- package/website/src/examples/hooks-interop/index.tsx +0 -9
- package/website/src/examples/passthrough-props/PassThroughPropsExample.jsx +0 -57
- package/website/src/examples/passthrough-props/index.tsx +0 -11
- package/website/src/examples/reactive-state/ReactiveState.example.jsx +0 -43
- package/website/src/examples/reactive-state/index.ts +0 -9
- package/website/src/examples/readme-examples/README.mdx +0 -0
- package/website/src/examples/readme-examples/index.ts +0 -11
- package/website/src/examples/shared-state/SharedState.example.tsx +0 -59
- package/website/src/examples/shared-state/index.tsx +0 -9
- package/website/src/examples/simple/Counter.example.tsx +0 -14
- package/website/src/examples/simple/index.tsx +0 -9
- package/website/src/examples/sync/Sync.example.tsx +0 -9
- package/website/src/examples/sync/index.tsx +0 -9
- package/website/src/examples/tick/TickExample.jsx +0 -51
- package/website/src/examples/tick/index.ts +0 -9
- package/website/src/examples/todo-app/TodoApp.example.tsx +0 -88
- package/website/src/examples/todo-app/index.tsx +0 -12
- package/website/src/examples/todo-app/storage.ts +0 -27
- package/website/src/examples/use-element/UseElementExample.tsx +0 -70
- package/website/src/examples/use-element/index.tsx +0 -9
- package/website/src/examples/use-observable/search/SearchExample.tsx +0 -82
- package/website/src/examples/use-observable/search/index.tsx +0 -8
- package/website/src/examples/use-observable/use-observable/UseObservableExample.tsx +0 -70
- package/website/src/examples/use-observable/use-observable/index.tsx +0 -9
- package/website/src/index.html +0 -10
- package/website/src/mdx-components.tsx +0 -74
- package/website/src/pages/Api/Api.mdx +0 -134
- package/website/src/pages/Api/ApiPage.tsx +0 -25
- package/website/src/pages/Examples/Examples.tsx +0 -105
- package/website/src/pages/Examples/ExamplesPage.tsx +0 -13
- package/website/src/pages/Guide/Guide.mdx +0 -275
- package/website/src/pages/Guide/GuidePage.tsx +0 -25
- package/website/src/pages/Index/IndexPage.tsx +0 -50
- package/website/src/pages/Index/ReactRxReadme.md +0 -20
- package/website/src/pages/NotFound.tsx +0 -3
- package/website/src/pages/pages.ts +0 -46
- package/website/src/pages/styles.tsx +0 -24
- package/website/src/theme.ts +0 -61
- package/website/src/utils/parseCodeFenceHeader.ts +0 -32
- package/website/tsconfig.json +0 -30
- package/website/vercel.json +0 -4
- package/website/webpack/config.js +0 -5
- package/website/webpack/createConfig.js +0 -95
- package/website/webpack/mdx-toc-loader.js +0 -38
|
@@ -1,9 +0,0 @@
|
|
|
1
|
-
import {Example} from '../../pages/Examples/Examples'
|
|
2
|
-
|
|
3
|
-
const fs = require('fs')
|
|
4
|
-
|
|
5
|
-
export const ReactiveStateExample: Example = {
|
|
6
|
-
id: 'reactive-state',
|
|
7
|
-
title: 'Reactive component state',
|
|
8
|
-
source: fs.readFileSync(`${__dirname}/ReactiveState.example.jsx`, 'utf-8')
|
|
9
|
-
}
|
|
File without changes
|
|
@@ -1,11 +0,0 @@
|
|
|
1
|
-
import ReadmeExamples from './README.mdx'
|
|
2
|
-
|
|
3
|
-
const fs = require('fs')
|
|
4
|
-
|
|
5
|
-
export default {
|
|
6
|
-
name: 'readme-examples',
|
|
7
|
-
component: ReadmeExamples,
|
|
8
|
-
title: 'Readme examples',
|
|
9
|
-
type: 'mixed',
|
|
10
|
-
source: fs.readFileSync(`${__dirname}/ReadmeExamples.tsx`, 'utf-8')
|
|
11
|
-
}
|
|
@@ -1,59 +0,0 @@
|
|
|
1
|
-
import {
|
|
2
|
-
map,
|
|
3
|
-
of,
|
|
4
|
-
React,
|
|
5
|
-
ReactDOM,
|
|
6
|
-
rxComponent,
|
|
7
|
-
scan
|
|
8
|
-
} from '../_utils/globalScope'
|
|
9
|
-
|
|
10
|
-
import {observableCallback} from 'observable-callback'
|
|
11
|
-
import {CSSProperties} from 'react'
|
|
12
|
-
//@endimport
|
|
13
|
-
|
|
14
|
-
const CONTAINER: CSSProperties = {
|
|
15
|
-
display: 'flex',
|
|
16
|
-
alignItems: 'center',
|
|
17
|
-
position: 'relative',
|
|
18
|
-
height: 200,
|
|
19
|
-
width: 200,
|
|
20
|
-
textAlign: 'center'
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
const BADGE: CSSProperties = {
|
|
24
|
-
borderRadius: 26,
|
|
25
|
-
backgroundColor: 'red',
|
|
26
|
-
padding: 4,
|
|
27
|
-
height: 26,
|
|
28
|
-
width: 26
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
const [clicks$, click] = observableCallback()
|
|
32
|
-
const clickCount$ = clicks$.pipe(scan((count) => count + 1, 0))
|
|
33
|
-
|
|
34
|
-
const ClickCountBadge = rxComponent(
|
|
35
|
-
clickCount$.pipe(map((clicks) => <span style={BADGE}>{clicks}</span>))
|
|
36
|
-
)
|
|
37
|
-
|
|
38
|
-
const Clicker = rxComponent(of(<button onClick={click}>CLICK ME!</button>))
|
|
39
|
-
|
|
40
|
-
const Example = (
|
|
41
|
-
<div style={CONTAINER}>
|
|
42
|
-
<div style={{position: 'absolute', top: 0, left: 0}}>
|
|
43
|
-
<ClickCountBadge />
|
|
44
|
-
</div>
|
|
45
|
-
<div style={{position: 'absolute', top: 0, right: 0}}>
|
|
46
|
-
<ClickCountBadge />
|
|
47
|
-
</div>
|
|
48
|
-
<div style={{width: '100%'}}>
|
|
49
|
-
<Clicker />
|
|
50
|
-
</div>
|
|
51
|
-
<div style={{position: 'absolute', bottom: 0, left: 0}}>
|
|
52
|
-
<ClickCountBadge />
|
|
53
|
-
</div>
|
|
54
|
-
<div style={{position: 'absolute', bottom: 0, right: 0}}>
|
|
55
|
-
<ClickCountBadge />
|
|
56
|
-
</div>
|
|
57
|
-
</div>
|
|
58
|
-
)
|
|
59
|
-
ReactDOM.render(Example, document.getElementById('shared-state-example'))
|
|
@@ -1,14 +0,0 @@
|
|
|
1
|
-
import {
|
|
2
|
-
map,
|
|
3
|
-
React,
|
|
4
|
-
ReactDOM,
|
|
5
|
-
rxComponent,
|
|
6
|
-
timer
|
|
7
|
-
} from '../_utils/globalScope'
|
|
8
|
-
//@endimport
|
|
9
|
-
|
|
10
|
-
const Counter = rxComponent(
|
|
11
|
-
timer(0, 1000).pipe(map(seconds => <>Seconds: {seconds}</>))
|
|
12
|
-
)
|
|
13
|
-
|
|
14
|
-
ReactDOM.render(<Counter />, document.getElementById('counter-example'))
|
|
@@ -1,9 +0,0 @@
|
|
|
1
|
-
import * as React from 'react'
|
|
2
|
-
import {from, ReactDOM, rxComponent} from '../_utils/globalScope'
|
|
3
|
-
//@endimport
|
|
4
|
-
|
|
5
|
-
const Sync = rxComponent(
|
|
6
|
-
from(['This', 'will', 'only', 'render', 'once!'])
|
|
7
|
-
)
|
|
8
|
-
|
|
9
|
-
ReactDOM.render(<Sync />, document.getElementById('counter-example'))
|
|
@@ -1,51 +0,0 @@
|
|
|
1
|
-
import {
|
|
2
|
-
map,
|
|
3
|
-
mapTo,
|
|
4
|
-
React,
|
|
5
|
-
ReactDOM,
|
|
6
|
-
rxComponent,
|
|
7
|
-
startWith,
|
|
8
|
-
switchMap,
|
|
9
|
-
timer
|
|
10
|
-
} from '../_utils/globalScope'
|
|
11
|
-
//@endimport
|
|
12
|
-
|
|
13
|
-
const {distinctUntilChanged, sampleTime} = operators
|
|
14
|
-
|
|
15
|
-
const Ticker = rxComponent(props$ =>
|
|
16
|
-
props$.pipe(
|
|
17
|
-
map(props => props.tick),
|
|
18
|
-
distinctUntilChanged(),
|
|
19
|
-
switchMap(tick => timer(300).pipe(mapTo(tick))),
|
|
20
|
-
startWith(0),
|
|
21
|
-
map(tick => `Delayed tick: ${tick}`)
|
|
22
|
-
)
|
|
23
|
-
)
|
|
24
|
-
|
|
25
|
-
const TickerWithSubTick = rxComponent(props$ =>
|
|
26
|
-
props$.pipe(
|
|
27
|
-
map(props => props.tick),
|
|
28
|
-
distinctUntilChanged(),
|
|
29
|
-
switchMap(tick => timer(0, 10).pipe(map(subtick => ({tick, subtick})))),
|
|
30
|
-
sampleTime(20),
|
|
31
|
-
map(props => (
|
|
32
|
-
<div>
|
|
33
|
-
{props.tick}:{props.subtick}
|
|
34
|
-
</div>
|
|
35
|
-
))
|
|
36
|
-
)
|
|
37
|
-
)
|
|
38
|
-
|
|
39
|
-
const TickExample = rxComponent(
|
|
40
|
-
timer(0, 1000).pipe(
|
|
41
|
-
map(tick => (
|
|
42
|
-
<>
|
|
43
|
-
<div>Tick: {tick}</div>
|
|
44
|
-
<Ticker tick={tick} />
|
|
45
|
-
<TickerWithSubTick tick={tick} />
|
|
46
|
-
</>
|
|
47
|
-
))
|
|
48
|
-
)
|
|
49
|
-
)
|
|
50
|
-
|
|
51
|
-
ReactDOM.render(<TickExample />, document.getElementById('ticker-example'))
|
|
@@ -1,88 +0,0 @@
|
|
|
1
|
-
import {ChangeEvent, FormEvent} from 'react'
|
|
2
|
-
import {
|
|
3
|
-
combineLatest,
|
|
4
|
-
filter,
|
|
5
|
-
map,
|
|
6
|
-
mapTo,
|
|
7
|
-
merge,
|
|
8
|
-
operators,
|
|
9
|
-
React,
|
|
10
|
-
ReactDOM,
|
|
11
|
-
rxComponent,
|
|
12
|
-
scan,
|
|
13
|
-
startWith,
|
|
14
|
-
tap,
|
|
15
|
-
handler
|
|
16
|
-
} from '../_utils/globalScope'
|
|
17
|
-
import styled from 'styled-components'
|
|
18
|
-
//@endimport
|
|
19
|
-
|
|
20
|
-
const {withLatestFrom} = operators
|
|
21
|
-
|
|
22
|
-
interface TodoItem {
|
|
23
|
-
id: number
|
|
24
|
-
text: string
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
const TodoApp = rxComponent(() => {
|
|
28
|
-
const [onInput$, handleInput] = handler<ChangeEvent<HTMLInputElement>>()
|
|
29
|
-
const [onSubmit$, handleSubmit] = handler<FormEvent<HTMLFormElement>>()
|
|
30
|
-
|
|
31
|
-
const text$ = onInput$.pipe(
|
|
32
|
-
map(e => e.currentTarget.value),
|
|
33
|
-
startWith('')
|
|
34
|
-
)
|
|
35
|
-
|
|
36
|
-
const items$ = onSubmit$.pipe(
|
|
37
|
-
tap(e => e.preventDefault()),
|
|
38
|
-
withLatestFrom(text$),
|
|
39
|
-
map(([_, text]) => text),
|
|
40
|
-
filter(text => text.length > 0),
|
|
41
|
-
map(text => ({text, id: Date.now()})),
|
|
42
|
-
scan((items: TodoItem[], item) => items.concat(item), []),
|
|
43
|
-
startWith([])
|
|
44
|
-
)
|
|
45
|
-
|
|
46
|
-
const inputValue$ = merge(text$, onSubmit$.pipe(mapTo('')))
|
|
47
|
-
|
|
48
|
-
return combineLatest([inputValue$, items$]).pipe(
|
|
49
|
-
map(([text, items]) => (
|
|
50
|
-
<Wrapper>
|
|
51
|
-
<h3>TODO</h3>
|
|
52
|
-
<TodoList items={items} />
|
|
53
|
-
<form onSubmit={handleSubmit}>
|
|
54
|
-
<label htmlFor="new-todo">What needs to be done?</label>
|
|
55
|
-
<input id="new-todo" onChange={handleInput} value={text} />
|
|
56
|
-
<button>Add #{items.length + 1}</button>
|
|
57
|
-
</form>
|
|
58
|
-
</Wrapper>
|
|
59
|
-
))
|
|
60
|
-
)
|
|
61
|
-
})
|
|
62
|
-
|
|
63
|
-
interface ListProps {
|
|
64
|
-
items: TodoItem[]
|
|
65
|
-
}
|
|
66
|
-
|
|
67
|
-
function TodoList(props: ListProps) {
|
|
68
|
-
return (
|
|
69
|
-
<ul>
|
|
70
|
-
{props.items.map(item => (
|
|
71
|
-
<li key={item.id}>{item.text}</li>
|
|
72
|
-
))}
|
|
73
|
-
</ul>
|
|
74
|
-
)
|
|
75
|
-
}
|
|
76
|
-
|
|
77
|
-
ReactDOM.render(<TodoApp />, document.getElementById('todo-app-example'))
|
|
78
|
-
|
|
79
|
-
const Wrapper = styled.div`
|
|
80
|
-
label {
|
|
81
|
-
display: block;
|
|
82
|
-
margin-top: 10px;
|
|
83
|
-
}
|
|
84
|
-
input {
|
|
85
|
-
width: 100%;
|
|
86
|
-
padding: 5px;
|
|
87
|
-
}
|
|
88
|
-
`
|
|
@@ -1,12 +0,0 @@
|
|
|
1
|
-
import {Example} from '../../pages/Examples/Examples'
|
|
2
|
-
import storage from './storage'
|
|
3
|
-
import styled from 'styled-components'
|
|
4
|
-
|
|
5
|
-
const fs = require('fs')
|
|
6
|
-
|
|
7
|
-
export const TodoAppExample: Example = {
|
|
8
|
-
id: 'todo-app',
|
|
9
|
-
title: 'An Application',
|
|
10
|
-
scope: {storage, styled},
|
|
11
|
-
source: fs.readFileSync(`${__dirname}/TodoApp.example.tsx`, 'utf-8')
|
|
12
|
-
}
|
|
@@ -1,27 +0,0 @@
|
|
|
1
|
-
import {Observable, of} from 'rxjs'
|
|
2
|
-
|
|
3
|
-
const tryParse = <T>(val: any, defaultValue: T): T => {
|
|
4
|
-
try {
|
|
5
|
-
return JSON.parse(val)
|
|
6
|
-
} catch (err) {
|
|
7
|
-
return defaultValue
|
|
8
|
-
}
|
|
9
|
-
}
|
|
10
|
-
|
|
11
|
-
const get = <T>(key: string, defValue: T): Observable<T> => {
|
|
12
|
-
const val = localStorage.getItem(key)
|
|
13
|
-
return of(val === null ? defValue : tryParse<T>(val, defValue))
|
|
14
|
-
}
|
|
15
|
-
|
|
16
|
-
const set = <T>(key: string, nextValue: T): Observable<T> => {
|
|
17
|
-
// Can't stringify undefined, and nulls are what
|
|
18
|
-
// `getItem` returns when key does not exist
|
|
19
|
-
if (typeof nextValue === 'undefined' || nextValue === null) {
|
|
20
|
-
localStorage.removeItem(key)
|
|
21
|
-
} else {
|
|
22
|
-
localStorage.setItem(key, JSON.stringify(nextValue))
|
|
23
|
-
}
|
|
24
|
-
return of(nextValue)
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
export default {get, set}
|
|
@@ -1,70 +0,0 @@
|
|
|
1
|
-
import {
|
|
2
|
-
map,
|
|
3
|
-
elementRef,
|
|
4
|
-
operators,
|
|
5
|
-
React,
|
|
6
|
-
ReactDOM,
|
|
7
|
-
rxComponent,
|
|
8
|
-
timer
|
|
9
|
-
} from '../_utils/globalScope'
|
|
10
|
-
|
|
11
|
-
//@endimport
|
|
12
|
-
|
|
13
|
-
const {withLatestFrom} = operators
|
|
14
|
-
|
|
15
|
-
const STYLE: React.CSSProperties = {
|
|
16
|
-
textAlign: 'center',
|
|
17
|
-
border: '1px dashed'
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
const SPEED = 2
|
|
21
|
-
const unpx = (v: string) => Number(v.replace(/px$/, ''))
|
|
22
|
-
|
|
23
|
-
const UseElementExample = rxComponent(() => {
|
|
24
|
-
const [element$, ref] = elementRef<HTMLElement>()
|
|
25
|
-
|
|
26
|
-
const count$ = timer(0, 16).pipe(
|
|
27
|
-
map((n) => n % 400),
|
|
28
|
-
map((n) => (n > 200 ? -1 : 1))
|
|
29
|
-
)
|
|
30
|
-
|
|
31
|
-
return count$.pipe(
|
|
32
|
-
withLatestFrom(element$),
|
|
33
|
-
map(([direction, element]) => {
|
|
34
|
-
const Tag = direction === 1 ? 'section' : 'article'
|
|
35
|
-
return (
|
|
36
|
-
<div style={{height: '20em', display: 'flex', alignItems: 'center'}}>
|
|
37
|
-
<Tag
|
|
38
|
-
// this connects the element$ observable to the actual element
|
|
39
|
-
ref={ref}
|
|
40
|
-
style={{
|
|
41
|
-
...STYLE,
|
|
42
|
-
backgroundColor: Tag == 'article' ? '#335186' : '#90441a',
|
|
43
|
-
borderRadius:
|
|
44
|
-
unpx(element?.style.borderRadius || '20px') +
|
|
45
|
-
direction * SPEED * -0.1,
|
|
46
|
-
height: (element?.clientHeight || 0) + direction * SPEED,
|
|
47
|
-
width: (element?.clientWidth || 0) + direction * SPEED
|
|
48
|
-
}}
|
|
49
|
-
>
|
|
50
|
-
<div
|
|
51
|
-
style={{
|
|
52
|
-
...(element && {fontSize: element.clientHeight / 5}),
|
|
53
|
-
width: '100%',
|
|
54
|
-
height: '100%',
|
|
55
|
-
lineHeight: '500%'
|
|
56
|
-
}}
|
|
57
|
-
>
|
|
58
|
-
{`<${Tag}>`}
|
|
59
|
-
</div>
|
|
60
|
-
</Tag>
|
|
61
|
-
</div>
|
|
62
|
-
)
|
|
63
|
-
})
|
|
64
|
-
)
|
|
65
|
-
})
|
|
66
|
-
|
|
67
|
-
ReactDOM.render(
|
|
68
|
-
<UseElementExample />,
|
|
69
|
-
document.getElementById('use-element-example')
|
|
70
|
-
)
|
|
@@ -1,82 +0,0 @@
|
|
|
1
|
-
import {
|
|
2
|
-
map,
|
|
3
|
-
React,
|
|
4
|
-
ReactDOM,
|
|
5
|
-
timer,
|
|
6
|
-
useMemoObservable,
|
|
7
|
-
of,
|
|
8
|
-
operators,
|
|
9
|
-
filter,
|
|
10
|
-
switchMap
|
|
11
|
-
} from '../../_utils/globalScope'
|
|
12
|
-
import {Observable} from 'rxjs'
|
|
13
|
-
//@endimport
|
|
14
|
-
|
|
15
|
-
const {distinctUntilChanged, debounceTime} = operators
|
|
16
|
-
|
|
17
|
-
interface SearchResult {
|
|
18
|
-
keyword: string
|
|
19
|
-
hits: Hit[]
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
interface Hit {
|
|
23
|
-
title: string
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
const range = (len: number) => {
|
|
27
|
-
const res = []
|
|
28
|
-
for (let i = 0; i <= len; i++) {
|
|
29
|
-
res.push(null)
|
|
30
|
-
}
|
|
31
|
-
return res
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
// A search function that takes longer time to complete for shorter keywords
|
|
35
|
-
// e.g. a keyword of one character takes 9 seconds while a keyword of 9 characters takes 1 second
|
|
36
|
-
const search = (keyword: string): Observable<SearchResult> => {
|
|
37
|
-
const delay = Math.max(1, Math.round(10 - keyword.length))
|
|
38
|
-
return timer(delay * 200).pipe(
|
|
39
|
-
map(() => range(delay).map((_, i) => ({title: `Hit #${i}`}))),
|
|
40
|
-
map((hits) => ({keyword, hits}))
|
|
41
|
-
)
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
function SearchExample() {
|
|
45
|
-
const [keyword, setKeyword] = React.useState('')
|
|
46
|
-
return (
|
|
47
|
-
<>
|
|
48
|
-
<input
|
|
49
|
-
type="search"
|
|
50
|
-
style={{width: '100%'}}
|
|
51
|
-
value={keyword}
|
|
52
|
-
placeholder="Type a keyword to search"
|
|
53
|
-
onChange={(event) => setKeyword(event.target.value)}
|
|
54
|
-
/>
|
|
55
|
-
<div>
|
|
56
|
-
The more characters you type, the faster the results will appear
|
|
57
|
-
</div>
|
|
58
|
-
{useMemoObservable(() =>
|
|
59
|
-
of(keyword).pipe(
|
|
60
|
-
debounceTime(200),
|
|
61
|
-
distinctUntilChanged(),
|
|
62
|
-
filter((v) => v !== ''),
|
|
63
|
-
switchMap((kw: string) => search(kw)),
|
|
64
|
-
map((result: SearchResult) => (
|
|
65
|
-
<>
|
|
66
|
-
<h1>Searched for {result.keyword}</h1>
|
|
67
|
-
<div>Got {result.hits.length} hits</div>
|
|
68
|
-
<ul>
|
|
69
|
-
{result.hits.map((hit, i) => (
|
|
70
|
-
<li key={i}>{hit.title}</li>
|
|
71
|
-
))}
|
|
72
|
-
</ul>
|
|
73
|
-
</>
|
|
74
|
-
))
|
|
75
|
-
),
|
|
76
|
-
[keyword]
|
|
77
|
-
)}
|
|
78
|
-
</>
|
|
79
|
-
)
|
|
80
|
-
}
|
|
81
|
-
|
|
82
|
-
ReactDOM.render(<SearchExample />, document.getElementById('search-example'))
|
|
@@ -1,70 +0,0 @@
|
|
|
1
|
-
import * as React from 'react'
|
|
2
|
-
import {Observable, of, timer} from 'rxjs'
|
|
3
|
-
import {ReactDOM, useMemoObservable} from '../../_utils/globalScope'
|
|
4
|
-
import {observableCallback} from 'observable-callback'
|
|
5
|
-
import {map, startWith, switchMap} from 'rxjs/operators'
|
|
6
|
-
//@endimport
|
|
7
|
-
|
|
8
|
-
const justNumbers$ = timer(0, 500)
|
|
9
|
-
|
|
10
|
-
const numberReactElement$ = justNumbers$.pipe(
|
|
11
|
-
map((num) => <div>The number is {num}!</div>)
|
|
12
|
-
)
|
|
13
|
-
|
|
14
|
-
const [onSpeedChange$, onSpeedChange] = observableCallback<
|
|
15
|
-
React.SyntheticEvent<HTMLInputElement>
|
|
16
|
-
>()
|
|
17
|
-
|
|
18
|
-
const speed$: Observable<number> = onSpeedChange$.pipe(
|
|
19
|
-
map((event) => Number(event.currentTarget.value)),
|
|
20
|
-
startWith(1000)
|
|
21
|
-
)
|
|
22
|
-
|
|
23
|
-
const UseObservableExample = () => (
|
|
24
|
-
<>
|
|
25
|
-
<h2>An observable of react elements</h2>
|
|
26
|
-
{useMemoObservable(of(<div>HELLO SYNC</div>), [])}
|
|
27
|
-
{useMemoObservable(numberReactElement$.pipe(startWith(2)), [])}
|
|
28
|
-
<h2>An observable with child as render func</h2>
|
|
29
|
-
{useMemoObservable(
|
|
30
|
-
timer(0, 100).pipe(
|
|
31
|
-
startWith(2),
|
|
32
|
-
map((num) => <>The number is {num}</>)
|
|
33
|
-
),
|
|
34
|
-
[]
|
|
35
|
-
)}
|
|
36
|
-
|
|
37
|
-
<h2>Nested</h2>
|
|
38
|
-
<p>You can adjust the update speed by changing update interval below</p>
|
|
39
|
-
{useMemoObservable(
|
|
40
|
-
() =>
|
|
41
|
-
speed$.pipe(
|
|
42
|
-
switchMap(
|
|
43
|
-
(speed: number): Observable<[number, number]> =>
|
|
44
|
-
timer(0, speed).pipe(
|
|
45
|
-
map((update): [number, number] => [speed, update])
|
|
46
|
-
)
|
|
47
|
-
),
|
|
48
|
-
map(([speed, update]: [number, number]) => (
|
|
49
|
-
<>
|
|
50
|
-
Update interval:
|
|
51
|
-
<input
|
|
52
|
-
type="number"
|
|
53
|
-
value={speed}
|
|
54
|
-
onChange={onSpeedChange}
|
|
55
|
-
step={200}
|
|
56
|
-
min={0}
|
|
57
|
-
/>
|
|
58
|
-
<div>Update {update}</div>
|
|
59
|
-
</>
|
|
60
|
-
))
|
|
61
|
-
),
|
|
62
|
-
[]
|
|
63
|
-
)}
|
|
64
|
-
</>
|
|
65
|
-
)
|
|
66
|
-
|
|
67
|
-
ReactDOM.render(
|
|
68
|
-
<UseObservableExample />,
|
|
69
|
-
document.getElementById('use-observable-example')
|
|
70
|
-
)
|
|
@@ -1,9 +0,0 @@
|
|
|
1
|
-
import {Example} from '../../../pages/Examples/Examples'
|
|
2
|
-
|
|
3
|
-
const fs = require('fs')
|
|
4
|
-
|
|
5
|
-
export const UseObservableExample: Example = {
|
|
6
|
-
id: 'use-observable',
|
|
7
|
-
title: 'Use observable',
|
|
8
|
-
source: fs.readFileSync(`${__dirname}/UseObservableExample.tsx`, 'utf-8')
|
|
9
|
-
}
|
package/website/src/index.html
DELETED
|
@@ -1,74 +0,0 @@
|
|
|
1
|
-
import {CodeMirrorMode} from './components/repl/CodeMirrorMode'
|
|
2
|
-
|
|
3
|
-
import * as React from 'react'
|
|
4
|
-
import styled from 'styled-components'
|
|
5
|
-
import {rxComponent} from 'react-rx'
|
|
6
|
-
import {map} from 'rxjs/operators'
|
|
7
|
-
import {combineLatest} from 'rxjs'
|
|
8
|
-
import {location$} from './datastores/location'
|
|
9
|
-
import {parseCodeFenceHeader} from './utils/parseCodeFenceHeader'
|
|
10
|
-
import {ModeSpec} from './components/repl/runMode'
|
|
11
|
-
|
|
12
|
-
const ModeWrapper = styled.div`
|
|
13
|
-
color: #fff;
|
|
14
|
-
`
|
|
15
|
-
|
|
16
|
-
const InlineCode = styled.code`
|
|
17
|
-
font-size: 0.9em;
|
|
18
|
-
background-color: #e4e4e4;
|
|
19
|
-
padding: 1px 4px;
|
|
20
|
-
border-radius: 2px;
|
|
21
|
-
`
|
|
22
|
-
|
|
23
|
-
const CODEMIRROR_TSX_MODE: ModeSpec = {
|
|
24
|
-
name: 'jsx',
|
|
25
|
-
base: {name: 'javascript', typescript: true}
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
const TSX_MODE_TYPES = ['js', 'jsx', 'tsx', 'ts']
|
|
29
|
-
|
|
30
|
-
interface InlineCodeProps {
|
|
31
|
-
children: string
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
interface CodeProps {
|
|
35
|
-
children: string
|
|
36
|
-
className: 'language-js' | 'language-jsx' | 'language-tsx'
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
export const components = {
|
|
40
|
-
inlineCode: InlineCode,
|
|
41
|
-
code: (props: CodeProps) => {
|
|
42
|
-
const [lang, range] = parseCodeFenceHeader(
|
|
43
|
-
props.className.replace(/^language-/, '')
|
|
44
|
-
)
|
|
45
|
-
const mode =
|
|
46
|
-
lang && TSX_MODE_TYPES.includes(lang) ? CODEMIRROR_TSX_MODE : null
|
|
47
|
-
return (
|
|
48
|
-
<ModeWrapper>
|
|
49
|
-
<CodeMirrorMode highlighted={range} mode={mode}>
|
|
50
|
-
{props.children}
|
|
51
|
-
</CodeMirrorMode>
|
|
52
|
-
</ModeWrapper>
|
|
53
|
-
)
|
|
54
|
-
}
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
const hash$ = location$.pipe(map(location => location.hash))
|
|
58
|
-
|
|
59
|
-
const BookmarkedLink = rxComponent<{
|
|
60
|
-
href: string
|
|
61
|
-
children: React.ReactNode
|
|
62
|
-
}>(props$ =>
|
|
63
|
-
combineLatest([props$, hash$]).pipe(
|
|
64
|
-
map(([props, hash]) => (
|
|
65
|
-
<a href={props.href} className={hash === props.href ? 'selected' : ''}>
|
|
66
|
-
{props.children}
|
|
67
|
-
</a>
|
|
68
|
-
))
|
|
69
|
-
)
|
|
70
|
-
)
|
|
71
|
-
|
|
72
|
-
export const tocComponents = {
|
|
73
|
-
a: BookmarkedLink
|
|
74
|
-
}
|