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.
Files changed (171) hide show
  1. package/.idea/codeStyles/Project.xml +0 -6
  2. package/.idea/inspectionProfiles/Project_Default.xml +0 -4
  3. package/.idea/workspace.xml +62 -49
  4. package/dist/cjs/WithObservable.d.ts +3 -3
  5. package/dist/cjs/WithObservable.js +3 -3
  6. package/dist/cjs/index.d.ts +6 -2
  7. package/dist/cjs/index.js +18 -11
  8. package/dist/cjs/reactiveComponent.d.ts +6 -6
  9. package/dist/cjs/reactiveComponent.js +8 -26
  10. package/dist/cjs/useAsObservable.d.ts +9 -0
  11. package/dist/cjs/useAsObservable.js +31 -0
  12. package/dist/cjs/useIsomorphicEffect.d.ts +2 -0
  13. package/dist/cjs/useIsomorphicEffect.js +5 -0
  14. package/dist/cjs/useObservable.d.ts +6 -15
  15. package/dist/cjs/useObservable.js +17 -73
  16. package/dist/cjs/useObservableCallback.d.ts +3 -0
  17. package/dist/cjs/useObservableCallback.js +24 -0
  18. package/dist/cjs/useWithObservable.d.ts +9 -0
  19. package/dist/cjs/useWithObservable.js +11 -0
  20. package/dist/cjs/utils.d.ts +7 -3
  21. package/dist/cjs/utils.js +29 -5
  22. package/dist/cjs/withPropsStream.js +3 -3
  23. package/dist/es2015/WithObservable.d.ts +3 -3
  24. package/dist/es2015/index.d.ts +6 -2
  25. package/dist/es2015/index.js +7 -2
  26. package/dist/es2015/reactiveComponent.d.ts +6 -6
  27. package/dist/es2015/reactiveComponent.js +9 -6
  28. package/dist/es2015/useAsObservable.d.ts +9 -0
  29. package/dist/es2015/useAsObservable.js +27 -0
  30. package/dist/es2015/useIsomorphicEffect.d.ts +2 -0
  31. package/dist/es2015/useIsomorphicEffect.js +2 -0
  32. package/dist/es2015/useObservable.d.ts +6 -15
  33. package/dist/es2015/useObservable.js +15 -46
  34. package/dist/es2015/useObservableCallback.d.ts +3 -0
  35. package/dist/es2015/useObservableCallback.js +19 -0
  36. package/dist/es2015/useWithObservable.d.ts +9 -0
  37. package/dist/es2015/useWithObservable.js +7 -0
  38. package/dist/es2015/utils.d.ts +7 -3
  39. package/dist/es2015/utils.js +24 -3
  40. package/dist/esm/WithObservable.d.ts +3 -3
  41. package/dist/esm/index.d.ts +6 -2
  42. package/dist/esm/index.js +7 -2
  43. package/dist/esm/reactiveComponent.d.ts +6 -6
  44. package/dist/esm/reactiveComponent.js +7 -6
  45. package/dist/esm/useAsObservable.d.ts +9 -0
  46. package/dist/esm/useAsObservable.js +27 -0
  47. package/dist/esm/useIsomorphicEffect.d.ts +2 -0
  48. package/dist/esm/useIsomorphicEffect.js +2 -0
  49. package/dist/esm/useObservable.d.ts +6 -15
  50. package/dist/esm/useObservable.js +15 -48
  51. package/dist/esm/useObservableCallback.d.ts +3 -0
  52. package/dist/esm/useObservableCallback.js +20 -0
  53. package/dist/esm/useWithObservable.d.ts +9 -0
  54. package/dist/esm/useWithObservable.js +7 -0
  55. package/dist/esm/utils.d.ts +7 -3
  56. package/dist/esm/utils.js +24 -3
  57. package/package.json +9 -4
  58. package/src/WithObservable.tsx +4 -3
  59. package/src/index.ts +12 -12
  60. package/src/reactiveComponent.ts +28 -20
  61. package/src/useAsObservable.ts +43 -0
  62. package/src/useIsomorphicEffect.ts +3 -0
  63. package/src/useObservable.ts +36 -77
  64. package/src/useObservableCallback.ts +30 -0
  65. package/src/useWithObservable.ts +23 -0
  66. package/src/utils.ts +39 -3
  67. package/website/.babelrc +21 -0
  68. package/website/.prettierrc +7 -0
  69. package/website/README.mdx +1 -0
  70. package/website/package.json +84 -0
  71. package/website/src/@types/babel.d.ts +4 -0
  72. package/website/src/@types/mdx.d.ts +11 -0
  73. package/website/src/@types/react-css-burger.d.ts +4 -0
  74. package/website/src/App.tsx +68 -0
  75. package/website/src/components/Header.tsx +118 -0
  76. package/website/src/components/Link.tsx +18 -0
  77. package/website/src/components/LoadPage.tsx +60 -0
  78. package/website/src/components/Sidebar.tsx +88 -0
  79. package/website/src/components/logos/Github.tsx +10 -0
  80. package/website/src/components/logos/React.tsx +27 -0
  81. package/website/src/components/logos/ReactRxLogo.tsx +39 -0
  82. package/website/src/components/logos/RxJs.tsx +69 -0
  83. package/website/src/components/repl/Checkerboard.tsx +25 -0
  84. package/website/src/components/repl/CodeBlock.tsx +147 -0
  85. package/website/src/components/repl/CodeMirror.tsx +37 -0
  86. package/website/src/components/repl/CodeMirrorMode.tsx +67 -0
  87. package/website/src/components/repl/EvalCode.tsx +55 -0
  88. package/website/src/components/repl/Prelude.tsx +50 -0
  89. package/website/src/components/repl/ShowError.tsx +27 -0
  90. package/website/src/components/repl/codemirror-lib.ts +8 -0
  91. package/website/src/components/repl/codemirror-theme.css +131 -0
  92. package/website/src/components/repl/compile/babel.ts +21 -0
  93. package/website/src/components/repl/eval/evalCallback.ts +27 -0
  94. package/website/src/components/repl/eval/evalCode.ts +7 -0
  95. package/website/src/components/repl/eval/evalExpression.ts +4 -0
  96. package/website/src/components/repl/eval/evalReactDomRender.ts +23 -0
  97. package/website/src/components/repl/index.ts +1 -0
  98. package/website/src/components/repl/runMode.ts +42 -0
  99. package/website/src/datastores/location.ts +14 -0
  100. package/website/src/datastores/page.ts +11 -0
  101. package/website/src/datastores/pageTransition.ts +97 -0
  102. package/website/src/entries/main.css +2 -0
  103. package/website/src/entries/main.tsx +6 -0
  104. package/website/src/examples/FizzBuzz/FizzBuzzExample.tsx +39 -0
  105. package/website/src/examples/FizzBuzz/index.tsx +9 -0
  106. package/website/src/examples/_utils/globalScope.ts +45 -0
  107. package/website/src/examples/animation/AnimationExample.tsx +152 -0
  108. package/website/src/examples/animation/easings.ts +0 -0
  109. package/website/src/examples/animation/index.tsx +15 -0
  110. package/website/src/examples/context/Context.example.jsx +67 -0
  111. package/website/src/examples/context/index.tsx +9 -0
  112. package/website/src/examples/errors/Errors.example.jsx +69 -0
  113. package/website/src/examples/errors/index.tsx +9 -0
  114. package/website/src/examples/event-handlers/EventHandlersExample.tsx +48 -0
  115. package/website/src/examples/event-handlers/index.tsx +9 -0
  116. package/website/src/examples/fetch/FetchExample.jsx +43 -0
  117. package/website/src/examples/fetch/a.txt +1 -0
  118. package/website/src/examples/fetch/b.txt +1 -0
  119. package/website/src/examples/fetch/index.tsx +9 -0
  120. package/website/src/examples/form-data/FormDataExample.jsx +119 -0
  121. package/website/src/examples/form-data/index.tsx +12 -0
  122. package/website/src/examples/form-data/storage.ts +27 -0
  123. package/website/src/examples/forward-ref/ForwardRefExample.tsx +55 -0
  124. package/website/src/examples/forward-ref/index.tsx +9 -0
  125. package/website/src/examples/hello-world/HelloWorld.example.jsx +6 -0
  126. package/website/src/examples/hello-world/index.tsx +9 -0
  127. package/website/src/examples/hooks-interop/HooksInterop.example.tsx +42 -0
  128. package/website/src/examples/hooks-interop/index.tsx +9 -0
  129. package/website/src/examples/passthrough-props/PassThroughPropsExample.jsx +57 -0
  130. package/website/src/examples/passthrough-props/index.tsx +11 -0
  131. package/website/src/examples/reactive-state/ReactiveState.example.jsx +43 -0
  132. package/website/src/examples/reactive-state/index.ts +9 -0
  133. package/website/src/examples/readme-examples/README.mdx +0 -0
  134. package/website/src/examples/readme-examples/index.ts +11 -0
  135. package/website/src/examples/shared-state/SharedState.example.tsx +59 -0
  136. package/website/src/examples/shared-state/index.tsx +9 -0
  137. package/website/src/examples/simple/Counter.example.tsx +14 -0
  138. package/website/src/examples/simple/index.tsx +9 -0
  139. package/website/src/examples/sync/Sync.example.tsx +9 -0
  140. package/website/src/examples/sync/index.tsx +9 -0
  141. package/website/src/examples/tick/TickExample.jsx +51 -0
  142. package/website/src/examples/tick/index.ts +9 -0
  143. package/website/src/examples/todo-app/TodoApp.example.tsx +88 -0
  144. package/website/src/examples/todo-app/index.tsx +12 -0
  145. package/website/src/examples/todo-app/storage.ts +27 -0
  146. package/website/src/examples/use-element/UseElementExample.tsx +70 -0
  147. package/website/src/examples/use-element/index.tsx +9 -0
  148. package/website/src/examples/use-observable/search/SearchExample.tsx +82 -0
  149. package/website/src/examples/use-observable/search/index.tsx +8 -0
  150. package/website/src/examples/use-observable/use-observable/UseObservableExample.tsx +70 -0
  151. package/website/src/examples/use-observable/use-observable/index.tsx +9 -0
  152. package/website/src/index.html +10 -0
  153. package/website/src/mdx-components.tsx +74 -0
  154. package/website/src/pages/Api/Api.mdx +134 -0
  155. package/website/src/pages/Api/ApiPage.tsx +25 -0
  156. package/website/src/pages/Examples/Examples.tsx +105 -0
  157. package/website/src/pages/Examples/ExamplesPage.tsx +13 -0
  158. package/website/src/pages/Guide/Guide.mdx +275 -0
  159. package/website/src/pages/Guide/GuidePage.tsx +25 -0
  160. package/website/src/pages/Index/IndexPage.tsx +50 -0
  161. package/website/src/pages/Index/ReactRxReadme.md +20 -0
  162. package/website/src/pages/NotFound.tsx +3 -0
  163. package/website/src/pages/pages.ts +46 -0
  164. package/website/src/pages/styles.tsx +24 -0
  165. package/website/src/theme.ts +61 -0
  166. package/website/src/utils/parseCodeFenceHeader.ts +32 -0
  167. package/website/tsconfig.json +30 -0
  168. package/website/vercel.json +4 -0
  169. package/website/webpack/config.js +5 -0
  170. package/website/webpack/createConfig.js +95 -0
  171. 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,9 @@
1
+ import {Example} from '../../pages/Examples/Examples'
2
+
3
+ const fs = require('fs')
4
+
5
+ export const ForwardRefExample: Example = {
6
+ id: 'forward-ref',
7
+ title: 'Forward Ref',
8
+ source: fs.readFileSync(`${__dirname}/ForwardRefExample.tsx`, 'utf-8')
9
+ }
@@ -0,0 +1,6 @@
1
+ import {of, React, ReactDOM, rxComponent} from '../_utils/globalScope'
2
+ //@endimport
3
+
4
+ const HelloWorld = rxComponent(of(<div>Hello World!</div>))
5
+
6
+ ReactDOM.render(<HelloWorld />, document.getElementById('hello-world-example'))
@@ -0,0 +1,9 @@
1
+ import {Example} from '../../pages/Examples/Examples'
2
+
3
+ const fs = require('fs')
4
+
5
+ export const HelloWorldExample: Example = {
6
+ id: 'hello-world',
7
+ title: 'A simple component',
8
+ source: fs.readFileSync(`${__dirname}/HelloWorld.example.jsx`, 'utf-8')
9
+ }
@@ -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
+ }
@@ -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,9 @@
1
+ import {Example} from '../../pages/Examples/Examples'
2
+
3
+ const fs = require('fs')
4
+
5
+ export const SharedStateExample: Example = {
6
+ id: 'shared-state',
7
+ title: 'Sharing state',
8
+ source: fs.readFileSync(`${__dirname}/SharedState.example.tsx`, 'utf-8')
9
+ }
@@ -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 {Example} from '../../pages/Examples/Examples'
2
+
3
+ const fs = require('fs')
4
+
5
+ export const SimpleExample: Example = {
6
+ id: 'stateful-component',
7
+ title: 'A stateful component',
8
+ source: fs.readFileSync(`${__dirname}/Counter.example.tsx`, 'utf-8')
9
+ }
@@ -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,9 @@
1
+ import {Example} from '../../pages/Examples/Examples'
2
+
3
+ import {readFileSync} from 'fs'
4
+
5
+ export const SyncExample: Example = {
6
+ id: 'sync-render',
7
+ title: 'Sync rendering',
8
+ source: readFileSync(`${__dirname}/Sync.example.tsx`, 'utf-8')
9
+ }
@@ -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'))
@@ -0,0 +1,9 @@
1
+ import {Example} from '../../pages/Examples/Examples'
2
+
3
+ const fs = require('fs')
4
+
5
+ export const TickExample: Example = {
6
+ id: 'ticker',
7
+ title: 'Ticker',
8
+ source: fs.readFileSync(`${__dirname}/TickExample.jsx`, 'utf-8')
9
+ }