@zat-design/sisyphus-react 3.1.4 → 3.1.5-beta.10

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 (174) hide show
  1. package/.dumi/theme/builtins/Alert.tsx +19 -0
  2. package/.dumi/theme/builtins/Previewer.tsx +232 -0
  3. package/.dumi/theme/builtins/SourceCode.tsx +64 -0
  4. package/.dumi/theme/hooks/useCodeSandbox.tsx +197 -0
  5. package/.dumi/theme/hooks/useTheme.tsx +707 -0
  6. package/.dumi/theme/layouts/BasicLayout.tsx +88 -0
  7. package/.dumi/theme/layouts/components/Dark.less +157 -0
  8. package/.dumi/theme/layouts/components/Dark.tsx +78 -0
  9. package/.dumi/theme/layouts/components/Navbar.tsx +83 -0
  10. package/.dumi/theme/layouts/components/SideMenu.tsx +61 -0
  11. package/.dumi/theme/layouts/index.tsx +26 -0
  12. package/.dumi/theme/layouts/layout.less +87 -0
  13. package/.dumi/theme/typings.d.ts +7 -0
  14. package/dist/index.esm.css +122 -249
  15. package/es/ProAction/index.less +3 -2
  16. package/es/ProConfigProvider/index.d.ts +2 -0
  17. package/es/ProConfigProvider/index.js +18 -2
  18. package/es/ProDrawerForm/index.js +5 -3
  19. package/es/ProDrawerForm/style/index.less +15 -11
  20. package/es/ProEditLabel/style/index.less +2 -2
  21. package/es/ProEditTable/style/index.less +15 -8
  22. package/es/ProEditTable/utils/config.js +11 -4
  23. package/es/ProEnum/style/index.less +1 -1
  24. package/es/ProForm/components/base/RangePicker/index.js +0 -3
  25. package/es/ProForm/components/base/TextArea/index.less +1 -1
  26. package/es/ProForm/components/combination/Container/style/index.less +0 -1
  27. package/es/ProForm/components/combination/FormList/style/index.less +20 -19
  28. package/es/ProForm/components/combination/Group/index.js +2 -2
  29. package/es/ProForm/components/combination/ProAddressBar/index.js +81 -61
  30. package/es/ProForm/components/combination/ProAddressBar/propsType.d.ts +3 -2
  31. package/es/ProForm/components/combination/ProModalSelect/index.js +75 -13
  32. package/es/ProForm/components/combination/ProModalSelect/propsType.d.ts +1 -0
  33. package/es/ProForm/components/combination/ProModalSelect/style/index.less +3 -3
  34. package/es/ProForm/components/combination/ProNumberRange/style/index.less +1 -1
  35. package/es/ProForm/components/combination/ProRangeLimit/index.d.ts +1 -1
  36. package/es/ProForm/components/combination/ProTimeLimit/index.d.ts +10 -5
  37. package/es/ProForm/components/combination/ProTimeLimit/style/index.less +1 -1
  38. package/es/ProForm/components/old/EnumSelect/style/index.less +7 -8
  39. package/es/ProForm/components/render/RenderFields.js +10 -5
  40. package/es/ProForm/components/render/propsType.d.ts +5 -4
  41. package/es/ProForm/index.js +5 -0
  42. package/es/ProForm/style/index.less +55 -169
  43. package/es/ProForm/utils/useShouldUpdate.js +16 -16
  44. package/es/ProLayout/components/Layout/Menu/OpenMenu/style/index.less +2 -2
  45. package/es/ProLayout/components/ProCollapse/style/index.less +4 -4
  46. package/es/ProLayout/components/ProHeader/components/ProBackBtn/style/index.less +21 -0
  47. package/es/ProLayout/components/ProHeader/components/index.d.ts +1 -0
  48. package/es/ProLayout/components/ProHeader/components/index.js +2 -1
  49. package/es/ProLayout/components/ProHeader/index.js +4 -2
  50. package/es/ProLayout/components/ProHeader/style/index.less +16 -7
  51. package/es/ProStep/style/index.less +0 -1
  52. package/es/ProTable/components/RenderColumn/index.d.ts +5 -5
  53. package/es/ProTable/components/RenderColumn/index.js +41 -25
  54. package/es/ProTable/index.js +3 -2
  55. package/es/ProTable/propsType.d.ts +2 -0
  56. package/es/ProTable/style/index.less +14 -1
  57. package/es/ProTable/utils.d.ts +1 -1
  58. package/es/ProTable/utils.js +258 -201
  59. package/es/ProTabs/style/index.less +1 -1
  60. package/es/ProThemeTools/component/PrdTools/index.js +1 -1
  61. package/es/ProThemeTools/component/PrdTools/style/index.less +3 -3
  62. package/es/ProThemeTools/index.d.ts +2 -2
  63. package/es/ProThemeTools/index.js +24 -17
  64. package/es/ProThemeTools/propsType.d.ts +8 -6
  65. package/es/ProThemeTools/style/index.less +2 -2
  66. package/es/ProThemeTools/utils/index.d.ts +7 -0
  67. package/es/ProThemeTools/utils/index.js +19 -1
  68. package/es/ProTree/components/ProTree.js +1 -1
  69. package/es/ProTree/components/SearchTitle.d.ts +2 -2
  70. package/es/ProTree/components/SearchTitle.js +11 -1
  71. package/es/ProTree/components/Tree.js +6 -1
  72. package/es/ProTree/style/index.less +193 -141
  73. package/es/ProTreeModal/style/index.less +2 -6
  74. package/es/ProUpload/style/index.less +41 -39
  75. package/es/index.d.ts +2 -1
  76. package/es/index.js +2 -1
  77. package/es/locale/en_US.d.ts +69 -0
  78. package/es/locale/en_US.js +68 -0
  79. package/es/locale/index.d.ts +7 -0
  80. package/es/locale/index.js +21 -0
  81. package/es/locale/zh_CN.d.ts +69 -0
  82. package/es/locale/zh_CN.js +68 -0
  83. package/es/old/ProEditableTable/style/index.less +1 -2
  84. package/es/style/components.less +0 -1
  85. package/es/style/core/normalize.less +1 -1
  86. package/es/style/theme/antd.less +3 -4
  87. package/es/style/theme/index.less +80 -79
  88. package/es/style/theme/tokens.less +1 -0
  89. package/lib/ProAction/index.less +3 -2
  90. package/lib/ProConfigProvider/index.d.ts +2 -0
  91. package/lib/ProConfigProvider/index.js +17 -2
  92. package/lib/ProDrawerForm/index.js +5 -3
  93. package/lib/ProDrawerForm/style/index.less +15 -11
  94. package/lib/ProEditLabel/style/index.less +2 -2
  95. package/lib/ProEditTable/style/index.less +15 -8
  96. package/lib/ProEditTable/utils/config.js +11 -4
  97. package/lib/ProEnum/style/index.less +1 -1
  98. package/lib/ProForm/components/base/RangePicker/index.js +0 -3
  99. package/lib/ProForm/components/base/TextArea/index.less +1 -1
  100. package/lib/ProForm/components/combination/Container/style/index.less +0 -1
  101. package/lib/ProForm/components/combination/FormList/style/index.less +20 -19
  102. package/lib/ProForm/components/combination/Group/index.js +2 -2
  103. package/lib/ProForm/components/combination/ProAddressBar/index.js +76 -58
  104. package/lib/ProForm/components/combination/ProAddressBar/propsType.d.ts +3 -2
  105. package/lib/ProForm/components/combination/ProModalSelect/index.js +75 -13
  106. package/lib/ProForm/components/combination/ProModalSelect/propsType.d.ts +1 -0
  107. package/lib/ProForm/components/combination/ProModalSelect/style/index.less +3 -3
  108. package/lib/ProForm/components/combination/ProNumberRange/style/index.less +1 -1
  109. package/lib/ProForm/components/combination/ProRangeLimit/index.d.ts +1 -1
  110. package/lib/ProForm/components/combination/ProTimeLimit/index.d.ts +10 -5
  111. package/lib/ProForm/components/combination/ProTimeLimit/style/index.less +1 -1
  112. package/lib/ProForm/components/old/EnumSelect/style/index.less +7 -8
  113. package/lib/ProForm/components/render/RenderFields.js +9 -4
  114. package/lib/ProForm/components/render/propsType.d.ts +5 -4
  115. package/lib/ProForm/index.js +5 -0
  116. package/lib/ProForm/style/index.less +55 -169
  117. package/lib/ProForm/utils/useShouldUpdate.js +16 -16
  118. package/lib/ProLayout/components/Layout/Menu/OpenMenu/style/index.less +2 -2
  119. package/lib/ProLayout/components/ProCollapse/style/index.less +4 -4
  120. package/lib/ProLayout/components/ProHeader/components/ProBackBtn/style/index.less +21 -0
  121. package/lib/ProLayout/components/ProHeader/components/index.d.ts +1 -0
  122. package/lib/ProLayout/components/ProHeader/components/index.js +8 -1
  123. package/lib/ProLayout/components/ProHeader/index.js +4 -2
  124. package/lib/ProLayout/components/ProHeader/style/index.less +16 -7
  125. package/lib/ProStep/style/index.less +0 -1
  126. package/lib/ProTable/components/RenderColumn/index.d.ts +5 -5
  127. package/lib/ProTable/components/RenderColumn/index.js +38 -24
  128. package/lib/ProTable/index.js +3 -2
  129. package/lib/ProTable/propsType.d.ts +2 -0
  130. package/lib/ProTable/style/index.less +14 -1
  131. package/lib/ProTable/utils.d.ts +1 -1
  132. package/lib/ProTable/utils.js +258 -201
  133. package/lib/ProTabs/style/index.less +1 -1
  134. package/lib/ProThemeTools/component/PrdTools/index.js +1 -1
  135. package/lib/ProThemeTools/component/PrdTools/style/index.less +3 -3
  136. package/lib/ProThemeTools/index.d.ts +2 -2
  137. package/lib/ProThemeTools/index.js +23 -16
  138. package/lib/ProThemeTools/propsType.d.ts +8 -6
  139. package/lib/ProThemeTools/style/index.less +2 -2
  140. package/lib/ProThemeTools/utils/index.d.ts +7 -0
  141. package/lib/ProThemeTools/utils/index.js +20 -2
  142. package/lib/ProTree/components/ProTree.js +1 -1
  143. package/lib/ProTree/components/SearchTitle.d.ts +2 -2
  144. package/lib/ProTree/components/SearchTitle.js +11 -1
  145. package/lib/ProTree/components/Tree.js +6 -1
  146. package/lib/ProTree/style/index.less +193 -141
  147. package/lib/ProTreeModal/style/index.less +2 -6
  148. package/lib/ProUpload/style/index.less +41 -39
  149. package/lib/index.d.ts +2 -1
  150. package/lib/index.js +13 -1
  151. package/lib/locale/en_US.d.ts +69 -0
  152. package/lib/locale/en_US.js +74 -0
  153. package/lib/locale/index.d.ts +7 -0
  154. package/lib/locale/index.js +28 -0
  155. package/lib/locale/zh_CN.d.ts +69 -0
  156. package/lib/locale/zh_CN.js +74 -0
  157. package/lib/old/ProEditableTable/style/index.less +1 -2
  158. package/lib/style/components.less +0 -1
  159. package/lib/style/core/normalize.less +1 -1
  160. package/lib/style/theme/antd.less +3 -4
  161. package/lib/style/theme/index.less +80 -79
  162. package/lib/style/theme/tokens.less +1 -0
  163. package/package.json +2 -2
  164. package/typings.d.ts +2 -0
  165. package/es/old/ProBackBtn/style/index.less +0 -19
  166. package/lib/old/ProBackBtn/style/index.less +0 -19
  167. /package/es/{old → ProLayout/components/ProHeader/components}/ProBackBtn/index.d.ts +0 -0
  168. /package/es/{old → ProLayout/components/ProHeader/components}/ProBackBtn/index.js +0 -0
  169. /package/es/{old → ProLayout/components/ProHeader/components}/ProBackBtn/propsType.d.ts +0 -0
  170. /package/es/{old → ProLayout/components/ProHeader/components}/ProBackBtn/propsType.js +0 -0
  171. /package/lib/{old → ProLayout/components/ProHeader/components}/ProBackBtn/index.d.ts +0 -0
  172. /package/lib/{old → ProLayout/components/ProHeader/components}/ProBackBtn/index.js +0 -0
  173. /package/lib/{old → ProLayout/components/ProHeader/components}/ProBackBtn/propsType.d.ts +0 -0
  174. /package/lib/{old → ProLayout/components/ProHeader/components}/ProBackBtn/propsType.js +0 -0
@@ -0,0 +1,19 @@
1
+ import React from 'react'
2
+ import { InfoCircleFilled } from '@ant-design/icons'
3
+
4
+ export default function MyAlert(props: any) {
5
+ return (
6
+ <span
7
+ style={{
8
+ display: 'block',
9
+ backgroundColor: '#e6f7ff',
10
+ border: '1px solid #91d5ff',
11
+ borderRadius: 2,
12
+ padding: '8px 15px'
13
+ }}
14
+ >
15
+ <InfoCircleFilled style={{ color: '#1890ff', marginRight: 8 }} />
16
+ {props.children}
17
+ </span>
18
+ )
19
+ }
@@ -0,0 +1,232 @@
1
+ import React, { useState, useContext, useRef, useEffect } from 'react'
2
+ import Tabs, { TabPane } from 'rc-tabs'
3
+ // @ts-ignore
4
+ import { history } from 'dumi'
5
+ import { IPreviewerComponentProps } from 'dumi/theme'
6
+ import {
7
+ context,
8
+ useRiddle,
9
+ useMotions,
10
+ useCopy,
11
+ useLocaleProps,
12
+ useDemoUrl,
13
+ useTSPlaygroundUrl,
14
+ Link,
15
+ AnchorLink,
16
+ usePrefersColor
17
+ } from 'dumi/theme'
18
+ import { ICodeBlockProps } from './SourceCode'
19
+ import SourceCode from './SourceCode'
20
+ import 'dumi-theme-default/src/builtins/Previewer.less'
21
+ import useCodeSandbox from '../hooks/useCodeSandbox'
22
+
23
+ export interface IPreviewerProps extends IPreviewerComponentProps {
24
+ /**
25
+ * enable transform to change CSS containing block for demo
26
+ */
27
+ transform?: boolean
28
+ /**
29
+ * modify background for demo area
30
+ */
31
+ background?: string
32
+ /**
33
+ * collapse padding of demo area
34
+ */
35
+ compact?: boolean
36
+ /**
37
+ * configurations for action button
38
+ */
39
+ hideActions?: ('CSB' | 'EXTERNAL' | 'RIDDLE')[]
40
+ /**
41
+ * show source code by default
42
+ */
43
+ defaultShowCode?: boolean
44
+ /**
45
+ * use iframe mode for this demo
46
+ */
47
+ iframe?: true | number
48
+ /**
49
+ * replace builtin demo url
50
+ */
51
+ demoUrl?: string
52
+ }
53
+
54
+ /**
55
+ * get source code type for file
56
+ * @param file file path
57
+ * @param source file source object
58
+ */
59
+ function getSourceType(file: string, source: IPreviewerComponentProps['sources']['_']) {
60
+ // use file extension as source type first
61
+ let type = file.match(/\.(\w+)$/)?.[1]
62
+
63
+ if (!type) {
64
+ type = source.tsx ? 'tsx' : 'jsx'
65
+ }
66
+
67
+ return type as ICodeBlockProps['lang']
68
+ }
69
+
70
+ const Previewer: React.FC<IPreviewerProps> = oProps => {
71
+ const demoRef = useRef()
72
+ const { locale } = useContext(context)
73
+ const props = useLocaleProps<IPreviewerProps>(locale, oProps)
74
+ const builtinDemoUrl = useDemoUrl(props.identifier)
75
+ const demoUrl = props.demoUrl || builtinDemoUrl
76
+ const isActive = history?.location.hash === `#${props.identifier}`
77
+ const isSingleFile = Object.keys(props.sources).length === 1
78
+ const openCSB = useCodeSandbox(props.hideActions?.includes('CSB') ? null : props)
79
+ const openRiddle = useRiddle(props.hideActions?.includes('RIDDLE') ? null : props)
80
+ const [execMotions, isMotionRunning] = useMotions(props.motions || [], demoRef.current)
81
+ const [copyCode, copyStatus] = useCopy()
82
+ const [currentFile, setCurrentFile] = useState('_')
83
+ const [sourceType, setSourceType] = useState(getSourceType(currentFile, props.sources[currentFile]))
84
+ const [showSource, setShowSource] = useState(Boolean(props.defaultShowCode))
85
+ const [iframeKey, setIframeKey] = useState(Math.random())
86
+ const currentFileCode = props.sources[currentFile][sourceType] || props.sources[currentFile].content
87
+ const playgroundUrl = useTSPlaygroundUrl(locale, currentFileCode)
88
+ const iframeRef = useRef<HTMLIFrameElement>()
89
+ const [color] = usePrefersColor()
90
+
91
+ // re-render iframe if prefers color changed
92
+ useEffect(() => {
93
+ setIframeKey(Math.random())
94
+ }, [color])
95
+
96
+ function handleFileChange(filename: string) {
97
+ setCurrentFile(filename)
98
+ setSourceType(getSourceType(filename, props.sources[filename]))
99
+ }
100
+
101
+ return (
102
+ <div
103
+ style={props.style}
104
+ className={[props.className, '__dumi-default-previewer', isActive ? '__dumi-default-previewer-target' : '']
105
+ .filter(Boolean)
106
+ .join(' ')}
107
+ id={props.identifier}
108
+ data-debug={props.debug || undefined}
109
+ data-iframe={props.iframe || undefined}
110
+ >
111
+ {props.iframe && <div className="__dumi-default-previewer-browser-nav" />}
112
+ <div
113
+ ref={demoRef}
114
+ className="__dumi-default-previewer-demo"
115
+ style={{
116
+ transform: props.transform ? 'translate(0, 0)' : undefined,
117
+ padding: props.compact || (props.iframe && props.compact !== false) ? '0' : undefined,
118
+ background: props.background
119
+ }}
120
+ >
121
+ {props.iframe ? (
122
+ <iframe
123
+ title="dumi-previewer"
124
+ style={{
125
+ // both compatible with unit or non-unit, such as 100, 100px, 100vh
126
+ height: String(props.iframe).replace(/(\d)$/, '$1px')
127
+ }}
128
+ key={iframeKey}
129
+ src={demoUrl}
130
+ ref={iframeRef}
131
+ />
132
+ ) : (
133
+ props.children
134
+ )}
135
+ </div>
136
+ <div className="__dumi-default-previewer-desc" data-title={props.title}>
137
+ {props.title && <AnchorLink to={`#${props.identifier}`}>{props.title}</AnchorLink>}
138
+ {props.description && (
139
+ <div
140
+ // eslint-disable-next-line
141
+ dangerouslySetInnerHTML={{ __html: props.description }}
142
+ />
143
+ )}
144
+ </div>
145
+ <div className="__dumi-default-previewer-actions">
146
+ {openCSB && (
147
+ <button
148
+ title="Open demo on CodeSandbox.io"
149
+ className="__dumi-default-icon"
150
+ role="codesandbox"
151
+ onClick={openCSB}
152
+ />
153
+ )}
154
+ {openRiddle && (
155
+ <button title="Open demo on Riddle" className="__dumi-default-icon" role="riddle" onClick={openRiddle} />
156
+ )}
157
+ {props.motions && (
158
+ <button
159
+ title="Execute motions"
160
+ className="__dumi-default-icon"
161
+ role="motions"
162
+ disabled={isMotionRunning}
163
+ onClick={() => execMotions()}
164
+ />
165
+ )}
166
+ {props.iframe && (
167
+ <button
168
+ title="Reload demo iframe page"
169
+ className="__dumi-default-icon"
170
+ role="refresh"
171
+ onClick={() => setIframeKey(Math.random())}
172
+ />
173
+ )}
174
+ {!props.hideActions?.includes('EXTERNAL') && (
175
+ <Link target="_blank" to={demoUrl}>
176
+ <button title="Open demo in new tab" className="__dumi-default-icon" role="open-demo" type="button" />
177
+ </Link>
178
+ )}
179
+ <span />
180
+ <button
181
+ title="Copy source code"
182
+ className="__dumi-default-icon"
183
+ role="copy"
184
+ data-status={copyStatus}
185
+ onClick={() => copyCode(currentFileCode)}
186
+ />
187
+ {sourceType === 'tsx' && showSource && (
188
+ <Link target="_blank" to={playgroundUrl}>
189
+ <button
190
+ title="Get JSX via TypeScript Playground"
191
+ className="__dumi-default-icon"
192
+ role="change-tsx"
193
+ type="button"
194
+ />
195
+ </Link>
196
+ )}
197
+ <button
198
+ title="Toggle source code panel"
199
+ className={`__dumi-default-icon${showSource ? ' __dumi-default-btn-expand' : ''}`}
200
+ role="source"
201
+ type="button"
202
+ onClick={() => setShowSource(!showSource)}
203
+ />
204
+ </div>
205
+ {showSource && (
206
+ <div className="__dumi-default-previewer-source-wrapper">
207
+ {!isSingleFile && (
208
+ <Tabs
209
+ className="__dumi-default-previewer-source-tab"
210
+ prefixCls="__dumi-default-tabs"
211
+ moreIcon="···"
212
+ defaultActiveKey={currentFile}
213
+ onChange={handleFileChange}
214
+ >
215
+ {Object.keys(props.sources).map(filename => (
216
+ <TabPane
217
+ tab={filename === '_' ? `index.${getSourceType(filename, props.sources[filename])}` : filename}
218
+ key={filename}
219
+ />
220
+ ))}
221
+ </Tabs>
222
+ )}
223
+ <div className="__dumi-default-previewer-source">
224
+ <SourceCode code={currentFileCode} lang={sourceType} showCopy={false} />
225
+ </div>
226
+ </div>
227
+ )}
228
+ </div>
229
+ )
230
+ }
231
+
232
+ export default Previewer
@@ -0,0 +1,64 @@
1
+ import React from 'react'
2
+ // import styled from 'styled-components'
3
+ import { Language } from 'prism-react-renderer'
4
+ import Highlight, { defaultProps } from 'prism-react-renderer'
5
+ import { useCopy } from 'dumi/theme'
6
+ import 'prismjs/themes/prism.css'
7
+ import 'dumi-theme-default/src/builtins/SourceCode.less'
8
+
9
+ export interface ICodeBlockProps {
10
+ code: string
11
+ lang: Language
12
+ showCopy?: boolean
13
+ }
14
+
15
+ // const Line = styled.div`
16
+ // display: table-row;
17
+ // `
18
+
19
+ // const LineNo = styled.span`
20
+ // display: table-cell;
21
+ // text-align: right;
22
+ // padding-right: 1em;
23
+ // min-width: 4em;
24
+ // user-select: none;
25
+ // opacity: 0.5;
26
+ // `
27
+
28
+ // const LineContent = styled.span`
29
+ // display: table-cell;
30
+ // `
31
+
32
+ export default ({ code, lang, showCopy = true }: ICodeBlockProps) => {
33
+ const [copyCode, copyStatus] = useCopy()
34
+
35
+ return (
36
+ <div className="__dumi-default-code-block">
37
+ <Highlight {...defaultProps} code={code} language={lang} theme={undefined}>
38
+ {({ className, style, tokens, getLineProps, getTokenProps }) => (
39
+ <pre className={className} style={style}>
40
+ {showCopy && (
41
+ <button
42
+ className="__dumi-default-icon __dumi-default-code-block-copy-btn"
43
+ data-status={copyStatus}
44
+ onClick={() => copyCode(code)}
45
+ />
46
+ )}
47
+ {tokens.map((line, i) => (
48
+ <div {...getLineProps({ line, key: i })}>
49
+ <div key={i} {...getLineProps({ line, key: i })}>
50
+ {/* <div>{i + 1}</div> */}
51
+ <div>
52
+ {line.map((token, key) => (
53
+ <span key={key} {...getTokenProps({ token, key })} />
54
+ ))}
55
+ </div>
56
+ </div>
57
+ </div>
58
+ ))}
59
+ </pre>
60
+ )}
61
+ </Highlight>
62
+ </div>
63
+ )
64
+ }
@@ -0,0 +1,197 @@
1
+ import { useState, useEffect } from 'react'
2
+ import LZString from 'lz-string'
3
+ import { linkList } from './useTheme'
4
+
5
+ interface IPreviewerComponentProps {
6
+ title?: string
7
+ description?: string
8
+ sources:
9
+ | {
10
+ /**
11
+ * self source code for demo
12
+ * @note jsx exsits definitely, tsx exists when the source code language is tsx
13
+ */
14
+ _: { jsx: string; tsx?: string }
15
+ }
16
+ | Record<
17
+ string,
18
+ {
19
+ import: string
20
+ content: string
21
+ path?: string
22
+ tsx?: string
23
+ }
24
+ >
25
+ /**
26
+ * third-party dependencies of demo
27
+ */
28
+ dependencies: any
29
+ /**
30
+ * global identifier for demo
31
+ */
32
+ identifier: string
33
+ /**
34
+ * the component which demo belongs to
35
+ */
36
+ componentName?: string
37
+ /**
38
+ * motions of current demo, for snapshot or preview
39
+ */
40
+ motions?: string[]
41
+ /**
42
+ * mark demo as debug demo, will be discarded in production mode
43
+ */
44
+ debug?: true
45
+ [key: string]: any
46
+ }
47
+
48
+ const CSB_API_ENDPOINT = 'https://codesandbox.io/api/v1/sandboxes/define'
49
+
50
+ // ref: https://github.com/codesandbox/codesandbox-importers/blob/master/packages/import-utils/src/api/define.ts
51
+ function serialize(data: Record<string, any>) {
52
+ return LZString.compressToBase64(JSON.stringify(data))
53
+ .replace(/\+/g, '-') // Convert '+' to '-'
54
+ .replace(/\//g, '_') // Convert '/' to '_'
55
+ .replace(/=+$/, '') // Remove ending '='
56
+ }
57
+
58
+ function getTextContent(raw: string) {
59
+ const elm = document.createElement('span')
60
+
61
+ elm.innerHTML = raw
62
+ const text = elm.textContent
63
+ elm.remove()
64
+
65
+ return text
66
+ }
67
+
68
+ /**
69
+ * get serialized data that use to submit to codesandbox.io
70
+ * @param opts previewer props
71
+ */
72
+ function getCSBData(opts: IPreviewerComponentProps) {
73
+ const isTSX = Boolean(opts.sources._.tsx)
74
+ const ext = isTSX ? '.tsx' : '.jsx'
75
+ const files: Record<string, { content: string }> = {}
76
+ const deps: Record<string, string> = {}
77
+ const CSSDeps = Object.values(opts.dependencies).filter((dep: any) => dep.css)
78
+ const appFileName = `App${ext}`
79
+ const entryFileName = `index${ext}`
80
+
81
+ // generate dependencies
82
+ Object.entries(opts.dependencies).forEach(([dep, { version }]: any) => {
83
+ deps[dep] = version
84
+ })
85
+
86
+ deps.tslib = '2.3.1'
87
+
88
+ // add react-dom dependency
89
+ if (!deps['react-dom']) {
90
+ deps['react-dom'] = deps.react || 'latest'
91
+ }
92
+
93
+ // append sandbox.config.json
94
+ files['sandbox.config.json'] = {
95
+ content: JSON.stringify(
96
+ {
97
+ template: isTSX ? 'create-react-app-typescript' : 'create-react-app'
98
+ },
99
+ null,
100
+ 2
101
+ )
102
+ }
103
+
104
+ // append package.json
105
+ files['package.json'] = {
106
+ content: JSON.stringify(
107
+ {
108
+ name: opts.title,
109
+ description: getTextContent(opts.description) || 'Amiya Demo',
110
+ main: entryFileName,
111
+ dependencies: deps,
112
+ // add TypeScript dependency if required, must in devDeps to avoid csb compile error
113
+ devDependencies: isTSX ? { typescript: '^3' } : {}
114
+ },
115
+ null,
116
+ 2
117
+ )
118
+ }
119
+
120
+ let name = localStorage.getItem('AMIYA_COLOR')
121
+
122
+ if (!name) {
123
+ name = 'default'
124
+ }
125
+
126
+ let color = linkList.find(item => item.name === name)
127
+
128
+ let link = color.link
129
+
130
+ // append index.html
131
+ files['index.html'] = {
132
+ content: `<link rel="stylesheet" href="${link}" class="amiya-theme"><div style="margin: 16px;" id="root"></div>`
133
+ }
134
+
135
+ // append entry file
136
+ files[entryFileName] = {
137
+ content: `/**
138
+ * This is an auto-generated demo by amiya
139
+ * if you think it is not working as expected,
140
+ * please report the issue at
141
+ * https://github.com/viewweiwu/amiya/issues
142
+ **/
143
+ import React from 'react';
144
+ import ReactDOM from 'react-dom';
145
+ ${CSSDeps.map(({ css }: any) => `import '${css}';`).join('\n')}
146
+ import App from './App';
147
+ ReactDOM.render(
148
+ <App />,
149
+ document.getElementById('root'),
150
+ );`
151
+ }
152
+
153
+ // append other imported local files
154
+ Object.entries(opts.sources).forEach(([filename, { tsx, jsx, content }]) => {
155
+ // handle primary content
156
+ files[filename === '_' ? appFileName : filename] = {
157
+ content: tsx || jsx || content
158
+ }
159
+ })
160
+
161
+ return serialize({ files })
162
+ }
163
+
164
+ /**
165
+ * use CodeSandbox.io
166
+ * @param opts previewer opts
167
+ * @note return a open function for open demo on codesandbox.io
168
+ */
169
+ export default (opts: IPreviewerComponentProps | null, api: string = CSB_API_ENDPOINT) => {
170
+ const [handler, setHandler] = useState<(...args: any) => void | undefined>()
171
+
172
+ useEffect(() => {
173
+ if (opts) {
174
+ const form = document.createElement('form')
175
+ const input = document.createElement('input')
176
+ const data = getCSBData(opts)
177
+
178
+ form.method = 'POST'
179
+ form.target = '_blank'
180
+ form.style.display = 'none'
181
+ form.action = api
182
+ form.appendChild(input)
183
+ form.setAttribute('data-demo', opts.title || '')
184
+
185
+ input.name = 'parameters'
186
+ input.value = data
187
+
188
+ document.body.appendChild(form)
189
+
190
+ setHandler(() => () => form.submit())
191
+
192
+ return () => form.remove()
193
+ }
194
+ }, [opts])
195
+
196
+ return handler
197
+ }