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,97 @@
|
|
|
1
|
+
import {
|
|
2
|
+
map,
|
|
3
|
+
publishReplay,
|
|
4
|
+
refCount,
|
|
5
|
+
scan,
|
|
6
|
+
skip,
|
|
7
|
+
switchMap,
|
|
8
|
+
tap
|
|
9
|
+
} from 'rxjs/operators'
|
|
10
|
+
import {concat, from, Observable, of} from 'rxjs'
|
|
11
|
+
import * as React from 'react'
|
|
12
|
+
import {page$} from './page'
|
|
13
|
+
import {Page} from '../pages/pages'
|
|
14
|
+
|
|
15
|
+
interface PageTransition {
|
|
16
|
+
title: string
|
|
17
|
+
isTransitioning: boolean
|
|
18
|
+
component: null | React.ComponentType<any>
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
interface TransitionStart {
|
|
22
|
+
type: 'transitionStart'
|
|
23
|
+
page: Page
|
|
24
|
+
component: null
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
interface TransitionEnd {
|
|
28
|
+
type: 'transitionEnd'
|
|
29
|
+
page: Page
|
|
30
|
+
component: React.ComponentType<any>
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
type TransitionEvent = TransitionStart | TransitionEnd
|
|
34
|
+
|
|
35
|
+
interface TransitionState {
|
|
36
|
+
isTransitioning: boolean
|
|
37
|
+
prev: null | Page
|
|
38
|
+
current: null | Page
|
|
39
|
+
next: null | Page
|
|
40
|
+
component: null | React.ComponentType
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
const transitionStart = (page: Page): TransitionStart => ({
|
|
44
|
+
type: 'transitionStart',
|
|
45
|
+
page,
|
|
46
|
+
component: null
|
|
47
|
+
})
|
|
48
|
+
|
|
49
|
+
const transitionEnd = (page: Page) => (
|
|
50
|
+
component: React.ComponentType<any>
|
|
51
|
+
): TransitionEnd => ({
|
|
52
|
+
type: 'transitionEnd',
|
|
53
|
+
page,
|
|
54
|
+
component
|
|
55
|
+
})
|
|
56
|
+
|
|
57
|
+
const INITIAL_TRANSITION_STATE: TransitionState = {
|
|
58
|
+
isTransitioning: true,
|
|
59
|
+
component: null,
|
|
60
|
+
next: null,
|
|
61
|
+
current: null,
|
|
62
|
+
prev: null
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
export const pageTransition$: Observable<TransitionState> = page$.pipe(
|
|
66
|
+
switchMap(page =>
|
|
67
|
+
concat(
|
|
68
|
+
of(transitionStart(page)),
|
|
69
|
+
from(page.load()).pipe(map(transitionEnd(page)))
|
|
70
|
+
)
|
|
71
|
+
),
|
|
72
|
+
scan(
|
|
73
|
+
(
|
|
74
|
+
acc: TransitionState,
|
|
75
|
+
event: TransitionStart | TransitionEnd
|
|
76
|
+
): TransitionState => {
|
|
77
|
+
return event.type === 'transitionStart'
|
|
78
|
+
? {
|
|
79
|
+
isTransitioning: true,
|
|
80
|
+
component: acc.component,
|
|
81
|
+
prev: acc.next || acc.current,
|
|
82
|
+
current: acc.current || null,
|
|
83
|
+
next: event.page
|
|
84
|
+
}
|
|
85
|
+
: {
|
|
86
|
+
isTransitioning: false,
|
|
87
|
+
component: event.component,
|
|
88
|
+
current: acc.next,
|
|
89
|
+
next: null,
|
|
90
|
+
prev: acc.current
|
|
91
|
+
}
|
|
92
|
+
},
|
|
93
|
+
INITIAL_TRANSITION_STATE
|
|
94
|
+
),
|
|
95
|
+
publishReplay(1),
|
|
96
|
+
refCount()
|
|
97
|
+
)
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import {
|
|
2
|
+
map,
|
|
3
|
+
React,
|
|
4
|
+
ReactDOM,
|
|
5
|
+
rxComponent,
|
|
6
|
+
take,
|
|
7
|
+
timer
|
|
8
|
+
} from '../_utils/globalScope'
|
|
9
|
+
//@endimport
|
|
10
|
+
|
|
11
|
+
const FizzBuzzExample = rxComponent(
|
|
12
|
+
timer(0, 500).pipe(
|
|
13
|
+
map(n => n + 1),
|
|
14
|
+
map(n => {
|
|
15
|
+
const divBy3 = n % 3 === 0
|
|
16
|
+
const divBy5 = n % 5 === 0
|
|
17
|
+
const divBy3And5 = divBy3 && divBy5
|
|
18
|
+
return divBy3And5
|
|
19
|
+
? 'Fizz Buzz'
|
|
20
|
+
: divBy3
|
|
21
|
+
? 'Fizz'
|
|
22
|
+
: divBy5
|
|
23
|
+
? 'Buzz'
|
|
24
|
+
: String(n)
|
|
25
|
+
}),
|
|
26
|
+
// map((seq: string[], curr) => seq.concat(curr), []),
|
|
27
|
+
map((n, i) => (
|
|
28
|
+
<div key={n + i}>
|
|
29
|
+
{i + 1}: {n}
|
|
30
|
+
</div>
|
|
31
|
+
)),
|
|
32
|
+
take(100)
|
|
33
|
+
)
|
|
34
|
+
)
|
|
35
|
+
|
|
36
|
+
ReactDOM.render(
|
|
37
|
+
<FizzBuzzExample />,
|
|
38
|
+
document.getElementById('fizz-buzz-example')
|
|
39
|
+
)
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import * as React from 'react'
|
|
2
|
+
import * as ReactDOM from 'react-dom'
|
|
3
|
+
import * as RxJS from 'rxjs'
|
|
4
|
+
import * as operators from 'rxjs/operators'
|
|
5
|
+
|
|
6
|
+
const {of, from, concat, merge} = RxJS
|
|
7
|
+
const {timer, interval, throwError, combineLatest, Observable} = RxJS
|
|
8
|
+
|
|
9
|
+
const {map, filter, reduce, scan, tap} = operators
|
|
10
|
+
const {concatMap, mergeMap, switchMap, mapTo} = operators
|
|
11
|
+
const {startWith, catchError, take} = operators
|
|
12
|
+
//@endimport
|
|
13
|
+
|
|
14
|
+
export {of, from, timer, interval, concat, merge, throwError, combineLatest, Observable}
|
|
15
|
+
export {
|
|
16
|
+
map,
|
|
17
|
+
filter,
|
|
18
|
+
reduce,
|
|
19
|
+
scan,
|
|
20
|
+
concatMap,
|
|
21
|
+
tap,
|
|
22
|
+
mapTo,
|
|
23
|
+
mergeMap,
|
|
24
|
+
startWith,
|
|
25
|
+
take,
|
|
26
|
+
switchMap,
|
|
27
|
+
catchError
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
export {React, ReactDOM}
|
|
31
|
+
export {RxJS, operators}
|
|
32
|
+
|
|
33
|
+
export {
|
|
34
|
+
useObservable,
|
|
35
|
+
useMemoObservable,
|
|
36
|
+
rxComponent,
|
|
37
|
+
context,
|
|
38
|
+
handler,
|
|
39
|
+
state,
|
|
40
|
+
elementRef,
|
|
41
|
+
forwardRef,
|
|
42
|
+
useAsObservable
|
|
43
|
+
} from 'react-rx'
|
|
44
|
+
|
|
45
|
+
export {observableCallback} from 'observable-callback'
|
|
@@ -0,0 +1,152 @@
|
|
|
1
|
+
/* eslint-disable @typescript-eslint/no-use-before-define */
|
|
2
|
+
import {
|
|
3
|
+
map,
|
|
4
|
+
React,
|
|
5
|
+
ReactDOM,
|
|
6
|
+
rxComponent,
|
|
7
|
+
switchMap,
|
|
8
|
+
timer,
|
|
9
|
+
state
|
|
10
|
+
} from '../_utils/globalScope'
|
|
11
|
+
import styled from 'styled-components'
|
|
12
|
+
import bezier from 'bezier-easing'
|
|
13
|
+
//@endimport
|
|
14
|
+
|
|
15
|
+
const BALL_SIZE = 30
|
|
16
|
+
const BOX_SIZE = 300
|
|
17
|
+
|
|
18
|
+
const MAX_TOP = BOX_SIZE - BALL_SIZE
|
|
19
|
+
|
|
20
|
+
function easeCustom(n: number) {
|
|
21
|
+
// implement your own easing function here by returning a number in the range of [0, 1]
|
|
22
|
+
return n
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
type EasingName = keyof typeof EASINGS
|
|
26
|
+
|
|
27
|
+
const AnimationExample = rxComponent(() => {
|
|
28
|
+
const [easing$, setEasing] = state<EasingName>('easeCustom')
|
|
29
|
+
return easing$.pipe(
|
|
30
|
+
switchMap((easing: EasingName) =>
|
|
31
|
+
timer(0, 16).pipe(
|
|
32
|
+
map((n) => (n % MAX_TOP) * 2),
|
|
33
|
+
map((n) => (n > MAX_TOP ? MAX_TOP * 2 - n : n)),
|
|
34
|
+
map((linearTop): [number, EasingName] => [
|
|
35
|
+
EASINGS[easing](linearTop / MAX_TOP) * MAX_TOP,
|
|
36
|
+
easing
|
|
37
|
+
])
|
|
38
|
+
)
|
|
39
|
+
),
|
|
40
|
+
map(([top, currentEasing]) => (
|
|
41
|
+
<>
|
|
42
|
+
<BoxWrapper>
|
|
43
|
+
<Box>
|
|
44
|
+
<Ball style={{top}} />
|
|
45
|
+
</Box>
|
|
46
|
+
</BoxWrapper>
|
|
47
|
+
<SelectWrapperLabel>Easing function:</SelectWrapperLabel>
|
|
48
|
+
<SelectWrapper>
|
|
49
|
+
{Object.keys(EASINGS).map((easingName) => (
|
|
50
|
+
<label key={easingName} className={easingName === currentEasing ? 'selected' : ''}>
|
|
51
|
+
<input
|
|
52
|
+
tabIndex={0}
|
|
53
|
+
type="checkbox"
|
|
54
|
+
checked={easingName === currentEasing}
|
|
55
|
+
key={easingName}
|
|
56
|
+
onChange={() => setEasing(easingName as EasingName)}
|
|
57
|
+
/>
|
|
58
|
+
{easingName.substring(4)}
|
|
59
|
+
</label>
|
|
60
|
+
))}
|
|
61
|
+
</SelectWrapper>
|
|
62
|
+
</>
|
|
63
|
+
))
|
|
64
|
+
)
|
|
65
|
+
})
|
|
66
|
+
|
|
67
|
+
ReactDOM.render(
|
|
68
|
+
<AnimationExample />,
|
|
69
|
+
document.getElementById('animation-example')
|
|
70
|
+
)
|
|
71
|
+
|
|
72
|
+
// --- easing definitions and stylings
|
|
73
|
+
const EASINGS = {
|
|
74
|
+
easeCustom: easeCustom,
|
|
75
|
+
easeInSine: bezier(0.47, 0, 0.745, 0.715),
|
|
76
|
+
easeOutSine: bezier(0.39, 0.575, 0.565, 1),
|
|
77
|
+
easeInOutSine: bezier(0.445, 0.05, 0.55, 0.95),
|
|
78
|
+
easeInQuad: bezier(0.55, 0.085, 0.68, 0.53),
|
|
79
|
+
easeOutQuad: bezier(0.25, 0.46, 0.45, 0.94),
|
|
80
|
+
easeInOutQuad: bezier(0.455, 0.03, 0.515, 0.955),
|
|
81
|
+
easeInCubic: bezier(0.55, 0.055, 0.675, 0.19),
|
|
82
|
+
easeOutCubic: bezier(0.215, 0.61, 0.355, 1),
|
|
83
|
+
easeInOutCubic: bezier(0.645, 0.045, 0.355, 1),
|
|
84
|
+
easeInQuart: bezier(0.895, 0.03, 0.685, 0.22),
|
|
85
|
+
easeOutQuart: bezier(0.165, 0.84, 0.44, 1),
|
|
86
|
+
easeInOutQuart: bezier(0.77, 0, 0.175, 1),
|
|
87
|
+
easeInQuint: bezier(0.755, 0.05, 0.855, 0.06),
|
|
88
|
+
easeOutQuint: bezier(0.23, 1, 0.32, 1),
|
|
89
|
+
easeInOutQuint: bezier(0.86, 0, 0.07, 1),
|
|
90
|
+
easeInExpo: bezier(0.95, 0.05, 0.795, 0.035),
|
|
91
|
+
easeOutExpo: bezier(0.19, 1, 0.22, 1),
|
|
92
|
+
easeInOutExpo: bezier(1, 0, 0, 1),
|
|
93
|
+
easeInCirc: bezier(0.6, 0.04, 0.98, 0.335),
|
|
94
|
+
easeOutCirc: bezier(0.075, 0.82, 0.165, 1),
|
|
95
|
+
easeInOutCirc: bezier(0.785, 0.135, 0.15, 0.86),
|
|
96
|
+
easeInBack: bezier(0.6, -0.28, 0.735, 0.045),
|
|
97
|
+
easeOutBack: bezier(0.175, 0.885, 0.32, 1.275),
|
|
98
|
+
easeInOutBack: bezier(0.68, -0.55, 0.265, 1.55),
|
|
99
|
+
easeLinear: (n: number) => n
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
const BoxWrapper = styled.div`
|
|
103
|
+
display: flex;
|
|
104
|
+
flex-direction: column;
|
|
105
|
+
align-items: center;
|
|
106
|
+
`
|
|
107
|
+
const Box = styled.div`
|
|
108
|
+
position: relative;
|
|
109
|
+
border: 1px solid #555;
|
|
110
|
+
height: ${BOX_SIZE}px;
|
|
111
|
+
width: ${BOX_SIZE}px;
|
|
112
|
+
`
|
|
113
|
+
|
|
114
|
+
const Ball = styled.div`
|
|
115
|
+
position: absolute;
|
|
116
|
+
border-radius: 100%;
|
|
117
|
+
background-color: #901a3b;
|
|
118
|
+
width: ${BALL_SIZE}px;
|
|
119
|
+
height: ${BALL_SIZE}px;
|
|
120
|
+
left: ${BOX_SIZE / 2 - BALL_SIZE / 2}px;
|
|
121
|
+
`
|
|
122
|
+
|
|
123
|
+
const SelectWrapperLabel = styled.h2`
|
|
124
|
+
margin-top: 2em;
|
|
125
|
+
font-size: 0.8em;
|
|
126
|
+
`
|
|
127
|
+
|
|
128
|
+
const SelectWrapper = styled.div`
|
|
129
|
+
display: flex;
|
|
130
|
+
flex-wrap: wrap;
|
|
131
|
+
flex-direction: row;
|
|
132
|
+
input[type='checkbox'] {
|
|
133
|
+
opacity: 0;
|
|
134
|
+
position: absolute;
|
|
135
|
+
height: 1px;
|
|
136
|
+
width: 1px;
|
|
137
|
+
}
|
|
138
|
+
font-size: 90%;
|
|
139
|
+
label {
|
|
140
|
+
border-radius: 3px;
|
|
141
|
+
padding: 0 2px;
|
|
142
|
+
margin: 0 2px;
|
|
143
|
+
}
|
|
144
|
+
label:focus-within {
|
|
145
|
+
color: #333;
|
|
146
|
+
background-color: #ccc;
|
|
147
|
+
}
|
|
148
|
+
label.selected {
|
|
149
|
+
background-color: #5588ee;
|
|
150
|
+
color: #333;
|
|
151
|
+
}
|
|
152
|
+
`
|
|
File without changes
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import {Example} from '../../pages/Examples/Examples'
|
|
2
|
+
import styled from 'styled-components'
|
|
3
|
+
import bezier from 'bezier-easing'
|
|
4
|
+
|
|
5
|
+
const fs = require('fs')
|
|
6
|
+
|
|
7
|
+
export const AnimationExample: Example = {
|
|
8
|
+
id: 'animation',
|
|
9
|
+
title: 'Animation',
|
|
10
|
+
prelude: `import styled from 'styled-components'
|
|
11
|
+
import bezier from 'bezier-easing'
|
|
12
|
+
`,
|
|
13
|
+
scope: {bezier, styled},
|
|
14
|
+
source: fs.readFileSync(`${__dirname}/AnimationExample.tsx`, 'utf-8')
|
|
15
|
+
}
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
import {
|
|
2
|
+
map,
|
|
3
|
+
React,
|
|
4
|
+
ReactDOM,
|
|
5
|
+
rxComponent,
|
|
6
|
+
context,
|
|
7
|
+
state
|
|
8
|
+
} from '../_utils/globalScope'
|
|
9
|
+
import { tap } from "rxjs/operators";
|
|
10
|
+
//@endimport
|
|
11
|
+
|
|
12
|
+
const ModeContext = React.createContext({
|
|
13
|
+
current: 'light',
|
|
14
|
+
set: (nextMode) => {}
|
|
15
|
+
})
|
|
16
|
+
|
|
17
|
+
const observeMode = () => context(ModeContext).pipe(map(({current}) => current))
|
|
18
|
+
|
|
19
|
+
const LIGHT = {backgroundColor: '#eee', color: '#333'}
|
|
20
|
+
const DARK = {backgroundColor: '#222', color: '#eee'}
|
|
21
|
+
|
|
22
|
+
const MODE = {light: LIGHT, dark: DARK}
|
|
23
|
+
|
|
24
|
+
const ModeSwitch = rxComponent(() => {
|
|
25
|
+
const modeCtx$ = context(ModeContext)
|
|
26
|
+
|
|
27
|
+
return modeCtx$.pipe(
|
|
28
|
+
map(({current, set}) => {
|
|
29
|
+
const next = current === 'light' ? 'dark' : 'light'
|
|
30
|
+
return (
|
|
31
|
+
<button onClick={() => set(next)} style={MODE[current]}>
|
|
32
|
+
Change to {next}
|
|
33
|
+
</button>
|
|
34
|
+
)
|
|
35
|
+
})
|
|
36
|
+
)
|
|
37
|
+
})
|
|
38
|
+
|
|
39
|
+
const App = rxComponent(() => {
|
|
40
|
+
const mode$ = observeMode()
|
|
41
|
+
|
|
42
|
+
return mode$.pipe(
|
|
43
|
+
tap(console.log),
|
|
44
|
+
map((mode) => (
|
|
45
|
+
<div style={{...MODE[mode], padding: '1em'}}>
|
|
46
|
+
<h2>Using {mode} mode</h2>
|
|
47
|
+
<ModeSwitch />
|
|
48
|
+
</div>
|
|
49
|
+
))
|
|
50
|
+
)
|
|
51
|
+
})
|
|
52
|
+
|
|
53
|
+
const ContextExample = rxComponent(() => {
|
|
54
|
+
const [mode$, setMode] = state('light')
|
|
55
|
+
|
|
56
|
+
return mode$.pipe(
|
|
57
|
+
map((mode) => (
|
|
58
|
+
<>
|
|
59
|
+
<ModeContext.Provider value={{current: mode, set: setMode}}>
|
|
60
|
+
<App />
|
|
61
|
+
</ModeContext.Provider>
|
|
62
|
+
</>
|
|
63
|
+
))
|
|
64
|
+
)
|
|
65
|
+
})
|
|
66
|
+
|
|
67
|
+
ReactDOM.render(<ContextExample />, document.getElementById('context-example'))
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
import {
|
|
2
|
+
catchError,
|
|
3
|
+
concat,
|
|
4
|
+
map,
|
|
5
|
+
merge,
|
|
6
|
+
of,
|
|
7
|
+
operators,
|
|
8
|
+
React,
|
|
9
|
+
ReactDOM,
|
|
10
|
+
rxComponent,
|
|
11
|
+
take,
|
|
12
|
+
throwError,
|
|
13
|
+
timer,
|
|
14
|
+
handler
|
|
15
|
+
} from '../_utils/globalScope'
|
|
16
|
+
//@endimport
|
|
17
|
+
|
|
18
|
+
const {mergeMapTo, switchMapTo} = operators
|
|
19
|
+
|
|
20
|
+
const timer$ = timer(0, 1000)
|
|
21
|
+
|
|
22
|
+
const ErrorsExample = rxComponent(() => {
|
|
23
|
+
const [onRetry$, onRetry] = handler()
|
|
24
|
+
const [onError$, onError] = handler()
|
|
25
|
+
|
|
26
|
+
const errors$ = onError$.pipe(
|
|
27
|
+
mergeMapTo(throwError(new Error("You clicked the button, didn't you!?")))
|
|
28
|
+
)
|
|
29
|
+
|
|
30
|
+
return merge(timer$, errors$).pipe(
|
|
31
|
+
map(n => ({number: n})),
|
|
32
|
+
catchError((error, caught$) => {
|
|
33
|
+
return merge(
|
|
34
|
+
of({error}),
|
|
35
|
+
onRetry$.pipe(
|
|
36
|
+
take(1),
|
|
37
|
+
switchMapTo(concat(of({error, retrying: true}), caught$))
|
|
38
|
+
)
|
|
39
|
+
)
|
|
40
|
+
}),
|
|
41
|
+
map(props => (
|
|
42
|
+
<div>
|
|
43
|
+
{props.error ? (
|
|
44
|
+
props.retrying ? (
|
|
45
|
+
<>Trying again…</>
|
|
46
|
+
) : (
|
|
47
|
+
<>
|
|
48
|
+
<div style={{color: 'crimson'}}>
|
|
49
|
+
Oh no! An error occurred:
|
|
50
|
+
<br />
|
|
51
|
+
{props.error.message}
|
|
52
|
+
</div>
|
|
53
|
+
<button onClick={onRetry}>Try again</button>
|
|
54
|
+
</>
|
|
55
|
+
)
|
|
56
|
+
) : (
|
|
57
|
+
<>
|
|
58
|
+
<div>You did not click the button for: {props.number}s</div>
|
|
59
|
+
<button type="button" onClick={onError}>
|
|
60
|
+
DO NOT CLICK THE BUTTON
|
|
61
|
+
</button>
|
|
62
|
+
</>
|
|
63
|
+
)}
|
|
64
|
+
</div>
|
|
65
|
+
))
|
|
66
|
+
)
|
|
67
|
+
})
|
|
68
|
+
|
|
69
|
+
ReactDOM.render(<ErrorsExample />, document.getElementById('errors-example'))
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import {
|
|
2
|
+
map,
|
|
3
|
+
React,
|
|
4
|
+
ReactDOM,
|
|
5
|
+
rxComponent,
|
|
6
|
+
startWith,
|
|
7
|
+
handler
|
|
8
|
+
} from '../_utils/globalScope'
|
|
9
|
+
//@endimport
|
|
10
|
+
|
|
11
|
+
const STYLE: React.CSSProperties = {
|
|
12
|
+
display: 'flex',
|
|
13
|
+
alignItems: 'center',
|
|
14
|
+
textAlign: 'center',
|
|
15
|
+
height: 150,
|
|
16
|
+
width: 150,
|
|
17
|
+
border: '1px dashed',
|
|
18
|
+
padding: '1em'
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
const EventHandlersExample = rxComponent(() => {
|
|
22
|
+
const [mouseMoves$, onMouseMove] = handler<React.MouseEvent>()
|
|
23
|
+
|
|
24
|
+
const mousePosition$ = mouseMoves$.pipe(
|
|
25
|
+
map(event => ({x: event.clientX, y: event.clientY})),
|
|
26
|
+
startWith(null)
|
|
27
|
+
)
|
|
28
|
+
return mousePosition$.pipe(
|
|
29
|
+
map(position => (
|
|
30
|
+
<div style={STYLE} onMouseMove={onMouseMove}>
|
|
31
|
+
<div style={{width: '100%'}}>
|
|
32
|
+
{position ? (
|
|
33
|
+
<>
|
|
34
|
+
Cursor position: X:{position.x}, Y: {position.y}
|
|
35
|
+
</>
|
|
36
|
+
) : (
|
|
37
|
+
<>Move mouse here</>
|
|
38
|
+
)}
|
|
39
|
+
</div>
|
|
40
|
+
</div>
|
|
41
|
+
))
|
|
42
|
+
)
|
|
43
|
+
})
|
|
44
|
+
|
|
45
|
+
ReactDOM.render(
|
|
46
|
+
<EventHandlersExample />,
|
|
47
|
+
document.getElementById('event-handlers-example')
|
|
48
|
+
)
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import {Example} from '../../pages/Examples/Examples'
|
|
2
|
+
|
|
3
|
+
const fs = require('fs')
|
|
4
|
+
|
|
5
|
+
export const EventHandlersExample: Example = {
|
|
6
|
+
id: 'event-handlers',
|
|
7
|
+
title: 'Event handlers',
|
|
8
|
+
source: fs.readFileSync(`${__dirname}/EventHandlersExample.tsx`, 'utf-8')
|
|
9
|
+
}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import {
|
|
2
|
+
map,
|
|
3
|
+
React,
|
|
4
|
+
ReactDOM,
|
|
5
|
+
rxComponent,
|
|
6
|
+
switchMap
|
|
7
|
+
} from '../_utils/globalScope'
|
|
8
|
+
//@endimport
|
|
9
|
+
|
|
10
|
+
const {distinctUntilChanged} = operators
|
|
11
|
+
|
|
12
|
+
const FetchComponent = rxComponent(props$ =>
|
|
13
|
+
props$.pipe(
|
|
14
|
+
map(props => props.url),
|
|
15
|
+
distinctUntilChanged(),
|
|
16
|
+
switchMap(url => fetch(url).then(response => response.text())),
|
|
17
|
+
map(responseText => <div>The result was: {responseText}</div>)
|
|
18
|
+
)
|
|
19
|
+
)
|
|
20
|
+
|
|
21
|
+
const URLS = ['/fetch/a.txt', '/fetch/b.txt']
|
|
22
|
+
|
|
23
|
+
function FetchExample() {
|
|
24
|
+
const [currentUrl, setCurrentUrl] = React.useState('')
|
|
25
|
+
return (
|
|
26
|
+
<div>
|
|
27
|
+
<p>
|
|
28
|
+
{URLS.map(url => (
|
|
29
|
+
<button key={url} onClick={() => setCurrentUrl(url)}>
|
|
30
|
+
{url}
|
|
31
|
+
</button>
|
|
32
|
+
))}
|
|
33
|
+
</p>
|
|
34
|
+
{currentUrl ? (
|
|
35
|
+
<FetchComponent url={currentUrl} />
|
|
36
|
+
) : (
|
|
37
|
+
<>Click on url to fetch</>
|
|
38
|
+
)}
|
|
39
|
+
</div>
|
|
40
|
+
)
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
ReactDOM.render(<FetchExample />, document.getElementById('fetch-example'))
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
Hello this is A
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
Hello this is B
|