react-rx 1.0.0-beta.6 → 2.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 (128) hide show
  1. package/.idea/compiler.xml +1 -1
  2. package/.idea/inspectionProfiles/Project_Default.xml +1 -0
  3. package/.idea/markdown.xml +9 -0
  4. package/.idea/misc.xml +0 -6
  5. package/dist/cjs/WithObservable.js +3 -3
  6. package/dist/cjs/displayName.js +1 -1
  7. package/dist/cjs/reactiveComponent.js +6 -6
  8. package/dist/cjs/useAsObservable.js +10 -18
  9. package/dist/cjs/useObservable.js +26 -31
  10. package/dist/cjs/useObservableCallback.js +4 -4
  11. package/dist/cjs/useWithObservable.js +2 -2
  12. package/dist/cjs/utils.js +7 -7
  13. package/dist/cjs/withPropsStream.js +8 -4
  14. package/dist/es2015/useAsObservable.js +10 -18
  15. package/dist/es2015/useObservable.js +24 -31
  16. package/dist/esm/displayName.js +1 -1
  17. package/dist/esm/useAsObservable.js +10 -18
  18. package/dist/esm/useObservable.js +26 -31
  19. package/package.json +5 -3
  20. package/src/useAsObservable.ts +13 -18
  21. package/src/useObservable.ts +39 -34
  22. package/.idea/workspace.xml +0 -228
  23. package/jest.config.js +0 -5
  24. package/website/.babelrc +0 -21
  25. package/website/.prettierrc +0 -7
  26. package/website/README.mdx +0 -1
  27. package/website/package.json +0 -84
  28. package/website/src/@types/babel.d.ts +0 -4
  29. package/website/src/@types/mdx.d.ts +0 -11
  30. package/website/src/@types/react-css-burger.d.ts +0 -4
  31. package/website/src/App.tsx +0 -68
  32. package/website/src/components/Header.tsx +0 -118
  33. package/website/src/components/Link.tsx +0 -18
  34. package/website/src/components/LoadPage.tsx +0 -60
  35. package/website/src/components/Sidebar.tsx +0 -88
  36. package/website/src/components/logos/Github.tsx +0 -10
  37. package/website/src/components/logos/React.tsx +0 -27
  38. package/website/src/components/logos/ReactRxLogo.tsx +0 -39
  39. package/website/src/components/logos/RxJs.tsx +0 -69
  40. package/website/src/components/repl/Checkerboard.tsx +0 -25
  41. package/website/src/components/repl/CodeBlock.tsx +0 -147
  42. package/website/src/components/repl/CodeMirror.tsx +0 -37
  43. package/website/src/components/repl/CodeMirrorMode.tsx +0 -67
  44. package/website/src/components/repl/EvalCode.tsx +0 -55
  45. package/website/src/components/repl/Prelude.tsx +0 -50
  46. package/website/src/components/repl/ShowError.tsx +0 -27
  47. package/website/src/components/repl/codemirror-lib.ts +0 -8
  48. package/website/src/components/repl/codemirror-theme.css +0 -131
  49. package/website/src/components/repl/compile/babel.ts +0 -21
  50. package/website/src/components/repl/eval/evalCallback.ts +0 -27
  51. package/website/src/components/repl/eval/evalCode.ts +0 -7
  52. package/website/src/components/repl/eval/evalExpression.ts +0 -4
  53. package/website/src/components/repl/eval/evalReactDomRender.ts +0 -23
  54. package/website/src/components/repl/index.ts +0 -1
  55. package/website/src/components/repl/runMode.ts +0 -42
  56. package/website/src/datastores/location.ts +0 -14
  57. package/website/src/datastores/page.ts +0 -11
  58. package/website/src/datastores/pageTransition.ts +0 -97
  59. package/website/src/entries/main.css +0 -2
  60. package/website/src/entries/main.tsx +0 -6
  61. package/website/src/examples/FizzBuzz/FizzBuzzExample.tsx +0 -39
  62. package/website/src/examples/FizzBuzz/index.tsx +0 -9
  63. package/website/src/examples/_utils/globalScope.ts +0 -45
  64. package/website/src/examples/animation/AnimationExample.tsx +0 -152
  65. package/website/src/examples/animation/easings.ts +0 -0
  66. package/website/src/examples/animation/index.tsx +0 -15
  67. package/website/src/examples/context/Context.example.jsx +0 -67
  68. package/website/src/examples/context/index.tsx +0 -9
  69. package/website/src/examples/errors/Errors.example.jsx +0 -69
  70. package/website/src/examples/errors/index.tsx +0 -9
  71. package/website/src/examples/event-handlers/EventHandlersExample.tsx +0 -48
  72. package/website/src/examples/event-handlers/index.tsx +0 -9
  73. package/website/src/examples/fetch/FetchExample.jsx +0 -43
  74. package/website/src/examples/fetch/a.txt +0 -1
  75. package/website/src/examples/fetch/b.txt +0 -1
  76. package/website/src/examples/fetch/index.tsx +0 -9
  77. package/website/src/examples/form-data/FormDataExample.jsx +0 -119
  78. package/website/src/examples/form-data/index.tsx +0 -12
  79. package/website/src/examples/form-data/storage.ts +0 -27
  80. package/website/src/examples/forward-ref/ForwardRefExample.tsx +0 -55
  81. package/website/src/examples/forward-ref/index.tsx +0 -9
  82. package/website/src/examples/hello-world/HelloWorld.example.jsx +0 -6
  83. package/website/src/examples/hello-world/index.tsx +0 -9
  84. package/website/src/examples/hooks-interop/HooksInterop.example.tsx +0 -42
  85. package/website/src/examples/hooks-interop/index.tsx +0 -9
  86. package/website/src/examples/passthrough-props/PassThroughPropsExample.jsx +0 -57
  87. package/website/src/examples/passthrough-props/index.tsx +0 -11
  88. package/website/src/examples/reactive-state/ReactiveState.example.jsx +0 -43
  89. package/website/src/examples/reactive-state/index.ts +0 -9
  90. package/website/src/examples/readme-examples/README.mdx +0 -0
  91. package/website/src/examples/readme-examples/index.ts +0 -11
  92. package/website/src/examples/shared-state/SharedState.example.tsx +0 -59
  93. package/website/src/examples/shared-state/index.tsx +0 -9
  94. package/website/src/examples/simple/Counter.example.tsx +0 -14
  95. package/website/src/examples/simple/index.tsx +0 -9
  96. package/website/src/examples/sync/Sync.example.tsx +0 -9
  97. package/website/src/examples/sync/index.tsx +0 -9
  98. package/website/src/examples/tick/TickExample.jsx +0 -51
  99. package/website/src/examples/tick/index.ts +0 -9
  100. package/website/src/examples/todo-app/TodoApp.example.tsx +0 -88
  101. package/website/src/examples/todo-app/index.tsx +0 -12
  102. package/website/src/examples/todo-app/storage.ts +0 -27
  103. package/website/src/examples/use-element/UseElementExample.tsx +0 -70
  104. package/website/src/examples/use-element/index.tsx +0 -9
  105. package/website/src/examples/use-observable/search/SearchExample.tsx +0 -82
  106. package/website/src/examples/use-observable/search/index.tsx +0 -8
  107. package/website/src/examples/use-observable/use-observable/UseObservableExample.tsx +0 -70
  108. package/website/src/examples/use-observable/use-observable/index.tsx +0 -9
  109. package/website/src/index.html +0 -10
  110. package/website/src/mdx-components.tsx +0 -74
  111. package/website/src/pages/Api/Api.mdx +0 -134
  112. package/website/src/pages/Api/ApiPage.tsx +0 -25
  113. package/website/src/pages/Examples/Examples.tsx +0 -105
  114. package/website/src/pages/Examples/ExamplesPage.tsx +0 -13
  115. package/website/src/pages/Guide/Guide.mdx +0 -275
  116. package/website/src/pages/Guide/GuidePage.tsx +0 -25
  117. package/website/src/pages/Index/IndexPage.tsx +0 -50
  118. package/website/src/pages/Index/ReactRxReadme.md +0 -20
  119. package/website/src/pages/NotFound.tsx +0 -3
  120. package/website/src/pages/pages.ts +0 -46
  121. package/website/src/pages/styles.tsx +0 -24
  122. package/website/src/theme.ts +0 -61
  123. package/website/src/utils/parseCodeFenceHeader.ts +0 -32
  124. package/website/tsconfig.json +0 -30
  125. package/website/vercel.json +0 -4
  126. package/website/webpack/config.js +0 -5
  127. package/website/webpack/createConfig.js +0 -95
  128. package/website/webpack/mdx-toc-loader.js +0 -38
@@ -1,152 +0,0 @@
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
@@ -1,15 +0,0 @@
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
- }
@@ -1,67 +0,0 @@
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'))
@@ -1,9 +0,0 @@
1
- import {Example} from '../../pages/Examples/Examples'
2
-
3
- const fs = require('fs')
4
-
5
- export const ContextExample: Example = {
6
- id: 'react-context',
7
- title: 'React context',
8
- source: fs.readFileSync(`${__dirname}/Context.example.jsx`, 'utf-8')
9
- }
@@ -1,69 +0,0 @@
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'))
@@ -1,9 +0,0 @@
1
- import {Example} from '../../pages/Examples/Examples'
2
-
3
- const fs = require('fs')
4
-
5
- export const ErrorsExample: Example = {
6
- id: 'errors',
7
- title: 'Errors',
8
- source: fs.readFileSync(`${__dirname}/Errors.example.jsx`, 'utf-8')
9
- }
@@ -1,48 +0,0 @@
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
- )
@@ -1,9 +0,0 @@
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
- }
@@ -1,43 +0,0 @@
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'))
@@ -1 +0,0 @@
1
- Hello this is A
@@ -1 +0,0 @@
1
- Hello this is B
@@ -1,9 +0,0 @@
1
- import {Example} from '../../pages/Examples/Examples'
2
-
3
- const fs = require('fs')
4
-
5
- export const FetchExample: Example = {
6
- id: 'fetch',
7
- title: 'Fetch',
8
- source: fs.readFileSync(`${__dirname}/FetchExample.jsx`, 'utf-8')
9
- }
@@ -1,119 +0,0 @@
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
- `
@@ -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 FormDataExample: Example = {
8
- id: 'form-data',
9
- title: 'Form data',
10
- scope: {storage, styled},
11
- source: fs.readFileSync(`${__dirname}/FormDataExample.jsx`, '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,55 +0,0 @@
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
- )
@@ -1,9 +0,0 @@
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
- }
@@ -1,6 +0,0 @@
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'))
@@ -1,9 +0,0 @@
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
- }