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,147 @@
1
+ import * as React from 'react'
2
+
3
+ import * as globalScope from '../../examples/_utils/globalScope'
4
+ import {Checkerboard} from './Checkerboard'
5
+ import {ShowError} from './ShowError'
6
+ import {CodeMirror} from './CodeMirror'
7
+ import {compile} from './compile/babel'
8
+ import {evalReactDomRender} from './eval/evalReactDomRender'
9
+ import {Prelude} from './Prelude'
10
+ import {EvalCode} from './EvalCode'
11
+ import './codemirror-lib'
12
+ import styled from 'styled-components'
13
+
14
+ const fs = require('fs')
15
+
16
+ interface Scope {
17
+ [variableName: string]: any
18
+ }
19
+
20
+ interface Props {
21
+ source: string
22
+ scope?: Scope
23
+ filename: string
24
+ prelude?: string
25
+ }
26
+
27
+ const tryCompile = (code: string, filename: string) => {
28
+ try {
29
+ return [null, compile(code, {filename})?.code || '']
30
+ } catch (error) {
31
+ return [error]
32
+ }
33
+ }
34
+
35
+ const evalRender = (code: string, scope: Scope = {}) => {
36
+ return evalReactDomRender(code, {
37
+ ...scope,
38
+ ...globalScope
39
+ })
40
+ }
41
+
42
+ const COMMON_PRELUDE = `import {rxComponent, observeEvent, observeContext, observeState, forwardRef} from 'react-rx'\n${
43
+ fs
44
+ .readFileSync(`${__dirname}/../../examples/_utils/globalScope.ts`, 'utf-8')
45
+ .split('//@endimport')[0]
46
+ }`
47
+
48
+ const stripImports = (str: string) => {
49
+ return str
50
+ .split('//@endimport')
51
+ .slice(-1)[0]
52
+ .trim()
53
+ }
54
+
55
+ const CODEMIRROR_MODE = {
56
+ name: 'jsx',
57
+ base: {name: 'javascript', typescript: true}
58
+ }
59
+
60
+ const CODEMIRROR_OPTIONS = {
61
+ theme: 'custom',
62
+ smartIndent: false,
63
+ tabSize: 2,
64
+ mode: CODEMIRROR_MODE
65
+ }
66
+
67
+ const StyledWrapper = styled.div`
68
+ @media (max-width: 979px) {
69
+ display: block;
70
+ }
71
+ @media (min-width: 1280px) {
72
+ display: flex;
73
+ align-items: stretch;
74
+ flex-direction: row;
75
+ }
76
+ `
77
+ const Header = styled.div`
78
+ color: #d8d8d8;
79
+ font-size: 0.9em;
80
+ text-transform: uppercase;
81
+ padding: 0.5em 1.5em;
82
+ `
83
+ const BORDER_RADIUS = 0.5
84
+ const Column = styled.div<{type: 'editor' | 'result'}>`
85
+ @media (min-width: 1280px) {
86
+ border-radius: ${props =>
87
+ props.type === 'editor'
88
+ ? `${BORDER_RADIUS}em 0 0 ${BORDER_RADIUS}em`
89
+ : `0 ${BORDER_RADIUS}em ${BORDER_RADIUS}em 0`};
90
+ padding: ${props =>
91
+ props.type === 'editor' ? '0 1px 0.5em 0' : '0 0 0.5em 1px'};
92
+ }
93
+ @media (max-width: 1279px) {
94
+ border-radius: ${props =>
95
+ props.type === 'editor'
96
+ ? `${BORDER_RADIUS}em ${BORDER_RADIUS}em 0 0`
97
+ : `0 0 ${BORDER_RADIUS}em ${BORDER_RADIUS}em`};
98
+ padding: ${props => (props.type === 'editor' ? '0' : '0 0 0.5em 0')};
99
+ }
100
+ flex: 0 0 ${props => (props.type === 'editor' ? 60 : 40)}%;
101
+ background: #282c34;
102
+ `
103
+
104
+ export function CodeBlock(props: Props) {
105
+ const source = stripImports(props.source)
106
+ const [code, setCode] = React.useState(source.trim())
107
+
108
+ const [compileError, transformed] = tryCompile(code, props.filename)
109
+ return (
110
+ <StyledWrapper>
111
+ <Column type="editor">
112
+ <Header>Live editor</Header>
113
+ <Prelude
114
+ mode={CODEMIRROR_MODE}
115
+ value={`${COMMON_PRELUDE}${props.prelude ? props.prelude : ''}`}
116
+ />
117
+ <CodeMirror
118
+ value={code}
119
+ options={CODEMIRROR_OPTIONS}
120
+ onBeforeChange={(editor, data, value) => {
121
+ setCode(value)
122
+ }}
123
+ />
124
+ </Column>
125
+ <Column type="result">
126
+ <Header>Result</Header>
127
+ <Checkerboard>
128
+ <div style={{padding: '2em'}}>
129
+ {compileError ? (
130
+ <ShowError title="Compile error">
131
+ {compileError.message}
132
+ </ShowError>
133
+ ) : (
134
+ <EvalCode
135
+ code={transformed}
136
+ evalWith={src => evalRender(src, props.scope)}
137
+ renderError={error => (
138
+ <ShowError title="Runtime error">{error.message}</ShowError>
139
+ )}
140
+ />
141
+ )}
142
+ </div>
143
+ </Checkerboard>
144
+ </Column>
145
+ </StyledWrapper>
146
+ )
147
+ }
@@ -0,0 +1,37 @@
1
+ import styled from 'styled-components'
2
+ import {Controlled} from 'react-codemirror2'
3
+
4
+ const SCROLLBAR_BG_COLOR = '#1f222a'
5
+ const SCROLLBAR_THUMB_COLOR = '#575757'
6
+
7
+ export const CodeMirror = styled(Controlled)`
8
+ font-size: 0.8em;
9
+ background-color: #282c34;
10
+
11
+ & ::-webkit-scrollbar {
12
+ width: 11px;
13
+ }
14
+ & {
15
+ scrollbar-width: thin;
16
+ scrollbar-color: ${SCROLLBAR_THUMB_COLOR} ${SCROLLBAR_BG_COLOR};
17
+ }
18
+
19
+ & ::-webkit-scrollbar-track {
20
+ background: ${SCROLLBAR_BG_COLOR};
21
+ }
22
+ & ::-webkit-scrollbar-thumb {
23
+ background-color: ${SCROLLBAR_THUMB_COLOR} ;
24
+ border-radius: 6px;
25
+ border: 3px solid ${SCROLLBAR_BG_COLOR};
26
+ }
27
+ .CodeMirror-scroll {
28
+ max-height: calc(100vh - 24em);
29
+ }
30
+ .CodeMirror {
31
+ padding: 0.6rem;
32
+ height: auto;
33
+ font-family: source-code-pro,Menlo,Monaco,Consolas,Courier New,monospace;
34
+ -webkit-font-smoothing: antialiased;
35
+ line-height: 1.4em;
36
+ }
37
+ }`
@@ -0,0 +1,67 @@
1
+ import {rxComponent} from 'react-rx'
2
+ import {map, switchMap, toArray} from 'rxjs/operators'
3
+ import * as React from 'react'
4
+ import styled from 'styled-components'
5
+ import {runMode} from './runMode'
6
+
7
+ export interface CodeMirrorModeProps {
8
+ mode: null | {name: string; base?: any}
9
+ highlighted?: number[]
10
+ children: string
11
+ className?: string
12
+ }
13
+
14
+ export const CodeMirrorMode = rxComponent<CodeMirrorModeProps>(
15
+ (props$) => {
16
+ return props$.pipe(
17
+ switchMap((props) =>
18
+ runMode(props.children, props.mode).pipe(
19
+ toArray(),
20
+ map((lines, i) => (
21
+ <Code
22
+ key={`line-${i}`}
23
+ className={`cm-s-custom${
24
+ props.className ? ` ${props.className}` : ''
25
+ }`}
26
+ >
27
+ {lines.map((line, lineNo) => (
28
+ <div
29
+ key={`line-${i}-${lineNo}`}
30
+ className={`cm-line${
31
+ (props.highlighted || []).includes(lineNo + 1)
32
+ ? ' CodeMirror-selected'
33
+ : ''
34
+ }`}
35
+ >
36
+ {line.map((token, i) =>
37
+ token.style ? (
38
+ <span key={i} className={`cm-${token.style}`}>
39
+ {token.token}
40
+ </span>
41
+ ) : (
42
+ token.token
43
+ )
44
+ )}
45
+ </div>
46
+ ))}
47
+ </Code>
48
+ ))
49
+ )
50
+ )
51
+ )
52
+ }
53
+ )
54
+
55
+ const Code = styled.div`
56
+ font-size: 0.8em;
57
+
58
+ background-color: rgb(40, 44, 52);
59
+ color: #fff;
60
+ margin: 0;
61
+ white-space: pre;
62
+ overflow: auto;
63
+ padding: 0.9rem;
64
+ font-family: source-code-pro, Menlo, Monaco, Consolas, Courier New, monospace;
65
+ -webkit-font-smoothing: antialiased;
66
+ line-height: 1.4em;
67
+ `
@@ -0,0 +1,55 @@
1
+ import * as React from 'react'
2
+
3
+ interface EvalErrorBoundaryProps {
4
+ code: string
5
+ renderError: (error: Error) => React.ReactNode
6
+ }
7
+
8
+ interface EvalErrorBoundaryState {
9
+ error: Error | null
10
+ }
11
+
12
+ class EvalErrorBoundary extends React.Component<
13
+ EvalErrorBoundaryProps,
14
+ EvalErrorBoundaryState
15
+ > {
16
+ state: EvalErrorBoundaryState = {error: null}
17
+
18
+ static getDerivedStateFromError(error: Error) {
19
+ return {error}
20
+ }
21
+
22
+ componentDidUpdate(
23
+ prevProps: Readonly<EvalErrorBoundaryProps>,
24
+ prevState: Readonly<EvalErrorBoundaryState>
25
+ ) {
26
+ if (prevProps.code !== this.props.code) {
27
+ this.setState({error: null})
28
+ }
29
+ }
30
+
31
+ render() {
32
+ const {error} = this.state
33
+ return error ? this.props.renderError(error) : this.props.children
34
+ }
35
+ }
36
+
37
+ type Runner = (code: string) => React.ReactNode
38
+
39
+ const Eval = (props: {with: Runner; code: string}) => (
40
+ <>{props.with(props.code)}</>
41
+ )
42
+
43
+ interface Props {
44
+ code: string
45
+ renderError: (error: Error) => React.ReactNode
46
+ evalWith: Runner
47
+ }
48
+
49
+ export function EvalCode(props: Props) {
50
+ return (
51
+ <EvalErrorBoundary code={props.code} renderError={props.renderError}>
52
+ <Eval with={props.evalWith} code={props.code} />
53
+ </EvalErrorBoundary>
54
+ )
55
+ }
@@ -0,0 +1,50 @@
1
+ import * as React from 'react'
2
+ import styled from 'styled-components'
3
+ import {CodeMirrorMode} from './CodeMirrorMode'
4
+
5
+ const Details = styled.details`
6
+ text-align: right;
7
+ white-space: pre;
8
+ background-color: #1f222a;
9
+ line-height: 1.4em;
10
+ border: 0;
11
+ box-sizing: border-box;
12
+ `
13
+
14
+ const Summary = styled.summary`
15
+ background-color: #242831;
16
+ display: inline-block;
17
+ color: #65737e;
18
+ font-size: 0.8em;
19
+ border-radius: 2px 2px 0 0;
20
+ margin: 1px 0 0 0;
21
+ text-transform: uppercase;
22
+ padding: 0.4em 0.9em;
23
+ font-family: source-code-pro, Menlo, Monaco, Consolas, Courier New, monospace;
24
+ -webkit-font-smoothing: antialiased;
25
+ outline: none;
26
+ `
27
+
28
+ const StyledCodeMirrorMode = styled(CodeMirrorMode)`
29
+ opacity: 0.7;
30
+ text-align: left;
31
+ `
32
+
33
+ interface Props {
34
+ mode: any
35
+ value: string
36
+ }
37
+
38
+ export const Prelude = (props: Props) => {
39
+ const [isOpen, setOpen] = React.useState(false)
40
+ return (
41
+ <Details>
42
+ <Summary onClick={() => setOpen(current => !current)}>
43
+ {isOpen ? 'hide prelude' : 'show prelude'}
44
+ </Summary>
45
+ <StyledCodeMirrorMode mode={props.mode}>
46
+ {props.value}
47
+ </StyledCodeMirrorMode>
48
+ </Details>
49
+ )
50
+ }
@@ -0,0 +1,27 @@
1
+ import * as React from 'react'
2
+ import styled from 'styled-components'
3
+
4
+ interface Props {
5
+ title: string
6
+ children: React.ReactNode
7
+ className?: string
8
+ }
9
+
10
+ const Pre = styled.pre`
11
+ color: rgb(255, 100, 100);
12
+ `
13
+
14
+ const Heading = styled.h2`
15
+ padding: 3px:
16
+ color: #fff
17
+ padding: 8px;
18
+ `
19
+
20
+ export function ShowError(props: Props) {
21
+ return (
22
+ <div className={props.className}>
23
+ <Heading>{props.title}</Heading>
24
+ <Pre>{props.children}</Pre>
25
+ </div>
26
+ )
27
+ }
@@ -0,0 +1,8 @@
1
+ import * as codemirror from 'codemirror'
2
+ import 'codemirror/mode/javascript/javascript'
3
+ import 'codemirror/mode/jsx/jsx'
4
+ import 'codemirror/addon/selection/active-line'
5
+ import 'codemirror/addon/edit/matchbrackets'
6
+ import 'codemirror/addon/edit/matchtags'
7
+
8
+ export default codemirror
@@ -0,0 +1,131 @@
1
+ .cm-s-custom.CodeMirror {
2
+ background: rgb(32, 35, 42);
3
+ color: #f8f8f2;
4
+ }
5
+
6
+ .cm-s-custom div.CodeMirror-selected {
7
+ background: rgba(101, 115, 126, 0.33);
8
+ }
9
+
10
+ .cm-s-custom .CodeMirror-line::selection,
11
+ .cm-s-custom .CodeMirror-line > span::selection,
12
+ .cm-s-custom .CodeMirror-line > span > span::selection {
13
+ background: rgba(101, 115, 126, 0.33);
14
+ }
15
+
16
+ .cm-s-custom .CodeMirror-line::-moz-selection,
17
+ .cm-s-custom .CodeMirror-line > span::-moz-selection,
18
+ .cm-s-custom .CodeMirror-line > span > span::-moz-selection {
19
+ background: rgba(101, 115, 126, 0.33);
20
+ }
21
+
22
+ .cm-s-custom .CodeMirror-gutters {
23
+ background: #304148;
24
+ border-right: 10px;
25
+ }
26
+
27
+ .cm-s-custom .CodeMirror-guttermarker {
28
+ color: white;
29
+ }
30
+
31
+ .cm-s-custom .CodeMirror-guttermarker-subtle {
32
+ color: #d0d0d0;
33
+ }
34
+
35
+ .cm-s-custom .CodeMirror-linenumber {
36
+ color: #d0d0d0;
37
+ }
38
+
39
+ .cm-s-custom .CodeMirror-cursor {
40
+ border-left: 1px solid #f8f8f0;
41
+ }
42
+
43
+ .cm-s-custom span.cm-comment {
44
+ color: #65737e;
45
+ }
46
+
47
+ .cm-s-custom span.cm-atom {
48
+ color: #c594c5;
49
+ }
50
+
51
+ .cm-s-custom span.cm-number {
52
+ color: #f99157;
53
+ }
54
+
55
+ .cm-s-custom span.cm-type {
56
+ color: #48aab5;
57
+ }
58
+
59
+ .cm-s-custom span.cm-property {
60
+ color: rgb(121, 182, 242);
61
+ }
62
+
63
+ .cm-s-custom span.cm-attribute,
64
+ .cm-s-custom span.cm-keyword {
65
+ color: rgb(197, 165, 197);
66
+ }
67
+
68
+ .cm-s-custom span.cm-builtin {
69
+ color: #66d9ef;
70
+ }
71
+
72
+ .cm-s-custom span.cm-string {
73
+ color: #8dc891;
74
+ }
75
+
76
+ .cm-s-custom span.cm-variable {
77
+ color: #d8d8d8;
78
+ }
79
+
80
+ .cm-s-custom span.cm-variable-2,
81
+ .cm-s-custom span.cm-variable-3 {
82
+ color: #f8f8f2;
83
+ }
84
+
85
+ .cm-s-custom span.cm-def {
86
+ color: #fac863;
87
+ }
88
+
89
+ .cm-s-custom span.cm-bracket {
90
+ color: #5fb3b3;
91
+ }
92
+
93
+ .cm-s-custom span.cm-tag {
94
+ color: rgb(252, 146, 158);
95
+ }
96
+
97
+ .cm-s-custom span.cm-tag.cm-bracket {
98
+ color: rgb(88, 200, 252);
99
+ }
100
+
101
+ .cm-s-custom span.cm-header {
102
+ color: #c594c5;
103
+ }
104
+
105
+ .cm-s-custom span.cm-link {
106
+ color: #c594c5;
107
+ }
108
+
109
+ .cm-s-custom span.cm-error {
110
+ background: #c594c5;
111
+ color: #f8f8f0;
112
+ }
113
+
114
+ .cm-s-custom .CodeMirror-activeline-background {
115
+ background: rgba(101, 115, 126, 0.1);
116
+ }
117
+
118
+ .cm-s-custom .CodeMirror-nonmatchingbracket {
119
+ color: #fa87b5 !important;
120
+ }
121
+
122
+ .cm-s-custom .CodeMirror-matchingbracket {
123
+ color: #fa87b5 !important;
124
+ background-color: rgba(255, 255, 255, 0.22) !important;
125
+ border-radius: 2px;
126
+ }
127
+
128
+ .cm-s-custom .CodeMirror-matchingtag {
129
+ background-color: rgba(255, 255, 255, 0.1) !important;
130
+ border-radius: 2px;
131
+ }
@@ -0,0 +1,21 @@
1
+ import * as babel from '@babel/standalone'
2
+ import transformTs from '@babel/plugin-transform-typescript'
3
+ import transformJsx from '@babel/plugin-transform-react-jsx'
4
+ import optionalChaining from '@babel/plugin-proposal-optional-chaining'
5
+
6
+ interface Options {
7
+ filename?: string
8
+ plugins?: any[]
9
+ }
10
+
11
+ export function compile(code: string, options: Options = {}) {
12
+ return babel.transform(code, {
13
+ filename: options.filename || 'Unknown.tsx',
14
+ plugins: [
15
+ ...(options.plugins || []),
16
+ optionalChaining,
17
+ [transformTs, {allExtensions: true, isTSX: true}],
18
+ transformJsx
19
+ ]
20
+ })
21
+ }
@@ -0,0 +1,27 @@
1
+ import {evalCode} from './evalCode'
2
+
3
+ export const evalCallback = (
4
+ code: string,
5
+ callbackName = 'callback',
6
+ scope = {}
7
+ ): any => {
8
+ let renderCount = 0
9
+ let renderRes = null
10
+
11
+ const callback = (arg: any) => {
12
+ renderCount++
13
+ renderRes = arg
14
+ }
15
+
16
+ evalCode(code, {...scope, [callbackName]: callback})
17
+
18
+ if (renderCount === 0) {
19
+ throw new Error(`${callbackName}() was not called`)
20
+ }
21
+
22
+ if (renderCount > 1) {
23
+ throw new Error(`${callbackName}() was called more than once`)
24
+ }
25
+
26
+ return renderRes
27
+ }
@@ -0,0 +1,7 @@
1
+ export const evalCode = (code: string, scope: {[v: string]: any}) => {
2
+ const scopeKeys = Object.keys(scope)
3
+ const scopeValues = scopeKeys.map(key => scope[key])
4
+ // eslint-disable-next-line no-new-func
5
+ const res = new Function(...scopeKeys, code)
6
+ return res(...scopeValues)
7
+ }
@@ -0,0 +1,4 @@
1
+ import {evalCode} from './evalCode'
2
+
3
+ export const evalExpression = (code: string, scope = {}) =>
4
+ evalCode(`return ${code}`, scope)
@@ -0,0 +1,23 @@
1
+ import {evalCode} from './evalCode'
2
+
3
+ export const evalReactDomRender = (code: string, scope = {}): any => {
4
+ let renderCount = 0
5
+ let renderRes = null
6
+
7
+ const callback = (arg: any) => {
8
+ renderCount++
9
+ renderRes = arg
10
+ }
11
+
12
+ evalCode(code, {...scope, ReactDOM: {render: callback}})
13
+
14
+ if (renderCount === 0) {
15
+ throw new Error(`ReactDOM.render() was never called`)
16
+ }
17
+
18
+ if (renderCount > 1) {
19
+ throw new Error(`ReactDOM.render() was called more than once`)
20
+ }
21
+
22
+ return renderRes
23
+ }
@@ -0,0 +1 @@
1
+ export {CodeBlock} from './CodeBlock'
@@ -0,0 +1,42 @@
1
+ import {Mode} from 'codemirror'
2
+ import CodeMirror from './codemirror-lib'
3
+ import {Observable} from 'rxjs'
4
+
5
+ interface Token {
6
+ style: string | null
7
+ token: string
8
+ }
9
+
10
+ export interface ModeSpec {
11
+ name: string
12
+
13
+ [key: string]: any
14
+ }
15
+
16
+ export function runMode(
17
+ source: string,
18
+ modespec: ModeSpec | null,
19
+ options?: {state?: any; tabSize: number}
20
+ ): Observable<Token[]> {
21
+ return new Observable(subscriber => {
22
+ const mode: Mode<any> = CodeMirror.getMode(CodeMirror.defaults, modespec)
23
+ const lines = CodeMirror.splitLines(source)
24
+ const state = (options && options.state) || CodeMirror.startState(mode)
25
+
26
+ for (let i = 0, e = lines.length; i < e; ++i) {
27
+ const tokens = []
28
+ const stream = new CodeMirror.StringStream(lines[i])
29
+ if (!stream.string && mode.blankLine) mode.blankLine(state)
30
+ while (!stream.eol()) {
31
+ const style = mode.token!(stream, state)
32
+ tokens.push({token: stream.current(), style})
33
+ stream.start = stream.pos
34
+ }
35
+ if (i !== lines.length - 1) {
36
+ tokens.push({token: '\n', style: null})
37
+ }
38
+ subscriber.next(tokens)
39
+ }
40
+ subscriber.complete()
41
+ })
42
+ }
@@ -0,0 +1,14 @@
1
+ import {createBrowserHistory, Location} from 'history'
2
+ import {Observable} from 'rxjs'
3
+ import {publishReplay, refCount} from 'rxjs/operators'
4
+
5
+ const history = createBrowserHistory()
6
+
7
+ export const location$ = new Observable<Location>((subscriber) => {
8
+ subscriber.next(history.location)
9
+ return history.listen((update) => subscriber.next(update.location))
10
+ }).pipe(publishReplay(1), refCount())
11
+
12
+ export const navigate = (url: string) => {
13
+ history.push(url)
14
+ }
@@ -0,0 +1,11 @@
1
+ import {map} from 'rxjs/operators'
2
+ import {location$} from './location'
3
+ import {NOT_FOUND, Page, pages} from '../pages/pages'
4
+ import {Observable} from 'rxjs'
5
+
6
+ export const page$: Observable<Page> = location$.pipe(
7
+ map(
8
+ location =>
9
+ pages.find(page => page.route === location.pathname) || NOT_FOUND
10
+ )
11
+ )