react-rx 1.0.0-beta.3 → 1.0.0
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/codeStyles/Project.xml +0 -6
- package/.idea/inspectionProfiles/Project_Default.xml +0 -4
- package/.idea/workspace.xml +62 -49
- package/dist/cjs/WithObservable.d.ts +3 -3
- package/dist/cjs/WithObservable.js +3 -3
- package/dist/cjs/index.d.ts +6 -2
- package/dist/cjs/index.js +18 -11
- package/dist/cjs/reactiveComponent.d.ts +6 -6
- package/dist/cjs/reactiveComponent.js +8 -26
- package/dist/cjs/useAsObservable.d.ts +9 -0
- package/dist/cjs/useAsObservable.js +31 -0
- package/dist/cjs/useIsomorphicEffect.d.ts +2 -0
- package/dist/cjs/useIsomorphicEffect.js +5 -0
- package/dist/cjs/useObservable.d.ts +6 -15
- package/dist/cjs/useObservable.js +17 -73
- package/dist/cjs/useObservableCallback.d.ts +3 -0
- package/dist/cjs/useObservableCallback.js +24 -0
- package/dist/cjs/useWithObservable.d.ts +9 -0
- package/dist/cjs/useWithObservable.js +11 -0
- package/dist/cjs/utils.d.ts +7 -3
- package/dist/cjs/utils.js +29 -5
- package/dist/cjs/withPropsStream.js +3 -3
- package/dist/es2015/WithObservable.d.ts +3 -3
- package/dist/es2015/index.d.ts +6 -2
- package/dist/es2015/index.js +7 -2
- package/dist/es2015/reactiveComponent.d.ts +6 -6
- package/dist/es2015/reactiveComponent.js +9 -6
- package/dist/es2015/useAsObservable.d.ts +9 -0
- package/dist/es2015/useAsObservable.js +27 -0
- package/dist/es2015/useIsomorphicEffect.d.ts +2 -0
- package/dist/es2015/useIsomorphicEffect.js +2 -0
- package/dist/es2015/useObservable.d.ts +6 -15
- package/dist/es2015/useObservable.js +15 -46
- package/dist/es2015/useObservableCallback.d.ts +3 -0
- package/dist/es2015/useObservableCallback.js +19 -0
- package/dist/es2015/useWithObservable.d.ts +9 -0
- package/dist/es2015/useWithObservable.js +7 -0
- package/dist/es2015/utils.d.ts +7 -3
- package/dist/es2015/utils.js +24 -3
- package/dist/esm/WithObservable.d.ts +3 -3
- package/dist/esm/index.d.ts +6 -2
- package/dist/esm/index.js +7 -2
- package/dist/esm/reactiveComponent.d.ts +6 -6
- package/dist/esm/reactiveComponent.js +7 -6
- package/dist/esm/useAsObservable.d.ts +9 -0
- package/dist/esm/useAsObservable.js +27 -0
- package/dist/esm/useIsomorphicEffect.d.ts +2 -0
- package/dist/esm/useIsomorphicEffect.js +2 -0
- package/dist/esm/useObservable.d.ts +6 -15
- package/dist/esm/useObservable.js +15 -48
- package/dist/esm/useObservableCallback.d.ts +3 -0
- package/dist/esm/useObservableCallback.js +20 -0
- package/dist/esm/useWithObservable.d.ts +9 -0
- package/dist/esm/useWithObservable.js +7 -0
- package/dist/esm/utils.d.ts +7 -3
- package/dist/esm/utils.js +24 -3
- package/package.json +9 -4
- package/src/WithObservable.tsx +4 -3
- package/src/index.ts +12 -12
- package/src/reactiveComponent.ts +28 -20
- package/src/useAsObservable.ts +43 -0
- package/src/useIsomorphicEffect.ts +3 -0
- package/src/useObservable.ts +36 -77
- package/src/useObservableCallback.ts +30 -0
- package/src/useWithObservable.ts +23 -0
- package/src/utils.ts +39 -3
- package/website/.babelrc +21 -0
- package/website/.prettierrc +7 -0
- package/website/README.mdx +1 -0
- package/website/package.json +84 -0
- package/website/src/@types/babel.d.ts +4 -0
- package/website/src/@types/mdx.d.ts +11 -0
- package/website/src/@types/react-css-burger.d.ts +4 -0
- package/website/src/App.tsx +68 -0
- package/website/src/components/Header.tsx +118 -0
- package/website/src/components/Link.tsx +18 -0
- package/website/src/components/LoadPage.tsx +60 -0
- package/website/src/components/Sidebar.tsx +88 -0
- package/website/src/components/logos/Github.tsx +10 -0
- package/website/src/components/logos/React.tsx +27 -0
- package/website/src/components/logos/ReactRxLogo.tsx +39 -0
- package/website/src/components/logos/RxJs.tsx +69 -0
- package/website/src/components/repl/Checkerboard.tsx +25 -0
- package/website/src/components/repl/CodeBlock.tsx +147 -0
- package/website/src/components/repl/CodeMirror.tsx +37 -0
- package/website/src/components/repl/CodeMirrorMode.tsx +67 -0
- package/website/src/components/repl/EvalCode.tsx +55 -0
- package/website/src/components/repl/Prelude.tsx +50 -0
- package/website/src/components/repl/ShowError.tsx +27 -0
- package/website/src/components/repl/codemirror-lib.ts +8 -0
- package/website/src/components/repl/codemirror-theme.css +131 -0
- package/website/src/components/repl/compile/babel.ts +21 -0
- package/website/src/components/repl/eval/evalCallback.ts +27 -0
- package/website/src/components/repl/eval/evalCode.ts +7 -0
- package/website/src/components/repl/eval/evalExpression.ts +4 -0
- package/website/src/components/repl/eval/evalReactDomRender.ts +23 -0
- package/website/src/components/repl/index.ts +1 -0
- package/website/src/components/repl/runMode.ts +42 -0
- package/website/src/datastores/location.ts +14 -0
- package/website/src/datastores/page.ts +11 -0
- package/website/src/datastores/pageTransition.ts +97 -0
- package/website/src/entries/main.css +2 -0
- package/website/src/entries/main.tsx +6 -0
- package/website/src/examples/FizzBuzz/FizzBuzzExample.tsx +39 -0
- package/website/src/examples/FizzBuzz/index.tsx +9 -0
- package/website/src/examples/_utils/globalScope.ts +45 -0
- package/website/src/examples/animation/AnimationExample.tsx +152 -0
- package/website/src/examples/animation/easings.ts +0 -0
- package/website/src/examples/animation/index.tsx +15 -0
- package/website/src/examples/context/Context.example.jsx +67 -0
- package/website/src/examples/context/index.tsx +9 -0
- package/website/src/examples/errors/Errors.example.jsx +69 -0
- package/website/src/examples/errors/index.tsx +9 -0
- package/website/src/examples/event-handlers/EventHandlersExample.tsx +48 -0
- package/website/src/examples/event-handlers/index.tsx +9 -0
- package/website/src/examples/fetch/FetchExample.jsx +43 -0
- package/website/src/examples/fetch/a.txt +1 -0
- package/website/src/examples/fetch/b.txt +1 -0
- package/website/src/examples/fetch/index.tsx +9 -0
- package/website/src/examples/form-data/FormDataExample.jsx +119 -0
- package/website/src/examples/form-data/index.tsx +12 -0
- package/website/src/examples/form-data/storage.ts +27 -0
- package/website/src/examples/forward-ref/ForwardRefExample.tsx +55 -0
- package/website/src/examples/forward-ref/index.tsx +9 -0
- package/website/src/examples/hello-world/HelloWorld.example.jsx +6 -0
- package/website/src/examples/hello-world/index.tsx +9 -0
- package/website/src/examples/hooks-interop/HooksInterop.example.tsx +42 -0
- package/website/src/examples/hooks-interop/index.tsx +9 -0
- package/website/src/examples/passthrough-props/PassThroughPropsExample.jsx +57 -0
- package/website/src/examples/passthrough-props/index.tsx +11 -0
- package/website/src/examples/reactive-state/ReactiveState.example.jsx +43 -0
- package/website/src/examples/reactive-state/index.ts +9 -0
- package/website/src/examples/readme-examples/README.mdx +0 -0
- package/website/src/examples/readme-examples/index.ts +11 -0
- package/website/src/examples/shared-state/SharedState.example.tsx +59 -0
- package/website/src/examples/shared-state/index.tsx +9 -0
- package/website/src/examples/simple/Counter.example.tsx +14 -0
- package/website/src/examples/simple/index.tsx +9 -0
- package/website/src/examples/sync/Sync.example.tsx +9 -0
- package/website/src/examples/sync/index.tsx +9 -0
- package/website/src/examples/tick/TickExample.jsx +51 -0
- package/website/src/examples/tick/index.ts +9 -0
- package/website/src/examples/todo-app/TodoApp.example.tsx +88 -0
- package/website/src/examples/todo-app/index.tsx +12 -0
- package/website/src/examples/todo-app/storage.ts +27 -0
- package/website/src/examples/use-element/UseElementExample.tsx +70 -0
- package/website/src/examples/use-element/index.tsx +9 -0
- package/website/src/examples/use-observable/search/SearchExample.tsx +82 -0
- package/website/src/examples/use-observable/search/index.tsx +8 -0
- package/website/src/examples/use-observable/use-observable/UseObservableExample.tsx +70 -0
- package/website/src/examples/use-observable/use-observable/index.tsx +9 -0
- package/website/src/index.html +10 -0
- package/website/src/mdx-components.tsx +74 -0
- package/website/src/pages/Api/Api.mdx +134 -0
- package/website/src/pages/Api/ApiPage.tsx +25 -0
- package/website/src/pages/Examples/Examples.tsx +105 -0
- package/website/src/pages/Examples/ExamplesPage.tsx +13 -0
- package/website/src/pages/Guide/Guide.mdx +275 -0
- package/website/src/pages/Guide/GuidePage.tsx +25 -0
- package/website/src/pages/Index/IndexPage.tsx +50 -0
- package/website/src/pages/Index/ReactRxReadme.md +20 -0
- package/website/src/pages/NotFound.tsx +3 -0
- package/website/src/pages/pages.ts +46 -0
- package/website/src/pages/styles.tsx +24 -0
- package/website/src/theme.ts +61 -0
- package/website/src/utils/parseCodeFenceHeader.ts +32 -0
- package/website/tsconfig.json +30 -0
- package/website/vercel.json +4 -0
- package/website/webpack/config.js +5 -0
- package/website/webpack/createConfig.js +95 -0
- package/website/webpack/mdx-toc-loader.js +38 -0
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
import {
|
|
2
|
+
concat,
|
|
3
|
+
concatMap,
|
|
4
|
+
map,
|
|
5
|
+
merge,
|
|
6
|
+
React,
|
|
7
|
+
ReactDOM,
|
|
8
|
+
rxComponent,
|
|
9
|
+
scan,
|
|
10
|
+
startWith,
|
|
11
|
+
tap,
|
|
12
|
+
timer,
|
|
13
|
+
handler
|
|
14
|
+
} from 'examples/_utils/globalScope'
|
|
15
|
+
|
|
16
|
+
import storage from './storage'
|
|
17
|
+
import styled from 'styled-components'
|
|
18
|
+
//@endimport
|
|
19
|
+
|
|
20
|
+
const {withLatestFrom} = operators
|
|
21
|
+
|
|
22
|
+
const STORAGE_KEY = '__form-submit-example__'
|
|
23
|
+
|
|
24
|
+
const save = formData =>
|
|
25
|
+
timer(100 + Math.round(Math.random() * 1000)).pipe(
|
|
26
|
+
concatMap(() => storage.set(STORAGE_KEY, formData))
|
|
27
|
+
)
|
|
28
|
+
|
|
29
|
+
const INITIAL_PROPS = {
|
|
30
|
+
submitState: {status: 'unsaved', result: null},
|
|
31
|
+
formData: {}
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
const INITIAL_SUBMIT_STATE = {status: 'saving', result: null}
|
|
35
|
+
|
|
36
|
+
const FormDataExample = rxComponent(() => {
|
|
37
|
+
const [onChange$, onChange] = handler()
|
|
38
|
+
const [onSubmit$, onSubmit] = handler()
|
|
39
|
+
|
|
40
|
+
const formData$ = concat(
|
|
41
|
+
storage.get(STORAGE_KEY, {title: '', description: ''}),
|
|
42
|
+
onChange$.pipe(
|
|
43
|
+
map(event => event.target),
|
|
44
|
+
map(target => ({
|
|
45
|
+
[target.name]: target.value
|
|
46
|
+
}))
|
|
47
|
+
)
|
|
48
|
+
).pipe(scan((formData, update) => ({...formData, ...update}), {}))
|
|
49
|
+
|
|
50
|
+
const submitState$ = onSubmit$.pipe(
|
|
51
|
+
tap(event => event.preventDefault()),
|
|
52
|
+
withLatestFrom(formData$),
|
|
53
|
+
map(([event, formData]) => formData),
|
|
54
|
+
concatMap(formData =>
|
|
55
|
+
save(formData).pipe(
|
|
56
|
+
map(res => ({status: 'saved', result: res})),
|
|
57
|
+
startWith(INITIAL_SUBMIT_STATE)
|
|
58
|
+
)
|
|
59
|
+
)
|
|
60
|
+
)
|
|
61
|
+
|
|
62
|
+
return merge(
|
|
63
|
+
formData$.pipe(map(formData => ({formData}))),
|
|
64
|
+
submitState$.pipe(map(submitState => ({submitState})))
|
|
65
|
+
).pipe(
|
|
66
|
+
scan((prev, curr) => ({...prev, ...curr}), INITIAL_PROPS),
|
|
67
|
+
map(props => (
|
|
68
|
+
<Form onSubmit={onSubmit}>
|
|
69
|
+
<div>
|
|
70
|
+
<label>
|
|
71
|
+
<strong>Title: </strong>
|
|
72
|
+
<input
|
|
73
|
+
type="text"
|
|
74
|
+
name="title"
|
|
75
|
+
value={props.formData.title}
|
|
76
|
+
onChange={onChange}
|
|
77
|
+
/>
|
|
78
|
+
</label>
|
|
79
|
+
</div>
|
|
80
|
+
<div>
|
|
81
|
+
<label>
|
|
82
|
+
<strong>Description: </strong>
|
|
83
|
+
<textarea
|
|
84
|
+
name="description"
|
|
85
|
+
value={props.formData.description}
|
|
86
|
+
onChange={onChange}
|
|
87
|
+
/>
|
|
88
|
+
</label>
|
|
89
|
+
</div>
|
|
90
|
+
<div>
|
|
91
|
+
<button disabled={props.submitState.status === 'saving'}>
|
|
92
|
+
{props.submitState.status === 'saving'
|
|
93
|
+
? 'Saving…'
|
|
94
|
+
: props.submitState.status === 'saved'
|
|
95
|
+
? 'Saved!'
|
|
96
|
+
: 'Save'}
|
|
97
|
+
</button>
|
|
98
|
+
</div>
|
|
99
|
+
</Form>
|
|
100
|
+
))
|
|
101
|
+
)
|
|
102
|
+
})
|
|
103
|
+
|
|
104
|
+
ReactDOM.render(
|
|
105
|
+
<FormDataExample />,
|
|
106
|
+
document.getElementById('formdata-example')
|
|
107
|
+
)
|
|
108
|
+
|
|
109
|
+
const Form = styled.form`
|
|
110
|
+
label {
|
|
111
|
+
display: block;
|
|
112
|
+
margin-top: 10px;
|
|
113
|
+
}
|
|
114
|
+
input,
|
|
115
|
+
textarea {
|
|
116
|
+
width: 100%;
|
|
117
|
+
padding: 5px;
|
|
118
|
+
}
|
|
119
|
+
`
|
|
@@ -0,0 +1,12 @@
|
|
|
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 FormDataExample: Example = {
|
|
8
|
+
id: 'form-data',
|
|
9
|
+
title: 'Form data',
|
|
10
|
+
scope: {storage, styled},
|
|
11
|
+
source: fs.readFileSync(`${__dirname}/FormDataExample.jsx`, 'utf-8')
|
|
12
|
+
}
|
|
@@ -0,0 +1,27 @@
|
|
|
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}
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import {
|
|
2
|
+
forwardRef,
|
|
3
|
+
map,
|
|
4
|
+
React,
|
|
5
|
+
ReactDOM,
|
|
6
|
+
rxComponent,
|
|
7
|
+
state
|
|
8
|
+
} from '../_utils/globalScope'
|
|
9
|
+
//@endimport
|
|
10
|
+
|
|
11
|
+
const CustomInput = forwardRef((props$, ref) => {
|
|
12
|
+
return props$.pipe(
|
|
13
|
+
map((props) => (
|
|
14
|
+
<input
|
|
15
|
+
ref={ref}
|
|
16
|
+
type="text"
|
|
17
|
+
value={props.value}
|
|
18
|
+
onChange={props.onChange}
|
|
19
|
+
/>
|
|
20
|
+
))
|
|
21
|
+
)
|
|
22
|
+
})
|
|
23
|
+
|
|
24
|
+
const ForwardRefExample = rxComponent(() => {
|
|
25
|
+
const [value$, setValue] = state('hello world')
|
|
26
|
+
const inputRef = React.useRef<HTMLInputElement>(null)
|
|
27
|
+
|
|
28
|
+
return value$.pipe(
|
|
29
|
+
map((value) => (
|
|
30
|
+
<>
|
|
31
|
+
<button
|
|
32
|
+
onClick={() => {
|
|
33
|
+
inputRef.current?.select()
|
|
34
|
+
}}
|
|
35
|
+
>
|
|
36
|
+
Select text in input
|
|
37
|
+
</button>
|
|
38
|
+
<div>
|
|
39
|
+
<CustomInput
|
|
40
|
+
ref={inputRef}
|
|
41
|
+
value={value}
|
|
42
|
+
onChange={() => {
|
|
43
|
+
setValue(inputRef.current?.value || '')
|
|
44
|
+
}}
|
|
45
|
+
/>
|
|
46
|
+
</div>
|
|
47
|
+
</>
|
|
48
|
+
))
|
|
49
|
+
)
|
|
50
|
+
})
|
|
51
|
+
|
|
52
|
+
ReactDOM.render(
|
|
53
|
+
<ForwardRefExample />,
|
|
54
|
+
document.getElementById('forward-ref-example')
|
|
55
|
+
)
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import {
|
|
2
|
+
forwardRef,
|
|
3
|
+
map,
|
|
4
|
+
React,
|
|
5
|
+
ReactDOM,
|
|
6
|
+
rxComponent,
|
|
7
|
+
useAsObservable
|
|
8
|
+
} from '../_utils/globalScope'
|
|
9
|
+
import {combineLatest, timer} from 'rxjs'
|
|
10
|
+
//@endimport
|
|
11
|
+
|
|
12
|
+
const ticks$ = timer(0, 1000)
|
|
13
|
+
|
|
14
|
+
function useClickCounter(): [number, () => void] {
|
|
15
|
+
const [clickCount, setClickCount] = React.useState(0)
|
|
16
|
+
const inc = React.useCallback(() => setClickCount((c) => c + 1), [])
|
|
17
|
+
|
|
18
|
+
return [clickCount, inc]
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
const HooksInteropExample = rxComponent(() => {
|
|
22
|
+
const [clickCount, inc] = useClickCounter()
|
|
23
|
+
|
|
24
|
+
// This is required in order to turn clickCount into an observable value
|
|
25
|
+
const click$ = useAsObservable(clickCount)
|
|
26
|
+
|
|
27
|
+
return combineLatest([click$, ticks$]).pipe(
|
|
28
|
+
map(([clickCount, tickNumber]) => (
|
|
29
|
+
<>
|
|
30
|
+
Tick: {tickNumber}
|
|
31
|
+
<button onClick={inc}>
|
|
32
|
+
This button has been clicked {clickCount} times
|
|
33
|
+
</button>
|
|
34
|
+
</>
|
|
35
|
+
))
|
|
36
|
+
)
|
|
37
|
+
})
|
|
38
|
+
|
|
39
|
+
ReactDOM.render(
|
|
40
|
+
<HooksInteropExample />,
|
|
41
|
+
document.getElementById('forward-ref-example')
|
|
42
|
+
)
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import {Example} from '../../pages/Examples/Examples'
|
|
2
|
+
|
|
3
|
+
const fs = require('fs')
|
|
4
|
+
|
|
5
|
+
export const HooksInteropExample: Example = {
|
|
6
|
+
id: 'hooks-interop',
|
|
7
|
+
title: 'React hooks interop',
|
|
8
|
+
source: fs.readFileSync(`${__dirname}/HooksInterop.example.tsx`, 'utf-8')
|
|
9
|
+
}
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
import {
|
|
2
|
+
combineLatest,
|
|
3
|
+
map,
|
|
4
|
+
React,
|
|
5
|
+
ReactDOM,
|
|
6
|
+
rxComponent,
|
|
7
|
+
take,
|
|
8
|
+
timer
|
|
9
|
+
} from '../_utils/globalScope'
|
|
10
|
+
import {formatDistance} from 'date-fns'
|
|
11
|
+
//@endimport
|
|
12
|
+
|
|
13
|
+
const {share} = operators
|
|
14
|
+
|
|
15
|
+
const UPDATE_INTERVAL = 1000
|
|
16
|
+
const currentTime$ = timer(0, UPDATE_INTERVAL).pipe(
|
|
17
|
+
take(10),
|
|
18
|
+
map(() => new Date()),
|
|
19
|
+
share()
|
|
20
|
+
)
|
|
21
|
+
|
|
22
|
+
const TimeDistance = rxComponent(props$ =>
|
|
23
|
+
combineLatest([currentTime$, props$]).pipe(
|
|
24
|
+
map(([currentTime, ownerProps]) =>
|
|
25
|
+
formatDistance(ownerProps.time, currentTime, {
|
|
26
|
+
includeSeconds: ownerProps.includeSeconds
|
|
27
|
+
})
|
|
28
|
+
)
|
|
29
|
+
)
|
|
30
|
+
)
|
|
31
|
+
|
|
32
|
+
const NOW = new Date()
|
|
33
|
+
const PassThroughPropsExample = () => (
|
|
34
|
+
<>
|
|
35
|
+
<h2>
|
|
36
|
+
With <code>includeSeconds</code> true
|
|
37
|
+
</h2>
|
|
38
|
+
With synchronized updates
|
|
39
|
+
<p>
|
|
40
|
+
Page loaded <TimeDistance time={NOW} includeSeconds /> ago
|
|
41
|
+
</p>
|
|
42
|
+
<p>
|
|
43
|
+
Page loaded <TimeDistance time={NOW} includeSeconds /> ago
|
|
44
|
+
</p>
|
|
45
|
+
<h2>
|
|
46
|
+
Without <code>includeSeconds</code>
|
|
47
|
+
</h2>
|
|
48
|
+
<p>
|
|
49
|
+
Page loaded <TimeDistance time={NOW} /> ago
|
|
50
|
+
</p>
|
|
51
|
+
</>
|
|
52
|
+
)
|
|
53
|
+
|
|
54
|
+
ReactDOM.render(
|
|
55
|
+
<PassThroughPropsExample />,
|
|
56
|
+
document.getElementById('pass-through-props-example')
|
|
57
|
+
)
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import {Example} from '../../pages/Examples/Examples'
|
|
2
|
+
import {formatDistance} from 'date-fns'
|
|
3
|
+
|
|
4
|
+
const fs = require('fs')
|
|
5
|
+
|
|
6
|
+
export const PassThroughPropsExample: Example = {
|
|
7
|
+
id: 'pass-through-props',
|
|
8
|
+
title: 'Pass through props',
|
|
9
|
+
scope: {formatDistance},
|
|
10
|
+
source: fs.readFileSync(`${__dirname}/PassThroughPropsExample.jsx`, 'utf-8')
|
|
11
|
+
}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import {
|
|
2
|
+
map,
|
|
3
|
+
React,
|
|
4
|
+
ReactDOM,
|
|
5
|
+
rxComponent,
|
|
6
|
+
startWith,
|
|
7
|
+
switchMap,
|
|
8
|
+
timer,
|
|
9
|
+
state
|
|
10
|
+
} from '../_utils/globalScope'
|
|
11
|
+
//@endimport
|
|
12
|
+
|
|
13
|
+
const ReactiveStateExample = rxComponent(() => {
|
|
14
|
+
const [delay$, setDelay] = state(100)
|
|
15
|
+
|
|
16
|
+
return delay$.pipe(
|
|
17
|
+
switchMap(delay =>
|
|
18
|
+
timer(500, delay).pipe(
|
|
19
|
+
map(n => `Count: ${n}`),
|
|
20
|
+
startWith('Starting counter…'),
|
|
21
|
+
map(label => (
|
|
22
|
+
<>
|
|
23
|
+
Counter interval (ms):{' '}
|
|
24
|
+
<input
|
|
25
|
+
type="range"
|
|
26
|
+
min={0}
|
|
27
|
+
max={1000}
|
|
28
|
+
step={100}
|
|
29
|
+
onChange={e => setDelay(Number(e.currentTarget.value))}
|
|
30
|
+
/>
|
|
31
|
+
{delay}
|
|
32
|
+
<div>{label}</div>
|
|
33
|
+
</>
|
|
34
|
+
))
|
|
35
|
+
)
|
|
36
|
+
)
|
|
37
|
+
)
|
|
38
|
+
})
|
|
39
|
+
|
|
40
|
+
ReactDOM.render(
|
|
41
|
+
<ReactiveStateExample />,
|
|
42
|
+
document.getElementById('use-state-example')
|
|
43
|
+
)
|
|
@@ -0,0 +1,9 @@
|
|
|
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
|
|
@@ -0,0 +1,11 @@
|
|
|
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
|
+
}
|
|
@@ -0,0 +1,59 @@
|
|
|
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'))
|
|
@@ -0,0 +1,14 @@
|
|
|
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'))
|
|
@@ -0,0 +1,9 @@
|
|
|
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'))
|
|
@@ -0,0 +1,51 @@
|
|
|
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'))
|